ucar.nc2.iosp.dorade.Doradeheader Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
// $Id:Doradeheader.java 63 2006-07-12 21:50:51Z edavis $
package ucar.nc2.iosp.dorade;
import ucar.nc2.*;
import ucar.nc2.constants.*;
import ucar.ma2.Array;
import ucar.ma2.DataType;
import ucar.ma2.MAMath;
import ucar.atd.dorade.*;
import java.io.*;
import java.util.*;
public class Doradeheader {
private boolean debug = false;
private ucar.nc2.NetcdfFile ncfile;
private float[] lat_min, lat_max, lon_min, lon_max, hi_max, hi_min;
static public boolean isValidFile(ucar.unidata.io.RandomAccessFile raf) {
try {
java.io.RandomAccessFile file = raf.getRandomAccessFile();
if (file == null) return false;
boolean t = DoradeSweep.isDoradeSweep(file);
if (!t) return false;
} catch (DoradeSweep.DoradeSweepException ex) {
return false;
}
return true;
}
void read(DoradeSweep mySweep, ucar.nc2.NetcdfFile ncfile, PrintStream out) throws IOException {
this.ncfile = ncfile;
DoradePARM[] parms = mySweep.getParamList();
int nRays = mySweep.getNRays();
if (debug) System.out.println(parms.length + " params in file");
int numSensor = mySweep.getNSensors();
int[] ncells = new int[numSensor];
Dimension[] gateDim = new Dimension[numSensor];
for (int i = 0; i < numSensor; i++) {
try {
int j = i + 1;
ncells[i] = mySweep.getNCells(i);
gateDim[i] = new Dimension("gate_" + j, ncells[i]);
ncfile.addDimension(null, gateDim[i]);
} catch (Exception ex) {
ex.printStackTrace();
}
}
ArrayList[] dims = new ArrayList[numSensor];
ArrayList dims1 = new ArrayList();
ArrayList[] dims2 = new ArrayList[numSensor];
int nCells = mySweep.getNCells(0);
// Dimension sensorDim = new Dimension("sensor", numSensor, true);
// ncfile.addDimension( null, sensorDim);
Dimension radialDim = new Dimension("radial", nRays);
ncfile.addDimension(null, radialDim);
for (int i = 0; i < numSensor; i++) {
dims[i] = new ArrayList();
dims2[i] = new ArrayList();
dims[i].add(radialDim);
dims[i].add(gateDim[i]);
dims2[i].add(gateDim[i]);
}
// dims1.add( sensorDim);
dims1.add(radialDim);
float[][] altitudes = new float[numSensor][];
float[][] latitudes = new float[numSensor][];
float[][] longitudes = new float[numSensor][];
lat_min = new float[numSensor];
lat_max = new float[numSensor];
lon_min = new float[numSensor];
lon_max = new float[numSensor];
hi_min = new float[numSensor];
hi_max = new float[numSensor];
MAMath.MinMax[] latMinMax = new MAMath.MinMax[numSensor];
MAMath.MinMax[] lonMinMax = new MAMath.MinMax[numSensor];
MAMath.MinMax[] hiMinMax = new MAMath.MinMax[numSensor];
boolean[] isMoving = new boolean[numSensor];
for (int i = 0; i < numSensor; i++) {
try {
int nc = mySweep.getNCells(i);
altitudes[i] = new float[nRays];
latitudes[i] = new float[nRays];
longitudes[i] = new float[nRays];
isMoving[i] = mySweep.sensorIsMoving(i);
altitudes[i] = mySweep.getAltitudes(i);
latitudes[i] = mySweep.getLatitudes(i);
longitudes[i] = mySweep.getLongitudes(i);
} catch (Exception ex) {
ex.printStackTrace();
}
latMinMax[i] = getMinMaxData(latitudes[i]);
lonMinMax[i] = getMinMaxData(longitudes[i]);
hiMinMax[i] = getMinMaxData(altitudes[i]);
float dis = (float) ((mySweep.getRangeToFirstCell(i) + (mySweep.getNCells(i) - 1) * mySweep.getCellSpacing(i)) * 1.853 / 111.26 / 1000);
lat_min[i] = (float) (latMinMax[i].min - dis);
lat_max[i] = (float) (latMinMax[i].max + dis);
lon_min[i] = (float) (lonMinMax[i].min + dis * Math.cos(latitudes[i][0]));
lon_max[i] = (float) (lonMinMax[i].max - dis * Math.cos(latitudes[i][0]));
hi_min[i] = (float) hiMinMax[i].min;
hi_max[i] = (float) hiMinMax[i].max;
}
//adding the global nc attribute
addNCAttributes(ncfile, mySweep);
// add elevation coordinate variable
String vName = "elevation";
String lName = "elevation angle in degres: 0 = parallel to pedestal base, 90 = perpendicular";
Attribute att = new Attribute(_Coordinate.AxisType, AxisType.RadialElevation.toString());
addParameter(vName, lName, ncfile, dims1, att, DataType.FLOAT, "degrees");
// add azimuth coordinate variable
vName = "azimuth";
lName = "azimuth angle in degrees: 0 = true north, 90 = east";
att = new Attribute(_Coordinate.AxisType, AxisType.RadialAzimuth.toString());
addParameter(vName, lName, ncfile, dims1, att, DataType.FLOAT, "degrees");
// add gate coordinate variable
for (int i = 0; i < numSensor; i++) {
int j = i + 1;
vName = "distance_" + j;
lName = "Radial distance to the start of gate";
att = new Attribute(_Coordinate.AxisType, AxisType.RadialDistance.toString());
addParameter(vName, lName, ncfile, dims2[i], att, DataType.FLOAT, "meters");
}
// add radial coordinate variable
for (int i = 0; i < numSensor; i++) {
int j = i + 1;
vName = "latitudes_" + j;
lName = "Latitude of the instrument " + j;
att = new Attribute(_Coordinate.AxisType, AxisType.Lat.toString());
addParameter(vName, lName, ncfile, dims1, att, DataType.FLOAT, "degrees");
vName = "longitudes_" + j;
lName = "Longitude of the instrument " + j;
att = new Attribute(_Coordinate.AxisType, AxisType.Lon.toString());
addParameter(vName, lName, ncfile, dims1, att, DataType.FLOAT, "degrees");
vName = "altitudes_" + j;
lName = "Altitude in meters (asl) of the instrument " + j;
att = new Attribute(_Coordinate.AxisType, AxisType.Height.toString());
addParameter(vName, lName, ncfile, dims1, att, DataType.FLOAT, "meters");
vName = "rays_time";
lName = "rays time";
att = new Attribute(_Coordinate.AxisType, AxisType.Time.toString());
addParameter(vName, lName, ncfile, dims1, att, DataType.DOUBLE, "milliseconds since 1970-01-01 00:00 UTC");
}
vName = "Range_to_First_Cell";
lName = "Range to the center of the first cell";
addParameter(vName, lName, ncfile, null, null, DataType.FLOAT, "meters");
vName = "Cell_Spacing";
lName = "Distance between cells";
addParameter(vName, lName, ncfile, null, null, DataType.FLOAT, "meters");
vName = "Fixed_Angle";
lName = "Targeted fixed angle for this scan";
addParameter(vName, lName, ncfile, null, null, DataType.FLOAT, "degrees");
vName = "Nyquist_Velocity";
lName = "Effective unambigous velocity";
addParameter(vName, lName, ncfile, null, null, DataType.FLOAT, "m/s");
vName = "Unambiguous_Range";
lName = "Effective unambigous range";
addParameter(vName, lName, ncfile, null, null, DataType.FLOAT, "meters");
vName = "Radar_Constant";
lName = "Radar constant";
addParameter(vName, lName, ncfile, null, null, DataType.FLOAT, "c");
vName = "rcvr_gain";
lName = "Receiver Gain";
addParameter(vName, lName, ncfile, null, null, DataType.FLOAT, "db");
vName = "ant_gain";
lName = "Antenna Gain";
addParameter(vName, lName, ncfile, null, null, DataType.FLOAT, "db");
vName = "sys_gain";
lName = "System Gain";
addParameter(vName, lName, ncfile, null, null, DataType.FLOAT, "db");
vName = "bm_width";
lName = "Beam Width";
addParameter(vName, lName, ncfile, null, null, DataType.FLOAT, "degrees");
/* Variable ct = new Variable(ncfile, null, null, "radialCoordinateTransform");
ct.setDataType(DataType.CHAR);
ct.setDimensions(""); // scalar
ct.addAttribute( new Attribute("transform_type", "Radial"));
ct.addAttribute( new Attribute("_CoordinateTransformType", "Radial"));
ct.addAttribute( new Attribute("_CoordinateAxes", "elevation azimuth distance_1"));
ncfile.addVariable(null, ct); */
try {
for (int p = 0; p < parms.length; p++) {
String pval = parms[p].getDescription();
nCells = parms[p].getNCells();
int ii = getGateDimsIndex(nCells, gateDim, numSensor);
if (debug) System.out.println("Param " + p + " name " + pval + " and ncel " + nCells);
addVariable(ncfile, dims[ii], parms[p]);
}
} catch (Exception ex) {
ex.printStackTrace();
}
// finish
ncfile.finish();
}
public MAMath.MinMax getMinMaxData(float[] data) {
int[] shape = new int[1];
shape[0] = data.length;
Array a = Array.factory(DataType.FLOAT, shape, data);
return MAMath.getMinMax(a);
}
int getGateDimsIndex(int cell, Dimension[] dList, int numSensor) {
int j = 0;
for (int i = 0; i < numSensor; i++) {
Dimension d = new Dimension("gate_" + i, cell);
if (dList[i].equals(d)) {
j = i;
break;
}
}
return j;
}
private void makeCoordinateData(Variable elev, Variable azim, DoradeSweep mySweep) {
Object ele = mySweep.getElevations();
Object azi = mySweep.getAzimuths();
Array elevData = Array.factory(elev.getDataType(), elev.getShape(), ele);
Array aziData = Array.factory(azim.getDataType(), azim.getShape(), azi);
elev.setCachedData(elevData, false);
azim.setCachedData(aziData, false);
}
void addParameter(String pName, String longName, NetcdfFile nc, ArrayList dims, Attribute att, DataType dtype, String ut) {
Variable vVar = new Variable(nc, null, null, pName);
vVar.setDataType(dtype);
if (dims != null) vVar.setDimensions(dims);
else vVar.setDimensions("");
if (att != null) vVar.addAttribute(att);
vVar.addAttribute(new Attribute(CDM.UNITS, ut));
vVar.addAttribute(new Attribute(CDM.LONG_NAME, longName));
nc.addVariable(null, vVar);
}
void addVariable(NetcdfFile nc, ArrayList dims, DoradePARM dparm) {
Variable v = new Variable(nc, null, null, dparm.getName());
v.setDataType(DataType.FLOAT);
v.setDimensions(dims);
ncfile.addVariable(null, v);
v.addAttribute(new Attribute(CDM.LONG_NAME, dparm.getDescription()));
v.addAttribute(new Attribute(CDM.UNITS, dparm.getUnits()));
String coordinates = "elevation azimuth distance_1 " + "latitudes_1 longitudes_1 altitudes_1";
v.addAttribute(new Attribute(_Coordinate.Axes, coordinates));
/*
v.addAttribute( new Attribute(CDM.MISSING_VALUE, new Float(dparm.getBadDataFlag())));
v.addAttribute( new Attribute("_FillValue", new Float(dparm.getBadDataFlag())));
v.addAttribute( new Attribute("scale_factor", dparm.getUnits()));
v.addAttribute( new Attribute("polarization", dparm.getUnits()));
v.addAttribute( new Attribute("Frequencies_GHz", dparm.getUnits()));
v.addAttribute( new Attribute("InterPulsePeriods_secs", dparm.getUnits()));
v.addAttribute( new Attribute("ThresholdValue", new Float(dparm.getThresholdValue())));
v.addAttribute( new Attribute("ThresholdParamName", dparm.getthresholdParamName()));
v.addAttribute( new Attribute("usedPRTs", new Integer(dparm.getusedPRTs())));
v.addAttribute( new Attribute("usedFrequencies", new Integer(dparm.getusedFrequencies())));
*/
}
void addNCAttributes(NetcdfFile nc, DoradeSweep mySweep) throws DoradeSweep.DoradeSweepException {
nc.addAttribute(null, new Attribute("summary", "Dorade radar data " +
"from radar " + mySweep.getSensorName(0) + " in the project " + mySweep.getProjectName()));
nc.addAttribute(null, new Attribute("radar_name", mySweep.getSensorName(0)));
nc.addAttribute(null, new Attribute("project_name", mySweep.getProjectName()));
nc.addAttribute(null, new Attribute("keywords_vocabulary", "dorade"));
nc.addAttribute(null, new Attribute("geospatial_lat_min", lat_min[0]));
nc.addAttribute(null, new Attribute("geospatial_lat_max", lat_max[0]));
nc.addAttribute(null, new Attribute("geospatial_lon_min", lon_min[0]));
nc.addAttribute(null, new Attribute("geospatial_lon_max", lon_max[0]));
nc.addAttribute(null, new Attribute("geospatial_vertical_min", lon_min[0]));
nc.addAttribute(null, new Attribute("geospatial_vertical_max", lon_max[0]));
Date[] dd = mySweep.getTimes();
if (dd != null) {
nc.addAttribute(null, new Attribute("time_coverage_start", dd[0].toString()));
nc.addAttribute(null, new Attribute("time_coverage_end", dd[dd.length - 1].toString()));
}
nc.addAttribute(null, new Attribute("Content", "This file contains one scan of remotely sensed data"));
nc.addAttribute(null, new Attribute(CDM.CONVENTIONS, _Coordinate.Convention));
nc.addAttribute(null, new Attribute(CF.FEATURE_TYPE, FeatureType.RADIAL.toString()));
nc.addAttribute(null, new Attribute("format", "Unidata/netCDF/Dorade"));
nc.addAttribute(null, new Attribute("Radar_Name", mySweep.getSensorName(0)));
nc.addAttribute(null, new Attribute("Project_name", "" + mySweep.getProjectName()));
nc.addAttribute(null, new Attribute("VolumeCoveragePatternName", mySweep.getScanMode(0).getName()));
nc.addAttribute(null, new Attribute("Volume_Number", "" + mySweep.getVolumnNumber()));
nc.addAttribute(null, new Attribute("Sweep_Number", "" + mySweep.getSweepNumber()));
nc.addAttribute(null, new Attribute("Sweep_Date", DoradeSweep.formatDate(mySweep.getTime())));
if (mySweep.sensorIsMoving(0))
nc.addAttribute(null, new Attribute("IsStationary", "0"));
else
nc.addAttribute(null, new Attribute("IsStationary", "1"));
}
// Return the string of entity ID for the Dorade image file
DataType getDataType(int format) {
DataType p;
switch (format) {
case 1: // 8-bit signed integer format.
p = DataType.SHORT;
break;
case 2: // 16-bit signed integer format.
p = DataType.FLOAT;
break;
case 3: // 32-bit signed integer format.
p = DataType.LONG;
break;
case 4: // 32-bit IEEE float format.
p = DataType.FLOAT;
break;
case 5: // 16-bit IEEE float format.
p = DataType.DOUBLE;
break;
default:
p = null;
break;
} //end of switch
return p;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
}
/* Change History:
$Log: Doradeheader.java,v $
Revision 1.5 2006/04/19 20:24:09 yuanho
radial dataset sweep for all radar dataset
Revision 1.4 2005/08/08 22:45:32 yuanho
spelling bug fix
Revision 1.3 2005/08/03 21:50:45 yuanho
called IsDoradeSweep to check input file, adding global atts.
Revision 1.2 2005/05/11 00:10:03 caron
refactor StuctureData, dt.point
Revision 1.1 2005/04/26 19:39:06 yuanho
iosp for dorade format radar data
Revision 1.8 2004/12/15 22:35:25 caron
add _unsigned
Revision 1.7 2004/12/07 22:13:28 yuanho
add phyElem for 1hour and total precipitation
Revision 1.6 2004/12/07 22:13:15 yuanho
add phyElem for 1hour and total precipitation
Revision 1.5 2004/12/07 01:29:31 caron
redo convention parsing, use _Coordinate encoding.
Revision 1.4 2004/10/29 00:14:11 caron
no message
Revision 1.3 2004/10/19 15:17:22 yuanho
Dorade header DxKm update
Revision 1.2 2004/10/15 23:18:34 yuanho
Dorade projection update
Revision 1.1 2004/10/13 22:57:57 yuanho
no message
Revision 1.4 2004/08/16 20:53:45 caron
2.2 alpha (2)
Revision 1.3 2004/07/12 23:40:17 caron
2.2 alpha 1.0 checkin
Revision 1.2 2004/07/06 19:28:10 caron
pre-alpha checkin
Revision 1.1.1.1 2003/12/04 21:05:27 caron
checkin 2.2
*/