From 91ef2834171c3c86bc779accac444fc22f56c525 Mon Sep 17 00:00:00 2001 From: ValentinaHutter Date: Tue, 26 Nov 2024 13:50:24 +0100 Subject: [PATCH] fix resample cube spatial, not crop data --- .../process_implementations/cubes/resample.py | 112 ++++++++---------- openeo_processes_dask/specs/openeo-processes | 2 +- tests/test_resample.py | 5 +- 3 files changed, 54 insertions(+), 65 deletions(-) diff --git a/openeo_processes_dask/process_implementations/cubes/resample.py b/openeo_processes_dask/process_implementations/cubes/resample.py index a9d80b0..0b9e3c4 100644 --- a/openeo_processes_dask/process_implementations/cubes/resample.py +++ b/openeo_processes_dask/process_implementations/cubes/resample.py @@ -43,6 +43,35 @@ def resample_spatial( ): """Resamples the spatial dimensions (x,y) of the data cube to a specified resolution and/or warps the data cube to the target projection. At least resolution or projection must be specified.""" + if ( + data.openeo.y_dim is None + or data.openeo.x_dim is None + ): + raise DimensionMissing( + f"Spatial dimension missing for dataset: {data} " + ) + + methods_list = [ + "near", + "bilinear", + "cubic", + "cubicspline", + "lanczos", + "average", + "mode", + "max", + "min", + "med", + "q1", + "q3", + ] + + if method not in methods_list: + raise Exception( + f'Selected resampling method "{method}" is not available! Please select one of ' + f"[{', '.join(methods_list)}]" + ) + # Assert resampling method is correct. if method == "near": method = "nearest" @@ -53,18 +82,9 @@ def resample_spatial( f"[{', '.join(resample_methods_list)}]" ) - dims = list(data.dims) - - known_dims = [] - if len(data.openeo.band_dims) > 0: - known_dims.append(data.openeo.band_dims[0]) - if len(data.openeo.temporal_dims) > 0: - known_dims.append(data.openeo.temporal_dims[0]) - known_dims += [data.openeo.y_dim, data.openeo.x_dim] + dim_order = data.dims - other_dims = [dim for dim in dims if dim not in known_dims] - - data_cp = data.transpose(*other_dims, *known_dims) + data_cp = data.transpose(..., data.openeo.y_dim, data.openeo.x_dim) if projection is None: projection = data_cp.rio.crs @@ -89,6 +109,8 @@ def resample_spatial( if reprojected.openeo.y_dim != data.openeo.y_dim: reprojected = reprojected.rename({reprojected.openeo.y_dim: data.openeo.y_dim}) + reprojected = reprojected.transpose(*dim_order) + reprojected.attrs["crs"] = data_cp.rio.crs return reprojected @@ -97,67 +119,35 @@ def resample_spatial( def resample_cube_spatial( data: RasterCube, target: RasterCube, method="near", options=None ) -> RasterCube: - methods_list = [ - "near", - "bilinear", - "cubic", - "cubicspline", - "lanczos", - "average", - "mode", - "max", - "min", - "med", - "q1", - "q3", - ] if ( - data.openeo.y_dim is None - or data.openeo.x_dim is None - or target.openeo.y_dim is None + target.openeo.y_dim is None or target.openeo.x_dim is None ): raise DimensionMissing( - f"Spatial dimension missing from data or target. Available dimensions for data: {data.dims} for target: {target.dims}" + f"Spatial dimension missing for target dataset: {target} " ) - # ODC reproject requires y to be before x - required_dim_order = (..., data.openeo.y_dim, data.openeo.x_dim) - - data_reordered = data.transpose(*required_dim_order, missing_dims="ignore") - target_reordered = target.transpose(*required_dim_order, missing_dims="ignore") - - if method == "near": - method = "nearest" - - elif method not in methods_list: - raise Exception( - f'Selected resampling method "{method}" is not available! Please select one of ' - f"[{', '.join(methods_list)}]" + target_resolution, target_crs = None, None + if hasattr(target, 'rio'): + if hasattr(target.rio, 'resolution'): + if type(target.rio.resolution()) in [tuple, list]: + target_resolution = target.rio.resolution()[0] + else: + target_resolution = target.rio.resolution() + if hasattr(target.rio, 'crs'): + target_crs = target.rio.crs + if not target_crs: + raise OpenEOException( + f"Projection not found in target dataset: {target} " ) - - resampled_data = data_reordered.odc.reproject( - target_reordered.odc.geobox, resampling=method - ) - - resampled_data.rio.write_crs(target_reordered.rio.crs, inplace=True) - - try: - # odc.reproject renames the coordinates according to the geobox, this undoes that. - resampled_data = resampled_data.rename( - {"longitude": data.openeo.x_dim, "latitude": data.openeo.y_dim} + if not target_resolution: + raise OpenEOException( + f"Resolution not found in target dataset: {target} " ) - except ValueError: - pass - # Order axes back to how they were before - resampled_data = resampled_data.transpose(*data.dims) + resampled_data = resample_spatial(data = data, projection=target_crs, resolution=target_resolution, method=method) - # Ensure that attrs except crs are copied over - for k, v in data.attrs.items(): - if k.lower() != "crs": - resampled_data.attrs[k] = v return resampled_data diff --git a/openeo_processes_dask/specs/openeo-processes b/openeo_processes_dask/specs/openeo-processes index fcc9e54..45f52ab 160000 --- a/openeo_processes_dask/specs/openeo-processes +++ b/openeo_processes_dask/specs/openeo-processes @@ -1 +1 @@ -Subproject commit fcc9e54d2e7be11a9cd7c5e155db2b743c1f9635 +Subproject commit 45f52ab1cc7ce00e6afbe78a6a9827c51f086a42 diff --git a/tests/test_resample.py b/tests/test_resample.py index 77049cb..ebd6de3 100644 --- a/tests/test_resample.py +++ b/tests/test_resample.py @@ -166,10 +166,9 @@ def test_resample_cube_spatial_small( resampled_cube = resample_spatial( data=input_cube, projection=output_crs, resolution=output_res ) - print("RESAMPLE: ", output_crs, output_res, resampled_cube.shape) output_cube = resample_cube_spatial( - data=input_cube, target=resampled_cube[:25,:25,:15,:3], method="average" + data=input_cube, target=resampled_cube[10:60, 20:150,:,:], method="average" ) general_output_checks( @@ -180,7 +179,7 @@ def test_resample_cube_spatial_small( verify_crs=False, ) - assert (list(output_cube.shape) < list(resampled_cube.shape)) + assert (list(output_cube.shape) == list(resampled_cube.shape)) @pytest.mark.parametrize("size", [(6, 5, 30, 4)])