public CoverageCoordAxis1D getTimeAxisForRun(CalendarDate rundate) { double rundateTarget = runCoord.convert(rundate); int run_index = new CoordAxisHelper(runCoord).findCoordElement(rundateTarget, false); // LOOK not Bounded return (run_index < 0 || run_index >= runCoord.getNcoords()) ? null : getTimeAxisForRun(run_index); }
private int findSingleHit(double target) { int hits = 0; int idxFound = -1; int n = axis.getNcoords(); for (int i = 0; i < n; i++) { if (contains(target, i)) { hits++; idxFound = i; } } if (hits == 1) return idxFound; if (hits == 0) return -1; return -hits; }
private int findCoordElementDiscontiguousInterval(double target, boolean bounded) { int idx = findSingleHit(target); if (idx >= 0) return idx; if (idx == -1) return -1; // no hits // multiple hits = choose closest to the midpoint return findClosest(target); }
/** * Given a coordinate interval, find what grid element matches it. * @param target interval in this coordinate system * @param bounded if true, always return a valid index. otherwise can return < 0 or > n-1 * @return index of grid point containing it, or < 0 or > n-1 if outside grid area */ int findCoordElement(double[] target, boolean bounded) { switch (axis.getSpacing()) { case regularInterval: // can use midpoint return findCoordElementRegular((target[0]+target[1])/2, bounded); case contiguousInterval: // can use midpoint return findCoordElementContiguous((target[0]+target[1])/2, bounded); case discontiguousInterval: // cant use midpoint return findCoordElementDiscontiguousInterval(target, bounded); } throw new IllegalStateException("unknown spacing" + axis.getSpacing()); }
CoordAxisHelper helper = new CoordAxisHelper(this); Double dval = params.getVertCoord(); if (dval != null) return Optional.of(helper.subsetClosest(dval)); return Optional.of(helper.subsetClosest((intv[0]+intv[1])/2)); return helper.subset(vertRange[0], vertRange[1], 1); Double eval = params.getDouble(SubsetParams.ensCoord); if (eval != null) { return Optional.of(helper.subsetClosest(eval)); return Optional.of(helper.subsetLatest()); return Optional.of(helper.subsetClosest(date)); return helper.subset(dateRange, stride); if (runtime != null) { date = makeDateInTimeUnits(runtime, timeOffset); return Optional.of(helper.subsetClosest(date)); } else { return Optional.of(helper.subsetClosest(timeOffset)); dateIntv[0] = makeDateInTimeUnits(runtime, timeOffsetIntv[0]); dateIntv[1] = makeDateInTimeUnits(runtime, timeOffsetIntv[1]); return Optional.of(helper.subsetClosest(dateIntv));
@Nonnull private CoverageCoordAxisBuilder subsetValuesClosest(double[] want) { int closest_index = findCoordElement(want, true); // bounded, always valid index if (closest_index < 0) findCoordElement(want, true); CoverageCoordAxisBuilder builder = new CoverageCoordAxisBuilder(axis); if (axis.spacing == CoverageCoordAxis.Spacing.regularInterval) { double val1 = axis.getCoordEdge1(closest_index); double val2 = axis.getCoordEdge2(closest_index); builder.subset(1, val1, val2, val2-val1, null); } else { builder.subset(1, 0, 0, 0.0, makeValues(closest_index)); } try { builder.setRange(new Range(closest_index, closest_index)); } catch (InvalidRangeException e) { throw new RuntimeException(e); // cant happen } return builder; }
private Optional<CoverageCoordAxisBuilder> subsetValues(double minValue, double maxValue, int stride) { if (axis.getSpacing() == CoverageCoordAxis.Spacing.discontiguousInterval) return subsetValuesDiscontinuous(minValue, maxValue, stride); double lower = axis.isAscending() ? Math.min(minValue, maxValue) : Math.max(minValue, maxValue); double upper = axis.isAscending() ? Math.max(minValue, maxValue) : Math.min(minValue, maxValue); int minIndex = findCoordElement(lower, false); int maxIndex = findCoordElement(upper, false); if (minIndex >= axis.getNcoords()) return Optional.empty(String.format("no points in subset: lower %f > end %f", lower, axis.getEndValue())); if (maxIndex < 0) return Optional.empty(String.format("no points in subset: upper %f < start %f", upper, axis.getStartValue())); if (minIndex < 0) minIndex = 0; if (maxIndex >= axis.getNcoords()) maxIndex = axis.getNcoords() - 1; int count = maxIndex - minIndex + 1; if (count <= 0) throw new IllegalArgumentException("no points in subset"); try { return Optional.of(subsetByIndex(new Range(minIndex, maxIndex, stride))); } catch (InvalidRangeException e) { return Optional.empty(e.getMessage()); } }
public Optional<TimeOffsetAxis> subsetFromTime(SubsetParams params, CalendarDate runDate) { CoordAxisHelper helper = new CoordAxisHelper(this); CoverageCoordAxisBuilder builder = null; if (params.isTrue(SubsetParams.timePresent)) { double offset = getOffsetInTimeUnits(runDate, CalendarDate.present()); builder = helper.subsetClosest(offset); } CalendarDate dateWanted = (CalendarDate) params.get(SubsetParams.time); if (dateWanted != null) { // convertFrom, convertTo double offset = getOffsetInTimeUnits(runDate, dateWanted); builder = helper.subsetClosest(offset); } Integer stride = (Integer) params.get(SubsetParams.timeStride); if (stride == null || stride < 0) stride = 1; CalendarDateRange dateRange = (CalendarDateRange) params.get(SubsetParams.timeRange); if (dateRange != null) { double min = getOffsetInTimeUnits(runDate, dateRange.getStart()); double max = getOffsetInTimeUnits(runDate, dateRange.getEnd()); Optional<CoverageCoordAxisBuilder> buildero = helper.subset(min, max, stride); if (buildero.isPresent()) builder = buildero.get(); else return Optional.empty(buildero.getErrorMessage()); } assert (builder != null); // all the offsets are reletive to rundate builder.setReferenceDate(runDate); return Optional.of(new TimeOffsetAxis(builder)); }
@Override public Optional<CoverageCoordAxis> subset(double minValue, double maxValue, int stride) throws InvalidRangeException { CoordAxisHelper helper = new CoordAxisHelper(this); Optional<CoverageCoordAxisBuilder> buildero = helper.subset(minValue, maxValue, stride); return !buildero.isPresent() ? Optional.empty(buildero.getErrorMessage()) : Optional.of(new CoverageCoordAxis1D(buildero.get())); }
public Optional<CoverageCoordAxis> subsetByIndex(Range range) { try { CoordAxisHelper helper = new CoordAxisHelper(this); CoverageCoordAxisBuilder builder = helper.subsetByIndex(range); return Optional.of(new CoverageCoordAxis1D(builder)); } catch (InvalidRangeException e) { return Optional.empty(e.getMessage()); } }
public Optional<CoverageCoordAxis> subsetByIntervals(List<MAMath.MinMax> lonIntvs, int stride) { if (axisType != AxisType.Lon) return Optional.empty("subsetByIntervals only for longitude"); if (!isRegular()) return Optional.empty("subsetByIntervals only for regular longitude"); CoordAxisHelper helper = new CoordAxisHelper(this); double start = Double.NaN; boolean first = true; List<RangeIterator> ranges = new ArrayList<>(); for (MAMath.MinMax lonIntv : lonIntvs) { if (first) start = lonIntv.min; first = false; Optional<RangeIterator> opt = helper.makeRange(lonIntv.min, lonIntv.max, stride); if (!opt.isPresent()) return Optional.empty(opt.getErrorMessage()); ranges.add(opt.get()); } try { RangeComposite compositeRange = new RangeComposite(AxisType.Lon.toString(), ranges); int npts = compositeRange.length(); double end = start + npts * resolution; CoverageCoordAxisBuilder builder = new CoverageCoordAxisBuilder(this); // copy builder.subset(npts, start, end, resolution, null); builder.setRange(null); builder.setCompositeRange(compositeRange); return Optional.of(new CoverageCoordAxis1D(builder)); } catch (InvalidRangeException e) { return Optional.empty(e.getMessage()); } }
double start = timeOffset.getStartValue(); double end = timeOffset.getEndValue(); CoordAxisHelper helper = new CoordAxisHelper(timeOffset); if (end + runOffset < wantOffset) continue; if (wantOffset < start + runOffset) break; int idx = helper.search(wantOffset - runOffset); if (idx >= 0) {
if (latlon != null) { // overrides other horiz subset params if (isProjection) { CoordAxisHelper xhelper = new CoordAxisHelper(xAxis); CoordAxisHelper yhelper = new CoordAxisHelper(yAxis); optb = xhelper.subsetContaining(pp.getX()); if (optb.isPresent()) xaxisSubset = new CoverageCoordAxis1D(optb.get()); else errMessages.format("xaxis: %s;%n", optb.getErrorMessage()); optb = yhelper.subsetContaining(pp.getY()); if (optb.isPresent()) yaxisSubset = new CoverageCoordAxis1D(optb.get()); else errMessages.format("yaxis: %s;%n", optb.getErrorMessage()); CoordAxisHelper xhelper = new CoordAxisHelper(lonAxis); CoordAxisHelper yhelper = new CoordAxisHelper(latAxis); optb = xhelper.subsetContaining(lonNormal); if (optb.isPresent()) lonaxisSubset = new CoverageCoordAxis1D(optb.get()); else errMessages.format("lonaxis: %s;%n", optb.getErrorMessage()); optb = yhelper.subsetContaining(latlon.getLatitude()); if (optb.isPresent()) lataxisSubset = new CoverageCoordAxis1D(optb.get()); else errMessages.format("lataxis: %s;%n", optb.getErrorMessage());
@Nonnull private CoverageCoordAxisBuilder subsetValuesLatest() { int last = axis.getNcoords() - 1; double val = axis.getCoordMidpoint(last); CoverageCoordAxisBuilder builder = new CoverageCoordAxisBuilder(axis); builder.subset(1, val, val, 0.0, makeValues(last)); try { builder.setRange(new Range(last, last)); } catch (InvalidRangeException e) { throw new RuntimeException(e); // cant happen } return builder; }
public Optional<RangeIterator> makeRange(double minValue, double maxValue, int stride) { //if (axis.getSpacing() == CoverageCoordAxis.Spacing.discontiguousInterval) // return subsetValuesDiscontinuous(minValue, maxValue, stride); double lower = axis.isAscending() ? Math.min(minValue, maxValue) : Math.max(minValue, maxValue); double upper = axis.isAscending() ? Math.max(minValue, maxValue) : Math.min(minValue, maxValue); int minIndex = findCoordElement(lower, false); int maxIndex = findCoordElement(upper, false); if (minIndex >= axis.getNcoords()) return Optional.empty(String.format("no points in subset: lower %f > end %f", lower, axis.getEndValue())); if (maxIndex < 0) return Optional.empty(String.format("no points in subset: upper %f < start %f", upper, axis.getStartValue())); if (minIndex < 0) minIndex = 0; if (maxIndex >= axis.getNcoords()) maxIndex = axis.getNcoords() - 1; int count = maxIndex - minIndex + 1; if (count <= 0) return Optional.empty("no points in subset"); try { return Optional.of(new Range(minIndex, maxIndex, stride)); } catch (InvalidRangeException e) { return Optional.empty(e.getMessage()); } }
/** * Given a coordinate position, find what grid element contains it. * This means that * <pre> * edge[i] <= target < edge[i+1] (if values are ascending) * edge[i] > target >= edge[i+1] (if values are descending) * </pre> * * @param target position in this coordinate system * @param bounded if true, always return a valid index. otherwise can return < 0 or > n-1 * @return index of grid point containing it, or < 0 or > n-1 if outside grid area */ int findCoordElement(double target, boolean bounded) { switch (axis.getSpacing()) { case regularInterval: case regularPoint: return findCoordElementRegular(target, bounded); case irregularPoint: case contiguousInterval: return findCoordElementContiguous(target, bounded); case discontiguousInterval: return findCoordElementDiscontiguousInterval(target, bounded); } throw new IllegalStateException("unknown spacing" + axis.getSpacing()); }
Optional<CoverageCoordAxisBuilder> subsetContaining(double want) { int index = findCoordElement(want, false); // not bounded, may not be valid index if (index < 0 || index >= axis.getNcoords()) return Optional.empty(String.format("value %f not in axis %s", want, axis.getName())); double val = axis.getCoordMidpoint(index); CoverageCoordAxisBuilder builder = new CoverageCoordAxisBuilder(axis); builder.subset(1, val, val, 0.0, makeValues(index)); try { builder.setRange(new Range(index, index)); } catch (InvalidRangeException e) { throw new RuntimeException(e); // cant happen } return Optional.of(builder); }
@Override public Optional<CoverageCoordAxis> subset(double minValue, double maxValue, int stride) { CoordAxisHelper helper = new CoordAxisHelper(this); Optional<CoverageCoordAxisBuilder> buildero = helper.subset(minValue, maxValue, stride); return !buildero.isPresent() ? Optional.empty(buildero.getErrorMessage()) : Optional.of(new TimeOffsetAxis(buildero.get())); }
@Override public Optional<CoverageCoordAxis> subsetDependent(CoverageCoordAxis1D dependsOn) { CoverageCoordAxisBuilder builder; try { builder = new CoordAxisHelper(this).subsetByIndex(dependsOn.getRange()); // LOOK Other possible subsets? } catch (InvalidRangeException e) { return Optional.empty(e.getMessage()); } return Optional.of(new CoverageCoordAxis1D(builder)); }
public Optional<CoordReturn> findXYindexFromCoord(double x, double y) { CoordReturn result = new CoordReturn(); if (isProjection) { CoordAxisHelper xhelper = new CoordAxisHelper(xAxis); CoordAxisHelper yhelper = new CoordAxisHelper(yAxis); result.x = xhelper.findCoordElement(x, false); result.y = yhelper.findCoordElement(y, false); if (result.x >= 0 && result.x < xAxis.getNcoords() && result.y >= 0 && result.y < yAxis.getNcoords()) { result.xcoord = xAxis.getCoordMidpoint(result.x); result.ycoord = yAxis.getCoordMidpoint(result.y); return Optional.of(result); } else { return Optional.empty("not in grid"); } } else { // 1D lat lon case CoordAxisHelper xhelper = new CoordAxisHelper(lonAxis); CoordAxisHelper yhelper = new CoordAxisHelper(latAxis); double lon = LatLonPointImpl.lonNormalFrom(x, lonAxis.getStartValue()); result.x = xhelper.findCoordElement(lon, false); result.y = yhelper.findCoordElement(y, false); if (result.x >= 0 && result.x < lonAxis.getNcoords() && result.y >= 0 && result.y < latAxis.getNcoords()) { result.xcoord = lonAxis.getCoordMidpoint(result.x); result.ycoord = latAxis.getCoordMidpoint(result.y); return Optional.of(result); } else { return Optional.empty("not in grid"); } } }