// create from a dataset public VariableBean(Variable vs) { this.vs = vs; // vs = (v instanceof VariableEnhanced) ? (VariableEnhanced) v : new VariableStandardized( v); setName(vs.getShortName()); setDescription(vs.getDescription()); setUnits(vs.getUnitsString()); setDataType(vs.getDataType().toString()); // Attribute csAtt = vs.findAttribute("_coordSystems"); // if (csAtt != null) // setCoordSys( csAtt.getStringValue()); // collect dimensions StringBuilder lens = new StringBuilder(); StringBuilder names = new StringBuilder(); java.util.List dims = vs.getDimensions(); for (int j = 0; j < dims.size(); j++) { ucar.nc2.Dimension dim = (ucar.nc2.Dimension) dims.get(j); if (j > 0) { lens.append(","); names.append(","); } String name = dim.isShared() ? dim.getName() : "anon"; names.append(name); lens.append(dim.getLength()); } setDimensions(names.toString()); setShape(lens.toString()); }
/** Create a DAS for this netcdf file */ NcDAS(NetcdfFile ncfile) { // Variable attributes Iterator iter = ncfile.getVariables().iterator(); while (iter.hasNext()) { Variable v = (Variable) iter.next(); doVariable(v, null); } // Global attributes opendap.dap.AttributeTable gtable = new opendap.dap.AttributeTable("NC_GLOBAL"); int count = addAttributes(gtable, null, ncfile.getGlobalAttributes().iterator()); if (count > 0) try { addAttributeTable("NC_GLOBAL", gtable); } catch (AttributeExistsException e) { log.error("Cant add NC_GLOBAL", e); } // unlimited dimension iter = ncfile.getDimensions().iterator(); while (iter.hasNext()) { Dimension d = (Dimension) iter.next(); if (d.isUnlimited()) { opendap.dap.AttributeTable table = new opendap.dap.AttributeTable("DODS_EXTRA"); try { table.appendAttribute("Unlimited_Dimension", opendap.dap.Attribute.STRING, d.getName()); addAttributeTable("DODS_EXTRA", table); } catch (Exception e) { log.error("Error adding Unlimited_Dimension =" + e); } break; } } // unused dimensions opendap.dap.AttributeTable dimTable = null; iter = ncfile.getDimensions().iterator(); while (iter.hasNext()) { Dimension d = (Dimension) iter.next(); if (null == usedDims.get(d.getName())) { if (dimTable == null) dimTable = new opendap.dap.AttributeTable("EXTRA_DIMENSION"); try { dimTable.appendAttribute( d.getName(), opendap.dap.Attribute.INT32, Integer.toString(d.getLength())); } catch (Exception e) { log.error("Error adding Unlimited_Dimension =" + e); } } } if (dimTable != null) try { addAttributeTable("EXTRA_DIMENSION", dimTable); } catch (AttributeExistsException e) { log.error("Cant add EXTRA_DIMENSION", e); } }
/** Instances which have same contents are equal. Careful!! this is not object identity !! */ @Override public boolean equals(Object oo) { if (this == oo) return true; if (!(oo instanceof Dimension)) return false; Dimension other = (Dimension) oo; if ((g != null) && !g.equals(other.getGroup())) return false; if ((getName() == null) && (other.getName() != null)) return false; if ((getName() != null) && !getName().equals(other.getName())) return false; return (getLength() == other.getLength()) && (isUnlimited() == other.isUnlimited()) && (isVariableLength() == other.isVariableLength()) && (isShared() == other.isShared()); }
private void doVariable(Variable v, opendap.dap.AttributeTable parentTable) { List dims = v.getDimensions(); for (int i = 0; i < dims.size(); i++) { Dimension dim = (Dimension) dims.get(i); if (dim.isShared()) usedDims.put(dim.getName(), dim); } // if (v.getAttributes().size() == 0) return; // LOOK DAP 2 say must have empty String name = NcDDS.escapeName(v.getShortName()); opendap.dap.AttributeTable table; if (parentTable == null) { table = new opendap.dap.AttributeTable(name); try { addAttributeTable(name, table); } catch (AttributeExistsException e) { log.error("Cant add " + name, e); } } else { table = parentTable.appendContainer(name); } addAttributes(table, v, v.getAttributes().iterator()); if (v instanceof Structure) { Structure s = (Structure) v; List nested = s.getVariables(); for (int i = 0; i < nested.size(); i++) { Variable nv = (Variable) nested.get(i); doVariable(nv, table); } } }
private int addAttributes(opendap.dap.AttributeTable table, Variable v, Iterator iter) { int count = 0; // add attribute table for this variable while (iter.hasNext()) { Attribute att = (Attribute) iter.next(); int dods_type = DODSNetcdfFile.convertToDODSType(att.getDataType(), false); try { String attName = NcDDS.escapeName(att.getName()); if (att.isString()) { /* FIX String value = escapeAttributeStringValues(att.getStringValue()); table.appendAttribute(attName, dods_type, "\""+value+"\""); */ table.appendAttribute(attName, dods_type, att.getStringValue()); } else { // cant send signed bytes if (att.getDataType() == DataType.BYTE) { boolean signed = false; for (int i = 0; i < att.getLength(); i++) { if (att.getNumericValue(i).byteValue() < 0) signed = true; } if (signed) // promote to signed short dods_type = opendap.dap.Attribute.INT16; } for (int i = 0; i < att.getLength(); i++) table.appendAttribute(attName, dods_type, att.getNumericValue(i).toString()); } count++; } catch (Exception e) { log.error( "Error appending attribute " + att.getName() + " = " + att.getStringValue() + "\n" + e); } } // loop over variable attributes // kludgy thing to map char arrays to DODS Strings if ((v != null) && (v.getDataType().getPrimitiveClassType() == char.class)) { int rank = v.getRank(); int strlen = (rank == 0) ? 0 : v.getShape(rank - 1); Dimension dim = (rank == 0) ? null : v.getDimension(rank - 1); try { opendap.dap.AttributeTable dodsTable = table.appendContainer("DODS"); dodsTable.appendAttribute("strlen", opendap.dap.Attribute.INT32, Integer.toString(strlen)); if ((dim != null) && dim.isShared()) dodsTable.appendAttribute("dimName", opendap.dap.Attribute.STRING, dim.getName()); count++; } catch (Exception e) { log.error("Error appending attribute strlen\n" + e); } } return count; }
private void createDataVariables(List<VariableSimpleIF> dataVars) throws IOException { /* height variable Variable heightVar = ncfile.addStringVariable(altName, recordDims, 20); ncfile.addVariableAttribute(heightVar, new Attribute("long_name", "height of observation")); ncfile.addVariableAttribute(heightVar, new Attribute("units", altUnits)); */ Variable v = ncfile.addVariable(parentProfileIndex, DataType.INT, recordDimName); ncfile.addVariableAttribute(v, new Attribute("long_name", "index of parent profile")); v = ncfile.addVariable(nextObsName, DataType.INT, recordDimName); ncfile.addVariableAttribute( v, new Attribute("long_name", "record number of next obs in linked list for this profile")); // find all dimensions needed by the data variables for (VariableSimpleIF var : dataVars) { List<Dimension> dims = var.getDimensions(); dimSet.addAll(dims); } // add them for (Dimension d : dimSet) { if (!d.isUnlimited()) ncfile.addDimension(d.getName(), d.getLength(), d.isShared(), false, d.isVariableLength()); } // add the data variables all using the record dimension for (VariableSimpleIF oldVar : dataVars) { List<Dimension> dims = oldVar.getDimensions(); StringBuffer dimNames = new StringBuffer(recordDimName); for (Dimension d : dims) { if (!d.isUnlimited()) dimNames.append(" ").append(d.getName()); } Variable newVar = ncfile.addVariable(oldVar.getName(), oldVar.getDataType(), dimNames.toString()); List<Attribute> atts = oldVar.getAttributes(); for (Attribute att : atts) { ncfile.addVariableAttribute(newVar, att); } } }
private int[] getWeights(Variable v) { int rank = v.getRank(); int[] w = new int[rank]; for (int n = 0; n < rank; n++) { Dimension dim = v.getDimension(n); String dimName = dim.getName(); if (dimName.equals("time")) w[n] = 1000; if (dimName.equals("z")) w[n] = 100; if (dimName.equals("y")) w[n] = 10; if (dimName.equals("x")) w[n] = 1; } return w; }
/** * Build the configuration from the dataset * * @param ncd NetcdfDataset * @return the trajectory configuration */ private static Config buildConfig(NetcdfDataset ncd) { // already did this in isValid, but we'll keep here for later refactor Attribute attrib = ncd.findGlobalAttributeIgnoreCase("center"); if (attrib == null) { return null; } if (!attrib.isString()) { return null; } if (!attrib.getStringValue().equals("UCAR/CDAAC")) { return null; } // Check for start_time, stop_time attrib = ncd.findGlobalAttributeIgnoreCase("start_time"); if (attrib == null) { return null; } if (attrib.isString()) { return null; } double startTime = attrib.getNumericValue().doubleValue(); attrib = ncd.findGlobalAttributeIgnoreCase("stop_time"); if (attrib == null) { return null; } if (attrib.isString()) { return null; } double endTime = attrib.getNumericValue().doubleValue(); // Check that only one dimension and that it is the alt dimension. List list = ncd.getRootGroup().getDimensions(); if (list.size() != 1) { return null; } Dimension d = (Dimension) list.get(0); if (!d.getName().equals(timeDimName)) { return null; } Config trajConfig = new Config(); trajConfig.setTimeDim(d); // Check for latitude variable with time dimension and units convertable to "degrees_north". Variable var = ncd.getRootGroup().findVariable(latVarName); if (var == null) { return null; } list = var.getDimensions(); if (list.size() != 1) { return null; } d = (Dimension) list.get(0); if (!d.getName().equals(timeDimName)) { return null; } String units = var.findAttribute("units").getStringValue(); if (!SimpleUnit.isCompatible(units, "degrees_north")) { return null; } trajConfig.setLatVar(var); // Make the time Variable int numTimes = d.getLength(); double[] times = new double[numTimes]; // Variable timeVar = new Variable(var); // timeVar.setName(timeVarName); VariableDS timeVar = new VariableDS( ncd, ncd.getRootGroup(), null, timeVarName, DataType.DOUBLE, timeDimName, "seconds since 1980-01-06 00:00:00", "Time coordinate"); // Variable timeVar = new Variable(ncd, ncd.getRootGroup(), null, // timeVarName); // timeVar.setDataType(DataType.DOUBLE); // timeVar.setDimensions(list); // Attribute newUnits = // new Attribute("units", "seconds since 1980-01-06 00:00:00"); // timeVar.addAttribute(newUnits); timeVar.setCachedData( Array.makeArray(DataType.DOUBLE, numTimes, endTime, ((startTime - endTime) / numTimes)), true); ncd.addVariable(ncd.getRootGroup(), timeVar); trajConfig.setTimeVar(timeVar); // Check for longitude variable with time dimension and units convertable to "degrees_east". var = ncd.getRootGroup().findVariable(lonVarName); if (var == null) { return null; } list = var.getDimensions(); if (list.size() != 1) { return null; } d = (Dimension) list.get(0); if (!d.getName().equals(timeDimName)) { return null; } units = var.findAttribute("units").getStringValue(); if (!SimpleUnit.isCompatible(units, "degrees_east")) { return null; } trajConfig.setLonVar(var); // Check for altitude variable with time dimension and units convertable to "m". var = ncd.getRootGroup().findVariable(elevVarName); if (var == null) { return null; } list = var.getDimensions(); if (list.size() != 1) { return null; } d = (Dimension) list.get(0); if (!d.getName().equals(timeDimName)) { return null; } units = var.findAttribute("units").getStringValue(); if (!SimpleUnit.isCompatible(units, "meters")) { return null; } trajConfig.setElevVar(var); trajConfig.setTrajectoryId(trajId); return trajConfig; }
public static String makeDimensionList(List<Dimension> dimList) { StringBuilder out = new StringBuilder(); for (Dimension dim : dimList) out.append(dim.getName()).append(" "); return out.toString(); }
/** * Dimensions with the same name are equal. * * @param o compare to this Dimension * @return 0, 1, or -1 */ public int compareTo(Object o) { Dimension odim = (Dimension) o; return name.compareTo(odim.getName()); }
/** * Parses a variable recursively into appropriate ViewVariable implementations * * @throws IOException * @throws */ private static AbstractViewVariable parseVariableRecursive(Variable var) throws IOException { List<Dimension> dimensions = var.getDimensions(); // A single dimension means we can parse a SimpleAxis if (dimensions.size() == 1) { SimpleAxis axis = new SimpleAxis(var.getName(), var.getDataType().name(), var.getUnitsString(), null, null); Dimension d = dimensions.get(0); axis.setDimensionBounds(new SimpleBounds(0, d.getLength())); // Read our first and last values Array first = null, last = null; try { first = var.read(new int[] {0}, new int[] {1}); last = var.read(new int[] {d.getLength() - 1}, new int[] {1}); } catch (InvalidRangeException ex) { throw new IllegalArgumentException( String.format("Unable to read variable ranges '%1$s'", var), ex); } axis.setValueBounds(new SimpleBounds(first.getDouble(0), last.getDouble(0))); return axis; // Otherwise we have a multi dimensional variable that we can parse as a grid } else if (dimensions.size() > 0) { SimpleGrid grid = new SimpleGrid(var.getName(), var.getDataType().name(), var.getUnitsString(), null); List<AbstractViewVariable> childAxes = new ArrayList<>(); // Recursively parse each dimension (which should map to a variable in the parent group) for (Dimension d : dimensions) { Variable mappedVariable = d.getGroup().findVariable(d.getName()); if (mappedVariable == null) { // If the dimension doesn't map to a variable, we can't pull much information out of it // So instead we'll have to introduce an axis that only includes dimension bounds log.warn( String.format( "Dimension '%1$s' has no matching variable in parent group '%2$s'", d, d.getGroup())); SimpleAxis axis = new SimpleAxis(d.getName(), DataType.FLOAT.name(), "????", null, null); axis.setDimensionBounds(new SimpleBounds(0, d.getLength() - 1)); childAxes.add(axis); } else { AbstractViewVariable parsedVar = parseVariableRecursive(mappedVariable); if (parsedVar != null) childAxes.add(parsedVar); } } if (childAxes.size() > 0) { grid.setAxes(childAxes.toArray(new AbstractViewVariable[childAxes.size()])); return grid; } else { return null; } } else { // Currently unsupported... log.warn( String.format("Variables with 0 dimensions are currently unsupported. var='%1$s'", var)); return null; } }
Write2ncRect(NetcdfFile bufr, String fileOutName, boolean fill) throws IOException, InvalidRangeException { NetcdfFileWriteable ncfile = NetcdfFileWriteable.createNew(fileOutName, fill); if (debug) { System.out.println("FileWriter write " + bufr.getLocation() + " to " + fileOutName); } // global attributes List<Attribute> glist = bufr.getGlobalAttributes(); for (Attribute att : glist) { String useName = N3iosp.makeValidNetcdfObjectName(att.getName()); Attribute useAtt; if (att.isArray()) useAtt = ncfile.addGlobalAttribute(useName, att.getValues()); else if (att.isString()) useAtt = ncfile.addGlobalAttribute(useName, att.getStringValue()); else useAtt = ncfile.addGlobalAttribute(useName, att.getNumericValue()); if (debug) System.out.println("add gatt= " + useAtt); } // global dimensions Dimension recordDim = null; Map<String, Dimension> dimHash = new HashMap<String, Dimension>(); for (Dimension oldD : bufr.getDimensions()) { String useName = N3iosp.makeValidNetcdfObjectName(oldD.getName()); boolean isRecord = useName.equals("record"); Dimension newD = ncfile.addDimension(useName, oldD.getLength(), true, false, false); dimHash.put(newD.getName(), newD); if (isRecord) recordDim = newD; if (debug) System.out.println("add dim= " + newD); } // Variables Structure recordStruct = (Structure) bufr.findVariable(BufrIosp.obsRecord); for (Variable oldVar : recordStruct.getVariables()) { if (oldVar.getDataType() == DataType.STRUCTURE) continue; String varName = N3iosp.makeValidNetcdfObjectName(oldVar.getShortName()); DataType newType = oldVar.getDataType(); List<Dimension> newDims = new ArrayList<Dimension>(); newDims.add(recordDim); for (Dimension dim : oldVar.getDimensions()) { newDims.add(ncfile.addDimension(oldVar.getShortName() + "_strlen", dim.getLength())); } Variable newVar = ncfile.addVariable(varName, newType, newDims); if (debug) System.out.println("add var= " + newVar); // attributes List<Attribute> attList = oldVar.getAttributes(); for (Attribute att : attList) { String useName = N3iosp.makeValidNetcdfObjectName(att.getName()); if (att.isArray()) ncfile.addVariableAttribute(varName, useName, att.getValues()); else if (att.isString()) ncfile.addVariableAttribute(varName, useName, att.getStringValue()); else ncfile.addVariableAttribute(varName, useName, att.getNumericValue()); } } // int max_seq = countSeq(recordStruct); // Dimension seqD = ncfile.addDimension("level", max_seq); for (Variable v : recordStruct.getVariables()) { if (v.getDataType() != DataType.STRUCTURE) continue; String structName = N3iosp.makeValidNetcdfObjectName(v.getShortName()); int shape[] = v.getShape(); Dimension structDim = ncfile.addDimension(structName, shape[0]); Structure struct = (Structure) v; for (Variable seqVar : struct.getVariables()) { String varName = N3iosp.makeValidNetcdfObjectName(seqVar.getShortName() + "-" + structName); DataType newType = seqVar.getDataType(); List<Dimension> newDims = new ArrayList<Dimension>(); newDims.add(recordDim); newDims.add(structDim); for (Dimension dim : seqVar.getDimensions()) { newDims.add(ncfile.addDimension(seqVar.getShortName() + "_strlen", dim.getLength())); } Variable newVar = ncfile.addVariable(varName, newType, newDims); if (debug) System.out.println("add var= " + newVar); // attributes List<Attribute> attList = seqVar.getAttributes(); for (Attribute att : attList) { String useName = N3iosp.makeValidNetcdfObjectName(att.getName()); if (att.isArray()) ncfile.addVariableAttribute(varName, useName, att.getValues()); else if (att.isString()) ncfile.addVariableAttribute(varName, useName, att.getStringValue()); else ncfile.addVariableAttribute(varName, useName, att.getNumericValue()); } } } // create the file ncfile.create(); if (debug) System.out.println("File Out= " + ncfile.toString()); // boolean ok = (Boolean) ncfile.sendIospMessage(NetcdfFile.IOSP_MESSAGE_ADD_RECORD_STRUCTURE); double total = copyVarData(ncfile, recordStruct); ncfile.flush(); System.out.println("FileWriter done total bytes = " + total); ncfile.close(); }
/** * This reads an arbitrary data slice, returning the data in canonical order (rt-e-t-z-y-x). If * any dimension does not exist, ignore it. * * @param rt if < 0, get all of runtime dim; if valid index, fix slice to that value. * @param e if < 0, get all of ensemble dim; if valid index, fix slice to that value. * @param t if < 0, get all of time dim; if valid index, fix slice to that value. * @param z if < 0, get all of z dim; if valid index, fix slice to that value. * @param y if < 0, get all of y dim; if valid index, fix slice to that value. * @param x if < 0, get all of x dim; if valid index, fix slice to that value. * @return data[rt,e,t,z,y,x], eliminating missing or fixed dimension. */ public Array readDataSlice(int rt, int e, int t, int z, int y, int x) throws java.io.IOException { int rank = vs.getRank(); int[] start = new int[rank]; int[] shape = new int[rank]; for (int i = 0; i < rank; i++) { start[i] = 0; shape[i] = 1; } Dimension xdim = getXDimension(); Dimension ydim = getYDimension(); Dimension zdim = getZDimension(); Dimension tdim = getTimeDimension(); Dimension edim = getEnsembleDimension(); Dimension rtdim = getRunTimeDimension(); // construct the shape of the data volume to be read if (rtdim != null) { if ((rt >= 0) && (rt < rtdim.getLength())) start[rtDimOrgIndex] = rt; // fix rt else { shape[rtDimOrgIndex] = rtdim.getLength(); // all of rt } } if (edim != null) { if ((e >= 0) && (e < edim.getLength())) start[eDimOrgIndex] = e; // fix e else { shape[eDimOrgIndex] = edim.getLength(); // all of e } } if (tdim != null) { if ((t >= 0) && (t < tdim.getLength())) start[tDimOrgIndex] = t; // fix t else { shape[tDimOrgIndex] = tdim.getLength(); // all of t } } if (zdim != null) { if ((z >= 0) && (z < zdim.getLength())) start[zDimOrgIndex] = z; // fix z else { shape[zDimOrgIndex] = zdim.getLength(); // all of z } } if (ydim != null) { if ((y >= 0) && (y < ydim.getLength())) start[yDimOrgIndex] = y; // fix y else { shape[yDimOrgIndex] = ydim.getLength(); // all of y } } if (xdim != null) { if ((x >= 0) && (x < xdim.getLength())) // all of x start[xDimOrgIndex] = x; // fix x else { shape[xDimOrgIndex] = xdim.getLength(); // all of x } } if (debugArrayShape) { System.out.println("read shape from org variable = "); for (int i = 0; i < rank; i++) System.out.println( " start = " + start[i] + " shape = " + shape[i] + " name = " + vs.getDimension(i).getName()); } // read it Array dataVolume; try { dataVolume = vs.read(start, shape); } catch (Exception ex) { log.error( "GeoGrid.getdataSlice() on dataset " + getFullName() + " " + dataset.getLocation(), ex); throw new java.io.IOException(ex.getMessage()); } // LOOK: the real problem is the lack of named dimensions in the Array object // figure out correct permutation for canonical ordering for permute List<Dimension> oldDims = new ArrayList<Dimension>(vs.getDimensions()); int[] permuteIndex = new int[dataVolume.getRank()]; int count = 0; if (oldDims.contains(rtdim)) permuteIndex[count++] = oldDims.indexOf(rtdim); if (oldDims.contains(edim)) permuteIndex[count++] = oldDims.indexOf(edim); if (oldDims.contains(tdim)) permuteIndex[count++] = oldDims.indexOf(tdim); if (oldDims.contains(zdim)) permuteIndex[count++] = oldDims.indexOf(zdim); if (oldDims.contains(ydim)) permuteIndex[count++] = oldDims.indexOf(ydim); if (oldDims.contains(xdim)) permuteIndex[count] = oldDims.indexOf(xdim); if (debugArrayShape) { System.out.println("oldDims = "); for (Dimension oldDim : oldDims) System.out.println(" oldDim = " + oldDim.getName()); System.out.println("permute dims = "); for (int aPermuteIndex : permuteIndex) System.out.println(" oldDim index = " + aPermuteIndex); } // check to see if we need to permute boolean needPermute = false; for (int i = 0; i < permuteIndex.length; i++) { if (i != permuteIndex[i]) needPermute = true; } // permute to the order rt,e,t,z,y,x if (needPermute) dataVolume = dataVolume.permute(permuteIndex); // eliminate fixed dimensions, but not all dimensions of length 1. count = 0; if (rtdim != null) { if (rt >= 0) dataVolume = dataVolume.reduce(count); else count++; } if (edim != null) { if (e >= 0) dataVolume = dataVolume.reduce(count); else count++; } if (tdim != null) { if (t >= 0) dataVolume = dataVolume.reduce(count); else count++; } if (zdim != null) { if (z >= 0) dataVolume = dataVolume.reduce(count); else count++; } if (ydim != null) { if (y >= 0) dataVolume = dataVolume.reduce(count); else count++; } if (xdim != null) { if (x >= 0) dataVolume = dataVolume.reduce(count); } return dataVolume; }
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; }