From b6339e6e5cbd32431255c0b2576586110c11e2a9 Mon Sep 17 00:00:00 2001 From: James Douglass Date: Thu, 19 Sep 2024 16:02:40 -0700 Subject: [PATCH 1/6] Noting change in HISTORY. RE:#1293 --- HISTORY.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index dfa49b3025..c888d1bfd2 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -37,6 +37,10 @@ Unreleased Changes ------------------ +* Urban Nature Access + * The model now works as expected when the user provides an LULC raster + that does not have a nodata value defined. + https://github.com/natcap/invest/issues/1293 * Workbench * Several small updates to the model input form UI to improve usability and visual consistency (https://github.com/natcap/invest/issues/912) From e6eb1a037a28c8c56adc633425dc8bb467e83ad8 Mon Sep 17 00:00:00 2001 From: James Douglass Date: Thu, 19 Sep 2024 16:06:24 -0700 Subject: [PATCH 2/6] Adding a test for when the LULC has no nodata value. RE:#1293 --- tests/test_urban_nature_access.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/test_urban_nature_access.py b/tests/test_urban_nature_access.py index 0e4858a832..4e5141f0b6 100644 --- a/tests/test_urban_nature_access.py +++ b/tests/test_urban_nature_access.py @@ -358,6 +358,21 @@ def test_core_model(self): self.assertAlmostEqual(numpy.min(valid_pixels), 1171.7352294921875) self.assertAlmostEqual(numpy.max(valid_pixels), 11898.0712890625) + def test_no_lulc_nodata(self): + """UNA: verify behavior when the LULC has no nodata value.""" + from natcap.invest import urban_nature_access + + args = _build_model_args(self.workspace_dir) + args['search_radius_mode'] = urban_nature_access.RADIUS_OPT_UNIFORM + args['search_radius'] = 100 + + raster = gdal.OpenEx(args['lulc_raster_path'], gdal.OF_RASTER) + band = raster.GetRasterBand(1) + band.DeleteNoDataValue() + band = None + raster = None + urban_nature_access.execute(args) + def test_split_urban_nature(self): from natcap.invest import urban_nature_access From 94f7f006e88c277362f33ff86a0d89cc037564ea Mon Sep 17 00:00:00 2001 From: James Douglass Date: Tue, 1 Oct 2024 14:34:39 -0700 Subject: [PATCH 3/6] Cleaning up a conditional. RE:#1293 --- src/natcap/invest/urban_nature_access.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/natcap/invest/urban_nature_access.py b/src/natcap/invest/urban_nature_access.py index c8b4928699..136575a956 100644 --- a/src/natcap/invest/urban_nature_access.py +++ b/src/natcap/invest/urban_nature_access.py @@ -2542,11 +2542,6 @@ def _warp_lulc(source_lulc_path, target_lulc_path, target_pixel_size, """ source_raster_info = pygeoprocessing.get_raster_info(source_lulc_path) target_nodata = source_raster_info['nodata'][0] - if target_nodata is None: - # Guarantee that our nodata cannot be represented by the datatype - - # select a nodata value that's out of range. - target_nodata = pygeoprocessing.choose_nodata( - source_raster_info['numpy_type']) + 1 pygeoprocessing.warp_raster( source_lulc_path, target_pixel_size, target_lulc_path, @@ -2554,11 +2549,16 @@ def _warp_lulc(source_lulc_path, target_lulc_path, target_pixel_size, target_projection_wkt=source_raster_info['projection_wkt']) # if there is no defined nodata, set a default value - raster = gdal.OpenEx(target_lulc_path, gdal.GA_Update) - band = raster.GetRasterBand(1) - band.SetNoDataValue(target_nodata) - band = None - raster = None + if target_nodata is None: + # Guarantee that our nodata cannot be represented by the datatype - + # select a nodata value that's out of range. + target_nodata = pygeoprocessing.choose_nodata( + source_raster_info['numpy_type']) + 1 + raster = gdal.OpenEx(target_lulc_path, gdal.GA_Update) + band = raster.GetRasterBand(1) + band.SetNoDataValue(target_nodata) + band = None + raster = None def _mask_raster(source_raster_path, mask_raster_path, target_raster_path): From 2ab42a9e9f1f720b8e106bea05bea4d8be053035 Mon Sep 17 00:00:00 2001 From: Emily Davis Date: Tue, 8 Oct 2024 13:47:53 -0600 Subject: [PATCH 4/6] Update conf.py to fix RTD build --- doc/api-docs/conf.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/api-docs/conf.py b/doc/api-docs/conf.py index 495e68e8b8..5594c7dbd8 100644 --- a/doc/api-docs/conf.py +++ b/doc/api-docs/conf.py @@ -78,6 +78,13 @@ # -- Options for HTML output ---------------------------------------------- import sphinx_rtd_theme + +# Tell Jinja2 templates the build is running on Read the Docs +if os.environ.get('READTHEDOCS', '') == 'True': + if 'html_context' not in globals(): + html_context = {} + html_context['READTHEDOCS'] = True + # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'sphinx_rtd_theme' @@ -130,7 +137,7 @@ # dir menu entry, description, category) texinfo_documents = [ ('index', 'InVEST', 'InVEST Documentation', - 'The Natural Capital Project', 'InVEST', + 'The Natural Capital Project', 'InVEST', 'Integrated Valuation of Ecosystem Services and Tradeoffs', 'Scientific Software'), ] @@ -138,8 +145,8 @@ # -- Prepare for sphinx build --------------------------------------------- -# Use sphinx apidoc tool to generate documentation for invest. Generated rst -# files go into the api/ directory. Note that some apidoc options may not work +# Use sphinx apidoc tool to generate documentation for invest. Generated rst +# files go into the api/ directory. Note that some apidoc options may not work # the same because we aren't using their values in the custom templates apidoc.main([ '--force', # overwrite any files from previous run @@ -164,7 +171,7 @@ All InVEST models share a consistent python API: - - Every InVEST model has a corresponding module or subpackage in the + - Every InVEST model has a corresponding module or subpackage in the ``natcap.invest`` package - The model modules contain a function called ``execute`` - The ``execute`` function takes a single argument (``args``), a dictionary From 0f45a5c42f17f02d59681d13abdb7bfcd87c19b4 Mon Sep 17 00:00:00 2001 From: Emily Davis Date: Tue, 8 Oct 2024 13:57:23 -0600 Subject: [PATCH 5/6] Remove call to deprecated get_html_theme_path --- doc/api-docs/conf.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/api-docs/conf.py b/doc/api-docs/conf.py index 5594c7dbd8..3d9eeab372 100644 --- a/doc/api-docs/conf.py +++ b/doc/api-docs/conf.py @@ -89,9 +89,6 @@ # a list of builtin themes. html_theme = 'sphinx_rtd_theme' -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - # The name of an image file (relative to this directory) to place at the top # of the sidebar. html_logo = "_static/invest-logo.png" From 28b9c3dbfdd9e3ff13d38b4f7fa34bb38e103888 Mon Sep 17 00:00:00 2001 From: Emily Davis Date: Tue, 8 Oct 2024 14:09:51 -0600 Subject: [PATCH 6/6] Remove recently added code to see if we truly need it --- doc/api-docs/conf.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/api-docs/conf.py b/doc/api-docs/conf.py index 3d9eeab372..52205cf614 100644 --- a/doc/api-docs/conf.py +++ b/doc/api-docs/conf.py @@ -79,12 +79,6 @@ import sphinx_rtd_theme -# Tell Jinja2 templates the build is running on Read the Docs -if os.environ.get('READTHEDOCS', '') == 'True': - if 'html_context' not in globals(): - html_context = {} - html_context['READTHEDOCS'] = True - # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'sphinx_rtd_theme'