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

ucar.nc2.ft2.coverage.Time2DOffsetCoordSys 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.ft2.coverage;

import com.google.common.collect.Lists;
import ucar.ma2.DataType;
import ucar.nc2.Attribute;
import ucar.nc2.AttributeContainerHelper;
import ucar.nc2.constants.AxisType;
import ucar.nc2.constants.CDM;
import ucar.nc2.constants.CF;
import ucar.nc2.time.CalendarDate;
import ucar.nc2.util.Optional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Time2DCoordSys with run and timeOffset coordinate axes.
 *
 * @author caron
 * @since 10/20/2015.
 */
public class Time2DOffsetCoordSys extends Time2DCoordSys {
  public final TimeOffsetAxis timeOffset;

  public Time2DOffsetCoordSys(CoverageCoordAxis1D runAxis, TimeOffsetAxis timeOffset) {
    super(runAxis, null);
    this.timeOffset = timeOffset;
  }

  @Override
  public int[] getShape() {
    if (runAxis.isScalar())
      return new int[] {timeOffset.getNcoords()};
    else
      return new int[] {runAxis.getNcoords(), timeOffset.getNcoords()};
  }

  /*
    (from CdmrfParams.adoc) :

    2D Time subsetting
    A 2D time dataset will have CoverageType set to FMRC.
    You may specify a runtime with a date, latest or all; specify a timeOffset with a numeric value, first, or all.
      If only one is set, use the default for the other. If neither is set, then return all times for latest runtime.
    Time parameters are only used if explicitly set and timeOffset is not set. There are only 2 cases where time can be used:
    Set runtime to a specific value or latest (not all). Time parameters (point or range) can be used.
    Set runtime to all. Time point (date, or present) can be used.
    Special cases:
      set specific runtime = constant runtime dataset
      set specific timeOffset, set runTime to all = constant offset dataset
      set specific time, set runTime to all = constant forecast dataset
   */
  /*
  1) single runtime
     1a timeOffset
     1b time or timeRange
     1c none = constant runtime dataset
  2) multiple runtimes
     2a timeOffset       = constant offset dataset
     2b time (not range) = constant forecast dataset
   */
  public Optional> subset(SubsetParams params, AtomicBoolean isConstantForcast, boolean makeCFcompliant) {
    List result = new ArrayList<>();

    Optional axiso = runAxis.subset(params);
    if (!axiso.isPresent())
      return Optional.empty(axiso.getErrorMessage());
    CoverageCoordAxis1D runAxisSubset = (CoverageCoordAxis1D) axiso.get();
    result.add(runAxisSubset);

    // subset on timeOffset (1a, 1c, 2a)
    if (params.hasTimeOffsetParam() || !params.hasTimeParam()) {
      axiso = timeOffset.subset(params);
      if (!axiso.isPresent())
        return Optional.empty(axiso.getErrorMessage());
      CoverageCoordAxis timeOffsetSubset = axiso.get();
      result.add(timeOffsetSubset);

      if (makeCFcompliant) // add a time cordinate
        result.add(makeCFTimeCoord(runAxisSubset, (CoverageCoordAxis1D) timeOffsetSubset)); // possible the twoD time case, if nruns > 1
      return Optional.of(result);
    }

    // subset on time, # runtimes = 1 (1b)
    if (runAxisSubset.getNcoords() == 1) {
      double val = runAxisSubset.getCoordMidpoint(0);   // not sure runAxis is needed. maybe use runtimeSubset
      CalendarDate runDate = runAxisSubset.makeDate(val);
      Optional too = timeOffset.subsetFromTime(params, runDate);
      if (!too.isPresent())
        return Optional.empty(too.getErrorMessage());
      TimeOffsetAxis timeOffsetSubset =  too.get();
      result.add(timeOffsetSubset);

      if (makeCFcompliant)
        result.add(makeCFTimeCoord(runAxisSubset, timeOffsetSubset));
      return Optional.of(result);
    }

    // tricky case 2b time (point only not range) = constant forecast dataset
    // data reader has to skip around the 2D times
    // 1) the runtimes may be subset by whats available
    // 2) timeOffset could become an aux coordinate
    // 3) time coordinate becomes a scalar,
    isConstantForcast.set(true);

    CalendarDate dateWanted;
    if (params.isTrue(SubsetParams.timePresent))
      dateWanted = CalendarDate.present();
    else
      dateWanted = (CalendarDate) params.get(SubsetParams.time);
    if (dateWanted == null)
      throw new IllegalStateException("Must have time parameter");

    double wantOffset = runAxisSubset.convert(dateWanted); // forecastDate offset from refdate
    double start = timeOffset.getStartValue();
    double end = timeOffset.getEndValue();
    CoordAxisHelper helper = new CoordAxisHelper(timeOffset);

    // brute force search LOOK specialize for regular ?
    List runtimeIdx = new ArrayList<>();  // list of runtime indexes that have this forecast
    // List offsetIdx = new ArrayList<>();  // list of offset indexes that have this forecast
    List offset = new ArrayList<>();      // corresponding offset from start of run
    for (int i=0; i= 0) {
        runtimeIdx.add(i);  // the ith runtime
        // offsetIdx.add(idx);   // the idx time offset
        offset.add(wantOffset - runOffset);   // the offset from the runtime
      }
    }

    // here are the runtimes
    int ncoords = runtimeIdx.size();
    double[] runValues = new double[ncoords];
    double[] offsetValues = new double[ncoords];
    int count = 0;
    for (int k=0; k




© 2015 - 2024 Weber Informatics LLC | Privacy Policy