Skip to content

Commit e621412

Browse files
authored
Merge pull request #1431 from lesserwhirls/dint
2 parents 3c871ce + ae0209f commit e621412

File tree

2 files changed

+66
-26
lines changed

2 files changed

+66
-26
lines changed

cdm-test/src/test/java/ucar/nc2/ft/coverage/TestCoverageSubsetTime.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,46 @@ public void testRegularIntervalSubsetTimeRange() throws IOException, InvalidRang
792792
}
793793
}
794794

795+
@Test
796+
public void testDiscontiguousIntervalSubsetTimeRangeStartNoInInterval() throws IOException, InvalidRangeException {
797+
String endpoint = TestDir.cdmUnitTestDir + "datasets/NDFD-CONUS-5km/NDFD-CONUS-5km.ncx4";
798+
String covName = "Minimum_temperature_height_above_ground_12_Hour_Minimum";
799+
800+
logger.debug("testDiscontiguousIntervalTime Dataset {} coverage {}", endpoint, covName);
801+
802+
try (FeatureDatasetCoverage featureDatasetCoverage = CoverageDatasetFactory.open(endpoint)) {
803+
assertThat(featureDatasetCoverage).isNotNull();
804+
CoverageCollection coverageCollection = featureDatasetCoverage.findCoverageDataset(FeatureType.GRID);
805+
assertThat(coverageCollection).isNotNull();
806+
Coverage coverage = coverageCollection.findCoverage(covName);
807+
assertThat(coverage).isNotNull();
808+
809+
SubsetParams params = new SubsetParams();
810+
811+
// key point of test - start time lands between two discontiguous time windows
812+
CalendarDate subsetTimeStart = CalendarDate.parseISOformat(null, "2013-12-18T20:00:00Z");
813+
CalendarDate subsetTimeEnd = CalendarDate.parseISOformat(null, "2013-12-19T13:00:00Z");
814+
// expect: any interval containing or ending on the start or end times
815+
// idx keep interval
816+
// 0 N ( 84.000000, 96.000000) == (2013-12-15T12:00:00Z, 2013-12-16T00:00:00Z)
817+
// 1 N (108.000000, 120.000000) == (2013-12-16T12:00:00Z, 2013-12-17T00:00:00Z)
818+
// 2 N (132.000000, 144.000000) == (2013-12-17T12:00:00Z, 2013-12-18T00:00:00Z)
819+
// 3 Y (156.000000, 168.000000) == (2013-12-18T12:00:00Z, 2013-12-19T00:00:00Z)
820+
// 4 Y (180.000000, 192.000000) == (2013-12-19T12:00:00Z, 2013-12-20T00:00:00Z)
821+
// 5 N (204.000000, 216.000000) == (2013-12-20T12:00:00Z, 2013-12-21T00:00:00Z)
822+
int expectedStartIndex = 3;
823+
int expectedEndIndex = 4;
824+
params.setTimeRange(CalendarDateRange.of(subsetTimeStart, subsetTimeEnd));
825+
logger.debug(" subset {}", params);
826+
827+
GeoReferencedArray geo = coverage.readData(params);
828+
assertThat(geo).isNotNull();
829+
CoverageCoordAxis timeAxis = geo.findCoordAxis("time1");
830+
assertThat(timeAxis).isNotNull();
831+
assertThat(timeAxis.getSpacing()).isEqualTo(Spacing.discontiguousInterval);
832+
assertThat(timeAxis.getRange()).isEqualTo(new Range(expectedStartIndex, expectedEndIndex));
833+
}
834+
}
795835
///////////////////////////////////////////////////////////////////////////////////////////
796836
// ENsemble
797837

cdm/core/src/main/java/ucar/nc2/ft2/coverage/CoordAxisHelper.java

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,16 @@ else if (upperIndex > axis.getCoordEdgeLast())
205205
// same contract as findCoordElement(); in addition, -1 is returned when the target is not contained in any interval
206206
private int findCoordElementDiscontiguousInterval(double target, boolean bounded) {
207207
int idx = findSingleHit(target);
208-
// multiple hits = choose closest (definition of closest will be based on axis type)
209-
if (idx == MULTIPLE_HITS) {
210-
return findClosestDiscontiguousInterval(target);
211-
}
212208
if (bounded && (idx >= axis.getNcoords())) {
213209
return -1;
214210
}
211+
// multiple hits = choose closest (definition of closest will be based on axis type)
212+
// - OR -
213+
// idx will be Ncoords if target not contained within an interval window - however, that
214+
// does not mean target isn't between two discontiguous windows, so find the closest one
215+
if (idx == MULTIPLE_HITS || idx == axis.getNcoords()) {
216+
return findClosestDiscontiguousInterval(target);
217+
}
215218
return idx;
216219
}
217220

@@ -272,28 +275,25 @@ private int findClosestDiscontiguousTimeInterval(double target) {
272275
int idxFound = -1;
273276

274277
for (int i = 0; i < axis.getNcoords(); i++) {
275-
// only check if target is in discontiguous interval i
276-
if (intervalContains(target, i)) {
277-
// find the end of the time interval
278-
double coord = axis.getCoordEdge2(i);
279-
// We want to make sure the interval includes our target point, and that means the end of the interval
280-
// must be greater than or equal to the target.
281-
if (coord >= target) {
282-
// compute the width (in time) of the interval
283-
double width = coord - axis.getCoordEdge1(i);
284-
// we want to identify the interval with the end point closest to our target
285-
// why? Because a statistic computed over a time window will only have meaning at the end
286-
// of that interval, so the closer we can get to that the better.
287-
double diff = Math.abs(coord - target);
288-
// Here we minimize the difference between the end of an interval and our target value. If multiple
289-
// intervals result in the same difference value, we will pick the one with the smallest non-zero
290-
// width interval.
291-
boolean tiebreaker = (diff == minDiff) && (width != 0) && (width < useValue);
292-
if (diff < minDiff || tiebreaker) {
293-
minDiff = diff;
294-
idxFound = i;
295-
useValue = width;
296-
}
278+
// find the end of the time interval
279+
double coord = axis.getCoordEdge2(i);
280+
// We want to make sure the interval includes our target point, and that means the end of the interval
281+
// must be greater than or equal to the target.
282+
if (coord >= target) {
283+
// compute the width (in time) of the interval
284+
double width = coord - axis.getCoordEdge1(i);
285+
// we want to identify the interval with the end point closest to our target
286+
// why? Because a statistic computed over a time window will only have meaning at the end
287+
// of that interval, so the closer we can get to that the better.
288+
double diff = Math.abs(coord - target);
289+
// Here we minimize the difference between the end of an interval and our target value. If multiple
290+
// intervals result in the same difference value, we will pick the one with the smallest non-zero
291+
// width interval.
292+
boolean tiebreaker = (diff == minDiff) && (width != 0) && (width < useValue);
293+
if (diff < minDiff || tiebreaker) {
294+
minDiff = diff;
295+
idxFound = i;
296+
useValue = width;
297297
}
298298
}
299299
}

0 commit comments

Comments
 (0)