From 69fabb1500f39ac07ab797191412c67db6942adb Mon Sep 17 00:00:00 2001 From: davemfish Date: Tue, 20 Feb 2024 13:54:43 -0500 Subject: [PATCH 1/4] add tests to cover nan nodata in bathymetry. #1528 --- tests/test_coastal_vulnerability.py | 32 +++++++++++++++-------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/tests/test_coastal_vulnerability.py b/tests/test_coastal_vulnerability.py index 9f3f7b51d2..8d8a6a37d2 100644 --- a/tests/test_coastal_vulnerability.py +++ b/tests/test_coastal_vulnerability.py @@ -224,27 +224,29 @@ def test_extract_bathymetry(self): projection_wkt = srs.ExportToWkt() geotransform = [0, 1.0, 0.0, 0, 0.0, -1.0] n = 5 - nodata_val = 9999 + band1_nodata = numpy.nan gtiff_driver = gdal.GetDriverByName('GTiff') new_raster = gtiff_driver.Create( - raster_path, n, n, 2, gdal.GDT_Int32, options=[ + raster_path, n, n, 2, gdal.GDT_Float32, options=[ 'TILED=YES', 'BIGTIFF=YES', 'COMPRESS=LZW', 'BLOCKXSIZE=16', 'BLOCKYSIZE=16']) new_raster.SetProjection(projection_wkt) new_raster.SetGeoTransform(geotransform) - array = numpy.array([-1]*n*n).reshape((n, n)) + valid_value = -10.0 + array = numpy.array([valid_value]*n*n).reshape((n, n)) # nodata across the top row for Band 1 new_band = new_raster.GetRasterBand(1) - array[:1] = nodata_val + array[:1] = band1_nodata new_band.WriteArray(array) - new_band.SetNoDataValue(nodata_val) + new_band.SetNoDataValue(band1_nodata) # all nodata for Band 2 + band2_nodata = 999.99 nodata_band = new_raster.GetRasterBand(2) - array[:] = nodata_val + array[:] = band2_nodata nodata_band.WriteArray(array) - nodata_band.SetNoDataValue(nodata_val) + nodata_band.SetNoDataValue(band2_nodata) new_raster.FlushCache() new_band = None @@ -276,25 +278,25 @@ def test_extract_bathymetry(self): band = raster.GetRasterBand(1) # nodata across top row values = coastal_vulnerability.extract_bathymetry_along_ray( - all_valid_ray, geotransform, nodata_val, band) - self.assertTrue(numpy.mean(values) == -1) + all_valid_ray, geotransform, band1_nodata, band) + self.assertEqual(numpy.mean(values), valid_value) values = coastal_vulnerability.extract_bathymetry_along_ray( - some_nodata_ray, geotransform, nodata_val, band) - self.assertTrue(numpy.mean(values) == -1) + some_nodata_ray, geotransform, band1_nodata, band) + self.assertEqual(numpy.mean(values), valid_value) values = coastal_vulnerability.extract_bathymetry_along_ray( - all_nodata_ray, geotransform, nodata_val, band) - self.assertTrue(numpy.mean(values) == -1) + all_nodata_ray, geotransform, band1_nodata, band) + self.assertEqual(numpy.mean(values), valid_value) with self.assertRaises(ValueError): values = coastal_vulnerability.extract_bathymetry_along_ray( - out_of_bounds_ray, geotransform, nodata_val, band) + out_of_bounds_ray, geotransform, band1_nodata, band) nodata_band = raster.GetRasterBand(2) # all nodata band with self.assertRaises(ValueError): values = coastal_vulnerability.extract_bathymetry_along_ray( - all_valid_ray, geotransform, nodata_val, nodata_band) + all_valid_ray, geotransform, band2_nodata, nodata_band) raster = None band = None From a14f719cecdbc4822836e23ef056fa933ec2c23d Mon Sep 17 00:00:00 2001 From: davemfish Date: Tue, 20 Feb 2024 13:55:32 -0500 Subject: [PATCH 2/4] use numpy.isclose and check for equal nan. #1528 --- src/natcap/invest/coastal_vulnerability.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/natcap/invest/coastal_vulnerability.py b/src/natcap/invest/coastal_vulnerability.py index ced65f9d71..01135ef85a 100644 --- a/src/natcap/invest/coastal_vulnerability.py +++ b/src/natcap/invest/coastal_vulnerability.py @@ -1754,7 +1754,8 @@ def extract_bathymetry_along_ray( raise ValueError( f'got a {value} when trying to read bathymetry at {location}. ' 'Does the bathymetry input fully cover the fetch ray area?') - if bathy_nodata is None or not math.isclose(value[0][0], bathy_nodata): + if bathy_nodata is None or not numpy.isclose( + value[0][0], bathy_nodata, equal_nan=True): bathy_values.append(value) # Gaps between shoreline and bathymetry input datasets could result in no From 086aade1d9398f9afe2ad21f6f851053656f8f35 Mon Sep 17 00:00:00 2001 From: davemfish Date: Wed, 21 Feb 2024 09:45:04 -0500 Subject: [PATCH 3/4] note for history. #1528 --- HISTORY.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index cf88c717be..3a0a557003 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -41,6 +41,11 @@ Unreleased Changes * Annual Water Yield * Added the results_suffix to a few intermediate files where it was missing. https://github.com/natcap/invest/issues/1517 +* Coastal Vulnerability + * Fixed a bug in handling ``nan`` as the nodata value of the bathymetry + raster. ``nan`` pixels will now be propertly ignored before calculating + mean depths along fetch rays. + https://github.com/natcap/invest/issues/1528 * Urban Nature Access * Fixed a ``NameError`` that occurred when running the model using search radii defined per population group with an exponential search From beca6d7b9a93a2461b6ce2976ac37be16acbc304 Mon Sep 17 00:00:00 2001 From: davemfish Date: Wed, 21 Feb 2024 09:52:59 -0500 Subject: [PATCH 4/4] fix indent. #1528 --- src/natcap/invest/coastal_vulnerability.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/natcap/invest/coastal_vulnerability.py b/src/natcap/invest/coastal_vulnerability.py index 01135ef85a..8ebf032988 100644 --- a/src/natcap/invest/coastal_vulnerability.py +++ b/src/natcap/invest/coastal_vulnerability.py @@ -3161,7 +3161,7 @@ def _aggregate_raster_values_in_radius( max_distance=pixel_dist, normalize=False) radial_kernel_mask = pygeoprocessing.raster_to_numpy_array( - kernel_path).astype(bool) + kernel_path).astype(bool) shutil.rmtree(temp_dir, ignore_errors=True) result = {}