@@ -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