From 5b0b2d8097f7fecfd5cf2f56de1682f39e53c4a0 Mon Sep 17 00:00:00 2001 From: Kenn Cartier Date: Wed, 18 Dec 2024 09:53:02 -0800 Subject: [PATCH] Added handling of no resampling --- city_metrix/layers/albedo.py | 16 +++++++++++----- city_metrix/layers/alos_dsm.py | 23 ++++++++++++++++------- city_metrix/layers/layer.py | 9 +++------ city_metrix/layers/nasa_dem.py | 21 ++++++++++++++------- tests/resources/layer_dumps/conftest.py | 2 +- tests/test_layer_metrics.py | 23 ++++++++++++++++++----- 6 files changed, 63 insertions(+), 31 deletions(-) diff --git a/city_metrix/layers/albedo.py b/city_metrix/layers/albedo.py index da63bb1..d8f1430 100644 --- a/city_metrix/layers/albedo.py +++ b/city_metrix/layers/albedo.py @@ -9,7 +9,7 @@ class Albedo(Layer): start_date: starting date for data retrieval end_date: ending date for data retrieval spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster) - resampling_method: interpolation method used by Google Earth Engine. Albedo default is 'bilinear'. All options are: ('bilinear', 'bicubic', 'default'). + resampling_method: interpolation method used by Google Earth Engine. Albedo default is 'bilinear'. All options are: ('bilinear', 'bicubic', None). threshold: threshold value for filtering the retrieval """ @@ -119,10 +119,16 @@ def calc_s2_albedo(image): ## S2 MOSAIC AND ALBEDO dataset = get_masked_s2_collection(ee.Geometry.BBox(*bbox), self.start_date, self.end_date) s2_albedo = dataset.map(calc_s2_albedo) - albedo_mean = (s2_albedo - .map(lambda x: set_resampling_method(x, self.resampling_method),) - .reduce(ee.Reducer.mean()) - ) + + if self.resampling_method is not None: + albedo_mean = (s2_albedo + .map(lambda x: set_resampling_method(x, self.resampling_method)) + .reduce(ee.Reducer.mean()) + ) + else: + albedo_mean = (s2_albedo + .reduce(ee.Reducer.mean()) + ) albedo_mean_ic = ee.ImageCollection(albedo_mean) data = get_image_collection( diff --git a/city_metrix/layers/alos_dsm.py b/city_metrix/layers/alos_dsm.py index ca34ef6..4d5db37 100644 --- a/city_metrix/layers/alos_dsm.py +++ b/city_metrix/layers/alos_dsm.py @@ -7,7 +7,7 @@ class AlosDSM(Layer): """ Attributes: spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster) - resampling_method: interpolation method used by Google Earth Engine. AlosDSM default is 'bilinear'. All options are: ('bilinear', 'bicubic', 'default'). + resampling_method: interpolation method used by Google Earth Engine. AlosDSM default is 'bilinear'. All options are: ('bilinear', 'bicubic', None). """ def __init__(self, spatial_resolution=30, resampling_method='bilinear', **kwargs): @@ -18,12 +18,21 @@ def __init__(self, spatial_resolution=30, resampling_method='bilinear', **kwargs def get_data(self, bbox): alos_dsm = ee.ImageCollection("JAXA/ALOS/AW3D30/V3_2") - alos_dsm_ic = ee.ImageCollection(alos_dsm - .filterBounds(ee.Geometry.BBox(*bbox)) - .map(lambda x: set_resampling_method(x, self.resampling_method),) - .select('DSM') - .mean() - ) + if self.resampling_method is not None: + alos_dsm_ic = ee.ImageCollection( + alos_dsm + .filterBounds(ee.Geometry.BBox(*bbox)) + .map(lambda x: set_resampling_method(x, self.resampling_method), ) + .select('DSM') + .mean() + ) + else: + alos_dsm_ic = ee.ImageCollection( + alos_dsm + .filterBounds(ee.Geometry.BBox(*bbox)) + .select('DSM') + .mean() + ) data = get_image_collection( alos_dsm_ic, diff --git a/city_metrix/layers/layer.py b/city_metrix/layers/layer.py index d30deeb..336b3ee 100644 --- a/city_metrix/layers/layer.py +++ b/city_metrix/layers/layer.py @@ -323,17 +323,14 @@ def get_stats_funcs(stats_func): return [stats_func] -def set_resampling_method(dataset, resampling_method): - valid_raster_resampling_methods = ['bilinear', 'bicubic', 'default'] +def set_resampling_method(image: ee.Image, resampling_method: str): + valid_raster_resampling_methods = ['bilinear', 'bicubic'] if resampling_method not in valid_raster_resampling_methods: raise ValueError(f"Invalid resampling method ('{resampling_method}'). " f"Valid methods: {valid_raster_resampling_methods}") - if resampling_method == 'default': - data = dataset - else: - data = dataset.resample(resampling_method) + data = image.resample(resampling_method) return data diff --git a/city_metrix/layers/nasa_dem.py b/city_metrix/layers/nasa_dem.py index baf66af..bcdd48a 100644 --- a/city_metrix/layers/nasa_dem.py +++ b/city_metrix/layers/nasa_dem.py @@ -7,7 +7,7 @@ class NasaDEM(Layer): """ Attributes: spatial_resolution: raster resolution in meters (see https://github.com/stac-extensions/raster) - resampling_method: interpolation method used by Google Earth Engine. NasaDEM default is 'bilinear'. All options are: ('bilinear', 'bicubic', 'default'). + resampling_method: interpolation method used by Google Earth Engine. NasaDEM default is 'bilinear'. All options are: ('bilinear', 'bicubic', None). """ def __init__(self, spatial_resolution=30, resampling_method='bilinear', **kwargs): @@ -18,12 +18,19 @@ def __init__(self, spatial_resolution=30, resampling_method='bilinear', **kwargs def get_data(self, bbox): nasa_dem = ee.Image("NASA/NASADEM_HGT/001") - nasa_dem_elev = (ee.ImageCollection(nasa_dem) - .filterBounds(ee.Geometry.BBox(*bbox)) - .map(lambda x: set_resampling_method(x, self.resampling_method),) - .select('elevation') - .mean() - ) + if self.resampling_method is not None: + nasa_dem_elev = (ee.ImageCollection(nasa_dem) + .filterBounds(ee.Geometry.BBox(*bbox)) + .map(lambda x: set_resampling_method(x, self.resampling_method), ) + .select('elevation') + .mean() + ) + else: + nasa_dem_elev = (ee.ImageCollection(nasa_dem) + .filterBounds(ee.Geometry.BBox(*bbox)) + .select('elevation') + .mean() + ) nasa_dem_elev_ic = ee.ImageCollection(nasa_dem_elev) data = get_image_collection( diff --git a/tests/resources/layer_dumps/conftest.py b/tests/resources/layer_dumps/conftest.py index 07faa75..9a5dd9a 100644 --- a/tests/resources/layer_dumps/conftest.py +++ b/tests/resources/layer_dumps/conftest.py @@ -11,7 +11,7 @@ # RUN_DUMPS is the master control for whether the writes and tests are executed # Setting RUN_DUMPS to True turns on code execution. # Values should normally be set to False in order to avoid unnecessary execution. -RUN_DUMPS = True +RUN_DUMPS = False # Multiplier applied to the default spatial_resolution of the layer # Use value of 1 for default resolution. diff --git a/tests/test_layer_metrics.py b/tests/test_layer_metrics.py index 434b211..659af0c 100644 --- a/tests/test_layer_metrics.py +++ b/tests/test_layer_metrics.py @@ -47,11 +47,24 @@ def test_read_image_collection_scale(): pytest.approx(expected_y_size, rel=EE_IMAGE_DIMENSION_TOLERANCE) == actual_y_size ) -def test_albedo_metrics(): + +def test_albedo_metrics_default_resampling(): + # Default resampling_method is bilinear data = Albedo(spatial_resolution=10).get_data(BBOX) - # data = Albedo(spatial_resolution=10, resampling_method='default').get_data(BBOX) - # data = Albedo(spatial_resolution=10, resampling_method='bilinear').get_data(BBOX) - # data = Albedo(spatial_resolution=10, resampling_method='bicubic').get_data(BBOX) + + # Bounding values + expected_min_value = _convert_fraction_to_rounded_percent(0.03) + expected_max_value = _convert_fraction_to_rounded_percent(0.32) + actual_min_value = _convert_fraction_to_rounded_percent(data.values.min()) + actual_max_value = _convert_fraction_to_rounded_percent(data.values.max()) + + # Value range + assert expected_min_value == actual_min_value + assert expected_max_value == actual_max_value + + +def test_albedo_metrics_no_resampling(): + data = Albedo(spatial_resolution=10, resampling_method= None).get_data(BBOX) # Bounding values expected_min_value = _convert_fraction_to_rounded_percent(0.03) @@ -65,7 +78,7 @@ def test_albedo_metrics(): def test_alos_dsm_metrics(): - data = AlosDSM().get_data(BBOX) + data = AlosDSM(resampling_method= None).get_data(BBOX) # Bounding values expected_min_value = 16