@ohif/app 3.13.0-beta.121 → 3.13.0-beta.123

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/{1206.bundle.e04ca1efe6f987ba.js → 1206.bundle.8ca95ea92d278d25.js} +1 -1
  2. package/dist/{1602.bundle.4b753c5f05c22071.js → 1602.bundle.adc9c42f3f0cee10.js} +4 -4
  3. package/dist/{2493.bundle.f3b6a64d158365da.js → 2493.bundle.d16ea70ddcc1fb6b.js} +68 -12
  4. package/dist/{7231.bundle.1063d727ad99108a.js → 2623.bundle.983a376f7b7e86a5.js} +142 -33
  5. package/dist/{3330.bundle.b1297ef8c94e5440.js → 3330.bundle.1b8bc8f7c4071336.js} +46 -2
  6. package/dist/{3500.bundle.ba1a8fe6005447be.js → 3500.bundle.642aa0112968cf71.js} +1 -1
  7. package/dist/{3568.bundle.45dc681ef6890166.js → 3568.bundle.9aa4b4b27294ff6d.js} +41 -10
  8. package/dist/{3760.bundle.cfe49d20e6a29953.js → 3760.bundle.5e5d19b9f8d56cae.js} +4 -4
  9. package/dist/{5189.bundle.ea191ea99047fd6f.js → 5189.bundle.fc73612f2e198892.js} +2 -2
  10. package/dist/{5448.bundle.5686ebb99c379f64.js → 5448.bundle.316b091e38440aef.js} +1 -1
  11. package/dist/{5910.bundle.0f19608f3e76859b.js → 5910.bundle.d9cbcbb62ddd6638.js} +2 -2
  12. package/dist/{6495.bundle.a6764fdb8c0c252f.js → 6495.bundle.5ad5a10d2c9dcba1.js} +48 -3
  13. package/dist/{7248.bundle.5adba26c3591ab03.js → 7248.bundle.1b52f19fbd2bbc40.js} +28 -10
  14. package/dist/{7499.bundle.1b824fb1c3d9938b.js → 7499.bundle.e958878c66174ab0.js} +74 -29
  15. package/dist/{781.bundle.8317fbb14b5fc160.js → 781.bundle.f6fa3ab2b8ec22a5.js} +106 -47
  16. package/dist/{8423.bundle.884545a446ec1b71.js → 8423.bundle.d9be5db38ca5b9cd.js} +2 -2
  17. package/dist/{5642.bundle.98e17a4413db6ef1.js → 8478.bundle.163d258bf75a0aed.js} +32847 -7919
  18. package/dist/{8668.bundle.0e47f7231aa07da2.js → 8668.bundle.e254939790f776e2.js} +44 -0
  19. package/dist/{8832.bundle.7e4d2e03edaf6125.js → 8832.bundle.62e66fad140b5182.js} +3 -3
  20. package/dist/{2343.bundle.6bb1c41a0c23c387.js → 89.bundle.fe29d1712fd47341.js} +16340 -1013
  21. package/dist/{899.bundle.50c16f860acbc848.js → 899.bundle.b012ed530e343897.js} +2 -2
  22. package/dist/{9068.bundle.95f1e638ef694ea9.js → 9068.bundle.13173c70d4f33cf0.js} +2 -2
  23. package/dist/{9415.bundle.8ae772df11b43623.js → 9415.bundle.3044caa6fbf3e331.js} +2 -2
  24. package/dist/app-config.js +16 -0
  25. package/dist/{app.bundle.19807b66b97eef1c.js → app.bundle.ce26bd25f1b2d6eb.js} +297 -44
  26. package/dist/{compute.bundle.9cc3697d07fbb082.js → compute.bundle.690de60973ccebc4.js} +1 -1
  27. package/dist/index.html +1 -1
  28. package/dist/{polySeg.bundle.a526954fc2fed311.js → polySeg.bundle.369c7996934b22e3.js} +1 -1
  29. package/dist/sw.js +1 -1
  30. package/package.json +6 -6
  31. package/dist/8432.bundle.7d5ebe1ed1610bc3.js +0 -24931
  32. package/dist/8595.css +0 -2
  33. package/dist/9402.bundle.e566ac372cd263ab.js +0 -13041
  34. /package/dist/{100.bundle.18576d13e84cf65d.js → 100.bundle.a747be7c54b03050.js} +0 -0
  35. /package/dist/{1180.bundle.71384bae9915f7ef.js → 1180.bundle.12decb70e347ab18.js} +0 -0
  36. /package/dist/{1483.bundle.0856e89556f39a44.js → 1483.bundle.5d7cb3b2c8339993.js} +0 -0
  37. /package/dist/{7231.css → 2623.css} +0 -0
  38. /package/dist/{2779.bundle.c9e19f9d340f49dd.js → 2779.bundle.50f6254deda46e49.js} +0 -0
  39. /package/dist/{4556.bundle.c21eb013145d11cb.js → 4556.bundle.1ea04fd48fc5d2ca.js} +0 -0
  40. /package/dist/{4683.bundle.00b9ec64ffdac536.js → 4683.bundle.b560312b5eebd925.js} +0 -0
  41. /package/dist/{5696.bundle.1166a7d20afd2ec1.js → 5696.bundle.78c7e21c71846f7b.js} +0 -0
  42. /package/dist/{6749.bundle.46d07e206a29a04c.js → 6749.bundle.87258a158729e73d.js} +0 -0
  43. /package/dist/{8492.bundle.b2d1f0d9d97eeb99.js → 8492.bundle.1dbc1691c7db0e87.js} +0 -0
  44. /package/dist/{9116.bundle.b5fe63fa3d55bd70.js → 9116.bundle.3173fbc0a9246402.js} +0 -0
  45. /package/dist/{9290.bundle.e11c9ec528de238f.js → 9290.bundle.e84eec85a00eb7a1.js} +0 -0
  46. /package/dist/{9383.bundle.ec44c452ccc23e93.js → 9383.bundle.885123e100c1b477.js} +0 -0
  47. /package/dist/{9437.bundle.e32fbfe63bfc0e72.js → 9437.bundle.dabd58171e5f91e9.js} +0 -0
  48. /package/dist/{9560.bundle.517f0ef7ee3a20bf.js → 9560.bundle.4c9bc48e09c0bae1.js} +0 -0
@@ -639,8 +639,8 @@ function getHangingProtocolModule() {
639
639
  }
640
640
  /* export default */ const src_getHangingProtocolModule = (getHangingProtocolModule);
641
641
 
642
- // EXTERNAL MODULE: ../../../extensions/default/src/index.ts + 147 modules
643
- var default_src = __webpack_require__(7825);
642
+ // EXTERNAL MODULE: ../../../extensions/default/src/index.ts + 148 modules
643
+ var default_src = __webpack_require__(50904);
644
644
  // EXTERNAL MODULE: ../../../extensions/default/src/utils/_shared/PROMPT_RESPONSES.ts
645
645
  var PROMPT_RESPONSES = __webpack_require__(95526);
646
646
  ;// CONCATENATED MODULE: ../../../extensions/cornerstone-dicom-seg/src/commandsModule.ts
@@ -757,49 +757,59 @@ const commandsModule = ({
757
757
  // otherwise the active one (e.g. download).
758
758
  const dataSourceDefinition = dataSourceName ? extensionManager.getDataSourceDefinition(dataSourceName) : extensionManager.getActiveDataSourceDefinition();
759
759
  const dataSourceStoreOverride = dataSourceDefinition?.configuration?.segmentation?.store;
760
- const {
761
- imageIds
762
- } = segmentation.representationData.Labelmap;
763
- const segImages = imageIds.map(imageId => esm.cache.getImage(imageId));
764
- const referencedImages = segImages.map((segImage, sliceIndex) => {
765
- const referencedImage = esm.cache.getImage(segImage.referencedImageId);
766
- if (!referencedImage) {
767
- throw new Error(`Referenced source image not in cache for segmentation slice ${sliceIndex} ` + `(referencedImageId: ${segImage.referencedImageId}). Ensure the referenced series is fully loaded before storing.`);
768
- }
769
- return referencedImage;
770
- });
771
- const labelmaps2D = [];
772
- let z = 0;
773
- for (const segImage of segImages) {
774
- const segmentsOnLabelmap = new Set();
775
- const pixelData = segImage.getPixelData();
776
- const {
777
- rows,
778
- columns
779
- } = segImage;
780
-
781
- // Use a single pass through the pixel data
782
- for (let i = 0; i < pixelData.length; i++) {
783
- const segment = pixelData[i];
784
- if (segment !== 0) {
785
- segmentsOnLabelmap.add(segment);
760
+ const labelmapData = segmentation.representationData.Labelmap;
761
+
762
+ // Build a labelmap3D (one labelmaps2D entry per source slice) from a list of
763
+ // derived labelmap image ids. When `referencedImageIds` is supplied (the
764
+ // multi-layer/overlap path) each frame is indexed by its source slice so the
765
+ // layers align to the same frames; otherwise frames are sequential (the legacy
766
+ // single-layer behavior, kept byte-identical).
767
+ const buildLabelmap3D = (segImageIds, metadata, referencedImageIds) => {
768
+ const segImages = segImageIds.map(imageId => esm.cache.getImage(imageId));
769
+ const labelmaps2D = [];
770
+
771
+ // Map each source imageId to its frame index once (O(n)) so the per-slice lookup
772
+ // below is O(1) — avoids the O(slices^2) indexOf scan on the multi-layer path.
773
+ const referencedFrameIndexById = referencedImageIds ? new Map(referencedImageIds.map((imageId, index) => [imageId, index])) : undefined;
774
+ let z = 0;
775
+ for (const segImage of segImages) {
776
+ const segmentsOnLabelmap = new Set();
777
+ const pixelData = segImage.getPixelData();
778
+ const {
779
+ rows,
780
+ columns
781
+ } = segImage;
782
+
783
+ // Use a single pass through the pixel data
784
+ for (let i = 0; i < pixelData.length; i++) {
785
+ const segment = pixelData[i];
786
+ if (segment !== 0) {
787
+ segmentsOnLabelmap.add(segment);
788
+ }
786
789
  }
790
+ const frameIndex = referencedFrameIndexById ? referencedFrameIndexById.get(segImage.referencedImageId) ?? -1 : z++;
791
+ if (frameIndex < 0) {
792
+ continue;
793
+ }
794
+ labelmaps2D[frameIndex] = {
795
+ segmentsOnLabelmap: Array.from(segmentsOnLabelmap),
796
+ pixelData,
797
+ rows,
798
+ columns
799
+ };
787
800
  }
788
- labelmaps2D[z++] = {
789
- segmentsOnLabelmap: Array.from(segmentsOnLabelmap),
790
- pixelData,
791
- rows,
792
- columns
801
+ const allSegmentsOnLabelmap = labelmaps2D.filter(Boolean).map(labelmap => labelmap.segmentsOnLabelmap);
802
+ return {
803
+ segmentsOnLabelmap: Array.from(new Set(allSegmentsOnLabelmap.flat())),
804
+ metadata,
805
+ labelmaps2D
793
806
  };
794
- }
795
- const allSegmentsOnLabelmap = labelmaps2D.map(labelmap => labelmap.segmentsOnLabelmap);
796
- const labelmap3D = {
797
- segmentsOnLabelmap: Array.from(new Set(allSegmentsOnLabelmap.flat())),
798
- metadata: [],
799
- labelmaps2D
800
807
  };
808
+
809
+ // Segment metadata (shared across all layers).
801
810
  const segmentationInOHIF = segmentationService.getSegmentation(segmentationId);
802
811
  const representations = segmentationService.getRepresentationsForSegmentation(segmentationId);
812
+ const metadata = [];
803
813
  Object.entries(segmentationInOHIF.segments).forEach(([segmentIndex, segment]) => {
804
814
  // segmentation service already has a color for each segment
805
815
  if (!segment) {
@@ -811,7 +821,7 @@ const commandsModule = ({
811
821
  const firstRepresentation = representations[0];
812
822
  const color = segmentationService.getSegmentColor(firstRepresentation.viewportId, segmentationId, segment.segmentIndex);
813
823
  const RecommendedDisplayCIELabValue = dcmjs_es/* ["default"].data.Colors.rgb2DICOMLAB */.Ay.data.Colors.rgb2DICOMLAB(color.slice(0, 3).map(value => value / 255)).map(value => Math.round(value));
814
- const segmentMetadata = {
824
+ metadata[segmentIndex] = {
815
825
  SegmentNumber: segmentIndex.toString(),
816
826
  SegmentLabel: label,
817
827
  SegmentAlgorithmType: segment?.algorithmType || 'MANUAL',
@@ -828,13 +838,58 @@ const commandsModule = ({
828
838
  CodeMeaning: 'Tissue'
829
839
  }
830
840
  };
831
- labelmap3D.metadata[segmentIndex] = segmentMetadata;
832
841
  });
833
- const generatedSegmentation = generateSegmentation(referencedImages, labelmap3D, esm.metaData, {
842
+
843
+ // Multi-layer (overlapping) SEGs register one labelmap layer per conflict-free
844
+ // group. Export each layer as its own labelmap3D against the UNIQUE referenced
845
+ // source series, so cornerstone writes overlapping segments as separate frames
846
+ // that reference the same source slice (the DICOM SEG overlap encoding). The
847
+ // cs3D adapter's fillSegmentation accepts an array of labelmap3D for exactly
848
+ // this. Single-layer SEGs keep the original single-labelmap3D path unchanged.
849
+ const layers = labelmapData.labelmaps ? Object.values(labelmapData.labelmaps) : undefined;
850
+
851
+ // The referenced source images must be fully loaded (in cache) before we can
852
+ // build the SEG dataset against them; fail loudly rather than passing undefined
853
+ // frames to the adapter.
854
+ const resolveReferencedImage = (referencedImageId, sliceIndex) => {
855
+ const referencedImage = esm.cache.getImage(referencedImageId);
856
+ if (!referencedImage) {
857
+ throw new Error(`Referenced source image not in cache for segmentation slice ${sliceIndex} ` + `(referencedImageId: ${referencedImageId}). Ensure the referenced series is fully loaded before storing.`);
858
+ }
859
+ return referencedImage;
860
+ };
861
+ let referencedImages;
862
+ let labelmaps3D;
863
+ if (layers && layers.length > 1) {
864
+ const referencedImageIds = layers[0].referencedImageIds ?? labelmapData.referencedImageIds ?? [];
865
+ referencedImages = referencedImageIds.map(resolveReferencedImage);
866
+ labelmaps3D = layers.map(layer => buildLabelmap3D(layer.imageIds ?? [], metadata, referencedImageIds));
867
+ } else {
868
+ const {
869
+ imageIds
870
+ } = labelmapData;
871
+ const segImages = imageIds.map(imageId => esm.cache.getImage(imageId));
872
+ referencedImages = segImages.map((image, sliceIndex) => resolveReferencedImage(image.referencedImageId, sliceIndex));
873
+ labelmaps3D = buildLabelmap3D(imageIds, metadata);
874
+ }
875
+ const saveOptions = {
834
876
  predecessorImageId,
835
877
  ...getSegmentationSaveOptions(customizationService, dataSourceStoreOverride),
836
878
  ...generateOptions
837
- });
879
+ };
880
+
881
+ // A LABELMAP SEG frame stores a single label per voxel, so the labelmap
882
+ // encoder cannot represent overlapping segments — it keeps only the last
883
+ // layer written to each voxel. Overlapping segmentations arrive here as
884
+ // multiple layers, so switch those to the binary SEG encoding, which
885
+ // writes overlapping segments as separate frames referencing the same
886
+ // source slice.
887
+ const hasOverlappingLayers = Boolean(layers && layers.length > 1);
888
+ if (hasOverlappingLayers && saveOptions.sopClassUID === LABELMAP_SEG_SOP_CLASS_UID) {
889
+ console.warn('generateSegmentation: overlapping segments cannot be stored as a LABELMAP SEG; ' + 'switching to the binary SEG encoding for this store.');
890
+ saveOptions.sopClassUID = BITMAP_SEG_SOP_CLASS_UID;
891
+ }
892
+ const generatedSegmentation = generateSegmentation(referencedImages, labelmaps3D, esm.metaData, saveOptions);
838
893
  return generatedSegmentation;
839
894
  },
840
895
  /**
@@ -1037,8 +1092,8 @@ function getCustomizationModule() {
1037
1092
  value: customizations_segmentationCustomization
1038
1093
  }];
1039
1094
  }
1040
- // EXTERNAL MODULE: ../../../extensions/cornerstone/src/index.tsx + 200 modules
1041
- var cornerstone_src = __webpack_require__(86714);
1095
+ // EXTERNAL MODULE: ../../../extensions/cornerstone/src/index.tsx + 211 modules
1096
+ var cornerstone_src = __webpack_require__(75609);
1042
1097
  // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3682 modules
1043
1098
  var ui_next_src = __webpack_require__(39987);
1044
1099
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/index.js
@@ -1094,7 +1149,8 @@ function SegmentSelector({
1094
1149
  onValueChange: onValueChange,
1095
1150
  value: value
1096
1151
  }, /*#__PURE__*/react.createElement(ui_next_src/* .SelectTrigger */.bqE, {
1097
- className: "overflow-hidden"
1152
+ className: "overflow-hidden",
1153
+ "data-cy": `logical-contour-segment-${label.toLowerCase()}-trigger`
1098
1154
  }, /*#__PURE__*/react.createElement(ui_next_src/* .SelectValue */.yvm, {
1099
1155
  placeholder: t(placeholder)
1100
1156
  })), /*#__PURE__*/react.createElement(ui_next_src/* .SelectContent */.gCo, null, segments.map(segment => /*#__PURE__*/react.createElement(ui_next_src/* .SelectItem */.ebT, {
@@ -1182,7 +1238,8 @@ function LogicalContourOperationOptions() {
1182
1238
  return /*#__PURE__*/react.createElement(ui_next_src/* .TabsTrigger */.Xib, {
1183
1239
  value: value,
1184
1240
  key: `logical-contour-operation-${value}`,
1185
- onClick: () => setOperation(option)
1241
+ onClick: () => setOperation(option),
1242
+ "data-cy": `logical-contour-operation-${value}`
1186
1243
  }, /*#__PURE__*/react.createElement(ui_next_src/* .Icons.ByName */.FI1.ByName, {
1187
1244
  name: icon
1188
1245
  }));
@@ -1203,6 +1260,7 @@ function LogicalContourOperationOptions() {
1203
1260
  }), /*#__PURE__*/react.createElement("div", {
1204
1261
  className: "flex justify-end pl-[34px]"
1205
1262
  }, /*#__PURE__*/react.createElement(ui_next_src/* .Button */.$nd, {
1263
+ "data-cy": "apply-logical-contour-operation",
1206
1264
  className: "border-primary/60 grow border",
1207
1265
  variant: "ghost",
1208
1266
  onClick: () => {
@@ -1216,6 +1274,7 @@ function LogicalContourOperationOptions() {
1216
1274
  className: "flex items-center justify-start gap-2"
1217
1275
  }, /*#__PURE__*/react.createElement(ui_next_src/* .Switch */.dOG, {
1218
1276
  id: "logical-contour-operations-create-new-segment-switch",
1277
+ "data-cy": "logical-contour-create-new-segment-switch",
1219
1278
  onCheckedChange: setCreateNewSegment
1220
1279
  }), /*#__PURE__*/react.createElement(ui_next_src/* .Label */.JU7, {
1221
1280
  htmlFor: "logical-contour-operations-create-new-segment-switch"
@@ -484,8 +484,8 @@ function getCustomizationModule() {
484
484
  /* export default */ const maxNumImageFrames = ((study, extraData) => Math.max(...(extraData?.displaySets?.map?.(ds => ds.numImageFrames ?? 0) || [0])));
485
485
  // EXTERNAL MODULE: ../../../node_modules/react/index.js
486
486
  var react = __webpack_require__(86326);
487
- // EXTERNAL MODULE: ../../../extensions/cornerstone/src/index.tsx + 200 modules
488
- var src = __webpack_require__(86714);
487
+ // EXTERNAL MODULE: ../../../extensions/cornerstone/src/index.tsx + 211 modules
488
+ var src = __webpack_require__(75609);
489
489
  ;// CONCATENATED MODULE: ../../../extensions/test-extension/src/getPanelModule.tsx
490
490
 
491
491