Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 20 additions & 13 deletions src/spatialdata_plot/pl/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,14 @@ def show(
panels = [(cs, None) for cs in coordinate_systems]
num_panels = len(panels)

# Titles are panel-level: require one title (broadcast to all panels) or exactly one
# per panel. Validating up front surfaces the error before any drawing, and also rejects
# an over-long list (previously silently truncated).
if title is not None and len(title) not in (1, num_panels):
raise ValueError(
f"The number of titles ({len(title)}) must be 1 or match the number of panels ({num_panels})."
)

if ax is not None:
n_ax = 1 if isinstance(ax, Axes) else len(ax)
if num_panels != n_ax:
Expand Down Expand Up @@ -1794,19 +1802,18 @@ def _draw_colorbar(
colorbar_requests=axis_colorbar_requests,
)

if title is None:
t = panel_key if panel_key is not None else cs
elif len(title) == 1:
t = title[0]
else:
try:
t = title[i]
except IndexError as e:
raise IndexError("The number of titles must match the number of panels.") from e
ax.set_title(t)
ax.set_aspect("equal")
if fig_params.frameon is False:
ax.axis("off")
# Title/aspect/frameon are panel-level: set once per panel.
if title is None:
t = panel_key if panel_key is not None else cs
elif len(title) == 1:
t = title[0]
else:
# len(title) == num_panels is guaranteed by the up-front check above.
t = title[i]
ax.set_title(t)
ax.set_aspect("equal")
if fig_params.frameon is False:
ax.axis("off")

if has_shapes and wants_shapes:
empty_shape_elements = [
Expand Down
18 changes: 18 additions & 0 deletions tests/pl/test_show.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,24 @@ def test_fig_parameter_default_no_warning(sdata_blobs: SpatialData):
plt.close("all")


def test_title_count_validation(sdata_blobs: SpatialData):
"""title must be length 1 or one-per-panel; mismatches raise up front (regression for #695)."""
base = sdata_blobs.pl.render_images(element="blobs_image")
with pytest.raises(ValueError, match="number of titles"): # single panel, too many
base.pl.show(title=["a", "b"], show=False)
plt.close("all")

set_transformation(sdata_blobs["blobs_image"], Identity(), "second_cs")
base2 = sdata_blobs.pl.render_images(element="blobs_image")
with pytest.raises(ValueError, match="number of titles"): # 2 panels, too many (was silently truncated)
base2.pl.show(title=["a", "b", "c"], show=False)
plt.close("all")

axs = base2.pl.show(title=["left", "right"], return_ax=True, show=False) # one per panel -> applied
assert sorted(a.get_title() for a in axs) == ["left", "right"]
plt.close("all")


def test_fig_parameter_warns_with_ax_list(sdata_blobs: SpatialData):
"""Passing fig= alongside a list of axes should also emit the deprecation (regression for #625)."""
set_transformation(sdata_blobs["blobs_image"], Identity(), "second_cs")
Expand Down
Loading