diff --git a/cdm/core/src/main/java/ucar/nc2/ft2/coverage/CoordAxisHelper.java b/cdm/core/src/main/java/ucar/nc2/ft2/coverage/CoordAxisHelper.java index 76dceedb7a..bb19bffb9a 100644 --- a/cdm/core/src/main/java/ucar/nc2/ft2/coverage/CoordAxisHelper.java +++ b/cdm/core/src/main/java/ucar/nc2/ft2/coverage/CoordAxisHelper.java @@ -11,7 +11,7 @@ import ucar.nc2.constants.AxisType; import ucar.nc2.time.CalendarDate; import ucar.nc2.time.CalendarDateRange; -import ucar.nc2.util.Misc; + import javax.annotation.Nonnull; import java.util.Arrays; import ucar.nc2.util.Optional; @@ -25,6 +25,8 @@ class CoordAxisHelper { private final CoverageCoordAxis1D axis; + private static final int MULTIPLE_HITS = -2; + CoordAxisHelper(CoverageCoordAxis1D axis) { this.axis = axis; } @@ -201,16 +203,16 @@ else if (upperIndex > axis.getCoordEdgeLast()) } // same contract as findCoordElement(); in addition, -1 is returned when the target is not contained in any interval - // LOOK not using bounded 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 (definition of closest will be based on axis type) - return findClosestDiscontiguousInterval(target); + if (idx == MULTIPLE_HITS) { + return findClosestDiscontiguousInterval(target); + } + if (bounded && (idx >= axis.getNcoords())) { + return -1; + } + return idx; } boolean intervalContains(double target, int coordIdx) { @@ -229,22 +231,25 @@ private boolean intervalContains(double target, int coordIdx, boolean ascending) return lowerVal <= target && target <= upperVal; } - // return index if only one match, if no matches return -1, if > 1 match return -nhits + // return index if only one match + // return MULTIPLE_HITS if in several private int findSingleHit(double target) { - int hits = 0; + // edge cases: outside first interval + double firstCoord = axis.getCoordEdge1(0); + if ((axis.isAscending() && target < firstCoord) || (!axis.isAscending() && target > firstCoord)) { + return -1; + } int idxFound = -1; int n = axis.getNcoords(); for (int i = 0; i < n; i++) { if (intervalContains(target, i)) { - hits++; + if (idxFound >= 0) { + return MULTIPLE_HITS; + } idxFound = i; } } - if (hits == 1) - return idxFound; - if (hits == 0) - return -1; - return -hits; + return idxFound > -1 ? idxFound : n; } // return index of closest value to target @@ -273,7 +278,7 @@ private int findClosestDiscontiguousTimeInterval(double target) { // must be greater than or equal to the target. if (coord >= target) { // compute the width (in time) of the interval - double width = axis.getCoordEdge2(i) - axis.getCoordEdge1(i); + double width = coord - axis.getCoordEdge1(i); // we want to identify the interval with the end point closest to our target // why? Because a statistic computed over a time window will only have meaning at the end // of that interval, so the closer we can get to that the better. diff --git a/cdm/core/src/main/java/ucar/nc2/ft2/coverage/writer/CFGridCoverageWriter.java b/cdm/core/src/main/java/ucar/nc2/ft2/coverage/writer/CFGridCoverageWriter.java index 169c784217..1e9063e8ce 100644 --- a/cdm/core/src/main/java/ucar/nc2/ft2/coverage/writer/CFGridCoverageWriter.java +++ b/cdm/core/src/main/java/ucar/nc2/ft2/coverage/writer/CFGridCoverageWriter.java @@ -58,6 +58,8 @@ public class CFGridCoverageWriter { private static final String BOUNDS = "_bounds"; private static final String BOUNDS_DIM = "bounds_dim"; // dimension of length 2, can be used by any bounds coordinate + public static final String TOO_LARGE_MESSAGE = "Request too large"; + /** A value class holding information about the write() */ public static class Result { private final long sizeToBeWritten; @@ -158,7 +160,7 @@ private Result writeFile(CoverageCollection gdsOrg, List gridNames, Subs // test if its too large long totalSizeOfVars = ncwriter.calcSize(); if (maxBytes > 0 && totalSizeOfVars > maxBytes) { - return Result.create(totalSizeOfVars, false, String.format("Too large, max size = %d", maxBytes)); + return Result.create(totalSizeOfVars, false, TOO_LARGE_MESSAGE); } writeCoordinateData(subsetDataset, ncwriter);