@ohif/app 3.13.0-beta.7 → 3.13.0-beta.70
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.
- package/dist/{1459.bundle.0b4384c95c63e0d5245b.js → 1459.bundle.8df5bb7808389c8dcaa0.js} +5 -6
- package/dist/{1608.bundle.0687c661f1c9edfb3b8a.js → 1608.bundle.26306ea38618db59eff7.js} +12 -12
- package/dist/{1927.bundle.3050588e95f43cf57cdd.js → 1927.bundle.be67b3aafe238ca9f191.js} +27 -38
- package/dist/{1933.bundle.052fd9ab23c1236f788d.js → 1933.bundle.87b41a716353fed2610d.js} +32 -27
- package/dist/{2018.bundle.8d5580bd4dcea3ebaa23.js → 2018.bundle.e7a25ccc24941c9039e8.js} +18 -19
- package/dist/{6409.bundle.b36048896cb11c8571fb.js → 2075.bundle.23265b8e7597c398db4f.js} +327 -256
- package/dist/{2108.bundle.e84aa8d858d8c4f2413e.js → 2108.bundle.aea8d3b39486dd5ab39e.js} +569 -558
- package/dist/{213.bundle.9974b55ea267a38098f2.js → 213.bundle.ddafd3a6cc133357f03e.js} +3 -5
- package/dist/{2424.bundle.f62de9c66b85446b577b.js → 2424.bundle.daf0c3e78529e8aee79e.js} +3 -5
- package/dist/{2516.bundle.1ea0988d309a757bb6da.js → 2516.bundle.f62228e9a800de8d4b31.js} +6 -6
- package/dist/{2701.bundle.12bd01a80a9f8ea4cd94.js → 2701.bundle.6873805ddfdccc7a8b1e.js} +10 -10
- package/dist/{9195.bundle.ebe8a2e0ed02f4b5ffb6.js → 2851.bundle.51e26e3a79a24f508a03.js} +482 -177
- package/dist/{1730.bundle.82fdc899ec54ab6c18a0.js → 3138.bundle.1359814ebef04d7b2f2b.js} +16 -310
- package/dist/{3461.bundle.acbbc488820719343d48.js → 3461.bundle.522c6009f47a1a01ce47.js} +131 -107
- package/dist/{147.bundle.37d627289453cb6c3937.js → 3754.bundle.fd4b67c2a29c4bc4a840.js} +486 -49
- package/dist/{4202.bundle.5a0f8e4004c5d8a68548.js → 4202.bundle.4fcd0de412907efd5b53.js} +6 -6
- package/dist/{4019.bundle.83a604779f7da0101ced.js → 4287.bundle.b7840e7b94cbbc102236.js} +348 -237
- package/dist/{5462.bundle.21beddaca145b7465c72.js → 4406.bundle.573d234b4641d23cf8db.js} +1083 -1308
- package/dist/{1403.bundle.2fc4502e0990b048a4bb.js → 4507.bundle.929c147b8f17517e7769.js} +10 -305
- package/dist/{6347.bundle.784c48912700f281de1d.js → 4579.bundle.0a6b2f49a7e136a79e37.js} +561 -649
- package/dist/{4819.bundle.9fc6f913afc5f53fe33d.js → 4819.bundle.38df45ea36b450c9c236.js} +39 -39
- package/dist/{4775.bundle.7c0cead4a44ddc0b06d7.js → 5015.bundle.e907b7e60824e9b21863.js} +29 -333
- package/dist/{5028.bundle.6e48cc78ac80a3860418.js → 5028.bundle.807858e82e7c652139d9.js} +11 -13
- package/dist/{5261.bundle.6e1a017f8f1027557f5b.js → 5261.bundle.2655560097e9250eac44.js} +412 -345
- package/dist/{5457.bundle.716478f2792f83daa2bc.js → 5457.bundle.361d8d5426840a12b668.js} +16 -23
- package/dist/{5485.bundle.782d3f49f1020dc1f730.js → 5485.bundle.82495f29805a950f9172.js} +30 -36
- package/dist/{5491.bundle.2e01dd7ad29e4cc01bc1.js → 5491.bundle.4866d2ecb20dd089e071.js} +54 -51
- package/dist/{5802.bundle.3bf5e6b3ab330a594a47.js → 5802.bundle.26f84db0ff8851532c36.js} +79 -20
- package/dist/5802.css +1 -1
- package/dist/{5830.bundle.b073c265c4fcea1afff3.js → 5830.bundle.791019deddd536980a11.js} +3 -3
- package/dist/{5858.bundle.ff6b340cf7457db76a1a.js → 5858.bundle.466e58128de344ab53f3.js} +90 -86
- package/dist/{6027.bundle.5f39b6eb697906760a97.js → 6027.bundle.2f64fca578d9f2636144.js} +3 -5
- package/dist/{6354.bundle.c387737dc09c9cab4ff2.js → 6354.bundle.929febcf6d326e582e00.js} +151 -140
- package/dist/{6376.bundle.9cb74d7bc08476e2f1a7.js → 6376.bundle.527820a5cb1eece2a8d2.js} +6 -6
- package/dist/{2842.bundle.860b9f10fcdd9656947a.js → 6386.bundle.5d82d1f41d1c37a0358d.js} +904 -2298
- package/dist/6939.bundle.41fbdef87597b5172ec6.js +3 -3
- package/dist/{7159.bundle.a5991a5d4f0dd8f1c95f.js → 7159.bundle.fb9df255868960f69765.js} +7 -5
- package/dist/{3081.bundle.a91d88fbfb53b4f77ee4.js → 7166.bundle.5ac3827d0b367fe6bd6e.js} +1232 -470
- package/dist/{7190.bundle.e8f0193e0e06472f795c.js → 7190.bundle.479332d662ffe08d1f92.js} +1228 -855
- package/dist/{732.bundle.6978ac30a1e36abf06db.js → 732.bundle.ea6f9d8504e37e01a208.js} +5 -13
- package/dist/{7431.bundle.b01791d10e6cf9f503b0.js → 7431.bundle.5e14641f2c71e852abe7.js} +28 -28
- package/dist/{4410.bundle.c5224cd7d6238a7d4660.js → 7537.bundle.889ba5f2707418c6fd88.js} +5216 -2238
- package/dist/{7639.bundle.a6b187c87374ce1508bb.js → 7639.bundle.7e3a1383fb92172e8079.js} +3 -5
- package/dist/7758.bundle.c8d106364298e7d288f0.js +3 -3
- package/dist/{8094.bundle.5c44190a325ac23e3e5c.js → 8094.bundle.148a66619607e37cbf19.js} +3 -4
- package/dist/{8305.bundle.4e40a6d83d548535b0a4.js → 8305.bundle.1790ebf371ba9caf3a24.js} +71 -66
- package/dist/{6163.bundle.ad576a38d517b0031edb.js → 8499.bundle.2386efbfe1210c92d384.js} +7 -302
- package/dist/8499.css +2 -0
- package/dist/{85.bundle.29e6f5b4d8068a50e5ca.js → 85.bundle.3ebecb20682a1798dc77.js} +3 -5
- package/dist/{8558.bundle.0e8b808e19293cdd69a4.js → 8558.bundle.0cf331cc257bb5a04f21.js} +15 -309
- package/dist/{8583.bundle.9b62be9d8431e17782c8.js → 8583.bundle.1cb20f6f1e7ec1ca549c.js} +24 -27
- package/dist/{997.bundle.822b33e561263084e18c.js → 9039.bundle.f72736f47fedeff521e2.js} +4049 -2992
- package/dist/{7412.bundle.fab1742191b7fe937330.js → 9205.bundle.ed7bce8436a7a431955e.js} +6154 -3313
- package/dist/{3584.bundle.8cc0750425513433e9cc.js → 9567.bundle.ff782480a4c66e306027.js} +3751 -2856
- package/dist/{9845.bundle.255e7c7f7a88193b4e47.js → 9845.bundle.8c450e8d65a78a5afcd3.js} +10 -10
- package/dist/{9862.bundle.3a8958a82c572015d25d.js → 9862.bundle.a5f7925840868fa4ecdb.js} +8 -6
- package/dist/{9927.bundle.e0f2262ef305795ce7b1.js → 9927.bundle.e21480928d7062501426.js} +8 -6
- package/dist/app-config.js +12 -0
- package/dist/{app.bundle.4d14ef92d206bcd77aa6.js → app.bundle.3c03c873a65adf3826e0.js} +67399 -64373
- package/dist/app.bundle.css +3 -3
- package/dist/{polySeg.bundle.a5aa9130b4191253c410.js → compute.bundle.b7c2ea55f1a69f4a736b.js} +8 -20
- package/dist/{histogram-worker.bundle.d4e40a8018d2698b072e.js → histogram-worker.bundle.a2a50c4674d99c619ca7.js} +11 -23
- package/dist/index.html +1 -1
- package/dist/{interpolation.bundle.c70cb95d164dc494e6dc.js → interpolation.bundle.829844ff3f72f5645f29.js} +14 -26
- package/dist/{compute.bundle.64280c7af19ff567465f.js → polySeg.bundle.e1f6f05d81ea1352bef3.js} +10 -22
- package/dist/sw.js +1 -1
- package/package.json +23 -22
- package/dist/3343.bundle.d7578ce8f75d158c0bab.js +0 -297
- /package/dist/{1730.css → 3138.css} +0 -0
- /package/dist/{147.css → 3754.css} +0 -0
- /package/dist/{3343.css → 4972.css} +0 -0
- /package/dist/{6163.css → 7829.css} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
(globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[
|
|
2
|
+
(globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[7166],{
|
|
3
3
|
|
|
4
|
-
/***/ 38007
|
|
5
|
-
|
|
4
|
+
/***/ 38007
|
|
5
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
// EXPORTS
|
|
@@ -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 +
|
|
29
|
-
var src = __webpack_require__(
|
|
28
|
+
// EXTERNAL MODULE: ../../ui-next/src/index.ts + 3085 modules
|
|
29
|
+
var src = __webpack_require__(564);
|
|
30
30
|
;// ../../../extensions/cornerstone/src/hooks/useViewportHover.ts
|
|
31
31
|
|
|
32
32
|
|
|
@@ -109,15 +109,15 @@ var useViewportRendering = __webpack_require__(47488);
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
/***/ }
|
|
112
|
+
/***/ },
|
|
113
113
|
|
|
114
|
-
/***/ 9234
|
|
115
|
-
|
|
114
|
+
/***/ 9234
|
|
115
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
116
116
|
|
|
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__(
|
|
120
|
+
/* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(564);
|
|
121
121
|
/* harmony import */ var _useViewportSegmentations__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(79063);
|
|
122
122
|
|
|
123
123
|
|
|
@@ -131,10 +131,10 @@ function useActiveViewportSegmentationRepresentations() {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
|
|
134
|
-
/***/ }
|
|
134
|
+
/***/ },
|
|
135
135
|
|
|
136
|
-
/***/ 84535
|
|
137
|
-
|
|
136
|
+
/***/ 84535
|
|
137
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
138
138
|
|
|
139
139
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
140
140
|
/* harmony export */ R: () => (/* binding */ useMeasurementTracking)
|
|
@@ -238,10 +238,10 @@ function useMeasurementTracking({
|
|
|
238
238
|
}
|
|
239
239
|
/* unused harmony default export */ var __WEBPACK_DEFAULT_EXPORT__ = ((/* unused pure expression or super */ null && (useMeasurementTracking)));
|
|
240
240
|
|
|
241
|
-
/***/ }
|
|
241
|
+
/***/ },
|
|
242
242
|
|
|
243
|
-
/***/ 19214
|
|
244
|
-
|
|
243
|
+
/***/ 19214
|
|
244
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
245
245
|
|
|
246
246
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
247
247
|
/* harmony export */ d: () => (/* binding */ useMeasurements)
|
|
@@ -348,10 +348,10 @@ function useMeasurements({
|
|
|
348
348
|
return displayMeasurements;
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
-
/***/ }
|
|
351
|
+
/***/ },
|
|
352
352
|
|
|
353
|
-
/***/ 73421
|
|
354
|
-
|
|
353
|
+
/***/ 73421
|
|
354
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
355
355
|
|
|
356
356
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
357
357
|
/* harmony export */ j: () => (/* binding */ useSegmentations)
|
|
@@ -483,10 +483,10 @@ function useSegmentations(options) {
|
|
|
483
483
|
return segmentations;
|
|
484
484
|
}
|
|
485
485
|
|
|
486
|
-
/***/ }
|
|
486
|
+
/***/ },
|
|
487
487
|
|
|
488
|
-
/***/ 10225
|
|
489
|
-
|
|
488
|
+
/***/ 10225
|
|
489
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
490
490
|
|
|
491
491
|
|
|
492
492
|
// EXPORTS
|
|
@@ -498,8 +498,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
498
498
|
var react = __webpack_require__(86326);
|
|
499
499
|
// EXTERNAL MODULE: ../../core/src/index.ts + 69 modules
|
|
500
500
|
var src = __webpack_require__(42356);
|
|
501
|
-
// EXTERNAL MODULE: ../../ui-next/src/index.ts +
|
|
502
|
-
var ui_next_src = __webpack_require__(
|
|
501
|
+
// EXTERNAL MODULE: ../../ui-next/src/index.ts + 3085 modules
|
|
502
|
+
var ui_next_src = __webpack_require__(564);
|
|
503
503
|
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 1 modules
|
|
504
504
|
var esm = __webpack_require__(15327);
|
|
505
505
|
;// ../../../extensions/cornerstone/src/components/ViewportDataOverlaySettingMenu/utils.ts
|
|
@@ -805,10 +805,10 @@ function useViewportDisplaySets(viewportId, options) {
|
|
|
805
805
|
return result;
|
|
806
806
|
}
|
|
807
807
|
|
|
808
|
-
/***/ }
|
|
808
|
+
/***/ },
|
|
809
809
|
|
|
810
|
-
/***/ 47488
|
|
811
|
-
|
|
810
|
+
/***/ 47488
|
|
811
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
812
812
|
|
|
813
813
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
814
814
|
/* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__),
|
|
@@ -818,7 +818,9 @@ function useViewportDisplaySets(viewportId, options) {
|
|
|
818
818
|
/* harmony import */ var _ohif_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42356);
|
|
819
819
|
/* harmony import */ var _useViewportDisplaySets__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10225);
|
|
820
820
|
/* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(15327);
|
|
821
|
-
/* harmony import */ var
|
|
821
|
+
/* harmony import */ var _utils_getDataIdForViewport__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(67142);
|
|
822
|
+
/* harmony import */ var _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(93813);
|
|
823
|
+
|
|
822
824
|
|
|
823
825
|
|
|
824
826
|
|
|
@@ -826,13 +828,13 @@ function useViewportDisplaySets(viewportId, options) {
|
|
|
826
828
|
|
|
827
829
|
const getPosition = location => {
|
|
828
830
|
switch (location) {
|
|
829
|
-
case
|
|
831
|
+
case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_5__/* .ButtonLocation */ .ij.LeftMiddle:
|
|
830
832
|
return 'left';
|
|
831
|
-
case
|
|
833
|
+
case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_5__/* .ButtonLocation */ .ij.RightMiddle:
|
|
832
834
|
return 'right';
|
|
833
|
-
case
|
|
835
|
+
case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_5__/* .ButtonLocation */ .ij.BottomMiddle:
|
|
834
836
|
return 'bottom';
|
|
835
|
-
case
|
|
837
|
+
case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_5__/* .ButtonLocation */ .ij.TopMiddle:
|
|
836
838
|
return 'top';
|
|
837
839
|
default:
|
|
838
840
|
return 'bottom';
|
|
@@ -846,13 +848,6 @@ const linearToOpacity = linearValue => {
|
|
|
846
848
|
const opacityToLinear = opacityValue => {
|
|
847
849
|
return Math.pow(opacityValue, 1.0 / GAMMA);
|
|
848
850
|
};
|
|
849
|
-
const is3DViewport = ({
|
|
850
|
-
viewportId,
|
|
851
|
-
cornerstoneViewportService
|
|
852
|
-
}) => {
|
|
853
|
-
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
854
|
-
return viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.VolumeViewport3D;
|
|
855
|
-
};
|
|
856
851
|
|
|
857
852
|
/**
|
|
858
853
|
* Hook to access window level functionality for a specific viewport
|
|
@@ -871,14 +866,13 @@ function useViewportRendering(viewportId, options) {
|
|
|
871
866
|
colorbarService,
|
|
872
867
|
customizationService
|
|
873
868
|
} = servicesManager.services;
|
|
874
|
-
const [is3DVolume, setIs3DVolume] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(is3DViewport({
|
|
875
|
-
viewportId,
|
|
876
|
-
cornerstoneViewportService
|
|
877
|
-
}));
|
|
878
869
|
const [hasColorbar, setHasColorbar] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(colorbarService.hasColorbar(viewportId));
|
|
879
870
|
const [colorbarPosition, setColorbarPosition] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(options?.location ? getPosition(options.location) : 'bottom');
|
|
880
871
|
const [voiRange, setVoiRange] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)();
|
|
881
872
|
const voiRangeRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef();
|
|
873
|
+
// Viewport from service; kept in state so we can subscribe to VIEWPORT_DATA_CHANGED when null and re-run effects when it becomes available
|
|
874
|
+
const [viewport, setViewport] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(() => viewportId ? cornerstoneViewportService.getCornerstoneViewport(viewportId) ?? null : null);
|
|
875
|
+
const [is3DVolume, setIs3DVolume] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.VolumeViewport3D);
|
|
882
876
|
const [opacity, setOpacityState] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)();
|
|
883
877
|
const [opacityLinear, setOpacityLinearState] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)();
|
|
884
878
|
const [threshold, setThresholdState] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)();
|
|
@@ -922,6 +916,35 @@ function useViewportRendering(viewportId, options) {
|
|
|
922
916
|
}) || [];
|
|
923
917
|
}, [viewportDisplaySets, presets]);
|
|
924
918
|
|
|
919
|
+
// Keep viewport in state; when not available, subscribe to VIEWPORT_DATA_CHANGED so we set it when the viewport is ready
|
|
920
|
+
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
|
|
921
|
+
if (!viewportId) {
|
|
922
|
+
setViewport(null);
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
const vp = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
926
|
+
setViewport(vp ?? null);
|
|
927
|
+
if (vp) {
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
const {
|
|
931
|
+
unsubscribe
|
|
932
|
+
} = cornerstoneViewportService.subscribe(cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED, ({
|
|
933
|
+
viewportId: eventViewportId
|
|
934
|
+
}) => {
|
|
935
|
+
if (eventViewportId !== viewportId) {
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
const next = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
939
|
+
if (next) {
|
|
940
|
+
setViewport(next);
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
return () => {
|
|
944
|
+
unsubscribe();
|
|
945
|
+
};
|
|
946
|
+
}, [viewportId, cornerstoneViewportService]);
|
|
947
|
+
|
|
925
948
|
// Calculate pixel value range for the active display set
|
|
926
949
|
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
|
|
927
950
|
if (!activeDisplaySetInstanceUID) {
|
|
@@ -931,21 +954,20 @@ function useViewportRendering(viewportId, options) {
|
|
|
931
954
|
if (!selectedDisplaySet?.imageIds?.length) {
|
|
932
955
|
return;
|
|
933
956
|
}
|
|
934
|
-
|
|
935
|
-
if (!csViewport) {
|
|
957
|
+
if (!viewport) {
|
|
936
958
|
return;
|
|
937
959
|
}
|
|
938
|
-
if (!(
|
|
960
|
+
if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.BaseVolumeViewport)) {
|
|
939
961
|
return;
|
|
940
962
|
}
|
|
941
|
-
const volumeIds =
|
|
963
|
+
const volumeIds = viewport.getAllVolumeIds();
|
|
942
964
|
const volumeId = volumeIds.find(id => id.includes(activeDisplaySetInstanceUID));
|
|
943
965
|
if (!volumeId) {
|
|
944
966
|
return;
|
|
945
967
|
}
|
|
946
968
|
|
|
947
969
|
// only handle volume viewports for now
|
|
948
|
-
const imageData =
|
|
970
|
+
const imageData = viewport.getImageData(volumeId);
|
|
949
971
|
if (!imageData) {
|
|
950
972
|
return;
|
|
951
973
|
}
|
|
@@ -958,7 +980,7 @@ function useViewportRendering(viewportId, options) {
|
|
|
958
980
|
min: range[0],
|
|
959
981
|
max: range[1]
|
|
960
982
|
});
|
|
961
|
-
}, [activeDisplaySetInstanceUID, displaySetService,
|
|
983
|
+
}, [activeDisplaySetInstanceUID, displaySetService, viewport]);
|
|
962
984
|
|
|
963
985
|
// Get the presets specifically for the active display set
|
|
964
986
|
const activeDisplaySetPresets = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => {
|
|
@@ -972,52 +994,33 @@ function useViewportRendering(viewportId, options) {
|
|
|
972
994
|
return activePresetData.presets;
|
|
973
995
|
}, [allWindowLevelPresets, activeDisplaySetInstanceUID]);
|
|
974
996
|
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
|
|
975
|
-
setIs3DVolume(
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
let properties;
|
|
985
|
-
if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.StackViewport) {
|
|
986
|
-
properties = viewport.getProperties();
|
|
987
|
-
if (properties.voiRange) {
|
|
988
|
-
setVoiRange(properties.voiRange);
|
|
989
|
-
voiRangeRef.current = properties.voiRange;
|
|
990
|
-
}
|
|
991
|
-
} else if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.BaseVolumeViewport) {
|
|
992
|
-
// For volume viewports, find the actor for the active display set
|
|
993
|
-
const volumeIds = viewport.getAllVolumeIds();
|
|
994
|
-
const volumeId = volumeIds.find(id => id.includes(activeDisplaySetInstanceUID));
|
|
995
|
-
if (volumeId) {
|
|
996
|
-
properties = viewport.getProperties(volumeId);
|
|
997
|
-
if (properties?.voiRange) {
|
|
998
|
-
setVoiRange(properties.voiRange);
|
|
999
|
-
voiRangeRef.current = properties.voiRange;
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
// Get opacity from colormap if available
|
|
1003
|
-
if (properties?.colormap?.opacity !== undefined) {
|
|
1004
|
-
const isArray = Array.isArray(properties.colormap.opacity);
|
|
1005
|
-
const opacity = isArray ? properties.colormap.opacity.reduce((max, current) => Math.max(max, current), 0) : properties.colormap.opacity;
|
|
1006
|
-
setOpacityState(opacity);
|
|
1007
|
-
setOpacityLinearState(opacityToLinear(opacity));
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
// Get threshold from colormap if available
|
|
1011
|
-
if (properties?.colormap && properties.colormap.threshold !== undefined) {
|
|
1012
|
-
setThresholdState(properties.colormap.threshold);
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
} catch (error) {
|
|
1017
|
-
console.error('Error initializing VOI range:', error);
|
|
997
|
+
setIs3DVolume(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.VolumeViewport3D);
|
|
998
|
+
if (!viewport || !activeDisplaySetInstanceUID) {
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
try {
|
|
1002
|
+
const dataId = (0,_utils_getDataIdForViewport__WEBPACK_IMPORTED_MODULE_4__/* .getDataIdForViewport */ .V)(viewport, activeDisplaySetInstanceUID);
|
|
1003
|
+
const properties = dataId != null ? viewport.getProperties(dataId) : viewport.getProperties();
|
|
1004
|
+
if (!properties) {
|
|
1005
|
+
return;
|
|
1018
1006
|
}
|
|
1007
|
+
if (properties.voiRange) {
|
|
1008
|
+
setVoiRange(properties.voiRange);
|
|
1009
|
+
voiRangeRef.current = properties.voiRange;
|
|
1010
|
+
}
|
|
1011
|
+
if (properties.colormap?.opacity !== undefined) {
|
|
1012
|
+
const opacityVal = properties.colormap.opacity;
|
|
1013
|
+
const opacity = Array.isArray(opacityVal) ? opacityVal.reduce((max, current) => Math.max(max, current), 0) : opacityVal;
|
|
1014
|
+
setOpacityState(opacity);
|
|
1015
|
+
setOpacityLinearState(opacityToLinear(opacity));
|
|
1016
|
+
}
|
|
1017
|
+
if (properties.colormap?.threshold !== undefined) {
|
|
1018
|
+
setThresholdState(properties.colormap.threshold);
|
|
1019
|
+
}
|
|
1020
|
+
} catch (error) {
|
|
1021
|
+
console.error('Error initializing VOI range:', error);
|
|
1019
1022
|
}
|
|
1020
|
-
}, [
|
|
1023
|
+
}, [activeDisplaySetInstanceUID, viewport]);
|
|
1021
1024
|
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
|
|
1022
1025
|
if (!viewportId) {
|
|
1023
1026
|
return;
|
|
@@ -1035,17 +1038,10 @@ function useViewportRendering(viewportId, options) {
|
|
|
1035
1038
|
};
|
|
1036
1039
|
}, [colorbarService, viewportId]);
|
|
1037
1040
|
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
|
|
1038
|
-
if (!
|
|
1039
|
-
return;
|
|
1040
|
-
}
|
|
1041
|
-
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
1042
|
-
if (!viewport) {
|
|
1041
|
+
if (!activeDisplaySetInstanceUID || !viewport?.element) {
|
|
1043
1042
|
return;
|
|
1044
1043
|
}
|
|
1045
1044
|
const element = viewport.element;
|
|
1046
|
-
if (!element) {
|
|
1047
|
-
return;
|
|
1048
|
-
}
|
|
1049
1045
|
const updateVOI = eventDetail => {
|
|
1050
1046
|
const {
|
|
1051
1047
|
range
|
|
@@ -1085,7 +1081,7 @@ function useViewportRendering(viewportId, options) {
|
|
|
1085
1081
|
element.removeEventListener(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.Enums.Events.VOI_MODIFIED, updateVOI);
|
|
1086
1082
|
element.removeEventListener(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.Enums.Events.COLORMAP_MODIFIED, updateColormap);
|
|
1087
1083
|
};
|
|
1088
|
-
}, [
|
|
1084
|
+
}, [activeDisplaySetInstanceUID, viewport, opacityToLinear]);
|
|
1089
1085
|
const validateActiveDisplaySet = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => {
|
|
1090
1086
|
if (!activeDisplaySetInstanceUID) {
|
|
1091
1087
|
throw new Error('No active display set instance UID is available');
|
|
@@ -1238,12 +1234,8 @@ function useViewportRendering(viewportId, options) {
|
|
|
1238
1234
|
},
|
|
1239
1235
|
context: 'CORNERSTONE'
|
|
1240
1236
|
});
|
|
1241
|
-
}, [commandsManager,
|
|
1237
|
+
}, [commandsManager, validateActiveDisplaySet, viewport, viewportId]);
|
|
1242
1238
|
const setOpacity = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(opacityValue => {
|
|
1243
|
-
if (!viewportId) {
|
|
1244
|
-
return;
|
|
1245
|
-
}
|
|
1246
|
-
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
1247
1239
|
if (!viewport || !(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.BaseVolumeViewport)) {
|
|
1248
1240
|
return;
|
|
1249
1241
|
}
|
|
@@ -1274,17 +1266,13 @@ function useViewportRendering(viewportId, options) {
|
|
|
1274
1266
|
colormap: updatedColormap
|
|
1275
1267
|
}, volumeId);
|
|
1276
1268
|
viewport.render();
|
|
1277
|
-
}, [
|
|
1269
|
+
}, [validateActiveDisplaySet, opacityToLinear, viewport]);
|
|
1278
1270
|
const setOpacityLinear = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(linearValue => {
|
|
1279
1271
|
// Convert linear UI value to actual opacity value and apply it
|
|
1280
1272
|
const actualOpacity = linearToOpacity(linearValue);
|
|
1281
1273
|
setOpacity(actualOpacity);
|
|
1282
1274
|
}, [linearToOpacity, setOpacity]);
|
|
1283
1275
|
const setThreshold = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(thresholdValue => {
|
|
1284
|
-
if (!viewportId) {
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
1288
1276
|
if (!viewport || !(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.BaseVolumeViewport)) {
|
|
1289
1277
|
return;
|
|
1290
1278
|
}
|
|
@@ -1302,15 +1290,14 @@ function useViewportRendering(viewportId, options) {
|
|
|
1302
1290
|
}
|
|
1303
1291
|
}, volumeId);
|
|
1304
1292
|
viewport.render();
|
|
1305
|
-
}, [
|
|
1293
|
+
}, [validateActiveDisplaySet, viewport]);
|
|
1306
1294
|
|
|
1307
1295
|
// Get the current colormap for the active display set
|
|
1308
1296
|
const colormap = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => {
|
|
1309
|
-
if (!
|
|
1297
|
+
if (!activeDisplaySetInstanceUID || !viewportDisplaySets?.length) {
|
|
1310
1298
|
return null;
|
|
1311
1299
|
}
|
|
1312
1300
|
try {
|
|
1313
|
-
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
1314
1301
|
if (!viewport) {
|
|
1315
1302
|
return null;
|
|
1316
1303
|
}
|
|
@@ -1339,7 +1326,7 @@ function useViewportRendering(viewportId, options) {
|
|
|
1339
1326
|
console.error('Error getting viewport colormap:', error);
|
|
1340
1327
|
return colorbarProperties?.colormaps?.find(c => c.Name === 'Grayscale') || colorbarProperties?.colormaps?.[0];
|
|
1341
1328
|
}
|
|
1342
|
-
}, [
|
|
1329
|
+
}, [activeDisplaySetInstanceUID, viewportDisplaySets, colorbarProperties?.colormaps, viewport]);
|
|
1343
1330
|
|
|
1344
1331
|
// 3D volume rendering functions
|
|
1345
1332
|
const setVolumeRenderingPreset = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(preset => {
|
|
@@ -1405,7 +1392,10 @@ function useViewportRendering(viewportId, options) {
|
|
|
1405
1392
|
setWindowLevel,
|
|
1406
1393
|
setVOIRange,
|
|
1407
1394
|
voiRange,
|
|
1408
|
-
windowLevel: _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.utilities.windowLevel.toWindowLevel(voiRange?.lower, voiRange?.upper)
|
|
1395
|
+
windowLevel: voiRange ? _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.utilities.windowLevel.toWindowLevel(voiRange?.lower, voiRange?.upper) : {
|
|
1396
|
+
windowCenter: null,
|
|
1397
|
+
windowWidth: null
|
|
1398
|
+
},
|
|
1409
1399
|
// Colorbar functions
|
|
1410
1400
|
hasColorbar,
|
|
1411
1401
|
toggleColorbar,
|
|
@@ -1473,10 +1463,10 @@ function getCustomizationData(customizationService) {
|
|
|
1473
1463
|
};
|
|
1474
1464
|
}
|
|
1475
1465
|
|
|
1476
|
-
/***/ }
|
|
1466
|
+
/***/ },
|
|
1477
1467
|
|
|
1478
|
-
/***/ 79063
|
|
1479
|
-
|
|
1468
|
+
/***/ 79063
|
|
1469
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
1480
1470
|
|
|
1481
1471
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
1482
1472
|
/* harmony export */ L: () => (/* binding */ useViewportSegmentations)
|
|
@@ -1494,7 +1484,8 @@ const excludedModalities = ['SM', 'OT', 'DOC', 'ECG'];
|
|
|
1494
1484
|
function mapSegmentationToDisplay(segmentation, customizationService) {
|
|
1495
1485
|
const {
|
|
1496
1486
|
label,
|
|
1497
|
-
segments
|
|
1487
|
+
segments,
|
|
1488
|
+
fallbackLabel
|
|
1498
1489
|
} = segmentation;
|
|
1499
1490
|
|
|
1500
1491
|
// Get the readable text mapping once
|
|
@@ -1555,6 +1546,7 @@ function mapSegmentationToDisplay(segmentation, customizationService) {
|
|
|
1555
1546
|
return {
|
|
1556
1547
|
...segmentation,
|
|
1557
1548
|
label,
|
|
1549
|
+
fallbackLabel,
|
|
1558
1550
|
segments: updatedSegments
|
|
1559
1551
|
};
|
|
1560
1552
|
}
|
|
@@ -1657,74 +1649,36 @@ function useViewportSegmentations({
|
|
|
1657
1649
|
return segmentationsWithRepresentations;
|
|
1658
1650
|
}
|
|
1659
1651
|
|
|
1660
|
-
/***/ }
|
|
1652
|
+
/***/ },
|
|
1661
1653
|
|
|
1662
|
-
/***/
|
|
1663
|
-
|
|
1654
|
+
/***/ 87166
|
|
1655
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
1664
1656
|
|
|
1665
|
-
// ESM COMPAT FLAG
|
|
1666
|
-
__webpack_require__.r(__webpack_exports__);
|
|
1667
1657
|
|
|
1668
1658
|
// EXPORTS
|
|
1669
1659
|
__webpack_require__.d(__webpack_exports__, {
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
MeasurementsOrAdditionalFindings: () => (/* reexport */ MeasurementsOrAdditionalFindings),
|
|
1682
|
-
OHIFCornerstoneViewport: () => (/* binding */ OHIFCornerstoneViewport),
|
|
1683
|
-
PanelMeasurement: () => (/* reexport */ PanelMeasurement),
|
|
1684
|
-
PanelSegmentation: () => (/* reexport */ PanelSegmentation),
|
|
1685
|
-
PlanarFreehandROI: () => (/* reexport */ measurementServiceMappings_PlanarFreehandROI),
|
|
1686
|
-
RectangleROI: () => (/* reexport */ measurementServiceMappings_RectangleROI),
|
|
1687
|
-
SeriesMeasurementTrigger: () => (/* reexport */ SeriesMeasurementTrigger),
|
|
1688
|
-
SeriesMeasurements: () => (/* reexport */ SeriesMeasurements),
|
|
1689
|
-
StudyMeasurements: () => (/* reexport */ StudyMeasurements),
|
|
1690
|
-
StudyMeasurementsActions: () => (/* reexport */ StudyMeasurementsActions),
|
|
1691
|
-
StudySummaryFromMetadata: () => (/* reexport */ StudySummaryFromMetadata),
|
|
1692
|
-
Types: () => (/* reexport */ types_namespaceObject),
|
|
1693
|
-
VOLUME_LOADER_SCHEME: () => (/* reexport */ VOLUME_LOADER_SCHEME),
|
|
1694
|
-
VolumeLighting: () => (/* reexport */ VolumeLighting),
|
|
1695
|
-
VolumeRenderingOptions: () => (/* reexport */ VolumeRenderingOptions),
|
|
1696
|
-
VolumeRenderingPresets: () => (/* reexport */ VolumeRenderingPresets),
|
|
1697
|
-
VolumeRenderingQuality: () => (/* reexport */ VolumeRenderingQuality),
|
|
1698
|
-
VolumeShade: () => (/* reexport */ VolumeShade),
|
|
1699
|
-
VolumeShift: () => (/* reexport */ VolumeShift),
|
|
1700
|
-
WindowLevel: () => (/* reexport */ WindowLevel),
|
|
1701
|
-
WindowLevelActionMenu: () => (/* reexport */ WindowLevelActionMenu),
|
|
1702
|
-
WindowLevelActionMenuContent: () => (/* reexport */ WindowLevelActionMenuContent),
|
|
1703
|
-
WindowLevelActionMenuWrapper: () => (/* reexport */ WindowLevelActionMenuWrapper),
|
|
1660
|
+
_I: () => (/* reexport */ AccordionGroup),
|
|
1661
|
+
fX: () => (/* reexport */ enums),
|
|
1662
|
+
CP: () => (/* reexport */ MeasurementsOrAdditionalFindings),
|
|
1663
|
+
R9: () => (/* binding */ OHIFCornerstoneViewport),
|
|
1664
|
+
re: () => (/* reexport */ PanelMeasurement),
|
|
1665
|
+
rE: () => (/* reexport */ PanelSegmentation),
|
|
1666
|
+
V: () => (/* reexport */ SeriesMeasurements),
|
|
1667
|
+
B9: () => (/* reexport */ StudyMeasurements),
|
|
1668
|
+
_9: () => (/* reexport */ StudyMeasurementsActions),
|
|
1669
|
+
x3: () => (/* reexport */ StudySummaryFromMetadata),
|
|
1670
|
+
Rj: () => (/* reexport */ VOLUME_LOADER_SCHEME),
|
|
1704
1671
|
"default": () => (/* binding */ cornerstone_src),
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
groupByNamedSets: () => (/* reexport */ groupByNamedSets),
|
|
1712
|
-
groupByStudy: () => (/* reexport */ groupByStudy),
|
|
1713
|
-
measurementMappingUtils: () => (/* reexport */ utils_namespaceObject),
|
|
1714
|
-
setEnabledElement: () => (/* reexport */ state/* setEnabledElement */.ye),
|
|
1715
|
-
toolNames: () => (/* reexport */ toolNames),
|
|
1716
|
-
useActiveViewportSegmentationRepresentations: () => (/* reexport */ useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c),
|
|
1717
|
-
useLutPresentationStore: () => (/* reexport */ useLutPresentationStore/* useLutPresentationStore */.I),
|
|
1718
|
-
useMeasurementTracking: () => (/* reexport */ useMeasurementTracking/* useMeasurementTracking */.R),
|
|
1719
|
-
useMeasurements: () => (/* reexport */ useMeasurements/* useMeasurements */.d),
|
|
1720
|
-
usePositionPresentationStore: () => (/* reexport */ usePositionPresentationStore/* usePositionPresentationStore */.q),
|
|
1721
|
-
useSegmentationPresentationStore: () => (/* reexport */ useSegmentationPresentationStore/* useSegmentationPresentationStore */.v),
|
|
1722
|
-
useSegmentations: () => (/* reexport */ useSegmentations/* useSegmentations */.j),
|
|
1723
|
-
useSelectedSegmentationsForViewportStore: () => (/* reexport */ useSelectedSegmentationsForViewportStore),
|
|
1724
|
-
useSynchronizersStore: () => (/* reexport */ useSynchronizersStore/* useSynchronizersStore */.U),
|
|
1725
|
-
utils: () => (/* reexport */ src_utils)
|
|
1672
|
+
HA: () => (/* reexport */ utils_dicomLoaderService),
|
|
1673
|
+
J4: () => (/* reexport */ getSOPInstanceAttributes),
|
|
1674
|
+
c3: () => (/* reexport */ useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c),
|
|
1675
|
+
qu: () => (/* reexport */ usePositionPresentationStore/* usePositionPresentationStore */.q),
|
|
1676
|
+
jo: () => (/* reexport */ useSegmentations/* useSegmentations */.j),
|
|
1677
|
+
Wp: () => (/* reexport */ src_utils)
|
|
1726
1678
|
});
|
|
1727
1679
|
|
|
1680
|
+
// UNUSED EXPORTS: CloneChildren, Colorbar, Colormap, CornerstoneViewportDownloadForm, DYNAMIC_VOLUME_LOADER_SCHEME, DicomUpload, ImageOverlayViewerTool, MeasumentsMenu, MeasurementOrAdditionalFindingSets, PlanarFreehandROI, RectangleROI, SeriesMeasurementTrigger, Types, VolumeLighting, VolumeRenderingOptions, VolumeRenderingPresets, VolumeRenderingQuality, VolumeShade, VolumeShift, WindowLevel, WindowLevelActionMenu, WindowLevelActionMenuContent, WindowLevelActionMenuWrapper, findNearbyToolData, getActiveViewportEnabledElement, getEnabledElement, groupByDisplaySet, groupByNamedSets, groupByStudy, measurementMappingUtils, setEnabledElement, toolNames, useLutPresentationStore, useMeasurementTracking, useMeasurements, useSegmentationPresentationStore, useSelectedSegmentationsForViewportStore, useSynchronizersStore
|
|
1681
|
+
|
|
1728
1682
|
// NAMESPACE OBJECT: ../../../extensions/cornerstone/src/enums.ts
|
|
1729
1683
|
var enums_namespaceObject = {};
|
|
1730
1684
|
__webpack_require__.r(enums_namespaceObject);
|
|
@@ -1734,22 +1688,6 @@ __webpack_require__.d(enums_namespaceObject, {
|
|
|
1734
1688
|
Ay: () => (enums)
|
|
1735
1689
|
});
|
|
1736
1690
|
|
|
1737
|
-
// NAMESPACE OBJECT: ../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/index.ts
|
|
1738
|
-
var utils_namespaceObject = {};
|
|
1739
|
-
__webpack_require__.r(utils_namespaceObject);
|
|
1740
|
-
__webpack_require__.d(utils_namespaceObject, {
|
|
1741
|
-
getDisplayUnit: () => (utils_getDisplayUnit),
|
|
1742
|
-
getFirstAnnotationSelected: () => (getFirstAnnotationSelected),
|
|
1743
|
-
getHandlesFromPoints: () => (getHandlesFromPoints),
|
|
1744
|
-
getSOPInstanceAttributes: () => (getSOPInstanceAttributes),
|
|
1745
|
-
isAnnotationSelected: () => (isAnnotationSelected),
|
|
1746
|
-
setAnnotationSelected: () => (setAnnotationSelected)
|
|
1747
|
-
});
|
|
1748
|
-
|
|
1749
|
-
// NAMESPACE OBJECT: ../../../extensions/cornerstone/src/types/index.ts
|
|
1750
|
-
var types_namespaceObject = {};
|
|
1751
|
-
__webpack_require__.r(types_namespaceObject);
|
|
1752
|
-
|
|
1753
1691
|
// EXTERNAL MODULE: ../../../node_modules/react/index.js
|
|
1754
1692
|
var react = __webpack_require__(86326);
|
|
1755
1693
|
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 1 modules
|
|
@@ -1770,8 +1708,8 @@ var src = __webpack_require__(42356);
|
|
|
1770
1708
|
var loaders = __webpack_require__(19742);
|
|
1771
1709
|
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/enums/RequestType.js
|
|
1772
1710
|
var RequestType = __webpack_require__(43213);
|
|
1773
|
-
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/dicom-image-loader/dist/esm/index.js +
|
|
1774
|
-
var dicom_image_loader_dist_esm = __webpack_require__(
|
|
1711
|
+
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/dicom-image-loader/dist/esm/index.js + 80 modules
|
|
1712
|
+
var dicom_image_loader_dist_esm = __webpack_require__(76318);
|
|
1775
1713
|
;// ../../../extensions/cornerstone/src/initWADOImageLoader.js
|
|
1776
1714
|
|
|
1777
1715
|
|
|
@@ -1810,8 +1748,8 @@ function destroy() {
|
|
|
1810
1748
|
var ai_dist_esm = __webpack_require__(75165);
|
|
1811
1749
|
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/polymorphic-segmentation/dist/esm/index.js + 14 modules
|
|
1812
1750
|
var polymorphic_segmentation_dist_esm = __webpack_require__(56983);
|
|
1813
|
-
// EXTERNAL MODULE: ../../../extensions/default/src/index.ts +
|
|
1814
|
-
var default_src = __webpack_require__(
|
|
1751
|
+
// EXTERNAL MODULE: ../../../extensions/default/src/index.ts + 140 modules
|
|
1752
|
+
var default_src = __webpack_require__(62851);
|
|
1815
1753
|
// EXTERNAL MODULE: ../../../extensions/cornerstone/src/state.ts
|
|
1816
1754
|
var state = __webpack_require__(71353);
|
|
1817
1755
|
;// ../../../extensions/cornerstone/src/utils/getViewportEnabledElement.ts
|
|
@@ -1913,7 +1851,7 @@ function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
|
|
|
1913
1851
|
reject('UIDialogService is not initiated');
|
|
1914
1852
|
return;
|
|
1915
1853
|
}
|
|
1916
|
-
(0,default_src
|
|
1854
|
+
(0,default_src/* callInputDialog */.l5)({
|
|
1917
1855
|
uiDialogService,
|
|
1918
1856
|
title: 'Calibration',
|
|
1919
1857
|
placeholder: 'Actual Physical distance (mm)',
|
|
@@ -2614,6 +2552,7 @@ function getHandlesFromPoints(points) {
|
|
|
2614
2552
|
}), {});
|
|
2615
2553
|
}
|
|
2616
2554
|
;// ../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/selection.ts
|
|
2555
|
+
/* unused harmony import specifier */ var cs3dToolAnnotationUtils;
|
|
2617
2556
|
|
|
2618
2557
|
|
|
2619
2558
|
/**
|
|
@@ -2622,7 +2561,7 @@ function getHandlesFromPoints(points) {
|
|
|
2622
2561
|
* @returns boolean
|
|
2623
2562
|
*/
|
|
2624
2563
|
function isAnnotationSelected(annotationUID) {
|
|
2625
|
-
return
|
|
2564
|
+
return cs3dToolAnnotationUtils.selection.isAnnotationSelected(annotationUID);
|
|
2626
2565
|
}
|
|
2627
2566
|
|
|
2628
2567
|
/**
|
|
@@ -2634,7 +2573,7 @@ function setAnnotationSelected(annotationUID, selected) {
|
|
|
2634
2573
|
const isCurrentSelected = isAnnotationSelected(annotationUID);
|
|
2635
2574
|
// branch cut, avoid invoking imaging library unnecessarily.
|
|
2636
2575
|
if (isCurrentSelected !== selected) {
|
|
2637
|
-
|
|
2576
|
+
cs3dToolAnnotationUtils.selection.setAnnotationSelected(annotationUID, selected);
|
|
2638
2577
|
}
|
|
2639
2578
|
}
|
|
2640
2579
|
function getFirstAnnotationSelected(element) {
|
|
@@ -6065,6 +6004,12 @@ const connectMeasurementServiceToTools = ({
|
|
|
6065
6004
|
if (source?.name && source.name !== initMeasurementService_CORNERSTONE_3D_TOOLS_SOURCE_NAME) {
|
|
6066
6005
|
return;
|
|
6067
6006
|
}
|
|
6007
|
+
// Cancel any active tool manipulation (e.g., Spline/Livewire) to avoid leaving the tool
|
|
6008
|
+
// in a drawing state after deleting a not completed measurement, which can block viewport interactivity.
|
|
6009
|
+
const element = getActiveViewportEnabledElement(viewportGridService)?.viewport?.element;
|
|
6010
|
+
if (element) {
|
|
6011
|
+
(0,dist_esm.cancelActiveManipulations)(element);
|
|
6012
|
+
}
|
|
6068
6013
|
const removedAnnotation = dist_esm.annotation.state.getAnnotation(removedMeasurementId);
|
|
6069
6014
|
removeAnnotation(removedMeasurementId);
|
|
6070
6015
|
// Ensure `removedAnnotation` is available before triggering the memo,
|
|
@@ -7463,7 +7408,8 @@ function _showCPURenderingModal(uiModalService, hangingProtocolService) {
|
|
|
7463
7408
|
'viewportOverlay.topRight': [],
|
|
7464
7409
|
'viewportOverlay.bottomLeft': [{
|
|
7465
7410
|
id: 'WindowLevel',
|
|
7466
|
-
inheritsFrom: 'ohif.overlayItem.windowLevel'
|
|
7411
|
+
inheritsFrom: 'ohif.overlayItem.windowLevel',
|
|
7412
|
+
title: 'Window Level'
|
|
7467
7413
|
}, {
|
|
7468
7414
|
id: 'ZoomLevel',
|
|
7469
7415
|
inheritsFrom: 'ohif.overlayItem.zoomLevel',
|
|
@@ -7474,11 +7420,12 @@ function _showCPURenderingModal(uiModalService, hangingProtocolService) {
|
|
|
7474
7420
|
}],
|
|
7475
7421
|
'viewportOverlay.bottomRight': [{
|
|
7476
7422
|
id: 'InstanceNumber',
|
|
7477
|
-
inheritsFrom: 'ohif.overlayItem.instanceNumber'
|
|
7423
|
+
inheritsFrom: 'ohif.overlayItem.instanceNumber',
|
|
7424
|
+
title: 'Instance Number'
|
|
7478
7425
|
}]
|
|
7479
7426
|
});
|
|
7480
|
-
// EXTERNAL MODULE: ../../ui-next/src/index.ts +
|
|
7481
|
-
var ui_next_src = __webpack_require__(
|
|
7427
|
+
// EXTERNAL MODULE: ../../ui-next/src/index.ts + 3085 modules
|
|
7428
|
+
var ui_next_src = __webpack_require__(564);
|
|
7482
7429
|
// EXTERNAL MODULE: ../../../node_modules/react-i18next/dist/es/index.js + 15 modules
|
|
7483
7430
|
var es = __webpack_require__(99993);
|
|
7484
7431
|
;// ../../../extensions/cornerstone/src/components/ExportSegmentationSubMenuItem.tsx
|
|
@@ -7501,37 +7448,13 @@ const ExportSegmentationSubMenuItem = ({
|
|
|
7501
7448
|
className: "text-foreground"
|
|
7502
7449
|
}), /*#__PURE__*/react.createElement("span", {
|
|
7503
7450
|
className: "pl-2"
|
|
7504
|
-
}, t('
|
|
7505
|
-
className: "flex items-center pl-0"
|
|
7506
|
-
}, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Download, {
|
|
7507
|
-
className: "h-5 w-5"
|
|
7508
|
-
}), /*#__PURE__*/react.createElement("span", {
|
|
7509
|
-
className: "pl-1"
|
|
7510
|
-
}, t('Download'))), segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
|
|
7451
|
+
}, t('Export'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuPortal */.dce, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubContent */.M56, null, segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
|
|
7511
7452
|
onClick: e => {
|
|
7512
7453
|
e.preventDefault();
|
|
7513
7454
|
actions.downloadCSVSegmentationReport(segmentationId);
|
|
7514
7455
|
},
|
|
7515
7456
|
disabled: !allowExport
|
|
7516
7457
|
}, t('CSV Report')), segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
|
|
7517
|
-
onClick: e => {
|
|
7518
|
-
e.preventDefault();
|
|
7519
|
-
actions.onSegmentationDownload(segmentationId);
|
|
7520
|
-
},
|
|
7521
|
-
disabled: !allowExport
|
|
7522
|
-
}, t('DICOM SEG')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
|
|
7523
|
-
onClick: e => {
|
|
7524
|
-
e.preventDefault();
|
|
7525
|
-
actions.onSegmentationDownloadRTSS(segmentationId);
|
|
7526
|
-
},
|
|
7527
|
-
disabled: !allowExport
|
|
7528
|
-
}, t('DICOM RTSS')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuLabel */.lpj, {
|
|
7529
|
-
className: "flex items-center pl-0"
|
|
7530
|
-
}, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
|
|
7531
|
-
className: "h-5 w-5"
|
|
7532
|
-
}), /*#__PURE__*/react.createElement("span", {
|
|
7533
|
-
className: "pl-1 pt-1"
|
|
7534
|
-
}, t('Export'))), segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
|
|
7535
7458
|
onClick: e => {
|
|
7536
7459
|
e.preventDefault();
|
|
7537
7460
|
actions.storeSegmentation(segmentationId, 'SEG');
|
|
@@ -7608,16 +7531,6 @@ const CustomDropdownMenuContent = () => {
|
|
|
7608
7531
|
context: 'CORNERSTONE'
|
|
7609
7532
|
});
|
|
7610
7533
|
},
|
|
7611
|
-
onSegmentationDownloadRTSS: segmentationId => {
|
|
7612
|
-
commandsManager.run('downloadRTSS', {
|
|
7613
|
-
segmentationId
|
|
7614
|
-
});
|
|
7615
|
-
},
|
|
7616
|
-
onSegmentationDownload: segmentationId => {
|
|
7617
|
-
commandsManager.run('downloadSegmentation', {
|
|
7618
|
-
segmentationId
|
|
7619
|
-
});
|
|
7620
|
-
},
|
|
7621
7534
|
downloadCSVSegmentationReport: segmentationId => {
|
|
7622
7535
|
commandsManager.run('downloadCSVSegmentationReport', {
|
|
7623
7536
|
segmentationId
|
|
@@ -7815,7 +7728,7 @@ function SegmentationToolConfig() {
|
|
|
7815
7728
|
});
|
|
7816
7729
|
};
|
|
7817
7730
|
return /*#__PURE__*/react.createElement("div", {
|
|
7818
|
-
className: "bg-muted flex flex-col gap-2 border-b border-b-[2px] border-
|
|
7731
|
+
className: "bg-muted flex flex-col gap-2 border-b border-b-[2px] border-background px-2 py-3"
|
|
7819
7732
|
}, /*#__PURE__*/react.createElement("div", {
|
|
7820
7733
|
className: "flex items-center gap-2"
|
|
7821
7734
|
}, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
|
|
@@ -8624,7 +8537,7 @@ const DicomUploadProgressItem = /*#__PURE__*/(0,react.memo)(({
|
|
|
8624
8537
|
}, /*#__PURE__*/react.createElement("div", {
|
|
8625
8538
|
className: "flex w-6 shrink-0 items-center justify-center"
|
|
8626
8539
|
}, getStatusIcon()), /*#__PURE__*/react.createElement("div", {
|
|
8627
|
-
className: "overflow-hidden text-ellipsis whitespace-nowrap
|
|
8540
|
+
className: "text-foreground overflow-hidden text-ellipsis whitespace-nowrap"
|
|
8628
8541
|
}, dicomFileUploader.getFileName())), failedReason && /*#__PURE__*/react.createElement("div", {
|
|
8629
8542
|
className: "pl-10"
|
|
8630
8543
|
}, failedReason)), /*#__PURE__*/react.createElement("div", {
|
|
@@ -8866,7 +8779,7 @@ function DicomUploadProgress({
|
|
|
8866
8779
|
}, [numFilesCompleted]);
|
|
8867
8780
|
const getNumCompletedAndTimeRemainingComponent = () => {
|
|
8868
8781
|
return /*#__PURE__*/react.createElement("div", {
|
|
8869
|
-
className: "bg-muted flex h-14 items-center px-1 pb-4 text-lg
|
|
8782
|
+
className: "bg-muted text-foreground flex h-14 items-center px-1 pb-4 text-lg"
|
|
8870
8783
|
}, numFilesCompleted === dicomFileUploaderArr.length ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("span", {
|
|
8871
8784
|
className: NO_WRAP_ELLIPSIS_CLASS_NAMES
|
|
8872
8785
|
}, `${dicomFileUploaderArr.length} ${dicomFileUploaderArr.length > 1 ? 'files' : 'file'} completed.`), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
|
|
@@ -8916,7 +8829,7 @@ function DicomUploadProgress({
|
|
|
8916
8829
|
return /*#__PURE__*/react.createElement("div", {
|
|
8917
8830
|
className: "flex grow flex-col"
|
|
8918
8831
|
}, getNumCompletedAndTimeRemainingComponent(), /*#__PURE__*/react.createElement("div", {
|
|
8919
|
-
className: "flex grow flex-col overflow-hidden bg-
|
|
8832
|
+
className: "flex grow flex-col overflow-hidden bg-background text-lg"
|
|
8920
8833
|
}, getPercentCompleteComponent(), /*#__PURE__*/react.createElement("div", {
|
|
8921
8834
|
className: "ohif-scrollbar h-1 grow overflow-y-scroll px-2"
|
|
8922
8835
|
}, dicomFileUploaderArr.filter(dicomFileUploader => !showFailedOnly || dicomFileUploader.getStatus() === UploadStatus.Failed).map(dicomFileUploader => /*#__PURE__*/react.createElement(DicomUpload_DicomUploadProgressItem, {
|
|
@@ -8945,7 +8858,7 @@ function DicomUpload({
|
|
|
8945
8858
|
onComplete,
|
|
8946
8859
|
onStarted
|
|
8947
8860
|
}) {
|
|
8948
|
-
const baseClassNames = 'min-h-[375px] flex flex-col bg-
|
|
8861
|
+
const baseClassNames = 'min-h-[375px] flex flex-col bg-background select-none rounded-lg overflow-hidden';
|
|
8949
8862
|
const [dicomFileUploaderArr, setDicomFileUploaderArr] = (0,react.useState)([]);
|
|
8950
8863
|
const onDrop = (0,react.useCallback)(async acceptedFiles => {
|
|
8951
8864
|
onStarted();
|
|
@@ -9067,7 +8980,8 @@ function ViewportDownloadFormNew({
|
|
|
9067
8980
|
onDimensionsChange,
|
|
9068
8981
|
onEnableViewport,
|
|
9069
8982
|
onDisableViewport,
|
|
9070
|
-
onDownload
|
|
8983
|
+
onDownload,
|
|
8984
|
+
onCopyToClipboard
|
|
9071
8985
|
}) {
|
|
9072
8986
|
const [viewportElement, setViewportElement] = (0,react.useState)(null);
|
|
9073
8987
|
const [showWarningMessage, setShowWarningMessage] = (0,react.useState)(true);
|
|
@@ -9094,7 +9008,7 @@ function ViewportDownloadFormNew({
|
|
|
9094
9008
|
"data-viewport-uid": viewportId,
|
|
9095
9009
|
ref: setViewportElement
|
|
9096
9010
|
}, warningState.enabled && showWarningMessage && /*#__PURE__*/react.createElement("div", {
|
|
9097
|
-
className: "text-foreground absolute left-1/2 bottom-[5px] z-[1000] -translate-x-1/2 whitespace-nowrap rounded bg-
|
|
9011
|
+
className: "text-foreground absolute left-1/2 bottom-[5px] z-[1000] -translate-x-1/2 whitespace-nowrap rounded bg-background p-3 text-xs font-bold",
|
|
9098
9012
|
style: {
|
|
9099
9013
|
fontSize: '12px'
|
|
9100
9014
|
}
|
|
@@ -9140,12 +9054,23 @@ function ViewportDownloadFormNew({
|
|
|
9140
9054
|
className: "mt-2"
|
|
9141
9055
|
}, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Right, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Secondary, {
|
|
9142
9056
|
onClick: onClose
|
|
9143
|
-
}, t('Common:Cancel')), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.
|
|
9057
|
+
}, t('Common:Cancel')), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Secondary, {
|
|
9058
|
+
onClick: async () => {
|
|
9059
|
+
try {
|
|
9060
|
+
await onCopyToClipboard();
|
|
9061
|
+
ui_next_src/* toast */.oRP.success(t('Image copied to clipboard'));
|
|
9062
|
+
onClose();
|
|
9063
|
+
} catch (error) {
|
|
9064
|
+
ui_next_src/* toast */.oRP.error(t('Failed to copy image to clipboard'));
|
|
9065
|
+
console.error('Failed to copy to clipboard:', error);
|
|
9066
|
+
}
|
|
9067
|
+
}
|
|
9068
|
+
}, t('Copy to Clipboard')), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Primary, {
|
|
9144
9069
|
onClick: () => {
|
|
9145
9070
|
onDownload(filename || DEFAULT_FILENAME, fileType);
|
|
9146
9071
|
onClose();
|
|
9147
9072
|
}
|
|
9148
|
-
}, t('
|
|
9073
|
+
}, t('Save Image')))))));
|
|
9149
9074
|
}
|
|
9150
9075
|
/* harmony default export */ const captureViewportModalCustomization = ({
|
|
9151
9076
|
'ohif.captureViewportModal': ViewportDownloadFormNew
|
|
@@ -9157,6 +9082,34 @@ function ViewportDownloadFormNew({
|
|
|
9157
9082
|
value: 'Not For Diagnostic Use'
|
|
9158
9083
|
}
|
|
9159
9084
|
});
|
|
9085
|
+
;// ../../../extensions/cornerstone/src/customizations/viewportScrollbarCustomization.tsx
|
|
9086
|
+
/**
|
|
9087
|
+
* Default customization values for viewport scrollbar behavior.
|
|
9088
|
+
* The `progress` scrollbar variant is in full mode for stack viewports and
|
|
9089
|
+
* acquisition-plane orthographic viewports.
|
|
9090
|
+
* Otherwise, viewports using the `progress` scrollbar show only the indicator.
|
|
9091
|
+
*
|
|
9092
|
+
* - `viewportScrollbar.variant`: `'progress' | 'legacy'` (default: `'progress'`)
|
|
9093
|
+
* - `viewportScrollbar.showLoadedEndpoints`: show loaded-range endpoint caps in full mode
|
|
9094
|
+
* - `viewportScrollbar.showLoadedFill`: show loaded/cached fill in full mode
|
|
9095
|
+
* - `viewportScrollbar.showViewedFill`: show viewed fill in full mode
|
|
9096
|
+
* - `viewportScrollbar.showLoadingPattern`: show loading pattern in full mode while not fully loaded
|
|
9097
|
+
* - `viewportScrollbar.viewedDwellMs`: delay before marking current image viewed in full mode (ms)
|
|
9098
|
+
* - `viewportScrollbar.loadedBatchIntervalMs`: loaded-state version batch interval in full mode (ms)
|
|
9099
|
+
* - `viewportScrollbar.indicator`: optional custom indicator config
|
|
9100
|
+
*/
|
|
9101
|
+
function getViewportScrollbarCustomization() {
|
|
9102
|
+
return {
|
|
9103
|
+
'viewportScrollbar.variant': 'progress',
|
|
9104
|
+
'viewportScrollbar.showLoadedEndpoints': true,
|
|
9105
|
+
'viewportScrollbar.showLoadedFill': true,
|
|
9106
|
+
'viewportScrollbar.showViewedFill': true,
|
|
9107
|
+
'viewportScrollbar.showLoadingPattern': true,
|
|
9108
|
+
'viewportScrollbar.viewedDwellMs': 0,
|
|
9109
|
+
'viewportScrollbar.loadedBatchIntervalMs': 200,
|
|
9110
|
+
'viewportScrollbar.indicator': {}
|
|
9111
|
+
};
|
|
9112
|
+
}
|
|
9160
9113
|
;// ../../../extensions/cornerstone/src/getCustomizationModule.tsx
|
|
9161
9114
|
|
|
9162
9115
|
|
|
@@ -9171,6 +9124,7 @@ function ViewportDownloadFormNew({
|
|
|
9171
9124
|
|
|
9172
9125
|
|
|
9173
9126
|
|
|
9127
|
+
|
|
9174
9128
|
function getCustomizationModule({
|
|
9175
9129
|
commandsManager,
|
|
9176
9130
|
servicesManager,
|
|
@@ -9195,7 +9149,8 @@ function getCustomizationModule({
|
|
|
9195
9149
|
...windowLevelPresetsCustomization,
|
|
9196
9150
|
...miscCustomization,
|
|
9197
9151
|
...captureViewportModalCustomization,
|
|
9198
|
-
...viewportDownloadWarningCustomization
|
|
9152
|
+
...viewportDownloadWarningCustomization,
|
|
9153
|
+
...getViewportScrollbarCustomization()
|
|
9199
9154
|
}
|
|
9200
9155
|
}];
|
|
9201
9156
|
}
|
|
@@ -9563,17 +9518,39 @@ const CornerstoneViewportDownloadForm = ({
|
|
|
9563
9518
|
} = activeViewportEnabledElement;
|
|
9564
9519
|
const downloadViewport = renderingEngine.getViewport(VIEWPORT_ID);
|
|
9565
9520
|
try {
|
|
9521
|
+
// Capture current viewport state
|
|
9522
|
+
// - properties: VOI, colormap, interpolation, etc.
|
|
9523
|
+
// - viewPresentation: flip/rotate/zoom presentation state added for
|
|
9524
|
+
// saving flip and rotation for capture
|
|
9525
|
+
// - viewReference: image/volume reference
|
|
9526
|
+
const properties = viewport.getProperties();
|
|
9527
|
+
const viewPresentation = viewport.getViewPresentation?.();
|
|
9528
|
+
const viewRef = viewport.getViewReference?.();
|
|
9566
9529
|
if (downloadViewport instanceof esm.StackViewport) {
|
|
9567
9530
|
const imageId = viewport.getCurrentImageId();
|
|
9568
|
-
const properties = viewport.getProperties();
|
|
9569
9531
|
await downloadViewport.setStack([imageId]);
|
|
9570
|
-
downloadViewport.setProperties(properties);
|
|
9571
9532
|
} else if (downloadViewport instanceof esm.BaseVolumeViewport) {
|
|
9572
9533
|
const volumeIds = viewport.getAllVolumeIds();
|
|
9573
|
-
downloadViewport.setVolumes([{
|
|
9534
|
+
await downloadViewport.setVolumes([{
|
|
9574
9535
|
volumeId: volumeIds[0]
|
|
9575
9536
|
}]);
|
|
9576
9537
|
}
|
|
9538
|
+
|
|
9539
|
+
// Apply presentation state so captured image preserves flip/rotate
|
|
9540
|
+
if (viewPresentation && downloadViewport.setViewPresentation) {
|
|
9541
|
+
downloadViewport.setViewPresentation(viewPresentation);
|
|
9542
|
+
}
|
|
9543
|
+
|
|
9544
|
+
// Apply viewport display properties
|
|
9545
|
+
downloadViewport.setProperties(properties);
|
|
9546
|
+
|
|
9547
|
+
// Ensure correct image/volume reference
|
|
9548
|
+
if (viewRef && downloadViewport.setViewReference) {
|
|
9549
|
+
downloadViewport.setViewReference(viewRef);
|
|
9550
|
+
}
|
|
9551
|
+
downloadViewport.render();
|
|
9552
|
+
|
|
9553
|
+
// Re-apply segmentation overlays to the download viewport
|
|
9577
9554
|
if (segmentationRepresentations?.length) {
|
|
9578
9555
|
segmentationRepresentations.forEach(segRepresentation => {
|
|
9579
9556
|
const {
|
|
@@ -9667,6 +9644,36 @@ const CornerstoneViewportDownloadForm = ({
|
|
|
9667
9644
|
filename
|
|
9668
9645
|
});
|
|
9669
9646
|
};
|
|
9647
|
+
const handleCopyToClipboard = async () => {
|
|
9648
|
+
const divForDownloadViewport = document.querySelector(`div[data-viewport-uid="${VIEWPORT_ID}"]`);
|
|
9649
|
+
if (!divForDownloadViewport) {
|
|
9650
|
+
console.debug('No viewport found for copy');
|
|
9651
|
+
return;
|
|
9652
|
+
}
|
|
9653
|
+
try {
|
|
9654
|
+
const canvas = await (0,html2canvas_esm/* default */.A)(divForDownloadViewport);
|
|
9655
|
+
|
|
9656
|
+
// Clipboard API only supports PNG format in most browsers
|
|
9657
|
+
const blob = await new Promise((resolve, reject) => {
|
|
9658
|
+
canvas.toBlob(blob => {
|
|
9659
|
+
if (blob) {
|
|
9660
|
+
resolve(blob);
|
|
9661
|
+
} else {
|
|
9662
|
+
reject(new Error('Failed to create blob from canvas'));
|
|
9663
|
+
}
|
|
9664
|
+
}, 'image/png', 1.0);
|
|
9665
|
+
});
|
|
9666
|
+
|
|
9667
|
+
// Copy to clipboard using the Clipboard API
|
|
9668
|
+
await navigator.clipboard.write([new ClipboardItem({
|
|
9669
|
+
'image/png': blob
|
|
9670
|
+
})]);
|
|
9671
|
+
console.log('Image copied to clipboard successfully');
|
|
9672
|
+
} catch (error) {
|
|
9673
|
+
console.error('Failed to copy image to clipboard:', error);
|
|
9674
|
+
throw error;
|
|
9675
|
+
}
|
|
9676
|
+
};
|
|
9670
9677
|
const ViewportDownloadFormNew = customizationService.getCustomization('ohif.captureViewportModal');
|
|
9671
9678
|
return /*#__PURE__*/react.createElement(ViewportDownloadFormNew, {
|
|
9672
9679
|
onClose: hide,
|
|
@@ -9680,6 +9687,7 @@ const CornerstoneViewportDownloadForm = ({
|
|
|
9680
9687
|
onEnableViewport: handleEnableViewport,
|
|
9681
9688
|
onDisableViewport: handleDisableViewport,
|
|
9682
9689
|
onDownload: handleDownload,
|
|
9690
|
+
onCopyToClipboard: handleCopyToClipboard,
|
|
9683
9691
|
warningState: warningState
|
|
9684
9692
|
});
|
|
9685
9693
|
};
|
|
@@ -9942,6 +9950,51 @@ function generateSegmentationCSVReport(segmentationData, info) {
|
|
|
9942
9950
|
});
|
|
9943
9951
|
}
|
|
9944
9952
|
;// ../../../extensions/cornerstone/src/utils/hydrationUtils.ts
|
|
9953
|
+
/**
|
|
9954
|
+
* After SEG hydration we must refresh every viewport that shows the referenced volume so
|
|
9955
|
+
* presentations (including segmentation) apply to all MPR/3D tiles. Hanging-protocol matching
|
|
9956
|
+
* can return only the active viewport when protocol definitions omit viewportId (e.g. 3D four-up)
|
|
9957
|
+
* or when layout state diverges from the protocol; this merges in all grid panes that already
|
|
9958
|
+
* list that volume in `displaySetInstanceUIDs`.
|
|
9959
|
+
*
|
|
9960
|
+
* Only exact displaySetInstanceUID matches are used (no Frame-of-Reference inference): sibling
|
|
9961
|
+
* MPR planes must already share the same referenced volume UID in grid state, or HP matching
|
|
9962
|
+
* must list them; otherwise forcing a different UID onto a volume viewport can leave it blank.
|
|
9963
|
+
*/
|
|
9964
|
+
function mergeVolumeSharingViewports(hangingProtocolUpdates, volumeUid, viewports) {
|
|
9965
|
+
if (!volumeUid) {
|
|
9966
|
+
return hangingProtocolUpdates ?? [];
|
|
9967
|
+
}
|
|
9968
|
+
const byId = new Map();
|
|
9969
|
+
const add = (viewportId, uids) => {
|
|
9970
|
+
if (!viewportId) {
|
|
9971
|
+
return;
|
|
9972
|
+
}
|
|
9973
|
+
byId.set(viewportId, {
|
|
9974
|
+
viewportId,
|
|
9975
|
+
displaySetInstanceUIDs: uids
|
|
9976
|
+
});
|
|
9977
|
+
};
|
|
9978
|
+
if (Array.isArray(hangingProtocolUpdates)) {
|
|
9979
|
+
for (const entry of hangingProtocolUpdates) {
|
|
9980
|
+
const vid = entry.viewportId ?? entry.viewportOptions?.viewportId;
|
|
9981
|
+
if (vid) {
|
|
9982
|
+
add(vid, entry.displaySetInstanceUIDs?.length ? entry.displaySetInstanceUIDs : [volumeUid]);
|
|
9983
|
+
}
|
|
9984
|
+
}
|
|
9985
|
+
}
|
|
9986
|
+
viewports.forEach(vp => {
|
|
9987
|
+
const uids = vp.displaySetInstanceUIDs || [];
|
|
9988
|
+
if (uids.includes(volumeUid)) {
|
|
9989
|
+
add(vp.viewportId, [volumeUid]);
|
|
9990
|
+
}
|
|
9991
|
+
});
|
|
9992
|
+
const merged = Array.from(byId.values());
|
|
9993
|
+
if (merged.length === 0 && Array.isArray(hangingProtocolUpdates) && hangingProtocolUpdates.length > 0) {
|
|
9994
|
+
return hangingProtocolUpdates;
|
|
9995
|
+
}
|
|
9996
|
+
return merged;
|
|
9997
|
+
}
|
|
9945
9998
|
function getUpdatedViewportsForSegmentation({
|
|
9946
9999
|
viewportId,
|
|
9947
10000
|
servicesManager,
|
|
@@ -9952,7 +10005,8 @@ function getUpdatedViewportsForSegmentation({
|
|
|
9952
10005
|
viewportGridService
|
|
9953
10006
|
} = servicesManager.services;
|
|
9954
10007
|
const {
|
|
9955
|
-
isHangingProtocolLayout
|
|
10008
|
+
isHangingProtocolLayout,
|
|
10009
|
+
viewports
|
|
9956
10010
|
} = viewportGridService.getState();
|
|
9957
10011
|
const viewport = getTargetViewport({
|
|
9958
10012
|
viewportId,
|
|
@@ -9960,7 +10014,10 @@ function getUpdatedViewportsForSegmentation({
|
|
|
9960
10014
|
});
|
|
9961
10015
|
const targetViewportId = viewport.viewportOptions.viewportId;
|
|
9962
10016
|
const updatedViewports = hangingProtocolService.getViewportsRequireUpdate(targetViewportId, displaySetInstanceUIDs[0], isHangingProtocolLayout);
|
|
9963
|
-
|
|
10017
|
+
if (updatedViewports == null) {
|
|
10018
|
+
return updatedViewports;
|
|
10019
|
+
}
|
|
10020
|
+
return mergeVolumeSharingViewports(updatedViewports, displaySetInstanceUIDs[0], viewports);
|
|
9964
10021
|
}
|
|
9965
10022
|
const getTargetViewport = ({
|
|
9966
10023
|
viewportId,
|
|
@@ -10520,7 +10577,14 @@ function commandsModule({
|
|
|
10520
10577
|
}
|
|
10521
10578
|
function _getActiveViewportToolGroupId() {
|
|
10522
10579
|
const viewport = _getActiveViewportEnabledElement();
|
|
10523
|
-
|
|
10580
|
+
const toolGroup = viewport && toolGroupService.getToolGroupForViewport(viewport.id);
|
|
10581
|
+
return toolGroup?.id;
|
|
10582
|
+
}
|
|
10583
|
+
function _usesPrimaryActivation(bindings) {
|
|
10584
|
+
if (!bindings?.length) {
|
|
10585
|
+
return true;
|
|
10586
|
+
}
|
|
10587
|
+
return bindings.some(binding => binding.mouseButton === dist_esm.Enums.MouseBindings.Primary && binding.modifierKey == null && binding.numTouchPoints == null);
|
|
10524
10588
|
}
|
|
10525
10589
|
function _getActiveSegmentationInfo() {
|
|
10526
10590
|
const viewportId = viewportGridService.getActiveViewportId();
|
|
@@ -10756,11 +10820,26 @@ function commandsModule({
|
|
|
10756
10820
|
segmentIndex: targetIndex
|
|
10757
10821
|
} = targetSegmentation;
|
|
10758
10822
|
|
|
10823
|
+
// Check if the segment has voxels before computing bidirectional measurement
|
|
10824
|
+
const uniqueSegmentIndices = dist_esm.utilities.segmentation.getUniqueSegmentIndices(targetId);
|
|
10825
|
+
const hasVoxels = uniqueSegmentIndices.includes(targetIndex);
|
|
10826
|
+
if (!hasVoxels) {
|
|
10827
|
+
uiNotificationService.show({
|
|
10828
|
+
title: i18n_src/* default */.A.t('SegmentationPanel:Segment Bidirectional'),
|
|
10829
|
+
message: i18n_src/* default */.A.t('SegmentationPanel:Draw a segment before using bidirectional measurement'),
|
|
10830
|
+
type: 'warning'
|
|
10831
|
+
});
|
|
10832
|
+
return;
|
|
10833
|
+
}
|
|
10834
|
+
|
|
10759
10835
|
// Get bidirectional measurement data
|
|
10760
10836
|
const bidirectionalData = await dist_esm.utilities.segmentation.getSegmentLargestBidirectional({
|
|
10761
10837
|
segmentationId: targetId,
|
|
10762
10838
|
segmentIndices: [targetIndex]
|
|
10763
10839
|
});
|
|
10840
|
+
if (!bidirectionalData.length) {
|
|
10841
|
+
return;
|
|
10842
|
+
}
|
|
10764
10843
|
const activeViewportId = viewportGridService.getActiveViewportId();
|
|
10765
10844
|
|
|
10766
10845
|
// Process each bidirectional measurement
|
|
@@ -10799,7 +10878,7 @@ function commandsModule({
|
|
|
10799
10878
|
// get the active segmentIndex bidirectional annotation and jump to it
|
|
10800
10879
|
const activeBidirectional = bidirectionalData.find(measurement => measurement.segmentIndex === targetIndex);
|
|
10801
10880
|
commandsManager.run('jumpToMeasurement', {
|
|
10802
|
-
uid: activeBidirectional
|
|
10881
|
+
uid: activeBidirectional?.annotationUID
|
|
10803
10882
|
});
|
|
10804
10883
|
},
|
|
10805
10884
|
interpolateLabelmap: () => {
|
|
@@ -10962,7 +11041,7 @@ function commandsModule({
|
|
|
10962
11041
|
return;
|
|
10963
11042
|
}
|
|
10964
11043
|
if (!labelConfig) {
|
|
10965
|
-
const label = await (0,default_src
|
|
11044
|
+
const label = await (0,default_src/* callInputDialog */.l5)({
|
|
10966
11045
|
uiDialogService,
|
|
10967
11046
|
title: i18n_src/* default */.A.t('Tools:Edit Measurement Label'),
|
|
10968
11047
|
placeholder: measurement.label || i18n_src/* default */.A.t('Tools:Enter new label'),
|
|
@@ -10976,7 +11055,7 @@ function commandsModule({
|
|
|
10976
11055
|
}
|
|
10977
11056
|
return;
|
|
10978
11057
|
}
|
|
10979
|
-
const val = await (0,default_src
|
|
11058
|
+
const val = await (0,default_src/* callInputDialogAutoComplete */.fq)({
|
|
10980
11059
|
measurement,
|
|
10981
11060
|
uiDialogService,
|
|
10982
11061
|
labelConfig,
|
|
@@ -11099,6 +11178,9 @@ function commandsModule({
|
|
|
11099
11178
|
uid,
|
|
11100
11179
|
displayMeasurements = []
|
|
11101
11180
|
}) => {
|
|
11181
|
+
if (!uid) {
|
|
11182
|
+
return;
|
|
11183
|
+
}
|
|
11102
11184
|
measurementService.jumpToMeasurement(viewportGridService.getActiveViewportId(), uid);
|
|
11103
11185
|
for (const measurement of displayMeasurements) {
|
|
11104
11186
|
measurement.isActive = measurement.uid === uid;
|
|
@@ -11196,7 +11278,7 @@ function commandsModule({
|
|
|
11196
11278
|
const labelConfig = customizationService.getCustomization('measurementLabels');
|
|
11197
11279
|
const renderContent = customizationService.getCustomization('ui.labellingComponent');
|
|
11198
11280
|
if (!labelConfig) {
|
|
11199
|
-
const label = await (0,default_src
|
|
11281
|
+
const label = await (0,default_src/* callInputDialog */.l5)({
|
|
11200
11282
|
uiDialogService,
|
|
11201
11283
|
title: i18n_src/* default */.A.t('Tools:Edit Arrow Text'),
|
|
11202
11284
|
placeholder: data?.data?.label || i18n_src/* default */.A.t('Tools:Enter new text'),
|
|
@@ -11205,7 +11287,7 @@ function commandsModule({
|
|
|
11205
11287
|
callback?.(label);
|
|
11206
11288
|
return;
|
|
11207
11289
|
}
|
|
11208
|
-
const value = await (0,default_src
|
|
11290
|
+
const value = await (0,default_src/* callInputDialogAutoComplete */.fq)({
|
|
11209
11291
|
uiDialogService,
|
|
11210
11292
|
labelConfig,
|
|
11211
11293
|
renderContent
|
|
@@ -11369,31 +11451,46 @@ function commandsModule({
|
|
|
11369
11451
|
toggleActiveDisabledToolbar({
|
|
11370
11452
|
value,
|
|
11371
11453
|
itemId,
|
|
11372
|
-
toolGroupId
|
|
11454
|
+
toolGroupId,
|
|
11455
|
+
toolGroupIds
|
|
11373
11456
|
}) {
|
|
11374
11457
|
const toolName = itemId || value;
|
|
11375
|
-
|
|
11376
|
-
|
|
11377
|
-
|
|
11378
|
-
|
|
11379
|
-
|
|
11380
|
-
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
|
|
11458
|
+
const resolvedToolGroupIds = toolGroupIds?.length ? toolGroupIds : [toolGroupId ?? _getActiveViewportToolGroupId()];
|
|
11459
|
+
resolvedToolGroupIds.forEach(toolGroupId => {
|
|
11460
|
+
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
|
|
11461
|
+
if (!toolGroup || !toolGroup.hasTool(toolName)) {
|
|
11462
|
+
return;
|
|
11463
|
+
}
|
|
11464
|
+
const toolIsActive = [dist_esm.Enums.ToolModes.Active, dist_esm.Enums.ToolModes.Enabled, dist_esm.Enums.ToolModes.Passive].includes(toolGroup.getToolOptions(toolName).mode);
|
|
11465
|
+
if (toolIsActive) {
|
|
11466
|
+
toolGroup.setToolDisabled(toolName);
|
|
11467
|
+
const bindings = toolGroupService.getToolBindings(toolGroupId, toolName);
|
|
11468
|
+
if (_usesPrimaryActivation(bindings)) {
|
|
11469
|
+
// we should set the previously active tool to active after we set the
|
|
11470
|
+
// current tool disabled
|
|
11471
|
+
const prevToolName = toolGroup.getPrevActivePrimaryToolName();
|
|
11472
|
+
if (prevToolName !== toolName) {
|
|
11473
|
+
actions.setToolActive({
|
|
11474
|
+
toolName: prevToolName,
|
|
11475
|
+
toolGroupId
|
|
11476
|
+
});
|
|
11477
|
+
}
|
|
11478
|
+
}
|
|
11479
|
+
return;
|
|
11480
|
+
}
|
|
11481
|
+
const bindings = toolGroupService.getToolBindings(toolGroupId, toolName);
|
|
11482
|
+
if (_usesPrimaryActivation(bindings)) {
|
|
11391
11483
|
actions.setToolActive({
|
|
11392
|
-
toolName
|
|
11393
|
-
toolGroupId
|
|
11484
|
+
toolName,
|
|
11485
|
+
toolGroupId,
|
|
11486
|
+
bindings
|
|
11487
|
+
});
|
|
11488
|
+
} else {
|
|
11489
|
+
toolGroup.setToolActive(toolName, {
|
|
11490
|
+
bindings
|
|
11394
11491
|
});
|
|
11395
11492
|
}
|
|
11396
|
-
}
|
|
11493
|
+
});
|
|
11397
11494
|
},
|
|
11398
11495
|
setToolActiveToolbar: ({
|
|
11399
11496
|
value,
|
|
@@ -12101,7 +12198,7 @@ function commandsModule({
|
|
|
12101
12198
|
segmentationService,
|
|
12102
12199
|
viewportGridService
|
|
12103
12200
|
} = servicesManager.services;
|
|
12104
|
-
const displaySetInstanceUIDs = await (0,default_src
|
|
12201
|
+
const displaySetInstanceUIDs = await (0,default_src/* createReportAsync */.Vy)({
|
|
12105
12202
|
servicesManager,
|
|
12106
12203
|
getReport: () => commandsManager.runCommand('storeSegmentation', args),
|
|
12107
12204
|
reportType: 'Segmentation'
|
|
@@ -12178,14 +12275,15 @@ function commandsModule({
|
|
|
12178
12275
|
* @param props.segmentationId - The ID of the segmentation to remove
|
|
12179
12276
|
*/
|
|
12180
12277
|
removeSegmentationFromViewportCommand: ({
|
|
12181
|
-
segmentationId
|
|
12278
|
+
segmentationId: displaySetInstanceUID
|
|
12182
12279
|
}) => {
|
|
12183
12280
|
const {
|
|
12184
|
-
segmentationService,
|
|
12185
12281
|
viewportGridService
|
|
12186
12282
|
} = servicesManager.services;
|
|
12187
|
-
|
|
12188
|
-
|
|
12283
|
+
const viewportId = viewportGridService.getActiveViewportId();
|
|
12284
|
+
commandsManager.runCommand('removeDisplaySetLayer', {
|
|
12285
|
+
viewportId,
|
|
12286
|
+
displaySetInstanceUID
|
|
12189
12287
|
});
|
|
12190
12288
|
},
|
|
12191
12289
|
/**
|
|
@@ -12213,7 +12311,7 @@ function commandsModule({
|
|
|
12213
12311
|
return;
|
|
12214
12312
|
}
|
|
12215
12313
|
const segment = segmentation.segments[segmentIndex];
|
|
12216
|
-
(0,default_src
|
|
12314
|
+
(0,default_src/* callInputDialog */.l5)({
|
|
12217
12315
|
uiDialogService,
|
|
12218
12316
|
title: i18n_src/* default */.A.t('Tools:Edit Segment Label'),
|
|
12219
12317
|
placeholder: i18n_src/* default */.A.t('Tools:Enter new label'),
|
|
@@ -12236,7 +12334,7 @@ function commandsModule({
|
|
|
12236
12334
|
const {
|
|
12237
12335
|
label
|
|
12238
12336
|
} = segmentation;
|
|
12239
|
-
(0,default_src
|
|
12337
|
+
(0,default_src/* callInputDialog */.l5)({
|
|
12240
12338
|
uiDialogService,
|
|
12241
12339
|
title: i18n_src/* default */.A.t('Tools:Edit Segmentation Label'),
|
|
12242
12340
|
placeholder: i18n_src/* default */.A.t('Tools:Enter new label'),
|
|
@@ -12266,7 +12364,7 @@ function commandsModule({
|
|
|
12266
12364
|
a: color[3] / 255.0
|
|
12267
12365
|
};
|
|
12268
12366
|
uiDialogService.show({
|
|
12269
|
-
content: default_src
|
|
12367
|
+
content: default_src/* colorPickerDialog */.wS,
|
|
12270
12368
|
title: i18n_src/* default */.A.t('Tools:Segment Color'),
|
|
12271
12369
|
contentProps: {
|
|
12272
12370
|
value: rgbaColor,
|
|
@@ -12545,6 +12643,15 @@ function commandsModule({
|
|
|
12545
12643
|
servicesManager,
|
|
12546
12644
|
displaySetInstanceUIDs
|
|
12547
12645
|
});
|
|
12646
|
+
if (!updatedViewports?.length) {
|
|
12647
|
+
return;
|
|
12648
|
+
}
|
|
12649
|
+
updatedViewports.forEach(({
|
|
12650
|
+
viewportId: csViewportId
|
|
12651
|
+
}) => {
|
|
12652
|
+
const csViewport = cornerstoneViewportService.getCornerstoneViewport(csViewportId);
|
|
12653
|
+
csViewport?.setNeedsRender?.();
|
|
12654
|
+
});
|
|
12548
12655
|
actions.setDisplaySetsForViewports({
|
|
12549
12656
|
viewportsToUpdate: updatedViewports.map(viewport => ({
|
|
12550
12657
|
viewportId: viewport.viewportId,
|
|
@@ -13256,6 +13363,29 @@ const HYDRATE_SEG_SYNC_GROUP = {
|
|
|
13256
13363
|
matchingRules: ['sameFOR']
|
|
13257
13364
|
}
|
|
13258
13365
|
};
|
|
13366
|
+
const viewportStructure = {
|
|
13367
|
+
layoutType: 'grid',
|
|
13368
|
+
properties: {
|
|
13369
|
+
rows: 1,
|
|
13370
|
+
columns: 3,
|
|
13371
|
+
layoutOptions: [{
|
|
13372
|
+
x: 0,
|
|
13373
|
+
y: 0,
|
|
13374
|
+
width: 1 / 3,
|
|
13375
|
+
height: 1
|
|
13376
|
+
}, {
|
|
13377
|
+
x: 1 / 3,
|
|
13378
|
+
y: 0,
|
|
13379
|
+
width: 1 / 3,
|
|
13380
|
+
height: 1
|
|
13381
|
+
}, {
|
|
13382
|
+
x: 2 / 3,
|
|
13383
|
+
y: 0,
|
|
13384
|
+
width: 1 / 3,
|
|
13385
|
+
height: 1
|
|
13386
|
+
}]
|
|
13387
|
+
}
|
|
13388
|
+
};
|
|
13259
13389
|
const mpr = {
|
|
13260
13390
|
id: 'mpr',
|
|
13261
13391
|
name: i18next/* default */.A.t('Hps:MPR'),
|
|
@@ -13286,29 +13416,7 @@ const mpr = {
|
|
|
13286
13416
|
},
|
|
13287
13417
|
stages: [{
|
|
13288
13418
|
name: 'MPR 1x3',
|
|
13289
|
-
viewportStructure
|
|
13290
|
-
layoutType: 'grid',
|
|
13291
|
-
properties: {
|
|
13292
|
-
rows: 1,
|
|
13293
|
-
columns: 3,
|
|
13294
|
-
layoutOptions: [{
|
|
13295
|
-
x: 0,
|
|
13296
|
-
y: 0,
|
|
13297
|
-
width: 1 / 3,
|
|
13298
|
-
height: 1
|
|
13299
|
-
}, {
|
|
13300
|
-
x: 1 / 3,
|
|
13301
|
-
y: 0,
|
|
13302
|
-
width: 1 / 3,
|
|
13303
|
-
height: 1
|
|
13304
|
-
}, {
|
|
13305
|
-
x: 2 / 3,
|
|
13306
|
-
y: 0,
|
|
13307
|
-
width: 1 / 3,
|
|
13308
|
-
height: 1
|
|
13309
|
-
}]
|
|
13310
|
-
}
|
|
13311
|
-
},
|
|
13419
|
+
viewportStructure,
|
|
13312
13420
|
viewports: [{
|
|
13313
13421
|
viewportOptions: {
|
|
13314
13422
|
viewportId: 'mpr-axial',
|
|
@@ -13352,36 +13460,82 @@ const mpr = {
|
|
|
13352
13460
|
id: 'activeDisplaySet'
|
|
13353
13461
|
}]
|
|
13354
13462
|
}]
|
|
13355
|
-
}
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
|
|
13373
|
-
|
|
13374
|
-
|
|
13375
|
-
|
|
13376
|
-
|
|
13377
|
-
|
|
13378
|
-
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
|
|
13383
|
-
|
|
13384
|
-
|
|
13463
|
+
}, {
|
|
13464
|
+
name: 'MPR Reformat 1x3',
|
|
13465
|
+
viewportStructure,
|
|
13466
|
+
viewports: [{
|
|
13467
|
+
viewportOptions: {
|
|
13468
|
+
viewportId: 'mpr-axial',
|
|
13469
|
+
toolGroupId: 'mpr',
|
|
13470
|
+
viewportType: 'volume',
|
|
13471
|
+
orientation: 'axial_reformat',
|
|
13472
|
+
initialImageOptions: {
|
|
13473
|
+
preset: 'middle'
|
|
13474
|
+
},
|
|
13475
|
+
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
|
|
13476
|
+
},
|
|
13477
|
+
displaySets: [{
|
|
13478
|
+
id: 'activeDisplaySet'
|
|
13479
|
+
}]
|
|
13480
|
+
}, {
|
|
13481
|
+
viewportOptions: {
|
|
13482
|
+
viewportId: 'mpr-sagittal',
|
|
13483
|
+
toolGroupId: 'mpr',
|
|
13484
|
+
viewportType: 'volume',
|
|
13485
|
+
orientation: 'sagittal_reformat',
|
|
13486
|
+
initialImageOptions: {
|
|
13487
|
+
preset: 'middle'
|
|
13488
|
+
},
|
|
13489
|
+
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
|
|
13490
|
+
},
|
|
13491
|
+
displaySets: [{
|
|
13492
|
+
id: 'activeDisplaySet'
|
|
13493
|
+
}]
|
|
13494
|
+
}, {
|
|
13495
|
+
viewportOptions: {
|
|
13496
|
+
viewportId: 'mpr-coronal',
|
|
13497
|
+
toolGroupId: 'mpr',
|
|
13498
|
+
viewportType: 'volume',
|
|
13499
|
+
orientation: 'coronal_reformat',
|
|
13500
|
+
initialImageOptions: {
|
|
13501
|
+
preset: 'middle'
|
|
13502
|
+
},
|
|
13503
|
+
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
|
|
13504
|
+
},
|
|
13505
|
+
displaySets: [{
|
|
13506
|
+
id: 'activeDisplaySet'
|
|
13507
|
+
}]
|
|
13508
|
+
}]
|
|
13509
|
+
}]
|
|
13510
|
+
};
|
|
13511
|
+
;// ../../../extensions/cornerstone/src/hps/fourUp.ts
|
|
13512
|
+
|
|
13513
|
+
|
|
13514
|
+
const fourUp = {
|
|
13515
|
+
id: 'fourUp',
|
|
13516
|
+
locked: true,
|
|
13517
|
+
name: i18next/* default */.A.t('Hps:3D four up'),
|
|
13518
|
+
icon: 'layout-advanced-3d-four-up',
|
|
13519
|
+
isPreset: true,
|
|
13520
|
+
createdDate: '2023-03-15T10:29:44.894Z',
|
|
13521
|
+
modifiedDate: '2023-03-15T10:29:44.894Z',
|
|
13522
|
+
availableTo: {},
|
|
13523
|
+
editableBy: {},
|
|
13524
|
+
protocolMatchingRules: [],
|
|
13525
|
+
imageLoadStrategy: 'interleaveCenter',
|
|
13526
|
+
displaySetSelectors: {
|
|
13527
|
+
activeDisplaySet: {
|
|
13528
|
+
seriesMatchingRules: [{
|
|
13529
|
+
weight: 1,
|
|
13530
|
+
attribute: 'isReconstructable',
|
|
13531
|
+
constraint: {
|
|
13532
|
+
equals: {
|
|
13533
|
+
value: true
|
|
13534
|
+
}
|
|
13535
|
+
},
|
|
13536
|
+
required: true
|
|
13537
|
+
}]
|
|
13538
|
+
}
|
|
13385
13539
|
},
|
|
13386
13540
|
stages: [{
|
|
13387
13541
|
id: 'fourUpStage',
|
|
@@ -15342,6 +15496,9 @@ function ViewportDataOverlayMenu({
|
|
|
15342
15496
|
} = (0,useViewportDisplaySets/* useViewportDisplaySets */.N)(viewportId);
|
|
15343
15497
|
const [optimisticOverlayDisplaySets, setOptimisticOverlayDisplaySets] = (0,react.useState)(overlayDisplaySets);
|
|
15344
15498
|
const [thresholdOpacityEnabled, setThresholdOpacityEnabled] = (0,react.useState)(false);
|
|
15499
|
+
(0,react.useEffect)(() => {
|
|
15500
|
+
setOptimisticOverlayDisplaySets(overlayDisplaySets);
|
|
15501
|
+
}, [backgroundDisplaySet?.displaySetInstanceUID, overlayDisplaySets]);
|
|
15345
15502
|
|
|
15346
15503
|
/**
|
|
15347
15504
|
* Change the background display set
|
|
@@ -15648,7 +15805,8 @@ function ViewportDataOverlayMenu({
|
|
|
15648
15805
|
}
|
|
15649
15806
|
}
|
|
15650
15807
|
}, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, {
|
|
15651
|
-
className: "flex-1"
|
|
15808
|
+
className: "flex-1",
|
|
15809
|
+
"data-cy": `overlay-background-ds-select-${viewportId}`
|
|
15652
15810
|
}, /*#__PURE__*/react.createElement(ui_next_src/* SelectValue */.yvm, null, (backgroundDisplaySet?.SeriesDescription || backgroundDisplaySet?.label || 'background').toUpperCase())), /*#__PURE__*/react.createElement(ui_next_src/* SelectContent */.gCo, null, potentialBackgroundDisplaySets.map(displaySet => /*#__PURE__*/react.createElement(ui_next_src/* SelectItem */.ebT, {
|
|
15653
15811
|
key: displaySet.displaySetInstanceUID,
|
|
15654
15812
|
value: displaySet.displaySetInstanceUID,
|
|
@@ -15923,7 +16081,7 @@ function ViewportOrientationMenu({
|
|
|
15923
16081
|
}) : null), /*#__PURE__*/react.createElement("div", {
|
|
15924
16082
|
className: "flex-1 text-left"
|
|
15925
16083
|
}, "Acquisition")), /*#__PURE__*/react.createElement("div", {
|
|
15926
|
-
className: "mx-1 my-2 border-t
|
|
16084
|
+
className: "border-input mx-1 my-2 border-t"
|
|
15927
16085
|
}), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
|
|
15928
16086
|
variant: "ghost",
|
|
15929
16087
|
className: "flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0",
|
|
@@ -16264,7 +16422,7 @@ function VolumeRenderingPresetsContent({
|
|
|
16264
16422
|
}
|
|
16265
16423
|
}, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.ByName, {
|
|
16266
16424
|
name: preset.name,
|
|
16267
|
-
className: selectedPreset?.name === preset.name ? 'border-highlight h-[75px] w-[95px] max-w-none rounded border-2' : 'hover:border-highlight h-[75px] w-[95px] max-w-none rounded border-2 border-
|
|
16425
|
+
className: selectedPreset?.name === preset.name ? 'border-highlight h-[75px] w-[95px] max-w-none rounded border-2' : 'hover:border-highlight h-[75px] w-[95px] max-w-none rounded border-2 border-background'
|
|
16268
16426
|
}), /*#__PURE__*/react.createElement("label", {
|
|
16269
16427
|
className: "text-muted-foreground mt-1 text-left text-xs"
|
|
16270
16428
|
}, formatLabel(preset.name, 11)))))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu, {
|
|
@@ -17410,9 +17568,9 @@ function ModalityLoadBadge({
|
|
|
17410
17568
|
if (!statusInfo.isHydrated) {
|
|
17411
17569
|
return /*#__PURE__*/react.createElement("div", {
|
|
17412
17570
|
"data-cy": `ModalityLoadBadge-${viewportId}`,
|
|
17413
|
-
className: "flex h-6 cursor-default text-sm leading-6
|
|
17571
|
+
className: "text-foreground flex h-6 cursor-default text-sm leading-6"
|
|
17414
17572
|
}, /*#__PURE__*/react.createElement("div", {
|
|
17415
|
-
className: "bg-
|
|
17573
|
+
className: "bg-popover flex min-w-[45px] items-center rounded-l-xl rounded-r p-1"
|
|
17416
17574
|
}, /*#__PURE__*/react.createElement(StatusIcon, null), /*#__PURE__*/react.createElement("span", {
|
|
17417
17575
|
className: "ml-1"
|
|
17418
17576
|
}, statusInfo.type)), statusInfo.type !== 'SR' && /*#__PURE__*/react.createElement(ui_next_src/* ViewportActionButton */.N8H, {
|
|
@@ -18339,6 +18497,36 @@ function getToolbarModule({
|
|
|
18339
18497
|
isActive: isPrimaryActive
|
|
18340
18498
|
};
|
|
18341
18499
|
}
|
|
18500
|
+
}, {
|
|
18501
|
+
name: 'evaluate.cornerstoneTool.toggleWithModifier',
|
|
18502
|
+
evaluate: ({
|
|
18503
|
+
viewportId,
|
|
18504
|
+
button,
|
|
18505
|
+
disabledText,
|
|
18506
|
+
toggledOnIcon,
|
|
18507
|
+
defaultIcon
|
|
18508
|
+
}) => {
|
|
18509
|
+
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
|
18510
|
+
if (!toolGroup) {
|
|
18511
|
+
return;
|
|
18512
|
+
}
|
|
18513
|
+
const toolName = toolbarService.getToolNameForButton(button);
|
|
18514
|
+
if (!toolGroup.hasTool(toolName)) {
|
|
18515
|
+
return getDisabledState(disabledText);
|
|
18516
|
+
}
|
|
18517
|
+
const {
|
|
18518
|
+
mode
|
|
18519
|
+
} = toolGroup.getToolOptions(toolName) ?? {};
|
|
18520
|
+
const isToggled = mode === dist_esm.Enums.ToolModes.Passive || mode === dist_esm.Enums.ToolModes.Active || mode === dist_esm.Enums.ToolModes.Enabled;
|
|
18521
|
+
const toolBindings = toolGroupService.getToolBindings(toolGroup.id, toolName);
|
|
18522
|
+
const hasModifierKey = toolBindings?.some(binding => binding.modifierKey != null) ?? false;
|
|
18523
|
+
return {
|
|
18524
|
+
disabled: false,
|
|
18525
|
+
isActive: false,
|
|
18526
|
+
isToggled,
|
|
18527
|
+
icon: isToggled && hasModifierKey && toggledOnIcon ? toggledOnIcon : defaultIcon ?? button.props.icon
|
|
18528
|
+
};
|
|
18529
|
+
}
|
|
18342
18530
|
}, {
|
|
18343
18531
|
name: 'evaluate.action',
|
|
18344
18532
|
evaluate: () => {
|
|
@@ -18491,7 +18679,10 @@ class ToolGroupService {
|
|
|
18491
18679
|
this.cornerstoneViewportService = void 0;
|
|
18492
18680
|
this.viewportGridService = void 0;
|
|
18493
18681
|
this.uiNotificationService = void 0;
|
|
18682
|
+
this.customizationService = void 0;
|
|
18494
18683
|
this.toolGroupIds = new Set();
|
|
18684
|
+
this.toolBindingsMap = new Map();
|
|
18685
|
+
this.defaultToolBindingsMap = new Map();
|
|
18495
18686
|
/**
|
|
18496
18687
|
* Service-specific
|
|
18497
18688
|
*/
|
|
@@ -18517,11 +18708,13 @@ class ToolGroupService {
|
|
|
18517
18708
|
const {
|
|
18518
18709
|
cornerstoneViewportService,
|
|
18519
18710
|
viewportGridService,
|
|
18520
|
-
uiNotificationService
|
|
18711
|
+
uiNotificationService,
|
|
18712
|
+
customizationService
|
|
18521
18713
|
} = servicesManager.services;
|
|
18522
18714
|
this.cornerstoneViewportService = cornerstoneViewportService;
|
|
18523
18715
|
this.viewportGridService = viewportGridService;
|
|
18524
18716
|
this.uiNotificationService = uiNotificationService;
|
|
18717
|
+
this.customizationService = customizationService;
|
|
18525
18718
|
this.listeners = {};
|
|
18526
18719
|
this.EVENTS = ToolGroupService_EVENTS;
|
|
18527
18720
|
Object.assign(this, src/* pubSubServiceInterface */.Ml);
|
|
@@ -18579,6 +18772,8 @@ class ToolGroupService {
|
|
|
18579
18772
|
destroy() {
|
|
18580
18773
|
dist_esm.ToolGroupManager.destroy();
|
|
18581
18774
|
this.toolGroupIds = new Set();
|
|
18775
|
+
this.toolBindingsMap.clear();
|
|
18776
|
+
this.defaultToolBindingsMap.clear();
|
|
18582
18777
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.TOOL_ACTIVATED, this._onToolActivated);
|
|
18583
18778
|
}
|
|
18584
18779
|
destroyToolGroup(toolGroupId) {
|
|
@@ -18633,6 +18828,7 @@ class ToolGroupService {
|
|
|
18633
18828
|
// this.changeConfigurationIfNecessary(toolGroup, volumeId);
|
|
18634
18829
|
this._addTools(toolGroup, tools, configs);
|
|
18635
18830
|
this._setToolsMode(toolGroup, tools);
|
|
18831
|
+
this._loadPersistedBindings(toolGroupId);
|
|
18636
18832
|
}
|
|
18637
18833
|
createToolGroupAndAddTools(toolGroupId, tools) {
|
|
18638
18834
|
const toolGroup = this.createToolGroup(toolGroupId);
|
|
@@ -18672,6 +18868,84 @@ class ToolGroupService {
|
|
|
18672
18868
|
getActivePrimaryMouseButtonTool(toolGroupId) {
|
|
18673
18869
|
return this.getToolGroup(toolGroupId)?.getActivePrimaryMouseButtonTool();
|
|
18674
18870
|
}
|
|
18871
|
+
getToolBindings(toolGroupId, toolName) {
|
|
18872
|
+
return this.toolBindingsMap.get(toolGroupId)?.get(toolName);
|
|
18873
|
+
}
|
|
18874
|
+
setToolBindings(toolGroupId, toolName, bindings) {
|
|
18875
|
+
if (!this.toolBindingsMap.has(toolGroupId)) {
|
|
18876
|
+
this.toolBindingsMap.set(toolGroupId, new Map());
|
|
18877
|
+
}
|
|
18878
|
+
this.toolBindingsMap.get(toolGroupId).set(toolName, this._cloneToolBindings(bindings));
|
|
18879
|
+
}
|
|
18880
|
+
getDefaultToolBindings(toolGroupId, toolName) {
|
|
18881
|
+
const defaultBindings = this.defaultToolBindingsMap.get(toolGroupId)?.get(toolName);
|
|
18882
|
+
return defaultBindings ? this._cloneToolBindings(defaultBindings) : undefined;
|
|
18883
|
+
}
|
|
18884
|
+
persistToolBindings(toolGroupId, toolName, bindings) {
|
|
18885
|
+
const persistedBindings = this._readPersistedToolBindings();
|
|
18886
|
+
if (!persistedBindings[toolGroupId]) {
|
|
18887
|
+
persistedBindings[toolGroupId] = {};
|
|
18888
|
+
}
|
|
18889
|
+
persistedBindings[toolGroupId][toolName] = bindings;
|
|
18890
|
+
this._writePersistedToolBindings(persistedBindings);
|
|
18891
|
+
}
|
|
18892
|
+
removePersistedToolBindings(toolGroupId, toolName) {
|
|
18893
|
+
const persistedBindings = this._readPersistedToolBindings();
|
|
18894
|
+
if (!persistedBindings[toolGroupId]) {
|
|
18895
|
+
return;
|
|
18896
|
+
}
|
|
18897
|
+
if (toolName) {
|
|
18898
|
+
delete persistedBindings[toolGroupId][toolName];
|
|
18899
|
+
if (!Object.keys(persistedBindings[toolGroupId]).length) {
|
|
18900
|
+
delete persistedBindings[toolGroupId];
|
|
18901
|
+
}
|
|
18902
|
+
} else {
|
|
18903
|
+
delete persistedBindings[toolGroupId];
|
|
18904
|
+
}
|
|
18905
|
+
this._writePersistedToolBindings(persistedBindings);
|
|
18906
|
+
}
|
|
18907
|
+
|
|
18908
|
+
/**
|
|
18909
|
+
* Applies the currently tracked bindings to the runtime tool instance.
|
|
18910
|
+
*
|
|
18911
|
+
* Note: this method may activate tools that are currently Passive or Enabled.
|
|
18912
|
+
* Assigning bindings is treated as making the tool interactable.
|
|
18913
|
+
*/
|
|
18914
|
+
applyToolBindings(toolGroupId, toolName, options = {}) {
|
|
18915
|
+
const toolGroup = dist_esm.ToolGroupManager.getToolGroup(toolGroupId);
|
|
18916
|
+
if (!toolGroup || !toolGroup.hasTool(toolName)) {
|
|
18917
|
+
return;
|
|
18918
|
+
}
|
|
18919
|
+
const bindings = this.getToolBindings(toolGroupId, toolName);
|
|
18920
|
+
if (!bindings) {
|
|
18921
|
+
return;
|
|
18922
|
+
}
|
|
18923
|
+
const {
|
|
18924
|
+
mode
|
|
18925
|
+
} = toolGroup.getToolOptions(toolName);
|
|
18926
|
+
if (mode === dist_esm.Enums.ToolModes.Active || mode === dist_esm.Enums.ToolModes.Passive || mode === dist_esm.Enums.ToolModes.Enabled) {
|
|
18927
|
+
if (options.replaceExisting) {
|
|
18928
|
+
// Opt-in behavior for callers that need replacement semantics.
|
|
18929
|
+
toolGroup.setToolDisabled(toolName);
|
|
18930
|
+
}
|
|
18931
|
+
toolGroup.setToolActive(toolName, {
|
|
18932
|
+
bindings
|
|
18933
|
+
});
|
|
18934
|
+
}
|
|
18935
|
+
}
|
|
18936
|
+
getAllToolBindings() {
|
|
18937
|
+
const result = [];
|
|
18938
|
+
for (const [toolGroupId, toolMap] of this.toolBindingsMap) {
|
|
18939
|
+
for (const [toolName, bindings] of toolMap) {
|
|
18940
|
+
result.push({
|
|
18941
|
+
toolGroupId,
|
|
18942
|
+
toolName,
|
|
18943
|
+
bindings
|
|
18944
|
+
});
|
|
18945
|
+
}
|
|
18946
|
+
}
|
|
18947
|
+
return result;
|
|
18948
|
+
}
|
|
18675
18949
|
_setToolsMode(toolGroup, tools) {
|
|
18676
18950
|
const {
|
|
18677
18951
|
active,
|
|
@@ -18684,6 +18958,10 @@ class ToolGroupService {
|
|
|
18684
18958
|
toolName,
|
|
18685
18959
|
bindings
|
|
18686
18960
|
}) => {
|
|
18961
|
+
if (bindings) {
|
|
18962
|
+
this.setToolBindings(toolGroup.id, toolName, bindings);
|
|
18963
|
+
this._setDefaultToolBindingsIfMissing(toolGroup.id, toolName, bindings);
|
|
18964
|
+
}
|
|
18687
18965
|
toolGroup.setToolActive(toolName, {
|
|
18688
18966
|
bindings
|
|
18689
18967
|
});
|
|
@@ -18691,26 +18969,50 @@ class ToolGroupService {
|
|
|
18691
18969
|
}
|
|
18692
18970
|
if (passive) {
|
|
18693
18971
|
passive.forEach(({
|
|
18694
|
-
toolName
|
|
18972
|
+
toolName,
|
|
18973
|
+
bindings
|
|
18695
18974
|
}) => {
|
|
18975
|
+
if (bindings) {
|
|
18976
|
+
this.setToolBindings(toolGroup.id, toolName, bindings);
|
|
18977
|
+
this._setDefaultToolBindingsIfMissing(toolGroup.id, toolName, bindings);
|
|
18978
|
+
}
|
|
18696
18979
|
toolGroup.setToolPassive(toolName);
|
|
18697
18980
|
});
|
|
18698
18981
|
}
|
|
18699
18982
|
if (enabled) {
|
|
18700
18983
|
enabled.forEach(({
|
|
18701
|
-
toolName
|
|
18984
|
+
toolName,
|
|
18985
|
+
bindings
|
|
18702
18986
|
}) => {
|
|
18987
|
+
if (bindings) {
|
|
18988
|
+
this.setToolBindings(toolGroup.id, toolName, bindings);
|
|
18989
|
+
this._setDefaultToolBindingsIfMissing(toolGroup.id, toolName, bindings);
|
|
18990
|
+
}
|
|
18703
18991
|
toolGroup.setToolEnabled(toolName);
|
|
18704
18992
|
});
|
|
18705
18993
|
}
|
|
18706
18994
|
if (disabled) {
|
|
18707
18995
|
disabled.forEach(({
|
|
18708
|
-
toolName
|
|
18996
|
+
toolName,
|
|
18997
|
+
bindings
|
|
18709
18998
|
}) => {
|
|
18999
|
+
if (bindings) {
|
|
19000
|
+
this.setToolBindings(toolGroup.id, toolName, bindings);
|
|
19001
|
+
this._setDefaultToolBindingsIfMissing(toolGroup.id, toolName, bindings);
|
|
19002
|
+
}
|
|
18710
19003
|
toolGroup.setToolDisabled(toolName);
|
|
18711
19004
|
});
|
|
18712
19005
|
}
|
|
18713
19006
|
}
|
|
19007
|
+
_setDefaultToolBindingsIfMissing(toolGroupId, toolName, bindings) {
|
|
19008
|
+
if (!this.defaultToolBindingsMap.has(toolGroupId)) {
|
|
19009
|
+
this.defaultToolBindingsMap.set(toolGroupId, new Map());
|
|
19010
|
+
}
|
|
19011
|
+
const toolMap = this.defaultToolBindingsMap.get(toolGroupId);
|
|
19012
|
+
if (!toolMap.has(toolName)) {
|
|
19013
|
+
toolMap.set(toolName, this._cloneToolBindings(bindings));
|
|
19014
|
+
}
|
|
19015
|
+
}
|
|
18714
19016
|
_addTools(toolGroup, tools) {
|
|
18715
19017
|
const addTools = tools => {
|
|
18716
19018
|
tools.forEach(({
|
|
@@ -18742,6 +19044,60 @@ class ToolGroupService {
|
|
|
18742
19044
|
addTools(tools.disabled);
|
|
18743
19045
|
}
|
|
18744
19046
|
}
|
|
19047
|
+
_loadPersistedBindings(toolGroupId) {
|
|
19048
|
+
const toolGroupBindings = this._readPersistedToolBindings()[toolGroupId];
|
|
19049
|
+
if (!toolGroupBindings) {
|
|
19050
|
+
return;
|
|
19051
|
+
}
|
|
19052
|
+
const toolGroup = dist_esm.ToolGroupManager.getToolGroup(toolGroupId);
|
|
19053
|
+
for (const [toolName, bindings] of Object.entries(toolGroupBindings)) {
|
|
19054
|
+
this.setToolBindings(toolGroupId, toolName, bindings);
|
|
19055
|
+
if (!toolGroup || !toolGroup.hasTool(toolName)) {
|
|
19056
|
+
continue;
|
|
19057
|
+
}
|
|
19058
|
+
const {
|
|
19059
|
+
mode
|
|
19060
|
+
} = toolGroup.getToolOptions(toolName);
|
|
19061
|
+
if (mode === dist_esm.Enums.ToolModes.Active) {
|
|
19062
|
+
this.applyToolBindings(toolGroupId, toolName, {
|
|
19063
|
+
replaceExisting: true
|
|
19064
|
+
});
|
|
19065
|
+
}
|
|
19066
|
+
}
|
|
19067
|
+
}
|
|
19068
|
+
_readPersistedToolBindings() {
|
|
19069
|
+
try {
|
|
19070
|
+
const stored = localStorage.getItem(this._getToolBindingsStorageKey());
|
|
19071
|
+
if (!stored) {
|
|
19072
|
+
return {};
|
|
19073
|
+
}
|
|
19074
|
+
const parsed = JSON.parse(stored);
|
|
19075
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
19076
|
+
return {};
|
|
19077
|
+
}
|
|
19078
|
+
return parsed;
|
|
19079
|
+
} catch {
|
|
19080
|
+
// ignore corrupt localStorage
|
|
19081
|
+
return {};
|
|
19082
|
+
}
|
|
19083
|
+
}
|
|
19084
|
+
_writePersistedToolBindings(bindings) {
|
|
19085
|
+
const storageKey = this._getToolBindingsStorageKey();
|
|
19086
|
+
if (!Object.keys(bindings).length) {
|
|
19087
|
+
localStorage.removeItem(storageKey);
|
|
19088
|
+
return;
|
|
19089
|
+
}
|
|
19090
|
+
localStorage.setItem(storageKey, JSON.stringify(bindings));
|
|
19091
|
+
}
|
|
19092
|
+
_cloneToolBindings(bindings) {
|
|
19093
|
+
return bindings.map(binding => ({
|
|
19094
|
+
...binding
|
|
19095
|
+
}));
|
|
19096
|
+
}
|
|
19097
|
+
_getToolBindingsStorageKey() {
|
|
19098
|
+
const customizationValue = this.customizationService?.getCustomization('ohif.userPreferences.toolBindingsStorageKey');
|
|
19099
|
+
return typeof customizationValue === 'string' && customizationValue.length > 0 ? customizationValue : 'user-preferred-tool-bindings';
|
|
19100
|
+
}
|
|
18745
19101
|
}
|
|
18746
19102
|
_ToolGroupService = ToolGroupService;
|
|
18747
19103
|
ToolGroupService.REGISTRATION = {
|
|
@@ -18829,7 +19185,12 @@ const segmentationRepresentationModifiedCallback = async (synchronizerInstance,
|
|
|
18829
19185
|
const sourceDisplaySetUIDs = extractDisplaySetUIDs(sourceViewportInfo);
|
|
18830
19186
|
const targetDisplaySetUIDs = extractDisplaySetUIDs(targetViewportInfo);
|
|
18831
19187
|
const sharedDisplaySetExists = isAnyDisplaySetCommon(sourceDisplaySetUIDs, targetDisplaySetUIDs);
|
|
18832
|
-
|
|
19188
|
+
const targetFrameOfReferenceUID = viewport.getFrameOfReferenceUID();
|
|
19189
|
+
const sourceFrameOfReferenceUID = (0,esm.getEnabledElementByViewportId)(sourceViewportId)?.viewport?.getFrameOfReferenceUID();
|
|
19190
|
+
if (!sharedDisplaySetExists && !targetFrameOfReferenceUID) {
|
|
19191
|
+
return;
|
|
19192
|
+
}
|
|
19193
|
+
if (!sharedDisplaySetExists && targetFrameOfReferenceUID !== sourceFrameOfReferenceUID) {
|
|
18833
19194
|
return;
|
|
18834
19195
|
}
|
|
18835
19196
|
const targetViewportRepresentation = segmentationService.getSegmentationRepresentations(targetViewportId, {
|
|
@@ -19196,11 +19557,11 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19196
19557
|
this.EVENTS = SegmentationService_EVENTS;
|
|
19197
19558
|
this.destroy = () => {
|
|
19198
19559
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_MODIFIED, this._onSegmentationModifiedFromSource);
|
|
19199
|
-
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this.
|
|
19560
|
+
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationRemovedFromSource);
|
|
19200
19561
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_DATA_MODIFIED, this._onSegmentationDataModifiedFromSource);
|
|
19201
19562
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_MODIFIED, this._onSegmentationRepresentationModifiedFromSource);
|
|
19202
19563
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_ADDED, this._onSegmentationRepresentationModifiedFromSource);
|
|
19203
|
-
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this.
|
|
19564
|
+
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationRemovedFromSource);
|
|
19204
19565
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
|
|
19205
19566
|
this.reset();
|
|
19206
19567
|
};
|
|
@@ -19261,6 +19622,16 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19261
19622
|
viewportId
|
|
19262
19623
|
});
|
|
19263
19624
|
};
|
|
19625
|
+
this._onSegmentationRepresentationRemovedFromSource = evt => {
|
|
19626
|
+
const {
|
|
19627
|
+
segmentationId,
|
|
19628
|
+
viewportId
|
|
19629
|
+
} = evt.detail;
|
|
19630
|
+
this._broadcastEvent(this.EVENTS.SEGMENTATION_REPRESENTATION_REMOVED, {
|
|
19631
|
+
segmentationId,
|
|
19632
|
+
viewportId
|
|
19633
|
+
});
|
|
19634
|
+
};
|
|
19264
19635
|
this._onSegmentationModifiedFromSource = evt => {
|
|
19265
19636
|
const {
|
|
19266
19637
|
segmentationId
|
|
@@ -19277,6 +19648,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19277
19648
|
segmentationId
|
|
19278
19649
|
});
|
|
19279
19650
|
};
|
|
19651
|
+
this._onSegmentationRemovedFromSource = evt => {
|
|
19652
|
+
const {
|
|
19653
|
+
segmentationId
|
|
19654
|
+
} = evt.detail;
|
|
19655
|
+
this._broadcastEvent(this.EVENTS.SEGMENTATION_REMOVED, {
|
|
19656
|
+
segmentationId
|
|
19657
|
+
});
|
|
19658
|
+
};
|
|
19280
19659
|
this._onAnnotationCutMergeProcessCompletedFromSource = evt => {
|
|
19281
19660
|
const {
|
|
19282
19661
|
segmentationId
|
|
@@ -19482,6 +19861,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19482
19861
|
},
|
|
19483
19862
|
config: {
|
|
19484
19863
|
label,
|
|
19864
|
+
fallbackLabel: `S:${displaySet.SeriesNumber} ${displaySet.Modality}`,
|
|
19485
19865
|
segments: options?.segments && Object.keys(options.segments).length > 0 ? options.segments : {
|
|
19486
19866
|
1: {
|
|
19487
19867
|
label: `${i18n_src/* default */.A.t('Segment')} 1`,
|
|
@@ -19613,6 +19993,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19613
19993
|
},
|
|
19614
19994
|
config: {
|
|
19615
19995
|
label: segDisplaySet.SeriesDescription,
|
|
19996
|
+
fallbackLabel: `S:${segDisplaySet.SeriesNumber} ${segDisplaySet.Modality}`,
|
|
19616
19997
|
segments
|
|
19617
19998
|
}
|
|
19618
19999
|
};
|
|
@@ -19673,7 +20054,8 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19673
20054
|
}
|
|
19674
20055
|
},
|
|
19675
20056
|
config: {
|
|
19676
|
-
label: rtDisplaySet.SeriesDescription
|
|
20057
|
+
label: rtDisplaySet.SeriesDescription,
|
|
20058
|
+
fallbackLabel: `S:${rtDisplaySet.SeriesNumber} ${rtDisplaySet.Modality}`
|
|
19677
20059
|
}
|
|
19678
20060
|
};
|
|
19679
20061
|
const segments = {};
|
|
@@ -20170,14 +20552,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
20170
20552
|
}
|
|
20171
20553
|
/**
|
|
20172
20554
|
* Clears segmentation representations from the viewport.
|
|
20173
|
-
* Unlike
|
|
20555
|
+
* Unlike removeRepresentationsFromViewport, this doesn't update
|
|
20174
20556
|
* removed display set and representation maps.
|
|
20175
20557
|
* We track removed segmentations manually to avoid re-adding them
|
|
20176
20558
|
* when the display set is added again.
|
|
20177
20559
|
* @param viewportId - The viewport ID to clear segmentation representations from.
|
|
20178
20560
|
*/
|
|
20179
20561
|
clearSegmentationRepresentations(viewportId) {
|
|
20180
|
-
this.
|
|
20562
|
+
this.removeRepresentationsFromViewport(viewportId);
|
|
20181
20563
|
}
|
|
20182
20564
|
|
|
20183
20565
|
/**
|
|
@@ -20192,7 +20574,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
20192
20574
|
}
|
|
20193
20575
|
|
|
20194
20576
|
/**
|
|
20195
|
-
*
|
|
20577
|
+
* Removes segmentation representations from the viewport.
|
|
20196
20578
|
* @param viewportId - The viewport id to remove the segmentation representations from.
|
|
20197
20579
|
* @param specifier - The specifier to remove the segmentation representations.
|
|
20198
20580
|
*
|
|
@@ -20202,7 +20584,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
20202
20584
|
* If a type specifier is provided, only the segmentation representation with the specified type are removed.
|
|
20203
20585
|
* If both a segmentationId and type specifier are provided, only the segmentation representation with the specified segmentationId and type are removed.
|
|
20204
20586
|
*/
|
|
20205
|
-
|
|
20587
|
+
removeRepresentationsFromViewport(viewportId, specifier = {}) {
|
|
20206
20588
|
dist_esm.segmentation.removeSegmentationRepresentations(viewportId, specifier);
|
|
20207
20589
|
}
|
|
20208
20590
|
|
|
@@ -20558,6 +20940,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
20558
20940
|
id: id,
|
|
20559
20941
|
segmentationId,
|
|
20560
20942
|
label: segmentation.label,
|
|
20943
|
+
fallbackLabel: segmentation.fallbackLabel,
|
|
20561
20944
|
active,
|
|
20562
20945
|
type,
|
|
20563
20946
|
visible,
|
|
@@ -20570,11 +20953,11 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
20570
20953
|
}
|
|
20571
20954
|
_initSegmentationService() {
|
|
20572
20955
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_MODIFIED, this._onSegmentationModifiedFromSource);
|
|
20573
|
-
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this.
|
|
20956
|
+
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationRemovedFromSource);
|
|
20574
20957
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_DATA_MODIFIED, this._onSegmentationDataModifiedFromSource);
|
|
20575
20958
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_MODIFIED, this._onSegmentationRepresentationModifiedFromSource);
|
|
20576
20959
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_ADDED, this._onSegmentationRepresentationModifiedFromSource);
|
|
20577
|
-
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this.
|
|
20960
|
+
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationRemovedFromSource);
|
|
20578
20961
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
|
|
20579
20962
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED, this._onAnnotationCutMergeProcessCompletedFromSource);
|
|
20580
20963
|
}
|
|
@@ -20780,6 +21163,7 @@ const ORTHOGRAPHIC = 'orthographic';
|
|
|
20780
21163
|
const VOLUME_3D = 'volume3d';
|
|
20781
21164
|
const VIDEO = 'video';
|
|
20782
21165
|
const WHOLESLIDE = 'wholeslide';
|
|
21166
|
+
const ECG = 'ecg';
|
|
20783
21167
|
function getCornerstoneViewportType(viewportType, displaySets) {
|
|
20784
21168
|
const lowerViewportType = displaySets?.[0]?.viewportType?.toLowerCase() || viewportType.toLowerCase();
|
|
20785
21169
|
if (lowerViewportType === STACK) {
|
|
@@ -20791,13 +21175,16 @@ function getCornerstoneViewportType(viewportType, displaySets) {
|
|
|
20791
21175
|
if (lowerViewportType === WHOLESLIDE) {
|
|
20792
21176
|
return esm.Enums.ViewportType.WHOLE_SLIDE;
|
|
20793
21177
|
}
|
|
21178
|
+
if (lowerViewportType === ECG) {
|
|
21179
|
+
return esm.Enums.ViewportType.ECG;
|
|
21180
|
+
}
|
|
20794
21181
|
if (lowerViewportType === VOLUME || lowerViewportType === ORTHOGRAPHIC) {
|
|
20795
21182
|
return esm.Enums.ViewportType.ORTHOGRAPHIC;
|
|
20796
21183
|
}
|
|
20797
21184
|
if (lowerViewportType === VOLUME_3D) {
|
|
20798
21185
|
return esm.Enums.ViewportType.VOLUME_3D;
|
|
20799
21186
|
}
|
|
20800
|
-
throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide`);
|
|
21187
|
+
throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide, ecg`);
|
|
20801
21188
|
}
|
|
20802
21189
|
;// ../../../extensions/cornerstone/src/services/CornerstoneCacheService/CornerstoneCacheService.ts
|
|
20803
21190
|
var _CornerstoneCacheService;
|
|
@@ -21104,15 +21491,24 @@ function getCornerstoneBlendMode(blendMode) {
|
|
|
21104
21491
|
const AXIAL = 'axial';
|
|
21105
21492
|
const SAGITTAL = 'sagittal';
|
|
21106
21493
|
const CORONAL = 'coronal';
|
|
21494
|
+
const AXIAL_REFORMAT = 'axial_reformat';
|
|
21495
|
+
const SAGITTAL_REFORMAT = 'sagittal_reformat';
|
|
21496
|
+
const CORONAL_REFORMAT = 'coronal_reformat';
|
|
21107
21497
|
function getCornerstoneOrientation(orientation) {
|
|
21108
21498
|
if (orientation) {
|
|
21109
21499
|
switch (orientation.toLowerCase()) {
|
|
21110
21500
|
case AXIAL:
|
|
21111
21501
|
return esm.Enums.OrientationAxis.AXIAL;
|
|
21502
|
+
case AXIAL_REFORMAT:
|
|
21503
|
+
return esm.Enums.OrientationAxis.AXIAL_REFORMAT;
|
|
21112
21504
|
case SAGITTAL:
|
|
21113
21505
|
return esm.Enums.OrientationAxis.SAGITTAL;
|
|
21506
|
+
case SAGITTAL_REFORMAT:
|
|
21507
|
+
return esm.Enums.OrientationAxis.SAGITTAL_REFORMAT;
|
|
21114
21508
|
case CORONAL:
|
|
21115
21509
|
return esm.Enums.OrientationAxis.CORONAL;
|
|
21510
|
+
case CORONAL_REFORMAT:
|
|
21511
|
+
return esm.Enums.OrientationAxis.CORONAL_REFORMAT;
|
|
21116
21512
|
default:
|
|
21117
21513
|
return esm.Enums.OrientationAxis.ACQUISITION;
|
|
21118
21514
|
}
|
|
@@ -21385,6 +21781,32 @@ const CornerstoneViewportService_EVENTS = {
|
|
|
21385
21781
|
};
|
|
21386
21782
|
const MIN_STACK_VIEWPORTS_TO_ENQUEUE_RESIZE = 12;
|
|
21387
21783
|
const MIN_VOLUME_VIEWPORTS_TO_ENQUEUE_RESIZE = 6;
|
|
21784
|
+
function getVolumeActorReferencedIds(viewport) {
|
|
21785
|
+
const actors = viewport.getActors?.() ?? [];
|
|
21786
|
+
return actors.filter(ac => ac.actor?.getClassName?.() === 'vtkVolume').map(ac => ac.referencedId).filter(Boolean);
|
|
21787
|
+
}
|
|
21788
|
+
function volumeIdPrefixesMatch(existingIds, prefixLen, targetIds) {
|
|
21789
|
+
if (prefixLen > targetIds.length) {
|
|
21790
|
+
return false;
|
|
21791
|
+
}
|
|
21792
|
+
for (let i = 0; i < prefixLen; i++) {
|
|
21793
|
+
if (existingIds[i] !== targetIds[i]) {
|
|
21794
|
+
return false;
|
|
21795
|
+
}
|
|
21796
|
+
}
|
|
21797
|
+
return true;
|
|
21798
|
+
}
|
|
21799
|
+
|
|
21800
|
+
/**
|
|
21801
|
+
* Returns true when the viewport type matches a volume-based presentation (ORTHOGRAPHIC or VOLUME_3D).
|
|
21802
|
+
*/
|
|
21803
|
+
function viewportMatchesDesiredVolumePresentation(viewport, desiredViewportInfo) {
|
|
21804
|
+
const desiredType = desiredViewportInfo.getViewportType();
|
|
21805
|
+
if (viewport.type !== desiredType) {
|
|
21806
|
+
return false;
|
|
21807
|
+
}
|
|
21808
|
+
return desiredType === esm.Enums.ViewportType.ORTHOGRAPHIC || desiredType === esm.Enums.ViewportType.VOLUME_3D;
|
|
21809
|
+
}
|
|
21388
21810
|
const WITH_NAVIGATION = {
|
|
21389
21811
|
withNavigation: true,
|
|
21390
21812
|
withOrientation: false
|
|
@@ -22072,6 +22494,15 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22072
22494
|
/**
|
|
22073
22495
|
* Sets the image data for the given viewport.
|
|
22074
22496
|
*/
|
|
22497
|
+
async _setEcgViewport(viewport, viewportData) {
|
|
22498
|
+
const [displaySet] = viewportData.data;
|
|
22499
|
+
const imageId = displaySet.imageIds?.[0];
|
|
22500
|
+
if (!imageId) {
|
|
22501
|
+
console.error('[CornerstoneViewportService] ECG display set has no imageId');
|
|
22502
|
+
return;
|
|
22503
|
+
}
|
|
22504
|
+
return viewport.setEcg(imageId);
|
|
22505
|
+
}
|
|
22075
22506
|
async _setOtherViewport(viewport, viewportData, viewportInfo, _presentations = {}) {
|
|
22076
22507
|
const [displaySet] = viewportData.data;
|
|
22077
22508
|
return viewport.setDataIds(displaySet.imageIds, {
|
|
@@ -22140,32 +22571,25 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22140
22571
|
if (initialImageIndexToUse === undefined || initialImageIndexToUse === null || initialImageIndexToUse < 0) {
|
|
22141
22572
|
initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0;
|
|
22142
22573
|
}
|
|
22143
|
-
|
|
22574
|
+
await viewport.setStack(imageIds, initialImageIndexToUse);
|
|
22575
|
+
viewport.setProperties({
|
|
22576
|
+
...properties
|
|
22577
|
+
});
|
|
22578
|
+
this.setPresentations(viewport.id, presentations, viewportInfo);
|
|
22579
|
+
await this._addOverlayRepresentations(overlayProcessingResults);
|
|
22580
|
+
if (displayArea) {
|
|
22581
|
+
viewport.setDisplayArea(displayArea);
|
|
22582
|
+
}
|
|
22583
|
+
if (rotation) {
|
|
22144
22584
|
viewport.setProperties({
|
|
22145
|
-
|
|
22585
|
+
rotation
|
|
22146
22586
|
});
|
|
22147
|
-
|
|
22148
|
-
|
|
22149
|
-
|
|
22150
|
-
|
|
22151
|
-
|
|
22152
|
-
|
|
22153
|
-
});
|
|
22154
|
-
}
|
|
22155
|
-
if (displayArea) {
|
|
22156
|
-
viewport.setDisplayArea(displayArea);
|
|
22157
|
-
}
|
|
22158
|
-
if (rotation) {
|
|
22159
|
-
viewport.setProperties({
|
|
22160
|
-
rotation
|
|
22161
|
-
});
|
|
22162
|
-
}
|
|
22163
|
-
if (flipHorizontal) {
|
|
22164
|
-
viewport.setCamera({
|
|
22165
|
-
flipHorizontal: true
|
|
22166
|
-
});
|
|
22167
|
-
}
|
|
22168
|
-
});
|
|
22587
|
+
}
|
|
22588
|
+
if (flipHorizontal) {
|
|
22589
|
+
viewport.setCamera({
|
|
22590
|
+
flipHorizontal: true
|
|
22591
|
+
});
|
|
22592
|
+
}
|
|
22169
22593
|
}
|
|
22170
22594
|
_getInitialImageIndexForViewport(viewportInfo, imageIds) {
|
|
22171
22595
|
const initialImageOptions = viewportInfo.getInitialImageOptions();
|
|
@@ -22388,16 +22812,34 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22388
22812
|
}
|
|
22389
22813
|
});
|
|
22390
22814
|
}
|
|
22391
|
-
|
|
22392
|
-
|
|
22393
|
-
|
|
22394
|
-
|
|
22395
|
-
|
|
22396
|
-
|
|
22397
|
-
|
|
22815
|
+
const baseVolumeInputs = filteredVolumeInputArray.map(({
|
|
22816
|
+
volumeInput
|
|
22817
|
+
}) => volumeInput);
|
|
22818
|
+
const nextBaseVolumeIds = baseVolumeInputs.map(v => v.volumeId);
|
|
22819
|
+
const existingVolumeIds = getVolumeActorReferencedIds(viewport);
|
|
22820
|
+
let skippedIdenticalBaseVolumes = false;
|
|
22821
|
+
if (baseVolumeInputs.length) {
|
|
22822
|
+
const singleBaseViewport = nextBaseVolumeIds.length === 1;
|
|
22823
|
+
|
|
22824
|
+
// Only skip setVolumes() when the viewport type already matches the desired OHIF type
|
|
22825
|
+
// (ORTHOGRAPHIC / VOLUME_3D); otherwise a stack → MPR switch with the same volumeId
|
|
22826
|
+
// would incorrectly skip rebuilding the viewport.
|
|
22827
|
+
if (singleBaseViewport && existingVolumeIds.length >= nextBaseVolumeIds.length && volumeIdPrefixesMatch(existingVolumeIds, nextBaseVolumeIds.length, nextBaseVolumeIds) && viewportMatchesDesiredVolumePresentation(viewport, viewportInfo)) {
|
|
22828
|
+
// Same primary volume already loaded (e.g. labelmap / extra actors after it) — avoid
|
|
22829
|
+
// setVolumes(), which tears down all actors and blanks MPR during SEG hydrate.
|
|
22830
|
+
skippedIdenticalBaseVolumes = true;
|
|
22831
|
+
} else if (existingVolumeIds.length && nextBaseVolumeIds.length > existingVolumeIds.length && volumeIdPrefixesMatch(existingVolumeIds, existingVolumeIds.length, nextBaseVolumeIds) && typeof viewport.addVolumes === 'function') {
|
|
22832
|
+
const toAdd = baseVolumeInputs.slice(existingVolumeIds.length);
|
|
22833
|
+
if (toAdd.length) {
|
|
22834
|
+
await viewport.addVolumes(toAdd);
|
|
22398
22835
|
}
|
|
22399
|
-
}
|
|
22836
|
+
} else {
|
|
22837
|
+
await viewport.setVolumes(baseVolumeInputs);
|
|
22838
|
+
}
|
|
22839
|
+
} else if (volumeInputArray.length) {
|
|
22840
|
+
await viewport.setVolumes(volumeInputArray);
|
|
22400
22841
|
}
|
|
22842
|
+
await this._addOverlayRepresentations(overlayProcessingResults);
|
|
22401
22843
|
viewport.render();
|
|
22402
22844
|
volumesProperties.forEach(({
|
|
22403
22845
|
properties,
|
|
@@ -22409,7 +22851,10 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22409
22851
|
});
|
|
22410
22852
|
});
|
|
22411
22853
|
this.setPresentations(viewport.id, presentations);
|
|
22412
|
-
|
|
22854
|
+
// Presentations apply segmentation (hydrated labelmap etc.) after the render above — redraw so
|
|
22855
|
+
// every orthographic/3D tile shows the updated scene (fixes MPR siblings blank after SEG hydrate).
|
|
22856
|
+
viewport.render();
|
|
22857
|
+
if (!presentations.positionPresentation && !skippedIdenticalBaseVolumes) {
|
|
22413
22858
|
const imageIndex = this._getInitialImageIndexForViewport(viewportInfo);
|
|
22414
22859
|
if (imageIndex !== undefined) {
|
|
22415
22860
|
esm.utilities.jumpToSlice(viewport.element, {
|
|
@@ -22460,7 +22905,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22460
22905
|
const {
|
|
22461
22906
|
predecessorImageId
|
|
22462
22907
|
} = displaySet;
|
|
22463
|
-
segmentationService.addSegmentationRepresentation(viewport.id, {
|
|
22908
|
+
const segmentationRepresentationPromise = segmentationService.addSegmentationRepresentation(viewport.id, {
|
|
22464
22909
|
segmentationId,
|
|
22465
22910
|
predecessorImageId,
|
|
22466
22911
|
type: representationType,
|
|
@@ -22468,11 +22913,21 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22468
22913
|
blendMode: viewport?.getBlendMode?.() === 1 ? dist_esm_enums.BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined
|
|
22469
22914
|
}
|
|
22470
22915
|
});
|
|
22471
|
-
|
|
22472
22916
|
// store the segmentation presentation id in the viewport info
|
|
22473
22917
|
this.storePresentation({
|
|
22474
22918
|
viewportId: viewport.id
|
|
22475
22919
|
});
|
|
22920
|
+
return segmentationRepresentationPromise;
|
|
22921
|
+
}
|
|
22922
|
+
async _addOverlayRepresentations(overlayProcessingResults) {
|
|
22923
|
+
if (!overlayProcessingResults?.length) {
|
|
22924
|
+
return;
|
|
22925
|
+
}
|
|
22926
|
+
for (const overlayProcessingResult of overlayProcessingResults) {
|
|
22927
|
+
if (overlayProcessingResult?.addOverlayFn) {
|
|
22928
|
+
await overlayProcessingResult.addOverlayFn();
|
|
22929
|
+
}
|
|
22930
|
+
}
|
|
22476
22931
|
}
|
|
22477
22932
|
|
|
22478
22933
|
// Todo: keepCamera is an interim solution until we have a better solution for
|
|
@@ -22507,6 +22962,9 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22507
22962
|
if ([esm.VolumeViewport, esm.VolumeViewport3D].some(type => viewport instanceof type)) {
|
|
22508
22963
|
return this._setVolumeViewport(viewport, viewportData, viewportInfo, presentations);
|
|
22509
22964
|
}
|
|
22965
|
+
if (viewport instanceof esm.ECGViewport) {
|
|
22966
|
+
return this._setEcgViewport(viewport, viewportData);
|
|
22967
|
+
}
|
|
22510
22968
|
return this._setOtherViewport(viewport, viewportData, viewportInfo, presentations);
|
|
22511
22969
|
}
|
|
22512
22970
|
|
|
@@ -22549,8 +23007,8 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22549
23007
|
if (!displaySet) {
|
|
22550
23008
|
return;
|
|
22551
23009
|
}
|
|
22552
|
-
if (displaySet.
|
|
22553
|
-
return displaySet.
|
|
23010
|
+
if (displaySet.FrameOfReferenceUID) {
|
|
23011
|
+
return displaySet.FrameOfReferenceUID;
|
|
22554
23012
|
}
|
|
22555
23013
|
if (displaySet.Modality === 'SEG') {
|
|
22556
23014
|
const {
|
|
@@ -22728,6 +23186,8 @@ CornerstoneViewportService.REGISTRATION = {
|
|
|
22728
23186
|
}
|
|
22729
23187
|
};
|
|
22730
23188
|
/* harmony default export */ const ViewportService_CornerstoneViewportService = (CornerstoneViewportService);
|
|
23189
|
+
// EXTERNAL MODULE: ../../../extensions/cornerstone/src/utils/getDataIdForViewport.ts
|
|
23190
|
+
var getDataIdForViewport = __webpack_require__(67142);
|
|
22731
23191
|
;// ../../../extensions/cornerstone/src/types/Colorbar.ts
|
|
22732
23192
|
// Position options
|
|
22733
23193
|
|
|
@@ -22770,6 +23230,7 @@ var _ColorbarService;
|
|
|
22770
23230
|
|
|
22771
23231
|
|
|
22772
23232
|
|
|
23233
|
+
|
|
22773
23234
|
class ColorbarService extends src/* PubSubService */.Rc {
|
|
22774
23235
|
constructor(servicesManager) {
|
|
22775
23236
|
super(ColorbarService.EVENTS);
|
|
@@ -22793,23 +23254,6 @@ class ColorbarService extends src/* PubSubService */.Rc {
|
|
|
22793
23254
|
this.servicesManager = servicesManager;
|
|
22794
23255
|
}
|
|
22795
23256
|
|
|
22796
|
-
/**
|
|
22797
|
-
* Gets the appropriate data ID for a viewport and display set
|
|
22798
|
-
* @param viewport - The viewport instance
|
|
22799
|
-
* @param displaySetInstanceUID - The display set instance UID to identify data
|
|
22800
|
-
* @returns The appropriate data ID for the viewport type (volumeId for volume viewports, undefined for stack)
|
|
22801
|
-
*/
|
|
22802
|
-
getDataIdForViewport(viewport, displaySetInstanceUID) {
|
|
22803
|
-
// For volume viewports, find the matching volumeId
|
|
22804
|
-
if (viewport.getAllVolumeIds) {
|
|
22805
|
-
const volumeIds = viewport.getAllVolumeIds() || [];
|
|
22806
|
-
return volumeIds.length > 0 ? volumeIds.find(id => id.includes(displaySetInstanceUID)) || undefined : undefined;
|
|
22807
|
-
}
|
|
22808
|
-
|
|
22809
|
-
// For other viewports, no specific dataId is needed for now
|
|
22810
|
-
return undefined;
|
|
22811
|
-
}
|
|
22812
|
-
|
|
22813
23257
|
/**
|
|
22814
23258
|
* Adds a colorbar to a specific viewport identified by `viewportId`, using the provided `displaySetInstanceUIDs` and `options`.
|
|
22815
23259
|
* This method prepares the colorbar state that will be used by the ViewportColorbarsContainer component.
|
|
@@ -22841,7 +23285,7 @@ class ColorbarService extends src/* PubSubService */.Rc {
|
|
|
22841
23285
|
if (displaySet.isOverlayDisplaySet) {
|
|
22842
23286
|
return;
|
|
22843
23287
|
}
|
|
22844
|
-
const dataId =
|
|
23288
|
+
const dataId = (0,getDataIdForViewport/* getDataIdForViewport */.V)(viewport, displaySetInstanceUID);
|
|
22845
23289
|
const properties = dataId ? viewport.getProperties(dataId) : viewport.getProperties();
|
|
22846
23290
|
const colormap = properties?.colormap;
|
|
22847
23291
|
if (activeColormapName && !colormap) {
|
|
@@ -22979,7 +23423,7 @@ class ColorbarService extends src/* PubSubService */.Rc {
|
|
|
22979
23423
|
}
|
|
22980
23424
|
|
|
22981
23425
|
// Get the appropriate dataId for this viewport/displaySet combination
|
|
22982
|
-
const dataId =
|
|
23426
|
+
const dataId = (0,getDataIdForViewport/* getDataIdForViewport */.V)(viewport, displaySetInstanceUID);
|
|
22983
23427
|
|
|
22984
23428
|
// Set properties with or without dataId based on what the viewport supports
|
|
22985
23429
|
viewport.setProperties({
|
|
@@ -23005,6 +23449,54 @@ ColorbarService.REGISTRATION = {
|
|
|
23005
23449
|
;// ../../../extensions/cornerstone/src/services/ColorbarService/index.ts
|
|
23006
23450
|
|
|
23007
23451
|
/* harmony default export */ const services_ColorbarService = (ColorbarService);
|
|
23452
|
+
;// ../../../extensions/cornerstone/src/services/ViewedDataService/ViewedDataService.ts
|
|
23453
|
+
var _ViewedDataService;
|
|
23454
|
+
|
|
23455
|
+
class ViewedDataService extends src/* PubSubService */.Rc {
|
|
23456
|
+
constructor() {
|
|
23457
|
+
super(ViewedDataService.EVENTS);
|
|
23458
|
+
this.viewedDataIds = new Set();
|
|
23459
|
+
}
|
|
23460
|
+
markDataViewed(dataId) {
|
|
23461
|
+
if (!dataId || this.viewedDataIds.has(dataId)) {
|
|
23462
|
+
return;
|
|
23463
|
+
}
|
|
23464
|
+
this.viewedDataIds.add(dataId);
|
|
23465
|
+
this._broadcastEvent(this.EVENTS.VIEWED_DATA_CHANGED, {
|
|
23466
|
+
viewedDataId: dataId
|
|
23467
|
+
});
|
|
23468
|
+
}
|
|
23469
|
+
isDataViewed(dataId) {
|
|
23470
|
+
if (!dataId) {
|
|
23471
|
+
return false;
|
|
23472
|
+
}
|
|
23473
|
+
return this.viewedDataIds.has(dataId);
|
|
23474
|
+
}
|
|
23475
|
+
clearViewedData() {
|
|
23476
|
+
this.viewedDataIds.clear();
|
|
23477
|
+
this._broadcastEvent(this.EVENTS.VIEWED_DATA_CHANGED, {
|
|
23478
|
+
viewedDataCleared: true
|
|
23479
|
+
});
|
|
23480
|
+
}
|
|
23481
|
+
subscribeViewedDataChanges(listener) {
|
|
23482
|
+
return this.subscribe(this.EVENTS.VIEWED_DATA_CHANGED, listener);
|
|
23483
|
+
}
|
|
23484
|
+
}
|
|
23485
|
+
_ViewedDataService = ViewedDataService;
|
|
23486
|
+
ViewedDataService.EVENTS = {
|
|
23487
|
+
VIEWED_DATA_CHANGED: 'event::viewedDataChanged'
|
|
23488
|
+
};
|
|
23489
|
+
ViewedDataService.REGISTRATION = {
|
|
23490
|
+
name: 'viewedDataService',
|
|
23491
|
+
altName: 'ViewedDataService',
|
|
23492
|
+
create: () => {
|
|
23493
|
+
return new _ViewedDataService();
|
|
23494
|
+
}
|
|
23495
|
+
};
|
|
23496
|
+
/* harmony default export */ const ViewedDataService_ViewedDataService = (ViewedDataService);
|
|
23497
|
+
;// ../../../extensions/cornerstone/src/services/ViewedDataService/index.ts
|
|
23498
|
+
|
|
23499
|
+
/* harmony default export */ const services_ViewedDataService = (ViewedDataService_ViewedDataService);
|
|
23008
23500
|
;// ../../../extensions/cornerstone/src/types/Presentation.ts
|
|
23009
23501
|
|
|
23010
23502
|
|
|
@@ -23249,12 +23741,114 @@ const createFrameViewSynchronizer = synchronizerName => {
|
|
|
23249
23741
|
|
|
23250
23742
|
// EXTERNAL MODULE: ../../../node_modules/dcmjs/build/dcmjs.es.js
|
|
23251
23743
|
var dcmjs_es = __webpack_require__(5842);
|
|
23744
|
+
;// ../../../extensions/cornerstone/src/utils/ecgMetadata.ts
|
|
23745
|
+
/**
|
|
23746
|
+
* Decode a multiplexed Int16 buffer into per-channel arrays.
|
|
23747
|
+
* Layout: sample0ch0, sample0ch1 ... sample0chN, sample1ch0, …
|
|
23748
|
+
* Note: DICOM ECG data is canonically SS (signed short). The sampleInterpretation
|
|
23749
|
+
* field is forwarded to ECGViewport for its own use; the raw buffer is always
|
|
23750
|
+
* treated as Int16 because Cornerstone ECGViewport expects Int16Array[].
|
|
23751
|
+
*/
|
|
23752
|
+
function decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples) {
|
|
23753
|
+
const src = new Int16Array(buffer);
|
|
23754
|
+
const channels = [];
|
|
23755
|
+
for (let ch = 0; ch < numberOfChannels; ch++) {
|
|
23756
|
+
const out = new Int16Array(numberOfSamples);
|
|
23757
|
+
for (let s = 0; s < numberOfSamples; s++) {
|
|
23758
|
+
out[s] = src[s * numberOfChannels + ch];
|
|
23759
|
+
}
|
|
23760
|
+
channels.push(out);
|
|
23761
|
+
}
|
|
23762
|
+
return channels;
|
|
23763
|
+
}
|
|
23764
|
+
|
|
23765
|
+
/**
|
|
23766
|
+
* Decode a base64 InlineBinary string into a raw ArrayBuffer.
|
|
23767
|
+
*/
|
|
23768
|
+
function base64ToArrayBuffer(base64) {
|
|
23769
|
+
const binaryStr = atob(base64);
|
|
23770
|
+
const bytes = new Uint8Array(binaryStr.length);
|
|
23771
|
+
for (let i = 0; i < binaryStr.length; i++) {
|
|
23772
|
+
bytes[i] = binaryStr.charCodeAt(i);
|
|
23773
|
+
}
|
|
23774
|
+
return bytes.buffer;
|
|
23775
|
+
}
|
|
23776
|
+
/**
|
|
23777
|
+
* Parse the naturalized DICOM instance's WaveformSequence and build the ecgModule
|
|
23778
|
+
* that Cornerstone's ECGViewport.setEcg() expects via
|
|
23779
|
+
* metaData.get(MetadataModules.ECG, imageId).
|
|
23780
|
+
*
|
|
23781
|
+
* Returns null if the instance has no WaveformSequence.
|
|
23782
|
+
*/
|
|
23783
|
+
function buildEcgModule(instance, userAuthenticationService) {
|
|
23784
|
+
const waveformGroups = instance?.WaveformSequence;
|
|
23785
|
+
if (!waveformGroups?.length) {
|
|
23786
|
+
return null;
|
|
23787
|
+
}
|
|
23788
|
+
|
|
23789
|
+
// Use the first (and typically only) multiplex group
|
|
23790
|
+
const group = waveformGroups[0];
|
|
23791
|
+
const numberOfChannels = group.NumberOfWaveformChannels ?? 0;
|
|
23792
|
+
const numberOfSamples = group.NumberOfWaveformSamples ?? 0;
|
|
23793
|
+
const samplingFrequency = group.SamplingFrequency ?? 1;
|
|
23794
|
+
const bitsAllocated = group.WaveformBitsAllocated ?? 16;
|
|
23795
|
+
const sampleInterpretation = group.WaveformSampleInterpretation ?? 'SS';
|
|
23796
|
+
const multiplexGroupLabel = group.MultiplexGroupLabel ?? '';
|
|
23797
|
+
const channelDefinitionSequence = (group.ChannelDefinitionSequence ?? []).map(ch => ({
|
|
23798
|
+
channelSourceSequence: {
|
|
23799
|
+
codeMeaning: ch?.ChannelSourceSequence?.[0]?.CodeMeaning ?? ch?.ChannelSourceSequence?.[0]?.codeMeaning ?? ''
|
|
23800
|
+
}
|
|
23801
|
+
}));
|
|
23802
|
+
const retrieveBulkData = async () => {
|
|
23803
|
+
const waveformData = group.WaveformData;
|
|
23804
|
+
if (!waveformData) {
|
|
23805
|
+
console.warn('[ECGViewport] No WaveformData found on instance');
|
|
23806
|
+
return [];
|
|
23807
|
+
}
|
|
23808
|
+
let buffer;
|
|
23809
|
+
if (waveformData.InlineBinary) {
|
|
23810
|
+
buffer = base64ToArrayBuffer(waveformData.InlineBinary);
|
|
23811
|
+
} else if (waveformData.BulkDataURI) {
|
|
23812
|
+
const headers = {
|
|
23813
|
+
Accept: 'application/octet-stream'
|
|
23814
|
+
};
|
|
23815
|
+
const authHeader = userAuthenticationService?.getAuthorizationHeader?.();
|
|
23816
|
+
if (authHeader) {
|
|
23817
|
+
Object.assign(headers, authHeader);
|
|
23818
|
+
}
|
|
23819
|
+
const response = await fetch(waveformData.BulkDataURI, {
|
|
23820
|
+
headers
|
|
23821
|
+
});
|
|
23822
|
+
if (!response.ok) {
|
|
23823
|
+
throw new Error(`[ECGViewport] Failed to fetch waveform BulkDataURI: ${response.status}`);
|
|
23824
|
+
}
|
|
23825
|
+
buffer = await response.arrayBuffer();
|
|
23826
|
+
} else {
|
|
23827
|
+
console.warn('[ECGViewport] WaveformData has no InlineBinary or BulkDataURI');
|
|
23828
|
+
return [];
|
|
23829
|
+
}
|
|
23830
|
+
return decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples);
|
|
23831
|
+
};
|
|
23832
|
+
return {
|
|
23833
|
+
numberOfWaveformChannels: numberOfChannels,
|
|
23834
|
+
numberOfWaveformSamples: numberOfSamples,
|
|
23835
|
+
samplingFrequency,
|
|
23836
|
+
waveformBitsAllocated: bitsAllocated,
|
|
23837
|
+
waveformSampleInterpretation: sampleInterpretation,
|
|
23838
|
+
multiplexGroupLabel,
|
|
23839
|
+
channelDefinitionSequence,
|
|
23840
|
+
waveformData: {
|
|
23841
|
+
retrieveBulkData
|
|
23842
|
+
}
|
|
23843
|
+
};
|
|
23844
|
+
}
|
|
23252
23845
|
;// ../../../extensions/cornerstone/src/getSopClassHandlerModule.js
|
|
23253
23846
|
|
|
23254
23847
|
|
|
23255
23848
|
|
|
23256
23849
|
|
|
23257
23850
|
|
|
23851
|
+
|
|
23258
23852
|
const {
|
|
23259
23853
|
MetadataModules
|
|
23260
23854
|
} = esm.Enums;
|
|
@@ -23265,9 +23859,9 @@ const {
|
|
|
23265
23859
|
denaturalizeDataset
|
|
23266
23860
|
} = dcmjs_es/* default.data */.Ay.data.DicomMetaDictionary;
|
|
23267
23861
|
const {
|
|
23268
|
-
transferDenaturalizedDataset,
|
|
23269
|
-
fixMultiValueKeys
|
|
23270
|
-
} = default_src
|
|
23862
|
+
/* transferDenaturalizedDataset */ "If": transferDenaturalizedDataset,
|
|
23863
|
+
/* fixMultiValueKeys */ "Uk": fixMultiValueKeys
|
|
23864
|
+
} = default_src/* dicomWebUtils */.CA;
|
|
23271
23865
|
const SOP_CLASS_UIDS = {
|
|
23272
23866
|
VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE: '1.2.840.10008.5.1.4.1.1.77.1.6'
|
|
23273
23867
|
};
|
|
@@ -23393,8 +23987,92 @@ function getDicomMicroscopySopClassHandler({
|
|
|
23393
23987
|
getDisplaySetsFromSeries
|
|
23394
23988
|
};
|
|
23395
23989
|
}
|
|
23990
|
+
|
|
23991
|
+
/**
|
|
23992
|
+
* DICOM Waveform SOP Class UIDs for ECG / cardiac electrophysiology.
|
|
23993
|
+
* Reference: https://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_B.5.html
|
|
23994
|
+
*/
|
|
23995
|
+
const ECG_SOP_CLASS_UIDS = {
|
|
23996
|
+
TWELVE_LEAD_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.1',
|
|
23997
|
+
GENERAL_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.2',
|
|
23998
|
+
AMBULATORY_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.3',
|
|
23999
|
+
HEMODYNAMIC_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.2.1',
|
|
24000
|
+
CARDIAC_ELECTROPHYSIOLOGY_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.3.1'
|
|
24001
|
+
};
|
|
24002
|
+
const ecgSopClassUids = Object.values(ECG_SOP_CLASS_UIDS);
|
|
24003
|
+
const DicomEcgSOPClassHandlerId = '@ohif/extension-cornerstone.sopClassHandlerModule.DicomEcgSopClassHandler';
|
|
24004
|
+
function _getEcgDisplaySetsFromSeries(instances, servicesManager) {
|
|
24005
|
+
const {
|
|
24006
|
+
userAuthenticationService
|
|
24007
|
+
} = servicesManager.services;
|
|
24008
|
+
return instances.map(instance => {
|
|
24009
|
+
const {
|
|
24010
|
+
Modality,
|
|
24011
|
+
SOPInstanceUID
|
|
24012
|
+
} = instance;
|
|
24013
|
+
const {
|
|
24014
|
+
SeriesDescription,
|
|
24015
|
+
SeriesNumber,
|
|
24016
|
+
SeriesDate
|
|
24017
|
+
} = instance;
|
|
24018
|
+
const {
|
|
24019
|
+
SeriesInstanceUID,
|
|
24020
|
+
StudyInstanceUID,
|
|
24021
|
+
SOPClassUID
|
|
24022
|
+
} = instance;
|
|
24023
|
+
const imageId = instance.imageId;
|
|
24024
|
+
|
|
24025
|
+
// Register ECG metadata in the OHIF metadata provider so that
|
|
24026
|
+
// Cornerstone's ECGViewport can retrieve it via metaData.get('ecgModule', imageId).
|
|
24027
|
+
if (imageId) {
|
|
24028
|
+
const ecgModule = buildEcgModule(instance, userAuthenticationService);
|
|
24029
|
+
if (ecgModule) {
|
|
24030
|
+
esm.utilities.genericMetadataProvider.addRaw(imageId, {
|
|
24031
|
+
type: MetadataModules.ECG,
|
|
24032
|
+
metadata: ecgModule
|
|
24033
|
+
});
|
|
24034
|
+
}
|
|
24035
|
+
}
|
|
24036
|
+
return {
|
|
24037
|
+
Modality,
|
|
24038
|
+
displaySetInstanceUID: getSopClassHandlerModule_utils.guid(),
|
|
24039
|
+
SeriesDescription,
|
|
24040
|
+
SeriesNumber,
|
|
24041
|
+
SeriesDate,
|
|
24042
|
+
SOPInstanceUID,
|
|
24043
|
+
SeriesInstanceUID,
|
|
24044
|
+
StudyInstanceUID,
|
|
24045
|
+
SOPClassHandlerId: DicomEcgSOPClassHandlerId,
|
|
24046
|
+
SOPClassUID,
|
|
24047
|
+
referencedImages: null,
|
|
24048
|
+
measurements: null,
|
|
24049
|
+
viewportType: esm.Enums.ViewportType.ECG,
|
|
24050
|
+
instances: [instance],
|
|
24051
|
+
instance,
|
|
24052
|
+
thumbnailSrc: null,
|
|
24053
|
+
isDerivedDisplaySet: false,
|
|
24054
|
+
isLoaded: false,
|
|
24055
|
+
sopClassUids: ecgSopClassUids,
|
|
24056
|
+
numImageFrames: 0,
|
|
24057
|
+
numInstances: 1,
|
|
24058
|
+
imageIds: imageId ? [imageId] : [],
|
|
24059
|
+
supportsWindowLevel: false,
|
|
24060
|
+
label: SeriesDescription || 'ECG'
|
|
24061
|
+
};
|
|
24062
|
+
});
|
|
24063
|
+
}
|
|
24064
|
+
function getDicomEcgSopClassHandler({
|
|
24065
|
+
servicesManager
|
|
24066
|
+
}) {
|
|
24067
|
+
const getDisplaySetsFromSeries = instances => _getEcgDisplaySetsFromSeries(instances, servicesManager);
|
|
24068
|
+
return {
|
|
24069
|
+
name: 'DicomEcgSopClassHandler',
|
|
24070
|
+
sopClassUids: ecgSopClassUids,
|
|
24071
|
+
getDisplaySetsFromSeries
|
|
24072
|
+
};
|
|
24073
|
+
}
|
|
23396
24074
|
function getSopClassHandlerModule(params) {
|
|
23397
|
-
return [getDicomMicroscopySopClassHandler(params)];
|
|
24075
|
+
return [getDicomMicroscopySopClassHandler(params), getDicomEcgSopClassHandler(params)];
|
|
23398
24076
|
}
|
|
23399
24077
|
// EXTERNAL MODULE: ../../../extensions/cornerstone/src/hooks/useActiveViewportSegmentationRepresentations.ts
|
|
23400
24078
|
var useActiveViewportSegmentationRepresentations = __webpack_require__(9234);
|
|
@@ -23424,7 +24102,7 @@ function SegmentationUtilityButton(props) {
|
|
|
23424
24102
|
isActive,
|
|
23425
24103
|
id
|
|
23426
24104
|
} = props;
|
|
23427
|
-
const activeSegmentationUtility = (0,default_src
|
|
24105
|
+
const activeSegmentationUtility = (0,default_src/* useUIStateStore */.FS)(store => store.uiState.activeSegmentationUtility);
|
|
23428
24106
|
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');
|
|
23429
24107
|
const handleMouseDownCapture = (0,react.useCallback)(event => {
|
|
23430
24108
|
if (activeSegmentationUtility === id) {
|
|
@@ -23555,7 +24233,7 @@ function PanelSegmentation({
|
|
|
23555
24233
|
segmentationsWithRepresentations,
|
|
23556
24234
|
disabled
|
|
23557
24235
|
} = (0,useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c)();
|
|
23558
|
-
const setUIState = (0,default_src
|
|
24236
|
+
const setUIState = (0,default_src/* useUIStateStore */.FS)(store => store.setUIState);
|
|
23559
24237
|
|
|
23560
24238
|
// useEffect for handling clicks on any of the non-active viewports.
|
|
23561
24239
|
// The ViewportGrid stops the propagation of pointer/mouse events
|
|
@@ -23816,7 +24494,7 @@ function PanelSegmentation({
|
|
|
23816
24494
|
IconContainer: components_SegmentationUtilityButton
|
|
23817
24495
|
}, /*#__PURE__*/react.createElement("div", {
|
|
23818
24496
|
className: "flex flex-wrap gap-[3px] bg-transparent pb-[2px] pl-[8px] pt-[6px]"
|
|
23819
|
-
}, /*#__PURE__*/react.createElement(default_src
|
|
24497
|
+
}, /*#__PURE__*/react.createElement(default_src/* Toolbar */.M7, {
|
|
23820
24498
|
buttonSection: buttonSection
|
|
23821
24499
|
})));
|
|
23822
24500
|
};
|
|
@@ -24343,12 +25021,12 @@ function DefaultAccordion(props) {
|
|
|
24343
25021
|
if (!allChildren || !groups) {
|
|
24344
25022
|
return null;
|
|
24345
25023
|
}
|
|
24346
|
-
if (
|
|
25024
|
+
if (asChild) {
|
|
24347
25025
|
return /*#__PURE__*/react.cloneElement(props.children, props);
|
|
24348
25026
|
}
|
|
24349
25027
|
return /*#__PURE__*/react.createElement(ui_next_src/* Accordion */.nD3, {
|
|
24350
25028
|
type: grouping.type || 'multiple',
|
|
24351
|
-
className: "text-
|
|
25029
|
+
className: "text-foreground",
|
|
24352
25030
|
defaultValue: defaultValue
|
|
24353
25031
|
}, [...groups.entries()].map(([key, group]) => {
|
|
24354
25032
|
return /*#__PURE__*/react.createElement(ui_next_src/* AccordionItem */.AsP, {
|
|
@@ -24826,7 +25504,7 @@ function PanelMeasurement(props) {
|
|
|
24826
25504
|
return EmptyComponent ? /*#__PURE__*/react.createElement(EmptyComponent, {
|
|
24827
25505
|
items: displayMeasurements
|
|
24828
25506
|
}) : /*#__PURE__*/react.createElement("span", {
|
|
24829
|
-
className: "text-
|
|
25507
|
+
className: "text-foreground"
|
|
24830
25508
|
}, "No Measurements");
|
|
24831
25509
|
}
|
|
24832
25510
|
if (children) {
|
|
@@ -24891,7 +25569,7 @@ const getPanelModule = ({
|
|
|
24891
25569
|
} = (0,es/* useTranslation */.Bd)('SegmentationPanel');
|
|
24892
25570
|
const tKey = `${props.segmentationRepresentationTypes?.[0] ?? 'Segmentation'} tools`;
|
|
24893
25571
|
const tValue = t(tKey);
|
|
24894
|
-
return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src
|
|
25572
|
+
return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src/* Toolbox */.OO, {
|
|
24895
25573
|
buttonSectionId: toolSectionMap[props.segmentationRepresentationTypes?.[0]],
|
|
24896
25574
|
title: tValue
|
|
24897
25575
|
}), /*#__PURE__*/react.createElement(PanelSegmentation, {
|
|
@@ -25245,7 +25923,7 @@ function promptHydrationDialog({
|
|
|
25245
25923
|
customizationService
|
|
25246
25924
|
} = servicesManager.services;
|
|
25247
25925
|
const extensionManager = servicesManager._extensionManager;
|
|
25248
|
-
const appConfig = extensionManager.
|
|
25926
|
+
const appConfig = extensionManager.appConfig;
|
|
25249
25927
|
|
|
25250
25928
|
// Todo: make this use enum from the extension, we should move the enum
|
|
25251
25929
|
const standardMode = appConfig?.measurementTrackingMode === 'standard';
|
|
@@ -25262,20 +25940,30 @@ function promptHydrationDialog({
|
|
|
25262
25940
|
if (type === HydrationType.SEG) {
|
|
25263
25941
|
// SEG needs setTimeout
|
|
25264
25942
|
window.setTimeout(async () => {
|
|
25265
|
-
|
|
25266
|
-
|
|
25267
|
-
|
|
25268
|
-
|
|
25269
|
-
|
|
25943
|
+
try {
|
|
25944
|
+
const isHydrated = await hydrateCallback({
|
|
25945
|
+
segDisplaySet: displaySet,
|
|
25946
|
+
viewportId
|
|
25947
|
+
});
|
|
25948
|
+
resolve(isHydrated);
|
|
25949
|
+
} catch (error) {
|
|
25950
|
+
reject(error);
|
|
25951
|
+
}
|
|
25270
25952
|
}, 0);
|
|
25271
25953
|
} else if (type === HydrationType.RTSTRUCT) {
|
|
25272
25954
|
// RT hydration
|
|
25273
|
-
|
|
25274
|
-
|
|
25275
|
-
|
|
25276
|
-
|
|
25277
|
-
|
|
25278
|
-
|
|
25955
|
+
window.setTimeout(async () => {
|
|
25956
|
+
try {
|
|
25957
|
+
const isHydrated = await hydrateCallback({
|
|
25958
|
+
rtDisplaySet: displaySet,
|
|
25959
|
+
viewportId,
|
|
25960
|
+
servicesManager
|
|
25961
|
+
});
|
|
25962
|
+
resolve(isHydrated);
|
|
25963
|
+
} catch (error) {
|
|
25964
|
+
reject(error);
|
|
25965
|
+
}
|
|
25966
|
+
}, 0);
|
|
25279
25967
|
} else if (type === HydrationType.SR) {
|
|
25280
25968
|
// SR has a different result structure
|
|
25281
25969
|
const hydrationResult = await hydrateCallback(displaySet);
|
|
@@ -25368,7 +26056,8 @@ const setUpSegmentationEventHandlers = ({
|
|
|
25368
26056
|
const {
|
|
25369
26057
|
segmentationService,
|
|
25370
26058
|
customizationService,
|
|
25371
|
-
displaySetService
|
|
26059
|
+
displaySetService,
|
|
26060
|
+
viewportGridService
|
|
25372
26061
|
} = servicesManager.services;
|
|
25373
26062
|
const {
|
|
25374
26063
|
unsubscribe: unsubscribeSegmentationDataModifiedHandler
|
|
@@ -25413,12 +26102,42 @@ const setUpSegmentationEventHandlers = ({
|
|
|
25413
26102
|
};
|
|
25414
26103
|
displaySetService.addDisplaySets(segmentationDisplaySet);
|
|
25415
26104
|
});
|
|
26105
|
+
const {
|
|
26106
|
+
unsubscribe: unsubscribeSegmentationRemoved
|
|
26107
|
+
} = segmentationService.subscribe(segmentationService.EVENTS.SEGMENTATION_REMOVED, ({
|
|
26108
|
+
segmentationId
|
|
26109
|
+
}) => {
|
|
26110
|
+
const displaySet = displaySetService.getDisplaySetByUID(segmentationId);
|
|
26111
|
+
|
|
26112
|
+
// Remove the display set layer from all viewports that have it
|
|
26113
|
+
if (displaySet) {
|
|
26114
|
+
const state = viewportGridService.getState();
|
|
26115
|
+
const viewports = state.viewports;
|
|
26116
|
+
|
|
26117
|
+
// Find all viewports that contain this segmentation's display set as a layer
|
|
26118
|
+
for (const [viewportId, viewport] of viewports.entries()) {
|
|
26119
|
+
const displaySetInstanceUIDs = viewport.displaySetInstanceUIDs || [];
|
|
26120
|
+
if (displaySetInstanceUIDs.includes(segmentationId)) {
|
|
26121
|
+
// Remove the display set layer from this viewport
|
|
26122
|
+
commandsManager.runCommand('removeDisplaySetLayer', {
|
|
26123
|
+
viewportId,
|
|
26124
|
+
displaySetInstanceUID: segmentationId
|
|
26125
|
+
});
|
|
26126
|
+
}
|
|
26127
|
+
}
|
|
26128
|
+
|
|
26129
|
+
// Delete the display set from the service if it was made in client
|
|
26130
|
+
if (displaySet.madeInClient) {
|
|
26131
|
+
displaySetService.deleteDisplaySet(segmentationId);
|
|
26132
|
+
}
|
|
26133
|
+
}
|
|
26134
|
+
});
|
|
25416
26135
|
const {
|
|
25417
26136
|
unsubscribeSelectedSegmentationsForViewportEvents
|
|
25418
26137
|
} = setUpSelectedSegmentationsForViewportHandler({
|
|
25419
26138
|
segmentationService
|
|
25420
26139
|
});
|
|
25421
|
-
const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, ...unsubscribeSelectedSegmentationsForViewportEvents];
|
|
26140
|
+
const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, unsubscribeSegmentationRemoved, ...unsubscribeSelectedSegmentationsForViewportEvents];
|
|
25422
26141
|
return {
|
|
25423
26142
|
unsubscriptions
|
|
25424
26143
|
};
|
|
@@ -25561,7 +26280,7 @@ function PanelAccordionTrigger(props) {
|
|
|
25561
26280
|
}, /*#__PURE__*/react.createElement("button", {
|
|
25562
26281
|
onClick: onClickDefault.bind(props)
|
|
25563
26282
|
}, /*#__PURE__*/react.createElement("span", {
|
|
25564
|
-
className: `inline-flex rounded-l border-r border-
|
|
26283
|
+
className: `inline-flex rounded-l border-r border-background ${isActive ? 'bg-highlight' : 'bg-muted'}`
|
|
25565
26284
|
}, count !== undefined ? /*#__PURE__*/react.createElement("span", {
|
|
25566
26285
|
className: "px-2"
|
|
25567
26286
|
}, count) : null, colorHex && /*#__PURE__*/react.createElement(ui_next_src/* ColorCircle */.cd8, {
|
|
@@ -25810,13 +26529,14 @@ function src_extends() { return src_extends = Object.assign ? Object.assign.bind
|
|
|
25810
26529
|
|
|
25811
26530
|
|
|
25812
26531
|
|
|
26532
|
+
|
|
25813
26533
|
|
|
25814
26534
|
|
|
25815
26535
|
const {
|
|
25816
26536
|
imageRetrieveMetadataProvider
|
|
25817
26537
|
} = esm.utilities;
|
|
25818
26538
|
const Component = /*#__PURE__*/react.lazy(() => {
|
|
25819
|
-
return __webpack_require__.e(/* import() */
|
|
26539
|
+
return __webpack_require__.e(/* import() */ 3754).then(__webpack_require__.bind(__webpack_require__, 33754));
|
|
25820
26540
|
});
|
|
25821
26541
|
const OHIFCornerstoneViewport = props => {
|
|
25822
26542
|
return /*#__PURE__*/react.createElement(react.Suspense, {
|
|
@@ -25909,9 +26629,10 @@ const cornerstoneExtension = {
|
|
|
25909
26629
|
useLutPresentationStore/* useLutPresentationStore */.I.getState().clearLutPresentationStore();
|
|
25910
26630
|
usePositionPresentationStore/* usePositionPresentationStore */.q.getState().clearPositionPresentationStore();
|
|
25911
26631
|
useSynchronizersStore/* useSynchronizersStore */.U.getState().clearSynchronizersStore();
|
|
25912
|
-
default_src
|
|
26632
|
+
default_src/* useToggleOneUpViewportGridStore */.Yd.getState().clearToggleOneUpViewportGridStore();
|
|
25913
26633
|
useSegmentationPresentationStore/* useSegmentationPresentationStore */.v.getState().clearSegmentationPresentationStore();
|
|
25914
26634
|
useSelectedSegmentationsForViewportStore.getState().clearSelectedSegmentationsForViewportStore();
|
|
26635
|
+
servicesManager.services.viewedDataService?.clearViewedData();
|
|
25915
26636
|
segmentationService.removeAllSegmentations();
|
|
25916
26637
|
},
|
|
25917
26638
|
/**
|
|
@@ -25929,6 +26650,7 @@ const cornerstoneExtension = {
|
|
|
25929
26650
|
servicesManager.registerService(services_SegmentationService.REGISTRATION);
|
|
25930
26651
|
servicesManager.registerService(services_CornerstoneCacheService.REGISTRATION);
|
|
25931
26652
|
servicesManager.registerService(services_ColorbarService.REGISTRATION);
|
|
26653
|
+
servicesManager.registerService(services_ViewedDataService.REGISTRATION);
|
|
25932
26654
|
const {
|
|
25933
26655
|
syncGroupService
|
|
25934
26656
|
} = servicesManager.services;
|
|
@@ -26000,10 +26722,10 @@ const cornerstoneExtension = {
|
|
|
26000
26722
|
|
|
26001
26723
|
/* harmony default export */ const cornerstone_src = (cornerstoneExtension);
|
|
26002
26724
|
|
|
26003
|
-
/***/ }
|
|
26725
|
+
/***/ },
|
|
26004
26726
|
|
|
26005
|
-
/***/ 71353
|
|
26006
|
-
|
|
26727
|
+
/***/ 71353
|
|
26728
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26007
26729
|
|
|
26008
26730
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
26009
26731
|
/* harmony export */ cL: () => (/* binding */ reset),
|
|
@@ -26042,10 +26764,10 @@ const reset = () => {
|
|
|
26042
26764
|
};
|
|
26043
26765
|
|
|
26044
26766
|
|
|
26045
|
-
/***/ }
|
|
26767
|
+
/***/ },
|
|
26046
26768
|
|
|
26047
|
-
/***/ 46026
|
|
26048
|
-
|
|
26769
|
+
/***/ 46026
|
|
26770
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26049
26771
|
|
|
26050
26772
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
26051
26773
|
/* harmony export */ FG: () => (/* binding */ JOIN_STR),
|
|
@@ -26085,10 +26807,10 @@ const addUniqueIndex = (arr, key, viewports, isUpdatingSameViewport) => {
|
|
|
26085
26807
|
};
|
|
26086
26808
|
|
|
26087
26809
|
|
|
26088
|
-
/***/ }
|
|
26810
|
+
/***/ },
|
|
26089
26811
|
|
|
26090
|
-
/***/ 10182
|
|
26091
|
-
|
|
26812
|
+
/***/ 10182
|
|
26813
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26092
26814
|
|
|
26093
26815
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
26094
26816
|
/* harmony export */ I: () => (/* binding */ useLutPresentationStore)
|
|
@@ -26200,10 +26922,10 @@ const useLutPresentationStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .creat
|
|
|
26200
26922
|
name: 'LutPresentationStore'
|
|
26201
26923
|
}) : createLutPresentationStore);
|
|
26202
26924
|
|
|
26203
|
-
/***/ }
|
|
26925
|
+
/***/ },
|
|
26204
26926
|
|
|
26205
|
-
/***/ 44646
|
|
26206
|
-
|
|
26927
|
+
/***/ 44646
|
|
26928
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26207
26929
|
|
|
26208
26930
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
26209
26931
|
/* harmony export */ q: () => (/* binding */ usePositionPresentationStore)
|
|
@@ -26311,10 +27033,10 @@ const usePositionPresentationStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .
|
|
|
26311
27033
|
name: 'PositionPresentationStore'
|
|
26312
27034
|
}) : createPositionPresentationStore);
|
|
26313
27035
|
|
|
26314
|
-
/***/ }
|
|
27036
|
+
/***/ },
|
|
26315
27037
|
|
|
26316
|
-
/***/ 2847
|
|
26317
|
-
|
|
27038
|
+
/***/ 2847
|
|
27039
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26318
27040
|
|
|
26319
27041
|
|
|
26320
27042
|
// EXPORTS
|
|
@@ -26426,20 +27148,34 @@ const _getSegmentationPresentationId = ({
|
|
|
26426
27148
|
if (!viewport?.viewportOptions || !viewport.displaySetInstanceUIDs?.length) {
|
|
26427
27149
|
return;
|
|
26428
27150
|
}
|
|
27151
|
+
const {
|
|
27152
|
+
displaySetService
|
|
27153
|
+
} = servicesManager.services;
|
|
26429
27154
|
const {
|
|
26430
27155
|
displaySetInstanceUIDs,
|
|
26431
27156
|
viewportOptions
|
|
26432
27157
|
} = viewport;
|
|
27158
|
+
|
|
27159
|
+
// Match keys used by updateStoredSegmentationPresentation (referenced volume only).
|
|
27160
|
+
// Including overlay UIDs (e.g. SEG) produced ids like "MR&SEG" while the store
|
|
27161
|
+
// entry is under "MR", so hydrated segmentations never applied and viewports could mis-render.
|
|
27162
|
+
const nonOverlayUIDs = displaySetInstanceUIDs.filter(uid => {
|
|
27163
|
+
const ds = displaySetService.getDisplaySetByUID(uid);
|
|
27164
|
+
return ds && !ds.isOverlayDisplaySet;
|
|
27165
|
+
});
|
|
27166
|
+
if (!nonOverlayUIDs.length) {
|
|
27167
|
+
return;
|
|
27168
|
+
}
|
|
26433
27169
|
let orientation = viewportOptions.orientation;
|
|
26434
27170
|
if (!orientation) {
|
|
26435
27171
|
// Calculate orientation from the viewport sample image
|
|
26436
|
-
const displaySet =
|
|
26437
|
-
const sampleImage = displaySet
|
|
27172
|
+
const displaySet = displaySetService.getDisplaySetByUID(nonOverlayUIDs[0]);
|
|
27173
|
+
const sampleImage = displaySet?.images?.[0];
|
|
26438
27174
|
const imageOrientationPatient = sampleImage?.ImageOrientationPatient;
|
|
26439
27175
|
orientation = getViewportOrientationFromImageOrientationPatient(imageOrientationPatient);
|
|
26440
27176
|
}
|
|
26441
27177
|
const segmentationPresentationArr = [];
|
|
26442
|
-
segmentationPresentationArr.push(...
|
|
27178
|
+
segmentationPresentationArr.push(...nonOverlayUIDs);
|
|
26443
27179
|
|
|
26444
27180
|
// Uncomment if unique indexing is needed
|
|
26445
27181
|
// addUniqueIndex(
|
|
@@ -26520,10 +27256,10 @@ const useSegmentationPresentationStore = (0,esm/* create */.vt)()(DEBUG_STORE ?
|
|
|
26520
27256
|
name: 'Segmentation Presentation Store'
|
|
26521
27257
|
}) : createSegmentationPresentationStore);
|
|
26522
27258
|
|
|
26523
|
-
/***/ }
|
|
27259
|
+
/***/ },
|
|
26524
27260
|
|
|
26525
|
-
/***/ 68578
|
|
26526
|
-
|
|
27261
|
+
/***/ 68578
|
|
27262
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26527
27263
|
|
|
26528
27264
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
26529
27265
|
/* harmony export */ U: () => (/* binding */ useSynchronizersStore)
|
|
@@ -26584,6 +27320,32 @@ const useSynchronizersStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .create
|
|
|
26584
27320
|
name: 'SynchronizersStore'
|
|
26585
27321
|
}) : createSynchronizersStore);
|
|
26586
27322
|
|
|
26587
|
-
/***/ }
|
|
27323
|
+
/***/ },
|
|
27324
|
+
|
|
27325
|
+
/***/ 67142
|
|
27326
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
27327
|
+
|
|
27328
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
27329
|
+
/* harmony export */ V: () => (/* binding */ getDataIdForViewport)
|
|
27330
|
+
/* harmony export */ });
|
|
27331
|
+
/**
|
|
27332
|
+
* Resolves the data ID (e.g. volumeId) for a viewport and display set.
|
|
27333
|
+
* For viewports with multiple volumes/actors, returns the id that matches the display set; otherwise undefined.
|
|
27334
|
+
* Use this to call viewport.getProperties(dataId) in a viewport-type-agnostic way.
|
|
27335
|
+
*
|
|
27336
|
+
* @param viewport - Viewport instance (stack, volume, or future types with optional getAllVolumeIds)
|
|
27337
|
+
* @param displaySetInstanceUID - Display set instance UID to match
|
|
27338
|
+
* @returns volumeId (or equivalent) for multi-actor viewports, undefined for single-actor
|
|
27339
|
+
*/
|
|
27340
|
+
function getDataIdForViewport(viewport, displaySetInstanceUID) {
|
|
27341
|
+
const vp = viewport;
|
|
27342
|
+
if (typeof vp.getAllVolumeIds !== 'function') {
|
|
27343
|
+
return undefined;
|
|
27344
|
+
}
|
|
27345
|
+
const volumeIds = vp.getAllVolumeIds() || [];
|
|
27346
|
+
return volumeIds.length > 0 ? volumeIds.find(id => id.includes(displaySetInstanceUID)) ?? undefined : undefined;
|
|
27347
|
+
}
|
|
27348
|
+
|
|
27349
|
+
/***/ }
|
|
26588
27350
|
|
|
26589
27351
|
}]);
|