public Variable makeVariable( NetcdfFile ncfile, int datatype, String shortName, String longName, String abbrev, List groups) throws IOException { int nscans = groups.size(); if (nscans == 0) { throw new IllegalStateException("No data for " + shortName); } // get representative record List firstGroup = (List) groups.get(0); Cinrad2Record firstRecord = (Cinrad2Record) firstGroup.get(0); int ngates = firstRecord.getGateCount(datatype); String scanDimName = "scan" + abbrev; String gateDimName = "gate" + abbrev; Dimension scanDim = new Dimension(scanDimName, nscans); Dimension gateDim = new Dimension(gateDimName, ngates); ncfile.addDimension(null, scanDim); ncfile.addDimension(null, gateDim); ArrayList dims = new ArrayList(); dims.add(scanDim); dims.add(radialDim); dims.add(gateDim); Variable v = new Variable(ncfile, null, null, shortName); v.setDataType(DataType.BYTE); v.setDimensions(dims); ncfile.addVariable(null, v); v.addAttribute(new Attribute(CDM.UNITS, Cinrad2Record.getDatatypeUnits(datatype))); v.addAttribute(new Attribute(CDM.LONG_NAME, longName)); byte[] b = new byte[2]; b[0] = Cinrad2Record.MISSING_DATA; b[1] = Cinrad2Record.BELOW_THRESHOLD; Array missingArray = Array.factory(DataType.BYTE.getPrimitiveClassType(), new int[] {2}, b); v.addAttribute(new Attribute(CDM.MISSING_VALUE, missingArray)); v.addAttribute( new Attribute("signal_below_threshold", new Byte(Cinrad2Record.BELOW_THRESHOLD))); v.addAttribute( new Attribute(CDM.SCALE_FACTOR, new Float(Cinrad2Record.getDatatypeScaleFactor(datatype)))); v.addAttribute( new Attribute(CDM.ADD_OFFSET, new Float(Cinrad2Record.getDatatypeAddOffset(datatype)))); v.addAttribute(new Attribute(CDM.UNSIGNED, "true")); ArrayList dim2 = new ArrayList(); dim2.add(scanDim); dim2.add(radialDim); // add time coordinate variable String timeCoordName = "time" + abbrev; Variable timeVar = new Variable(ncfile, null, null, timeCoordName); timeVar.setDataType(DataType.INT); timeVar.setDimensions(dim2); ncfile.addVariable(null, timeVar); // int julianDays = volScan.getTitleJulianDays(); // Date d = Cinrad2Record.getDate( julianDays, 0); // Date d = Cinrad2Record.getDate(volScan.getTitleJulianDays(), volScan.getTitleMsecs()); Date d = volScan.getStartDate(); String units = "msecs since " + formatter.toDateTimeStringISO(d); timeVar.addAttribute(new Attribute(CDM.LONG_NAME, "time since base date")); timeVar.addAttribute(new Attribute(CDM.UNITS, units)); timeVar.addAttribute(new Attribute(CDM.MISSING_VALUE, new Integer(MISSING_INT))); timeVar.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.Time.toString())); // add elevation coordinate variable String elevCoordName = "elevation" + abbrev; Variable elevVar = new Variable(ncfile, null, null, elevCoordName); elevVar.setDataType(DataType.FLOAT); elevVar.setDimensions(dim2); ncfile.addVariable(null, elevVar); elevVar.addAttribute(new Attribute(CDM.UNITS, "degrees")); elevVar.addAttribute( new Attribute( CDM.LONG_NAME, "elevation angle in degres: 0 = parallel to pedestal base, 90 = perpendicular")); elevVar.addAttribute(new Attribute(CDM.MISSING_VALUE, new Float(MISSING_FLOAT))); elevVar.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.RadialElevation.toString())); // add azimuth coordinate variable String aziCoordName = "azimuth" + abbrev; Variable aziVar = new Variable(ncfile, null, null, aziCoordName); aziVar.setDataType(DataType.FLOAT); aziVar.setDimensions(dim2); ncfile.addVariable(null, aziVar); aziVar.addAttribute(new Attribute(CDM.UNITS, "degrees")); aziVar.addAttribute( new Attribute(CDM.LONG_NAME, "azimuth angle in degrees: 0 = true north, 90 = east")); aziVar.addAttribute(new Attribute(CDM.MISSING_VALUE, new Float(MISSING_FLOAT))); aziVar.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.RadialAzimuth.toString())); // add gate coordinate variable String gateCoordName = "distance" + abbrev; Variable gateVar = new Variable(ncfile, null, null, gateCoordName); gateVar.setDataType(DataType.FLOAT); gateVar.setDimensions(gateDimName); Array data = Array.makeArray( DataType.FLOAT, ngates, (double) firstRecord.getGateStart(datatype), (double) firstRecord.getGateSize(datatype)); gateVar.setCachedData(data, false); ncfile.addVariable(null, gateVar); radarRadius = firstRecord.getGateStart(datatype) + ngates * firstRecord.getGateSize(datatype); gateVar.addAttribute(new Attribute(CDM.UNITS, "m")); gateVar.addAttribute(new Attribute(CDM.LONG_NAME, "radial distance to start of gate")); gateVar.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.RadialDistance.toString())); // add number of radials variable String nradialsName = "numRadials" + abbrev; Variable nradialsVar = new Variable(ncfile, null, null, nradialsName); nradialsVar.setDataType(DataType.INT); nradialsVar.setDimensions(scanDim.getName()); nradialsVar.addAttribute(new Attribute(CDM.LONG_NAME, "number of valid radials in this scan")); ncfile.addVariable(null, nradialsVar); // add number of gates variable String ngateName = "numGates" + abbrev; Variable ngateVar = new Variable(ncfile, null, null, ngateName); ngateVar.setDataType(DataType.INT); ngateVar.setDimensions(scanDim.getName()); ngateVar.addAttribute(new Attribute(CDM.LONG_NAME, "number of valid gates in this scan")); ncfile.addVariable(null, ngateVar); makeCoordinateDataWithMissing( datatype, timeVar, elevVar, aziVar, nradialsVar, ngateVar, groups); // back to the data variable String coordinates = timeCoordName + " " + elevCoordName + " " + aziCoordName + " " + gateCoordName; v.addAttribute(new Attribute(_Coordinate.Axes, coordinates)); // make the record map int nradials = radialDim.getLength(); Cinrad2Record[][] map = new Cinrad2Record[nscans][nradials]; for (int i = 0; i < groups.size(); i++) { Cinrad2Record[] mapScan = map[i]; List group = (List) groups.get(i); for (int j = 0; j < group.size(); j++) { Cinrad2Record r = (Cinrad2Record) group.get(j); int radial = r.radial_num - 1; mapScan[radial] = r; } } Vgroup vg = new Vgroup(datatype, map); v.setSPobject(vg); return v; }