@ohif/app 3.12.0-beta.76 → 3.12.0-beta.78

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/{147.bundle.23cc8fbbd94c0b65d337.js → 147.bundle.53fe889b205dd91c245b.js} +2 -2
  2. package/dist/{1604.bundle.be258dabc41390df344a.js → 1604.bundle.0d3b54b754c97de7aa88.js} +5 -5
  3. package/dist/{1919.bundle.06157a0c305d32dc0686.js → 1919.bundle.099a3ad4025e527284b0.js} +6 -6
  4. package/dist/{2701.bundle.4c715c1d9bb7828886d8.js → 2701.bundle.6418ae6e9e372ccae322.js} +4 -4
  5. package/dist/{9856.bundle.31827ec7e09a8978744c.js → 306.bundle.a2380c4b23436c127faf.js} +110 -1
  6. package/dist/{9892.bundle.7a23896727af274e8c43.js → 3190.bundle.cd955568fe4d80ab2e4b.js} +115 -2
  7. package/dist/{3613.bundle.14721af2527117f720b0.js → 3613.bundle.f5fceb4697407a89921b.js} +65 -108
  8. package/dist/{4019.bundle.acd0f85d0467cb10d86a.js → 4019.bundle.6505ff57ca48af03da8a.js} +3 -6
  9. package/dist/{7197.bundle.87ad61b63709fa4e7931.js → 4092.bundle.48390d480273857e794e.js} +338 -7
  10. package/dist/{7197.css → 4092.css} +1 -0
  11. package/dist/{4113.bundle.cde76f3e8b32d2af685e.js → 4113.bundle.8e8cca0c8fbf690e7b93.js} +2 -2
  12. package/dist/{414.bundle.46e21842faff1e8bbba1.js → 414.bundle.597500ee9c214b0a7212.js} +8 -8
  13. package/dist/{4202.bundle.1cef28d8aec1155d35d1.js → 4202.bundle.1c5271f1cacf5794aba7.js} +2 -2
  14. package/dist/{5349.bundle.14d76a9cb0f587c90614.js → 5349.bundle.6bf58c3e9e9571fa8a7d.js} +4 -4
  15. package/dist/{5457.bundle.dc13074667c75d5f535d.js → 5457.bundle.9758280deb7db83edb99.js} +0 -8
  16. package/dist/{5485.bundle.3ea12c6fc33a5e36ad91.js → 5485.bundle.aafe4c0e2e9e2afd878d.js} +0 -8
  17. package/dist/{5802.bundle.48e7f1324fc9e4486603.js → 5802.bundle.8922caf16c088b10cdb0.js} +2 -2
  18. package/dist/{6201.bundle.324015c05481ff7de620.js → 6201.bundle.b0a52e8b23e83d7820d6.js} +2 -2
  19. package/dist/{8815.bundle.c79ac728379c1869be34.js → 6725.bundle.75f59fc21a7fbecb9bce.js} +468 -37
  20. package/dist/{6991.bundle.30771aade45e20788c23.js → 6991.bundle.500dbaf5bec95a3d49d2.js} +2 -2
  21. package/dist/{7412.bundle.a8aa0b243b2a05031789.js → 7412.bundle.94802a6a629f62daab88.js} +2 -2
  22. package/dist/{3409.bundle.04c822ec34d5d6c9b0af.js → 7948.bundle.8c0bd83ffaacabc3dcbd.js} +918 -249
  23. package/dist/{810.bundle.55fc6ba6d7b593558a69.js → 810.bundle.d31e9fd894cac5ec768a.js} +6 -6
  24. package/dist/{8558.bundle.7a27346ef479a9690733.js → 8558.bundle.83d96d728f9f186ea5ad.js} +1 -1
  25. package/dist/{934.bundle.7cf27b71ceda28ed08d1.js → 934.bundle.a25daa6ed5038a83faf8.js} +2 -2
  26. package/dist/{1447.bundle.0a31b7c6fb44339bea7e.js → 9548.bundle.9e723f4ad09b9c1b431a.js} +69 -43
  27. package/dist/{8740.bundle.39b40ee21a873e824ce8.js → 9845.bundle.6ee5ca8fe9f68cefd56d.js} +5 -5
  28. package/dist/{9862.bundle.dc627e5f01fc4698a00f.js → 9862.bundle.e2c4c129f7907500b840.js} +2 -2
  29. package/dist/{app.bundle.a2374869593ba63a0d94.js → app.bundle.0cf7e86910258d22401b.js} +487 -148
  30. package/dist/app.bundle.css +1 -1
  31. package/dist/{compute.bundle.5d0df54f99d2a555a02a.js → compute.bundle.f6f1236073e2a486ddfb.js} +3 -3
  32. package/dist/index.html +1 -1
  33. package/dist/{polySeg.bundle.eb47d9d9105dcfbb56fc.js → polySeg.bundle.d0ed88f3bfea700c211b.js} +3 -3
  34. package/dist/sw.js +1 -1
  35. package/package.json +21 -21
  36. package/dist/8740.css +0 -1
  37. /package/dist/{1459.bundle.bdf22c0d63ec1b2519dc.js → 1459.bundle.c878b794be71883de852.js} +0 -0
  38. /package/dist/{1807.bundle.810171e611515ea8cb58.js → 1807.bundle.ade363b62ad3a0442a9c.js} +0 -0
  39. /package/dist/{213.bundle.b5a02d8b38e4c17b1b0e.js → 213.bundle.1cc1975ae90ca2eadfd5.js} +0 -0
  40. /package/dist/{2243.bundle.1bb57e90de774280b935.js → 2243.bundle.a4c417be34f113e1fbc6.js} +0 -0
  41. /package/dist/{2424.bundle.99953053dd849df7ee56.js → 2424.bundle.22082b8a1483bc47cbb1.js} +0 -0
  42. /package/dist/{2518.bundle.bdbd870da5355fdf502a.js → 2518.bundle.b21d8c66dc8deb8ba922.js} +0 -0
  43. /package/dist/{319.bundle.cd9383a345b9da2ba840.js → 319.bundle.f5adcbbef5767dedc45d.js} +0 -0
  44. /package/dist/{6027.bundle.e9ec5f8022d806495795.js → 6027.bundle.5649e4e1fde732251102.js} +0 -0
  45. /package/dist/{7159.bundle.a472333e58e930b53e22.js → 7159.bundle.a5991a5d4f0dd8f1c95f.js} +0 -0
  46. /package/dist/{7431.bundle.6dee1ec831da974a7433.js → 7431.bundle.ad1982d7c54a5931d409.js} +0 -0
  47. /package/dist/{7639.bundle.11226f984521a7530cd7.js → 7639.bundle.c6ee8cf4672716943e89.js} +0 -0
  48. /package/dist/{85.bundle.70a34e52cc20a6d042da.js → 85.bundle.b1586702f9300c017632.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[3409],{
2
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[7948],{
3
3
 
4
4
  /***/ 38007:
5
5
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
@@ -25,8 +25,8 @@ var useSegmentations = __webpack_require__(73421);
25
25
  var useViewportSegmentations = __webpack_require__(79063);
26
26
  // EXTERNAL MODULE: ../../../node_modules/react/index.js
27
27
  var react = __webpack_require__(86326);
28
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3072 modules
29
- var src = __webpack_require__(42606);
28
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3073 modules
29
+ var src = __webpack_require__(1246);
30
30
  ;// ../../../extensions/cornerstone/src/hooks/useViewportHover.ts
31
31
 
32
32
 
@@ -117,7 +117,7 @@ var useViewportRendering = __webpack_require__(47488);
117
117
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
118
118
  /* harmony export */ c: () => (/* binding */ useActiveViewportSegmentationRepresentations)
119
119
  /* harmony export */ });
120
- /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(42606);
120
+ /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1246);
121
121
  /* harmony import */ var _useViewportSegmentations__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(79063);
122
122
 
123
123
 
@@ -496,8 +496,8 @@ __webpack_require__.d(__webpack_exports__, {
496
496
  var react = __webpack_require__(86326);
497
497
  // EXTERNAL MODULE: ../../core/src/index.ts + 69 modules
498
498
  var src = __webpack_require__(42356);
499
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3072 modules
500
- var ui_next_src = __webpack_require__(42606);
499
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3073 modules
500
+ var ui_next_src = __webpack_require__(1246);
501
501
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 1 modules
502
502
  var esm = __webpack_require__(15327);
503
503
  ;// ../../../extensions/cornerstone/src/components/ViewportDataOverlaySettingMenu/utils.ts
@@ -1322,7 +1322,7 @@ function useViewportRendering(viewportId, options) {
1322
1322
  return colormap;
1323
1323
  }
1324
1324
  const actorEntries = viewport.getActors();
1325
- const actorEntry = actorEntries?.find(entry => entry.referencedId.includes(activeDisplaySetInstanceUID));
1325
+ const actorEntry = actorEntries?.find(entry => entry.referencedId?.includes(activeDisplaySetInstanceUID));
1326
1326
  if (!actorEntry) {
1327
1327
  return colorbarProperties?.colormaps?.find(c => c.Name === 'Grayscale') || colorbarProperties?.colormaps?.[0];
1328
1328
  }
@@ -1657,7 +1657,7 @@ function useViewportSegmentations({
1657
1657
 
1658
1658
  /***/ }),
1659
1659
 
1660
- /***/ 23409:
1660
+ /***/ 37948:
1661
1661
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1662
1662
 
1663
1663
  // ESM COMPAT FLAG
@@ -1718,6 +1718,7 @@ __webpack_require__.d(__webpack_exports__, {
1718
1718
  usePositionPresentationStore: () => (/* reexport */ usePositionPresentationStore/* usePositionPresentationStore */.q),
1719
1719
  useSegmentationPresentationStore: () => (/* reexport */ useSegmentationPresentationStore/* useSegmentationPresentationStore */.v),
1720
1720
  useSegmentations: () => (/* reexport */ useSegmentations/* useSegmentations */.j),
1721
+ useSelectedSegmentationsForViewportStore: () => (/* reexport */ useSelectedSegmentationsForViewportStore),
1721
1722
  useSynchronizersStore: () => (/* reexport */ useSynchronizersStore/* useSynchronizersStore */.U),
1722
1723
  utils: () => (/* reexport */ src_utils)
1723
1724
  });
@@ -1807,8 +1808,8 @@ function destroy() {
1807
1808
  var ai_dist_esm = __webpack_require__(75165);
1808
1809
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/polymorphic-segmentation/dist/esm/index.js + 14 modules
1809
1810
  var polymorphic_segmentation_dist_esm = __webpack_require__(56983);
1810
- // EXTERNAL MODULE: ../../../extensions/default/src/index.ts + 139 modules
1811
- var default_src = __webpack_require__(11447);
1811
+ // EXTERNAL MODULE: ../../../extensions/default/src/index.ts + 141 modules
1812
+ var default_src = __webpack_require__(39548);
1812
1813
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/state.ts
1813
1814
  var state = __webpack_require__(71353);
1814
1815
  ;// ../../../extensions/cornerstone/src/utils/getViewportEnabledElement.ts
@@ -2246,6 +2247,10 @@ function initCornerstoneTools(configuration = {}) {
2246
2247
  (0,dist_esm.addTool)(ai_dist_esm/* LabelmapSlicePropagationTool */.Bj);
2247
2248
  (0,dist_esm.addTool)(ai_dist_esm/* MarkerLabelmapTool */.pY);
2248
2249
  (0,dist_esm.addTool)(dist_esm.RegionSegmentPlusTool);
2250
+ (0,dist_esm.addTool)(dist_esm.LivewireContourSegmentationTool);
2251
+ (0,dist_esm.addTool)(dist_esm.SculptorTool);
2252
+ (0,dist_esm.addTool)(dist_esm.SplineContourSegmentationTool);
2253
+ (0,dist_esm.addTool)(dist_esm.LabelMapEditWithContourTool);
2249
2254
  // Modify annotation tools to use dashed lines on SR
2250
2255
  const annotationStyle = {
2251
2256
  textBoxFontSize: '15px',
@@ -2302,7 +2307,11 @@ const toolNames = {
2302
2307
  SegmentLabel: dist_esm.SegmentLabelTool.toolName,
2303
2308
  LabelmapSlicePropagation: ai_dist_esm/* LabelmapSlicePropagationTool */.Bj.toolName,
2304
2309
  MarkerLabelmap: ai_dist_esm/* MarkerLabelmapTool */.pY.toolName,
2305
- RegionSegmentPlus: dist_esm.RegionSegmentPlusTool.toolName
2310
+ RegionSegmentPlus: dist_esm.RegionSegmentPlusTool.toolName,
2311
+ LivewireContourSegmentation: dist_esm.LivewireContourSegmentationTool.toolName,
2312
+ SculptorTool: dist_esm.SculptorTool.toolName,
2313
+ SplineContourSegmentation: dist_esm.SplineContourSegmentationTool.toolName,
2314
+ LabelMapEditWithContourTool: dist_esm.LabelMapEditWithContourTool.toolName
2306
2315
  };
2307
2316
 
2308
2317
  ;// ../../../extensions/cornerstone/src/utils/measurementServiceMappings/constants/supportedTools.js
@@ -6325,7 +6334,7 @@ function interleaveCenterLoader({
6325
6334
  // the imageIds and save them in AllRequests for later use
6326
6335
  const AllRequests = [];
6327
6336
  volumes.forEach(volume => {
6328
- const requests = volume.getImageLoadRequests();
6337
+ const requests = volume.getImageLoadRequests?.() ?? [];
6329
6338
  if (!requests.length || !requests[0] || !requests[0].imageId) {
6330
6339
  return;
6331
6340
  }
@@ -6621,7 +6630,7 @@ function interleaveTopToBottom({
6621
6630
  // the imageIds and save them in AllRequests for later use
6622
6631
  const AllRequests = [];
6623
6632
  volumes.forEach(volume => {
6624
- const requests = volume.getImageLoadRequests();
6633
+ const requests = volume.getImageLoadRequests?.() ?? [];
6625
6634
  if (!requests?.[0]?.imageId) {
6626
6635
  return;
6627
6636
  }
@@ -7171,6 +7180,7 @@ async function init({
7171
7180
  toolbarService
7172
7181
  } = servicesManager.services;
7173
7182
  toolbarService.registerEventForToolbarUpdate(colorbarService, [colorbarService.EVENTS.STATE_CHANGED]);
7183
+ toolbarService.registerEventForToolbarUpdate(segmentationService, [segmentationService.EVENTS.SEGMENTATION_MODIFIED, segmentationService.EVENTS.SEGMENTATION_REPRESENTATION_MODIFIED, segmentationService.EVENTS.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED]);
7174
7184
  window.services = servicesManager.services;
7175
7185
  window.extensionManager = extensionManager;
7176
7186
  window.commandsManager = commandsManager;
@@ -7446,16 +7456,85 @@ function _showCPURenderingModal(uiModalService, hangingProtocolService) {
7446
7456
  inheritsFrom: 'ohif.overlayItem.instanceNumber'
7447
7457
  }]
7448
7458
  });
7449
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3072 modules
7450
- var ui_next_src = __webpack_require__(42606);
7459
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3073 modules
7460
+ var ui_next_src = __webpack_require__(1246);
7451
7461
  // EXTERNAL MODULE: ../../../node_modules/react-i18next/dist/es/index.js + 15 modules
7452
7462
  var es = __webpack_require__(99993);
7463
+ ;// ../../../extensions/cornerstone/src/components/ExportSegmentationSubMenuItem.tsx
7464
+
7465
+
7466
+
7467
+
7468
+ const ExportSegmentationSubMenuItem = ({
7469
+ segmentationId,
7470
+ segmentationRepresentationType,
7471
+ allowExport,
7472
+ actions
7473
+ }) => {
7474
+ const {
7475
+ t
7476
+ } = (0,es/* useTranslation */.Bd)('SegmentationTable');
7477
+ return /*#__PURE__*/react.createElement(react.Fragment, null, segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSub */.lvB, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubTrigger */.nVd, {
7478
+ className: "pl-1"
7479
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7480
+ className: "text-foreground"
7481
+ }), /*#__PURE__*/react.createElement("span", {
7482
+ className: "pl-2"
7483
+ }, t('Download & Export'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuPortal */.dce, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubContent */.M56, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuLabel */.lpj, {
7484
+ className: "flex items-center pl-0"
7485
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Download, {
7486
+ className: "h-5 w-5"
7487
+ }), /*#__PURE__*/react.createElement("span", {
7488
+ className: "pl-1"
7489
+ }, t('Download'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7490
+ onClick: e => {
7491
+ e.preventDefault();
7492
+ actions.downloadCSVSegmentationReport(segmentationId);
7493
+ },
7494
+ disabled: !allowExport
7495
+ }, t('CSV Report')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7496
+ onClick: e => {
7497
+ e.preventDefault();
7498
+ actions.onSegmentationDownload(segmentationId);
7499
+ },
7500
+ disabled: !allowExport
7501
+ }, t('DICOM SEG')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7502
+ onClick: e => {
7503
+ e.preventDefault();
7504
+ actions.onSegmentationDownloadRTSS(segmentationId);
7505
+ },
7506
+ disabled: !allowExport
7507
+ }, t('DICOM RTSS')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuLabel */.lpj, {
7508
+ className: "flex items-center pl-0"
7509
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7510
+ className: "h-5 w-5"
7511
+ }), /*#__PURE__*/react.createElement("span", {
7512
+ className: "pl-1 pt-1"
7513
+ }, t('Export'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7514
+ onClick: e => {
7515
+ e.preventDefault();
7516
+ actions.storeSegmentation(segmentationId);
7517
+ },
7518
+ disabled: !allowExport
7519
+ }, t('DICOM SEG'))))), segmentationRepresentationType === esm_enums.SegmentationRepresentations.Contour && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7520
+ onClick: e => {
7521
+ e.preventDefault();
7522
+ actions.onSegmentationDownloadRTSS(segmentationId);
7523
+ },
7524
+ disabled: !allowExport
7525
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7526
+ className: "text-foreground"
7527
+ }), /*#__PURE__*/react.createElement("span", {
7528
+ className: "pl-2"
7529
+ }, t('Download DICOM RTSS')))));
7530
+ };
7453
7531
  ;// ../../../extensions/cornerstone/src/customizations/CustomDropdownMenuContent.tsx
7454
7532
 
7455
7533
 
7456
7534
 
7457
7535
 
7458
7536
 
7537
+
7459
7538
  /**
7460
7539
  * Custom dropdown menu component for segmentation panel that uses context for data
7461
7540
  */
@@ -7473,7 +7552,9 @@ const CustomDropdownMenuContent = () => {
7473
7552
  onSegmentationDelete,
7474
7553
  exportOptions,
7475
7554
  activeSegmentation,
7476
- activeSegmentationId
7555
+ activeSegmentationId,
7556
+ segmentationRepresentationType,
7557
+ disableEditing
7477
7558
  } = (0,ui_next_src/* useSegmentationTableContext */.dQ$)('CustomDropdownMenu');
7478
7559
 
7479
7560
  // Try to get segmentation data from expanded context first, fall back to table context
@@ -7527,8 +7608,11 @@ const CustomDropdownMenuContent = () => {
7527
7608
  };
7528
7609
  return /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuContent */.SQm, {
7529
7610
  align: "start"
7530
- }, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7531
- onClick: () => onSegmentationAdd(segmentationId)
7611
+ }, !disableEditing && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7612
+ onClick: () => onSegmentationAdd({
7613
+ segmentationId,
7614
+ segmentationRepresentationType
7615
+ })
7532
7616
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Add, {
7533
7617
  className: "text-foreground"
7534
7618
  }), /*#__PURE__*/react.createElement("span", {
@@ -7545,49 +7629,12 @@ const CustomDropdownMenuContent = () => {
7545
7629
  className: "text-foreground"
7546
7630
  }), /*#__PURE__*/react.createElement("span", {
7547
7631
  className: "pl-2"
7548
- }, t('Rename'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSub */.lvB, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubTrigger */.nVd, {
7549
- className: "pl-1"
7550
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7551
- className: "text-foreground"
7552
- }), /*#__PURE__*/react.createElement("span", {
7553
- className: "pl-2"
7554
- }, t('Download & Export'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuPortal */.dce, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubContent */.M56, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuLabel */.lpj, {
7555
- className: "flex items-center pl-0"
7556
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Download, {
7557
- className: "h-5 w-5"
7558
- }), /*#__PURE__*/react.createElement("span", {
7559
- className: "pl-1"
7560
- }, t('Download'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7561
- onClick: e => {
7562
- e.preventDefault();
7563
- actions.downloadCSVSegmentationReport(segmentationId);
7564
- },
7565
- disabled: !allowExport
7566
- }, t('CSV Report')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7567
- onClick: e => {
7568
- e.preventDefault();
7569
- actions.onSegmentationDownload(segmentationId);
7570
- },
7571
- disabled: !allowExport
7572
- }, t('DICOM SEG')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7573
- onClick: e => {
7574
- e.preventDefault();
7575
- actions.onSegmentationDownloadRTSS(segmentationId);
7576
- },
7577
- disabled: !allowExport
7578
- }, t('DICOM RTSS')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuLabel */.lpj, {
7579
- className: "flex items-center pl-0"
7580
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7581
- className: "h-5 w-5"
7582
- }), /*#__PURE__*/react.createElement("span", {
7583
- className: "pl-1 pt-1"
7584
- }, t('Export'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7585
- onClick: e => {
7586
- e.preventDefault();
7587
- actions.storeSegmentation(segmentationId);
7588
- },
7589
- disabled: !allowExport
7590
- }, t('DICOM SEG'))))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7632
+ }, t('Rename'))), /*#__PURE__*/react.createElement(ExportSegmentationSubMenuItem, {
7633
+ segmentationId: segmentationId,
7634
+ segmentationRepresentationType: segmentationRepresentationType,
7635
+ allowExport: allowExport,
7636
+ actions: actions
7637
+ }), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7591
7638
  onClick: () => onSegmentationDelete(segmentationId)
7592
7639
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Delete, {
7593
7640
  className: "text-red-600"
@@ -7707,11 +7754,83 @@ const CustomSegmentStatisticsHeader = ({
7707
7754
  className: "bg-input"
7708
7755
  }));
7709
7756
  };
7757
+ ;// ../../../extensions/cornerstone/src/components/SegmentationToolConfig.tsx
7758
+
7759
+
7760
+
7761
+ function SegmentationToolConfig() {
7762
+ const {
7763
+ commandsManager
7764
+ } = (0,src/* useSystem */.Jg)();
7765
+
7766
+ // Get initial states based on current configuration
7767
+ const [previewEdits, setPreviewEdits] = (0,react.useState)(false);
7768
+ const [segmentLabelEnabled, setSegmentLabelEnabled] = (0,react.useState)(false);
7769
+ const [toggleSegmentEnabled, setToggleSegmentEnabled] = (0,react.useState)(false);
7770
+ const [useCenterAsSegmentIndex, setUseCenterAsSegmentIndex] = (0,react.useState)(false);
7771
+ const handlePreviewEditsChange = checked => {
7772
+ setPreviewEdits(checked);
7773
+ commandsManager.run('toggleSegmentPreviewEdit', {
7774
+ toggle: checked
7775
+ });
7776
+ };
7777
+ const handleToggleSegmentEnabledChange = checked => {
7778
+ setToggleSegmentEnabled(checked);
7779
+ commandsManager.run('toggleSegmentSelect', {
7780
+ toggle: checked
7781
+ });
7782
+ };
7783
+ const handleUseCenterAsSegmentIndexChange = checked => {
7784
+ setUseCenterAsSegmentIndex(checked);
7785
+ commandsManager.run('toggleUseCenterSegmentIndex', {
7786
+ toggle: checked
7787
+ });
7788
+ };
7789
+ const handleSegmentLabelEnabledChange = checked => {
7790
+ setSegmentLabelEnabled(checked);
7791
+ commandsManager.run('toggleSegmentLabel', {
7792
+ enabled: checked
7793
+ });
7794
+ };
7795
+ return /*#__PURE__*/react.createElement("div", {
7796
+ className: "bg-muted flex flex-col gap-2 border-b border-b-[2px] border-black px-2 py-3"
7797
+ }, /*#__PURE__*/react.createElement("div", {
7798
+ className: "flex items-center gap-2"
7799
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7800
+ checked: previewEdits,
7801
+ onCheckedChange: handlePreviewEditsChange
7802
+ }), /*#__PURE__*/react.createElement("span", {
7803
+ className: "text-foreground text-base"
7804
+ }, "Preview edits before creating")), /*#__PURE__*/react.createElement("div", {
7805
+ className: "flex items-center gap-2"
7806
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7807
+ checked: useCenterAsSegmentIndex,
7808
+ onCheckedChange: handleUseCenterAsSegmentIndexChange
7809
+ }), /*#__PURE__*/react.createElement("span", {
7810
+ className: "text-foreground text-base"
7811
+ }, "Use center as segment index")), /*#__PURE__*/react.createElement("div", {
7812
+ className: "flex items-center gap-2"
7813
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7814
+ checked: toggleSegmentEnabled,
7815
+ onCheckedChange: handleToggleSegmentEnabledChange
7816
+ }), /*#__PURE__*/react.createElement("span", {
7817
+ className: "text-foreground text-base"
7818
+ }, "Hover on segment border to activate")), /*#__PURE__*/react.createElement("div", {
7819
+ className: "flex items-center gap-2"
7820
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7821
+ checked: segmentLabelEnabled,
7822
+ onCheckedChange: handleSegmentLabelEnabledChange
7823
+ }), /*#__PURE__*/react.createElement("span", {
7824
+ className: "text-foreground text-base"
7825
+ }, "Show segment name on hover")));
7826
+ }
7710
7827
  ;// ../../../extensions/cornerstone/src/customizations/segmentationPanelCustomization.tsx
7711
7828
 
7712
7829
 
7713
7830
 
7714
7831
 
7832
+
7833
+
7715
7834
  function getSegmentationPanelCustomization({
7716
7835
  commandsManager,
7717
7836
  servicesManager
@@ -7721,14 +7840,29 @@ function getSegmentationPanelCustomization({
7721
7840
  'panelSegmentation.customSegmentStatisticsHeader': CustomSegmentStatisticsHeader,
7722
7841
  'panelSegmentation.disableEditing': false,
7723
7842
  'panelSegmentation.showAddSegment': true,
7724
- 'panelSegmentation.onSegmentationAdd': () => {
7843
+ 'panelSegmentation.onSegmentationAdd': async ({
7844
+ segmentationRepresentationType = esm_enums.SegmentationRepresentations.Labelmap
7845
+ }) => {
7725
7846
  const {
7726
7847
  viewportGridService
7727
7848
  } = servicesManager.services;
7728
7849
  const viewportId = viewportGridService.getState().activeViewportId;
7729
- commandsManager.run('createLabelmapForViewport', {
7730
- viewportId
7731
- });
7850
+ if (segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap) {
7851
+ commandsManager.run('createLabelmapForViewport', {
7852
+ viewportId
7853
+ });
7854
+ } else if (segmentationRepresentationType === esm_enums.SegmentationRepresentations.Contour) {
7855
+ const segmentationId = await commandsManager.run('createContourForViewport', {
7856
+ viewportId
7857
+ });
7858
+ dist_esm.segmentation.config.style.setStyle({
7859
+ segmentationId,
7860
+ type: esm_enums.SegmentationRepresentations.Contour
7861
+ }, {
7862
+ fillAlpha: 0.5,
7863
+ renderFill: true
7864
+ });
7865
+ }
7732
7866
  },
7733
7867
  'panelSegmentation.tableMode': 'collapsed',
7734
7868
  'panelSegmentation.readableText': {
@@ -7749,67 +7883,11 @@ function getSegmentationPanelCustomization({
7749
7883
  lesionGlycolysis: 'Lesion Glycolysis',
7750
7884
  center: 'Center'
7751
7885
  },
7752
- 'segmentationToolbox.config': () => {
7753
- // Get initial states based on current configuration
7754
- const [previewEdits, setPreviewEdits] = (0,react.useState)(false);
7755
- const [segmentLabelEnabled, setSegmentLabelEnabled] = (0,react.useState)(false);
7756
- const [toggleSegmentEnabled, setToggleSegmentEnabled] = (0,react.useState)(false);
7757
- const [useCenterAsSegmentIndex, setUseCenterAsSegmentIndex] = (0,react.useState)(false);
7758
- const handlePreviewEditsChange = checked => {
7759
- setPreviewEdits(checked);
7760
- commandsManager.run('toggleSegmentPreviewEdit', {
7761
- toggle: checked
7762
- });
7763
- };
7764
- const handleToggleSegmentEnabledChange = checked => {
7765
- setToggleSegmentEnabled(checked);
7766
- commandsManager.run('toggleSegmentSelect', {
7767
- toggle: checked
7768
- });
7769
- };
7770
- const handleUseCenterAsSegmentIndexChange = checked => {
7771
- setUseCenterAsSegmentIndex(checked);
7772
- commandsManager.run('toggleUseCenterSegmentIndex', {
7773
- toggle: checked
7774
- });
7775
- };
7776
- const handleSegmentLabelEnabledChange = checked => {
7777
- setSegmentLabelEnabled(checked);
7778
- commandsManager.run('toggleSegmentLabel', {
7779
- enabled: checked
7780
- });
7781
- };
7782
- return /*#__PURE__*/react.createElement("div", {
7783
- className: "bg-muted flex flex-col gap-2 border-b border-b-[2px] border-black px-2 py-3"
7784
- }, /*#__PURE__*/react.createElement("div", {
7785
- className: "flex items-center gap-2"
7786
- }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7787
- checked: previewEdits,
7788
- onCheckedChange: handlePreviewEditsChange
7789
- }), /*#__PURE__*/react.createElement("span", {
7790
- className: "text-foreground text-base"
7791
- }, "Preview edits before creating")), /*#__PURE__*/react.createElement("div", {
7792
- className: "flex items-center gap-2"
7793
- }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7794
- checked: useCenterAsSegmentIndex,
7795
- onCheckedChange: handleUseCenterAsSegmentIndexChange
7796
- }), /*#__PURE__*/react.createElement("span", {
7797
- className: "text-foreground text-base"
7798
- }, "Use center as segment index")), /*#__PURE__*/react.createElement("div", {
7799
- className: "flex items-center gap-2"
7800
- }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7801
- checked: toggleSegmentEnabled,
7802
- onCheckedChange: handleToggleSegmentEnabledChange
7803
- }), /*#__PURE__*/react.createElement("span", {
7804
- className: "text-foreground text-base"
7805
- }, "Hover on segment border to activate")), /*#__PURE__*/react.createElement("div", {
7806
- className: "flex items-center gap-2"
7807
- }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7808
- checked: segmentLabelEnabled,
7809
- onCheckedChange: handleSegmentLabelEnabledChange
7810
- }), /*#__PURE__*/react.createElement("span", {
7811
- className: "text-foreground text-base"
7812
- }, "Show segment name on hover")));
7886
+ 'labelMapSegmentationToolbox.config': () => {
7887
+ return /*#__PURE__*/react.createElement(SegmentationToolConfig, null);
7888
+ },
7889
+ 'contourSegmentationToolbox.config': () => {
7890
+ return /*#__PURE__*/react.createElement(SegmentationToolConfig, null);
7813
7891
  }
7814
7892
  };
7815
7893
  }
@@ -9031,10 +9109,10 @@ function getCustomizationModule({
9031
9109
  }];
9032
9110
  }
9033
9111
  /* harmony default export */ const src_getCustomizationModule = (getCustomizationModule);
9112
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/contourSegmentation/logicalOperators.js + 1 modules
9113
+ var logicalOperators = __webpack_require__(21536);
9034
9114
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/labelmap-interpolation/dist/esm/index.js + 2 modules
9035
9115
  var labelmap_interpolation_dist_esm = __webpack_require__(7927);
9036
- // EXTERNAL MODULE: ../../i18n/src/index.js + 210 modules
9037
- var i18n_src = __webpack_require__(68523);
9038
9116
  // EXTERNAL MODULE: ../../../node_modules/gl-matrix/esm/index.js + 1 modules
9039
9117
  var gl_matrix_esm = __webpack_require__(3823);
9040
9118
  ;// ../../../extensions/cornerstone/src/utils/imageSliceSync/toggleImageSliceSync.ts
@@ -9222,11 +9300,59 @@ function groupViewportsByModality(viewportGridService, displaySetService) {
9222
9300
  }
9223
9301
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/stores/useSynchronizersStore.ts
9224
9302
  var useSynchronizersStore = __webpack_require__(68578);
9303
+ // EXTERNAL MODULE: ../../../node_modules/zustand/esm/index.mjs + 1 modules
9304
+ var zustand_esm = __webpack_require__(78713);
9305
+ // EXTERNAL MODULE: ../../../node_modules/zustand/esm/middleware.mjs
9306
+ var middleware = __webpack_require__(21978);
9307
+ ;// ../../../extensions/cornerstone/src/stores/useSelectedSegmentationsForViewportStore.ts
9308
+
9309
+
9310
+ const PRESENTATION_TYPE_ID = 'selectedSegmentationsForViewportId';
9311
+ const DEBUG_STORE = false;
9312
+
9313
+ /**
9314
+ * Represents the state and actions for managing selected segmentations for a viewport by representation type.
9315
+ */
9316
+
9317
+ /**
9318
+ * Creates the Selected Segmentations For Viewport store.
9319
+ *
9320
+ * @param set - The zustand set function.
9321
+ * @returns The selected segmentations for viewport store state and actions.
9322
+ */
9323
+ const createSelectedSegmentationsForViewportStore = set => ({
9324
+ selectedSegmentationsForViewport: {},
9325
+ type: PRESENTATION_TYPE_ID,
9326
+ /**
9327
+ * Sets the selected segmentations for a given viewport id.
9328
+ */
9329
+ setSelectedSegmentationsForViewport: (key, value) => set(state => ({
9330
+ selectedSegmentationsForViewport: {
9331
+ ...state.selectedSegmentationsForViewport,
9332
+ [key]: value
9333
+ }
9334
+ }), false, 'setSelectedSegmentationsForViewport'),
9335
+ /**
9336
+ * Clears all selected segmentations for all viewports.
9337
+ */
9338
+ clearSelectedSegmentationsForViewportStore: () => set({
9339
+ selectedSegmentationsForViewport: {}
9340
+ }, false, 'clearSelectedSegmentationsForViewportStore')
9341
+ });
9342
+
9343
+ /**
9344
+ * Zustand store for managing selected segmentations for a viewport by representation type.
9345
+ * Applies devtools middleware when DEBUG_STORE is enabled.
9346
+ */
9347
+ const useSelectedSegmentationsForViewportStore = (0,zustand_esm/* create */.vt)()(DEBUG_STORE ? (0,middleware/* devtools */.lt)(createSelectedSegmentationsForViewportStore, {
9348
+ name: 'SelectedSegmentationsForViewportStore'
9349
+ }) : createSelectedSegmentationsForViewportStore);
9225
9350
  ;// ../../../extensions/cornerstone/src/stores/index.ts
9226
9351
 
9227
9352
 
9228
9353
 
9229
9354
 
9355
+
9230
9356
  // EXTERNAL MODULE: ../../../node_modules/html2canvas/dist/html2canvas.esm.js
9231
9357
  var html2canvas_esm = __webpack_require__(91037);
9232
9358
  ;// ../../../extensions/cornerstone/src/utils/CornerstoneViewportDownloadForm.tsx
@@ -9731,7 +9857,7 @@ function getUpdatedViewportsForSegmentation({
9731
9857
  });
9732
9858
  const targetViewportId = viewport.viewportOptions.viewportId;
9733
9859
  const updatedViewports = hangingProtocolService.getViewportsRequireUpdate(targetViewportId, displaySetInstanceUIDs[0], isHangingProtocolLayout);
9734
- return updatedViewports.filter(v => v.viewportOptions?.viewportType !== 'volume3d');
9860
+ return updatedViewports;
9735
9861
  }
9736
9862
  const getTargetViewport = ({
9737
9863
  viewportId,
@@ -10113,6 +10239,66 @@ let EasingFunctionEnum = /*#__PURE__*/function (EasingFunctionEnum) {
10113
10239
  return EasingFunctionEnum;
10114
10240
  }({});
10115
10241
  const EasingFunctionMap = new Map([[EasingFunctionEnum.EASE, ease], [EasingFunctionEnum.EASE_IN, easeIn], [EasingFunctionEnum.EASE_OUT, easeOut], [EasingFunctionEnum.EASE_IN_OUT, easeInOut], [EasingFunctionEnum.LINEAR, linear]]);
10242
+ // EXTERNAL MODULE: ../../i18n/src/index.js + 210 modules
10243
+ var i18n_src = __webpack_require__(68523);
10244
+ ;// ../../../extensions/cornerstone/src/utils/createSegmentationForViewport.ts
10245
+
10246
+
10247
+
10248
+ function _createDefaultSegments(createInitialSegment) {
10249
+ return createInitialSegment ? {
10250
+ 1: {
10251
+ label: `${i18n_src/* default */.A.t('Tools:Segment')} 1`,
10252
+ active: true
10253
+ }
10254
+ } : {};
10255
+ }
10256
+ /**
10257
+ * Creates a segmentation for the active viewport
10258
+ *
10259
+ * The created segmentation will be registered as a display set and also added
10260
+ * as a segmentation representation to the viewport.
10261
+ */
10262
+ async function createSegmentationForViewport(servicesManager, {
10263
+ viewportId,
10264
+ options = {},
10265
+ segmentationType
10266
+ }) {
10267
+ const {
10268
+ viewportGridService,
10269
+ displaySetService,
10270
+ segmentationService
10271
+ } = servicesManager.services;
10272
+ const {
10273
+ viewports
10274
+ } = viewportGridService.getState();
10275
+ const targetViewportId = viewportId;
10276
+ const viewport = viewports.get(targetViewportId);
10277
+
10278
+ // Todo: add support for multiple display sets
10279
+ const displaySetInstanceUID = options.displaySetInstanceUID || viewport.displaySetInstanceUIDs[0];
10280
+ const segs = segmentationService.getSegmentations();
10281
+ const label = options.label || `${i18n_src/* default */.A.t('Tools:Segmentation')} ${segs.length + 1}`;
10282
+ const segmentationId = options.segmentationId || `${esm.utilities.uuidv4()}`;
10283
+ const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
10284
+ const segmentationCreationOptions = {
10285
+ label,
10286
+ segmentationId,
10287
+ segments: _createDefaultSegments(options.createInitialSegment)
10288
+ };
10289
+
10290
+ // This will create the segmentation and register it as a display set
10291
+ const generatedSegmentationId = await (segmentationType === esm_enums.SegmentationRepresentations.Labelmap ? segmentationService.createLabelmapForDisplaySet(displaySet, segmentationCreationOptions) : segmentationService.createContourForDisplaySet(displaySet, segmentationCreationOptions));
10292
+
10293
+ // Also add the segmentation representation to the viewport
10294
+ await segmentationService.addSegmentationRepresentation(viewportId, {
10295
+ segmentationId,
10296
+ type: segmentationType
10297
+ });
10298
+ return generatedSegmentationId;
10299
+ }
10300
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/stateManagement/segmentation/index.js + 9 modules
10301
+ var segmentation = __webpack_require__(55126);
10116
10302
  ;// ../../../extensions/cornerstone/src/commandsModule.ts
10117
10303
 
10118
10304
 
@@ -10138,6 +10324,15 @@ const EasingFunctionMap = new Map([[EasingFunctionEnum.EASE, ease], [EasingFunct
10138
10324
 
10139
10325
 
10140
10326
 
10327
+
10328
+
10329
+
10330
+ const {
10331
+ add,
10332
+ intersect,
10333
+ subtract,
10334
+ copy
10335
+ } = dist_esm.utilities.contourSegmentation;
10141
10336
  const {
10142
10337
  DefaultHistoryMemo
10143
10338
  } = esm.utilities.HistoryMemo;
@@ -10324,13 +10519,21 @@ function commandsModule({
10324
10519
  if (!displaySet) {
10325
10520
  return;
10326
10521
  }
10522
+ const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
10523
+ if (!viewport) {
10524
+ return;
10525
+ }
10327
10526
  if (displaySet.isOverlayDisplaySet) {
10328
10527
  // update the previously stored segmentationPresentation with the new viewportId
10329
10528
  // presentation so that when we put the referencedDisplaySet back in the viewport
10330
10529
  // it will have the correct segmentation representation hydrated
10530
+
10531
+ const segmentationType =
10532
+ // Todo: check if PMAP modality should be handled such as SEG
10533
+ displaySet.Modality !== 'SEG' ? esm_enums.SegmentationRepresentations.Contour : viewport.type === esm.Enums.ViewportType.VOLUME_3D ? esm_enums.SegmentationRepresentations.Surface : esm_enums.SegmentationRepresentations.Labelmap;
10331
10534
  commandsManager.runCommand('updateStoredSegmentationPresentation', {
10332
10535
  displaySet,
10333
- type: displaySet.Modality === 'SEG' ? esm_enums.SegmentationRepresentations.Labelmap : esm_enums.SegmentationRepresentations.Contour
10536
+ type: segmentationType
10334
10537
  });
10335
10538
  }
10336
10539
  const referencedDisplaySetInstanceUID = displaySet.referencedDisplaySetInstanceUID;
@@ -11040,7 +11243,8 @@ function commandsModule({
11040
11243
  value,
11041
11244
  itemId,
11042
11245
  toolName,
11043
- toolGroupIds = []
11246
+ toolGroupIds = [],
11247
+ bindings
11044
11248
  }) => {
11045
11249
  // Sometimes it is passed as value (tools with options), sometimes as itemId (toolbar buttons)
11046
11250
  toolName = toolName || itemId || value;
@@ -11048,13 +11252,17 @@ function commandsModule({
11048
11252
  toolGroupIds.forEach(toolGroupId => {
11049
11253
  actions.setToolActive({
11050
11254
  toolName,
11051
- toolGroupId
11255
+ toolGroupId,
11256
+ bindings
11052
11257
  });
11053
11258
  });
11054
11259
  },
11055
11260
  setToolActive: ({
11056
11261
  toolName,
11057
- toolGroupId = null
11262
+ toolGroupId = null,
11263
+ bindings = [{
11264
+ mouseButton: dist_esm.Enums.MouseBindings.Primary
11265
+ }]
11058
11266
  }) => {
11059
11267
  const {
11060
11268
  viewports
@@ -11077,9 +11285,7 @@ function commandsModule({
11077
11285
 
11078
11286
  // Set the new toolName to be active
11079
11287
  toolGroup.setToolActive(toolName, {
11080
- bindings: [{
11081
- mouseButton: dist_esm.Enums.MouseBindings.Primary
11082
- }]
11288
+ bindings
11083
11289
  });
11084
11290
  },
11085
11291
  // capture viewport
@@ -11593,42 +11799,27 @@ function commandsModule({
11593
11799
  viewportId,
11594
11800
  options = {}
11595
11801
  }) => {
11596
- const {
11597
- viewportGridService,
11598
- displaySetService,
11599
- segmentationService
11600
- } = servicesManager.services;
11601
- const {
11602
- viewports
11603
- } = viewportGridService.getState();
11604
- const targetViewportId = viewportId;
11605
- const viewport = viewports.get(targetViewportId);
11606
-
11607
- // Todo: add support for multiple display sets
11608
- const displaySetInstanceUID = options.displaySetInstanceUID || viewport.displaySetInstanceUIDs[0];
11609
- const segs = segmentationService.getSegmentations();
11610
- const label = options.label || `${i18n_src/* default */.A.t('Tools:Segmentation')} ${segs.length + 1}`;
11611
- const segmentationId = options.segmentationId || `${esm.utilities.uuidv4()}`;
11612
- const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
11613
-
11614
- // This will create the segmentation and register it as a display set
11615
- const generatedSegmentationId = await segmentationService.createLabelmapForDisplaySet(displaySet, {
11616
- label,
11617
- segmentationId,
11618
- segments: options.createInitialSegment ? {
11619
- 1: {
11620
- label: `${i18n_src/* default */.A.t('Tools:Segment')} 1`,
11621
- active: true
11622
- }
11623
- } : {}
11802
+ return createSegmentationForViewport(servicesManager, {
11803
+ viewportId,
11804
+ options,
11805
+ segmentationType: esm_enums.SegmentationRepresentations.Labelmap
11624
11806
  });
11625
-
11626
- // Also add the segmentation representation to the viewport
11627
- await segmentationService.addSegmentationRepresentation(viewportId, {
11628
- segmentationId,
11629
- type: dist_esm.Enums.SegmentationRepresentations.Labelmap
11807
+ },
11808
+ /**
11809
+ * Creates a contour for the active viewport
11810
+ *
11811
+ * The created contour will be registered as a display set and also added
11812
+ * as a segmentation representation to the viewport.
11813
+ */
11814
+ createContourForViewport: async ({
11815
+ viewportId,
11816
+ options = {}
11817
+ }) => {
11818
+ return createSegmentationForViewport(servicesManager, {
11819
+ viewportId,
11820
+ options,
11821
+ segmentationType: esm_enums.SegmentationRepresentations.Contour
11630
11822
  });
11631
- return generatedSegmentationId;
11632
11823
  },
11633
11824
  /**
11634
11825
  * Sets the active segmentation for a viewport
@@ -11648,12 +11839,13 @@ function commandsModule({
11648
11839
  * @param props.segmentationId - The ID of the segmentation to add the segment to
11649
11840
  */
11650
11841
  addSegmentCommand: ({
11651
- segmentationId
11842
+ segmentationId,
11843
+ config
11652
11844
  }) => {
11653
11845
  const {
11654
11846
  segmentationService
11655
11847
  } = servicesManager.services;
11656
- segmentationService.addSegment(segmentationId);
11848
+ segmentationService.addSegment(segmentationId, config);
11657
11849
  },
11658
11850
  /**
11659
11851
  * Sets the active segment and jumps to its center
@@ -12463,6 +12655,193 @@ function commandsModule({
12463
12655
  newAnnotation,
12464
12656
  deleting
12465
12657
  });
12658
+ },
12659
+ activateSelectedSegmentationOfType: ({
12660
+ segmentationRepresentationType
12661
+ }) => {
12662
+ const {
12663
+ segmentationService,
12664
+ viewportGridService
12665
+ } = servicesManager.services;
12666
+ const activeViewportId = viewportGridService.getActiveViewportId();
12667
+ const {
12668
+ selectedSegmentationsForViewport
12669
+ } = useSelectedSegmentationsForViewportStore.getState();
12670
+ const segmentationId = selectedSegmentationsForViewport[activeViewportId]?.get(segmentationRepresentationType);
12671
+ if (!segmentationId) {
12672
+ return;
12673
+ }
12674
+ segmentationService.setActiveSegmentation(activeViewportId, segmentationId);
12675
+ },
12676
+ setDynamicCursorSizeForSculptorTool: ({
12677
+ value: isDynamicCursorSize
12678
+ }) => {
12679
+ const viewportId = viewportGridService.getActiveViewportId();
12680
+ const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
12681
+ const sculptorToolInstance = toolGroup.getToolInstance(toolNames.SculptorTool);
12682
+ const oldConfiguration = sculptorToolInstance.configuration;
12683
+ sculptorToolInstance.configuration = {
12684
+ ...oldConfiguration,
12685
+ updateCursorSize: isDynamicCursorSize ? 'dynamic' : ''
12686
+ };
12687
+ },
12688
+ setInterpolationToolConfiguration: ({
12689
+ value: interpolateContours,
12690
+ toolNames
12691
+ }) => {
12692
+ const viewportId = viewportGridService.getActiveViewportId();
12693
+ const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
12694
+
12695
+ // Set the interpolation configuration for the active tool.
12696
+ const activeTool = toolGroupService.getActiveToolForViewport(viewportId);
12697
+ const interpolationConfig = {
12698
+ interpolation: {
12699
+ enabled: interpolateContours,
12700
+ showInterpolationPolyline: true
12701
+ }
12702
+ };
12703
+ toolGroup.setToolConfiguration(activeTool, interpolationConfig);
12704
+
12705
+ // Now set the interpolation configuration for the other tools specified.
12706
+ if (toolNames) {
12707
+ Object.values(toolGroup.getToolInstances()).forEach(toolInstance => {
12708
+ if (toolNames?.includes(toolInstance.toolName)) {
12709
+ toolGroup.setToolConfiguration(toolInstance.toolName, interpolationConfig);
12710
+ }
12711
+ });
12712
+ }
12713
+ },
12714
+ setSimplifiedSplineForSplineContourSegmentationTool: ({
12715
+ value: simplifiedSpline
12716
+ }) => {
12717
+ const viewportId = viewportGridService.getActiveViewportId();
12718
+ const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
12719
+ Object.values(toolGroup.getToolInstances()).forEach(toolInstance => {
12720
+ if (toolInstance instanceof dist_esm.SplineContourSegmentationTool) {
12721
+ const oldConfiguration = toolInstance.configuration;
12722
+ toolInstance.configuration = {
12723
+ ...oldConfiguration,
12724
+ simplifiedSpline
12725
+ };
12726
+ }
12727
+ });
12728
+ },
12729
+ removeSmallContours: ({
12730
+ areaThreshold: threshold
12731
+ }) => {
12732
+ const viewportId = viewportGridService.getActiveViewportId();
12733
+ const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
12734
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
12735
+ if (!activeSegmentation || !activeSegment) {
12736
+ return;
12737
+ }
12738
+ const {
12739
+ removeContourIslands
12740
+ } = segmentation.utilities;
12741
+ removeContourIslands(activeSegmentation.segmentationId, activeSegment.segmentIndex, {
12742
+ threshold
12743
+ });
12744
+ const renderingEngine = cornerstoneViewportService.getRenderingEngine();
12745
+ renderingEngine.render();
12746
+ },
12747
+ applyLogicalContourOperation: ({
12748
+ segmentAInfo,
12749
+ segmentBInfo,
12750
+ resultSegmentInfo,
12751
+ logicalOperation
12752
+ }) => {
12753
+ switch (logicalOperation) {
12754
+ case logicalOperators/* LogicalOperation */.Dp.Union:
12755
+ add(segmentAInfo, segmentBInfo, resultSegmentInfo);
12756
+ break;
12757
+ case logicalOperators/* LogicalOperation */.Dp.Intersect:
12758
+ intersect(segmentAInfo, segmentBInfo, resultSegmentInfo);
12759
+ break;
12760
+ case logicalOperators/* LogicalOperation */.Dp.Subtract:
12761
+ subtract(segmentAInfo, segmentBInfo, resultSegmentInfo);
12762
+ break;
12763
+ default:
12764
+ throw new Error('Unsupported logical operation');
12765
+ break;
12766
+ }
12767
+ },
12768
+ copyContourSegment: ({
12769
+ sourceSegmentInfo,
12770
+ targetSegmentInfo
12771
+ }) => {
12772
+ if (!targetSegmentInfo) {
12773
+ targetSegmentInfo = {
12774
+ segmentationId: sourceSegmentInfo.segmentationId,
12775
+ segmentIndex: segmentationService.getNextAvailableSegmentIndex(sourceSegmentInfo.segmentationId)
12776
+ };
12777
+ segmentationService.addSegment(targetSegmentInfo.segmentationId, {
12778
+ segmentIndex: targetSegmentInfo.segmentIndex
12779
+ });
12780
+ }
12781
+ copy(sourceSegmentInfo, targetSegmentInfo);
12782
+ },
12783
+ smoothContours: () => {
12784
+ const viewportId = viewportGridService.getActiveViewportId();
12785
+ const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
12786
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
12787
+ if (!activeSegmentation || !activeSegment) {
12788
+ return;
12789
+ }
12790
+ const {
12791
+ smoothContours
12792
+ } = segmentation.utilities;
12793
+ smoothContours(activeSegmentation.segmentationId, activeSegment.segmentIndex);
12794
+ const renderingEngine = cornerstoneViewportService.getRenderingEngine();
12795
+ renderingEngine.render();
12796
+ },
12797
+ removeContourHoles: () => {
12798
+ const viewportId = viewportGridService.getActiveViewportId();
12799
+ const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
12800
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
12801
+ if (!activeSegmentation || !activeSegment) {
12802
+ return;
12803
+ }
12804
+ const {
12805
+ removeContourHoles
12806
+ } = segmentation.utilities;
12807
+ removeContourHoles(activeSegmentation.segmentationId, activeSegment.segmentIndex);
12808
+ const renderingEngine = cornerstoneViewportService.getRenderingEngine();
12809
+ renderingEngine.render();
12810
+ },
12811
+ decimateContours: () => {
12812
+ const viewportId = viewportGridService.getActiveViewportId();
12813
+ const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
12814
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
12815
+ if (!activeSegmentation || !activeSegment) {
12816
+ return;
12817
+ }
12818
+ const {
12819
+ decimateContours
12820
+ } = segmentation.utilities;
12821
+ decimateContours(activeSegmentation.segmentationId, activeSegment.segmentIndex);
12822
+ const renderingEngine = cornerstoneViewportService.getRenderingEngine();
12823
+ renderingEngine.render();
12824
+ },
12825
+ convertContourHoles: () => {
12826
+ const viewportId = viewportGridService.getActiveViewportId();
12827
+ const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
12828
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
12829
+ if (!activeSegmentation || !activeSegment) {
12830
+ return;
12831
+ }
12832
+ const targetSegmentInfo = {
12833
+ segmentationId: activeSegmentation.segmentationId,
12834
+ segmentIndex: segmentationService.getNextAvailableSegmentIndex(activeSegmentation.segmentationId)
12835
+ };
12836
+ segmentationService.addSegment(targetSegmentInfo.segmentationId, {
12837
+ segmentIndex: targetSegmentInfo.segmentIndex
12838
+ });
12839
+ const {
12840
+ convertContourHoles
12841
+ } = segmentation.utilities;
12842
+ convertContourHoles(activeSegmentation.segmentationId, activeSegment.segmentIndex, targetSegmentInfo.segmentationId, targetSegmentInfo.segmentIndex);
12843
+ const renderingEngine = cornerstoneViewportService.getRenderingEngine();
12844
+ renderingEngine.render();
12466
12845
  }
12467
12846
  };
12468
12847
  const definitions = {
@@ -12684,6 +13063,9 @@ function commandsModule({
12684
13063
  createLabelmapForViewport: {
12685
13064
  commandFn: actions.createLabelmapForViewport
12686
13065
  },
13066
+ createContourForViewport: {
13067
+ commandFn: actions.createContourForViewport
13068
+ },
12687
13069
  setActiveSegmentation: {
12688
13070
  commandFn: actions.setActiveSegmentation
12689
13071
  },
@@ -12784,7 +13166,18 @@ function commandsModule({
12784
13166
  endRecordingForAnnotationGroup: actions.endRecordingForAnnotationGroup,
12785
13167
  toggleSegmentLabel: actions.toggleSegmentLabel,
12786
13168
  jumpToMeasurementViewport: actions.jumpToMeasurementViewport,
12787
- initializeSegmentLabelTool: actions.initializeSegmentLabelTool
13169
+ initializeSegmentLabelTool: actions.initializeSegmentLabelTool,
13170
+ activateSelectedSegmentationOfType: actions.activateSelectedSegmentationOfType,
13171
+ setDynamicCursorSizeForSculptorTool: actions.setDynamicCursorSizeForSculptorTool,
13172
+ setSimplifiedSplineForSplineContourSegmentationTool: actions.setSimplifiedSplineForSplineContourSegmentationTool,
13173
+ removeSmallContours: actions.removeSmallContours,
13174
+ applyLogicalContourOperation: actions.applyLogicalContourOperation,
13175
+ copyContourSegment: actions.copyContourSegment,
13176
+ smoothContours: actions.smoothContours,
13177
+ removeContourHoles: actions.removeContourHoles,
13178
+ decimateContours: actions.decimateContours,
13179
+ convertContourHoles: actions.convertContourHoles,
13180
+ setInterpolationToolConfiguration: actions.setInterpolationToolConfiguration
12788
13181
  };
12789
13182
  return {
12790
13183
  actions,
@@ -17335,8 +17728,8 @@ const ViewportColorbarsContainer = /*#__PURE__*/(0,react.memo)(function Viewport
17335
17728
 
17336
17729
 
17337
17730
  /* harmony default export */ const components_ViewportColorbar = (ViewportColorbar_ViewportColorbarsContainer);
17338
- // EXTERNAL MODULE: ../../core/src/hooks/index.ts + 3 modules
17339
- var src_hooks = __webpack_require__(69419);
17731
+ // EXTERNAL MODULE: ../../core/src/hooks/index.ts + 5 modules
17732
+ var src_hooks = __webpack_require__(85490);
17340
17733
  // EXTERNAL MODULE: ../../core/src/services/ToolBarService/ToolbarService.ts
17341
17734
  var ToolbarService = __webpack_require__(93813);
17342
17735
  ;// ../../../extensions/cornerstone/src/components/AdvancedRenderingControls/AdvancedRenderingControls.tsx
@@ -18653,7 +19046,9 @@ const SegmentationService_EVENTS = {
18653
19046
  // fired when the active segment is loaded in SEG or RTSTRUCT
18654
19047
  SEGMENT_LOADING_COMPLETE: 'event::segment_loading_complete',
18655
19048
  // loading completed for all segments
18656
- SEGMENTATION_LOADING_COMPLETE: 'event::segmentation_loading_complete'
19049
+ SEGMENTATION_LOADING_COMPLETE: 'event::segmentation_loading_complete',
19050
+ // fired when a contour annotation cut merge process is completed
19051
+ ANNOTATION_CUT_MERGE_PROCESS_COMPLETED: 'event::annotation_cut_merge_process_completed'
18657
19052
  };
18658
19053
  const VALUE_TYPES = {};
18659
19054
  class SegmentationService extends src/* PubSubService */.Rc {
@@ -18744,6 +19139,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
18744
19139
  segmentationId
18745
19140
  });
18746
19141
  };
19142
+ this._onAnnotationCutMergeProcessCompletedFromSource = evt => {
19143
+ const {
19144
+ segmentationId
19145
+ } = evt.detail;
19146
+ this._broadcastEvent(this.EVENTS.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED, {
19147
+ segmentationId
19148
+ });
19149
+ };
18747
19150
  this._segmentationIdToColorLUTIndexMap = new Map();
18748
19151
  this.servicesManager = servicesManager;
18749
19152
  this._segmentationGroupStatsMap = new Map();
@@ -18895,6 +19298,21 @@ class SegmentationService extends src/* PubSubService */.Rc {
18895
19298
  * @returns A promise that resolves to the created segmentation ID.
18896
19299
  */
18897
19300
  async createLabelmapForDisplaySet(displaySet, options) {
19301
+ return this._createSegmentationForDisplaySet(displaySet, LABELMAP, options);
19302
+ }
19303
+ async createContourForDisplaySet(displaySet, options) {
19304
+ return this._createSegmentationForDisplaySet(displaySet, CONTOUR, options);
19305
+ }
19306
+
19307
+ /**
19308
+ * Private method to create segmentation for a display set with the specified type
19309
+ *
19310
+ * @param displaySet - The display set to create the segmentation for
19311
+ * @param segmentationType - The type of segmentation (SegmentationRepresentations enum)
19312
+ * @param options - Optional parameters for creating the segmentation
19313
+ * @returns A promise that resolves to the created segmentation ID
19314
+ */
19315
+ async _createSegmentationForDisplaySet(displaySet, segmentationType, options) {
18898
19316
  // Todo: random does not makes sense, make this better, like
18899
19317
  // labelmap 1, 2, 3 etc
18900
19318
  const segmentationId = options?.segmentationId ?? `${esm.utilities.uuidv4()}`;
@@ -18913,7 +19331,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
18913
19331
  const segmentationPublicInput = {
18914
19332
  segmentationId,
18915
19333
  representation: {
18916
- type: LABELMAP,
19334
+ type: segmentationType,
18917
19335
  data: {
18918
19336
  imageIds: segImageIds,
18919
19337
  // referencedVolumeId: this._getVolumeIdForDisplaySet(displaySet),
@@ -19267,6 +19685,15 @@ class SegmentationService extends src/* PubSubService */.Rc {
19267
19685
  hasCustomStyles(specifier) {
19268
19686
  return dist_esm.segmentation.config.style.hasCustomStyle(specifier);
19269
19687
  }
19688
+ getNextAvailableSegmentIndex(segmentationId) {
19689
+ const csSegmentation = this.getCornerstoneSegmentation(segmentationId);
19690
+ // grab the next available segment index based on the object keys,
19691
+ // so basically get the highest segment index value + 1
19692
+
19693
+ const segmentKeys = Object.keys(csSegmentation.segments);
19694
+ return segmentKeys.length === 0 ? 1 : Math.max(...segmentKeys.map(Number)) + 1;
19695
+ }
19696
+
19270
19697
  /**
19271
19698
  * Adds a new segment to the specified segmentation.
19272
19699
  * @param segmentationId - The ID of the segmentation to add the segment to.
@@ -19288,10 +19715,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
19288
19715
  const csSegmentation = this.getCornerstoneSegmentation(segmentationId);
19289
19716
  let segmentIndex = config.segmentIndex;
19290
19717
  if (!segmentIndex) {
19291
- // grab the next available segment index based on the object keys,
19292
- // so basically get the highest segment index value + 1
19293
- const segmentKeys = Object.keys(csSegmentation.segments);
19294
- segmentIndex = segmentKeys.length === 0 ? 1 : Math.max(...segmentKeys.map(Number)) + 1;
19718
+ segmentIndex = this.getNextAvailableSegmentIndex(segmentationId);
19295
19719
  }
19296
19720
 
19297
19721
  // update the segmentation
@@ -19838,6 +20262,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
19838
20262
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_ADDED, this._onSegmentationRepresentationModifiedFromSource);
19839
20263
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationModifiedFromSource);
19840
20264
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
20265
+ esm.eventTarget.addEventListener(dist_esm.Enums.Events.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED, this._onAnnotationCutMergeProcessCompletedFromSource);
19841
20266
  }
19842
20267
  getCornerstoneSegmentation(segmentationId) {
19843
20268
  return dist_esm.segmentation.state.getSegmentation(segmentationId);
@@ -21446,6 +21871,10 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
21446
21871
  const displaySet = displaySetService.getDisplaySetByUID(displaySetUIDs[0]);
21447
21872
  const displaySetModality = displaySet?.Modality;
21448
21873
 
21874
+ // seems like a hack but we need the actor to be ready first before
21875
+ // we set the properties
21876
+ const timeoutViewportCallback = callback => setTimeout(callback, 0);
21877
+
21449
21878
  // filter overlay display sets (e.g. segmentation) since they will get handled below via the segmentation service
21450
21879
  const filteredVolumeInputArray = volumeInputArray.map((volumeInput, index) => {
21451
21880
  return {
@@ -21511,10 +21940,18 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
21511
21940
  // care of the background overlay display set first then the addOverlayFn will add the
21512
21941
  // SEG displaySet
21513
21942
  const sampleImageId = imageIds[0];
21514
- const backgroundDisplaySet = displaySetService.getDisplaySetsBy(displaySet => !displaySet.isOverlayDisplaySet && displaySet.images.some(image => image.imageId === sampleImageId));
21943
+ const backgroundDisplaySet = displaySetService.getDisplaySetsBy(displaySet => !displaySet.isOverlayDisplaySet && displaySet.images?.some(image => image.imageId === sampleImageId));
21515
21944
  if (backgroundDisplaySet.length !== 1) {
21516
21945
  throw new Error('Background display set not found');
21517
21946
  }
21947
+ if (viewport.type === esm.Enums.ViewportType.VOLUME_3D) {
21948
+ timeoutViewportCallback(() => {
21949
+ viewportGridService.setDisplaySetsForViewport({
21950
+ viewportId: viewport.id,
21951
+ displaySetInstanceUIDs: [backgroundDisplaySet[0].displaySetInstanceUID]
21952
+ });
21953
+ });
21954
+ }
21518
21955
  }
21519
21956
  });
21520
21957
  }
@@ -21533,14 +21970,12 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
21533
21970
  properties,
21534
21971
  volumeId
21535
21972
  }) => {
21536
- setTimeout(() => {
21537
- // seems like a hack but we need the actor to be ready first before
21538
- // we set the properties
21973
+ timeoutViewportCallback(() => {
21539
21974
  viewport.setProperties(properties, volumeId);
21540
21975
  viewport.render();
21541
- }, 0);
21976
+ });
21542
21977
  });
21543
- this.setPresentations(viewport.id, presentations, viewportInfo);
21978
+ this.setPresentations(viewport.id, presentations);
21544
21979
  if (!presentations.positionPresentation) {
21545
21980
  const imageIndex = this._getInitialImageIndexForViewport(viewportInfo);
21546
21981
  if (imageIndex !== undefined) {
@@ -22522,14 +22957,130 @@ function getSopClassHandlerModule(params) {
22522
22957
  var useActiveViewportSegmentationRepresentations = __webpack_require__(9234);
22523
22958
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/hooks/useMeasurements.ts
22524
22959
  var useMeasurements = __webpack_require__(19214);
22960
+ ;// ../../../extensions/cornerstone/src/components/SegmentationUtilityButton.tsx
22961
+ function SegmentationUtilityButton_extends() { return SegmentationUtilityButton_extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, SegmentationUtilityButton_extends.apply(null, arguments); }
22962
+
22963
+
22964
+
22965
+ /**
22966
+ * A button that represents a segmentation utility.
22967
+ * It is implicitly the PopoverTrigger for the options Popover panel that is
22968
+ * opened in the PanelSegmentation component. It in essence is the PopoverTrigger
22969
+ * because typically this button has the associated options to display in the Popover.
22970
+ * Furthermore it also typically has a command for toggling the activeSegmentationUtility
22971
+ * value in the UIStateStore that triggers the fetching of its options.
22972
+
22973
+ * @param props - The props for the button.
22974
+ * @param props.className - The class name for the button.
22975
+ * @param props.isActive - Whether the button is active
22976
+ * @param props.id - The id of the button.
22977
+ */
22978
+ function SegmentationUtilityButton(props) {
22979
+ const {
22980
+ className,
22981
+ isActive,
22982
+ id
22983
+ } = props;
22984
+ const activeSegmentationUtility = (0,default_src.useUIStateStore)(store => store.uiState.activeSegmentationUtility);
22985
+ const toolButtonClassName = (0,ui_next_src.cn)('w-7 h-7 text-primary hover:text-primary hover:!bg-primary/30', className, isActive && 'bg-primary/30');
22986
+ const handleMouseDownCapture = (0,react.useCallback)(event => {
22987
+ if (activeSegmentationUtility === id) {
22988
+ // If this active button is clicked, prevent the default Popover
22989
+ // behaviour of closing the Popover on a pointer/mouse down.
22990
+ // Not doing this will cause the Popover to close and then reopen again.
22991
+ // Why? Because propagating this event will cause PanelSegmentation to
22992
+ // close the Popover by clearing the activeSegmentationUtility. Then
22993
+ // this button will set the activeSegmentationUtility again and the
22994
+ // Popover will reopen.
22995
+ event.preventDefault();
22996
+ event.stopPropagation();
22997
+ }
22998
+ }, [activeSegmentationUtility, id]);
22999
+ return /*#__PURE__*/react.createElement("div", {
23000
+ onPointerDownCapture: handleMouseDownCapture
23001
+ }, /*#__PURE__*/react.createElement(ui_next_src/* ToolButton */.T0e, SegmentationUtilityButton_extends({}, props, {
23002
+ className: toolButtonClassName
23003
+ })));
23004
+ }
23005
+ /* harmony default export */ const components_SegmentationUtilityButton = (SegmentationUtilityButton);
23006
+ ;// ../../../extensions/cornerstone/src/utils/segmentationExportUtils.ts
23007
+
23008
+ /**
23009
+ * Checks if a labelmap segmentation has exportable data
23010
+ * A label map is exportable if it has any pixel data and
23011
+ * it is referenced by a display set that is reconstructable.
23012
+ *
23013
+ * @param labelmap - The labelmap representation data
23014
+ * @param displaySetService - The display set service instance
23015
+ * @returns boolean - Whether the labelmap has exportable data
23016
+ */
23017
+ const hasExportableLabelMapData = (labelmap, displaySetService) => {
23018
+ if (!labelmap) {
23019
+ return false;
23020
+ }
23021
+ const imageIds = labelmap?.imageIds;
23022
+ if (!imageIds?.length) {
23023
+ return false;
23024
+ }
23025
+ const hasPixelData = imageIds.some(imageId => {
23026
+ const pixelData = esm.cache.getImage(imageId)?.getPixelData();
23027
+ if (!pixelData) {
23028
+ return false;
23029
+ }
23030
+ for (let i = 0; i < pixelData.length; i++) {
23031
+ if (pixelData[i] !== 0) {
23032
+ return true;
23033
+ }
23034
+ }
23035
+ });
23036
+ if (!hasPixelData) {
23037
+ return false;
23038
+ }
23039
+ const referencedImageIds = labelmap?.referencedImageIds;
23040
+ if (!referencedImageIds) {
23041
+ return false;
23042
+ }
23043
+ const firstImageId = referencedImageIds[0];
23044
+ const instance = esm.metaData.get('instance', firstImageId);
23045
+ if (!instance) {
23046
+ return false;
23047
+ }
23048
+ const SOPInstanceUID = instance.SOPInstanceUID || instance.SopInstanceUID;
23049
+ const SeriesInstanceUID = instance.SeriesInstanceUID;
23050
+ const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(SOPInstanceUID, SeriesInstanceUID);
23051
+ return displaySet?.isReconstructable;
23052
+ };
23053
+
23054
+ /**
23055
+ * Checks if a contour segmentation has exportable data
23056
+ * A contour is exportable if it has any contour annotation/geometry data.
23057
+ *
23058
+ * @param contour - The contour representation data
23059
+ * @returns boolean - Whether the contour has exportable data
23060
+ */
23061
+ const hasExportableContourData = contour => {
23062
+ if (!contour) {
23063
+ return false;
23064
+ }
23065
+ const contourAnnotationUIDsMap = contour?.annotationUIDsMap;
23066
+ if (!contourAnnotationUIDsMap) {
23067
+ return false;
23068
+ }
23069
+ return contourAnnotationUIDsMap.size > 0;
23070
+ };
22525
23071
  ;// ../../../extensions/cornerstone/src/panels/PanelSegmentation.tsx
22526
23072
 
22527
23073
 
22528
23074
 
22529
23075
 
22530
23076
 
23077
+
23078
+
23079
+
23080
+
22531
23081
  function PanelSegmentation({
22532
- children
23082
+ children,
23083
+ segmentationRepresentationType
22533
23084
  }) {
22534
23085
  const {
22535
23086
  commandsManager,
@@ -22537,12 +23088,56 @@ function PanelSegmentation({
22537
23088
  } = (0,src/* useSystem */.Jg)();
22538
23089
  const {
22539
23090
  customizationService,
22540
- displaySetService
23091
+ displaySetService,
23092
+ viewportGridService,
23093
+ toolbarService,
23094
+ segmentationService
22541
23095
  } = servicesManager.services;
23096
+ const {
23097
+ activeViewportId
23098
+ } = viewportGridService.getState();
23099
+ const utilitiesSectionMap = {
23100
+ [esm_enums.SegmentationRepresentations.Labelmap]: toolbarService.sections.labelMapSegmentationUtilities,
23101
+ [esm_enums.SegmentationRepresentations.Contour]: toolbarService.sections.contourSegmentationUtilities
23102
+ };
23103
+ const selectedSegmentationsForViewportMap = useSelectedSegmentationsForViewportStore(store => store.selectedSegmentationsForViewport[activeViewportId]);
23104
+ const selectedSegmentationIdForType = segmentationRepresentationType ? selectedSegmentationsForViewportMap?.get(segmentationRepresentationType) : segmentationService?.getActiveSegmentation(activeViewportId)?.segmentationId;
23105
+ const buttonSection = utilitiesSectionMap[segmentationRepresentationType];
23106
+ const {
23107
+ activeToolOptions: activeUtilityOptions
23108
+ } = (0,src/* useActiveToolOptions */.KP)({
23109
+ buttonSectionId: buttonSection
23110
+ });
22542
23111
  const {
22543
23112
  segmentationsWithRepresentations,
22544
23113
  disabled
22545
23114
  } = (0,useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c)();
23115
+ const setUIState = (0,default_src.useUIStateStore)(store => store.setUIState);
23116
+
23117
+ // useEffect for handling clicks on any of the non-active viewports.
23118
+ // The ViewportGrid stops the propagation of pointer/mouse events
23119
+ // for non-active viewports so the Popover below
23120
+ // is not closed when clicking on any of the non-active viewports.
23121
+ (0,react.useEffect)(() => {
23122
+ setUIState('activeSegmentationUtility', null);
23123
+ toolbarService.refreshToolbarState({
23124
+ viewportId: activeViewportId
23125
+ });
23126
+ }, [activeViewportId, setUIState, toolbarService]);
23127
+
23128
+ // The callback for handling clicks outside of the Popover and, the SegmentationUtilityButton
23129
+ // that triggered it to open. Clicks outside those components must close the Popover.
23130
+ // The Popover is made visible whenever the options associated with the
23131
+ // activeSegmentationUtility exist. Thus clearing the activeSegmentationUtility
23132
+ // clears the associated options and will keep the Popover closed.
23133
+ const handlePopoverOpenChange = (0,react.useCallback)(open => {
23134
+ if (!open) {
23135
+ setUIState('activeSegmentationUtility', null);
23136
+ toolbarService.refreshToolbarState({
23137
+ viewportId: activeViewportId
23138
+ });
23139
+ }
23140
+ }, [activeViewportId, setUIState, toolbarService]);
22546
23141
 
22547
23142
  // Extract customization options
22548
23143
  const segmentationTableMode = customizationService.getCustomization('panelSegmentation.tableMode');
@@ -22563,6 +23158,9 @@ function PanelSegmentation({
22563
23158
  commandsManager.run('addSegment', {
22564
23159
  segmentationId
22565
23160
  });
23161
+ commandsManager.run('setActiveSegmentation', {
23162
+ segmentationId
23163
+ });
22566
23164
  },
22567
23165
  onSegmentClick: (segmentationId, segmentIndex) => {
22568
23166
  commandsManager.run('setActiveSegmentAndCenter', {
@@ -22593,6 +23191,14 @@ function PanelSegmentation({
22593
23191
  segmentIndex
22594
23192
  });
22595
23193
  },
23194
+ onSegmentCopy: segmentationRepresentationType === esm_enums.SegmentationRepresentations.Contour ? (segmentationId, segmentIndex) => {
23195
+ commandsManager.run('copyContourSegment', {
23196
+ sourceSegmentInfo: {
23197
+ segmentationId,
23198
+ segmentIndex
23199
+ }
23200
+ });
23201
+ } : undefined,
22596
23202
  onToggleSegmentVisibility: (segmentationId, segmentIndex, type) => {
22597
23203
  commandsManager.run('toggleSegmentVisibility', {
22598
23204
  segmentationId,
@@ -22684,6 +23290,8 @@ function PanelSegmentation({
22684
23290
  };
22685
23291
 
22686
23292
  // Generate export options
23293
+ // Map each segmentation to an export option for it.
23294
+ // A segmentation is exportable if it has any labelmap or contour data.
22687
23295
  const exportOptions = segmentationsWithRepresentations.map(({
22688
23296
  segmentation
22689
23297
  }) => {
@@ -22692,49 +23300,24 @@ function PanelSegmentation({
22692
23300
  segmentationId
22693
23301
  } = segmentation;
22694
23302
  const {
22695
- Labelmap
23303
+ Labelmap,
23304
+ Contour
22696
23305
  } = representationData;
22697
- if (!Labelmap) {
23306
+ if (!Labelmap && !Contour) {
22698
23307
  return {
22699
23308
  segmentationId,
22700
23309
  isExportable: true
22701
23310
  };
22702
23311
  }
22703
-
22704
- // Check if any segments have anything drawn in any of the viewports
22705
- const hasAnySegmentData = (() => {
22706
- const imageIds = Labelmap.imageIds;
22707
- if (!imageIds?.length) return false;
22708
- for (const imageId of imageIds) {
22709
- const pixelData = esm.cache.getImage(imageId)?.getPixelData();
22710
- if (!pixelData) continue;
22711
- for (let i = 0; i < pixelData.length; i++) {
22712
- if (pixelData[i] !== 0) return true;
22713
- }
22714
- }
22715
- return false;
22716
- })();
22717
- if (!hasAnySegmentData) {
22718
- return {
22719
- segmentationId,
22720
- isExportable: false
22721
- };
22722
- }
22723
- const referencedImageIds = Labelmap.referencedImageIds;
22724
- const firstImageId = referencedImageIds[0];
22725
- const instance = esm.metaData.get('instance', firstImageId);
22726
- if (!instance) {
23312
+ if (!hasExportableLabelMapData(Labelmap, displaySetService) && !hasExportableContourData(Contour)) {
22727
23313
  return {
22728
23314
  segmentationId,
22729
23315
  isExportable: false
22730
23316
  };
22731
23317
  }
22732
- const SOPInstanceUID = instance.SOPInstanceUID || instance.SopInstanceUID;
22733
- const SeriesInstanceUID = instance.SeriesInstanceUID;
22734
- const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(SOPInstanceUID, SeriesInstanceUID);
22735
23318
  return {
22736
23319
  segmentationId,
22737
- isExportable: displaySet?.isReconstructable
23320
+ isExportable: true
22738
23321
  };
22739
23322
  });
22740
23323
 
@@ -22743,14 +23326,29 @@ function PanelSegmentation({
22743
23326
  disabled,
22744
23327
  data: segmentationsWithRepresentations,
22745
23328
  mode: segmentationTableMode,
22746
- title: 'Segmentations',
23329
+ title: `${segmentationRepresentationType ? `${segmentationRepresentationType} ` : ''}Segmentations`,
22747
23330
  exportOptions,
22748
23331
  disableEditing,
22749
23332
  onSegmentationAdd,
22750
23333
  showAddSegment,
22751
23334
  renderInactiveSegmentations: handlers.getRenderInactiveSegmentations(),
23335
+ segmentationRepresentationType,
23336
+ selectedSegmentationIdForType,
22752
23337
  ...handlers
22753
23338
  };
23339
+ const renderUtilitiesToolbar = () => {
23340
+ if (!buttonSection) {
23341
+ return null;
23342
+ }
23343
+ return /*#__PURE__*/react.createElement(ui_next_src/* IconPresentationProvider */.TNf, {
23344
+ size: "large",
23345
+ IconContainer: components_SegmentationUtilityButton
23346
+ }, /*#__PURE__*/react.createElement("div", {
23347
+ className: "flex flex-wrap gap-[3px] bg-transparent pb-[2px] pl-[8px] pt-[6px]"
23348
+ }, /*#__PURE__*/react.createElement(default_src.Toolbar, {
23349
+ buttonSection: buttonSection
23350
+ })));
23351
+ };
22754
23352
  const renderSegments = () => {
22755
23353
  return /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Segments, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.SegmentStatistics.Header, null, /*#__PURE__*/react.createElement(CustomSegmentStatisticsHeader, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.SegmentStatistics.Body, null));
22756
23354
  };
@@ -22758,11 +23356,20 @@ function PanelSegmentation({
22758
23356
  // Render content based on mode
22759
23357
  const renderModeContent = () => {
22760
23358
  if (tableProps.mode === 'collapsed') {
22761
- return /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Header, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.DropdownMenu, null, /*#__PURE__*/react.createElement(CustomDropdownMenuContent, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Selector, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Info, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Content, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentRow, null), renderSegments()));
23359
+ return /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed, null, renderUtilitiesToolbar(), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Header, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.DropdownMenu, null, /*#__PURE__*/react.createElement(CustomDropdownMenuContent, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Selector, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Info, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Content, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentRow, null), renderSegments()));
22762
23360
  }
22763
- return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Header, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.DropdownMenu, null, /*#__PURE__*/react.createElement(CustomDropdownMenuContent, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Label, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Info, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Content, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentRow, null), renderSegments())));
23361
+ return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded, null, renderUtilitiesToolbar(), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Header, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.DropdownMenu, null, /*#__PURE__*/react.createElement(CustomDropdownMenuContent, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Label, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Info, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Content, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentRow, null), renderSegments())));
22764
23362
  };
22765
- return /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h, tableProps, children, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Config, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentationRow, null), renderModeContent());
23363
+ return /*#__PURE__*/react.createElement(ui_next_src/* Popover */.AMh, {
23364
+ open: !!activeUtilityOptions,
23365
+ onOpenChange: handlePopoverOpenChange
23366
+ }, /*#__PURE__*/react.createElement(ui_next_src/* PopoverAnchor */.dTQ, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h, tableProps, children, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Config, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentationRow, null), renderModeContent())), activeUtilityOptions && /*#__PURE__*/react.createElement(ui_next_src/* PopoverContent */.hlN, {
23367
+ side: "left",
23368
+ align: "start",
23369
+ className: "w-auto"
23370
+ }, /*#__PURE__*/react.createElement(ui_next_src/* ToolSettings */.k_3, {
23371
+ options: activeUtilityOptions
23372
+ })));
22766
23373
  }
22767
23374
  // EXTERNAL MODULE: ../../../node_modules/lodash.debounce/index.js
22768
23375
  var lodash_debounce = __webpack_require__(62051);
@@ -23756,51 +24363,60 @@ function PanelMeasurement(props) {
23756
24363
 
23757
24364
 
23758
24365
 
24366
+
24367
+
24368
+
23759
24369
  const getPanelModule = ({
23760
24370
  commandsManager,
23761
24371
  servicesManager,
23762
24372
  extensionManager
23763
24373
  }) => {
23764
- const wrappedPanelSegmentation = ({
23765
- configuration
23766
- }) => {
24374
+ const {
24375
+ toolbarService
24376
+ } = servicesManager.services;
24377
+ const toolSectionMap = {
24378
+ [esm_enums.SegmentationRepresentations.Labelmap]: toolbarService.sections.labelMapSegmentationToolbox,
24379
+ [esm_enums.SegmentationRepresentations.Contour]: toolbarService.sections.contourSegmentationToolbox
24380
+ };
24381
+ const wrappedPanelSegmentation = props => {
23767
24382
  return /*#__PURE__*/react.createElement(PanelSegmentation, {
23768
24383
  commandsManager: commandsManager,
23769
24384
  servicesManager: servicesManager,
23770
24385
  extensionManager: extensionManager,
23771
24386
  configuration: {
23772
- ...configuration
23773
- }
24387
+ ...props?.configuration
24388
+ },
24389
+ segmentationRepresentationType: props?.segmentationRepresentationType
23774
24390
  });
23775
24391
  };
23776
- const wrappedPanelSegmentationNoHeader = ({
23777
- configuration
23778
- }) => {
24392
+ const wrappedPanelSegmentationNoHeader = props => {
23779
24393
  return /*#__PURE__*/react.createElement(PanelSegmentation, {
23780
24394
  commandsManager: commandsManager,
23781
24395
  servicesManager: servicesManager,
23782
24396
  extensionManager: extensionManager,
23783
24397
  configuration: {
23784
- ...configuration
23785
- }
24398
+ ...props?.configuration
24399
+ },
24400
+ segmentationRepresentationType: props?.segmentationRepresentationType
23786
24401
  });
23787
24402
  };
23788
- const wrappedPanelSegmentationWithTools = ({
23789
- configuration
23790
- }) => {
24403
+ const wrappedPanelSegmentationWithTools = props => {
23791
24404
  const {
23792
- toolbarService
23793
- } = servicesManager.services;
24405
+ t
24406
+ } = (0,es/* useTranslation */.Bd)('SegmentationTable');
24407
+ const tKey = `${props.segmentationRepresentationType ?? 'Segmentation'} tools`;
24408
+ const tValue = t(tKey);
23794
24409
  return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src.Toolbox, {
23795
- buttonSectionId: toolbarService.sections.segmentationToolbox,
23796
- title: "Segmentation Tools"
24410
+ buttonSectionId: toolSectionMap[props.segmentationRepresentationType],
24411
+ title: tValue
23797
24412
  }), /*#__PURE__*/react.createElement(PanelSegmentation, {
23798
24413
  commandsManager: commandsManager,
23799
24414
  servicesManager: servicesManager,
23800
24415
  extensionManager: extensionManager,
23801
24416
  configuration: {
23802
- ...configuration
23803
- }
24417
+ ...props?.configuration
24418
+ },
24419
+ segmentationRepresentationType: props?.segmentationRepresentationType
23804
24420
  }));
23805
24421
  };
23806
24422
  return [{
@@ -23829,11 +24445,23 @@ const getPanelModule = ({
23829
24445
  label: 'Segmentation',
23830
24446
  component: wrappedPanelSegmentationNoHeader
23831
24447
  }, {
23832
- name: 'panelSegmentationWithTools',
24448
+ name: 'panelSegmentationWithToolsLabelMap',
23833
24449
  iconName: 'tab-segmentation',
23834
24450
  iconLabel: 'Segmentation',
23835
- label: 'Segmentation',
23836
- component: wrappedPanelSegmentationWithTools
24451
+ label: i18n_src/* default */.A.t('SegmentationTable:Labelmap'),
24452
+ component: props => wrappedPanelSegmentationWithTools({
24453
+ ...props,
24454
+ segmentationRepresentationType: esm_enums.SegmentationRepresentations.Labelmap
24455
+ })
24456
+ }, {
24457
+ name: 'panelSegmentationWithToolsContour',
24458
+ iconName: 'tab-contours',
24459
+ iconLabel: 'Segmentation',
24460
+ label: i18n_src/* default */.A.t('SegmentationTable:Contour'),
24461
+ component: props => wrappedPanelSegmentationWithTools({
24462
+ ...props,
24463
+ segmentationRepresentationType: esm_enums.SegmentationRepresentations.Contour
24464
+ })
23837
24465
  }];
23838
24466
  };
23839
24467
  /* harmony default export */ const src_getPanelModule = (getPanelModule);
@@ -24047,6 +24675,39 @@ function setupSegmentationModifiedHandler({
24047
24675
  unsubscribe
24048
24676
  };
24049
24677
  }
24678
+
24679
+ /**
24680
+ * Sets up auto tab switching for when the first segmentation is added into the viewer.
24681
+ */
24682
+ function setUpSelectedSegmentationsForViewportHandler({
24683
+ segmentationService
24684
+ }) {
24685
+ const selectedSegmentationsForViewportEvents = [segmentationService.EVENTS.SEGMENTATION_MODIFIED, segmentationService.EVENTS.SEGMENTATION_REPRESENTATION_MODIFIED];
24686
+ const unsubscribeSelectedSegmentationsForViewportEvents = selectedSegmentationsForViewportEvents.map(eventName => segmentationService.subscribe(eventName, event => {
24687
+ const {
24688
+ viewportId
24689
+ } = event;
24690
+ if (!viewportId) {
24691
+ return;
24692
+ }
24693
+ const {
24694
+ selectedSegmentationsForViewport,
24695
+ setSelectedSegmentationsForViewport
24696
+ } = useSelectedSegmentationsForViewportStore.getState();
24697
+ const representations = segmentationService.getSegmentationRepresentations(viewportId);
24698
+ const activeRepresentation = representations.find(representation => representation.active);
24699
+ const typeToSegmentationIdMap = selectedSegmentationsForViewport[viewportId] ?? new Map();
24700
+ if (activeRepresentation) {
24701
+ typeToSegmentationIdMap.set(activeRepresentation.type, activeRepresentation.segmentationId);
24702
+ } else {
24703
+ typeToSegmentationIdMap.clear();
24704
+ }
24705
+ setSelectedSegmentationsForViewport(viewportId, typeToSegmentationIdMap);
24706
+ })).map(subscription => subscription.unsubscribe);
24707
+ return {
24708
+ unsubscribeSelectedSegmentationsForViewportEvents
24709
+ };
24710
+ }
24050
24711
  ;// ../../../extensions/cornerstone/src/utils/promptHydrationDialog.ts
24051
24712
  const HydrationType = {
24052
24713
  SEG: 'SEG',
@@ -24201,13 +24862,15 @@ function _askHydrate(uiViewportDialogService, customizationService, viewportId,
24201
24862
 
24202
24863
 
24203
24864
 
24865
+
24204
24866
  const utils_utils = {
24205
24867
  handleSegmentChange: handleSegmentChange,
24206
24868
  isReferenceViewable: isReferenceViewable,
24207
24869
  setupSegmentationDataModifiedHandler: setupSegmentationDataModifiedHandler,
24208
24870
  setupSegmentationModifiedHandler: setupSegmentationModifiedHandler,
24209
24871
  promptHydrationDialog: utils_promptHydrationDialog,
24210
- getCenterExtent: getCenterExtent
24872
+ getCenterExtent: getCenterExtent,
24873
+ createSegmentationForViewport: createSegmentationForViewport
24211
24874
  };
24212
24875
  /* harmony default export */ const src_utils = (utils_utils);
24213
24876
  ;// ../../../extensions/cornerstone/src/utils/setUpSegmentationEventHandlers.ts
@@ -24245,7 +24908,7 @@ const setUpSegmentationEventHandlers = ({
24245
24908
  }
24246
24909
  const segmentation = segmentationService.getSegmentation(segmentationId);
24247
24910
  const label = segmentation.cachedStats.info;
24248
- const imageIds = segmentation.representationData.Labelmap.imageIds;
24911
+ const imageIds = segmentation.representationData?.Labelmap?.imageIds ?? segmentation.representationData?.Contour?.imageIds;
24249
24912
 
24250
24913
  // Create a display set for the segmentation
24251
24914
  const segmentationDisplaySet = {
@@ -24264,7 +24927,12 @@ const setUpSegmentationEventHandlers = ({
24264
24927
  };
24265
24928
  displaySetService.addDisplaySets(segmentationDisplaySet);
24266
24929
  });
24267
- const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated];
24930
+ const {
24931
+ unsubscribeSelectedSegmentationsForViewportEvents
24932
+ } = setUpSelectedSegmentationsForViewportHandler({
24933
+ segmentationService
24934
+ });
24935
+ const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, ...unsubscribeSelectedSegmentationsForViewportEvents];
24268
24936
  return {
24269
24937
  unsubscriptions
24270
24938
  };
@@ -24675,7 +25343,7 @@ const cornerstoneExtension = {
24675
25343
  });
24676
25344
  unsubscriptions.push(...segmentationUnsubscriptions);
24677
25345
  toolbarService.registerEventForToolbarUpdate(cornerstoneViewportService, [cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED]);
24678
- toolbarService.registerEventForToolbarUpdate(segmentationService, [segmentationService.EVENTS.SEGMENTATION_REMOVED, segmentationService.EVENTS.SEGMENTATION_MODIFIED]);
25346
+ toolbarService.registerEventForToolbarUpdate(segmentationService, [segmentationService.EVENTS.SEGMENTATION_REMOVED, segmentationService.EVENTS.SEGMENTATION_MODIFIED, segmentationService.EVENTS.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED]);
24679
25347
  toolbarService.registerEventForToolbarUpdate(esm.eventTarget, [dist_esm.Enums.Events.TOOL_ACTIVATED]);
24680
25348
 
24681
25349
  // Configure the interleaved/HTJ2K loader
@@ -24714,6 +25382,7 @@ const cornerstoneExtension = {
24714
25382
  useSynchronizersStore/* useSynchronizersStore */.U.getState().clearSynchronizersStore();
24715
25383
  default_src.useToggleOneUpViewportGridStore.getState().clearToggleOneUpViewportGridStore();
24716
25384
  useSegmentationPresentationStore/* useSegmentationPresentationStore */.v.getState().clearSegmentationPresentationStore();
25385
+ useSelectedSegmentationsForViewportStore.getState().clearSelectedSegmentationsForViewportStore();
24717
25386
  segmentationService.removeAllSegmentations();
24718
25387
  },
24719
25388
  /**