Exemple #1
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) {
    }
  }
 public String getAbbrev() {
   Attribute att = ve.findAttributeIgnoreCase(CDM.ABBREV);
   return (att == null) ? null : att.getStringValue();
 }
 private String getCalendarAttribute(VariableEnhanced vds) {
   Attribute cal = vds.findAttribute("calendar");
   return (cal == null) ? null : cal.getStringValue();
 }
  /**
   * 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);
  }
Exemple #6
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();
  }