Beispiel #1
0
  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;
  }
  public static boolean isValidFile(NetcdfFile ds) {
    Attribute cdmDtAtt = ds.findGlobalAttributeIgnoreCase("cdm_data_type");
    if (cdmDtAtt == null) cdmDtAtt = ds.findGlobalAttributeIgnoreCase("cdm_datatype");
    if (cdmDtAtt == null) return false;
    if (!cdmDtAtt.isString()) return false;

    String cdmDtString = cdmDtAtt.getStringValue();
    if (cdmDtString == null) return false;
    if (!cdmDtString.equalsIgnoreCase(FeatureType.TRAJECTORY.toString())) return false;

    Attribute conventionsAtt = ds.findGlobalAttributeIgnoreCase("Conventions");
    if (conventionsAtt == null) return (false);
    if (!conventionsAtt.isString()) return (false);
    String convString = conventionsAtt.getStringValue();

    StringTokenizer stoke = new StringTokenizer(convString, ",");
    while (stoke.hasMoreTokens()) {
      String toke = stoke.nextToken().trim();
      if (toke.equalsIgnoreCase("Unidata Observation Dataset v1.0")) return true;
    }

    return false;
  }
 /**
  * Is this the right format for this adapter
  *
  * @param ncd NetcdfDataset to check
  * @return true if the right format
  */
 public static boolean isValidFile(NetcdfDataset ncd) {
   // return (buildConfig(ncd) != null);
   // Check for "center" attribute w/ value of "UCAR/CDAAC".
   Attribute attrib = ncd.findGlobalAttributeIgnoreCase("center");
   if (attrib == null) {
     return false;
   }
   if (!attrib.isString()) {
     return false;
   }
   if (!attrib.getStringValue().equals("UCAR/CDAAC")) {
     return false;
   }
   return true;
 }
Beispiel #4
0
 MetadataAttribute attributeToMetadata(Attribute attribute) {
   final int productDataType = getProductDataType(attribute.getDataType(), false, false);
   if (productDataType != -1) {
     ProductData productData;
     if (attribute.isString()) {
       productData = ProductData.createInstance(attribute.getStringValue());
     } else if (attribute.isArray()) {
       productData = ProductData.createInstance(productDataType, attribute.getLength());
       productData.setElems(attribute.getValues().getStorage());
     } else {
       productData = ProductData.createInstance(productDataType, 1);
       productData.setElems(attribute.getValues().getStorage());
     }
     return new MetadataAttribute(attribute.getShortName(), productData, true);
   }
   return null;
 }
Beispiel #5
0
  /** Instances which have same content are equal. */
  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if ((o == null) || !(o instanceof Attribute)) return false;

    final Attribute att = (Attribute) o;

    if (!name.equals(att.name)) return false;
    if (nelems != att.nelems) return false;
    if (!dataType.equals(att.dataType)) return false;

    if (svalue != null) return svalue.equals(att.getStringValue());

    if (values != null) {
      for (int i = 0; i < getLength(); i++) {
        int r1 = isString() ? getStringValue(i).hashCode() : getNumericValue(i).hashCode();
        int r2 =
            att.isString() ? att.getStringValue(i).hashCode() : att.getNumericValue(i).hashCode();
        if (r1 != r2) return false;
      }
    }

    return true;
  }
  public void testCoordVar(NetcdfFile ncfile) {

    Variable lat = ncfile.findVariable("lat");
    assert null != lat;
    assert lat.getShortName().equals("lat");
    assert lat.getRank() == 1;
    assert lat.getSize() == 3;
    assert lat.getShape()[0] == 3;
    assert lat.getDataType() == DataType.FLOAT;

    assert !lat.isUnlimited();
    assert lat.getDimension(0).equals(ncfile.findDimension("lat"));

    Attribute att = lat.findAttribute("units");
    assert null != att;
    assert !att.isArray();
    assert att.isString();
    assert att.getDataType() == DataType.STRING;
    assert att.getStringValue().equals("degrees_north");
    assert att.getNumericValue() == null;
    assert att.getNumericValue(3) == null;

    try {
      Array data = lat.read();
      assert data.getRank() == 1;
      assert data.getSize() == 3;
      assert data.getShape()[0] == 3;
      assert data.getElementType() == float.class;

      IndexIterator dataI = data.getIndexIterator();
      assert TestUtils.close(dataI.getDoubleNext(), 41.0);
      assert TestUtils.close(dataI.getDoubleNext(), 40.0);
      assert TestUtils.close(dataI.getDoubleNext(), 39.0);
    } catch (IOException io) {
    }
  }
  /**
   * 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;
  }
  /**
   * Constructor. If scale/offset attributes are found, remove them from the decorated variable.
   *
   * @param forVar the Variable to decorate.
   * @param useNaNs pre-fill isMissing() data with NaNs
   * @param fillValueIsMissing use _FillValue for isMissing()
   * @param invalidDataIsMissing use valid_range for isMissing()
   * @param missingDataIsMissing use missing_value for isMissing()
   */
  EnhanceScaleMissingImpl(
      VariableDS forVar,
      boolean useNaNs,
      boolean fillValueIsMissing,
      boolean invalidDataIsMissing,
      boolean missingDataIsMissing) {

    this.fillValueIsMissing = fillValueIsMissing;
    this.invalidDataIsMissing = invalidDataIsMissing;
    this.missingDataIsMissing = missingDataIsMissing;

    // see if underlying variable has scale/offset already applied
    Variable orgVar = forVar.getOriginalVariable();
    if (orgVar instanceof VariableDS) {
      VariableDS orgVarDS = (VariableDS) orgVar;
      EnumSet<NetcdfDataset.Enhance> orgEnhanceMode = orgVarDS.getEnhanceMode();
      if ((orgEnhanceMode != null) && orgEnhanceMode.contains(NetcdfDataset.Enhance.ScaleMissing))
        return;
    }

    // the other possibility is that you want to apply scale and offset to a signed value, then
    // declare the result unsigned
    // this.isUnsigned = (orgVar != null) ? orgVar.isUnsigned() : forVar.isUnsigned();
    this.isUnsigned = forVar.isUnsigned();
    this.convertedDataType = forVar.getDataType();

    DataType scaleType = null, missType = null, validType = null, fillType = null;
    if (debug) System.out.println("EnhancementsImpl for Variable = " + forVar.getFullName());
    Attribute att;

    // scale and offset
    if (null != (att = forVar.findAttribute(CDM.SCALE_FACTOR))) {
      if (!att.isString()) {
        scale = att.getNumericValue().doubleValue();
        hasScaleOffset = true;
        scaleType = att.getDataType();
        forVar.remove(att);
        if (debug) System.out.println("scale = " + scale + " type " + scaleType);
      }
    }
    if (null != (att = forVar.findAttribute(CDM.ADD_OFFSET))) {
      if (!att.isString()) {
        offset = att.getNumericValue().doubleValue();
        hasScaleOffset = true;
        DataType offType = att.getDataType();
        if (rank(offType) > rank(scaleType)) scaleType = offType;
        forVar.remove(att);
        if (debug) System.out.println("offset = " + offset);
      }
    }

    ////// missing data : valid_range. assume here its in units of unpacked data. correct this below
    Attribute validRangeAtt;
    if (null != (validRangeAtt = forVar.findAttribute(CDM.VALID_RANGE))) {
      if (!validRangeAtt.isString() && validRangeAtt.getLength() > 1) {
        valid_min = validRangeAtt.getNumericValue(0).doubleValue();
        valid_max = validRangeAtt.getNumericValue(1).doubleValue();
        hasValidRange = true;
        validType = validRangeAtt.getDataType();
        if (hasScaleOffset) forVar.remove(validRangeAtt);
        if (debug) System.out.println("valid_range = " + valid_min + " " + valid_max);
      }
    }

    Attribute validMinAtt = null, validMaxAtt = null;
    if (!hasValidRange) {
      if (null != (validMinAtt = forVar.findAttribute("valid_min"))) {
        if (!validMinAtt.isString()) {
          valid_min = validMinAtt.getNumericValue().doubleValue();
          hasValidMin = true;
          validType = validMinAtt.getDataType();
          if (hasScaleOffset) forVar.remove(validMinAtt);
          if (debug) System.out.println("valid_min = " + valid_min);
        }
      }

      if (null != (validMaxAtt = forVar.findAttribute("valid_max"))) {
        if (!validMaxAtt.isString()) {
          valid_max = validMaxAtt.getNumericValue().doubleValue();
          hasValidMax = true;
          DataType t = validMaxAtt.getDataType();
          if (rank(t) > rank(validType)) validType = t;
          if (hasScaleOffset) forVar.remove(validMaxAtt);
          if (debug) System.out.println("valid_min = " + valid_max);
        }
      }
    }
    boolean hasValidData = hasValidMin || hasValidMax || hasValidRange;
    if (hasValidMin && hasValidMax) hasValidRange = true;

    /// _FillValue
    if ((null != (att = forVar.findAttribute(CDM.FILL_VALUE))) && !att.isString()) {
      double[] values = getValueAsDouble(att); // LOOK double WTF ??
      if (values.length > 0) {
        fillValue = values[0];
        hasFillValue = true;
        fillType = att.getDataType();
        if (hasScaleOffset) forVar.remove(att);
        if (debug) System.out.println("missing_datum from _FillValue = " + fillValue);
      }
    }

    /// missing_value
    if (null != (att = forVar.findAttribute(CDM.MISSING_VALUE))) {
      if (att.isString()) {
        String svalue = att.getStringValue();
        if (forVar.getDataType() == DataType.CHAR) {
          missingValue = new double[1];
          if (svalue.length() == 0) missingValue[0] = 0;
          else missingValue[0] = svalue.charAt(0);

          missType = DataType.CHAR;
          hasMissingValue = true;

        } else { // not a CHAR - try to fix problem where they use a numeric value as a String
                 // attribute

          try {
            missingValue = new double[1];
            missingValue[0] = Double.parseDouble(svalue);
            missType = att.getDataType();
            hasMissingValue = true;
          } catch (NumberFormatException ex) {
            if (debug)
              System.out.println(
                  "String missing_value not parsable as double= " + att.getStringValue());
          }
        }

      } else { // not a string
        missingValue = getValueAsDouble(att);
        missType = att.getDataType();
        for (double mv : missingValue)
          if (!Double.isNaN(mv))
            hasMissingValue = true; // dont need to do anything if its already a NaN
      }
      if (hasScaleOffset) forVar.remove(att);
    }

    // missing
    boolean hasMissing =
        (invalidDataIsMissing && hasValidData)
            || (fillValueIsMissing && hasFillValue)
            || (missingDataIsMissing && hasMissingValue);

    /// assign convertedDataType if needed
    if (hasScaleOffset) {

      convertedDataType = forVar.getDataType();
      if (hasMissing) {
        // has missing data : must be float or double
        if (rank(scaleType) > rank(convertedDataType)) convertedDataType = scaleType;
        if (missingDataIsMissing && rank(missType) > rank(convertedDataType))
          convertedDataType = missType;
        if (fillValueIsMissing && rank(fillType) > rank(convertedDataType))
          convertedDataType = fillType;
        if (invalidDataIsMissing && rank(validType) > rank(convertedDataType))
          convertedDataType = validType;
        if (rank(convertedDataType) < rank(DataType.DOUBLE)) convertedDataType = DataType.FLOAT;

      } else {
        // no missing data; can use wider of data and scale
        if (rank(scaleType) > rank(convertedDataType)) convertedDataType = scaleType;
      }
      if (debug) System.out.println("assign dataType = " + convertedDataType);

      // validData may be external or internal
      if (hasValidData) {
        DataType orgType = forVar.getDataType();

        // If valid_range is the same type as scale_factor (actually the wider of
        // scale_factor and add_offset) and this is wider than the external data, then it
        // will be interpreted as being in the units of the internal (unpacked) data.
        // Otherwise it is in the units of the external (unpacked) data.
        // we assumed unpacked data above, redo if its really packed data
        if (!((rank(validType) == rank(scaleType)) && (rank(scaleType) >= rank(orgType)))) {
          if (validRangeAtt != null) {
            double[] values = getValueAsDouble(validRangeAtt);
            valid_min = values[0];
            valid_max = values[1];
          } else {
            if (validMinAtt != null) {
              double[] values = getValueAsDouble(validMinAtt);
              valid_min = values[0];
            }
            if (validMaxAtt != null) {
              double[] values = getValueAsDouble(validMaxAtt);
              valid_max = values[0];
            }
          }
        }
      }
    }

    if (hasMissing
        && ((convertedDataType == DataType.DOUBLE) || (convertedDataType == DataType.FLOAT)))
      this.useNaNs = useNaNs;
    if (debug) System.out.println("this.useNaNs = " + this.useNaNs);
  }
Beispiel #9
0
  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();
  }