@cornerstonejs/adapters 0.6.0 → 0.101.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.
|
@@ -3,19 +3,43 @@ import ndarray from 'ndarray';
|
|
|
3
3
|
import cloneDeep from 'lodash.clonedeep';
|
|
4
4
|
import { vec3 } from 'gl-matrix';
|
|
5
5
|
|
|
6
|
+
function _iterableToArrayLimit(arr, i) {
|
|
7
|
+
var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"];
|
|
8
|
+
if (null != _i) {
|
|
9
|
+
var _s,
|
|
10
|
+
_e,
|
|
11
|
+
_x,
|
|
12
|
+
_r,
|
|
13
|
+
_arr = [],
|
|
14
|
+
_n = !0,
|
|
15
|
+
_d = !1;
|
|
16
|
+
try {
|
|
17
|
+
if (_x = (_i = _i.call(arr)).next, 0 === i) {
|
|
18
|
+
if (Object(_i) !== _i) return;
|
|
19
|
+
_n = !1;
|
|
20
|
+
} else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0);
|
|
21
|
+
} catch (err) {
|
|
22
|
+
_d = !0, _e = err;
|
|
23
|
+
} finally {
|
|
24
|
+
try {
|
|
25
|
+
if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return;
|
|
26
|
+
} finally {
|
|
27
|
+
if (_d) throw _e;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return _arr;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
6
33
|
function ownKeys(object, enumerableOnly) {
|
|
7
34
|
var keys = Object.keys(object);
|
|
8
|
-
|
|
9
35
|
if (Object.getOwnPropertySymbols) {
|
|
10
36
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
11
37
|
enumerableOnly && (symbols = symbols.filter(function (sym) {
|
|
12
38
|
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
13
39
|
})), keys.push.apply(keys, symbols);
|
|
14
40
|
}
|
|
15
|
-
|
|
16
41
|
return keys;
|
|
17
42
|
}
|
|
18
|
-
|
|
19
43
|
function _objectSpread2(target) {
|
|
20
44
|
for (var i = 1; i < arguments.length; i++) {
|
|
21
45
|
var source = null != arguments[i] ? arguments[i] : {};
|
|
@@ -25,26 +49,22 @@ function _objectSpread2(target) {
|
|
|
25
49
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
26
50
|
});
|
|
27
51
|
}
|
|
28
|
-
|
|
29
52
|
return target;
|
|
30
53
|
}
|
|
31
|
-
|
|
32
54
|
function _classCallCheck(instance, Constructor) {
|
|
33
55
|
if (!(instance instanceof Constructor)) {
|
|
34
56
|
throw new TypeError("Cannot call a class as a function");
|
|
35
57
|
}
|
|
36
58
|
}
|
|
37
|
-
|
|
38
59
|
function _defineProperties(target, props) {
|
|
39
60
|
for (var i = 0; i < props.length; i++) {
|
|
40
61
|
var descriptor = props[i];
|
|
41
62
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
42
63
|
descriptor.configurable = true;
|
|
43
64
|
if ("value" in descriptor) descriptor.writable = true;
|
|
44
|
-
Object.defineProperty(target, descriptor.key, descriptor);
|
|
65
|
+
Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
|
|
45
66
|
}
|
|
46
67
|
}
|
|
47
|
-
|
|
48
68
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
49
69
|
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
50
70
|
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
@@ -53,8 +73,8 @@ function _createClass(Constructor, protoProps, staticProps) {
|
|
|
53
73
|
});
|
|
54
74
|
return Constructor;
|
|
55
75
|
}
|
|
56
|
-
|
|
57
76
|
function _defineProperty(obj, key, value) {
|
|
77
|
+
key = _toPropertyKey(key);
|
|
58
78
|
if (key in obj) {
|
|
59
79
|
Object.defineProperty(obj, key, {
|
|
60
80
|
value: value,
|
|
@@ -65,60 +85,23 @@ function _defineProperty(obj, key, value) {
|
|
|
65
85
|
} else {
|
|
66
86
|
obj[key] = value;
|
|
67
87
|
}
|
|
68
|
-
|
|
69
88
|
return obj;
|
|
70
89
|
}
|
|
71
|
-
|
|
72
90
|
function _slicedToArray(arr, i) {
|
|
73
91
|
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
|
|
74
92
|
}
|
|
75
|
-
|
|
76
93
|
function _toConsumableArray(arr) {
|
|
77
94
|
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
|
78
95
|
}
|
|
79
|
-
|
|
80
96
|
function _arrayWithoutHoles(arr) {
|
|
81
97
|
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
|
|
82
98
|
}
|
|
83
|
-
|
|
84
99
|
function _arrayWithHoles(arr) {
|
|
85
100
|
if (Array.isArray(arr)) return arr;
|
|
86
101
|
}
|
|
87
|
-
|
|
88
102
|
function _iterableToArray(iter) {
|
|
89
103
|
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
90
104
|
}
|
|
91
|
-
|
|
92
|
-
function _iterableToArrayLimit(arr, i) {
|
|
93
|
-
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
94
|
-
|
|
95
|
-
if (_i == null) return;
|
|
96
|
-
var _arr = [];
|
|
97
|
-
var _n = true;
|
|
98
|
-
var _d = false;
|
|
99
|
-
|
|
100
|
-
var _s, _e;
|
|
101
|
-
|
|
102
|
-
try {
|
|
103
|
-
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
|
|
104
|
-
_arr.push(_s.value);
|
|
105
|
-
|
|
106
|
-
if (i && _arr.length === i) break;
|
|
107
|
-
}
|
|
108
|
-
} catch (err) {
|
|
109
|
-
_d = true;
|
|
110
|
-
_e = err;
|
|
111
|
-
} finally {
|
|
112
|
-
try {
|
|
113
|
-
if (!_n && _i["return"] != null) _i["return"]();
|
|
114
|
-
} finally {
|
|
115
|
-
if (_d) throw _e;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return _arr;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
105
|
function _unsupportedIterableToArray(o, minLen) {
|
|
123
106
|
if (!o) return;
|
|
124
107
|
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
@@ -127,33 +110,24 @@ function _unsupportedIterableToArray(o, minLen) {
|
|
|
127
110
|
if (n === "Map" || n === "Set") return Array.from(o);
|
|
128
111
|
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
129
112
|
}
|
|
130
|
-
|
|
131
113
|
function _arrayLikeToArray(arr, len) {
|
|
132
114
|
if (len == null || len > arr.length) len = arr.length;
|
|
133
|
-
|
|
134
115
|
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
135
|
-
|
|
136
116
|
return arr2;
|
|
137
117
|
}
|
|
138
|
-
|
|
139
118
|
function _nonIterableSpread() {
|
|
140
119
|
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
141
120
|
}
|
|
142
|
-
|
|
143
121
|
function _nonIterableRest() {
|
|
144
122
|
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
145
123
|
}
|
|
146
|
-
|
|
147
124
|
function _createForOfIteratorHelper(o, allowArrayLike) {
|
|
148
125
|
var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
|
|
149
|
-
|
|
150
126
|
if (!it) {
|
|
151
127
|
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
|
|
152
128
|
if (it) o = it;
|
|
153
129
|
var i = 0;
|
|
154
|
-
|
|
155
130
|
var F = function () {};
|
|
156
|
-
|
|
157
131
|
return {
|
|
158
132
|
s: F,
|
|
159
133
|
n: function () {
|
|
@@ -171,13 +145,11 @@ function _createForOfIteratorHelper(o, allowArrayLike) {
|
|
|
171
145
|
f: F
|
|
172
146
|
};
|
|
173
147
|
}
|
|
174
|
-
|
|
175
148
|
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
176
149
|
}
|
|
177
|
-
|
|
178
150
|
var normalCompletion = true,
|
|
179
|
-
|
|
180
|
-
|
|
151
|
+
didErr = false,
|
|
152
|
+
err;
|
|
181
153
|
return {
|
|
182
154
|
s: function () {
|
|
183
155
|
it = it.call(o);
|
|
@@ -200,11 +172,24 @@ function _createForOfIteratorHelper(o, allowArrayLike) {
|
|
|
200
172
|
}
|
|
201
173
|
};
|
|
202
174
|
}
|
|
175
|
+
function _toPrimitive(input, hint) {
|
|
176
|
+
if (typeof input !== "object" || input === null) return input;
|
|
177
|
+
var prim = input[Symbol.toPrimitive];
|
|
178
|
+
if (prim !== undefined) {
|
|
179
|
+
var res = prim.call(input, hint || "default");
|
|
180
|
+
if (typeof res !== "object") return res;
|
|
181
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
182
|
+
}
|
|
183
|
+
return (hint === "string" ? String : Number)(input);
|
|
184
|
+
}
|
|
185
|
+
function _toPropertyKey(arg) {
|
|
186
|
+
var key = _toPrimitive(arg, "string");
|
|
187
|
+
return typeof key === "symbol" ? key : String(key);
|
|
188
|
+
}
|
|
203
189
|
|
|
204
190
|
var toArray = function toArray(x) {
|
|
205
191
|
return Array.isArray(x) ? x : [x];
|
|
206
192
|
};
|
|
207
|
-
|
|
208
193
|
var codeMeaningEquals = function codeMeaningEquals(codeMeaningName) {
|
|
209
194
|
return function (contentItem) {
|
|
210
195
|
return contentItem.ConceptNameCodeSequence.CodeMeaning === codeMeaningName;
|
|
@@ -212,11 +197,11 @@ var codeMeaningEquals = function codeMeaningEquals(codeMeaningName) {
|
|
|
212
197
|
};
|
|
213
198
|
|
|
214
199
|
var TID1500$1 = utilities.TID1500,
|
|
215
|
-
|
|
200
|
+
addAccessors$1 = utilities.addAccessors;
|
|
216
201
|
var StructuredReport$1 = derivations.StructuredReport;
|
|
217
202
|
var Normalizer$3 = normalizers.Normalizer;
|
|
218
203
|
var TID1500MeasurementReport$1 = TID1500$1.TID1500MeasurementReport,
|
|
219
|
-
|
|
204
|
+
TID1501MeasurementGroup$1 = TID1500$1.TID1501MeasurementGroup;
|
|
220
205
|
var DicomMetaDictionary$3 = data.DicomMetaDictionary;
|
|
221
206
|
var FINDING$2 = {
|
|
222
207
|
CodingSchemeDesignator: "DCM",
|
|
@@ -230,43 +215,37 @@ var FINDING_SITE_OLD$1 = {
|
|
|
230
215
|
CodingSchemeDesignator: "SRT",
|
|
231
216
|
CodeValue: "G-C0E3"
|
|
232
217
|
};
|
|
233
|
-
|
|
234
218
|
var codeValueMatch$1 = function codeValueMatch(group, code, oldCode) {
|
|
235
219
|
var ConceptNameCodeSequence = group.ConceptNameCodeSequence;
|
|
236
220
|
if (!ConceptNameCodeSequence) return;
|
|
237
221
|
var CodingSchemeDesignator = ConceptNameCodeSequence.CodingSchemeDesignator,
|
|
238
|
-
|
|
222
|
+
CodeValue = ConceptNameCodeSequence.CodeValue;
|
|
239
223
|
return CodingSchemeDesignator == code.CodingSchemeDesignator && CodeValue == code.CodeValue || oldCode && CodingSchemeDesignator == oldCode.CodingSchemeDesignator && CodeValue == oldCode.CodeValue;
|
|
240
224
|
};
|
|
241
|
-
|
|
242
225
|
function getTID300ContentItem$1(tool, toolType, ReferencedSOPSequence, toolClass) {
|
|
243
226
|
var args = toolClass.getTID300RepresentationArguments(tool);
|
|
244
227
|
args.ReferencedSOPSequence = ReferencedSOPSequence;
|
|
245
228
|
var TID300Measurement = new toolClass.TID300Representation(args);
|
|
246
229
|
return TID300Measurement;
|
|
247
230
|
}
|
|
248
|
-
|
|
249
231
|
function getMeasurementGroup$1(toolType, toolData, ReferencedSOPSequence) {
|
|
250
232
|
var toolTypeData = toolData[toolType];
|
|
251
233
|
var toolClass = MeasurementReport$1.CORNERSTONE_TOOL_CLASSES_BY_TOOL_TYPE[toolType];
|
|
252
|
-
|
|
253
234
|
if (!toolTypeData || !toolTypeData.data || !toolTypeData.data.length || !toolClass) {
|
|
254
235
|
return;
|
|
255
|
-
}
|
|
256
|
-
// for this tool
|
|
257
|
-
|
|
236
|
+
}
|
|
258
237
|
|
|
238
|
+
// Loop through the array of tool instances
|
|
239
|
+
// for this tool
|
|
259
240
|
var Measurements = toolTypeData.data.map(function (tool) {
|
|
260
241
|
return getTID300ContentItem$1(tool, toolType, ReferencedSOPSequence, toolClass);
|
|
261
242
|
});
|
|
262
243
|
return new TID1501MeasurementGroup$1(Measurements);
|
|
263
244
|
}
|
|
264
|
-
|
|
265
245
|
var MeasurementReport$1 = /*#__PURE__*/function () {
|
|
266
246
|
function MeasurementReport() {
|
|
267
247
|
_classCallCheck(this, MeasurementReport);
|
|
268
248
|
}
|
|
269
|
-
|
|
270
249
|
_createClass(MeasurementReport, null, [{
|
|
271
250
|
key: "getSetupMeasurementData",
|
|
272
251
|
value: function getSetupMeasurementData(MeasurementGroup) {
|
|
@@ -286,7 +265,7 @@ var MeasurementReport$1 = /*#__PURE__*/function () {
|
|
|
286
265
|
});
|
|
287
266
|
var ReferencedSOPSequence = SCOORDGroup.ContentSequence.ReferencedSOPSequence;
|
|
288
267
|
var ReferencedSOPInstanceUID = ReferencedSOPSequence.ReferencedSOPInstanceUID,
|
|
289
|
-
|
|
268
|
+
ReferencedFrameNumber = ReferencedSOPSequence.ReferencedFrameNumber;
|
|
290
269
|
var defaultState = {
|
|
291
270
|
sopInstanceUid: ReferencedSOPInstanceUID,
|
|
292
271
|
frameIndex: ReferencedFrameNumber || 1,
|
|
@@ -296,17 +275,13 @@ var MeasurementReport$1 = /*#__PURE__*/function () {
|
|
|
296
275
|
return addAccessors$1(fsg.ConceptCodeSequence);
|
|
297
276
|
})
|
|
298
277
|
};
|
|
299
|
-
|
|
300
278
|
if (defaultState.finding) {
|
|
301
279
|
defaultState.description = defaultState.finding.CodeMeaning;
|
|
302
280
|
}
|
|
303
|
-
|
|
304
281
|
var findingSite = defaultState.findingSites && defaultState.findingSites[0];
|
|
305
|
-
|
|
306
282
|
if (findingSite) {
|
|
307
283
|
defaultState.location = findingSite[0] && findingSite[0].CodeMeaning || findingSite.CodeMeaning;
|
|
308
284
|
}
|
|
309
|
-
|
|
310
285
|
return {
|
|
311
286
|
defaultState: defaultState,
|
|
312
287
|
findingGroup: findingGroup,
|
|
@@ -323,28 +298,30 @@ var MeasurementReport$1 = /*#__PURE__*/function () {
|
|
|
323
298
|
value: function generateReport(toolState, metadataProvider, options) {
|
|
324
299
|
// ToolState for array of imageIDs to a Report
|
|
325
300
|
// Assume Cornerstone metadata provider has access to Study / Series / Sop Instance UID
|
|
301
|
+
|
|
326
302
|
var allMeasurementGroups = [];
|
|
327
303
|
var firstImageId = Object.keys(toolState)[0];
|
|
328
|
-
|
|
329
304
|
if (!firstImageId) {
|
|
330
305
|
throw new Error("No measurements provided.");
|
|
331
306
|
}
|
|
307
|
+
|
|
332
308
|
/* Patient ID
|
|
333
309
|
Warning - Missing attribute or value that would be needed to build DICOMDIR - Patient ID
|
|
334
310
|
Warning - Missing attribute or value that would be needed to build DICOMDIR - Study Date
|
|
335
311
|
Warning - Missing attribute or value that would be needed to build DICOMDIR - Study Time
|
|
336
312
|
Warning - Missing attribute or value that would be needed to build DICOMDIR - Study ID
|
|
337
313
|
*/
|
|
314
|
+
var generalSeriesModule = metadataProvider.get("generalSeriesModule", firstImageId);
|
|
338
315
|
|
|
316
|
+
//const sopCommonModule = metadataProvider.get('sopCommonModule', firstImageId);
|
|
339
317
|
|
|
340
|
-
var generalSeriesModule = metadataProvider.get("generalSeriesModule", firstImageId); //const sopCommonModule = metadataProvider.get('sopCommonModule', firstImageId);
|
|
341
318
|
// NOTE: We are getting the Series and Study UIDs from the first imageId of the toolState
|
|
342
319
|
// which means that if the toolState is for multiple series, the report will have the incorrect
|
|
343
320
|
// SeriesInstanceUIDs
|
|
344
|
-
|
|
345
321
|
var studyInstanceUID = generalSeriesModule.studyInstanceUID,
|
|
346
|
-
|
|
322
|
+
seriesInstanceUID = generalSeriesModule.seriesInstanceUID;
|
|
347
323
|
|
|
324
|
+
// Loop through each image in the toolData
|
|
348
325
|
Object.keys(toolState).forEach(function (imageId) {
|
|
349
326
|
var sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
|
|
350
327
|
var frameNumber = metadataProvider.get("frameNumber", imageId);
|
|
@@ -354,38 +331,36 @@ var MeasurementReport$1 = /*#__PURE__*/function () {
|
|
|
354
331
|
ReferencedSOPClassUID: sopCommonModule.sopClassUID,
|
|
355
332
|
ReferencedSOPInstanceUID: sopCommonModule.sopInstanceUID
|
|
356
333
|
};
|
|
357
|
-
|
|
358
334
|
if (Normalizer$3.isMultiframeSOPClassUID(sopCommonModule.sopClassUID)) {
|
|
359
335
|
ReferencedSOPSequence.ReferencedFrameNumber = frameNumber;
|
|
360
|
-
}
|
|
361
|
-
|
|
336
|
+
}
|
|
362
337
|
|
|
338
|
+
// Loop through each tool type for the image
|
|
363
339
|
var measurementGroups = [];
|
|
364
340
|
toolTypes.forEach(function (toolType) {
|
|
365
341
|
var group = getMeasurementGroup$1(toolType, toolData, ReferencedSOPSequence);
|
|
366
|
-
|
|
367
342
|
if (group) {
|
|
368
343
|
measurementGroups.push(group);
|
|
369
344
|
}
|
|
370
345
|
});
|
|
371
346
|
allMeasurementGroups = allMeasurementGroups.concat(measurementGroups);
|
|
372
347
|
});
|
|
373
|
-
|
|
374
348
|
var _MeasurementReport = new TID1500MeasurementReport$1({
|
|
375
349
|
TID1501MeasurementGroups: allMeasurementGroups
|
|
376
|
-
}, options);
|
|
350
|
+
}, options);
|
|
351
|
+
|
|
352
|
+
// TODO: what is the correct metaheader
|
|
377
353
|
// http://dicom.nema.org/medical/Dicom/current/output/chtml/part10/chapter_7.html
|
|
378
354
|
// TODO: move meta creation to happen in derivations.js
|
|
379
|
-
|
|
380
|
-
|
|
381
355
|
var fileMetaInformationVersionArray = new Uint8Array(2);
|
|
382
356
|
fileMetaInformationVersionArray[1] = 1;
|
|
383
357
|
var derivationSourceDataset = {
|
|
384
358
|
StudyInstanceUID: studyInstanceUID,
|
|
385
|
-
SeriesInstanceUID: seriesInstanceUID
|
|
359
|
+
SeriesInstanceUID: seriesInstanceUID
|
|
360
|
+
//SOPInstanceUID: sopInstanceUID, // TODO: Necessary?
|
|
386
361
|
//SOPClassUID: sopClassUID,
|
|
387
|
-
|
|
388
362
|
};
|
|
363
|
+
|
|
389
364
|
var _meta = {
|
|
390
365
|
FileMetaInformationVersion: {
|
|
391
366
|
Value: [fileMetaInformationVersionArray.buffer],
|
|
@@ -413,14 +388,14 @@ var MeasurementReport$1 = /*#__PURE__*/function () {
|
|
|
413
388
|
derivationSourceDataset._meta = _meta;
|
|
414
389
|
derivationSourceDataset._vrMap = _vrMap;
|
|
415
390
|
var report = new StructuredReport$1([derivationSourceDataset]);
|
|
391
|
+
var contentItem = _MeasurementReport.contentItem(derivationSourceDataset);
|
|
416
392
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
393
|
+
// Merge the derived dataset with the content from the Measurement Report
|
|
420
394
|
report.dataset = Object.assign(report.dataset, contentItem);
|
|
421
395
|
report.dataset._meta = _meta;
|
|
422
396
|
return report;
|
|
423
397
|
}
|
|
398
|
+
|
|
424
399
|
/**
|
|
425
400
|
* Generate Cornerstone tool state from dataset
|
|
426
401
|
* @param {object} dataset dataset
|
|
@@ -428,25 +403,25 @@ var MeasurementReport$1 = /*#__PURE__*/function () {
|
|
|
428
403
|
* @param {function} hooks.getToolClass Function to map dataset to a tool class
|
|
429
404
|
* @returns
|
|
430
405
|
*/
|
|
431
|
-
|
|
432
406
|
}, {
|
|
433
407
|
key: "generateToolState",
|
|
434
408
|
value: function generateToolState(dataset) {
|
|
435
409
|
var hooks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
436
|
-
|
|
437
410
|
// For now, bail out if the dataset is not a TID1500 SR with length measurements
|
|
438
411
|
if (dataset.ContentTemplateSequence.TemplateIdentifier !== "1500") {
|
|
439
412
|
throw new Error("This package can currently only interpret DICOM SR TID 1500");
|
|
440
413
|
}
|
|
441
|
-
|
|
442
414
|
var REPORT = "Imaging Measurements";
|
|
443
415
|
var GROUP = "Measurement Group";
|
|
444
|
-
var TRACKING_IDENTIFIER = "Tracking Identifier";
|
|
416
|
+
var TRACKING_IDENTIFIER = "Tracking Identifier";
|
|
445
417
|
|
|
446
|
-
|
|
418
|
+
// Identify the Imaging Measurements
|
|
419
|
+
var imagingMeasurementContent = toArray(dataset.ContentSequence).find(codeMeaningEquals(REPORT));
|
|
447
420
|
|
|
448
|
-
|
|
421
|
+
// Retrieve the Measurements themselves
|
|
422
|
+
var measurementGroups = toArray(imagingMeasurementContent.ContentSequence).filter(codeMeaningEquals(GROUP));
|
|
449
423
|
|
|
424
|
+
// For each of the supported measurement types, compute the measurement data
|
|
450
425
|
var measurementData = {};
|
|
451
426
|
var cornerstoneToolClasses = MeasurementReport.CORNERSTONE_TOOL_CLASSES_BY_UTILITY_TYPE;
|
|
452
427
|
var registeredToolClasses = [];
|
|
@@ -463,16 +438,16 @@ var MeasurementReport$1 = /*#__PURE__*/function () {
|
|
|
463
438
|
var toolClass = hooks.getToolClass ? hooks.getToolClass(measurementGroup, dataset, registeredToolClasses) : registeredToolClasses.find(function (tc) {
|
|
464
439
|
return tc.isValidCornerstoneTrackingIdentifier(TrackingIdentifierValue);
|
|
465
440
|
});
|
|
466
|
-
|
|
467
441
|
if (toolClass) {
|
|
468
442
|
var measurement = toolClass.getMeasurementData(measurementGroup);
|
|
469
443
|
console.log("=== ".concat(toolClass.toolType, " ==="));
|
|
470
444
|
console.log(measurement);
|
|
471
445
|
measurementData[toolClass.toolType].push(measurement);
|
|
472
446
|
}
|
|
473
|
-
});
|
|
474
|
-
// That is up to the consumer to derive from the SOPInstanceUIDs.
|
|
447
|
+
});
|
|
475
448
|
|
|
449
|
+
// NOTE: There is no way of knowing the cornerstone imageIds as that could be anything.
|
|
450
|
+
// That is up to the consumer to derive from the SOPInstanceUIDs.
|
|
476
451
|
return measurementData;
|
|
477
452
|
}
|
|
478
453
|
}, {
|
|
@@ -483,7 +458,6 @@ var MeasurementReport$1 = /*#__PURE__*/function () {
|
|
|
483
458
|
MeasurementReport.MEASUREMENT_BY_TOOLTYPE[toolClass.toolType] = toolClass.utilityToolType;
|
|
484
459
|
}
|
|
485
460
|
}]);
|
|
486
|
-
|
|
487
461
|
return MeasurementReport;
|
|
488
462
|
}();
|
|
489
463
|
MeasurementReport$1.MEASUREMENT_BY_TOOLTYPE = {};
|
|
@@ -494,21 +468,19 @@ var CORNERSTONE_4_TAG = "cornerstoneTools@^4.0.0";
|
|
|
494
468
|
|
|
495
469
|
var TID300Length$1 = utilities.TID300.Length;
|
|
496
470
|
var LENGTH$1 = "Length";
|
|
497
|
-
|
|
498
471
|
var Length$1 = /*#__PURE__*/function () {
|
|
499
472
|
function Length() {
|
|
500
473
|
_classCallCheck(this, Length);
|
|
501
474
|
}
|
|
502
|
-
|
|
503
475
|
_createClass(Length, null, [{
|
|
504
476
|
key: "getMeasurementData",
|
|
505
|
-
value:
|
|
477
|
+
value:
|
|
478
|
+
// TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport.
|
|
506
479
|
function getMeasurementData(MeasurementGroup) {
|
|
507
480
|
var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
481
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
482
|
+
NUMGroup = _MeasurementReport$ge.NUMGroup,
|
|
483
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup;
|
|
512
484
|
var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
|
|
513
485
|
length: NUMGroup.MeasuredValueSequence.NumericValue,
|
|
514
486
|
toolType: Length.toolType,
|
|
@@ -524,9 +496,7 @@ var Length$1 = /*#__PURE__*/function () {
|
|
|
524
496
|
}
|
|
525
497
|
}
|
|
526
498
|
});
|
|
527
|
-
|
|
528
499
|
var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 4);
|
|
529
|
-
|
|
530
500
|
state.handles.start.x = _SCOORDGroup$GraphicD[0];
|
|
531
501
|
state.handles.start.y = _SCOORDGroup$GraphicD[1];
|
|
532
502
|
state.handles.end.x = _SCOORDGroup$GraphicD[2];
|
|
@@ -537,8 +507,8 @@ var Length$1 = /*#__PURE__*/function () {
|
|
|
537
507
|
key: "getTID300RepresentationArguments",
|
|
538
508
|
value: function getTID300RepresentationArguments(tool) {
|
|
539
509
|
var handles = tool.handles,
|
|
540
|
-
|
|
541
|
-
|
|
510
|
+
finding = tool.finding,
|
|
511
|
+
findingSites = tool.findingSites;
|
|
542
512
|
var point1 = handles.start;
|
|
543
513
|
var point2 = handles.end;
|
|
544
514
|
var distance = tool.length;
|
|
@@ -553,48 +523,38 @@ var Length$1 = /*#__PURE__*/function () {
|
|
|
553
523
|
};
|
|
554
524
|
}
|
|
555
525
|
}]);
|
|
556
|
-
|
|
557
526
|
return Length;
|
|
558
527
|
}();
|
|
559
|
-
|
|
560
528
|
Length$1.toolType = LENGTH$1;
|
|
561
529
|
Length$1.utilityToolType = LENGTH$1;
|
|
562
530
|
Length$1.TID300Representation = TID300Length$1;
|
|
563
|
-
|
|
564
531
|
Length$1.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
565
532
|
if (!TrackingIdentifier.includes(":")) {
|
|
566
533
|
return false;
|
|
567
534
|
}
|
|
568
|
-
|
|
569
535
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
536
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
537
|
+
cornerstone4Tag = _TrackingIdentifier$s2[0],
|
|
538
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
574
539
|
if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
|
|
575
540
|
return false;
|
|
576
541
|
}
|
|
577
|
-
|
|
578
542
|
return toolType === LENGTH$1;
|
|
579
543
|
};
|
|
580
|
-
|
|
581
544
|
MeasurementReport$1.registerTool(Length$1);
|
|
582
545
|
|
|
583
546
|
var TID300Polyline$3 = utilities.TID300.Polyline;
|
|
584
|
-
|
|
585
547
|
var FreehandRoi = /*#__PURE__*/function () {
|
|
586
548
|
function FreehandRoi() {
|
|
587
549
|
_classCallCheck(this, FreehandRoi);
|
|
588
550
|
}
|
|
589
|
-
|
|
590
551
|
_createClass(FreehandRoi, null, [{
|
|
591
552
|
key: "getMeasurementData",
|
|
592
553
|
value: function getMeasurementData(MeasurementGroup) {
|
|
593
554
|
var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
555
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
556
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup,
|
|
557
|
+
NUMGroup = _MeasurementReport$ge.NUMGroup;
|
|
598
558
|
var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
|
|
599
559
|
toolType: FreehandRoi.toolType,
|
|
600
560
|
handles: {
|
|
@@ -614,31 +574,28 @@ var FreehandRoi = /*#__PURE__*/function () {
|
|
|
614
574
|
color: undefined,
|
|
615
575
|
invalidated: true
|
|
616
576
|
});
|
|
617
|
-
|
|
618
577
|
var GraphicData = SCOORDGroup.GraphicData;
|
|
619
|
-
|
|
620
578
|
for (var i = 0; i < GraphicData.length; i += 2) {
|
|
621
579
|
state.handles.points.push({
|
|
622
580
|
x: GraphicData[i],
|
|
623
581
|
y: GraphicData[i + 1]
|
|
624
582
|
});
|
|
625
583
|
}
|
|
626
|
-
|
|
627
584
|
return state;
|
|
628
585
|
}
|
|
629
586
|
}, {
|
|
630
587
|
key: "getTID300RepresentationArguments",
|
|
631
588
|
value: function getTID300RepresentationArguments(tool) {
|
|
632
589
|
var handles = tool.handles,
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
590
|
+
finding = tool.finding,
|
|
591
|
+
findingSites = tool.findingSites,
|
|
592
|
+
_tool$cachedStats = tool.cachedStats,
|
|
593
|
+
cachedStats = _tool$cachedStats === void 0 ? {} : _tool$cachedStats;
|
|
637
594
|
var points = handles.points;
|
|
638
595
|
var _cachedStats$area = cachedStats.area,
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
596
|
+
area = _cachedStats$area === void 0 ? 0 : _cachedStats$area,
|
|
597
|
+
_cachedStats$perimete = cachedStats.perimeter,
|
|
598
|
+
perimeter = _cachedStats$perimete === void 0 ? 0 : _cachedStats$perimete;
|
|
642
599
|
var trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:FreehandRoi";
|
|
643
600
|
return {
|
|
644
601
|
points: points,
|
|
@@ -650,31 +607,24 @@ var FreehandRoi = /*#__PURE__*/function () {
|
|
|
650
607
|
};
|
|
651
608
|
}
|
|
652
609
|
}]);
|
|
653
|
-
|
|
654
610
|
return FreehandRoi;
|
|
655
611
|
}();
|
|
656
|
-
|
|
657
612
|
FreehandRoi.toolType = "FreehandRoi";
|
|
658
613
|
FreehandRoi.utilityToolType = "FreehandRoi";
|
|
659
614
|
FreehandRoi.TID300Representation = TID300Polyline$3;
|
|
660
|
-
|
|
661
615
|
FreehandRoi.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
662
616
|
if (!TrackingIdentifier.includes(":")) {
|
|
663
617
|
return false;
|
|
664
618
|
}
|
|
665
|
-
|
|
666
619
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
620
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
621
|
+
cornerstone4Tag = _TrackingIdentifier$s2[0],
|
|
622
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
671
623
|
if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
|
|
672
624
|
return false;
|
|
673
625
|
}
|
|
674
|
-
|
|
675
626
|
return toolType === FreehandRoi.toolType;
|
|
676
627
|
};
|
|
677
|
-
|
|
678
628
|
MeasurementReport$1.registerTool(FreehandRoi);
|
|
679
629
|
|
|
680
630
|
var TID300Bidirectional$1 = utilities.TID300.Bidirectional;
|
|
@@ -683,15 +633,14 @@ var LONG_AXIS$1 = "Long Axis";
|
|
|
683
633
|
var SHORT_AXIS$1 = "Short Axis";
|
|
684
634
|
var FINDING$1 = "121071";
|
|
685
635
|
var FINDING_SITE$1 = "G-C0E3";
|
|
686
|
-
|
|
687
636
|
var Bidirectional$1 = /*#__PURE__*/function () {
|
|
688
637
|
function Bidirectional() {
|
|
689
638
|
_classCallCheck(this, Bidirectional);
|
|
690
639
|
}
|
|
691
|
-
|
|
692
640
|
_createClass(Bidirectional, null, [{
|
|
693
641
|
key: "getMeasurementData",
|
|
694
|
-
value:
|
|
642
|
+
value:
|
|
643
|
+
// TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport.
|
|
695
644
|
function getMeasurementData(MeasurementGroup) {
|
|
696
645
|
var ContentSequence = MeasurementGroup.ContentSequence;
|
|
697
646
|
var findingGroup = toArray(ContentSequence).find(function (group) {
|
|
@@ -714,7 +663,9 @@ var Bidirectional$1 = /*#__PURE__*/function () {
|
|
|
714
663
|
});
|
|
715
664
|
var ReferencedSOPSequence = longAxisSCOORDGroup.ContentSequence.ReferencedSOPSequence;
|
|
716
665
|
var ReferencedSOPInstanceUID = ReferencedSOPSequence.ReferencedSOPInstanceUID,
|
|
717
|
-
|
|
666
|
+
ReferencedFrameNumber = ReferencedSOPSequence.ReferencedFrameNumber;
|
|
667
|
+
|
|
668
|
+
// Long axis
|
|
718
669
|
|
|
719
670
|
var longestDiameter = String(longAxisNUMGroup.MeasuredValueSequence.NumericValue);
|
|
720
671
|
var shortestDiameter = String(shortAxisNUMGroup.MeasuredValueSequence.NumericValue);
|
|
@@ -793,14 +744,14 @@ var Bidirectional$1 = /*#__PURE__*/function () {
|
|
|
793
744
|
key: "getTID300RepresentationArguments",
|
|
794
745
|
value: function getTID300RepresentationArguments(tool) {
|
|
795
746
|
var _tool$handles = tool.handles,
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
747
|
+
start = _tool$handles.start,
|
|
748
|
+
end = _tool$handles.end,
|
|
749
|
+
perpendicularStart = _tool$handles.perpendicularStart,
|
|
750
|
+
perpendicularEnd = _tool$handles.perpendicularEnd;
|
|
800
751
|
var shortestDiameter = tool.shortestDiameter,
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
752
|
+
longestDiameter = tool.longestDiameter,
|
|
753
|
+
finding = tool.finding,
|
|
754
|
+
findingSites = tool.findingSites;
|
|
804
755
|
var trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:Bidirectional";
|
|
805
756
|
return {
|
|
806
757
|
longAxis: {
|
|
@@ -819,50 +770,41 @@ var Bidirectional$1 = /*#__PURE__*/function () {
|
|
|
819
770
|
};
|
|
820
771
|
}
|
|
821
772
|
}]);
|
|
822
|
-
|
|
823
773
|
return Bidirectional;
|
|
824
774
|
}();
|
|
825
|
-
|
|
826
775
|
Bidirectional$1.toolType = BIDIRECTIONAL$1;
|
|
827
776
|
Bidirectional$1.utilityToolType = BIDIRECTIONAL$1;
|
|
828
777
|
Bidirectional$1.TID300Representation = TID300Bidirectional$1;
|
|
829
|
-
|
|
830
778
|
Bidirectional$1.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
831
779
|
if (!TrackingIdentifier.includes(":")) {
|
|
832
780
|
return false;
|
|
833
781
|
}
|
|
834
|
-
|
|
835
782
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
783
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
784
|
+
cornerstone4Tag = _TrackingIdentifier$s2[0],
|
|
785
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
840
786
|
if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
|
|
841
787
|
return false;
|
|
842
788
|
}
|
|
843
|
-
|
|
844
789
|
return toolType === BIDIRECTIONAL$1;
|
|
845
790
|
};
|
|
846
|
-
|
|
847
791
|
MeasurementReport$1.registerTool(Bidirectional$1);
|
|
848
792
|
|
|
849
793
|
var TID300Ellipse$1 = utilities.TID300.Ellipse;
|
|
850
794
|
var ELLIPTICALROI$1 = "EllipticalRoi";
|
|
851
|
-
|
|
852
795
|
var EllipticalRoi = /*#__PURE__*/function () {
|
|
853
796
|
function EllipticalRoi() {
|
|
854
797
|
_classCallCheck(this, EllipticalRoi);
|
|
855
798
|
}
|
|
856
|
-
|
|
857
799
|
_createClass(EllipticalRoi, null, [{
|
|
858
800
|
key: "getMeasurementData",
|
|
859
|
-
value:
|
|
801
|
+
value:
|
|
802
|
+
// TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport.
|
|
860
803
|
function getMeasurementData(MeasurementGroup) {
|
|
861
804
|
var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
805
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
806
|
+
NUMGroup = _MeasurementReport$ge.NUMGroup,
|
|
807
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup;
|
|
866
808
|
var GraphicData = SCOORDGroup.GraphicData;
|
|
867
809
|
var majorAxis = [{
|
|
868
810
|
x: GraphicData[0],
|
|
@@ -877,25 +819,28 @@ var EllipticalRoi = /*#__PURE__*/function () {
|
|
|
877
819
|
}, {
|
|
878
820
|
x: GraphicData[6],
|
|
879
821
|
y: GraphicData[7]
|
|
880
|
-
}];
|
|
822
|
+
}];
|
|
823
|
+
|
|
824
|
+
// Calculate two opposite corners of box defined by two axes.
|
|
881
825
|
|
|
882
826
|
var minorAxisLength = Math.sqrt(Math.pow(minorAxis[0].x - minorAxis[1].x, 2) + Math.pow(minorAxis[0].y - minorAxis[1].y, 2));
|
|
883
827
|
var minorAxisDirection = {
|
|
884
828
|
x: (minorAxis[1].x - minorAxis[0].x) / minorAxisLength,
|
|
885
829
|
y: (minorAxis[1].y - minorAxis[0].y) / minorAxisLength
|
|
886
830
|
};
|
|
887
|
-
var halfMinorAxisLength = minorAxisLength / 2;
|
|
831
|
+
var halfMinorAxisLength = minorAxisLength / 2;
|
|
888
832
|
|
|
833
|
+
// First end point of major axis + half minor axis vector
|
|
889
834
|
var corner1 = {
|
|
890
835
|
x: majorAxis[0].x + minorAxisDirection.x * halfMinorAxisLength,
|
|
891
836
|
y: majorAxis[0].y + minorAxisDirection.y * halfMinorAxisLength
|
|
892
|
-
};
|
|
837
|
+
};
|
|
893
838
|
|
|
839
|
+
// Second end point of major axis - half of minor axis vector
|
|
894
840
|
var corner2 = {
|
|
895
841
|
x: majorAxis[1].x - minorAxisDirection.x * halfMinorAxisLength,
|
|
896
842
|
y: majorAxis[1].y - minorAxisDirection.y * halfMinorAxisLength
|
|
897
843
|
};
|
|
898
|
-
|
|
899
844
|
var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
|
|
900
845
|
toolType: EllipticalRoi.toolType,
|
|
901
846
|
active: false,
|
|
@@ -927,19 +872,18 @@ var EllipticalRoi = /*#__PURE__*/function () {
|
|
|
927
872
|
invalidated: true,
|
|
928
873
|
visible: true
|
|
929
874
|
});
|
|
930
|
-
|
|
931
875
|
return state;
|
|
932
876
|
}
|
|
933
877
|
}, {
|
|
934
878
|
key: "getTID300RepresentationArguments",
|
|
935
879
|
value: function getTID300RepresentationArguments(tool) {
|
|
936
880
|
var _tool$cachedStats = tool.cachedStats,
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
881
|
+
cachedStats = _tool$cachedStats === void 0 ? {} : _tool$cachedStats,
|
|
882
|
+
handles = tool.handles,
|
|
883
|
+
finding = tool.finding,
|
|
884
|
+
findingSites = tool.findingSites;
|
|
941
885
|
var start = handles.start,
|
|
942
|
-
|
|
886
|
+
end = handles.end;
|
|
943
887
|
var area = cachedStats.area;
|
|
944
888
|
var halfXLength = Math.abs(start.x - end.x) / 2;
|
|
945
889
|
var halfYLength = Math.abs(start.y - end.y) / 2;
|
|
@@ -948,7 +892,6 @@ var EllipticalRoi = /*#__PURE__*/function () {
|
|
|
948
892
|
x: (start.x + end.x) / 2,
|
|
949
893
|
y: (start.y + end.y) / 2
|
|
950
894
|
};
|
|
951
|
-
|
|
952
895
|
if (halfXLength > halfYLength) {
|
|
953
896
|
// X-axis major
|
|
954
897
|
// Major axis
|
|
@@ -959,8 +902,8 @@ var EllipticalRoi = /*#__PURE__*/function () {
|
|
|
959
902
|
points.push({
|
|
960
903
|
x: center.x + halfXLength,
|
|
961
904
|
y: center.y
|
|
962
|
-
});
|
|
963
|
-
|
|
905
|
+
});
|
|
906
|
+
// Minor axis
|
|
964
907
|
points.push({
|
|
965
908
|
x: center.x,
|
|
966
909
|
y: center.y - halfYLength
|
|
@@ -979,8 +922,8 @@ var EllipticalRoi = /*#__PURE__*/function () {
|
|
|
979
922
|
points.push({
|
|
980
923
|
x: center.x,
|
|
981
924
|
y: center.y + halfYLength
|
|
982
|
-
});
|
|
983
|
-
|
|
925
|
+
});
|
|
926
|
+
// Minor axis
|
|
984
927
|
points.push({
|
|
985
928
|
x: center.x - halfXLength,
|
|
986
929
|
y: center.y
|
|
@@ -990,7 +933,6 @@ var EllipticalRoi = /*#__PURE__*/function () {
|
|
|
990
933
|
y: center.y
|
|
991
934
|
});
|
|
992
935
|
}
|
|
993
|
-
|
|
994
936
|
var trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:EllipticalRoi";
|
|
995
937
|
return {
|
|
996
938
|
area: area,
|
|
@@ -1001,51 +943,40 @@ var EllipticalRoi = /*#__PURE__*/function () {
|
|
|
1001
943
|
};
|
|
1002
944
|
}
|
|
1003
945
|
}]);
|
|
1004
|
-
|
|
1005
946
|
return EllipticalRoi;
|
|
1006
947
|
}();
|
|
1007
|
-
|
|
1008
948
|
EllipticalRoi.toolType = ELLIPTICALROI$1;
|
|
1009
949
|
EllipticalRoi.utilityToolType = ELLIPTICALROI$1;
|
|
1010
950
|
EllipticalRoi.TID300Representation = TID300Ellipse$1;
|
|
1011
|
-
|
|
1012
951
|
EllipticalRoi.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
1013
952
|
if (!TrackingIdentifier.includes(":")) {
|
|
1014
953
|
return false;
|
|
1015
954
|
}
|
|
1016
|
-
|
|
1017
955
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
956
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
957
|
+
cornerstone4Tag = _TrackingIdentifier$s2[0],
|
|
958
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
1022
959
|
if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
|
|
1023
960
|
return false;
|
|
1024
961
|
}
|
|
1025
|
-
|
|
1026
962
|
return toolType === ELLIPTICALROI$1;
|
|
1027
963
|
};
|
|
1028
|
-
|
|
1029
964
|
MeasurementReport$1.registerTool(EllipticalRoi);
|
|
1030
965
|
|
|
1031
966
|
var TID300Circle$1 = utilities.TID300.Circle;
|
|
1032
967
|
var CIRCLEROI$1 = "CircleRoi";
|
|
1033
|
-
|
|
1034
968
|
var CircleRoi = /*#__PURE__*/function () {
|
|
1035
969
|
function CircleRoi() {
|
|
1036
970
|
_classCallCheck(this, CircleRoi);
|
|
1037
971
|
}
|
|
1038
|
-
|
|
1039
972
|
_createClass(CircleRoi, null, [{
|
|
1040
973
|
key: "getMeasurementData",
|
|
1041
|
-
value:
|
|
1042
|
-
/** Gets the measurement data for cornerstone, given DICOM SR measurement data. */
|
|
974
|
+
value: /** Gets the measurement data for cornerstone, given DICOM SR measurement data. */
|
|
1043
975
|
function getMeasurementData(MeasurementGroup) {
|
|
1044
976
|
var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
977
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
978
|
+
NUMGroup = _MeasurementReport$ge.NUMGroup,
|
|
979
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup;
|
|
1049
980
|
var GraphicData = SCOORDGroup.GraphicData;
|
|
1050
981
|
var center = {
|
|
1051
982
|
x: GraphicData[0],
|
|
@@ -1055,7 +986,6 @@ var CircleRoi = /*#__PURE__*/function () {
|
|
|
1055
986
|
x: GraphicData[2],
|
|
1056
987
|
y: GraphicData[3]
|
|
1057
988
|
};
|
|
1058
|
-
|
|
1059
989
|
var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
|
|
1060
990
|
toolType: CircleRoi.toolType,
|
|
1061
991
|
active: false,
|
|
@@ -1086,28 +1016,27 @@ var CircleRoi = /*#__PURE__*/function () {
|
|
|
1086
1016
|
invalidated: true,
|
|
1087
1017
|
visible: true
|
|
1088
1018
|
});
|
|
1089
|
-
|
|
1090
1019
|
return state;
|
|
1091
1020
|
}
|
|
1021
|
+
|
|
1092
1022
|
/**
|
|
1093
1023
|
* Gets the TID 300 representation of a circle, given the cornerstone representation.
|
|
1094
1024
|
*
|
|
1095
1025
|
* @param {Object} tool
|
|
1096
1026
|
* @returns
|
|
1097
1027
|
*/
|
|
1098
|
-
|
|
1099
1028
|
}, {
|
|
1100
1029
|
key: "getTID300RepresentationArguments",
|
|
1101
1030
|
value: function getTID300RepresentationArguments(tool) {
|
|
1102
1031
|
var _tool$cachedStats = tool.cachedStats,
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1032
|
+
cachedStats = _tool$cachedStats === void 0 ? {} : _tool$cachedStats,
|
|
1033
|
+
handles = tool.handles,
|
|
1034
|
+
finding = tool.finding,
|
|
1035
|
+
findingSites = tool.findingSites;
|
|
1107
1036
|
var center = handles.start,
|
|
1108
|
-
|
|
1037
|
+
end = handles.end;
|
|
1109
1038
|
var area = cachedStats.area,
|
|
1110
|
-
|
|
1039
|
+
radius = cachedStats.radius;
|
|
1111
1040
|
var perimeter = 2 * Math.PI * radius;
|
|
1112
1041
|
var points = [];
|
|
1113
1042
|
points.push(center);
|
|
@@ -1124,53 +1053,42 @@ var CircleRoi = /*#__PURE__*/function () {
|
|
|
1124
1053
|
};
|
|
1125
1054
|
}
|
|
1126
1055
|
}]);
|
|
1127
|
-
|
|
1128
1056
|
return CircleRoi;
|
|
1129
1057
|
}();
|
|
1130
|
-
|
|
1131
1058
|
CircleRoi.toolType = CIRCLEROI$1;
|
|
1132
1059
|
CircleRoi.utilityToolType = CIRCLEROI$1;
|
|
1133
1060
|
CircleRoi.TID300Representation = TID300Circle$1;
|
|
1134
|
-
|
|
1135
1061
|
CircleRoi.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
1136
1062
|
if (!TrackingIdentifier.includes(":")) {
|
|
1137
1063
|
return false;
|
|
1138
1064
|
}
|
|
1139
|
-
|
|
1140
1065
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1066
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
1067
|
+
cornerstone4Tag = _TrackingIdentifier$s2[0],
|
|
1068
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
1145
1069
|
if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
|
|
1146
1070
|
return false;
|
|
1147
1071
|
}
|
|
1148
|
-
|
|
1149
1072
|
return toolType === CIRCLEROI$1;
|
|
1150
1073
|
};
|
|
1151
|
-
|
|
1152
1074
|
MeasurementReport$1.registerTool(CircleRoi);
|
|
1153
1075
|
|
|
1154
1076
|
var TID300Point$2 = utilities.TID300.Point;
|
|
1155
1077
|
var ARROW_ANNOTATE$1 = "ArrowAnnotate";
|
|
1156
1078
|
var CORNERSTONEFREETEXT$1 = "CORNERSTONEFREETEXT";
|
|
1157
|
-
|
|
1158
1079
|
var ArrowAnnotate$1 = /*#__PURE__*/function () {
|
|
1159
1080
|
function ArrowAnnotate() {
|
|
1160
1081
|
_classCallCheck(this, ArrowAnnotate);
|
|
1161
1082
|
}
|
|
1162
|
-
|
|
1163
1083
|
_createClass(ArrowAnnotate, null, [{
|
|
1164
1084
|
key: "getMeasurementData",
|
|
1165
1085
|
value: function getMeasurementData(MeasurementGroup) {
|
|
1166
1086
|
var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1087
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
1088
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup,
|
|
1089
|
+
findingGroup = _MeasurementReport$ge.findingGroup;
|
|
1171
1090
|
var text = findingGroup.ConceptCodeSequence.CodeMeaning;
|
|
1172
1091
|
var GraphicData = SCOORDGroup.GraphicData;
|
|
1173
|
-
|
|
1174
1092
|
var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
|
|
1175
1093
|
toolType: ArrowAnnotate.toolType,
|
|
1176
1094
|
active: false,
|
|
@@ -1201,7 +1119,6 @@ var ArrowAnnotate$1 = /*#__PURE__*/function () {
|
|
|
1201
1119
|
text: text,
|
|
1202
1120
|
visible: true
|
|
1203
1121
|
});
|
|
1204
|
-
|
|
1205
1122
|
return state;
|
|
1206
1123
|
}
|
|
1207
1124
|
}, {
|
|
@@ -1209,13 +1126,14 @@ var ArrowAnnotate$1 = /*#__PURE__*/function () {
|
|
|
1209
1126
|
value: function getTID300RepresentationArguments(tool) {
|
|
1210
1127
|
var points = [tool.handles.start, tool.handles.end];
|
|
1211
1128
|
var finding = tool.finding,
|
|
1212
|
-
|
|
1129
|
+
findingSites = tool.findingSites;
|
|
1213
1130
|
var TID300RepresentationArguments = {
|
|
1214
1131
|
points: points,
|
|
1215
1132
|
trackingIdentifierTextValue: "cornerstoneTools@^4.0.0:ArrowAnnotate",
|
|
1216
1133
|
findingSites: findingSites || []
|
|
1217
|
-
};
|
|
1134
|
+
};
|
|
1218
1135
|
|
|
1136
|
+
// If freetext finding isn't present, add it from the tool text.
|
|
1219
1137
|
if (!finding || finding.CodeValue !== CORNERSTONEFREETEXT$1) {
|
|
1220
1138
|
finding = {
|
|
1221
1139
|
CodeValue: CORNERSTONEFREETEXT$1,
|
|
@@ -1223,53 +1141,46 @@ var ArrowAnnotate$1 = /*#__PURE__*/function () {
|
|
|
1223
1141
|
CodeMeaning: tool.text
|
|
1224
1142
|
};
|
|
1225
1143
|
}
|
|
1226
|
-
|
|
1227
1144
|
TID300RepresentationArguments.finding = finding;
|
|
1228
1145
|
return TID300RepresentationArguments;
|
|
1229
1146
|
}
|
|
1230
1147
|
}]);
|
|
1231
|
-
|
|
1232
1148
|
return ArrowAnnotate;
|
|
1233
1149
|
}();
|
|
1234
|
-
|
|
1235
1150
|
ArrowAnnotate$1.toolType = ARROW_ANNOTATE$1;
|
|
1236
1151
|
ArrowAnnotate$1.utilityToolType = ARROW_ANNOTATE$1;
|
|
1237
1152
|
ArrowAnnotate$1.TID300Representation = TID300Point$2;
|
|
1238
|
-
|
|
1239
1153
|
ArrowAnnotate$1.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
1240
1154
|
if (!TrackingIdentifier.includes(":")) {
|
|
1241
1155
|
return false;
|
|
1242
1156
|
}
|
|
1243
|
-
|
|
1244
1157
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1158
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
1159
|
+
cornerstone4Tag = _TrackingIdentifier$s2[0],
|
|
1160
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
1249
1161
|
if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
|
|
1250
1162
|
return false;
|
|
1251
1163
|
}
|
|
1252
|
-
|
|
1253
1164
|
return toolType === ARROW_ANNOTATE$1;
|
|
1254
1165
|
};
|
|
1255
|
-
|
|
1256
1166
|
MeasurementReport$1.registerTool(ArrowAnnotate$1);
|
|
1257
1167
|
|
|
1258
1168
|
var _utilities$orientatio$1 = utilities.orientation,
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1169
|
+
rotateDirectionCosinesInPlane$1 = _utilities$orientatio$1.rotateDirectionCosinesInPlane,
|
|
1170
|
+
flipIOP$1 = _utilities$orientatio$1.flipImageOrientationPatient,
|
|
1171
|
+
flipMatrix2D$1 = _utilities$orientatio$1.flipMatrix2D,
|
|
1172
|
+
rotateMatrix902D$1 = _utilities$orientatio$1.rotateMatrix902D;
|
|
1263
1173
|
var datasetToBlob$1 = utilities.datasetToBlob,
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1174
|
+
BitArray$2 = utilities.BitArray,
|
|
1175
|
+
DicomMessage$1 = utilities.DicomMessage,
|
|
1176
|
+
DicomMetaDictionary$2 = utilities.DicomMetaDictionary;
|
|
1267
1177
|
var Normalizer$2 = normalizers.Normalizer;
|
|
1268
1178
|
var SegmentationDerivation$1 = derivations.Segmentation;
|
|
1269
1179
|
var Segmentation$3 = {
|
|
1270
1180
|
generateSegmentation: generateSegmentation$2,
|
|
1271
1181
|
generateToolState: generateToolState$2
|
|
1272
1182
|
};
|
|
1183
|
+
|
|
1273
1184
|
/**
|
|
1274
1185
|
*
|
|
1275
1186
|
* @typedef {Object} BrushData
|
|
@@ -1286,14 +1197,14 @@ var Segmentation$3 = {
|
|
|
1286
1197
|
* @param {BrushData} brushData and object containing the brushData.
|
|
1287
1198
|
* @returns {type} description
|
|
1288
1199
|
*/
|
|
1289
|
-
|
|
1290
1200
|
function generateSegmentation$2(images, brushData) {
|
|
1291
1201
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
|
|
1292
1202
|
includeSliceSpacing: true
|
|
1293
1203
|
};
|
|
1294
1204
|
var toolState = brushData.toolState,
|
|
1295
|
-
|
|
1205
|
+
segments = brushData.segments;
|
|
1296
1206
|
|
|
1207
|
+
// Calculate the dimensions of the data cube.
|
|
1297
1208
|
var image0 = images[0];
|
|
1298
1209
|
var dims = {
|
|
1299
1210
|
x: image0.columns,
|
|
@@ -1301,105 +1212,84 @@ function generateSegmentation$2(images, brushData) {
|
|
|
1301
1212
|
z: images.length
|
|
1302
1213
|
};
|
|
1303
1214
|
dims.xy = dims.x * dims.y;
|
|
1304
|
-
|
|
1305
1215
|
var numSegments = _getSegCount(seg, segments);
|
|
1306
|
-
|
|
1307
1216
|
if (!numSegments) {
|
|
1308
1217
|
throw new Error("No segments to export!");
|
|
1309
1218
|
}
|
|
1310
|
-
|
|
1311
1219
|
var isMultiframe = image0.imageId.includes("?frame");
|
|
1312
|
-
|
|
1313
1220
|
var seg = _createSegFromImages$1(images, isMultiframe, options);
|
|
1314
|
-
|
|
1315
1221
|
var _getNumberOfFramesPer = _getNumberOfFramesPerSegment(toolState, images, segments),
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1222
|
+
referencedFramesPerSegment = _getNumberOfFramesPer.referencedFramesPerSegment,
|
|
1223
|
+
segmentIndicies = _getNumberOfFramesPer.segmentIndicies;
|
|
1319
1224
|
var NumberOfFrames = 0;
|
|
1320
|
-
|
|
1321
1225
|
for (var i = 0; i < referencedFramesPerSegment.length; i++) {
|
|
1322
1226
|
NumberOfFrames += referencedFramesPerSegment[i].length;
|
|
1323
1227
|
}
|
|
1324
|
-
|
|
1325
1228
|
seg.setNumberOfFrames(NumberOfFrames);
|
|
1326
|
-
|
|
1327
1229
|
for (var _i = 0; _i < segmentIndicies.length; _i++) {
|
|
1328
1230
|
var segmentIndex = segmentIndicies[_i];
|
|
1329
|
-
var referencedFrameIndicies = referencedFramesPerSegment[_i];
|
|
1231
|
+
var referencedFrameIndicies = referencedFramesPerSegment[_i];
|
|
1330
1232
|
|
|
1233
|
+
// Frame numbers start from 1.
|
|
1331
1234
|
var referencedFrameNumbers = referencedFrameIndicies.map(function (element) {
|
|
1332
1235
|
return element + 1;
|
|
1333
1236
|
});
|
|
1334
1237
|
var segment = segments[segmentIndex];
|
|
1335
1238
|
seg.addSegment(segment, _extractCornerstoneToolsPixelData(segmentIndex, referencedFrameIndicies, toolState, images, dims), referencedFrameNumbers);
|
|
1336
1239
|
}
|
|
1337
|
-
|
|
1338
1240
|
seg.bitPackPixelData();
|
|
1339
1241
|
var segBlob = datasetToBlob$1(seg.dataset);
|
|
1340
1242
|
return segBlob;
|
|
1341
1243
|
}
|
|
1342
|
-
|
|
1343
1244
|
function _extractCornerstoneToolsPixelData(segmentIndex, referencedFrames, toolState, images, dims) {
|
|
1344
1245
|
var pixelData = new Uint8Array(dims.xy * referencedFrames.length);
|
|
1345
1246
|
var pixelDataIndex = 0;
|
|
1346
|
-
|
|
1347
1247
|
for (var i = 0; i < referencedFrames.length; i++) {
|
|
1348
1248
|
var frame = referencedFrames[i];
|
|
1349
1249
|
var imageId = images[frame].imageId;
|
|
1350
1250
|
var imageIdSpecificToolState = toolState[imageId];
|
|
1351
1251
|
var brushPixelData = imageIdSpecificToolState.brush.data[segmentIndex].pixelData;
|
|
1352
|
-
|
|
1353
1252
|
for (var p = 0; p < brushPixelData.length; p++) {
|
|
1354
1253
|
pixelData[pixelDataIndex] = brushPixelData[p];
|
|
1355
1254
|
pixelDataIndex++;
|
|
1356
1255
|
}
|
|
1357
1256
|
}
|
|
1358
|
-
|
|
1359
1257
|
return pixelData;
|
|
1360
1258
|
}
|
|
1361
|
-
|
|
1362
1259
|
function _getNumberOfFramesPerSegment(toolState, images, segments) {
|
|
1363
1260
|
var segmentIndicies = [];
|
|
1364
1261
|
var referencedFramesPerSegment = [];
|
|
1365
|
-
|
|
1366
1262
|
for (var i = 0; i < segments.length; i++) {
|
|
1367
1263
|
if (segments[i]) {
|
|
1368
1264
|
segmentIndicies.push(i);
|
|
1369
1265
|
referencedFramesPerSegment.push([]);
|
|
1370
1266
|
}
|
|
1371
1267
|
}
|
|
1372
|
-
|
|
1373
1268
|
for (var z = 0; z < images.length; z++) {
|
|
1374
1269
|
var imageId = images[z].imageId;
|
|
1375
1270
|
var imageIdSpecificToolState = toolState[imageId];
|
|
1376
|
-
|
|
1377
1271
|
for (var _i2 = 0; _i2 < segmentIndicies.length; _i2++) {
|
|
1378
1272
|
var segIdx = segmentIndicies[_i2];
|
|
1379
|
-
|
|
1380
1273
|
if (imageIdSpecificToolState && imageIdSpecificToolState.brush && imageIdSpecificToolState.brush.data && imageIdSpecificToolState.brush.data[segIdx] && imageIdSpecificToolState.brush.data[segIdx].pixelData) {
|
|
1381
1274
|
referencedFramesPerSegment[_i2].push(z);
|
|
1382
1275
|
}
|
|
1383
1276
|
}
|
|
1384
1277
|
}
|
|
1385
|
-
|
|
1386
1278
|
return {
|
|
1387
1279
|
referencedFramesPerSegment: referencedFramesPerSegment,
|
|
1388
1280
|
segmentIndicies: segmentIndicies
|
|
1389
1281
|
};
|
|
1390
1282
|
}
|
|
1391
|
-
|
|
1392
1283
|
function _getSegCount(seg, segments) {
|
|
1393
1284
|
var numSegments = 0;
|
|
1394
|
-
|
|
1395
1285
|
for (var i = 0; i < segments.length; i++) {
|
|
1396
1286
|
if (segments[i]) {
|
|
1397
1287
|
numSegments++;
|
|
1398
1288
|
}
|
|
1399
1289
|
}
|
|
1400
|
-
|
|
1401
1290
|
return numSegments;
|
|
1402
1291
|
}
|
|
1292
|
+
|
|
1403
1293
|
/**
|
|
1404
1294
|
* _createSegFromImages - description
|
|
1405
1295
|
*
|
|
@@ -1407,11 +1297,8 @@ function _getSegCount(seg, segments) {
|
|
|
1407
1297
|
* @param {Boolean} isMultiframe Whether the images are multiframe.
|
|
1408
1298
|
* @returns {Object} The Seg derived dataSet.
|
|
1409
1299
|
*/
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
1300
|
function _createSegFromImages$1(images, isMultiframe, options) {
|
|
1413
1301
|
var datasets = [];
|
|
1414
|
-
|
|
1415
1302
|
if (isMultiframe) {
|
|
1416
1303
|
var image = images[0];
|
|
1417
1304
|
var arrayBuffer = image.data.byteArray.buffer;
|
|
@@ -1423,19 +1310,16 @@ function _createSegFromImages$1(images, isMultiframe, options) {
|
|
|
1423
1310
|
for (var i = 0; i < images.length; i++) {
|
|
1424
1311
|
var _image = images[i];
|
|
1425
1312
|
var _arrayBuffer = _image.data.byteArray.buffer;
|
|
1426
|
-
|
|
1427
1313
|
var _dicomData = DicomMessage$1.readFile(_arrayBuffer);
|
|
1428
|
-
|
|
1429
1314
|
var _dataset = DicomMetaDictionary$2.naturalizeDataset(_dicomData.dict);
|
|
1430
|
-
|
|
1431
1315
|
_dataset._meta = DicomMetaDictionary$2.namifyDataset(_dicomData.meta);
|
|
1432
1316
|
datasets.push(_dataset);
|
|
1433
1317
|
}
|
|
1434
1318
|
}
|
|
1435
|
-
|
|
1436
1319
|
var multiframe = Normalizer$2.normalizeToDataset(datasets);
|
|
1437
1320
|
return new SegmentationDerivation$1([multiframe], options);
|
|
1438
1321
|
}
|
|
1322
|
+
|
|
1439
1323
|
/**
|
|
1440
1324
|
* generateToolState - Given a set of cornrstoneTools imageIds and a Segmentation buffer,
|
|
1441
1325
|
* derive cornerstoneTools toolState and brush metadata.
|
|
@@ -1446,21 +1330,18 @@ function _createSegFromImages$1(images, isMultiframe, options) {
|
|
|
1446
1330
|
* @returns {Object} The toolState and an object from which the
|
|
1447
1331
|
* segment metadata can be derived.
|
|
1448
1332
|
*/
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
1333
|
function generateToolState$2(imageIds, arrayBuffer, metadataProvider) {
|
|
1452
1334
|
var dicomData = DicomMessage$1.readFile(arrayBuffer);
|
|
1453
1335
|
var dataset = DicomMetaDictionary$2.naturalizeDataset(dicomData.dict);
|
|
1454
1336
|
dataset._meta = DicomMetaDictionary$2.namifyDataset(dicomData.meta);
|
|
1455
1337
|
var multiframe = Normalizer$2.normalizeToDataset([dataset]);
|
|
1456
1338
|
var imagePlaneModule = metadataProvider.get("imagePlaneModule", imageIds[0]);
|
|
1457
|
-
|
|
1458
1339
|
if (!imagePlaneModule) {
|
|
1459
1340
|
console.warn("Insufficient metadata, imagePlaneModule missing.");
|
|
1460
1341
|
}
|
|
1342
|
+
var ImageOrientationPatient = Array.isArray(imagePlaneModule.rowCosines) ? [].concat(_toConsumableArray(imagePlaneModule.rowCosines), _toConsumableArray(imagePlaneModule.columnCosines)) : [imagePlaneModule.rowCosines.x, imagePlaneModule.rowCosines.y, imagePlaneModule.rowCosines.z, imagePlaneModule.columnCosines.x, imagePlaneModule.columnCosines.y, imagePlaneModule.columnCosines.z];
|
|
1461
1343
|
|
|
1462
|
-
|
|
1463
|
-
|
|
1344
|
+
// Get IOP from ref series, compute supported orientations:
|
|
1464
1345
|
var validOrientations = getValidOrientations$1(ImageOrientationPatient);
|
|
1465
1346
|
var SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence;
|
|
1466
1347
|
var sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
|
|
@@ -1470,70 +1351,59 @@ function generateToolState$2(imageIds, arrayBuffer, metadataProvider) {
|
|
|
1470
1351
|
var PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence;
|
|
1471
1352
|
var toolState = {};
|
|
1472
1353
|
var inPlane = true;
|
|
1473
|
-
|
|
1474
1354
|
for (var i = 0; i < PerFrameFunctionalGroupsSequence.length; i++) {
|
|
1475
1355
|
var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[i];
|
|
1476
1356
|
var ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
|
|
1477
1357
|
var pixelDataI2D = ndarray(new Uint8Array(pixelData.buffer, i * sliceLength, sliceLength), [multiframe.Rows, multiframe.Columns]);
|
|
1478
1358
|
var alignedPixelDataI = alignPixelDataWithSourceData$1(pixelDataI2D, ImageOrientationPatientI, validOrientations);
|
|
1479
|
-
|
|
1480
1359
|
if (!alignedPixelDataI) {
|
|
1481
1360
|
console.warn("This segmentation object is not in-plane with the source data. Bailing out of IO. It'd be better to render this with vtkjs. ");
|
|
1482
1361
|
inPlane = false;
|
|
1483
1362
|
break;
|
|
1484
1363
|
}
|
|
1485
|
-
|
|
1486
1364
|
var segmentIndex = PerFrameFunctionalGroups.SegmentIdentificationSequence.ReferencedSegmentNumber - 1;
|
|
1487
1365
|
var SourceImageSequence = void 0;
|
|
1488
|
-
|
|
1489
1366
|
if (SharedFunctionalGroupsSequence.DerivationImageSequence && SharedFunctionalGroupsSequence.DerivationImageSequence.SourceImageSequence) {
|
|
1490
1367
|
SourceImageSequence = SharedFunctionalGroupsSequence.DerivationImageSequence.SourceImageSequence[i];
|
|
1491
1368
|
} else {
|
|
1492
1369
|
SourceImageSequence = PerFrameFunctionalGroups.DerivationImageSequence.SourceImageSequence;
|
|
1493
1370
|
}
|
|
1494
|
-
|
|
1495
1371
|
var imageId = getImageIdOfSourceImage(SourceImageSequence, imageIds, metadataProvider);
|
|
1496
1372
|
addImageIdSpecificBrushToolState(toolState, imageId, segmentIndex, alignedPixelDataI);
|
|
1497
1373
|
}
|
|
1498
|
-
|
|
1499
1374
|
if (!inPlane) {
|
|
1500
1375
|
return;
|
|
1501
1376
|
}
|
|
1502
|
-
|
|
1503
1377
|
return {
|
|
1504
1378
|
toolState: toolState,
|
|
1505
1379
|
segMetadata: segMetadata
|
|
1506
1380
|
};
|
|
1507
1381
|
}
|
|
1382
|
+
|
|
1508
1383
|
/**
|
|
1509
1384
|
* unpackPixelData - Unpacks bitpacked pixelData if the Segmentation is BINARY.
|
|
1510
1385
|
*
|
|
1511
1386
|
* @param {Object} multiframe The multiframe dataset.
|
|
1512
1387
|
* @return {Uint8Array} The unpacked pixelData.
|
|
1513
1388
|
*/
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
1389
|
function unpackPixelData$1(multiframe) {
|
|
1517
1390
|
var segType = multiframe.SegmentationType;
|
|
1518
|
-
|
|
1519
1391
|
if (segType === "BINARY") {
|
|
1520
1392
|
return BitArray$2.unpack(multiframe.PixelData);
|
|
1521
1393
|
}
|
|
1522
|
-
|
|
1523
1394
|
var pixelData = new Uint8Array(multiframe.PixelData);
|
|
1524
1395
|
var max = multiframe.MaximumFractionalValue;
|
|
1525
1396
|
var onlyMaxAndZero = pixelData.find(function (element) {
|
|
1526
1397
|
return element !== 0 && element !== max;
|
|
1527
1398
|
}) === undefined;
|
|
1528
|
-
|
|
1529
1399
|
if (!onlyMaxAndZero) {
|
|
1530
1400
|
log.warn("This is a fractional segmentation, which is not currently supported.");
|
|
1531
1401
|
return;
|
|
1532
1402
|
}
|
|
1533
|
-
|
|
1534
1403
|
log.warn("This segmentation object is actually binary... processing as such.");
|
|
1535
1404
|
return pixelData;
|
|
1536
1405
|
}
|
|
1406
|
+
|
|
1537
1407
|
/**
|
|
1538
1408
|
* addImageIdSpecificBrushToolState - Adds brush pixel data to cornerstoneTools
|
|
1539
1409
|
* formatted toolState object.
|
|
@@ -1543,8 +1413,6 @@ function unpackPixelData$1(multiframe) {
|
|
|
1543
1413
|
* @param {Number} segmentIndex The index of the segment data being added.
|
|
1544
1414
|
* @param {Ndarray} pixelData2D The pixelData in Ndarry 2D format.
|
|
1545
1415
|
*/
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
1416
|
function addImageIdSpecificBrushToolState(toolState, imageId, segmentIndex, pixelData2D) {
|
|
1549
1417
|
if (!toolState[imageId]) {
|
|
1550
1418
|
toolState[imageId] = {};
|
|
@@ -1556,12 +1424,10 @@ function addImageIdSpecificBrushToolState(toolState, imageId, segmentIndex, pixe
|
|
|
1556
1424
|
} else if (!toolState[imageId].brush.data) {
|
|
1557
1425
|
toolState[imageId].brush.data = [];
|
|
1558
1426
|
}
|
|
1559
|
-
|
|
1560
1427
|
toolState[imageId].brush.data[segmentIndex] = {};
|
|
1561
1428
|
var brushDataI = toolState[imageId].brush.data[segmentIndex];
|
|
1562
1429
|
brushDataI.pixelData = new Uint8Array(pixelData2D.data.length);
|
|
1563
1430
|
var cToolsPixelData = brushDataI.pixelData;
|
|
1564
|
-
|
|
1565
1431
|
for (var p = 0; p < cToolsPixelData.length; p++) {
|
|
1566
1432
|
if (pixelData2D.data[p]) {
|
|
1567
1433
|
cToolsPixelData[p] = 1;
|
|
@@ -1570,6 +1436,7 @@ function addImageIdSpecificBrushToolState(toolState, imageId, segmentIndex, pixe
|
|
|
1570
1436
|
}
|
|
1571
1437
|
}
|
|
1572
1438
|
}
|
|
1439
|
+
|
|
1573
1440
|
/**
|
|
1574
1441
|
* getImageIdOfSourceImage - Returns the Cornerstone imageId of the source image.
|
|
1575
1442
|
*
|
|
@@ -1579,13 +1446,12 @@ function addImageIdSpecificBrushToolState(toolState, imageId, segmentIndex, pixe
|
|
|
1579
1446
|
* metadata from imageIds.
|
|
1580
1447
|
* @return {String} The corresponding imageId.
|
|
1581
1448
|
*/
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
1449
|
function getImageIdOfSourceImage(SourceImageSequence, imageIds, metadataProvider) {
|
|
1585
1450
|
var ReferencedSOPInstanceUID = SourceImageSequence.ReferencedSOPInstanceUID,
|
|
1586
|
-
|
|
1451
|
+
ReferencedFrameNumber = SourceImageSequence.ReferencedFrameNumber;
|
|
1587
1452
|
return ReferencedFrameNumber ? getImageIdOfReferencedFrame$1(ReferencedSOPInstanceUID, ReferencedFrameNumber, imageIds, metadataProvider) : getImageIdOfReferencedSingleFramedSOPInstance$1(ReferencedSOPInstanceUID, imageIds, metadataProvider);
|
|
1588
1453
|
}
|
|
1454
|
+
|
|
1589
1455
|
/**
|
|
1590
1456
|
* getImageIdOfReferencedSingleFramedSOPInstance - Returns the imageId
|
|
1591
1457
|
* corresponding to the specified sopInstanceUid for single-frame images.
|
|
@@ -1596,19 +1462,16 @@ function getImageIdOfSourceImage(SourceImageSequence, imageIds, metadataProvider
|
|
|
1596
1462
|
* from the cornerstone imageIds.
|
|
1597
1463
|
* @return {String} The imageId that corresponds to the sopInstanceUid.
|
|
1598
1464
|
*/
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
1465
|
function getImageIdOfReferencedSingleFramedSOPInstance$1(sopInstanceUid, imageIds, metadataProvider) {
|
|
1602
1466
|
return imageIds.find(function (imageId) {
|
|
1603
1467
|
var sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
|
|
1604
|
-
|
|
1605
1468
|
if (!sopCommonModule) {
|
|
1606
1469
|
return;
|
|
1607
1470
|
}
|
|
1608
|
-
|
|
1609
1471
|
return sopCommonModule.sopInstanceUID === sopInstanceUid;
|
|
1610
1472
|
});
|
|
1611
1473
|
}
|
|
1474
|
+
|
|
1612
1475
|
/**
|
|
1613
1476
|
* getImageIdOfReferencedFrame - Returns the imageId corresponding to the
|
|
1614
1477
|
* specified sopInstanceUid and frameNumber for multi-frame images.
|
|
@@ -1620,33 +1483,31 @@ function getImageIdOfReferencedSingleFramedSOPInstance$1(sopInstanceUid, imageId
|
|
|
1620
1483
|
* from the cornerstone imageIds.
|
|
1621
1484
|
* @return {String} The imageId that corresponds to the sopInstanceUid.
|
|
1622
1485
|
*/
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
1486
|
function getImageIdOfReferencedFrame$1(sopInstanceUid, frameNumber, imageIds, metadataProvider) {
|
|
1626
1487
|
var imageId = imageIds.find(function (imageId) {
|
|
1627
1488
|
var sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
|
|
1628
|
-
|
|
1629
1489
|
if (!sopCommonModule) {
|
|
1630
1490
|
return;
|
|
1631
1491
|
}
|
|
1632
|
-
|
|
1633
1492
|
var imageIdFrameNumber = Number(imageId.split("frame=")[1]);
|
|
1634
|
-
return (
|
|
1493
|
+
return (
|
|
1494
|
+
//frameNumber is zero indexed for cornerstoneDICOMImageLoader image Ids.
|
|
1635
1495
|
sopCommonModule.sopInstanceUID === sopInstanceUid && imageIdFrameNumber === frameNumber - 1
|
|
1636
1496
|
);
|
|
1637
1497
|
});
|
|
1638
1498
|
return imageId;
|
|
1639
1499
|
}
|
|
1500
|
+
|
|
1640
1501
|
/**
|
|
1641
1502
|
* getValidOrientations - returns an array of valid orientations.
|
|
1642
1503
|
*
|
|
1643
1504
|
* @param iop - The row (0..2) an column (3..5) direction cosines.
|
|
1644
1505
|
* @return An array of valid orientations.
|
|
1645
1506
|
*/
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
1507
|
function getValidOrientations$1(iop) {
|
|
1649
|
-
var orientations = [];
|
|
1508
|
+
var orientations = [];
|
|
1509
|
+
|
|
1510
|
+
// [0, 1, 2]: 0, 0hf, 0vf
|
|
1650
1511
|
// [3, 4, 5]: 90, 90hf, 90vf
|
|
1651
1512
|
// [6, 7]: 180, 270
|
|
1652
1513
|
|
|
@@ -1661,6 +1522,7 @@ function getValidOrientations$1(iop) {
|
|
|
1661
1522
|
orientations[7] = rotateDirectionCosinesInPlane$1(iop, 1.5 * Math.PI);
|
|
1662
1523
|
return orientations;
|
|
1663
1524
|
}
|
|
1525
|
+
|
|
1664
1526
|
/**
|
|
1665
1527
|
* alignPixelDataWithSourceData -
|
|
1666
1528
|
*
|
|
@@ -1669,8 +1531,6 @@ function getValidOrientations$1(iop) {
|
|
|
1669
1531
|
* @param orientations - An array of valid imageOrientationPatient values.
|
|
1670
1532
|
* @return The aligned pixelData.
|
|
1671
1533
|
*/
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
1534
|
function alignPixelDataWithSourceData$1(pixelData2D, iop, orientations) {
|
|
1675
1535
|
if (compareIOP(iop, orientations[0])) {
|
|
1676
1536
|
//Same orientation.
|
|
@@ -1698,8 +1558,8 @@ function alignPixelDataWithSourceData$1(pixelData2D, iop, orientations) {
|
|
|
1698
1558
|
return rotateMatrix902D$1(rotateMatrix902D$1(rotateMatrix902D$1(pixelData2D)));
|
|
1699
1559
|
}
|
|
1700
1560
|
}
|
|
1701
|
-
|
|
1702
1561
|
var dx = 1e-5;
|
|
1562
|
+
|
|
1703
1563
|
/**
|
|
1704
1564
|
* compareIOP - Returns true if iop1 and iop2 are equal
|
|
1705
1565
|
* within a tollerance, dx.
|
|
@@ -1708,15 +1568,12 @@ var dx = 1e-5;
|
|
|
1708
1568
|
* @param iop2 - An ImageOrientationPatient array.
|
|
1709
1569
|
* @return True if iop1 and iop2 are equal.
|
|
1710
1570
|
*/
|
|
1711
|
-
|
|
1712
1571
|
function compareIOP(iop1, iop2) {
|
|
1713
1572
|
return Math.abs(iop1[0] - iop2[0]) < dx && Math.abs(iop1[1] - iop2[1]) < dx && Math.abs(iop1[2] - iop2[2]) < dx && Math.abs(iop1[3] - iop2[3]) < dx && Math.abs(iop1[4] - iop2[4]) < dx && Math.abs(iop1[5] - iop2[5]) < dx;
|
|
1714
1573
|
}
|
|
1715
|
-
|
|
1716
1574
|
function getSegmentMetadata$1(multiframe) {
|
|
1717
1575
|
var data = [];
|
|
1718
1576
|
var segmentSequence = multiframe.SegmentSequence;
|
|
1719
|
-
|
|
1720
1577
|
if (Array.isArray(segmentSequence)) {
|
|
1721
1578
|
for (var segIdx = 0; segIdx < segmentSequence.length; segIdx++) {
|
|
1722
1579
|
data.push(segmentSequence[segIdx]);
|
|
@@ -1725,7 +1582,6 @@ function getSegmentMetadata$1(multiframe) {
|
|
|
1725
1582
|
// Only one segment, will be stored as an object.
|
|
1726
1583
|
data.push(segmentSequence);
|
|
1727
1584
|
}
|
|
1728
|
-
|
|
1729
1585
|
return {
|
|
1730
1586
|
seriesInstanceUid: multiframe.ReferencedSeriesSequence.SeriesInstanceUID,
|
|
1731
1587
|
data: data
|
|
@@ -1733,25 +1589,26 @@ function getSegmentMetadata$1(multiframe) {
|
|
|
1733
1589
|
}
|
|
1734
1590
|
|
|
1735
1591
|
var _utilities$orientatio = utilities.orientation,
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1592
|
+
rotateDirectionCosinesInPlane = _utilities$orientatio.rotateDirectionCosinesInPlane,
|
|
1593
|
+
flipIOP = _utilities$orientatio.flipImageOrientationPatient,
|
|
1594
|
+
flipMatrix2D = _utilities$orientatio.flipMatrix2D,
|
|
1595
|
+
rotateMatrix902D = _utilities$orientatio.rotateMatrix902D,
|
|
1596
|
+
nearlyEqual = _utilities$orientatio.nearlyEqual;
|
|
1741
1597
|
var datasetToBlob = utilities.datasetToBlob,
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1598
|
+
BitArray$1 = utilities.BitArray,
|
|
1599
|
+
DicomMessage = utilities.DicomMessage,
|
|
1600
|
+
DicomMetaDictionary$1 = utilities.DicomMetaDictionary;
|
|
1745
1601
|
var Normalizer$1 = normalizers.Normalizer;
|
|
1746
1602
|
var SegmentationDerivation = derivations.Segmentation;
|
|
1747
1603
|
var _utilities$compressio = utilities.compression,
|
|
1748
|
-
|
|
1749
|
-
|
|
1604
|
+
encode = _utilities$compressio.encode,
|
|
1605
|
+
decode = _utilities$compressio.decode;
|
|
1750
1606
|
var Segmentation$2 = {
|
|
1751
1607
|
generateSegmentation: generateSegmentation$1,
|
|
1752
1608
|
generateToolState: generateToolState$1,
|
|
1753
1609
|
fillSegmentation: fillSegmentation$1
|
|
1754
1610
|
};
|
|
1611
|
+
|
|
1755
1612
|
/**
|
|
1756
1613
|
*
|
|
1757
1614
|
* @typedef {Object} BrushData
|
|
@@ -1764,6 +1621,7 @@ var generateSegmentationDefaultOptions = {
|
|
|
1764
1621
|
includeSliceSpacing: true,
|
|
1765
1622
|
rleEncode: true
|
|
1766
1623
|
};
|
|
1624
|
+
|
|
1767
1625
|
/**
|
|
1768
1626
|
* generateSegmentation - Generates cornerstoneTools brush data, given a stack of
|
|
1769
1627
|
* imageIds, images and the cornerstoneTools brushData.
|
|
@@ -1774,15 +1632,13 @@ var generateSegmentationDefaultOptions = {
|
|
|
1774
1632
|
* @param {Object} userOptions Options to pass to the segmentation derivation and `fillSegmentation`.
|
|
1775
1633
|
* @returns {Blob}
|
|
1776
1634
|
*/
|
|
1777
|
-
|
|
1778
1635
|
function generateSegmentation$1(images, inputLabelmaps3D) {
|
|
1779
1636
|
var userOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
1780
1637
|
var isMultiframe = images[0].imageId.includes("?frame");
|
|
1781
|
-
|
|
1782
1638
|
var segmentation = _createSegFromImages(images, isMultiframe, userOptions);
|
|
1783
|
-
|
|
1784
1639
|
return fillSegmentation$1(segmentation, inputLabelmaps3D, userOptions);
|
|
1785
1640
|
}
|
|
1641
|
+
|
|
1786
1642
|
/**
|
|
1787
1643
|
* fillSegmentation - Fills a derived segmentation dataset with cornerstoneTools `LabelMap3D` data.
|
|
1788
1644
|
*
|
|
@@ -1791,31 +1647,26 @@ function generateSegmentation$1(images, inputLabelmaps3D) {
|
|
|
1791
1647
|
* @param {Object} userOptions Options object to override default options.
|
|
1792
1648
|
* @returns {Blob} description
|
|
1793
1649
|
*/
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
1650
|
function fillSegmentation$1(segmentation, inputLabelmaps3D) {
|
|
1797
1651
|
var userOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
1798
|
-
var options = Object.assign({}, generateSegmentationDefaultOptions, userOptions);
|
|
1652
|
+
var options = Object.assign({}, generateSegmentationDefaultOptions, userOptions);
|
|
1799
1653
|
|
|
1654
|
+
// Use another variable so we don't redefine labelmaps3D.
|
|
1800
1655
|
var labelmaps3D = Array.isArray(inputLabelmaps3D) ? inputLabelmaps3D : [inputLabelmaps3D];
|
|
1801
1656
|
var numberOfFrames = 0;
|
|
1802
1657
|
var referencedFramesPerLabelmap = [];
|
|
1803
|
-
|
|
1804
|
-
var _loop = function _loop(labelmapIndex) {
|
|
1658
|
+
var _loop = function _loop() {
|
|
1805
1659
|
var labelmap3D = labelmaps3D[labelmapIndex];
|
|
1806
1660
|
var labelmaps2D = labelmap3D.labelmaps2D,
|
|
1807
|
-
|
|
1661
|
+
metadata = labelmap3D.metadata;
|
|
1808
1662
|
var referencedFramesPerSegment = [];
|
|
1809
|
-
|
|
1810
1663
|
for (var i = 1; i < metadata.length; i++) {
|
|
1811
1664
|
if (metadata[i]) {
|
|
1812
1665
|
referencedFramesPerSegment[i] = [];
|
|
1813
1666
|
}
|
|
1814
1667
|
}
|
|
1815
|
-
|
|
1816
1668
|
var _loop2 = function _loop2(_i) {
|
|
1817
1669
|
var labelmap2D = labelmaps2D[_i];
|
|
1818
|
-
|
|
1819
1670
|
if (labelmaps2D[_i]) {
|
|
1820
1671
|
var segmentsOnLabelmap = labelmap2D.segmentsOnLabelmap;
|
|
1821
1672
|
segmentsOnLabelmap.forEach(function (segmentIndex) {
|
|
@@ -1826,47 +1677,38 @@ function fillSegmentation$1(segmentation, inputLabelmaps3D) {
|
|
|
1826
1677
|
});
|
|
1827
1678
|
}
|
|
1828
1679
|
};
|
|
1829
|
-
|
|
1830
1680
|
for (var _i = 0; _i < labelmaps2D.length; _i++) {
|
|
1831
1681
|
_loop2(_i);
|
|
1832
1682
|
}
|
|
1833
|
-
|
|
1834
1683
|
referencedFramesPerLabelmap[labelmapIndex] = referencedFramesPerSegment;
|
|
1835
1684
|
};
|
|
1836
|
-
|
|
1837
1685
|
for (var labelmapIndex = 0; labelmapIndex < labelmaps3D.length; labelmapIndex++) {
|
|
1838
|
-
_loop(
|
|
1686
|
+
_loop();
|
|
1839
1687
|
}
|
|
1840
|
-
|
|
1841
1688
|
segmentation.setNumberOfFrames(numberOfFrames);
|
|
1842
|
-
|
|
1843
1689
|
for (var _labelmapIndex = 0; _labelmapIndex < labelmaps3D.length; _labelmapIndex++) {
|
|
1844
1690
|
var referencedFramesPerSegment = referencedFramesPerLabelmap[_labelmapIndex];
|
|
1845
1691
|
var labelmap3D = labelmaps3D[_labelmapIndex];
|
|
1846
1692
|
var metadata = labelmap3D.metadata;
|
|
1847
|
-
|
|
1848
1693
|
for (var segmentIndex = 1; segmentIndex < referencedFramesPerSegment.length; segmentIndex++) {
|
|
1849
1694
|
var referencedFrameIndicies = referencedFramesPerSegment[segmentIndex];
|
|
1850
|
-
|
|
1851
1695
|
if (referencedFrameIndicies) {
|
|
1852
1696
|
// Frame numbers start from 1.
|
|
1853
1697
|
var referencedFrameNumbers = referencedFrameIndicies.map(function (element) {
|
|
1854
1698
|
return element + 1;
|
|
1855
1699
|
});
|
|
1856
1700
|
var segmentMetadata = metadata[segmentIndex];
|
|
1857
|
-
|
|
1858
1701
|
var labelmaps = _getLabelmapsFromRefernecedFrameIndicies(labelmap3D, referencedFrameIndicies);
|
|
1859
|
-
|
|
1860
1702
|
segmentation.addSegmentFromLabelmap(segmentMetadata, labelmaps, segmentIndex, referencedFrameNumbers);
|
|
1861
1703
|
}
|
|
1862
1704
|
}
|
|
1863
1705
|
}
|
|
1864
|
-
|
|
1865
1706
|
if (options.rleEncode) {
|
|
1866
|
-
var rleEncodedFrames = encode(segmentation.dataset.PixelData, numberOfFrames, segmentation.dataset.Rows, segmentation.dataset.Columns);
|
|
1707
|
+
var rleEncodedFrames = encode(segmentation.dataset.PixelData, numberOfFrames, segmentation.dataset.Rows, segmentation.dataset.Columns);
|
|
1708
|
+
|
|
1709
|
+
// Must use fractional now to RLE encode, as the DICOM standard only allows BitStored && BitsAllocated
|
|
1867
1710
|
// to be 1 for BINARY. This is not ideal and there should be a better format for compression in this manner
|
|
1868
1711
|
// added to the standard.
|
|
1869
|
-
|
|
1870
1712
|
segmentation.assignToDataset({
|
|
1871
1713
|
BitsAllocated: "8",
|
|
1872
1714
|
BitsStored: "8",
|
|
@@ -1885,22 +1727,19 @@ function fillSegmentation$1(segmentation, inputLabelmaps3D) {
|
|
|
1885
1727
|
// If no rleEncoding, at least bitpack the data.
|
|
1886
1728
|
segmentation.bitPackPixelData();
|
|
1887
1729
|
}
|
|
1888
|
-
|
|
1889
1730
|
var segBlob = datasetToBlob(segmentation.dataset);
|
|
1890
1731
|
return segBlob;
|
|
1891
1732
|
}
|
|
1892
|
-
|
|
1893
1733
|
function _getLabelmapsFromRefernecedFrameIndicies(labelmap3D, referencedFrameIndicies) {
|
|
1894
1734
|
var labelmaps2D = labelmap3D.labelmaps2D;
|
|
1895
1735
|
var labelmaps = [];
|
|
1896
|
-
|
|
1897
1736
|
for (var i = 0; i < referencedFrameIndicies.length; i++) {
|
|
1898
1737
|
var frame = referencedFrameIndicies[i];
|
|
1899
1738
|
labelmaps.push(labelmaps2D[frame].pixelData);
|
|
1900
1739
|
}
|
|
1901
|
-
|
|
1902
1740
|
return labelmaps;
|
|
1903
1741
|
}
|
|
1742
|
+
|
|
1904
1743
|
/**
|
|
1905
1744
|
* _createSegFromImages - description
|
|
1906
1745
|
*
|
|
@@ -1908,11 +1747,8 @@ function _getLabelmapsFromRefernecedFrameIndicies(labelmap3D, referencedFrameInd
|
|
|
1908
1747
|
* @param {Boolean} isMultiframe Whether the images are multiframe.
|
|
1909
1748
|
* @returns {Object} The Seg derived dataSet.
|
|
1910
1749
|
*/
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
1750
|
function _createSegFromImages(images, isMultiframe, options) {
|
|
1914
1751
|
var datasets = [];
|
|
1915
|
-
|
|
1916
1752
|
if (isMultiframe) {
|
|
1917
1753
|
var image = images[0];
|
|
1918
1754
|
var arrayBuffer = image.data.byteArray.buffer;
|
|
@@ -1924,19 +1760,16 @@ function _createSegFromImages(images, isMultiframe, options) {
|
|
|
1924
1760
|
for (var i = 0; i < images.length; i++) {
|
|
1925
1761
|
var _image = images[i];
|
|
1926
1762
|
var _arrayBuffer = _image.data.byteArray.buffer;
|
|
1927
|
-
|
|
1928
1763
|
var _dicomData = DicomMessage.readFile(_arrayBuffer);
|
|
1929
|
-
|
|
1930
1764
|
var _dataset = DicomMetaDictionary$1.naturalizeDataset(_dicomData.dict);
|
|
1931
|
-
|
|
1932
1765
|
_dataset._meta = DicomMetaDictionary$1.namifyDataset(_dicomData.meta);
|
|
1933
1766
|
datasets.push(_dataset);
|
|
1934
1767
|
}
|
|
1935
1768
|
}
|
|
1936
|
-
|
|
1937
1769
|
var multiframe = Normalizer$1.normalizeToDataset(datasets);
|
|
1938
1770
|
return new SegmentationDerivation([multiframe], options);
|
|
1939
1771
|
}
|
|
1772
|
+
|
|
1940
1773
|
/**
|
|
1941
1774
|
* generateToolState - Given a set of cornrstoneTools imageIds and a Segmentation buffer,
|
|
1942
1775
|
* derive cornerstoneTools toolState and brush metadata.
|
|
@@ -1953,8 +1786,6 @@ function _createSegFromImages(images, isMultiframe, options) {
|
|
|
1953
1786
|
* @return {[][][]} 3D list containing the track of segments per frame for each labelMap
|
|
1954
1787
|
* (available only for the overlapping case).
|
|
1955
1788
|
*/
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
1789
|
function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
1959
1790
|
var skipOverlapping = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
1960
1791
|
var tolerance = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1e-3;
|
|
@@ -1965,44 +1796,36 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
|
1965
1796
|
var imagePlaneModule = metadataProvider.get("imagePlaneModule", imageIds[0]);
|
|
1966
1797
|
var generalSeriesModule = metadataProvider.get("generalSeriesModule", imageIds[0]);
|
|
1967
1798
|
var SeriesInstanceUID = generalSeriesModule.seriesInstanceUID;
|
|
1968
|
-
|
|
1969
1799
|
if (!imagePlaneModule) {
|
|
1970
1800
|
console.warn("Insufficient metadata, imagePlaneModule missing.");
|
|
1971
1801
|
}
|
|
1802
|
+
var ImageOrientationPatient = Array.isArray(imagePlaneModule.rowCosines) ? [].concat(_toConsumableArray(imagePlaneModule.rowCosines), _toConsumableArray(imagePlaneModule.columnCosines)) : [imagePlaneModule.rowCosines.x, imagePlaneModule.rowCosines.y, imagePlaneModule.rowCosines.z, imagePlaneModule.columnCosines.x, imagePlaneModule.columnCosines.y, imagePlaneModule.columnCosines.z];
|
|
1972
1803
|
|
|
1973
|
-
|
|
1974
|
-
|
|
1804
|
+
// Get IOP from ref series, compute supported orientations:
|
|
1975
1805
|
var validOrientations = getValidOrientations(ImageOrientationPatient);
|
|
1976
1806
|
var sliceLength = multiframe.Columns * multiframe.Rows;
|
|
1977
1807
|
var segMetadata = getSegmentMetadata(multiframe, SeriesInstanceUID);
|
|
1978
1808
|
var TransferSyntaxUID = multiframe._meta.TransferSyntaxUID.Value[0];
|
|
1979
1809
|
var pixelData;
|
|
1980
|
-
|
|
1981
1810
|
if (TransferSyntaxUID === "1.2.840.10008.1.2.5") {
|
|
1982
1811
|
var rleEncodedFrames = Array.isArray(multiframe.PixelData) ? multiframe.PixelData : [multiframe.PixelData];
|
|
1983
1812
|
pixelData = decode(rleEncodedFrames, multiframe.Rows, multiframe.Columns);
|
|
1984
|
-
|
|
1985
1813
|
if (multiframe.BitsStored === 1) {
|
|
1986
1814
|
console.warn("No implementation for rle + bitbacking.");
|
|
1987
1815
|
return;
|
|
1988
1816
|
}
|
|
1989
1817
|
} else {
|
|
1990
1818
|
pixelData = unpackPixelData(multiframe);
|
|
1991
|
-
|
|
1992
1819
|
if (!pixelData) {
|
|
1993
1820
|
throw new Error("Fractional segmentations are not yet supported");
|
|
1994
1821
|
}
|
|
1995
1822
|
}
|
|
1996
|
-
|
|
1997
1823
|
var orientation = checkOrientation(multiframe, validOrientations, [imagePlaneModule.rows, imagePlaneModule.columns, imageIds.length], tolerance);
|
|
1998
1824
|
var overlapping = false;
|
|
1999
|
-
|
|
2000
1825
|
if (!skipOverlapping) {
|
|
2001
1826
|
overlapping = checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance);
|
|
2002
1827
|
}
|
|
2003
|
-
|
|
2004
1828
|
var insertFunction;
|
|
2005
|
-
|
|
2006
1829
|
switch (orientation) {
|
|
2007
1830
|
case "Planar":
|
|
2008
1831
|
if (overlapping) {
|
|
@@ -2010,28 +1833,24 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
|
2010
1833
|
} else {
|
|
2011
1834
|
insertFunction = insertPixelDataPlanar;
|
|
2012
1835
|
}
|
|
2013
|
-
|
|
2014
1836
|
break;
|
|
2015
|
-
|
|
2016
1837
|
case "Perpendicular":
|
|
2017
1838
|
//insertFunction = insertPixelDataPerpendicular;
|
|
2018
1839
|
throw new Error("Segmentations orthogonal to the acquisition plane of the source data are not yet supported.");
|
|
2019
|
-
|
|
2020
1840
|
case "Oblique":
|
|
2021
1841
|
throw new Error("Segmentations oblique to the acquisition plane of the source data are not yet supported.");
|
|
2022
1842
|
}
|
|
1843
|
+
|
|
2023
1844
|
/* if SEGs are overlapping:
|
|
2024
1845
|
1) the labelmapBuffer will contain M volumes which have non-overlapping segments;
|
|
2025
1846
|
2) segmentsOnFrame will have M * numberOfFrames values to track in which labelMap are the segments;
|
|
2026
1847
|
3) insertFunction will return the number of LabelMaps
|
|
2027
1848
|
4) generateToolState return is an array*/
|
|
2028
1849
|
|
|
2029
|
-
|
|
2030
1850
|
var segmentsOnFrameArray = [];
|
|
2031
1851
|
segmentsOnFrameArray[0] = [];
|
|
2032
1852
|
var segmentsOnFrame = [];
|
|
2033
1853
|
var arrayBufferLength = sliceLength * imageIds.length * 2; // 2 bytes per label voxel in cst4.
|
|
2034
|
-
|
|
2035
1854
|
var labelmapBufferArray = [];
|
|
2036
1855
|
labelmapBufferArray[0] = new ArrayBuffer(arrayBufferLength);
|
|
2037
1856
|
insertFunction(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance);
|
|
@@ -2041,7 +1860,9 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
|
2041
1860
|
segmentsOnFrame: segmentsOnFrame,
|
|
2042
1861
|
segmentsOnFrameArray: segmentsOnFrameArray
|
|
2043
1862
|
};
|
|
2044
|
-
}
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
// function insertPixelDataPerpendicular(
|
|
2045
1866
|
// segmentsOnFrame,
|
|
2046
1867
|
// labelmapBuffer,
|
|
2047
1868
|
// pixelData,
|
|
@@ -2056,23 +1877,30 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
|
2056
1877
|
// Rows,
|
|
2057
1878
|
// Columns
|
|
2058
1879
|
// } = multiframe;
|
|
1880
|
+
|
|
2059
1881
|
// const firstImagePlaneModule = metadataProvider.get(
|
|
2060
1882
|
// "imagePlaneModule",
|
|
2061
1883
|
// imageIds[0]
|
|
2062
1884
|
// );
|
|
1885
|
+
|
|
2063
1886
|
// const lastImagePlaneModule = metadataProvider.get(
|
|
2064
1887
|
// "imagePlaneModule",
|
|
2065
1888
|
// imageIds[imageIds.length - 1]
|
|
2066
1889
|
// );
|
|
1890
|
+
|
|
2067
1891
|
// console.log(firstImagePlaneModule);
|
|
2068
1892
|
// console.log(lastImagePlaneModule);
|
|
1893
|
+
|
|
2069
1894
|
// const corners = [
|
|
2070
1895
|
// ...getCorners(firstImagePlaneModule),
|
|
2071
1896
|
// ...getCorners(lastImagePlaneModule)
|
|
2072
1897
|
// ];
|
|
1898
|
+
|
|
2073
1899
|
// console.log(`corners:`);
|
|
2074
1900
|
// console.log(corners);
|
|
1901
|
+
|
|
2075
1902
|
// const indexToWorld = mat4.create();
|
|
1903
|
+
|
|
2076
1904
|
// const ippFirstFrame = firstImagePlaneModule.imagePositionPatient;
|
|
2077
1905
|
// const rowCosines = Array.isArray(firstImagePlaneModule.rowCosines)
|
|
2078
1906
|
// ? [...firstImagePlaneModule.rowCosines]
|
|
@@ -2081,6 +1909,7 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
|
2081
1909
|
// firstImagePlaneModule.rowCosines.y,
|
|
2082
1910
|
// firstImagePlaneModule.rowCosines.z
|
|
2083
1911
|
// ];
|
|
1912
|
+
|
|
2084
1913
|
// const columnCosines = Array.isArray(firstImagePlaneModule.columnCosines)
|
|
2085
1914
|
// ? [...firstImagePlaneModule.columnCosines]
|
|
2086
1915
|
// : [
|
|
@@ -2088,7 +1917,9 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
|
2088
1917
|
// firstImagePlaneModule.columnCosines.y,
|
|
2089
1918
|
// firstImagePlaneModule.columnCosines.z
|
|
2090
1919
|
// ];
|
|
1920
|
+
|
|
2091
1921
|
// const { pixelSpacing } = firstImagePlaneModule;
|
|
1922
|
+
|
|
2092
1923
|
// mat4.set(
|
|
2093
1924
|
// indexToWorld,
|
|
2094
1925
|
// // Column 1
|
|
@@ -2112,36 +1943,50 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
|
2112
1943
|
// 0,
|
|
2113
1944
|
// 1
|
|
2114
1945
|
// );
|
|
1946
|
+
|
|
2115
1947
|
// // TODO -> Get origin and (x,y,z) increments to build a translation matrix:
|
|
2116
1948
|
// // TODO -> Equation C.7.6.2.1-1
|
|
1949
|
+
|
|
2117
1950
|
// // | cx*di rx* Xx 0 | |x|
|
|
2118
1951
|
// // | cy*di ry Xy 0 | |y|
|
|
2119
1952
|
// // | cz*di rz Xz 0 | |z|
|
|
2120
1953
|
// // | tx ty tz 1 | |1|
|
|
1954
|
+
|
|
2121
1955
|
// // const [
|
|
2122
1956
|
// // 0, 0 , 0 , 0,
|
|
2123
1957
|
// // 0, 0 , 0 , 0,
|
|
2124
1958
|
// // 0, 0 , 0 , 0,
|
|
2125
1959
|
// // ipp[0], ipp[1] , ipp[2] , 1,
|
|
2126
1960
|
// // ]
|
|
1961
|
+
|
|
2127
1962
|
// // Each frame:
|
|
1963
|
+
|
|
2128
1964
|
// // Find which corner the first voxel lines up with (one of 8 corners.)
|
|
1965
|
+
|
|
2129
1966
|
// // Find how i,j,k orient with respect to source volume.
|
|
2130
1967
|
// // Go through each frame, find location in source to start, and whether to increment +/ix,+/-y,+/-z
|
|
2131
1968
|
// // through each voxel.
|
|
1969
|
+
|
|
2132
1970
|
// // [1,0,0,0,1,0]
|
|
1971
|
+
|
|
2133
1972
|
// // const [
|
|
1973
|
+
|
|
2134
1974
|
// // ]
|
|
1975
|
+
|
|
2135
1976
|
// // Invert transformation matrix to get worldToIndex
|
|
1977
|
+
|
|
2136
1978
|
// // Apply world to index on each point to fill up the matrix.
|
|
1979
|
+
|
|
2137
1980
|
// // const sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence
|
|
2138
1981
|
// // ? SharedFunctionalGroupsSequence.PlaneOrientationSequence
|
|
2139
1982
|
// // .ImageOrientationPatient
|
|
2140
1983
|
// // : undefined;
|
|
2141
1984
|
// // const sliceLength = Columns * Rows;
|
|
2142
1985
|
// }
|
|
1986
|
+
|
|
2143
1987
|
// function getCorners(imagePlaneModule) {
|
|
2144
1988
|
// // console.log(imagePlaneModule);
|
|
1989
|
+
|
|
2145
1990
|
// const {
|
|
2146
1991
|
// rows,
|
|
2147
1992
|
// columns,
|
|
@@ -2151,18 +1996,22 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
|
2151
1996
|
// rowPixelSpacing,
|
|
2152
1997
|
// columnPixelSpacing
|
|
2153
1998
|
// } = imagePlaneModule;
|
|
1999
|
+
|
|
2154
2000
|
// const rowLength = columns * columnPixelSpacing;
|
|
2155
2001
|
// const columnLength = rows * rowPixelSpacing;
|
|
2002
|
+
|
|
2156
2003
|
// const entireRowVector = [
|
|
2157
2004
|
// rowLength * columnCosines[0],
|
|
2158
2005
|
// rowLength * columnCosines[1],
|
|
2159
2006
|
// rowLength * columnCosines[2]
|
|
2160
2007
|
// ];
|
|
2008
|
+
|
|
2161
2009
|
// const entireColumnVector = [
|
|
2162
2010
|
// columnLength * rowCosines[0],
|
|
2163
2011
|
// columnLength * rowCosines[1],
|
|
2164
2012
|
// columnLength * rowCosines[2]
|
|
2165
2013
|
// ];
|
|
2014
|
+
|
|
2166
2015
|
// const topLeft = [ipp[0], ipp[1], ipp[2]];
|
|
2167
2016
|
// const topRight = [
|
|
2168
2017
|
// topLeft[0] + entireRowVector[0],
|
|
@@ -2174,11 +2023,13 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
|
2174
2023
|
// topLeft[1] + entireColumnVector[1],
|
|
2175
2024
|
// topLeft[2] + entireColumnVector[2]
|
|
2176
2025
|
// ];
|
|
2026
|
+
|
|
2177
2027
|
// const bottomRight = [
|
|
2178
2028
|
// bottomLeft[0] + entireRowVector[0],
|
|
2179
2029
|
// bottomLeft[1] + entireRowVector[1],
|
|
2180
2030
|
// bottomLeft[2] + entireRowVector[2]
|
|
2181
2031
|
// ];
|
|
2032
|
+
|
|
2182
2033
|
// return [topLeft, topRight, bottomLeft, bottomRight];
|
|
2183
2034
|
// }
|
|
2184
2035
|
|
|
@@ -2194,37 +2045,27 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
|
|
|
2194
2045
|
*
|
|
2195
2046
|
* @returns {String} Returns the imageId
|
|
2196
2047
|
*/
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
2048
|
function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadataProvider, tolerance) {
|
|
2200
2049
|
var imageId = undefined;
|
|
2201
|
-
|
|
2202
2050
|
if (!multiframe) {
|
|
2203
2051
|
return imageId;
|
|
2204
2052
|
}
|
|
2205
|
-
|
|
2206
2053
|
var FrameOfReferenceUID = multiframe.FrameOfReferenceUID,
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2054
|
+
PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
2055
|
+
SourceImageSequence = multiframe.SourceImageSequence,
|
|
2056
|
+
ReferencedSeriesSequence = multiframe.ReferencedSeriesSequence;
|
|
2211
2057
|
if (!PerFrameFunctionalGroupsSequence || PerFrameFunctionalGroupsSequence.length === 0) {
|
|
2212
2058
|
return imageId;
|
|
2213
2059
|
}
|
|
2214
|
-
|
|
2215
2060
|
var PerFrameFunctionalGroup = PerFrameFunctionalGroupsSequence[frameSegment];
|
|
2216
|
-
|
|
2217
2061
|
if (!PerFrameFunctionalGroup) {
|
|
2218
2062
|
return imageId;
|
|
2219
2063
|
}
|
|
2220
|
-
|
|
2221
2064
|
var frameSourceImageSequence = undefined;
|
|
2222
|
-
|
|
2223
2065
|
if (SourceImageSequence && SourceImageSequence.length !== 0) {
|
|
2224
2066
|
frameSourceImageSequence = SourceImageSequence[frameSegment];
|
|
2225
2067
|
} else if (PerFrameFunctionalGroup.DerivationImageSequence) {
|
|
2226
2068
|
var DerivationImageSequence = PerFrameFunctionalGroup.DerivationImageSequence;
|
|
2227
|
-
|
|
2228
2069
|
if (Array.isArray(DerivationImageSequence)) {
|
|
2229
2070
|
if (DerivationImageSequence.length !== 0) {
|
|
2230
2071
|
DerivationImageSequence = DerivationImageSequence[0];
|
|
@@ -2232,10 +2073,8 @@ function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadata
|
|
|
2232
2073
|
DerivationImageSequence = undefined;
|
|
2233
2074
|
}
|
|
2234
2075
|
}
|
|
2235
|
-
|
|
2236
2076
|
if (DerivationImageSequence) {
|
|
2237
2077
|
frameSourceImageSequence = DerivationImageSequence.SourceImageSequence;
|
|
2238
|
-
|
|
2239
2078
|
if (Array.isArray(frameSourceImageSequence)) {
|
|
2240
2079
|
if (frameSourceImageSequence.length !== 0) {
|
|
2241
2080
|
frameSourceImageSequence = frameSourceImageSequence[0];
|
|
@@ -2245,40 +2084,36 @@ function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadata
|
|
|
2245
2084
|
}
|
|
2246
2085
|
}
|
|
2247
2086
|
}
|
|
2248
|
-
|
|
2249
2087
|
if (frameSourceImageSequence) {
|
|
2250
2088
|
imageId = getImageIdOfSourceImagebySourceImageSequence(frameSourceImageSequence, imageIds, metadataProvider);
|
|
2251
2089
|
}
|
|
2252
|
-
|
|
2253
2090
|
if (imageId === undefined && ReferencedSeriesSequence) {
|
|
2254
2091
|
var referencedSeriesSequence = Array.isArray(ReferencedSeriesSequence) ? ReferencedSeriesSequence[0] : ReferencedSeriesSequence;
|
|
2255
2092
|
var ReferencedSeriesInstanceUID = referencedSeriesSequence.SeriesInstanceUID;
|
|
2256
2093
|
imageId = getImageIdOfSourceImagebyGeometry(ReferencedSeriesInstanceUID, FrameOfReferenceUID, PerFrameFunctionalGroup, imageIds, metadataProvider, tolerance);
|
|
2257
2094
|
}
|
|
2258
|
-
|
|
2259
2095
|
return imageId;
|
|
2260
2096
|
}
|
|
2097
|
+
|
|
2261
2098
|
/**
|
|
2262
2099
|
* Checks if there is any overlapping segmentations.
|
|
2263
2100
|
* @returns {boolean} Returns a flag if segmentations overlapping
|
|
2264
2101
|
*/
|
|
2265
2102
|
|
|
2266
|
-
|
|
2267
2103
|
function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance) {
|
|
2268
2104
|
var SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2105
|
+
PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
2106
|
+
SegmentSequence = multiframe.SegmentSequence,
|
|
2107
|
+
Rows = multiframe.Rows,
|
|
2108
|
+
Columns = multiframe.Columns;
|
|
2273
2109
|
var numberOfSegs = SegmentSequence.length;
|
|
2274
|
-
|
|
2275
2110
|
if (numberOfSegs < 2) {
|
|
2276
2111
|
return false;
|
|
2277
2112
|
}
|
|
2278
|
-
|
|
2279
2113
|
var sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
|
|
2280
2114
|
var sliceLength = Columns * Rows;
|
|
2281
2115
|
var groupsLen = PerFrameFunctionalGroupsSequence.length;
|
|
2116
|
+
|
|
2282
2117
|
/** sort groupsLen to have all the segments for each frame in an array
|
|
2283
2118
|
* frame 2 : 1, 2
|
|
2284
2119
|
* frame 4 : 1, 3
|
|
@@ -2286,29 +2121,22 @@ function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations
|
|
|
2286
2121
|
*/
|
|
2287
2122
|
|
|
2288
2123
|
var frameSegmentsMapping = new Map();
|
|
2289
|
-
|
|
2290
|
-
var _loop3 = function _loop3(frameSegment) {
|
|
2124
|
+
var _loop3 = function _loop3() {
|
|
2291
2125
|
var segmentIndex = getSegmentIndex(multiframe, frameSegment);
|
|
2292
|
-
|
|
2293
2126
|
if (segmentIndex === undefined) {
|
|
2294
2127
|
console.warn("Could not retrieve the segment index for frame segment " + frameSegment + ", skipping this frame.");
|
|
2295
2128
|
return "continue";
|
|
2296
2129
|
}
|
|
2297
|
-
|
|
2298
2130
|
var imageId = findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadataProvider, tolerance);
|
|
2299
|
-
|
|
2300
2131
|
if (!imageId) {
|
|
2301
2132
|
console.warn("Image not present in stack, can't import frame : " + frameSegment + ".");
|
|
2302
2133
|
return "continue";
|
|
2303
2134
|
}
|
|
2304
|
-
|
|
2305
2135
|
var imageIdIndex = imageIds.findIndex(function (element) {
|
|
2306
2136
|
return element === imageId;
|
|
2307
2137
|
});
|
|
2308
|
-
|
|
2309
2138
|
if (frameSegmentsMapping.has(imageIdIndex)) {
|
|
2310
2139
|
var segmentArray = frameSegmentsMapping.get(imageIdIndex);
|
|
2311
|
-
|
|
2312
2140
|
if (!segmentArray.includes(frameSegment)) {
|
|
2313
2141
|
segmentArray.push(frameSegment);
|
|
2314
2142
|
frameSegmentsMapping.set(imageIdIndex, segmentArray);
|
|
@@ -2317,41 +2145,31 @@ function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations
|
|
|
2317
2145
|
frameSegmentsMapping.set(imageIdIndex, [frameSegment]);
|
|
2318
2146
|
}
|
|
2319
2147
|
};
|
|
2320
|
-
|
|
2321
2148
|
for (var frameSegment = 0; frameSegment < groupsLen; ++frameSegment) {
|
|
2322
|
-
var _ret = _loop3(
|
|
2323
|
-
|
|
2149
|
+
var _ret = _loop3();
|
|
2324
2150
|
if (_ret === "continue") continue;
|
|
2325
2151
|
}
|
|
2326
|
-
|
|
2327
2152
|
var _iterator = _createForOfIteratorHelper(frameSegmentsMapping.entries()),
|
|
2328
|
-
|
|
2329
|
-
|
|
2153
|
+
_step;
|
|
2330
2154
|
try {
|
|
2331
2155
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
2332
2156
|
var _step$value = _slicedToArray(_step.value, 2),
|
|
2333
|
-
|
|
2334
|
-
|
|
2157
|
+
role = _step$value[1];
|
|
2335
2158
|
var temp2DArray = new Uint16Array(sliceLength).fill(0);
|
|
2336
|
-
|
|
2337
2159
|
for (var i = 0; i < role.length; ++i) {
|
|
2338
2160
|
var _frameSegment = role[i];
|
|
2339
2161
|
var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[_frameSegment];
|
|
2340
2162
|
var ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
|
|
2341
2163
|
var pixelDataI2D = ndarray(new Uint8Array(pixelData.buffer, _frameSegment * sliceLength, sliceLength), [Rows, Columns]);
|
|
2342
2164
|
var alignedPixelDataI = alignPixelDataWithSourceData(pixelDataI2D, ImageOrientationPatientI, validOrientations, tolerance);
|
|
2343
|
-
|
|
2344
2165
|
if (!alignedPixelDataI) {
|
|
2345
2166
|
console.warn("Individual SEG frames are out of plane with respect to the first SEG frame, this is not yet supported, skipping this frame.");
|
|
2346
2167
|
continue;
|
|
2347
2168
|
}
|
|
2348
|
-
|
|
2349
2169
|
var data = alignedPixelDataI.data;
|
|
2350
|
-
|
|
2351
2170
|
for (var j = 0, len = data.length; j < len; ++j) {
|
|
2352
2171
|
if (data[j] !== 0) {
|
|
2353
2172
|
temp2DArray[j]++;
|
|
2354
|
-
|
|
2355
2173
|
if (temp2DArray[j] > 1) {
|
|
2356
2174
|
return true;
|
|
2357
2175
|
}
|
|
@@ -2364,27 +2182,29 @@ function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations
|
|
|
2364
2182
|
} finally {
|
|
2365
2183
|
_iterator.f();
|
|
2366
2184
|
}
|
|
2367
|
-
|
|
2368
2185
|
return false;
|
|
2369
2186
|
}
|
|
2370
|
-
|
|
2371
2187
|
function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance) {
|
|
2372
2188
|
var SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2189
|
+
PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
2190
|
+
Rows = multiframe.Rows,
|
|
2191
|
+
Columns = multiframe.Columns;
|
|
2376
2192
|
var sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
|
|
2377
2193
|
var sliceLength = Columns * Rows;
|
|
2378
2194
|
var arrayBufferLength = sliceLength * imageIds.length * 2; // 2 bytes per label voxel in cst4.
|
|
2379
|
-
// indicate the number of labelMaps
|
|
2380
2195
|
|
|
2381
|
-
|
|
2196
|
+
// indicate the number of labelMaps
|
|
2197
|
+
var M = 1;
|
|
2382
2198
|
|
|
2383
|
-
|
|
2199
|
+
// indicate the current labelMap array index;
|
|
2200
|
+
var m = 0;
|
|
2384
2201
|
|
|
2385
|
-
|
|
2202
|
+
// temp array for checking overlaps
|
|
2203
|
+
var tempBuffer = labelmapBufferArray[m].slice(0);
|
|
2386
2204
|
|
|
2205
|
+
// temp list for checking overlaps
|
|
2387
2206
|
var tempSegmentsOnFrame = cloneDeep(segmentsOnFrameArray[m]);
|
|
2207
|
+
|
|
2388
2208
|
/** split overlapping SEGs algorithm for each segment:
|
|
2389
2209
|
* A) copy the labelmapBuffer in the array with index 0
|
|
2390
2210
|
* B) add the segment pixel per pixel on the copied buffer from (A)
|
|
@@ -2393,43 +2213,33 @@ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray,
|
|
|
2393
2213
|
*/
|
|
2394
2214
|
|
|
2395
2215
|
var numberOfSegs = multiframe.SegmentSequence.length;
|
|
2396
|
-
|
|
2397
2216
|
for (var segmentIndexToProcess = 1; segmentIndexToProcess <= numberOfSegs; ++segmentIndexToProcess) {
|
|
2398
|
-
var _loop4 = function _loop4(_i2
|
|
2217
|
+
var _loop4 = function _loop4(_i2) {
|
|
2399
2218
|
var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[_i2];
|
|
2400
2219
|
var segmentIndex = getSegmentIndex(multiframe, _i2);
|
|
2401
|
-
|
|
2402
2220
|
if (segmentIndex === undefined) {
|
|
2403
2221
|
throw new Error("Could not retrieve the segment index. Aborting segmentation loading.");
|
|
2404
2222
|
}
|
|
2405
|
-
|
|
2406
2223
|
if (segmentIndex !== segmentIndexToProcess) {
|
|
2407
2224
|
i = _i2;
|
|
2408
2225
|
return "continue";
|
|
2409
2226
|
}
|
|
2410
|
-
|
|
2411
2227
|
var ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
|
|
2412
2228
|
var pixelDataI2D = ndarray(new Uint8Array(pixelData.buffer, _i2 * sliceLength, sliceLength), [Rows, Columns]);
|
|
2413
2229
|
var alignedPixelDataI = alignPixelDataWithSourceData(pixelDataI2D, ImageOrientationPatientI, validOrientations, tolerance);
|
|
2414
|
-
|
|
2415
2230
|
if (!alignedPixelDataI) {
|
|
2416
2231
|
throw new Error("Individual SEG frames are out of plane with respect to the first SEG frame. " + "This is not yet supported. Aborting segmentation loading.");
|
|
2417
2232
|
}
|
|
2418
|
-
|
|
2419
2233
|
var imageId = findReferenceSourceImageId(multiframe, _i2, imageIds, metadataProvider, tolerance);
|
|
2420
|
-
|
|
2421
2234
|
if (!imageId) {
|
|
2422
2235
|
console.warn("Image not present in stack, can't import frame : " + _i2 + ".");
|
|
2423
2236
|
i = _i2;
|
|
2424
2237
|
return "continue";
|
|
2425
2238
|
}
|
|
2426
|
-
|
|
2427
2239
|
var sourceImageMetadata = metadataProvider.get("instance", imageId);
|
|
2428
|
-
|
|
2429
2240
|
if (Rows !== sourceImageMetadata.Rows || Columns !== sourceImageMetadata.Columns) {
|
|
2430
2241
|
throw new Error("Individual SEG frames have different geometry dimensions (Rows and Columns) " + "respect to the source image reference frame. This is not yet supported. " + "Aborting segmentation loading. ");
|
|
2431
2242
|
}
|
|
2432
|
-
|
|
2433
2243
|
var imageIdIndex = imageIds.findIndex(function (element) {
|
|
2434
2244
|
return element === imageId;
|
|
2435
2245
|
});
|
|
@@ -2438,18 +2248,15 @@ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray,
|
|
|
2438
2248
|
var labelmap2DView = new Uint16Array(tempBuffer, byteOffset, sliceLength);
|
|
2439
2249
|
var data = alignedPixelDataI.data;
|
|
2440
2250
|
var segmentOnFrame = false;
|
|
2441
|
-
|
|
2442
2251
|
for (var j = 0, len = alignedPixelDataI.data.length; j < len; ++j) {
|
|
2443
2252
|
if (data[j]) {
|
|
2444
2253
|
if (labelmap2DView[j] !== 0) {
|
|
2445
2254
|
m++;
|
|
2446
|
-
|
|
2447
2255
|
if (m >= M) {
|
|
2448
2256
|
labelmapBufferArray[m] = new ArrayBuffer(arrayBufferLength);
|
|
2449
2257
|
segmentsOnFrameArray[m] = [];
|
|
2450
2258
|
M++;
|
|
2451
2259
|
}
|
|
2452
|
-
|
|
2453
2260
|
tempBuffer = labelmapBufferArray[m].slice(0);
|
|
2454
2261
|
tempSegmentsOnFrame = cloneDeep(segmentsOnFrameArray[m]);
|
|
2455
2262
|
_i2 = 0;
|
|
@@ -2460,83 +2267,65 @@ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray,
|
|
|
2460
2267
|
}
|
|
2461
2268
|
}
|
|
2462
2269
|
}
|
|
2463
|
-
|
|
2464
2270
|
if (segmentOnFrame) {
|
|
2465
2271
|
if (!tempSegmentsOnFrame[imageIdIndex]) {
|
|
2466
2272
|
tempSegmentsOnFrame[imageIdIndex] = [];
|
|
2467
2273
|
}
|
|
2468
|
-
|
|
2469
2274
|
tempSegmentsOnFrame[imageIdIndex].push(segmentIndex);
|
|
2470
|
-
|
|
2471
2275
|
if (!segmentsOnFrame[imageIdIndex]) {
|
|
2472
2276
|
segmentsOnFrame[imageIdIndex] = [];
|
|
2473
2277
|
}
|
|
2474
|
-
|
|
2475
2278
|
segmentsOnFrame[imageIdIndex].push(segmentIndex);
|
|
2476
2279
|
}
|
|
2477
|
-
|
|
2478
2280
|
i = _i2;
|
|
2479
2281
|
};
|
|
2480
|
-
|
|
2481
2282
|
for (var i = 0, groupsLen = PerFrameFunctionalGroupsSequence.length; i < groupsLen; ++i) {
|
|
2482
|
-
var _ret2 = _loop4(i
|
|
2483
|
-
|
|
2283
|
+
var _ret2 = _loop4(i);
|
|
2484
2284
|
if (_ret2 === "continue") continue;
|
|
2485
2285
|
}
|
|
2486
|
-
|
|
2487
2286
|
labelmapBufferArray[m] = tempBuffer.slice(0);
|
|
2488
|
-
segmentsOnFrameArray[m] = cloneDeep(tempSegmentsOnFrame);
|
|
2287
|
+
segmentsOnFrameArray[m] = cloneDeep(tempSegmentsOnFrame);
|
|
2489
2288
|
|
|
2289
|
+
// reset temp variables/buffers for new segment
|
|
2490
2290
|
m = 0;
|
|
2491
2291
|
tempBuffer = labelmapBufferArray[m].slice(0);
|
|
2492
2292
|
tempSegmentsOnFrame = cloneDeep(segmentsOnFrameArray[m]);
|
|
2493
2293
|
}
|
|
2494
2294
|
}
|
|
2495
|
-
|
|
2496
2295
|
var getSegmentIndex = function getSegmentIndex(multiframe, frame) {
|
|
2497
2296
|
var PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
2498
|
-
|
|
2297
|
+
SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence;
|
|
2499
2298
|
var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[frame];
|
|
2500
2299
|
return PerFrameFunctionalGroups && PerFrameFunctionalGroups.SegmentIdentificationSequence ? PerFrameFunctionalGroups.SegmentIdentificationSequence.ReferencedSegmentNumber : SharedFunctionalGroupsSequence.SegmentIdentificationSequence ? SharedFunctionalGroupsSequence.SegmentIdentificationSequence.ReferencedSegmentNumber : undefined;
|
|
2501
2300
|
};
|
|
2502
|
-
|
|
2503
2301
|
function insertPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance) {
|
|
2504
2302
|
var SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2303
|
+
PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
2304
|
+
Rows = multiframe.Rows,
|
|
2305
|
+
Columns = multiframe.Columns;
|
|
2508
2306
|
var sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
|
|
2509
2307
|
var sliceLength = Columns * Rows;
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[_i3];
|
|
2308
|
+
var _loop5 = function _loop5() {
|
|
2309
|
+
var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[i];
|
|
2513
2310
|
var ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
|
|
2514
|
-
var pixelDataI2D = ndarray(new Uint8Array(pixelData.buffer,
|
|
2311
|
+
var pixelDataI2D = ndarray(new Uint8Array(pixelData.buffer, i * sliceLength, sliceLength), [Rows, Columns]);
|
|
2515
2312
|
var alignedPixelDataI = alignPixelDataWithSourceData(pixelDataI2D, ImageOrientationPatientI, validOrientations, tolerance);
|
|
2516
|
-
|
|
2517
2313
|
if (!alignedPixelDataI) {
|
|
2518
2314
|
throw new Error("Individual SEG frames are out of plane with respect to the first SEG frame. " + "This is not yet supported. Aborting segmentation loading.");
|
|
2519
2315
|
}
|
|
2520
|
-
|
|
2521
|
-
var segmentIndex = getSegmentIndex(multiframe, _i3);
|
|
2522
|
-
|
|
2316
|
+
var segmentIndex = getSegmentIndex(multiframe, i);
|
|
2523
2317
|
if (segmentIndex === undefined) {
|
|
2524
2318
|
throw new Error("Could not retrieve the segment index. Aborting segmentation loading.");
|
|
2525
2319
|
}
|
|
2526
|
-
|
|
2527
|
-
var imageId = findReferenceSourceImageId(multiframe, _i3, imageIds, metadataProvider, tolerance);
|
|
2528
|
-
|
|
2320
|
+
var imageId = findReferenceSourceImageId(multiframe, i, imageIds, metadataProvider, tolerance);
|
|
2529
2321
|
if (!imageId) {
|
|
2530
|
-
console.warn("Image not present in stack, can't import frame : " +
|
|
2322
|
+
console.warn("Image not present in stack, can't import frame : " + i + ".");
|
|
2531
2323
|
return "continue";
|
|
2532
2324
|
}
|
|
2533
|
-
|
|
2534
2325
|
var sourceImageMetadata = metadataProvider.get("instance", imageId);
|
|
2535
|
-
|
|
2536
2326
|
if (Rows !== sourceImageMetadata.Rows || Columns !== sourceImageMetadata.Columns) {
|
|
2537
2327
|
throw new Error("Individual SEG frames have different geometry dimensions (Rows and Columns) " + "respect to the source image reference frame. This is not yet supported. " + "Aborting segmentation loading. ");
|
|
2538
2328
|
}
|
|
2539
|
-
|
|
2540
2329
|
var imageIdIndex = imageIds.findIndex(function (element) {
|
|
2541
2330
|
return element === imageId;
|
|
2542
2331
|
});
|
|
@@ -2544,7 +2333,6 @@ function insertPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBu
|
|
|
2544
2333
|
|
|
2545
2334
|
var labelmap2DView = new Uint16Array(labelmapBufferArray[0], byteOffset, sliceLength);
|
|
2546
2335
|
var data = alignedPixelDataI.data;
|
|
2547
|
-
|
|
2548
2336
|
for (var j = 0, len = alignedPixelDataI.data.length; j < len; ++j) {
|
|
2549
2337
|
if (data[j]) {
|
|
2550
2338
|
for (var x = j; x < len; ++x) {
|
|
@@ -2552,46 +2340,40 @@ function insertPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBu
|
|
|
2552
2340
|
labelmap2DView[x] = segmentIndex;
|
|
2553
2341
|
}
|
|
2554
2342
|
}
|
|
2555
|
-
|
|
2556
2343
|
if (!segmentsOnFrame[imageIdIndex]) {
|
|
2557
2344
|
segmentsOnFrame[imageIdIndex] = [];
|
|
2558
2345
|
}
|
|
2559
|
-
|
|
2560
2346
|
segmentsOnFrame[imageIdIndex].push(segmentIndex);
|
|
2561
2347
|
break;
|
|
2562
2348
|
}
|
|
2563
2349
|
}
|
|
2564
2350
|
};
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
var _ret3 = _loop5(groupsLen, _i3);
|
|
2568
|
-
|
|
2351
|
+
for (var i = 0, groupsLen = PerFrameFunctionalGroupsSequence.length; i < groupsLen; ++i) {
|
|
2352
|
+
var _ret3 = _loop5();
|
|
2569
2353
|
if (_ret3 === "continue") continue;
|
|
2570
2354
|
}
|
|
2571
2355
|
}
|
|
2572
|
-
|
|
2573
2356
|
function checkOrientation(multiframe, validOrientations, sourceDataDimensions, tolerance) {
|
|
2574
2357
|
var SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
|
|
2575
|
-
|
|
2576
|
-
var sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
|
|
2358
|
+
PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence;
|
|
2359
|
+
var sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
|
|
2577
2360
|
|
|
2361
|
+
// Check if in plane.
|
|
2578
2362
|
var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[0];
|
|
2579
2363
|
var iop = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
|
|
2580
2364
|
var inPlane = validOrientations.some(function (operation) {
|
|
2581
2365
|
return compareArrays(iop, operation, tolerance);
|
|
2582
2366
|
});
|
|
2583
|
-
|
|
2584
2367
|
if (inPlane) {
|
|
2585
2368
|
return "Planar";
|
|
2586
2369
|
}
|
|
2587
|
-
|
|
2588
2370
|
if (checkIfPerpendicular(iop, validOrientations[0], tolerance) && sourceDataDimensions.includes(multiframe.Rows) && sourceDataDimensions.includes(multiframe.Columns)) {
|
|
2589
2371
|
// Perpendicular and fits on same grid.
|
|
2590
2372
|
return "Perpendicular";
|
|
2591
2373
|
}
|
|
2592
|
-
|
|
2593
2374
|
return "Oblique";
|
|
2594
2375
|
}
|
|
2376
|
+
|
|
2595
2377
|
/**
|
|
2596
2378
|
* checkIfPerpendicular - Returns true if iop1 and iop2 are perpendicular
|
|
2597
2379
|
* within a tolerance.
|
|
@@ -2601,53 +2383,45 @@ function checkOrientation(multiframe, validOrientations, sourceDataDimensions, t
|
|
|
2601
2383
|
* @param {Number} tolerance.
|
|
2602
2384
|
* @return {Boolean} True if iop1 and iop2 are equal.
|
|
2603
2385
|
*/
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
2386
|
function checkIfPerpendicular(iop1, iop2, tolerance) {
|
|
2607
2387
|
var absDotColumnCosines = Math.abs(iop1[0] * iop2[0] + iop1[1] * iop2[1] + iop1[2] * iop2[2]);
|
|
2608
2388
|
var absDotRowCosines = Math.abs(iop1[3] * iop2[3] + iop1[4] * iop2[4] + iop1[5] * iop2[5]);
|
|
2609
2389
|
return (absDotColumnCosines < tolerance || Math.abs(absDotColumnCosines - 1) < tolerance) && (absDotRowCosines < tolerance || Math.abs(absDotRowCosines - 1) < tolerance);
|
|
2610
2390
|
}
|
|
2391
|
+
|
|
2611
2392
|
/**
|
|
2612
2393
|
* unpackPixelData - Unpacks bitpacked pixelData if the Segmentation is BINARY.
|
|
2613
2394
|
*
|
|
2614
2395
|
* @param {Object} multiframe The multiframe dataset.
|
|
2615
2396
|
* @return {Uint8Array} The unpacked pixelData.
|
|
2616
2397
|
*/
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
2398
|
function unpackPixelData(multiframe) {
|
|
2620
2399
|
var segType = multiframe.SegmentationType;
|
|
2621
2400
|
var data;
|
|
2622
|
-
|
|
2623
2401
|
if (Array.isArray(multiframe.PixelData)) {
|
|
2624
2402
|
data = multiframe.PixelData[0];
|
|
2625
2403
|
} else {
|
|
2626
2404
|
data = multiframe.PixelData;
|
|
2627
2405
|
}
|
|
2628
|
-
|
|
2629
2406
|
if (data === undefined) {
|
|
2630
2407
|
log.error("This segmentation pixeldata is undefined.");
|
|
2631
2408
|
}
|
|
2632
|
-
|
|
2633
2409
|
if (segType === "BINARY") {
|
|
2634
2410
|
return BitArray$1.unpack(data);
|
|
2635
2411
|
}
|
|
2636
|
-
|
|
2637
2412
|
var pixelData = new Uint8Array(data);
|
|
2638
2413
|
var max = multiframe.MaximumFractionalValue;
|
|
2639
2414
|
var onlyMaxAndZero = pixelData.find(function (element) {
|
|
2640
2415
|
return element !== 0 && element !== max;
|
|
2641
2416
|
}) === undefined;
|
|
2642
|
-
|
|
2643
2417
|
if (!onlyMaxAndZero) {
|
|
2644
2418
|
// This is a fractional segmentation, which is not currently supported.
|
|
2645
2419
|
return;
|
|
2646
2420
|
}
|
|
2647
|
-
|
|
2648
2421
|
log.warn("This segmentation object is actually binary... processing as such.");
|
|
2649
2422
|
return pixelData;
|
|
2650
2423
|
}
|
|
2424
|
+
|
|
2651
2425
|
/**
|
|
2652
2426
|
* getImageIdOfSourceImagebySourceImageSequence - Returns the Cornerstone imageId of the source image.
|
|
2653
2427
|
*
|
|
@@ -2657,13 +2431,12 @@ function unpackPixelData(multiframe) {
|
|
|
2657
2431
|
* metadata from imageIds.
|
|
2658
2432
|
* @return {String} The corresponding imageId.
|
|
2659
2433
|
*/
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
2434
|
function getImageIdOfSourceImagebySourceImageSequence(SourceImageSequence, imageIds, metadataProvider) {
|
|
2663
2435
|
var ReferencedSOPInstanceUID = SourceImageSequence.ReferencedSOPInstanceUID,
|
|
2664
|
-
|
|
2436
|
+
ReferencedFrameNumber = SourceImageSequence.ReferencedFrameNumber;
|
|
2665
2437
|
return ReferencedFrameNumber ? getImageIdOfReferencedFrame(ReferencedSOPInstanceUID, ReferencedFrameNumber, imageIds, metadataProvider) : getImageIdOfReferencedSingleFramedSOPInstance(ReferencedSOPInstanceUID, imageIds, metadataProvider);
|
|
2666
2438
|
}
|
|
2439
|
+
|
|
2667
2440
|
/**
|
|
2668
2441
|
* getImageIdOfSourceImagebyGeometry - Returns the Cornerstone imageId of the source image.
|
|
2669
2442
|
*
|
|
@@ -2676,25 +2449,21 @@ function getImageIdOfSourceImagebySourceImageSequence(SourceImageSequence, image
|
|
|
2676
2449
|
*
|
|
2677
2450
|
* @return {String} The corresponding imageId.
|
|
2678
2451
|
*/
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
2452
|
function getImageIdOfSourceImagebyGeometry(ReferencedSeriesInstanceUID, FrameOfReferenceUID, PerFrameFunctionalGroup, imageIds, metadataProvider, tolerance) {
|
|
2682
2453
|
if (ReferencedSeriesInstanceUID === undefined || PerFrameFunctionalGroup.PlanePositionSequence === undefined || PerFrameFunctionalGroup.PlanePositionSequence[0] === undefined || PerFrameFunctionalGroup.PlanePositionSequence[0].ImagePositionPatient === undefined) {
|
|
2683
2454
|
return undefined;
|
|
2684
2455
|
}
|
|
2685
|
-
|
|
2686
2456
|
for (var imageIdsIndexc = 0; imageIdsIndexc < imageIds.length; ++imageIdsIndexc) {
|
|
2687
2457
|
var sourceImageMetadata = metadataProvider.get("instance", imageIds[imageIdsIndexc]);
|
|
2688
|
-
|
|
2689
2458
|
if (sourceImageMetadata === undefined || sourceImageMetadata.ImagePositionPatient === undefined || sourceImageMetadata.FrameOfReferenceUID !== FrameOfReferenceUID || sourceImageMetadata.SeriesInstanceUID !== ReferencedSeriesInstanceUID) {
|
|
2690
2459
|
continue;
|
|
2691
2460
|
}
|
|
2692
|
-
|
|
2693
2461
|
if (compareArrays(PerFrameFunctionalGroup.PlanePositionSequence[0].ImagePositionPatient, sourceImageMetadata.ImagePositionPatient, tolerance)) {
|
|
2694
2462
|
return imageIds[imageIdsIndexc];
|
|
2695
2463
|
}
|
|
2696
2464
|
}
|
|
2697
2465
|
}
|
|
2466
|
+
|
|
2698
2467
|
/**
|
|
2699
2468
|
* getImageIdOfReferencedSingleFramedSOPInstance - Returns the imageId
|
|
2700
2469
|
* corresponding to the specified sopInstanceUid for single-frame images.
|
|
@@ -2705,19 +2474,16 @@ function getImageIdOfSourceImagebyGeometry(ReferencedSeriesInstanceUID, FrameOfR
|
|
|
2705
2474
|
* from the cornerstone imageIds.
|
|
2706
2475
|
* @return {String} The imageId that corresponds to the sopInstanceUid.
|
|
2707
2476
|
*/
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
2477
|
function getImageIdOfReferencedSingleFramedSOPInstance(sopInstanceUid, imageIds, metadataProvider) {
|
|
2711
2478
|
return imageIds.find(function (imageId) {
|
|
2712
2479
|
var sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
|
|
2713
|
-
|
|
2714
2480
|
if (!sopCommonModule) {
|
|
2715
2481
|
return;
|
|
2716
2482
|
}
|
|
2717
|
-
|
|
2718
2483
|
return sopCommonModule.sopInstanceUID === sopInstanceUid;
|
|
2719
2484
|
});
|
|
2720
2485
|
}
|
|
2486
|
+
|
|
2721
2487
|
/**
|
|
2722
2488
|
* getImageIdOfReferencedFrame - Returns the imageId corresponding to the
|
|
2723
2489
|
* specified sopInstanceUid and frameNumber for multi-frame images.
|
|
@@ -2729,33 +2495,31 @@ function getImageIdOfReferencedSingleFramedSOPInstance(sopInstanceUid, imageIds,
|
|
|
2729
2495
|
* from the cornerstone imageIds.
|
|
2730
2496
|
* @return {String} The imageId that corresponds to the sopInstanceUid.
|
|
2731
2497
|
*/
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
2498
|
function getImageIdOfReferencedFrame(sopInstanceUid, frameNumber, imageIds, metadataProvider) {
|
|
2735
2499
|
var imageId = imageIds.find(function (imageId) {
|
|
2736
2500
|
var sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
|
|
2737
|
-
|
|
2738
2501
|
if (!sopCommonModule) {
|
|
2739
2502
|
return;
|
|
2740
2503
|
}
|
|
2741
|
-
|
|
2742
2504
|
var imageIdFrameNumber = Number(imageId.split("frame=")[1]);
|
|
2743
|
-
return (
|
|
2505
|
+
return (
|
|
2506
|
+
//frameNumber is zero indexed for cornerstoneDICOMImageLoader image Ids.
|
|
2744
2507
|
sopCommonModule.sopInstanceUID === sopInstanceUid && imageIdFrameNumber === frameNumber - 1
|
|
2745
2508
|
);
|
|
2746
2509
|
});
|
|
2747
2510
|
return imageId;
|
|
2748
2511
|
}
|
|
2512
|
+
|
|
2749
2513
|
/**
|
|
2750
2514
|
* getValidOrientations - returns an array of valid orientations.
|
|
2751
2515
|
*
|
|
2752
2516
|
* @param {Number[6]} iop The row (0..2) an column (3..5) direction cosines.
|
|
2753
2517
|
* @return {Number[8][6]} An array of valid orientations.
|
|
2754
2518
|
*/
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
2519
|
function getValidOrientations(iop) {
|
|
2758
|
-
var orientations = [];
|
|
2520
|
+
var orientations = [];
|
|
2521
|
+
|
|
2522
|
+
// [0, 1, 2]: 0, 0hf, 0vf
|
|
2759
2523
|
// [3, 4, 5]: 90, 90hf, 90vf
|
|
2760
2524
|
// [6, 7]: 180, 270
|
|
2761
2525
|
|
|
@@ -2770,6 +2534,7 @@ function getValidOrientations(iop) {
|
|
|
2770
2534
|
orientations[7] = rotateDirectionCosinesInPlane(iop, 1.5 * Math.PI);
|
|
2771
2535
|
return orientations;
|
|
2772
2536
|
}
|
|
2537
|
+
|
|
2773
2538
|
/**
|
|
2774
2539
|
* alignPixelDataWithSourceData -
|
|
2775
2540
|
*
|
|
@@ -2779,40 +2544,46 @@ function getValidOrientations(iop) {
|
|
|
2779
2544
|
* @param {Number} tolerance.
|
|
2780
2545
|
* @return {Ndarray} The aligned pixelData.
|
|
2781
2546
|
*/
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
2547
|
function alignPixelDataWithSourceData(pixelData2D, iop, orientations, tolerance) {
|
|
2785
2548
|
if (compareArrays(iop, orientations[0], tolerance)) {
|
|
2786
2549
|
return pixelData2D;
|
|
2787
2550
|
} else if (compareArrays(iop, orientations[1], tolerance)) {
|
|
2788
2551
|
// Flipped vertically.
|
|
2552
|
+
|
|
2789
2553
|
// Undo Flip
|
|
2790
2554
|
return flipMatrix2D.v(pixelData2D);
|
|
2791
2555
|
} else if (compareArrays(iop, orientations[2], tolerance)) {
|
|
2792
2556
|
// Flipped horizontally.
|
|
2557
|
+
|
|
2793
2558
|
// Unfo flip
|
|
2794
2559
|
return flipMatrix2D.h(pixelData2D);
|
|
2795
2560
|
} else if (compareArrays(iop, orientations[3], tolerance)) {
|
|
2796
2561
|
//Rotated 90 degrees
|
|
2562
|
+
|
|
2797
2563
|
// Rotate back
|
|
2798
2564
|
return rotateMatrix902D(pixelData2D);
|
|
2799
2565
|
} else if (compareArrays(iop, orientations[4], tolerance)) {
|
|
2800
2566
|
//Rotated 90 degrees and fliped horizontally.
|
|
2567
|
+
|
|
2801
2568
|
// Undo flip and rotate back.
|
|
2802
2569
|
return rotateMatrix902D(flipMatrix2D.h(pixelData2D));
|
|
2803
2570
|
} else if (compareArrays(iop, orientations[5], tolerance)) {
|
|
2804
2571
|
// Rotated 90 degrees and fliped vertically
|
|
2572
|
+
|
|
2805
2573
|
// Unfo flip and rotate back.
|
|
2806
2574
|
return rotateMatrix902D(flipMatrix2D.v(pixelData2D));
|
|
2807
2575
|
} else if (compareArrays(iop, orientations[6], tolerance)) {
|
|
2808
2576
|
// Rotated 180 degrees. // TODO -> Do this more effeciently, there is a 1:1 mapping like 90 degree rotation.
|
|
2577
|
+
|
|
2809
2578
|
return rotateMatrix902D(rotateMatrix902D(pixelData2D));
|
|
2810
2579
|
} else if (compareArrays(iop, orientations[7], tolerance)) {
|
|
2811
2580
|
// Rotated 270 degrees
|
|
2581
|
+
|
|
2812
2582
|
// Rotate back.
|
|
2813
2583
|
return rotateMatrix902D(rotateMatrix902D(rotateMatrix902D(pixelData2D)));
|
|
2814
2584
|
}
|
|
2815
2585
|
}
|
|
2586
|
+
|
|
2816
2587
|
/**
|
|
2817
2588
|
* compareArrays - Returns true if array1 and array2 are equal
|
|
2818
2589
|
* within a tolerance.
|
|
@@ -2822,33 +2593,26 @@ function alignPixelDataWithSourceData(pixelData2D, iop, orientations, tolerance)
|
|
|
2822
2593
|
* @param {Number} tolerance.
|
|
2823
2594
|
* @return {Boolean} True if array1 and array2 are equal.
|
|
2824
2595
|
*/
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
2596
|
function compareArrays(array1, array2, tolerance) {
|
|
2828
2597
|
if (array1.length != array2.length) {
|
|
2829
2598
|
return false;
|
|
2830
2599
|
}
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
if (!nearlyEqual(array1[_i4], array2[_i4], tolerance)) {
|
|
2600
|
+
for (var i = 0; i < array1.length; ++i) {
|
|
2601
|
+
if (!nearlyEqual(array1[i], array2[i], tolerance)) {
|
|
2834
2602
|
return false;
|
|
2835
2603
|
}
|
|
2836
2604
|
}
|
|
2837
|
-
|
|
2838
2605
|
return true;
|
|
2839
2606
|
}
|
|
2840
|
-
|
|
2841
2607
|
function getSegmentMetadata(multiframe, seriesInstanceUid) {
|
|
2842
2608
|
var segmentSequence = multiframe.SegmentSequence;
|
|
2843
2609
|
var data = [];
|
|
2844
|
-
|
|
2845
2610
|
if (Array.isArray(segmentSequence)) {
|
|
2846
2611
|
data = [undefined].concat(_toConsumableArray(segmentSequence));
|
|
2847
2612
|
} else {
|
|
2848
2613
|
// Only one segment, will be stored as an object.
|
|
2849
2614
|
data = [undefined, segmentSequence];
|
|
2850
2615
|
}
|
|
2851
|
-
|
|
2852
2616
|
return {
|
|
2853
2617
|
seriesInstanceUid: seriesInstanceUid,
|
|
2854
2618
|
data: data
|
|
@@ -2860,6 +2624,7 @@ var Segmentation$1 = {
|
|
|
2860
2624
|
generateToolState: generateToolState,
|
|
2861
2625
|
fillSegmentation: fillSegmentation
|
|
2862
2626
|
};
|
|
2627
|
+
|
|
2863
2628
|
/**
|
|
2864
2629
|
* generateSegmentation - Generates a DICOM Segmentation object given cornerstoneTools data.
|
|
2865
2630
|
*
|
|
@@ -2869,23 +2634,20 @@ var Segmentation$1 = {
|
|
|
2869
2634
|
* @param {number} cornerstoneToolsVersion The cornerstoneTools major version to map against.
|
|
2870
2635
|
* @returns {Object}
|
|
2871
2636
|
*/
|
|
2872
|
-
|
|
2873
2637
|
function generateSegmentation(images, labelmaps3DorBrushData) {
|
|
2874
2638
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
|
|
2875
2639
|
includeSliceSpacing: true
|
|
2876
2640
|
};
|
|
2877
2641
|
var cornerstoneToolsVersion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 4;
|
|
2878
|
-
|
|
2879
2642
|
if (cornerstoneToolsVersion === 4) {
|
|
2880
2643
|
return Segmentation$2.generateSegmentation(images, labelmaps3DorBrushData, options);
|
|
2881
2644
|
}
|
|
2882
|
-
|
|
2883
2645
|
if (cornerstoneToolsVersion === 3) {
|
|
2884
2646
|
return Segmentation$3.generateSegmentation(images, labelmaps3DorBrushData, options);
|
|
2885
2647
|
}
|
|
2886
|
-
|
|
2887
2648
|
console.warn("No generateSegmentation adapater for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
|
|
2888
2649
|
}
|
|
2650
|
+
|
|
2889
2651
|
/**
|
|
2890
2652
|
* generateToolState - Given a set of cornrstoneTools imageIds and a Segmentation buffer,
|
|
2891
2653
|
* derive cornerstoneTools toolState and brush metadata.
|
|
@@ -2900,23 +2662,19 @@ function generateSegmentation(images, labelmaps3DorBrushData) {
|
|
|
2900
2662
|
* @returns {Object} The toolState and an object from which the
|
|
2901
2663
|
* segment metadata can be derived.
|
|
2902
2664
|
*/
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
2665
|
function generateToolState(imageIds, arrayBuffer, metadataProvider) {
|
|
2906
2666
|
var skipOverlapping = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
2907
2667
|
var tolerance = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1e-3;
|
|
2908
2668
|
var cornerstoneToolsVersion = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 4;
|
|
2909
|
-
|
|
2910
2669
|
if (cornerstoneToolsVersion === 4) {
|
|
2911
2670
|
return Segmentation$2.generateToolState(imageIds, arrayBuffer, metadataProvider, skipOverlapping, tolerance);
|
|
2912
2671
|
}
|
|
2913
|
-
|
|
2914
2672
|
if (cornerstoneToolsVersion === 3) {
|
|
2915
2673
|
return Segmentation$3.generateToolState(imageIds, arrayBuffer, metadataProvider);
|
|
2916
2674
|
}
|
|
2917
|
-
|
|
2918
2675
|
console.warn("No generateToolState adapater for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
|
|
2919
2676
|
}
|
|
2677
|
+
|
|
2920
2678
|
/**
|
|
2921
2679
|
* fillSegmentation - Fills a derived segmentation dataset with cornerstoneTools `LabelMap3D` data.
|
|
2922
2680
|
*
|
|
@@ -2925,38 +2683,32 @@ function generateToolState(imageIds, arrayBuffer, metadataProvider) {
|
|
|
2925
2683
|
* @param {Object} userOptions Options object to override default options.
|
|
2926
2684
|
* @returns {Blob} description
|
|
2927
2685
|
*/
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
2686
|
function fillSegmentation(segmentation, inputLabelmaps3D) {
|
|
2931
2687
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
|
|
2932
2688
|
includeSliceSpacing: true
|
|
2933
2689
|
};
|
|
2934
2690
|
var cornerstoneToolsVersion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 4;
|
|
2935
|
-
|
|
2936
2691
|
if (cornerstoneToolsVersion === 4) {
|
|
2937
2692
|
return Segmentation$2.fillSegmentation(segmentation, inputLabelmaps3D, options);
|
|
2938
2693
|
}
|
|
2939
|
-
|
|
2940
2694
|
console.warn("No generateSegmentation adapater for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
|
|
2941
2695
|
}
|
|
2942
2696
|
|
|
2943
2697
|
var TID300CobbAngle$2 = utilities.TID300.CobbAngle;
|
|
2944
2698
|
var COBB_ANGLE = "CobbAngle";
|
|
2945
|
-
|
|
2946
2699
|
var CobbAngle$1 = /*#__PURE__*/function () {
|
|
2947
2700
|
function CobbAngle() {
|
|
2948
2701
|
_classCallCheck(this, CobbAngle);
|
|
2949
2702
|
}
|
|
2950
|
-
|
|
2951
2703
|
_createClass(CobbAngle, null, [{
|
|
2952
2704
|
key: "getMeasurementData",
|
|
2953
|
-
value:
|
|
2705
|
+
value:
|
|
2706
|
+
// TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport.
|
|
2954
2707
|
function getMeasurementData(MeasurementGroup) {
|
|
2955
2708
|
var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2709
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
2710
|
+
NUMGroup = _MeasurementReport$ge.NUMGroup,
|
|
2711
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup;
|
|
2960
2712
|
var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
|
|
2961
2713
|
rAngle: NUMGroup.MeasuredValueSequence.NumericValue,
|
|
2962
2714
|
toolType: CobbAngle.toolType,
|
|
@@ -2980,9 +2732,7 @@ var CobbAngle$1 = /*#__PURE__*/function () {
|
|
|
2980
2732
|
}
|
|
2981
2733
|
}
|
|
2982
2734
|
});
|
|
2983
|
-
|
|
2984
2735
|
var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 8);
|
|
2985
|
-
|
|
2986
2736
|
state.handles.start.x = _SCOORDGroup$GraphicD[0];
|
|
2987
2737
|
state.handles.start.y = _SCOORDGroup$GraphicD[1];
|
|
2988
2738
|
state.handles.end.x = _SCOORDGroup$GraphicD[2];
|
|
@@ -2997,8 +2747,8 @@ var CobbAngle$1 = /*#__PURE__*/function () {
|
|
|
2997
2747
|
key: "getTID300RepresentationArguments",
|
|
2998
2748
|
value: function getTID300RepresentationArguments(tool) {
|
|
2999
2749
|
var handles = tool.handles,
|
|
3000
|
-
|
|
3001
|
-
|
|
2750
|
+
finding = tool.finding,
|
|
2751
|
+
findingSites = tool.findingSites;
|
|
3002
2752
|
var point1 = handles.start;
|
|
3003
2753
|
var point2 = handles.end;
|
|
3004
2754
|
var point3 = handles.start2;
|
|
@@ -3017,41 +2767,32 @@ var CobbAngle$1 = /*#__PURE__*/function () {
|
|
|
3017
2767
|
};
|
|
3018
2768
|
}
|
|
3019
2769
|
}]);
|
|
3020
|
-
|
|
3021
2770
|
return CobbAngle;
|
|
3022
2771
|
}();
|
|
3023
|
-
|
|
3024
2772
|
CobbAngle$1.toolType = COBB_ANGLE;
|
|
3025
2773
|
CobbAngle$1.utilityToolType = COBB_ANGLE;
|
|
3026
2774
|
CobbAngle$1.TID300Representation = TID300CobbAngle$2;
|
|
3027
|
-
|
|
3028
2775
|
CobbAngle$1.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
3029
2776
|
if (!TrackingIdentifier.includes(":")) {
|
|
3030
2777
|
return false;
|
|
3031
2778
|
}
|
|
3032
|
-
|
|
3033
2779
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
2780
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
2781
|
+
cornerstone4Tag = _TrackingIdentifier$s2[0],
|
|
2782
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
3038
2783
|
if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
|
|
3039
2784
|
return false;
|
|
3040
2785
|
}
|
|
3041
|
-
|
|
3042
2786
|
return toolType === COBB_ANGLE;
|
|
3043
2787
|
};
|
|
3044
|
-
|
|
3045
2788
|
MeasurementReport$1.registerTool(CobbAngle$1);
|
|
3046
2789
|
|
|
3047
2790
|
var TID300Angle = utilities.TID300.Angle;
|
|
3048
2791
|
var ANGLE = "Angle";
|
|
3049
|
-
|
|
3050
2792
|
var Angle$1 = /*#__PURE__*/function () {
|
|
3051
2793
|
function Angle() {
|
|
3052
2794
|
_classCallCheck(this, Angle);
|
|
3053
2795
|
}
|
|
3054
|
-
|
|
3055
2796
|
_createClass(Angle, null, [{
|
|
3056
2797
|
key: "getMeasurementData",
|
|
3057
2798
|
value:
|
|
@@ -3060,10 +2801,9 @@ var Angle$1 = /*#__PURE__*/function () {
|
|
|
3060
2801
|
*/
|
|
3061
2802
|
function getMeasurementData(MeasurementGroup) {
|
|
3062
2803
|
var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
2804
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
2805
|
+
NUMGroup = _MeasurementReport$ge.NUMGroup,
|
|
2806
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup;
|
|
3067
2807
|
var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
|
|
3068
2808
|
rAngle: NUMGroup.MeasuredValueSequence.NumericValue,
|
|
3069
2809
|
toolType: Angle.toolType,
|
|
@@ -3080,9 +2820,7 @@ var Angle$1 = /*#__PURE__*/function () {
|
|
|
3080
2820
|
}
|
|
3081
2821
|
}
|
|
3082
2822
|
});
|
|
3083
|
-
|
|
3084
2823
|
var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 8);
|
|
3085
|
-
|
|
3086
2824
|
state.handles.start.x = _SCOORDGroup$GraphicD[0];
|
|
3087
2825
|
state.handles.start.y = _SCOORDGroup$GraphicD[1];
|
|
3088
2826
|
state.handles.middle.x = _SCOORDGroup$GraphicD[2];
|
|
@@ -3097,8 +2835,8 @@ var Angle$1 = /*#__PURE__*/function () {
|
|
|
3097
2835
|
key: "getTID300RepresentationArguments",
|
|
3098
2836
|
value: function getTID300RepresentationArguments(tool) {
|
|
3099
2837
|
var handles = tool.handles,
|
|
3100
|
-
|
|
3101
|
-
|
|
2838
|
+
finding = tool.finding,
|
|
2839
|
+
findingSites = tool.findingSites;
|
|
3102
2840
|
var point1 = handles.start;
|
|
3103
2841
|
var point2 = handles.middle;
|
|
3104
2842
|
var point3 = handles.middle;
|
|
@@ -3117,48 +2855,38 @@ var Angle$1 = /*#__PURE__*/function () {
|
|
|
3117
2855
|
};
|
|
3118
2856
|
}
|
|
3119
2857
|
}]);
|
|
3120
|
-
|
|
3121
2858
|
return Angle;
|
|
3122
2859
|
}();
|
|
3123
|
-
|
|
3124
2860
|
Angle$1.toolType = ANGLE;
|
|
3125
2861
|
Angle$1.utilityToolType = ANGLE;
|
|
3126
2862
|
Angle$1.TID300Representation = TID300Angle;
|
|
3127
|
-
|
|
3128
2863
|
Angle$1.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
3129
2864
|
if (!TrackingIdentifier.includes(":")) {
|
|
3130
2865
|
return false;
|
|
3131
2866
|
}
|
|
3132
|
-
|
|
3133
2867
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
2868
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
2869
|
+
cornerstone4Tag = _TrackingIdentifier$s2[0],
|
|
2870
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
3138
2871
|
if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
|
|
3139
2872
|
return false;
|
|
3140
2873
|
}
|
|
3141
|
-
|
|
3142
2874
|
return toolType === ANGLE;
|
|
3143
2875
|
};
|
|
3144
|
-
|
|
3145
2876
|
MeasurementReport$1.registerTool(Angle$1);
|
|
3146
2877
|
|
|
3147
2878
|
var TID300Polyline$2 = utilities.TID300.Polyline;
|
|
3148
|
-
|
|
3149
2879
|
var RectangleRoi = /*#__PURE__*/function () {
|
|
3150
2880
|
function RectangleRoi() {
|
|
3151
2881
|
_classCallCheck(this, RectangleRoi);
|
|
3152
2882
|
}
|
|
3153
|
-
|
|
3154
2883
|
_createClass(RectangleRoi, null, [{
|
|
3155
2884
|
key: "getMeasurementData",
|
|
3156
2885
|
value: function getMeasurementData(MeasurementGroup) {
|
|
3157
2886
|
var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
2887
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
2888
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup,
|
|
2889
|
+
NUMGroup = _MeasurementReport$ge.NUMGroup;
|
|
3162
2890
|
var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
|
|
3163
2891
|
toolType: RectangleRoi.toolType,
|
|
3164
2892
|
handles: {
|
|
@@ -3180,9 +2908,7 @@ var RectangleRoi = /*#__PURE__*/function () {
|
|
|
3180
2908
|
color: undefined,
|
|
3181
2909
|
invalidated: true
|
|
3182
2910
|
});
|
|
3183
|
-
|
|
3184
2911
|
var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 6);
|
|
3185
|
-
|
|
3186
2912
|
state.handles.start.x = _SCOORDGroup$GraphicD[0];
|
|
3187
2913
|
state.handles.start.y = _SCOORDGroup$GraphicD[1];
|
|
3188
2914
|
_SCOORDGroup$GraphicD[2];
|
|
@@ -3195,12 +2921,12 @@ var RectangleRoi = /*#__PURE__*/function () {
|
|
|
3195
2921
|
key: "getTID300RepresentationArguments",
|
|
3196
2922
|
value: function getTID300RepresentationArguments(tool) {
|
|
3197
2923
|
var finding = tool.finding,
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
2924
|
+
findingSites = tool.findingSites,
|
|
2925
|
+
_tool$cachedStats = tool.cachedStats,
|
|
2926
|
+
cachedStats = _tool$cachedStats === void 0 ? {} : _tool$cachedStats,
|
|
2927
|
+
handles = tool.handles;
|
|
3202
2928
|
var start = handles.start,
|
|
3203
|
-
|
|
2929
|
+
end = handles.end;
|
|
3204
2930
|
var points = [start, {
|
|
3205
2931
|
x: start.x,
|
|
3206
2932
|
y: end.y
|
|
@@ -3209,7 +2935,7 @@ var RectangleRoi = /*#__PURE__*/function () {
|
|
|
3209
2935
|
y: start.y
|
|
3210
2936
|
}];
|
|
3211
2937
|
var area = cachedStats.area,
|
|
3212
|
-
|
|
2938
|
+
perimeter = cachedStats.perimeter;
|
|
3213
2939
|
var trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:RectangleRoi";
|
|
3214
2940
|
return {
|
|
3215
2941
|
points: points,
|
|
@@ -3221,31 +2947,24 @@ var RectangleRoi = /*#__PURE__*/function () {
|
|
|
3221
2947
|
};
|
|
3222
2948
|
}
|
|
3223
2949
|
}]);
|
|
3224
|
-
|
|
3225
2950
|
return RectangleRoi;
|
|
3226
2951
|
}();
|
|
3227
|
-
|
|
3228
2952
|
RectangleRoi.toolType = "RectangleRoi";
|
|
3229
2953
|
RectangleRoi.utilityToolType = "RectangleRoi";
|
|
3230
2954
|
RectangleRoi.TID300Representation = TID300Polyline$2;
|
|
3231
|
-
|
|
3232
2955
|
RectangleRoi.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
3233
2956
|
if (!TrackingIdentifier.includes(":")) {
|
|
3234
2957
|
return false;
|
|
3235
2958
|
}
|
|
3236
|
-
|
|
3237
2959
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
2960
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
2961
|
+
cornerstone4Tag = _TrackingIdentifier$s2[0],
|
|
2962
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
3242
2963
|
if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
|
|
3243
2964
|
return false;
|
|
3244
2965
|
}
|
|
3245
|
-
|
|
3246
2966
|
return toolType === RectangleRoi.toolType;
|
|
3247
2967
|
};
|
|
3248
|
-
|
|
3249
2968
|
MeasurementReport$1.registerTool(RectangleRoi);
|
|
3250
2969
|
|
|
3251
2970
|
var Cornerstone = {
|
|
@@ -3280,13 +2999,10 @@ var __assign = function () {
|
|
|
3280
2999
|
__assign = Object.assign || function __assign(t) {
|
|
3281
3000
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
3282
3001
|
s = arguments[i];
|
|
3283
|
-
|
|
3284
3002
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
3285
3003
|
}
|
|
3286
|
-
|
|
3287
3004
|
return t;
|
|
3288
3005
|
};
|
|
3289
|
-
|
|
3290
3006
|
return __assign.apply(this, arguments);
|
|
3291
3007
|
};
|
|
3292
3008
|
function __spreadArray(to, from, pack) {
|
|
@@ -3304,8 +3020,9 @@ var CORNERSTONE_3D_TAG = "Cornerstone3DTools@^0.1.0";
|
|
|
3304
3020
|
// This is a custom coding scheme defined to store some annotations from Cornerstone.
|
|
3305
3021
|
// Note: CodeMeaning is VR type LO, which means we only actually support 64 characters
|
|
3306
3022
|
// here this is fine for most labels, but may be problematic at some point.
|
|
3307
|
-
var CORNERSTONEFREETEXT = "CORNERSTONEFREETEXT";
|
|
3023
|
+
var CORNERSTONEFREETEXT = "CORNERSTONEFREETEXT";
|
|
3308
3024
|
|
|
3025
|
+
// Cornerstone specified coding scheme for storing findings
|
|
3309
3026
|
var CodingSchemeDesignator$1 = "CORNERSTONEJS";
|
|
3310
3027
|
var CodingScheme = {
|
|
3311
3028
|
CodingSchemeDesignator: CodingSchemeDesignator$1,
|
|
@@ -3587,49 +3304,42 @@ var TID300Point$1 = utilities.TID300.Point;
|
|
|
3587
3304
|
var ARROW_ANNOTATE = "ArrowAnnotate";
|
|
3588
3305
|
var trackingIdentifierTextValue$7 = "".concat(CORNERSTONE_3D_TAG, ":").concat(ARROW_ANNOTATE);
|
|
3589
3306
|
var codeValues = CodingScheme.codeValues,
|
|
3590
|
-
|
|
3591
|
-
|
|
3307
|
+
CodingSchemeDesignator = CodingScheme.CodingSchemeDesignator;
|
|
3592
3308
|
var ArrowAnnotate = /*#__PURE__*/function () {
|
|
3593
3309
|
function ArrowAnnotate() {
|
|
3594
3310
|
_classCallCheck(this, ArrowAnnotate);
|
|
3595
3311
|
}
|
|
3596
|
-
|
|
3597
3312
|
_createClass(ArrowAnnotate, null, [{
|
|
3598
3313
|
key: "getMeasurementData",
|
|
3599
3314
|
value: function getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata) {
|
|
3600
3315
|
var _MeasurementReport$ge = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, ArrowAnnotate.toolType),
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3316
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
3317
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup,
|
|
3318
|
+
ReferencedFrameNumber = _MeasurementReport$ge.ReferencedFrameNumber;
|
|
3605
3319
|
var referencedImageId = defaultState.annotation.metadata.referencedImageId;
|
|
3606
3320
|
var text = defaultState.annotation.metadata.label;
|
|
3607
3321
|
var GraphicData = SCOORDGroup.GraphicData;
|
|
3608
3322
|
var worldCoords = [];
|
|
3609
|
-
|
|
3610
3323
|
for (var i = 0; i < GraphicData.length; i += 2) {
|
|
3611
3324
|
var point = imageToWorldCoords(referencedImageId, [GraphicData[i], GraphicData[i + 1]]);
|
|
3612
3325
|
worldCoords.push(point);
|
|
3613
|
-
}
|
|
3614
|
-
// we derive the second point based on the image size relative to the first point.
|
|
3615
|
-
|
|
3326
|
+
}
|
|
3616
3327
|
|
|
3328
|
+
// Since the arrowAnnotate measurement is just a point, to generate the tool state
|
|
3329
|
+
// we derive the second point based on the image size relative to the first point.
|
|
3617
3330
|
if (worldCoords.length === 1) {
|
|
3618
3331
|
var imagePixelModule = metadata.get("imagePixelModule", referencedImageId);
|
|
3619
3332
|
var xOffset = 10;
|
|
3620
3333
|
var yOffset = 10;
|
|
3621
|
-
|
|
3622
3334
|
if (imagePixelModule) {
|
|
3623
3335
|
var columns = imagePixelModule.columns,
|
|
3624
|
-
|
|
3336
|
+
rows = imagePixelModule.rows;
|
|
3625
3337
|
xOffset = columns / 10;
|
|
3626
3338
|
yOffset = rows / 10;
|
|
3627
3339
|
}
|
|
3628
|
-
|
|
3629
3340
|
var secondPoint = imageToWorldCoords(referencedImageId, [GraphicData[0] + xOffset, GraphicData[1] + yOffset]);
|
|
3630
3341
|
worldCoords.push(secondPoint);
|
|
3631
3342
|
}
|
|
3632
|
-
|
|
3633
3343
|
var state = defaultState;
|
|
3634
3344
|
state.annotation.data = {
|
|
3635
3345
|
text: text,
|
|
@@ -3649,26 +3359,22 @@ var ArrowAnnotate = /*#__PURE__*/function () {
|
|
|
3649
3359
|
key: "getTID300RepresentationArguments",
|
|
3650
3360
|
value: function getTID300RepresentationArguments(tool, worldToImageCoords) {
|
|
3651
3361
|
var data = tool.data,
|
|
3652
|
-
|
|
3362
|
+
metadata = tool.metadata;
|
|
3653
3363
|
var finding = tool.finding,
|
|
3654
|
-
|
|
3364
|
+
findingSites = tool.findingSites;
|
|
3655
3365
|
var referencedImageId = metadata.referencedImageId;
|
|
3656
|
-
|
|
3657
3366
|
if (!referencedImageId) {
|
|
3658
3367
|
throw new Error("ArrowAnnotate.getTID300RepresentationArguments: referencedImageId is not defined");
|
|
3659
3368
|
}
|
|
3660
|
-
|
|
3661
3369
|
var _data$handles = data.handles,
|
|
3662
|
-
|
|
3663
|
-
|
|
3370
|
+
points = _data$handles.points,
|
|
3371
|
+
arrowFirst = _data$handles.arrowFirst;
|
|
3664
3372
|
var point;
|
|
3665
|
-
|
|
3666
3373
|
if (arrowFirst) {
|
|
3667
3374
|
point = points[0];
|
|
3668
3375
|
} else {
|
|
3669
3376
|
point = points[1];
|
|
3670
3377
|
}
|
|
3671
|
-
|
|
3672
3378
|
var pointImage = worldToImageCoords(referencedImageId, point);
|
|
3673
3379
|
var TID300RepresentationArguments = {
|
|
3674
3380
|
points: [{
|
|
@@ -3677,8 +3383,9 @@ var ArrowAnnotate = /*#__PURE__*/function () {
|
|
|
3677
3383
|
}],
|
|
3678
3384
|
trackingIdentifierTextValue: trackingIdentifierTextValue$7,
|
|
3679
3385
|
findingSites: findingSites || []
|
|
3680
|
-
};
|
|
3386
|
+
};
|
|
3681
3387
|
|
|
3388
|
+
// If freetext finding isn't present, add it from the tool text.
|
|
3682
3389
|
if (!finding || finding.CodeValue !== codeValues.CORNERSTONEFREETEXT) {
|
|
3683
3390
|
finding = {
|
|
3684
3391
|
CodeValue: codeValues.CORNERSTONEFREETEXT,
|
|
@@ -3686,36 +3393,28 @@ var ArrowAnnotate = /*#__PURE__*/function () {
|
|
|
3686
3393
|
CodeMeaning: data.text
|
|
3687
3394
|
};
|
|
3688
3395
|
}
|
|
3689
|
-
|
|
3690
3396
|
TID300RepresentationArguments.finding = finding;
|
|
3691
3397
|
return TID300RepresentationArguments;
|
|
3692
3398
|
}
|
|
3693
3399
|
}]);
|
|
3694
|
-
|
|
3695
3400
|
return ArrowAnnotate;
|
|
3696
3401
|
}();
|
|
3697
|
-
|
|
3698
3402
|
ArrowAnnotate.toolType = ARROW_ANNOTATE;
|
|
3699
3403
|
ArrowAnnotate.utilityToolType = ARROW_ANNOTATE;
|
|
3700
3404
|
ArrowAnnotate.TID300Representation = TID300Point$1;
|
|
3701
|
-
|
|
3702
3405
|
ArrowAnnotate.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
3703
3406
|
if (!TrackingIdentifier.includes(":")) {
|
|
3704
3407
|
return false;
|
|
3705
3408
|
}
|
|
3706
|
-
|
|
3707
3409
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3410
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
3411
|
+
cornerstone3DTag = _TrackingIdentifier$s2[0],
|
|
3412
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
3712
3413
|
if (cornerstone3DTag !== CORNERSTONE_3D_TAG) {
|
|
3713
3414
|
return false;
|
|
3714
3415
|
}
|
|
3715
|
-
|
|
3716
3416
|
return toolType === ARROW_ANNOTATE;
|
|
3717
3417
|
};
|
|
3718
|
-
|
|
3719
3418
|
MeasurementReport.registerTool(ArrowAnnotate);
|
|
3720
3419
|
|
|
3721
3420
|
var TID300Bidirectional = utilities.TID300.Bidirectional;
|
|
@@ -4350,31 +4049,27 @@ MeasurementReport.registerTool(RectangleROI);
|
|
|
4350
4049
|
var TID300Length = utilities.TID300.Length;
|
|
4351
4050
|
var LENGTH = "Length";
|
|
4352
4051
|
var trackingIdentifierTextValue$2 = "".concat(CORNERSTONE_3D_TAG, ":").concat(LENGTH);
|
|
4353
|
-
|
|
4354
4052
|
var Length = /*#__PURE__*/function () {
|
|
4355
4053
|
function Length() {
|
|
4356
4054
|
_classCallCheck(this, Length);
|
|
4357
4055
|
}
|
|
4358
|
-
|
|
4359
4056
|
_createClass(Length, null, [{
|
|
4360
4057
|
key: "getMeasurementData",
|
|
4361
|
-
value:
|
|
4058
|
+
value:
|
|
4059
|
+
// TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport.
|
|
4362
4060
|
function getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata) {
|
|
4363
4061
|
var _MeasurementReport$ge = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, Length.toolType),
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4062
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
4063
|
+
NUMGroup = _MeasurementReport$ge.NUMGroup,
|
|
4064
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup,
|
|
4065
|
+
ReferencedFrameNumber = _MeasurementReport$ge.ReferencedFrameNumber;
|
|
4369
4066
|
var referencedImageId = defaultState.annotation.metadata.referencedImageId;
|
|
4370
4067
|
var GraphicData = SCOORDGroup.GraphicData;
|
|
4371
4068
|
var worldCoords = [];
|
|
4372
|
-
|
|
4373
4069
|
for (var i = 0; i < GraphicData.length; i += 2) {
|
|
4374
4070
|
var point = imageToWorldCoords(referencedImageId, [GraphicData[i], GraphicData[i + 1]]);
|
|
4375
4071
|
worldCoords.push(point);
|
|
4376
4072
|
}
|
|
4377
|
-
|
|
4378
4073
|
var state = defaultState;
|
|
4379
4074
|
state.annotation.data = {
|
|
4380
4075
|
handles: {
|
|
@@ -4395,18 +4090,16 @@ var Length = /*#__PURE__*/function () {
|
|
|
4395
4090
|
key: "getTID300RepresentationArguments",
|
|
4396
4091
|
value: function getTID300RepresentationArguments(tool, worldToImageCoords) {
|
|
4397
4092
|
var data = tool.data,
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4093
|
+
finding = tool.finding,
|
|
4094
|
+
findingSites = tool.findingSites,
|
|
4095
|
+
metadata = tool.metadata;
|
|
4401
4096
|
var _data$cachedStats = data.cachedStats,
|
|
4402
|
-
|
|
4403
|
-
|
|
4097
|
+
cachedStats = _data$cachedStats === void 0 ? {} : _data$cachedStats,
|
|
4098
|
+
handles = data.handles;
|
|
4404
4099
|
var referencedImageId = metadata.referencedImageId;
|
|
4405
|
-
|
|
4406
4100
|
if (!referencedImageId) {
|
|
4407
4101
|
throw new Error("Length.getTID300RepresentationArguments: referencedImageId is not defined");
|
|
4408
4102
|
}
|
|
4409
|
-
|
|
4410
4103
|
var start = worldToImageCoords(referencedImageId, handles.points[0]);
|
|
4411
4104
|
var end = worldToImageCoords(referencedImageId, handles.points[1]);
|
|
4412
4105
|
var point1 = {
|
|
@@ -4417,10 +4110,8 @@ var Length = /*#__PURE__*/function () {
|
|
|
4417
4110
|
x: end[0],
|
|
4418
4111
|
y: end[1]
|
|
4419
4112
|
};
|
|
4420
|
-
|
|
4421
4113
|
var _ref = cachedStats["imageId:".concat(referencedImageId)] || {},
|
|
4422
|
-
|
|
4423
|
-
|
|
4114
|
+
distance = _ref.length;
|
|
4424
4115
|
return {
|
|
4425
4116
|
point1: point1,
|
|
4426
4117
|
point2: point2,
|
|
@@ -4431,31 +4122,24 @@ var Length = /*#__PURE__*/function () {
|
|
|
4431
4122
|
};
|
|
4432
4123
|
}
|
|
4433
4124
|
}]);
|
|
4434
|
-
|
|
4435
4125
|
return Length;
|
|
4436
4126
|
}();
|
|
4437
|
-
|
|
4438
4127
|
Length.toolType = LENGTH;
|
|
4439
4128
|
Length.utilityToolType = LENGTH;
|
|
4440
4129
|
Length.TID300Representation = TID300Length;
|
|
4441
|
-
|
|
4442
4130
|
Length.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
4443
4131
|
if (!TrackingIdentifier.includes(":")) {
|
|
4444
4132
|
return false;
|
|
4445
4133
|
}
|
|
4446
|
-
|
|
4447
4134
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4135
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
4136
|
+
cornerstone3DTag = _TrackingIdentifier$s2[0],
|
|
4137
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
4452
4138
|
if (cornerstone3DTag !== CORNERSTONE_3D_TAG) {
|
|
4453
4139
|
return false;
|
|
4454
4140
|
}
|
|
4455
|
-
|
|
4456
4141
|
return toolType === LENGTH;
|
|
4457
4142
|
};
|
|
4458
|
-
|
|
4459
4143
|
MeasurementReport.registerTool(Length);
|
|
4460
4144
|
|
|
4461
4145
|
var TID300Polyline = utilities.TID300.Polyline;
|
|
@@ -4550,29 +4234,24 @@ MeasurementReport.registerTool(PlanarFreehandROI);
|
|
|
4550
4234
|
var TID300Point = utilities.TID300.Point;
|
|
4551
4235
|
var PROBE = "Probe";
|
|
4552
4236
|
var trackingIdentifierTextValue = "".concat(CORNERSTONE_3D_TAG, ":").concat(PROBE);
|
|
4553
|
-
|
|
4554
4237
|
var Probe = /*#__PURE__*/function () {
|
|
4555
4238
|
function Probe() {
|
|
4556
4239
|
_classCallCheck(this, Probe);
|
|
4557
4240
|
}
|
|
4558
|
-
|
|
4559
4241
|
_createClass(Probe, null, [{
|
|
4560
4242
|
key: "getMeasurementData",
|
|
4561
4243
|
value: function getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata) {
|
|
4562
4244
|
var _MeasurementReport$ge = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, Probe.toolType),
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4245
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
4246
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup,
|
|
4247
|
+
ReferencedFrameNumber = _MeasurementReport$ge.ReferencedFrameNumber;
|
|
4567
4248
|
var referencedImageId = defaultState.annotation.metadata.referencedImageId;
|
|
4568
4249
|
var GraphicData = SCOORDGroup.GraphicData;
|
|
4569
4250
|
var worldCoords = [];
|
|
4570
|
-
|
|
4571
4251
|
for (var i = 0; i < GraphicData.length; i += 2) {
|
|
4572
4252
|
var point = imageToWorldCoords(referencedImageId, [GraphicData[i], GraphicData[i + 1]]);
|
|
4573
4253
|
worldCoords.push(point);
|
|
4574
4254
|
}
|
|
4575
|
-
|
|
4576
4255
|
var state = defaultState;
|
|
4577
4256
|
state.annotation.data = {
|
|
4578
4257
|
handles: {
|
|
@@ -4590,15 +4269,13 @@ var Probe = /*#__PURE__*/function () {
|
|
|
4590
4269
|
key: "getTID300RepresentationArguments",
|
|
4591
4270
|
value: function getTID300RepresentationArguments(tool, worldToImageCoords) {
|
|
4592
4271
|
var data = tool.data,
|
|
4593
|
-
|
|
4272
|
+
metadata = tool.metadata;
|
|
4594
4273
|
var finding = tool.finding,
|
|
4595
|
-
|
|
4274
|
+
findingSites = tool.findingSites;
|
|
4596
4275
|
var referencedImageId = metadata.referencedImageId;
|
|
4597
|
-
|
|
4598
4276
|
if (!referencedImageId) {
|
|
4599
4277
|
throw new Error("Probe.getTID300RepresentationArguments: referencedImageId is not defined");
|
|
4600
4278
|
}
|
|
4601
|
-
|
|
4602
4279
|
var points = data.handles.points;
|
|
4603
4280
|
var pointsImage = points.map(function (point) {
|
|
4604
4281
|
var pointImage = worldToImageCoords(referencedImageId, point);
|
|
@@ -4616,31 +4293,24 @@ var Probe = /*#__PURE__*/function () {
|
|
|
4616
4293
|
return TID300RepresentationArguments;
|
|
4617
4294
|
}
|
|
4618
4295
|
}]);
|
|
4619
|
-
|
|
4620
4296
|
return Probe;
|
|
4621
4297
|
}();
|
|
4622
|
-
|
|
4623
4298
|
Probe.toolType = PROBE;
|
|
4624
4299
|
Probe.utilityToolType = PROBE;
|
|
4625
4300
|
Probe.TID300Representation = TID300Point;
|
|
4626
|
-
|
|
4627
4301
|
Probe.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
|
|
4628
4302
|
if (!TrackingIdentifier.includes(":")) {
|
|
4629
4303
|
return false;
|
|
4630
4304
|
}
|
|
4631
|
-
|
|
4632
4305
|
var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4306
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
4307
|
+
cornerstone3DTag = _TrackingIdentifier$s2[0],
|
|
4308
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
4637
4309
|
if (cornerstone3DTag !== CORNERSTONE_3D_TAG) {
|
|
4638
4310
|
return false;
|
|
4639
4311
|
}
|
|
4640
|
-
|
|
4641
4312
|
return toolType === PROBE;
|
|
4642
4313
|
};
|
|
4643
|
-
|
|
4644
4314
|
MeasurementReport.registerTool(Probe);
|
|
4645
4315
|
|
|
4646
4316
|
var Cornerstone3D = {
|
|
@@ -4660,20 +4330,21 @@ var Cornerstone3D = {
|
|
|
4660
4330
|
};
|
|
4661
4331
|
|
|
4662
4332
|
var Colors = data.Colors,
|
|
4663
|
-
|
|
4664
|
-
// Should we move it to Colors.js
|
|
4333
|
+
BitArray = data.BitArray;
|
|
4665
4334
|
|
|
4335
|
+
// TODO: Is there a better name for this? RGBAInt?
|
|
4336
|
+
// Should we move it to Colors.js
|
|
4666
4337
|
function dicomlab2RGBA(cielab) {
|
|
4667
4338
|
var rgba = Colors.dicomlab2RGB(cielab).map(function (x) {
|
|
4668
4339
|
return Math.round(x * 255);
|
|
4669
4340
|
});
|
|
4670
4341
|
rgba.push(255);
|
|
4671
4342
|
return rgba;
|
|
4672
|
-
}
|
|
4343
|
+
}
|
|
4344
|
+
|
|
4345
|
+
// TODO: Copied these functions in from VTK Math so we don't need a dependency.
|
|
4673
4346
|
// I guess we should put them somewhere
|
|
4674
4347
|
// https://github.com/Kitware/vtk-js/blob/master/Sources/Common/Core/Math/index.js
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
4348
|
function cross(x, y, out) {
|
|
4678
4349
|
var Zx = x[1] * y[2] - x[2] * y[1];
|
|
4679
4350
|
var Zy = x[2] * y[0] - x[0] * y[2];
|
|
@@ -4682,68 +4353,59 @@ function cross(x, y, out) {
|
|
|
4682
4353
|
out[1] = Zy;
|
|
4683
4354
|
out[2] = Zz;
|
|
4684
4355
|
}
|
|
4685
|
-
|
|
4686
4356
|
function norm(x) {
|
|
4687
4357
|
var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3;
|
|
4688
|
-
|
|
4689
4358
|
switch (n) {
|
|
4690
4359
|
case 1:
|
|
4691
4360
|
return Math.abs(x);
|
|
4692
|
-
|
|
4693
4361
|
case 2:
|
|
4694
4362
|
return Math.sqrt(x[0] * x[0] + x[1] * x[1]);
|
|
4695
|
-
|
|
4696
4363
|
case 3:
|
|
4697
4364
|
return Math.sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
|
|
4698
|
-
|
|
4699
4365
|
default:
|
|
4700
4366
|
{
|
|
4701
4367
|
var sum = 0;
|
|
4702
|
-
|
|
4703
4368
|
for (var i = 0; i < n; i++) {
|
|
4704
4369
|
sum += x[i] * x[i];
|
|
4705
4370
|
}
|
|
4706
|
-
|
|
4707
4371
|
return Math.sqrt(sum);
|
|
4708
4372
|
}
|
|
4709
4373
|
}
|
|
4710
4374
|
}
|
|
4711
|
-
|
|
4712
4375
|
function normalize(x) {
|
|
4713
4376
|
var den = norm(x);
|
|
4714
|
-
|
|
4715
4377
|
if (den !== 0.0) {
|
|
4716
4378
|
x[0] /= den;
|
|
4717
4379
|
x[1] /= den;
|
|
4718
4380
|
x[2] /= den;
|
|
4719
4381
|
}
|
|
4720
|
-
|
|
4721
4382
|
return den;
|
|
4722
4383
|
}
|
|
4723
|
-
|
|
4724
4384
|
function subtract(a, b, out) {
|
|
4725
4385
|
out[0] = a[0] - b[0];
|
|
4726
4386
|
out[1] = a[1] - b[1];
|
|
4727
4387
|
out[2] = a[2] - b[2];
|
|
4728
|
-
}
|
|
4729
|
-
// dcmjs.adapters.vtk.Multiframe? dcmjs.utils?
|
|
4730
|
-
|
|
4388
|
+
}
|
|
4731
4389
|
|
|
4390
|
+
// TODO: This is a useful utility on its own. We should move it somewhere?
|
|
4391
|
+
// dcmjs.adapters.vtk.Multiframe? dcmjs.utils?
|
|
4732
4392
|
function geometryFromFunctionalGroups(dataset, PerFrameFunctionalGroups) {
|
|
4733
4393
|
var geometry = {};
|
|
4734
4394
|
var pixelMeasures = dataset.SharedFunctionalGroupsSequence.PixelMeasuresSequence;
|
|
4735
|
-
var planeOrientation = dataset.SharedFunctionalGroupsSequence.PlaneOrientationSequence;
|
|
4395
|
+
var planeOrientation = dataset.SharedFunctionalGroupsSequence.PlaneOrientationSequence;
|
|
4396
|
+
|
|
4397
|
+
// Find the origin of the volume from the PerFrameFunctionalGroups' ImagePositionPatient values
|
|
4736
4398
|
//
|
|
4737
4399
|
// TODO: assumes sorted frames. This should read the ImagePositionPatient from each frame and
|
|
4738
4400
|
// sort them to obtain the first and last position along the acquisition axis.
|
|
4739
|
-
|
|
4740
4401
|
var firstFunctionalGroup = PerFrameFunctionalGroups[0];
|
|
4741
4402
|
var lastFunctionalGroup = PerFrameFunctionalGroups[PerFrameFunctionalGroups.length - 1];
|
|
4742
4403
|
var firstPosition = firstFunctionalGroup.PlanePositionSequence.ImagePositionPatient.map(Number);
|
|
4743
4404
|
var lastPosition = lastFunctionalGroup.PlanePositionSequence.ImagePositionPatient.map(Number);
|
|
4744
|
-
geometry.origin = firstPosition;
|
|
4745
|
-
// unlike ImageOrientationPatient
|
|
4405
|
+
geometry.origin = firstPosition;
|
|
4746
4406
|
|
|
4407
|
+
// NB: DICOM PixelSpacing is defined as Row then Column,
|
|
4408
|
+
// unlike ImageOrientationPatient
|
|
4747
4409
|
geometry.spacing = [pixelMeasures.PixelSpacing[1], pixelMeasures.PixelSpacing[0], pixelMeasures.SpacingBetweenSlices].map(Number);
|
|
4748
4410
|
geometry.dimensions = [dataset.Columns, dataset.Rows, PerFrameFunctionalGroups.length].map(Number);
|
|
4749
4411
|
var orientation = planeOrientation.ImageOrientationPatient.map(Number);
|
|
@@ -4757,11 +4419,11 @@ function geometryFromFunctionalGroups(dataset, PerFrameFunctionalGroups) {
|
|
|
4757
4419
|
geometry.direction = columnStepToPatient.concat(rowStepToPatient).concat(geometry.sliceStep);
|
|
4758
4420
|
return geometry;
|
|
4759
4421
|
}
|
|
4760
|
-
|
|
4761
4422
|
var Segmentation = /*#__PURE__*/function () {
|
|
4762
4423
|
function Segmentation() {
|
|
4763
4424
|
_classCallCheck(this, Segmentation);
|
|
4764
4425
|
}
|
|
4426
|
+
|
|
4765
4427
|
/**
|
|
4766
4428
|
* Produces an array of Segments from an input DICOM Segmentation dataset
|
|
4767
4429
|
*
|
|
@@ -4800,19 +4462,17 @@ var Segmentation = /*#__PURE__*/function () {
|
|
|
4800
4462
|
* @param dataset
|
|
4801
4463
|
* @return {{}}
|
|
4802
4464
|
*/
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
4465
|
_createClass(Segmentation, null, [{
|
|
4806
4466
|
key: "generateSegments",
|
|
4807
4467
|
value: function generateSegments(dataset) {
|
|
4808
4468
|
if (dataset.SegmentSequence.constructor.name !== "Array") {
|
|
4809
4469
|
dataset.SegmentSequence = [dataset.SegmentSequence];
|
|
4810
4470
|
}
|
|
4811
|
-
|
|
4812
4471
|
dataset.SegmentSequence.forEach(function (segment) {
|
|
4813
4472
|
// TODO: other interesting fields could be extracted from the segment
|
|
4814
4473
|
// TODO: Read SegmentsOverlay field
|
|
4815
4474
|
// http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.8.20.2.html
|
|
4475
|
+
|
|
4816
4476
|
// TODO: Looks like vtkColor only wants RGB in 0-1 values.
|
|
4817
4477
|
// Why was this example converting to RGBA with 0-255 values?
|
|
4818
4478
|
var color = dicomlab2RGBA(segment.RecommendedDisplayCIELabValue);
|
|
@@ -4823,14 +4483,16 @@ var Segmentation = /*#__PURE__*/function () {
|
|
|
4823
4483
|
size: null,
|
|
4824
4484
|
pixelData: null
|
|
4825
4485
|
};
|
|
4826
|
-
});
|
|
4486
|
+
});
|
|
4827
4487
|
|
|
4488
|
+
// make a list of functional groups per segment
|
|
4828
4489
|
dataset.PerFrameFunctionalGroupsSequence.forEach(function (functionalGroup) {
|
|
4829
4490
|
var segmentNumber = functionalGroup.SegmentIdentificationSequence.ReferencedSegmentNumber;
|
|
4830
4491
|
segments[segmentNumber].functionalGroups.push(functionalGroup);
|
|
4831
|
-
});
|
|
4832
|
-
// TODO: only handles one-bit-per pixel
|
|
4492
|
+
});
|
|
4833
4493
|
|
|
4494
|
+
// determine per-segment index into the pixel data
|
|
4495
|
+
// TODO: only handles one-bit-per pixel
|
|
4834
4496
|
var frameSize = Math.ceil(dataset.Rows * dataset.Columns / 8);
|
|
4835
4497
|
var nextOffset = 0;
|
|
4836
4498
|
Object.keys(segments).forEach(function (segmentNumber) {
|
|
@@ -4847,7 +4509,6 @@ var Segmentation = /*#__PURE__*/function () {
|
|
|
4847
4509
|
return segments;
|
|
4848
4510
|
}
|
|
4849
4511
|
}]);
|
|
4850
|
-
|
|
4851
4512
|
return Segmentation;
|
|
4852
4513
|
}();
|
|
4853
4514
|
|