Package ucar.nc2.iosp.grid

Source Code of ucar.nc2.iosp.grid.GridVariable$Belongs

/*
* 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.iosp.grid;

import ucar.grib.grib1.Grib1Data;
import ucar.grib.grib2.Grib2Data;
import ucar.grib.grib2.Grib2Pds;
import ucar.ma2.Array;
import ucar.ma2.DataType;

import ucar.nc2.*;
import ucar.nc2.constants.CF;
import ucar.nc2.iosp.AbstractIOServiceProvider;
import ucar.nc2.units.DateFormatter;
import ucar.grid.GridRecord;
import ucar.grid.GridTableLookup;
import ucar.grid.GridParameter;
import ucar.grid.GridDefRecord;
import ucar.unidata.io.RandomAccessFile;
import ucar.grib.grib1.Grib1GridTableLookup;
import ucar.grib.grib2.Grib2GridTableLookup;
import ucar.grib.grib2.Grib2Tables;
import ucar.grib.GribGridRecord;
import ucar.unidata.util.StringUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;


/**
* A Variable for a Grid dataset.
*
* @author caron
*/
public class GridVariable {

  /**
   * logger
   */
  static private org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GridVariable.class);
  static private boolean warnOk = true;
  static private boolean compareData = false;
  static private boolean sendAll = false; // if false, just send once per variable

  private final String filename;

  /**
   * disambiguated name == parameter name [ + suffix] [ + level]
   */
  private final String name;

  /**
   * variable name
   */
  private String vname;

  /**
   * first grid record
   */
  private GridRecord firstRecord;

  /**
   * lookup table
   */
  private GridTableLookup lookup;

  /**
   * horizontal coord system
   */
  private GridHorizCoordSys hcs;

  /**
   * vertical coord system
   *
  private GridCoordSys vcs;  // maximal strategy (old way) */

  /**
   * time coord system
   */
  private GridTimeCoord tcs = null;

  /**
   * ensemble coord system
   */
  private GridEnsembleCoord ecs = null;

  /**
   * vertical coordinate
   */
  private GridVertCoord vc = null;

  /**
   * list of records that make up this variable
   */
  private List<GridRecord> records = new ArrayList<GridRecord>()// GridRecord

  /**
   * number of levels
   */
  private int nlevels;

  /**
   * number of Ensembles
   */
  private int nens;

  /**
   * number of times
   */
  private int ntimes;

  /**
   * record tracker
   */
  private GridRecord[] recordTracker;

  /**
   * flag for having a vertical coordinate
   */
  private boolean hasVert = false;

  /**
   * Create a new GridVariable
   *
   * @param name   name with level
   * @param hcs    horizontal coordinate system
   * @param lookup lookup table
   */
  GridVariable(String filename, String name, GridHorizCoordSys hcs, GridTableLookup lookup) {
    this.filename = filename;  //for debugging
    this.name = name;  // used to get unique grouping of products
    this.hcs = hcs;
    this.lookup = lookup;
  }

  /**
   * Add in a new product
   *
   * @param record grid  to add
   */
  void addProduct(GridRecord record) {
    records.add(record);
    if (firstRecord == null) {
      firstRecord = record;
    }
  }

  /**
   * Get the list of grids
   *
   * @return grid records
   */
  List<GridRecord> getRecords() {
    return records;
  }

  /**
   * get the first grid record
   *
   * @return the first in the list
   */
  GridRecord getFirstRecord() {
    return records.get(0);
  }

  /**
   * Get the horizontal coordinate system
   *
   * @return the horizontal coordinate system
   */
  GridHorizCoordSys getHorizCoordSys() {
    return hcs;
  }

  /**
   * Get the vertical coordinate
   *
   * @return the vertical coordinate
   */
  GridVertCoord getVertCoord() {
    return vc;
  }

  /**
   * Does this have a vertical dimension
   *
   * @return true if has a vertical dimension
   */
  boolean hasVert() {
    return hasVert;
  }

  /**
   * Set the variable name
   *
   * @param vname the variable name
   */
  void setVarName(String vname) {
    this.vname = vname;
  }

  /**
   * Set the vertical coordinate
   *
   * @param vc the vertical coordinate
   */
  void setVertCoord(GridVertCoord vc) {
    this.vc = vc;
  }

  /**
   * Set the time coordinate
   *
   * @param tcs the time coordinate
   */
  void setTimeCoord(GridTimeCoord tcs) {
    this.tcs = tcs;
  }

  /**
   * Set the Ensemble coordinate
   *
   * @param ecs the Ensemble coordinate
   */
  void setEnsembleCoord(GridEnsembleCoord ecs) {
    this.ecs = ecs;
  }

  /**
   * Get the number of Ensemble
   *
   * @return the number of Ensemble
   */
  public int getNEnsembles() {
    return (ecs == null) ? 1 : ecs.getNEnsembles();
  }

  /*
   * Get the product definition number of Ensemble
   *
   * @return the product definition number of Ensemble
   *
  public int getPDN() {
    return (ecs == null) ? -1 : ecs.getPDN();
  }

  /*
   * Get the types of Ensemble
   *
   * @return the types of Ensemble
   *
  public int[] getEnsTypes() {
    return (ecs == null) ? null : ecs.getEnsType();
  } */

  /*
   * Get the Index of Ensemble
   *
   * @param record GridRecord
   * @return the Index of Ensemble
   *
  int getEnsembleIndex(GridRecord record) {
    return (ecs == null) ? 1 : ecs.getIndex(record);
  } */

  /**
   * Does this have a Ensemble coordinate
   *
   * @return true if has a Ensemble coordinate
   */
  boolean hasEnsemble() {
    return (ecs != null);
  }

  boolean isEnsemble() {
    if (firstRecord instanceof GribGridRecord) {
      GribGridRecord ggr = (GribGridRecord) firstRecord;
      return ggr.getPds().isEnsemble();
    }
    return false;
  }

  /**
   * Get the number of vertical levels
   *
   * @return the number of vertical levels
   */
  int getVertNlevels() {
    return vc.getNLevels();
  }

  /**
   * Get the name of the vertical dimension
   *
   * @return the name of the vertical dimension
   */
  String getVertName() {
    return vc.getVariableName();
  }

  /**
   * Get the name of the vertical level
   *
   * @return the name of the vertical level
   */
  String getVertLevelName() {
    return  vc.getLevelName();
  }

  /**
   * Is vertical used?
   *
   * @return true if vertical used
   */
  boolean getVertIsUsed() {
    return vc.isVertDimensionUsed();
  }

  /**
   * Get the index in the vertical for the particular grid
   *
   * @param p grid to check
   * @return the index
   */
  int getVertIndex(GridRecord p) {
    return vc.getIndex(p);
  }

  /**
   * Get the number of times
   *
   * @return the number of times
   */
  int getNTimes() {
    return (tcs == null) ? 1 : tcs.getNTimes();
  }

  /*
   * is this a time interval variable
   *
   * @return true if uses time intervals
   *
  boolean isInterval() {
    if (firstRecord instanceof GribGridRecord) {
      GribGridRecord ggr = (GribGridRecord) firstRecord;
      return ggr.isInterval();
    }
    return false;
  }

  String getIntervalTypeName() {
    if (firstRecord instanceof GribGridRecord) {
      GribGridRecord ggr = (GribGridRecord) firstRecord;
      return ggr.getStatisticalProcessTypeName();
    }
    return null;
  } */

  /**
   * Make the netcdf variable. If vname is not already set, use useName as name
   *
   * @param ncfile  netCDF file
   * @param g       group
   * @param useName use this as the variable name
   * @param raf read from here
   * @return the netcdf variable
   */
  Variable makeVariable(NetcdfFile ncfile, Group g, String useName, RandomAccessFile raf) {
    assert records.size() > 0 : "no records for this variable";

    this.nlevels = getVertNlevels();
    this.ntimes = tcs.getNTimes();
    if (vname == null) {
      useName = StringUtil.replace(useName, ' ', "_");
      this.vname = useName;
    }

    Variable v = new Variable(ncfile, g, null, vname);
    v.setDataType(DataType.FLOAT);

    Formatter dims = new Formatter();

    if (hasEnsemble()) {
      dims.format("ens ");
    }

    dims.format("%s ", tcs.getName());

    if (getVertIsUsed()) {
      dims.format("%s ",  getVertName());
      hasVert = true;
    }

    if (hcs.isLatLon()) {
      dims.format("lat lon");
    } else {
      dims.format("y x");
    }

    v.setDimensions(dims.toString());

    // add attributes
    GridParameter param = lookup.getParameter(firstRecord);
    String unit = param.getUnit();
    if (unit == null) unit = "";
    v.addAttribute(new Attribute("units", unit));

    v.addAttribute(new Attribute("long_name", makeLongName()));
    if (firstRecord instanceof GribGridRecord) {
      GribGridRecord ggr = (GribGridRecord) firstRecord;
      if (ggr.isInterval()) {
        CF.CellMethods cm = CF.CellMethods.convertGribCodeTable4_10(ggr.getStatisticalProcessType());
        if (cm != null)
          v.addAttribute(new Attribute("cell_methods", tcs.getName() + ": " + cm.toString()));
      }
    }
    v.addAttribute(new Attribute("missing_value", new Float(lookup.getFirstMissingValue())));
    if (!hcs.isLatLon()) {
      if (ucar.nc2.iosp.grib.GribGridServiceProvider.addLatLon)
        v.addAttribute(new Attribute("coordinates", "lat lon"));
      v.addAttribute(new Attribute("grid_mapping", hcs.getGridName()));
    }

    // LOOK VECTOR_COMPONENT_FLAG handling is very lame
    int icf = hcs.getGds().getInt(GridDefRecord.VECTOR_COMPONENT_FLAG);
    String flag;
    if (icf == 0) {
      flag = Grib2Tables.VectorComponentFlag.easterlyNortherlyRelative.toString();
    } else {
      flag = Grib2Tables.VectorComponentFlag.gridRelative.toString();
    }

    if (lookup instanceof Grib2GridTableLookup) {
      Grib2GridTableLookup g2lookup = (Grib2GridTableLookup) lookup;
      GribGridRecord ggr = (GribGridRecord) firstRecord;
      Grib2Pds pds2 = (Grib2Pds) ggr.getPds();

      int[] paramId = g2lookup.getParameterId(firstRecord);
      v.addAttribute(new Attribute("GRIB_param_discipline", lookup.getDisciplineName(firstRecord)));
      v.addAttribute(new Attribute("GRIB_param_category", lookup.getCategoryName(firstRecord)));
      v.addAttribute(new Attribute("GRIB_param_name", param.getName()));
      v.addAttribute(new Attribute("GRIB_generating_process_type", g2lookup.getGenProcessTypeName(firstRecord)));
      v.addAttribute(new Attribute("GRIB_param_id", Array.factory(int.class, new int[]{paramId.length}, paramId)));
      v.addAttribute(new Attribute("GRIB_product_definition_template", pds2.getProductDefinitionTemplate()));
      v.addAttribute(new Attribute("GRIB_product_definition_template_desc", Grib2Tables.codeTable4_0( pds2.getProductDefinitionTemplate())));
      v.addAttribute(new Attribute("GRIB_level_type", new Integer(pds2.getLevelType1())));
      v.addAttribute(new Attribute("GRIB_level_type_name", lookup.getLevelName(firstRecord)));
      if (pds2.isInterval())
        v.addAttribute(new Attribute("GRIB_interval_stat_type", ggr.getStatisticalProcessTypeName() ));
      if (pds2.isEnsembleDerived()) {
        Grib2Pds.PdsEnsembleDerived pdsDerived = (Grib2Pds.PdsEnsembleDerived) pds2;
        v.addAttribute(new Attribute("GRIB_ensemble_derived_type", new Integer(pdsDerived.getDerivedForecastType()) ));
      }
      if (pds2.isEnsemble())
        v.addAttribute(new Attribute("GRIB_ensemble", "true"));
      if (pds2.isProbability()) {
        Grib2Pds.PdsProbability pdsProb = (Grib2Pds.PdsProbability) pds2;
        v.addAttribute(new Attribute("GRIB_probability_type", new Integer(pdsProb.getProbabilityType()) ));
        v.addAttribute(new Attribute("GRIB_probability_lower_limit", new Double(pdsProb.getProbabilityLowerLimit()) ));
        v.addAttribute(new Attribute("GRIB_probability_upper_limit", new Double(pdsProb.getProbabilityUpperLimit()) ));
      }
      v.addAttribute(new Attribute("GRIB_" + GridDefRecord.VECTOR_COMPONENT_FLAG, flag));

    } else if (lookup instanceof Grib1GridTableLookup) {
      Grib1GridTableLookup g1lookup = (Grib1GridTableLookup) lookup;
      int[] paramId = g1lookup.getParameterId(firstRecord);
      v.addAttribute(new Attribute("GRIB_param_name", param.getDescription()));
      v.addAttribute(new Attribute("GRIB_param_short_name", param.getName()));
      v.addAttribute(new Attribute("GRIB_center_id", new Integer(paramId[1])));
      v.addAttribute(new Attribute("GRIB_table_id", new Integer(paramId[2])));
      v.addAttribute(new Attribute("GRIB_param_number", new Integer(paramId[3])));
      v.addAttribute(new Attribute("GRIB_param_id", Array.factory(int.class, new int[]{paramId.length}, paramId)));
      v.addAttribute(new Attribute("GRIB_product_definition_type", g1lookup.getProductDefinitionName(firstRecord)));
      v.addAttribute(new Attribute("GRIB_level_type", new Integer(firstRecord.getLevelType1())));
      v.addAttribute(new Attribute("GRIB_" + GridDefRecord.VECTOR_COMPONENT_FLAG, flag));

    } else {
      v.addAttribute(new Attribute(GridDefRecord.VECTOR_COMPONENT_FLAG, flag));
    }
    v.setSPobject(this);

    int nrecs = ntimes * nlevels;
    if (hasEnsemble()) nrecs *= ecs.getNEnsembles();
    recordTracker = new GridRecord[nrecs];

    if (log.isDebugEnabled()) log.debug("Record Assignment for Variable " + getName());
    boolean oneSent = false;

    for (GridRecord p : records) {
      int level = getVertIndex(p);
      if (!getVertIsUsed() && (level > 0)) {
        log.warn("inconsistent level encoding=" + level);
        level = 0// inconsistent level encoding ??
      }

      int time = tcs.findIndex(p);
      // System.out.println("time="+time+" level="+level);
      if (level < 0) {
        log.warn("LEVEL NOT FOUND record; level=" + level + " time= "
                + time + " for " + getName() + " file="
                + ncfile.getLocation() + "\n" + "   "
                + getVertLevelName() + " (type=" + p.getLevelType1()
                + "," + p.getLevelType2() + ")  value="
                + p.getLevel1() + "," + p.getLevel2() + "\n");

        getVertIndex(p)// allow breakpoint
        continue;
      }

      if (time < 0) {
        log.warn("TIME NOT FOUND record; level=" + level + " time= "
                + time + " for " + getName() + " file="
                + ncfile.getLocation() + "\n" + " validTime= "
                + p.getValidTime() + "\n");

        tcs.findIndex(p)// allow breakpoint
        continue;
      }

      int recno;
      if (hasEnsemble()) {
        GribGridRecord ggr = (GribGridRecord) p;  // LOOK assumes GribGridRecord
        int ens = ecs.getIndex(ggr);
        if (ens < 0) {
          int ensNumber = ggr.getPds().getPerturbationNumber();
          int ensType = ggr.getPds().getPerturbationType();

          log.warn("ENS NOT FOUND record; level=" + level + " time= "+ time +
                  " for " + getName() + " file="+ ncfile.getLocation() +
                  "\n ensNumber= "+ ensNumber + " ensType= "+ ensType + "\n");

          ecs.getIndex(ggr); // allow breakpoint
          continue; // skip
        }
        recno = ens * (ntimes * nlevels) + (time * nlevels) + level;  // order is ens, time, level
        if (recno < 0) {
          System.out.println("HEY");
          ecs.getIndex(ggr);
        }
      } else {
        recno = time * nlevels + level;
      }

      boolean sentMessage = false;
      if (p instanceof GribGridRecord) {
        GribGridRecord ggp = (GribGridRecord) p;
        if (ggp.getBelongs() != null) {
          log.warn("GribGridRecord " + ggp.cdmVariableName(lookup, true, true) + " recno = " + recno + " already belongs to = " + ggp.getBelongs());
        }
        ggp.setBelongs(new Belongs(recno, this));

        if (recordTracker[recno] != null) {
          GribGridRecord ggq = (GribGridRecord) recordTracker[recno];
          if (compareData) {
            if (!compareData(ggq, ggp, raf)) {
              log.warn("GridVariable " + vname + " recno = " + recno + " already has in slot = " + ggq.toString()+
                    " with different data for "+filename);
              sentMessage = true;
            }
          }
        }
      }

      if (recordTracker[recno] == null) {
        recordTracker[recno] = p;
        if (log.isDebugEnabled()) log.debug(" " + vc.getVariableName() + " (type=" + p.getLevelType1() + "," + p.getLevelType2() + ")  value="
                + p.getLevel1() + "," + p.getLevel2());

      } else { // already one in that slot
        if ((p instanceof GribGridRecord) && !sentMessage && warnOk && !oneSent) {
          GribGridRecord gp = (GribGridRecord) p;
          GribGridRecord qp = (GribGridRecord) recordTracker[recno];
          log.warn("Duplicate record for "+filename + "\n "+gp.toString() + "\n " + qp.toString());
        }
        if ((!sendAll)) oneSent = true;
        recordTracker[recno] = p;  // replace it with latest one
      }                                                
    }

    // let all references to Index go, to reduce retained size LOOK
    records.clear();

    return v;
  }

  private boolean compareData(GribGridRecord ggr1, GribGridRecord ggr2, RandomAccessFile raf) {
    if (raf == null) return false;

    float[] data1 = null, data2 = null;
    try {
      if (ggr1.getEdition() == 2) {
        Grib2Data g2read = new Grib2Data(raf);
        data1 =  g2read.getData(ggr1.getGdsOffset(), ggr1.getPdsOffset(), ggr1.getReferenceTimeInMsecs());
        data2 =  g2read.getData(ggr2.getGdsOffset(), ggr2.getPdsOffset(), ggr2.getReferenceTimeInMsecs());
      } else  {
        Grib1Data g1read = new Grib1Data(raf);
        data1 =  g1read.getData(ggr1.getGdsOffset(), ggr1.getPdsOffset(), ggr1.getDecimalScale(), ggr1.isBmsExists());
        data2 =  g1read.getData(ggr2.getGdsOffset(), ggr2.getPdsOffset(), ggr2.getDecimalScale(), ggr2.isBmsExists());
      }
    } catch (IOException e) {
      log.error("Failed to read data", e);
      return false;
    }

    if (data1.length != data2.length)
      return false;

    for (int i = 0; i < data1.length; i++) {
      if (data1[i] != data2[i] && !Double.isNaN(data1[i]) && !Double.isNaN(data2[i]))
        return false;
    }
    return true;
  }


  //////////////////////////////////////
  // debugging

  public class Belongs {
    public int recnum;
    public GridVariable gv;

    private Belongs(int recnum, GridVariable gv) {
      this.recnum = recnum;
      this.gv = gv;
    }

    @Override
    public String toString() {
      return "Belongs{" +
              "recnum=" + recnum +
              ", gv=" + gv.vname +
              '}';
    }
  }

  public void showRecord(int recnum, Formatter f) {
    if ((recnum < 0) || (recnum > recordTracker.length - 1)) {
      f.format("%d out of range [0,%d]%n", recnum, recordTracker.length - 1);
      return;
    }
    GridRecord gr = recordTracker[recnum];

    if (hasEnsemble()) {
      // recnum = ens * (ntimes * nlevels) + (time * nlevels) + level
      int ens = recnum / (nlevels * ntimes);
      int tmp = recnum - ens *(nlevels * ntimes);
      int time = tmp / nlevels;
      int level = tmp % nlevels;
      f.format("recnum=%d (record hash=%d) ens=%d time=%s(%d) level=%f(%d)%n", recnum, gr.hashCode(), ens, tcs.getCoord(time), time, vc.getCoord(level), level);
    else {
      int time = recnum / nlevels;
      int level = recnum % nlevels;
      f.format("recnum=%d (record hash=%d) time=%s(%d) level=%f(%d)%n", recnum, gr.hashCode(), tcs.getCoord(time), time, vc.getCoord(level), level);
    }
  }


  /**
   * Dump out the missing data
   * @param f write to this
   */
  public void showMissing(Formatter f) {
    //System.out.println("  " +name+" ntimes (across)= "+ ntimes+" nlevs (down)= "+ nlevels+":");
    int count = 0, total = 0;
    f.format("  %s%n", name);
    for (int j = 0; j < nlevels; j++) {
      f.format("   ");
      for (int i = 0; i < ntimes; i++) {
        boolean missing = recordTracker[i * nlevels + j] == null;
        f.format("%s", missing ? "-" : "X");
        if (missing) count++;
        total++;
      }
      f.format("%n");
    }
    f.format("  MISSING= %d / %d for %s%n",count,total, name);
  }

  /**
   * Dump out the missing data as a summary
   *
   * @param f write to this
   * @return number of missing levels
   */
  public int showMissingSummary(Formatter f) {
    int count = 0;
    int total = recordTracker.length;

    for (int i = 0; i < total; i++) {
      if (recordTracker[i] == null)
        count++;
    }

    f.format("  MISSING= %d / %d for %s%n", count, total, name);
    return count;
  }

  /**
   * Find the grid record for the time and level indices
   * Canonical ordering is ens, time, level
   * @param ens   ensemble index
   * @param time  time index
   * @param level level index
   * @return the record or null
   */
  public GridRecord findRecord(int ens, int time, int level) {
    if (hasEnsemble()) {
      return recordTracker[ens * (ntimes * nlevels) + (time * nlevels) + level];
    } else {
      return recordTracker[time * nlevels + level];
    }
  }

  /**
   * Check for equality
   *
   * @param oo object in question
   * @return true if they are equal
   */
  public boolean equals(Object oo) {
    if (this == oo) {
      return true;
    }
    if (!(oo instanceof GridVariable)) {
      return false;
    }
    return hashCode() == oo.hashCode();
  }

  /**
   * Get the name
   *
   * @return the name
   */
  public String getName() {
    return name;
  }

  /**
   * Override Object.hashCode() to implement equals.
   *
   * @return equals;
   */
  public int hashCode() {
    if (hashCode == 0) {
      int result = 17;
      result = 37 * result + name.hashCode();
      result += 37 * result + firstRecord.getLevelType1();
      result += 37 * result + hcs.getID().hashCode();
      hashCode = result;
    }
    return hashCode;
  }

  /**
   * hash code
   */
  private volatile int hashCode = 0;

  @Override
  public String toString() {
    return vname == null ? name : vname;
  }

  /**
   * Dump this variable
   *
   * @return the variable
   */
  public String dump() {
    DateFormatter formatter = new DateFormatter();
    Formatter sbuff = new Formatter();
    sbuff.format("%s %d %n", name, records.size());
    for (GridRecord record : records) {
      sbuff.format(" level = %d %f", record.getLevelType1(), record.getLevel1());
      if (null != record.getValidTime())
        sbuff.format(" time = %s", formatter.toDateTimeString(record.getValidTime()));
      sbuff.format("%n");
    }
    return sbuff.toString();
  }

  /**
   * Make a long name for the variable
   *
   * @return long variable name
   */
  private String makeLongName() {

    Formatter f = new Formatter();
    GridParameter param = lookup.getParameter(firstRecord);
    f.format("%s", param.getDescription());

    if (firstRecord instanceof GribGridRecord) {
      GribGridRecord ggr = (GribGridRecord) firstRecord;

      if (ggr.getEdition() == 2) {
        Grib2Pds pds2 = (Grib2Pds) ggr.getPds();
        String useGenType = pds2.getUseGenProcessType();
        if (useGenType != null)
          f.format("_%s", useGenType);
      }

      String suffixName = ggr.makeSuffix( );
      if (suffixName != null && suffixName.length() != 0)
        f.format("%s", suffixName);

      if (ggr.isInterval()) {
        String intervalName = makeIntervalName();
        if (intervalName.length() != 0) {
          String stat = ggr.getStatisticalProcessTypeNameShort();
          if (stat != null)
            f.format(" (%s for %s)", ggr.getStatisticalProcessTypeName(), intervalName);
          else
            f.format(" (%s)", intervalName);
        }
      }
    }

    String levelName = GridIndexToNC.makeLevelName(firstRecord, lookup);
    if (levelName.length() != 0)
      f.format(" @ %s", levelName);

    return f.toString();
  }

  private String makeIntervalName() {
    // get information from timeCoord
    if (tcs.getConstantInterval() < 0)
      return " Mixed Intervals";
    else
      return tcs.getConstantInterval() + " " + tcs.getTimeUnit() + " Intervals";
  }


}
TOP

Related Classes of ucar.nc2.iosp.grid.GridVariable$Belongs

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.