示例#1
0
  /**
   * Set the sounding in the table
   *
   * @param sounding the sounding
   * @throws RemoteException Java RMI problem
   * @throws VisADException problem dissecting data
   */
  private void setSounding(Field sounding) throws VisADException, RemoteException {
    domainData = null;

    // domain values
    Set domain = sounding.getDomainSet();
    CoordinateSystem cs = domain.getCoordinateSystem();

    float[][] domSamples = domain.getSamples(false);
    if ((cs != null)) {
      float[][] domFloats = Set.copyFloats(domSamples);
      // Must convert from the default coordinate domain system to
      // the domain coordinate system of the sounding.
      String fromUnit = sounding.getDomainUnits()[0].toString();
      String toUnit = cs.getCoordinateSystemUnits()[0].toString();
      if (!fromUnit.equals(toUnit) && SimpleUnit.isCompatible(fromUnit, toUnit)) {
        float conversionFactor = (float) SimpleUnit.getConversionFactor(fromUnit, toUnit);
        for (int i = 0; i < domFloats.length; i++) {
          for (int j = 0; j < domFloats[i].length; j++) {
            domFloats[i][j] = domFloats[i][j] * conversionFactor;
          }
        }
      }
      float[][] refData = cs.toReference(domFloats);
      domainData = new float[][] {domSamples[0], refData[0]};
    }
    // range values
    RealType[] rangeComps = ((FunctionType) sounding.getType()).getRealComponents();
    rangeData = sounding.getFloats(false);

    // wind
    if (rangeComps.length > 2) {
      transformWinds = (showUAndV && !haveUV) || (!showUAndV && haveUV);
      if (!transformWinds) {
        for (int i = 2; i < 4; i++) {
          columnNames[numDomainCols + i] =
              makeColumnName(rangeComps[i], rangeComps[i].getDefaultUnit());
        }
      } else {
        RealTupleType refType = windTransform.getReference();
        Unit[] refUnits = windTransform.getReferenceUnits();
        for (int i = 0; i < 2; i++) {
          columnNames[numDomainCols + i + 2] =
              makeColumnName((RealType) refType.getComponent(i), refUnits[i]);
        }
        float[][] newVals =
            windTransform.toReference(Set.copyFloats(new float[][] {rangeData[2], rangeData[3]}));
        rangeData[2] = newVals[0];
        rangeData[3] = newVals[1];
      }
    }
    sorter.setTableModel(model);
  }
  /**
   * 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;
  }
 protected static double getMetersConversionFactor(String unitsString) throws Exception {
   SimpleUnit unit = SimpleUnit.factoryWithExceptions(unitsString);
   return unit.convertTo(1.0, SimpleUnit.meterUnit);
 }
  /**
   * Setup needed for all SingleTrajectoryObsDatatypes. Can only be called once.
   *
   * <p>Units of time varible must be udunits time units. Units of latitude variable must be
   * convertible to "degrees_north" by udunits. Units of longitude variable must be convertible to
   * "degrees_east" by udunits. Units of altitude variable must be convertible to "meters" by
   * udunits.
   *
   * @throws IllegalArgumentException if units of time, latitude, longitude, or altitude variables
   *     are not as required.
   * @throws IllegalStateException if this method has already been called.
   */
  public void setTrajectoryInfo(Config trajConfig) throws IOException {
    if (timeDim != null)
      throw new IllegalStateException("The setTrajectoryInfo() method can only be called once.");

    this.trajectoryId = trajConfig.getTrajectoryId();
    this.timeDim = trajConfig.getTimeDim();
    this.timeVar = trajConfig.getTimeVar();
    this.latVar = trajConfig.getLatVar();
    this.lonVar = trajConfig.getLonVar();
    this.elevVar = trajConfig.getElevVar();

    trajectoryNumPoint = this.timeDim.getLength();
    timeVarUnitsString = this.timeVar.findAttribute("units").getStringValue();

    // Check that time, lat, lon, elev units are acceptable.
    if (DateUnit.getStandardDate(timeVarUnitsString) == null) {
      throw new IllegalArgumentException(
          "Units of time variable <" + timeVarUnitsString + "> not a date unit.");
    }
    String latVarUnitsString = this.latVar.findAttribute("units").getStringValue();
    if (!SimpleUnit.isCompatible(latVarUnitsString, "degrees_north")) {
      throw new IllegalArgumentException(
          "Units of lat var <" + latVarUnitsString + "> not compatible with \"degrees_north\".");
    }
    String lonVarUnitsString = this.lonVar.findAttribute("units").getStringValue();
    if (!SimpleUnit.isCompatible(lonVarUnitsString, "degrees_east")) {
      throw new IllegalArgumentException(
          "Units of lon var <" + lonVarUnitsString + "> not compatible with \"degrees_east\".");
    }
    String elevVarUnitsString = this.elevVar.findAttribute("units").getStringValue();
    if (!SimpleUnit.isCompatible(elevVarUnitsString, "meters")) {
      throw new IllegalArgumentException(
          "Units of elev var <" + elevVarUnitsString + "> not compatible with \"meters\".");
    }

    try {
      elevVarUnitsConversionFactor = getMetersConversionFactor(elevVarUnitsString);
    } catch (Exception e) {
      throw new IllegalArgumentException(
          "Exception on getMetersConversionFactor() for the units of elev var <"
              + elevVarUnitsString
              + ">.");
    }

    if (this.ncfile.hasUnlimitedDimension()
        && this.ncfile.getUnlimitedDimension().equals(timeDim)) {
      Object result = this.ncfile.sendIospMessage(NetcdfFile.IOSP_MESSAGE_ADD_RECORD_STRUCTURE);
      if ((result != null) && (Boolean) result)
        this.recordVar = (Structure) this.ncfile.getRootGroup().findVariable("record");
      else this.recordVar = new StructurePseudo(this.ncfile, null, "record", timeDim);
    } else {
      this.recordVar = new StructurePseudo(this.ncfile, null, "record", timeDim);
    }

    // @todo HACK, HACK, HACK - remove once addRecordStructure() deals with ncd attribute changes.
    Variable elevVarInRecVar = this.recordVar.findVariable(this.elevVar.getFullNameEscaped());
    if (!elevVarUnitsString.equals(elevVarInRecVar.findAttribute("units").getStringValue())) {
      elevVarInRecVar.addAttribute(new Attribute("units", elevVarUnitsString));
    }

    trajectoryVarsMap = new HashMap();
    // for ( Iterator it = this.recordVar.getVariables().iterator(); it.hasNext(); )
    for (Iterator it = this.ncfile.getRootGroup().getVariables().iterator(); it.hasNext(); ) {
      Variable curVar = (Variable) it.next();
      if (curVar.getRank() > 0
          && !curVar.equals(this.timeVar)
          && !curVar.equals(this.latVar)
          && !curVar.equals(this.lonVar)
          && !curVar.equals(this.elevVar)
          && (this.recordVar == null ? true : !curVar.equals(this.recordVar))) {
        MyTypedDataVariable typedVar = new MyTypedDataVariable(new VariableDS(null, curVar, true));
        dataVariables.add(typedVar);
        trajectoryVarsMap.put(typedVar.getShortName(), typedVar);
      }
    }

    trajectory =
        new SingleTrajectory(
            this.trajectoryId,
            trajectoryNumPoint,
            this.timeVar,
            timeVarUnitsString,
            this.latVar,
            this.lonVar,
            this.elevVar,
            dataVariables,
            trajectoryVarsMap);

    startDate = trajectory.getTime(0);
    endDate = trajectory.getTime(trajectoryNumPoint - 1);

    ((SingleTrajectory) trajectory).setStartDate(startDate);
    ((SingleTrajectory) trajectory).setEndDate(endDate);
  }
  /** create a NetcdfDataset out of this NetcdfFile, adding coordinates etc. */
  public void augmentDataset(NetcdfDataset ds, CancelTask cancelTask) throws IOException {

    // latitude
    if (!hasAxisType(ds, AxisType.Lat)) { // already has _CoordinateAxisType

      if (!addAxisType(ds, "latitude", AxisType.Lat)) { // directly named

        String vname = ds.findAttValueIgnoreCase(null, "latitude_coordinate", null);
        if (!addAxisType(ds, vname, AxisType.Lat)) { // attribute named

          Variable v =
              hasUnits(ds, "degrees_north,degrees_N,degreesN,degree_north,degree_N,degreeN");
          if (v != null) addAxisType(v, AxisType.Lat); // CF-1
        }
      }
    }

    // longitude
    if (!hasAxisType(ds, AxisType.Lon)) { // already has _CoordinateAxisType

      if (!addAxisType(ds, "longitude", AxisType.Lon)) { // directly named

        String vname = ds.findAttValueIgnoreCase(null, "longitude_coordinate", null);
        if (!addAxisType(ds, vname, AxisType.Lon)) { // attribute named

          Variable v = hasUnits(ds, "degrees_east,degrees_E,degreesE,degree_east,degree_E,degreeE");
          if (v != null) addAxisType(v, AxisType.Lon); // CF-1
        }
      }
    }

    // altitude
    if (!hasAxisType(ds, AxisType.Height)) { // already has _CoordinateAxisType

      if (!addAxisType(ds, "altitude", AxisType.Height)) { // directly named
        if (!addAxisType(ds, "depth", AxisType.Height)) { // directly named

          String vname = ds.findAttValueIgnoreCase(null, "altitude_coordinate", null);
          if (!addAxisType(ds, vname, AxisType.Height)) { // attribute named

            for (int i = 0; i < ds.getVariables().size(); i++) {
              VariableEnhanced ve = (VariableEnhanced) ds.getVariables().get(i);
              String positive = ds.findAttValueIgnoreCase((Variable) ve, "positive", null);
              if (positive != null) {
                addAxisType((Variable) ve, AxisType.Height); // CF-1
                break;
              }
            }
          }
        }
      }
    }

    // time
    if (!hasAxisType(ds, AxisType.Time)) { // already has _CoordinateAxisType

      if (!addAxisType(ds, "time", AxisType.Time)) { // directly named

        String vname = ds.findAttValueIgnoreCase(null, "time_coordinate", null);
        if (!addAxisType(ds, vname, AxisType.Time)) { // attribute named

          for (int i = 0; i < ds.getVariables().size(); i++) {
            VariableEnhanced ve = (VariableEnhanced) ds.getVariables().get(i);
            String unit = ve.getUnitsString();
            if (unit == null) continue;
            if (SimpleUnit.isDateUnit(unit)) {
              addAxisType((Variable) ve, AxisType.Time); // CF-1
              break;
            }
          }
        }
      }
    }
  }
  /**
   * Add this coord as a variable in the netCDF file
   *
   * @param ncfile netCDF file to add to
   * @param g group in file
   */
  void addToNetcdfFile(NetcdfFile ncfile, Group g) {
    if (dontUseVertical) {
      typicalRecord = null;
      return;
    }

    if (g == null) {
      g = ncfile.getRootGroup();
    }

    // coordinate axis
    Variable v = new Variable(ncfile, g, null, getVariableName());
    v.setDataType(DataType.DOUBLE);

    String desc = lookup.getLevelDescription(typicalRecord);
    if (lookup instanceof Grib2GridTableLookup && usesBounds) {
      desc = "Layer between " + desc;
    }

    v.addAttribute(new Attribute("long_name", desc));
    v.addAttribute(new Attribute("units", lookup.getLevelUnit(typicalRecord)));

    // positive attribute needed for CF-1 Height and Pressure
    if (positive != null) {
      v.addAttribute(new Attribute("positive", positive));
    }

    if (units != null) {
      AxisType axisType;
      if (SimpleUnit.isCompatible("millibar", units)) {
        axisType = AxisType.Pressure;
      } else if (SimpleUnit.isCompatible("m", units)) {
        axisType = AxisType.Height;
      } else {
        axisType = AxisType.GeoZ;
      }

      if (lookup instanceof Grib2GridTableLookup || lookup instanceof Grib1GridTableLookup) {
        v.addAttribute(
            new Attribute("GRIB_level_type", Integer.toString(typicalRecord.getLevelType1())));
      } else {
        v.addAttribute(
            new Attribute("level_type", Integer.toString(typicalRecord.getLevelType1())));
      }
      v.addAttribute(new Attribute(_Coordinate.AxisType, axisType.toString()));
    }

    if (coordValues == null) {
      coordValues = new double[levels.size()];
      for (int i = 0; i < levels.size(); i++) {
        LevelCoord lc = (LevelCoord) levels.get(i);
        coordValues[i] = lc.mid;
      }
    }
    Array dataArray = Array.factory(DataType.DOUBLE, new int[] {coordValues.length}, coordValues);

    v.setDimensions(getVariableName());
    v.setCachedData(dataArray, true);

    ncfile.addVariable(g, v);

    if (usesBounds) {
      String boundsDimName = "bounds_dim";
      if (g.findDimension(boundsDimName) == null) {
        ncfile.addDimension(g, new Dimension(boundsDimName, 2, true));
      }

      String bname = getVariableName() + "_bounds";
      v.addAttribute(new Attribute("bounds", bname));
      v.addAttribute(new Attribute(_Coordinate.ZisLayer, "true"));

      Variable b = new Variable(ncfile, g, null, bname);
      b.setDataType(DataType.DOUBLE);
      b.setDimensions(getVariableName() + " " + boundsDimName);
      b.addAttribute(new Attribute("long_name", "bounds for " + v.getName()));
      b.addAttribute(new Attribute("units", lookup.getLevelUnit(typicalRecord)));

      Array boundsArray = Array.factory(DataType.DOUBLE, new int[] {coordValues.length, 2});
      ucar.ma2.Index ima = boundsArray.getIndex();
      for (int i = 0; i < coordValues.length; i++) {
        LevelCoord lc = (LevelCoord) levels.get(i);
        boundsArray.setDouble(ima.set(i, 0), lc.value1);
        boundsArray.setDouble(ima.set(i, 1), lc.value2);
      }
      b.setCachedData(boundsArray, true);

      ncfile.addVariable(g, b);
    }

    if (factors != null) {
      // check if already created
      if (g == null) {
        g = ncfile.getRootGroup();
      }
      if (g.findVariable("hybrida") != null) return;
      v.addAttribute(new Attribute("standard_name", "atmosphere_hybrid_sigma_pressure_coordinate"));
      v.addAttribute(new Attribute("formula_terms", "ap: hybrida b: hybridb ps: Pressure"));
      // create  hybrid factor variables
      // add hybrida variable
      Variable ha = new Variable(ncfile, g, null, "hybrida");
      ha.setDataType(DataType.DOUBLE);
      ha.addAttribute(new Attribute("long_name", "level_a_factor"));
      ha.addAttribute(new Attribute("units", ""));
      ha.setDimensions(getVariableName());
      // add data
      int middle = factors.length / 2;
      double[] adata;
      double[] bdata;
      if (levels.size() < middle) { // only partial data wanted
        adata = new double[levels.size()];
        bdata = new double[levels.size()];
      } else {
        adata = new double[middle];
        bdata = new double[middle];
      }
      for (int i = 0; i < middle && i < levels.size(); i++) adata[i] = factors[i];
      Array haArray = Array.factory(DataType.DOUBLE, new int[] {adata.length}, adata);
      ha.setCachedData(haArray, true);
      ncfile.addVariable(g, ha);

      // add hybridb variable
      Variable hb = new Variable(ncfile, g, null, "hybridb");
      hb.setDataType(DataType.DOUBLE);
      hb.addAttribute(new Attribute("long_name", "level_b_factor"));
      hb.addAttribute(new Attribute("units", ""));
      hb.setDimensions(getVariableName());
      // add data
      for (int i = 0; i < middle && i < levels.size(); i++) bdata[i] = factors[i + middle];
      Array hbArray = Array.factory(DataType.DOUBLE, new int[] {bdata.length}, bdata);
      hb.setCachedData(hbArray, true);
      ncfile.addVariable(g, hb);

      /*  // TODO: delete next time modifying code
      double[] adata = new double[ middle ];
      for( int i = 0; i < middle; i++ )
        adata[ i ] = factors[ i ];
      Array haArray = Array.factory(DataType.DOUBLE, new int[]{adata.length}, adata);
      ha.setCachedData(haArray, true);
      ncfile.addVariable(g, ha);

      // add hybridb variable
      Variable hb = new Variable(ncfile, g, null, "hybridb");
      hb.setDataType(DataType.DOUBLE);
      hb.addAttribute(new Attribute("long_name",  "level_b_factor" ));
      //hb.addAttribute(new Attribute("standard_name", "atmosphere_hybrid_sigma_pressure_coordinate" ));
      hb.addAttribute(new Attribute("units", ""));
      hb.setDimensions(getVariableName());
      // add data
      double[] bdata = new double[ middle ];
      for( int i = 0; i < middle; i++ )
        bdata[ i ] = factors[ i + middle ];
      Array hbArray = Array.factory(DataType.DOUBLE, new int[]{bdata.length}, bdata);
      hb.setCachedData(hbArray, true);
      ncfile.addVariable(g, hb);
      */
    }
  }
  public static boolean isValidFile(NetcdfDataset ds) {
    // Check that has a time dimension and a trajectory dimension.
    List list = ds.getRootGroup().getDimensions();
    if (list.size() != 2) return (false);
    Dimension d;
    for (int i = 0; i < 2; i++) {
      d = (Dimension) list.get(i);
      if (!d.getShortName().equals(timeDimNameDefault)
          && !d.getShortName().equals(trajDimNameDefault)) return (false);
    }

    // Check that has a trajectory coordinate variable.
    Variable var = ds.getRootGroup().findVariable(trajVarNameDefault);
    if (var == null) return (false);
    list = var.getDimensions();
    if (list.size() != 1) return (false);
    d = (Dimension) list.get(0);
    if (!d.getShortName().equals(trajDimNameDefault)) return (false);

    // Check that has a time coordinate variable with units that are udunits time
    var = ds.getRootGroup().findVariable(timeVarNameDefault);
    if (var == null) return (false);
    list = var.getDimensions();
    if (list.size() != 1) return (false);
    d = (Dimension) list.get(0);
    if (!d.getShortName().equals(timeDimNameDefault)) return (false);
    String units = var.findAttribute("units").getStringValue();
    Date date = DateUnit.getStandardDate("0 " + units);
    if (date == null) return (false);

    // Check for variable latitude(time) with units of "deg".
    var = ds.getRootGroup().findVariable(latVarNameDefault);
    if (var == null) return (false);
    list = var.getDimensions();
    if (list.size() != 2) return (false);
    for (int i = 0; i < 2; i++) {
      d = (Dimension) list.get(i);
      if (!d.getShortName().equals(timeDimNameDefault)
          && !d.getShortName().equals(trajDimNameDefault)) return (false);
    }
    //    units = var.findAttribute( "units").getStringValue();
    //    if ( ! SimpleUnit.isCompatible( units, "degrees_north")) return( false);

    // Check for variable longitude(time) with units of "deg".
    var = ds.getRootGroup().findVariable(lonVarNameDefault);
    if (var == null) return (false);
    list = var.getDimensions();
    if (list.size() != 2) return (false);
    for (int i = 0; i < 2; i++) {
      d = (Dimension) list.get(i);
      if (!d.getShortName().equals(timeDimNameDefault)
          && !d.getShortName().equals(trajDimNameDefault)) return (false);
    }
    //    units = var.findAttribute( "units").getStringValue();
    //    if ( ! SimpleUnit.isCompatible( units, "degrees_east")) return( false);

    // Check for variable altitude(time) with units of "m".
    var = ds.getRootGroup().findVariable(elevVarNameDefault);
    if (var == null) return (false);
    list = var.getDimensions();
    if (list.size() != 2) return (false);
    for (int i = 0; i < 2; i++) {
      d = (Dimension) list.get(i);
      if (!d.getShortName().equals(timeDimNameDefault)
          && !d.getShortName().equals(trajDimNameDefault)) return (false);
    }
    units = var.findAttribute("units").getStringValue();
    if (!SimpleUnit.isCompatible(units, "m")) return (false);

    return (true);
  }