ucar.nc2.iosp.uf.Ray Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cdm Show documentation
Show all versions of cdm Show documentation
The NetCDF-Java Library is a Java interface to NetCDF files,
as well as to many other types of scientific data formats.
The newest version!
/*
* Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.nc2.iosp.uf;
import ucar.nc2.constants.CDM;
import ucar.unidata.io.RandomAccessFile;
import ucar.ma2.Range;
import ucar.ma2.IndexIterator;
import java.nio.ByteBuffer;
import java.util.*;
import java.io.IOException;
public class Ray {
int raySize;
long rayOffset;
static final int UF_MANDATORY_HEADER2_LEN = 90;
static final int UF_FIELD_HEADER2_LEN = 50;
boolean debug = false;
/** moment identifier */
long data_msecs = 0;
UF_mandatory_header2 uf_header2;
UF_optional_header uf_opt_header;
short numberOfFields; // in this ray
short numberOfRecords; // in this ray
short numberOfFieldsInRecord; // in this record
Map field_header_map; // key = 2 byte "data type"
public Ray( ByteBuffer bos, int raySize, long rayOffset) {
this.raySize = raySize;
this.rayOffset = rayOffset;
field_header_map = new HashMap<>();
bos.position(0);
byte[] data = new byte[UF_MANDATORY_HEADER2_LEN];
bos.get(data);
uf_header2 = new UF_mandatory_header2(data);
if(uf_header2.offset2StartOfOptionalHeader > 0 &&
(uf_header2.dataHeaderPosition != uf_header2.offset2StartOfOptionalHeader)){
data = new byte[28];
bos.get(data);
uf_opt_header = new UF_optional_header(data);
}
int position = uf_header2.dataHeaderPosition*2 -2;
bos.position(position);
data_msecs = setDateMesc();
byte [] b2 = new byte[2];
bos.get(b2);
numberOfFields = getShort(b2, 0);
bos.get(b2);
numberOfRecords = getShort(b2, 0);
bos.get(b2);
numberOfFieldsInRecord = getShort(b2, 0);
data = new byte[UF_FIELD_HEADER2_LEN];
for(int i = 0; i < numberOfFields; i++){
bos.get(b2);
//int type = getShort(b2, 0);
String type = new String(b2, CDM.utf8Charset);
bos.get(b2);
int offs = getShort(b2, 0);
int position0 = bos.position();
bos.position(offs*2 - 2);
bos.get(data);
UF_field_header2 field_header = new UF_field_header2(data);
bos.position(position0);
field_header_map.put(type, field_header);
}
}
public int getRaySize(){
return raySize;
}
public int getGateCount(String abbrev) {
UF_field_header2 header = field_header_map.get(abbrev);
return header.binCount;
}
public String getDatatypeName(String abbrev) {
if( abbrev.equals("ZN") || abbrev.equals("ZS"))
return "Reflectivity";
else if (abbrev.equals("ZF") || abbrev.equals("ZX") || abbrev.equals("DR"))
return "Reflectivity";
else if(abbrev.equals("VR") || abbrev.equals("DN") || abbrev.equals("DS") || abbrev.equals("DF") ||abbrev.equals("DX") )
return "RadialVelocity";
else if(abbrev.equals("VN") || abbrev.equals("VF") )
return "CorrectedRadialVelocity";
else if(abbrev.equals("SW") || abbrev.equals("WS") || abbrev.equals("WF") || abbrev.equals("WX") || abbrev.equals("WN"))
return "SpectrumWidth";
else if(abbrev.equals("PN") || abbrev.equals("PS") || abbrev.equals("PF") || abbrev.equals("PX"))
return "Power";
else if(abbrev.equals("MN") || abbrev.equals("MS") || abbrev.equals("MF") || abbrev.equals("MX"))
return "Power";
else if(abbrev.equals("PH"))
return "PhiDP";
else if(abbrev.equals("RH"))
return "RhoHV";
else if(abbrev.equals("LH"))
return "LdrH";
else if(abbrev.equals("KD"))
return "KDP";
else if(abbrev.equals("LV"))
return "LdrV" ;
else if(abbrev.equals("DR"))
return "ZDR";
else if(abbrev.equals("CZ"))
return "CorrecteddBZ";
else if(abbrev.equals("DZ"))
return "TotalReflectivity";
else if(abbrev.equals("DR"))
return "ZDR";
else
return abbrev;
}
public String getDatatypeUnits(String abbrev) {
if(abbrev.equals("CZ") || abbrev.equals("DZ") || abbrev.equals("ZN") || abbrev.equals("ZS"))
return "dBz";
else if (abbrev.equals("ZF") || abbrev.equals("ZX"))
return "dBz";
else if(abbrev.equals("VR") || abbrev.equals("DN") || abbrev.equals("DS") || abbrev.equals("DF") ||abbrev.equals("DX") )
return "m/s";
else if(abbrev.equals("VN") || abbrev.equals("VF") )
return "m/s";
else if(abbrev.equals("SW") || abbrev.equals("WS") || abbrev.equals("WF") || abbrev.equals("WX") || abbrev.equals("WN"))
return "m/s";
else if(abbrev.equals("PN") || abbrev.equals("PS") || abbrev.equals("PF") || abbrev.equals("PX"))
return "dBM";
else if(abbrev.equals("MN") || abbrev.equals("MS") || abbrev.equals("MF") || abbrev.equals("MX"))
return "dBM";
else
return abbrev;
}
public short getDatatypeRangeFoldingThreshhold(String abbrev) {
UF_field_header2 header = field_header_map.get(abbrev);
return header.thresholdValue;
}
public float getDatatypeScaleFactor(String abbrev) {
UF_field_header2 header = field_header_map.get(abbrev);
return 1.0f/header.scaleFactor;
}
public float getDatatypeAddOffset(String abbrev) {
return 0.0f;
}
public int getGateStart(String abbrev) {
UF_field_header2 header = field_header_map.get(abbrev);
return header.startRange;
}
public int getDataOffset(String abbrev) {
UF_field_header2 header = field_header_map.get(abbrev);
return header.dataOffset;
}
public int getGateSize(String abbrev) {
UF_field_header2 header = field_header_map.get(abbrev);
return header.binSpacing;
}
public float getElevation(){
return uf_header2.elevation/64.f;
}
public float getAzimuth(){
return uf_header2.azimuth/64.f;
}
public short getMissingData() {
return uf_header2.missing;
}
public int getYear() {
return getYear(uf_header2.year) ;
}
public float getLatitude(){
return uf_header2.latitudeD + (uf_header2.latitudeM + uf_header2.latitudeS/(64*60.f))/60.f;
}
public float getLongtitude(){
return uf_header2.longitudeD + (uf_header2.longitudeM + uf_header2.longitudeS/(64*60.f))/60.f;
}
public float getHorizontalBeamWidth(String abbrev) {
UF_field_header2 header = field_header_map.get(abbrev);
return header.HorizontalBeamWidth/64.f;
}
public int getYear(int year) {
if(year > 1970)
return year;
if( year > 70 && year < 100)
return 1900+ year;
if( year < 60)
return 2000 + year;
return 0;
}
public long getTitleMsecs() {
return data_msecs;
}
public long setDateMesc() {
Calendar cal;
if(uf_header2.timeZone.equals("UT") || uf_header2.timeZone.equals("GM")) {
cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
}else{
cal = Calendar.getInstance();
}
cal.set(Calendar.YEAR, uf_header2.year);
cal.set(Calendar.MONTH,uf_header2.month - 1 );
cal.set(Calendar.DAY_OF_MONTH, uf_header2.day );
cal.set(Calendar.HOUR_OF_DAY, uf_header2.hour);
cal.set(Calendar.MINUTE, uf_header2.minute);
cal.set(Calendar.SECOND, uf_header2.second);
return cal.getTimeInMillis();
}
public Date getDate() {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(data_msecs);
return cal.getTime();
}
class UF_mandatory_header2 {
String textUF;
short recordSize; // in 16-bit words
short offset2StartOfOptionalHeader; //, origin 1
short localUseHeaderPosition;
short dataHeaderPosition;
short recordNumber;
short volumeNumber; // on tape, n/a for disk
short rayNumber; // within the volume scan
short recordNumber1; // within ray (origin 1)
short sweepNumber; // within the volume scan
String radarName; // char[8]
String siteName; // char[8]
short latitudeD; // degrees (North positive, South negative)
short latitudeM; // minutes
short latitudeS; // seconds*64
short longitudeD; // degrees (East positive, West negative)
short longitudeM; // Minutes
short longitudeS; // Seconds
short height; // of antenna above sea level in meters
short year; // (time of data acquisition)
short month ;
short day;
short hour;
short minute;
short second;
String timeZone; // UT for universal char[2]
short azimuth; // (degrees*64) of midpoint of sample
short elevation; // (degrees*64)
short sweepMode;
// 0:Cal 1:PPI 2:Coplane 3:RHI
// 4:Vertical 5:Target 6:Manual 7:Idle
short fixedAngle; // (degrees*64)
short sweepRate; // ((degrees/second)*64)
short year1; // (generation data of UF format)
short month1;
short day1;
String nameOfUFGeneratorProgram; // char[8]
short missing; // Value stored for deleted or missing data (0x8000)
UF_mandatory_header2(byte[] data){
// data is of length 90 bytes
textUF = new String(data, 0, 2, CDM.utf8Charset);
if (debug){
System.out.println(textUF);
}
recordSize = getShort(data, 2);
offset2StartOfOptionalHeader = getShort(data, 4);
localUseHeaderPosition= getShort(data, 6);
dataHeaderPosition= getShort(data, 8);
recordNumber= getShort(data, 10);
volumeNumber= getShort(data, 12);
rayNumber= getShort(data, 14);
recordNumber1= getShort(data, 16);
sweepNumber= getShort(data, 18);
radarName= new String(data, 20, 8, CDM.utf8Charset).trim();
siteName= new String(data, 28, 8, CDM.utf8Charset).trim();
latitudeD= getShort(data, 36);
latitudeM= getShort(data, 38);
latitudeS= getShort(data, 40);
longitudeD= getShort(data, 42);
longitudeM= getShort(data, 44);
longitudeS= getShort(data, 46);
height= getShort(data, 48);
int yearValue= getShort(data, 50);
year = (short)getYear(yearValue);
month = getShort(data, 52);
day= getShort(data, 54);
hour= getShort(data, 56);
minute= getShort(data, 58);
second= getShort(data, 60);
timeZone = new String(data, 62, 2, CDM.utf8Charset);
azimuth= getShort(data, 64);
elevation= getShort(data, 66);
sweepMode= getShort(data, 68);
fixedAngle= getShort(data, 70); // (degrees*64)
sweepRate = getShort(data, 72); // ((degrees/second)*64)
year1 = getShort(data, 74); // (generation data of UF format)
month1 = getShort(data, 76);
day1 = getShort(data, 78);
nameOfUFGeneratorProgram = new String(data, 80, 8,
CDM.utf8Charset); // char[8]
missing = getShort(data, 88); // Value stored for deleted or missing data (0x8000)
}
}
class UF_optional_header{
String sProjectName; // char[8]
short iBaselineAzimuth;
short iBaselineelevation;
short iVolumeScanHour; /* Time of start of current volume scan */
short iVolumeScanMinute;
short iVolumeScanSecond;
String sFieldTapeName; // char[8]
short iFlag;
UF_optional_header(byte[] data){
sProjectName = new String(data, 0, 8, CDM.utf8Charset);
iBaselineAzimuth = getShort(data, 8);
iBaselineelevation = getShort(data, 10);
iVolumeScanHour = getShort(data, 12);
iVolumeScanMinute = getShort(data, 14);
iVolumeScanSecond = getShort(data, 16);
sFieldTapeName = new String(data, 18, 8, CDM.utf8Charset);
iFlag = getShort(data, 26);
}
}
class UF_field_header2 {
short dataOffset; // from start of record, origin 1
short scaleFactor; // met units = file value/scale
short startRange; // km
short startRange1; // meters
short binSpacing; // in meters
short binCount;
short pulseWidth; // in meters
short HorizontalBeamWidth; // in degrees*64
short verticalBeamWidth; // in degrees*64
short receiverBandwidth; // in Mhz*64 ?
short polarization; //: 1:horz 2:vert
short waveLength; // in cm*64
short sampleSize;
String typeOfData; //used to threshold // char[2]
short thresholdValue;
short scale;
String editCode; // char[2]
short prt; // in microseconds
short bits; // per bin, must be 16
// 38 12
UF_field_header2(byte[] data){
dataOffset = getShort(data, 0);
scaleFactor = getShort(data, 2);
startRange = getShort(data, 4);
startRange1 = getShort(data, 6);
binSpacing = getShort(data, 8);
binCount = getShort(data, 10);
pulseWidth = getShort(data, 12);
HorizontalBeamWidth = getShort(data, 14);
verticalBeamWidth =getShort(data, 16);
receiverBandwidth = getShort(data, 18);
polarization = getShort(data, 20);
waveLength = getShort(data, 22);
sampleSize = getShort(data, 24);
typeOfData = new String(data, 26, 2, CDM.utf8Charset);
thresholdValue = getShort(data, 28);
scale = getShort(data, 30);
editCode = new String(data, 32, 2, CDM.utf8Charset);
prt = getShort(data, 34);
bits = getShort(data, 36);
}
}
protected short getShort(byte[] bytes, int offset) {
// careful that we only allow sign extension on the highest order byte
return (short) bytesToShort(bytes[offset], bytes[offset+1], false);
}
public static int bytesToShort(byte a, byte b, boolean swapBytes) {
// again, high order bit is expressed left into 32-bit form
if (swapBytes) {
return (a & 0xff) + ((int)b << 8);
} else {
return ((int)a << 8) + (b & 0xff);
}
}
public short[] byte2short(byte [] a, int length){
int len = length/2;
short [] b = new short[len];
byte [] b2 = new byte[2];
for(int i = 0; i < len; i++){
b2[0] = a[2*i];
b2[1] = a[2*i + 1];
b[i] = getShort(b2, 0);
}
return b;
}
/**
* Read data from this ray.
* @param raf read from this file
* @param abbrev which data type we want
* @param gateRange handles the possible subset of data to return
* @param ii put the data here
* @throws java.io.IOException
*/
public void readData(RandomAccessFile raf, String abbrev, Range gateRange, IndexIterator ii) throws IOException {
long offset = rayOffset;
offset += (getDataOffset( abbrev) * 2 - 2) ;
raf.seek(offset);
byte[] b2 = new byte[2];
int dataCount = getGateCount( abbrev);
byte[] data = new byte[dataCount*2];
raf.readFully(data);
for (int i = gateRange.first(); i <= gateRange.last(); i += gateRange.stride()) {
if (i >= dataCount)
ii.setShortNext(uf_header2.missing);
else {
b2[0] = data[i*2];
b2[1] = data[i*2+1];
short value = getShort(b2, 0);
ii.setShortNext(value);
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy