Skip to content

Slicer: normalize comma-separated selections — dedup always, axis order by default - #191

Merged
cboulay merged 1 commit into
mainfrom
fix/slicer-selection-set-semantics
Aug 2, 2026
Merged

Slicer: normalize comma-separated selections — dedup always, axis order by default#191
cboulay merged 1 commit into
mainfrom
fix/slicer-selection-set-semantics

Conversation

@cboulay

@cboulay cboulay commented Aug 2, 2026

Copy link
Copy Markdown
Member

Fixes #188.

Problem

Slicer resolved a comma-separated selection token by token and concatenated the per-token indices in token order, keeping duplicates:

  • ".*-m1-.*,.*-aip-.*" and ".*-aip-.*,.*-m1-.*" selected the same channels in different orders — same shape, no signal, so a downstream consumer (e.g. a trained decoder) reads every column as the wrong channel.
  • "3:10,1,7" duplicated index 7, so the output ch axis carried a repeated label, breaking coordinate-axis uniqueness for any later label-based selection or channel-keyed stage.

Solution

Per the issue's directions 3 + 4: a new order setting on SlicerSettings (also exposed via the slicer() convenience function), with the safer semantics as the default, plus logging whenever normalization changes anything.

  • order="axis" (default): after token resolution, indices are deduplicated and sorted into axis order. A selection is a filter — the same channel set always produces the same output regardless of token order, matching how label/regex selections read.
  • order="selection": entries keep token order, so a positional "3,1,2" remains an intentional permutation. Duplicates are still removed (first occurrence wins) — a repeated channel on a coordinate axis is never what anyone meant.
  • A warning is logged when overlapping tokens produced duplicates, and an info message when token order differed from axis order under order="axis" (once per stream configuration, like the on_empty logs).

Since one selection string can mix positional and label tokens, one rule wins: the default treats the whole selection as a filter, and order="selection" is the explicit opt-in for permutation semantics.

Implementation notes

  • Normalization lives in SlicerTransformer._reset_state (via a _normalize_indices helper), which is the one place that knows the resolved index array and axis length. parse_slice is unchanged — its documented concatenate-in-token-order behavior (from Select channels based on their labels #61) remains, with a docstring note pointing at the transformer-level normalization.
  • A single non-comma slice token (e.g. "::-1", "5:") still takes the plain-slice path and is not normalized, so explicit reverse/strided slices keep working; the issue is scoped to comma-separated selections.
  • Invalid order values raise at first message, mirroring on_empty validation.

Tests

  • Both issue repros: "3:10,1,7"ch01, ch03..ch09 (dedup + axis order, both log messages asserted), and the m1/aip regex pair producing identical output in either token order.
  • order="selection": permutation preserved, duplicates still dropped keeping first occurrence.
  • Already-normalized selections pass through with no log output; "::-1" untouched; invalid order raises.
  • Full unit suite: 3649 passed.

A comma-separated selection resolved token by token and concatenated in
token order, keeping duplicates. Selections naming the same channels in
a different token order silently produced differently-ordered output of
identical shape, and overlapping tokens duplicated channels so the
coordinate axis carried repeated labels.

SlicerTransformer now normalizes the resolved indices per a new `order`
setting:

- "axis" (default): indices are deduplicated and sorted into axis order,
  making a selection a filter — token order never matters and the
  coordinate axis stays unique.
- "selection": entries keep token order for intentional permutations
  (e.g. "3,1,2"); duplicates are still removed, first occurrence wins.

Normalization logs when it changes anything: a warning when overlapping
tokens produced duplicates, an info message when token order differed
from axis order under order="axis". A single non-comma slice token
(e.g. "::-1") is applied as-is and not normalized. parse_slice is
unchanged; normalization happens in _reset_state where the axis length
is known.

Fixes #188
@cboulay
cboulay merged commit da3c8c3 into main Aug 2, 2026
14 checks passed
@cboulay
cboulay deleted the fix/slicer-selection-set-semantics branch August 2, 2026 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant