Skip to content

Commit 8b1baae

Browse files
authored
Skip wasted cs-level table copy in render_shapes/render_labels (#680)
1 parent 8a6a33f commit 8b1baae

1 file changed

Lines changed: 19 additions & 5 deletions

File tree

src/spatialdata_plot/pl/render.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,11 @@ def _render_shapes(
411411

412412
_check_obs_var_shadow(sdata, element, col_for_color, render_params.table_name)
413413

414+
# filter_tables=False: join_spatialelement_table below overwrites the table,
415+
# so the cs-level sparse copy is wasted work.
414416
sdata_filt = sdata.filter_by_coordinate_system(
415417
coordinate_system=coordinate_system,
416-
filter_tables=bool(render_params.table_name),
418+
filter_tables=False,
417419
)
418420

419421
table_name = render_params.table_name
@@ -425,18 +427,28 @@ def _render_shapes(
425427

426428
# Workaround for upstream spatialdata bug (scverse/spatialdata#1099):
427429
# join_spatialelement_table calls table.obs.reset_index() which fails when
428-
# the obs index name matches an existing column (e.g. "EntityID" in Merfish data).
429-
# Temporarily drop the conflicting index name for the join, then restore it.
430+
# the obs index name matches an existing column (e.g. "EntityID" in Merfish
431+
# data). When that collision is present, the obs index may also be a
432+
# non-RangeIndex of int dtype, which AnnData's `_normalize_index` rejects
433+
# when the join indexes back into the table. Temporarily swap to a clean
434+
# RangeIndex / drop the conflicting name; restore on exit.
430435
_obs = sdata[table_name].obs
431436
_saved_index_name = _obs.index.name
432-
if _saved_index_name is not None and _saved_index_name in _obs.columns:
437+
_saved_index: pd.Index | None = None
438+
_name_collides = _saved_index_name is not None and _saved_index_name in _obs.columns
439+
if _name_collides and not isinstance(_obs.index, pd.RangeIndex):
440+
_saved_index = _obs.index
441+
_obs.index = pd.RangeIndex(len(_obs))
442+
elif _name_collides:
433443
_obs.index.name = None
434444

435445
try:
436446
element_dict, joined_table = join_spatialelement_table(
437447
sdata, spatial_element_names=element, table_name=table_name, how="inner"
438448
)
439449
finally:
450+
if _saved_index is not None:
451+
_obs.index = _saved_index
440452
_obs.index.name = _saved_index_name
441453
sdata_filt[element] = shapes = element_dict[element]
442454
joined_table.uns["spatialdata_attrs"]["region"] = (
@@ -1748,9 +1760,11 @@ def _render_labels(
17481760

17491761
_check_obs_var_shadow(sdata, element, col_for_color, table_name)
17501762

1763+
# filter_tables=False: match_table_to_element below already filters per
1764+
# element, so the cs-level sparse copy is wasted work.
17511765
sdata_filt = sdata.filter_by_coordinate_system(
17521766
coordinate_system=coordinate_system,
1753-
filter_tables=bool(table_name),
1767+
filter_tables=False,
17541768
)
17551769

17561770
label = sdata_filt.labels[element]

0 commit comments

Comments
 (0)