diff --git a/src/main/java/gov/usgs/earthquake/nshmp/netcdf/reader/NetcdfUtils.java b/src/main/java/gov/usgs/earthquake/nshmp/netcdf/reader/NetcdfUtils.java index 945557ca5b6bae9a54f60431981b66d9c2f5a225..dfd4f874f7117dca03d0f22a3383826bc1d3dd2a 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/netcdf/reader/NetcdfUtils.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/netcdf/reader/NetcdfUtils.java @@ -18,6 +18,9 @@ import ucar.nc2.Group; public class NetcdfUtils { + // Tolerance for longitude/latitude comparisons + static final double LOCATION_TOLERANCE = 0.000001; + /** * Creates a border going clockwise of the given longitudes and latitudes. * @@ -32,15 +35,16 @@ public class NetcdfUtils { builder.add(lat, longitudes[0]); } - for (var lon : longitudes) { - builder.add(latitudes[latitudes.length - 1], lon); + // omit duplicate points at corners + for (var i = 1; i < longitudes.length; i++) { + builder.add(latitudes[latitudes.length - 1], longitudes[i]); } - for (var i = latitudes.length - 1; i >= 0; i--) { + for (var i = latitudes.length - 2; i >= 0; i--) { builder.add(latitudes[i], longitudes[longitudes.length - 1]); } - for (var i = longitudes.length - 1; i >= 0; i--) { + for (var i = longitudes.length - 2; i >= 0; i--) { builder.add(latitudes[0], longitudes[i]); } @@ -94,7 +98,6 @@ public class NetcdfUtils { static int getIdxLTEQ(double[] a, double t) { // assumes array is in sorted order (a[i] < a[i+1]) // make sure target is within the range of the array - var tol = 0.000001; var n = a.length; if (t < a[0] || t > a[n - 1]) { @@ -105,11 +108,11 @@ public class NetcdfUtils { } // if (t == a[0]) { - if (DoubleMath.fuzzyEquals(a[0], t, tol)) { + if (DoubleMath.fuzzyEquals(a[0], t, LOCATION_TOLERANCE)) { return 0; } // if (t == a[n - 1]) { - if (DoubleMath.fuzzyEquals(a[n - 1], t, tol)) { + if (DoubleMath.fuzzyEquals(a[n - 1], t, LOCATION_TOLERANCE)) { return n - 2; // return second to last index number } @@ -129,12 +132,10 @@ public class NetcdfUtils { * Calculate fractional distance from a1 to t, between a1 and a2 */ static double calcFrac(double a1, double a2, double t) { - var tol = 0.00001; - - if (Math.abs(t - a1) < tol) { + if (Math.abs(t - a1) < LOCATION_TOLERANCE) { // target value == a1 return 0.0; - } else if (Math.abs(t - a2) < tol) { + } else if (Math.abs(t - a2) < LOCATION_TOLERANCE) { // target value == a2 return 1.0; } else { diff --git a/src/test/java/gov/usgs/earthquake/nshmp/netcdf/NshmNetcdfReaderTests.java b/src/test/java/gov/usgs/earthquake/nshmp/netcdf/NshmNetcdfReaderTests.java index 0584f365eab948ee73ac7d531077811c6c5cac09..d02c735f71a62610233e0b4d9a560aab4f28c716 100644 --- a/src/test/java/gov/usgs/earthquake/nshmp/netcdf/NshmNetcdfReaderTests.java +++ b/src/test/java/gov/usgs/earthquake/nshmp/netcdf/NshmNetcdfReaderTests.java @@ -30,7 +30,7 @@ import gov.usgs.earthquake.nshmp.netcdf.reader.NetcdfUtils; import gov.usgs.earthquake.nshmp.netcdf.reader.StaticHazard; import gov.usgs.earthquake.nshmp.netcdf.reader.StaticHazards; -class NshmNetcdfReaderTests { +public class NshmNetcdfReaderTests { static final String CONUS_TEST_FILE = "conus-test.nc"; static final Path NETCDF_PATH = Paths.get(Resources.getResource(CONUS_TEST_FILE).getPath()); @@ -46,8 +46,9 @@ class NshmNetcdfReaderTests { static final Location TARGET_LOCATION = Location.create(39.213, -105.234); - static final double[] EXPECTED_LONGITUDES = new double[] { -105.3, -105.25, -105.2, -105.15 }; - static final double[] EXPECTED_LATITUDES = new double[] { 39.15, 39.2, 39.25, 39.3 }; + public static final double[] EXPECTED_LONGITUDES = + new double[] { -105.3, -105.25, -105.2, -105.15 }; + public static final double[] EXPECTED_LATITUDES = new double[] { 39.15, 39.2, 39.25, 39.3 }; static final LocationList BOUNDING_LOCATIONS = LocationList.builder() .add(EXPECTED_LATITUDES[1], EXPECTED_LONGITUDES[1]) diff --git a/src/test/java/gov/usgs/earthquake/nshmp/netcdf/reader/NetcdfUtilsTests.java b/src/test/java/gov/usgs/earthquake/nshmp/netcdf/reader/NetcdfUtilsTests.java index 00f90792ef6b978b0290105d701675a805022459..28543f08b9e96de11c1c272550fa6c31d7e38c73 100644 --- a/src/test/java/gov/usgs/earthquake/nshmp/netcdf/reader/NetcdfUtilsTests.java +++ b/src/test/java/gov/usgs/earthquake/nshmp/netcdf/reader/NetcdfUtilsTests.java @@ -11,6 +11,7 @@ import java.util.List; import org.junit.jupiter.api.Test; import gov.usgs.earthquake.nshmp.data.XySequence; +import gov.usgs.earthquake.nshmp.geo.LocationList; import gov.usgs.earthquake.nshmp.gmm.Imt; import gov.usgs.earthquake.nshmp.netcdf.SiteClass; @@ -25,6 +26,10 @@ class NetcdfUtilsTests { 39.13, 39.14, 39.15, 39.16, 39.17, 39.18, 39.19, 39.20, 39.21, 39.22, 39.23, 39.24, 39.25, 39.26, 39.27, 39.28, 39.29, 39.30, 39.31, 39.32, 39.33, 39.34, 39.35 }; + private static final double[] BORDER_LONGITUDES = new double[] { 5.0, 6.0 }; + private static final double[] BORDER_LATITUDES = new double[] { 8.0, 9.0 }; + private static final LocationList BORDER_LOCATIONS; + private static final double TOL = 1e-7; static StaticHazards mapHaz0; @@ -38,6 +43,15 @@ class NetcdfUtilsTests { private static final double FRAC = 0.5; static { + + BORDER_LOCATIONS = LocationList.builder() + .add(BORDER_LATITUDES[0], BORDER_LONGITUDES[0]) + .add(BORDER_LATITUDES[1], BORDER_LONGITUDES[0]) + .add(BORDER_LATITUDES[1], BORDER_LONGITUDES[1]) + .add(BORDER_LATITUDES[0], BORDER_LONGITUDES[1]) + .add(BORDER_LATITUDES[0], BORDER_LONGITUDES[0]) + .build(); + var siteClasses = List.of(SiteClass.B, SiteClass.C, SiteClass.D); var imts = List.of(Imt.PGA, Imt.SA0P1, Imt.SA1P5); var imlValues = new double[] { 0.1, 0.5, 0.75 }; @@ -106,7 +120,12 @@ class NetcdfUtilsTests { } @Test - final void testGetIdxLTEQ() { + final void buildBorderTest() { + assertEquals(BORDER_LOCATIONS, NetcdfUtils.buildBorder(BORDER_LONGITUDES, BORDER_LATITUDES)); + } + + @Test + final void getIdxLTEQTest() { // target is out of range, expect IAE assertThrows(IllegalArgumentException.class, () -> { NetcdfUtils.getIdxLTEQ(LONGITUDES, -100.0); @@ -134,7 +153,25 @@ class NetcdfUtilsTests { } @Test - final void testCalcGridFrac() { + final void calcFracTest() { + double bottom = 5.0; + double top = bottom + 1.0; + double frac = 0.36; + assertEquals(0.0, NetcdfUtils.calcFrac(bottom, top, bottom)); + assertEquals(1.0, NetcdfUtils.calcFrac(bottom, top, top)); + assertEquals(0.0, NetcdfUtils.calcFrac( + bottom, + top, + bottom + NetcdfUtils.LOCATION_TOLERANCE * 0.9)); + assertEquals(1.0, NetcdfUtils.calcFrac( + bottom, + top, + top - NetcdfUtils.LOCATION_TOLERANCE * 0.9)); + assertEquals(frac, NetcdfUtils.calcFrac(bottom, top, bottom + frac), 1e-4); + } + + @Test + final void calcGridFracTest() { double f = 0.13; int i = 4; assertEquals(f, @@ -147,7 +184,7 @@ class NetcdfUtilsTests { } @Test - final void testLinearInterpolate() { + final void linearInterpolateTest() { var actual = NetcdfUtils.linearInterpolate(mapHaz0, mapHaz1, FRAC); assertTrue(mapHazTarget.keySet().containsAll(actual.keySet()));