@@ -1067,6 +1067,51 @@ def test_plot_can_handle_non_numeric_radius_values(sdata_blobs: SpatialData):
10671067 sdata_blobs .pl .render_shapes (element = "blobs_circles" , color = "red" ).pl .show ()
10681068
10691069
1070+ def test_groups_filtering_preserves_transformation (sdata_blobs : SpatialData ):
1071+ """Regression test for #420: groups filtering must not strip coordinate-system metadata.
1072+
1073+ Simulates the exact sequence that ``_render_shapes`` performs —
1074+ ``filter_by_coordinate_system`` ➜ groups boolean-index ➜ ``reset_index`` ➜
1075+ re-assign to ``sdata_filt`` — then asserts that ``_prepare_transformation``
1076+ can still retrieve the non-global transformation with the correct scale.
1077+ """
1078+ from spatialdata .transformations import set_transformation
1079+
1080+ from spatialdata_plot .pl .utils import _prepare_transformation
1081+
1082+ scale_factor = 2.5
1083+ cs = "not_global"
1084+ set_transformation (
1085+ sdata_blobs ["blobs_polygons" ],
1086+ transformation = {cs : Scale ([scale_factor , scale_factor ], axes = ("x" , "y" ))},
1087+ set_all = True ,
1088+ )
1089+ sdata_blobs .shapes ["blobs_polygons" ]["cluster" ] = pd .Categorical (["c1" , "c2" , "c1" , "c2" , "c1" ])
1090+
1091+ sdata_filt = sdata_blobs .filter_by_coordinate_system (coordinate_system = cs , filter_tables = False )
1092+
1093+ # --- replicate the groups-filtering path from _render_shapes (lines 382-389) ---
1094+ shapes = sdata_filt .shapes ["blobs_polygons" ]
1095+ keep = shapes ["cluster" ] == "c1"
1096+ shapes = shapes [keep ].reset_index (drop = True )
1097+ sdata_filt ["blobs_polygons" ] = shapes
1098+ # also replicate the GeoDataFrame re-wrap that follows (line 432), which strips .attrs
1099+ shapes = gpd .GeoDataFrame (shapes , geometry = "geometry" )
1100+
1101+ # The sdata_filt element must still carry the correct transformation
1102+ # (this is where _render_shapes reads the transform after the fix).
1103+ trans , _ = _prepare_transformation (sdata_filt .shapes ["blobs_polygons" ], cs )
1104+ matrix = trans .get_matrix ()
1105+ np .testing .assert_allclose (matrix [0 , 0 ], scale_factor , err_msg = "x-scale lost after groups filtering" )
1106+ np .testing .assert_allclose (matrix [1 , 1 ], scale_factor , err_msg = "y-scale lost after groups filtering" )
1107+
1108+ # The GeoDataFrame re-wrap (which _render_shapes does right after) strips
1109+ # attrs — prove that reading the transform from *that* object would fail,
1110+ # demonstrating why early capture matters.
1111+ with pytest .raises ((KeyError , AssertionError )):
1112+ _prepare_transformation (shapes , cs )
1113+
1114+
10701115def test_plot_can_handle_mixed_numeric_and_color_data (sdata_blobs : SpatialData ):
10711116 """Test that mixed numeric and color-like data raises a clear error."""
10721117 sdata_blobs ["table" ].obs ["region" ] = pd .Categorical (["blobs_circles" ] * sdata_blobs ["table" ].n_obs )
0 commit comments