diff --git a/src/spatialdata_plot/pl/utils.py b/src/spatialdata_plot/pl/utils.py index 6a150f7f..574ca56b 100644 --- a/src/spatialdata_plot/pl/utils.py +++ b/src/spatialdata_plot/pl/utils.py @@ -1834,7 +1834,8 @@ def _validate_label_render_params( element_params[el]["table_name"] = None element_params[el]["color"] = None - if (color := param_dict["color"]) is not None: + color = param_dict["color"] + if color is not None: color, table_name = _validate_col_for_column_table(sdata, el, color, param_dict["table_name"], labels=True) element_params[el]["table_name"] = table_name element_params[el]["color"] = color @@ -1996,6 +1997,11 @@ def _validate_col_for_column_table( if table_name not in tables or ( col_for_color not in sdata[table_name].obs.columns and col_for_color not in sdata[table_name].var_names ): + warnings.warn( + f"Table '{table_name}' does not annotate element '{element_name}'.", + UserWarning, + stacklevel=2, + ) table_name = None col_for_color = None else: diff --git a/tests/pl/test_render_labels.py b/tests/pl/test_render_labels.py index 69c2da42..a1de6f76 100644 --- a/tests/pl/test_render_labels.py +++ b/tests/pl/test_render_labels.py @@ -299,3 +299,25 @@ def test_plot_can_handle_dropping_small_labels_after_rasterize_categorical(self, sdata_blobs = self._prepare_small_labels(sdata_blobs) sdata_blobs.pl.render_labels("blobs_labels_large", color="category", table_name="table").pl.show() + + +def test_warns_when_table_does_not_annotate_element(sdata_blobs: SpatialData): + # Work on an independent copy since we mutate tables + sdata_blobs_local = deepcopy(sdata_blobs) + + # Create a table that annotates a DIFFERENT element than the one we will render + other_table = sdata_blobs_local["table"].copy() + other_table.obs["region"] = "blobs_multiscale_labels" + other_table.uns["spatialdata_attrs"]["region"] = "blobs_multiscale_labels" + sdata_blobs_local["other_table"] = other_table + + # Rendering "blobs_labels" with a table that annotates "blobs_multiscale_labels" + # should raise a warning and fall back to using no table. + with pytest.warns(UserWarning, match="does not annotate element"): + ( + sdata_blobs_local.pl.render_labels( + "blobs_labels", + color="channel_0_sum", + table_name="other_table", + ).pl.show() + ) diff --git a/tests/pl/test_render_points.py b/tests/pl/test_render_points.py index aa9d8ff7..d60d0a9f 100644 --- a/tests/pl/test_render_points.py +++ b/tests/pl/test_render_points.py @@ -5,6 +5,7 @@ import matplotlib.pyplot as plt import numpy as np import pandas as pd +import pytest import scanpy as sc from anndata import AnnData from matplotlib.colors import Normalize @@ -350,3 +351,25 @@ def test_plot_can_annotate_points_with_table_layer(self, sdata_blobs: SpatialDat sdata_blobs["points_table"].layers["normalized"] = RNG.random((nrows, ncols)) sdata_blobs.pl.render_points("blobs_points", color="feature0", size=10, table_layer="normalized").pl.show() + + +def test_warns_when_table_does_not_annotate_element(sdata_blobs: SpatialData): + # Work on an independent copy since we mutate tables + sdata_blobs_local = deepcopy(sdata_blobs) + + # Create a table that annotates a DIFFERENT element than the one we will render + other_table = sdata_blobs_local["table"].copy() + other_table.obs["region"] = "blobs_labels" # Different from blobs_points + other_table.uns["spatialdata_attrs"]["region"] = "blobs_labels" + sdata_blobs_local["other_table"] = other_table + + # Rendering "blobs_points" with a table that annotates "blobs_labels" + # should raise a warning and fall back to using no table. + with pytest.warns(UserWarning, match="does not annotate element"): + ( + sdata_blobs_local.pl.render_points( + "blobs_points", + color="channel_0_sum", + table_name="other_table", + ).pl.show() + ) diff --git a/tests/pl/test_render_shapes.py b/tests/pl/test_render_shapes.py index 67bc70f9..b509492a 100644 --- a/tests/pl/test_render_shapes.py +++ b/tests/pl/test_render_shapes.py @@ -6,6 +6,7 @@ import matplotlib.pyplot as plt import numpy as np import pandas as pd +import pytest import scanpy as sc from anndata import AnnData from matplotlib.colors import Normalize @@ -564,3 +565,25 @@ def test_plot_can_annotate_shapes_with_table_layer(self, sdata_blobs: SpatialDat sdata_blobs["circle_table"].layers["normalized"] = RNG.random((nrows, ncols)) sdata_blobs.pl.render_shapes("blobs_circles", color="feature0", table_layer="normalized").pl.show() + + +def test_warns_when_table_does_not_annotate_element(sdata_blobs: SpatialData): + # Work on an independent copy since we mutate tables + sdata_blobs_local = deepcopy(sdata_blobs) + + # Create a table that annotates a DIFFERENT element than the one we will render + other_table = sdata_blobs_local["table"].copy() + other_table.obs["region"] = "blobs_points" # Different from blobs_circles + other_table.uns["spatialdata_attrs"]["region"] = "blobs_points" + sdata_blobs_local["other_table"] = other_table + + # Rendering "blobs_circles" with a table that annotates "blobs_points" + # should raise a warning and fall back to using no table. + with pytest.warns(UserWarning, match="does not annotate element"): + ( + sdata_blobs_local.pl.render_shapes( + "blobs_circles", + color="channel_0_sum", + table_name="other_table", + ).pl.show() + )