Skip to content

Fix labelmap edit with contour issues - #2838

Open
arul-trenser wants to merge 3 commits into
cornerstonejs:mainfrom
arul-trenser:fix-labelmap-edit-with-contour-issues
Open

Fix labelmap edit with contour issues#2838
arul-trenser wants to merge 3 commits into
cornerstonejs:mainfrom
arul-trenser:fix-labelmap-edit-with-contour-issues

Conversation

@arul-trenser

@arul-trenser arul-trenser commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Context

Contour editing tool had few bugs:

  • Locked/hidden segments could still be edited by mistake.
  • Old event-listener logic to setup contour representation was not reliable.
  • Contour edits were also going into annotation undo history, causing double undo entries.
  • Temporary contour representation was not cleaned up after use.
  • Only one contour should convert to labelmap, but all visible contours were getting converted.

The PR is incorporated by FlyWheel.io.

Fixes: #2837
Fixes: #2836
Fixes: #2833

Changes & Results

  • SegmentationStateManager.ts: Don't force-activate another representation if viewport already has an active one.
  • LabelmapBaseTool.ts:
    • viewportContoursToLabelmap now takes annotationFilter, so only needed annotation is converted.
    • Skip locked/hidden segments while painting labelmap.
    • Call doneEditMemo() so undo/redo works for labelmap edit.
  • LabelmapEditWithContour.ts:
    • Removed old event listeners and cache, now checks contour setup fresh on each new annotation.
    • Block drawing if active segment is locked/hidden.
    • createMemo() now does nothing, since labelmap memo already handles undo/redo.
    • Added cleanup function to remove temp contour representation after conversion.
    • annotationCompleted now converts only the just-drawn contour, using originalToolName match

Testing

#2833
Before:

2833-before.mp4

After:

2833-after.mp4

#2836
Before:
Scenario 1:

2836-MPR1-before.mp4

Scenario 2:

2836-MPR2-before.mp4

After:
Scenario 1:

2836-MPR1-after.mp4

Scenario 2:

2836-MPR2-after.mp4

#2837
Before:

2837-before.mp4

After:

2837-after.mp4

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: Windows 11
  • "Node version: 22.19.0
  • "Browser: 150.0.7871.187

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added annotation filtering before converting contours to labelmaps.
    • Added support for creating contour representations as needed.
    • Added automatic cleanup for temporary contour data.
  • Bug Fixes

    • Protected locked or hidden segments and voxels from editing.
    • Improved active-representation selection after removing the active representation.
    • Improved handling of incomplete contours and invalid drawing states.

@coderabbitai

coderabbitai Bot commented Aug 3, 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: 5887bdea-ecf3-4598-8c0b-267fa4b3dc16

📥 Commits

Reviewing files that changed from the base of the PR and between ab8a356 and 0312299.

📒 Files selected for processing (3)
  • packages/tools/src/stateManagement/segmentation/SegmentationStateManager.ts
  • packages/tools/src/tools/segmentation/LabelmapBaseTool.ts
  • packages/tools/src/tools/segmentation/LabelmapEditWithContour.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/tools/src/stateManagement/segmentation/SegmentationStateManager.ts
  • packages/tools/src/tools/segmentation/LabelmapBaseTool.ts
  • packages/tools/src/tools/segmentation/LabelmapEditWithContour.ts

📝 Walkthrough

Walkthrough

The change updates contour editing to use live segmentation state, enforce locked and hidden segment rules, filter annotations before conversion, clean temporary representations, and limit fallback activation to cases with no remaining active segmentation.

Changes

Contour segmentation editing

Layer / File(s) Summary
Representation activation fallback
packages/tools/src/stateManagement/segmentation/SegmentationStateManager.ts
Fallback activation occurs only when removing an active representation leaves no active segmentation.
Protected contour-to-labelmap conversion
packages/tools/src/tools/segmentation/LabelmapBaseTool.ts
viewportContoursToLabelmap accepts an annotation filter. Conversion skips locked or hidden segments and voxels. The edit memo is finalized after segmentation updates.
Live contour lifecycle
packages/tools/src/tools/segmentation/LabelmapEditWithContour.ts
Contour drawing resolves live segmentation state, creates temporary representations lazily, suppresses transient memos, validates completion, and removes temporary state.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant LabelmapEditWithContour
  participant SegmentationState
  participant LabelmapBaseTool
  User->>LabelmapEditWithContour: start contour annotation
  LabelmapEditWithContour->>SegmentationState: resolve active segmentation
  SegmentationState-->>LabelmapEditWithContour: active segmentation state
  LabelmapEditWithContour->>SegmentationState: create temporary contour representation
  User->>LabelmapEditWithContour: complete contour
  LabelmapEditWithContour->>LabelmapBaseTool: convert eligible annotations
  LabelmapBaseTool->>SegmentationState: update labelmap
  LabelmapEditWithContour->>SegmentationState: remove temporary contour state
Loading

Possibly related PRs

Suggested reviewers: wayfarer3130, sedghi

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies fixes to labelmap contour editing and matches the main purpose of the changes.
Description check ✅ Passed The description includes context, linked issues, changes, testing evidence, checklist items, and tested environment details.
Linked Issues check ✅ Passed The changes address #2837, #2836, and #2833 through annotation filtering, representation handling, and corrected undo/redo memo processing.
Out of Scope Changes check ✅ Passed All changes support the stated contour-editing fixes, including representation activation, filtering, locking, memo handling, and cleanup.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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: 5

🧹 Nitpick comments (1)
packages/tools/src/tools/segmentation/LabelmapEditWithContour.ts (1)

400-407: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Filter by the specific completed annotation, not by tool name.

annotationFilter matches every annotation created by LabelMapEditWithContourTool, not only the one that just completed. This relies on removeContours cleanup elsewhere in viewportContoursToLabelmap to keep at most one such annotation pending at a time. Filtering directly by annotationUID removes that dependency and matches the stated objective ("only the newly created ROI should be converted to a labelmap") without relying on other code paths to stay precise.

♻️ Proposed refactor
     BrushTool.viewportContoursToLabelmap(viewport, {
       annotationFilter: (annotations) =>
         annotations.filter(
-          (a) =>
-            (a as ContourSegmentationAnnotation).metadata?.originalToolName ===
-            LabelMapEditWithContourTool.toolName
+          (a) => a.annotationUID === annotationUID
         ),
     });
🤖 Prompt for 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.

In `@packages/tools/src/tools/segmentation/LabelmapEditWithContour.ts` around
lines 400 - 407, Update the annotationFilter in the
BrushTool.viewportContoursToLabelmap call to retain only the completed
annotation by matching each annotation’s annotationUID against the specific
newly completed annotation’s UID, rather than filtering by
LabelMapEditWithContourTool.toolName. Preserve conversion of only that newly
created ROI and remove the dependency on removeContours cleanup.
🤖 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 `@packages/tools/src/stateManagement/segmentation/SegmentationStateManager.ts`:
- Around line 590-599: Update the fallback-activation guard in the state update
logic to inspect the draft state’s remaining representations directly rather
than calling the stale-state getter getActiveSegmentation. When
activeRepresentationRemoved is true, determine whether any remaining
representation in state.viewportSegRepresentations[viewportId] is active, and
activate the first one only when none are active.

In `@packages/tools/src/tools/segmentation/LabelmapBaseTool.ts`:
- Around line 743-760: Update the per-voxel segment handling in the
LabelmapBaseTool conversion loop to verify that currentSegmentIndex resolves to
an existing entry in the segmentation’s segments collection before calling
isSegmentIndexLocked. Treat orphaned indices as unlocked and visible so they are
skipped safely without throwing, while preserving the existing lock and
visibility checks for valid segments.
- Around line 605-636: Update viewportContoursToLabelmap so annotations are
first restricted to entries with a non-empty data.contour.polyline, then pass
that filtered set through options.annotationFilter when provided. Preserve the
existing default filtering behavior and ensure viewAnnotations cannot contain
annotations that later violate the unconditional contour/polyline access.
- Around line 705-736: Re-validate the fallback activeIndex in the segment
usability logic around isSegmentIndexLocked and getSegmentIndexVisibility before
writing the annotation. After redirecting from a locked or hidden segment,
re-check activeIndex and remove or skip the annotation when it is also locked or
hidden; preserve the existing behavior for usable fallback segments.

In `@packages/tools/src/tools/segmentation/LabelmapEditWithContour.ts`:
- Around line 119-142: Guard the active-segmentation flow before dereferencing
it: after segmentation.getActiveSegmentation(viewportId), return null when
activeSeg is undefined, and after
getActiveSegmentIndex(activeSeg.segmentationId), return null when activeSegIndex
is undefined. Only then call isSegmentIndexLocked, getSegmentIndexVisibility,
and checkContourSegmentation, preserving the existing locked/hidden behavior.

---

Nitpick comments:
In `@packages/tools/src/tools/segmentation/LabelmapEditWithContour.ts`:
- Around line 400-407: Update the annotationFilter in the
BrushTool.viewportContoursToLabelmap call to retain only the completed
annotation by matching each annotation’s annotationUID against the specific
newly completed annotation’s UID, rather than filtering by
LabelMapEditWithContourTool.toolName. Preserve conversion of only that newly
created ROI and remove the dependency on removeContours cleanup.
🪄 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: ced514e3-7a9e-493a-a0cd-106105569158

📥 Commits

Reviewing files that changed from the base of the PR and between a35a2b5 and 9a85a90.

📒 Files selected for processing (3)
  • packages/tools/src/stateManagement/segmentation/SegmentationStateManager.ts
  • packages/tools/src/tools/segmentation/LabelmapBaseTool.ts
  • packages/tools/src/tools/segmentation/LabelmapEditWithContour.ts

Comment thread packages/tools/src/tools/segmentation/LabelmapBaseTool.ts
Comment thread packages/tools/src/tools/segmentation/LabelmapBaseTool.ts
Comment thread packages/tools/src/tools/segmentation/LabelmapBaseTool.ts
Comment thread packages/tools/src/tools/segmentation/LabelmapEditWithContour.ts
@arul-trenser
arul-trenser force-pushed the fix-labelmap-edit-with-contour-issues branch from 1f7c71f to 0312299 Compare August 5, 2026 07:09
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@sen-trenser

Copy link
Copy Markdown

@sedghi Could you please take a look at this PR?
Thanks!

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