From 5e60893d137f5d833a5423175b86bdcb7d669e8d Mon Sep 17 00:00:00 2001 From: Tim Treis Date: Mon, 23 Mar 2026 23:30:34 +0100 Subject: [PATCH 1/2] Fix `scale` parameter for polygons with datashader (#473) The datashader rendering path only applied the `scale` parameter to circle geometries (Points with radius). Polygon and MultiPolygon geometries were passed through unscaled. This adds scaling via `shapely.affinity.scale()` around each geometry's centroid, matching the existing matplotlib path behavior. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/spatialdata_plot/pl/render.py | 9 +++++++++ tests/pl/test_render_shapes.py | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/src/spatialdata_plot/pl/render.py b/src/spatialdata_plot/pl/render.py index 488db5c9..5cd71168 100644 --- a/src/spatialdata_plot/pl/render.py +++ b/src/spatialdata_plot/pl/render.py @@ -394,6 +394,15 @@ def _render_shapes( scale = radius_numeric * render_params.scale shapes.loc[is_point, "geometry"] = _geometry[is_point].buffer(scale.to_numpy()) + # Handle polygon/multipolygon scaling + is_polygon = _geometry.type.isin(["Polygon", "MultiPolygon"]) + if is_polygon.any() and render_params.scale != 1.0: + from shapely import affinity + + shapes.loc[is_polygon, "geometry"] = _geometry[is_polygon].apply( + lambda geom: affinity.scale(geom, xfact=render_params.scale, yfact=render_params.scale) + ) + # apply transformations to the individual points tm = trans.get_matrix() transformed_geometry = shapes["geometry"].transform( diff --git a/tests/pl/test_render_shapes.py b/tests/pl/test_render_shapes.py index dece73b3..dd165ece 100644 --- a/tests/pl/test_render_shapes.py +++ b/tests/pl/test_render_shapes.py @@ -242,6 +242,10 @@ def test_plot_can_color_from_geodataframe(self, sdata_blobs: SpatialData): def test_plot_can_scale_shapes(self, sdata_blobs: SpatialData): sdata_blobs.pl.render_shapes(element="blobs_circles", scale=0.5).pl.show() + def test_plot_can_scale_polygons_datashader(self, sdata_blobs: SpatialData): + # Regression test for #473: scale parameter had no effect on polygons with datashader + sdata_blobs.pl.render_shapes(element="blobs_polygons", method="datashader", scale=2.0).pl.show() + def test_plot_can_filter_with_groups(self, sdata_blobs: SpatialData): _, axs = plt.subplots(nrows=1, ncols=2, layout="tight") From b199ad01a51493998cea07d684e972bb8f3dea48 Mon Sep 17 00:00:00 2001 From: Tim Treis Date: Mon, 23 Mar 2026 23:37:09 +0100 Subject: [PATCH 2/2] Add baseline image for polygon datashader scale test Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Shapes_can_scale_polygons_datashader.png | Bin 0 -> 21864 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/_images/Shapes_can_scale_polygons_datashader.png diff --git a/tests/_images/Shapes_can_scale_polygons_datashader.png b/tests/_images/Shapes_can_scale_polygons_datashader.png new file mode 100644 index 0000000000000000000000000000000000000000..a3da4a0e75c0417bab009f71ef721db542164562 GIT binary patch literal 21864 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

(}x<5^f;ctTSRSFW9 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

r*}88 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 literal 0 HcmV?d00001