@ohif/app 3.13.0-beta.8 → 3.13.0-beta.82
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.9fbac3c8e089c433777e.js → 1459.bundle.e7cfa1c06bc157e2c64a.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.7ae9ef1a7b5ed55d9550.js → 1933.bundle.ed916e36a22e150594b5.js} +32 -27
- package/dist/{2018.bundle.b8f9fe454ee996818531.js → 2018.bundle.b41b19f62647c65b2d9e.js} +18 -19
- package/dist/{6409.bundle.b36048896cb11c8571fb.js → 2075.bundle.ba9ac60662f1fa739378.js} +337 -261
- package/dist/{2108.bundle.e84aa8d858d8c4f2413e.js → 2108.bundle.aea8d3b39486dd5ab39e.js} +569 -558
- package/dist/{213.bundle.9cff7f3868971abefe05.js → 213.bundle.69683d18ac20f3324845.js} +3 -5
- package/dist/{2424.bundle.9c081095926163e359e0.js → 2424.bundle.2c29c4871b1c920c2c3c.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.a749686750f08e4adf93.js → 2851.bundle.1023a4363b4b9bc3a945.js} +484 -177
- package/dist/{1730.bundle.4f947de94428632e2499.js → 3138.bundle.5d0d632ccff4722d4398.js} +16 -310
- package/dist/{3461.bundle.8ce95fd079101d3e01b6.js → 3461.bundle.3d5e701f6b03df3c1a06.js} +131 -107
- package/dist/{147.bundle.37d627289453cb6c3937.js → 3754.bundle.d2435bb372912595708c.js} +486 -49
- package/dist/{4202.bundle.5a0f8e4004c5d8a68548.js → 4202.bundle.4fcd0de412907efd5b53.js} +6 -6
- package/dist/{4019.bundle.83a604779f7da0101ced.js → 4287.bundle.4f28e48c1e39a46dfc87.js} +352 -238
- package/dist/{5462.bundle.21beddaca145b7465c72.js → 4406.bundle.573d234b4641d23cf8db.js} +1083 -1308
- package/dist/{1403.bundle.f7392178d9262e1d99c2.js → 4507.bundle.ecfaa4ab17afa3d0c709.js} +10 -305
- package/dist/{6347.bundle.784c48912700f281de1d.js → 4579.bundle.1c315389368cc476aed3.js} +1439 -1879
- package/dist/{4819.bundle.c0b6dd8690d5755fde43.js → 4819.bundle.6a9bb28948e541d37fd5.js} +88 -53
- package/dist/{4775.bundle.5671e155db52c026a803.js → 5015.bundle.c5a7e45f949cd99d0f66.js} +29 -333
- package/dist/{5028.bundle.bc79f49125393ecc4f5f.js → 5028.bundle.739f91f1551cc7e33100.js} +11 -13
- package/dist/{5261.bundle.6e1a017f8f1027557f5b.js → 5261.bundle.2655560097e9250eac44.js} +412 -345
- package/dist/{5457.bundle.7720e5daa4e2bdff83ee.js → 5457.bundle.6ea5e826de729c202520.js} +16 -23
- package/dist/{5485.bundle.2c2a09db8c7a29258e9f.js → 5485.bundle.69f632603c550f76f519.js} +30 -36
- package/dist/{5491.bundle.2e01dd7ad29e4cc01bc1.js → 5491.bundle.4866d2ecb20dd089e071.js} +54 -51
- package/dist/{5802.bundle.3bf5e6b3ab330a594a47.js → 5802.bundle.cd36386cbe1613913ed4.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.49a5c78a49ed6cd15f72.js → 6027.bundle.12e74735b79df55bf1ef.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.dc7e3b159d6b4733647f.js} +913 -2290
- package/dist/6939.bundle.41fbdef87597b5172ec6.js +3 -3
- package/dist/{7159.bundle.a5991a5d4f0dd8f1c95f.js → 7159.bundle.fb9df255868960f69765.js} +7 -5
- package/dist/{3081.bundle.30cd450e2dd213b1b978.js → 7166.bundle.77012bc3ee99cd20787f.js} +1257 -467
- 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.a9b4dbf97a8c196efe51.js} +28 -28
- package/dist/{4410.bundle.c5224cd7d6238a7d4660.js → 7537.bundle.3c7d71348190ed4e9565.js} +5226 -2250
- package/dist/{7639.bundle.78e54c6f8dee95f4a6b7.js → 7639.bundle.bbbe6f05a1956e579cd7.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.d7423a538dca30c376ce.js → 8305.bundle.b8332f9c3bd96ba61085.js} +71 -66
- package/dist/{6163.bundle.ab7295912f610ef8b0eb.js → 8499.bundle.ac9af1089a32969e85cb.js} +7 -302
- package/dist/8499.css +2 -0
- package/dist/{85.bundle.0efe2e23b40b836a1fc1.js → 85.bundle.a2156faa09d13db19b44.js} +3 -5
- package/dist/{8558.bundle.53e0018bbb77300516b5.js → 8558.bundle.4008a0b4394aa8fbd0a0.js} +15 -309
- package/dist/{8583.bundle.4658de27c0d59037cc9b.js → 8583.bundle.555bfdada9e2fb8c240b.js} +24 -27
- package/dist/{997.bundle.822b33e561263084e18c.js → 9039.bundle.49ab126163ca208e52b3.js} +4091 -3016
- package/dist/{7412.bundle.fab1742191b7fe937330.js → 9205.bundle.c974537f15d86687f6d2.js} +6185 -3331
- 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.6d793a997f85d73002e9.js} +8 -6
- package/dist/{9927.bundle.34fec2c87a385cd104be.js → 9927.bundle.dff41e134390fc2121c0.js} +8 -6
- package/dist/app-config.js +12 -0
- package/dist/{app.bundle.43da7d5a1360d749cf34.js → app.bundle.a685f9eb4e80bae34996.js} +65881 -62856
- package/dist/app.bundle.css +3 -3
- package/dist/{polySeg.bundle.a5aa9130b4191253c410.js → compute.bundle.2b82d8a0d1f3b41df1d2.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.ad2080f28d2c471bf208.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) {
|
|
@@ -4034,10 +3973,10 @@ function getColumnValueReport(annotation, customizationService) {
|
|
|
4034
3973
|
} = annotation;
|
|
4035
3974
|
const stats = data.cachedStats[`imageId:${metadata.referencedImageId}`];
|
|
4036
3975
|
report.forEach(({
|
|
4037
|
-
|
|
3976
|
+
displayName,
|
|
4038
3977
|
value
|
|
4039
3978
|
}) => {
|
|
4040
|
-
columns.push(
|
|
3979
|
+
columns.push(displayName);
|
|
4041
3980
|
stats[value] ? values.push(stats[value]) : values.push('not available');
|
|
4042
3981
|
});
|
|
4043
3982
|
|
|
@@ -4504,10 +4443,10 @@ function SplineROI_getColumnValueReport(annotation, customizationService) {
|
|
|
4504
4443
|
} = annotation;
|
|
4505
4444
|
const stats = data.cachedStats[`imageId:${metadata.referencedImageId}`];
|
|
4506
4445
|
report.forEach(({
|
|
4507
|
-
|
|
4446
|
+
displayName,
|
|
4508
4447
|
value
|
|
4509
4448
|
}) => {
|
|
4510
|
-
columns.push(
|
|
4449
|
+
columns.push(displayName);
|
|
4511
4450
|
stats[value] ? values.push(stats[value]) : values.push('not available');
|
|
4512
4451
|
});
|
|
4513
4452
|
|
|
@@ -5699,6 +5638,9 @@ const {
|
|
|
5699
5638
|
removeAnnotation
|
|
5700
5639
|
} = dist_esm.annotation.state;
|
|
5701
5640
|
const csToolsEvents = dist_esm.Enums.Events;
|
|
5641
|
+
const {
|
|
5642
|
+
DefaultHistoryMemo
|
|
5643
|
+
} = esm.utilities.HistoryMemo;
|
|
5702
5644
|
const initMeasurementService = (measurementService, displaySetService, cornerstoneViewportService, customizationService) => {
|
|
5703
5645
|
/* Initialization */
|
|
5704
5646
|
const {
|
|
@@ -5902,7 +5844,8 @@ const connectMeasurementServiceToTools = ({
|
|
|
5902
5844
|
RAW_MEASUREMENT_ADDED
|
|
5903
5845
|
} = measurementService.EVENTS;
|
|
5904
5846
|
measurementService.subscribe(MEASUREMENTS_CLEARED, ({
|
|
5905
|
-
measurements
|
|
5847
|
+
measurements,
|
|
5848
|
+
trackingContext
|
|
5906
5849
|
}) => {
|
|
5907
5850
|
if (!Object.keys(measurements).length) {
|
|
5908
5851
|
return;
|
|
@@ -5926,6 +5869,28 @@ const connectMeasurementServiceToTools = ({
|
|
|
5926
5869
|
}
|
|
5927
5870
|
});
|
|
5928
5871
|
}
|
|
5872
|
+
|
|
5873
|
+
// If tracking context was provided, push a memo that keeps XState in sync with
|
|
5874
|
+
// Cornerstone's annotation history across unlimited undo/redo cycles:
|
|
5875
|
+
// undo → re-populate trackedStudy/trackedSeries so the panel reflects the
|
|
5876
|
+
// restored annotations.
|
|
5877
|
+
// redo → wipe trackedStudy/trackedSeries because the annotations have been
|
|
5878
|
+
// re-deleted by their own Cornerstone memos; no measurements are
|
|
5879
|
+
// deleted here (they are already gone), so CLEAR_TRACKING_CONTEXT is
|
|
5880
|
+
// used instead of UNTRACK_ALL to avoid a double-delete.
|
|
5881
|
+
if (trackingContext) {
|
|
5882
|
+
DefaultHistoryMemo.push({
|
|
5883
|
+
id: esm.utilities.uuidv4(),
|
|
5884
|
+
operationType: 'trackingState',
|
|
5885
|
+
restoreMemo(undo) {
|
|
5886
|
+
if (undo === true) {
|
|
5887
|
+
commandsManager.run('restoreTrackedSeries', trackingContext);
|
|
5888
|
+
} else if (undo === false) {
|
|
5889
|
+
commandsManager.run('clearTrackedSeries');
|
|
5890
|
+
}
|
|
5891
|
+
}
|
|
5892
|
+
});
|
|
5893
|
+
}
|
|
5929
5894
|
commandsManager.run('endRecordingForAnnotationGroup');
|
|
5930
5895
|
|
|
5931
5896
|
// trigger a render
|
|
@@ -6065,6 +6030,12 @@ const connectMeasurementServiceToTools = ({
|
|
|
6065
6030
|
if (source?.name && source.name !== initMeasurementService_CORNERSTONE_3D_TOOLS_SOURCE_NAME) {
|
|
6066
6031
|
return;
|
|
6067
6032
|
}
|
|
6033
|
+
// Cancel any active tool manipulation (e.g., Spline/Livewire) to avoid leaving the tool
|
|
6034
|
+
// in a drawing state after deleting a not completed measurement, which can block viewport interactivity.
|
|
6035
|
+
const element = getActiveViewportEnabledElement(viewportGridService)?.viewport?.element;
|
|
6036
|
+
if (element) {
|
|
6037
|
+
(0,dist_esm.cancelActiveManipulations)(element);
|
|
6038
|
+
}
|
|
6068
6039
|
const removedAnnotation = dist_esm.annotation.state.getAnnotation(removedMeasurementId);
|
|
6069
6040
|
removeAnnotation(removedMeasurementId);
|
|
6070
6041
|
// Ensure `removedAnnotation` is available before triggering the memo,
|
|
@@ -7241,10 +7212,6 @@ async function init({
|
|
|
7241
7212
|
hangingProtocolService.registerImageLoadStrategy(name, createMetadataWrappedStrategy(strategyFn));
|
|
7242
7213
|
});
|
|
7243
7214
|
|
|
7244
|
-
// add metadata providers
|
|
7245
|
-
esm.metaData.addProvider(esm.utilities.calibratedPixelSpacingMetadataProvider.get.bind(esm.utilities.calibratedPixelSpacingMetadataProvider)); // this provider is required for Calibration tool
|
|
7246
|
-
esm.metaData.addProvider(metadataProvider.get.bind(metadataProvider), 9999);
|
|
7247
|
-
|
|
7248
7215
|
// These are set reasonably low to allow for interleaved retrieves and slower
|
|
7249
7216
|
// connections.
|
|
7250
7217
|
esm.imageLoadPoolManager.maxNumRequests = {
|
|
@@ -7255,6 +7222,12 @@ async function init({
|
|
|
7255
7222
|
};
|
|
7256
7223
|
initWADOImageLoader(userAuthenticationService, appConfig, extensionManager);
|
|
7257
7224
|
|
|
7225
|
+
// Add OHIF metadata providers after dicomImageLoader.init().
|
|
7226
|
+
// The linked metadata branch clears providers during loader init.
|
|
7227
|
+
esm.metaData.addProvider(esm.utilities.genericMetadataProvider.get, 9998);
|
|
7228
|
+
esm.metaData.addProvider(esm.utilities.calibratedPixelSpacingMetadataProvider.get.bind(esm.utilities.calibratedPixelSpacingMetadataProvider)); // this provider is required for Calibration tool
|
|
7229
|
+
esm.metaData.addProvider(metadataProvider.get.bind(metadataProvider), 9999);
|
|
7230
|
+
|
|
7258
7231
|
/* Measurement Service */
|
|
7259
7232
|
this.measurementServiceSource = connectToolsToMeasurementService({
|
|
7260
7233
|
servicesManager,
|
|
@@ -7463,7 +7436,8 @@ function _showCPURenderingModal(uiModalService, hangingProtocolService) {
|
|
|
7463
7436
|
'viewportOverlay.topRight': [],
|
|
7464
7437
|
'viewportOverlay.bottomLeft': [{
|
|
7465
7438
|
id: 'WindowLevel',
|
|
7466
|
-
inheritsFrom: 'ohif.overlayItem.windowLevel'
|
|
7439
|
+
inheritsFrom: 'ohif.overlayItem.windowLevel',
|
|
7440
|
+
title: 'Window Level'
|
|
7467
7441
|
}, {
|
|
7468
7442
|
id: 'ZoomLevel',
|
|
7469
7443
|
inheritsFrom: 'ohif.overlayItem.zoomLevel',
|
|
@@ -7474,11 +7448,12 @@ function _showCPURenderingModal(uiModalService, hangingProtocolService) {
|
|
|
7474
7448
|
}],
|
|
7475
7449
|
'viewportOverlay.bottomRight': [{
|
|
7476
7450
|
id: 'InstanceNumber',
|
|
7477
|
-
inheritsFrom: 'ohif.overlayItem.instanceNumber'
|
|
7451
|
+
inheritsFrom: 'ohif.overlayItem.instanceNumber',
|
|
7452
|
+
title: 'Instance Number'
|
|
7478
7453
|
}]
|
|
7479
7454
|
});
|
|
7480
|
-
// EXTERNAL MODULE: ../../ui-next/src/index.ts +
|
|
7481
|
-
var ui_next_src = __webpack_require__(
|
|
7455
|
+
// EXTERNAL MODULE: ../../ui-next/src/index.ts + 3085 modules
|
|
7456
|
+
var ui_next_src = __webpack_require__(564);
|
|
7482
7457
|
// EXTERNAL MODULE: ../../../node_modules/react-i18next/dist/es/index.js + 15 modules
|
|
7483
7458
|
var es = __webpack_require__(99993);
|
|
7484
7459
|
;// ../../../extensions/cornerstone/src/components/ExportSegmentationSubMenuItem.tsx
|
|
@@ -7501,37 +7476,13 @@ const ExportSegmentationSubMenuItem = ({
|
|
|
7501
7476
|
className: "text-foreground"
|
|
7502
7477
|
}), /*#__PURE__*/react.createElement("span", {
|
|
7503
7478
|
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, {
|
|
7479
|
+
}, 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
7480
|
onClick: e => {
|
|
7512
7481
|
e.preventDefault();
|
|
7513
7482
|
actions.downloadCSVSegmentationReport(segmentationId);
|
|
7514
7483
|
},
|
|
7515
7484
|
disabled: !allowExport
|
|
7516
7485
|
}, 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
7486
|
onClick: e => {
|
|
7536
7487
|
e.preventDefault();
|
|
7537
7488
|
actions.storeSegmentation(segmentationId, 'SEG');
|
|
@@ -7608,16 +7559,6 @@ const CustomDropdownMenuContent = () => {
|
|
|
7608
7559
|
context: 'CORNERSTONE'
|
|
7609
7560
|
});
|
|
7610
7561
|
},
|
|
7611
|
-
onSegmentationDownloadRTSS: segmentationId => {
|
|
7612
|
-
commandsManager.run('downloadRTSS', {
|
|
7613
|
-
segmentationId
|
|
7614
|
-
});
|
|
7615
|
-
},
|
|
7616
|
-
onSegmentationDownload: segmentationId => {
|
|
7617
|
-
commandsManager.run('downloadSegmentation', {
|
|
7618
|
-
segmentationId
|
|
7619
|
-
});
|
|
7620
|
-
},
|
|
7621
7562
|
downloadCSVSegmentationReport: segmentationId => {
|
|
7622
7563
|
commandsManager.run('downloadCSVSegmentationReport', {
|
|
7623
7564
|
segmentationId
|
|
@@ -7815,7 +7756,7 @@ function SegmentationToolConfig() {
|
|
|
7815
7756
|
});
|
|
7816
7757
|
};
|
|
7817
7758
|
return /*#__PURE__*/react.createElement("div", {
|
|
7818
|
-
className: "bg-muted flex flex-col gap-2 border-b border-b-[2px] border-
|
|
7759
|
+
className: "bg-muted flex flex-col gap-2 border-b border-b-[2px] border-background px-2 py-3"
|
|
7819
7760
|
}, /*#__PURE__*/react.createElement("div", {
|
|
7820
7761
|
className: "flex items-center gap-2"
|
|
7821
7762
|
}, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
|
|
@@ -8624,7 +8565,7 @@ const DicomUploadProgressItem = /*#__PURE__*/(0,react.memo)(({
|
|
|
8624
8565
|
}, /*#__PURE__*/react.createElement("div", {
|
|
8625
8566
|
className: "flex w-6 shrink-0 items-center justify-center"
|
|
8626
8567
|
}, getStatusIcon()), /*#__PURE__*/react.createElement("div", {
|
|
8627
|
-
className: "overflow-hidden text-ellipsis whitespace-nowrap
|
|
8568
|
+
className: "text-foreground overflow-hidden text-ellipsis whitespace-nowrap"
|
|
8628
8569
|
}, dicomFileUploader.getFileName())), failedReason && /*#__PURE__*/react.createElement("div", {
|
|
8629
8570
|
className: "pl-10"
|
|
8630
8571
|
}, failedReason)), /*#__PURE__*/react.createElement("div", {
|
|
@@ -8866,7 +8807,7 @@ function DicomUploadProgress({
|
|
|
8866
8807
|
}, [numFilesCompleted]);
|
|
8867
8808
|
const getNumCompletedAndTimeRemainingComponent = () => {
|
|
8868
8809
|
return /*#__PURE__*/react.createElement("div", {
|
|
8869
|
-
className: "bg-muted flex h-14 items-center px-1 pb-4 text-lg
|
|
8810
|
+
className: "bg-muted text-foreground flex h-14 items-center px-1 pb-4 text-lg"
|
|
8870
8811
|
}, numFilesCompleted === dicomFileUploaderArr.length ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("span", {
|
|
8871
8812
|
className: NO_WRAP_ELLIPSIS_CLASS_NAMES
|
|
8872
8813
|
}, `${dicomFileUploaderArr.length} ${dicomFileUploaderArr.length > 1 ? 'files' : 'file'} completed.`), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
|
|
@@ -8916,7 +8857,7 @@ function DicomUploadProgress({
|
|
|
8916
8857
|
return /*#__PURE__*/react.createElement("div", {
|
|
8917
8858
|
className: "flex grow flex-col"
|
|
8918
8859
|
}, getNumCompletedAndTimeRemainingComponent(), /*#__PURE__*/react.createElement("div", {
|
|
8919
|
-
className: "flex grow flex-col overflow-hidden bg-
|
|
8860
|
+
className: "flex grow flex-col overflow-hidden bg-background text-lg"
|
|
8920
8861
|
}, getPercentCompleteComponent(), /*#__PURE__*/react.createElement("div", {
|
|
8921
8862
|
className: "ohif-scrollbar h-1 grow overflow-y-scroll px-2"
|
|
8922
8863
|
}, dicomFileUploaderArr.filter(dicomFileUploader => !showFailedOnly || dicomFileUploader.getStatus() === UploadStatus.Failed).map(dicomFileUploader => /*#__PURE__*/react.createElement(DicomUpload_DicomUploadProgressItem, {
|
|
@@ -8945,7 +8886,7 @@ function DicomUpload({
|
|
|
8945
8886
|
onComplete,
|
|
8946
8887
|
onStarted
|
|
8947
8888
|
}) {
|
|
8948
|
-
const baseClassNames = 'min-h-[375px] flex flex-col bg-
|
|
8889
|
+
const baseClassNames = 'min-h-[375px] flex flex-col bg-background select-none rounded-lg overflow-hidden';
|
|
8949
8890
|
const [dicomFileUploaderArr, setDicomFileUploaderArr] = (0,react.useState)([]);
|
|
8950
8891
|
const onDrop = (0,react.useCallback)(async acceptedFiles => {
|
|
8951
8892
|
onStarted();
|
|
@@ -9067,7 +9008,8 @@ function ViewportDownloadFormNew({
|
|
|
9067
9008
|
onDimensionsChange,
|
|
9068
9009
|
onEnableViewport,
|
|
9069
9010
|
onDisableViewport,
|
|
9070
|
-
onDownload
|
|
9011
|
+
onDownload,
|
|
9012
|
+
onCopyToClipboard
|
|
9071
9013
|
}) {
|
|
9072
9014
|
const [viewportElement, setViewportElement] = (0,react.useState)(null);
|
|
9073
9015
|
const [showWarningMessage, setShowWarningMessage] = (0,react.useState)(true);
|
|
@@ -9094,7 +9036,7 @@ function ViewportDownloadFormNew({
|
|
|
9094
9036
|
"data-viewport-uid": viewportId,
|
|
9095
9037
|
ref: setViewportElement
|
|
9096
9038
|
}, 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-
|
|
9039
|
+
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
9040
|
style: {
|
|
9099
9041
|
fontSize: '12px'
|
|
9100
9042
|
}
|
|
@@ -9140,12 +9082,23 @@ function ViewportDownloadFormNew({
|
|
|
9140
9082
|
className: "mt-2"
|
|
9141
9083
|
}, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Right, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Secondary, {
|
|
9142
9084
|
onClick: onClose
|
|
9143
|
-
}, t('Common:Cancel')), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.
|
|
9085
|
+
}, t('Common:Cancel')), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Secondary, {
|
|
9086
|
+
onClick: async () => {
|
|
9087
|
+
try {
|
|
9088
|
+
await onCopyToClipboard();
|
|
9089
|
+
ui_next_src/* toast */.oRP.success(t('Image copied to clipboard'));
|
|
9090
|
+
onClose();
|
|
9091
|
+
} catch (error) {
|
|
9092
|
+
ui_next_src/* toast */.oRP.error(t('Failed to copy image to clipboard'));
|
|
9093
|
+
console.error('Failed to copy to clipboard:', error);
|
|
9094
|
+
}
|
|
9095
|
+
}
|
|
9096
|
+
}, t('Copy to Clipboard')), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Primary, {
|
|
9144
9097
|
onClick: () => {
|
|
9145
9098
|
onDownload(filename || DEFAULT_FILENAME, fileType);
|
|
9146
9099
|
onClose();
|
|
9147
9100
|
}
|
|
9148
|
-
}, t('
|
|
9101
|
+
}, t('Save Image')))))));
|
|
9149
9102
|
}
|
|
9150
9103
|
/* harmony default export */ const captureViewportModalCustomization = ({
|
|
9151
9104
|
'ohif.captureViewportModal': ViewportDownloadFormNew
|
|
@@ -9157,6 +9110,34 @@ function ViewportDownloadFormNew({
|
|
|
9157
9110
|
value: 'Not For Diagnostic Use'
|
|
9158
9111
|
}
|
|
9159
9112
|
});
|
|
9113
|
+
;// ../../../extensions/cornerstone/src/customizations/viewportScrollbarCustomization.tsx
|
|
9114
|
+
/**
|
|
9115
|
+
* Default customization values for viewport scrollbar behavior.
|
|
9116
|
+
* The `progress` scrollbar variant is in full mode for stack viewports and
|
|
9117
|
+
* acquisition-plane orthographic viewports.
|
|
9118
|
+
* Otherwise, viewports using the `progress` scrollbar show only the indicator.
|
|
9119
|
+
*
|
|
9120
|
+
* - `viewportScrollbar.variant`: `'progress' | 'legacy'` (default: `'progress'`)
|
|
9121
|
+
* - `viewportScrollbar.showLoadedEndpoints`: show loaded-range endpoint caps in full mode
|
|
9122
|
+
* - `viewportScrollbar.showLoadedFill`: show loaded/cached fill in full mode
|
|
9123
|
+
* - `viewportScrollbar.showViewedFill`: show viewed fill in full mode
|
|
9124
|
+
* - `viewportScrollbar.showLoadingPattern`: show loading pattern in full mode while not fully loaded
|
|
9125
|
+
* - `viewportScrollbar.viewedDwellMs`: delay before marking current image viewed in full mode (ms)
|
|
9126
|
+
* - `viewportScrollbar.loadedBatchIntervalMs`: loaded-state version batch interval in full mode (ms)
|
|
9127
|
+
* - `viewportScrollbar.indicator`: optional custom indicator config
|
|
9128
|
+
*/
|
|
9129
|
+
function getViewportScrollbarCustomization() {
|
|
9130
|
+
return {
|
|
9131
|
+
'viewportScrollbar.variant': 'progress',
|
|
9132
|
+
'viewportScrollbar.showLoadedEndpoints': true,
|
|
9133
|
+
'viewportScrollbar.showLoadedFill': true,
|
|
9134
|
+
'viewportScrollbar.showViewedFill': true,
|
|
9135
|
+
'viewportScrollbar.showLoadingPattern': true,
|
|
9136
|
+
'viewportScrollbar.viewedDwellMs': 0,
|
|
9137
|
+
'viewportScrollbar.loadedBatchIntervalMs': 200,
|
|
9138
|
+
'viewportScrollbar.indicator': {}
|
|
9139
|
+
};
|
|
9140
|
+
}
|
|
9160
9141
|
;// ../../../extensions/cornerstone/src/getCustomizationModule.tsx
|
|
9161
9142
|
|
|
9162
9143
|
|
|
@@ -9171,6 +9152,7 @@ function ViewportDownloadFormNew({
|
|
|
9171
9152
|
|
|
9172
9153
|
|
|
9173
9154
|
|
|
9155
|
+
|
|
9174
9156
|
function getCustomizationModule({
|
|
9175
9157
|
commandsManager,
|
|
9176
9158
|
servicesManager,
|
|
@@ -9195,7 +9177,8 @@ function getCustomizationModule({
|
|
|
9195
9177
|
...windowLevelPresetsCustomization,
|
|
9196
9178
|
...miscCustomization,
|
|
9197
9179
|
...captureViewportModalCustomization,
|
|
9198
|
-
...viewportDownloadWarningCustomization
|
|
9180
|
+
...viewportDownloadWarningCustomization,
|
|
9181
|
+
...getViewportScrollbarCustomization()
|
|
9199
9182
|
}
|
|
9200
9183
|
}];
|
|
9201
9184
|
}
|
|
@@ -9563,17 +9546,39 @@ const CornerstoneViewportDownloadForm = ({
|
|
|
9563
9546
|
} = activeViewportEnabledElement;
|
|
9564
9547
|
const downloadViewport = renderingEngine.getViewport(VIEWPORT_ID);
|
|
9565
9548
|
try {
|
|
9549
|
+
// Capture current viewport state
|
|
9550
|
+
// - properties: VOI, colormap, interpolation, etc.
|
|
9551
|
+
// - viewPresentation: flip/rotate/zoom presentation state added for
|
|
9552
|
+
// saving flip and rotation for capture
|
|
9553
|
+
// - viewReference: image/volume reference
|
|
9554
|
+
const properties = viewport.getProperties();
|
|
9555
|
+
const viewPresentation = viewport.getViewPresentation?.();
|
|
9556
|
+
const viewRef = viewport.getViewReference?.();
|
|
9566
9557
|
if (downloadViewport instanceof esm.StackViewport) {
|
|
9567
9558
|
const imageId = viewport.getCurrentImageId();
|
|
9568
|
-
const properties = viewport.getProperties();
|
|
9569
9559
|
await downloadViewport.setStack([imageId]);
|
|
9570
|
-
downloadViewport.setProperties(properties);
|
|
9571
9560
|
} else if (downloadViewport instanceof esm.BaseVolumeViewport) {
|
|
9572
9561
|
const volumeIds = viewport.getAllVolumeIds();
|
|
9573
|
-
downloadViewport.setVolumes([{
|
|
9562
|
+
await downloadViewport.setVolumes([{
|
|
9574
9563
|
volumeId: volumeIds[0]
|
|
9575
9564
|
}]);
|
|
9576
9565
|
}
|
|
9566
|
+
|
|
9567
|
+
// Apply presentation state so captured image preserves flip/rotate
|
|
9568
|
+
if (viewPresentation && downloadViewport.setViewPresentation) {
|
|
9569
|
+
downloadViewport.setViewPresentation(viewPresentation);
|
|
9570
|
+
}
|
|
9571
|
+
|
|
9572
|
+
// Apply viewport display properties
|
|
9573
|
+
downloadViewport.setProperties(properties);
|
|
9574
|
+
|
|
9575
|
+
// Ensure correct image/volume reference
|
|
9576
|
+
if (viewRef && downloadViewport.setViewReference) {
|
|
9577
|
+
downloadViewport.setViewReference(viewRef);
|
|
9578
|
+
}
|
|
9579
|
+
downloadViewport.render();
|
|
9580
|
+
|
|
9581
|
+
// Re-apply segmentation overlays to the download viewport
|
|
9577
9582
|
if (segmentationRepresentations?.length) {
|
|
9578
9583
|
segmentationRepresentations.forEach(segRepresentation => {
|
|
9579
9584
|
const {
|
|
@@ -9667,6 +9672,36 @@ const CornerstoneViewportDownloadForm = ({
|
|
|
9667
9672
|
filename
|
|
9668
9673
|
});
|
|
9669
9674
|
};
|
|
9675
|
+
const handleCopyToClipboard = async () => {
|
|
9676
|
+
const divForDownloadViewport = document.querySelector(`div[data-viewport-uid="${VIEWPORT_ID}"]`);
|
|
9677
|
+
if (!divForDownloadViewport) {
|
|
9678
|
+
console.debug('No viewport found for copy');
|
|
9679
|
+
return;
|
|
9680
|
+
}
|
|
9681
|
+
try {
|
|
9682
|
+
const canvas = await (0,html2canvas_esm/* default */.A)(divForDownloadViewport);
|
|
9683
|
+
|
|
9684
|
+
// Clipboard API only supports PNG format in most browsers
|
|
9685
|
+
const blob = await new Promise((resolve, reject) => {
|
|
9686
|
+
canvas.toBlob(blob => {
|
|
9687
|
+
if (blob) {
|
|
9688
|
+
resolve(blob);
|
|
9689
|
+
} else {
|
|
9690
|
+
reject(new Error('Failed to create blob from canvas'));
|
|
9691
|
+
}
|
|
9692
|
+
}, 'image/png', 1.0);
|
|
9693
|
+
});
|
|
9694
|
+
|
|
9695
|
+
// Copy to clipboard using the Clipboard API
|
|
9696
|
+
await navigator.clipboard.write([new ClipboardItem({
|
|
9697
|
+
'image/png': blob
|
|
9698
|
+
})]);
|
|
9699
|
+
console.log('Image copied to clipboard successfully');
|
|
9700
|
+
} catch (error) {
|
|
9701
|
+
console.error('Failed to copy image to clipboard:', error);
|
|
9702
|
+
throw error;
|
|
9703
|
+
}
|
|
9704
|
+
};
|
|
9670
9705
|
const ViewportDownloadFormNew = customizationService.getCustomization('ohif.captureViewportModal');
|
|
9671
9706
|
return /*#__PURE__*/react.createElement(ViewportDownloadFormNew, {
|
|
9672
9707
|
onClose: hide,
|
|
@@ -9680,6 +9715,7 @@ const CornerstoneViewportDownloadForm = ({
|
|
|
9680
9715
|
onEnableViewport: handleEnableViewport,
|
|
9681
9716
|
onDisableViewport: handleDisableViewport,
|
|
9682
9717
|
onDownload: handleDownload,
|
|
9718
|
+
onCopyToClipboard: handleCopyToClipboard,
|
|
9683
9719
|
warningState: warningState
|
|
9684
9720
|
});
|
|
9685
9721
|
};
|
|
@@ -9942,6 +9978,51 @@ function generateSegmentationCSVReport(segmentationData, info) {
|
|
|
9942
9978
|
});
|
|
9943
9979
|
}
|
|
9944
9980
|
;// ../../../extensions/cornerstone/src/utils/hydrationUtils.ts
|
|
9981
|
+
/**
|
|
9982
|
+
* After SEG hydration we must refresh every viewport that shows the referenced volume so
|
|
9983
|
+
* presentations (including segmentation) apply to all MPR/3D tiles. Hanging-protocol matching
|
|
9984
|
+
* can return only the active viewport when protocol definitions omit viewportId (e.g. 3D four-up)
|
|
9985
|
+
* or when layout state diverges from the protocol; this merges in all grid panes that already
|
|
9986
|
+
* list that volume in `displaySetInstanceUIDs`.
|
|
9987
|
+
*
|
|
9988
|
+
* Only exact displaySetInstanceUID matches are used (no Frame-of-Reference inference): sibling
|
|
9989
|
+
* MPR planes must already share the same referenced volume UID in grid state, or HP matching
|
|
9990
|
+
* must list them; otherwise forcing a different UID onto a volume viewport can leave it blank.
|
|
9991
|
+
*/
|
|
9992
|
+
function mergeVolumeSharingViewports(hangingProtocolUpdates, volumeUid, viewports) {
|
|
9993
|
+
if (!volumeUid) {
|
|
9994
|
+
return hangingProtocolUpdates ?? [];
|
|
9995
|
+
}
|
|
9996
|
+
const byId = new Map();
|
|
9997
|
+
const add = (viewportId, uids) => {
|
|
9998
|
+
if (!viewportId) {
|
|
9999
|
+
return;
|
|
10000
|
+
}
|
|
10001
|
+
byId.set(viewportId, {
|
|
10002
|
+
viewportId,
|
|
10003
|
+
displaySetInstanceUIDs: uids
|
|
10004
|
+
});
|
|
10005
|
+
};
|
|
10006
|
+
if (Array.isArray(hangingProtocolUpdates)) {
|
|
10007
|
+
for (const entry of hangingProtocolUpdates) {
|
|
10008
|
+
const vid = entry.viewportId ?? entry.viewportOptions?.viewportId;
|
|
10009
|
+
if (vid) {
|
|
10010
|
+
add(vid, entry.displaySetInstanceUIDs?.length ? entry.displaySetInstanceUIDs : [volumeUid]);
|
|
10011
|
+
}
|
|
10012
|
+
}
|
|
10013
|
+
}
|
|
10014
|
+
viewports.forEach(vp => {
|
|
10015
|
+
const uids = vp.displaySetInstanceUIDs || [];
|
|
10016
|
+
if (uids.includes(volumeUid)) {
|
|
10017
|
+
add(vp.viewportId, [volumeUid]);
|
|
10018
|
+
}
|
|
10019
|
+
});
|
|
10020
|
+
const merged = Array.from(byId.values());
|
|
10021
|
+
if (merged.length === 0 && Array.isArray(hangingProtocolUpdates) && hangingProtocolUpdates.length > 0) {
|
|
10022
|
+
return hangingProtocolUpdates;
|
|
10023
|
+
}
|
|
10024
|
+
return merged;
|
|
10025
|
+
}
|
|
9945
10026
|
function getUpdatedViewportsForSegmentation({
|
|
9946
10027
|
viewportId,
|
|
9947
10028
|
servicesManager,
|
|
@@ -9952,7 +10033,8 @@ function getUpdatedViewportsForSegmentation({
|
|
|
9952
10033
|
viewportGridService
|
|
9953
10034
|
} = servicesManager.services;
|
|
9954
10035
|
const {
|
|
9955
|
-
isHangingProtocolLayout
|
|
10036
|
+
isHangingProtocolLayout,
|
|
10037
|
+
viewports
|
|
9956
10038
|
} = viewportGridService.getState();
|
|
9957
10039
|
const viewport = getTargetViewport({
|
|
9958
10040
|
viewportId,
|
|
@@ -9960,7 +10042,10 @@ function getUpdatedViewportsForSegmentation({
|
|
|
9960
10042
|
});
|
|
9961
10043
|
const targetViewportId = viewport.viewportOptions.viewportId;
|
|
9962
10044
|
const updatedViewports = hangingProtocolService.getViewportsRequireUpdate(targetViewportId, displaySetInstanceUIDs[0], isHangingProtocolLayout);
|
|
9963
|
-
|
|
10045
|
+
if (updatedViewports == null || !isHangingProtocolLayout) {
|
|
10046
|
+
return updatedViewports;
|
|
10047
|
+
}
|
|
10048
|
+
return mergeVolumeSharingViewports(updatedViewports, displaySetInstanceUIDs[0], viewports);
|
|
9964
10049
|
}
|
|
9965
10050
|
const getTargetViewport = ({
|
|
9966
10051
|
viewportId,
|
|
@@ -10437,7 +10522,7 @@ const {
|
|
|
10437
10522
|
copy
|
|
10438
10523
|
} = dist_esm.utilities.contourSegmentation;
|
|
10439
10524
|
const {
|
|
10440
|
-
DefaultHistoryMemo
|
|
10525
|
+
DefaultHistoryMemo: commandsModule_DefaultHistoryMemo
|
|
10441
10526
|
} = esm.utilities.HistoryMemo;
|
|
10442
10527
|
const toggleSyncFunctions = {
|
|
10443
10528
|
imageSlice: toggleImageSliceSync,
|
|
@@ -10520,7 +10605,14 @@ function commandsModule({
|
|
|
10520
10605
|
}
|
|
10521
10606
|
function _getActiveViewportToolGroupId() {
|
|
10522
10607
|
const viewport = _getActiveViewportEnabledElement();
|
|
10523
|
-
|
|
10608
|
+
const toolGroup = viewport && toolGroupService.getToolGroupForViewport(viewport.id);
|
|
10609
|
+
return toolGroup?.id;
|
|
10610
|
+
}
|
|
10611
|
+
function _usesPrimaryActivation(bindings) {
|
|
10612
|
+
if (!bindings?.length) {
|
|
10613
|
+
return true;
|
|
10614
|
+
}
|
|
10615
|
+
return bindings.some(binding => binding.mouseButton === dist_esm.Enums.MouseBindings.Primary && binding.modifierKey == null && binding.numTouchPoints == null);
|
|
10524
10616
|
}
|
|
10525
10617
|
function _getActiveSegmentationInfo() {
|
|
10526
10618
|
const viewportId = viewportGridService.getActiveViewportId();
|
|
@@ -10756,11 +10848,26 @@ function commandsModule({
|
|
|
10756
10848
|
segmentIndex: targetIndex
|
|
10757
10849
|
} = targetSegmentation;
|
|
10758
10850
|
|
|
10851
|
+
// Check if the segment has voxels before computing bidirectional measurement
|
|
10852
|
+
const uniqueSegmentIndices = dist_esm.utilities.segmentation.getUniqueSegmentIndices(targetId);
|
|
10853
|
+
const hasVoxels = uniqueSegmentIndices.includes(targetIndex);
|
|
10854
|
+
if (!hasVoxels) {
|
|
10855
|
+
uiNotificationService.show({
|
|
10856
|
+
title: i18n_src/* default */.A.t('SegmentationPanel:Segment Bidirectional'),
|
|
10857
|
+
message: i18n_src/* default */.A.t('SegmentationPanel:Draw a segment before using bidirectional measurement'),
|
|
10858
|
+
type: 'warning'
|
|
10859
|
+
});
|
|
10860
|
+
return;
|
|
10861
|
+
}
|
|
10862
|
+
|
|
10759
10863
|
// Get bidirectional measurement data
|
|
10760
10864
|
const bidirectionalData = await dist_esm.utilities.segmentation.getSegmentLargestBidirectional({
|
|
10761
10865
|
segmentationId: targetId,
|
|
10762
10866
|
segmentIndices: [targetIndex]
|
|
10763
10867
|
});
|
|
10868
|
+
if (!bidirectionalData.length) {
|
|
10869
|
+
return;
|
|
10870
|
+
}
|
|
10764
10871
|
const activeViewportId = viewportGridService.getActiveViewportId();
|
|
10765
10872
|
|
|
10766
10873
|
// Process each bidirectional measurement
|
|
@@ -10799,7 +10906,7 @@ function commandsModule({
|
|
|
10799
10906
|
// get the active segmentIndex bidirectional annotation and jump to it
|
|
10800
10907
|
const activeBidirectional = bidirectionalData.find(measurement => measurement.segmentIndex === targetIndex);
|
|
10801
10908
|
commandsManager.run('jumpToMeasurement', {
|
|
10802
|
-
uid: activeBidirectional
|
|
10909
|
+
uid: activeBidirectional?.annotationUID
|
|
10803
10910
|
});
|
|
10804
10911
|
},
|
|
10805
10912
|
interpolateLabelmap: () => {
|
|
@@ -10962,7 +11069,7 @@ function commandsModule({
|
|
|
10962
11069
|
return;
|
|
10963
11070
|
}
|
|
10964
11071
|
if (!labelConfig) {
|
|
10965
|
-
const label = await (0,default_src
|
|
11072
|
+
const label = await (0,default_src/* callInputDialog */.l5)({
|
|
10966
11073
|
uiDialogService,
|
|
10967
11074
|
title: i18n_src/* default */.A.t('Tools:Edit Measurement Label'),
|
|
10968
11075
|
placeholder: measurement.label || i18n_src/* default */.A.t('Tools:Enter new label'),
|
|
@@ -10976,7 +11083,7 @@ function commandsModule({
|
|
|
10976
11083
|
}
|
|
10977
11084
|
return;
|
|
10978
11085
|
}
|
|
10979
|
-
const val = await (0,default_src
|
|
11086
|
+
const val = await (0,default_src/* callInputDialogAutoComplete */.fq)({
|
|
10980
11087
|
measurement,
|
|
10981
11088
|
uiDialogService,
|
|
10982
11089
|
labelConfig,
|
|
@@ -11099,6 +11206,9 @@ function commandsModule({
|
|
|
11099
11206
|
uid,
|
|
11100
11207
|
displayMeasurements = []
|
|
11101
11208
|
}) => {
|
|
11209
|
+
if (!uid) {
|
|
11210
|
+
return;
|
|
11211
|
+
}
|
|
11102
11212
|
measurementService.jumpToMeasurement(viewportGridService.getActiveViewportId(), uid);
|
|
11103
11213
|
for (const measurement of displayMeasurements) {
|
|
11104
11214
|
measurement.isActive = measurement.uid === uid;
|
|
@@ -11196,7 +11306,7 @@ function commandsModule({
|
|
|
11196
11306
|
const labelConfig = customizationService.getCustomization('measurementLabels');
|
|
11197
11307
|
const renderContent = customizationService.getCustomization('ui.labellingComponent');
|
|
11198
11308
|
if (!labelConfig) {
|
|
11199
|
-
const label = await (0,default_src
|
|
11309
|
+
const label = await (0,default_src/* callInputDialog */.l5)({
|
|
11200
11310
|
uiDialogService,
|
|
11201
11311
|
title: i18n_src/* default */.A.t('Tools:Edit Arrow Text'),
|
|
11202
11312
|
placeholder: data?.data?.label || i18n_src/* default */.A.t('Tools:Enter new text'),
|
|
@@ -11205,7 +11315,7 @@ function commandsModule({
|
|
|
11205
11315
|
callback?.(label);
|
|
11206
11316
|
return;
|
|
11207
11317
|
}
|
|
11208
|
-
const value = await (0,default_src
|
|
11318
|
+
const value = await (0,default_src/* callInputDialogAutoComplete */.fq)({
|
|
11209
11319
|
uiDialogService,
|
|
11210
11320
|
labelConfig,
|
|
11211
11321
|
renderContent
|
|
@@ -11369,31 +11479,46 @@ function commandsModule({
|
|
|
11369
11479
|
toggleActiveDisabledToolbar({
|
|
11370
11480
|
value,
|
|
11371
11481
|
itemId,
|
|
11372
|
-
toolGroupId
|
|
11482
|
+
toolGroupId,
|
|
11483
|
+
toolGroupIds
|
|
11373
11484
|
}) {
|
|
11374
11485
|
const toolName = itemId || value;
|
|
11375
|
-
|
|
11376
|
-
|
|
11377
|
-
|
|
11378
|
-
|
|
11379
|
-
|
|
11380
|
-
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
|
|
11486
|
+
const resolvedToolGroupIds = toolGroupIds?.length ? toolGroupIds : [toolGroupId ?? _getActiveViewportToolGroupId()];
|
|
11487
|
+
resolvedToolGroupIds.forEach(toolGroupId => {
|
|
11488
|
+
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
|
|
11489
|
+
if (!toolGroup || !toolGroup.hasTool(toolName)) {
|
|
11490
|
+
return;
|
|
11491
|
+
}
|
|
11492
|
+
const toolIsActive = [dist_esm.Enums.ToolModes.Active, dist_esm.Enums.ToolModes.Enabled, dist_esm.Enums.ToolModes.Passive].includes(toolGroup.getToolOptions(toolName).mode);
|
|
11493
|
+
if (toolIsActive) {
|
|
11494
|
+
toolGroup.setToolDisabled(toolName);
|
|
11495
|
+
const bindings = toolGroupService.getToolBindings(toolGroupId, toolName);
|
|
11496
|
+
if (_usesPrimaryActivation(bindings)) {
|
|
11497
|
+
// we should set the previously active tool to active after we set the
|
|
11498
|
+
// current tool disabled
|
|
11499
|
+
const prevToolName = toolGroup.getPrevActivePrimaryToolName();
|
|
11500
|
+
if (prevToolName !== toolName) {
|
|
11501
|
+
actions.setToolActive({
|
|
11502
|
+
toolName: prevToolName,
|
|
11503
|
+
toolGroupId
|
|
11504
|
+
});
|
|
11505
|
+
}
|
|
11506
|
+
}
|
|
11507
|
+
return;
|
|
11508
|
+
}
|
|
11509
|
+
const bindings = toolGroupService.getToolBindings(toolGroupId, toolName);
|
|
11510
|
+
if (_usesPrimaryActivation(bindings)) {
|
|
11391
11511
|
actions.setToolActive({
|
|
11392
|
-
toolName
|
|
11393
|
-
toolGroupId
|
|
11512
|
+
toolName,
|
|
11513
|
+
toolGroupId,
|
|
11514
|
+
bindings
|
|
11515
|
+
});
|
|
11516
|
+
} else {
|
|
11517
|
+
toolGroup.setToolActive(toolName, {
|
|
11518
|
+
bindings
|
|
11394
11519
|
});
|
|
11395
11520
|
}
|
|
11396
|
-
}
|
|
11521
|
+
});
|
|
11397
11522
|
},
|
|
11398
11523
|
setToolActiveToolbar: ({
|
|
11399
11524
|
value,
|
|
@@ -12101,7 +12226,7 @@ function commandsModule({
|
|
|
12101
12226
|
segmentationService,
|
|
12102
12227
|
viewportGridService
|
|
12103
12228
|
} = servicesManager.services;
|
|
12104
|
-
const displaySetInstanceUIDs = await (0,default_src
|
|
12229
|
+
const displaySetInstanceUIDs = await (0,default_src/* createReportAsync */.Vy)({
|
|
12105
12230
|
servicesManager,
|
|
12106
12231
|
getReport: () => commandsManager.runCommand('storeSegmentation', args),
|
|
12107
12232
|
reportType: 'Segmentation'
|
|
@@ -12178,14 +12303,15 @@ function commandsModule({
|
|
|
12178
12303
|
* @param props.segmentationId - The ID of the segmentation to remove
|
|
12179
12304
|
*/
|
|
12180
12305
|
removeSegmentationFromViewportCommand: ({
|
|
12181
|
-
segmentationId
|
|
12306
|
+
segmentationId: displaySetInstanceUID
|
|
12182
12307
|
}) => {
|
|
12183
12308
|
const {
|
|
12184
|
-
segmentationService,
|
|
12185
12309
|
viewportGridService
|
|
12186
12310
|
} = servicesManager.services;
|
|
12187
|
-
|
|
12188
|
-
|
|
12311
|
+
const viewportId = viewportGridService.getActiveViewportId();
|
|
12312
|
+
commandsManager.runCommand('removeDisplaySetLayer', {
|
|
12313
|
+
viewportId,
|
|
12314
|
+
displaySetInstanceUID
|
|
12189
12315
|
});
|
|
12190
12316
|
},
|
|
12191
12317
|
/**
|
|
@@ -12213,7 +12339,7 @@ function commandsModule({
|
|
|
12213
12339
|
return;
|
|
12214
12340
|
}
|
|
12215
12341
|
const segment = segmentation.segments[segmentIndex];
|
|
12216
|
-
(0,default_src
|
|
12342
|
+
(0,default_src/* callInputDialog */.l5)({
|
|
12217
12343
|
uiDialogService,
|
|
12218
12344
|
title: i18n_src/* default */.A.t('Tools:Edit Segment Label'),
|
|
12219
12345
|
placeholder: i18n_src/* default */.A.t('Tools:Enter new label'),
|
|
@@ -12236,7 +12362,7 @@ function commandsModule({
|
|
|
12236
12362
|
const {
|
|
12237
12363
|
label
|
|
12238
12364
|
} = segmentation;
|
|
12239
|
-
(0,default_src
|
|
12365
|
+
(0,default_src/* callInputDialog */.l5)({
|
|
12240
12366
|
uiDialogService,
|
|
12241
12367
|
title: i18n_src/* default */.A.t('Tools:Edit Segmentation Label'),
|
|
12242
12368
|
placeholder: i18n_src/* default */.A.t('Tools:Enter new label'),
|
|
@@ -12266,7 +12392,7 @@ function commandsModule({
|
|
|
12266
12392
|
a: color[3] / 255.0
|
|
12267
12393
|
};
|
|
12268
12394
|
uiDialogService.show({
|
|
12269
|
-
content: default_src
|
|
12395
|
+
content: default_src/* colorPickerDialog */.wS,
|
|
12270
12396
|
title: i18n_src/* default */.A.t('Tools:Segment Color'),
|
|
12271
12397
|
contentProps: {
|
|
12272
12398
|
value: rgbaColor,
|
|
@@ -12311,10 +12437,10 @@ function commandsModule({
|
|
|
12311
12437
|
viewportGridService.setDisplaySetsForViewports(viewportsToUpdate);
|
|
12312
12438
|
},
|
|
12313
12439
|
undo: () => {
|
|
12314
|
-
|
|
12440
|
+
commandsModule_DefaultHistoryMemo.undo();
|
|
12315
12441
|
},
|
|
12316
12442
|
redo: () => {
|
|
12317
|
-
|
|
12443
|
+
commandsModule_DefaultHistoryMemo.redo();
|
|
12318
12444
|
},
|
|
12319
12445
|
toggleSegmentPreviewEdit: ({
|
|
12320
12446
|
toggle
|
|
@@ -12545,6 +12671,15 @@ function commandsModule({
|
|
|
12545
12671
|
servicesManager,
|
|
12546
12672
|
displaySetInstanceUIDs
|
|
12547
12673
|
});
|
|
12674
|
+
if (!updatedViewports?.length) {
|
|
12675
|
+
return;
|
|
12676
|
+
}
|
|
12677
|
+
updatedViewports.forEach(({
|
|
12678
|
+
viewportId: csViewportId
|
|
12679
|
+
}) => {
|
|
12680
|
+
const csViewport = cornerstoneViewportService.getCornerstoneViewport(csViewportId);
|
|
12681
|
+
csViewport?.setNeedsRender?.();
|
|
12682
|
+
});
|
|
12548
12683
|
actions.setDisplaySetsForViewports({
|
|
12549
12684
|
viewportsToUpdate: updatedViewports.map(viewport => ({
|
|
12550
12685
|
viewportId: viewport.viewportId,
|
|
@@ -13256,6 +13391,29 @@ const HYDRATE_SEG_SYNC_GROUP = {
|
|
|
13256
13391
|
matchingRules: ['sameFOR']
|
|
13257
13392
|
}
|
|
13258
13393
|
};
|
|
13394
|
+
const viewportStructure = {
|
|
13395
|
+
layoutType: 'grid',
|
|
13396
|
+
properties: {
|
|
13397
|
+
rows: 1,
|
|
13398
|
+
columns: 3,
|
|
13399
|
+
layoutOptions: [{
|
|
13400
|
+
x: 0,
|
|
13401
|
+
y: 0,
|
|
13402
|
+
width: 1 / 3,
|
|
13403
|
+
height: 1
|
|
13404
|
+
}, {
|
|
13405
|
+
x: 1 / 3,
|
|
13406
|
+
y: 0,
|
|
13407
|
+
width: 1 / 3,
|
|
13408
|
+
height: 1
|
|
13409
|
+
}, {
|
|
13410
|
+
x: 2 / 3,
|
|
13411
|
+
y: 0,
|
|
13412
|
+
width: 1 / 3,
|
|
13413
|
+
height: 1
|
|
13414
|
+
}]
|
|
13415
|
+
}
|
|
13416
|
+
};
|
|
13259
13417
|
const mpr = {
|
|
13260
13418
|
id: 'mpr',
|
|
13261
13419
|
name: i18next/* default */.A.t('Hps:MPR'),
|
|
@@ -13286,29 +13444,7 @@ const mpr = {
|
|
|
13286
13444
|
},
|
|
13287
13445
|
stages: [{
|
|
13288
13446
|
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
|
-
},
|
|
13447
|
+
viewportStructure,
|
|
13312
13448
|
viewports: [{
|
|
13313
13449
|
viewportOptions: {
|
|
13314
13450
|
viewportId: 'mpr-axial',
|
|
@@ -13352,21 +13488,67 @@ const mpr = {
|
|
|
13352
13488
|
id: 'activeDisplaySet'
|
|
13353
13489
|
}]
|
|
13354
13490
|
}]
|
|
13355
|
-
}
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
|
|
13491
|
+
}, {
|
|
13492
|
+
name: 'MPR Reformat 1x3',
|
|
13493
|
+
viewportStructure,
|
|
13494
|
+
viewports: [{
|
|
13495
|
+
viewportOptions: {
|
|
13496
|
+
viewportId: 'mpr-axial',
|
|
13497
|
+
toolGroupId: 'mpr',
|
|
13498
|
+
viewportType: 'volume',
|
|
13499
|
+
orientation: 'axial_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
|
+
viewportOptions: {
|
|
13510
|
+
viewportId: 'mpr-sagittal',
|
|
13511
|
+
toolGroupId: 'mpr',
|
|
13512
|
+
viewportType: 'volume',
|
|
13513
|
+
orientation: 'sagittal_reformat',
|
|
13514
|
+
initialImageOptions: {
|
|
13515
|
+
preset: 'middle'
|
|
13516
|
+
},
|
|
13517
|
+
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
|
|
13518
|
+
},
|
|
13519
|
+
displaySets: [{
|
|
13520
|
+
id: 'activeDisplaySet'
|
|
13521
|
+
}]
|
|
13522
|
+
}, {
|
|
13523
|
+
viewportOptions: {
|
|
13524
|
+
viewportId: 'mpr-coronal',
|
|
13525
|
+
toolGroupId: 'mpr',
|
|
13526
|
+
viewportType: 'volume',
|
|
13527
|
+
orientation: 'coronal_reformat',
|
|
13528
|
+
initialImageOptions: {
|
|
13529
|
+
preset: 'middle'
|
|
13530
|
+
},
|
|
13531
|
+
syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
|
|
13532
|
+
},
|
|
13533
|
+
displaySets: [{
|
|
13534
|
+
id: 'activeDisplaySet'
|
|
13535
|
+
}]
|
|
13536
|
+
}]
|
|
13537
|
+
}]
|
|
13538
|
+
};
|
|
13539
|
+
;// ../../../extensions/cornerstone/src/hps/fourUp.ts
|
|
13540
|
+
|
|
13541
|
+
|
|
13542
|
+
const fourUp = {
|
|
13543
|
+
id: 'fourUp',
|
|
13544
|
+
locked: true,
|
|
13545
|
+
name: i18next/* default */.A.t('Hps:3D four up'),
|
|
13546
|
+
icon: 'layout-advanced-3d-four-up',
|
|
13547
|
+
isPreset: true,
|
|
13548
|
+
createdDate: '2023-03-15T10:29:44.894Z',
|
|
13549
|
+
modifiedDate: '2023-03-15T10:29:44.894Z',
|
|
13550
|
+
availableTo: {},
|
|
13551
|
+
editableBy: {},
|
|
13370
13552
|
protocolMatchingRules: [],
|
|
13371
13553
|
imageLoadStrategy: 'interleaveCenter',
|
|
13372
13554
|
displaySetSelectors: {
|
|
@@ -15342,6 +15524,9 @@ function ViewportDataOverlayMenu({
|
|
|
15342
15524
|
} = (0,useViewportDisplaySets/* useViewportDisplaySets */.N)(viewportId);
|
|
15343
15525
|
const [optimisticOverlayDisplaySets, setOptimisticOverlayDisplaySets] = (0,react.useState)(overlayDisplaySets);
|
|
15344
15526
|
const [thresholdOpacityEnabled, setThresholdOpacityEnabled] = (0,react.useState)(false);
|
|
15527
|
+
(0,react.useEffect)(() => {
|
|
15528
|
+
setOptimisticOverlayDisplaySets(overlayDisplaySets);
|
|
15529
|
+
}, [backgroundDisplaySet?.displaySetInstanceUID, overlayDisplaySets]);
|
|
15345
15530
|
|
|
15346
15531
|
/**
|
|
15347
15532
|
* Change the background display set
|
|
@@ -15648,7 +15833,8 @@ function ViewportDataOverlayMenu({
|
|
|
15648
15833
|
}
|
|
15649
15834
|
}
|
|
15650
15835
|
}, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, {
|
|
15651
|
-
className: "flex-1"
|
|
15836
|
+
className: "flex-1",
|
|
15837
|
+
"data-cy": `overlay-background-ds-select-${viewportId}`
|
|
15652
15838
|
}, /*#__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
15839
|
key: displaySet.displaySetInstanceUID,
|
|
15654
15840
|
value: displaySet.displaySetInstanceUID,
|
|
@@ -15923,7 +16109,7 @@ function ViewportOrientationMenu({
|
|
|
15923
16109
|
}) : null), /*#__PURE__*/react.createElement("div", {
|
|
15924
16110
|
className: "flex-1 text-left"
|
|
15925
16111
|
}, "Acquisition")), /*#__PURE__*/react.createElement("div", {
|
|
15926
|
-
className: "mx-1 my-2 border-t
|
|
16112
|
+
className: "border-input mx-1 my-2 border-t"
|
|
15927
16113
|
}), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
|
|
15928
16114
|
variant: "ghost",
|
|
15929
16115
|
className: "flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0",
|
|
@@ -16264,7 +16450,7 @@ function VolumeRenderingPresetsContent({
|
|
|
16264
16450
|
}
|
|
16265
16451
|
}, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.ByName, {
|
|
16266
16452
|
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-
|
|
16453
|
+
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
16454
|
}), /*#__PURE__*/react.createElement("label", {
|
|
16269
16455
|
className: "text-muted-foreground mt-1 text-left text-xs"
|
|
16270
16456
|
}, formatLabel(preset.name, 11)))))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu, {
|
|
@@ -17410,9 +17596,9 @@ function ModalityLoadBadge({
|
|
|
17410
17596
|
if (!statusInfo.isHydrated) {
|
|
17411
17597
|
return /*#__PURE__*/react.createElement("div", {
|
|
17412
17598
|
"data-cy": `ModalityLoadBadge-${viewportId}`,
|
|
17413
|
-
className: "flex h-6 cursor-default text-sm leading-6
|
|
17599
|
+
className: "text-foreground flex h-6 cursor-default text-sm leading-6"
|
|
17414
17600
|
}, /*#__PURE__*/react.createElement("div", {
|
|
17415
|
-
className: "bg-
|
|
17601
|
+
className: "bg-popover flex min-w-[45px] items-center rounded-l-xl rounded-r p-1"
|
|
17416
17602
|
}, /*#__PURE__*/react.createElement(StatusIcon, null), /*#__PURE__*/react.createElement("span", {
|
|
17417
17603
|
className: "ml-1"
|
|
17418
17604
|
}, statusInfo.type)), statusInfo.type !== 'SR' && /*#__PURE__*/react.createElement(ui_next_src/* ViewportActionButton */.N8H, {
|
|
@@ -18339,6 +18525,36 @@ function getToolbarModule({
|
|
|
18339
18525
|
isActive: isPrimaryActive
|
|
18340
18526
|
};
|
|
18341
18527
|
}
|
|
18528
|
+
}, {
|
|
18529
|
+
name: 'evaluate.cornerstoneTool.toggleWithModifier',
|
|
18530
|
+
evaluate: ({
|
|
18531
|
+
viewportId,
|
|
18532
|
+
button,
|
|
18533
|
+
disabledText,
|
|
18534
|
+
toggledOnIcon,
|
|
18535
|
+
defaultIcon
|
|
18536
|
+
}) => {
|
|
18537
|
+
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
|
18538
|
+
if (!toolGroup) {
|
|
18539
|
+
return;
|
|
18540
|
+
}
|
|
18541
|
+
const toolName = toolbarService.getToolNameForButton(button);
|
|
18542
|
+
if (!toolGroup.hasTool(toolName)) {
|
|
18543
|
+
return getDisabledState(disabledText);
|
|
18544
|
+
}
|
|
18545
|
+
const {
|
|
18546
|
+
mode
|
|
18547
|
+
} = toolGroup.getToolOptions(toolName) ?? {};
|
|
18548
|
+
const isToggled = mode === dist_esm.Enums.ToolModes.Passive || mode === dist_esm.Enums.ToolModes.Active || mode === dist_esm.Enums.ToolModes.Enabled;
|
|
18549
|
+
const toolBindings = toolGroupService.getToolBindings(toolGroup.id, toolName);
|
|
18550
|
+
const hasModifierKey = toolBindings?.some(binding => binding.modifierKey != null) ?? false;
|
|
18551
|
+
return {
|
|
18552
|
+
disabled: false,
|
|
18553
|
+
isActive: false,
|
|
18554
|
+
isToggled,
|
|
18555
|
+
icon: isToggled && hasModifierKey && toggledOnIcon ? toggledOnIcon : defaultIcon ?? button.props.icon
|
|
18556
|
+
};
|
|
18557
|
+
}
|
|
18342
18558
|
}, {
|
|
18343
18559
|
name: 'evaluate.action',
|
|
18344
18560
|
evaluate: () => {
|
|
@@ -18491,7 +18707,10 @@ class ToolGroupService {
|
|
|
18491
18707
|
this.cornerstoneViewportService = void 0;
|
|
18492
18708
|
this.viewportGridService = void 0;
|
|
18493
18709
|
this.uiNotificationService = void 0;
|
|
18710
|
+
this.customizationService = void 0;
|
|
18494
18711
|
this.toolGroupIds = new Set();
|
|
18712
|
+
this.toolBindingsMap = new Map();
|
|
18713
|
+
this.defaultToolBindingsMap = new Map();
|
|
18495
18714
|
/**
|
|
18496
18715
|
* Service-specific
|
|
18497
18716
|
*/
|
|
@@ -18517,11 +18736,13 @@ class ToolGroupService {
|
|
|
18517
18736
|
const {
|
|
18518
18737
|
cornerstoneViewportService,
|
|
18519
18738
|
viewportGridService,
|
|
18520
|
-
uiNotificationService
|
|
18739
|
+
uiNotificationService,
|
|
18740
|
+
customizationService
|
|
18521
18741
|
} = servicesManager.services;
|
|
18522
18742
|
this.cornerstoneViewportService = cornerstoneViewportService;
|
|
18523
18743
|
this.viewportGridService = viewportGridService;
|
|
18524
18744
|
this.uiNotificationService = uiNotificationService;
|
|
18745
|
+
this.customizationService = customizationService;
|
|
18525
18746
|
this.listeners = {};
|
|
18526
18747
|
this.EVENTS = ToolGroupService_EVENTS;
|
|
18527
18748
|
Object.assign(this, src/* pubSubServiceInterface */.Ml);
|
|
@@ -18579,6 +18800,8 @@ class ToolGroupService {
|
|
|
18579
18800
|
destroy() {
|
|
18580
18801
|
dist_esm.ToolGroupManager.destroy();
|
|
18581
18802
|
this.toolGroupIds = new Set();
|
|
18803
|
+
this.toolBindingsMap.clear();
|
|
18804
|
+
this.defaultToolBindingsMap.clear();
|
|
18582
18805
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.TOOL_ACTIVATED, this._onToolActivated);
|
|
18583
18806
|
}
|
|
18584
18807
|
destroyToolGroup(toolGroupId) {
|
|
@@ -18633,6 +18856,7 @@ class ToolGroupService {
|
|
|
18633
18856
|
// this.changeConfigurationIfNecessary(toolGroup, volumeId);
|
|
18634
18857
|
this._addTools(toolGroup, tools, configs);
|
|
18635
18858
|
this._setToolsMode(toolGroup, tools);
|
|
18859
|
+
this._loadPersistedBindings(toolGroupId);
|
|
18636
18860
|
}
|
|
18637
18861
|
createToolGroupAndAddTools(toolGroupId, tools) {
|
|
18638
18862
|
const toolGroup = this.createToolGroup(toolGroupId);
|
|
@@ -18672,6 +18896,84 @@ class ToolGroupService {
|
|
|
18672
18896
|
getActivePrimaryMouseButtonTool(toolGroupId) {
|
|
18673
18897
|
return this.getToolGroup(toolGroupId)?.getActivePrimaryMouseButtonTool();
|
|
18674
18898
|
}
|
|
18899
|
+
getToolBindings(toolGroupId, toolName) {
|
|
18900
|
+
return this.toolBindingsMap.get(toolGroupId)?.get(toolName);
|
|
18901
|
+
}
|
|
18902
|
+
setToolBindings(toolGroupId, toolName, bindings) {
|
|
18903
|
+
if (!this.toolBindingsMap.has(toolGroupId)) {
|
|
18904
|
+
this.toolBindingsMap.set(toolGroupId, new Map());
|
|
18905
|
+
}
|
|
18906
|
+
this.toolBindingsMap.get(toolGroupId).set(toolName, this._cloneToolBindings(bindings));
|
|
18907
|
+
}
|
|
18908
|
+
getDefaultToolBindings(toolGroupId, toolName) {
|
|
18909
|
+
const defaultBindings = this.defaultToolBindingsMap.get(toolGroupId)?.get(toolName);
|
|
18910
|
+
return defaultBindings ? this._cloneToolBindings(defaultBindings) : undefined;
|
|
18911
|
+
}
|
|
18912
|
+
persistToolBindings(toolGroupId, toolName, bindings) {
|
|
18913
|
+
const persistedBindings = this._readPersistedToolBindings();
|
|
18914
|
+
if (!persistedBindings[toolGroupId]) {
|
|
18915
|
+
persistedBindings[toolGroupId] = {};
|
|
18916
|
+
}
|
|
18917
|
+
persistedBindings[toolGroupId][toolName] = bindings;
|
|
18918
|
+
this._writePersistedToolBindings(persistedBindings);
|
|
18919
|
+
}
|
|
18920
|
+
removePersistedToolBindings(toolGroupId, toolName) {
|
|
18921
|
+
const persistedBindings = this._readPersistedToolBindings();
|
|
18922
|
+
if (!persistedBindings[toolGroupId]) {
|
|
18923
|
+
return;
|
|
18924
|
+
}
|
|
18925
|
+
if (toolName) {
|
|
18926
|
+
delete persistedBindings[toolGroupId][toolName];
|
|
18927
|
+
if (!Object.keys(persistedBindings[toolGroupId]).length) {
|
|
18928
|
+
delete persistedBindings[toolGroupId];
|
|
18929
|
+
}
|
|
18930
|
+
} else {
|
|
18931
|
+
delete persistedBindings[toolGroupId];
|
|
18932
|
+
}
|
|
18933
|
+
this._writePersistedToolBindings(persistedBindings);
|
|
18934
|
+
}
|
|
18935
|
+
|
|
18936
|
+
/**
|
|
18937
|
+
* Applies the currently tracked bindings to the runtime tool instance.
|
|
18938
|
+
*
|
|
18939
|
+
* Note: this method may activate tools that are currently Passive or Enabled.
|
|
18940
|
+
* Assigning bindings is treated as making the tool interactable.
|
|
18941
|
+
*/
|
|
18942
|
+
applyToolBindings(toolGroupId, toolName, options = {}) {
|
|
18943
|
+
const toolGroup = dist_esm.ToolGroupManager.getToolGroup(toolGroupId);
|
|
18944
|
+
if (!toolGroup || !toolGroup.hasTool(toolName)) {
|
|
18945
|
+
return;
|
|
18946
|
+
}
|
|
18947
|
+
const bindings = this.getToolBindings(toolGroupId, toolName);
|
|
18948
|
+
if (!bindings) {
|
|
18949
|
+
return;
|
|
18950
|
+
}
|
|
18951
|
+
const {
|
|
18952
|
+
mode
|
|
18953
|
+
} = toolGroup.getToolOptions(toolName);
|
|
18954
|
+
if (mode === dist_esm.Enums.ToolModes.Active || mode === dist_esm.Enums.ToolModes.Passive || mode === dist_esm.Enums.ToolModes.Enabled) {
|
|
18955
|
+
if (options.replaceExisting) {
|
|
18956
|
+
// Opt-in behavior for callers that need replacement semantics.
|
|
18957
|
+
toolGroup.setToolDisabled(toolName);
|
|
18958
|
+
}
|
|
18959
|
+
toolGroup.setToolActive(toolName, {
|
|
18960
|
+
bindings
|
|
18961
|
+
});
|
|
18962
|
+
}
|
|
18963
|
+
}
|
|
18964
|
+
getAllToolBindings() {
|
|
18965
|
+
const result = [];
|
|
18966
|
+
for (const [toolGroupId, toolMap] of this.toolBindingsMap) {
|
|
18967
|
+
for (const [toolName, bindings] of toolMap) {
|
|
18968
|
+
result.push({
|
|
18969
|
+
toolGroupId,
|
|
18970
|
+
toolName,
|
|
18971
|
+
bindings
|
|
18972
|
+
});
|
|
18973
|
+
}
|
|
18974
|
+
}
|
|
18975
|
+
return result;
|
|
18976
|
+
}
|
|
18675
18977
|
_setToolsMode(toolGroup, tools) {
|
|
18676
18978
|
const {
|
|
18677
18979
|
active,
|
|
@@ -18684,6 +18986,10 @@ class ToolGroupService {
|
|
|
18684
18986
|
toolName,
|
|
18685
18987
|
bindings
|
|
18686
18988
|
}) => {
|
|
18989
|
+
if (bindings) {
|
|
18990
|
+
this.setToolBindings(toolGroup.id, toolName, bindings);
|
|
18991
|
+
this._setDefaultToolBindingsIfMissing(toolGroup.id, toolName, bindings);
|
|
18992
|
+
}
|
|
18687
18993
|
toolGroup.setToolActive(toolName, {
|
|
18688
18994
|
bindings
|
|
18689
18995
|
});
|
|
@@ -18691,26 +18997,50 @@ class ToolGroupService {
|
|
|
18691
18997
|
}
|
|
18692
18998
|
if (passive) {
|
|
18693
18999
|
passive.forEach(({
|
|
18694
|
-
toolName
|
|
19000
|
+
toolName,
|
|
19001
|
+
bindings
|
|
18695
19002
|
}) => {
|
|
19003
|
+
if (bindings) {
|
|
19004
|
+
this.setToolBindings(toolGroup.id, toolName, bindings);
|
|
19005
|
+
this._setDefaultToolBindingsIfMissing(toolGroup.id, toolName, bindings);
|
|
19006
|
+
}
|
|
18696
19007
|
toolGroup.setToolPassive(toolName);
|
|
18697
19008
|
});
|
|
18698
19009
|
}
|
|
18699
19010
|
if (enabled) {
|
|
18700
19011
|
enabled.forEach(({
|
|
18701
|
-
toolName
|
|
19012
|
+
toolName,
|
|
19013
|
+
bindings
|
|
18702
19014
|
}) => {
|
|
19015
|
+
if (bindings) {
|
|
19016
|
+
this.setToolBindings(toolGroup.id, toolName, bindings);
|
|
19017
|
+
this._setDefaultToolBindingsIfMissing(toolGroup.id, toolName, bindings);
|
|
19018
|
+
}
|
|
18703
19019
|
toolGroup.setToolEnabled(toolName);
|
|
18704
19020
|
});
|
|
18705
19021
|
}
|
|
18706
19022
|
if (disabled) {
|
|
18707
19023
|
disabled.forEach(({
|
|
18708
|
-
toolName
|
|
19024
|
+
toolName,
|
|
19025
|
+
bindings
|
|
18709
19026
|
}) => {
|
|
19027
|
+
if (bindings) {
|
|
19028
|
+
this.setToolBindings(toolGroup.id, toolName, bindings);
|
|
19029
|
+
this._setDefaultToolBindingsIfMissing(toolGroup.id, toolName, bindings);
|
|
19030
|
+
}
|
|
18710
19031
|
toolGroup.setToolDisabled(toolName);
|
|
18711
19032
|
});
|
|
18712
19033
|
}
|
|
18713
19034
|
}
|
|
19035
|
+
_setDefaultToolBindingsIfMissing(toolGroupId, toolName, bindings) {
|
|
19036
|
+
if (!this.defaultToolBindingsMap.has(toolGroupId)) {
|
|
19037
|
+
this.defaultToolBindingsMap.set(toolGroupId, new Map());
|
|
19038
|
+
}
|
|
19039
|
+
const toolMap = this.defaultToolBindingsMap.get(toolGroupId);
|
|
19040
|
+
if (!toolMap.has(toolName)) {
|
|
19041
|
+
toolMap.set(toolName, this._cloneToolBindings(bindings));
|
|
19042
|
+
}
|
|
19043
|
+
}
|
|
18714
19044
|
_addTools(toolGroup, tools) {
|
|
18715
19045
|
const addTools = tools => {
|
|
18716
19046
|
tools.forEach(({
|
|
@@ -18742,6 +19072,60 @@ class ToolGroupService {
|
|
|
18742
19072
|
addTools(tools.disabled);
|
|
18743
19073
|
}
|
|
18744
19074
|
}
|
|
19075
|
+
_loadPersistedBindings(toolGroupId) {
|
|
19076
|
+
const toolGroupBindings = this._readPersistedToolBindings()[toolGroupId];
|
|
19077
|
+
if (!toolGroupBindings) {
|
|
19078
|
+
return;
|
|
19079
|
+
}
|
|
19080
|
+
const toolGroup = dist_esm.ToolGroupManager.getToolGroup(toolGroupId);
|
|
19081
|
+
for (const [toolName, bindings] of Object.entries(toolGroupBindings)) {
|
|
19082
|
+
this.setToolBindings(toolGroupId, toolName, bindings);
|
|
19083
|
+
if (!toolGroup || !toolGroup.hasTool(toolName)) {
|
|
19084
|
+
continue;
|
|
19085
|
+
}
|
|
19086
|
+
const {
|
|
19087
|
+
mode
|
|
19088
|
+
} = toolGroup.getToolOptions(toolName);
|
|
19089
|
+
if (mode === dist_esm.Enums.ToolModes.Active) {
|
|
19090
|
+
this.applyToolBindings(toolGroupId, toolName, {
|
|
19091
|
+
replaceExisting: true
|
|
19092
|
+
});
|
|
19093
|
+
}
|
|
19094
|
+
}
|
|
19095
|
+
}
|
|
19096
|
+
_readPersistedToolBindings() {
|
|
19097
|
+
try {
|
|
19098
|
+
const stored = localStorage.getItem(this._getToolBindingsStorageKey());
|
|
19099
|
+
if (!stored) {
|
|
19100
|
+
return {};
|
|
19101
|
+
}
|
|
19102
|
+
const parsed = JSON.parse(stored);
|
|
19103
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
19104
|
+
return {};
|
|
19105
|
+
}
|
|
19106
|
+
return parsed;
|
|
19107
|
+
} catch {
|
|
19108
|
+
// ignore corrupt localStorage
|
|
19109
|
+
return {};
|
|
19110
|
+
}
|
|
19111
|
+
}
|
|
19112
|
+
_writePersistedToolBindings(bindings) {
|
|
19113
|
+
const storageKey = this._getToolBindingsStorageKey();
|
|
19114
|
+
if (!Object.keys(bindings).length) {
|
|
19115
|
+
localStorage.removeItem(storageKey);
|
|
19116
|
+
return;
|
|
19117
|
+
}
|
|
19118
|
+
localStorage.setItem(storageKey, JSON.stringify(bindings));
|
|
19119
|
+
}
|
|
19120
|
+
_cloneToolBindings(bindings) {
|
|
19121
|
+
return bindings.map(binding => ({
|
|
19122
|
+
...binding
|
|
19123
|
+
}));
|
|
19124
|
+
}
|
|
19125
|
+
_getToolBindingsStorageKey() {
|
|
19126
|
+
const customizationValue = this.customizationService?.getCustomization('ohif.userPreferences.toolBindingsStorageKey');
|
|
19127
|
+
return typeof customizationValue === 'string' && customizationValue.length > 0 ? customizationValue : 'user-preferred-tool-bindings';
|
|
19128
|
+
}
|
|
18745
19129
|
}
|
|
18746
19130
|
_ToolGroupService = ToolGroupService;
|
|
18747
19131
|
ToolGroupService.REGISTRATION = {
|
|
@@ -18829,7 +19213,12 @@ const segmentationRepresentationModifiedCallback = async (synchronizerInstance,
|
|
|
18829
19213
|
const sourceDisplaySetUIDs = extractDisplaySetUIDs(sourceViewportInfo);
|
|
18830
19214
|
const targetDisplaySetUIDs = extractDisplaySetUIDs(targetViewportInfo);
|
|
18831
19215
|
const sharedDisplaySetExists = isAnyDisplaySetCommon(sourceDisplaySetUIDs, targetDisplaySetUIDs);
|
|
18832
|
-
|
|
19216
|
+
const targetFrameOfReferenceUID = viewport.getFrameOfReferenceUID();
|
|
19217
|
+
const sourceFrameOfReferenceUID = (0,esm.getEnabledElementByViewportId)(sourceViewportId)?.viewport?.getFrameOfReferenceUID();
|
|
19218
|
+
if (!sharedDisplaySetExists && !targetFrameOfReferenceUID) {
|
|
19219
|
+
return;
|
|
19220
|
+
}
|
|
19221
|
+
if (!sharedDisplaySetExists && targetFrameOfReferenceUID !== sourceFrameOfReferenceUID) {
|
|
18833
19222
|
return;
|
|
18834
19223
|
}
|
|
18835
19224
|
const targetViewportRepresentation = segmentationService.getSegmentationRepresentations(targetViewportId, {
|
|
@@ -19196,11 +19585,11 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19196
19585
|
this.EVENTS = SegmentationService_EVENTS;
|
|
19197
19586
|
this.destroy = () => {
|
|
19198
19587
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_MODIFIED, this._onSegmentationModifiedFromSource);
|
|
19199
|
-
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this.
|
|
19588
|
+
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationRemovedFromSource);
|
|
19200
19589
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_DATA_MODIFIED, this._onSegmentationDataModifiedFromSource);
|
|
19201
19590
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_MODIFIED, this._onSegmentationRepresentationModifiedFromSource);
|
|
19202
19591
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_ADDED, this._onSegmentationRepresentationModifiedFromSource);
|
|
19203
|
-
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this.
|
|
19592
|
+
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationRemovedFromSource);
|
|
19204
19593
|
esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
|
|
19205
19594
|
this.reset();
|
|
19206
19595
|
};
|
|
@@ -19261,6 +19650,16 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19261
19650
|
viewportId
|
|
19262
19651
|
});
|
|
19263
19652
|
};
|
|
19653
|
+
this._onSegmentationRepresentationRemovedFromSource = evt => {
|
|
19654
|
+
const {
|
|
19655
|
+
segmentationId,
|
|
19656
|
+
viewportId
|
|
19657
|
+
} = evt.detail;
|
|
19658
|
+
this._broadcastEvent(this.EVENTS.SEGMENTATION_REPRESENTATION_REMOVED, {
|
|
19659
|
+
segmentationId,
|
|
19660
|
+
viewportId
|
|
19661
|
+
});
|
|
19662
|
+
};
|
|
19264
19663
|
this._onSegmentationModifiedFromSource = evt => {
|
|
19265
19664
|
const {
|
|
19266
19665
|
segmentationId
|
|
@@ -19277,6 +19676,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19277
19676
|
segmentationId
|
|
19278
19677
|
});
|
|
19279
19678
|
};
|
|
19679
|
+
this._onSegmentationRemovedFromSource = evt => {
|
|
19680
|
+
const {
|
|
19681
|
+
segmentationId
|
|
19682
|
+
} = evt.detail;
|
|
19683
|
+
this._broadcastEvent(this.EVENTS.SEGMENTATION_REMOVED, {
|
|
19684
|
+
segmentationId
|
|
19685
|
+
});
|
|
19686
|
+
};
|
|
19280
19687
|
this._onAnnotationCutMergeProcessCompletedFromSource = evt => {
|
|
19281
19688
|
const {
|
|
19282
19689
|
segmentationId
|
|
@@ -19482,6 +19889,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19482
19889
|
},
|
|
19483
19890
|
config: {
|
|
19484
19891
|
label,
|
|
19892
|
+
fallbackLabel: `S:${displaySet.SeriesNumber} ${displaySet.Modality}`,
|
|
19485
19893
|
segments: options?.segments && Object.keys(options.segments).length > 0 ? options.segments : {
|
|
19486
19894
|
1: {
|
|
19487
19895
|
label: `${i18n_src/* default */.A.t('Segment')} 1`,
|
|
@@ -19613,6 +20021,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19613
20021
|
},
|
|
19614
20022
|
config: {
|
|
19615
20023
|
label: segDisplaySet.SeriesDescription,
|
|
20024
|
+
fallbackLabel: `S:${segDisplaySet.SeriesNumber} ${segDisplaySet.Modality}`,
|
|
19616
20025
|
segments
|
|
19617
20026
|
}
|
|
19618
20027
|
};
|
|
@@ -19673,7 +20082,8 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
19673
20082
|
}
|
|
19674
20083
|
},
|
|
19675
20084
|
config: {
|
|
19676
|
-
label: rtDisplaySet.SeriesDescription
|
|
20085
|
+
label: rtDisplaySet.SeriesDescription,
|
|
20086
|
+
fallbackLabel: `S:${rtDisplaySet.SeriesNumber} ${rtDisplaySet.Modality}`
|
|
19677
20087
|
}
|
|
19678
20088
|
};
|
|
19679
20089
|
const segments = {};
|
|
@@ -20170,14 +20580,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
20170
20580
|
}
|
|
20171
20581
|
/**
|
|
20172
20582
|
* Clears segmentation representations from the viewport.
|
|
20173
|
-
* Unlike
|
|
20583
|
+
* Unlike removeRepresentationsFromViewport, this doesn't update
|
|
20174
20584
|
* removed display set and representation maps.
|
|
20175
20585
|
* We track removed segmentations manually to avoid re-adding them
|
|
20176
20586
|
* when the display set is added again.
|
|
20177
20587
|
* @param viewportId - The viewport ID to clear segmentation representations from.
|
|
20178
20588
|
*/
|
|
20179
20589
|
clearSegmentationRepresentations(viewportId) {
|
|
20180
|
-
this.
|
|
20590
|
+
this.removeRepresentationsFromViewport(viewportId);
|
|
20181
20591
|
}
|
|
20182
20592
|
|
|
20183
20593
|
/**
|
|
@@ -20192,7 +20602,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
20192
20602
|
}
|
|
20193
20603
|
|
|
20194
20604
|
/**
|
|
20195
|
-
*
|
|
20605
|
+
* Removes segmentation representations from the viewport.
|
|
20196
20606
|
* @param viewportId - The viewport id to remove the segmentation representations from.
|
|
20197
20607
|
* @param specifier - The specifier to remove the segmentation representations.
|
|
20198
20608
|
*
|
|
@@ -20202,7 +20612,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
20202
20612
|
* If a type specifier is provided, only the segmentation representation with the specified type are removed.
|
|
20203
20613
|
* If both a segmentationId and type specifier are provided, only the segmentation representation with the specified segmentationId and type are removed.
|
|
20204
20614
|
*/
|
|
20205
|
-
|
|
20615
|
+
removeRepresentationsFromViewport(viewportId, specifier = {}) {
|
|
20206
20616
|
dist_esm.segmentation.removeSegmentationRepresentations(viewportId, specifier);
|
|
20207
20617
|
}
|
|
20208
20618
|
|
|
@@ -20558,6 +20968,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
20558
20968
|
id: id,
|
|
20559
20969
|
segmentationId,
|
|
20560
20970
|
label: segmentation.label,
|
|
20971
|
+
fallbackLabel: segmentation.fallbackLabel,
|
|
20561
20972
|
active,
|
|
20562
20973
|
type,
|
|
20563
20974
|
visible,
|
|
@@ -20570,11 +20981,11 @@ class SegmentationService extends src/* PubSubService */.Rc {
|
|
|
20570
20981
|
}
|
|
20571
20982
|
_initSegmentationService() {
|
|
20572
20983
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_MODIFIED, this._onSegmentationModifiedFromSource);
|
|
20573
|
-
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this.
|
|
20984
|
+
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationRemovedFromSource);
|
|
20574
20985
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_DATA_MODIFIED, this._onSegmentationDataModifiedFromSource);
|
|
20575
20986
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_MODIFIED, this._onSegmentationRepresentationModifiedFromSource);
|
|
20576
20987
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_ADDED, this._onSegmentationRepresentationModifiedFromSource);
|
|
20577
|
-
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this.
|
|
20988
|
+
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationRemovedFromSource);
|
|
20578
20989
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
|
|
20579
20990
|
esm.eventTarget.addEventListener(dist_esm.Enums.Events.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED, this._onAnnotationCutMergeProcessCompletedFromSource);
|
|
20580
20991
|
}
|
|
@@ -20780,6 +21191,7 @@ const ORTHOGRAPHIC = 'orthographic';
|
|
|
20780
21191
|
const VOLUME_3D = 'volume3d';
|
|
20781
21192
|
const VIDEO = 'video';
|
|
20782
21193
|
const WHOLESLIDE = 'wholeslide';
|
|
21194
|
+
const ECG = 'ecg';
|
|
20783
21195
|
function getCornerstoneViewportType(viewportType, displaySets) {
|
|
20784
21196
|
const lowerViewportType = displaySets?.[0]?.viewportType?.toLowerCase() || viewportType.toLowerCase();
|
|
20785
21197
|
if (lowerViewportType === STACK) {
|
|
@@ -20791,13 +21203,16 @@ function getCornerstoneViewportType(viewportType, displaySets) {
|
|
|
20791
21203
|
if (lowerViewportType === WHOLESLIDE) {
|
|
20792
21204
|
return esm.Enums.ViewportType.WHOLE_SLIDE;
|
|
20793
21205
|
}
|
|
21206
|
+
if (lowerViewportType === ECG) {
|
|
21207
|
+
return esm.Enums.ViewportType.ECG;
|
|
21208
|
+
}
|
|
20794
21209
|
if (lowerViewportType === VOLUME || lowerViewportType === ORTHOGRAPHIC) {
|
|
20795
21210
|
return esm.Enums.ViewportType.ORTHOGRAPHIC;
|
|
20796
21211
|
}
|
|
20797
21212
|
if (lowerViewportType === VOLUME_3D) {
|
|
20798
21213
|
return esm.Enums.ViewportType.VOLUME_3D;
|
|
20799
21214
|
}
|
|
20800
|
-
throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide`);
|
|
21215
|
+
throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide, ecg`);
|
|
20801
21216
|
}
|
|
20802
21217
|
;// ../../../extensions/cornerstone/src/services/CornerstoneCacheService/CornerstoneCacheService.ts
|
|
20803
21218
|
var _CornerstoneCacheService;
|
|
@@ -21104,15 +21519,24 @@ function getCornerstoneBlendMode(blendMode) {
|
|
|
21104
21519
|
const AXIAL = 'axial';
|
|
21105
21520
|
const SAGITTAL = 'sagittal';
|
|
21106
21521
|
const CORONAL = 'coronal';
|
|
21522
|
+
const AXIAL_REFORMAT = 'axial_reformat';
|
|
21523
|
+
const SAGITTAL_REFORMAT = 'sagittal_reformat';
|
|
21524
|
+
const CORONAL_REFORMAT = 'coronal_reformat';
|
|
21107
21525
|
function getCornerstoneOrientation(orientation) {
|
|
21108
21526
|
if (orientation) {
|
|
21109
21527
|
switch (orientation.toLowerCase()) {
|
|
21110
21528
|
case AXIAL:
|
|
21111
21529
|
return esm.Enums.OrientationAxis.AXIAL;
|
|
21530
|
+
case AXIAL_REFORMAT:
|
|
21531
|
+
return esm.Enums.OrientationAxis.AXIAL_REFORMAT;
|
|
21112
21532
|
case SAGITTAL:
|
|
21113
21533
|
return esm.Enums.OrientationAxis.SAGITTAL;
|
|
21534
|
+
case SAGITTAL_REFORMAT:
|
|
21535
|
+
return esm.Enums.OrientationAxis.SAGITTAL_REFORMAT;
|
|
21114
21536
|
case CORONAL:
|
|
21115
21537
|
return esm.Enums.OrientationAxis.CORONAL;
|
|
21538
|
+
case CORONAL_REFORMAT:
|
|
21539
|
+
return esm.Enums.OrientationAxis.CORONAL_REFORMAT;
|
|
21116
21540
|
default:
|
|
21117
21541
|
return esm.Enums.OrientationAxis.ACQUISITION;
|
|
21118
21542
|
}
|
|
@@ -21385,6 +21809,32 @@ const CornerstoneViewportService_EVENTS = {
|
|
|
21385
21809
|
};
|
|
21386
21810
|
const MIN_STACK_VIEWPORTS_TO_ENQUEUE_RESIZE = 12;
|
|
21387
21811
|
const MIN_VOLUME_VIEWPORTS_TO_ENQUEUE_RESIZE = 6;
|
|
21812
|
+
function getVolumeActorReferencedIds(viewport) {
|
|
21813
|
+
const actors = viewport.getActors?.() ?? [];
|
|
21814
|
+
return actors.filter(ac => ac.actor?.getClassName?.() === 'vtkVolume').map(ac => ac.referencedId).filter(Boolean);
|
|
21815
|
+
}
|
|
21816
|
+
function volumeIdPrefixesMatch(existingIds, prefixLen, targetIds) {
|
|
21817
|
+
if (prefixLen > targetIds.length) {
|
|
21818
|
+
return false;
|
|
21819
|
+
}
|
|
21820
|
+
for (let i = 0; i < prefixLen; i++) {
|
|
21821
|
+
if (existingIds[i] !== targetIds[i]) {
|
|
21822
|
+
return false;
|
|
21823
|
+
}
|
|
21824
|
+
}
|
|
21825
|
+
return true;
|
|
21826
|
+
}
|
|
21827
|
+
|
|
21828
|
+
/**
|
|
21829
|
+
* Returns true when the viewport type matches a volume-based presentation (ORTHOGRAPHIC or VOLUME_3D).
|
|
21830
|
+
*/
|
|
21831
|
+
function viewportMatchesDesiredVolumePresentation(viewport, desiredViewportInfo) {
|
|
21832
|
+
const desiredType = desiredViewportInfo.getViewportType();
|
|
21833
|
+
if (viewport.type !== desiredType) {
|
|
21834
|
+
return false;
|
|
21835
|
+
}
|
|
21836
|
+
return desiredType === esm.Enums.ViewportType.ORTHOGRAPHIC || desiredType === esm.Enums.ViewportType.VOLUME_3D;
|
|
21837
|
+
}
|
|
21388
21838
|
const WITH_NAVIGATION = {
|
|
21389
21839
|
withNavigation: true,
|
|
21390
21840
|
withOrientation: false
|
|
@@ -22072,6 +22522,15 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22072
22522
|
/**
|
|
22073
22523
|
* Sets the image data for the given viewport.
|
|
22074
22524
|
*/
|
|
22525
|
+
async _setEcgViewport(viewport, viewportData) {
|
|
22526
|
+
const [displaySet] = viewportData.data;
|
|
22527
|
+
const imageId = displaySet.imageIds?.[0];
|
|
22528
|
+
if (!imageId) {
|
|
22529
|
+
console.error('[CornerstoneViewportService] ECG display set has no imageId');
|
|
22530
|
+
return;
|
|
22531
|
+
}
|
|
22532
|
+
return viewport.setEcg(imageId);
|
|
22533
|
+
}
|
|
22075
22534
|
async _setOtherViewport(viewport, viewportData, viewportInfo, _presentations = {}) {
|
|
22076
22535
|
const [displaySet] = viewportData.data;
|
|
22077
22536
|
return viewport.setDataIds(displaySet.imageIds, {
|
|
@@ -22140,32 +22599,25 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22140
22599
|
if (initialImageIndexToUse === undefined || initialImageIndexToUse === null || initialImageIndexToUse < 0) {
|
|
22141
22600
|
initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0;
|
|
22142
22601
|
}
|
|
22143
|
-
|
|
22602
|
+
await viewport.setStack(imageIds, initialImageIndexToUse);
|
|
22603
|
+
viewport.setProperties({
|
|
22604
|
+
...properties
|
|
22605
|
+
});
|
|
22606
|
+
this.setPresentations(viewport.id, presentations, viewportInfo);
|
|
22607
|
+
await this._addOverlayRepresentations(overlayProcessingResults);
|
|
22608
|
+
if (displayArea) {
|
|
22609
|
+
viewport.setDisplayArea(displayArea);
|
|
22610
|
+
}
|
|
22611
|
+
if (rotation) {
|
|
22144
22612
|
viewport.setProperties({
|
|
22145
|
-
|
|
22613
|
+
rotation
|
|
22146
22614
|
});
|
|
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
|
-
});
|
|
22615
|
+
}
|
|
22616
|
+
if (flipHorizontal) {
|
|
22617
|
+
viewport.setCamera({
|
|
22618
|
+
flipHorizontal: true
|
|
22619
|
+
});
|
|
22620
|
+
}
|
|
22169
22621
|
}
|
|
22170
22622
|
_getInitialImageIndexForViewport(viewportInfo, imageIds) {
|
|
22171
22623
|
const initialImageOptions = viewportInfo.getInitialImageOptions();
|
|
@@ -22388,16 +22840,34 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22388
22840
|
}
|
|
22389
22841
|
});
|
|
22390
22842
|
}
|
|
22391
|
-
|
|
22392
|
-
|
|
22393
|
-
|
|
22394
|
-
|
|
22395
|
-
|
|
22396
|
-
|
|
22397
|
-
|
|
22843
|
+
const baseVolumeInputs = filteredVolumeInputArray.map(({
|
|
22844
|
+
volumeInput
|
|
22845
|
+
}) => volumeInput);
|
|
22846
|
+
const nextBaseVolumeIds = baseVolumeInputs.map(v => v.volumeId);
|
|
22847
|
+
const existingVolumeIds = getVolumeActorReferencedIds(viewport);
|
|
22848
|
+
let skippedIdenticalBaseVolumes = false;
|
|
22849
|
+
if (baseVolumeInputs.length) {
|
|
22850
|
+
const singleBaseViewport = nextBaseVolumeIds.length === 1;
|
|
22851
|
+
|
|
22852
|
+
// Only skip setVolumes() when the viewport type already matches the desired OHIF type
|
|
22853
|
+
// (ORTHOGRAPHIC / VOLUME_3D); otherwise a stack → MPR switch with the same volumeId
|
|
22854
|
+
// would incorrectly skip rebuilding the viewport.
|
|
22855
|
+
if (singleBaseViewport && existingVolumeIds.length >= nextBaseVolumeIds.length && volumeIdPrefixesMatch(existingVolumeIds, nextBaseVolumeIds.length, nextBaseVolumeIds) && viewportMatchesDesiredVolumePresentation(viewport, viewportInfo)) {
|
|
22856
|
+
// Same primary volume already loaded (e.g. labelmap / extra actors after it) — avoid
|
|
22857
|
+
// setVolumes(), which tears down all actors and blanks MPR during SEG hydrate.
|
|
22858
|
+
skippedIdenticalBaseVolumes = true;
|
|
22859
|
+
} else if (existingVolumeIds.length && nextBaseVolumeIds.length > existingVolumeIds.length && volumeIdPrefixesMatch(existingVolumeIds, existingVolumeIds.length, nextBaseVolumeIds) && typeof viewport.addVolumes === 'function') {
|
|
22860
|
+
const toAdd = baseVolumeInputs.slice(existingVolumeIds.length);
|
|
22861
|
+
if (toAdd.length) {
|
|
22862
|
+
await viewport.addVolumes(toAdd);
|
|
22398
22863
|
}
|
|
22399
|
-
}
|
|
22864
|
+
} else {
|
|
22865
|
+
await viewport.setVolumes(baseVolumeInputs);
|
|
22866
|
+
}
|
|
22867
|
+
} else if (volumeInputArray.length) {
|
|
22868
|
+
await viewport.setVolumes(volumeInputArray);
|
|
22400
22869
|
}
|
|
22870
|
+
await this._addOverlayRepresentations(overlayProcessingResults);
|
|
22401
22871
|
viewport.render();
|
|
22402
22872
|
volumesProperties.forEach(({
|
|
22403
22873
|
properties,
|
|
@@ -22409,7 +22879,10 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22409
22879
|
});
|
|
22410
22880
|
});
|
|
22411
22881
|
this.setPresentations(viewport.id, presentations);
|
|
22412
|
-
|
|
22882
|
+
// Presentations apply segmentation (hydrated labelmap etc.) after the render above — redraw so
|
|
22883
|
+
// every orthographic/3D tile shows the updated scene (fixes MPR siblings blank after SEG hydrate).
|
|
22884
|
+
viewport.render();
|
|
22885
|
+
if (!presentations.positionPresentation && !skippedIdenticalBaseVolumes) {
|
|
22413
22886
|
const imageIndex = this._getInitialImageIndexForViewport(viewportInfo);
|
|
22414
22887
|
if (imageIndex !== undefined) {
|
|
22415
22888
|
esm.utilities.jumpToSlice(viewport.element, {
|
|
@@ -22460,7 +22933,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22460
22933
|
const {
|
|
22461
22934
|
predecessorImageId
|
|
22462
22935
|
} = displaySet;
|
|
22463
|
-
segmentationService.addSegmentationRepresentation(viewport.id, {
|
|
22936
|
+
const segmentationRepresentationPromise = segmentationService.addSegmentationRepresentation(viewport.id, {
|
|
22464
22937
|
segmentationId,
|
|
22465
22938
|
predecessorImageId,
|
|
22466
22939
|
type: representationType,
|
|
@@ -22468,11 +22941,21 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22468
22941
|
blendMode: viewport?.getBlendMode?.() === 1 ? dist_esm_enums.BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined
|
|
22469
22942
|
}
|
|
22470
22943
|
});
|
|
22471
|
-
|
|
22472
22944
|
// store the segmentation presentation id in the viewport info
|
|
22473
22945
|
this.storePresentation({
|
|
22474
22946
|
viewportId: viewport.id
|
|
22475
22947
|
});
|
|
22948
|
+
return segmentationRepresentationPromise;
|
|
22949
|
+
}
|
|
22950
|
+
async _addOverlayRepresentations(overlayProcessingResults) {
|
|
22951
|
+
if (!overlayProcessingResults?.length) {
|
|
22952
|
+
return;
|
|
22953
|
+
}
|
|
22954
|
+
for (const overlayProcessingResult of overlayProcessingResults) {
|
|
22955
|
+
if (overlayProcessingResult?.addOverlayFn) {
|
|
22956
|
+
await overlayProcessingResult.addOverlayFn();
|
|
22957
|
+
}
|
|
22958
|
+
}
|
|
22476
22959
|
}
|
|
22477
22960
|
|
|
22478
22961
|
// Todo: keepCamera is an interim solution until we have a better solution for
|
|
@@ -22507,6 +22990,9 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22507
22990
|
if ([esm.VolumeViewport, esm.VolumeViewport3D].some(type => viewport instanceof type)) {
|
|
22508
22991
|
return this._setVolumeViewport(viewport, viewportData, viewportInfo, presentations);
|
|
22509
22992
|
}
|
|
22993
|
+
if (viewport instanceof esm.ECGViewport) {
|
|
22994
|
+
return this._setEcgViewport(viewport, viewportData);
|
|
22995
|
+
}
|
|
22510
22996
|
return this._setOtherViewport(viewport, viewportData, viewportInfo, presentations);
|
|
22511
22997
|
}
|
|
22512
22998
|
|
|
@@ -22549,8 +23035,8 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
|
|
|
22549
23035
|
if (!displaySet) {
|
|
22550
23036
|
return;
|
|
22551
23037
|
}
|
|
22552
|
-
if (displaySet.
|
|
22553
|
-
return displaySet.
|
|
23038
|
+
if (displaySet.FrameOfReferenceUID) {
|
|
23039
|
+
return displaySet.FrameOfReferenceUID;
|
|
22554
23040
|
}
|
|
22555
23041
|
if (displaySet.Modality === 'SEG') {
|
|
22556
23042
|
const {
|
|
@@ -22728,6 +23214,8 @@ CornerstoneViewportService.REGISTRATION = {
|
|
|
22728
23214
|
}
|
|
22729
23215
|
};
|
|
22730
23216
|
/* harmony default export */ const ViewportService_CornerstoneViewportService = (CornerstoneViewportService);
|
|
23217
|
+
// EXTERNAL MODULE: ../../../extensions/cornerstone/src/utils/getDataIdForViewport.ts
|
|
23218
|
+
var getDataIdForViewport = __webpack_require__(67142);
|
|
22731
23219
|
;// ../../../extensions/cornerstone/src/types/Colorbar.ts
|
|
22732
23220
|
// Position options
|
|
22733
23221
|
|
|
@@ -22770,6 +23258,7 @@ var _ColorbarService;
|
|
|
22770
23258
|
|
|
22771
23259
|
|
|
22772
23260
|
|
|
23261
|
+
|
|
22773
23262
|
class ColorbarService extends src/* PubSubService */.Rc {
|
|
22774
23263
|
constructor(servicesManager) {
|
|
22775
23264
|
super(ColorbarService.EVENTS);
|
|
@@ -22793,23 +23282,6 @@ class ColorbarService extends src/* PubSubService */.Rc {
|
|
|
22793
23282
|
this.servicesManager = servicesManager;
|
|
22794
23283
|
}
|
|
22795
23284
|
|
|
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
23285
|
/**
|
|
22814
23286
|
* Adds a colorbar to a specific viewport identified by `viewportId`, using the provided `displaySetInstanceUIDs` and `options`.
|
|
22815
23287
|
* This method prepares the colorbar state that will be used by the ViewportColorbarsContainer component.
|
|
@@ -22841,7 +23313,7 @@ class ColorbarService extends src/* PubSubService */.Rc {
|
|
|
22841
23313
|
if (displaySet.isOverlayDisplaySet) {
|
|
22842
23314
|
return;
|
|
22843
23315
|
}
|
|
22844
|
-
const dataId =
|
|
23316
|
+
const dataId = (0,getDataIdForViewport/* getDataIdForViewport */.V)(viewport, displaySetInstanceUID);
|
|
22845
23317
|
const properties = dataId ? viewport.getProperties(dataId) : viewport.getProperties();
|
|
22846
23318
|
const colormap = properties?.colormap;
|
|
22847
23319
|
if (activeColormapName && !colormap) {
|
|
@@ -22979,7 +23451,7 @@ class ColorbarService extends src/* PubSubService */.Rc {
|
|
|
22979
23451
|
}
|
|
22980
23452
|
|
|
22981
23453
|
// Get the appropriate dataId for this viewport/displaySet combination
|
|
22982
|
-
const dataId =
|
|
23454
|
+
const dataId = (0,getDataIdForViewport/* getDataIdForViewport */.V)(viewport, displaySetInstanceUID);
|
|
22983
23455
|
|
|
22984
23456
|
// Set properties with or without dataId based on what the viewport supports
|
|
22985
23457
|
viewport.setProperties({
|
|
@@ -23005,6 +23477,54 @@ ColorbarService.REGISTRATION = {
|
|
|
23005
23477
|
;// ../../../extensions/cornerstone/src/services/ColorbarService/index.ts
|
|
23006
23478
|
|
|
23007
23479
|
/* harmony default export */ const services_ColorbarService = (ColorbarService);
|
|
23480
|
+
;// ../../../extensions/cornerstone/src/services/ViewedDataService/ViewedDataService.ts
|
|
23481
|
+
var _ViewedDataService;
|
|
23482
|
+
|
|
23483
|
+
class ViewedDataService extends src/* PubSubService */.Rc {
|
|
23484
|
+
constructor() {
|
|
23485
|
+
super(ViewedDataService.EVENTS);
|
|
23486
|
+
this.viewedDataIds = new Set();
|
|
23487
|
+
}
|
|
23488
|
+
markDataViewed(dataId) {
|
|
23489
|
+
if (!dataId || this.viewedDataIds.has(dataId)) {
|
|
23490
|
+
return;
|
|
23491
|
+
}
|
|
23492
|
+
this.viewedDataIds.add(dataId);
|
|
23493
|
+
this._broadcastEvent(this.EVENTS.VIEWED_DATA_CHANGED, {
|
|
23494
|
+
viewedDataId: dataId
|
|
23495
|
+
});
|
|
23496
|
+
}
|
|
23497
|
+
isDataViewed(dataId) {
|
|
23498
|
+
if (!dataId) {
|
|
23499
|
+
return false;
|
|
23500
|
+
}
|
|
23501
|
+
return this.viewedDataIds.has(dataId);
|
|
23502
|
+
}
|
|
23503
|
+
clearViewedData() {
|
|
23504
|
+
this.viewedDataIds.clear();
|
|
23505
|
+
this._broadcastEvent(this.EVENTS.VIEWED_DATA_CHANGED, {
|
|
23506
|
+
viewedDataCleared: true
|
|
23507
|
+
});
|
|
23508
|
+
}
|
|
23509
|
+
subscribeViewedDataChanges(listener) {
|
|
23510
|
+
return this.subscribe(this.EVENTS.VIEWED_DATA_CHANGED, listener);
|
|
23511
|
+
}
|
|
23512
|
+
}
|
|
23513
|
+
_ViewedDataService = ViewedDataService;
|
|
23514
|
+
ViewedDataService.EVENTS = {
|
|
23515
|
+
VIEWED_DATA_CHANGED: 'event::viewedDataChanged'
|
|
23516
|
+
};
|
|
23517
|
+
ViewedDataService.REGISTRATION = {
|
|
23518
|
+
name: 'viewedDataService',
|
|
23519
|
+
altName: 'ViewedDataService',
|
|
23520
|
+
create: () => {
|
|
23521
|
+
return new _ViewedDataService();
|
|
23522
|
+
}
|
|
23523
|
+
};
|
|
23524
|
+
/* harmony default export */ const ViewedDataService_ViewedDataService = (ViewedDataService);
|
|
23525
|
+
;// ../../../extensions/cornerstone/src/services/ViewedDataService/index.ts
|
|
23526
|
+
|
|
23527
|
+
/* harmony default export */ const services_ViewedDataService = (ViewedDataService_ViewedDataService);
|
|
23008
23528
|
;// ../../../extensions/cornerstone/src/types/Presentation.ts
|
|
23009
23529
|
|
|
23010
23530
|
|
|
@@ -23249,12 +23769,114 @@ const createFrameViewSynchronizer = synchronizerName => {
|
|
|
23249
23769
|
|
|
23250
23770
|
// EXTERNAL MODULE: ../../../node_modules/dcmjs/build/dcmjs.es.js
|
|
23251
23771
|
var dcmjs_es = __webpack_require__(5842);
|
|
23772
|
+
;// ../../../extensions/cornerstone/src/utils/ecgMetadata.ts
|
|
23773
|
+
/**
|
|
23774
|
+
* Decode a multiplexed Int16 buffer into per-channel arrays.
|
|
23775
|
+
* Layout: sample0ch0, sample0ch1 ... sample0chN, sample1ch0, …
|
|
23776
|
+
* Note: DICOM ECG data is canonically SS (signed short). The sampleInterpretation
|
|
23777
|
+
* field is forwarded to ECGViewport for its own use; the raw buffer is always
|
|
23778
|
+
* treated as Int16 because Cornerstone ECGViewport expects Int16Array[].
|
|
23779
|
+
*/
|
|
23780
|
+
function decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples) {
|
|
23781
|
+
const src = new Int16Array(buffer);
|
|
23782
|
+
const channels = [];
|
|
23783
|
+
for (let ch = 0; ch < numberOfChannels; ch++) {
|
|
23784
|
+
const out = new Int16Array(numberOfSamples);
|
|
23785
|
+
for (let s = 0; s < numberOfSamples; s++) {
|
|
23786
|
+
out[s] = src[s * numberOfChannels + ch];
|
|
23787
|
+
}
|
|
23788
|
+
channels.push(out);
|
|
23789
|
+
}
|
|
23790
|
+
return channels;
|
|
23791
|
+
}
|
|
23792
|
+
|
|
23793
|
+
/**
|
|
23794
|
+
* Decode a base64 InlineBinary string into a raw ArrayBuffer.
|
|
23795
|
+
*/
|
|
23796
|
+
function base64ToArrayBuffer(base64) {
|
|
23797
|
+
const binaryStr = atob(base64);
|
|
23798
|
+
const bytes = new Uint8Array(binaryStr.length);
|
|
23799
|
+
for (let i = 0; i < binaryStr.length; i++) {
|
|
23800
|
+
bytes[i] = binaryStr.charCodeAt(i);
|
|
23801
|
+
}
|
|
23802
|
+
return bytes.buffer;
|
|
23803
|
+
}
|
|
23804
|
+
/**
|
|
23805
|
+
* Parse the naturalized DICOM instance's WaveformSequence and build the ecgModule
|
|
23806
|
+
* that Cornerstone's ECGViewport.setEcg() expects via
|
|
23807
|
+
* metaData.get(MetadataModules.ECG, imageId).
|
|
23808
|
+
*
|
|
23809
|
+
* Returns null if the instance has no WaveformSequence.
|
|
23810
|
+
*/
|
|
23811
|
+
function buildEcgModule(instance, userAuthenticationService) {
|
|
23812
|
+
const waveformGroups = instance?.WaveformSequence;
|
|
23813
|
+
if (!waveformGroups?.length) {
|
|
23814
|
+
return null;
|
|
23815
|
+
}
|
|
23816
|
+
|
|
23817
|
+
// Use the first (and typically only) multiplex group
|
|
23818
|
+
const group = waveformGroups[0];
|
|
23819
|
+
const numberOfChannels = group.NumberOfWaveformChannels ?? 0;
|
|
23820
|
+
const numberOfSamples = group.NumberOfWaveformSamples ?? 0;
|
|
23821
|
+
const samplingFrequency = group.SamplingFrequency ?? 1;
|
|
23822
|
+
const bitsAllocated = group.WaveformBitsAllocated ?? 16;
|
|
23823
|
+
const sampleInterpretation = group.WaveformSampleInterpretation ?? 'SS';
|
|
23824
|
+
const multiplexGroupLabel = group.MultiplexGroupLabel ?? '';
|
|
23825
|
+
const channelDefinitionSequence = (group.ChannelDefinitionSequence ?? []).map(ch => ({
|
|
23826
|
+
channelSourceSequence: {
|
|
23827
|
+
codeMeaning: ch?.ChannelSourceSequence?.[0]?.CodeMeaning ?? ch?.ChannelSourceSequence?.[0]?.codeMeaning ?? ''
|
|
23828
|
+
}
|
|
23829
|
+
}));
|
|
23830
|
+
const retrieveBulkData = async () => {
|
|
23831
|
+
const waveformData = group.WaveformData;
|
|
23832
|
+
if (!waveformData) {
|
|
23833
|
+
console.warn('[ECGViewport] No WaveformData found on instance');
|
|
23834
|
+
return [];
|
|
23835
|
+
}
|
|
23836
|
+
let buffer;
|
|
23837
|
+
if (waveformData.InlineBinary) {
|
|
23838
|
+
buffer = base64ToArrayBuffer(waveformData.InlineBinary);
|
|
23839
|
+
} else if (waveformData.BulkDataURI) {
|
|
23840
|
+
const headers = {
|
|
23841
|
+
Accept: 'application/octet-stream'
|
|
23842
|
+
};
|
|
23843
|
+
const authHeader = userAuthenticationService?.getAuthorizationHeader?.();
|
|
23844
|
+
if (authHeader) {
|
|
23845
|
+
Object.assign(headers, authHeader);
|
|
23846
|
+
}
|
|
23847
|
+
const response = await fetch(waveformData.BulkDataURI, {
|
|
23848
|
+
headers
|
|
23849
|
+
});
|
|
23850
|
+
if (!response.ok) {
|
|
23851
|
+
throw new Error(`[ECGViewport] Failed to fetch waveform BulkDataURI: ${response.status}`);
|
|
23852
|
+
}
|
|
23853
|
+
buffer = await response.arrayBuffer();
|
|
23854
|
+
} else {
|
|
23855
|
+
console.warn('[ECGViewport] WaveformData has no InlineBinary or BulkDataURI');
|
|
23856
|
+
return [];
|
|
23857
|
+
}
|
|
23858
|
+
return decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples);
|
|
23859
|
+
};
|
|
23860
|
+
return {
|
|
23861
|
+
numberOfWaveformChannels: numberOfChannels,
|
|
23862
|
+
numberOfWaveformSamples: numberOfSamples,
|
|
23863
|
+
samplingFrequency,
|
|
23864
|
+
waveformBitsAllocated: bitsAllocated,
|
|
23865
|
+
waveformSampleInterpretation: sampleInterpretation,
|
|
23866
|
+
multiplexGroupLabel,
|
|
23867
|
+
channelDefinitionSequence,
|
|
23868
|
+
waveformData: {
|
|
23869
|
+
retrieveBulkData
|
|
23870
|
+
}
|
|
23871
|
+
};
|
|
23872
|
+
}
|
|
23252
23873
|
;// ../../../extensions/cornerstone/src/getSopClassHandlerModule.js
|
|
23253
23874
|
|
|
23254
23875
|
|
|
23255
23876
|
|
|
23256
23877
|
|
|
23257
23878
|
|
|
23879
|
+
|
|
23258
23880
|
const {
|
|
23259
23881
|
MetadataModules
|
|
23260
23882
|
} = esm.Enums;
|
|
@@ -23265,9 +23887,9 @@ const {
|
|
|
23265
23887
|
denaturalizeDataset
|
|
23266
23888
|
} = dcmjs_es/* default.data */.Ay.data.DicomMetaDictionary;
|
|
23267
23889
|
const {
|
|
23268
|
-
transferDenaturalizedDataset,
|
|
23269
|
-
fixMultiValueKeys
|
|
23270
|
-
} = default_src
|
|
23890
|
+
/* transferDenaturalizedDataset */ "If": transferDenaturalizedDataset,
|
|
23891
|
+
/* fixMultiValueKeys */ "Uk": fixMultiValueKeys
|
|
23892
|
+
} = default_src/* dicomWebUtils */.CA;
|
|
23271
23893
|
const SOP_CLASS_UIDS = {
|
|
23272
23894
|
VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE: '1.2.840.10008.5.1.4.1.1.77.1.6'
|
|
23273
23895
|
};
|
|
@@ -23393,8 +24015,92 @@ function getDicomMicroscopySopClassHandler({
|
|
|
23393
24015
|
getDisplaySetsFromSeries
|
|
23394
24016
|
};
|
|
23395
24017
|
}
|
|
24018
|
+
|
|
24019
|
+
/**
|
|
24020
|
+
* DICOM Waveform SOP Class UIDs for ECG / cardiac electrophysiology.
|
|
24021
|
+
* Reference: https://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_B.5.html
|
|
24022
|
+
*/
|
|
24023
|
+
const ECG_SOP_CLASS_UIDS = {
|
|
24024
|
+
TWELVE_LEAD_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.1',
|
|
24025
|
+
GENERAL_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.2',
|
|
24026
|
+
AMBULATORY_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.3',
|
|
24027
|
+
HEMODYNAMIC_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.2.1',
|
|
24028
|
+
CARDIAC_ELECTROPHYSIOLOGY_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.3.1'
|
|
24029
|
+
};
|
|
24030
|
+
const ecgSopClassUids = Object.values(ECG_SOP_CLASS_UIDS);
|
|
24031
|
+
const DicomEcgSOPClassHandlerId = '@ohif/extension-cornerstone.sopClassHandlerModule.DicomEcgSopClassHandler';
|
|
24032
|
+
function _getEcgDisplaySetsFromSeries(instances, servicesManager) {
|
|
24033
|
+
const {
|
|
24034
|
+
userAuthenticationService
|
|
24035
|
+
} = servicesManager.services;
|
|
24036
|
+
return instances.map(instance => {
|
|
24037
|
+
const {
|
|
24038
|
+
Modality,
|
|
24039
|
+
SOPInstanceUID
|
|
24040
|
+
} = instance;
|
|
24041
|
+
const {
|
|
24042
|
+
SeriesDescription,
|
|
24043
|
+
SeriesNumber,
|
|
24044
|
+
SeriesDate
|
|
24045
|
+
} = instance;
|
|
24046
|
+
const {
|
|
24047
|
+
SeriesInstanceUID,
|
|
24048
|
+
StudyInstanceUID,
|
|
24049
|
+
SOPClassUID
|
|
24050
|
+
} = instance;
|
|
24051
|
+
const imageId = instance.imageId;
|
|
24052
|
+
|
|
24053
|
+
// Register ECG metadata in the OHIF metadata provider so that
|
|
24054
|
+
// Cornerstone's ECGViewport can retrieve it via metaData.get('ecgModule', imageId).
|
|
24055
|
+
if (imageId) {
|
|
24056
|
+
const ecgModule = buildEcgModule(instance, userAuthenticationService);
|
|
24057
|
+
if (ecgModule) {
|
|
24058
|
+
esm.utilities.genericMetadataProvider.addRaw(imageId, {
|
|
24059
|
+
type: MetadataModules.ECG,
|
|
24060
|
+
metadata: ecgModule
|
|
24061
|
+
});
|
|
24062
|
+
}
|
|
24063
|
+
}
|
|
24064
|
+
return {
|
|
24065
|
+
Modality,
|
|
24066
|
+
displaySetInstanceUID: getSopClassHandlerModule_utils.guid(),
|
|
24067
|
+
SeriesDescription,
|
|
24068
|
+
SeriesNumber,
|
|
24069
|
+
SeriesDate,
|
|
24070
|
+
SOPInstanceUID,
|
|
24071
|
+
SeriesInstanceUID,
|
|
24072
|
+
StudyInstanceUID,
|
|
24073
|
+
SOPClassHandlerId: DicomEcgSOPClassHandlerId,
|
|
24074
|
+
SOPClassUID,
|
|
24075
|
+
referencedImages: null,
|
|
24076
|
+
measurements: null,
|
|
24077
|
+
viewportType: esm.Enums.ViewportType.ECG,
|
|
24078
|
+
instances: [instance],
|
|
24079
|
+
instance,
|
|
24080
|
+
thumbnailSrc: null,
|
|
24081
|
+
isDerivedDisplaySet: false,
|
|
24082
|
+
isLoaded: false,
|
|
24083
|
+
sopClassUids: ecgSopClassUids,
|
|
24084
|
+
numImageFrames: 0,
|
|
24085
|
+
numInstances: 1,
|
|
24086
|
+
imageIds: imageId ? [imageId] : [],
|
|
24087
|
+
supportsWindowLevel: false,
|
|
24088
|
+
label: SeriesDescription || 'ECG'
|
|
24089
|
+
};
|
|
24090
|
+
});
|
|
24091
|
+
}
|
|
24092
|
+
function getDicomEcgSopClassHandler({
|
|
24093
|
+
servicesManager
|
|
24094
|
+
}) {
|
|
24095
|
+
const getDisplaySetsFromSeries = instances => _getEcgDisplaySetsFromSeries(instances, servicesManager);
|
|
24096
|
+
return {
|
|
24097
|
+
name: 'DicomEcgSopClassHandler',
|
|
24098
|
+
sopClassUids: ecgSopClassUids,
|
|
24099
|
+
getDisplaySetsFromSeries
|
|
24100
|
+
};
|
|
24101
|
+
}
|
|
23396
24102
|
function getSopClassHandlerModule(params) {
|
|
23397
|
-
return [getDicomMicroscopySopClassHandler(params)];
|
|
24103
|
+
return [getDicomMicroscopySopClassHandler(params), getDicomEcgSopClassHandler(params)];
|
|
23398
24104
|
}
|
|
23399
24105
|
// EXTERNAL MODULE: ../../../extensions/cornerstone/src/hooks/useActiveViewportSegmentationRepresentations.ts
|
|
23400
24106
|
var useActiveViewportSegmentationRepresentations = __webpack_require__(9234);
|
|
@@ -23424,7 +24130,7 @@ function SegmentationUtilityButton(props) {
|
|
|
23424
24130
|
isActive,
|
|
23425
24131
|
id
|
|
23426
24132
|
} = props;
|
|
23427
|
-
const activeSegmentationUtility = (0,default_src
|
|
24133
|
+
const activeSegmentationUtility = (0,default_src/* useUIStateStore */.FS)(store => store.uiState.activeSegmentationUtility);
|
|
23428
24134
|
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
24135
|
const handleMouseDownCapture = (0,react.useCallback)(event => {
|
|
23430
24136
|
if (activeSegmentationUtility === id) {
|
|
@@ -23555,7 +24261,7 @@ function PanelSegmentation({
|
|
|
23555
24261
|
segmentationsWithRepresentations,
|
|
23556
24262
|
disabled
|
|
23557
24263
|
} = (0,useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c)();
|
|
23558
|
-
const setUIState = (0,default_src
|
|
24264
|
+
const setUIState = (0,default_src/* useUIStateStore */.FS)(store => store.setUIState);
|
|
23559
24265
|
|
|
23560
24266
|
// useEffect for handling clicks on any of the non-active viewports.
|
|
23561
24267
|
// The ViewportGrid stops the propagation of pointer/mouse events
|
|
@@ -23816,7 +24522,7 @@ function PanelSegmentation({
|
|
|
23816
24522
|
IconContainer: components_SegmentationUtilityButton
|
|
23817
24523
|
}, /*#__PURE__*/react.createElement("div", {
|
|
23818
24524
|
className: "flex flex-wrap gap-[3px] bg-transparent pb-[2px] pl-[8px] pt-[6px]"
|
|
23819
|
-
}, /*#__PURE__*/react.createElement(default_src
|
|
24525
|
+
}, /*#__PURE__*/react.createElement(default_src/* Toolbar */.M7, {
|
|
23820
24526
|
buttonSection: buttonSection
|
|
23821
24527
|
})));
|
|
23822
24528
|
};
|
|
@@ -24343,12 +25049,12 @@ function DefaultAccordion(props) {
|
|
|
24343
25049
|
if (!allChildren || !groups) {
|
|
24344
25050
|
return null;
|
|
24345
25051
|
}
|
|
24346
|
-
if (
|
|
25052
|
+
if (asChild) {
|
|
24347
25053
|
return /*#__PURE__*/react.cloneElement(props.children, props);
|
|
24348
25054
|
}
|
|
24349
25055
|
return /*#__PURE__*/react.createElement(ui_next_src/* Accordion */.nD3, {
|
|
24350
25056
|
type: grouping.type || 'multiple',
|
|
24351
|
-
className: "text-
|
|
25057
|
+
className: "text-foreground",
|
|
24352
25058
|
defaultValue: defaultValue
|
|
24353
25059
|
}, [...groups.entries()].map(([key, group]) => {
|
|
24354
25060
|
return /*#__PURE__*/react.createElement(ui_next_src/* AccordionItem */.AsP, {
|
|
@@ -24826,7 +25532,7 @@ function PanelMeasurement(props) {
|
|
|
24826
25532
|
return EmptyComponent ? /*#__PURE__*/react.createElement(EmptyComponent, {
|
|
24827
25533
|
items: displayMeasurements
|
|
24828
25534
|
}) : /*#__PURE__*/react.createElement("span", {
|
|
24829
|
-
className: "text-
|
|
25535
|
+
className: "text-foreground"
|
|
24830
25536
|
}, "No Measurements");
|
|
24831
25537
|
}
|
|
24832
25538
|
if (children) {
|
|
@@ -24891,7 +25597,7 @@ const getPanelModule = ({
|
|
|
24891
25597
|
} = (0,es/* useTranslation */.Bd)('SegmentationPanel');
|
|
24892
25598
|
const tKey = `${props.segmentationRepresentationTypes?.[0] ?? 'Segmentation'} tools`;
|
|
24893
25599
|
const tValue = t(tKey);
|
|
24894
|
-
return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src
|
|
25600
|
+
return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src/* Toolbox */.OO, {
|
|
24895
25601
|
buttonSectionId: toolSectionMap[props.segmentationRepresentationTypes?.[0]],
|
|
24896
25602
|
title: tValue
|
|
24897
25603
|
}), /*#__PURE__*/react.createElement(PanelSegmentation, {
|
|
@@ -25245,7 +25951,7 @@ function promptHydrationDialog({
|
|
|
25245
25951
|
customizationService
|
|
25246
25952
|
} = servicesManager.services;
|
|
25247
25953
|
const extensionManager = servicesManager._extensionManager;
|
|
25248
|
-
const appConfig = extensionManager.
|
|
25954
|
+
const appConfig = extensionManager.appConfig;
|
|
25249
25955
|
|
|
25250
25956
|
// Todo: make this use enum from the extension, we should move the enum
|
|
25251
25957
|
const standardMode = appConfig?.measurementTrackingMode === 'standard';
|
|
@@ -25262,20 +25968,30 @@ function promptHydrationDialog({
|
|
|
25262
25968
|
if (type === HydrationType.SEG) {
|
|
25263
25969
|
// SEG needs setTimeout
|
|
25264
25970
|
window.setTimeout(async () => {
|
|
25265
|
-
|
|
25266
|
-
|
|
25267
|
-
|
|
25268
|
-
|
|
25269
|
-
|
|
25971
|
+
try {
|
|
25972
|
+
const isHydrated = await hydrateCallback({
|
|
25973
|
+
segDisplaySet: displaySet,
|
|
25974
|
+
viewportId
|
|
25975
|
+
});
|
|
25976
|
+
resolve(isHydrated);
|
|
25977
|
+
} catch (error) {
|
|
25978
|
+
reject(error);
|
|
25979
|
+
}
|
|
25270
25980
|
}, 0);
|
|
25271
25981
|
} else if (type === HydrationType.RTSTRUCT) {
|
|
25272
25982
|
// RT hydration
|
|
25273
|
-
|
|
25274
|
-
|
|
25275
|
-
|
|
25276
|
-
|
|
25277
|
-
|
|
25278
|
-
|
|
25983
|
+
window.setTimeout(async () => {
|
|
25984
|
+
try {
|
|
25985
|
+
const isHydrated = await hydrateCallback({
|
|
25986
|
+
rtDisplaySet: displaySet,
|
|
25987
|
+
viewportId,
|
|
25988
|
+
servicesManager
|
|
25989
|
+
});
|
|
25990
|
+
resolve(isHydrated);
|
|
25991
|
+
} catch (error) {
|
|
25992
|
+
reject(error);
|
|
25993
|
+
}
|
|
25994
|
+
}, 0);
|
|
25279
25995
|
} else if (type === HydrationType.SR) {
|
|
25280
25996
|
// SR has a different result structure
|
|
25281
25997
|
const hydrationResult = await hydrateCallback(displaySet);
|
|
@@ -25368,7 +26084,8 @@ const setUpSegmentationEventHandlers = ({
|
|
|
25368
26084
|
const {
|
|
25369
26085
|
segmentationService,
|
|
25370
26086
|
customizationService,
|
|
25371
|
-
displaySetService
|
|
26087
|
+
displaySetService,
|
|
26088
|
+
viewportGridService
|
|
25372
26089
|
} = servicesManager.services;
|
|
25373
26090
|
const {
|
|
25374
26091
|
unsubscribe: unsubscribeSegmentationDataModifiedHandler
|
|
@@ -25413,12 +26130,42 @@ const setUpSegmentationEventHandlers = ({
|
|
|
25413
26130
|
};
|
|
25414
26131
|
displaySetService.addDisplaySets(segmentationDisplaySet);
|
|
25415
26132
|
});
|
|
26133
|
+
const {
|
|
26134
|
+
unsubscribe: unsubscribeSegmentationRemoved
|
|
26135
|
+
} = segmentationService.subscribe(segmentationService.EVENTS.SEGMENTATION_REMOVED, ({
|
|
26136
|
+
segmentationId
|
|
26137
|
+
}) => {
|
|
26138
|
+
const displaySet = displaySetService.getDisplaySetByUID(segmentationId);
|
|
26139
|
+
|
|
26140
|
+
// Remove the display set layer from all viewports that have it
|
|
26141
|
+
if (displaySet) {
|
|
26142
|
+
const state = viewportGridService.getState();
|
|
26143
|
+
const viewports = state.viewports;
|
|
26144
|
+
|
|
26145
|
+
// Find all viewports that contain this segmentation's display set as a layer
|
|
26146
|
+
for (const [viewportId, viewport] of viewports.entries()) {
|
|
26147
|
+
const displaySetInstanceUIDs = viewport.displaySetInstanceUIDs || [];
|
|
26148
|
+
if (displaySetInstanceUIDs.includes(segmentationId)) {
|
|
26149
|
+
// Remove the display set layer from this viewport
|
|
26150
|
+
commandsManager.runCommand('removeDisplaySetLayer', {
|
|
26151
|
+
viewportId,
|
|
26152
|
+
displaySetInstanceUID: segmentationId
|
|
26153
|
+
});
|
|
26154
|
+
}
|
|
26155
|
+
}
|
|
26156
|
+
|
|
26157
|
+
// Delete the display set from the service if it was made in client
|
|
26158
|
+
if (displaySet.madeInClient) {
|
|
26159
|
+
displaySetService.deleteDisplaySet(segmentationId);
|
|
26160
|
+
}
|
|
26161
|
+
}
|
|
26162
|
+
});
|
|
25416
26163
|
const {
|
|
25417
26164
|
unsubscribeSelectedSegmentationsForViewportEvents
|
|
25418
26165
|
} = setUpSelectedSegmentationsForViewportHandler({
|
|
25419
26166
|
segmentationService
|
|
25420
26167
|
});
|
|
25421
|
-
const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, ...unsubscribeSelectedSegmentationsForViewportEvents];
|
|
26168
|
+
const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, unsubscribeSegmentationRemoved, ...unsubscribeSelectedSegmentationsForViewportEvents];
|
|
25422
26169
|
return {
|
|
25423
26170
|
unsubscriptions
|
|
25424
26171
|
};
|
|
@@ -25561,7 +26308,7 @@ function PanelAccordionTrigger(props) {
|
|
|
25561
26308
|
}, /*#__PURE__*/react.createElement("button", {
|
|
25562
26309
|
onClick: onClickDefault.bind(props)
|
|
25563
26310
|
}, /*#__PURE__*/react.createElement("span", {
|
|
25564
|
-
className: `inline-flex rounded-l border-r border-
|
|
26311
|
+
className: `inline-flex rounded-l border-r border-background ${isActive ? 'bg-highlight' : 'bg-muted'}`
|
|
25565
26312
|
}, count !== undefined ? /*#__PURE__*/react.createElement("span", {
|
|
25566
26313
|
className: "px-2"
|
|
25567
26314
|
}, count) : null, colorHex && /*#__PURE__*/react.createElement(ui_next_src/* ColorCircle */.cd8, {
|
|
@@ -25810,13 +26557,14 @@ function src_extends() { return src_extends = Object.assign ? Object.assign.bind
|
|
|
25810
26557
|
|
|
25811
26558
|
|
|
25812
26559
|
|
|
26560
|
+
|
|
25813
26561
|
|
|
25814
26562
|
|
|
25815
26563
|
const {
|
|
25816
26564
|
imageRetrieveMetadataProvider
|
|
25817
26565
|
} = esm.utilities;
|
|
25818
26566
|
const Component = /*#__PURE__*/react.lazy(() => {
|
|
25819
|
-
return __webpack_require__.e(/* import() */
|
|
26567
|
+
return __webpack_require__.e(/* import() */ 3754).then(__webpack_require__.bind(__webpack_require__, 33754));
|
|
25820
26568
|
});
|
|
25821
26569
|
const OHIFCornerstoneViewport = props => {
|
|
25822
26570
|
return /*#__PURE__*/react.createElement(react.Suspense, {
|
|
@@ -25909,9 +26657,10 @@ const cornerstoneExtension = {
|
|
|
25909
26657
|
useLutPresentationStore/* useLutPresentationStore */.I.getState().clearLutPresentationStore();
|
|
25910
26658
|
usePositionPresentationStore/* usePositionPresentationStore */.q.getState().clearPositionPresentationStore();
|
|
25911
26659
|
useSynchronizersStore/* useSynchronizersStore */.U.getState().clearSynchronizersStore();
|
|
25912
|
-
default_src
|
|
26660
|
+
default_src/* useToggleOneUpViewportGridStore */.Yd.getState().clearToggleOneUpViewportGridStore();
|
|
25913
26661
|
useSegmentationPresentationStore/* useSegmentationPresentationStore */.v.getState().clearSegmentationPresentationStore();
|
|
25914
26662
|
useSelectedSegmentationsForViewportStore.getState().clearSelectedSegmentationsForViewportStore();
|
|
26663
|
+
servicesManager.services.viewedDataService?.clearViewedData();
|
|
25915
26664
|
segmentationService.removeAllSegmentations();
|
|
25916
26665
|
},
|
|
25917
26666
|
/**
|
|
@@ -25929,6 +26678,7 @@ const cornerstoneExtension = {
|
|
|
25929
26678
|
servicesManager.registerService(services_SegmentationService.REGISTRATION);
|
|
25930
26679
|
servicesManager.registerService(services_CornerstoneCacheService.REGISTRATION);
|
|
25931
26680
|
servicesManager.registerService(services_ColorbarService.REGISTRATION);
|
|
26681
|
+
servicesManager.registerService(services_ViewedDataService.REGISTRATION);
|
|
25932
26682
|
const {
|
|
25933
26683
|
syncGroupService
|
|
25934
26684
|
} = servicesManager.services;
|
|
@@ -26000,10 +26750,10 @@ const cornerstoneExtension = {
|
|
|
26000
26750
|
|
|
26001
26751
|
/* harmony default export */ const cornerstone_src = (cornerstoneExtension);
|
|
26002
26752
|
|
|
26003
|
-
/***/ }
|
|
26753
|
+
/***/ },
|
|
26004
26754
|
|
|
26005
|
-
/***/ 71353
|
|
26006
|
-
|
|
26755
|
+
/***/ 71353
|
|
26756
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26007
26757
|
|
|
26008
26758
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
26009
26759
|
/* harmony export */ cL: () => (/* binding */ reset),
|
|
@@ -26042,10 +26792,10 @@ const reset = () => {
|
|
|
26042
26792
|
};
|
|
26043
26793
|
|
|
26044
26794
|
|
|
26045
|
-
/***/ }
|
|
26795
|
+
/***/ },
|
|
26046
26796
|
|
|
26047
|
-
/***/ 46026
|
|
26048
|
-
|
|
26797
|
+
/***/ 46026
|
|
26798
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26049
26799
|
|
|
26050
26800
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
26051
26801
|
/* harmony export */ FG: () => (/* binding */ JOIN_STR),
|
|
@@ -26085,10 +26835,10 @@ const addUniqueIndex = (arr, key, viewports, isUpdatingSameViewport) => {
|
|
|
26085
26835
|
};
|
|
26086
26836
|
|
|
26087
26837
|
|
|
26088
|
-
/***/ }
|
|
26838
|
+
/***/ },
|
|
26089
26839
|
|
|
26090
|
-
/***/ 10182
|
|
26091
|
-
|
|
26840
|
+
/***/ 10182
|
|
26841
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26092
26842
|
|
|
26093
26843
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
26094
26844
|
/* harmony export */ I: () => (/* binding */ useLutPresentationStore)
|
|
@@ -26200,10 +26950,10 @@ const useLutPresentationStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .creat
|
|
|
26200
26950
|
name: 'LutPresentationStore'
|
|
26201
26951
|
}) : createLutPresentationStore);
|
|
26202
26952
|
|
|
26203
|
-
/***/ }
|
|
26953
|
+
/***/ },
|
|
26204
26954
|
|
|
26205
|
-
/***/ 44646
|
|
26206
|
-
|
|
26955
|
+
/***/ 44646
|
|
26956
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26207
26957
|
|
|
26208
26958
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
26209
26959
|
/* harmony export */ q: () => (/* binding */ usePositionPresentationStore)
|
|
@@ -26311,10 +27061,10 @@ const usePositionPresentationStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .
|
|
|
26311
27061
|
name: 'PositionPresentationStore'
|
|
26312
27062
|
}) : createPositionPresentationStore);
|
|
26313
27063
|
|
|
26314
|
-
/***/ }
|
|
27064
|
+
/***/ },
|
|
26315
27065
|
|
|
26316
|
-
/***/ 2847
|
|
26317
|
-
|
|
27066
|
+
/***/ 2847
|
|
27067
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26318
27068
|
|
|
26319
27069
|
|
|
26320
27070
|
// EXPORTS
|
|
@@ -26426,20 +27176,34 @@ const _getSegmentationPresentationId = ({
|
|
|
26426
27176
|
if (!viewport?.viewportOptions || !viewport.displaySetInstanceUIDs?.length) {
|
|
26427
27177
|
return;
|
|
26428
27178
|
}
|
|
27179
|
+
const {
|
|
27180
|
+
displaySetService
|
|
27181
|
+
} = servicesManager.services;
|
|
26429
27182
|
const {
|
|
26430
27183
|
displaySetInstanceUIDs,
|
|
26431
27184
|
viewportOptions
|
|
26432
27185
|
} = viewport;
|
|
27186
|
+
|
|
27187
|
+
// Match keys used by updateStoredSegmentationPresentation (referenced volume only).
|
|
27188
|
+
// Including overlay UIDs (e.g. SEG) produced ids like "MR&SEG" while the store
|
|
27189
|
+
// entry is under "MR", so hydrated segmentations never applied and viewports could mis-render.
|
|
27190
|
+
const nonOverlayUIDs = displaySetInstanceUIDs.filter(uid => {
|
|
27191
|
+
const ds = displaySetService.getDisplaySetByUID(uid);
|
|
27192
|
+
return ds && !ds.isOverlayDisplaySet;
|
|
27193
|
+
});
|
|
27194
|
+
if (!nonOverlayUIDs.length) {
|
|
27195
|
+
return;
|
|
27196
|
+
}
|
|
26433
27197
|
let orientation = viewportOptions.orientation;
|
|
26434
27198
|
if (!orientation) {
|
|
26435
27199
|
// Calculate orientation from the viewport sample image
|
|
26436
|
-
const displaySet =
|
|
26437
|
-
const sampleImage = displaySet
|
|
27200
|
+
const displaySet = displaySetService.getDisplaySetByUID(nonOverlayUIDs[0]);
|
|
27201
|
+
const sampleImage = displaySet?.images?.[0];
|
|
26438
27202
|
const imageOrientationPatient = sampleImage?.ImageOrientationPatient;
|
|
26439
27203
|
orientation = getViewportOrientationFromImageOrientationPatient(imageOrientationPatient);
|
|
26440
27204
|
}
|
|
26441
27205
|
const segmentationPresentationArr = [];
|
|
26442
|
-
segmentationPresentationArr.push(...
|
|
27206
|
+
segmentationPresentationArr.push(...nonOverlayUIDs);
|
|
26443
27207
|
|
|
26444
27208
|
// Uncomment if unique indexing is needed
|
|
26445
27209
|
// addUniqueIndex(
|
|
@@ -26520,10 +27284,10 @@ const useSegmentationPresentationStore = (0,esm/* create */.vt)()(DEBUG_STORE ?
|
|
|
26520
27284
|
name: 'Segmentation Presentation Store'
|
|
26521
27285
|
}) : createSegmentationPresentationStore);
|
|
26522
27286
|
|
|
26523
|
-
/***/ }
|
|
27287
|
+
/***/ },
|
|
26524
27288
|
|
|
26525
|
-
/***/ 68578
|
|
26526
|
-
|
|
27289
|
+
/***/ 68578
|
|
27290
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
26527
27291
|
|
|
26528
27292
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
26529
27293
|
/* harmony export */ U: () => (/* binding */ useSynchronizersStore)
|
|
@@ -26584,6 +27348,32 @@ const useSynchronizersStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .create
|
|
|
26584
27348
|
name: 'SynchronizersStore'
|
|
26585
27349
|
}) : createSynchronizersStore);
|
|
26586
27350
|
|
|
26587
|
-
/***/ }
|
|
27351
|
+
/***/ },
|
|
27352
|
+
|
|
27353
|
+
/***/ 67142
|
|
27354
|
+
(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
|
27355
|
+
|
|
27356
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
27357
|
+
/* harmony export */ V: () => (/* binding */ getDataIdForViewport)
|
|
27358
|
+
/* harmony export */ });
|
|
27359
|
+
/**
|
|
27360
|
+
* Resolves the data ID (e.g. volumeId) for a viewport and display set.
|
|
27361
|
+
* For viewports with multiple volumes/actors, returns the id that matches the display set; otherwise undefined.
|
|
27362
|
+
* Use this to call viewport.getProperties(dataId) in a viewport-type-agnostic way.
|
|
27363
|
+
*
|
|
27364
|
+
* @param viewport - Viewport instance (stack, volume, or future types with optional getAllVolumeIds)
|
|
27365
|
+
* @param displaySetInstanceUID - Display set instance UID to match
|
|
27366
|
+
* @returns volumeId (or equivalent) for multi-actor viewports, undefined for single-actor
|
|
27367
|
+
*/
|
|
27368
|
+
function getDataIdForViewport(viewport, displaySetInstanceUID) {
|
|
27369
|
+
const vp = viewport;
|
|
27370
|
+
if (typeof vp.getAllVolumeIds !== 'function') {
|
|
27371
|
+
return undefined;
|
|
27372
|
+
}
|
|
27373
|
+
const volumeIds = vp.getAllVolumeIds() || [];
|
|
27374
|
+
return volumeIds.length > 0 ? volumeIds.find(id => id.includes(displaySetInstanceUID)) ?? undefined : undefined;
|
|
27375
|
+
}
|
|
27376
|
+
|
|
27377
|
+
/***/ }
|
|
26588
27378
|
|
|
26589
27379
|
}]);
|