All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.nc2.dt.point.RecordDatasetHelper Maven / Gradle / Ivy

Go to download

The NetCDF-Java Library is a Java interface to NetCDF files, as well as to many other types of scientific data formats.

The newest version!
/*
 * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
 *
 * Portions of this software were developed by the Unidata Program at the
 * University Corporation for Atmospheric Research.
 *
 * Access and use of this software shall impose the following obligations
 * and understandings on the user. The user is granted the right, without
 * any fee or cost, to use, copy, modify, alter, enhance and distribute
 * this software, and any derivative works thereof, and its supporting
 * documentation for any purpose whatsoever, provided that this entire
 * notice appears in all copies of the software, derivative works and
 * supporting documentation.  Further, UCAR requests that the user credit
 * UCAR/Unidata in any publications that result from the use of this
 * software or in any product that includes this software. The names UCAR
 * and/or Unidata, however, may not be used in any advertising or publicity
 * to endorse or promote any products or commercial entity unless specific
 * written permission is obtained from UCAR/Unidata. The user also
 * understands that UCAR/Unidata is not obligated to provide the user with
 * any support, consulting, training or assistance of any kind with regard
 * to the use, operation and performance of this software nor to provide
 * the user with any updates, revisions, new versions or "bug fixes."
 *
 * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package ucar.nc2.dt.point;

import ucar.nc2.*;
import ucar.nc2.dataset.NetcdfDataset;
import ucar.nc2.dataset.StructureDS;
import ucar.nc2.StructurePseudo;
import ucar.nc2.units.DateUnit;
import ucar.nc2.util.CancelTask;
import ucar.nc2.dt.*;
import ucar.unidata.geoloc.LatLonPointImpl;
import ucar.unidata.geoloc.LatLonRect;
import ucar.unidata.geoloc.LatLonPoint;
import ucar.ma2.StructureData;
import ucar.ma2.DataType;
import ucar.ma2.StructureMembers;
import ucar.ma2.StructureDataIterator;

import java.io.*;
import java.util.*;

/**
 * Helper class for using the netcdf-3 record dimension. Can be used for PointObs or StationObs.
 *
 * @author caron
 * @deprecated use ucar.nc2.ft.*
 */

public class RecordDatasetHelper {
  protected NetcdfDataset ncfile;
  protected String obsTimeVName, nomTimeVName;
  protected String stnIdVName, stnNameVName, stnDescVName;
  protected String latVName, lonVName, altVName;
  protected DataType stationIdType;

  protected Map stnHash;
  protected StructureDS recordVar;
  protected Dimension obsDim;

  protected LatLonRect boundingBox;
  protected double minDate, maxDate;
  protected DateUnit timeUnit;

  protected double altScaleFactor = 1.0;

  protected StringBuffer errs = null;
  protected boolean showErrors = true;

  /**
   * Constructor.
   *
   * @param ncfile             the netccdf file
   * @param typedDataVariables list of data variables; all record variables will be added to this list, except . You
   *                           can remove extra
   * @param obsTimeVName       observation time variable name (required)
   * @param nomTimeVName       nominal time variable name (may be null)
   * @throws IllegalArgumentException if ncfile has no unlimited dimension.
   */
  public RecordDatasetHelper(NetcdfDataset ncfile, String obsTimeVName, String nomTimeVName, List typedDataVariables) {
    this(ncfile, obsTimeVName, nomTimeVName, typedDataVariables, null, null);
  }

  public RecordDatasetHelper(NetcdfDataset ncfile, String obsTimeVName, String nomTimeVName, List typedDataVariables,
                             StringBuffer errBuffer) {
    this(ncfile, obsTimeVName, nomTimeVName, typedDataVariables, null, errBuffer);
  }

  /**
   * Constructor.
   *
   * @param ncfile             the netccdf file
   * @param typedDataVariables list of data variables; all record variables will be added to this list, except . You
   *                           can remove extra
   * @param obsTimeVName       observation time variable name (required)
   * @param nomTimeVName       nominal time variable name (may be null)
   * @throws IllegalArgumentException if ncfile has no unlimited dimension and recDimName is null.
   */
  public RecordDatasetHelper(NetcdfDataset ncfile, String obsTimeVName, String nomTimeVName, List typedDataVariables,
                             String recDimName, StringBuffer errBuffer) {
    this.ncfile = ncfile;
    this.obsTimeVName = obsTimeVName;
    this.nomTimeVName = nomTimeVName;
    this.errs = errBuffer;

    // check if we already have a structure vs if we have to add it.

    if (this.ncfile.hasUnlimitedDimension()) {
      this.ncfile.sendIospMessage(NetcdfFile.IOSP_MESSAGE_ADD_RECORD_STRUCTURE);
      this.recordVar = (StructureDS) this.ncfile.getRootGroup().findVariable("record");
      this.obsDim = ncfile.getUnlimitedDimension();

    } else {
      if (recDimName == null)
        throw new IllegalArgumentException("File <" + this.ncfile.getLocation() +
                "> has no unlimited dimension, specify psuedo record dimension with observationDimension global attribute.");
      this.obsDim = this.ncfile.getRootGroup().findDimension(recDimName);
      this.recordVar = new StructureDS(null, new StructurePseudo(this.ncfile, null, "record", obsDim)); // true
    }

    // create member variables
    List recordMembers = ncfile.getVariables();
    for (Variable v : recordMembers) {
      if (v == recordVar) continue;
      if (v.isScalar()) continue;
      if (v.getDimension(0) == this.obsDim)
        typedDataVariables.add(v);
    }

    // need the time units
    Variable timeVar = ncfile.findVariable(obsTimeVName);
    String timeUnitString = ncfile.findAttValueIgnoreCase(timeVar, "units", "seconds since 1970-01-01");
    try {
      timeUnit = new DateUnit(timeUnitString);
    } catch (Exception e) {
      if (null != errs) errs.append("Error on string = " + timeUnitString + " == " + e.getMessage() + "\n");
      try {
        timeUnit = new DateUnit("seconds since 1970-01-01");
      } catch (Exception e1) {
        // cant happen
      }
    }
  }

  /**
   * Set extra information used by station obs datasets.
   *
   * @param stnIdVName   the obs variable that is used to find the station in the stnHash; may be type  int or a String (char).
   * @param stnDescVName optional station var containing station description
   */
  public void setStationInfo(String stnIdVName, String stnDescVName) {
    this.stnIdVName = stnIdVName;
    this.stnDescVName = stnDescVName;

    Variable stationVar = ncfile.findVariable(stnIdVName);
    stationIdType = stationVar.getDataType();
  }

  public void setLocationInfo(String latVName, String lonVName, String altVName) {
    this.latVName = latVName;
    this.lonVName = lonVName;
    this.altVName = altVName;

    // check for meter conversion
    if (altVName != null) {
      Variable v = ncfile.findVariable(altVName);
      String units = ncfile.findAttValueIgnoreCase(v, "units", null);
      if (units != null)
        try {
          altScaleFactor = PointObsDatasetImpl.getMetersConversionFactor(units);
        } catch (Exception e) {
          if (errs != null) errs.append(e.getMessage());
        }
    }
  }

  public Structure getRecordVar() {
    return (this.recordVar);
  }

  public int getRecordCount() {
    Dimension unlimitedDim = ncfile.getUnlimitedDimension();
    return unlimitedDim.getLength();
  }

  public void setTimeUnit(DateUnit timeUnit) {
    this.timeUnit = timeUnit;
  }

  public DateUnit getTimeUnit() {
    return (this.timeUnit);
  }

  /**
   * This reads through all the records in the dataset, and constructs a list of
   * RecordPointObs or RecordStationObs. It does not cache the data.
   * 

If stnIdVName is not null, its a StationDataset, then construct a Station HashMap of StationImpl * objects. Add the RecordStationObs into the list of obs for that station. * * @param cancel allow user to cancel * @return List of RecordPointObs or RecordStationObs * @throws IOException */ public ArrayList readAllCreateObs(CancelTask cancel) throws IOException { // see if its a station or point dataset boolean hasStations = stnIdVName != null; if (hasStations) stnHash = new HashMap(); // get min and max date and lat,lon double minDate = Double.MAX_VALUE; double maxDate = -Double.MAX_VALUE; double minLat = Double.MAX_VALUE; double maxLat = -Double.MAX_VALUE; double minLon = Double.MAX_VALUE; double maxLon = -Double.MAX_VALUE; // read all the data, create a RecordObs ArrayList records = new ArrayList(); int recno = 0; StructureDataIterator ii = recordVar.getStructureIterator(); try { while (ii.hasNext()) { StructureData sdata = ii.next(); StructureMembers members = sdata.getStructureMembers(); Object stationId = null; if (hasStations) { if (stationIdType == DataType.INT) { int stationNum = sdata.getScalarInt(stnIdVName); stationId = new Integer(stationNum); } else stationId = sdata.getScalarString(stnIdVName).trim(); } String desc = (stnDescVName == null) ? null : sdata.getScalarString(stnDescVName); double lat = sdata.convertScalarDouble(latVName); double lon = sdata.convertScalarDouble(lonVName); double alt = (altVName == null) ? Double.NaN : altScaleFactor * sdata.convertScalarDouble(altVName); double obsTime = sdata.convertScalarDouble(members.findMember(obsTimeVName)); double nomTime = (nomTimeVName == null) ? obsTime : sdata.convertScalarDouble(members.findMember(nomTimeVName)); //double obsTime = sdata.convertScalarDouble( members.findMember( obsTimeVName) ); //double nomTime = (nomTimeVName == null) ? obsTime : sdata.convertScalarDouble( members.findMember( nomTimeVName)); if (hasStations) { StationImpl stn = (StationImpl) stnHash.get(stationId); if (stn == null) { stn = new StationImpl(stationId.toString(), desc, lat, lon, alt); stnHash.put(stationId, stn); } RecordStationObs stnObs = new RecordStationObs(stn, obsTime, nomTime, recno); records.add(stnObs); stn.addObs(stnObs); } else { records.add(new RecordPointObs(new ucar.unidata.geoloc.EarthLocationImpl(lat, lon, alt), obsTime, nomTime, recno)); } // track date range and bounding box minDate = Math.min(minDate, obsTime); maxDate = Math.max(maxDate, obsTime); minLat = Math.min(minLat, lat); maxLat = Math.max(maxLat, lat); minLon = Math.min(minLon, lon); maxLon = Math.max(maxLon, lon); recno++; if ((cancel != null) && cancel.isCancel()) return null; } } finally { ii.finish(); } boundingBox = new LatLonRect(new LatLonPointImpl(minLat, minLon), new LatLonPointImpl(maxLat, maxLon)); return records; } // make structure variable names to shortNames so StructureData sdata can // access it members public void setShortNames(String latVName, String lonVName, String altVName, String obsTimeVName, String nomTimeVName) { this.latVName = latVName; this.lonVName = lonVName; this.altVName = altVName; this.obsTimeVName = obsTimeVName; this.nomTimeVName = nomTimeVName; } private boolean debugBB = false; public List getData(ArrayList records, LatLonRect boundingBox, CancelTask cancel) throws IOException { if (debugBB) System.out.println("Want bb= " + boundingBox); ArrayList result = new ArrayList(); for (int i = 0; i < records.size(); i++) { RecordDatasetHelper.RecordPointObs r = (RecordDatasetHelper.RecordPointObs) records.get(i); if (boundingBox.contains(r.getLatLon())) { if (debugBB) System.out.println(" ok latlon= " + r.getLatLon()); result.add(r); } if ((cancel != null) && cancel.isCancel()) return null; } return result; } // return List public List getData(ArrayList records, LatLonRect boundingBox, double startTime, double endTime, CancelTask cancel) throws IOException { if (debugBB) System.out.println("Want bb= " + boundingBox); ArrayList result = new ArrayList(); for (int i = 0; i < records.size(); i++) { RecordDatasetHelper.RecordPointObs r = (RecordDatasetHelper.RecordPointObs) records.get(i); if (boundingBox.contains(r.getLatLon())) { if (debugBB) System.out.println(" ok latlon= " + r.getLatLon()); double timeValue = r.getObservationTime(); if ((timeValue >= startTime) && (timeValue <= endTime)) result.add(r); } if ((cancel != null) && cancel.isCancel()) return null; } return result; } ////////////////////////////////////////////////////////////////////////////////////// public class RecordPointObs extends PointObsDatatypeImpl { protected int recno; protected LatLonPointImpl llpt = null; protected StructureData sdata; protected RecordPointObs() { } /** * Constructor for the case where you keep track of the location, time of each record, but not the data. */ protected RecordPointObs(ucar.unidata.geoloc.EarthLocation location, double obsTime, double nomTime, int recno) { super(location, obsTime, nomTime); this.recno = recno; } /** * Constructor for when you already have the StructureData and want to wrap it in a StationObsDatatype * * @param recno record number LOOK why do we need ?? * @param sdata the structure data */ public RecordPointObs(int recno, StructureData sdata) { this.recno = recno; this.sdata = sdata; StructureMembers members = sdata.getStructureMembers(); obsTime = sdata.convertScalarDouble(members.findMember(obsTimeVName)); nomTime = (nomTimeVName == null) ? obsTime : sdata.convertScalarDouble(members.findMember(nomTimeVName)); // obsTime = sdata.convertScalarDouble( members.findMember(obsTimeVName) ); //nomTime = (nomTimeVName == null) ? obsTime : sdata.convertScalarDouble( members.findMember(nomTimeVName)); double lat = sdata.convertScalarDouble(latVName); double lon = sdata.convertScalarDouble(lonVName); double alt = (altVName == null) ? Double.NaN : altScaleFactor * sdata.convertScalarDouble(altVName); location = new ucar.unidata.geoloc.EarthLocationImpl(lat, lon, alt); } public LatLonPoint getLatLon() { if (llpt == null) llpt = new LatLonPointImpl(location.getLatitude(), location.getLongitude()); return llpt; } public Date getNominalTimeAsDate() { return timeUnit.makeDate(getNominalTime()); } public Date getObservationTimeAsDate() { return timeUnit.makeDate(getObservationTime()); } public StructureData getData() throws IOException { if (null != sdata) return sdata; try { return recordVar.readStructure(recno); } catch (ucar.ma2.InvalidRangeException e) { e.printStackTrace(); throw new IOException(e.getMessage()); } } } ////////////////////////////////////////////////////////////////////////////////////// public class RecordStationObs extends RecordPointObs implements StationObsDatatype { private ucar.unidata.geoloc.Station station; /** * Constructor for the case where you keep track of the station, time of each record, but the data reading is deferred. * * @param station data is for this Station * @param obsTime observation time * @param nomTime nominal time (may be NaN) * @param recno data is at this record number */ protected RecordStationObs(ucar.unidata.geoloc.Station station, double obsTime, double nomTime, int recno) { super(station, obsTime, nomTime, recno); this.station = station; } /** * Constructor for when you already have the StructureData and want to wrap it in a StationObsDatatype * * @param recno record number LOOK why do we need ?? * @param sdata the structure data */ protected RecordStationObs(int recno, StructureData sdata) { this.recno = recno; this.sdata = sdata; StructureMembers members = sdata.getStructureMembers(); obsTime = sdata.convertScalarDouble(members.findMember(obsTimeVName)); nomTime = (nomTimeVName == null) ? obsTime : sdata.convertScalarDouble(members.findMember(nomTimeVName)); //obsTime = sdata.convertScalarDouble( members.findMember(obsTimeVName) ); //nomTime = (nomTimeVName == null) ? obsTime : sdata.convertScalarDouble( members.findMember(nomTimeVName)); Object stationId; if (stationIdType == DataType.INT) { stationId = sdata.getScalarInt(stnIdVName); } else stationId = sdata.getScalarString(stnIdVName).trim(); station = (ucar.unidata.geoloc.Station) stnHash.get(stationId); location = station; if (station == null) { if (null != errs) errs.append(" cant find station = <").append(stationId).append(">" + "when reading record ").append(recno).append("\n"); if (showErrors) System.out.println(" cant find station = <" + stationId + ">" + "when reading record " + recno); } } /** * Constructor for when you already have the StructureData and want to wrap it in a StationObsDatatype * * @param station data is for this Station * @param obsTime observation time * @param nomTime nominal time (may be NaN) * @param sdata the structure data */ protected RecordStationObs(ucar.unidata.geoloc.Station station, double obsTime, double nomTime, StructureData sdata) { this.station = station; this.location = station; this.obsTime = obsTime; this.nomTime = nomTime; this.sdata = sdata; } /** * Constructor for when you already have the StructureData and want to wrap it in a StationObsDatatype * * @param station data is for this Station * @param sdata the structure data */ protected RecordStationObs(ucar.unidata.geoloc.Station station, StructureData sdata) { this.station = station; this.location = station; this.sdata = sdata; StructureMembers members = sdata.getStructureMembers(); obsTime = sdata.convertScalarDouble(members.findMember(obsTimeVName)); nomTime = (nomTimeVName == null) ? obsTime : sdata.convertScalarDouble(members.findMember(nomTimeVName)); //obsTime = sdata.convertScalarDouble( members.findMember(obsTimeVName) ); //nomTime = (nomTimeVName == null) ? obsTime : sdata.convertScalarDouble( members.findMember(nomTimeVName)); } public ucar.unidata.geoloc.Station getStation() { return station; } public StructureData getData() throws IOException { if (null != sdata) return sdata; try { return recordVar.readStructure(recno); // note we dont cache sdata } catch (ucar.ma2.InvalidRangeException e) { e.printStackTrace(); throw new IOException(e.getMessage()); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy