Skip to content

Commit 8c2b5af

Browse files
authored
Merge pull request #1437 from lesserwhirls/enhance
Only apply enhancements once for CoordinateAxis variables
2 parents 0364a04 + 69d2e61 commit 8c2b5af

File tree

4 files changed

+111
-5
lines changed

4 files changed

+111
-5
lines changed

cdm/core/src/main/java/ucar/nc2/dataset/VariableDS.java

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998-2018 John Caron and University Corporation for Atmospheric Research/Unidata
2+
* Copyright (c) 1998-2025 John Caron and University Corporation for Atmospheric Research/Unidata
33
* See LICENSE for license information.
44
*/
55
package ucar.nc2.dataset;
@@ -494,9 +494,28 @@ protected Array _read(Section section) throws IOException, InvalidRangeException
494494
// do not call directly
495495
@Override
496496
public Array reallyRead(Variable client, CancelTask cancelTask) throws IOException {
497-
if (orgVar == null)
497+
if (orgVar == null) {
498+
// possible aggregation
499+
if (this.proxyReader != null && this.proxyReader instanceof ucar.nc2.ncml.Aggregation) {
500+
return this.proxyReader.reallyRead(client, cancelTask);
501+
}
498502
return getMissingDataArray(shape);
503+
}
499504

505+
if (client instanceof CoordinateAxis) {
506+
// If orgVar is a VariableDS (orgVar of a CoordinateAxis using the non-builder
507+
// API, for example), call reallyRead on it, otherwise, enhancements will get
508+
// applied twice in a second _read() call triggered by calling read() on the
509+
// VariableDS.
510+
if (orgVar instanceof VariableDS && !orgVar.hasCachedData()) {
511+
return orgVar.reallyRead(client, cancelTask);
512+
}
513+
// Some aggregations use a DatasetProxyReader for reading a coordinate axis
514+
// variable, so check to see if that's what we have and, if so, use it.
515+
if (ucar.nc2.ncml.Aggregation.instanceOfDatasetProxyReader(this.proxyReader)) {
516+
return this.proxyReader.reallyRead(client, cancelTask);
517+
}
518+
}
500519
return orgVar.read();
501520
}
502521

@@ -508,9 +527,28 @@ public Array reallyRead(Variable client, Section section, CancelTask cancelTask)
508527
if ((null == section) || section.computeSize() == getSize())
509528
return reallyRead(client, cancelTask);
510529

511-
if (orgVar == null)
512-
return getMissingDataArray(section.getShape());
530+
if (orgVar == null) {
531+
// possible aggregation
532+
if (this.proxyReader != null && this.proxyReader instanceof ucar.nc2.ncml.Aggregation) {
533+
return this.proxyReader.reallyRead(client, section, cancelTask);
534+
}
535+
return getMissingDataArray(shape);
536+
}
513537

538+
if (client instanceof CoordinateAxis) {
539+
// If orgVar is a VariableDS (orgVar of a CoordinateAxis using the non-builder
540+
// API, for example), call reallyRead on it, otherwise, enhancements will get
541+
// applied twice in a second _read() call triggered by calling read() on the
542+
// VariableDS.
543+
if (orgVar instanceof VariableDS && !orgVar.hasCachedData()) {
544+
return orgVar.reallyRead(client, section, cancelTask);
545+
}
546+
// Some aggregations use a DatasetProxyReader for reading a coordinate axis
547+
// variable, so check to see if that's what we have and, if so, use it.
548+
if (ucar.nc2.ncml.Aggregation.instanceOfDatasetProxyReader(this.proxyReader)) {
549+
return this.proxyReader.reallyRead(client, section, cancelTask);
550+
}
551+
}
514552
return orgVar.read(section);
515553
}
516554

cdm/core/src/main/java/ucar/nc2/ncml/Aggregation.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998-2020 John Caron and University Corporation for Atmospheric Research/Unidata
2+
* Copyright (c) 1998-2025 John Caron and University Corporation for Atmospheric Research/Unidata
33
* See LICENSE.txt for license information.
44
*/
55
package ucar.nc2.ncml;
@@ -777,6 +777,11 @@ protected void setDatasetAcquireProxy(DatasetProxyReader proxy, Group g) throws
777777
}
778778
}
779779

780+
public static boolean instanceOfDatasetProxyReader(Object obj) {
781+
if (obj == null)
782+
return false;
783+
return obj instanceof DatasetProxyReader;
784+
}
780785

781786
protected class DatasetProxyReader implements ProxyReader {
782787
Dataset dataset;
16.4 KB
Binary file not shown.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) 2025 University Corporation for Atmospheric Research/Unidata
3+
* See LICENSE.txt for license information.
4+
*/
5+
package ucar.nc2.dataset;
6+
7+
import java.io.IOException;
8+
import java.util.Objects;
9+
import org.junit.Test;
10+
import ucar.ma2.Array;
11+
import ucar.nc2.Attribute;
12+
import ucar.nc2.NetcdfFile;
13+
import ucar.nc2.NetcdfFiles;
14+
import ucar.nc2.Variable;
15+
import ucar.nc2.constants.AxisType;
16+
import ucar.unidata.util.test.TestDir;
17+
import static com.google.common.truth.Truth.assertThat;
18+
19+
public class TestScaledCoordAxis1D {
20+
21+
@Test
22+
public void testEnhancedOnce() throws IOException {
23+
String testfile = TestDir.cdmLocalTestDataDir + "scaledCoordAxis1D.nc4";
24+
try (NetcdfFile ncf = NetcdfFile.open(testfile, null); NetcdfDataset ncd = NetcdfDataset.openDataset(testfile)) {
25+
checkAxis(ncf, ncd, "x", AxisType.GeoX);
26+
checkAxis(ncf, ncd, "y", AxisType.GeoY);
27+
}
28+
}
29+
30+
@Test
31+
public void testEnhancedOnceBuilders() throws IOException {
32+
String testfile = TestDir.cdmLocalTestDataDir + "scaledCoordAxis1D.nc4";
33+
try (NetcdfFile ncf = NetcdfFiles.open(testfile, null); NetcdfDataset ncd = NetcdfDatasets.openDataset(testfile)) {
34+
checkAxis(ncf, ncd, "x", AxisType.GeoX);
35+
checkAxis(ncf, ncd, "y", AxisType.GeoY);
36+
}
37+
}
38+
39+
public void checkAxis(NetcdfFile ncf, NetcdfDataset ncd, String axisName, AxisType axisType) throws IOException {
40+
Variable var = ncf.findVariable(axisName);
41+
assertThat(var != null).isTrue();
42+
Array vals = var.read();
43+
Attribute scaleAttr = var.findAttribute("scale_factor");
44+
assertThat(scaleAttr).isNotNull();
45+
float scale = Objects.requireNonNull(scaleAttr.getNumericValue()).floatValue();
46+
Attribute offsetAttr = var.findAttribute("add_offset");
47+
assertThat(offsetAttr).isNotNull();
48+
float offset = Objects.requireNonNull(offsetAttr.getNumericValue()).floatValue();
49+
assertThat(vals.getShape().length).isEqualTo(1);
50+
int len = vals.getShape()[0];
51+
final float[] valsEnhanced = new float[len];
52+
for (int i = 0; i < len; i++) {
53+
valsEnhanced[i] = vals.getShort(i) * scale + offset;
54+
}
55+
// vals have a scale and offset.
56+
assertThat(vals).isNotNull();
57+
CoordinateAxis coodAxis = ncd.findCoordinateAxis(axisType);
58+
Array coordVals = coodAxis.read();
59+
for (int i = 0; i < len; i++) {
60+
assertThat(coordVals.getFloat(i)).isWithin(1e-6f).of(valsEnhanced[i]);
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)