Skip to content

Commit d288629

Browse files
authored
Fixes SpatialResizeTask that switched width/height when using resolution (#544)
* Fixes SpatialResizeTask bug that switched width/height when using resolution * Updates docstring of SpatialResizeTask with MR suggestions. * Updates docstring alignment for auto-generated docs. * Updated docstrings with multi-line bulleted list formatting.
1 parent 99b6cf3 commit d288629

File tree

2 files changed

+42
-26
lines changed

2 files changed

+42
-26
lines changed

features/eolearn/features/feature_manipulation.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import datetime as dt
1717
import logging
1818
from functools import partial
19-
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union, cast
19+
from typing import Any, Callable, Dict, Iterable, List, Optional, Union, cast
2020

2121
import numpy as np
2222
from geopandas import GeoDataFrame
@@ -252,38 +252,46 @@ class SpatialResizeTask(EOTask):
252252
def __init__(
253253
self,
254254
*,
255-
resize_parameters: Tuple[ResizeParam, Tuple[float, float]],
255+
resize_type: ResizeParam,
256+
height_param: float,
257+
width_param: float,
256258
features: FeaturesSpecification = ...,
257259
resize_method: ResizeMethod = ResizeMethod.LINEAR,
258260
resize_library: ResizeLib = ResizeLib.PIL,
259261
):
260262
"""
261263
:param features: Which features to resize. Supports new names for features.
262-
:param resize_parameters: Instructions on how to perform the resizing process. For example use:
263-
`['new_size', [500, 1000]]` to resize the data to size (500, 1000),
264-
`['resolution', [10, 20]]` for changing resolution from 10 to 20,
265-
`['scale_factors', [3, 3]]` to make the data three times larger.
264+
:param resize_type: Determines type of resizing process and how `width_param` and `height_param` are used.
265+
Options:
266+
* `new_size`: Resizes data to size (width_param, height_param)
267+
* | `resolution`: Resizes the data to have width_param, height_param resolution over width/height axis.
268+
| Uses EOPatch bbox to compute.
269+
* | `scale_factor` Resizes the data by scaling the width and height by a factor set by
270+
| width_param and height_param respectively.
271+
:param height_param: Parameter to be applied to the height in combination with the resize_type
272+
:param width_param: Parameter to be applied to the width in combination with the resize_type
266273
:param resize_method: Interpolation method used for resizing.
267274
:param resize_library: Which Python library to use for resizing. Default is PIL, as it supports all dtypes and
268275
features anti-aliasing. For cases where execution speed is crucial one can use CV2.
269276
"""
270277
self.features = features
271-
self.parameter_kind = ResizeParam(resize_parameters[0])
272-
self.parameter_values = resize_parameters[1]
278+
self.resize_type = ResizeParam(resize_type)
279+
self.height_param = height_param
280+
self.width_param = width_param
273281

274282
self.resize_function = partial(
275283
spatially_resize_image, resize_method=resize_method, resize_library=resize_library
276284
)
277285

278286
def execute(self, eopatch: EOPatch) -> EOPatch:
279287
resize_fun_kwargs: Dict[str, Any]
280-
if self.parameter_kind == ResizeParam.RESOLUTION:
288+
if self.resize_type == ResizeParam.RESOLUTION:
281289
if not eopatch.bbox:
282290
raise ValueError("Resolution-specified resizing can only be done on EOPatches with a defined BBox.")
283-
new_size = bbox_to_dimensions(eopatch.bbox, self.parameter_values)
284-
resize_fun_kwargs = {ResizeParam.NEW_SIZE.value: new_size}
291+
new_width, new_height = bbox_to_dimensions(eopatch.bbox, (self.width_param, self.height_param))
292+
resize_fun_kwargs = {ResizeParam.NEW_SIZE.value: (new_height, new_width)}
285293
else:
286-
resize_fun_kwargs = {self.parameter_kind.value: self.parameter_values}
294+
resize_fun_kwargs = {self.resize_type.value: (self.height_param, self.width_param)}
287295

288296
for ftype, fname, new_name in self.parse_renamed_features(self.features, eopatch=eopatch):
289297
if ftype.is_spatial() and ftype.is_raster():

features/eolearn/tests/test_feature_manipulation.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -231,29 +231,37 @@ def test_linear_function_task():
231231

232232

233233
@pytest.mark.parametrize(
234-
["resize_parameters", "features_call", "features_check", "outputs"],
234+
["resize_type", "height_param", "width_param", "features_call", "features_check", "outputs"],
235235
[
236-
((ResizeParam.NEW_SIZE, (50, 70)), ("data", "CLP"), ("data", "CLP"), (68, 50, 70, 1)),
237-
((ResizeParam.NEW_SIZE, (50, 70)), ("data", "CLP"), ("mask", "CLM"), (68, 101, 100, 1)),
238-
((ResizeParam.NEW_SIZE, (50, 70)), ..., ("data", "CLP"), (68, 50, 70, 1)),
239-
((ResizeParam.NEW_SIZE, (50, 70)), ..., ("mask", "CLM"), (68, 50, 70, 1)),
240-
((ResizeParam.NEW_SIZE, (50, 70)), ("data", "CLP", "CLP_small"), ("data", "CLP_small"), (68, 50, 70, 1)),
241-
((ResizeParam.NEW_SIZE, (50, 70)), ("data", "CLP", "CLP_small"), ("data", "CLP"), (68, 101, 100, 1)),
242-
((ResizeParam.SCALE_FACTORS, (2, 2)), ("data", "CLP"), ("data", "CLP"), (68, 202, 200, 1)),
243-
((ResizeParam.SCALE_FACTORS, (0.1, 0.1)), ("data", "CLP"), ("data", "CLP"), (68, 10, 10, 1)),
244-
((ResizeParam.RESOLUTION, (5, 5)), ("data", "CLP"), ("data", "CLP"), (68, 200, 202, 1)),
245-
((ResizeParam.RESOLUTION, (20, 20)), ("data", "CLP"), ("data", "CLP"), (68, 50, 50, 1)),
236+
(ResizeParam.NEW_SIZE, 50, 70, ("data", "CLP"), ("data", "CLP"), (68, 50, 70, 1)),
237+
(ResizeParam.NEW_SIZE, 50, 70, ("data", "CLP"), ("mask", "CLM"), (68, 101, 100, 1)),
238+
(ResizeParam.NEW_SIZE, 50, 70, ..., ("data", "CLP"), (68, 50, 70, 1)),
239+
(ResizeParam.NEW_SIZE, 50, 70, ..., ("mask", "CLM"), (68, 50, 70, 1)),
240+
(ResizeParam.NEW_SIZE, 50, 70, ("data", "CLP", "CLP_small"), ("data", "CLP_small"), (68, 50, 70, 1)),
241+
(ResizeParam.NEW_SIZE, 50, 70, ("data", "CLP", "CLP_small"), ("data", "CLP"), (68, 101, 100, 1)),
242+
(ResizeParam.SCALE_FACTORS, 2, 2, ("data", "CLP"), ("data", "CLP"), (68, 202, 200, 1)),
243+
(ResizeParam.SCALE_FACTORS, 0.5, 2, ("data", "CLP"), ("data", "CLP"), (68, 50, 200, 1)),
244+
(ResizeParam.SCALE_FACTORS, 0.1, 0.1, ("data", "CLP"), ("data", "CLP"), (68, 10, 10, 1)),
245+
(ResizeParam.RESOLUTION, 5, 5, ("data", "CLP"), ("data", "CLP"), (68, 202, 200, 1)),
246+
(ResizeParam.RESOLUTION, 20, 20, ("data", "CLP"), ("data", "CLP"), (68, 50, 50, 1)),
247+
(ResizeParam.RESOLUTION, 5, 20, ("data", "CLP"), ("data", "CLP"), (68, 202, 50, 1)),
246248
],
247249
)
248250
@pytest.mark.filterwarnings("ignore::RuntimeWarning")
249-
def test_spatial_resize_task(example_eopatch, resize_parameters, features_call, features_check, outputs):
251+
def test_spatial_resize_task(
252+
example_eopatch, resize_type, height_param, width_param, features_call, features_check, outputs
253+
):
250254
# Warnings occur due to lossy casting in the downsampling procedure
251255

252-
resize = SpatialResizeTask(resize_parameters=resize_parameters, features=features_call)
256+
resize = SpatialResizeTask(
257+
resize_type=resize_type, height_param=height_param, width_param=width_param, features=features_call
258+
)
253259
assert resize(example_eopatch)[features_check].shape == outputs
254260

255261

256262
def test_spatial_resize_task_exception(example_eopatch):
257263
with pytest.raises(ValueError):
258-
resize_wrong_param = SpatialResizeTask(features=("mask", "CLM"), resize_parameters=("blabla", (20, 20)))
264+
resize_wrong_param = SpatialResizeTask(
265+
features=("mask", "CLM"), resize_type="blabla", height_param=20, width_param=20
266+
)
259267
resize_wrong_param(example_eopatch)

0 commit comments

Comments
 (0)