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

ucar.nc2.ft.fmrc.TimeCoord Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
 * See LICENSE for license information.
 */

package ucar.nc2.ft.fmrc;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Formatter;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import ucar.nc2.Attribute;
import ucar.nc2.constants.CF;
import ucar.nc2.dataset.CoordinateAxis1DTime;
import ucar.nc2.time.Calendar;
import ucar.nc2.time.CalendarDate;
import ucar.nc2.time.CalendarDateUnit;
import ucar.nc2.units.DateUnit;
import ucar.nc2.util.Misc;

/**
 * Represents a list of offset times shared among variables
 * Tracks a list of variables that all have the same list of offset times.
 */
public class TimeCoord implements Comparable {
  static public final TimeCoord EMPTY = new TimeCoord(CalendarDate.of(new Date()), new double[0]);

  private CalendarDate runDate;
  private List gridInv; // track the grids that use this coord
  private int id; // unique id for serialization
  private String axisName; // time coordinate axis

  // time at point has offsets, intervals have bounds
  private boolean isInterval = false;
  private double[] offset; // hours since runDate
  private double[] bound1, bound2; // hours since runDate [ntimes,2]

  TimeCoord(CalendarDate runDate) {
    this.runDate = runDate;
  }

  TimeCoord(CalendarDate runDate, double[] offset) {
    this.runDate = runDate;
    this.offset = offset;
  }

  TimeCoord(TimeCoord from) {
    this.runDate = from.runDate;
    this.axisName = from.axisName;
    this.offset = from.offset;
    this.isInterval = from.isInterval;
    this.bound1 = from.bound1;
    this.bound2 = from.bound2;
    this.id = from.id;
  }

  TimeCoord(CalendarDate runDate, CoordinateAxis1DTime axis) {
    this.runDate = runDate;
    this.axisName = axis.getFullName();

    DateUnit unit = null;
    Attribute atrCal = null;
    Calendar cal = null;
    
    try {
      unit = new DateUnit(axis.getUnitsString());
      atrCal = axis.findAttribute(CF.CALENDAR );
      if(atrCal != null)
    	  cal = Calendar.get((String)atrCal.getValue(0) );
      else
    	  cal = Calendar.getDefault();
      
    } catch (Exception e) {
      throw new IllegalArgumentException("Not a unit of time " + axis.getUnitsString());
    }

    int n = (int) axis.getSize();
    if (axis.isInterval()) {
      this.isInterval = true;
      this.bound1 = new double[n];
      this.bound2 = new double[n];
      double[] orgBound1 =  axis.getBound1();
      double[] orgBound2 =  axis.getBound2();
      this.bound2 = new double[n];
      for (int i = 0; i < axis.getSize(); i++) {
        this.bound1[i] = getValueInHours(unit, orgBound1[i]);
        this.bound2[i] = getValueInHours(unit, orgBound2[i]);
      }
    } else {
      offset = new double[n];
      for (int i = 0; i < axis.getSize(); i++) {
        offset[i] = getValueInHours(cal, unit, axis.getCoordValue(i));
      }
    }
  }

  
  double getValueInHours(Calendar cal, DateUnit unit, double value) {
	    //CalendarDate d = unit.makeCalendarDate(value);
	    //double secs =  unit.getTimeUnit().getValueInSeconds(value);	    	    	    
	    //CalendarDate d = CalendarDate.of(cal, unit.getDateOrigin().getTime() + (long)(1000*secs));
	    
	    CalendarDateUnit dateUnit = CalendarDateUnit.withCalendar(cal, unit.getUnitsString() ); // this will throw exception on failure
	    CalendarDate d = dateUnit.makeCalendarDate(value);
	    return FmrcInv.getOffsetInHours(runDate, d);
	  }  
  
  double getValueInHours(DateUnit unit, double value) {
    CalendarDate d = unit.makeCalendarDate(value);
    return FmrcInv.getOffsetInHours(runDate, d);
  }

  void addGridInventory(GridDatasetInv.Grid grid) {
    if (gridInv == null)
      gridInv = new ArrayList<>();
    gridInv.add(grid);
  }

  public CalendarDate getRunDate() {
    return runDate;
  }

  public boolean isInterval() {
    return isInterval;
  }

  /**
   * The list of GridDatasetInv.Grid that use this TimeCoord
   *
   * @return list of GridDatasetInv.Grid that use this TimeCoord
   */
  public List getGridInventory() {
    return (gridInv == null) ? new ArrayList() : gridInv;
  }

  /**
   * A unique id for this TimeCoord
   *
   * @return unique id for this TimeCoord
   */
  public int getId() {
    return id;
  }

  /**
   * Set the unique id for this TimeCoord
   *
   * @param id id for this TimeCoord
   */
  public void setId(int id) {
    this.id = id;
  }

  public String getName() {
    if (this == EMPTY) return "EMPTY";
    return id == 0 ? "time" : "time" + id;
  }

  public String getAxisName() {
    return axisName;
  }

  public int getNCoords() {
    return (isInterval) ? bound1.length : offset.length;
  }

   /**
   * The list of valid times, in units of hours since the run time
   * @return list of valid times, in units of hours since the run time
   */
  public double[] getOffsetTimes() {
    return isInterval ? bound2 : offset;
  }

  public double[] getBound1() {
    return bound1;
  }

  public double[] getBound2() {
    return bound2;
  }

  public void setOffsetTimes(double[] offset) {
    this.offset = offset;
  }

  public void setBounds(double[] bound1, double[] bound2) {
    this.bound1 = bound1;
    this.bound2 = bound2;
    this.isInterval = true;
  }

  public void setBounds(List tinvs) {
    this.bound1 = new double[tinvs.size()];
    this.bound2 = new double[tinvs.size()];
    int count = 0;
    for (TimeCoord.Tinv tinv : tinvs) {
      this.bound1[count] = tinv.b1;
      this.bound2[count] = tinv.b2;
      count++;
    }
    this.isInterval = true;
  }

  @Override
  public String toString() {
    Formatter out = new Formatter();
    out.format("%-10s %-26s offsets=", getName(), runDate);
    if (isInterval)
      for (int i=0; i timeCoords, TimeCoord want) {
    if (want == null) return null;

    for (TimeCoord tc : timeCoords) {
      if (want.equalsData(tc))
        return tc;
    }

    // make a new one
    TimeCoord result = new TimeCoord(want);
    timeCoords.add(result);
    return result;
  }

  /**
   * Create the union of all the values in the list of TimeCoord, ignoring the TimeCoord's runDate
   * @param timeCoords list of TimeCoord
   * @param baseDate resulting union timeCoord uses this as a base date
   * @return union TimeCoord
   */
  static public TimeCoord makeUnion(List timeCoords, CalendarDate baseDate) {
    if (timeCoords.size() == 0) return new TimeCoord(baseDate);
    if (timeCoords.size() == 1) return timeCoords.get(0);

    if (timeCoords.get(0).isInterval)
      return makeUnionIntv(timeCoords, baseDate);
    else
      return makeUnionReg(timeCoords, baseDate);
  }

  static private TimeCoord makeUnionReg(List timeCoords, CalendarDate baseDate) {
    // put into a set for uniqueness
    Set offsets = new HashSet<>();
    for (TimeCoord tc : timeCoords) {
      if (tc.isInterval)
        throw new IllegalArgumentException("Cant mix interval coordinates");
      for (double off : tc.getOffsetTimes())
        offsets.add(off);
    }

    // extract into a List
    List offsetList = Arrays.asList((Double[]) offsets.toArray(new Double[offsets.size()]));

    // sort and extract into double[]
    Collections.sort(offsetList);
    double[] offset = new double[offsetList.size()];
    int count = 0;
    for (double off : offsetList)
      offset[count++] = off;

    // make the resulting time coord
    TimeCoord result = new TimeCoord(baseDate);
    result.setOffsetTimes(offset);
    return result;
  }

  static private TimeCoord makeUnionIntv(List timeCoords, CalendarDate baseDate) {
    // put into a set for uniqueness
    Set offsets = new HashSet<>();
    for (TimeCoord tc : timeCoords) {
      if (!tc.isInterval)
        throw new IllegalArgumentException("Cant mix non-interval coordinates");
      for (int i=0; i bounds = Arrays.asList((Tinv[]) offsets.toArray(new Tinv[offsets.size()]));

    // sort and extract into double[] bounds arrays
    Collections.sort(bounds);
    int n = bounds.size();
    double[] bounds1 = new double[n];
    double[] bounds2 = new double[n];
    for (int i=0; i {
    private double b1, b2;  // bounds

    public Tinv(double offset) {
      this.b2 = offset;
    }

    public Tinv(double b1, double b2) {
      this.b1 = b1;
      this.b2 = b2;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      Tinv tinv = (Tinv) o;

      if (!Misc.nearlyEquals(b2, tinv.b2)) return false;
      if (!Misc.nearlyEquals(b1, tinv.b1)) return false;

      return true;
    }

    @Override
    public int hashCode() {
      int result = (int) Math.round(b1 / Misc.defaultMaxRelativeDiffDouble);
      result = 31 * result + (int) Math.round(b2/Misc.defaultMaxRelativeDiffDouble);
      return result;
    }

    @Override
    public int compareTo(Tinv o) {
      boolean b1close = Misc.nearlyEquals(b1, o.b1);
      boolean b2close = Misc.nearlyEquals(b2, o.b2);
      if (b1close && b2close) return 0;
      if (b2close) return Double.compare(b1, o.b1);
      return Double.compare(b2, o.b2);
    }
  }

  /*
   * Create the union of all the values in the list of TimeCoord, converting all to a common baseDate
   * @param timeCoords list of TimeCoord
   * @param baseDate resulting union timeCoord uses this as a base date
   * @return union TimeCoord
   *
  static public TimeResult makeUnionConvert(List timeCoords, Date baseDate) {

    Map offsetMap = new HashMap(256);
    for (TimeCoord tc : timeCoords) {
      double run_offset = FmrcInv.getOffsetInHours(baseDate, tc.getRunDate());
      for (double offset : tc.getOffsetHours()) {
        offsetMap.put(run_offset + offset, run_offset); // later ones override
      }
    }

    Set keys = offsetMap.keySet();
    int n = keys.size();
    List offsetList = Arrays.asList((Double[]) keys.toArray(new Double[n]));
    Collections.sort(offsetList);

    int counto = 0;
    double[] offs = new double[n];
    double[] runoffs = new double[n];
    for (Double key : offsetList) {
      offs[counto] = key;
      runoffs[counto] = offsetMap.get(key);
      counto++;
    }

    return new TimeResult( baseDate, offs, runoffs);
  }

  static class TimeResult {
    double[] offsets;
    double[] runOffsets;
    Date base;

    TimeResult(Date base, double[] offsets, double[] runOffsets) {
      this.base = base;
      this.offsets = offsets;
      this.runOffsets = runOffsets;
    }
  } */


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy