@ohif/app 3.7.0-beta.8 → 3.7.0-beta.81
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/{917.bundle.d238efac58b7fe8fd1a3.js → 12.bundle.f5ca9901f923a487d8b3.js} +6 -6
- package/dist/{295.bundle.957b1159fec14b9199a1.js → 125.bundle.253395f320b72180da63.js} +6 -6
- package/dist/{208.bundle.37c2a73b3387e657568c.js → 128.bundle.2dfd63dcf3b846809dfb.js} +41 -59
- package/dist/{351.bundle.0742237651aef9694a65.js → 181.bundle.fa57199595cf28f44c7b.js} +226 -204
- package/dist/{351.css → 181.css} +1 -1
- package/dist/{744.bundle.23011553706b687f67e4.js → 19.bundle.0d74cbc1db3841b851a6.js} +240 -375
- package/dist/{606.bundle.5d876f5f3dd8287f0a28.js → 202.bundle.96bbb4547a346fe3921f.js} +1420 -750
- package/dist/{926.bundle.dbc9d0e591cb9217fda2.js → 220.bundle.f7e1c96c94245e70f2be.js} +990 -400
- package/dist/221.bundle.933ef6dcf6d29eea0259.js +1722 -0
- package/dist/221.css +2 -0
- package/dist/{664.bundle.09abae984223969d1bde.js → 23.bundle.e008ad788170f2ed5569.js} +5 -6
- package/dist/{976.bundle.dcbddf56a7d8f388bb8a.js → 236.bundle.3f6a0e3dd259bc60d4d0.js} +87 -103
- package/dist/{55.bundle.550a823e75eb608e8d5e.js → 250.bundle.36909d7bc681d66087d1.js} +52 -36
- package/dist/{973.bundle.03b016e6095622adf12f.js → 281.bundle.69d85dc35d1bc1335fbd.js} +18 -14
- package/dist/{82.bundle.10c2133333748ec6fba0.js → 342.bundle.46b3527fb38b74a044e8.js} +1768 -475
- package/dist/{192.bundle.2dc14a6e3c4c6be913b0.js → 348.bundle.46d4c41b9ae681c50903.js} +86 -73
- package/dist/{404.bundle.5d57295bc05206092d42.js → 359.bundle.408fa86b95fd1597552c.js} +46 -131
- package/dist/{790.bundle.cedf27deeed29266a92b.js → 410.bundle.bf702dcec9db605d0d72.js} +11 -9
- package/dist/{151.bundle.31ea35044218837bf73f.js → 417.bundle.af0a207c29b109f84159.js} +49 -17
- package/dist/{569.bundle.c8e771a8d28e237b32be.js → 451.bundle.dc0d14c3724464cca2bf.js} +86 -106
- package/dist/{581.bundle.dc6197189f7c88c27d4c.js → 471.bundle.2206d4c0ac2ad0df2362.js} +78 -99
- package/dist/{199.bundle.e4ac6606dd62e42e9da4.js → 506.bundle.90364a62dcd8e433c1a4.js} +11 -9
- package/dist/{531.bundle.2a82fb1d69e5b57cc72b.js → 530.bundle.a03b6f942ace3e1baa1e.js} +726 -447
- package/dist/579.css +1 -0
- package/dist/{935.bundle.deeffff0e4f7b528e3c3.js → 604.bundle.a51f83e64004bca5f497.js} +2 -3
- package/dist/613.bundle.a06431b9a1b14cb8f469.js +532 -0
- package/dist/{984.bundle.e7dcbd3b8992748823fb.js → 663.bundle.482bdfb562bfb3700c55.js} +68 -38
- package/dist/{205.bundle.b5a473c200dcf2bbcdb4.js → 686.bundle.dccef1f36e4bc79bcc48.js} +6 -6
- package/dist/{50.bundle.424f8d05f1bebaafcf2c.js → 687.bundle.b456dd5eae1afeaab05d.js} +218 -9
- package/dist/{331.bundle.bd0c13931a21d53086c9.js → 754.bundle.e3ce6855d8d4d187f224.js} +12423 -7549
- package/dist/{728.bundle.d13856835357400fef82.js → 774.bundle.d365320749c4f67cda70.js} +93 -64
- package/dist/{381.bundle.0905e683605fcbc0895f.js → 775.bundle.2285e7e0e67878948c0d.js} +16 -16
- package/dist/{270.bundle.4564621556b0f963a004.js → 777.bundle.ae3fdb8a470caecc0c6a.js} +1330 -929
- package/dist/{283.bundle.085cddb2f16e430677b0.js → 782.bundle.742caefc99a1393225d2.js} +117 -67
- package/dist/{642.bundle.25e56df5f0bcd2c729b4.js → 814.bundle.f84f8c34cd82d9456367.js} +6 -6
- package/dist/{799.bundle.758558e64147e5aad612.js → 822.bundle.5fca45a4f40f5259aec5.js} +81 -34
- package/dist/831.bundle.83658f62fcc769043605.js +16700 -0
- package/dist/{953.bundle.3b0189ebc11cf0946f18.js → 886.bundle.a9de117c3a42b7907cf6.js} +34 -29
- package/dist/945.min.worker.js +1 -1
- package/dist/945.min.worker.js.map +1 -1
- package/dist/{707.bundle.17a9d7352409b6269596.js → 967.bundle.aa7e40475fa7cab0726e.js} +895 -572
- package/dist/_redirects +1 -1
- package/dist/app-config.js +35 -17
- package/dist/{app.bundle.837996a8f7dd2aaac338.js → app.bundle.91713b6c13b1264236f9.js} +73339 -68140
- package/dist/app.bundle.css +13 -12
- package/dist/assets/yandex-browser-manifest.json +1 -1
- package/dist/cornerstoneDICOMImageLoader.min.js +1 -1
- package/dist/cornerstoneDICOMImageLoader.min.js.map +1 -1
- package/dist/{dicom-microscopy-viewer.bundle.aa60bdf008c32c39cfd7.js → dicom-microscopy-viewer.bundle.2c146384eb9466d02ff8.js} +5 -4
- package/dist/es6-shim.min.js +3569 -2
- package/dist/google.js +8 -7
- package/dist/index.html +1 -1
- package/dist/{index.worker.1c69152d710fa7b84bce.worker.js → index.worker.e62ecca63f1a2e124230.worker.js} +2 -2
- package/dist/index.worker.e62ecca63f1a2e124230.worker.js.map +1 -0
- package/dist/init-service-worker.js +3 -5
- package/dist/oidc-client.min.js +10857 -39
- package/dist/polyfill.min.js +184 -1
- package/dist/silent-refresh.html +18 -9
- package/dist/sw.js +1 -1
- package/package.json +20 -21
- package/dist/616.bundle.eb4887184da6c57bf7a3.js +0 -685
- package/dist/780.bundle.fd0f13dc92e9caa0581e.js +0 -4769
- package/dist/index.worker.1c69152d710fa7b84bce.worker.js.map +0 -1
- /package/dist/{806.css → 19.css} +0 -0
- /package/dist/{55.css → 250.css} +0 -0
- /package/dist/{707.css → 967.css} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
(
|
|
1
|
+
(self["webpackChunk"] = self["webpackChunk"] || []).push([[967],{
|
|
2
2
|
|
|
3
|
-
/***/
|
|
3
|
+
/***/ 94004:
|
|
4
4
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
5
5
|
|
|
6
6
|
"use strict";
|
|
@@ -9,7 +9,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
9
9
|
|
|
10
10
|
// EXPORTS
|
|
11
11
|
__webpack_require__.d(__webpack_exports__, {
|
|
12
|
-
|
|
12
|
+
Types: () => (/* reexport */ types_namespaceObject),
|
|
13
13
|
"default": () => (/* binding */ cornerstone_src),
|
|
14
14
|
getActiveViewportEnabledElement: () => (/* reexport */ getActiveViewportEnabledElement),
|
|
15
15
|
measurementMappingUtils: () => (/* reexport */ utils_namespaceObject),
|
|
@@ -26,27 +26,26 @@ __webpack_require__.r(utils_namespaceObject);
|
|
|
26
26
|
__webpack_require__.d(utils_namespaceObject, {
|
|
27
27
|
getFirstAnnotationSelected: () => (getFirstAnnotationSelected),
|
|
28
28
|
getHandlesFromPoints: () => (getHandlesFromPoints),
|
|
29
|
-
getModalityUnit: () => (utils_getModalityUnit),
|
|
30
29
|
getSOPInstanceAttributes: () => (getSOPInstanceAttributes/* default */.Z),
|
|
31
30
|
isAnnotationSelected: () => (isAnnotationSelected),
|
|
32
31
|
setAnnotationSelected: () => (setAnnotationSelected)
|
|
33
32
|
});
|
|
34
33
|
|
|
35
34
|
// EXTERNAL MODULE: ../../../node_modules/react/index.js
|
|
36
|
-
var react = __webpack_require__(
|
|
37
|
-
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js +
|
|
38
|
-
var esm = __webpack_require__(
|
|
39
|
-
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/index.js +
|
|
40
|
-
var dist_esm = __webpack_require__(
|
|
41
|
-
// EXTERNAL MODULE: ../../core/src/index.ts +
|
|
42
|
-
var src = __webpack_require__(
|
|
35
|
+
var react = __webpack_require__(43001);
|
|
36
|
+
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 337 modules
|
|
37
|
+
var esm = __webpack_require__(45754);
|
|
38
|
+
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/index.js + 327 modules
|
|
39
|
+
var dist_esm = __webpack_require__(99777);
|
|
40
|
+
// EXTERNAL MODULE: ../../core/src/index.ts + 75 modules
|
|
41
|
+
var src = __webpack_require__(34491);
|
|
43
42
|
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/streaming-image-volume-loader/dist/esm/index.js + 13 modules
|
|
44
|
-
var streaming_image_volume_loader_dist_esm = __webpack_require__(
|
|
43
|
+
var streaming_image_volume_loader_dist_esm = __webpack_require__(7087);
|
|
45
44
|
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/dicom-image-loader/dist/dynamic-import/cornerstoneDICOMImageLoader.min.js
|
|
46
|
-
var cornerstoneDICOMImageLoader_min = __webpack_require__(
|
|
45
|
+
var cornerstoneDICOMImageLoader_min = __webpack_require__(61539);
|
|
47
46
|
var cornerstoneDICOMImageLoader_min_default = /*#__PURE__*/__webpack_require__.n(cornerstoneDICOMImageLoader_min);
|
|
48
47
|
// EXTERNAL MODULE: ../../../node_modules/dicom-parser/dist/dicomParser.min.js
|
|
49
|
-
var dicomParser_min = __webpack_require__(
|
|
48
|
+
var dicomParser_min = __webpack_require__(56660);
|
|
50
49
|
var dicomParser_min_default = /*#__PURE__*/__webpack_require__.n(dicomParser_min);
|
|
51
50
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/initWADOImageLoader.js
|
|
52
51
|
|
|
@@ -76,7 +75,7 @@ function initWebWorkers(appConfig) {
|
|
|
76
75
|
initialized = true;
|
|
77
76
|
}
|
|
78
77
|
}
|
|
79
|
-
function initWADOImageLoader(userAuthenticationService, appConfig) {
|
|
78
|
+
function initWADOImageLoader(userAuthenticationService, appConfig, extensionManager) {
|
|
80
79
|
(cornerstoneDICOMImageLoader_min_default()).external.cornerstone = esm;
|
|
81
80
|
(cornerstoneDICOMImageLoader_min_default()).external.dicomParser = (dicomParser_min_default());
|
|
82
81
|
registerVolumeLoader('cornerstoneStreamingImageVolume', streaming_image_volume_loader_dist_esm/* cornerstoneStreamingImageVolumeLoader */.IU);
|
|
@@ -87,21 +86,17 @@ function initWADOImageLoader(userAuthenticationService, appConfig) {
|
|
|
87
86
|
// will convert everything to integers (to be able to work with cornerstone-2d).
|
|
88
87
|
// Until the default is set to true (which is the case for cornerstone3D),
|
|
89
88
|
// we should set this flag to false.
|
|
90
|
-
convertFloatPixelDataToInt: false
|
|
89
|
+
convertFloatPixelDataToInt: false,
|
|
90
|
+
use16BitDataType: Boolean(appConfig.use16BitDataType)
|
|
91
91
|
},
|
|
92
92
|
beforeSend: function (xhr) {
|
|
93
|
+
//TODO should be removed in the future and request emitted by DicomWebDataSource
|
|
94
|
+
const sourceConfig = extensionManager.getActiveDataSource()?.[0].getConfig() ?? {};
|
|
93
95
|
const headers = userAuthenticationService.getAuthorizationHeader();
|
|
94
|
-
|
|
95
|
-
// Request:
|
|
96
|
-
// JPEG-LS Lossless (1.2.840.10008.1.2.4.80) if available, otherwise accept
|
|
97
|
-
// whatever transfer-syntax the origin server provides.
|
|
98
|
-
// For now we use image/jls and image/x-jls because some servers still use the old type
|
|
99
|
-
// http://dicom.nema.org/medical/dicom/current/output/html/part18.html
|
|
96
|
+
const acceptHeader = src.utils.generateAcceptHeader(sourceConfig.acceptHeader, sourceConfig.requestTransferSyntaxUID, sourceConfig.omitQuotationForMultipartRequest);
|
|
100
97
|
const xhrRequestHeaders = {
|
|
101
|
-
Accept:
|
|
102
|
-
// 'multipart/related; type="image/x-jls", multipart/related; type="image/jls"; transfer-syntax="1.2.840.10008.1.2.4.80", multipart/related; type="image/x-jls", multipart/related; type="application/octet-stream"; transfer-syntax=*',
|
|
98
|
+
Accept: acceptHeader
|
|
103
99
|
};
|
|
104
|
-
|
|
105
100
|
if (headers) {
|
|
106
101
|
Object.assign(xhrRequestHeaders, headers);
|
|
107
102
|
}
|
|
@@ -116,14 +111,14 @@ function initWADOImageLoader(userAuthenticationService, appConfig) {
|
|
|
116
111
|
function destroy() {
|
|
117
112
|
// Note: we don't want to call .terminate on the webWorkerManager since
|
|
118
113
|
// that resets the config
|
|
119
|
-
const webWorkers =
|
|
114
|
+
const webWorkers = webWorkerManager.webWorkers;
|
|
120
115
|
for (let i = 0; i < webWorkers.length; i++) {
|
|
121
116
|
webWorkers[i].worker.terminate();
|
|
122
117
|
}
|
|
123
118
|
webWorkers.length = 0;
|
|
124
119
|
}
|
|
125
|
-
// EXTERNAL MODULE: ../../ui/src/index.js +
|
|
126
|
-
var ui_src = __webpack_require__(
|
|
120
|
+
// EXTERNAL MODULE: ../../ui/src/index.js + 485 modules
|
|
121
|
+
var ui_src = __webpack_require__(71783);
|
|
127
122
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/callInputDialog.tsx
|
|
128
123
|
|
|
129
124
|
|
|
@@ -157,7 +152,9 @@ function callInputDialog(uiDialogService, data, callback) {
|
|
|
157
152
|
} = _ref;
|
|
158
153
|
switch (action.id) {
|
|
159
154
|
case 'save':
|
|
160
|
-
if (typeof validateFunc === 'function' && !validateFunc(value.label))
|
|
155
|
+
if (typeof validateFunc === 'function' && !validateFunc(value.label)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
161
158
|
callback(value.label, action.id);
|
|
162
159
|
break;
|
|
163
160
|
case 'cancel':
|
|
@@ -187,11 +184,11 @@ function callInputDialog(uiDialogService, data, callback) {
|
|
|
187
184
|
actions: [{
|
|
188
185
|
id: 'cancel',
|
|
189
186
|
text: 'Cancel',
|
|
190
|
-
type: ui_src/* ButtonEnums.type */.LZ.
|
|
187
|
+
type: ui_src/* ButtonEnums.type */.LZ.dt.secondary
|
|
191
188
|
}, {
|
|
192
189
|
id: 'save',
|
|
193
190
|
text: 'Save',
|
|
194
|
-
type: ui_src/* ButtonEnums.type */.LZ.
|
|
191
|
+
type: ui_src/* ButtonEnums.type */.LZ.dt.primary
|
|
195
192
|
}],
|
|
196
193
|
onSubmit: onSubmitHandler,
|
|
197
194
|
body: _ref2 => {
|
|
@@ -201,7 +198,7 @@ function callInputDialog(uiDialogService, data, callback) {
|
|
|
201
198
|
} = _ref2;
|
|
202
199
|
return /*#__PURE__*/react.createElement(ui_src/* Input */.II, {
|
|
203
200
|
autoFocus: true,
|
|
204
|
-
className: "
|
|
201
|
+
className: "border-primary-main bg-black",
|
|
205
202
|
type: "text",
|
|
206
203
|
id: "annotation",
|
|
207
204
|
label: inputLabel,
|
|
@@ -232,17 +229,17 @@ function callInputDialog(uiDialogService, data, callback) {
|
|
|
232
229
|
}
|
|
233
230
|
/* harmony default export */ const utils_callInputDialog = (callInputDialog);
|
|
234
231
|
// EXTERNAL MODULE: ../../../extensions/cornerstone/src/state.ts
|
|
235
|
-
var state = __webpack_require__(
|
|
232
|
+
var state = __webpack_require__(73704);
|
|
236
233
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/getActiveViewportEnabledElement.ts
|
|
237
234
|
|
|
238
235
|
|
|
239
236
|
function getActiveViewportEnabledElement(viewportGridService) {
|
|
240
237
|
const {
|
|
241
|
-
|
|
238
|
+
activeViewportId
|
|
242
239
|
} = viewportGridService.getState();
|
|
243
240
|
const {
|
|
244
241
|
element
|
|
245
|
-
} = (0,state/* getEnabledElement */.K8)(
|
|
242
|
+
} = (0,state/* getEnabledElement */.K8)(activeViewportId) || {};
|
|
246
243
|
const enabledElement = (0,esm.getEnabledElement)(element);
|
|
247
244
|
return enabledElement;
|
|
248
245
|
}
|
|
@@ -322,11 +319,12 @@ function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
|
|
|
322
319
|
const currentColumnPixelSpacing = calibratedPixelSpacing?.[1] || imagePlaneModule?.columnPixelSpacing || 1;
|
|
323
320
|
const adjustCalibration = newLength => {
|
|
324
321
|
const spacingScale = newLength / length;
|
|
325
|
-
const rowSpacing = spacingScale * currentRowPixelSpacing;
|
|
326
|
-
const colSpacing = spacingScale * currentColumnPixelSpacing;
|
|
327
322
|
|
|
328
323
|
// trigger resize of the viewport to adjust the world/pixel mapping
|
|
329
|
-
calibrateImageSpacing(imageId, viewport.getRenderingEngine(),
|
|
324
|
+
calibrateImageSpacing(imageId, viewport.getRenderingEngine(), {
|
|
325
|
+
type: 'User',
|
|
326
|
+
scale: 1 / spacingScale
|
|
327
|
+
});
|
|
330
328
|
};
|
|
331
329
|
return new Promise((resolve, reject) => {
|
|
332
330
|
if (!uiDialogService) {
|
|
@@ -358,9 +356,221 @@ function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
|
|
|
358
356
|
});
|
|
359
357
|
});
|
|
360
358
|
}
|
|
359
|
+
// EXTERNAL MODULE: ../../core/src/utils/index.js + 25 modules
|
|
360
|
+
var utils = __webpack_require__(77250);
|
|
361
|
+
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/tools/ImageOverlayViewerTool.tsx
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Image Overlay Viewer tool is not a traditional tool that requires user interactin.
|
|
368
|
+
* But it is used to display Pixel Overlays. And it will provide toggling capability.
|
|
369
|
+
*
|
|
370
|
+
* The documentation for Overlay Plane Module of DICOM can be found in [C.9.2 of
|
|
371
|
+
* Part-3 of DICOM standard](https://dicom.nema.org/medical/dicom/2018b/output/chtml/part03/sect_C.9.2.html)
|
|
372
|
+
*
|
|
373
|
+
* Image Overlay rendered by this tool can be toggled on and off using
|
|
374
|
+
* toolGroup.setToolEnabled() and toolGroup.setToolDisabled()
|
|
375
|
+
*/
|
|
376
|
+
class ImageOverlayViewerTool extends dist_esm.AnnotationDisplayTool {
|
|
377
|
+
constructor() {
|
|
378
|
+
let toolProps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
379
|
+
let defaultToolProps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
|
|
380
|
+
supportedInteractionTypes: [],
|
|
381
|
+
configuration: {
|
|
382
|
+
fillColor: [255, 127, 127, 255]
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
super(toolProps, defaultToolProps);
|
|
386
|
+
this._cachedOverlayMetadata = new Map();
|
|
387
|
+
this._cachedStats = {};
|
|
388
|
+
this.onSetToolDisabled = () => {
|
|
389
|
+
this._cachedStats = {};
|
|
390
|
+
this._cachedOverlayMetadata = new Map();
|
|
391
|
+
};
|
|
392
|
+
this.renderAnnotation = (enabledElement, svgDrawingHelper) => {
|
|
393
|
+
const {
|
|
394
|
+
viewport
|
|
395
|
+
} = enabledElement;
|
|
396
|
+
const imageId = this.getReferencedImageId(viewport);
|
|
397
|
+
if (!imageId) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
const overlays = this._cachedOverlayMetadata.get(imageId) ?? esm.metaData.get('overlayPlaneModule', imageId)?.overlays;
|
|
401
|
+
|
|
402
|
+
// no overlays
|
|
403
|
+
if (!overlays?.length) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
this._cachedOverlayMetadata.set(imageId, overlays);
|
|
407
|
+
this._getCachedStat(imageId, overlays, this.configuration.fillColor).then(cachedStat => {
|
|
408
|
+
cachedStat.overlays.forEach(overlay => {
|
|
409
|
+
this._renderOverlay(enabledElement, svgDrawingHelper, overlay);
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
return true;
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
getReferencedImageId(viewport) {
|
|
416
|
+
if (viewport instanceof esm.VolumeViewport) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const targetId = this.getTargetId(viewport);
|
|
420
|
+
return targetId.split('imageId:')[1];
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Render to DOM
|
|
424
|
+
*
|
|
425
|
+
* @param enabledElement
|
|
426
|
+
* @param svgDrawingHelper
|
|
427
|
+
* @param overlayData
|
|
428
|
+
* @returns
|
|
429
|
+
*/
|
|
430
|
+
_renderOverlay(enabledElement, svgDrawingHelper, overlayData) {
|
|
431
|
+
const {
|
|
432
|
+
viewport
|
|
433
|
+
} = enabledElement;
|
|
434
|
+
const imageId = this.getReferencedImageId(viewport);
|
|
435
|
+
if (!imageId) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Decide the rendering position of the overlay image on the current canvas
|
|
440
|
+
const {
|
|
441
|
+
_id,
|
|
442
|
+
columns: width,
|
|
443
|
+
rows: height,
|
|
444
|
+
x,
|
|
445
|
+
y
|
|
446
|
+
} = overlayData;
|
|
447
|
+
const overlayTopLeftWorldPos = esm.utilities.imageToWorldCoords(imageId, [x - 1,
|
|
448
|
+
// Remind that top-left corner's (x, y) is be (1, 1)
|
|
449
|
+
y - 1]);
|
|
450
|
+
const overlayTopLeftOnCanvas = viewport.worldToCanvas(overlayTopLeftWorldPos);
|
|
451
|
+
const overlayBottomRightWorldPos = esm.utilities.imageToWorldCoords(imageId, [width, height]);
|
|
452
|
+
const overlayBottomRightOnCanvas = viewport.worldToCanvas(overlayBottomRightWorldPos);
|
|
453
|
+
|
|
454
|
+
// add image to the annotations svg layer
|
|
455
|
+
const svgns = 'http://www.w3.org/2000/svg';
|
|
456
|
+
const svgNodeHash = `image-overlay-${_id}`;
|
|
457
|
+
const existingImageElement = svgDrawingHelper.getSvgNode(svgNodeHash);
|
|
458
|
+
const attributes = {
|
|
459
|
+
'data-id': svgNodeHash,
|
|
460
|
+
width: overlayBottomRightOnCanvas[0] - overlayTopLeftOnCanvas[0],
|
|
461
|
+
height: overlayBottomRightOnCanvas[1] - overlayTopLeftOnCanvas[1],
|
|
462
|
+
x: overlayTopLeftOnCanvas[0],
|
|
463
|
+
y: overlayTopLeftOnCanvas[1],
|
|
464
|
+
href: overlayData.dataUrl
|
|
465
|
+
};
|
|
466
|
+
if (isNaN(attributes.x) || isNaN(attributes.y) || isNaN(attributes.width) || isNaN(attributes.height)) {
|
|
467
|
+
console.warn('Invalid rendering attribute for image overlay', attributes['data-id']);
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
if (existingImageElement) {
|
|
471
|
+
dist_esm.drawing.setAttributesIfNecessary(attributes, existingImageElement);
|
|
472
|
+
svgDrawingHelper.setNodeTouched(svgNodeHash);
|
|
473
|
+
} else {
|
|
474
|
+
const newImageElement = document.createElementNS(svgns, 'image');
|
|
475
|
+
dist_esm.drawing.setNewAttributesIfValid(attributes, newImageElement);
|
|
476
|
+
svgDrawingHelper.appendNode(newImageElement, svgNodeHash);
|
|
477
|
+
}
|
|
478
|
+
return true;
|
|
479
|
+
}
|
|
480
|
+
async _getCachedStat(imageId, overlayMetadata, color) {
|
|
481
|
+
if (this._cachedStats[imageId] && this._isSameColor(this._cachedStats[imageId].color, color)) {
|
|
482
|
+
return this._cachedStats[imageId];
|
|
483
|
+
}
|
|
484
|
+
const overlays = await Promise.all(overlayMetadata.filter(overlay => overlay.pixelData).map(async (overlay, idx) => {
|
|
485
|
+
let pixelData = null;
|
|
486
|
+
if (overlay.pixelData.Value) {
|
|
487
|
+
pixelData = overlay.pixelData.Value;
|
|
488
|
+
} else if (overlay.pixelData.retrieveBulkData) {
|
|
489
|
+
pixelData = await overlay.pixelData.retrieveBulkData();
|
|
490
|
+
}
|
|
491
|
+
if (!pixelData) {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
const dataUrl = this._renderOverlayToDataUrl({
|
|
495
|
+
width: overlay.columns,
|
|
496
|
+
height: overlay.rows
|
|
497
|
+
}, color, pixelData);
|
|
498
|
+
return {
|
|
499
|
+
...overlay,
|
|
500
|
+
_id: (0,utils/* guid */.M8)(),
|
|
501
|
+
dataUrl,
|
|
502
|
+
// this will be a data url expression of the rendered image
|
|
503
|
+
color
|
|
504
|
+
};
|
|
505
|
+
}));
|
|
506
|
+
this._cachedStats[imageId] = {
|
|
507
|
+
color: color,
|
|
508
|
+
overlays: overlays.filter(overlay => overlay)
|
|
509
|
+
};
|
|
510
|
+
return this._cachedStats[imageId];
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* compare two RGBA expression of colors.
|
|
515
|
+
*
|
|
516
|
+
* @param color1
|
|
517
|
+
* @param color2
|
|
518
|
+
* @returns
|
|
519
|
+
*/
|
|
520
|
+
_isSameColor(color1, color2) {
|
|
521
|
+
return color1 && color2 && color1[0] === color2[0] && color1[1] === color2[1] && color1[2] === color2[2] && color1[3] === color2[3];
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* pixelData of overlayPlane module is an array of bits corresponding
|
|
526
|
+
* to each of the underlying pixels of the image.
|
|
527
|
+
* Let's create pixel data from bit array of overlay data
|
|
528
|
+
*
|
|
529
|
+
* @param pixelDataRaw
|
|
530
|
+
* @param color
|
|
531
|
+
* @returns
|
|
532
|
+
*/
|
|
533
|
+
_renderOverlayToDataUrl(_ref, color, pixelDataRaw) {
|
|
534
|
+
let {
|
|
535
|
+
width,
|
|
536
|
+
height
|
|
537
|
+
} = _ref;
|
|
538
|
+
const pixelDataView = new DataView(pixelDataRaw);
|
|
539
|
+
const totalBits = width * height;
|
|
540
|
+
const canvas = document.createElement('canvas');
|
|
541
|
+
canvas.width = width;
|
|
542
|
+
canvas.height = height;
|
|
543
|
+
const ctx = canvas.getContext('2d');
|
|
544
|
+
ctx.clearRect(0, 0, width, height); // make it transparent
|
|
545
|
+
ctx.globalCompositeOperation = 'copy';
|
|
546
|
+
const imageData = ctx.getImageData(0, 0, width, height);
|
|
547
|
+
const data = imageData.data;
|
|
548
|
+
for (let i = 0, bitIdx = 0, byteIdx = 0; i < totalBits; i++) {
|
|
549
|
+
if (pixelDataView.getUint8(byteIdx) & 1 << bitIdx) {
|
|
550
|
+
data[i * 4] = color[0];
|
|
551
|
+
data[i * 4 + 1] = color[1];
|
|
552
|
+
data[i * 4 + 2] = color[2];
|
|
553
|
+
data[i * 4 + 3] = color[3];
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// next bit, byte
|
|
557
|
+
if (bitIdx >= 7) {
|
|
558
|
+
bitIdx = 0;
|
|
559
|
+
byteIdx++;
|
|
560
|
+
} else {
|
|
561
|
+
bitIdx++;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
ctx.putImageData(imageData, 0, 0);
|
|
565
|
+
return canvas.toDataURL();
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
ImageOverlayViewerTool.toolName = 'ImageOverlayViewer';
|
|
569
|
+
/* harmony default export */ const tools_ImageOverlayViewerTool = (ImageOverlayViewerTool);
|
|
361
570
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/initCornerstoneTools.js
|
|
362
571
|
|
|
363
572
|
|
|
573
|
+
|
|
364
574
|
function initCornerstoneTools() {
|
|
365
575
|
let configuration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
366
576
|
dist_esm.CrosshairsTool.isAnnotation = false;
|
|
@@ -390,6 +600,10 @@ function initCornerstoneTools() {
|
|
|
390
600
|
(0,dist_esm.addTool)(dist_esm.ReferenceLinesTool);
|
|
391
601
|
(0,dist_esm.addTool)(tools_CalibrationLineTool);
|
|
392
602
|
(0,dist_esm.addTool)(dist_esm.TrackballRotateTool);
|
|
603
|
+
(0,dist_esm.addTool)(dist_esm.CircleScissorsTool);
|
|
604
|
+
(0,dist_esm.addTool)(dist_esm.RectangleScissorsTool);
|
|
605
|
+
(0,dist_esm.addTool)(dist_esm.SphereScissorsTool);
|
|
606
|
+
(0,dist_esm.addTool)(tools_ImageOverlayViewerTool);
|
|
393
607
|
|
|
394
608
|
// Modify annotation tools to use dashed lines on SR
|
|
395
609
|
const annotationStyle = {
|
|
@@ -428,13 +642,17 @@ const toolNames = {
|
|
|
428
642
|
SegmentationDisplay: dist_esm.SegmentationDisplayTool.toolName,
|
|
429
643
|
ReferenceLines: dist_esm.ReferenceLinesTool.toolName,
|
|
430
644
|
CalibrationLine: tools_CalibrationLineTool.toolName,
|
|
431
|
-
TrackballRotateTool: dist_esm.TrackballRotateTool.toolName
|
|
645
|
+
TrackballRotateTool: dist_esm.TrackballRotateTool.toolName,
|
|
646
|
+
CircleScissors: dist_esm.CircleScissorsTool.toolName,
|
|
647
|
+
RectangleScissors: dist_esm.RectangleScissorsTool.toolName,
|
|
648
|
+
SphereScissors: dist_esm.SphereScissorsTool.toolName,
|
|
649
|
+
ImageOverlayViewer: tools_ImageOverlayViewerTool.toolName
|
|
432
650
|
};
|
|
433
651
|
|
|
434
652
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/measurementServiceMappings/constants/supportedTools.js
|
|
435
653
|
/* harmony default export */ const supportedTools = (['Length', 'EllipticalROI', 'CircleROI', 'Bidirectional', 'ArrowAnnotate', 'Angle', 'CobbAngle', 'Probe', 'RectangleROI', 'PlanarFreehandROI']);
|
|
436
654
|
// EXTERNAL MODULE: ../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/getSOPInstanceAttributes.js
|
|
437
|
-
var getSOPInstanceAttributes = __webpack_require__(
|
|
655
|
+
var getSOPInstanceAttributes = __webpack_require__(87172);
|
|
438
656
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/measurementServiceMappings/Length.ts
|
|
439
657
|
|
|
440
658
|
|
|
@@ -537,9 +755,9 @@ function getMappedAnnotations(annotation, displaySetService) {
|
|
|
537
755
|
SeriesNumber
|
|
538
756
|
} = displaySet;
|
|
539
757
|
const {
|
|
540
|
-
length
|
|
758
|
+
length,
|
|
759
|
+
unit = 'mm'
|
|
541
760
|
} = targetStats;
|
|
542
|
-
const unit = 'mm';
|
|
543
761
|
annotations.push({
|
|
544
762
|
SeriesInstanceUID,
|
|
545
763
|
SOPInstanceUID,
|
|
@@ -566,10 +784,13 @@ function _getReport(mappedAnnotations, points, FrameOfReferenceUID) {
|
|
|
566
784
|
values.push('Cornerstone:Length');
|
|
567
785
|
mappedAnnotations.forEach(annotation => {
|
|
568
786
|
const {
|
|
569
|
-
length
|
|
787
|
+
length,
|
|
788
|
+
unit
|
|
570
789
|
} = annotation;
|
|
571
|
-
columns.push(`Length
|
|
790
|
+
columns.push(`Length`);
|
|
572
791
|
values.push(length);
|
|
792
|
+
columns.push('Unit');
|
|
793
|
+
values.push(unit);
|
|
573
794
|
});
|
|
574
795
|
if (FrameOfReferenceUID) {
|
|
575
796
|
columns.push('FrameOfReferenceUID');
|
|
@@ -598,7 +819,8 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
|
|
598
819
|
length,
|
|
599
820
|
SeriesNumber,
|
|
600
821
|
SOPInstanceUID,
|
|
601
|
-
frameNumber
|
|
822
|
+
frameNumber,
|
|
823
|
+
unit
|
|
602
824
|
} = mappedAnnotations[0];
|
|
603
825
|
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
|
604
826
|
let InstanceNumber;
|
|
@@ -607,9 +829,11 @@ function getDisplayText(mappedAnnotations, displaySet) {
|
|
|
607
829
|
}
|
|
608
830
|
const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';
|
|
609
831
|
const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';
|
|
610
|
-
if (length === null || length === undefined)
|
|
832
|
+
if (length === null || length === undefined) {
|
|
833
|
+
return displayText;
|
|
834
|
+
}
|
|
611
835
|
const roundedLength = src.utils.roundNumber(length, 2);
|
|
612
|
-
displayText.push(`${roundedLength}
|
|
836
|
+
displayText.push(`${roundedLength} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`);
|
|
613
837
|
return displayText;
|
|
614
838
|
}
|
|
615
839
|
/* harmony default export */ const measurementServiceMappings_Length = (Length);
|
|
@@ -711,9 +935,9 @@ function Bidirectional_getMappedAnnotations(annotation, displaySetService) {
|
|
|
711
935
|
} = displaySet;
|
|
712
936
|
const {
|
|
713
937
|
length,
|
|
714
|
-
width
|
|
938
|
+
width,
|
|
939
|
+
unit
|
|
715
940
|
} = targetStats;
|
|
716
|
-
const unit = 'mm';
|
|
717
941
|
annotations.push({
|
|
718
942
|
SeriesInstanceUID,
|
|
719
943
|
SOPInstanceUID,
|
|
@@ -742,10 +966,11 @@ function Bidirectional_getReport(mappedAnnotations, points, FrameOfReferenceUID)
|
|
|
742
966
|
mappedAnnotations.forEach(annotation => {
|
|
743
967
|
const {
|
|
744
968
|
length,
|
|
745
|
-
width
|
|
969
|
+
width,
|
|
970
|
+
unit
|
|
746
971
|
} = annotation;
|
|
747
|
-
columns.push(`Length
|
|
748
|
-
values.push(length, width);
|
|
972
|
+
columns.push(`Length`, `Width`, 'Unit');
|
|
973
|
+
values.push(length, width, unit);
|
|
749
974
|
});
|
|
750
975
|
if (FrameOfReferenceUID) {
|
|
751
976
|
columns.push('FrameOfReferenceUID');
|
|
@@ -773,6 +998,7 @@ function Bidirectional_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
773
998
|
const {
|
|
774
999
|
length,
|
|
775
1000
|
width,
|
|
1001
|
+
unit,
|
|
776
1002
|
SeriesNumber,
|
|
777
1003
|
SOPInstanceUID,
|
|
778
1004
|
frameNumber
|
|
@@ -786,27 +1012,15 @@ function Bidirectional_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
786
1012
|
}
|
|
787
1013
|
const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';
|
|
788
1014
|
const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';
|
|
789
|
-
displayText.push(`L: ${roundedLength}
|
|
790
|
-
displayText.push(`W: ${roundedWidth}
|
|
1015
|
+
displayText.push(`L: ${roundedLength} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`);
|
|
1016
|
+
displayText.push(`W: ${roundedWidth} ${unit}`);
|
|
791
1017
|
return displayText;
|
|
792
1018
|
}
|
|
793
1019
|
/* harmony default export */ const measurementServiceMappings_Bidirectional = (Bidirectional);
|
|
794
|
-
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/getModalityUnit.js
|
|
795
|
-
function getModalityUnit(modality) {
|
|
796
|
-
if (modality === 'CT') {
|
|
797
|
-
return 'HU';
|
|
798
|
-
} else if (modality === 'PT') {
|
|
799
|
-
return 'SUV';
|
|
800
|
-
} else {
|
|
801
|
-
return '';
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
/* harmony default export */ const utils_getModalityUnit = (getModalityUnit);
|
|
805
1020
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/measurementServiceMappings/EllipticalROI.ts
|
|
806
1021
|
|
|
807
1022
|
|
|
808
1023
|
|
|
809
|
-
|
|
810
1024
|
const EllipticalROI = {
|
|
811
1025
|
toAnnotation: measurement => {},
|
|
812
1026
|
toMeasurement: (csToolsEventDetail, displaySetService, cornerstoneViewportService, getValueTypeFromToolType) => {
|
|
@@ -904,16 +1118,18 @@ function EllipticalROI_getMappedAnnotations(annotation, displaySetService) {
|
|
|
904
1118
|
stdDev,
|
|
905
1119
|
max,
|
|
906
1120
|
area,
|
|
907
|
-
Modality
|
|
1121
|
+
Modality,
|
|
1122
|
+
areaUnit,
|
|
1123
|
+
modalityUnit
|
|
908
1124
|
} = targetStats;
|
|
909
|
-
const unit = utils_getModalityUnit(Modality);
|
|
910
1125
|
annotations.push({
|
|
911
1126
|
SeriesInstanceUID,
|
|
912
1127
|
SOPInstanceUID,
|
|
913
1128
|
SeriesNumber,
|
|
914
1129
|
frameNumber,
|
|
915
1130
|
Modality,
|
|
916
|
-
unit,
|
|
1131
|
+
unit: modalityUnit,
|
|
1132
|
+
areaUnit,
|
|
917
1133
|
mean,
|
|
918
1134
|
stdDev,
|
|
919
1135
|
max,
|
|
@@ -941,13 +1157,14 @@ function EllipticalROI_getReport(mappedAnnotations, points, FrameOfReferenceUID)
|
|
|
941
1157
|
stdDev,
|
|
942
1158
|
max,
|
|
943
1159
|
area,
|
|
944
|
-
unit
|
|
1160
|
+
unit,
|
|
1161
|
+
areaUnit
|
|
945
1162
|
} = annotation;
|
|
946
1163
|
if (!mean || !unit || !max || !area) {
|
|
947
1164
|
return;
|
|
948
1165
|
}
|
|
949
|
-
columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`,
|
|
950
|
-
values.push(max, mean, stdDev, area);
|
|
1166
|
+
columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`, 'Area', 'Unit');
|
|
1167
|
+
values.push(max, mean, stdDev, area, areaUnit);
|
|
951
1168
|
});
|
|
952
1169
|
if (FrameOfReferenceUID) {
|
|
953
1170
|
columns.push('FrameOfReferenceUID');
|
|
@@ -975,7 +1192,8 @@ function EllipticalROI_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
975
1192
|
const {
|
|
976
1193
|
area,
|
|
977
1194
|
SOPInstanceUID,
|
|
978
|
-
frameNumber
|
|
1195
|
+
frameNumber,
|
|
1196
|
+
areaUnit
|
|
979
1197
|
} = mappedAnnotations[0];
|
|
980
1198
|
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
|
981
1199
|
let InstanceNumber;
|
|
@@ -984,10 +1202,8 @@ function EllipticalROI_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
984
1202
|
}
|
|
985
1203
|
const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';
|
|
986
1204
|
const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
const roundedArea = src.utils.roundNumber(area || 0, 2);
|
|
990
|
-
displayText.push(`${roundedArea} mm<sup>2</sup>`);
|
|
1205
|
+
const roundedArea = src.utils.roundNumber(area, 2);
|
|
1206
|
+
displayText.push(`${roundedArea} ${areaUnit}`);
|
|
991
1207
|
|
|
992
1208
|
// Todo: we need a better UI for displaying all these information
|
|
993
1209
|
mappedAnnotations.forEach(mappedAnnotation => {
|
|
@@ -1013,7 +1229,6 @@ function EllipticalROI_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
1013
1229
|
|
|
1014
1230
|
|
|
1015
1231
|
|
|
1016
|
-
|
|
1017
1232
|
const CircleROI = {
|
|
1018
1233
|
toAnnotation: measurement => {},
|
|
1019
1234
|
toMeasurement: (csToolsEventDetail, DisplaySetService, CornerstoneViewportService, getValueTypeFromToolType) => {
|
|
@@ -1111,20 +1326,22 @@ function CircleROI_getMappedAnnotations(annotation, DisplaySetService) {
|
|
|
1111
1326
|
stdDev,
|
|
1112
1327
|
max,
|
|
1113
1328
|
area,
|
|
1114
|
-
Modality
|
|
1329
|
+
Modality,
|
|
1330
|
+
areaUnit,
|
|
1331
|
+
modalityUnit
|
|
1115
1332
|
} = targetStats;
|
|
1116
|
-
const unit = utils_getModalityUnit(Modality);
|
|
1117
1333
|
annotations.push({
|
|
1118
1334
|
SeriesInstanceUID,
|
|
1119
1335
|
SOPInstanceUID,
|
|
1120
1336
|
SeriesNumber,
|
|
1121
1337
|
frameNumber,
|
|
1122
1338
|
Modality,
|
|
1123
|
-
unit,
|
|
1339
|
+
unit: modalityUnit,
|
|
1124
1340
|
mean,
|
|
1125
1341
|
stdDev,
|
|
1126
1342
|
max,
|
|
1127
|
-
area
|
|
1343
|
+
area,
|
|
1344
|
+
areaUnit
|
|
1128
1345
|
});
|
|
1129
1346
|
});
|
|
1130
1347
|
return annotations;
|
|
@@ -1148,13 +1365,14 @@ function CircleROI_getReport(mappedAnnotations, points, FrameOfReferenceUID) {
|
|
|
1148
1365
|
stdDev,
|
|
1149
1366
|
max,
|
|
1150
1367
|
area,
|
|
1151
|
-
unit
|
|
1368
|
+
unit,
|
|
1369
|
+
areaUnit
|
|
1152
1370
|
} = annotation;
|
|
1153
1371
|
if (!mean || !unit || !max || !area) {
|
|
1154
1372
|
return;
|
|
1155
1373
|
}
|
|
1156
|
-
columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`,
|
|
1157
|
-
values.push(max, mean, stdDev, area);
|
|
1374
|
+
columns.push(`max (${unit})`, `mean (${unit})`, `std (${unit})`, 'Area', 'Unit');
|
|
1375
|
+
values.push(max, mean, stdDev, area, areaUnit);
|
|
1158
1376
|
});
|
|
1159
1377
|
if (FrameOfReferenceUID) {
|
|
1160
1378
|
columns.push('FrameOfReferenceUID');
|
|
@@ -1182,7 +1400,8 @@ function CircleROI_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
1182
1400
|
const {
|
|
1183
1401
|
area,
|
|
1184
1402
|
SOPInstanceUID,
|
|
1185
|
-
frameNumber
|
|
1403
|
+
frameNumber,
|
|
1404
|
+
areaUnit
|
|
1186
1405
|
} = mappedAnnotations[0];
|
|
1187
1406
|
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
|
1188
1407
|
let InstanceNumber;
|
|
@@ -1194,7 +1413,7 @@ function CircleROI_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
1194
1413
|
|
|
1195
1414
|
// Area sometimes becomes undefined if `preventHandleOutsideImage` is off.
|
|
1196
1415
|
const roundedArea = src.utils.roundNumber(area || 0, 2);
|
|
1197
|
-
displayText.push(`${roundedArea}
|
|
1416
|
+
displayText.push(`${roundedArea} ${areaUnit}`);
|
|
1198
1417
|
|
|
1199
1418
|
// Todo: we need a better UI for displaying all these information
|
|
1200
1419
|
mappedAnnotations.forEach(mappedAnnotation => {
|
|
@@ -1515,7 +1734,9 @@ function CobbAngle_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
1515
1734
|
}
|
|
1516
1735
|
const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';
|
|
1517
1736
|
const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';
|
|
1518
|
-
if (angle === undefined)
|
|
1737
|
+
if (angle === undefined) {
|
|
1738
|
+
return displayText;
|
|
1739
|
+
}
|
|
1519
1740
|
const roundedAngle = src.utils.roundNumber(angle, 2);
|
|
1520
1741
|
displayText.push(`${roundedAngle} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`);
|
|
1521
1742
|
return displayText;
|
|
@@ -1695,7 +1916,9 @@ function Angle_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
1695
1916
|
}
|
|
1696
1917
|
const instanceText = InstanceNumber ? ` I: ${InstanceNumber}` : '';
|
|
1697
1918
|
const frameText = displaySet.isMultiFrame ? ` F: ${frameNumber}` : '';
|
|
1698
|
-
if (angle === undefined)
|
|
1919
|
+
if (angle === undefined) {
|
|
1920
|
+
return displayText;
|
|
1921
|
+
}
|
|
1699
1922
|
const roundedAngle = src.utils.roundNumber(angle, 2);
|
|
1700
1923
|
displayText.push(`${roundedAngle} ${unit} (S: ${SeriesNumber}${instanceText}${frameText})`);
|
|
1701
1924
|
return displayText;
|
|
@@ -1839,7 +2062,6 @@ function PlanarFreehandROI_getDisplayText(mappedAnnotations) {
|
|
|
1839
2062
|
|
|
1840
2063
|
|
|
1841
2064
|
|
|
1842
|
-
|
|
1843
2065
|
const RectangleROI = {
|
|
1844
2066
|
toAnnotation: measurement => {},
|
|
1845
2067
|
toMeasurement: (csToolsEventDetail, DisplaySetService, CornerstoneViewportService, getValueTypeFromToolType) => {
|
|
@@ -1937,20 +2159,22 @@ function RectangleROI_getMappedAnnotations(annotation, DisplaySetService) {
|
|
|
1937
2159
|
stdDev,
|
|
1938
2160
|
max,
|
|
1939
2161
|
area,
|
|
1940
|
-
Modality
|
|
2162
|
+
Modality,
|
|
2163
|
+
modalityUnit,
|
|
2164
|
+
areaUnit
|
|
1941
2165
|
} = targetStats;
|
|
1942
|
-
const unit = utils_getModalityUnit(Modality);
|
|
1943
2166
|
annotations.push({
|
|
1944
2167
|
SeriesInstanceUID,
|
|
1945
2168
|
SOPInstanceUID,
|
|
1946
2169
|
SeriesNumber,
|
|
1947
2170
|
frameNumber,
|
|
1948
2171
|
Modality,
|
|
1949
|
-
unit,
|
|
2172
|
+
unit: modalityUnit,
|
|
1950
2173
|
mean,
|
|
1951
2174
|
stdDev,
|
|
1952
2175
|
max,
|
|
1953
|
-
area
|
|
2176
|
+
area,
|
|
2177
|
+
areaUnit
|
|
1954
2178
|
});
|
|
1955
2179
|
});
|
|
1956
2180
|
return annotations;
|
|
@@ -1974,13 +2198,14 @@ function RectangleROI_getReport(mappedAnnotations, points, FrameOfReferenceUID)
|
|
|
1974
2198
|
stdDev,
|
|
1975
2199
|
max,
|
|
1976
2200
|
area,
|
|
1977
|
-
unit
|
|
2201
|
+
unit,
|
|
2202
|
+
areaUnit
|
|
1978
2203
|
} = annotation;
|
|
1979
2204
|
if (!mean || !unit || !max || !area) {
|
|
1980
2205
|
return;
|
|
1981
2206
|
}
|
|
1982
|
-
columns.push(`
|
|
1983
|
-
values.push(max, mean, stdDev, area);
|
|
2207
|
+
columns.push(`Maximum`, `Mean`, `Std Dev`, 'Pixel Unit', `Area`, 'Unit');
|
|
2208
|
+
values.push(max, mean, stdDev, unit, area, areaUnit);
|
|
1984
2209
|
});
|
|
1985
2210
|
if (FrameOfReferenceUID) {
|
|
1986
2211
|
columns.push('FrameOfReferenceUID');
|
|
@@ -2008,7 +2233,8 @@ function RectangleROI_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
2008
2233
|
const {
|
|
2009
2234
|
area,
|
|
2010
2235
|
SOPInstanceUID,
|
|
2011
|
-
frameNumber
|
|
2236
|
+
frameNumber,
|
|
2237
|
+
areaUnit
|
|
2012
2238
|
} = mappedAnnotations[0];
|
|
2013
2239
|
const instance = displaySet.images.find(image => image.SOPInstanceUID === SOPInstanceUID);
|
|
2014
2240
|
let InstanceNumber;
|
|
@@ -2020,7 +2246,7 @@ function RectangleROI_getDisplayText(mappedAnnotations, displaySet) {
|
|
|
2020
2246
|
|
|
2021
2247
|
// Area sometimes becomes undefined if `preventHandleOutsideImage` is off.
|
|
2022
2248
|
const roundedArea = src.utils.roundNumber(area || 0, 2);
|
|
2023
|
-
displayText.push(`${roundedArea}
|
|
2249
|
+
displayText.push(`${roundedArea} ${areaUnit}`);
|
|
2024
2250
|
|
|
2025
2251
|
// Todo: we need a better UI for displaying all these information
|
|
2026
2252
|
mappedAnnotations.forEach(mappedAnnotation => {
|
|
@@ -2515,7 +2741,7 @@ function getInterleavedFrames(imageIds) {
|
|
|
2515
2741
|
}
|
|
2516
2742
|
while (!prefetchQueuedFilled.currentPositionDownToMinimum || !prefetchQueuedFilled.currentPositionUpToMaximum) {
|
|
2517
2743
|
if (!prefetchQueuedFilled.currentPositionDownToMinimum) {
|
|
2518
|
-
// Add imageId
|
|
2744
|
+
// Add imageId below
|
|
2519
2745
|
lowerImageIdIndex--;
|
|
2520
2746
|
imageIdsToPrefetch.push({
|
|
2521
2747
|
imageId: imageIds[lowerImageIdIndex],
|
|
@@ -2540,7 +2766,7 @@ function getInterleavedFrames(imageIds) {
|
|
|
2540
2766
|
return imageIdsToPrefetch;
|
|
2541
2767
|
}
|
|
2542
2768
|
// EXTERNAL MODULE: ../../../node_modules/lodash/lodash.js
|
|
2543
|
-
var lodash = __webpack_require__(
|
|
2769
|
+
var lodash = __webpack_require__(44379);
|
|
2544
2770
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/interleaveCenterLoader.ts
|
|
2545
2771
|
|
|
2546
2772
|
|
|
@@ -2730,8 +2956,12 @@ function getNthFrames(imageIds) {
|
|
|
2730
2956
|
* @returns [] reordered to be breadth first traversal of lists
|
|
2731
2957
|
*/
|
|
2732
2958
|
function interleave(lists) {
|
|
2733
|
-
if (!lists || !lists.length)
|
|
2734
|
-
|
|
2959
|
+
if (!lists || !lists.length) {
|
|
2960
|
+
return [];
|
|
2961
|
+
}
|
|
2962
|
+
if (lists.length === 1) {
|
|
2963
|
+
return lists[0];
|
|
2964
|
+
}
|
|
2735
2965
|
console.time('interleave');
|
|
2736
2966
|
const useLists = [...lists];
|
|
2737
2967
|
const ret = [];
|
|
@@ -3004,6 +3234,7 @@ const DEFAULT_CONTEXT_MENU_CLICKS = {
|
|
|
3004
3234
|
commands: [{
|
|
3005
3235
|
commandName: 'showCornerstoneContextMenu',
|
|
3006
3236
|
commandOptions: {
|
|
3237
|
+
requireNearbyToolData: true,
|
|
3007
3238
|
menuId: 'measurementsContextMenu'
|
|
3008
3239
|
}
|
|
3009
3240
|
}]
|
|
@@ -3020,9 +3251,15 @@ const DEFAULT_CONTEXT_MENU_CLICKS = {
|
|
|
3020
3251
|
function getEventName(evt) {
|
|
3021
3252
|
const button = evt.detail.event.which;
|
|
3022
3253
|
const nameArr = [];
|
|
3023
|
-
if (evt.detail.event.altKey)
|
|
3024
|
-
|
|
3025
|
-
|
|
3254
|
+
if (evt.detail.event.altKey) {
|
|
3255
|
+
nameArr.push('alt');
|
|
3256
|
+
}
|
|
3257
|
+
if (evt.detail.event.ctrlKey) {
|
|
3258
|
+
nameArr.push('ctrl');
|
|
3259
|
+
}
|
|
3260
|
+
if (evt.detail.event.shiftKey) {
|
|
3261
|
+
nameArr.push('shift');
|
|
3262
|
+
}
|
|
3026
3263
|
nameArr.push('button');
|
|
3027
3264
|
nameArr.push(button);
|
|
3028
3265
|
return nameArr.join('');
|
|
@@ -3040,9 +3277,18 @@ function initContextMenu(_ref) {
|
|
|
3040
3277
|
const cornerstoneViewportHandleEvent = (name, evt) => {
|
|
3041
3278
|
const customizations = customizationService.get('cornerstoneViewportClickCommands') || DEFAULT_CONTEXT_MENU_CLICKS;
|
|
3042
3279
|
const toRun = customizations[name];
|
|
3043
|
-
|
|
3280
|
+
if (!toRun) {
|
|
3281
|
+
return;
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
// only find nearbyToolData if required, for the click (which closes the context menu
|
|
3285
|
+
// we don't need to find nearbyToolData)
|
|
3286
|
+
let nearbyToolData = null;
|
|
3287
|
+
if (toRun.commands.some(command => command.commandOptions?.requireNearbyToolData)) {
|
|
3288
|
+
nearbyToolData = findNearbyToolData(commandsManager, evt);
|
|
3289
|
+
}
|
|
3044
3290
|
const options = {
|
|
3045
|
-
nearbyToolData
|
|
3291
|
+
nearbyToolData,
|
|
3046
3292
|
event: evt
|
|
3047
3293
|
};
|
|
3048
3294
|
commandsManager.run(toRun, options);
|
|
@@ -3057,10 +3303,11 @@ function initContextMenu(_ref) {
|
|
|
3057
3303
|
element
|
|
3058
3304
|
} = evt.detail;
|
|
3059
3305
|
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
|
|
3060
|
-
if (!viewportInfo)
|
|
3061
|
-
|
|
3306
|
+
if (!viewportInfo) {
|
|
3307
|
+
return;
|
|
3308
|
+
}
|
|
3062
3309
|
// TODO check update upstream
|
|
3063
|
-
(0,state/* setEnabledElement */.Yc)(
|
|
3310
|
+
(0,state/* setEnabledElement */.Yc)(viewportId, element);
|
|
3064
3311
|
element.addEventListener(cs3DToolsEvents.MOUSE_CLICK, cornerstoneViewportHandleClick);
|
|
3065
3312
|
}
|
|
3066
3313
|
function elementDisabledHandler(evt) {
|
|
@@ -3094,9 +3341,15 @@ const DEFAULT_DOUBLE_CLICK = {
|
|
|
3094
3341
|
*/
|
|
3095
3342
|
function getDoubleClickEventName(evt) {
|
|
3096
3343
|
const nameArr = [];
|
|
3097
|
-
if (evt.detail.event.altKey)
|
|
3098
|
-
|
|
3099
|
-
|
|
3344
|
+
if (evt.detail.event.altKey) {
|
|
3345
|
+
nameArr.push('alt');
|
|
3346
|
+
}
|
|
3347
|
+
if (evt.detail.event.ctrlKey) {
|
|
3348
|
+
nameArr.push('ctrl');
|
|
3349
|
+
}
|
|
3350
|
+
if (evt.detail.event.shiftKey) {
|
|
3351
|
+
nameArr.push('shift');
|
|
3352
|
+
}
|
|
3100
3353
|
nameArr.push('doubleClick');
|
|
3101
3354
|
return nameArr.join('');
|
|
3102
3355
|
}
|
|
@@ -3154,7 +3407,6 @@ function initDoubleClick(_ref) {
|
|
|
3154
3407
|
|
|
3155
3408
|
|
|
3156
3409
|
|
|
3157
|
-
|
|
3158
3410
|
// TODO: Cypress tests are currently grabbing this from the window?
|
|
3159
3411
|
window.cornerstone = esm;
|
|
3160
3412
|
window.cornerstoneTools = dist_esm;
|
|
@@ -3169,10 +3421,25 @@ async function init(_ref) {
|
|
|
3169
3421
|
configuration,
|
|
3170
3422
|
appConfig
|
|
3171
3423
|
} = _ref;
|
|
3172
|
-
await (0,esm.init)(
|
|
3424
|
+
await (0,esm.init)({
|
|
3425
|
+
rendering: {
|
|
3426
|
+
preferSizeOverAccuracy: Boolean(appConfig.use16BitDataType),
|
|
3427
|
+
useNorm16Texture: Boolean(appConfig.use16BitDataType)
|
|
3428
|
+
}
|
|
3429
|
+
});
|
|
3173
3430
|
|
|
3174
3431
|
// For debugging e2e tests that are failing on CI
|
|
3175
3432
|
esm.setUseCPURendering(Boolean(appConfig.useCPURendering));
|
|
3433
|
+
switch (appConfig.useSharedArrayBuffer) {
|
|
3434
|
+
case 'AUTO':
|
|
3435
|
+
esm.setUseSharedArrayBuffer(esm.Enums.SharedArrayBufferModes.AUTO);
|
|
3436
|
+
break;
|
|
3437
|
+
case 'FALSE':
|
|
3438
|
+
esm.setUseSharedArrayBuffer(esm.Enums.SharedArrayBufferModes.FALSE);
|
|
3439
|
+
break;
|
|
3440
|
+
default:
|
|
3441
|
+
esm.setUseSharedArrayBuffer(esm.Enums.SharedArrayBufferModes.TRUE);
|
|
3442
|
+
}
|
|
3176
3443
|
esm.setConfiguration({
|
|
3177
3444
|
...esm.getConfiguration(),
|
|
3178
3445
|
rendering: {
|
|
@@ -3181,18 +3448,18 @@ async function init(_ref) {
|
|
|
3181
3448
|
}
|
|
3182
3449
|
});
|
|
3183
3450
|
|
|
3184
|
-
// For debugging large datasets
|
|
3185
|
-
const
|
|
3186
|
-
|
|
3187
|
-
|
|
3451
|
+
// For debugging large datasets, otherwise prefer the defaults
|
|
3452
|
+
const {
|
|
3453
|
+
maxCacheSize
|
|
3454
|
+
} = appConfig;
|
|
3455
|
+
if (maxCacheSize) {
|
|
3456
|
+
esm.cache.setMaxCacheSize(maxCacheSize);
|
|
3457
|
+
}
|
|
3188
3458
|
initCornerstoneTools();
|
|
3189
3459
|
esm.Settings.getRuntimeSettings().set('useCursors', Boolean(appConfig.useCursors));
|
|
3190
3460
|
const {
|
|
3191
3461
|
userAuthenticationService,
|
|
3192
|
-
measurementService,
|
|
3193
3462
|
customizationService,
|
|
3194
|
-
displaySetService,
|
|
3195
|
-
uiDialogService,
|
|
3196
3463
|
uiModalService,
|
|
3197
3464
|
uiNotificationService,
|
|
3198
3465
|
cineService,
|
|
@@ -3254,7 +3521,7 @@ async function init(_ref) {
|
|
|
3254
3521
|
thumbnail: appConfig?.maxNumRequests?.thumbnail || 75,
|
|
3255
3522
|
prefetch: appConfig?.maxNumRequests?.prefetch || 10
|
|
3256
3523
|
};
|
|
3257
|
-
initWADOImageLoader(userAuthenticationService, appConfig);
|
|
3524
|
+
initWADOImageLoader(userAuthenticationService, appConfig, extensionManager);
|
|
3258
3525
|
|
|
3259
3526
|
/* Measurement Service */
|
|
3260
3527
|
this.measurementServiceSource = connectToolsToMeasurementService(servicesManager);
|
|
@@ -3338,12 +3605,10 @@ async function init(_ref) {
|
|
|
3338
3605
|
|
|
3339
3606
|
esm.eventTarget.addEventListener(esm.EVENTS.ELEMENT_ENABLED, elementEnabledHandler.bind(null));
|
|
3340
3607
|
esm.eventTarget.addEventListener(esm.EVENTS.ELEMENT_DISABLED, elementDisabledHandler.bind(null));
|
|
3341
|
-
viewportGridService.subscribe(viewportGridService.EVENTS.
|
|
3608
|
+
viewportGridService.subscribe(viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED, _ref2 => {
|
|
3342
3609
|
let {
|
|
3343
|
-
viewportIndex,
|
|
3344
3610
|
viewportId
|
|
3345
3611
|
} = _ref2;
|
|
3346
|
-
viewportId = viewportId || `viewport-${viewportIndex}`;
|
|
3347
3612
|
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
|
3348
3613
|
if (!toolGroup || !toolGroup._toolInstances?.['ReferenceLines']) {
|
|
3349
3614
|
return;
|
|
@@ -3387,12 +3652,12 @@ function _showCPURenderingModal(uiModalService, hangingProtocolService) {
|
|
|
3387
3652
|
});
|
|
3388
3653
|
}
|
|
3389
3654
|
// EXTERNAL MODULE: ../../../node_modules/react-dropzone/dist/es/index.js + 5 modules
|
|
3390
|
-
var es = __webpack_require__(
|
|
3655
|
+
var es = __webpack_require__(74834);
|
|
3391
3656
|
// EXTERNAL MODULE: ../../../node_modules/prop-types/index.js
|
|
3392
|
-
var prop_types = __webpack_require__(
|
|
3657
|
+
var prop_types = __webpack_require__(3827);
|
|
3393
3658
|
var prop_types_default = /*#__PURE__*/__webpack_require__.n(prop_types);
|
|
3394
3659
|
// EXTERNAL MODULE: ../../../node_modules/classnames/index.js
|
|
3395
|
-
var classnames = __webpack_require__(
|
|
3660
|
+
var classnames = __webpack_require__(44921);
|
|
3396
3661
|
var classnames_default = /*#__PURE__*/__webpack_require__.n(classnames);
|
|
3397
3662
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/DicomFileUploader.ts
|
|
3398
3663
|
|
|
@@ -3541,7 +3806,9 @@ class DicomFileUploader extends src/* PubSubService */.hC {
|
|
|
3541
3806
|
request.addEventListener('loadend', cleanUpCallback);
|
|
3542
3807
|
}
|
|
3543
3808
|
_checkDicomFile(arrayBuffer) {
|
|
3544
|
-
if (arrayBuffer.length <= 132)
|
|
3809
|
+
if (arrayBuffer.length <= 132) {
|
|
3810
|
+
return false;
|
|
3811
|
+
}
|
|
3545
3812
|
const arr = new Uint8Array(arrayBuffer.slice(128, 132));
|
|
3546
3813
|
// bytes from 128 to 132 must be "DICM"
|
|
3547
3814
|
return Array.from('DICM').every((char, i) => char.charCodeAt(0) === arr[i]);
|
|
@@ -3560,7 +3827,6 @@ const DicomUploadProgressItem = /*#__PURE__*/(0,react.memo)(_ref => {
|
|
|
3560
3827
|
const [percentComplete, setPercentComplete] = (0,react.useState)(dicomFileUploader.getPercentComplete());
|
|
3561
3828
|
const [failedReason, setFailedReason] = (0,react.useState)('');
|
|
3562
3829
|
const [status, setStatus] = (0,react.useState)(dicomFileUploader.getStatus());
|
|
3563
|
-
console.info(`${dicomFileUploader.getFileId()}`);
|
|
3564
3830
|
const isComplete = (0,react.useCallback)(() => {
|
|
3565
3831
|
return status === UploadStatus.Failed || status === UploadStatus.Cancelled || status === UploadStatus.Success;
|
|
3566
3832
|
}, [status]);
|
|
@@ -3601,25 +3867,25 @@ const DicomUploadProgressItem = /*#__PURE__*/(0,react.memo)(_ref => {
|
|
|
3601
3867
|
}
|
|
3602
3868
|
};
|
|
3603
3869
|
return /*#__PURE__*/react.createElement("div", {
|
|
3604
|
-
className: "
|
|
3870
|
+
className: "min-h-14 border-secondary-light flex w-full items-center overflow-hidden border-b p-2.5 text-lg"
|
|
3605
3871
|
}, /*#__PURE__*/react.createElement("div", {
|
|
3606
|
-
className: "
|
|
3872
|
+
className: "self-top flex w-0 shrink grow flex-col gap-1"
|
|
3607
3873
|
}, /*#__PURE__*/react.createElement("div", {
|
|
3608
3874
|
className: "flex gap-4"
|
|
3609
3875
|
}, /*#__PURE__*/react.createElement("div", {
|
|
3610
|
-
className: "flex w-6
|
|
3876
|
+
className: "flex w-6 shrink-0 items-center justify-center"
|
|
3611
3877
|
}, getStatusIcon()), /*#__PURE__*/react.createElement("div", {
|
|
3612
|
-
className: "text-ellipsis whitespace-nowrap
|
|
3878
|
+
className: "overflow-hidden text-ellipsis whitespace-nowrap"
|
|
3613
3879
|
}, dicomFileUploader.getFileName())), failedReason && /*#__PURE__*/react.createElement("div", {
|
|
3614
3880
|
className: "pl-10"
|
|
3615
3881
|
}, failedReason)), /*#__PURE__*/react.createElement("div", {
|
|
3616
|
-
className: "w-24
|
|
3882
|
+
className: "flex w-24 items-center"
|
|
3617
3883
|
}, !isComplete() && /*#__PURE__*/react.createElement(react.Fragment, null, dicomFileUploader.getStatus() === UploadStatus.InProgress && /*#__PURE__*/react.createElement("div", {
|
|
3618
3884
|
className: "w-10 text-right"
|
|
3619
3885
|
}, percentComplete, "%"), /*#__PURE__*/react.createElement("div", {
|
|
3620
|
-
className: "flex cursor-pointer
|
|
3886
|
+
className: "ml-auto flex cursor-pointer"
|
|
3621
3887
|
}, /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
|
|
3622
|
-
className: "
|
|
3888
|
+
className: "text-primary-active self-center",
|
|
3623
3889
|
name: "close",
|
|
3624
3890
|
onClick: cancelUpload
|
|
3625
3891
|
})))));
|
|
@@ -3846,7 +4112,7 @@ function DicomUploadProgress(_ref) {
|
|
|
3846
4112
|
}, []);
|
|
3847
4113
|
const getNumCompletedAndTimeRemainingComponent = () => {
|
|
3848
4114
|
return /*#__PURE__*/react.createElement("div", {
|
|
3849
|
-
className: "
|
|
4115
|
+
className: "bg-primary-dark flex h-14 items-center px-1 pb-4 text-lg"
|
|
3850
4116
|
}, numFilesCompleted === dicomFileUploaderArr.length ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("span", {
|
|
3851
4117
|
className: NO_WRAP_ELLIPSIS_CLASS_NAMES
|
|
3852
4118
|
}, `${dicomFileUploaderArr.length} ${dicomFileUploaderArr.length > 1 ? 'files' : 'file'} completed.`), /*#__PURE__*/react.createElement(ui_src/* Button */.zx, {
|
|
@@ -3861,13 +4127,13 @@ function DicomUploadProgress(_ref) {
|
|
|
3861
4127
|
}, ' files completed.', "\xA0"), /*#__PURE__*/react.createElement("span", {
|
|
3862
4128
|
className: NO_WRAP_ELLIPSIS_CLASS_NAMES
|
|
3863
4129
|
}, timeRemaining ? `Less than ${getFormattedTimeRemaining()} remaining. ` : ''), /*#__PURE__*/react.createElement("span", {
|
|
3864
|
-
className: classnames_default()(NO_WRAP_ELLIPSIS_CLASS_NAMES, '
|
|
4130
|
+
className: classnames_default()(NO_WRAP_ELLIPSIS_CLASS_NAMES, 'text-primary-active hover:text-primary-light active:text-aqua-pale ml-auto cursor-pointer'),
|
|
3865
4131
|
onClick: cancelAllUploads
|
|
3866
4132
|
}, "Cancel All Uploads")));
|
|
3867
4133
|
};
|
|
3868
4134
|
const getShowFailedOnlyIconComponent = () => {
|
|
3869
4135
|
return /*#__PURE__*/react.createElement("div", {
|
|
3870
|
-
className: "ml-auto flex justify-center
|
|
4136
|
+
className: "ml-auto flex w-6 justify-center"
|
|
3871
4137
|
}, numFails > 0 && /*#__PURE__*/react.createElement("div", {
|
|
3872
4138
|
onClick: () => setShowFailedOnly(currentShowFailedOnly => !currentShowFailedOnly)
|
|
3873
4139
|
}, /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
|
|
@@ -3877,28 +4143,28 @@ function DicomUploadProgress(_ref) {
|
|
|
3877
4143
|
};
|
|
3878
4144
|
const getPercentCompleteComponent = () => {
|
|
3879
4145
|
return /*#__PURE__*/react.createElement("div", {
|
|
3880
|
-
className: "overflow-y-scroll
|
|
4146
|
+
className: "ohif-scrollbar border-secondary-light overflow-y-scroll border-b px-2"
|
|
3881
4147
|
}, /*#__PURE__*/react.createElement("div", {
|
|
3882
|
-
className: "flex w-full p-2.5
|
|
4148
|
+
className: "min-h-14 flex w-full items-center p-2.5"
|
|
3883
4149
|
}, numFilesCompleted === dicomFileUploaderArr.length ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
|
|
3884
|
-
className: "text-
|
|
4150
|
+
className: "text-primary-light text-xl"
|
|
3885
4151
|
}, numFails > 0 ? `Completed with ${numFails} ${numFails > 1 ? 'errors' : 'error'}!` : 'Completed!'), getShowFailedOnlyIconComponent()) : /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
|
|
3886
4152
|
ref: progressBarContainerRef,
|
|
3887
4153
|
className: "flex-grow"
|
|
3888
4154
|
}, /*#__PURE__*/react.createElement(ui_src/* ProgressLoadingBar */.YE, {
|
|
3889
4155
|
progress: showInfiniteProgressBar() ? undefined : Math.min(100, percentComplete)
|
|
3890
4156
|
})), /*#__PURE__*/react.createElement("div", {
|
|
3891
|
-
className: "
|
|
4157
|
+
className: "ml-1 flex w-24 items-center"
|
|
3892
4158
|
}, /*#__PURE__*/react.createElement("div", {
|
|
3893
4159
|
className: "w-10 text-right"
|
|
3894
4160
|
}, `${getPercentCompleteRounded()}%`), getShowFailedOnlyIconComponent()))));
|
|
3895
4161
|
};
|
|
3896
4162
|
return /*#__PURE__*/react.createElement("div", {
|
|
3897
|
-
className: "flex flex-col
|
|
4163
|
+
className: "flex grow flex-col"
|
|
3898
4164
|
}, getNumCompletedAndTimeRemainingComponent(), /*#__PURE__*/react.createElement("div", {
|
|
3899
|
-
className: "flex flex-col bg-black text-lg
|
|
4165
|
+
className: "flex grow flex-col overflow-hidden bg-black text-lg"
|
|
3900
4166
|
}, getPercentCompleteComponent(), /*#__PURE__*/react.createElement("div", {
|
|
3901
|
-
className: "overflow-y-scroll
|
|
4167
|
+
className: "ohif-scrollbar h-1 grow overflow-y-scroll px-2"
|
|
3902
4168
|
}, dicomFileUploaderArr.filter(dicomFileUploader => !showFailedOnly || dicomFileUploader.getStatus() === UploadStatus.Failed).map(dicomFileUploader => /*#__PURE__*/react.createElement(DicomUpload_DicomUploadProgressItem, {
|
|
3903
4169
|
key: dicomFileUploader.getFileId(),
|
|
3904
4170
|
dicomFileUploader: dicomFileUploader
|
|
@@ -3945,7 +4211,7 @@ function DicomUpload(_ref) {
|
|
|
3945
4211
|
getRootProps
|
|
3946
4212
|
} = _ref2;
|
|
3947
4213
|
return /*#__PURE__*/react.createElement("div", _extends({}, getRootProps(), {
|
|
3948
|
-
className: "
|
|
4214
|
+
className: "dicom-upload-drop-area-border-dash m-5 flex h-full flex-col items-center justify-center"
|
|
3949
4215
|
}), /*#__PURE__*/react.createElement("div", {
|
|
3950
4216
|
className: "flex gap-3"
|
|
3951
4217
|
}, /*#__PURE__*/react.createElement(es/* default */.Z, {
|
|
@@ -3969,7 +4235,7 @@ function DicomUpload(_ref) {
|
|
|
3969
4235
|
getInputProps
|
|
3970
4236
|
} = _ref4;
|
|
3971
4237
|
return /*#__PURE__*/react.createElement("div", getRootProps(), /*#__PURE__*/react.createElement(ui_src/* Button */.zx, {
|
|
3972
|
-
type: ui_src/* ButtonEnums.type */.LZ.
|
|
4238
|
+
type: ui_src/* ButtonEnums.type */.LZ.dt.secondary,
|
|
3973
4239
|
disabled: false,
|
|
3974
4240
|
onClick: () => {}
|
|
3975
4241
|
}, 'Add folder', /*#__PURE__*/react.createElement("input", _extends({}, getInputProps(), {
|
|
@@ -3979,7 +4245,7 @@ function DicomUpload(_ref) {
|
|
|
3979
4245
|
})), /*#__PURE__*/react.createElement("div", {
|
|
3980
4246
|
className: "pt-5"
|
|
3981
4247
|
}, "or drag images or folders here"), /*#__PURE__*/react.createElement("div", {
|
|
3982
|
-
className: "
|
|
4248
|
+
className: "text-aqua-pale pt-3 text-lg"
|
|
3983
4249
|
}, "(DICOM files supported)"));
|
|
3984
4250
|
});
|
|
3985
4251
|
};
|
|
@@ -4043,7 +4309,7 @@ function getCustomizationModule() {
|
|
|
4043
4309
|
}
|
|
4044
4310
|
/* harmony default export */ const src_getCustomizationModule = (getCustomizationModule);
|
|
4045
4311
|
// EXTERNAL MODULE: ../../../node_modules/html2canvas/dist/html2canvas.esm.js
|
|
4046
|
-
var html2canvas_esm = __webpack_require__(
|
|
4312
|
+
var html2canvas_esm = __webpack_require__(76010);
|
|
4047
4313
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/CornerstoneViewportDownloadForm.tsx
|
|
4048
4314
|
|
|
4049
4315
|
|
|
@@ -4059,10 +4325,10 @@ const VIEWPORT_ID = 'cornerstone-viewport-download-form';
|
|
|
4059
4325
|
const CornerstoneViewportDownloadForm = _ref => {
|
|
4060
4326
|
let {
|
|
4061
4327
|
onClose,
|
|
4062
|
-
|
|
4328
|
+
activeViewportId: activeViewportIdProp,
|
|
4063
4329
|
cornerstoneViewportService
|
|
4064
4330
|
} = _ref;
|
|
4065
|
-
const enabledElement = (0,state/* getEnabledElement */.K8)(
|
|
4331
|
+
const enabledElement = (0,state/* getEnabledElement */.K8)(activeViewportIdProp);
|
|
4066
4332
|
const activeViewportElement = enabledElement?.element;
|
|
4067
4333
|
const activeViewportEnabledElement = (0,esm.getEnabledElement)(activeViewportElement);
|
|
4068
4334
|
const {
|
|
@@ -4264,7 +4530,7 @@ const CornerstoneViewportDownloadForm = _ref => {
|
|
|
4264
4530
|
};
|
|
4265
4531
|
CornerstoneViewportDownloadForm.propTypes = {
|
|
4266
4532
|
onClose: (prop_types_default()).func,
|
|
4267
|
-
|
|
4533
|
+
activeViewportId: (prop_types_default()).string.isRequired
|
|
4268
4534
|
};
|
|
4269
4535
|
/* harmony default export */ const utils_CornerstoneViewportDownloadForm = (CornerstoneViewportDownloadForm);
|
|
4270
4536
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/stackSync/calculateViewportRegistrations.ts
|
|
@@ -4294,7 +4560,7 @@ const _getViewportPairs = viewports => {
|
|
|
4294
4560
|
|
|
4295
4561
|
// [ {
|
|
4296
4562
|
// synchronizerId: string,
|
|
4297
|
-
// viewports: [ { viewportId:
|
|
4563
|
+
// viewports: [ { viewportId: string, renderingEngineId: string, index: number } , ...]
|
|
4298
4564
|
// ]}
|
|
4299
4565
|
let STACK_IMAGE_SYNC_GROUPS_INFO = [];
|
|
4300
4566
|
function toggleStackImageSync(_ref) {
|
|
@@ -4328,27 +4594,23 @@ function toggleStackImageSync(_ref) {
|
|
|
4328
4594
|
STACK_IMAGE_SYNC_GROUPS_INFO = [];
|
|
4329
4595
|
|
|
4330
4596
|
// create synchronization groups and add viewports
|
|
4331
|
-
|
|
4597
|
+
const {
|
|
4332
4598
|
viewports
|
|
4333
4599
|
} = viewportGridService.getState();
|
|
4334
4600
|
|
|
4335
4601
|
// filter empty viewports
|
|
4336
|
-
|
|
4337
|
-
|
|
4602
|
+
const viewportsArray = Array.from(viewports.values()).filter(viewport => viewport.displaySetInstanceUIDs?.length)
|
|
4338
4603
|
// filter reconstructable viewports
|
|
4339
|
-
|
|
4604
|
+
.filter(viewport => {
|
|
4340
4605
|
const {
|
|
4341
4606
|
displaySetInstanceUIDs
|
|
4342
4607
|
} = viewport;
|
|
4343
4608
|
for (const displaySetInstanceUID of displaySetInstanceUIDs) {
|
|
4344
4609
|
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
|
4345
|
-
|
|
4346
|
-
return true;
|
|
4347
|
-
}
|
|
4348
|
-
return false;
|
|
4610
|
+
return !!displaySet?.isReconstructable;
|
|
4349
4611
|
}
|
|
4350
4612
|
});
|
|
4351
|
-
const viewportsByOrientation =
|
|
4613
|
+
const viewportsByOrientation = viewportsArray.reduce((acc, viewport) => {
|
|
4352
4614
|
const {
|
|
4353
4615
|
viewportId,
|
|
4354
4616
|
viewportType
|
|
@@ -4457,6 +4719,7 @@ function commandsModule(_ref) {
|
|
|
4457
4719
|
toolGroupService,
|
|
4458
4720
|
cineService,
|
|
4459
4721
|
toolbarService,
|
|
4722
|
+
stateSyncService,
|
|
4460
4723
|
uiDialogService,
|
|
4461
4724
|
cornerstoneViewportService,
|
|
4462
4725
|
uiNotificationService,
|
|
@@ -4650,8 +4913,7 @@ function commandsModule(_ref) {
|
|
|
4650
4913
|
console.warn('No viewport found for viewportId:', viewportId);
|
|
4651
4914
|
return;
|
|
4652
4915
|
}
|
|
4653
|
-
|
|
4654
|
-
viewportGridService.setActiveViewportIndex(viewportIndex);
|
|
4916
|
+
viewportGridService.setActiveViewportId(viewportId);
|
|
4655
4917
|
},
|
|
4656
4918
|
arrowTextCallback: _ref7 => {
|
|
4657
4919
|
let {
|
|
@@ -4719,7 +4981,8 @@ function commandsModule(_ref) {
|
|
|
4719
4981
|
setToolActive: _ref9 => {
|
|
4720
4982
|
let {
|
|
4721
4983
|
toolName,
|
|
4722
|
-
toolGroupId = null
|
|
4984
|
+
toolGroupId = null,
|
|
4985
|
+
toggledState
|
|
4723
4986
|
} = _ref9;
|
|
4724
4987
|
if (toolName === 'Crosshairs') {
|
|
4725
4988
|
const activeViewportToolGroup = toolGroupService.getToolGroup(null);
|
|
@@ -4735,9 +4998,10 @@ function commandsModule(_ref) {
|
|
|
4735
4998
|
}
|
|
4736
4999
|
const {
|
|
4737
5000
|
viewports
|
|
4738
|
-
} = viewportGridService.getState()
|
|
4739
|
-
|
|
4740
|
-
|
|
5001
|
+
} = viewportGridService.getState();
|
|
5002
|
+
if (!viewports.size) {
|
|
5003
|
+
return;
|
|
5004
|
+
}
|
|
4741
5005
|
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
|
|
4742
5006
|
const toolGroupViewportIds = toolGroup?.getViewportIds?.();
|
|
4743
5007
|
|
|
@@ -4745,11 +5009,8 @@ function commandsModule(_ref) {
|
|
|
4745
5009
|
if (!toolGroupViewportIds || !toolGroupViewportIds.length) {
|
|
4746
5010
|
return;
|
|
4747
5011
|
}
|
|
4748
|
-
const filteredViewports = viewports.filter(viewport => {
|
|
4749
|
-
|
|
4750
|
-
return false;
|
|
4751
|
-
}
|
|
4752
|
-
return toolGroupViewportIds.includes(viewport.viewportOptions.viewportId);
|
|
5012
|
+
const filteredViewports = Array.from(viewports.values()).filter(viewport => {
|
|
5013
|
+
return toolGroupViewportIds.includes(viewport.viewportId);
|
|
4753
5014
|
});
|
|
4754
5015
|
if (!filteredViewports.length) {
|
|
4755
5016
|
return;
|
|
@@ -4773,6 +5034,14 @@ function commandsModule(_ref) {
|
|
|
4773
5034
|
toolGroup.setToolPassive(activeToolName);
|
|
4774
5035
|
}
|
|
4775
5036
|
}
|
|
5037
|
+
|
|
5038
|
+
// If there is a toggle state, then simply set the enabled/disabled state without
|
|
5039
|
+
// setting the tool active.
|
|
5040
|
+
if (toggledState != null) {
|
|
5041
|
+
toggledState ? toolGroup.setToolEnabled(toolName) : toolGroup.setToolDisabled(toolName);
|
|
5042
|
+
return;
|
|
5043
|
+
}
|
|
5044
|
+
|
|
4776
5045
|
// Set the new toolName to be active
|
|
4777
5046
|
toolGroup.setToolActive(toolName, {
|
|
4778
5047
|
bindings: [{
|
|
@@ -4782,9 +5051,9 @@ function commandsModule(_ref) {
|
|
|
4782
5051
|
},
|
|
4783
5052
|
showDownloadViewportModal: () => {
|
|
4784
5053
|
const {
|
|
4785
|
-
|
|
5054
|
+
activeViewportId
|
|
4786
5055
|
} = viewportGridService.getState();
|
|
4787
|
-
if (!cornerstoneViewportService.
|
|
5056
|
+
if (!cornerstoneViewportService.getCornerstoneViewport(activeViewportId)) {
|
|
4788
5057
|
// Cannot download a non-cornerstone viewport (image).
|
|
4789
5058
|
uiNotificationService.show({
|
|
4790
5059
|
title: 'Download Image',
|
|
@@ -4801,7 +5070,7 @@ function commandsModule(_ref) {
|
|
|
4801
5070
|
content: utils_CornerstoneViewportDownloadForm,
|
|
4802
5071
|
title: 'Download High Quality Image',
|
|
4803
5072
|
contentProps: {
|
|
4804
|
-
|
|
5073
|
+
activeViewportId,
|
|
4805
5074
|
onClose: uiModalService.hide,
|
|
4806
5075
|
cornerstoneViewportService
|
|
4807
5076
|
}
|
|
@@ -4882,15 +5151,13 @@ function commandsModule(_ref) {
|
|
|
4882
5151
|
const {
|
|
4883
5152
|
viewport
|
|
4884
5153
|
} = enabledElement;
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
viewport.render();
|
|
4893
|
-
}
|
|
5154
|
+
const {
|
|
5155
|
+
invert
|
|
5156
|
+
} = viewport.getProperties();
|
|
5157
|
+
viewport.setProperties({
|
|
5158
|
+
invert: !invert
|
|
5159
|
+
});
|
|
5160
|
+
viewport.render();
|
|
4894
5161
|
},
|
|
4895
5162
|
resetViewport: () => {
|
|
4896
5163
|
const enabledElement = _getActiveViewportEnabledElement();
|
|
@@ -4993,12 +5260,12 @@ function commandsModule(_ref) {
|
|
|
4993
5260
|
},
|
|
4994
5261
|
setViewportColormap: _ref15 => {
|
|
4995
5262
|
let {
|
|
4996
|
-
|
|
5263
|
+
viewportId,
|
|
4997
5264
|
displaySetInstanceUID,
|
|
4998
5265
|
colormap,
|
|
4999
5266
|
immediate = false
|
|
5000
5267
|
} = _ref15;
|
|
5001
|
-
const viewport = cornerstoneViewportService.
|
|
5268
|
+
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
|
|
5002
5269
|
const actorEntries = viewport.getActors();
|
|
5003
5270
|
const actorEntry = actorEntries.find(actorEntry => {
|
|
5004
5271
|
return actorEntry.uid.includes(displaySetInstanceUID);
|
|
@@ -5015,51 +5282,52 @@ function commandsModule(_ref) {
|
|
|
5015
5282
|
viewport.render();
|
|
5016
5283
|
}
|
|
5017
5284
|
},
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
} = viewportGridService.getState();
|
|
5023
|
-
const nextViewportIndex = (activeViewportIndex + 1) % viewports.length;
|
|
5024
|
-
viewportGridService.setActiveViewportIndex(nextViewportIndex);
|
|
5025
|
-
},
|
|
5026
|
-
decrementActiveViewport: () => {
|
|
5285
|
+
changeActiveViewport: _ref16 => {
|
|
5286
|
+
let {
|
|
5287
|
+
direction = 1
|
|
5288
|
+
} = _ref16;
|
|
5027
5289
|
const {
|
|
5028
|
-
|
|
5290
|
+
activeViewportId,
|
|
5029
5291
|
viewports
|
|
5030
5292
|
} = viewportGridService.getState();
|
|
5031
|
-
const
|
|
5032
|
-
|
|
5293
|
+
const viewportIds = Array.from(viewports.keys());
|
|
5294
|
+
const currentIndex = viewportIds.indexOf(activeViewportId);
|
|
5295
|
+
const nextViewportIndex = (currentIndex + direction + viewportIds.length) % viewportIds.length;
|
|
5296
|
+
viewportGridService.setActiveViewportId(viewportIds[nextViewportIndex]);
|
|
5033
5297
|
},
|
|
5034
|
-
toggleStackImageSync:
|
|
5298
|
+
toggleStackImageSync: _ref17 => {
|
|
5035
5299
|
let {
|
|
5036
5300
|
toggledState
|
|
5037
|
-
} =
|
|
5301
|
+
} = _ref17;
|
|
5038
5302
|
toggleStackImageSync({
|
|
5039
5303
|
getEnabledElement: esm.getEnabledElement,
|
|
5040
5304
|
servicesManager,
|
|
5041
5305
|
toggledState
|
|
5042
5306
|
});
|
|
5043
5307
|
},
|
|
5044
|
-
|
|
5308
|
+
setSourceViewportForReferenceLinesTool: _ref18 => {
|
|
5045
5309
|
let {
|
|
5046
5310
|
toggledState
|
|
5047
|
-
} =
|
|
5311
|
+
} = _ref18;
|
|
5048
5312
|
const {
|
|
5049
|
-
|
|
5313
|
+
activeViewportId
|
|
5050
5314
|
} = viewportGridService.getState();
|
|
5051
|
-
const viewportInfo = cornerstoneViewportService.
|
|
5315
|
+
const viewportInfo = cornerstoneViewportService.getViewportInfo(activeViewportId);
|
|
5052
5316
|
const viewportId = viewportInfo.getViewportId();
|
|
5053
5317
|
const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
|
|
5054
|
-
if (!toggledState) {
|
|
5055
|
-
toolGroup.setToolDisabled(dist_esm.ReferenceLinesTool.toolName);
|
|
5056
|
-
}
|
|
5057
5318
|
toolGroup.setToolConfiguration(dist_esm.ReferenceLinesTool.toolName, {
|
|
5058
5319
|
sourceViewportId: viewportId
|
|
5059
5320
|
}, true // overwrite
|
|
5060
5321
|
);
|
|
5322
|
+
},
|
|
5061
5323
|
|
|
5062
|
-
|
|
5324
|
+
storePresentation: _ref19 => {
|
|
5325
|
+
let {
|
|
5326
|
+
viewportId
|
|
5327
|
+
} = _ref19;
|
|
5328
|
+
cornerstoneViewportService.storePresentation({
|
|
5329
|
+
viewportId
|
|
5330
|
+
});
|
|
5063
5331
|
}
|
|
5064
5332
|
};
|
|
5065
5333
|
const definitions = {
|
|
@@ -5114,10 +5382,13 @@ function commandsModule(_ref) {
|
|
|
5114
5382
|
}
|
|
5115
5383
|
},
|
|
5116
5384
|
incrementActiveViewport: {
|
|
5117
|
-
commandFn: actions.
|
|
5385
|
+
commandFn: actions.changeActiveViewport
|
|
5118
5386
|
},
|
|
5119
5387
|
decrementActiveViewport: {
|
|
5120
|
-
commandFn: actions.
|
|
5388
|
+
commandFn: actions.changeActiveViewport,
|
|
5389
|
+
options: {
|
|
5390
|
+
direction: -1
|
|
5391
|
+
}
|
|
5121
5392
|
},
|
|
5122
5393
|
flipViewportHorizontal: {
|
|
5123
5394
|
commandFn: actions.flipViewportHorizontal
|
|
@@ -5194,8 +5465,13 @@ function commandsModule(_ref) {
|
|
|
5194
5465
|
toggleStackImageSync: {
|
|
5195
5466
|
commandFn: actions.toggleStackImageSync
|
|
5196
5467
|
},
|
|
5197
|
-
|
|
5198
|
-
commandFn: actions.
|
|
5468
|
+
setSourceViewportForReferenceLinesTool: {
|
|
5469
|
+
commandFn: actions.setSourceViewportForReferenceLinesTool
|
|
5470
|
+
},
|
|
5471
|
+
storePresentation: {
|
|
5472
|
+
commandFn: actions.storePresentation,
|
|
5473
|
+
storeContexts: [],
|
|
5474
|
+
options: {}
|
|
5199
5475
|
}
|
|
5200
5476
|
};
|
|
5201
5477
|
return {
|
|
@@ -5210,9 +5486,8 @@ const mpr = {
|
|
|
5210
5486
|
id: 'mpr',
|
|
5211
5487
|
name: 'Multi-Planar Reconstruction',
|
|
5212
5488
|
locked: true,
|
|
5213
|
-
hasUpdatedPriorsInformation: false,
|
|
5214
5489
|
createdDate: '2021-02-23',
|
|
5215
|
-
modifiedDate: '2023-
|
|
5490
|
+
modifiedDate: '2023-08-15',
|
|
5216
5491
|
availableTo: {},
|
|
5217
5492
|
editableBy: {},
|
|
5218
5493
|
// Unknown number of priors referenced - so just match any study
|
|
@@ -5283,6 +5558,7 @@ const mpr = {
|
|
|
5283
5558
|
},
|
|
5284
5559
|
viewports: [{
|
|
5285
5560
|
viewportOptions: {
|
|
5561
|
+
viewportId: 'mpr-axial',
|
|
5286
5562
|
toolGroupId: 'mpr',
|
|
5287
5563
|
viewportType: 'volume',
|
|
5288
5564
|
orientation: 'axial',
|
|
@@ -5301,6 +5577,7 @@ const mpr = {
|
|
|
5301
5577
|
}]
|
|
5302
5578
|
}, {
|
|
5303
5579
|
viewportOptions: {
|
|
5580
|
+
viewportId: 'mpr-sagittal',
|
|
5304
5581
|
toolGroupId: 'mpr',
|
|
5305
5582
|
viewportType: 'volume',
|
|
5306
5583
|
orientation: 'sagittal',
|
|
@@ -5319,6 +5596,7 @@ const mpr = {
|
|
|
5319
5596
|
}]
|
|
5320
5597
|
}, {
|
|
5321
5598
|
viewportOptions: {
|
|
5599
|
+
viewportId: 'mpr-coronal',
|
|
5322
5600
|
toolGroupId: 'mpr',
|
|
5323
5601
|
viewportType: 'volume',
|
|
5324
5602
|
orientation: 'coronal',
|
|
@@ -5341,7 +5619,6 @@ const mpr = {
|
|
|
5341
5619
|
const mprAnd3DVolumeViewport = {
|
|
5342
5620
|
id: 'mprAnd3DVolumeViewport',
|
|
5343
5621
|
locked: true,
|
|
5344
|
-
hasUpdatedPriorsInformation: false,
|
|
5345
5622
|
name: 'mpr',
|
|
5346
5623
|
createdDate: '2023-03-15T10:29:44.894Z',
|
|
5347
5624
|
modifiedDate: '2023-03-15T10:29:44.894Z',
|
|
@@ -5530,9 +5807,9 @@ class ToolGroupService {
|
|
|
5530
5807
|
return dist_esm.ToolGroupManager.getToolGroupForViewport(viewportId, renderingEngine.id);
|
|
5531
5808
|
}
|
|
5532
5809
|
getActiveToolForViewport(viewportId) {
|
|
5533
|
-
const toolGroup =
|
|
5810
|
+
const toolGroup = this.getToolGroupForViewport(viewportId);
|
|
5534
5811
|
if (!toolGroup) {
|
|
5535
|
-
return
|
|
5812
|
+
return;
|
|
5536
5813
|
}
|
|
5537
5814
|
return toolGroup.getActivePrimaryMouseButtonTool();
|
|
5538
5815
|
}
|
|
@@ -5595,9 +5872,8 @@ class ToolGroupService {
|
|
|
5595
5872
|
this._setToolsMode(toolGroup, tools);
|
|
5596
5873
|
}
|
|
5597
5874
|
createToolGroupAndAddTools(toolGroupId, tools) {
|
|
5598
|
-
let configs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
5599
5875
|
const toolGroup = this.createToolGroup(toolGroupId);
|
|
5600
|
-
this.addToolsToToolGroup(toolGroupId, tools
|
|
5876
|
+
this.addToolsToToolGroup(toolGroupId, tools);
|
|
5601
5877
|
return toolGroup;
|
|
5602
5878
|
}
|
|
5603
5879
|
|
|
@@ -5643,30 +5919,6 @@ class ToolGroupService {
|
|
|
5643
5919
|
const toolInstance = toolGroup.getToolInstance(toolName);
|
|
5644
5920
|
toolInstance.configuration = config;
|
|
5645
5921
|
}
|
|
5646
|
-
_getToolNames(toolGroupTools) {
|
|
5647
|
-
const toolNames = [];
|
|
5648
|
-
if (toolGroupTools.active) {
|
|
5649
|
-
toolGroupTools.active.forEach(tool => {
|
|
5650
|
-
toolNames.push(tool.toolName);
|
|
5651
|
-
});
|
|
5652
|
-
}
|
|
5653
|
-
if (toolGroupTools.passive) {
|
|
5654
|
-
toolGroupTools.passive.forEach(tool => {
|
|
5655
|
-
toolNames.push(tool.toolName);
|
|
5656
|
-
});
|
|
5657
|
-
}
|
|
5658
|
-
if (toolGroupTools.enabled) {
|
|
5659
|
-
toolGroupTools.enabled.forEach(tool => {
|
|
5660
|
-
toolNames.push(tool.toolName);
|
|
5661
|
-
});
|
|
5662
|
-
}
|
|
5663
|
-
if (toolGroupTools.disabled) {
|
|
5664
|
-
toolGroupTools.disabled.forEach(tool => {
|
|
5665
|
-
toolNames.push(tool.toolName);
|
|
5666
|
-
});
|
|
5667
|
-
}
|
|
5668
|
-
return toolNames;
|
|
5669
|
-
}
|
|
5670
5922
|
_setToolsMode(toolGroup, tools) {
|
|
5671
5923
|
const {
|
|
5672
5924
|
active,
|
|
@@ -5710,29 +5962,46 @@ class ToolGroupService {
|
|
|
5710
5962
|
});
|
|
5711
5963
|
}
|
|
5712
5964
|
}
|
|
5713
|
-
_addTools(toolGroup, tools
|
|
5714
|
-
const
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5965
|
+
_addTools(toolGroup, tools) {
|
|
5966
|
+
const addTools = tools => {
|
|
5967
|
+
tools.forEach(_ref5 => {
|
|
5968
|
+
let {
|
|
5969
|
+
toolName,
|
|
5970
|
+
parentTool,
|
|
5971
|
+
configuration
|
|
5972
|
+
} = _ref5;
|
|
5973
|
+
if (parentTool) {
|
|
5974
|
+
toolGroup.addToolInstance(toolName, parentTool, {
|
|
5975
|
+
...configuration
|
|
5976
|
+
});
|
|
5977
|
+
} else {
|
|
5978
|
+
toolGroup.addTool(toolName, {
|
|
5979
|
+
...configuration
|
|
5980
|
+
});
|
|
5981
|
+
}
|
|
5725
5982
|
});
|
|
5726
|
-
}
|
|
5983
|
+
};
|
|
5984
|
+
if (tools.active) {
|
|
5985
|
+
addTools(tools.active);
|
|
5986
|
+
}
|
|
5987
|
+
if (tools.passive) {
|
|
5988
|
+
addTools(tools.passive);
|
|
5989
|
+
}
|
|
5990
|
+
if (tools.enabled) {
|
|
5991
|
+
addTools(tools.enabled);
|
|
5992
|
+
}
|
|
5993
|
+
if (tools.disabled) {
|
|
5994
|
+
addTools(tools.disabled);
|
|
5995
|
+
}
|
|
5727
5996
|
}
|
|
5728
5997
|
}
|
|
5729
5998
|
ToolGroupService.REGISTRATION = {
|
|
5730
5999
|
name: 'toolGroupService',
|
|
5731
6000
|
altName: 'ToolGroupService',
|
|
5732
|
-
create:
|
|
6001
|
+
create: _ref6 => {
|
|
5733
6002
|
let {
|
|
5734
6003
|
servicesManager
|
|
5735
|
-
} =
|
|
6004
|
+
} = _ref6;
|
|
5736
6005
|
return new ToolGroupService(servicesManager);
|
|
5737
6006
|
}
|
|
5738
6007
|
};
|
|
@@ -5789,7 +6058,7 @@ class SyncGroupService {
|
|
|
5789
6058
|
* @param type is the type of the synchronizer to create
|
|
5790
6059
|
* @param creator
|
|
5791
6060
|
*/
|
|
5792
|
-
|
|
6061
|
+
addSynchronizerType(type, creator) {
|
|
5793
6062
|
this.synchronizerCreators[type.toLowerCase()] = creator;
|
|
5794
6063
|
}
|
|
5795
6064
|
_getOrCreateSynchronizer(type, id, options) {
|
|
@@ -5867,10 +6136,10 @@ SyncGroupService.REGISTRATION = {
|
|
|
5867
6136
|
|
|
5868
6137
|
/* harmony default export */ const services_SyncGroupService = (SyncGroupService);
|
|
5869
6138
|
// EXTERNAL MODULE: ../../../node_modules/lodash.clonedeep/index.js
|
|
5870
|
-
var lodash_clonedeep = __webpack_require__(
|
|
6139
|
+
var lodash_clonedeep = __webpack_require__(11677);
|
|
5871
6140
|
var lodash_clonedeep_default = /*#__PURE__*/__webpack_require__.n(lodash_clonedeep);
|
|
5872
6141
|
// EXTERNAL MODULE: ../../../node_modules/lodash.isequal/index.js
|
|
5873
|
-
var lodash_isequal = __webpack_require__(
|
|
6142
|
+
var lodash_isequal = __webpack_require__(10311);
|
|
5874
6143
|
var lodash_isequal_default = /*#__PURE__*/__webpack_require__.n(lodash_isequal);
|
|
5875
6144
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/transitions.ts
|
|
5876
6145
|
/**
|
|
@@ -6026,6 +6295,82 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6026
6295
|
segmentation
|
|
6027
6296
|
});
|
|
6028
6297
|
};
|
|
6298
|
+
// Todo: this should not run on the main thread
|
|
6299
|
+
this.calculateCentroids = (segmentationId, segmentIndex) => {
|
|
6300
|
+
const segmentation = this.getSegmentation(segmentationId);
|
|
6301
|
+
const volume = this.getLabelmapVolume(segmentationId);
|
|
6302
|
+
const {
|
|
6303
|
+
dimensions,
|
|
6304
|
+
imageData
|
|
6305
|
+
} = volume;
|
|
6306
|
+
const scalarData = volume.getScalarData();
|
|
6307
|
+
const [dimX, dimY, numFrames] = dimensions;
|
|
6308
|
+
const frameLength = dimX * dimY;
|
|
6309
|
+
const segmentIndices = segmentIndex ? [segmentIndex] : segmentation.segments.filter(segment => segment?.segmentIndex).map(segment => segment.segmentIndex);
|
|
6310
|
+
const segmentIndicesSet = new Set(segmentIndices);
|
|
6311
|
+
const centroids = new Map();
|
|
6312
|
+
for (const index of segmentIndicesSet) {
|
|
6313
|
+
centroids.set(index, {
|
|
6314
|
+
x: 0,
|
|
6315
|
+
y: 0,
|
|
6316
|
+
z: 0,
|
|
6317
|
+
count: 0
|
|
6318
|
+
});
|
|
6319
|
+
}
|
|
6320
|
+
let voxelIndex = 0;
|
|
6321
|
+
for (let frame = 0; frame < numFrames; frame++) {
|
|
6322
|
+
for (let p = 0; p < frameLength; p++) {
|
|
6323
|
+
const segmentIndex = scalarData[voxelIndex++];
|
|
6324
|
+
if (segmentIndicesSet.has(segmentIndex)) {
|
|
6325
|
+
const centroid = centroids.get(segmentIndex);
|
|
6326
|
+
centroid.x += p % dimX;
|
|
6327
|
+
centroid.y += p / dimX | 0;
|
|
6328
|
+
centroid.z += frame;
|
|
6329
|
+
centroid.count++;
|
|
6330
|
+
}
|
|
6331
|
+
}
|
|
6332
|
+
}
|
|
6333
|
+
const result = new Map();
|
|
6334
|
+
for (const [index, centroid] of centroids) {
|
|
6335
|
+
const count = centroid.count;
|
|
6336
|
+
const normalizedCentroid = {
|
|
6337
|
+
x: centroid.x / count,
|
|
6338
|
+
y: centroid.y / count,
|
|
6339
|
+
z: centroid.z / count
|
|
6340
|
+
};
|
|
6341
|
+
normalizedCentroid.world = imageData.indexToWorld([normalizedCentroid.x, normalizedCentroid.y, normalizedCentroid.z]);
|
|
6342
|
+
result.set(index, normalizedCentroid);
|
|
6343
|
+
}
|
|
6344
|
+
this.setCentroids(segmentationId, result);
|
|
6345
|
+
return result;
|
|
6346
|
+
};
|
|
6347
|
+
this.setCentroids = (segmentationId, centroids) => {
|
|
6348
|
+
const segmentation = this.getSegmentation(segmentationId);
|
|
6349
|
+
const imageData = this.getLabelmapVolume(segmentationId).imageData; // Assuming this method returns imageData
|
|
6350
|
+
|
|
6351
|
+
if (!segmentation.cachedStats) {
|
|
6352
|
+
segmentation.cachedStats = {
|
|
6353
|
+
segmentCenter: {}
|
|
6354
|
+
};
|
|
6355
|
+
} else if (!segmentation.cachedStats.segmentCenter) {
|
|
6356
|
+
segmentation.cachedStats.segmentCenter = {};
|
|
6357
|
+
}
|
|
6358
|
+
for (const [segmentIndex, centroid] of centroids) {
|
|
6359
|
+
let world = centroid.world;
|
|
6360
|
+
|
|
6361
|
+
// If world coordinates are not provided, calculate them
|
|
6362
|
+
if (!world || world.length === 0) {
|
|
6363
|
+
world = imageData.indexToWorld(centroid.image);
|
|
6364
|
+
}
|
|
6365
|
+
segmentation.cachedStats.segmentCenter[segmentIndex] = {
|
|
6366
|
+
center: {
|
|
6367
|
+
image: centroid.image,
|
|
6368
|
+
world: world
|
|
6369
|
+
}
|
|
6370
|
+
};
|
|
6371
|
+
}
|
|
6372
|
+
this.addOrUpdateSegmentation(segmentation, true, true);
|
|
6373
|
+
};
|
|
6029
6374
|
this.createSegmentationForDisplaySet = async (displaySetInstanceUID, options) => {
|
|
6030
6375
|
const {
|
|
6031
6376
|
displaySetService
|
|
@@ -6055,6 +6400,7 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6055
6400
|
// We should set it as active by default, as it created for display
|
|
6056
6401
|
isActive: true,
|
|
6057
6402
|
type: representationType,
|
|
6403
|
+
FrameOfReferenceUID: options?.FrameOfReferenceUID || displaySet.instances?.[0]?.FrameOfReferenceUID,
|
|
6058
6404
|
representationData: {
|
|
6059
6405
|
LABELMAP: {
|
|
6060
6406
|
volumeId: segmentationId,
|
|
@@ -6078,6 +6424,7 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6078
6424
|
this.addSegmentationRepresentationToToolGroup = async function (toolGroupId, segmentationId) {
|
|
6079
6425
|
let hydrateSegmentation = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
6080
6426
|
let representationType = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : dist_esm.Enums.SegmentationRepresentations.Labelmap;
|
|
6427
|
+
let suppressEvents = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
6081
6428
|
const segmentation = _this.getSegmentation(segmentationId);
|
|
6082
6429
|
if (!segmentation) {
|
|
6083
6430
|
throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`);
|
|
@@ -6122,12 +6469,17 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6122
6469
|
if (visibility !== undefined) {
|
|
6123
6470
|
_this._setSegmentVisibility(segmentationId, segmentIndex, visibility, toolGroupId, suppressEvents);
|
|
6124
6471
|
}
|
|
6125
|
-
if (isLocked
|
|
6472
|
+
if (isLocked) {
|
|
6126
6473
|
_this._setSegmentLocked(segmentationId, segmentIndex, isLocked, suppressEvents);
|
|
6127
6474
|
}
|
|
6128
6475
|
}
|
|
6476
|
+
if (!suppressEvents) {
|
|
6477
|
+
_this._broadcastEvent(_this.EVENTS.SEGMENTATION_UPDATED, {
|
|
6478
|
+
segmentation
|
|
6479
|
+
});
|
|
6480
|
+
}
|
|
6129
6481
|
};
|
|
6130
|
-
this.
|
|
6482
|
+
this.setSegmentRGBAColor = (segmentationId, segmentIndex, rgbaColor, toolGroupId) => {
|
|
6131
6483
|
const segmentation = this.getSegmentation(segmentationId);
|
|
6132
6484
|
if (segmentation === undefined) {
|
|
6133
6485
|
throw new Error(`no segmentation for segmentationId: ${segmentationId}`);
|
|
@@ -6153,6 +6505,9 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6153
6505
|
throw new Error(`Segmentation with segmentationId ${segmentationId} not found.`);
|
|
6154
6506
|
}
|
|
6155
6507
|
segmentation.hydrated = true;
|
|
6508
|
+
|
|
6509
|
+
// Not all segmentations have dipslaysets, some of them are derived in the client
|
|
6510
|
+
_this._setDisplaySetIsHydrated(segmentationId, true);
|
|
6156
6511
|
if (!suppressEvents) {
|
|
6157
6512
|
_this._broadcastEvent(_this.EVENTS.SEGMENTATION_UPDATED, {
|
|
6158
6513
|
segmentation
|
|
@@ -6467,34 +6822,40 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6467
6822
|
this._initSegmentationService();
|
|
6468
6823
|
}
|
|
6469
6824
|
/**
|
|
6470
|
-
*
|
|
6471
|
-
* the segment.
|
|
6472
|
-
* @param
|
|
6473
|
-
* segment to.
|
|
6474
|
-
*
|
|
6475
|
-
*
|
|
6476
|
-
*
|
|
6477
|
-
*
|
|
6478
|
-
*
|
|
6479
|
-
*
|
|
6480
|
-
*
|
|
6481
|
-
*
|
|
6825
|
+
* Adds a new segment to the specified segmentation.
|
|
6826
|
+
* @param segmentationId - The ID of the segmentation to add the segment to.
|
|
6827
|
+
* @param config - An object containing the configuration options for the new segment.
|
|
6828
|
+
* - segmentIndex: (optional) The index of the segment to add. If not provided, the next available index will be used.
|
|
6829
|
+
* - toolGroupId: (optional) The ID of the tool group to associate the new segment with. If not provided, the first available tool group will be used.
|
|
6830
|
+
* - properties: (optional) An object containing the properties of the new segment.
|
|
6831
|
+
* - label: (optional) The label of the new segment. If not provided, a default label will be used.
|
|
6832
|
+
* - color: (optional) The color of the new segment in RGB format. If not provided, a default color will be used.
|
|
6833
|
+
* - opacity: (optional) The opacity of the new segment. If not provided, a default opacity will be used.
|
|
6834
|
+
* - visibility: (optional) Whether the new segment should be visible. If not provided, the segment will be visible by default.
|
|
6835
|
+
* - isLocked: (optional) Whether the new segment should be locked for editing. If not provided, the segment will not be locked by default.
|
|
6836
|
+
* - active: (optional) Whether the new segment should be the active segment to be edited. If not provided, the segment will not be active by default.
|
|
6482
6837
|
*/
|
|
6483
|
-
addSegment(segmentationId
|
|
6484
|
-
|
|
6838
|
+
addSegment(segmentationId) {
|
|
6839
|
+
let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
6840
|
+
if (config?.segmentIndex === 0) {
|
|
6485
6841
|
throw new Error('Segment index 0 is reserved for "no label"');
|
|
6486
6842
|
}
|
|
6487
|
-
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
|
6843
|
+
const toolGroupId = config.toolGroupId ?? this._getFirstToolGroupId();
|
|
6488
6844
|
const {
|
|
6489
6845
|
segmentationRepresentationUID,
|
|
6490
6846
|
segmentation
|
|
6491
6847
|
} = this._getSegmentationInfo(segmentationId, toolGroupId);
|
|
6848
|
+
let segmentIndex = config.segmentIndex;
|
|
6849
|
+
if (!segmentIndex) {
|
|
6850
|
+
// grab the next available segment index
|
|
6851
|
+
segmentIndex = segmentation.segments.length === 0 ? 1 : segmentation.segments.length;
|
|
6852
|
+
}
|
|
6492
6853
|
if (this._getSegmentInfo(segmentation, segmentIndex)) {
|
|
6493
6854
|
throw new Error(`Segment ${segmentIndex} already exists`);
|
|
6494
6855
|
}
|
|
6495
6856
|
const rgbaColor = dist_esm.segmentation.config.color.getColorForSegmentIndex(toolGroupId, segmentationRepresentationUID, segmentIndex);
|
|
6496
6857
|
segmentation.segments[segmentIndex] = {
|
|
6497
|
-
label: properties
|
|
6858
|
+
label: config.properties?.label ?? `Segment ${segmentIndex}`,
|
|
6498
6859
|
segmentIndex: segmentIndex,
|
|
6499
6860
|
color: [rgbaColor[0], rgbaColor[1], rgbaColor[2]],
|
|
6500
6861
|
opacity: rgbaColor[3],
|
|
@@ -6502,15 +6863,18 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6502
6863
|
isLocked: false
|
|
6503
6864
|
};
|
|
6504
6865
|
segmentation.segmentCount++;
|
|
6866
|
+
|
|
6867
|
+
// make the newly added segment the active segment
|
|
6868
|
+
this._setActiveSegment(segmentationId, segmentIndex);
|
|
6505
6869
|
const suppressEvents = true;
|
|
6506
|
-
if (properties !== undefined) {
|
|
6870
|
+
if (config.properties !== undefined) {
|
|
6507
6871
|
const {
|
|
6508
6872
|
color: newColor,
|
|
6509
6873
|
opacity,
|
|
6510
6874
|
isLocked,
|
|
6511
6875
|
visibility,
|
|
6512
6876
|
active
|
|
6513
|
-
} = properties;
|
|
6877
|
+
} = config.properties;
|
|
6514
6878
|
if (newColor !== undefined) {
|
|
6515
6879
|
this._setSegmentColor(segmentationId, segmentIndex, newColor, toolGroupId, suppressEvents);
|
|
6516
6880
|
}
|
|
@@ -6590,12 +6954,21 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6590
6954
|
let suppressEvents = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
6591
6955
|
this._setSegmentVisibility(segmentationId, segmentIndex, isVisible, toolGroupId, suppressEvents);
|
|
6592
6956
|
}
|
|
6593
|
-
|
|
6957
|
+
setSegmentLocked(segmentationId, segmentIndex, isLocked) {
|
|
6594
6958
|
const suppressEvents = false;
|
|
6595
6959
|
this._setSegmentLocked(segmentationId, segmentIndex, isLocked, suppressEvents);
|
|
6596
6960
|
}
|
|
6597
|
-
|
|
6598
|
-
|
|
6961
|
+
|
|
6962
|
+
/**
|
|
6963
|
+
* Toggles the locked state of a segment in a segmentation.
|
|
6964
|
+
* @param segmentationId - The ID of the segmentation.
|
|
6965
|
+
* @param segmentIndex - The index of the segment to toggle.
|
|
6966
|
+
*/
|
|
6967
|
+
toggleSegmentLocked(segmentationId, segmentIndex) {
|
|
6968
|
+
const segmentation = this.getSegmentation(segmentationId);
|
|
6969
|
+
const segment = this._getSegmentInfo(segmentation, segmentIndex);
|
|
6970
|
+
const isLocked = !segment.isLocked;
|
|
6971
|
+
this._setSegmentLocked(segmentationId, segmentIndex, isLocked);
|
|
6599
6972
|
}
|
|
6600
6973
|
setSegmentColor(segmentationId, segmentIndex, color, toolGroupId) {
|
|
6601
6974
|
this._setSegmentColor(segmentationId, segmentIndex, color, toolGroupId);
|
|
@@ -6608,7 +6981,7 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6608
6981
|
const suppressEvents = false;
|
|
6609
6982
|
this._setActiveSegmentationForToolGroup(segmentationId, toolGroupId, suppressEvents);
|
|
6610
6983
|
}
|
|
6611
|
-
|
|
6984
|
+
setActiveSegment(segmentationId, segmentIndex) {
|
|
6612
6985
|
this._setActiveSegment(segmentationId, segmentIndex, false);
|
|
6613
6986
|
}
|
|
6614
6987
|
|
|
@@ -6677,11 +7050,14 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6677
7050
|
}
|
|
6678
7051
|
}]);
|
|
6679
7052
|
|
|
6680
|
-
//
|
|
6681
|
-
//
|
|
6682
|
-
const
|
|
6683
|
-
|
|
6684
|
-
|
|
7053
|
+
// if first segmentation, we can use the default colorLUT, otherwise
|
|
7054
|
+
// we need to generate a new one and use a new colorLUT
|
|
7055
|
+
const colorLUTIndex = 0;
|
|
7056
|
+
if (Object.keys(this.segmentations).length !== 0) {
|
|
7057
|
+
const newColorLUT = this.generateNewColorLUT();
|
|
7058
|
+
const colorLUTIndex = this.getNextColorLUTIndex();
|
|
7059
|
+
dist_esm.segmentation.config.color.addColorLUT(newColorLUT, colorLUTIndex);
|
|
7060
|
+
}
|
|
6685
7061
|
this.segmentations[segmentationId] = {
|
|
6686
7062
|
...segmentation,
|
|
6687
7063
|
label: segmentation.label || '',
|
|
@@ -6689,8 +7065,8 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6689
7065
|
activeSegmentIndex: segmentation.activeSegmentIndex ?? null,
|
|
6690
7066
|
segmentCount: segmentation.segmentCount ?? 0,
|
|
6691
7067
|
isActive: false,
|
|
6692
|
-
|
|
6693
|
-
|
|
7068
|
+
isVisible: true,
|
|
7069
|
+
colorLUTIndex
|
|
6694
7070
|
};
|
|
6695
7071
|
cachedSegmentation = this.segmentations[segmentationId];
|
|
6696
7072
|
this._updateCornerstoneSegmentations({
|
|
@@ -6715,6 +7091,7 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6715
7091
|
id: segmentationId,
|
|
6716
7092
|
displaySetInstanceUID: segDisplaySet.displaySetInstanceUID,
|
|
6717
7093
|
type: representationType,
|
|
7094
|
+
label: segDisplaySet.SeriesDescription,
|
|
6718
7095
|
representationData: {
|
|
6719
7096
|
[LABELMAP]: {
|
|
6720
7097
|
volumeId: segmentationId,
|
|
@@ -6731,11 +7108,11 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6731
7108
|
return this.addOrUpdateSegmentation(Object.assign(segmentation, cachedSegmentation), suppressEvents);
|
|
6732
7109
|
}
|
|
6733
7110
|
const {
|
|
6734
|
-
|
|
7111
|
+
labelmapBufferArray,
|
|
6735
7112
|
referencedVolumeId
|
|
6736
7113
|
} = segDisplaySet;
|
|
6737
|
-
if (!
|
|
6738
|
-
throw new Error('
|
|
7114
|
+
if (!labelmapBufferArray || !referencedVolumeId) {
|
|
7115
|
+
throw new Error('No labelmapBufferArray or referencedVolumeId found for the SEG displaySet');
|
|
6739
7116
|
}
|
|
6740
7117
|
|
|
6741
7118
|
// if the labelmap doesn't exist, we need to create it first from the
|
|
@@ -6754,72 +7131,27 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6754
7131
|
sharedArrayBuffer: true
|
|
6755
7132
|
}
|
|
6756
7133
|
});
|
|
6757
|
-
const [rows, columns] = derivedVolume.dimensions;
|
|
6758
7134
|
const derivedVolumeScalarData = derivedVolume.getScalarData();
|
|
6759
|
-
const
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
} = esm.metaData.get('generalImageModule', imageId);
|
|
6766
|
-
acc[sopInstanceUid] = index;
|
|
6767
|
-
return acc;
|
|
6768
|
-
}, {});
|
|
6769
|
-
const numSegments = Object.keys(segments).length;
|
|
6770
|
-
// Note: ideally we could use the TypedArray set method, but since each
|
|
6771
|
-
// slice can have multiple segments, we need to loop over each slice and
|
|
6772
|
-
// set the segment value for each segment.
|
|
6773
|
-
let overlappingSegments = false;
|
|
6774
|
-
const _segmentInfoUpdate = (segmentInfo, segmentIndex) => {
|
|
7135
|
+
const segmentsInfo = segDisplaySet.segMetadata.data;
|
|
7136
|
+
derivedVolumeScalarData.set(new Uint8Array(labelmapBufferArray[0]));
|
|
7137
|
+
segmentation.segments = segmentsInfo.map((segmentInfo, segmentIndex) => {
|
|
7138
|
+
if (segmentIndex === 0) {
|
|
7139
|
+
return;
|
|
7140
|
+
}
|
|
6775
7141
|
const {
|
|
6776
|
-
|
|
7142
|
+
SegmentedPropertyCategoryCodeSequence,
|
|
7143
|
+
SegmentNumber,
|
|
7144
|
+
SegmentLabel,
|
|
7145
|
+
SegmentAlgorithmType,
|
|
7146
|
+
SegmentAlgorithmName,
|
|
7147
|
+
SegmentedPropertyTypeCodeSequence,
|
|
7148
|
+
rgba
|
|
6777
7149
|
} = segmentInfo;
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
const {
|
|
6784
|
-
ReferencedSOPInstanceUID
|
|
6785
|
-
} = functionalGroup.DerivationImageSequence.SourceImageSequence;
|
|
6786
|
-
const imageIdIndex = sopUIDImageIdIndexMap[ReferencedSOPInstanceUID];
|
|
6787
|
-
if (imageIdIndex === -1) {
|
|
6788
|
-
return;
|
|
6789
|
-
}
|
|
6790
|
-
const step = rows * columns;
|
|
6791
|
-
|
|
6792
|
-
// we need a faster way to get the pixel data for the current
|
|
6793
|
-
// functional group, which we use typed array view
|
|
6794
|
-
|
|
6795
|
-
const functionGroupPixelData = new Uint8Array(segPixelData.buffer, functionalGroupIndex * step, step);
|
|
6796
|
-
const functionalGroupStartIndex = imageIdIndex * step;
|
|
6797
|
-
const functionalGroupEndIndex = (imageIdIndex + 1) * step;
|
|
6798
|
-
|
|
6799
|
-
// Note: this for loop is not optimized, since DICOM SEG stores
|
|
6800
|
-
// each segment as a separate labelmap so if there is a slice
|
|
6801
|
-
// that has multiple segments, we will have to loop over each
|
|
6802
|
-
// segment and we cannot use the TypedArray set method.
|
|
6803
|
-
for (let i = functionalGroupStartIndex, j = 0; i < functionalGroupEndIndex; i++, j++) {
|
|
6804
|
-
if (functionGroupPixelData[j] !== 0) {
|
|
6805
|
-
if (derivedVolumeScalarData[i] !== 0) {
|
|
6806
|
-
overlappingSegments = true;
|
|
6807
|
-
}
|
|
6808
|
-
derivedVolumeScalarData[i] = segmentIndex;
|
|
6809
|
-
|
|
6810
|
-
// centroid calculations
|
|
6811
|
-
segmentX += i % columns;
|
|
6812
|
-
segmentY += Math.floor(i / columns) % rows;
|
|
6813
|
-
segmentZ += Math.floor(i / (columns * rows));
|
|
6814
|
-
count++;
|
|
6815
|
-
}
|
|
6816
|
-
}
|
|
6817
|
-
}
|
|
6818
|
-
|
|
6819
|
-
// centroid calculations
|
|
6820
|
-
const x = Math.floor(segmentX / count);
|
|
6821
|
-
const y = Math.floor(segmentY / count);
|
|
6822
|
-
const z = Math.floor(segmentZ / count);
|
|
7150
|
+
const {
|
|
7151
|
+
x,
|
|
7152
|
+
y,
|
|
7153
|
+
z
|
|
7154
|
+
} = segDisplaySet.centroids.get(segmentIndex);
|
|
6823
7155
|
const centerWorld = derivedVolume.imageData.indexToWorld([x, y, z]);
|
|
6824
7156
|
segmentation.cachedStats = {
|
|
6825
7157
|
...segmentation.cachedStats,
|
|
@@ -6834,51 +7166,24 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6834
7166
|
}
|
|
6835
7167
|
}
|
|
6836
7168
|
};
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
const promiseArray = [];
|
|
6847
|
-
for (const segmentIndex in segments) {
|
|
6848
|
-
const segmentInfo = segments[segmentIndex];
|
|
6849
|
-
|
|
6850
|
-
// Important: we need a non-blocking way to update the segmentation
|
|
6851
|
-
// state, otherwise the UI will freeze and the user will not be able
|
|
6852
|
-
// to interact with the app or progress bars will not be updated.
|
|
6853
|
-
const promise = new Promise((resolve, reject) => {
|
|
6854
|
-
setTimeout(() => {
|
|
6855
|
-
_segmentInfoUpdate(segmentInfo, segmentIndex);
|
|
6856
|
-
resolve();
|
|
6857
|
-
}, 0);
|
|
6858
|
-
});
|
|
6859
|
-
promiseArray.push(promise);
|
|
6860
|
-
}
|
|
6861
|
-
await Promise.all(promiseArray);
|
|
6862
|
-
segmentation.segmentCount = Object.keys(segments).length;
|
|
6863
|
-
segmentation.segments = [null]; // segment 0
|
|
6864
|
-
|
|
6865
|
-
Object.keys(segments).forEach(segmentIndex => {
|
|
6866
|
-
const segmentInfo = segments[segmentIndex];
|
|
6867
|
-
const segIndex = Number(segmentIndex);
|
|
6868
|
-
segmentation.segments[segIndex] = {
|
|
6869
|
-
label: segmentInfo.label || `Segment ${segIndex}`,
|
|
6870
|
-
segmentIndex: Number(segmentIndex),
|
|
6871
|
-
color: [segmentInfo.color[0], segmentInfo.color[1], segmentInfo.color[2]],
|
|
6872
|
-
opacity: segmentInfo.color[3],
|
|
7169
|
+
return {
|
|
7170
|
+
label: SegmentLabel || `Segment ${SegmentNumber}`,
|
|
7171
|
+
segmentIndex: Number(SegmentNumber),
|
|
7172
|
+
category: SegmentedPropertyCategoryCodeSequence ? SegmentedPropertyCategoryCodeSequence.CodeMeaning : '',
|
|
7173
|
+
type: SegmentedPropertyTypeCodeSequence ? SegmentedPropertyTypeCodeSequence.CodeMeaning : '',
|
|
7174
|
+
algorithmType: SegmentAlgorithmType,
|
|
7175
|
+
algorithmName: SegmentAlgorithmName,
|
|
7176
|
+
color: rgba,
|
|
7177
|
+
opacity: 255,
|
|
6873
7178
|
isVisible: true,
|
|
6874
7179
|
isLocked: false
|
|
6875
7180
|
};
|
|
6876
7181
|
});
|
|
7182
|
+
segmentation.segmentCount = segmentsInfo.length - 1;
|
|
6877
7183
|
segDisplaySet.isLoaded = true;
|
|
6878
7184
|
this._broadcastEvent(SegmentationService_EVENTS.SEGMENTATION_LOADING_COMPLETE, {
|
|
6879
7185
|
segmentationId,
|
|
6880
|
-
segDisplaySet
|
|
6881
|
-
overlappingSegments
|
|
7186
|
+
segDisplaySet
|
|
6882
7187
|
});
|
|
6883
7188
|
return this.addOrUpdateSegmentation(segmentation, suppressEvents);
|
|
6884
7189
|
}
|
|
@@ -6911,6 +7216,7 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
6911
7216
|
id: segmentationId,
|
|
6912
7217
|
displaySetInstanceUID: rtDisplaySetUID,
|
|
6913
7218
|
type: representationType,
|
|
7219
|
+
label: rtDisplaySet.SeriesDescription,
|
|
6914
7220
|
representationData: {
|
|
6915
7221
|
[CONTOUR]: {
|
|
6916
7222
|
geometryIds
|
|
@@ -7015,6 +7321,9 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
7015
7321
|
toolGroupService
|
|
7016
7322
|
} = this.servicesManager.services;
|
|
7017
7323
|
const center = this._getSegmentCenter(segmentationId, segmentIndex);
|
|
7324
|
+
if (!center?.world) {
|
|
7325
|
+
return;
|
|
7326
|
+
}
|
|
7018
7327
|
const {
|
|
7019
7328
|
world
|
|
7020
7329
|
} = center;
|
|
@@ -7068,6 +7377,17 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
7068
7377
|
const adjustedAlpha = type === LABELMAP ? alpha : 1 - alpha;
|
|
7069
7378
|
highlightFn(segmentIndex, adjustedAlpha, hideOthers, segments, toolGroupId, animationLength, segmentationRepresentation);
|
|
7070
7379
|
}
|
|
7380
|
+
_setDisplaySetIsHydrated(displaySetUID, isHydrated) {
|
|
7381
|
+
const {
|
|
7382
|
+
displaySetService
|
|
7383
|
+
} = this.servicesManager.services;
|
|
7384
|
+
const displaySet = displaySetService.getDisplaySetByUID(displaySetUID);
|
|
7385
|
+
if (!displaySet) {
|
|
7386
|
+
return;
|
|
7387
|
+
}
|
|
7388
|
+
displaySet.isHydrated = isHydrated;
|
|
7389
|
+
displaySetService.setDisplaySetMetadataInvalidated(displaySetUID, false);
|
|
7390
|
+
}
|
|
7071
7391
|
_highlightLabelmap(segmentIndex, alpha, hideOthers, segments, toolGroupId, animationLength, segmentationRepresentation) {
|
|
7072
7392
|
const newSegmentSpecificConfig = {
|
|
7073
7393
|
[segmentIndex]: {
|
|
@@ -7170,21 +7490,23 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
7170
7490
|
|
|
7171
7491
|
if (wasActive) {
|
|
7172
7492
|
const remainingSegmentations = this._getSegmentations();
|
|
7173
|
-
|
|
7493
|
+
const remainingHydratedSegmentations = remainingSegmentations.filter(segmentation => segmentation.hydrated);
|
|
7494
|
+
if (remainingHydratedSegmentations.length) {
|
|
7174
7495
|
const {
|
|
7175
7496
|
id
|
|
7176
|
-
} =
|
|
7497
|
+
} = remainingHydratedSegmentations[0];
|
|
7177
7498
|
this._setActiveSegmentationForToolGroup(id, this._getFirstToolGroupId(), false);
|
|
7178
7499
|
}
|
|
7179
7500
|
}
|
|
7501
|
+
this._setDisplaySetIsHydrated(segmentationId, false);
|
|
7180
7502
|
this._broadcastEvent(this.EVENTS.SEGMENTATION_REMOVED, {
|
|
7181
7503
|
segmentationId
|
|
7182
7504
|
});
|
|
7183
7505
|
}
|
|
7184
|
-
|
|
7185
|
-
this.
|
|
7506
|
+
setSegmentLabel(segmentationId, segmentIndex, label) {
|
|
7507
|
+
this._setSegmentLabel(segmentationId, segmentIndex, label);
|
|
7186
7508
|
}
|
|
7187
|
-
|
|
7509
|
+
_setSegmentLabel(segmentationId, segmentIndex, label) {
|
|
7188
7510
|
let suppressEvents = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
7189
7511
|
const segmentation = this.getSegmentation(segmentationId);
|
|
7190
7512
|
if (segmentation === undefined) {
|
|
@@ -7202,16 +7524,14 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
7202
7524
|
});
|
|
7203
7525
|
}
|
|
7204
7526
|
}
|
|
7205
|
-
shouldRenderSegmentation(viewportDisplaySetInstanceUIDs,
|
|
7206
|
-
if (!viewportDisplaySetInstanceUIDs
|
|
7527
|
+
shouldRenderSegmentation(viewportDisplaySetInstanceUIDs, segmentationFrameOfReferenceUID) {
|
|
7528
|
+
if (!viewportDisplaySetInstanceUIDs?.length) {
|
|
7207
7529
|
return false;
|
|
7208
7530
|
}
|
|
7209
7531
|
const {
|
|
7210
7532
|
displaySetService
|
|
7211
7533
|
} = this.servicesManager.services;
|
|
7212
7534
|
let shouldDisplaySeg = false;
|
|
7213
|
-
const segDisplaySet = displaySetService.getDisplaySetByUID(segDisplaySetInstanceUID);
|
|
7214
|
-
const segFrameOfReferenceUID = this._getFrameOfReferenceUIDForSeg(segDisplaySet);
|
|
7215
7535
|
|
|
7216
7536
|
// check if the displaySet is sharing the same frameOfReferenceUID
|
|
7217
7537
|
// with the new segmentation
|
|
@@ -7220,7 +7540,7 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
7220
7540
|
|
|
7221
7541
|
// Todo: this might not be ideal for use cases such as 4D, since we
|
|
7222
7542
|
// don't want to show the segmentation for all the frames
|
|
7223
|
-
if (displaySet.isReconstructable && displaySet?.images?.[0]?.FrameOfReferenceUID ===
|
|
7543
|
+
if (displaySet.isReconstructable && displaySet?.images?.[0]?.FrameOfReferenceUID === segmentationFrameOfReferenceUID) {
|
|
7224
7544
|
shouldDisplaySeg = true;
|
|
7225
7545
|
break;
|
|
7226
7546
|
}
|
|
@@ -7374,7 +7694,7 @@ class SegmentationService extends src/* PubSubService */.hC {
|
|
|
7374
7694
|
}
|
|
7375
7695
|
_getSegmentationRepresentation(segmentationId, toolGroupId) {
|
|
7376
7696
|
const segmentationRepresentations = this.getSegmentationRepresentationsForToolGroup(toolGroupId);
|
|
7377
|
-
if (segmentationRepresentations
|
|
7697
|
+
if (!segmentationRepresentations?.length) {
|
|
7378
7698
|
return;
|
|
7379
7699
|
}
|
|
7380
7700
|
|
|
@@ -7659,7 +7979,8 @@ class CornerstoneCacheService {
|
|
|
7659
7979
|
}
|
|
7660
7980
|
_shouldRenderSegmentation(displaySets) {
|
|
7661
7981
|
const {
|
|
7662
|
-
segmentationService
|
|
7982
|
+
segmentationService,
|
|
7983
|
+
displaySetService
|
|
7663
7984
|
} = this.servicesManager.services;
|
|
7664
7985
|
const viewportDisplaySetInstanceUIDs = displaySets.map(_ref2 => {
|
|
7665
7986
|
let {
|
|
@@ -7673,7 +7994,8 @@ class CornerstoneCacheService {
|
|
|
7673
7994
|
const segmentations = segmentationService.getSegmentations();
|
|
7674
7995
|
for (const segmentation of segmentations) {
|
|
7675
7996
|
const segDisplaySetInstanceUID = segmentation.displaySetInstanceUID;
|
|
7676
|
-
const
|
|
7997
|
+
const segDisplaySet = displaySetService.getDisplaySetByUID(segDisplaySetInstanceUID);
|
|
7998
|
+
const shouldDisplaySeg = segmentationService.shouldRenderSegmentation(viewportDisplaySetInstanceUIDs, segDisplaySet.instances[0].FrameOfReferenceUID);
|
|
7677
7999
|
if (shouldDisplaySeg) {
|
|
7678
8000
|
return true;
|
|
7679
8001
|
}
|
|
@@ -7747,16 +8069,17 @@ const DEFAULT_TOOLGROUP_ID = 'default';
|
|
|
7747
8069
|
// Return true if the data contains the given display set UID OR the imageId
|
|
7748
8070
|
// if it is a composite object.
|
|
7749
8071
|
const dataContains = (data, displaySetUID, imageId) => {
|
|
7750
|
-
if (data.displaySetInstanceUID === displaySetUID)
|
|
8072
|
+
if (data.displaySetInstanceUID === displaySetUID) {
|
|
8073
|
+
return true;
|
|
8074
|
+
}
|
|
7751
8075
|
if (imageId && data.isCompositeStack && data.imageIds) {
|
|
7752
8076
|
return !!data.imageIds.find(dataId => dataId === imageId);
|
|
7753
8077
|
}
|
|
7754
8078
|
return false;
|
|
7755
8079
|
};
|
|
7756
8080
|
class ViewportInfo {
|
|
7757
|
-
constructor(
|
|
8081
|
+
constructor(viewportId) {
|
|
7758
8082
|
this.viewportId = '';
|
|
7759
|
-
this.viewportIndex = void 0;
|
|
7760
8083
|
this.element = void 0;
|
|
7761
8084
|
this.viewportOptions = void 0;
|
|
7762
8085
|
this.displaySetOptions = void 0;
|
|
@@ -7768,7 +8091,6 @@ class ViewportInfo {
|
|
|
7768
8091
|
this.viewportOptions = null;
|
|
7769
8092
|
this.displaySetOptions = null;
|
|
7770
8093
|
};
|
|
7771
|
-
this.viewportIndex = viewportIndex;
|
|
7772
8094
|
this.viewportId = viewportId;
|
|
7773
8095
|
this.setPublicViewportOptions({});
|
|
7774
8096
|
this.setPublicDisplaySetOptions([{}]);
|
|
@@ -7779,7 +8101,9 @@ class ViewportInfo {
|
|
|
7779
8101
|
* OR if it is a composite stack and contains the given imageId
|
|
7780
8102
|
*/
|
|
7781
8103
|
contains(displaySetUID, imageId) {
|
|
7782
|
-
if (!this.viewportData?.data)
|
|
8104
|
+
if (!this.viewportData?.data) {
|
|
8105
|
+
return false;
|
|
8106
|
+
}
|
|
7783
8107
|
if (this.viewportData.data.length) {
|
|
7784
8108
|
return !!this.viewportData.data.find(data => dataContains(data, displaySetUID, imageId));
|
|
7785
8109
|
}
|
|
@@ -7794,9 +8118,6 @@ class ViewportInfo {
|
|
|
7794
8118
|
setViewportId(viewportId) {
|
|
7795
8119
|
this.viewportId = viewportId;
|
|
7796
8120
|
}
|
|
7797
|
-
setViewportIndex(viewportIndex) {
|
|
7798
|
-
this.viewportIndex = viewportIndex;
|
|
7799
|
-
}
|
|
7800
8121
|
setElement(element) {
|
|
7801
8122
|
this.element = element;
|
|
7802
8123
|
}
|
|
@@ -7806,9 +8127,6 @@ class ViewportInfo {
|
|
|
7806
8127
|
getViewportData() {
|
|
7807
8128
|
return this.viewportData;
|
|
7808
8129
|
}
|
|
7809
|
-
getViewportIndex() {
|
|
7810
|
-
return this.viewportIndex;
|
|
7811
|
-
}
|
|
7812
8130
|
getElement() {
|
|
7813
8131
|
return this.element;
|
|
7814
8132
|
}
|
|
@@ -7819,13 +8137,14 @@ class ViewportInfo {
|
|
|
7819
8137
|
// map the displaySetOptions and check if they are undefined then set them to default values
|
|
7820
8138
|
const displaySetOptions = this.mapDisplaySetOptions(publicDisplaySetOptions);
|
|
7821
8139
|
this.setDisplaySetOptions(displaySetOptions);
|
|
8140
|
+
return this.displaySetOptions;
|
|
7822
8141
|
}
|
|
7823
8142
|
hasDisplaySet(displaySetInstanceUID) {
|
|
7824
8143
|
// Todo: currently this does not work for non image & referenceImage displaySets.
|
|
7825
8144
|
// Since SEG and other derived displaySets are loaded in a different way, and not
|
|
7826
8145
|
// via cornerstoneViewportService
|
|
7827
8146
|
let viewportData = this.getViewportData();
|
|
7828
|
-
if (viewportData.viewportType === esm.Enums.ViewportType.ORTHOGRAPHIC) {
|
|
8147
|
+
if (viewportData.viewportType === esm.Enums.ViewportType.ORTHOGRAPHIC || viewportData.viewportType === esm.Enums.ViewportType.VOLUME_3D) {
|
|
7829
8148
|
viewportData = viewportData;
|
|
7830
8149
|
return viewportData.data.some(_ref => {
|
|
7831
8150
|
let {
|
|
@@ -7865,6 +8184,7 @@ class ViewportInfo {
|
|
|
7865
8184
|
toolGroupId,
|
|
7866
8185
|
presentationIds
|
|
7867
8186
|
});
|
|
8187
|
+
return this.viewportOptions;
|
|
7868
8188
|
}
|
|
7869
8189
|
setViewportOptions(viewportOptions) {
|
|
7870
8190
|
this.viewportOptions = viewportOptions;
|
|
@@ -7959,7 +8279,6 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
7959
8279
|
constructor(servicesManager) {
|
|
7960
8280
|
super(CornerstoneViewportService_EVENTS);
|
|
7961
8281
|
this.renderingEngine = void 0;
|
|
7962
|
-
this.viewportsInfo = new Map();
|
|
7963
8282
|
this.viewportsById = new Map();
|
|
7964
8283
|
this.viewportGridResizeObserver = void 0;
|
|
7965
8284
|
this.viewportsDisplaySets = new Map();
|
|
@@ -7975,37 +8294,16 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
7975
8294
|
|
|
7976
8295
|
/**
|
|
7977
8296
|
* Adds the HTML element to the viewportService
|
|
7978
|
-
* @param {*}
|
|
8297
|
+
* @param {*} viewportId
|
|
7979
8298
|
* @param {*} elementRef
|
|
7980
8299
|
*/
|
|
7981
|
-
enableViewport(
|
|
7982
|
-
|
|
7983
|
-
// Not providing a viewportId is frowned upon because it does weird things
|
|
7984
|
-
// on moving them around, but it does mostly work.
|
|
7985
|
-
if (!viewportOptions.viewportId) {
|
|
7986
|
-
console.warn('Should provide viewport id externally', viewportOptions);
|
|
7987
|
-
viewportOptions.viewportId = this.getViewportId(viewportIndex) || `viewport-${viewportIndex}`;
|
|
7988
|
-
}
|
|
7989
|
-
const {
|
|
7990
|
-
viewportId
|
|
7991
|
-
} = viewportOptions;
|
|
7992
|
-
const viewportInfo = new Viewport(viewportIndex, viewportId);
|
|
7993
|
-
if (!viewportInfo.viewportId) {
|
|
7994
|
-
throw new Error('Should have viewport ID afterwards');
|
|
7995
|
-
}
|
|
8300
|
+
enableViewport(viewportId, elementRef) {
|
|
8301
|
+
const viewportInfo = new Viewport(viewportId);
|
|
7996
8302
|
viewportInfo.setElement(elementRef);
|
|
7997
|
-
this.viewportsInfo.set(viewportIndex, viewportInfo);
|
|
7998
8303
|
this.viewportsById.set(viewportId, viewportInfo);
|
|
7999
8304
|
}
|
|
8000
8305
|
getViewportIds() {
|
|
8001
|
-
|
|
8002
|
-
this.viewportsInfo.forEach(viewportInfo => {
|
|
8003
|
-
viewportIds.push(viewportInfo.getViewportId());
|
|
8004
|
-
});
|
|
8005
|
-
return viewportIds;
|
|
8006
|
-
}
|
|
8007
|
-
getViewportId(viewportIndex) {
|
|
8008
|
-
return this.viewportsInfo[viewportIndex]?.viewportId;
|
|
8306
|
+
return Array.from(this.viewportsById.keys());
|
|
8009
8307
|
}
|
|
8010
8308
|
|
|
8011
8309
|
/**
|
|
@@ -8059,34 +8357,38 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8059
8357
|
* created for every new viewport, this will be called whenever the set of
|
|
8060
8358
|
* viewports is changed, but NOT when the viewport position changes only.
|
|
8061
8359
|
*
|
|
8062
|
-
* @param
|
|
8360
|
+
* @param viewportId - The viewportId to disable
|
|
8063
8361
|
*/
|
|
8064
|
-
disableElement(
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
}
|
|
8069
|
-
const viewportId = viewportInfo.getViewportId();
|
|
8070
|
-
this.renderingEngine && this.renderingEngine.disableElement(viewportId);
|
|
8071
|
-
this.viewportsInfo.get(viewportIndex).destroy();
|
|
8072
|
-
this.viewportsInfo.delete(viewportIndex);
|
|
8362
|
+
disableElement(viewportId) {
|
|
8363
|
+
this.renderingEngine?.disableElement(viewportId);
|
|
8364
|
+
|
|
8365
|
+
// clean up
|
|
8073
8366
|
this.viewportsById.delete(viewportId);
|
|
8367
|
+
this.viewportsDisplaySets.delete(viewportId);
|
|
8074
8368
|
}
|
|
8075
8369
|
setPresentations(viewport, presentations) {
|
|
8076
8370
|
const properties = presentations?.lutPresentation?.properties;
|
|
8077
|
-
if (properties)
|
|
8371
|
+
if (properties) {
|
|
8372
|
+
viewport.setProperties(properties);
|
|
8373
|
+
}
|
|
8078
8374
|
const camera = presentations?.positionPresentation?.camera;
|
|
8079
|
-
if (camera)
|
|
8375
|
+
if (camera) {
|
|
8376
|
+
viewport.setCamera(camera);
|
|
8377
|
+
}
|
|
8080
8378
|
}
|
|
8081
|
-
getPresentation(
|
|
8082
|
-
const viewportInfo = this.
|
|
8083
|
-
if (!viewportInfo)
|
|
8379
|
+
getPresentation(viewportId) {
|
|
8380
|
+
const viewportInfo = this.viewportsById.get(viewportId);
|
|
8381
|
+
if (!viewportInfo) {
|
|
8382
|
+
return;
|
|
8383
|
+
}
|
|
8084
8384
|
const {
|
|
8085
8385
|
viewportType,
|
|
8086
8386
|
presentationIds
|
|
8087
8387
|
} = viewportInfo.getViewportOptions();
|
|
8088
|
-
const csViewport = this.
|
|
8089
|
-
if (!csViewport)
|
|
8388
|
+
const csViewport = this.getCornerstoneViewport(viewportId);
|
|
8389
|
+
if (!csViewport) {
|
|
8390
|
+
return;
|
|
8391
|
+
}
|
|
8090
8392
|
const properties = csViewport.getProperties();
|
|
8091
8393
|
if (properties.isComputedVOI) {
|
|
8092
8394
|
delete properties.voiRange;
|
|
@@ -8102,40 +8404,78 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8102
8404
|
camera
|
|
8103
8405
|
};
|
|
8104
8406
|
}
|
|
8407
|
+
storePresentation(_ref) {
|
|
8408
|
+
let {
|
|
8409
|
+
viewportId
|
|
8410
|
+
} = _ref;
|
|
8411
|
+
const stateSyncService = this.servicesManager.services.stateSyncService;
|
|
8412
|
+
let presentation;
|
|
8413
|
+
try {
|
|
8414
|
+
presentation = this.getPresentation(viewportId);
|
|
8415
|
+
} catch (error) {
|
|
8416
|
+
console.warn(error);
|
|
8417
|
+
}
|
|
8418
|
+
if (!presentation || !presentation.presentationIds) {
|
|
8419
|
+
return;
|
|
8420
|
+
}
|
|
8421
|
+
const {
|
|
8422
|
+
lutPresentationStore,
|
|
8423
|
+
positionPresentationStore
|
|
8424
|
+
} = stateSyncService.getState();
|
|
8425
|
+
const {
|
|
8426
|
+
presentationIds
|
|
8427
|
+
} = presentation;
|
|
8428
|
+
const {
|
|
8429
|
+
lutPresentationId,
|
|
8430
|
+
positionPresentationId
|
|
8431
|
+
} = presentationIds || {};
|
|
8432
|
+
const storeState = {};
|
|
8433
|
+
if (lutPresentationId) {
|
|
8434
|
+
storeState.lutPresentationStore = {
|
|
8435
|
+
...lutPresentationStore,
|
|
8436
|
+
[lutPresentationId]: presentation
|
|
8437
|
+
};
|
|
8438
|
+
}
|
|
8439
|
+
if (positionPresentationId) {
|
|
8440
|
+
storeState.positionPresentationStore = {
|
|
8441
|
+
...positionPresentationStore,
|
|
8442
|
+
[positionPresentationId]: presentation
|
|
8443
|
+
};
|
|
8444
|
+
}
|
|
8445
|
+
stateSyncService.store(storeState);
|
|
8446
|
+
}
|
|
8105
8447
|
|
|
8106
8448
|
/**
|
|
8107
|
-
*
|
|
8108
|
-
*
|
|
8109
|
-
* @param
|
|
8110
|
-
* @param
|
|
8111
|
-
* @param
|
|
8112
|
-
* @
|
|
8449
|
+
* Sets the viewport data for a viewport.
|
|
8450
|
+
* @param viewportId - The ID of the viewport to set the data for.
|
|
8451
|
+
* @param viewportData - The viewport data to set.
|
|
8452
|
+
* @param publicViewportOptions - The public viewport options.
|
|
8453
|
+
* @param publicDisplaySetOptions - The public display set options.
|
|
8454
|
+
* @param presentations - The presentations to set.
|
|
8113
8455
|
*/
|
|
8114
|
-
setViewportData(
|
|
8456
|
+
setViewportData(viewportId, viewportData, publicViewportOptions, publicDisplaySetOptions, presentations) {
|
|
8115
8457
|
const renderingEngine = this.getRenderingEngine();
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
}
|
|
8458
|
+
|
|
8459
|
+
// This is the old viewportInfo, which may have old options but we might be
|
|
8460
|
+
// using its viewport (same viewportId as the new viewportInfo)
|
|
8120
8461
|
const viewportInfo = this.viewportsById.get(viewportId);
|
|
8462
|
+
|
|
8463
|
+
// We should store the presentation for the current viewport since we can't only
|
|
8464
|
+
// rely to store it WHEN the viewport is disabled since we might keep around the
|
|
8465
|
+
// same viewport/element and just change the viewportData for it (drag and drop etc.)
|
|
8466
|
+
// the disableElement storePresentation handle would not be called in this case
|
|
8467
|
+
// and we would lose the presentation.
|
|
8468
|
+
this.storePresentation({
|
|
8469
|
+
viewportId: viewportInfo.getViewportId()
|
|
8470
|
+
});
|
|
8121
8471
|
if (!viewportInfo) {
|
|
8122
|
-
throw new Error('
|
|
8472
|
+
throw new Error('element is not enabled for the given viewportId');
|
|
8123
8473
|
}
|
|
8124
8474
|
|
|
8125
|
-
//
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
viewportInfo.viewportIndex = viewportIndex;
|
|
8130
|
-
}
|
|
8131
|
-
viewportInfo.setRenderingEngineId(renderingEngine.id);
|
|
8132
|
-
const {
|
|
8133
|
-
viewportOptions,
|
|
8134
|
-
displaySetOptions
|
|
8135
|
-
} = this._getViewportAndDisplaySetOptions(publicViewportOptions, publicDisplaySetOptions, viewportInfo);
|
|
8136
|
-
viewportInfo.setViewportOptions(viewportOptions);
|
|
8137
|
-
viewportInfo.setDisplaySetOptions(displaySetOptions);
|
|
8138
|
-
viewportInfo.setViewportData(viewportData);
|
|
8475
|
+
// override the viewportOptions and displaySetOptions with the public ones
|
|
8476
|
+
// since those are the newly set ones, we set them here so that it handles defaults
|
|
8477
|
+
const displaySetOptions = viewportInfo.setPublicDisplaySetOptions(publicDisplaySetOptions);
|
|
8478
|
+
const viewportOptions = viewportInfo.setPublicViewportOptions(publicViewportOptions);
|
|
8139
8479
|
const element = viewportInfo.getElement();
|
|
8140
8480
|
const type = viewportInfo.getViewportType();
|
|
8141
8481
|
const background = viewportInfo.getBackground();
|
|
@@ -8150,11 +8490,23 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8150
8490
|
}
|
|
8151
8491
|
};
|
|
8152
8492
|
|
|
8493
|
+
// Rendering Engine Id set should happen before enabling the element
|
|
8494
|
+
// since there are callbacks that depend on the renderingEngine id
|
|
8495
|
+
// Todo: however, this is a limitation which means that we can't change
|
|
8496
|
+
// the rendering engine id for a given viewport which might be a super edge
|
|
8497
|
+
// case
|
|
8498
|
+
viewportInfo.setRenderingEngineId(renderingEngine.id);
|
|
8499
|
+
|
|
8153
8500
|
// Todo: this is not optimal at all, we are re-enabling the already enabled
|
|
8154
8501
|
// element which is not what we want. But enabledElement as part of the
|
|
8155
8502
|
// renderingEngine is designed to be used like this. This will trigger
|
|
8156
8503
|
// ENABLED_ELEMENT again and again, which will run onEnableElement callbacks
|
|
8157
8504
|
renderingEngine.enableElement(viewportInput);
|
|
8505
|
+
viewportInfo.setViewportOptions(viewportOptions);
|
|
8506
|
+
viewportInfo.setDisplaySetOptions(displaySetOptions);
|
|
8507
|
+
viewportInfo.setViewportData(viewportData);
|
|
8508
|
+
viewportInfo.setViewportId(viewportId);
|
|
8509
|
+
this.viewportsById.set(viewportId, viewportInfo);
|
|
8158
8510
|
const viewport = renderingEngine.getViewport(viewportId);
|
|
8159
8511
|
this._setDisplaySets(viewport, viewportData, viewportInfo, presentations);
|
|
8160
8512
|
|
|
@@ -8163,7 +8515,6 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8163
8515
|
// invalid data.
|
|
8164
8516
|
this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, {
|
|
8165
8517
|
viewportData,
|
|
8166
|
-
viewportIndex,
|
|
8167
8518
|
viewportId
|
|
8168
8519
|
});
|
|
8169
8520
|
}
|
|
@@ -8175,31 +8526,8 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8175
8526
|
const viewport = this.renderingEngine.getViewport(viewportId);
|
|
8176
8527
|
return viewport;
|
|
8177
8528
|
}
|
|
8178
|
-
getCornerstoneViewportByIndex(viewportIndex) {
|
|
8179
|
-
const viewportInfo = this.getViewportInfoByIndex(viewportIndex);
|
|
8180
|
-
if (!viewportInfo || !this.renderingEngine || this.renderingEngine.hasBeenDestroyed) {
|
|
8181
|
-
return null;
|
|
8182
|
-
}
|
|
8183
|
-
const viewport = this.renderingEngine.getViewport(viewportInfo.getViewportId());
|
|
8184
|
-
return viewport;
|
|
8185
|
-
}
|
|
8186
|
-
|
|
8187
|
-
/**
|
|
8188
|
-
* Returns the viewportIndex for the provided viewportId
|
|
8189
|
-
* @param {string} viewportId - the viewportId
|
|
8190
|
-
* @returns {number} - the viewportIndex
|
|
8191
|
-
*/
|
|
8192
|
-
getViewportInfoByIndex(viewportIndex) {
|
|
8193
|
-
return this.viewportsInfo.get(viewportIndex);
|
|
8194
|
-
}
|
|
8195
8529
|
getViewportInfo(viewportId) {
|
|
8196
|
-
|
|
8197
|
-
for (const [index, viewport] of this.viewportsInfo.entries()) {
|
|
8198
|
-
if (viewport.getViewportId() === viewportId) {
|
|
8199
|
-
return viewport;
|
|
8200
|
-
}
|
|
8201
|
-
}
|
|
8202
|
-
return null;
|
|
8530
|
+
return this.viewportsById.get(viewportId);
|
|
8203
8531
|
}
|
|
8204
8532
|
_setStackViewport(viewport, viewportData, viewportInfo, presentations) {
|
|
8205
8533
|
const displaySetOptions = viewportInfo.getDisplaySetOptions();
|
|
@@ -8236,9 +8564,13 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8236
8564
|
}
|
|
8237
8565
|
}
|
|
8238
8566
|
viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
|
|
8239
|
-
viewport.setProperties(
|
|
8567
|
+
viewport.setProperties({
|
|
8568
|
+
...properties
|
|
8569
|
+
});
|
|
8240
8570
|
const camera = presentations.positionPresentation?.camera;
|
|
8241
|
-
if (camera)
|
|
8571
|
+
if (camera) {
|
|
8572
|
+
viewport.setCamera(camera);
|
|
8573
|
+
}
|
|
8242
8574
|
});
|
|
8243
8575
|
}
|
|
8244
8576
|
_getInitialImageIndexForViewport(viewportInfo, imageIds) {
|
|
@@ -8333,7 +8665,7 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8333
8665
|
});
|
|
8334
8666
|
}
|
|
8335
8667
|
this.viewportsDisplaySets.set(viewport.id, displaySetInstanceUIDs);
|
|
8336
|
-
if (hangingProtocolService.
|
|
8668
|
+
if (hangingProtocolService.getShouldPerformCustomImageLoad()) {
|
|
8337
8669
|
// delegate the volume loading to the hanging protocol service if it has a custom image load strategy
|
|
8338
8670
|
return hangingProtocolService.runImageLoadStrategy({
|
|
8339
8671
|
viewportId: viewport.id,
|
|
@@ -8395,11 +8727,11 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8395
8727
|
};
|
|
8396
8728
|
});
|
|
8397
8729
|
await viewport.setVolumes(volumeInputArray);
|
|
8398
|
-
volumesProperties.forEach(
|
|
8730
|
+
volumesProperties.forEach(_ref2 => {
|
|
8399
8731
|
let {
|
|
8400
8732
|
properties,
|
|
8401
8733
|
volumeId
|
|
8402
|
-
} =
|
|
8734
|
+
} = _ref2;
|
|
8403
8735
|
viewport.setProperties(properties, volumeId);
|
|
8404
8736
|
});
|
|
8405
8737
|
this.setPresentations(viewport, presentations);
|
|
@@ -8448,13 +8780,25 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8448
8780
|
continue;
|
|
8449
8781
|
}
|
|
8450
8782
|
|
|
8451
|
-
// otherwise, check if the hydrated segmentations are in the same
|
|
8783
|
+
// otherwise, check if the hydrated segmentations are in the same FrameOfReferenceUID
|
|
8452
8784
|
// as the primary displaySet, if so add the representation (since it was not there)
|
|
8453
8785
|
const {
|
|
8454
|
-
id: segDisplaySetInstanceUID
|
|
8455
|
-
type
|
|
8786
|
+
id: segDisplaySetInstanceUID
|
|
8456
8787
|
} = segmentation;
|
|
8457
|
-
|
|
8788
|
+
let segFrameOfReferenceUID = this._getFrameOfReferenceUID(segDisplaySetInstanceUID);
|
|
8789
|
+
if (!segFrameOfReferenceUID) {
|
|
8790
|
+
// if the segmentation displaySet does not have a FrameOfReferenceUID, we might check the
|
|
8791
|
+
// segmentation itself maybe it has a FrameOfReferenceUID
|
|
8792
|
+
const {
|
|
8793
|
+
FrameOfReferenceUID
|
|
8794
|
+
} = segmentation;
|
|
8795
|
+
if (FrameOfReferenceUID) {
|
|
8796
|
+
segFrameOfReferenceUID = FrameOfReferenceUID;
|
|
8797
|
+
}
|
|
8798
|
+
}
|
|
8799
|
+
if (!segFrameOfReferenceUID) {
|
|
8800
|
+
return;
|
|
8801
|
+
}
|
|
8458
8802
|
let shouldDisplaySeg = false;
|
|
8459
8803
|
for (const displaySetInstanceUID of displaySetInstanceUIDs) {
|
|
8460
8804
|
const primaryFrameOfReferenceUID = this._getFrameOfReferenceUID(displaySetInstanceUID);
|
|
@@ -8487,13 +8831,12 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8487
8831
|
|
|
8488
8832
|
// Todo: keepCamera is an interim solution until we have a better solution for
|
|
8489
8833
|
// keeping the camera position when the viewport data is changed
|
|
8490
|
-
updateViewport(
|
|
8834
|
+
updateViewport(viewportId, viewportData) {
|
|
8491
8835
|
let keepCamera = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
8492
|
-
const viewportInfo = this.
|
|
8493
|
-
const viewportId = viewportInfo.getViewportId();
|
|
8836
|
+
const viewportInfo = this.getViewportInfo(viewportId);
|
|
8494
8837
|
const viewport = this.getCornerstoneViewport(viewportId);
|
|
8495
8838
|
const viewportCamera = viewport.getCamera();
|
|
8496
|
-
if (viewport instanceof esm.VolumeViewport) {
|
|
8839
|
+
if (viewport instanceof esm.VolumeViewport || viewport instanceof esm.VolumeViewport3D) {
|
|
8497
8840
|
this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {
|
|
8498
8841
|
if (keepCamera) {
|
|
8499
8842
|
viewport.setCamera(viewportCamera);
|
|
@@ -8548,23 +8891,6 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8548
8891
|
return slabThickness;
|
|
8549
8892
|
}
|
|
8550
8893
|
}
|
|
8551
|
-
_getViewportAndDisplaySetOptions(publicViewportOptions, publicDisplaySetOptions, viewportInfo) {
|
|
8552
|
-
const viewportIndex = viewportInfo.getViewportIndex();
|
|
8553
|
-
|
|
8554
|
-
// Creating a temporary viewportInfo to handle defaults
|
|
8555
|
-
const newViewportInfo = new Viewport(viewportIndex, viewportInfo.getViewportId());
|
|
8556
|
-
|
|
8557
|
-
// To handle setting the default values if missing for the viewportOptions and
|
|
8558
|
-
// displaySetOptions
|
|
8559
|
-
newViewportInfo.setPublicViewportOptions(publicViewportOptions);
|
|
8560
|
-
newViewportInfo.setPublicDisplaySetOptions(publicDisplaySetOptions);
|
|
8561
|
-
const newViewportOptions = newViewportInfo.getViewportOptions();
|
|
8562
|
-
const newDisplaySetOptions = newViewportInfo.getDisplaySetOptions();
|
|
8563
|
-
return {
|
|
8564
|
-
viewportOptions: newViewportOptions,
|
|
8565
|
-
displaySetOptions: newDisplaySetOptions
|
|
8566
|
-
};
|
|
8567
|
-
}
|
|
8568
8894
|
_getFrameOfReferenceUID(displaySetInstanceUID) {
|
|
8569
8895
|
const {
|
|
8570
8896
|
displaySetService
|
|
@@ -8602,28 +8928,28 @@ class CornerstoneViewportService extends src/* PubSubService */.hC {
|
|
|
8602
8928
|
*
|
|
8603
8929
|
* @param measurement
|
|
8604
8930
|
* The measurement that is desired to view.
|
|
8605
|
-
* @param
|
|
8931
|
+
* @param activeViewportId - the index that was active at the time the jump
|
|
8606
8932
|
* was initiated.
|
|
8607
|
-
* @return the
|
|
8933
|
+
* @return the viewportId that the measurement should be displayed in.
|
|
8608
8934
|
*/
|
|
8609
|
-
|
|
8610
|
-
const viewportInfo = this.
|
|
8935
|
+
getViewportIdToJump(activeViewportId, displaySetInstanceUID, cameraProps) {
|
|
8936
|
+
const viewportInfo = this.getViewportInfo(activeViewportId);
|
|
8611
8937
|
const {
|
|
8612
8938
|
referencedImageId
|
|
8613
8939
|
} = cameraProps;
|
|
8614
8940
|
if (viewportInfo?.contains(displaySetInstanceUID, referencedImageId)) {
|
|
8615
|
-
return
|
|
8941
|
+
return activeViewportId;
|
|
8616
8942
|
}
|
|
8617
|
-
return [...this.viewportsById.values()].find(viewportInfo => viewportInfo.contains(displaySetInstanceUID, referencedImageId))?.
|
|
8943
|
+
return [...this.viewportsById.values()].find(viewportInfo => viewportInfo.contains(displaySetInstanceUID, referencedImageId))?.viewportId ?? null;
|
|
8618
8944
|
}
|
|
8619
8945
|
}
|
|
8620
8946
|
CornerstoneViewportService.REGISTRATION = {
|
|
8621
8947
|
name: 'cornerstoneViewportService',
|
|
8622
8948
|
altName: 'CornerstoneViewportService',
|
|
8623
|
-
create:
|
|
8949
|
+
create: _ref3 => {
|
|
8624
8950
|
let {
|
|
8625
8951
|
servicesManager
|
|
8626
|
-
} =
|
|
8952
|
+
} = _ref3;
|
|
8627
8953
|
return new CornerstoneViewportService(servicesManager);
|
|
8628
8954
|
}
|
|
8629
8955
|
};
|
|
@@ -8632,7 +8958,7 @@ CornerstoneViewportService.REGISTRATION = {
|
|
|
8632
8958
|
|
|
8633
8959
|
|
|
8634
8960
|
// EXTERNAL MODULE: ../../../node_modules/dicomweb-client/build/dicomweb-client.es.js
|
|
8635
|
-
var dicomweb_client_es = __webpack_require__(
|
|
8961
|
+
var dicomweb_client_es = __webpack_require__(97604);
|
|
8636
8962
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/dicomLoaderService.js
|
|
8637
8963
|
|
|
8638
8964
|
|
|
@@ -8707,7 +9033,7 @@ class DicomLoaderService {
|
|
|
8707
9033
|
// Use referenced imageInstance
|
|
8708
9034
|
const imageInstance = getImageInstance(dataset);
|
|
8709
9035
|
const nonImageInstance = getNonImageInstance(dataset);
|
|
8710
|
-
if (!imageInstance && !nonImageInstance || !nonImageInstance.imageId
|
|
9036
|
+
if (!imageInstance && !nonImageInstance || !nonImageInstance.imageId?.startsWith('dicomfile')) {
|
|
8711
9037
|
return;
|
|
8712
9038
|
}
|
|
8713
9039
|
const instance = imageInstance || nonImageInstance;
|
|
@@ -8824,7 +9150,6 @@ function getHandlesFromPoints(points) {
|
|
|
8824
9150
|
|
|
8825
9151
|
|
|
8826
9152
|
|
|
8827
|
-
|
|
8828
9153
|
;// CONCATENATED MODULE: ../../../extensions/cornerstone/src/utils/measurementServiceMappings/index.ts
|
|
8829
9154
|
|
|
8830
9155
|
|
|
@@ -8849,11 +9174,10 @@ function src_extends() { src_extends = Object.assign ? Object.assign.bind() : fu
|
|
|
8849
9174
|
|
|
8850
9175
|
|
|
8851
9176
|
|
|
8852
|
-
|
|
8853
9177
|
|
|
8854
9178
|
|
|
8855
9179
|
const Component = /*#__PURE__*/react.lazy(() => {
|
|
8856
|
-
return Promise.all(/* import() */[__webpack_require__.e(
|
|
9180
|
+
return Promise.all(/* import() */[__webpack_require__.e(23), __webpack_require__.e(181)]).then(__webpack_require__.bind(__webpack_require__, 86181));
|
|
8857
9181
|
});
|
|
8858
9182
|
const OHIFCornerstoneViewport = props => {
|
|
8859
9183
|
return /*#__PURE__*/react.createElement(react.Suspense, {
|
|
@@ -8876,7 +9200,6 @@ const cornerstoneExtension = {
|
|
|
8876
9200
|
esm.imageLoadPoolManager.clearRequestStack(type);
|
|
8877
9201
|
esm.imageRetrievalPoolManager.clearRequestStack(type);
|
|
8878
9202
|
});
|
|
8879
|
-
destroy();
|
|
8880
9203
|
(0,state/* reset */.mc)();
|
|
8881
9204
|
},
|
|
8882
9205
|
/**
|
|
@@ -8956,7 +9279,7 @@ const cornerstoneExtension = {
|
|
|
8956
9279
|
|
|
8957
9280
|
/***/ }),
|
|
8958
9281
|
|
|
8959
|
-
/***/
|
|
9282
|
+
/***/ 73704:
|
|
8960
9283
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
8961
9284
|
|
|
8962
9285
|
"use strict";
|
|
@@ -8976,21 +9299,21 @@ const state = {
|
|
|
8976
9299
|
* @param {HTMLElement} dom Active viewport element.
|
|
8977
9300
|
* @return void
|
|
8978
9301
|
*/
|
|
8979
|
-
const setEnabledElement = (
|
|
9302
|
+
const setEnabledElement = (viewportId, element, context) => {
|
|
8980
9303
|
const targetContext = context || state.DEFAULT_CONTEXT;
|
|
8981
|
-
state.enabledElements[
|
|
9304
|
+
state.enabledElements[viewportId] = {
|
|
8982
9305
|
element,
|
|
8983
9306
|
context: targetContext
|
|
8984
9307
|
};
|
|
8985
9308
|
};
|
|
8986
9309
|
|
|
8987
9310
|
/**
|
|
8988
|
-
* Grabs the enabled element `dom` reference of an
|
|
9311
|
+
* Grabs the enabled element `dom` reference of an active viewport.
|
|
8989
9312
|
*
|
|
8990
9313
|
* @return {HTMLElement} Active viewport element.
|
|
8991
9314
|
*/
|
|
8992
|
-
const getEnabledElement =
|
|
8993
|
-
return state.enabledElements[
|
|
9315
|
+
const getEnabledElement = viewportId => {
|
|
9316
|
+
return state.enabledElements[viewportId];
|
|
8994
9317
|
};
|
|
8995
9318
|
const reset = () => {
|
|
8996
9319
|
state.enabledElements = {};
|
|
@@ -8999,14 +9322,14 @@ const reset = () => {
|
|
|
8999
9322
|
|
|
9000
9323
|
/***/ }),
|
|
9001
9324
|
|
|
9002
|
-
/***/
|
|
9325
|
+
/***/ 87172:
|
|
9003
9326
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
9004
9327
|
|
|
9005
9328
|
"use strict";
|
|
9006
9329
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
9007
9330
|
/* harmony export */ Z: () => (/* binding */ getSOPInstanceAttributes)
|
|
9008
9331
|
/* harmony export */ });
|
|
9009
|
-
/* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
|
|
9332
|
+
/* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(45754);
|
|
9010
9333
|
|
|
9011
9334
|
|
|
9012
9335
|
/**
|