diff --git a/tests/_images/Labels_can_render_transformed_labels_with_outline.png b/tests/_images/Labels_can_render_transformed_labels_with_outline.png new file mode 100644 index 00000000..0ab1796d Binary files /dev/null and b/tests/_images/Labels_can_render_transformed_labels_with_outline.png differ diff --git a/tests/pl/test_render_labels.py b/tests/pl/test_render_labels.py index 40353ab1..24ad341f 100644 --- a/tests/pl/test_render_labels.py +++ b/tests/pl/test_render_labels.py @@ -9,6 +9,7 @@ from spatial_image import to_spatial_image from spatialdata import SpatialData, deepcopy, get_element_instances from spatialdata.models import TableModel +from spatialdata.transformations import Affine, Scale, Sequence, Translation, set_transformation import spatialdata_plot # noqa: F401 from tests.conftest import DPI, PlotTester, PlotTesterMeta @@ -194,3 +195,52 @@ def test_plot_subset_categorical_label_maintains_order_when_palette_overwrite(se sdata_blobs.pl.render_labels( "blobs_labels", color="which_max", groups=["channel_0_sum"], palette="red" ).pl.show(ax=axs[1]) + + def test_plot_can_render_transformed_labels_with_outline(self, sdata_blobs: SpatialData): + # Blobs have by default an identity transform. Replace it by a rotated, scaled transform: + angle = np.deg2rad(15) + axes = ("y", "x") + rotation = Affine( + matrix=np.array( + [ + [np.cos(angle), -np.sin(angle), 0], + [np.sin(angle), np.cos(angle), 0], + [0, 0, 1], + ] + ), + input_axes=axes, + output_axes=axes, + ) + translation = Translation([10, 10], axes=axes) + scale = Scale([0.65, 0.65], axes=axes) + transform = Sequence([translation, rotation, scale]) + set_transformation(sdata_blobs["blobs_labels"], transform) + + # Render without fill, but with outline. + sdata_blobs.pl.render_labels( + "blobs_labels", + fill_alpha=0.0, + outline=True, + outline_alpha=1.0, + ).pl.show() + + def _make_tablemodel_with_categorical_labels(self, sdata_blobs, label): + n_obs = max(_get_unique_label_values_as_index(sdata_blobs[label])) + adata = AnnData( + RNG.normal(size=(n_obs, 10)), + obs=pd.DataFrame(RNG.normal(size=(n_obs, 3)), columns=["a", "b", "c"]), + ) + adata.obs["instance_id"] = np.arange(adata.n_obs) + adata.obs["category"] = RNG.choice(["a", "b", "c"], size=adata.n_obs) + adata.obs["category"][:3] = ["a", "b", "c"] + adata.obs["instance_id"] = list(range(adata.n_obs)) + adata.obs["region"] = label + table = TableModel.parse( + adata=adata, + region_key="region", + instance_key="instance_id", + region=label, + ) + sdata_blobs["other_table"] = table + sdata_blobs["other_table"].obs["category"] = sdata_blobs["other_table"].obs["category"].astype("category") + sdata_blobs.pl.render_labels(label, color="category").pl.show()