diff --git a/city_metrix/layers/layer.py b/city_metrix/layers/layer.py index 1c40664..01ad6e4 100644 --- a/city_metrix/layers/layer.py +++ b/city_metrix/layers/layer.py @@ -37,15 +37,6 @@ def get_data(self, bbox: Tuple[float]) -> Union[xr.DataArray, gpd.GeoDataFrame]: """ ... - @abstractmethod - def prepare_for_map_rendering(self, data, **kwargs) -> Union[xr.DataArray, gpd.GeoDataFrame]: - """ - Applies the standard post-processing adjustment used for rendering of the layer - :param are specific to the layer - :return: A rioxarray-format DataArray or a GeoPandas DataFrame - """ - return data - def mask(self, *layers): """ Apply layers as masks @@ -83,7 +74,6 @@ def write(self, bbox, output_path, tile_degrees=None, **kwargs): file_names = [] for tile in tiles["geometry"]: data = self.aggregate.get_data(tile.bounds) - data = self.prepare_for_map_rendering(data, **kwargs) file_name = f"{output_path}/{uuid4()}.tif" file_names.append(file_name) @@ -91,7 +81,6 @@ def write(self, bbox, output_path, tile_degrees=None, **kwargs): write_layer(file_name, data) else: data = self.aggregate.get_data(bbox) - data = self.prepare_for_map_rendering(data, **kwargs) write_layer(output_path, data) diff --git a/city_metrix/layers/ndvi_sentinel2_gee.py b/city_metrix/layers/ndvi_sentinel2_gee.py index 8458cb2..c5b21b9 100644 --- a/city_metrix/layers/ndvi_sentinel2_gee.py +++ b/city_metrix/layers/ndvi_sentinel2_gee.py @@ -1,5 +1,4 @@ import ee -from tools.xarray_tools import convert_ratio_to_percentage from .layer import Layer, get_image_collection class NdviSentinel2(Layer): @@ -45,21 +44,3 @@ def calculate_ndvi(image): xdata = ndvi_data.to_dataarray() return xdata - - def prepare_for_map_rendering(self, data, ndvi_threshold=0.4, convert_to_percentage=True, **kwargs): - """ - Applies the standard post-processing adjustment used for rendering of NDVI including masking - to a threshold and conversion to percentage values. - :param ndvi_threshold: (float) minimum threshold for keeping values - :param convert_to_percentage: (bool) controls whether NDVI values are converted to a percentage - :return: A rioxarray-format DataArray - """ - # Remove values less than the specified threshold - if ndvi_threshold is not None: - data = data.where(data >= ndvi_threshold) - - # Convert to percentage in byte data_type - if convert_to_percentage is True: - data = convert_ratio_to_percentage(data) - - return data diff --git a/tests/resources/layer_dumps_for_br_lauro_de_freitas/layers_for_br_lauro_de_freitas.qgz b/tests/resources/layer_dumps_for_br_lauro_de_freitas/layers_for_br_lauro_de_freitas.qgz index c0e237d..759515e 100644 Binary files a/tests/resources/layer_dumps_for_br_lauro_de_freitas/layers_for_br_lauro_de_freitas.qgz and b/tests/resources/layer_dumps_for_br_lauro_de_freitas/layers_for_br_lauro_de_freitas.qgz differ diff --git a/tests/resources/layer_dumps_for_br_lauro_de_freitas/test_write_layers_to_geotiff.py b/tests/resources/layer_dumps_for_br_lauro_de_freitas/test_write_layers_to_qgis_files.py similarity index 97% rename from tests/resources/layer_dumps_for_br_lauro_de_freitas/test_write_layers_to_geotiff.py rename to tests/resources/layer_dumps_for_br_lauro_de_freitas/test_write_layers_to_qgis_files.py index c7072f5..5e0efb9 100644 --- a/tests/resources/layer_dumps_for_br_lauro_de_freitas/test_write_layers_to_geotiff.py +++ b/tests/resources/layer_dumps_for_br_lauro_de_freitas/test_write_layers_to_qgis_files.py @@ -1,8 +1,6 @@ # This code is mostly intended for manual execution # Execution configuration is specified in the conftest file - import pytest -import os from city_metrix.layers import ( Albedo, @@ -23,7 +21,7 @@ TreeCanopyHeight, TreeCover, UrbanLandUse, - WorldPop + WorldPop, Layer ) from .conftest import RUN_DUMPS, prep_output_path, verify_file_is_populated @@ -86,8 +84,7 @@ def test_write_natural_areas(target_folder, bbox_info): @pytest.mark.skipif(RUN_DUMPS == False, reason='Skipping since RUN_DUMPS set to False') def test_write_ndvi_sentinel2_gee(target_folder, bbox_info): file_path = prep_output_path(target_folder, 'ndvi_sentinel2_gee.tif') - (NdviSentinel2(year=2023) - .write(bbox_info.bounds, file_path, tile_degrees=None, ndvi_threshold=0.4, convert_to_percentage=True)) + NdviSentinel2(year=2023).write(bbox_info.bounds, file_path, tile_degrees=None) assert verify_file_is_populated(file_path) @pytest.mark.skipif(RUN_DUMPS == False, reason='Skipping since RUN_DUMPS set to False') diff --git a/tests/test_layer_dimensions.py b/tests/test_layer_dimensions.py new file mode 100644 index 0000000..84fa669 --- /dev/null +++ b/tests/test_layer_dimensions.py @@ -0,0 +1,21 @@ +from city_metrix.layers import NdviSentinel2 +from tests.resources.bbox_constants import BBOX_BRA_LAURO_DE_FREITAS_1 +from tests.tools import post_process_layer + +COUNTRY_CODE_FOR_BBOX = 'BRA' +BBOX = BBOX_BRA_LAURO_DE_FREITAS_1 + +def test_ndvi_dimensions(): + data = NdviSentinel2(year=2023).get_data(BBOX) + data_for_map = post_process_layer(data, value_threshold=0.4, convert_to_percentage=True) + + expected_size = 37213 + actual_size = data_for_map.size + expected_min = 0 + actual_min = data_for_map.values.min() + expected_max = 85 + actual_max = data_for_map.values.max() + + assert actual_size == expected_size + assert actual_min == expected_min + assert actual_max == expected_max diff --git a/tests/tools.py b/tests/tools.py new file mode 100644 index 0000000..99425df --- /dev/null +++ b/tests/tools.py @@ -0,0 +1,35 @@ +import numpy as np + +def post_process_layer(data, value_threshold=0.4, convert_to_percentage=True): + """ + Applies the standard post-processing adjustment used for rendering of NDVI including masking + to a threshold and conversion to percentage values. + :param value_threshold: (float) minimum threshold for keeping values + :param convert_to_percentage: (bool) controls whether NDVI values are converted to a percentage + :return: A rioxarray-format DataArray + """ + # Remove values less than the specified threshold + if value_threshold is not None: + data = data.where(data >= value_threshold) + + # Convert to percentage in byte data_type + if convert_to_percentage is True: + data = convert_ratio_to_percentage(data) + + return data + +def convert_ratio_to_percentage(data): + """ + Converts xarray variable from a ratio to a percentage + :param data: (xarray) xarray to be converted + :return: A rioxarray-format DataArray + """ + + # convert to percentage and to bytes for efficient storage + values_as_percent = np.round(data * 100).astype(np.uint8) + + # reset CRS + source_crs = data.rio.crs + values_as_percent.rio.write_crs(source_crs, inplace=True) + + return values_as_percent diff --git a/tools/xarray_tools.py b/tools/xarray_tools.py deleted file mode 100644 index 2ef773d..0000000 --- a/tools/xarray_tools.py +++ /dev/null @@ -1,18 +0,0 @@ -import numpy as np -from rasterio import uint8 - -def convert_ratio_to_percentage(data): - """ - Converts xarray variable from a ratio to a percentage - :param data: (xarray) xarray to be converted - :return: A rioxarray-format DataArray - """ - - # convert to percentage and to bytes for efficient storage - values_as_percent = np.round(data * 100).astype(uint8) - - # reset CRS - source_crs = data.rio.crs - values_as_percent.rio.write_crs(source_crs, inplace=True) - - return values_as_percent