ucar.nc2.ft2.coverage.Time2DCoordSys 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 ucar.ma2.DataType;
import ucar.ma2.InvalidRangeException;
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.util.Optional;
import javax.annotation.concurrent.Immutable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Time2DCoordSys with run and 2D time coordinate axes. LOOK not complete
* A CoordSys has 0 or 1 Time2DCoordSys, but there may be several in a Dataset.
*
* @author John
* @since 8/14/2015
*/
@Immutable
public class Time2DCoordSys {
public final CoverageCoordAxis1D runAxis;
public final TimeAxis2DFmrc timeAxis2D;
public Time2DCoordSys(CoverageCoordAxis1D runAxis, TimeAxis2DFmrc timeAxis) {
this.runAxis = runAxis;
this.timeAxis2D = timeAxis;
}
public List getCoordAxes() throws InvalidRangeException {
List result = new ArrayList<>();
result.add(runAxis);
result.add(timeAxis2D);
return result;
}
public int[] getShape() {
return timeAxis2D.getShape();
}
/*
(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) {
return Optional.empty("not implemented by "+getClass().getName());
/* 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 = timeAxis2D.subset(params);
if (!axiso.isPresent())
return Optional.empty(axiso.getErrorMessage());
CoverageCoordAxis timeOffsetSubset = axiso.get();
result.add(timeOffsetSubset);
if (makeCFcompliant)
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.getCoord(0); // not sure runAxis is needed. maybe use runtimeSubset
CalendarDate runDate = runAxisSubset.makeDate(val);
Optional too = timeAxis2D.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 = timeAxis.getStartValue();
double end = timeAxis.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