Skip to content

fix(labels): align instance_id with colour vector for partial tables (#775) - #776

Open
timtreis wants to merge 1 commit into
mainfrom
fix/issue-775
Open

fix(labels): align instance_id with colour vector for partial tables (#775)#776
timtreis wants to merge 1 commit into
mainfrom
fix/issue-775

Conversation

@timtreis

@timtreis timtreis commented Sep 4, 2026

Copy link
Copy Markdown
Member

Problem

render_labels(color=...) raises IndexError when the annotating table has rows for instances that are not present in the labels element — e.g. objects lost when a segmentation is regenerated, or a table read from an upstream pipeline.

IndexError: boolean index did not match indexed array along axis 0;
size of axis is 2 but size of corresponding boolean axis is 3

Fixes #775.

Root cause

instance_id was derived from all table rows (np.unique(table.obs[instance_key])), but the colour vector from get_values is restricted to the element's present instances. The two diverged, so the rasterize mask (length = number of table rows) indexed the shorter colour vector → IndexError at render.py_color.py ColorSpec.filter.

This was only ever half-fixed: #603/#661 added _check_instance_ids_overlap, but that raises only when the ID sets are fully disjoint. Shapes/points already reindex colour to the element index and are robust to phantom rows; labels was left behind.

Fix

Restrict instance_id to the canonical instances actually present in the element (get_element_instances) intersected with the table — the same basis get_values uses for the colour vector, independent of the rendered scale:

instance_id = np.intersect1d(
    np.unique(table.obs[instance_key].values),
    np.asarray(get_element_instances(sdata_filt[element])),
)

Rasterize / multiscale display drops are still reconciled against both vectors by the existing mask further down, so alignment holds in all cases.

Behaviour

  • Changed: previously-crashing cases (phantom table rows; present-but-untabled labels under color) now render as missing instead of raising.
  • Unchanged: well-formed input — including rasterize/multiscale that drops small labels — is byte-for-byte the same (intersect equals the old np.unique(table.obs) there).
  • No public API change; one extra get_element_instances scan on the coloured-labels path.

Tests

tests/pl/test_render_labels.py: parametrized phantom-row + present-not-in-table × continuous/categorical, plus a rasterize-survival case. All fail on main (IndexError) and pass with the fix. Full non-visual labels suite: 35 passed.

https://claude.ai/code/session_01U9J5GSXR4XGjPMaQQR5iSj

…775)

render_labels(color=...) raised IndexError when the annotating table had
rows for instances absent from the labels (e.g. objects lost when a
segmentation is regenerated, or a table from an upstream pipeline).

instance_id was derived from all table rows, but the colour vector from
get_values is restricted to the element's present instances, so the two
diverged and the rasterize mask indexed the shorter colour vector.

Restrict instance_id to the canonical instances actually present in the
element (get_element_instances) intersected with the table, matching the
colour vector's basis independent of rasterize/multiscale display drops.

Claude-Session: https://claude.ai/code/session_01U9J5GSXR4XGjPMaQQR5iSj
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.09%. Comparing base (956eb0c) to head (ac66a15).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #776   +/-   ##
=======================================
  Coverage   80.09%   80.09%           
=======================================
  Files          18       18           
  Lines        4863     4863           
  Branches     1080     1080           
=======================================
  Hits         3895     3895           
  Misses        603      603           
  Partials      365      365           
Files with missing lines Coverage Δ
src/spatialdata_plot/pl/render.py 88.99% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants