Skip to content

[C-511] Overlay colors merge across datasets (additive blending + palette cycling) - #261

Merged
dahannes merged 4 commits into
mainfrom
dahannes/c-511-overlay-merge
Sep 20, 2026
Merged

dahannes merged 4 commits into
mainfrom
dahannes/c-511-overlay-merge

Conversation

@dahannes

@dahannes dahannes commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

[C-511] Overlay visualization colors should merge

Two loaded overlay datasets previously composited with straight alpha: the top set simply covered the one beneath, so e.g. CD3 detected by model X (red) and model Y (yellow) showed only the top color. OMERO-style comparison was impossible.

What changed

  • Additive blend state on overlay fill layersAdditivePolygonLayer / AdditiveScatterplotLayer now render with luma.gl blend parameters (src-alpha onto one): fragments accumulate on the framebuffer instead of overwriting it. Red + yellow → orange, complementary pairs → white. Strokes stay alpha-blended so outlines remain crisp; within-file multi-marker mixing (shader bitmask sum) is unchanged. The fill-opacity slider becomes per-set intensity.
  • Parameters passed explicitly to sublayersTileLayer.renderSubLayers spreads parent props over sublayers, and every deck.gl layer carries a defaulted parameters: {} that clobbers subclass defaultProps; the blend state is therefore set at both sublayer construction sites. Verified with a headless Chromium probe bundling deck.gl 9.3: blue quad + yellow quad with these parameters read back as pure white from the framebuffer.
  • Marker palette cycles across datasets — colors were assigned per file from the shared palette by column index, so "CD3" in two datasets started identical. The palette window is now offset by the marker count of the other loaded datasets, so same-named markers default to distinct colors.
  • One fill-opacity default: DEFAULT_OVERLAYS_FILL_OPACITY = 0.5 used at every fallback site.

Docs

  • SRS-CY-33231 + user guide updated in cytario-docs PR (branch dahannes/c-511-overlay-merge), covering cross-dataset additive blending and palette distinctness. E2E spec for the palette/blending contract to be added there as the remaining ticket scope item.

Verification

  • Full suite: 2381 tests, lint, typecheck, format:check green
  • Manually verified against USL-2024-58461-3.ome.tif with results_total + results_linear_10k overlays (CK blue vs CK yellow → white overlap)

Refs C-511

@dahannes
dahannes requested a review from a team as a code owner September 19, 2026 18:05
@cytario-plane

cytario-plane Bot commented Sep 19, 2026

Copy link
Copy Markdown

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

@dahannes dahannes changed the title C-511 Overlay visualization colors should merge [C-511] Overlay colors merge across datasets (additive blending + palette cycling) Sep 19, 2026
@dahannes
dahannes force-pushed the dahannes/c-511-overlay-merge branch from b6dd5a7 to aa0d812 Compare September 19, 2026 20:19
…sets blend

Overlay sets render as separate stacked layers composited with straight
alpha. The fill opacity fallbacks disagreed (0.5 for new state, 0.8 in the
layer hook, selector and sidecar schema), so the top set covered ~80% of the
set beneath and overlaps were indistinguishable from the top set alone.

Define one DEFAULT_OVERLAYS_FILL_OPACITY (0.5) and use it at every site.
Outlines stay opaque so borders remain readable.

Refs C-511
…s accumulate

Each overlay parquet renders as its own deck.gl layer and those layers
composited with straight alpha, so the top set simply covered the one
beneath — two runs of the same marker never blended (C-511).

Give AdditivePolygonLayer and AdditiveScatterplotLayer an additive
blend pipeline (src-alpha onto one): fragments accumulate onto the
framebuffer instead of alpha-blending over it, so yellow + blue reads
white and red + yellow reads orange, OMERO-style. The fill-opacity
slider becomes per-set intensity. Strokes keep default blending so
outlines stay crisp; within-file shader mixing is unchanged.
…named markers differ

Marker colors were assigned per file from the shared palette by column
index, so "CD3" in two loaded overlays started life the same color and
the user had to recolor one by hand before the additive blending meant
anything (C-511).

Offset the palette window by the marker count of the other loaded
overlays: the same marker in a second file automatically gets the next
distinct color, wrapping once exhausted. Offsets are read from the
store at fetch/apply time.
…layers

The blend state set as static defaultProps on the additive layer classes
never reached the GPU: every deck.gl layer carries a defaulted
parameters: {} prop, and TileLayer's renderSubLayers spreads the parent
props over the sublayer, so the explicit (empty) value clobbered the
subclass defaults. Verified via a headless deck.gl probe that explicit
parameters produce true additive accumulation (blue + yellow → white).

Set the parameters on both sublayer constructions in OverlaysLayer and
test through renderSubLayers so the clobbering mode is covered.
@dfrkp
dfrkp force-pushed the dahannes/c-511-overlay-merge branch from aa0d812 to 5d259ab Compare September 20, 2026 09:29
@dahannes
dahannes merged commit f042aa7 into main Sep 20, 2026
8 checks passed
@dahannes
dahannes deleted the dahannes/c-511-overlay-merge branch September 20, 2026 09:49
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 6.33.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 6.10.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants