ucar.nc2.iosp.sigmet.SigmetIOServiceProvider Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package ucar.nc2.iosp.sigmet;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import ucar.ma2.Range;
import ucar.ma2.Array;
import ucar.ma2.ArrayFloat;
import ucar.ma2.ArrayInt;
import ucar.ma2.DataType;
import ucar.ma2.Index;
import ucar.ma2.IndexIterator;
import ucar.ma2.InvalidRangeException;
import ucar.ma2.Section;
import ucar.nc2.Attribute;
import ucar.nc2.Dimension;
import ucar.nc2.NetcdfFile;
import ucar.nc2.Variable;
import ucar.nc2.constants.AxisType;
import ucar.nc2.constants.CDM;
import ucar.nc2.constants._Coordinate;
import ucar.nc2.iosp.AbstractIOServiceProvider;
import ucar.nc2.iosp.Layout;
import ucar.nc2.iosp.LayoutRegular;
import ucar.unidata.io.RandomAccessFile;
/**
* Implementation of the ServerProvider pattern provides input/output
* of the SIGMET-IRIS dataset. IOSP are managed by the NetcdfFile class.
* When the SigmetDataset is requested by calling NetcdfFile.open(), the file
* is opened as a ucar.unidata.io.RandomAccessFile.
* The SIGMET-IRIS data format are described in "IRIS Programmer's Manual" ch.3
* The SIGMET-IRIS file consists of records with fixed length=6144 bytes. Data is written in
* little-endian format. The organization of raw product SIGMET-IRIS file is:
* Record #1 { 0,0,0,...}
* Record #2 { 0,0,0,... }
* ---if there are several sweeps (usually 24) and one type of data:
* Record #3 { ...Data for sweep 1.. }
* Record #4 { ...Data for sweep 1... }
* .............................................
* Record #n { ...Data for sweep 1... 0.... }
* Record #n+1 { ...Data for sweep 2.. }
* Record #n+2 { ...Data for sweep 2... }
* .............................................
* Record #m { ...Data for sweep 2... 0... }
* Record #m+1 { ...Data for sweep 3.. }
* .............................................
* Structure of "Data for sweep" is: ......
* and are encoded with the compression algorithm
* ("IRIS Programmer's Manual" 3.5.4.1)
* ---if there are "n" types of data (usually 4 or 5) and one sweep:
* Record #3 { ...
* ...Data...}
* Record #4 { ...Data... }
* .............................................
* Record #n { ...Data... }
* Structure of "Data" is: ...
*
* ... ...
* and are encoded with the compression algorithm
* ("IRIS Programmer's Manual" 3.5.4.1)
*
* @author yuanho
* @see "ftp://ftp.sigmet.com/outgoing/manuals/program/3data.pdf"
* esp section 3.5
*/
public class SigmetIOServiceProvider extends AbstractIOServiceProvider {
private ArrayList varList = null;
private int[] tsu_sec = null;
private int[] sweep_bins = null;
private String date0;
public static java.util.Map recHdr = new java.util.HashMap();
private SigmetVolumeScan volScan;
public static void main(String[] args) {
String infile = " ";
if (args.length == 1) {
infile = args[0];
} else {
System.out.println("Usage: java SigmetIOServiceProvider inputFile");
System.exit(0);
}
try {
NetcdfFile.registerIOProvider(SigmetIOServiceProvider.class);
NetcdfFile ncfile = NetcdfFile.open(infile);
System.out.println("ncfile = \n" + ncfile);
} catch (Exception e) {
System.out.println("MAIN!!! " + e.toString());
e.printStackTrace();
}
}
public String getFileTypeDescription() {
return "SIGMET-IRIS";
}
public String getFileTypeVersion() {
return "SIGMET-IRIS";
}
public String getFileTypeId() {
return "SIGMET";
}
/**
* Check if this is a valid SIGMET-IRIS file for this IOServiceProvider.
*/
public boolean isValidFile(ucar.unidata.io.RandomAccessFile raf) {
try {
raf.order(RandomAccessFile.LITTLE_ENDIAN);
// The first struct in the file is the product_hdr, which will have the
// standard structure_header, followed by other embedded structures.
// Each of these structures also have a structure header. To validate
// the file we check for a product_hdr (by looking for type 27 in the
// structure_header), then a product_configuration structure (by looking
// for type 26 in its structure_header), then checking that that
// the product_configuration does indicate a type of RAW data (type 15)
raf.seek(0);
short[] data = new short[13];
raf.readShort(data, 0, 13);
return (data[0] == (short) 27 &&
data[6] == (short) 26 &&
data[12] ==(short) 15);
} catch (IOException ioe) {
System.out.println("In isValidFile(): " + ioe.toString());
return false;
}
}
/**
* Open existing file, and populate ncfile with it.
*/
public void open(ucar.unidata.io.RandomAccessFile raf, ucar.nc2.NetcdfFile ncfile,
ucar.nc2.util.CancelTask cancelTask) throws java.io.IOException {
super.open(raf, ncfile, cancelTask);
//java.util.Map recHdr=new java.util.HashMap();
java.util.Map hdrNames = new java.util.HashMap();
volScan = new SigmetVolumeScan(raf, ncfile, varList);
this.varList = init(raf, ncfile, hdrNames);
// doData(raf, ncfile, varList);
// raf.close();
// this.ncfile.close();
}
/**
* Read some global data from SIGMET file. The SIGMET file consists of records with
* fixed length=6144 bytes.
*/
static public java.util.Map readRecordsHdr(ucar.unidata.io.RandomAccessFile raf) {
java.util.Map recHdr1 = new java.util.HashMap();
try {
int nparams = 0;
// -- Read from of the 1st record -- 12+320+120
// -- Calculate Nyquist velocity --------------------
raf.seek(452);
int prf = raf.readInt();
raf.seek(480);
int wave = raf.readInt();
float vNyq = calcNyquist(prf, wave);
recHdr1.put("vNyq", vNyq);
// -- Read from the 2nd record----------- 6144+12(strucr_hdr)+168(from ingest_config)
raf.seek(6324);
int radar_lat = raf.readInt();
int radar_lon = raf.readInt(); //6328
short ground_height = raf.readShort(); //6332
short radar_height = raf.readShort(); //6334
raf.skipBytes(4);
short num_rays = raf.readShort(); // 6340
raf.skipBytes(2);
int radar_alt = raf.readInt(); //6344
raf.seek(6648);
int time_beg = raf.readInt();
raf.seek(6652);
int time_end = raf.readInt();
raf.seek(6772);
int data_mask = raf.readInt();
for (int j = 0; j < 32; j++) {
nparams += ((data_mask >> j) & (0x1));
}
raf.seek(6912);
short multiprf = raf.readShort();
raf.seek(7408);
int range_first = raf.readInt(); // cm 7408
int range_last = raf.readInt(); // cm 7412
raf.skipBytes(2);
short bins = raf.readShort(); //7418
if (bins % 2 != 0) bins = (short) (bins + 1);
raf.skipBytes(4);
int step = raf.readInt(); // cm 7424
raf.seek(7574);
short number_sweeps = raf.readShort(); // 7574
raf.seek(12312);
int base_time = raf.readInt(); // 3d rec
raf.skipBytes(2);
short year = raf.readShort();
short month = raf.readShort();
short day = raf.readShort();
recHdr1.put("radar_lat", calcAngle(radar_lat));
recHdr1.put("radar_lon", calcAngle(radar_lon));
recHdr1.put("range_first", range_first);
recHdr1.put("range_last", range_last);
recHdr1.put("ground_height", ground_height);
recHdr1.put("radar_height", radar_height);
recHdr1.put("radar_alt", radar_alt);
recHdr1.put("step", step);
recHdr1.put("bins", bins); //System.out.println(" bins="+bins);
recHdr1.put("num_rays", num_rays); //System.out.println(" rays="+num_rays);
recHdr1.put("nparams", nparams);//System.out.println(" nparams="+nparams);
recHdr1.put("multiprf", multiprf);
recHdr1.put("number_sweeps", number_sweeps); //System.out.println("IN HDR: number_sweeps="+number_sweeps);
recHdr1.put("year", year);
recHdr1.put("month", month);
recHdr1.put("day", day);
recHdr1.put("base_time", base_time);
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
return recHdr1;
}
/**
* Read StationName strings
*/
public java.util.Map readStnNames(ucar.unidata.io.RandomAccessFile raf) {
java.util.Map hdrNames = new java.util.HashMap();
try {
raf.seek(6288);
String stnName = raf.readString(16); //System.out.println(" stnName="+stnName.trim());
raf.seek(6306);
String stnName_util = raf.readString(16);
hdrNames.put("StationName", stnName.trim());
hdrNames.put("StationName_SetupUtility", stnName_util.trim());
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
return hdrNames;
}
/**
* Define Dimensions, Variables, Attributes in ncfile
*
* @param raf ucar.unidata.io.RandomAccessFile corresponds of SIGMET datafile.
* @param ncfile an empty NetcdfFile object which will be filled.
* @param hdrNames java.util.Map with values for "StationName.." Attributes
* @return ArrayList of Variables of ncfile
*/
public ArrayList init(ucar.unidata.io.RandomAccessFile raf, ucar.nc2.NetcdfFile ncfile,
java.util.Map hdrNames) throws java.io.IOException {
// prepare attribute values
String[] data_name = {" ", "TotalPower", "Reflectivity", "Velocity",
"Width", "Differential_Reflectivity"};
String[] unit = {" ", "dbZ", "dbZ", "m/sec", "m/sec", "dB"};
int[] type = {1, 2, 3, 4, 5};
String def_datafile = "SIGMET-IRIS";
String tim = "";
int ngates = 0;
recHdr = readRecordsHdr(raf);
hdrNames = readStnNames(raf);
String stnName = hdrNames.get("StationName");
String stnName_util = hdrNames.get("StationName_SetupUtility");
float radar_lat = recHdr.get("radar_lat").floatValue(); //System.out.println("rad_lat="+radar_lat);
float radar_lon = recHdr.get("radar_lon").floatValue(); //System.out.println("rad_lon="+radar_lon);
short ground_height = recHdr.get("ground_height").shortValue(); //System.out.println("ground_H="+ground_height);
short radar_height = recHdr.get("radar_height").shortValue(); //System.out.println("radar_H="+radar_height);
int radar_alt = (recHdr.get("radar_alt").intValue()) / 100; //System.out.println("rad_alt="+radar_alt);
short num_rays = recHdr.get("num_rays").shortValue(); //System.out.println("num_rays="+num_rays);
short bins = recHdr.get("bins").shortValue(); //System.out.println("bins="+bins);
float range_first = (recHdr.get("range_first").intValue()) * 0.01f; //System.out.println("range_1st="+range_first);
float range_last = (recHdr.get("range_last").intValue()) * 0.01f; //System.out.println("step="+step);
short number_sweeps = recHdr.get("number_sweeps").shortValue();
//System.out.println("number_sweeps="+number_sweeps);
int nparams = (recHdr.get("nparams").intValue()); //System.out.println("nparams="+nparams);
short year = recHdr.get("year").shortValue(); //System.out.println("year="+year);
short month = recHdr.get("month").shortValue();
short day = recHdr.get("day").shortValue();
int base_time = (recHdr.get("base_time").intValue());
// define number of gates for every sweep
sweep_bins = new int[nparams * number_sweeps];
if (number_sweeps > 1) {
sweep_bins = volScan.getNumberGates();
} else {
for (int kk = 0; kk < nparams; kk++) {
sweep_bins[kk] = bins;
}
}
// add Dimensions
Dimension scanR = new Dimension("scanR", number_sweeps, true);
Dimension radial = new Dimension("radial", num_rays, true);
Dimension[] gateR = new Dimension[number_sweeps];
String dim_name = "gateR";
for (int j = 0; j < number_sweeps; j++) {
if (number_sweeps > 1) {
dim_name = "gateR_sweep_" + (j + 1);
}
gateR[j] = new Dimension(dim_name, sweep_bins[j], true);
}
ncfile.addDimension(null, scanR);
ncfile.addDimension(null, radial);
for (int j = 0; j < number_sweeps; j++) {
ncfile.addDimension(null, gateR[j]);
}
ArrayList dims0 = new ArrayList();
ArrayList dims1 = new ArrayList();
ArrayList dims2 = new ArrayList();
ArrayList dims3 = new ArrayList();
ArrayList varList = new ArrayList();
Variable[][] v = new Variable[nparams][number_sweeps];
String var_name = "";
for (int j = 0; j < nparams; j++) {
int tp = type[j];
var_name = data_name[tp];
for (int jj = 0; jj < number_sweeps; jj++) {
if (number_sweeps > 1) {
var_name = data_name[tp] + "_sweep_" + (jj + 1);
}
v[j][jj] = new Variable(ncfile, null, null, var_name);
v[j][jj].setDataType(DataType.FLOAT);
dims2.add(radial);
dims2.add(gateR[jj]);
v[j][jj].setDimensions(dims2);
v[j][jj].addAttribute(new Attribute(CDM.LONG_NAME, var_name));
v[j][jj].addAttribute(new Attribute(CDM.UNITS, unit[tp]));
String coordinates = "time elevationR azimuthR distanceR";
v[j][jj].addAttribute(new Attribute(_Coordinate.Axes, coordinates));
v[j][jj].addAttribute(new Attribute(CDM.MISSING_VALUE, -999.99f));
ncfile.addVariable(null, v[j][jj]);
varList.add(v[j][jj]);
dims2.clear();
}
}
tsu_sec = new int[number_sweeps];
String[] tsu = new String[number_sweeps];
String[] time_units = new String[number_sweeps];
tsu_sec = volScan.getStartSweep();
for (int i = 0; i < number_sweeps; i++) {
String st1 = Short.toString(month);
if (st1.length() < 2) st1 = "0" + st1;
String st2 = Short.toString(day);
if (st2.length() < 2) st2 = "0" + st2;
date0 = String.valueOf(year) + "-" + st1 + "-" + st2;
tsu[i] = date0 + "T" + calcTime(tsu_sec[i], 0) + "Z";
}
for (int j = 0; j < number_sweeps; j++) {
time_units[j] = "secs since " + tsu[j];
}
dims0.add(radial);
// add "time" variable
Variable[] time = new Variable[number_sweeps];
String tm = "time";
String tm_name = "";
for (int j = 0; j < number_sweeps; j++) {
tm_name = tm;
if (number_sweeps > 1) {
tm_name = tm + "_sweep_" + (j + 1);
}
time[j] = new Variable(ncfile, null, null, tm_name);
time[j].setDataType(DataType.INT);
time[j].setDimensions(dims0);
time[j].addAttribute(new Attribute(CDM.LONG_NAME, "time from start of sweep"));
time[j].addAttribute(new Attribute(CDM.UNITS, time_units[j]));
time[j].addAttribute(new Attribute(_Coordinate.AxisType, AxisType.Time.toString()));
time[j].addAttribute(new Attribute(CDM.MISSING_VALUE, -99));
ncfile.addVariable(null, time[j]);
varList.add(time[j]);
}
// add "elevationR" variable
Variable[] elevationR = new Variable[number_sweeps];
String ele = "elevationR";
String ele_name = "";
for (int j = 0; j < number_sweeps; j++) {
ele_name = ele;
if (number_sweeps > 1) {
ele_name = ele + "_sweep_" + (j + 1);
}
elevationR[j] = new Variable(ncfile, null, null, ele_name);
elevationR[j].setDataType(DataType.FLOAT);
elevationR[j].setDimensions(dims0);
elevationR[j].addAttribute(new Attribute(CDM.LONG_NAME, "elevation angle"));
elevationR[j].addAttribute(new Attribute(CDM.UNITS, "degrees"));
elevationR[j].addAttribute(new Attribute(_Coordinate.AxisType, AxisType.RadialElevation.toString()));
elevationR[j].addAttribute(new Attribute(CDM.MISSING_VALUE, -999.99f));
ncfile.addVariable(null, elevationR[j]);
varList.add(elevationR[j]);
}
// add "azimuthR" variable
Variable[] azimuthR = new Variable[number_sweeps];
String azim = "azimuthR";
String azim_name = "";
for (int j = 0; j < number_sweeps; j++) {
azim_name = azim;
if (number_sweeps > 1) {
azim_name = azim + "_sweep_" + (j + 1);
}
azimuthR[j] = new Variable(ncfile, null, null, azim_name);
azimuthR[j].setDataType(DataType.FLOAT);
azimuthR[j].setDimensions(dims0);
azimuthR[j].addAttribute(new Attribute(CDM.LONG_NAME, "azimuth angle"));
azimuthR[j].addAttribute(new Attribute(CDM.UNITS, "degrees"));
azimuthR[j].addAttribute(new Attribute(_Coordinate.AxisType, AxisType.RadialAzimuth.toString()));
azimuthR[j].addAttribute(new Attribute(CDM.MISSING_VALUE, -999.99f));
ncfile.addVariable(null, azimuthR[j]);
varList.add(azimuthR[j]);
}
// add "distanceR" variable
Variable[] distanceR = new Variable[number_sweeps];
String dName = "distanceR";
String dist_name = "";
for (int j = 0; j < number_sweeps; j++) {
dist_name = dName;
if (number_sweeps > 1) {
dist_name = dName + "_sweep_" + (j + 1);
}
distanceR[j] = new Variable(ncfile, null, null, dist_name);
distanceR[j].setDataType(DataType.FLOAT);
dims1.add(gateR[j]);
distanceR[j].setDimensions(dims1);
distanceR[j].addAttribute(new Attribute(CDM.LONG_NAME, "radial distance"));
distanceR[j].addAttribute(new Attribute(CDM.UNITS, "m"));
distanceR[j].addAttribute(new Attribute(_Coordinate.AxisType, AxisType.RadialDistance.toString()));
ncfile.addVariable(null, distanceR[j]);
varList.add(distanceR[j]);
dims1.clear();
}
// add "numGates" variable
dims3.add(scanR);
Variable numGates = new Variable(ncfile, null, null, "numGates");
numGates.setDataType(DataType.INT);
numGates.setDimensions(dims3);
numGates.addAttribute(new Attribute(CDM.LONG_NAME, "number of gates in the sweep"));
ncfile.addVariable(null, numGates);
varList.add(numGates);
// add global attributes
ncfile.addAttribute(null, new Attribute("definition", "SIGMET-IRIS RAW"));
ncfile.addAttribute(null, new Attribute("description", "SIGMET-IRIS data are reading by Netcdf IOSP"));
ncfile.addAttribute(null, new Attribute("StationName", stnName));
ncfile.addAttribute(null, new Attribute("StationName_SetupUtility", stnName_util));
ncfile.addAttribute(null, new Attribute("radar_lat", radar_lat));
ncfile.addAttribute(null, new Attribute("radar_lon", radar_lon));
ncfile.addAttribute(null, new Attribute("ground_height", ground_height));
ncfile.addAttribute(null, new Attribute("radar_height", radar_height));
ncfile.addAttribute(null, new Attribute("radar_alt", radar_alt));
ncfile.addAttribute(null, new Attribute("num_data_types", nparams));
ncfile.addAttribute(null, new Attribute("number_sweeps", number_sweeps));
String sn = "start_sweep";
String snn = "";
for (int j = 0; j < number_sweeps; j++) {
snn = sn;
if (number_sweeps > 1) {
snn = sn + "_" + (j + 1);
}
ncfile.addAttribute(null, new Attribute(snn, tsu[j]));
}
ncfile.addAttribute(null, new Attribute("num_rays", num_rays));
ncfile.addAttribute(null, new Attribute("max_number_gates", bins));
ncfile.addAttribute(null, new Attribute("range_first", range_first));
ncfile.addAttribute(null, new Attribute("range_last", range_last));
ncfile.addAttribute(null, new Attribute("DataType", "Radial"));
ncfile.addAttribute(null, new Attribute(CDM.CONVENTIONS, _Coordinate.Convention));
// --------- fill all of values in the ncfile ------
doNetcdfFileCoordinate(ncfile, volScan.base_time, volScan.year, volScan.month, volScan.day, varList, recHdr);
ncfile.finish();
return varList;
}
/**
* Fill all of the variables/attributes in the ncfile
*
* @param ncfile NetcdfFile object which will be filled.
* @param bst number of seconds since midnight for start of sweep
* @param yr year of start of each sweep
* @param m month of start of each sweep
* @param dda day of start of each sweep
* @param varList ArrayList of Variables of ncfile
* @param recHdr java.util.Map with values for Attributes
*/
public void doNetcdfFileCoordinate(ucar.nc2.NetcdfFile ncfile, int[] bst,
short[] yr, short[] m, short[] dda,
ArrayList varList, java.util.Map recHdr) {
// prepare attribute values
String[] unit = {" ", "dbZ", "dbZ", "m/sec", "m/sec", "dB"};
String def_datafile = "SIGMET-IRIS";
Short header_length = 80;
Short ray_header_length = 6;
int ngates = 0;
float radar_lat = recHdr.get("radar_lat").floatValue(); //System.out.println("rad_lat="+radar_lat);
float radar_lon = recHdr.get("radar_lon").floatValue(); //System.out.println("rad_lon="+radar_lon);
short ground_height = recHdr.get("ground_height").shortValue(); //System.out.println("ground_H="+ground_height);
short radar_height = recHdr.get("radar_height").shortValue(); //System.out.println("radar_H="+radar_height);
int radar_alt = (recHdr.get("radar_alt").intValue()) / 100; //System.out.println("rad_alt="+radar_alt);
short num_rays = recHdr.get("num_rays").shortValue(); //System.out.println("HERE!! num_rays="+num_rays);
float range_first = (recHdr.get("range_first").intValue()) * 0.01f; //System.out.println("range_1st="+range_first);
float range_last = (recHdr.get("range_last").intValue()) * 0.01f; //System.out.println("step="+step);
short number_sweeps = recHdr.get("number_sweeps").shortValue();
int nparams = (recHdr.get("nparams").intValue()); //System.out.println("nparams="+nparams);
// define date/time
//int last_t=(int)(ray[nparams*number_sweeps-1][num_rays-1].getTime());
int last_t = volScan.lastRay.getTime();
String sss1 = Short.toString(m[0]);
if (sss1.length() < 2) sss1 = "0" + sss1;
String sss2 = Short.toString(dda[0]);
if (sss2.length() < 2) sss2 = "0" + sss2;
String base_date0 = String.valueOf(yr[0]) + "-" + sss1 + "-" + sss2;
String sss11 = Short.toString(m[number_sweeps - 1]);
if (sss11.length() < 2) sss11 = "0" + sss11;
String sss22 = Short.toString(dda[number_sweeps - 1]);
if (sss22.length() < 2) sss22 = "0" + sss22;
String base_date1 = String.valueOf(yr[number_sweeps - 1]) + "-" + sss11 + "-" + sss22;
String start_time = base_date0 + "T" + calcTime(bst[0], 0) + "Z";
String end_time = base_date1 + "T" + calcTime(bst[number_sweeps - 1], last_t) + "Z";
ncfile.addAttribute(null, new Attribute("time_coverage_start", start_time));
ncfile.addAttribute(null, new Attribute("time_coverage_end", end_time));
// set all of Variables
try {
int sz = varList.size();
ArrayFloat.D2[] dataArr = new ArrayFloat.D2[nparams * number_sweeps];
Index[] dataIndex = new Index[nparams * number_sweeps];
Ray[] rtemp = new Ray[(int) num_rays];
// NCdump.printArray(dataArr[0], "Total_Power", System.out, null);
Variable[] distanceR = new Variable[number_sweeps];
ArrayFloat.D1[] distArr = new ArrayFloat.D1[number_sweeps];
Index[] distIndex = new Index[number_sweeps];
String distName = "distanceR";
for (int i = 0; i < number_sweeps; i++) {
if (number_sweeps > 1) {
distName = "distanceR_sweep_" + (i + 1);
}
for (Variable aVarList : varList) {
if ((aVarList.getShortName()).equals(distName.trim())) {
distanceR[i] = aVarList;
break;
}
}
distArr[i] = (ArrayFloat.D1) Array.factory(DataType.FLOAT, distanceR[i].getShape());
distIndex[i] = distArr[i].getIndex();
// for (int jj=0; jj 1) {
t_n = "time_sweep_" + (i + 1);
}
for (Variable aVarList : varList) {
if ((aVarList.getShortName()).equals(t_n.trim())) {
time[i] = aVarList;
break;
}
}
// if (time[i].getShape().length == 0) {
// continue;
// }
timeArr[i] = (ArrayInt.D1) Array.factory(DataType.INT, time[i].getShape());
timeIndex[i] = timeArr[i].getIndex();
List rlist = sgp[i];
for (int jj = 0; jj < num_rays; jj++) {
rtemp[jj] = (Ray) rlist.get(jj);
} //ray[i][jj]; }
for (int jj = 0; jj < num_rays; jj++) {
timeArr[i].setInt(timeIndex[i].set(jj), rtemp[jj].getTime());
}
}
// NCdump.printArray(timeArr[0], "time", System.out, null);
Variable[] azimuthR = new Variable[number_sweeps];
ArrayFloat.D1[] azimArr = new ArrayFloat.D1[number_sweeps];
Index[] azimIndex = new Index[number_sweeps];
String azimName = "azimuthR";
for (int i = 0; i < number_sweeps; i++) {
if (number_sweeps > 1) {
azimName = "azimuthR_sweep_" + (i + 1);
}
for (Variable aVarList : varList) {
if ((aVarList.getShortName()).equals(azimName.trim())) {
azimuthR[i] = aVarList;
break;
}
}
azimArr[i] = (ArrayFloat.D1) Array.factory(DataType.FLOAT, azimuthR[i].getShape());
azimIndex[i] = azimArr[i].getIndex();
List rlist = sgp[i];
for (int jj = 0; jj < num_rays; jj++) {
rtemp[jj] = (Ray) rlist.get(jj);
} //ray[i][jj]; }
for (int jj = 0; jj < num_rays; jj++) {
azimArr[i].setFloat(azimIndex[i].set(jj), rtemp[jj].getAz());
}
}
//NCdump.printArray(azimArr[0], "azimuthR", System.out, null);
Variable[] elevationR = new Variable[number_sweeps];
ArrayFloat.D1[] elevArr = new ArrayFloat.D1[number_sweeps];
Index[] elevIndex = new Index[number_sweeps];
String elevName = "elevationR";
for (int i = 0; i < number_sweeps; i++) {
if (number_sweeps > 1) {
elevName = "elevationR_sweep_" + (i + 1);
}
for (Variable aVarList : varList) {
if ((aVarList.getShortName()).equals(elevName.trim())) {
elevationR[i] = aVarList;
break;
}
}
elevArr[i] = (ArrayFloat.D1) Array.factory(DataType.FLOAT, elevationR[i].getShape());
elevIndex[i] = elevArr[i].getIndex();
List rlist = sgp[i];
for (int jj = 0; jj < num_rays; jj++) {
rtemp[jj] = (Ray) rlist.get(jj);
} //ray[i][jj]; }
for (int jj = 0; jj < num_rays; jj++) {
elevArr[i].setFloat(elevIndex[i].set(jj), rtemp[jj].getElev());
}
}
// NCdump.printArray(elevArr[0], "elevationR", System.out, null);
Variable numGates = null;
for (int i = 0; i < number_sweeps; i++) {
for (Variable aVarList : varList) {
if ((aVarList.getShortName()).equals("numGates")) {
numGates = aVarList;
break;
}
}
}
ArrayInt.D1 gatesArr = (ArrayInt.D1) Array.factory(DataType.INT, numGates.getShape());
Index gatesIndex = gatesArr.getIndex();
for (int i = 0; i < number_sweeps; i++) {
List rlist = sgp[i];
for (int jj = 0; jj < num_rays; jj++) {
rtemp[jj] = (Ray) rlist.get(jj);
} //ray[i][jj]; }
ngates = rtemp[0].getBins();
gatesArr.setInt(gatesIndex.set(i), ngates);
}
for (int i = 0; i < number_sweeps; i++) {
distanceR[i].setCachedData(distArr[i], false);
time[i].setCachedData(timeArr[i], false);
azimuthR[i].setCachedData(azimArr[i], false);
elevationR[i].setCachedData(elevArr[i], false);
}
numGates.setCachedData(gatesArr, false);
// startSweep.setCachedData(sweepArr, false);
// -------------------------------------------------
// int b=(int)ray[0][0].getBins();
// -- Test of readData() and readToByteChannel() -----------------
/*
Range r1=new Range(356, 359);
Range r2=new Range(0, 15);
java.util.List arlist=new ArrayList();
arlist.add(r1);
arlist.add(r2);
Array testArr=readData(v[0], new Section(arlist));
NCdump.printArray(testArr, "Total_Power_sweep_1", System.out, null);
WritableByteChannel channel=new FileOutputStream(new File("C:\\netcdf\\tt.dat")).getChannel();
long ikk=readToByteChannel(v[0], new Section(arlist), channel);
System.out.println("IKK="+ikk);
channel.close();
*/
//---------------------------------------------------
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
} //----------- end of doNetcdf ----------------------------------
/**
* Read data from a top level Variable and return a memory resident Array.
*
* @param v2 Variable. It may have FLOAT/INTEGER data type.
* @param section wanted section of data of Variable. The section list is a list
* of ucar.ma2.Range which define the requested data subset.
* @return Array of data which will be read from Variable through this call.
*/
public Array readData1(ucar.nc2.Variable v2, Section section)
throws IOException, InvalidRangeException {
//doData(raf, ncfile, varList);
int[] sh = section.getShape();
Array temp = Array.factory(v2.getDataType(), sh);
long pos0 = 0;
// Suppose that the data has LayoutRegular
LayoutRegular index = new LayoutRegular(pos0, v2.getElementSize(), v2.getShape(), section);
if (v2.getShortName().startsWith("time") | v2.getShortName().startsWith("numGates")) {
temp = readIntData(index, v2);
} else {
temp = readFloatData(index, v2);
}
return temp;
}
public Array readData(Variable v2, Section section) throws IOException, InvalidRangeException {
// Vgroup vgroup = (Vgroup) v2.getSPobject();
// Range scanRange = section.getRange(0);
// Range radialRange = section.getRange(1);
// Range gateRange = section.getRange(2);
Array data = Array.factory(v2.getDataType(), section.getShape());
IndexIterator ii = data.getIndexIterator();
List> groups;
String shortName = v2.getShortName();
if (shortName.startsWith("Reflectivity"))
groups = volScan.getReflectivityGroups();
else if (shortName.startsWith("Velocity"))
groups = volScan.getVelocityGroups();
else if (shortName.startsWith("TotalPower"))
groups = volScan.getTotalPowerGroups();
else if (shortName.startsWith("Width"))
groups = volScan.getWidthGroups();
else if (shortName.startsWith("DiffReflectivity"))
groups = volScan.getDifferentialReflectivityGroups();
else
throw new IllegalStateException("Illegal variable name = "+shortName);
if (section.getRank() == 2) {
Range radialRange = section.getRange(0);
Range gateRange = section.getRange(1);
List lli = groups.get(0);
readOneScan(lli, radialRange, gateRange, ii);
} else {
Range scanRange = section.getRange(0);
Range radialRange = section.getRange(1);
Range gateRange = section.getRange(2);
for (int scanIdx : scanRange) {
readOneScan( groups.get(scanIdx), radialRange, gateRange, ii);
}
}
return data;
}
private void readOneScan(List mapScan, Range radialRange, Range gateRange, IndexIterator ii) throws IOException {
int siz = mapScan.size();
for (int radialIdx : radialRange) {
if (radialIdx >= siz)
readOneRadial(null, gateRange, ii);
else {
Ray r = mapScan.get(radialIdx);
readOneRadial(r, gateRange, ii);
}
}
}
private void readOneRadial(Ray r, Range gateRange, IndexIterator ii) throws IOException {
if (r == null) {
for (int i = 0; i < gateRange.length(); i++)
ii.setFloatNext(Float.NaN);
return;
}
r.readData(volScan.raf, gateRange, ii);
}
/**
* Read data from a top level Variable of INTEGER data type and return a memory resident Array.
*
* @param index LayoutRegular object
* @param v2 Variable has INTEGER data type.
* @return Array of data which will be read from Variable through this call.
*/
public Array readIntData(LayoutRegular index, Variable v2) throws IOException {
int[] var = (int[]) (v2.read().get1DJavaArray(v2.getDataType()));
int[] data = new int[(int) index.getTotalNelems()];
while (index.hasNext()) {
Layout.Chunk chunk = index.next();
System.arraycopy(var, (int) chunk.getSrcPos() / 4, data, (int) chunk.getDestElem(), chunk.getNelems());
}
return Array.factory(v2.getDataType(), new int[] {(int) index.getTotalNelems()}, data);
}
/**
* Read data from a top level Variable of FLOAT data type and return a memory resident Array.
*
* @param index LayoutRegular object
* @param v2 Variable has FLOAT data type.
* @return Array of data which will be read from Variable through this call.
*/
public Array readFloatData(LayoutRegular index, Variable v2)
throws IOException {
float[] var = (float[]) (v2.read().get1DJavaArray(v2.getDataType().getPrimitiveClassType()));
float[] data = new float[(int) index.getTotalNelems()];
while (index.hasNext()) {
Layout.Chunk chunk = index.next();
System.arraycopy(var, (int) chunk.getSrcPos() / 4, data,
(int) chunk.getDestElem(), chunk.getNelems());
}
return Array.factory(v2.getDataType(), new int[]{(int) index.getTotalNelems()}, data);
}
//----------------------------------------------------------------------------------
/**
* Read data from a top level Variable and send data to a WritableByteChannel.
*
* @param v2 Variable
* @param section wanted section of data of Variable. The section list is a list
* of ucar.ma2.Range which define the requested data subset.
* @param channel WritableByteChannel object - channel that can write bytes.
* @return the number of bytes written, possibly zero.
*/
public long readToByteChannel11(ucar.nc2.Variable v2, Section section, WritableByteChannel channel)
throws java.io.IOException, ucar.ma2.InvalidRangeException {
Array data = readData(v2, section);
float[] ftdata = new float[(int) data.getSize()];
byte[] bytedata = new byte[(int) data.getSize() * 4];
IndexIterator iter = data.getIndexIterator();
int i = 0;
ByteBuffer buffer = ByteBuffer.allocateDirect(bytedata.length);
while (iter.hasNext()) {
ftdata[i] = iter.getFloatNext();
bytedata[i] = new Float(ftdata[i]).byteValue();
buffer.put(bytedata[i]);
i++;
}
buffer = ByteBuffer.wrap(bytedata);
// write the bytes to the channel
int count = channel.write(buffer);
System.out.println("COUNT=" + count);
// check if all bytes where written
if (buffer.hasRemaining()) {
// if not all bytes were written, move the unwritten bytes to the beginning and
// set position just after the last unwritten byte
buffer.compact();
} else {
buffer.clear();
}
return (long) count;
}
// -----------------------------------------------------------------------
/**
* Convert 2 bytes binary angle to float
*
* @param angle two bytes binary angle
* @return float value of angle in degrees with precision of two decimal
*/
static float calcAngle(short angle) {
final double maxval = 65536.0;
double ang = (double) angle;
if (ang < 0.0) {
ang = maxval + ang;
}
double temp = (ang / maxval) * 360.0;
BigDecimal bd = new BigDecimal(temp);
BigDecimal result = bd.setScale(2, RoundingMode.HALF_DOWN);
return result.floatValue();
}
/**
* Convert 4 bytes binary angle to float
*
* @param ang four bytes binary angle
* @return float value of angle with precision of two decimal in degrees
*/
static float calcAngle(int ang) {
final double maxval = 4294967296.0;
double temp = (ang / maxval) * 360.0;
BigDecimal bd = new BigDecimal(temp);
BigDecimal result = bd.setScale(3, RoundingMode.HALF_DOWN);
return result.floatValue();
}
/**
* Calculate radial elevation of each ray
*
* @param angle two bytes binary angle
* @return float value of elevation in degrees with precision of two decimal
*/
static float calcElev(short angle) {
final double maxval = 65536.0;
double ang = (double) angle;
if (angle < 0) ang = (~angle) + 1;
double temp = (ang / maxval) * 360.0;
BigDecimal bd = new BigDecimal(temp);
BigDecimal result = bd.setScale(2, RoundingMode.HALF_DOWN);
return result.floatValue();
}
/**
* Calculate distance between sequential bins in a ray
*
* @param range_first range of first bin in centimeters
* @param range_last range of last bin in centimeters
* @param num_bins number of bins
* @return float distance in centimeters with precision of two decimal
*/
static float calcStep(float range_first, float range_last, short num_bins) {
float step = (range_last - range_first) / (num_bins - 1);
BigDecimal bd = new BigDecimal(step);
BigDecimal result = bd.setScale(2, RoundingMode.HALF_DOWN);
return result.floatValue();
}
/**
* Calculate azimuth of a ray
*
* @param az0 azimuth at beginning of ray (binary angle)
* @param az1 azimuth at end of ray (binary angle)
* @return float azimuth in degrees with precision of two decimal
*/
static float calcAz(short az0, short az1) {
// output in deg
float azim0 = calcAngle(az0);
float azim1 = calcAngle(az1);
float d = 0.0f;
d = Math.abs(azim0 - azim1);
if ((az0 < 0) & (az1 > 0)) {
d = Math.abs(360.0f - azim0) + Math.abs(azim1);
}
double temp = azim0 + d * 0.5;
if (temp > 360.0) {
temp -= 360.0;
}
BigDecimal bd = new BigDecimal(temp);
BigDecimal result = bd.setScale(2, RoundingMode.HALF_DOWN);
return result.floatValue();
}
/**
* Calculate data values from raw ingest data
*
* @param recHdr java.util.Map object with values for calculation
* @param dty type of data ( "Total_Power", "Reflectivity", "Velocity",
* "Width", "Differential_Reflectivity")
* @param data 1-byte input value
* @return float value with precision of two decimal
*/
static float calcData(Map recHdr, short dty, byte data) {
short[] coef = {1, 2, 3, 4}; // MultiPRF modes
short multiprf = recHdr.get("multiprf").shortValue();
float vNyq = recHdr.get("vNyq").floatValue();
double temp = -999.99;
switch (dty) {
default: // dty=1,2 -total_power, reflectivity (dBZ)
if (data != 0) {
temp = (((int) data & 0xFF) - 64) * 0.5;
}
break;
case 3: // dty=3 - mean velocity (m/sec)
if (data != 0) {
temp = ((((int) data & 0xFF) - 128) / 127.0) * vNyq * coef[multiprf];
}
break;
case 4: // dty=4 - spectrum width (m/sec)
if (data != 0) {
double v = ((((int) data & 0xFF) - 128) / 127.0) * vNyq * coef[multiprf];
temp = (((int) data & 0xFF) / 256.0) * v;
}
break;
case 5: // dty=5 - differential reflectivity (dB)
if (data != 0) {
temp = ((((int) data & 0xFF) - 128) / 16.0);
}
break;
}
BigDecimal bd = new BigDecimal(temp);
BigDecimal result = bd.setScale(2, RoundingMode.HALF_DOWN);
return result.floatValue();
}
/**
* Calculate time as hh:mm:ss
*
* @param t number of seconds since midnight for start of sweep
* @param t0 time in seconds from start of sweep
* @return time as string "hh:mm:ss"
*/
static String calcTime(int t, int t0) {
StringBuilder tim = new StringBuilder();
int[] tt = new int[3];
int mmh = (t + t0) / 60;
tt[2] = (t + t0) % 60; // Define SEC
tt[0] = mmh / 60; // Define HOUR
tt[1] = mmh % 60; // Define MIN
for (int i = 0; i < 3; i++) {
String s = Integer.toString(tt[i]);
int len = s.length();
if (len < 2) {
s = "0" + tt[i];
}
if (i != 2) s += ":";
tim.append(s);
}
return tim.toString();
}
/**
* Calculate of Nyquist velocity
*
* @param prf PRF in Hertz
* @param wave wavelength in 1/100 of centimeters
* @return float value of Nyquist velocity in m/sec with precision of two decimal
*/
static float calcNyquist(int prf, int wave) {
double tmp = (prf * wave * 0.01) * 0.25;
tmp = tmp * 0.01; //Make it m/sec
BigDecimal bd = new BigDecimal(tmp);
BigDecimal result = bd.setScale(2, RoundingMode.HALF_DOWN);
return result.floatValue();
}
}