@ohif/app 3.0.0 → 3.5.0
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/151.bundle.07bac9172580a60fae7a.js +2579 -0
- package/dist/192.bundle.62be5f0ef9705a485071.js +894 -0
- package/dist/199.bundle.2286f24cf0a068e7f50c.js +480 -0
- package/dist/205.bundle.39e6c847d618ad2b1b7a.js +62 -0
- package/dist/208.bundle.23748a85dfdc79c05d3a.js +864 -0
- package/dist/270.bundle.abbdb5348274bae3e8bc.js +23906 -0
- package/dist/283.bundle.33f99a75a5e2d9333da2.js +2939 -0
- package/dist/295.bundle.5105ce962be15c92484d.js +48 -0
- package/dist/331.bundle.7ac7b142d249d14fd99e.js +73034 -0
- package/dist/351.bundle.c5d7279ef42e30f61e08.js +1471 -0
- package/dist/351.css +3 -0
- package/dist/36785fbd89b0e17f6099.wasm +0 -0
- package/dist/381.bundle.0905e683605fcbc0895f.js +1009 -0
- package/dist/404.bundle.0f7a500421f246153d89.js +706 -0
- package/dist/50.bundle.4cb103cd20f5ffccf927.js +324 -0
- package/dist/5004fdc02f329ce53b69.wasm +0 -0
- package/dist/531.bundle.1bc152c87c7e2e987d2b.js +5935 -0
- package/dist/55.bundle.a5a215e13a8511f7aee7.js +685 -0
- package/dist/55.css +3 -0
- package/dist/569.bundle.d147c0aa0604f8ea2094.js +514 -0
- package/dist/581.bundle.646c89c5c3e3ee096363.js +508 -0
- package/dist/606.bundle.5d876f5f3dd8287f0a28.js +4939 -0
- package/dist/610.min.worker.js +2 -0
- package/dist/610.min.worker.js.map +1 -0
- package/dist/616.bundle.bec4736d8c9513e62856.js +686 -0
- package/dist/62ab5d58a2bea7b5a1dc.wasm +0 -0
- package/dist/642.bundle.030d908e22c8ff5611f3.js +169 -0
- package/dist/65916ef3def695744bda.wasm +0 -0
- package/dist/664.bundle.4792c88ae0d6d4b5ed13.js +901 -0
- package/dist/707.bundle.0a74aa3e61ed002eb3c6.js +9049 -0
- package/dist/707.css +1 -0
- package/dist/728.bundle.d13856835357400fef82.js +26221 -0
- package/dist/744.bundle.53b07e48e07a11e920ac.js +2355 -0
- package/dist/75788f12450d4c5ed494.wasm +0 -0
- package/dist/75a0c2dfe07b824c7d21.wasm +0 -0
- package/dist/780.bundle.f60ac1906e0ae080dee8.js +4769 -0
- package/dist/790.bundle.b4df2c5d78a2a565b150.js +454 -0
- package/dist/799.bundle.3fff638815e355b0bdfd.js +271 -0
- package/dist/806.css +1 -0
- package/dist/82.bundle.a24015533196e05d190e.js +6104 -0
- package/dist/917.bundle.a094ae9e9de6df4119ae.js +196 -0
- package/dist/926.bundle.dbc9d0e591cb9217fda2.js +72552 -0
- package/dist/935.bundle.deeffff0e4f7b528e3c3.js +1849 -0
- package/dist/945.min.worker.js +2 -0
- package/dist/945.min.worker.js.map +1 -0
- package/dist/953.bundle.c14d9eb6400f697019ee.js +449 -0
- package/dist/973.bundle.4100cf103686b64938d1.js +261 -0
- package/dist/976.bundle.2720eb892514e1818018.js +2725 -0
- package/dist/984.bundle.157fc66ea5040e1364af.js +1842 -0
- package/dist/_headers +6 -0
- package/dist/_redirects +6 -0
- package/dist/app-config.js +215 -0
- package/dist/app.bundle.253eeb2a7ee986e89c50.js +154621 -0
- package/dist/app.bundle.css +21 -0
- package/dist/assets/android-chrome-144x144.png +0 -0
- package/dist/assets/android-chrome-192x192.png +0 -0
- package/dist/assets/android-chrome-256x256.png +0 -0
- package/dist/assets/android-chrome-36x36.png +0 -0
- package/dist/assets/android-chrome-384x384.png +0 -0
- package/dist/assets/android-chrome-48x48.png +0 -0
- package/dist/assets/android-chrome-512x512.png +0 -0
- package/dist/assets/android-chrome-72x72.png +0 -0
- package/dist/assets/android-chrome-96x96.png +0 -0
- package/dist/assets/apple-touch-icon-1024x1024.png +0 -0
- package/dist/assets/apple-touch-icon-114x114.png +0 -0
- package/dist/assets/apple-touch-icon-120x120.png +0 -0
- package/dist/assets/apple-touch-icon-144x144.png +0 -0
- package/dist/assets/apple-touch-icon-152x152.png +0 -0
- package/dist/assets/apple-touch-icon-167x167.png +0 -0
- package/dist/assets/apple-touch-icon-180x180.png +0 -0
- package/dist/assets/apple-touch-icon-57x57.png +0 -0
- package/dist/assets/apple-touch-icon-60x60.png +0 -0
- package/dist/assets/apple-touch-icon-72x72.png +0 -0
- package/dist/assets/apple-touch-icon-76x76.png +0 -0
- package/dist/assets/apple-touch-icon-precomposed.png +0 -0
- package/dist/assets/apple-touch-icon.png +0 -0
- package/dist/assets/apple-touch-startup-image-1182x2208.png +0 -0
- package/dist/assets/apple-touch-startup-image-1242x2148.png +0 -0
- package/dist/assets/apple-touch-startup-image-1496x2048.png +0 -0
- package/dist/assets/apple-touch-startup-image-1536x2008.png +0 -0
- package/dist/assets/apple-touch-startup-image-320x460.png +0 -0
- package/dist/assets/apple-touch-startup-image-640x1096.png +0 -0
- package/dist/assets/apple-touch-startup-image-640x920.png +0 -0
- package/dist/assets/apple-touch-startup-image-748x1024.png +0 -0
- package/dist/assets/apple-touch-startup-image-750x1294.png +0 -0
- package/dist/assets/apple-touch-startup-image-768x1004.png +0 -0
- package/dist/assets/browserconfig.xml +12 -0
- package/dist/assets/coast-228x228.png +0 -0
- package/dist/assets/favicon-16x16.png +0 -0
- package/dist/assets/favicon-32x32.png +0 -0
- package/dist/assets/favicon.ico +0 -0
- package/dist/assets/firefox_app_128x128.png +0 -0
- package/dist/assets/firefox_app_512x512.png +0 -0
- package/dist/assets/firefox_app_60x60.png +0 -0
- package/dist/assets/manifest.webapp +14 -0
- package/dist/assets/mstile-144x144.png +0 -0
- package/dist/assets/mstile-150x150.png +0 -0
- package/dist/assets/mstile-310x150.png +0 -0
- package/dist/assets/mstile-310x310.png +0 -0
- package/dist/assets/mstile-70x70.png +0 -0
- package/dist/assets/yandex-browser-50x50.png +0 -0
- package/dist/assets/yandex-browser-manifest.json +9 -0
- package/dist/b6b803111e2d06a825bd.wasm +0 -0
- package/dist/c22b37c3488e1d6c3aa4.wasm +0 -0
- package/dist/cornerstoneDICOMImageLoader.min.js +2 -0
- package/dist/cornerstoneDICOMImageLoader.min.js.map +1 -0
- package/dist/dicom-microscopy-viewer.bundle.aa60bdf008c32c39cfd7.js +12 -0
- package/dist/dicomMicroscopyViewer.min.js +3 -0
- package/dist/dicomMicroscopyViewer.min.js.LICENSE.txt +29 -0
- package/dist/es6-shim.min.js +12 -0
- package/dist/google.js +75 -0
- package/dist/index.html +1 -0
- package/dist/index.worker.ea71efba2ce63c499055.worker.js +2 -0
- package/dist/index.worker.ea71efba2ce63c499055.worker.js.map +1 -0
- package/dist/index.worker.min.worker.js +2 -0
- package/dist/index.worker.min.worker.js.map +1 -0
- package/dist/init-service-worker.js +59 -0
- package/dist/manifest.json +59 -0
- package/dist/ohif-logo-light.svg +15 -0
- package/dist/ohif-logo.svg +15 -0
- package/dist/oidc-client.min.js +46 -0
- package/dist/polyfill.min.js +1 -0
- package/dist/silent-refresh.html +16 -0
- package/dist/sw.js +56 -0
- package/package.json +24 -23
|
@@ -0,0 +1,685 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[55,806],{
|
|
3
|
+
|
|
4
|
+
/***/ 76440:
|
|
5
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
6
|
+
|
|
7
|
+
// ESM COMPAT FLAG
|
|
8
|
+
__webpack_require__.r(__webpack_exports__);
|
|
9
|
+
|
|
10
|
+
// EXPORTS
|
|
11
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
12
|
+
"default": () => (/* binding */ src_DicomMicroscopyViewport)
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// EXTERNAL MODULE: ../../../node_modules/react/index.js
|
|
16
|
+
var react = __webpack_require__(32735);
|
|
17
|
+
// EXTERNAL MODULE: ../../../node_modules/react-resize-detector/build/index.esm.js
|
|
18
|
+
var index_esm = __webpack_require__(14664);
|
|
19
|
+
// EXTERNAL MODULE: ../../../node_modules/prop-types/index.js
|
|
20
|
+
var prop_types = __webpack_require__(60216);
|
|
21
|
+
var prop_types_default = /*#__PURE__*/__webpack_require__.n(prop_types);
|
|
22
|
+
// EXTERNAL MODULE: ../../../node_modules/lodash.debounce/index.js
|
|
23
|
+
var lodash_debounce = __webpack_require__(40001);
|
|
24
|
+
var lodash_debounce_default = /*#__PURE__*/__webpack_require__.n(lodash_debounce);
|
|
25
|
+
// EXTERNAL MODULE: ../../ui/src/index.js + 449 modules
|
|
26
|
+
var src = __webpack_require__(43803);
|
|
27
|
+
;// CONCATENATED MODULE: ../../../extensions/dicom-microscopy/src/DicomMicroscopyViewport.css
|
|
28
|
+
// extracted by mini-css-extract-plugin
|
|
29
|
+
|
|
30
|
+
// EXTERNAL MODULE: ../../../node_modules/classnames/index.js
|
|
31
|
+
var classnames = __webpack_require__(40841);
|
|
32
|
+
var classnames_default = /*#__PURE__*/__webpack_require__.n(classnames);
|
|
33
|
+
;// CONCATENATED MODULE: ../../../extensions/dicom-microscopy/src/components/ViewportOverlay/listComponentGenerator.tsx
|
|
34
|
+
const listComponentGenerator = props => {
|
|
35
|
+
const {
|
|
36
|
+
list,
|
|
37
|
+
itemGenerator
|
|
38
|
+
} = props;
|
|
39
|
+
if (!list) return;
|
|
40
|
+
return list.map(item => {
|
|
41
|
+
if (!item) return;
|
|
42
|
+
const generator = item.generator || itemGenerator;
|
|
43
|
+
if (!generator) throw new Error(`No generator for ${item}`);
|
|
44
|
+
return generator({
|
|
45
|
+
...props,
|
|
46
|
+
item
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
/* harmony default export */ const ViewportOverlay_listComponentGenerator = (listComponentGenerator);
|
|
51
|
+
;// CONCATENATED MODULE: ../../../extensions/dicom-microscopy/src/components/ViewportOverlay/ViewportOverlay.css
|
|
52
|
+
// extracted by mini-css-extract-plugin
|
|
53
|
+
|
|
54
|
+
// EXTERNAL MODULE: ../../../node_modules/moment/moment.js
|
|
55
|
+
var moment_moment = __webpack_require__(53806);
|
|
56
|
+
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 335 modules
|
|
57
|
+
var esm = __webpack_require__(77331);
|
|
58
|
+
;// CONCATENATED MODULE: ../../../extensions/dicom-microscopy/src/components/ViewportOverlay/utils.ts
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Checks if value is valid.
|
|
64
|
+
*
|
|
65
|
+
* @param {number} value
|
|
66
|
+
* @returns {boolean} is valid.
|
|
67
|
+
*/
|
|
68
|
+
function isValidNumber(value) {
|
|
69
|
+
return typeof value === 'number' && !isNaN(value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Formats number precision.
|
|
74
|
+
*
|
|
75
|
+
* @param {number} number
|
|
76
|
+
* @param {number} precision
|
|
77
|
+
* @returns {number} formatted number.
|
|
78
|
+
*/
|
|
79
|
+
function utils_formatNumberPrecision(number, precision) {
|
|
80
|
+
if (number !== null) {
|
|
81
|
+
return parseFloat(number).toFixed(precision);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Formats DICOM date.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} date
|
|
89
|
+
* @param {string} strFormat
|
|
90
|
+
* @returns {string} formatted date.
|
|
91
|
+
*/
|
|
92
|
+
function utils_formatDICOMDate(date) {
|
|
93
|
+
let strFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'MMM D, YYYY';
|
|
94
|
+
return moment(date, 'YYYYMMDD').format(strFormat);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* DICOM Time is stored as HHmmss.SSS, where:
|
|
99
|
+
* HH 24 hour time:
|
|
100
|
+
* m mm 0..59 Minutes
|
|
101
|
+
* s ss 0..59 Seconds
|
|
102
|
+
* S SS SSS 0..999 Fractional seconds
|
|
103
|
+
*
|
|
104
|
+
* Goal: '24:12:12'
|
|
105
|
+
*
|
|
106
|
+
* @param {*} time
|
|
107
|
+
* @param {string} strFormat
|
|
108
|
+
* @returns {string} formatted name.
|
|
109
|
+
*/
|
|
110
|
+
function utils_formatDICOMTime(time) {
|
|
111
|
+
let strFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'HH:mm:ss';
|
|
112
|
+
return moment(time, 'HH:mm:ss').format(strFormat);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Formats a patient name for display purposes
|
|
117
|
+
*
|
|
118
|
+
* @param {string} name
|
|
119
|
+
* @returns {string} formatted name.
|
|
120
|
+
*/
|
|
121
|
+
function utils_formatPN(name) {
|
|
122
|
+
if (!name) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Convert the first ^ to a ', '. String.replace() only affects
|
|
127
|
+
// the first appearance of the character.
|
|
128
|
+
const commaBetweenFirstAndLast = name.replace('^', ', ');
|
|
129
|
+
|
|
130
|
+
// Replace any remaining '^' characters with spaces
|
|
131
|
+
const cleaned = commaBetweenFirstAndLast.replace(/\^/g, ' ');
|
|
132
|
+
|
|
133
|
+
// Trim any extraneous whitespace
|
|
134
|
+
return cleaned.trim();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Gets compression type
|
|
139
|
+
*
|
|
140
|
+
* @param {number} imageId
|
|
141
|
+
* @returns {string} comrpession type.
|
|
142
|
+
*/
|
|
143
|
+
function getCompression(imageId) {
|
|
144
|
+
const generalImageModule = cornerstone.metaData.get('generalImageModule', imageId) || {};
|
|
145
|
+
const {
|
|
146
|
+
lossyImageCompression,
|
|
147
|
+
lossyImageCompressionRatio,
|
|
148
|
+
lossyImageCompressionMethod
|
|
149
|
+
} = generalImageModule;
|
|
150
|
+
if (lossyImageCompression === '01' && lossyImageCompressionRatio !== '') {
|
|
151
|
+
const compressionMethod = lossyImageCompressionMethod || 'Lossy: ';
|
|
152
|
+
const compressionRatio = utils_formatNumberPrecision(lossyImageCompressionRatio, 2);
|
|
153
|
+
return compressionMethod + compressionRatio + ' : 1';
|
|
154
|
+
}
|
|
155
|
+
return 'Lossless / Uncompressed';
|
|
156
|
+
}
|
|
157
|
+
;// CONCATENATED MODULE: ../../../extensions/dicom-microscopy/src/components/ViewportOverlay/index.tsx
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
*
|
|
165
|
+
* @param {*} config is a configuration object that defines four lists of elements,
|
|
166
|
+
* one topLeft, topRight, bottomLeft, bottomRight contents.
|
|
167
|
+
* @param {*} extensionManager is used to load the image data.
|
|
168
|
+
* @returns
|
|
169
|
+
*/
|
|
170
|
+
const generateFromConfig = _ref => {
|
|
171
|
+
let {
|
|
172
|
+
topLeft = [],
|
|
173
|
+
topRight = [],
|
|
174
|
+
bottomLeft = [],
|
|
175
|
+
bottomRight = [],
|
|
176
|
+
itemGenerator = () => {}
|
|
177
|
+
} = _ref;
|
|
178
|
+
return props => {
|
|
179
|
+
const topLeftClass = 'top-viewport left-viewport text-primary-light';
|
|
180
|
+
const topRightClass = 'top-viewport right-viewport-scrollbar text-primary-light';
|
|
181
|
+
const bottomRightClass = 'bottom-viewport right-viewport-scrollbar text-primary-light';
|
|
182
|
+
const bottomLeftClass = 'bottom-viewport left-viewport text-primary-light';
|
|
183
|
+
const overlay = 'absolute pointer-events-none microscopy-viewport-overlay';
|
|
184
|
+
return /*#__PURE__*/react.createElement(react.Fragment, null, topLeft && topLeft.length > 0 && /*#__PURE__*/react.createElement("div", {
|
|
185
|
+
"data-cy": 'viewport-overlay-top-left',
|
|
186
|
+
className: classnames_default()(overlay, topLeftClass)
|
|
187
|
+
}, ViewportOverlay_listComponentGenerator({
|
|
188
|
+
...props,
|
|
189
|
+
list: topLeft,
|
|
190
|
+
itemGenerator
|
|
191
|
+
})), topRight && topRight.length > 0 && /*#__PURE__*/react.createElement("div", {
|
|
192
|
+
"data-cy": 'viewport-overlay-top-right',
|
|
193
|
+
className: classnames_default()(overlay, topRightClass)
|
|
194
|
+
}, ViewportOverlay_listComponentGenerator({
|
|
195
|
+
...props,
|
|
196
|
+
list: topRight,
|
|
197
|
+
itemGenerator
|
|
198
|
+
})), bottomRight && bottomRight.length > 0 && /*#__PURE__*/react.createElement("div", {
|
|
199
|
+
"data-cy": 'viewport-overlay-bottom-right',
|
|
200
|
+
className: classnames_default()(overlay, bottomRightClass)
|
|
201
|
+
}, ViewportOverlay_listComponentGenerator({
|
|
202
|
+
...props,
|
|
203
|
+
list: bottomRight,
|
|
204
|
+
itemGenerator
|
|
205
|
+
})), bottomLeft && bottomLeft.length > 0 && /*#__PURE__*/react.createElement("div", {
|
|
206
|
+
"data-cy": 'viewport-overlay-bottom-left',
|
|
207
|
+
className: classnames_default()(overlay, bottomLeftClass)
|
|
208
|
+
}, ViewportOverlay_listComponentGenerator({
|
|
209
|
+
...props,
|
|
210
|
+
list: bottomLeft,
|
|
211
|
+
itemGenerator
|
|
212
|
+
})));
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
const itemGenerator = props => {
|
|
216
|
+
const {
|
|
217
|
+
item
|
|
218
|
+
} = props;
|
|
219
|
+
const {
|
|
220
|
+
title,
|
|
221
|
+
value: valueFunc,
|
|
222
|
+
condition,
|
|
223
|
+
contents
|
|
224
|
+
} = item;
|
|
225
|
+
props.image = {
|
|
226
|
+
...props.image,
|
|
227
|
+
...props.metadata
|
|
228
|
+
};
|
|
229
|
+
props.formatDate = formatDICOMDate;
|
|
230
|
+
props.formatTime = formatDICOMTime;
|
|
231
|
+
props.formatPN = formatPN;
|
|
232
|
+
props.formatNumberPrecision = formatNumberPrecision;
|
|
233
|
+
if (condition && !condition(props)) return null;
|
|
234
|
+
if (!contents && !valueFunc) return null;
|
|
235
|
+
const value = valueFunc && valueFunc(props);
|
|
236
|
+
const contentsValue = contents && contents(props) || [{
|
|
237
|
+
className: 'mr-1',
|
|
238
|
+
value: title
|
|
239
|
+
}, {
|
|
240
|
+
classname: 'mr-1 font-light',
|
|
241
|
+
value
|
|
242
|
+
}];
|
|
243
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
244
|
+
key: item.id,
|
|
245
|
+
className: "flex flex-row"
|
|
246
|
+
}, contentsValue.map((content, idx) => /*#__PURE__*/React.createElement("span", {
|
|
247
|
+
key: idx,
|
|
248
|
+
className: content.className
|
|
249
|
+
}, content.value)));
|
|
250
|
+
};
|
|
251
|
+
/* harmony default export */ const ViewportOverlay = (generateFromConfig({}));
|
|
252
|
+
// EXTERNAL MODULE: ../../../node_modules/dicomweb-client/build/dicomweb-client.es.js
|
|
253
|
+
var dicomweb_client_es = __webpack_require__(75935);
|
|
254
|
+
// EXTERNAL MODULE: ../../core/src/index.ts + 101 modules
|
|
255
|
+
var core_src = __webpack_require__(48501);
|
|
256
|
+
;// CONCATENATED MODULE: ../../../extensions/dicom-microscopy/src/utils/dicomWebClient.ts
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
const {
|
|
260
|
+
DICOMwebClient
|
|
261
|
+
} = dicomweb_client_es.api;
|
|
262
|
+
DICOMwebClient._buildMultipartAcceptHeaderFieldValue = () => {
|
|
263
|
+
return '*/*';
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* create a DICOMwebClient object to be used by Dicom Microscopy Viewer
|
|
268
|
+
*
|
|
269
|
+
* Referenced the code from `/extensions/default/src/DicomWebDataSource/index.js`
|
|
270
|
+
*
|
|
271
|
+
* @param param0
|
|
272
|
+
* @returns
|
|
273
|
+
*/
|
|
274
|
+
function getDicomWebClient(_ref) {
|
|
275
|
+
let {
|
|
276
|
+
extensionManager,
|
|
277
|
+
servicesManager
|
|
278
|
+
} = _ref;
|
|
279
|
+
const dataSourceConfig = window.config.dataSources.find(ds => ds.sourceName === extensionManager.activeDataSource);
|
|
280
|
+
const {
|
|
281
|
+
userAuthenticationService
|
|
282
|
+
} = servicesManager.services;
|
|
283
|
+
const {
|
|
284
|
+
wadoRoot,
|
|
285
|
+
staticWado,
|
|
286
|
+
singlepart
|
|
287
|
+
} = dataSourceConfig.configuration;
|
|
288
|
+
const wadoConfig = {
|
|
289
|
+
url: wadoRoot || '/dicomlocal',
|
|
290
|
+
staticWado,
|
|
291
|
+
singlepart,
|
|
292
|
+
headers: userAuthenticationService.getAuthorizationHeader(),
|
|
293
|
+
errorInterceptor: core_src/* errorHandler.getHTTPErrorHandler */.Po.getHTTPErrorHandler()
|
|
294
|
+
};
|
|
295
|
+
const client = new dicomweb_client_es.api.DICOMwebClient(wadoConfig);
|
|
296
|
+
client.wadoURL = wadoConfig.url;
|
|
297
|
+
if (extensionManager.activeDataSource === 'dicomlocal') {
|
|
298
|
+
/**
|
|
299
|
+
* For local data source, override the retrieveInstanceFrames() method of the
|
|
300
|
+
* dicomweb-client to retrieve image data from memory cached metadata.
|
|
301
|
+
* Other methods of the client doesn't matter, as we are feeding the DMV
|
|
302
|
+
* with the series metadata already.
|
|
303
|
+
*
|
|
304
|
+
* @param {Object} options
|
|
305
|
+
* @param {String} options.studyInstanceUID - Study Instance UID
|
|
306
|
+
* @param {String} options.seriesInstanceUID - Series Instance UID
|
|
307
|
+
* @param {String} options.sopInstanceUID - SOP Instance UID
|
|
308
|
+
* @param {String} options.frameNumbers - One-based indices of Frame Items
|
|
309
|
+
* @param {Object} [options.queryParams] - HTTP query parameters
|
|
310
|
+
* @returns {ArrayBuffer[]} Rendered Frame Items as byte arrays
|
|
311
|
+
*/
|
|
312
|
+
//
|
|
313
|
+
client.retrieveInstanceFrames = async options => {
|
|
314
|
+
if (!('studyInstanceUID' in options)) {
|
|
315
|
+
throw new Error('Study Instance UID is required for retrieval of instance frames');
|
|
316
|
+
}
|
|
317
|
+
if (!('seriesInstanceUID' in options)) {
|
|
318
|
+
throw new Error('Series Instance UID is required for retrieval of instance frames');
|
|
319
|
+
}
|
|
320
|
+
if (!('sopInstanceUID' in options)) {
|
|
321
|
+
throw new Error('SOP Instance UID is required for retrieval of instance frames');
|
|
322
|
+
}
|
|
323
|
+
if (!('frameNumbers' in options)) {
|
|
324
|
+
throw new Error('frame numbers are required for retrieval of instance frames');
|
|
325
|
+
}
|
|
326
|
+
console.log(`retrieve frames ${options.frameNumbers.toString()} of instance ${options.sopInstanceUID}`);
|
|
327
|
+
const instance = core_src.DicomMetadataStore.getInstance(options.studyInstanceUID, options.seriesInstanceUID, options.sopInstanceUID);
|
|
328
|
+
const frameNumbers = Array.isArray(options.frameNumbers) ? options.frameNumbers : options.frameNumbers.split(',');
|
|
329
|
+
return frameNumbers.map(fr => Array.isArray(instance.PixelData) ? instance.PixelData[+fr - 1] : instance.PixelData);
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
return client;
|
|
333
|
+
}
|
|
334
|
+
// EXTERNAL MODULE: ../../../node_modules/dcmjs/build/dcmjs.es.js
|
|
335
|
+
var dcmjs_es = __webpack_require__(22737);
|
|
336
|
+
// EXTERNAL MODULE: ../../../extensions/default/src/index.ts + 58 modules
|
|
337
|
+
var default_src = __webpack_require__(96082);
|
|
338
|
+
;// CONCATENATED MODULE: ../../../extensions/dicom-microscopy/src/utils/cleanDenaturalizedDataset.ts
|
|
339
|
+
|
|
340
|
+
function isPrimitive(v) {
|
|
341
|
+
return !(typeof v == 'object' || Array.isArray(v));
|
|
342
|
+
}
|
|
343
|
+
const vrNumerics = ['DS', 'FL', 'FD', 'IS', 'OD', 'OF', 'OL', 'OV', 'SL', 'SS', 'SV', 'UL', 'US', 'UV'];
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Specialized for DICOM JSON format dataset cleaning.
|
|
347
|
+
* @param obj
|
|
348
|
+
* @returns
|
|
349
|
+
*/
|
|
350
|
+
function cleanDenaturalizedDataset(obj, options) {
|
|
351
|
+
if (Array.isArray(obj)) {
|
|
352
|
+
const newAry = obj.map(o => isPrimitive(o) ? o : cleanDenaturalizedDataset(o, options));
|
|
353
|
+
return newAry;
|
|
354
|
+
} else if (isPrimitive(obj)) {
|
|
355
|
+
return obj;
|
|
356
|
+
} else {
|
|
357
|
+
Object.keys(obj).forEach(key => {
|
|
358
|
+
if (obj[key].Value === null && obj[key].vr) {
|
|
359
|
+
delete obj[key].Value;
|
|
360
|
+
} else if (Array.isArray(obj[key].Value) && obj[key].vr) {
|
|
361
|
+
if (obj[key].Value.length === 1 && obj[key].Value[0].BulkDataURI) {
|
|
362
|
+
default_src.dicomWebUtils.fixBulkDataURI(obj[key].Value[0], options, options.dataSourceConfig);
|
|
363
|
+
obj[key].BulkDataURI = obj[key].Value[0].BulkDataURI;
|
|
364
|
+
|
|
365
|
+
// prevent mixed-content blockage
|
|
366
|
+
if (window.location.protocol === 'https:' && obj[key].BulkDataURI.startsWith('http:')) {
|
|
367
|
+
obj[key].BulkDataURI = obj[key].BulkDataURI.replace('http:', 'https:');
|
|
368
|
+
}
|
|
369
|
+
delete obj[key].Value;
|
|
370
|
+
} else if (vrNumerics.includes(obj[key].vr)) {
|
|
371
|
+
obj[key].Value = obj[key].Value.map(v => +v);
|
|
372
|
+
} else {
|
|
373
|
+
obj[key].Value = obj[key].Value.map(entry => cleanDenaturalizedDataset(entry, options));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
return obj;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
;// CONCATENATED MODULE: ../../../extensions/dicom-microscopy/src/DicomMicroscopyViewport.tsx
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
function transformImageTypeUnnaturalized(entry) {
|
|
392
|
+
if (entry.vr === 'CS') {
|
|
393
|
+
return {
|
|
394
|
+
vr: 'US',
|
|
395
|
+
Value: entry.Value[0].split('\\')
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
return entry;
|
|
399
|
+
}
|
|
400
|
+
class DicomMicroscopyViewport extends react.Component {
|
|
401
|
+
constructor(props) {
|
|
402
|
+
super(props);
|
|
403
|
+
this.state = {
|
|
404
|
+
error: null,
|
|
405
|
+
isLoaded: false
|
|
406
|
+
};
|
|
407
|
+
this.microscopyService = void 0;
|
|
408
|
+
this.viewer = null;
|
|
409
|
+
// dicom-microscopy-viewer instance
|
|
410
|
+
this.managedViewer = null;
|
|
411
|
+
// managed wrapper of microscopy-dicom extension
|
|
412
|
+
this.container = /*#__PURE__*/react.createRef();
|
|
413
|
+
this.overlayElement = /*#__PURE__*/react.createRef();
|
|
414
|
+
this.debouncedResize = void 0;
|
|
415
|
+
this.setViewportActiveHandler = () => {
|
|
416
|
+
const {
|
|
417
|
+
setViewportActive,
|
|
418
|
+
viewportIndex,
|
|
419
|
+
activeViewportIndex
|
|
420
|
+
} = this.props;
|
|
421
|
+
if (viewportIndex !== activeViewportIndex) {
|
|
422
|
+
setViewportActive(viewportIndex);
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
this.onWindowResize = () => {
|
|
426
|
+
this.debouncedResize();
|
|
427
|
+
};
|
|
428
|
+
const {
|
|
429
|
+
microscopyService
|
|
430
|
+
} = this.props.servicesManager.services;
|
|
431
|
+
this.microscopyService = microscopyService;
|
|
432
|
+
this.debouncedResize = lodash_debounce_default()(() => {
|
|
433
|
+
if (this.viewer) this.viewer.resize();
|
|
434
|
+
}, 100);
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Get the nearest ROI from the mouse click point
|
|
438
|
+
*
|
|
439
|
+
* @param event
|
|
440
|
+
* @param autoselect
|
|
441
|
+
* @returns
|
|
442
|
+
*/
|
|
443
|
+
getNearbyROI(event) {
|
|
444
|
+
let autoselect = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
445
|
+
const symbols = Object.getOwnPropertySymbols(this.viewer);
|
|
446
|
+
const _drawingSource = symbols.find(p => p.description === 'drawingSource');
|
|
447
|
+
const _pyramid = symbols.find(p => p.description === 'pyramid');
|
|
448
|
+
const _map = symbols.find(p => p.description === 'map');
|
|
449
|
+
const _affine = symbols.find(p => p.description === 'affine');
|
|
450
|
+
const feature = this.viewer[_drawingSource].getClosestFeatureToCoordinate(this.viewer[_map].getEventCoordinate(event));
|
|
451
|
+
if (!feature) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
const roiAnnotation = this.viewer._getROIFromFeature(feature, this.viewer[_pyramid].metadata, this.viewer[_affine]);
|
|
455
|
+
if (roiAnnotation && autoselect) {
|
|
456
|
+
this.microscopyService.selectAnnotation(roiAnnotation);
|
|
457
|
+
}
|
|
458
|
+
return roiAnnotation;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// install the microscopy renderer into the web page.
|
|
462
|
+
// you should only do this once.
|
|
463
|
+
async installOpenLayersRenderer(container, displaySet) {
|
|
464
|
+
const loadViewer = async metadata => {
|
|
465
|
+
const {
|
|
466
|
+
viewer: DicomMicroscopyViewer,
|
|
467
|
+
metadata: metadataUtils
|
|
468
|
+
} = await __webpack_require__.e(/* import() | dicom-microscopy-viewer */ 18).then(__webpack_require__.t.bind(__webpack_require__, 78457, 23));
|
|
469
|
+
const microscopyViewer = DicomMicroscopyViewer.VolumeImageViewer;
|
|
470
|
+
const client = getDicomWebClient({
|
|
471
|
+
extensionManager: this.props.extensionManager,
|
|
472
|
+
servicesManager: this.props.servicesManager
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
// Parse, format, and filter metadata
|
|
476
|
+
const volumeImages = [];
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* This block of code is the original way of loading DICOM into dicom-microscopy-viewer
|
|
480
|
+
* as in their documentation.
|
|
481
|
+
* But we have the metadata already loaded by our loaders.
|
|
482
|
+
* As the metadata for microscopy DIOM files tends to be big and we don't
|
|
483
|
+
* want to double load it, below we have the mechanism to reconstruct the
|
|
484
|
+
* DICOM JSON structure (denaturalized) from naturalized metadata.
|
|
485
|
+
* (NOTE: Our loaders cache only naturalized metadata, not the denaturalized.)
|
|
486
|
+
*/
|
|
487
|
+
// {
|
|
488
|
+
// const retrieveOptions = {
|
|
489
|
+
// studyInstanceUID: metadata[0].StudyInstanceUID,
|
|
490
|
+
// seriesInstanceUID: metadata[0].SeriesInstanceUID,
|
|
491
|
+
// };
|
|
492
|
+
// metadata = await client.retrieveSeriesMetadata(retrieveOptions);
|
|
493
|
+
// // Parse, format, and filter metadata
|
|
494
|
+
// metadata.forEach(m => {
|
|
495
|
+
// if (
|
|
496
|
+
// volumeImages.length > 0 &&
|
|
497
|
+
// m['00200052'].Value[0] != volumeImages[0].FrameOfReferenceUID
|
|
498
|
+
// ) {
|
|
499
|
+
// console.warn(
|
|
500
|
+
// 'Expected FrameOfReferenceUID of difference instances within a series to be the same, found multiple different values',
|
|
501
|
+
// m['00200052'].Value[0]
|
|
502
|
+
// );
|
|
503
|
+
// m['00200052'].Value[0] = volumeImages[0].FrameOfReferenceUID;
|
|
504
|
+
// }
|
|
505
|
+
// NOTE: depending on different data source, image.ImageType sometimes
|
|
506
|
+
// is a string, not a string array.
|
|
507
|
+
// m['00080008'] = transformImageTypeUnnaturalized(m['00080008']);
|
|
508
|
+
|
|
509
|
+
// const image = new metadataUtils.VLWholeSlideMicroscopyImage({
|
|
510
|
+
// metadata: m,
|
|
511
|
+
// });
|
|
512
|
+
// const imageFlavor = image.ImageType[2];
|
|
513
|
+
// if (imageFlavor === 'VOLUME' || imageFlavor === 'THUMBNAIL') {
|
|
514
|
+
// volumeImages.push(image);
|
|
515
|
+
// }
|
|
516
|
+
// });
|
|
517
|
+
// }
|
|
518
|
+
|
|
519
|
+
metadata.forEach(m => {
|
|
520
|
+
// NOTE: depending on different data source, image.ImageType sometimes
|
|
521
|
+
// is a string, not a string array.
|
|
522
|
+
m.ImageType = typeof m.ImageType === 'string' ? m.ImageType.split('\\') : m.ImageType;
|
|
523
|
+
const inst = cleanDenaturalizedDataset(dcmjs_es["default"].data.DicomMetaDictionary.denaturalizeDataset(m), {
|
|
524
|
+
StudyInstanceUID: m.StudyInstanceUID,
|
|
525
|
+
SeriesInstanceUID: m.SeriesInstanceUID,
|
|
526
|
+
dataSourceConfig: this.props.dataSource.getConfig()
|
|
527
|
+
});
|
|
528
|
+
if (!inst['00480105']) {
|
|
529
|
+
// Optical Path Sequence, no OpticalPathIdentifier?
|
|
530
|
+
// NOTE: this is actually a not-well formatted DICOM VL Whole Slide Microscopy Image.
|
|
531
|
+
inst['00480105'] = {
|
|
532
|
+
vr: 'SQ',
|
|
533
|
+
Value: [{
|
|
534
|
+
'00480106': {
|
|
535
|
+
vr: 'SH',
|
|
536
|
+
Value: ['1']
|
|
537
|
+
}
|
|
538
|
+
}]
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
const image = new metadataUtils.VLWholeSlideMicroscopyImage({
|
|
542
|
+
metadata: inst
|
|
543
|
+
});
|
|
544
|
+
const imageFlavor = image.ImageType[2];
|
|
545
|
+
if (imageFlavor === 'VOLUME' || imageFlavor === 'THUMBNAIL') {
|
|
546
|
+
volumeImages.push(image);
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
// format metadata for microscopy-viewer
|
|
551
|
+
const options = {
|
|
552
|
+
client,
|
|
553
|
+
metadata: volumeImages,
|
|
554
|
+
retrieveRendered: false,
|
|
555
|
+
controls: ['overview', 'position']
|
|
556
|
+
};
|
|
557
|
+
this.viewer = new microscopyViewer(options);
|
|
558
|
+
if (this.overlayElement && this.overlayElement.current && this.viewer.addViewportOverlay) {
|
|
559
|
+
this.viewer.addViewportOverlay({
|
|
560
|
+
element: this.overlayElement.current,
|
|
561
|
+
coordinates: [0, 0],
|
|
562
|
+
// TODO: dicom-microscopy-viewer documentation says this can be false to be automatically, but it is not.
|
|
563
|
+
navigate: true,
|
|
564
|
+
className: 'OpenLayersOverlay'
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
this.viewer.render({
|
|
568
|
+
container
|
|
569
|
+
});
|
|
570
|
+
const {
|
|
571
|
+
StudyInstanceUID,
|
|
572
|
+
SeriesInstanceUID
|
|
573
|
+
} = displaySet;
|
|
574
|
+
this.managedViewer = this.microscopyService.addViewer(this.viewer, this.props.viewportIndex, container, StudyInstanceUID, SeriesInstanceUID);
|
|
575
|
+
this.managedViewer.addContextMenuCallback(event => {
|
|
576
|
+
// TODO: refactor this after Bill's changes on ContextMenu feature get merged
|
|
577
|
+
// const roiAnnotationNearBy = this.getNearbyROI(event);
|
|
578
|
+
});
|
|
579
|
+
};
|
|
580
|
+
this.microscopyService.clearAnnotations();
|
|
581
|
+
let smDisplaySet = displaySet;
|
|
582
|
+
if (displaySet.Modality === 'SR') {
|
|
583
|
+
// for SR displaySet, let's load the actual image displaySet
|
|
584
|
+
smDisplaySet = displaySet.getSourceDisplaySet();
|
|
585
|
+
}
|
|
586
|
+
console.log('Loading viewer metadata', smDisplaySet);
|
|
587
|
+
await loadViewer(smDisplaySet.others);
|
|
588
|
+
if (displaySet.Modality === 'SR') {
|
|
589
|
+
displaySet.load(smDisplaySet);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
componentDidMount() {
|
|
593
|
+
const {
|
|
594
|
+
displaySets,
|
|
595
|
+
viewportIndex
|
|
596
|
+
} = this.props;
|
|
597
|
+
const displaySet = displaySets[viewportIndex];
|
|
598
|
+
this.installOpenLayersRenderer(this.container.current, displaySet).then(() => {
|
|
599
|
+
this.setState({
|
|
600
|
+
isLoaded: true
|
|
601
|
+
});
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
componentDidUpdate(prevProps, prevState, snapshot) {
|
|
605
|
+
if (this.managedViewer && prevProps.displaySets !== this.props.displaySets) {
|
|
606
|
+
const {
|
|
607
|
+
displaySets
|
|
608
|
+
} = this.props;
|
|
609
|
+
const displaySet = displaySets[0];
|
|
610
|
+
this.microscopyService.clearAnnotations();
|
|
611
|
+
|
|
612
|
+
// loading SR
|
|
613
|
+
if (displaySet.Modality === 'SR') {
|
|
614
|
+
const referencedDisplaySet = displaySet.getSourceDisplaySet();
|
|
615
|
+
displaySet.load(referencedDisplaySet);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
componentWillUnmount() {
|
|
620
|
+
this.microscopyService.removeViewer(this.viewer);
|
|
621
|
+
}
|
|
622
|
+
render() {
|
|
623
|
+
const style = {
|
|
624
|
+
width: '100%',
|
|
625
|
+
height: '100%'
|
|
626
|
+
};
|
|
627
|
+
const displaySet = this.props.displaySets[0];
|
|
628
|
+
const firstInstance = displaySet.firstInstance || displaySet.instance;
|
|
629
|
+
return /*#__PURE__*/react.createElement("div", {
|
|
630
|
+
className: 'DicomMicroscopyViewer',
|
|
631
|
+
style: style,
|
|
632
|
+
onClick: this.setViewportActiveHandler
|
|
633
|
+
}, /*#__PURE__*/react.createElement("div", {
|
|
634
|
+
style: {
|
|
635
|
+
...style,
|
|
636
|
+
display: 'none'
|
|
637
|
+
}
|
|
638
|
+
}, /*#__PURE__*/react.createElement("div", {
|
|
639
|
+
style: {
|
|
640
|
+
...style
|
|
641
|
+
},
|
|
642
|
+
ref: this.overlayElement
|
|
643
|
+
}, /*#__PURE__*/react.createElement("div", {
|
|
644
|
+
style: {
|
|
645
|
+
position: 'relative',
|
|
646
|
+
height: '100%',
|
|
647
|
+
width: '100%'
|
|
648
|
+
}
|
|
649
|
+
}, displaySet && firstInstance.imageId && /*#__PURE__*/react.createElement(ViewportOverlay, {
|
|
650
|
+
displaySet: displaySet,
|
|
651
|
+
instance: displaySet.instance,
|
|
652
|
+
metadata: displaySet.metadata
|
|
653
|
+
})))), index_esm/* default */.ZP && /*#__PURE__*/react.createElement(index_esm/* default */.ZP, {
|
|
654
|
+
handleWidth: true,
|
|
655
|
+
handleHeight: true,
|
|
656
|
+
onResize: this.onWindowResize
|
|
657
|
+
}), this.state.error ? /*#__PURE__*/react.createElement("h2", null, JSON.stringify(this.state.error)) : /*#__PURE__*/react.createElement("div", {
|
|
658
|
+
style: style,
|
|
659
|
+
ref: this.container
|
|
660
|
+
}), this.state.isLoaded ? null : /*#__PURE__*/react.createElement(src/* LoadingIndicatorProgress */.LE, {
|
|
661
|
+
className: 'w-full h-full bg-black'
|
|
662
|
+
}));
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
DicomMicroscopyViewport.propTypes = {
|
|
666
|
+
viewportData: (prop_types_default()).object,
|
|
667
|
+
activeViewportIndex: (prop_types_default()).number,
|
|
668
|
+
setViewportActive: (prop_types_default()).func,
|
|
669
|
+
// props from OHIF Viewport Grid
|
|
670
|
+
displaySets: (prop_types_default()).array,
|
|
671
|
+
viewportIndex: (prop_types_default()).number,
|
|
672
|
+
viewportLabel: (prop_types_default()).string,
|
|
673
|
+
dataSource: (prop_types_default()).object,
|
|
674
|
+
viewportOptions: (prop_types_default()).object,
|
|
675
|
+
displaySetOptions: (prop_types_default()).array,
|
|
676
|
+
// other props from wrapping component
|
|
677
|
+
servicesManager: (prop_types_default()).object,
|
|
678
|
+
extensionManager: (prop_types_default()).object,
|
|
679
|
+
commandsManager: (prop_types_default()).object
|
|
680
|
+
};
|
|
681
|
+
/* harmony default export */ const src_DicomMicroscopyViewport = (DicomMicroscopyViewport);
|
|
682
|
+
|
|
683
|
+
/***/ })
|
|
684
|
+
|
|
685
|
+
}]);
|