Skip to content

Commit 6e70bc5

Browse files
committed
refactor(show): extract per-panel render dispatch into _render_panel/_finalize_panel
Extract the inner render-command dispatch loop (#697), behavior-preserving: - _render_panel(): dispatches each queued render command into one panel's axes, returning the wanted elements and per-type wants_* flags - _finalize_panel(): per-panel title / equal-aspect / frame visibility show() is now a compact orchestrator calling named stages. Full test suite passes unchanged (719 passed, 1 skipped), image baselines included. No behavior change.
1 parent fcdf1c0 commit 6e70bc5

1 file changed

Lines changed: 199 additions & 133 deletions

File tree

‎src/spatialdata_plot/pl/basic.py‎

Lines changed: 199 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,139 +1493,25 @@ def show(
14931493
axis_colorbar_requests: list[ColorbarSpec] | None = [] if legend_params_obj.colorbar else None
14941494
axis_channel_legend_entries: list[ChannelLegendEntry] = []
14951495

1496-
wants_images = False
1497-
wants_labels = False
1498-
wants_points = False
1499-
wants_shapes = False
1500-
wanted_elements: list[str] = []
1501-
1502-
for cmd, params in render_cmds:
1503-
# Skip render entries that belong to a different color panel. Entries with no
1504-
# `panel_key` (None) are shared and drawn into every panel (e.g. a background image).
1505-
cmd_panel_key = getattr(params, "panel_key", None)
1506-
if panel_key is not None and cmd_panel_key is not None and cmd_panel_key != panel_key:
1507-
continue
1508-
# We create a copy here as the wanted elements can change from one cs to another.
1509-
params_copy = deepcopy(params)
1510-
if cmd == "render_images" and has_images:
1511-
wanted_elements, wanted_images_on_this_cs, wants_images = _get_wanted_render_elements(
1512-
sdata, wanted_elements, params_copy, cs, "images"
1513-
)
1514-
1515-
if wanted_images_on_this_cs:
1516-
rasterize = (params_copy.scale is None) or (
1517-
isinstance(params_copy.scale, str)
1518-
and params_copy.scale != "full"
1519-
and (dpi is not None or figsize is not None)
1520-
)
1521-
_render_images(
1522-
sdata=sdata,
1523-
render_params=params_copy,
1524-
coordinate_system=cs,
1525-
ax=ax,
1526-
fig_params=fig_params,
1527-
legend_params=legend_params_obj,
1528-
colorbar_requests=axis_colorbar_requests,
1529-
channel_legend_entries=axis_channel_legend_entries,
1530-
rasterize=rasterize,
1531-
)
1532-
1533-
elif cmd == "render_shapes" and has_shapes:
1534-
wanted_elements, wanted_shapes_on_this_cs, wants_shapes = _get_wanted_render_elements(
1535-
sdata, wanted_elements, params_copy, cs, "shapes"
1536-
)
1537-
1538-
if wanted_shapes_on_this_cs:
1539-
_render_shapes(
1540-
sdata=sdata,
1541-
render_params=params_copy,
1542-
coordinate_system=cs,
1543-
ax=ax,
1544-
fig_params=fig_params,
1545-
legend_params=legend_params_obj,
1546-
colorbar_requests=axis_colorbar_requests,
1547-
)
1548-
1549-
elif cmd == "render_points" and has_points:
1550-
wanted_elements, wanted_points_on_this_cs, wants_points = _get_wanted_render_elements(
1551-
sdata, wanted_elements, params_copy, cs, "points"
1552-
)
1553-
1554-
if wanted_points_on_this_cs:
1555-
_render_points(
1556-
sdata=sdata,
1557-
render_params=params_copy,
1558-
coordinate_system=cs,
1559-
ax=ax,
1560-
fig_params=fig_params,
1561-
legend_params=legend_params_obj,
1562-
colorbar_requests=axis_colorbar_requests,
1563-
)
1564-
1565-
elif cmd == "render_labels" and has_labels:
1566-
wanted_elements, wanted_labels_on_this_cs, wants_labels = _get_wanted_render_elements(
1567-
sdata, wanted_elements, params_copy, cs, "labels"
1568-
)
1569-
1570-
if wanted_labels_on_this_cs:
1571-
table = params_copy.table_name
1572-
if table is not None and params_copy.col_for_color is not None:
1573-
colors = sc.get.obs_df(sdata[table], [params_copy.col_for_color])
1574-
if isinstance(
1575-
colors[params_copy.col_for_color].dtype,
1576-
pd.CategoricalDtype,
1577-
):
1578-
_maybe_set_colors(
1579-
source=sdata[table],
1580-
target=sdata[table],
1581-
key=params_copy.col_for_color,
1582-
palette=params_copy.palette,
1583-
)
1584-
1585-
rasterize = (params_copy.scale is None) or (
1586-
isinstance(params_copy.scale, str)
1587-
and params_copy.scale != "full"
1588-
and (dpi is not None or figsize is not None)
1589-
)
1590-
_render_labels(
1591-
sdata=sdata,
1592-
render_params=params_copy,
1593-
coordinate_system=cs,
1594-
ax=ax,
1595-
fig_params=fig_params,
1596-
legend_params=legend_params_obj,
1597-
colorbar_requests=axis_colorbar_requests,
1598-
rasterize=rasterize,
1599-
)
1600-
1601-
elif cmd == "render_graph":
1602-
graph_element = params_copy.element
1603-
element_in_cs = graph_element in sdata and cs in set(
1604-
get_transformation(sdata[graph_element], get_all=True).keys()
1605-
)
1606-
if element_in_cs:
1607-
_render_graph(
1608-
sdata=sdata,
1609-
render_params=params_copy,
1610-
coordinate_system=cs,
1611-
ax=ax,
1612-
legend_params=legend_params_obj,
1613-
colorbar_requests=axis_colorbar_requests,
1614-
)
1615-
1616-
if title is None:
1617-
t = panel_key if panel_key is not None else cs
1618-
elif len(title) == 1:
1619-
t = title[0]
1620-
else:
1621-
try:
1622-
t = title[i]
1623-
except IndexError as e:
1624-
raise IndexError("The number of titles must match the number of panels.") from e
1625-
ax.set_title(t)
1626-
ax.set_aspect("equal")
1627-
if fig_params.frameon is False:
1628-
ax.axis("off")
1496+
wanted_elements, wants_images, wants_labels, wants_points, wants_shapes = _render_panel(
1497+
sdata=sdata,
1498+
render_cmds=render_cmds,
1499+
cs=cs,
1500+
panel_key=panel_key,
1501+
panel_idx=i,
1502+
ax=ax,
1503+
fig_params=fig_params,
1504+
legend_params_obj=legend_params_obj,
1505+
axis_colorbar_requests=axis_colorbar_requests,
1506+
axis_channel_legend_entries=axis_channel_legend_entries,
1507+
has_images=has_images,
1508+
has_labels=has_labels,
1509+
has_points=has_points,
1510+
has_shapes=has_shapes,
1511+
title=title,
1512+
dpi=dpi,
1513+
figsize=figsize,
1514+
)
16291515

16301516
if has_shapes and wants_shapes:
16311517
empty_shape_elements = [
@@ -2010,3 +1896,183 @@ def _layout_pending_colorbars(
20101896
trackers_axes = {k: base_offsets_axes[k] for k in base_offsets_axes}
20111897
for spec in unique_specs:
20121898
_draw_colorbar(spec, fig, renderer, base_offsets_axes, trackers_axes, colorbar_params)
1899+
1900+
1901+
def _finalize_panel(
1902+
ax: Axes,
1903+
panel_idx: int,
1904+
title: list[str] | None,
1905+
panel_key: str | None,
1906+
cs: str,
1907+
frameon: bool | None,
1908+
) -> None:
1909+
"""Set a panel's title, equal aspect ratio and frame visibility.
1910+
1911+
With no explicit ``title`` the panel is labelled with its color key (multi-panel color mode)
1912+
or its coordinate-system name; a single-element list applies to every panel, otherwise the
1913+
title at ``panel_idx`` is used.
1914+
"""
1915+
if title is None:
1916+
t = panel_key if panel_key is not None else cs
1917+
elif len(title) == 1:
1918+
t = title[0]
1919+
else:
1920+
try:
1921+
t = title[panel_idx]
1922+
except IndexError as e:
1923+
raise IndexError("The number of titles must match the number of panels.") from e
1924+
ax.set_title(t)
1925+
ax.set_aspect("equal")
1926+
if frameon is False:
1927+
ax.axis("off")
1928+
1929+
1930+
def _render_panel(
1931+
sdata: sd.SpatialData,
1932+
render_cmds: list[_RenderCmd],
1933+
cs: str,
1934+
panel_key: str | None,
1935+
panel_idx: int,
1936+
ax: Axes,
1937+
fig_params: FigParams,
1938+
legend_params_obj: LegendParams,
1939+
axis_colorbar_requests: list[ColorbarSpec] | None,
1940+
axis_channel_legend_entries: list[ChannelLegendEntry],
1941+
has_images: bool,
1942+
has_labels: bool,
1943+
has_points: bool,
1944+
has_shapes: bool,
1945+
title: list[str] | None,
1946+
dpi: int | None,
1947+
figsize: tuple[float, float] | None,
1948+
) -> tuple[list[str], bool, bool, bool, bool]:
1949+
"""Render every applicable render command into a single panel's axes.
1950+
1951+
Dispatches each queued render command to its ``_render_*`` function, skipping entries that
1952+
belong to a different color panel (``panel_key``). Colorbar requests and channel-legend
1953+
entries accumulate on the passed-in lists. Returns the wanted element names and the per-type
1954+
``wants_*`` flags needed downstream for extent computation.
1955+
"""
1956+
wants_images = False
1957+
wants_labels = False
1958+
wants_points = False
1959+
wants_shapes = False
1960+
wanted_elements: list[str] = []
1961+
1962+
for cmd, params in render_cmds:
1963+
# Skip render entries that belong to a different color panel. Entries with no
1964+
# `panel_key` (None) are shared and drawn into every panel (e.g. a background image).
1965+
cmd_panel_key = getattr(params, "panel_key", None)
1966+
if panel_key is not None and cmd_panel_key is not None and cmd_panel_key != panel_key:
1967+
continue
1968+
# We create a copy here as the wanted elements can change from one cs to another.
1969+
params_copy = deepcopy(params)
1970+
if cmd == "render_images" and has_images:
1971+
wanted_elements, wanted_images_on_this_cs, wants_images = _get_wanted_render_elements(
1972+
sdata, wanted_elements, params_copy, cs, "images"
1973+
)
1974+
1975+
if wanted_images_on_this_cs:
1976+
rasterize = (params_copy.scale is None) or (
1977+
isinstance(params_copy.scale, str)
1978+
and params_copy.scale != "full"
1979+
and (dpi is not None or figsize is not None)
1980+
)
1981+
_render_images(
1982+
sdata=sdata,
1983+
render_params=params_copy,
1984+
coordinate_system=cs,
1985+
ax=ax,
1986+
fig_params=fig_params,
1987+
legend_params=legend_params_obj,
1988+
colorbar_requests=axis_colorbar_requests,
1989+
channel_legend_entries=axis_channel_legend_entries,
1990+
rasterize=rasterize,
1991+
)
1992+
1993+
elif cmd == "render_shapes" and has_shapes:
1994+
wanted_elements, wanted_shapes_on_this_cs, wants_shapes = _get_wanted_render_elements(
1995+
sdata, wanted_elements, params_copy, cs, "shapes"
1996+
)
1997+
1998+
if wanted_shapes_on_this_cs:
1999+
_render_shapes(
2000+
sdata=sdata,
2001+
render_params=params_copy,
2002+
coordinate_system=cs,
2003+
ax=ax,
2004+
fig_params=fig_params,
2005+
legend_params=legend_params_obj,
2006+
colorbar_requests=axis_colorbar_requests,
2007+
)
2008+
2009+
elif cmd == "render_points" and has_points:
2010+
wanted_elements, wanted_points_on_this_cs, wants_points = _get_wanted_render_elements(
2011+
sdata, wanted_elements, params_copy, cs, "points"
2012+
)
2013+
2014+
if wanted_points_on_this_cs:
2015+
_render_points(
2016+
sdata=sdata,
2017+
render_params=params_copy,
2018+
coordinate_system=cs,
2019+
ax=ax,
2020+
fig_params=fig_params,
2021+
legend_params=legend_params_obj,
2022+
colorbar_requests=axis_colorbar_requests,
2023+
)
2024+
2025+
elif cmd == "render_labels" and has_labels:
2026+
wanted_elements, wanted_labels_on_this_cs, wants_labels = _get_wanted_render_elements(
2027+
sdata, wanted_elements, params_copy, cs, "labels"
2028+
)
2029+
2030+
if wanted_labels_on_this_cs:
2031+
table = params_copy.table_name
2032+
if table is not None and params_copy.col_for_color is not None:
2033+
colors = sc.get.obs_df(sdata[table], [params_copy.col_for_color])
2034+
if isinstance(
2035+
colors[params_copy.col_for_color].dtype,
2036+
pd.CategoricalDtype,
2037+
):
2038+
_maybe_set_colors(
2039+
source=sdata[table],
2040+
target=sdata[table],
2041+
key=params_copy.col_for_color,
2042+
palette=params_copy.palette,
2043+
)
2044+
2045+
rasterize = (params_copy.scale is None) or (
2046+
isinstance(params_copy.scale, str)
2047+
and params_copy.scale != "full"
2048+
and (dpi is not None or figsize is not None)
2049+
)
2050+
_render_labels(
2051+
sdata=sdata,
2052+
render_params=params_copy,
2053+
coordinate_system=cs,
2054+
ax=ax,
2055+
fig_params=fig_params,
2056+
legend_params=legend_params_obj,
2057+
colorbar_requests=axis_colorbar_requests,
2058+
rasterize=rasterize,
2059+
)
2060+
2061+
elif cmd == "render_graph":
2062+
graph_element = params_copy.element
2063+
element_in_cs = graph_element in sdata and cs in set(
2064+
get_transformation(sdata[graph_element], get_all=True).keys()
2065+
)
2066+
if element_in_cs:
2067+
_render_graph(
2068+
sdata=sdata,
2069+
render_params=params_copy,
2070+
coordinate_system=cs,
2071+
ax=ax,
2072+
legend_params=legend_params_obj,
2073+
colorbar_requests=axis_colorbar_requests,
2074+
)
2075+
2076+
_finalize_panel(ax, panel_idx, title, panel_key, cs, fig_params.frameon)
2077+
2078+
return wanted_elements, wants_images, wants_labels, wants_points, wants_shapes

0 commit comments

Comments
 (0)