Skip to content

feat: add support for DICOM Labelmap Segmentation Storage - #430

Open
igoroctaviano wants to merge 4 commits into
masterfrom
feat/labelmap-segmentation-support
Open

feat: add support for DICOM Labelmap Segmentation Storage#430
igoroctaviano wants to merge 4 commits into
masterfrom
feat/labelmap-segmentation-support

Conversation

@igoroctaviano

@igoroctaviano igoroctaviano commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add support for Labelmap Segmentation (SOP Class UID 1.2.840.10008.5.1.4.1.1.66.7) as defined in DICOM Supplement 243.

  • Add LABELMAP_SEGMENTATION to StorageClasses enum
  • Include LABELMAP_SEGMENTATION in GCP secondary store's storage classes
  • Update SlideViewer.loadDerivedDataset to handle both Segmentation and LabelmapSegmentation SOP Classes
  • Add series store caching in DicomWebManager to reduce 404 noise when using multi-store fallback (e.g., GCP query parameter for secondary stores)

The series store caching remembers which store successfully served each series and tries that store first on subsequent requests, avoiding unnecessary 404 errors when loading frames from the correct store.

Requires: ImagingDataCommons/dicom-microscopy-viewer#281

DMV Branch: feat/labelmap-seg-support

Test plan

  • Test with LABELMAP segmentation files from gs://idc-dicom-test-inventory/labelmap_examples/wsi/labelmap_monochrome_tiled_full_native/
  • Verify each segment renders as an independent togglable layer
  • Verify background segment (SegmentNumber 0) is included
  • Verify existing BINARY and FRACTIONAL segmentations still work
  • Verify reduced 404 console noise when using gcp query parameter

Closes #271

Add onClick handler to SegmentItem to zoom to segment's bounding box
when the segment label is clicked. This is consistent with the bulk
annotation zoom behavior and provides a better UX than auto-zooming
on visibility toggle.

Changes:
- Add onClick prop to SegmentItem and SegmentList components
- Add handleSegmentClick method in SlideViewer
- Update dicom-microscopy-viewer types with zoomToSegment method
Add support for Labelmap Segmentation (SOP Class UID 1.2.840.10008.5.1.4.1.1.66.7)
as defined in DICOM Supplement 243.

Key changes:
- Add LABELMAP_SEGMENTATION to StorageClasses enum
- Include LABELMAP_SEGMENTATION in GCP secondary store's storage classes
- Update SlideViewer.loadDerivedDataset to handle both Segmentation and
  LabelmapSegmentation SOP Classes
- Add series store caching in DicomWebManager to reduce 404 noise when using
  multi-store fallback (e.g., GCP query parameter for secondary stores)

The series store caching remembers which store successfully served each series
and tries that store first on subsequent requests, avoiding unnecessary 404
errors when loading frames from the correct store.

Closes #271
@deepsource-io

deepsource-io Bot commented Aug 29, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in a2912f1...b011a34 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript Aug 31, 2026 12:48a.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

@github-actions

Copy link
Copy Markdown

📦 Firebase Preview - Using Published DMV

This preview is using the published dicom-microscopy-viewer from package.json:

Version ^0.48.24

To link a DMV branch for testing (requires an open PR in DMV):

  • Add dmv-branch: <branch-name> to the PR description, OR
  • Use the same branch name in both repos (automatic matching)

@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit b011a34):

https://idc-external-006--pr430-feat-labelmap-segmen-4t837sy1.web.app

(expires Mon, 07 Sep 2026 00:50:19 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 88aacecd98ba54d2f9c8d201a9444e43d1ad8307

@github-actions

Copy link
Copy Markdown

📦 Firebase Preview - Using Published DMV

This preview is using the published dicom-microscopy-viewer from package.json:

Version ^0.48.24

To link a DMV branch for testing (requires an open PR in DMV):

  • Add dmv-branch: <branch-name> to the PR description, OR
  • Use the same branch name in both repos (automatic matching)

Prefix unused onClick destructure with underscore in SegmentItem.tsx (JS-0356)
@github-actions

Copy link
Copy Markdown

📦 Firebase Preview - Using Published DMV

This preview is using the published dicom-microscopy-viewer from package.json:

Version ^0.48.24

To link a DMV branch for testing (requires an open PR in DMV):

  • Add dmv-branch: <branch-name> to the PR description, OR
  • Use the same branch name in both repos (automatic matching)

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown

📦 Firebase Preview - Using Published DMV

This preview is using the published dicom-microscopy-viewer from package.json:

Version ^0.48.24

To link a DMV branch for testing (requires an open PR in DMV):

  • Add dmv-branch: <branch-name> to the PR description, OR
  • Use the same branch name in both repos (automatic matching)

@CPBridge

CPBridge commented Sep 4, 2026

Copy link
Copy Markdown

@igoroctaviano @fedorov this is exciting progress!

I created a dicom store using one of the labelmap segmentations from the test data bucket mentioned above to test this:

http://localhost:3000/studies/2.25.169909530366026741902094648458907485460?gcp=https://healthcare.googleapis.com/v1/projects/idc-dicom-review/locations/us-central1/datasets/rms-labelmap-example-dataset/dicomStores/rms-labelmap-example-dicom-store/dicomWeb

The labelmap displays!

Screenshot 2026-09-04 at 4 21 40 PM

However there are definitely a few issues:

  • The colors of the segments in the image do not seem to match the color controls on the right, rather confusingly (you can see in the screenshot that the controls say that segments should be yellow, but this is not the case in the image). When I try to change the color, the segments disappear altogether
  • This is a delicate subject, but we need to think carefully about how to identify and handle the background class. Currently it is displayed as purple in this example for whatever reason, and it's all rather Andy Warhol. I personally would favor either not displaying the background class at all, or making it displayable but transparent by default. Then comes the issue of how to identify the background class. I think the best way is to treat the segment whose segment number matches the value of the "PixelPaddingValue" attribute as the background segment. Alternatively, one could look for the segmented property type (DCM, 125040, "Background"). @fedorov may have a perspective here as I know he has been having issues with this for radiology

@igoroctaviano

igoroctaviano commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

@CPBridge @fedorov thanks for testing this — I looked into the two issues and wanted to confirm the diagnosis and proposed fix before implementing.

Color mismatch / color change hides the overlay
After decode each LABELMAP layer is masked to {0, 1}, but then colorized like a FRACTIONAL overlay (createDistinctColormap: red / blue / green / orange / purple). The side panel only treats BINARY as having an explicit color, so the swatch falls back to yellow. That matches the screenshot: controls say yellow, the image does not.

Changing the color then calls setSegmentStyle with a 2-entry palette, and setSegmentStyle falls back to windowCenter = 128 / windowWidth = 256 because those values were never stored. For 0/1 data that maps the segment onto the transparent first bin, so the overlay disappears.

Background class
Auto-show currently turns every segment on, including background, which paints the whole field (the purple / Warhol effect).

Proposed plan

  • Treat masked LABELMAP layers as binary-colored overlays (not FRACTIONAL colormaps). Use RecommendedDisplayCIELabValue when present; otherwise a stable solid hue. Persist the 0/1 window so color changes stay visible.
  • Identify background primarily by SegmentNumber === PixelPaddingValue (0028,0120), with fallback to Segmented Property Type (DCM, 125040, "Background"). Do not treat Segment Number 0 alone as background. A coded-Background segment without a matching padding value stays a normal overlay.
  • Keep the background row in the panel so it can be inspected, but do not auto-show it (toggle off / transparent by default).

Most of this lands in ImagingDataCommons/dicom-microscopy-viewer#281; Slim needs matching UI defaults and to skip auto-show for background.

Does this approach make sense, especially the background identification and “listed but off by default” behavior?

@CPBridge

CPBridge commented Sep 4, 2026

Copy link
Copy Markdown

@igoroctaviano the color fixes sound good in outline though I don't follow the low level details

Regarding background the following sounds self-contradictory to me in how it treats a segment coded as background but without a matching pixel padding value:

Identify background primarily by SegmentNumber === PixelPaddingValue (0028,0120), with fallback to Segmented Property Type (DCM, 125040, "Background"). [...] A coded-Background segment without a matching padding value stays a normal overlay.

I think the "most correct" to do this would be to check SegmentNumber === PixelPaddingValue (0028,0120), however, it might also make practical sense to also treat any segment coded as (DCM, 125040, "Background") as background. Let's see what @fedorov suggests before proceeding.

@igoroctaviano

Copy link
Copy Markdown
Collaborator Author

@CPBridge you’re right — those two sentences contradicted each other. I’ll drop the “stays a normal overlay” part.

Two clean options, as you framed them:

  1. Most correct: treat as background only when SegmentNumber === PixelPaddingValue (0028,0120).
  2. Practical: that, or Segmented Property Type (DCM, 125040, "Background").

I’ll wait for @fedorov before locking that in. Color side I’ll treat as agreed in outline.

@CPBridge

CPBridge commented Sep 4, 2026

Copy link
Copy Markdown

I also think another option we should consider is just, once identified, hiding the background segment entirely

@fedorov

fedorov commented Sep 5, 2026

Copy link
Copy Markdown
Member

Most correct: treat as background only when SegmentNumber === PixelPaddingValue (0028,0120).
Practical: that, or Segmented Property Type (DCM, 125040, "Background").

Yes, I think that's what we do in dcmqi, and the long discussion is here (for completeness, or if Claude wants to read it sometime!): Slicer/Slicer#9163.

I also think another option we should consider is just, once identified, hiding the background segment entirely

Yes, that too!

Also, please add a note somewhere, if/when we get to creating LABELMAP in Slim, we should make sure we populate PixelPaddingValue!

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.

Add support for LABELMAP SEG

3 participants