@Override public String getSummary() { if (axisType != AxisType.RunTime) return super.getSummary(); if (ncoords < 7) { Formatter f = new Formatter(); for (int i = 0; i < ncoords; i++) { CalendarDate cd = makeDate(getCoordMidpoint(i)); if (i > 0) f.format(", "); f.format("%s", cd); } return f.toString(); } Formatter f = new Formatter(); CalendarDate start = makeDate(getStartValue()); f.format("start=%s", start); CalendarDate end = makeDate(getEndValue()); f.format(", end=%s", end); f.format(" (npts=%d spacing=%s)", getNcoords(), getSpacing()); return f.toString(); }
private int findCoordElementRegular(double coordValue, boolean bounded) { int n = axis.getNcoords(); if (n == 1 && bounded) return 0; double distance = coordValue - axis.getCoordEdge1(0); double exactNumSteps = distance / axis.getResolution(); //int index = (int) Math.round(exactNumSteps); // ties round to +Inf int index = (int) exactNumSteps; // truncate down if (bounded && index < 0) return 0; if (bounded && index >= n) return n - 1; // check that found point is within interval if (index >= 0 && index < n) { double lower = axis.getCoordEdge1(index); double upper = axis.getCoordEdge2(index); if (axis.isAscending()) { assert lower <= coordValue : lower + " should be le " + coordValue; assert upper >= coordValue : upper + " should be ge " + coordValue; } else { assert lower >= coordValue : lower + " should be ge " + coordValue; assert upper <= coordValue : upper + " should be le " + coordValue; } } return index; }
private CoverageCoordAxis makeCFTimeCoord(CoverageCoordAxis1D runAxisSubset, CoverageCoordAxis1D timeAxisSubset) { String name = timeAxisSubset.getName()+"Forecast"; String desc = "forecast time"; AttributeContainerHelper atts = new AttributeContainerHelper(name); atts.addAttribute(new Attribute(CDM.UNITS, runAxisSubset.getUnits())); atts.addAttribute(new Attribute(CF.STANDARD_NAME, CF.TIME)); atts.addAttribute(new Attribute(CDM.LONG_NAME, desc)); atts.addAttribute(new Attribute(CF.CALENDAR, runAxisSubset.getCalendar().toString())); if (runAxisSubset.getNcoords() == 1) { CoverageCoordAxisBuilder builder = new CoverageCoordAxisBuilder(); builder.name = name; builder.units = runAxisSubset.getUnits(); builder.description = desc; builder.dataType = DataType.DOUBLE; builder.attributes = atts; builder.dependenceType = CoverageCoordAxis.DependenceType.dependent; builder.setDependsOn(timeAxisSubset.getName()); builder.spacing = timeAxisSubset.getSpacing(); builder.ncoords = timeAxisSubset.ncoords; builder.isSubset = true; double offset = timeAxisSubset.getOffsetInTimeUnits(runAxis.getRefDate(), timeAxisSubset.getRefDate()); switch (timeAxisSubset.getSpacing()) { case regularInterval: case regularPoint: builder.startValue = timeAxisSubset.getStartValue() + offset;
public Object getCoordObject(int index) { if (axisType == AxisType.RunTime) return makeDate(getCoordMidpoint(index)); if (isInterval()) return new double[]{getCoordEdge1(index), getCoordEdge2(index)}; return getCoordMidpoint(index); }
private boolean contains(double target, int coordIdx, boolean ascending) { double midVal1 = axis.getCoordEdge1(coordIdx); double midVal2 = axis.getCoordEdge2(coordIdx); if (ascending) return (midVal1 <= target && target <= midVal2); else return (midVal1 >= target && target >= midVal2); }
private double[] makeValues(int index) { double[] subsetValues = null; // null for regular switch (axis.getSpacing()) { case irregularPoint: subsetValues = new double[1]; subsetValues[0] = axis.getCoordMidpoint(index); break; case discontiguousInterval: case contiguousInterval: subsetValues = new double[2]; subsetValues[0] = axis.getCoordEdge1(index); subsetValues[1] = axis.getCoordEdge2(index); break; } return subsetValues; }
Assert.assertEquals(4, runtimeAxis.getNcoords()); Assert.assertEquals(CoverageCoordAxis.Spacing.regularPoint, runtimeAxis.getSpacing()); Assert2.assertNearlyEquals(0.0, runtimeAxis.getCoordMidpoint(0)); Assert2.assertNearlyEquals(6.0, runtimeAxis.getResolution()); CoverageCoordAxis1D timeAxis1D = (CoverageCoordAxis1D) timeAxis; if (timeAxis.isInterval()) { Assert.assertTrue("time coord lower", timeAxis1D.getCoordEdge1(0) <= offsetVal); // lower <= time Assert.assertTrue("time coord lower", timeAxis1D.getCoordEdge2(0) >= offsetVal); // upper >= time Assert2.assertNearlyEquals(offsetVal, timeAxis1D.getCoordMidpoint(0));
public List<NamedObject> getCoordValueNames(CoverageCoordAxis1D axis) { axis.loadValuesIfNeeded(); List<NamedObject> result = new ArrayList<>(); for (int i = 0; i < axis.getNcoords(); i++) { double value; switch (axis.getSpacing()) { case regularPoint: case irregularPoint: value = axis.getCoordMidpoint(i); result.add(new NamedAnything(makeDate(value), axis.getAxisType().toString())); break; case regularInterval: case contiguousInterval: case discontiguousInterval: CoordInterval coord = new CoordInterval(axis.getCoordEdge1(i), axis.getCoordEdge2(i), 3); result.add(new NamedAnything(coord, coord + " " + axis.getUnits())); break; } } return result; }
Assert.assertEquals(1, time.getNcoords()); CalendarDate date = time.makeDate(time.getCoordMidpoint(0)); logger.debug("date = {}", date); Assert.assertEquals(date, CalendarDate.parseISOformat(null, "2012-04-19T00:00:00Z")); Assert.assertEquals(1, vert.getNcoords()); double vertCoord = vert.getCoordMidpoint(0); logger.debug("date = {}", date); Assert2.assertNearlyEquals(800.0, vertCoord);
Assert.assertEquals(1, time.getNcoords()); CalendarDate date = time.makeDate( time.getCoordMidpoint(0)); logger.debug("date = {}", date); CalendarDate expected = CalendarDate.parseISOformat(Calendar.gregorian.toString(), "2002-12-01T00:00:00Z"); // CF i guess Assert.assertEquals(291, xaxis.getNcoords()); Assert2.assertNearlyEquals(10.5, xaxis.getCoordMidpoint(0)); Assert2.assertNearlyEquals(300.5, xaxis.getEndValue()); // LOOK is that ok? BB = 10-300: its just catching the edge Assert2.assertNearlyEquals(1.0, xaxis.getResolution()); Assert.assertEquals(81, yaxis.getNcoords()); Assert2.assertNearlyEquals(79.5, yaxis.getCoordMidpoint(0)); Assert2.assertNearlyEquals(-.5, yaxis.getEndValue()); // LOOK is that ok? BB = 0-80: its just catching the edge Assert2.assertNearlyEquals(-1.0, yaxis.getResolution());
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()); } }
Optional<CoverageCoordAxis> axiso = runAxis.subset(params); if (!axiso.isPresent()) return Optional.empty(axiso.getErrorMessage()); if (runAxisSubset.getNcoords() == 1) { double val = runAxisSubset.getCoordMidpoint(0); // not sure runAxis is needed. maybe use runtimeSubset CalendarDate runDate = runAxisSubset.makeDate(val); Optional<TimeOffsetAxis> too = timeOffset.subsetFromTime(params, runDate); if (!too.isPresent()) double wantOffset = runAxisSubset.convert(dateWanted); // forecastDate offset from refdate double start = timeOffset.getStartValue(); double end = timeOffset.getEndValue(); for (int i=0; i<runAxisSubset.getNcoords(); i++) { double runOffset = runAxisSubset.getCoordMidpoint(i); if (end + runOffset < wantOffset) continue; if (wantOffset < start + runOffset) break; for (int k=0; k<ncoords; k++) { offsetValues[count] = offset.get(k); runValues[count++] = runAxisSubset.getCoordMidpoint(runtimeIdx.get(k)); CoverageCoordAxis1D runAxisSubset2 = new CoverageCoordAxis1D(runbuilder); .subset(runAxisSubset2.getName(), CoverageCoordAxis.Spacing.irregularPoint, ncoords, offsetValues); // aux coord (LOOK interval) ?? CoverageCoordAxis1D timeOffsetSubset = new TimeOffsetAxis(timebuilder);
private void addAdjustedTimeCoords(SubsetParams result, CoverageCoordAxis1D axis, int coordIdx, CalendarDate runtime) { // this must be adjusted to be offset from the runtime. // adjust = end - start // axisCoordOffset + axis.reftime = offset + runtime // offset = axisCoordOffset + axis.reftime - runtime // offset = axisCoordOffset + adjust // offset = axisCoordOffset + end - start = axisCoordOffset + axis.reftime - runtime // therefore: end = reftime, start = runtime double adjust = axis.getOffsetInTimeUnits(runtime, axis.getRefDate()); if (axis.isInterval()) { double[] adjustVal = new double[] {axis.getCoordEdge1(coordIdx)+adjust, axis.getCoordEdge2(coordIdx)+adjust}; result.setTimeOffsetIntv(adjustVal); double mid = (adjustVal[0]+adjustVal[1]) / 2.0; result.set(SubsetParams.timeOffsetUnit, axis.makeDateInTimeUnits(runtime, mid)); // validation result.set(SubsetParams.timeOffsetUnit, axis.getCalendarDateUnit()); // validation } else { double adjustVal = axis.getCoordMidpoint(coordIdx) + adjust; result.setTimeOffset(adjustVal); result.set(SubsetParams.timeOffsetDate, axis.makeDateInTimeUnits(runtime, adjustVal)); // validation result.set(SubsetParams.timeOffsetUnit, axis.getCalendarDateUnit()); // validation } }
public double getCoordMidpoint(int index) { if (index < 0 || index >= getNcoords()) throw new IllegalArgumentException("Index out of range=" + index); loadValuesIfNeeded(); switch (spacing) { case regularPoint: return startValue + index * getResolution(); case irregularPoint: return values[index]; case regularInterval: return startValue + (index + .5) * getResolution(); case contiguousInterval: case discontiguousInterval: return (getCoordEdge1(index) + getCoordEdge2(index)) / 2; } throw new IllegalStateException("Unknown spacing=" + spacing); }
@Nonnull CoverageCoordAxisBuilder subsetByIndex(Range range) throws InvalidRangeException { int ncoords = range.length(); if (range.last() >= axis.getNcoords()) throw new InvalidRangeException("range.last() >= axis.getNcoords()"); double[] values = axis.getValues(); // will be null for regular double[] subsetValues = null; switch (axis.getSpacing()) { case regularInterval: case regularPoint: resolution = range.stride() * axis.getResolution(); break; builder.subset(ncoords, axis.getCoordMidpoint(range.first()), axis.getCoordMidpoint(range.last()), resolution, subsetValues); builder.setRange(range); return builder;
int search(double want) { if (axis.getNcoords() == 1) { return Misc.nearlyEquals(want, axis.getStartValue()) ? 0 : -1; } if (axis.isRegular()) { double fval = (want - axis.getStartValue()) / axis.getResolution(); double ival = Math.rint(fval); return Misc.nearlyEquals(fval, ival) ? (int) ival : (int) -ival - 1; // LOOK } // otherwise do a binary search return Arrays.binarySearch(axis.getValues(), want); } }
private List<LatLonPoint> calcLatLon1DBoundaryPoints(int maxPointsInYEdge, int maxPointsInXEdge) { if (!isLatLon1D) { throw new UnsupportedOperationException("Coordinate system is not 1D latitude/longitude."); } checkMaxPointsInEdges(maxPointsInYEdge, maxPointsInXEdge); int numYtotal = latAxis.getNcoords(); int numXtotal = lonAxis.getNcoords(); int strideY = calcStride(numYtotal, maxPointsInYEdge); int strideX = calcStride(numXtotal, maxPointsInXEdge); List<LatLonPoint> points = new LinkedList<>(); // Bottom boundary points for (int i = 0; i < numXtotal; i += strideX) { points.add(new LatLonPointImpl(latAxis.getCoordEdgeFirst(), lonAxis.getCoordEdge1(i))); } // Right boundary points for (int j = 0; j < numYtotal; j += strideY) { points.add(new LatLonPointImpl(latAxis.getCoordEdge1(j), lonAxis.getCoordEdgeLast())); } // Top boundary points for (int i = numXtotal - 1; i >= 0; i -= strideX) { points.add(new LatLonPointImpl(latAxis.getCoordEdgeLast(), lonAxis.getCoordEdge2(i))); } // Left boundary points for (int j = numYtotal - 1; j >= 0; j -= strideY) { points.add(new LatLonPointImpl(latAxis.getCoordEdge2(j), lonAxis.getCoordEdgeFirst())); } assertNotExceedingMaxBoundaryPoints(points.size(), maxPointsInYEdge, maxPointsInXEdge); return points; }
double scaler = (xaxis.getUnits().equalsIgnoreCase("km")) ? 1000.0 : 1.0; double xStart = xaxis.getCoordEdge1(0) * scaler; double yStart = yaxis.getCoordEdge1(0) * scaler; double xInc = xaxis.getResolution() * scaler; double yInc = Math.abs(yaxis.getResolution()) * scaler; if (yaxis.getCoordMidpoint(0) < yaxis.getCoordMidpoint(1)) { data = data.flip(0); yStart = yaxis.getCoordEdgeLast();
public List<NamedObject> getCoordValueNames() { loadValuesIfNeeded(); if (timeHelper != null) return timeHelper.getCoordValueNames(this); List<NamedObject> result = new ArrayList<>(); for (int i = 0; i < ncoords; i++) { Object value = null; switch (spacing) { case regularPoint: case irregularPoint: value = Format.d(getCoordMidpoint(i), 3); break; case regularInterval: case contiguousInterval: case discontiguousInterval: value = new CoordInterval(getCoordEdge1(i), getCoordEdge2(i), 3); break; } result.add(new NamedAnything(value, value + " " + getUnits())); } return result; }
int n = axis.getNcoords(); if (axis.isAscending()) { if (target < axis.getCoordEdge1(0)) return bounded ? 0 : -1; else if (target > axis.getCoordEdgeLast()) return bounded ? n - 1 : n; mid = (low + high) / 2; // binary search if (contains(target, mid, true)) return mid; else if (axis.getCoordEdge2(mid) < target) low = mid; else high = mid; if (target > axis.getCoordEdge1(0)) return bounded ? 0 : -1; else if (target < axis.getCoordEdgeLast()) return bounded ? n - 1 : n; mid = (low + high) / 2; // binary search if (contains(target, mid, false)) return mid; else if (axis.getCoordEdge2(mid) < target) high = mid; else low = mid;