Skip to content

fix(cornerstone): share one color LUT across a segmentation's viewport representations#6141

Open
TFRadicalImaging wants to merge 2 commits into
OHIF:masterfrom
TFRadicalImaging:fix/labelmap-shared-color-lut
Open

fix(cornerstone): share one color LUT across a segmentation's viewport representations#6141
TFRadicalImaging wants to merge 2 commits into
OHIF:masterfrom
TFRadicalImaging:fix/labelmap-shared-color-lut

Conversation

@TFRadicalImaging

@TFRadicalImaging TFRadicalImaging commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Context

Editing a segment's color on a labelmap segmentation created by createLabelmapForDisplaySet (i.e. a segmentation the user creates in the viewer, as opposed to one loaded from a SEG or RT display set) does not stick: as soon as a drawing tool is used in another viewport, the segment reverts to its default color.

The cause is that createLabelmapForDisplaySet never creates a dedicated color LUT for the segmentation. The SEG and RT paths both do — they call addColorLUT and record the index in _segmentationIdToColorLUTIndexMap — but the labelmap path does not. With no index recorded, every viewport that renders the segmentation ends up with its own copy of the default LUT. A color edit therefore mutates only the LUT belonging to the viewport it was made in, and any other viewport keeps rendering the old default.

Changes & Results

extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts:

  • In createLabelmapForDisplaySet, create a dedicated color LUT up front and record its index in _segmentationIdToColorLUTIndexMap, mirroring what createSegmentationForSEGDisplaySet and createSegmentationForRTDisplaySet already do.
  • Every viewport representation of the segmentation then resolves to that same LUT, so a color edit made in one viewport is reflected in all of them.

Before: change a segment's colour, then draw in another viewport → the segment reverts to the default colour.
After: the edited colour is retained across all viewports.

This is 8 lines and does not change the SEG/RT paths or the LUT plumbing itself; it just brings the labelmap path in line with them.

Testing

extensions/cornerstone/src/services/SegmentationService/SegmentationService.test.ts — new case in the createLabelmapForDisplaySet block asserting that a dedicated color LUT is created and its index recorded against the segmentation id. It is a genuine regression test: it fails on master (addColorLUT is never called) and passes with this change.

cd extensions/cornerstone && jest src/services/SegmentationService/SegmentationService.test.ts

The full SegmentationService suite passes (86 tests).

Manually:

  1. Create a labelmap segmentation on a study displayed in a multi-viewport layout.
  2. Change a segment's colour from the segmentation panel.
  3. Use a drawing tool (e.g. the brush) in a different viewport.
  4. Before: the segment reverts to its default colour. After: the edited colour is retained.

Checklist

PR

  • My Pull Request title is descriptive, accurate and follows the
    semantic-release format and guidelines.

Code

  • My code has been well-documented (function documentation, inline comments,
    etc.)

Public Documentation Updates

  • The documentation page has been updated as necessary for any public API
    additions or removals.

Tested Environment

  • OS: macOS 15 (Darwin 25.5.0)
  • Node version: 24.3.0
  • Browser: Chrome 138

This fix is contributed by the University of Calgary, who are donating it back to OHIF. It was co-authored with Ron Leisti.

Summary by CodeRabbit

  • Bug Fixes
    • Improved segmentation display consistency across multiple viewports by reusing a dedicated color lookup table per segmentation ID.
    • Initialized newly created segmentation color lookup tables with a transparent entry to ensure consistent rendering.
  • Tests
    • Added unit tests to verify color lookup tables are created only once and reused on subsequent labelmap creation for the same segmentation.

…t representations

A labelmap segmentation created by createLabelmapForDisplaySet had no
dedicated color LUT, so every viewport that rendered it created its own
copy of the default LUT. Editing a segment color only mutated the active
viewport's LUT, so the change was lost as soon as a drawing tool was used
in another viewport and the segment reverted to the default color.

Create a dedicated color LUT when the segmentation is created and record
its index, mirroring the SEG and RT paths, so all representations reuse
the same LUT and color edits are retained everywhere.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@netlify

netlify Bot commented Jul 13, 2026

Copy link
Copy Markdown

Deploy Preview for ohif-dev ready!

Name Link
🔨 Latest commit 209edf4
🔍 Latest deploy log https://app.netlify.com/projects/ohif-dev/deploys/6a550fd8df710a0008ceb675
😎 Deploy Preview https://deploy-preview-6141--ohif-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@TFRadicalImaging

Copy link
Copy Markdown
Contributor Author

@wayfarer3130 @jbocce could one of you take a look? createLabelmapForDisplaySet is the only segmentation-creation path that doesn't register a dedicated color LUT — the SEG and RT paths both do — so each viewport falls back to its own copy of the default LUT and segment color edits don't survive interaction in another viewport. The new test fails on master and passes with the fix.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2135357d-2f83-4103-b0ec-376054582f88

📥 Commits

Reviewing files that changed from the base of the PR and between f8ef80c and 209edf4.

📒 Files selected for processing (2)
  • extensions/cornerstone/src/services/SegmentationService/SegmentationService.test.ts
  • extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts

📝 Walkthrough

Walkthrough

Changes

Segmentation Color LUT

Layer / File(s) Summary
Initialize and validate segmentation color LUT
extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts, extensions/cornerstone/src/services/SegmentationService/SegmentationService.test.ts
Display-set segmentation creation initializes a transparent color LUT once, stores its index by segmentation id, and verifies both initial creation and reuse through unit tests.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is specific, concise, and matches the main fix in the PR.
Description check ✅ Passed The description follows the template and includes context, changes, testing, checklist, and environment details.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@extensions/cornerstone/src/services/SegmentationService/SegmentationService.test.ts`:
- Around line 1335-1354: The regression test for createLabelmapForDisplaySet
must exercise representation creation, not only LUT registration. After creating
the segmentation, invoke the relevant addSegmentationRepresentation flow for two
viewports and assert each call receives the stored color LUT index 7, confirming
both representations reuse it.

In
`@extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts`:
- Around line 515-521: Update addOrUpdateSegmentation so reusing an existing
segmentationId does not allocate a new LUT or overwrite
_segmentationIdToColorLUTIndexMap. Before calling addColorLUT, retrieve and
reuse the existing LUT index for that ID, or reject the duplicate ID; preserve
the shared LUT for all current and future viewport representations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c3108dff-0a84-44e8-b9e3-877c6e088c8c

📥 Commits

Reviewing files that changed from the base of the PR and between 110b293 and f8ef80c.

📒 Files selected for processing (2)
  • extensions/cornerstone/src/services/SegmentationService/SegmentationService.test.ts
  • extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts

Comment thread extensions/cornerstone/src/services/SegmentationService/SegmentationService.ts Outdated
…is reused

The caller may pass the id of an existing segmentation, which this method
updates rather than replaces. Allocating a new LUT and overwriting the
mapping in that case would strand the representations already rendering
the segmentation on the previous LUT while later ones used the new index,
reintroducing the colour divergence this is meant to fix. Only allocate a
LUT when the segmentation has none.
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