From 6561ceb3900e89ee95b53358d9e8bab23692a11a Mon Sep 17 00:00:00 2001 From: Marvin Albert Date: Tue, 1 Jul 2025 15:12:09 +0200 Subject: [PATCH 1/3] Add test showing that DataTree transform fails when transformed scales have zero shape --- tests/core/operations/test_transform.py | 29 ++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tests/core/operations/test_transform.py b/tests/core/operations/test_transform.py index e8031820e..f9b4ee900 100644 --- a/tests/core/operations/test_transform.py +++ b/tests/core/operations/test_transform.py @@ -11,7 +11,7 @@ from spatialdata._core.data_extent import are_extents_equal, get_extent from spatialdata._core.spatialdata import SpatialData from spatialdata._utils import unpad_raster -from spatialdata.models import PointsModel, ShapesModel, get_axes_names +from spatialdata.models import Image2DModel, PointsModel, ShapesModel, get_axes_names from spatialdata.transformations.operations import ( align_elements_using_landmarks, get_transformation, @@ -229,6 +229,33 @@ def test_transform_shapes(shapes: SpatialData): assert geom_almost_equals(p0["geometry"], p1["geometry"]) +def test_transform_multiscale_image(): + """ + Test the case in which the highest scales of the result of a + transformed multi-scale image would be zero shape. + """ + + test_image = Image2DModel.parse( + np.ones((1, 10, 10)), + dims=("c", "y", "x"), + scale_factors=[2, 4], + transformations={ + "cs1": Scale([0.5] * 2, axes=["y", "x"]), + "cs2": Scale([0.01] * 2, axes=["y", "x"]), + }, + ) + + # check that the transform doesn't raise an error and that it + # discards the lowest resolution level + test_image_t = transform(test_image, to_coordinate_system="cs1") + assert len(test_image.items()) != len(test_image_t.items()) + + # check that a ValueError is raised when no resolution level + # is left after the transformation + with pytest.raises(ValueError, match="The transformation leads to zero shaped data."): + transform(test_image, to_coordinate_system="cs2") + + def test_map_coordinate_systems_single_path(full_sdata: SpatialData): scale = Scale([2], axes=("x",)) translation = Translation([100], axes=("x",)) From 98ec1008c23c9c3640591313be31e443baa42f50 Mon Sep 17 00:00:00 2001 From: Marvin Albert Date: Tue, 1 Jul 2025 15:33:33 +0200 Subject: [PATCH 2/3] Handle resulting scales of shape zero in DataTree transform and make associated test pass --- src/spatialdata/_core/operations/transform.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/spatialdata/_core/operations/transform.py b/src/spatialdata/_core/operations/transform.py index d74bbf2ff..fa3b1446a 100644 --- a/src/spatialdata/_core/operations/transform.py +++ b/src/spatialdata/_core/operations/transform.py @@ -388,6 +388,16 @@ def _( transformed_dask, raster_translation_single_scale = _transform_raster( data=xdata.data, axes=xdata.dims, transformation=composed, **kwargs ) + + # if a scale in the transformed data has zero shape, we skip it + if not np.min(transformed_dask.shape): + if k == "scale0": + raise ValueError( + "The transformation leads to zero shaped data even at the highest resolution level. " + "Check the scaling component of the transformation." + ) + continue + if raster_translation is None: raster_translation = raster_translation_single_scale # we set a dummy empty dict for the transformation that will be replaced with the correct transformation for From ba9fe1631341e496a7df01213bb09ab1464ef8b4 Mon Sep 17 00:00:00 2001 From: Marvin Albert Date: Tue, 1 Jul 2025 15:53:44 +0200 Subject: [PATCH 3/3] Make test name more specific --- tests/core/operations/test_transform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/operations/test_transform.py b/tests/core/operations/test_transform.py index f9b4ee900..b3e0cb7e3 100644 --- a/tests/core/operations/test_transform.py +++ b/tests/core/operations/test_transform.py @@ -229,7 +229,7 @@ def test_transform_shapes(shapes: SpatialData): assert geom_almost_equals(p0["geometry"], p1["geometry"]) -def test_transform_multiscale_image(): +def test_transform_datatree_scale_handling(): """ Test the case in which the highest scales of the result of a transformed multi-scale image would be zero shape.