@cornerstonejs/adapters 1.7.2 → 1.8.1

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.
Files changed (30) hide show
  1. package/dist/{@cornerstonejs/adapters.es.js → adapters.es.js} +1344 -698
  2. package/dist/adapters.es.js.map +1 -0
  3. package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone/index.d.ts +5 -3
  4. package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone3D/Angle.d.ts +1 -1
  5. package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone3D/Bidirectional.d.ts +1 -1
  6. package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone3D/CircleROI.d.ts +1 -1
  7. package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone3D/CobbAngle.d.ts +1 -1
  8. package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone3D/EllipticalROI.d.ts +1 -1
  9. package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone3D/MeasurementReport.d.ts +1 -1
  10. package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone3D/PlanarFreehandROI.d.ts +1 -1
  11. package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone3D/RectangleROI.d.ts +1 -1
  12. package/dist/types/adapters/Cornerstone3D/Segmentation/generateLabelMaps2DFrom3D.d.ts +18 -0
  13. package/dist/types/adapters/Cornerstone3D/Segmentation/generateSegmentation.d.ts +8 -0
  14. package/dist/types/adapters/Cornerstone3D/Segmentation/generateToolState.d.ts +16 -0
  15. package/dist/types/adapters/Cornerstone3D/Segmentation/index.d.ts +4 -0
  16. package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone3D/index.d.ts +6 -2
  17. package/dist/types/adapters/VTKjs/index.d.ts +4 -0
  18. package/dist/types/adapters/enums/Events.d.ts +10 -0
  19. package/dist/types/adapters/enums/index.d.ts +2 -0
  20. package/dist/types/adapters/helpers/codeMeaningEquals.d.ts +9 -0
  21. package/dist/types/adapters/helpers/graphicTypeEquals.d.ts +7 -0
  22. package/dist/types/adapters/helpers/index.d.ts +4 -0
  23. package/dist/types/adapters/helpers/toArray.d.ts +2 -0
  24. package/dist/{@cornerstonejs/dts → types}/adapters/index.d.ts +21 -3
  25. package/dist/types/index.d.ts +2 -0
  26. package/package.json +15 -8
  27. package/dist/@cornerstonejs/adapters.es.js.map +0 -1
  28. package/dist/@cornerstonejs/dts/adapters/VTKjs/index.d.ts +0 -4
  29. package/dist/@cornerstonejs/dts/index.d.ts +0 -3
  30. /package/dist/{@cornerstonejs/dts → types}/adapters/Cornerstone3D/isValidCornerstoneTrackingIdentifier.d.ts +0 -0
@@ -1,6 +1,7 @@
1
1
  import { utilities, derivations, normalizers, data, log } from 'dcmjs';
2
2
  import ndarray from 'ndarray';
3
3
  import cloneDeep from 'lodash.clonedeep';
4
+ import { Buffer } from 'buffer';
4
5
  import { vec3 } from 'gl-matrix';
5
6
 
6
7
  function _iterableToArrayLimit(arr, i) {
@@ -51,6 +52,337 @@ function _objectSpread2(target) {
51
52
  }
52
53
  return target;
53
54
  }
55
+ function _regeneratorRuntime() {
56
+ _regeneratorRuntime = function () {
57
+ return exports;
58
+ };
59
+ var exports = {},
60
+ Op = Object.prototype,
61
+ hasOwn = Op.hasOwnProperty,
62
+ defineProperty = Object.defineProperty || function (obj, key, desc) {
63
+ obj[key] = desc.value;
64
+ },
65
+ $Symbol = "function" == typeof Symbol ? Symbol : {},
66
+ iteratorSymbol = $Symbol.iterator || "@@iterator",
67
+ asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
68
+ toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
69
+ function define(obj, key, value) {
70
+ return Object.defineProperty(obj, key, {
71
+ value: value,
72
+ enumerable: !0,
73
+ configurable: !0,
74
+ writable: !0
75
+ }), obj[key];
76
+ }
77
+ try {
78
+ define({}, "");
79
+ } catch (err) {
80
+ define = function (obj, key, value) {
81
+ return obj[key] = value;
82
+ };
83
+ }
84
+ function wrap(innerFn, outerFn, self, tryLocsList) {
85
+ var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
86
+ generator = Object.create(protoGenerator.prototype),
87
+ context = new Context(tryLocsList || []);
88
+ return defineProperty(generator, "_invoke", {
89
+ value: makeInvokeMethod(innerFn, self, context)
90
+ }), generator;
91
+ }
92
+ function tryCatch(fn, obj, arg) {
93
+ try {
94
+ return {
95
+ type: "normal",
96
+ arg: fn.call(obj, arg)
97
+ };
98
+ } catch (err) {
99
+ return {
100
+ type: "throw",
101
+ arg: err
102
+ };
103
+ }
104
+ }
105
+ exports.wrap = wrap;
106
+ var ContinueSentinel = {};
107
+ function Generator() {}
108
+ function GeneratorFunction() {}
109
+ function GeneratorFunctionPrototype() {}
110
+ var IteratorPrototype = {};
111
+ define(IteratorPrototype, iteratorSymbol, function () {
112
+ return this;
113
+ });
114
+ var getProto = Object.getPrototypeOf,
115
+ NativeIteratorPrototype = getProto && getProto(getProto(values([])));
116
+ NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
117
+ var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
118
+ function defineIteratorMethods(prototype) {
119
+ ["next", "throw", "return"].forEach(function (method) {
120
+ define(prototype, method, function (arg) {
121
+ return this._invoke(method, arg);
122
+ });
123
+ });
124
+ }
125
+ function AsyncIterator(generator, PromiseImpl) {
126
+ function invoke(method, arg, resolve, reject) {
127
+ var record = tryCatch(generator[method], generator, arg);
128
+ if ("throw" !== record.type) {
129
+ var result = record.arg,
130
+ value = result.value;
131
+ return value && "object" == typeof value && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
132
+ invoke("next", value, resolve, reject);
133
+ }, function (err) {
134
+ invoke("throw", err, resolve, reject);
135
+ }) : PromiseImpl.resolve(value).then(function (unwrapped) {
136
+ result.value = unwrapped, resolve(result);
137
+ }, function (error) {
138
+ return invoke("throw", error, resolve, reject);
139
+ });
140
+ }
141
+ reject(record.arg);
142
+ }
143
+ var previousPromise;
144
+ defineProperty(this, "_invoke", {
145
+ value: function (method, arg) {
146
+ function callInvokeWithMethodAndArg() {
147
+ return new PromiseImpl(function (resolve, reject) {
148
+ invoke(method, arg, resolve, reject);
149
+ });
150
+ }
151
+ return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
152
+ }
153
+ });
154
+ }
155
+ function makeInvokeMethod(innerFn, self, context) {
156
+ var state = "suspendedStart";
157
+ return function (method, arg) {
158
+ if ("executing" === state) throw new Error("Generator is already running");
159
+ if ("completed" === state) {
160
+ if ("throw" === method) throw arg;
161
+ return doneResult();
162
+ }
163
+ for (context.method = method, context.arg = arg;;) {
164
+ var delegate = context.delegate;
165
+ if (delegate) {
166
+ var delegateResult = maybeInvokeDelegate(delegate, context);
167
+ if (delegateResult) {
168
+ if (delegateResult === ContinueSentinel) continue;
169
+ return delegateResult;
170
+ }
171
+ }
172
+ if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
173
+ if ("suspendedStart" === state) throw state = "completed", context.arg;
174
+ context.dispatchException(context.arg);
175
+ } else "return" === context.method && context.abrupt("return", context.arg);
176
+ state = "executing";
177
+ var record = tryCatch(innerFn, self, context);
178
+ if ("normal" === record.type) {
179
+ if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
180
+ return {
181
+ value: record.arg,
182
+ done: context.done
183
+ };
184
+ }
185
+ "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
186
+ }
187
+ };
188
+ }
189
+ function maybeInvokeDelegate(delegate, context) {
190
+ var methodName = context.method,
191
+ method = delegate.iterator[methodName];
192
+ if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel;
193
+ var record = tryCatch(method, delegate.iterator, context.arg);
194
+ if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
195
+ var info = record.arg;
196
+ return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel);
197
+ }
198
+ function pushTryEntry(locs) {
199
+ var entry = {
200
+ tryLoc: locs[0]
201
+ };
202
+ 1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
203
+ }
204
+ function resetTryEntry(entry) {
205
+ var record = entry.completion || {};
206
+ record.type = "normal", delete record.arg, entry.completion = record;
207
+ }
208
+ function Context(tryLocsList) {
209
+ this.tryEntries = [{
210
+ tryLoc: "root"
211
+ }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0);
212
+ }
213
+ function values(iterable) {
214
+ if (iterable) {
215
+ var iteratorMethod = iterable[iteratorSymbol];
216
+ if (iteratorMethod) return iteratorMethod.call(iterable);
217
+ if ("function" == typeof iterable.next) return iterable;
218
+ if (!isNaN(iterable.length)) {
219
+ var i = -1,
220
+ next = function next() {
221
+ for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;
222
+ return next.value = undefined, next.done = !0, next;
223
+ };
224
+ return next.next = next;
225
+ }
226
+ }
227
+ return {
228
+ next: doneResult
229
+ };
230
+ }
231
+ function doneResult() {
232
+ return {
233
+ value: undefined,
234
+ done: !0
235
+ };
236
+ }
237
+ return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", {
238
+ value: GeneratorFunctionPrototype,
239
+ configurable: !0
240
+ }), defineProperty(GeneratorFunctionPrototype, "constructor", {
241
+ value: GeneratorFunction,
242
+ configurable: !0
243
+ }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
244
+ var ctor = "function" == typeof genFun && genFun.constructor;
245
+ return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
246
+ }, exports.mark = function (genFun) {
247
+ return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun;
248
+ }, exports.awrap = function (arg) {
249
+ return {
250
+ __await: arg
251
+ };
252
+ }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
253
+ return this;
254
+ }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
255
+ void 0 === PromiseImpl && (PromiseImpl = Promise);
256
+ var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
257
+ return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
258
+ return result.done ? result.value : iter.next();
259
+ });
260
+ }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
261
+ return this;
262
+ }), define(Gp, "toString", function () {
263
+ return "[object Generator]";
264
+ }), exports.keys = function (val) {
265
+ var object = Object(val),
266
+ keys = [];
267
+ for (var key in object) keys.push(key);
268
+ return keys.reverse(), function next() {
269
+ for (; keys.length;) {
270
+ var key = keys.pop();
271
+ if (key in object) return next.value = key, next.done = !1, next;
272
+ }
273
+ return next.done = !0, next;
274
+ };
275
+ }, exports.values = values, Context.prototype = {
276
+ constructor: Context,
277
+ reset: function (skipTempReset) {
278
+ if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined);
279
+ },
280
+ stop: function () {
281
+ this.done = !0;
282
+ var rootRecord = this.tryEntries[0].completion;
283
+ if ("throw" === rootRecord.type) throw rootRecord.arg;
284
+ return this.rval;
285
+ },
286
+ dispatchException: function (exception) {
287
+ if (this.done) throw exception;
288
+ var context = this;
289
+ function handle(loc, caught) {
290
+ return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
291
+ }
292
+ for (var i = this.tryEntries.length - 1; i >= 0; --i) {
293
+ var entry = this.tryEntries[i],
294
+ record = entry.completion;
295
+ if ("root" === entry.tryLoc) return handle("end");
296
+ if (entry.tryLoc <= this.prev) {
297
+ var hasCatch = hasOwn.call(entry, "catchLoc"),
298
+ hasFinally = hasOwn.call(entry, "finallyLoc");
299
+ if (hasCatch && hasFinally) {
300
+ if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
301
+ if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
302
+ } else if (hasCatch) {
303
+ if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
304
+ } else {
305
+ if (!hasFinally) throw new Error("try statement without catch or finally");
306
+ if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
307
+ }
308
+ }
309
+ }
310
+ },
311
+ abrupt: function (type, arg) {
312
+ for (var i = this.tryEntries.length - 1; i >= 0; --i) {
313
+ var entry = this.tryEntries[i];
314
+ if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
315
+ var finallyEntry = entry;
316
+ break;
317
+ }
318
+ }
319
+ finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
320
+ var record = finallyEntry ? finallyEntry.completion : {};
321
+ return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
322
+ },
323
+ complete: function (record, afterLoc) {
324
+ if ("throw" === record.type) throw record.arg;
325
+ return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel;
326
+ },
327
+ finish: function (finallyLoc) {
328
+ for (var i = this.tryEntries.length - 1; i >= 0; --i) {
329
+ var entry = this.tryEntries[i];
330
+ if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
331
+ }
332
+ },
333
+ catch: function (tryLoc) {
334
+ for (var i = this.tryEntries.length - 1; i >= 0; --i) {
335
+ var entry = this.tryEntries[i];
336
+ if (entry.tryLoc === tryLoc) {
337
+ var record = entry.completion;
338
+ if ("throw" === record.type) {
339
+ var thrown = record.arg;
340
+ resetTryEntry(entry);
341
+ }
342
+ return thrown;
343
+ }
344
+ }
345
+ throw new Error("illegal catch attempt");
346
+ },
347
+ delegateYield: function (iterable, resultName, nextLoc) {
348
+ return this.delegate = {
349
+ iterator: values(iterable),
350
+ resultName: resultName,
351
+ nextLoc: nextLoc
352
+ }, "next" === this.method && (this.arg = undefined), ContinueSentinel;
353
+ }
354
+ }, exports;
355
+ }
356
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
357
+ try {
358
+ var info = gen[key](arg);
359
+ var value = info.value;
360
+ } catch (error) {
361
+ reject(error);
362
+ return;
363
+ }
364
+ if (info.done) {
365
+ resolve(value);
366
+ } else {
367
+ Promise.resolve(value).then(_next, _throw);
368
+ }
369
+ }
370
+ function _asyncToGenerator(fn) {
371
+ return function () {
372
+ var self = this,
373
+ args = arguments;
374
+ return new Promise(function (resolve, reject) {
375
+ var gen = fn.apply(self, args);
376
+ function _next(value) {
377
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
378
+ }
379
+ function _throw(err) {
380
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
381
+ }
382
+ _next(undefined);
383
+ });
384
+ };
385
+ }
54
386
  function _classCallCheck(instance, Constructor) {
55
387
  if (!(instance instanceof Constructor)) {
56
388
  throw new TypeError("Cannot call a class as a function");
@@ -187,19 +519,43 @@ function _toPropertyKey(arg) {
187
519
  return typeof key === "symbol" ? key : String(key);
188
520
  }
189
521
 
190
- var toArray = function toArray(x) {
191
- return Array.isArray(x) ? x : [x];
522
+ var toArray = function (x) { return (Array.isArray(x) ? x : [x]); };
523
+
524
+ /**
525
+ * Returns a function that checks if a given content item's ConceptNameCodeSequence.CodeMeaning
526
+ * matches the provided codeMeaningName.
527
+ * @param codeMeaningName - The CodeMeaning to match against.
528
+ * @returns A function that takes a content item and returns a boolean indicating whether the
529
+ * content item's CodeMeaning matches the provided codeMeaningName.
530
+ */
531
+ var codeMeaningEquals = function (codeMeaningName) {
532
+ return function (contentItem) {
533
+ return (contentItem.ConceptNameCodeSequence.CodeMeaning === codeMeaningName);
534
+ };
192
535
  };
193
- var codeMeaningEquals = function codeMeaningEquals(codeMeaningName) {
194
- return function (contentItem) {
195
- return contentItem.ConceptNameCodeSequence.CodeMeaning === codeMeaningName;
196
- };
536
+
537
+ /**
538
+ * Checks if a given content item's GraphicType property matches a specified value.
539
+ * @param {string} graphicType - The value to compare the content item's GraphicType property to.
540
+ * @returns {function} A function that takes a content item and returns a boolean indicating whether its GraphicType property matches the specified value.
541
+ */
542
+ var graphicTypeEquals = function (graphicType) {
543
+ return function (contentItem) {
544
+ return contentItem && contentItem.GraphicType === graphicType;
545
+ };
197
546
  };
198
547
 
548
+ var index$1 = /*#__PURE__*/Object.freeze({
549
+ __proto__: null,
550
+ codeMeaningEquals: codeMeaningEquals,
551
+ graphicTypeEquals: graphicTypeEquals,
552
+ toArray: toArray
553
+ });
554
+
199
555
  var TID1500$1 = utilities.TID1500,
200
556
  addAccessors$1 = utilities.addAccessors;
201
557
  var StructuredReport$1 = derivations.StructuredReport;
202
- var Normalizer$3 = normalizers.Normalizer;
558
+ var Normalizer$4 = normalizers.Normalizer;
203
559
  var TID1500MeasurementReport$1 = TID1500$1.TID1500MeasurementReport,
204
560
  TID1501MeasurementGroup$1 = TID1500$1.TID1501MeasurementGroup;
205
561
  var DicomMetaDictionary$3 = data.DicomMetaDictionary;
@@ -331,7 +687,7 @@ var MeasurementReport$1 = /*#__PURE__*/function () {
331
687
  ReferencedSOPClassUID: sopCommonModule.sopClassUID,
332
688
  ReferencedSOPInstanceUID: sopCommonModule.sopInstanceUID
333
689
  };
334
- if (Normalizer$3.isMultiframeSOPClassUID(sopCommonModule.sopClassUID)) {
690
+ if (Normalizer$4.isMultiframeSOPClassUID(sopCommonModule.sopClassUID)) {
335
691
  ReferencedSOPSequence.ReferencedFrameNumber = frameNumber;
336
692
  }
337
693
 
@@ -1165,80 +1521,353 @@ ArrowAnnotate$1.isValidCornerstoneTrackingIdentifier = function (TrackingIdentif
1165
1521
  };
1166
1522
  MeasurementReport$1.registerTool(ArrowAnnotate$1);
1167
1523
 
1168
- var _utilities$orientatio$1 = utilities.orientation,
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;
1173
- var datasetToBlob$1 = utilities.datasetToBlob,
1174
- BitArray$2 = utilities.BitArray,
1175
- DicomMessage$1 = utilities.DicomMessage,
1176
- DicomMetaDictionary$2 = utilities.DicomMetaDictionary;
1177
- var Normalizer$2 = normalizers.Normalizer;
1178
- var SegmentationDerivation$1 = derivations.Segmentation;
1179
- var Segmentation$3 = {
1180
- generateSegmentation: generateSegmentation$2,
1181
- generateToolState: generateToolState$2
1182
- };
1183
-
1184
- /**
1185
- *
1186
- * @typedef {Object} BrushData
1187
- * @property {Object} toolState - The cornerstoneTools global toolState.
1188
- * @property {Object[]} segments - The cornerstoneTools segment metadata that corresponds to the
1189
- * seriesInstanceUid.
1190
- */
1191
-
1192
- /**
1193
- * generateSegmentation - Generates cornerstoneTools brush data, given a stack of
1194
- * imageIds, images and the cornerstoneTools brushData.
1195
- *
1196
- * @param {object[]} images An array of the cornerstone image objects.
1197
- * @param {BrushData} brushData and object containing the brushData.
1198
- * @returns {type} description
1199
- */
1200
- function generateSegmentation$2(images, brushData) {
1201
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
1202
- includeSliceSpacing: true
1203
- };
1204
- var toolState = brushData.toolState,
1205
- segments = brushData.segments;
1206
-
1207
- // Calculate the dimensions of the data cube.
1208
- var image0 = images[0];
1209
- var dims = {
1210
- x: image0.columns,
1211
- y: image0.rows,
1212
- z: images.length
1213
- };
1214
- dims.xy = dims.x * dims.y;
1215
- var numSegments = _getSegCount(seg, segments);
1216
- if (!numSegments) {
1217
- throw new Error("No segments to export!");
1524
+ var TID300CobbAngle$2 = utilities.TID300.CobbAngle;
1525
+ var COBB_ANGLE = "CobbAngle";
1526
+ var CobbAngle$1 = /*#__PURE__*/function () {
1527
+ function CobbAngle() {
1528
+ _classCallCheck(this, CobbAngle);
1218
1529
  }
1219
- var isMultiframe = image0.imageId.includes("?frame");
1220
- var seg = _createSegFromImages$1(images, isMultiframe, options);
1221
- var _getNumberOfFramesPer = _getNumberOfFramesPerSegment(toolState, images, segments),
1222
- referencedFramesPerSegment = _getNumberOfFramesPer.referencedFramesPerSegment,
1223
- segmentIndicies = _getNumberOfFramesPer.segmentIndicies;
1224
- var NumberOfFrames = 0;
1225
- for (var i = 0; i < referencedFramesPerSegment.length; i++) {
1226
- NumberOfFrames += referencedFramesPerSegment[i].length;
1530
+ _createClass(CobbAngle, null, [{
1531
+ key: "getMeasurementData",
1532
+ value:
1533
+ // TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport.
1534
+ function getMeasurementData(MeasurementGroup) {
1535
+ var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
1536
+ defaultState = _MeasurementReport$ge.defaultState,
1537
+ NUMGroup = _MeasurementReport$ge.NUMGroup,
1538
+ SCOORDGroup = _MeasurementReport$ge.SCOORDGroup;
1539
+ var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
1540
+ rAngle: NUMGroup.MeasuredValueSequence.NumericValue,
1541
+ toolType: CobbAngle.toolType,
1542
+ handles: {
1543
+ start: {},
1544
+ end: {},
1545
+ start2: {
1546
+ highlight: true,
1547
+ drawnIndependently: true
1548
+ },
1549
+ end2: {
1550
+ highlight: true,
1551
+ drawnIndependently: true
1552
+ },
1553
+ textBox: {
1554
+ hasMoved: false,
1555
+ movesIndependently: false,
1556
+ drawnIndependently: true,
1557
+ allowedOutsideImage: true,
1558
+ hasBoundingBox: true
1559
+ }
1560
+ }
1561
+ });
1562
+ var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 8);
1563
+ state.handles.start.x = _SCOORDGroup$GraphicD[0];
1564
+ state.handles.start.y = _SCOORDGroup$GraphicD[1];
1565
+ state.handles.end.x = _SCOORDGroup$GraphicD[2];
1566
+ state.handles.end.y = _SCOORDGroup$GraphicD[3];
1567
+ state.handles.start2.x = _SCOORDGroup$GraphicD[4];
1568
+ state.handles.start2.y = _SCOORDGroup$GraphicD[5];
1569
+ state.handles.end2.x = _SCOORDGroup$GraphicD[6];
1570
+ state.handles.end2.y = _SCOORDGroup$GraphicD[7];
1571
+ return state;
1572
+ }
1573
+ }, {
1574
+ key: "getTID300RepresentationArguments",
1575
+ value: function getTID300RepresentationArguments(tool) {
1576
+ var handles = tool.handles,
1577
+ finding = tool.finding,
1578
+ findingSites = tool.findingSites;
1579
+ var point1 = handles.start;
1580
+ var point2 = handles.end;
1581
+ var point3 = handles.start2;
1582
+ var point4 = handles.end2;
1583
+ var rAngle = tool.rAngle;
1584
+ var trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:CobbAngle";
1585
+ return {
1586
+ point1: point1,
1587
+ point2: point2,
1588
+ point3: point3,
1589
+ point4: point4,
1590
+ rAngle: rAngle,
1591
+ trackingIdentifierTextValue: trackingIdentifierTextValue,
1592
+ finding: finding,
1593
+ findingSites: findingSites || []
1594
+ };
1595
+ }
1596
+ }]);
1597
+ return CobbAngle;
1598
+ }();
1599
+ CobbAngle$1.toolType = COBB_ANGLE;
1600
+ CobbAngle$1.utilityToolType = COBB_ANGLE;
1601
+ CobbAngle$1.TID300Representation = TID300CobbAngle$2;
1602
+ CobbAngle$1.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
1603
+ if (!TrackingIdentifier.includes(":")) {
1604
+ return false;
1227
1605
  }
1228
- seg.setNumberOfFrames(NumberOfFrames);
1229
- for (var _i = 0; _i < segmentIndicies.length; _i++) {
1230
- var segmentIndex = segmentIndicies[_i];
1231
- var referencedFrameIndicies = referencedFramesPerSegment[_i];
1606
+ var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
1607
+ _TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
1608
+ cornerstone4Tag = _TrackingIdentifier$s2[0],
1609
+ toolType = _TrackingIdentifier$s2[1];
1610
+ if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
1611
+ return false;
1612
+ }
1613
+ return toolType === COBB_ANGLE;
1614
+ };
1615
+ MeasurementReport$1.registerTool(CobbAngle$1);
1232
1616
 
1233
- // Frame numbers start from 1.
1234
- var referencedFrameNumbers = referencedFrameIndicies.map(function (element) {
1235
- return element + 1;
1236
- });
1237
- var segment = segments[segmentIndex];
1238
- seg.addSegment(segment, _extractCornerstoneToolsPixelData(segmentIndex, referencedFrameIndicies, toolState, images, dims), referencedFrameNumbers);
1617
+ var TID300Angle = utilities.TID300.Angle;
1618
+ var ANGLE = "Angle";
1619
+ var Angle$1 = /*#__PURE__*/function () {
1620
+ function Angle() {
1621
+ _classCallCheck(this, Angle);
1239
1622
  }
1240
- seg.bitPackPixelData();
1241
- var segBlob = datasetToBlob$1(seg.dataset);
1623
+ _createClass(Angle, null, [{
1624
+ key: "getMeasurementData",
1625
+ value:
1626
+ /**
1627
+ * Generate TID300 measurement data for a plane angle measurement - use a Angle, but label it as Angle
1628
+ */
1629
+ function getMeasurementData(MeasurementGroup) {
1630
+ var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
1631
+ defaultState = _MeasurementReport$ge.defaultState,
1632
+ NUMGroup = _MeasurementReport$ge.NUMGroup,
1633
+ SCOORDGroup = _MeasurementReport$ge.SCOORDGroup;
1634
+ var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
1635
+ rAngle: NUMGroup.MeasuredValueSequence.NumericValue,
1636
+ toolType: Angle.toolType,
1637
+ handles: {
1638
+ start: {},
1639
+ middle: {},
1640
+ end: {},
1641
+ textBox: {
1642
+ hasMoved: false,
1643
+ movesIndependently: false,
1644
+ drawnIndependently: true,
1645
+ allowedOutsideImage: true,
1646
+ hasBoundingBox: true
1647
+ }
1648
+ }
1649
+ });
1650
+ var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 8);
1651
+ state.handles.start.x = _SCOORDGroup$GraphicD[0];
1652
+ state.handles.start.y = _SCOORDGroup$GraphicD[1];
1653
+ state.handles.middle.x = _SCOORDGroup$GraphicD[2];
1654
+ state.handles.middle.y = _SCOORDGroup$GraphicD[3];
1655
+ state.handles.middle.x = _SCOORDGroup$GraphicD[4];
1656
+ state.handles.middle.y = _SCOORDGroup$GraphicD[5];
1657
+ state.handles.end.x = _SCOORDGroup$GraphicD[6];
1658
+ state.handles.end.y = _SCOORDGroup$GraphicD[7];
1659
+ return state;
1660
+ }
1661
+ }, {
1662
+ key: "getTID300RepresentationArguments",
1663
+ value: function getTID300RepresentationArguments(tool) {
1664
+ var handles = tool.handles,
1665
+ finding = tool.finding,
1666
+ findingSites = tool.findingSites;
1667
+ var point1 = handles.start;
1668
+ var point2 = handles.middle;
1669
+ var point3 = handles.middle;
1670
+ var point4 = handles.end;
1671
+ var rAngle = tool.rAngle;
1672
+ var trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:Angle";
1673
+ return {
1674
+ point1: point1,
1675
+ point2: point2,
1676
+ point3: point3,
1677
+ point4: point4,
1678
+ rAngle: rAngle,
1679
+ trackingIdentifierTextValue: trackingIdentifierTextValue,
1680
+ finding: finding,
1681
+ findingSites: findingSites || []
1682
+ };
1683
+ }
1684
+ }]);
1685
+ return Angle;
1686
+ }();
1687
+ Angle$1.toolType = ANGLE;
1688
+ Angle$1.utilityToolType = ANGLE;
1689
+ Angle$1.TID300Representation = TID300Angle;
1690
+ Angle$1.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
1691
+ if (!TrackingIdentifier.includes(":")) {
1692
+ return false;
1693
+ }
1694
+ var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
1695
+ _TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
1696
+ cornerstone4Tag = _TrackingIdentifier$s2[0],
1697
+ toolType = _TrackingIdentifier$s2[1];
1698
+ if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
1699
+ return false;
1700
+ }
1701
+ return toolType === ANGLE;
1702
+ };
1703
+ MeasurementReport$1.registerTool(Angle$1);
1704
+
1705
+ var TID300Polyline$2 = utilities.TID300.Polyline;
1706
+ var RectangleRoi = /*#__PURE__*/function () {
1707
+ function RectangleRoi() {
1708
+ _classCallCheck(this, RectangleRoi);
1709
+ }
1710
+ _createClass(RectangleRoi, null, [{
1711
+ key: "getMeasurementData",
1712
+ value: function getMeasurementData(MeasurementGroup) {
1713
+ var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
1714
+ defaultState = _MeasurementReport$ge.defaultState,
1715
+ SCOORDGroup = _MeasurementReport$ge.SCOORDGroup,
1716
+ NUMGroup = _MeasurementReport$ge.NUMGroup;
1717
+ var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
1718
+ toolType: RectangleRoi.toolType,
1719
+ handles: {
1720
+ start: {},
1721
+ end: {},
1722
+ textBox: {
1723
+ active: false,
1724
+ hasMoved: false,
1725
+ movesIndependently: false,
1726
+ drawnIndependently: true,
1727
+ allowedOutsideImage: true,
1728
+ hasBoundingBox: true
1729
+ },
1730
+ initialRotation: 0
1731
+ },
1732
+ cachedStats: {
1733
+ area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0
1734
+ },
1735
+ color: undefined,
1736
+ invalidated: true
1737
+ });
1738
+ var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 6);
1739
+ state.handles.start.x = _SCOORDGroup$GraphicD[0];
1740
+ state.handles.start.y = _SCOORDGroup$GraphicD[1];
1741
+ _SCOORDGroup$GraphicD[2];
1742
+ _SCOORDGroup$GraphicD[3];
1743
+ state.handles.end.x = _SCOORDGroup$GraphicD[4];
1744
+ state.handles.end.y = _SCOORDGroup$GraphicD[5];
1745
+ return state;
1746
+ }
1747
+ }, {
1748
+ key: "getTID300RepresentationArguments",
1749
+ value: function getTID300RepresentationArguments(tool) {
1750
+ var finding = tool.finding,
1751
+ findingSites = tool.findingSites,
1752
+ _tool$cachedStats = tool.cachedStats,
1753
+ cachedStats = _tool$cachedStats === void 0 ? {} : _tool$cachedStats,
1754
+ handles = tool.handles;
1755
+ var start = handles.start,
1756
+ end = handles.end;
1757
+ var points = [start, {
1758
+ x: start.x,
1759
+ y: end.y
1760
+ }, end, {
1761
+ x: end.x,
1762
+ y: start.y
1763
+ }];
1764
+ var area = cachedStats.area,
1765
+ perimeter = cachedStats.perimeter;
1766
+ var trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:RectangleRoi";
1767
+ return {
1768
+ points: points,
1769
+ area: area,
1770
+ perimeter: perimeter,
1771
+ trackingIdentifierTextValue: trackingIdentifierTextValue,
1772
+ finding: finding,
1773
+ findingSites: findingSites || []
1774
+ };
1775
+ }
1776
+ }]);
1777
+ return RectangleRoi;
1778
+ }();
1779
+ RectangleRoi.toolType = "RectangleRoi";
1780
+ RectangleRoi.utilityToolType = "RectangleRoi";
1781
+ RectangleRoi.TID300Representation = TID300Polyline$2;
1782
+ RectangleRoi.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
1783
+ if (!TrackingIdentifier.includes(":")) {
1784
+ return false;
1785
+ }
1786
+ var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
1787
+ _TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
1788
+ cornerstone4Tag = _TrackingIdentifier$s2[0],
1789
+ toolType = _TrackingIdentifier$s2[1];
1790
+ if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
1791
+ return false;
1792
+ }
1793
+ return toolType === RectangleRoi.toolType;
1794
+ };
1795
+ MeasurementReport$1.registerTool(RectangleRoi);
1796
+
1797
+ var _utilities$orientatio$1 = utilities.orientation,
1798
+ rotateDirectionCosinesInPlane$1 = _utilities$orientatio$1.rotateDirectionCosinesInPlane,
1799
+ flipIOP$1 = _utilities$orientatio$1.flipImageOrientationPatient,
1800
+ flipMatrix2D$1 = _utilities$orientatio$1.flipMatrix2D,
1801
+ rotateMatrix902D$1 = _utilities$orientatio$1.rotateMatrix902D;
1802
+ var datasetToBlob = utilities.datasetToBlob,
1803
+ BitArray$2 = utilities.BitArray,
1804
+ DicomMessage$1 = utilities.DicomMessage,
1805
+ DicomMetaDictionary$2 = utilities.DicomMetaDictionary;
1806
+ var Normalizer$3 = normalizers.Normalizer;
1807
+ var SegmentationDerivation$2 = derivations.Segmentation;
1808
+ var Segmentation$5 = {
1809
+ generateSegmentation: generateSegmentation$3,
1810
+ generateToolState: generateToolState$3
1811
+ };
1812
+
1813
+ /**
1814
+ *
1815
+ * @typedef {Object} BrushData
1816
+ * @property {Object} toolState - The cornerstoneTools global toolState.
1817
+ * @property {Object[]} segments - The cornerstoneTools segment metadata that corresponds to the
1818
+ * seriesInstanceUid.
1819
+ */
1820
+
1821
+ /**
1822
+ * generateSegmentation - Generates cornerstoneTools brush data, given a stack of
1823
+ * imageIds, images and the cornerstoneTools brushData.
1824
+ *
1825
+ * @param {object[]} images An array of the cornerstone image objects.
1826
+ * @param {BrushData} brushData and object containing the brushData.
1827
+ * @returns {type} description
1828
+ */
1829
+ function generateSegmentation$3(images, brushData) {
1830
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
1831
+ includeSliceSpacing: true
1832
+ };
1833
+ var toolState = brushData.toolState,
1834
+ segments = brushData.segments;
1835
+
1836
+ // Calculate the dimensions of the data cube.
1837
+ var image0 = images[0];
1838
+ var dims = {
1839
+ x: image0.columns,
1840
+ y: image0.rows,
1841
+ z: images.length
1842
+ };
1843
+ dims.xy = dims.x * dims.y;
1844
+ var numSegments = _getSegCount(seg, segments);
1845
+ if (!numSegments) {
1846
+ throw new Error("No segments to export!");
1847
+ }
1848
+ var isMultiframe = image0.imageId.includes("?frame");
1849
+ var seg = _createSegFromImages$1(images, isMultiframe, options);
1850
+ var _getNumberOfFramesPer = _getNumberOfFramesPerSegment(toolState, images, segments),
1851
+ referencedFramesPerSegment = _getNumberOfFramesPer.referencedFramesPerSegment,
1852
+ segmentIndicies = _getNumberOfFramesPer.segmentIndicies;
1853
+ var NumberOfFrames = 0;
1854
+ for (var i = 0; i < referencedFramesPerSegment.length; i++) {
1855
+ NumberOfFrames += referencedFramesPerSegment[i].length;
1856
+ }
1857
+ seg.setNumberOfFrames(NumberOfFrames);
1858
+ for (var _i = 0; _i < segmentIndicies.length; _i++) {
1859
+ var segmentIndex = segmentIndicies[_i];
1860
+ var referencedFrameIndicies = referencedFramesPerSegment[_i];
1861
+
1862
+ // Frame numbers start from 1.
1863
+ var referencedFrameNumbers = referencedFrameIndicies.map(function (element) {
1864
+ return element + 1;
1865
+ });
1866
+ var segment = segments[segmentIndex];
1867
+ seg.addSegment(segment, _extractCornerstoneToolsPixelData(segmentIndex, referencedFrameIndicies, toolState, images, dims), referencedFrameNumbers);
1868
+ }
1869
+ seg.bitPackPixelData();
1870
+ var segBlob = datasetToBlob(seg.dataset);
1242
1871
  return segBlob;
1243
1872
  }
1244
1873
  function _extractCornerstoneToolsPixelData(segmentIndex, referencedFrames, toolState, images, dims) {
@@ -1316,8 +1945,8 @@ function _createSegFromImages$1(images, isMultiframe, options) {
1316
1945
  datasets.push(_dataset);
1317
1946
  }
1318
1947
  }
1319
- var multiframe = Normalizer$2.normalizeToDataset(datasets);
1320
- return new SegmentationDerivation$1([multiframe], options);
1948
+ var multiframe = Normalizer$3.normalizeToDataset(datasets);
1949
+ return new SegmentationDerivation$2([multiframe], options);
1321
1950
  }
1322
1951
 
1323
1952
  /**
@@ -1330,11 +1959,11 @@ function _createSegFromImages$1(images, isMultiframe, options) {
1330
1959
  * @returns {Object} The toolState and an object from which the
1331
1960
  * segment metadata can be derived.
1332
1961
  */
1333
- function generateToolState$2(imageIds, arrayBuffer, metadataProvider) {
1962
+ function generateToolState$3(imageIds, arrayBuffer, metadataProvider) {
1334
1963
  var dicomData = DicomMessage$1.readFile(arrayBuffer);
1335
1964
  var dataset = DicomMetaDictionary$2.naturalizeDataset(dicomData.dict);
1336
1965
  dataset._meta = DicomMetaDictionary$2.namifyDataset(dicomData.meta);
1337
- var multiframe = Normalizer$2.normalizeToDataset([dataset]);
1966
+ var multiframe = Normalizer$3.normalizeToDataset([dataset]);
1338
1967
  var imagePlaneModule = metadataProvider.get("imagePlaneModule", imageIds[0]);
1339
1968
  if (!imagePlaneModule) {
1340
1969
  console.warn("Insufficient metadata, imagePlaneModule missing.");
@@ -1449,7 +2078,7 @@ function addImageIdSpecificBrushToolState(toolState, imageId, segmentIndex, pixe
1449
2078
  function getImageIdOfSourceImage(SourceImageSequence, imageIds, metadataProvider) {
1450
2079
  var ReferencedSOPInstanceUID = SourceImageSequence.ReferencedSOPInstanceUID,
1451
2080
  ReferencedFrameNumber = SourceImageSequence.ReferencedFrameNumber;
1452
- return ReferencedFrameNumber ? getImageIdOfReferencedFrame$1(ReferencedSOPInstanceUID, ReferencedFrameNumber, imageIds, metadataProvider) : getImageIdOfReferencedSingleFramedSOPInstance$1(ReferencedSOPInstanceUID, imageIds, metadataProvider);
2081
+ return ReferencedFrameNumber ? getImageIdOfReferencedFrame$1(ReferencedSOPInstanceUID, ReferencedFrameNumber, imageIds, metadataProvider) : getImageIdOfReferencedSingleFramedSOPInstance(ReferencedSOPInstanceUID, imageIds, metadataProvider);
1453
2082
  }
1454
2083
 
1455
2084
  /**
@@ -1462,7 +2091,7 @@ function getImageIdOfSourceImage(SourceImageSequence, imageIds, metadataProvider
1462
2091
  * from the cornerstone imageIds.
1463
2092
  * @return {String} The imageId that corresponds to the sopInstanceUid.
1464
2093
  */
1465
- function getImageIdOfReferencedSingleFramedSOPInstance$1(sopInstanceUid, imageIds, metadataProvider) {
2094
+ function getImageIdOfReferencedSingleFramedSOPInstance(sopInstanceUid, imageIds, metadataProvider) {
1466
2095
  return imageIds.find(function (imageId) {
1467
2096
  var sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
1468
2097
  if (!sopCommonModule) {
@@ -1588,26 +2217,38 @@ function getSegmentMetadata$1(multiframe) {
1588
2217
  };
1589
2218
  }
1590
2219
 
2220
+ /**
2221
+ * Cornerstone adapters events
2222
+ */
2223
+ var Events;
2224
+ (function (Events) {
2225
+ /**
2226
+ * Cornerstone segmentation load progress event
2227
+ */
2228
+ Events["SEGMENTATION_LOAD_PROGRESS"] = "CORNERSTONE_ADAPTER_SEGMENTATION_LOAD_PROGRESS";
2229
+ })(Events || (Events = {}));
2230
+ var Events$1 = Events;
2231
+
2232
+ var index = /*#__PURE__*/Object.freeze({
2233
+ __proto__: null,
2234
+ Events: Events$1
2235
+ });
2236
+
1591
2237
  var _utilities$orientatio = utilities.orientation,
1592
2238
  rotateDirectionCosinesInPlane = _utilities$orientatio.rotateDirectionCosinesInPlane,
1593
2239
  flipIOP = _utilities$orientatio.flipImageOrientationPatient,
1594
2240
  flipMatrix2D = _utilities$orientatio.flipMatrix2D,
1595
2241
  rotateMatrix902D = _utilities$orientatio.rotateMatrix902D,
1596
2242
  nearlyEqual = _utilities$orientatio.nearlyEqual;
1597
- var datasetToBlob = utilities.datasetToBlob,
1598
- BitArray$1 = utilities.BitArray,
1599
- DicomMessage = utilities.DicomMessage,
1600
- DicomMetaDictionary$1 = utilities.DicomMetaDictionary;
1601
- var Normalizer$1 = normalizers.Normalizer;
1602
- var SegmentationDerivation = derivations.Segmentation;
2243
+ var datasetToDict = data.datasetToDict,
2244
+ BitArray$1 = data.BitArray,
2245
+ DicomMessage = data.DicomMessage,
2246
+ DicomMetaDictionary$1 = data.DicomMetaDictionary;
2247
+ var Normalizer$2 = normalizers.Normalizer;
2248
+ var SegmentationDerivation$1 = derivations.Segmentation;
1603
2249
  var _utilities$compressio = utilities.compression,
1604
2250
  encode = _utilities$compressio.encode,
1605
2251
  decode = _utilities$compressio.decode;
1606
- var Segmentation$2 = {
1607
- generateSegmentation: generateSegmentation$1,
1608
- generateToolState: generateToolState$1,
1609
- fillSegmentation: fillSegmentation$1
1610
- };
1611
2252
 
1612
2253
  /**
1613
2254
  *
@@ -1616,10 +2257,9 @@ var Segmentation$2 = {
1616
2257
  * @property {Object[]} segments - The cornerstoneTools segment metadata that corresponds to the
1617
2258
  * seriesInstanceUid.
1618
2259
  */
1619
-
1620
2260
  var generateSegmentationDefaultOptions = {
1621
2261
  includeSliceSpacing: true,
1622
- rleEncode: true
2262
+ rleEncode: false
1623
2263
  };
1624
2264
 
1625
2265
  /**
@@ -1632,7 +2272,7 @@ var generateSegmentationDefaultOptions = {
1632
2272
  * @param {Object} userOptions Options to pass to the segmentation derivation and `fillSegmentation`.
1633
2273
  * @returns {Blob}
1634
2274
  */
1635
- function generateSegmentation$1(images, inputLabelmaps3D) {
2275
+ function generateSegmentation$2(images, inputLabelmaps3D) {
1636
2276
  var userOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1637
2277
  var isMultiframe = images[0].imageId.includes("?frame");
1638
2278
  var segmentation = _createSegFromImages(images, isMultiframe, userOptions);
@@ -1698,7 +2338,7 @@ function fillSegmentation$1(segmentation, inputLabelmaps3D) {
1698
2338
  return element + 1;
1699
2339
  });
1700
2340
  var segmentMetadata = metadata[segmentIndex];
1701
- var labelmaps = _getLabelmapsFromRefernecedFrameIndicies(labelmap3D, referencedFrameIndicies);
2341
+ var labelmaps = _getLabelmapsFromReferencedFrameIndicies(labelmap3D, referencedFrameIndicies);
1702
2342
  segmentation.addSegmentFromLabelmap(segmentMetadata, labelmaps, segmentIndex, referencedFrameNumbers);
1703
2343
  }
1704
2344
  }
@@ -1727,10 +2367,13 @@ function fillSegmentation$1(segmentation, inputLabelmaps3D) {
1727
2367
  // If no rleEncoding, at least bitpack the data.
1728
2368
  segmentation.bitPackPixelData();
1729
2369
  }
1730
- var segBlob = datasetToBlob(segmentation.dataset);
2370
+ var buffer = Buffer.from(datasetToDict(segmentation.dataset).write());
2371
+ var segBlob = new Blob([buffer], {
2372
+ type: "application/dicom"
2373
+ });
1731
2374
  return segBlob;
1732
2375
  }
1733
- function _getLabelmapsFromRefernecedFrameIndicies(labelmap3D, referencedFrameIndicies) {
2376
+ function _getLabelmapsFromReferencedFrameIndicies(labelmap3D, referencedFrameIndicies) {
1734
2377
  var labelmaps2D = labelmap3D.labelmaps2D;
1735
2378
  var labelmaps = [];
1736
2379
  for (var i = 0; i < referencedFrameIndicies.length; i++) {
@@ -1766,8 +2409,8 @@ function _createSegFromImages(images, isMultiframe, options) {
1766
2409
  datasets.push(_dataset);
1767
2410
  }
1768
2411
  }
1769
- var multiframe = Normalizer$1.normalizeToDataset(datasets);
1770
- return new SegmentationDerivation([multiframe], options);
2412
+ var multiframe = Normalizer$2.normalizeToDataset(datasets);
2413
+ return new SegmentationDerivation$1([multiframe], options);
1771
2414
  }
1772
2415
 
1773
2416
  /**
@@ -1777,8 +2420,7 @@ function _createSegFromImages(images, isMultiframe, options) {
1777
2420
  * @param {string[]} imageIds - An array of the imageIds.
1778
2421
  * @param {ArrayBuffer} arrayBuffer - The SEG arrayBuffer.
1779
2422
  * @param {*} metadataProvider.
1780
- * @param {bool} skipOverlapping - skip checks for overlapping segs, default value false.
1781
- * @param {number} tolerance - default value 1.e-3.
2423
+ * @param {obj} options - Options object.
1782
2424
  *
1783
2425
  * @return {[]ArrayBuffer}a list of array buffer for each labelMap
1784
2426
  * @return {Object} an object from which the segment metadata can be derived
@@ -1786,83 +2428,9 @@ function _createSegFromImages(images, isMultiframe, options) {
1786
2428
  * @return {[][][]} 3D list containing the track of segments per frame for each labelMap
1787
2429
  * (available only for the overlapping case).
1788
2430
  */
1789
- function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
1790
- var skipOverlapping = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
1791
- var tolerance = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1e-3;
1792
- var dicomData = DicomMessage.readFile(arrayBuffer);
1793
- var dataset = DicomMetaDictionary$1.naturalizeDataset(dicomData.dict);
1794
- dataset._meta = DicomMetaDictionary$1.namifyDataset(dicomData.meta);
1795
- var multiframe = Normalizer$1.normalizeToDataset([dataset]);
1796
- var imagePlaneModule = metadataProvider.get("imagePlaneModule", imageIds[0]);
1797
- var generalSeriesModule = metadataProvider.get("generalSeriesModule", imageIds[0]);
1798
- var SeriesInstanceUID = generalSeriesModule.seriesInstanceUID;
1799
- if (!imagePlaneModule) {
1800
- console.warn("Insufficient metadata, imagePlaneModule missing.");
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];
1803
-
1804
- // Get IOP from ref series, compute supported orientations:
1805
- var validOrientations = getValidOrientations(ImageOrientationPatient);
1806
- var sliceLength = multiframe.Columns * multiframe.Rows;
1807
- var segMetadata = getSegmentMetadata(multiframe, SeriesInstanceUID);
1808
- var TransferSyntaxUID = multiframe._meta.TransferSyntaxUID.Value[0];
1809
- var pixelData;
1810
- if (TransferSyntaxUID === "1.2.840.10008.1.2.5") {
1811
- var rleEncodedFrames = Array.isArray(multiframe.PixelData) ? multiframe.PixelData : [multiframe.PixelData];
1812
- pixelData = decode(rleEncodedFrames, multiframe.Rows, multiframe.Columns);
1813
- if (multiframe.BitsStored === 1) {
1814
- console.warn("No implementation for rle + bitbacking.");
1815
- return;
1816
- }
1817
- } else {
1818
- pixelData = unpackPixelData(multiframe);
1819
- if (!pixelData) {
1820
- throw new Error("Fractional segmentations are not yet supported");
1821
- }
1822
- }
1823
- var orientation = checkOrientation(multiframe, validOrientations, [imagePlaneModule.rows, imagePlaneModule.columns, imageIds.length], tolerance);
1824
- var overlapping = false;
1825
- if (!skipOverlapping) {
1826
- overlapping = checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance);
1827
- }
1828
- var insertFunction;
1829
- switch (orientation) {
1830
- case "Planar":
1831
- if (overlapping) {
1832
- insertFunction = insertOverlappingPixelDataPlanar;
1833
- } else {
1834
- insertFunction = insertPixelDataPlanar;
1835
- }
1836
- break;
1837
- case "Perpendicular":
1838
- //insertFunction = insertPixelDataPerpendicular;
1839
- throw new Error("Segmentations orthogonal to the acquisition plane of the source data are not yet supported.");
1840
- case "Oblique":
1841
- throw new Error("Segmentations oblique to the acquisition plane of the source data are not yet supported.");
1842
- }
1843
-
1844
- /* if SEGs are overlapping:
1845
- 1) the labelmapBuffer will contain M volumes which have non-overlapping segments;
1846
- 2) segmentsOnFrame will have M * numberOfFrames values to track in which labelMap are the segments;
1847
- 3) insertFunction will return the number of LabelMaps
1848
- 4) generateToolState return is an array*/
1849
-
1850
- var segmentsOnFrameArray = [];
1851
- segmentsOnFrameArray[0] = [];
1852
- var segmentsOnFrame = [];
1853
- var arrayBufferLength = sliceLength * imageIds.length * 2; // 2 bytes per label voxel in cst4.
1854
- var labelmapBufferArray = [];
1855
- labelmapBufferArray[0] = new ArrayBuffer(arrayBufferLength);
1856
- insertFunction(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance);
1857
- return {
1858
- labelmapBufferArray: labelmapBufferArray,
1859
- segMetadata: segMetadata,
1860
- segmentsOnFrame: segmentsOnFrame,
1861
- segmentsOnFrameArray: segmentsOnFrameArray
1862
- };
1863
- }
1864
-
1865
- // function insertPixelDataPerpendicular(
2431
+ function generateToolState$2(_x, _x2, _x3, _x4) {
2432
+ return _generateToolState.apply(this, arguments);
2433
+ } // function insertPixelDataPerpendicular(
1866
2434
  // segmentsOnFrame,
1867
2435
  // labelmapBuffer,
1868
2436
  // pixelData,
@@ -1877,30 +2445,23 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
1877
2445
  // Rows,
1878
2446
  // Columns
1879
2447
  // } = multiframe;
1880
-
1881
2448
  // const firstImagePlaneModule = metadataProvider.get(
1882
2449
  // "imagePlaneModule",
1883
2450
  // imageIds[0]
1884
2451
  // );
1885
-
1886
2452
  // const lastImagePlaneModule = metadataProvider.get(
1887
2453
  // "imagePlaneModule",
1888
2454
  // imageIds[imageIds.length - 1]
1889
2455
  // );
1890
-
1891
2456
  // console.log(firstImagePlaneModule);
1892
2457
  // console.log(lastImagePlaneModule);
1893
-
1894
2458
  // const corners = [
1895
2459
  // ...getCorners(firstImagePlaneModule),
1896
2460
  // ...getCorners(lastImagePlaneModule)
1897
2461
  // ];
1898
-
1899
2462
  // console.log(`corners:`);
1900
2463
  // console.log(corners);
1901
-
1902
2464
  // const indexToWorld = mat4.create();
1903
-
1904
2465
  // const ippFirstFrame = firstImagePlaneModule.imagePositionPatient;
1905
2466
  // const rowCosines = Array.isArray(firstImagePlaneModule.rowCosines)
1906
2467
  // ? [...firstImagePlaneModule.rowCosines]
@@ -1909,7 +2470,6 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
1909
2470
  // firstImagePlaneModule.rowCosines.y,
1910
2471
  // firstImagePlaneModule.rowCosines.z
1911
2472
  // ];
1912
-
1913
2473
  // const columnCosines = Array.isArray(firstImagePlaneModule.columnCosines)
1914
2474
  // ? [...firstImagePlaneModule.columnCosines]
1915
2475
  // : [
@@ -1917,9 +2477,7 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
1917
2477
  // firstImagePlaneModule.columnCosines.y,
1918
2478
  // firstImagePlaneModule.columnCosines.z
1919
2479
  // ];
1920
-
1921
2480
  // const { pixelSpacing } = firstImagePlaneModule;
1922
-
1923
2481
  // mat4.set(
1924
2482
  // indexToWorld,
1925
2483
  // // Column 1
@@ -1943,50 +2501,36 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
1943
2501
  // 0,
1944
2502
  // 1
1945
2503
  // );
1946
-
1947
2504
  // // TODO -> Get origin and (x,y,z) increments to build a translation matrix:
1948
2505
  // // TODO -> Equation C.7.6.2.1-1
1949
-
1950
2506
  // // | cx*di rx* Xx 0 | |x|
1951
2507
  // // | cy*di ry Xy 0 | |y|
1952
2508
  // // | cz*di rz Xz 0 | |z|
1953
2509
  // // | tx ty tz 1 | |1|
1954
-
1955
2510
  // // const [
1956
2511
  // // 0, 0 , 0 , 0,
1957
2512
  // // 0, 0 , 0 , 0,
1958
2513
  // // 0, 0 , 0 , 0,
1959
2514
  // // ipp[0], ipp[1] , ipp[2] , 1,
1960
2515
  // // ]
1961
-
1962
2516
  // // Each frame:
1963
-
1964
2517
  // // Find which corner the first voxel lines up with (one of 8 corners.)
1965
-
1966
2518
  // // Find how i,j,k orient with respect to source volume.
1967
2519
  // // Go through each frame, find location in source to start, and whether to increment +/ix,+/-y,+/-z
1968
2520
  // // through each voxel.
1969
-
1970
2521
  // // [1,0,0,0,1,0]
1971
-
1972
2522
  // // const [
1973
-
1974
2523
  // // ]
1975
-
1976
2524
  // // Invert transformation matrix to get worldToIndex
1977
-
1978
2525
  // // Apply world to index on each point to fill up the matrix.
1979
-
1980
2526
  // // const sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence
1981
2527
  // // ? SharedFunctionalGroupsSequence.PlaneOrientationSequence
1982
2528
  // // .ImageOrientationPatient
1983
2529
  // // : undefined;
1984
2530
  // // const sliceLength = Columns * Rows;
1985
2531
  // }
1986
-
1987
2532
  // function getCorners(imagePlaneModule) {
1988
2533
  // // console.log(imagePlaneModule);
1989
-
1990
2534
  // const {
1991
2535
  // rows,
1992
2536
  // columns,
@@ -1996,22 +2540,18 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
1996
2540
  // rowPixelSpacing,
1997
2541
  // columnPixelSpacing
1998
2542
  // } = imagePlaneModule;
1999
-
2000
2543
  // const rowLength = columns * columnPixelSpacing;
2001
2544
  // const columnLength = rows * rowPixelSpacing;
2002
-
2003
2545
  // const entireRowVector = [
2004
2546
  // rowLength * columnCosines[0],
2005
2547
  // rowLength * columnCosines[1],
2006
2548
  // rowLength * columnCosines[2]
2007
2549
  // ];
2008
-
2009
2550
  // const entireColumnVector = [
2010
2551
  // columnLength * rowCosines[0],
2011
2552
  // columnLength * rowCosines[1],
2012
2553
  // columnLength * rowCosines[2]
2013
2554
  // ];
2014
-
2015
2555
  // const topLeft = [ipp[0], ipp[1], ipp[2]];
2016
2556
  // const topRight = [
2017
2557
  // topLeft[0] + entireRowVector[0],
@@ -2023,29 +2563,160 @@ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
2023
2563
  // topLeft[1] + entireColumnVector[1],
2024
2564
  // topLeft[2] + entireColumnVector[2]
2025
2565
  // ];
2026
-
2027
2566
  // const bottomRight = [
2028
2567
  // bottomLeft[0] + entireRowVector[0],
2029
2568
  // bottomLeft[1] + entireRowVector[1],
2030
2569
  // bottomLeft[2] + entireRowVector[2]
2031
2570
  // ];
2032
-
2033
2571
  // return [topLeft, topRight, bottomLeft, bottomRight];
2034
2572
  // }
2035
-
2036
2573
  /**
2037
2574
  * Find the reference frame of the segmentation frame in the source data.
2038
2575
  *
2039
2576
  * @param {Object} multiframe dicom metadata
2040
2577
  * @param {Int} frameSegment frame dicom index
2041
2578
  * @param {String[]} imageIds A list of imageIds.
2042
- * @param {Object} metadataProvider A Cornerstone metadataProvider to query
2043
- * metadata from imageIds.
2579
+ * @param {Object} sopUIDImageIdIndexMap A map of SOPInstanceUID to imageId
2044
2580
  * @param {Float} tolerance The tolerance parameter
2045
2581
  *
2046
2582
  * @returns {String} Returns the imageId
2047
2583
  */
2048
- function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadataProvider, tolerance) {
2584
+ function _generateToolState() {
2585
+ _generateToolState = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(imageIds, arrayBuffer, metadataProvider, options) {
2586
+ var _options$skipOverlapp, skipOverlapping, _options$tolerance, tolerance, _options$TypedArrayCo, TypedArrayConstructor, _options$maxBytesPerC, maxBytesPerChunk, eventTarget, triggerEvent, dicomData, dataset, multiframe, imagePlaneModule, generalSeriesModule, SeriesInstanceUID, ImageOrientationPatient, validOrientations, sliceLength, segMetadata, TransferSyntaxUID, pixelData, pixelDataChunks, rleEncodedFrames, orientation, sopUIDImageIdIndexMap, overlapping, insertFunction, segmentsOnFrameArray, segmentsOnFrame, arrayBufferLength, labelmapBufferArray, imageIdMaps, segmentsPixelIndices, centroidXYZ;
2587
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
2588
+ while (1) switch (_context.prev = _context.next) {
2589
+ case 0:
2590
+ _options$skipOverlapp = options.skipOverlapping, skipOverlapping = _options$skipOverlapp === void 0 ? false : _options$skipOverlapp, _options$tolerance = options.tolerance, tolerance = _options$tolerance === void 0 ? 1e-3 : _options$tolerance, _options$TypedArrayCo = options.TypedArrayConstructor, TypedArrayConstructor = _options$TypedArrayCo === void 0 ? Uint8Array : _options$TypedArrayCo, _options$maxBytesPerC = options.maxBytesPerChunk, maxBytesPerChunk = _options$maxBytesPerC === void 0 ? 199000000 : _options$maxBytesPerC, eventTarget = options.eventTarget, triggerEvent = options.triggerEvent;
2591
+ dicomData = DicomMessage.readFile(arrayBuffer);
2592
+ dataset = DicomMetaDictionary$1.naturalizeDataset(dicomData.dict);
2593
+ dataset._meta = DicomMetaDictionary$1.namifyDataset(dicomData.meta);
2594
+ multiframe = Normalizer$2.normalizeToDataset([dataset]);
2595
+ imagePlaneModule = metadataProvider.get("imagePlaneModule", imageIds[0]);
2596
+ generalSeriesModule = metadataProvider.get("generalSeriesModule", imageIds[0]);
2597
+ SeriesInstanceUID = generalSeriesModule.seriesInstanceUID;
2598
+ if (!imagePlaneModule) {
2599
+ console.warn("Insufficient metadata, imagePlaneModule missing.");
2600
+ }
2601
+ 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]; // Get IOP from ref series, compute supported orientations:
2602
+ validOrientations = getValidOrientations(ImageOrientationPatient);
2603
+ sliceLength = multiframe.Columns * multiframe.Rows;
2604
+ segMetadata = getSegmentMetadata(multiframe, SeriesInstanceUID);
2605
+ TransferSyntaxUID = multiframe._meta.TransferSyntaxUID.Value[0];
2606
+ if (!(TransferSyntaxUID === "1.2.840.10008.1.2.5")) {
2607
+ _context.next = 23;
2608
+ break;
2609
+ }
2610
+ rleEncodedFrames = Array.isArray(multiframe.PixelData) ? multiframe.PixelData : [multiframe.PixelData];
2611
+ pixelData = decode(rleEncodedFrames, multiframe.Rows, multiframe.Columns);
2612
+ if (!(multiframe.BitsStored === 1)) {
2613
+ _context.next = 20;
2614
+ break;
2615
+ }
2616
+ console.warn("No implementation for rle + bitbacking.");
2617
+ return _context.abrupt("return");
2618
+ case 20:
2619
+ // Todo: need to test this with rle data
2620
+ pixelDataChunks = [pixelData];
2621
+ _context.next = 26;
2622
+ break;
2623
+ case 23:
2624
+ pixelDataChunks = unpackPixelData(multiframe, {
2625
+ maxBytesPerChunk: maxBytesPerChunk
2626
+ });
2627
+ if (pixelDataChunks) {
2628
+ _context.next = 26;
2629
+ break;
2630
+ }
2631
+ throw new Error("Fractional segmentations are not yet supported");
2632
+ case 26:
2633
+ orientation = checkOrientation(multiframe, validOrientations, [imagePlaneModule.rows, imagePlaneModule.columns, imageIds.length], tolerance); // Pre-compute the sop UID to imageId index map so that in the for loop
2634
+ // we don't have to call metadataProvider.get() for each imageId over
2635
+ // and over again.
2636
+ sopUIDImageIdIndexMap = imageIds.reduce(function (acc, imageId) {
2637
+ var _metadataProvider$get = metadataProvider.get("generalImageModule", imageId),
2638
+ sopInstanceUid = _metadataProvider$get.sopInstanceUid;
2639
+ acc[sopInstanceUid] = imageId;
2640
+ return acc;
2641
+ }, {});
2642
+ overlapping = false;
2643
+ if (!skipOverlapping) {
2644
+ overlapping = checkSEGsOverlapping(pixelDataChunks, multiframe, imageIds, validOrientations, metadataProvider, tolerance, TypedArrayConstructor, sopUIDImageIdIndexMap);
2645
+ }
2646
+ _context.t0 = orientation;
2647
+ _context.next = _context.t0 === "Planar" ? 33 : _context.t0 === "Perpendicular" ? 35 : _context.t0 === "Oblique" ? 36 : 37;
2648
+ break;
2649
+ case 33:
2650
+ if (overlapping) {
2651
+ insertFunction = insertOverlappingPixelDataPlanar;
2652
+ } else {
2653
+ insertFunction = insertPixelDataPlanar;
2654
+ }
2655
+ return _context.abrupt("break", 37);
2656
+ case 35:
2657
+ throw new Error("Segmentations orthogonal to the acquisition plane of the source data are not yet supported.");
2658
+ case 36:
2659
+ throw new Error("Segmentations oblique to the acquisition plane of the source data are not yet supported.");
2660
+ case 37:
2661
+ /* if SEGs are overlapping:
2662
+ 1) the labelmapBuffer will contain M volumes which have non-overlapping segments;
2663
+ 2) segmentsOnFrame will have M * numberOfFrames values to track in which labelMap are the segments;
2664
+ 3) insertFunction will return the number of LabelMaps
2665
+ 4) generateToolState return is an array*/
2666
+ segmentsOnFrameArray = [];
2667
+ segmentsOnFrameArray[0] = [];
2668
+ segmentsOnFrame = [];
2669
+ arrayBufferLength = sliceLength * imageIds.length * TypedArrayConstructor.BYTES_PER_ELEMENT;
2670
+ labelmapBufferArray = [];
2671
+ labelmapBufferArray[0] = new ArrayBuffer(arrayBufferLength);
2672
+
2673
+ // Precompute the indices and metadata so that we don't have to call
2674
+ // a function for each imageId in the for loop.
2675
+ imageIdMaps = imageIds.reduce(function (acc, curr, index) {
2676
+ acc.indices[curr] = index;
2677
+ acc.metadata[curr] = metadataProvider.get("instance", curr);
2678
+ return acc;
2679
+ }, {
2680
+ indices: {},
2681
+ metadata: {}
2682
+ }); // This is the centroid calculation for each segment Index, the data structure
2683
+ // is a Map with key = segmentIndex and value = {imageIdIndex: centroid, ...}
2684
+ // later on we will use this data structure to calculate the centroid of the
2685
+ // segment in the labelmapBuffer
2686
+ segmentsPixelIndices = new Map();
2687
+ _context.next = 47;
2688
+ return insertFunction(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelDataChunks, multiframe, imageIds, validOrientations, metadataProvider, tolerance, TypedArrayConstructor, segmentsPixelIndices, sopUIDImageIdIndexMap, imageIdMaps, eventTarget, triggerEvent);
2689
+ case 47:
2690
+ // calculate the centroid of each segment
2691
+ centroidXYZ = new Map();
2692
+ segmentsPixelIndices.forEach(function (imageIdIndexBufferIndex, segmentIndex) {
2693
+ var _calculateCentroid = calculateCentroid(imageIdIndexBufferIndex, multiframe),
2694
+ xAcc = _calculateCentroid.xAcc,
2695
+ yAcc = _calculateCentroid.yAcc,
2696
+ zAcc = _calculateCentroid.zAcc,
2697
+ count = _calculateCentroid.count;
2698
+ centroidXYZ.set(segmentIndex, {
2699
+ x: Math.floor(xAcc / count),
2700
+ y: Math.floor(yAcc / count),
2701
+ z: Math.floor(zAcc / count)
2702
+ });
2703
+ });
2704
+ return _context.abrupt("return", {
2705
+ labelmapBufferArray: labelmapBufferArray,
2706
+ segMetadata: segMetadata,
2707
+ segmentsOnFrame: segmentsOnFrame,
2708
+ segmentsOnFrameArray: segmentsOnFrameArray,
2709
+ centroids: centroidXYZ
2710
+ });
2711
+ case 50:
2712
+ case "end":
2713
+ return _context.stop();
2714
+ }
2715
+ }, _callee);
2716
+ }));
2717
+ return _generateToolState.apply(this, arguments);
2718
+ }
2719
+ function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadataProvider, tolerance, sopUIDImageIdIndexMap) {
2049
2720
  var imageId = undefined;
2050
2721
  if (!multiframe) {
2051
2722
  return imageId;
@@ -2085,7 +2756,7 @@ function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadata
2085
2756
  }
2086
2757
  }
2087
2758
  if (frameSourceImageSequence) {
2088
- imageId = getImageIdOfSourceImagebySourceImageSequence(frameSourceImageSequence, imageIds, metadataProvider);
2759
+ imageId = getImageIdOfSourceImageBySourceImageSequence(frameSourceImageSequence, sopUIDImageIdIndexMap);
2089
2760
  }
2090
2761
  if (imageId === undefined && ReferencedSeriesSequence) {
2091
2762
  var referencedSeriesSequence = Array.isArray(ReferencedSeriesSequence) ? ReferencedSeriesSequence[0] : ReferencedSeriesSequence;
@@ -2100,7 +2771,7 @@ function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadata
2100
2771
  * @returns {boolean} Returns a flag if segmentations overlapping
2101
2772
  */
2102
2773
 
2103
- function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance) {
2774
+ function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance, TypedArrayConstructor, sopUIDImageIdIndexMap) {
2104
2775
  var SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
2105
2776
  PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
2106
2777
  SegmentSequence = multiframe.SegmentSequence,
@@ -2127,7 +2798,7 @@ function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations
2127
2798
  console.warn("Could not retrieve the segment index for frame segment " + frameSegment + ", skipping this frame.");
2128
2799
  return "continue";
2129
2800
  }
2130
- var imageId = findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadataProvider, tolerance);
2801
+ var imageId = findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadataProvider, tolerance, sopUIDImageIdIndexMap);
2131
2802
  if (!imageId) {
2132
2803
  console.warn("Image not present in stack, can't import frame : " + frameSegment + ".");
2133
2804
  return "continue";
@@ -2155,12 +2826,13 @@ function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations
2155
2826
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
2156
2827
  var _step$value = _slicedToArray(_step.value, 2),
2157
2828
  role = _step$value[1];
2158
- var temp2DArray = new Uint16Array(sliceLength).fill(0);
2829
+ var temp2DArray = new TypedArrayConstructor(sliceLength).fill(0);
2159
2830
  for (var i = 0; i < role.length; ++i) {
2160
2831
  var _frameSegment = role[i];
2161
2832
  var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[_frameSegment];
2162
2833
  var ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
2163
- var pixelDataI2D = ndarray(new Uint8Array(pixelData.buffer, _frameSegment * sliceLength, sliceLength), [Rows, Columns]);
2834
+ var view = readFromUnpackedChunks(pixelData, _frameSegment * sliceLength, sliceLength);
2835
+ var pixelDataI2D = ndarray(view, [Rows, Columns]);
2164
2836
  var alignedPixelDataI = alignPixelDataWithSourceData(pixelDataI2D, ImageOrientationPatientI, validOrientations, tolerance);
2165
2837
  if (!alignedPixelDataI) {
2166
2838
  console.warn("Individual SEG frames are out of plane with respect to the first SEG frame, this is not yet supported, skipping this frame.");
@@ -2184,15 +2856,14 @@ function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations
2184
2856
  }
2185
2857
  return false;
2186
2858
  }
2187
- function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance) {
2859
+ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance, TypedArrayConstructor, segmentsPixelIndices, sopUIDImageIdIndexMap) {
2188
2860
  var SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
2189
2861
  PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
2190
2862
  Rows = multiframe.Rows,
2191
2863
  Columns = multiframe.Columns;
2192
2864
  var sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
2193
2865
  var sliceLength = Columns * Rows;
2194
- var arrayBufferLength = sliceLength * imageIds.length * 2; // 2 bytes per label voxel in cst4.
2195
-
2866
+ var arrayBufferLength = sliceLength * imageIds.length * TypedArrayConstructor.BYTES_PER_ELEMENT;
2196
2867
  // indicate the number of labelMaps
2197
2868
  var M = 1;
2198
2869
 
@@ -2225,12 +2896,17 @@ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray,
2225
2896
  return "continue";
2226
2897
  }
2227
2898
  var ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
2228
- var pixelDataI2D = ndarray(new Uint8Array(pixelData.buffer, _i2 * sliceLength, sliceLength), [Rows, Columns]);
2899
+
2900
+ // Since we moved to the chunks approach, we need to read the data
2901
+ // and handle scenarios where the portion of data is in one chunk
2902
+ // and the other portion is in another chunk
2903
+ var view = readFromUnpackedChunks(pixelData, _i2 * sliceLength, sliceLength);
2904
+ var pixelDataI2D = ndarray(view, [Rows, Columns]);
2229
2905
  var alignedPixelDataI = alignPixelDataWithSourceData(pixelDataI2D, ImageOrientationPatientI, validOrientations, tolerance);
2230
2906
  if (!alignedPixelDataI) {
2231
2907
  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.");
2232
2908
  }
2233
- var imageId = findReferenceSourceImageId(multiframe, _i2, imageIds, metadataProvider, tolerance);
2909
+ var imageId = findReferenceSourceImageId(multiframe, _i2, imageIds, metadataProvider, tolerance, sopUIDImageIdIndexMap);
2234
2910
  if (!imageId) {
2235
2911
  console.warn("Image not present in stack, can't import frame : " + _i2 + ".");
2236
2912
  i = _i2;
@@ -2243,9 +2919,8 @@ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray,
2243
2919
  var imageIdIndex = imageIds.findIndex(function (element) {
2244
2920
  return element === imageId;
2245
2921
  });
2246
- var byteOffset = sliceLength * 2 * imageIdIndex; // 2 bytes/pixel
2247
-
2248
- var labelmap2DView = new Uint16Array(tempBuffer, byteOffset, sliceLength);
2922
+ var byteOffset = sliceLength * imageIdIndex * TypedArrayConstructor.BYTES_PER_ELEMENT;
2923
+ var labelmap2DView = new TypedArrayConstructor(tempBuffer, byteOffset, sliceLength);
2249
2924
  var data = alignedPixelDataI.data;
2250
2925
  var segmentOnFrame = false;
2251
2926
  for (var j = 0, len = alignedPixelDataI.data.length; j < len; ++j) {
@@ -2298,60 +2973,93 @@ var getSegmentIndex = function getSegmentIndex(multiframe, frame) {
2298
2973
  var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[frame];
2299
2974
  return PerFrameFunctionalGroups && PerFrameFunctionalGroups.SegmentIdentificationSequence ? PerFrameFunctionalGroups.SegmentIdentificationSequence.ReferencedSegmentNumber : SharedFunctionalGroupsSequence.SegmentIdentificationSequence ? SharedFunctionalGroupsSequence.SegmentIdentificationSequence.ReferencedSegmentNumber : undefined;
2300
2975
  };
2301
- function insertPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance) {
2976
+ function insertPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance, TypedArrayConstructor, segmentsPixelIndices, sopUIDImageIdIndexMap, imageIdMaps, eventTarget, triggerEvent) {
2302
2977
  var SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
2303
2978
  PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
2304
2979
  Rows = multiframe.Rows,
2305
2980
  Columns = multiframe.Columns;
2306
2981
  var sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
2307
2982
  var sliceLength = Columns * Rows;
2308
- var _loop5 = function _loop5() {
2309
- var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[i];
2310
- var ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
2311
- var pixelDataI2D = ndarray(new Uint8Array(pixelData.buffer, i * sliceLength, sliceLength), [Rows, Columns]);
2312
- var alignedPixelDataI = alignPixelDataWithSourceData(pixelDataI2D, ImageOrientationPatientI, validOrientations, tolerance);
2313
- if (!alignedPixelDataI) {
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.");
2315
- }
2316
- var segmentIndex = getSegmentIndex(multiframe, i);
2317
- if (segmentIndex === undefined) {
2318
- throw new Error("Could not retrieve the segment index. Aborting segmentation loading.");
2319
- }
2320
- var imageId = findReferenceSourceImageId(multiframe, i, imageIds, metadataProvider, tolerance);
2321
- if (!imageId) {
2322
- console.warn("Image not present in stack, can't import frame : " + i + ".");
2323
- return "continue";
2324
- }
2325
- var sourceImageMetadata = metadataProvider.get("instance", imageId);
2326
- if (Rows !== sourceImageMetadata.Rows || Columns !== sourceImageMetadata.Columns) {
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. ");
2328
- }
2329
- var imageIdIndex = imageIds.findIndex(function (element) {
2330
- return element === imageId;
2331
- });
2332
- var byteOffset = sliceLength * 2 * imageIdIndex; // 2 bytes/pixel
2333
-
2334
- var labelmap2DView = new Uint16Array(labelmapBufferArray[0], byteOffset, sliceLength);
2335
- var data = alignedPixelDataI.data;
2336
- for (var j = 0, len = alignedPixelDataI.data.length; j < len; ++j) {
2337
- if (data[j]) {
2338
- for (var x = j; x < len; ++x) {
2339
- if (data[x]) {
2340
- labelmap2DView[x] = segmentIndex;
2341
- }
2983
+ var i = 0;
2984
+ var groupsLen = PerFrameFunctionalGroupsSequence.length;
2985
+ var chunkSize = Math.ceil(groupsLen / 10); // 10% of total length
2986
+
2987
+ var shouldTriggerEvent = triggerEvent && eventTarget;
2988
+
2989
+ // Below, we chunk the processing of the frames to avoid blocking the main thread
2990
+ // if the segmentation is large. We also use a promise to allow the caller to
2991
+ // wait for the processing to finish.
2992
+ return new Promise(function (resolve) {
2993
+ function processInChunks() {
2994
+ // process one chunk
2995
+ for (var end = Math.min(i + chunkSize, groupsLen); i < end; ++i) {
2996
+ var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[i];
2997
+ var ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
2998
+ var view = readFromUnpackedChunks(pixelData, i * sliceLength, sliceLength);
2999
+ var pixelDataI2D = ndarray(view, [Rows, Columns]);
3000
+ var alignedPixelDataI = alignPixelDataWithSourceData(pixelDataI2D, ImageOrientationPatientI, validOrientations, tolerance);
3001
+ if (!alignedPixelDataI) {
3002
+ 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.");
2342
3003
  }
2343
- if (!segmentsOnFrame[imageIdIndex]) {
2344
- segmentsOnFrame[imageIdIndex] = [];
3004
+ var segmentIndex = getSegmentIndex(multiframe, i);
3005
+ if (segmentIndex === undefined) {
3006
+ throw new Error("Could not retrieve the segment index. Aborting segmentation loading.");
2345
3007
  }
2346
- segmentsOnFrame[imageIdIndex].push(segmentIndex);
2347
- break;
3008
+ if (!segmentsPixelIndices.has(segmentIndex)) {
3009
+ segmentsPixelIndices.set(segmentIndex, {});
3010
+ }
3011
+ var imageId = findReferenceSourceImageId(multiframe, i, imageIds, metadataProvider, tolerance, sopUIDImageIdIndexMap);
3012
+ if (!imageId) {
3013
+ console.warn("Image not present in stack, can't import frame : " + i + ".");
3014
+ continue;
3015
+ }
3016
+ var sourceImageMetadata = imageIdMaps.metadata[imageId];
3017
+ if (Rows !== sourceImageMetadata.Rows || Columns !== sourceImageMetadata.Columns) {
3018
+ 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. ");
3019
+ }
3020
+ var imageIdIndex = imageIdMaps.indices[imageId];
3021
+ var byteOffset = sliceLength * imageIdIndex * TypedArrayConstructor.BYTES_PER_ELEMENT;
3022
+ var labelmap2DView = new TypedArrayConstructor(labelmapBufferArray[0], byteOffset, sliceLength);
3023
+ var data = alignedPixelDataI.data;
3024
+ var indexCache = [];
3025
+ for (var j = 0, len = alignedPixelDataI.data.length; j < len; ++j) {
3026
+ if (data[j]) {
3027
+ for (var x = j; x < len; ++x) {
3028
+ if (data[x]) {
3029
+ labelmap2DView[x] = segmentIndex;
3030
+ indexCache.push(x);
3031
+ }
3032
+ }
3033
+ if (!segmentsOnFrame[imageIdIndex]) {
3034
+ segmentsOnFrame[imageIdIndex] = [];
3035
+ }
3036
+ segmentsOnFrame[imageIdIndex].push(segmentIndex);
3037
+ break;
3038
+ }
3039
+ }
3040
+ var segmentIndexObject = segmentsPixelIndices.get(segmentIndex);
3041
+ segmentIndexObject[imageIdIndex] = indexCache;
3042
+ segmentsPixelIndices.set(segmentIndex, segmentIndexObject);
3043
+ }
3044
+
3045
+ // trigger an event after each chunk
3046
+ if (shouldTriggerEvent) {
3047
+ var percentComplete = Math.round(i / groupsLen * 100);
3048
+ triggerEvent(eventTarget, Events$1.SEGMENTATION_LOAD_PROGRESS, {
3049
+ percentComplete: percentComplete
3050
+ });
3051
+ }
3052
+
3053
+ // schedule next chunk
3054
+ if (i < groupsLen) {
3055
+ setTimeout(processInChunks, 0);
3056
+ } else {
3057
+ // resolve the Promise when all chunks have been processed
3058
+ resolve();
2348
3059
  }
2349
3060
  }
2350
- };
2351
- for (var i = 0, groupsLen = PerFrameFunctionalGroupsSequence.length; i < groupsLen; ++i) {
2352
- var _ret3 = _loop5();
2353
- if (_ret3 === "continue") continue;
2354
- }
3061
+ processInChunks();
3062
+ });
2355
3063
  }
2356
3064
  function checkOrientation(multiframe, validOrientations, sourceDataDimensions, tolerance) {
2357
3065
  var SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
@@ -2390,12 +3098,13 @@ function checkIfPerpendicular(iop1, iop2, tolerance) {
2390
3098
  }
2391
3099
 
2392
3100
  /**
2393
- * unpackPixelData - Unpacks bitpacked pixelData if the Segmentation is BINARY.
3101
+ * unpackPixelData - Unpacks bit packed pixelData if the Segmentation is BINARY.
2394
3102
  *
2395
3103
  * @param {Object} multiframe The multiframe dataset.
3104
+ * @param {Object} options Options for the unpacking.
2396
3105
  * @return {Uint8Array} The unpacked pixelData.
2397
3106
  */
2398
- function unpackPixelData(multiframe) {
3107
+ function unpackPixelData(multiframe, options) {
2399
3108
  var segType = multiframe.SegmentationType;
2400
3109
  var data;
2401
3110
  if (Array.isArray(multiframe.PixelData)) {
@@ -2407,7 +3116,10 @@ function unpackPixelData(multiframe) {
2407
3116
  log.error("This segmentation pixeldata is undefined.");
2408
3117
  }
2409
3118
  if (segType === "BINARY") {
2410
- return BitArray$1.unpack(data);
3119
+ // For extreme big data, we can't unpack the data at once and we need to
3120
+ // chunk it and unpack each chunk separately.
3121
+ // MAX 2GB is the limit right now to allocate a buffer
3122
+ return getUnpackedChunks(data, options.maxBytesPerChunk);
2411
3123
  }
2412
3124
  var pixelData = new Uint8Array(data);
2413
3125
  var max = multiframe.MaximumFractionalValue;
@@ -2421,20 +3133,35 @@ function unpackPixelData(multiframe) {
2421
3133
  log.warn("This segmentation object is actually binary... processing as such.");
2422
3134
  return pixelData;
2423
3135
  }
3136
+ function getUnpackedChunks(data, maxBytesPerChunk) {
3137
+ var bitArray = new Uint8Array(data);
3138
+ var chunks = [];
3139
+ var maxBitsPerChunk = maxBytesPerChunk * 8;
3140
+ var numberOfChunks = Math.ceil(bitArray.length * 8 / maxBitsPerChunk);
3141
+ for (var i = 0; i < numberOfChunks; i++) {
3142
+ var startBit = i * maxBitsPerChunk;
3143
+ var endBit = Math.min(startBit + maxBitsPerChunk, bitArray.length * 8);
3144
+ var startByte = Math.floor(startBit / 8);
3145
+ var endByte = Math.ceil(endBit / 8);
3146
+ var chunk = bitArray.slice(startByte, endByte);
3147
+ var unpackedChunk = BitArray$1.unpack(chunk);
3148
+ chunks.push(unpackedChunk);
3149
+ }
3150
+ return chunks;
3151
+ }
2424
3152
 
2425
3153
  /**
2426
- * getImageIdOfSourceImagebySourceImageSequence - Returns the Cornerstone imageId of the source image.
3154
+ * getImageIdOfSourceImageBySourceImageSequence - Returns the Cornerstone imageId of the source image.
2427
3155
  *
2428
3156
  * @param {Object} SourceImageSequence Sequence describing the source image.
2429
3157
  * @param {String[]} imageIds A list of imageIds.
2430
- * @param {Object} metadataProvider A Cornerstone metadataProvider to query
2431
- * metadata from imageIds.
3158
+ * @param {Object} sopUIDImageIdIndexMap A map of SOPInstanceUIDs to imageIds.
2432
3159
  * @return {String} The corresponding imageId.
2433
3160
  */
2434
- function getImageIdOfSourceImagebySourceImageSequence(SourceImageSequence, imageIds, metadataProvider) {
3161
+ function getImageIdOfSourceImageBySourceImageSequence(SourceImageSequence, sopUIDImageIdIndexMap) {
2435
3162
  var ReferencedSOPInstanceUID = SourceImageSequence.ReferencedSOPInstanceUID,
2436
3163
  ReferencedFrameNumber = SourceImageSequence.ReferencedFrameNumber;
2437
- return ReferencedFrameNumber ? getImageIdOfReferencedFrame(ReferencedSOPInstanceUID, ReferencedFrameNumber, imageIds, metadataProvider) : getImageIdOfReferencedSingleFramedSOPInstance(ReferencedSOPInstanceUID, imageIds, metadataProvider);
3164
+ return ReferencedFrameNumber ? getImageIdOfReferencedFrame(ReferencedSOPInstanceUID, ReferencedFrameNumber, sopUIDImageIdIndexMap) : sopUIDImageIdIndexMap[ReferencedSOPInstanceUID];
2438
3165
  }
2439
3166
 
2440
3167
  /**
@@ -2444,7 +3171,7 @@ function getImageIdOfSourceImagebySourceImageSequence(SourceImageSequence, image
2444
3171
  * @param {String} FrameOfReferenceUID Frame of reference.
2445
3172
  * @param {Object} PerFrameFunctionalGroup Sequence describing segmentation reference attributes per frame.
2446
3173
  * @param {String[]} imageIds A list of imageIds.
2447
- * @param {Object} metadataProvider A Cornerstone metadataProvider to query
3174
+ * @param {Object} sopUIDImageIdIndexMap A map of SOPInstanceUIDs to imageIds.
2448
3175
  * @param {Float} tolerance The tolerance parameter
2449
3176
  *
2450
3177
  * @return {String} The corresponding imageId.
@@ -2464,26 +3191,6 @@ function getImageIdOfSourceImagebyGeometry(ReferencedSeriesInstanceUID, FrameOfR
2464
3191
  }
2465
3192
  }
2466
3193
 
2467
- /**
2468
- * getImageIdOfReferencedSingleFramedSOPInstance - Returns the imageId
2469
- * corresponding to the specified sopInstanceUid for single-frame images.
2470
- *
2471
- * @param {String} sopInstanceUid The sopInstanceUid of the desired image.
2472
- * @param {String[]} imageIds The list of imageIds.
2473
- * @param {Object} metadataProvider The metadataProvider to obtain sopInstanceUids
2474
- * from the cornerstone imageIds.
2475
- * @return {String} The imageId that corresponds to the sopInstanceUid.
2476
- */
2477
- function getImageIdOfReferencedSingleFramedSOPInstance(sopInstanceUid, imageIds, metadataProvider) {
2478
- return imageIds.find(function (imageId) {
2479
- var sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
2480
- if (!sopCommonModule) {
2481
- return;
2482
- }
2483
- return sopCommonModule.sopInstanceUID === sopInstanceUid;
2484
- });
2485
- }
2486
-
2487
3194
  /**
2488
3195
  * getImageIdOfReferencedFrame - Returns the imageId corresponding to the
2489
3196
  * specified sopInstanceUid and frameNumber for multi-frame images.
@@ -2491,23 +3198,16 @@ function getImageIdOfReferencedSingleFramedSOPInstance(sopInstanceUid, imageIds,
2491
3198
  * @param {String} sopInstanceUid The sopInstanceUid of the desired image.
2492
3199
  * @param {Number} frameNumber The frame number.
2493
3200
  * @param {String} imageIds The list of imageIds.
2494
- * @param {Object} metadataProvider The metadataProvider to obtain sopInstanceUids
2495
- * from the cornerstone imageIds.
3201
+ * @param {Object} sopUIDImageIdIndexMap A map of SOPInstanceUIDs to imageIds.
2496
3202
  * @return {String} The imageId that corresponds to the sopInstanceUid.
2497
3203
  */
2498
- function getImageIdOfReferencedFrame(sopInstanceUid, frameNumber, imageIds, metadataProvider) {
2499
- var imageId = imageIds.find(function (imageId) {
2500
- var sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
2501
- if (!sopCommonModule) {
2502
- return;
2503
- }
2504
- var imageIdFrameNumber = Number(imageId.split("frame=")[1]);
2505
- return (
2506
- //frameNumber is zero indexed for cornerstoneDICOMImageLoader image Ids.
2507
- sopCommonModule.sopInstanceUID === sopInstanceUid && imageIdFrameNumber === frameNumber - 1
2508
- );
2509
- });
2510
- return imageId;
3204
+ function getImageIdOfReferencedFrame(sopInstanceUid, frameNumber, sopUIDImageIdIndexMap) {
3205
+ var imageId = sopUIDImageIdIndexMap[sopInstanceUid];
3206
+ if (!imageId) {
3207
+ return;
3208
+ }
3209
+ var imageIdFrameNumber = Number(imageId.split("frame=")[1]);
3210
+ return imageIdFrameNumber === frameNumber - 1 ? imageId : undefined;
2511
3211
  }
2512
3212
 
2513
3213
  /**
@@ -2587,387 +3287,216 @@ function alignPixelDataWithSourceData(pixelData2D, iop, orientations, tolerance)
2587
3287
  /**
2588
3288
  * compareArrays - Returns true if array1 and array2 are equal
2589
3289
  * within a tolerance.
2590
- *
2591
- * @param {Number[]} array1 - An array.
2592
- * @param {Number[]} array2 - An array.
2593
- * @param {Number} tolerance.
2594
- * @return {Boolean} True if array1 and array2 are equal.
2595
- */
2596
- function compareArrays(array1, array2, tolerance) {
2597
- if (array1.length != array2.length) {
2598
- return false;
2599
- }
2600
- for (var i = 0; i < array1.length; ++i) {
2601
- if (!nearlyEqual(array1[i], array2[i], tolerance)) {
2602
- return false;
2603
- }
2604
- }
2605
- return true;
2606
- }
2607
- function getSegmentMetadata(multiframe, seriesInstanceUid) {
2608
- var segmentSequence = multiframe.SegmentSequence;
2609
- var data = [];
2610
- if (Array.isArray(segmentSequence)) {
2611
- data = [undefined].concat(_toConsumableArray(segmentSequence));
2612
- } else {
2613
- // Only one segment, will be stored as an object.
2614
- data = [undefined, segmentSequence];
2615
- }
2616
- return {
2617
- seriesInstanceUid: seriesInstanceUid,
2618
- data: data
2619
- };
2620
- }
2621
-
2622
- var Segmentation$1 = {
2623
- generateSegmentation: generateSegmentation,
2624
- generateToolState: generateToolState,
2625
- fillSegmentation: fillSegmentation
2626
- };
2627
-
2628
- /**
2629
- * generateSegmentation - Generates a DICOM Segmentation object given cornerstoneTools data.
2630
- *
2631
- * @param {object[]} images An array of the cornerstone image objects.
2632
- * @param {Object|Object[]} labelmaps3DorBrushData For 4.X: The cornerstone `Labelmap3D` object, or an array of objects.
2633
- * For 3.X: the BrushData.
2634
- * @param {number} cornerstoneToolsVersion The cornerstoneTools major version to map against.
2635
- * @returns {Object}
2636
- */
2637
- function generateSegmentation(images, labelmaps3DorBrushData) {
2638
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
2639
- includeSliceSpacing: true
2640
- };
2641
- var cornerstoneToolsVersion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 4;
2642
- if (cornerstoneToolsVersion === 4) {
2643
- return Segmentation$2.generateSegmentation(images, labelmaps3DorBrushData, options);
2644
- }
2645
- if (cornerstoneToolsVersion === 3) {
2646
- return Segmentation$3.generateSegmentation(images, labelmaps3DorBrushData, options);
2647
- }
2648
- console.warn("No generateSegmentation adapater for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
2649
- }
2650
-
2651
- /**
2652
- * generateToolState - Given a set of cornrstoneTools imageIds and a Segmentation buffer,
2653
- * derive cornerstoneTools toolState and brush metadata.
2654
- *
2655
- * @param {string[]} imageIds An array of the imageIds.
2656
- * @param {ArrayBuffer} arrayBuffer The SEG arrayBuffer.
2657
- * @param {*} metadataProvider
2658
- * @param {bool} skipOverlapping - skip checks for overlapping segs, default value false.
2659
- * @param {number} tolerance - default value 1.e-3.
2660
- * @param {number} cornerstoneToolsVersion - default value 4.
2661
- *
2662
- * @returns {Object} The toolState and an object from which the
2663
- * segment metadata can be derived.
2664
- */
2665
- function generateToolState(imageIds, arrayBuffer, metadataProvider) {
2666
- var skipOverlapping = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
2667
- var tolerance = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1e-3;
2668
- var cornerstoneToolsVersion = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 4;
2669
- if (cornerstoneToolsVersion === 4) {
2670
- return Segmentation$2.generateToolState(imageIds, arrayBuffer, metadataProvider, skipOverlapping, tolerance);
2671
- }
2672
- if (cornerstoneToolsVersion === 3) {
2673
- return Segmentation$3.generateToolState(imageIds, arrayBuffer, metadataProvider);
2674
- }
2675
- console.warn("No generateToolState adapater for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
2676
- }
2677
-
2678
- /**
2679
- * fillSegmentation - Fills a derived segmentation dataset with cornerstoneTools `LabelMap3D` data.
2680
- *
2681
- * @param {object[]} segmentation An empty segmentation derived dataset.
2682
- * @param {Object|Object[]} inputLabelmaps3D The cornerstone `Labelmap3D` object, or an array of objects.
2683
- * @param {Object} userOptions Options object to override default options.
2684
- * @returns {Blob} description
2685
- */
2686
- function fillSegmentation(segmentation, inputLabelmaps3D) {
2687
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
2688
- includeSliceSpacing: true
2689
- };
2690
- var cornerstoneToolsVersion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 4;
2691
- if (cornerstoneToolsVersion === 4) {
2692
- return Segmentation$2.fillSegmentation(segmentation, inputLabelmaps3D, options);
2693
- }
2694
- console.warn("No generateSegmentation adapater for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
2695
- }
2696
-
2697
- var TID300CobbAngle$2 = utilities.TID300.CobbAngle;
2698
- var COBB_ANGLE = "CobbAngle";
2699
- var CobbAngle$1 = /*#__PURE__*/function () {
2700
- function CobbAngle() {
2701
- _classCallCheck(this, CobbAngle);
2702
- }
2703
- _createClass(CobbAngle, null, [{
2704
- key: "getMeasurementData",
2705
- value:
2706
- // TODO: this function is required for all Cornerstone Tool Adapters, since it is called by MeasurementReport.
2707
- function getMeasurementData(MeasurementGroup) {
2708
- var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
2709
- defaultState = _MeasurementReport$ge.defaultState,
2710
- NUMGroup = _MeasurementReport$ge.NUMGroup,
2711
- SCOORDGroup = _MeasurementReport$ge.SCOORDGroup;
2712
- var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
2713
- rAngle: NUMGroup.MeasuredValueSequence.NumericValue,
2714
- toolType: CobbAngle.toolType,
2715
- handles: {
2716
- start: {},
2717
- end: {},
2718
- start2: {
2719
- highlight: true,
2720
- drawnIndependently: true
2721
- },
2722
- end2: {
2723
- highlight: true,
2724
- drawnIndependently: true
2725
- },
2726
- textBox: {
2727
- hasMoved: false,
2728
- movesIndependently: false,
2729
- drawnIndependently: true,
2730
- allowedOutsideImage: true,
2731
- hasBoundingBox: true
2732
- }
2733
- }
2734
- });
2735
- var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 8);
2736
- state.handles.start.x = _SCOORDGroup$GraphicD[0];
2737
- state.handles.start.y = _SCOORDGroup$GraphicD[1];
2738
- state.handles.end.x = _SCOORDGroup$GraphicD[2];
2739
- state.handles.end.y = _SCOORDGroup$GraphicD[3];
2740
- state.handles.start2.x = _SCOORDGroup$GraphicD[4];
2741
- state.handles.start2.y = _SCOORDGroup$GraphicD[5];
2742
- state.handles.end2.x = _SCOORDGroup$GraphicD[6];
2743
- state.handles.end2.y = _SCOORDGroup$GraphicD[7];
2744
- return state;
2745
- }
2746
- }, {
2747
- key: "getTID300RepresentationArguments",
2748
- value: function getTID300RepresentationArguments(tool) {
2749
- var handles = tool.handles,
2750
- finding = tool.finding,
2751
- findingSites = tool.findingSites;
2752
- var point1 = handles.start;
2753
- var point2 = handles.end;
2754
- var point3 = handles.start2;
2755
- var point4 = handles.end2;
2756
- var rAngle = tool.rAngle;
2757
- var trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:CobbAngle";
2758
- return {
2759
- point1: point1,
2760
- point2: point2,
2761
- point3: point3,
2762
- point4: point4,
2763
- rAngle: rAngle,
2764
- trackingIdentifierTextValue: trackingIdentifierTextValue,
2765
- finding: finding,
2766
- findingSites: findingSites || []
2767
- };
2768
- }
2769
- }]);
2770
- return CobbAngle;
2771
- }();
2772
- CobbAngle$1.toolType = COBB_ANGLE;
2773
- CobbAngle$1.utilityToolType = COBB_ANGLE;
2774
- CobbAngle$1.TID300Representation = TID300CobbAngle$2;
2775
- CobbAngle$1.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
2776
- if (!TrackingIdentifier.includes(":")) {
2777
- return false;
2778
- }
2779
- var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
2780
- _TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
2781
- cornerstone4Tag = _TrackingIdentifier$s2[0],
2782
- toolType = _TrackingIdentifier$s2[1];
2783
- if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
2784
- return false;
2785
- }
2786
- return toolType === COBB_ANGLE;
2787
- };
2788
- MeasurementReport$1.registerTool(CobbAngle$1);
2789
-
2790
- var TID300Angle = utilities.TID300.Angle;
2791
- var ANGLE = "Angle";
2792
- var Angle$1 = /*#__PURE__*/function () {
2793
- function Angle() {
2794
- _classCallCheck(this, Angle);
2795
- }
2796
- _createClass(Angle, null, [{
2797
- key: "getMeasurementData",
2798
- value:
2799
- /**
2800
- * Generate TID300 measurement data for a plane angle measurement - use a Angle, but label it as Angle
2801
- */
2802
- function getMeasurementData(MeasurementGroup) {
2803
- var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
2804
- defaultState = _MeasurementReport$ge.defaultState,
2805
- NUMGroup = _MeasurementReport$ge.NUMGroup,
2806
- SCOORDGroup = _MeasurementReport$ge.SCOORDGroup;
2807
- var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
2808
- rAngle: NUMGroup.MeasuredValueSequence.NumericValue,
2809
- toolType: Angle.toolType,
2810
- handles: {
2811
- start: {},
2812
- middle: {},
2813
- end: {},
2814
- textBox: {
2815
- hasMoved: false,
2816
- movesIndependently: false,
2817
- drawnIndependently: true,
2818
- allowedOutsideImage: true,
2819
- hasBoundingBox: true
2820
- }
2821
- }
2822
- });
2823
- var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 8);
2824
- state.handles.start.x = _SCOORDGroup$GraphicD[0];
2825
- state.handles.start.y = _SCOORDGroup$GraphicD[1];
2826
- state.handles.middle.x = _SCOORDGroup$GraphicD[2];
2827
- state.handles.middle.y = _SCOORDGroup$GraphicD[3];
2828
- state.handles.middle.x = _SCOORDGroup$GraphicD[4];
2829
- state.handles.middle.y = _SCOORDGroup$GraphicD[5];
2830
- state.handles.end.x = _SCOORDGroup$GraphicD[6];
2831
- state.handles.end.y = _SCOORDGroup$GraphicD[7];
2832
- return state;
2833
- }
2834
- }, {
2835
- key: "getTID300RepresentationArguments",
2836
- value: function getTID300RepresentationArguments(tool) {
2837
- var handles = tool.handles,
2838
- finding = tool.finding,
2839
- findingSites = tool.findingSites;
2840
- var point1 = handles.start;
2841
- var point2 = handles.middle;
2842
- var point3 = handles.middle;
2843
- var point4 = handles.end;
2844
- var rAngle = tool.rAngle;
2845
- var trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:Angle";
2846
- return {
2847
- point1: point1,
2848
- point2: point2,
2849
- point3: point3,
2850
- point4: point4,
2851
- rAngle: rAngle,
2852
- trackingIdentifierTextValue: trackingIdentifierTextValue,
2853
- finding: finding,
2854
- findingSites: findingSites || []
2855
- };
2856
- }
2857
- }]);
2858
- return Angle;
2859
- }();
2860
- Angle$1.toolType = ANGLE;
2861
- Angle$1.utilityToolType = ANGLE;
2862
- Angle$1.TID300Representation = TID300Angle;
2863
- Angle$1.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
2864
- if (!TrackingIdentifier.includes(":")) {
3290
+ *
3291
+ * @param {Number[]} array1 - An array.
3292
+ * @param {Number[]} array2 - An array.
3293
+ * @param {Number} tolerance.
3294
+ * @return {Boolean} True if array1 and array2 are equal.
3295
+ */
3296
+ function compareArrays(array1, array2, tolerance) {
3297
+ if (array1.length != array2.length) {
2865
3298
  return false;
2866
3299
  }
2867
- var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
2868
- _TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
2869
- cornerstone4Tag = _TrackingIdentifier$s2[0],
2870
- toolType = _TrackingIdentifier$s2[1];
2871
- if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
2872
- return false;
3300
+ for (var i = 0; i < array1.length; ++i) {
3301
+ if (!nearlyEqual(array1[i], array2[i], tolerance)) {
3302
+ return false;
3303
+ }
2873
3304
  }
2874
- return toolType === ANGLE;
2875
- };
2876
- MeasurementReport$1.registerTool(Angle$1);
3305
+ return true;
3306
+ }
3307
+ function getSegmentMetadata(multiframe, seriesInstanceUid) {
3308
+ var segmentSequence = multiframe.SegmentSequence;
3309
+ var data = [];
3310
+ if (Array.isArray(segmentSequence)) {
3311
+ data = [undefined].concat(_toConsumableArray(segmentSequence));
3312
+ } else {
3313
+ // Only one segment, will be stored as an object.
3314
+ data = [undefined, segmentSequence];
3315
+ }
3316
+ return {
3317
+ seriesInstanceUid: seriesInstanceUid,
3318
+ data: data
3319
+ };
3320
+ }
2877
3321
 
2878
- var TID300Polyline$2 = utilities.TID300.Polyline;
2879
- var RectangleRoi = /*#__PURE__*/function () {
2880
- function RectangleRoi() {
2881
- _classCallCheck(this, RectangleRoi);
3322
+ /**
3323
+ * Reads a range of bytes from an array of ArrayBuffer chunks and
3324
+ * aggregate them into a new Uint8Array.
3325
+ *
3326
+ * @param {ArrayBuffer[]} chunks - An array of ArrayBuffer chunks.
3327
+ * @param {number} offset - The offset of the first byte to read.
3328
+ * @param {number} length - The number of bytes to read.
3329
+ * @returns {Uint8Array} A new Uint8Array containing the requested bytes.
3330
+ */
3331
+ function readFromUnpackedChunks(chunks, offset, length) {
3332
+ var mapping = getUnpackedOffsetAndLength(chunks, offset, length);
3333
+
3334
+ // If all the data is in one chunk, we can just slice that chunk
3335
+ if (mapping.start.chunkIndex === mapping.end.chunkIndex) {
3336
+ return new Uint8Array(chunks[mapping.start.chunkIndex].buffer, mapping.start.offset, length);
3337
+ } else {
3338
+ // If the data spans multiple chunks, we need to create a new Uint8Array and copy the data from each chunk
3339
+ var result = new Uint8Array(length);
3340
+ var resultOffset = 0;
3341
+ for (var i = mapping.start.chunkIndex; i <= mapping.end.chunkIndex; i++) {
3342
+ var start = i === mapping.start.chunkIndex ? mapping.start.offset : 0;
3343
+ var end = i === mapping.end.chunkIndex ? mapping.end.offset : chunks[i].length;
3344
+ result.set(new Uint8Array(chunks[i].buffer, start, end - start), resultOffset);
3345
+ resultOffset += end - start;
3346
+ }
3347
+ return result;
2882
3348
  }
2883
- _createClass(RectangleRoi, null, [{
2884
- key: "getMeasurementData",
2885
- value: function getMeasurementData(MeasurementGroup) {
2886
- var _MeasurementReport$ge = MeasurementReport$1.getSetupMeasurementData(MeasurementGroup),
2887
- defaultState = _MeasurementReport$ge.defaultState,
2888
- SCOORDGroup = _MeasurementReport$ge.SCOORDGroup,
2889
- NUMGroup = _MeasurementReport$ge.NUMGroup;
2890
- var state = _objectSpread2(_objectSpread2({}, defaultState), {}, {
2891
- toolType: RectangleRoi.toolType,
2892
- handles: {
2893
- start: {},
2894
- end: {},
2895
- textBox: {
2896
- active: false,
2897
- hasMoved: false,
2898
- movesIndependently: false,
2899
- drawnIndependently: true,
2900
- allowedOutsideImage: true,
2901
- hasBoundingBox: true
2902
- },
2903
- initialRotation: 0
2904
- },
2905
- cachedStats: {
2906
- area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0
2907
- },
2908
- color: undefined,
2909
- invalidated: true
2910
- });
2911
- var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 6);
2912
- state.handles.start.x = _SCOORDGroup$GraphicD[0];
2913
- state.handles.start.y = _SCOORDGroup$GraphicD[1];
2914
- _SCOORDGroup$GraphicD[2];
2915
- _SCOORDGroup$GraphicD[3];
2916
- state.handles.end.x = _SCOORDGroup$GraphicD[4];
2917
- state.handles.end.y = _SCOORDGroup$GraphicD[5];
2918
- return state;
3349
+ }
3350
+ function getUnpackedOffsetAndLength(chunks, offset, length) {
3351
+ var totalBytes = chunks.reduce(function (total, chunk) {
3352
+ return total + chunk.length;
3353
+ }, 0);
3354
+ if (offset < 0 || offset + length > totalBytes) {
3355
+ throw new Error("Offset and length out of bounds");
3356
+ }
3357
+ var startChunkIndex = 0;
3358
+ var startOffsetInChunk = offset;
3359
+ while (startOffsetInChunk >= chunks[startChunkIndex].length) {
3360
+ startOffsetInChunk -= chunks[startChunkIndex].length;
3361
+ startChunkIndex++;
3362
+ }
3363
+ var endChunkIndex = startChunkIndex;
3364
+ var endOffsetInChunk = startOffsetInChunk + length;
3365
+ while (endOffsetInChunk > chunks[endChunkIndex].length) {
3366
+ endOffsetInChunk -= chunks[endChunkIndex].length;
3367
+ endChunkIndex++;
3368
+ }
3369
+ return {
3370
+ start: {
3371
+ chunkIndex: startChunkIndex,
3372
+ offset: startOffsetInChunk
3373
+ },
3374
+ end: {
3375
+ chunkIndex: endChunkIndex,
3376
+ offset: endOffsetInChunk
2919
3377
  }
2920
- }, {
2921
- key: "getTID300RepresentationArguments",
2922
- value: function getTID300RepresentationArguments(tool) {
2923
- var finding = tool.finding,
2924
- findingSites = tool.findingSites,
2925
- _tool$cachedStats = tool.cachedStats,
2926
- cachedStats = _tool$cachedStats === void 0 ? {} : _tool$cachedStats,
2927
- handles = tool.handles;
2928
- var start = handles.start,
2929
- end = handles.end;
2930
- var points = [start, {
2931
- x: start.x,
2932
- y: end.y
2933
- }, end, {
2934
- x: end.x,
2935
- y: start.y
2936
- }];
2937
- var area = cachedStats.area,
2938
- perimeter = cachedStats.perimeter;
2939
- var trackingIdentifierTextValue = "cornerstoneTools@^4.0.0:RectangleRoi";
2940
- return {
2941
- points: points,
2942
- area: area,
2943
- perimeter: perimeter,
2944
- trackingIdentifierTextValue: trackingIdentifierTextValue,
2945
- finding: finding,
2946
- findingSites: findingSites || []
2947
- };
3378
+ };
3379
+ }
3380
+ function calculateCentroid(imageIdIndexBufferIndex, multiframe) {
3381
+ var xAcc = 0;
3382
+ var yAcc = 0;
3383
+ var zAcc = 0;
3384
+ var count = 0;
3385
+ for (var _i3 = 0, _Object$entries = Object.entries(imageIdIndexBufferIndex); _i3 < _Object$entries.length; _i3++) {
3386
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i3], 2),
3387
+ imageIdIndex = _Object$entries$_i[0],
3388
+ bufferIndices = _Object$entries$_i[1];
3389
+ var z = Number(imageIdIndex);
3390
+ if (!bufferIndices || bufferIndices.length === 0) {
3391
+ continue;
3392
+ }
3393
+ var _iterator2 = _createForOfIteratorHelper(bufferIndices),
3394
+ _step2;
3395
+ try {
3396
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
3397
+ var bufferIndex = _step2.value;
3398
+ var y = Math.floor(bufferIndex / multiframe.Rows);
3399
+ var x = bufferIndex % multiframe.Rows;
3400
+ xAcc += x;
3401
+ yAcc += y;
3402
+ zAcc += z;
3403
+ count++;
3404
+ }
3405
+ } catch (err) {
3406
+ _iterator2.e(err);
3407
+ } finally {
3408
+ _iterator2.f();
2948
3409
  }
2949
- }]);
2950
- return RectangleRoi;
2951
- }();
2952
- RectangleRoi.toolType = "RectangleRoi";
2953
- RectangleRoi.utilityToolType = "RectangleRoi";
2954
- RectangleRoi.TID300Representation = TID300Polyline$2;
2955
- RectangleRoi.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
2956
- if (!TrackingIdentifier.includes(":")) {
2957
- return false;
2958
- }
2959
- var _TrackingIdentifier$s = TrackingIdentifier.split(":"),
2960
- _TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
2961
- cornerstone4Tag = _TrackingIdentifier$s2[0],
2962
- toolType = _TrackingIdentifier$s2[1];
2963
- if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
2964
- return false;
2965
3410
  }
2966
- return toolType === RectangleRoi.toolType;
3411
+ return {
3412
+ xAcc: xAcc,
3413
+ yAcc: yAcc,
3414
+ zAcc: zAcc,
3415
+ count: count
3416
+ };
3417
+ }
3418
+ var Segmentation$4 = {
3419
+ generateSegmentation: generateSegmentation$2,
3420
+ generateToolState: generateToolState$2,
3421
+ fillSegmentation: fillSegmentation$1
2967
3422
  };
2968
- MeasurementReport$1.registerTool(RectangleRoi);
2969
3423
 
2970
- var Cornerstone = {
3424
+ var Segmentation$3 = {
3425
+ generateSegmentation: generateSegmentation$1,
3426
+ generateToolState: generateToolState$1,
3427
+ fillSegmentation: fillSegmentation
3428
+ };
3429
+
3430
+ /**
3431
+ * generateSegmentation - Generates a DICOM Segmentation object given cornerstoneTools data.
3432
+ *
3433
+ * @param {object[]} images An array of the cornerstone image objects.
3434
+ * @param {Object|Object[]} labelmaps3DorBrushData For 4.X: The cornerstone `Labelmap3D` object, or an array of objects.
3435
+ * For 3.X: the BrushData.
3436
+ * @param {number} cornerstoneToolsVersion The cornerstoneTools major version to map against.
3437
+ * @returns {Object}
3438
+ */
3439
+ function generateSegmentation$1(images, labelmaps3DorBrushData) {
3440
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
3441
+ includeSliceSpacing: true
3442
+ };
3443
+ var cornerstoneToolsVersion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 4;
3444
+ if (cornerstoneToolsVersion === 4) {
3445
+ return Segmentation$4.generateSegmentation(images, labelmaps3DorBrushData, options);
3446
+ }
3447
+ if (cornerstoneToolsVersion === 3) {
3448
+ return Segmentation$5.generateSegmentation(images, labelmaps3DorBrushData, options);
3449
+ }
3450
+ console.warn("No generateSegmentation adapater for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
3451
+ }
3452
+
3453
+ /**
3454
+ * generateToolState - Given a set of cornrstoneTools imageIds and a Segmentation buffer,
3455
+ * derive cornerstoneTools toolState and brush metadata.
3456
+ *
3457
+ * @param {string[]} imageIds An array of the imageIds.
3458
+ * @param {ArrayBuffer} arrayBuffer The SEG arrayBuffer.
3459
+ * @param {*} metadataProvider
3460
+ * @param {bool} skipOverlapping - skip checks for overlapping segs, default value false.
3461
+ * @param {number} tolerance - default value 1.e-3.
3462
+ * @param {number} cornerstoneToolsVersion - default value 4.
3463
+ *
3464
+ * @returns {Object} The toolState and an object from which the
3465
+ * segment metadata can be derived.
3466
+ */
3467
+ function generateToolState$1(imageIds, arrayBuffer, metadataProvider) {
3468
+ var skipOverlapping = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
3469
+ var tolerance = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1e-3;
3470
+ var cornerstoneToolsVersion = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 4;
3471
+ if (cornerstoneToolsVersion === 4) {
3472
+ return Segmentation$4.generateToolState(imageIds, arrayBuffer, metadataProvider, skipOverlapping, tolerance);
3473
+ }
3474
+ if (cornerstoneToolsVersion === 3) {
3475
+ return Segmentation$5.generateToolState(imageIds, arrayBuffer, metadataProvider);
3476
+ }
3477
+ console.warn("No generateToolState adapater for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
3478
+ }
3479
+
3480
+ /**
3481
+ * fillSegmentation - Fills a derived segmentation dataset with cornerstoneTools `LabelMap3D` data.
3482
+ *
3483
+ * @param {object[]} segmentation An empty segmentation derived dataset.
3484
+ * @param {Object|Object[]} inputLabelmaps3D The cornerstone `Labelmap3D` object, or an array of objects.
3485
+ * @param {Object} userOptions Options object to override default options.
3486
+ * @returns {Blob} description
3487
+ */
3488
+ function fillSegmentation(segmentation, inputLabelmaps3D) {
3489
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
3490
+ includeSliceSpacing: true
3491
+ };
3492
+ var cornerstoneToolsVersion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 4;
3493
+ if (cornerstoneToolsVersion === 4) {
3494
+ return Segmentation$4.fillSegmentation(segmentation, inputLabelmaps3D, options);
3495
+ }
3496
+ console.warn("No generateSegmentation adapater for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
3497
+ }
3498
+
3499
+ var CornerstoneSR = {
2971
3500
  Length: Length$1,
2972
3501
  FreehandRoi: FreehandRoi,
2973
3502
  Bidirectional: Bidirectional$1,
@@ -2975,11 +3504,13 @@ var Cornerstone = {
2975
3504
  CircleRoi: CircleRoi,
2976
3505
  ArrowAnnotate: ArrowAnnotate$1,
2977
3506
  MeasurementReport: MeasurementReport$1,
2978
- Segmentation: Segmentation$1,
2979
3507
  CobbAngle: CobbAngle$1,
2980
3508
  Angle: Angle$1,
2981
3509
  RectangleRoi: RectangleRoi
2982
3510
  };
3511
+ var CornerstoneSEG = {
3512
+ Segmentation: Segmentation$3
3513
+ };
2983
3514
 
2984
3515
  /******************************************************************************
2985
3516
  Copyright (c) Microsoft Corporation.
@@ -3033,7 +3564,7 @@ var CodingScheme = {
3033
3564
 
3034
3565
  var TID1500 = utilities.TID1500, addAccessors = utilities.addAccessors;
3035
3566
  var StructuredReport = derivations.StructuredReport;
3036
- var Normalizer = normalizers.Normalizer;
3567
+ var Normalizer$1 = normalizers.Normalizer;
3037
3568
  var TID1500MeasurementReport = TID1500.TID1500MeasurementReport, TID1501MeasurementGroup = TID1500.TID1501MeasurementGroup;
3038
3569
  var DicomMetaDictionary = data.DicomMetaDictionary;
3039
3570
  var FINDING = { CodingSchemeDesignator: "DCM", CodeValue: "121071" };
@@ -3202,7 +3733,7 @@ var MeasurementReport = /** @class */ (function () {
3202
3733
  if ((instance &&
3203
3734
  instance.NumberOfFrames &&
3204
3735
  instance.NumberOfFrames > 1) ||
3205
- Normalizer.isMultiframeSOPClassUID(sopClassUID)) {
3736
+ Normalizer$1.isMultiframeSOPClassUID(sopClassUID)) {
3206
3737
  ReferencedSOPSequence.ReferencedFrameNumber = frameNumber;
3207
3738
  }
3208
3739
  // Loop through each tool type for the image
@@ -4313,7 +4844,115 @@ Probe.isValidCornerstoneTrackingIdentifier = function (TrackingIdentifier) {
4313
4844
  };
4314
4845
  MeasurementReport.registerTool(Probe);
4315
4846
 
4316
- var Cornerstone3D = {
4847
+ var Normalizer = normalizers.Normalizer;
4848
+ var SegmentationDerivation = derivations.Segmentation;
4849
+ /**
4850
+ * generateSegmentation - Generates a DICOM Segmentation object given cornerstoneTools data.
4851
+ *
4852
+ * @param images - An array of the cornerstone image objects, which includes imageId and metadata
4853
+ * @param labelmaps - An array of the 3D Volumes that contain the segmentation data.
4854
+ */
4855
+ function generateSegmentation(images, labelmaps, metadata, options) {
4856
+ var segmentation = _createMultiframeSegmentationFromReferencedImages(images, metadata, options);
4857
+ return fillSegmentation$1(segmentation, labelmaps, options);
4858
+ }
4859
+ /**
4860
+ * _createMultiframeSegmentationFromReferencedImages - description
4861
+ *
4862
+ * @param images - An array of the cornerstone image objects related to the reference
4863
+ * series that the segmentation is derived from. You can use methods such as
4864
+ * volume.getCornerstoneImages() to get this array.
4865
+ *
4866
+ * @param options - the options object for the SegmentationDerivation.
4867
+ * @returns The Seg derived dataSet.
4868
+ */
4869
+ function _createMultiframeSegmentationFromReferencedImages(images, metadata, options) {
4870
+ var datasets = images.map(function (image) {
4871
+ // add the sopClassUID to the dataset
4872
+ var instance = metadata.get("instance", image.imageId);
4873
+ return __assign(__assign(__assign({}, image), instance), {
4874
+ // Todo: move to dcmjs tag style
4875
+ SOPClassUID: instance.SopClassUID, SOPInstanceUID: instance.SopInstanceUID, PixelData: image.getPixelData(), _vrMap: {
4876
+ PixelData: "OW"
4877
+ }, _meta: {} });
4878
+ });
4879
+ var multiframe = Normalizer.normalizeToDataset(datasets);
4880
+ return new SegmentationDerivation([multiframe], options);
4881
+ }
4882
+
4883
+ /**
4884
+ * Generates 2D label maps from a 3D label map.
4885
+ * @param labelmap3D - The 3D label map object to generate 2D label maps from. It is derived
4886
+ * from the volume labelmap.
4887
+ * @returns The label map object containing the 2D label maps and segments on label maps.
4888
+ */
4889
+ function generateLabelMaps2DFrom3D(labelmap3D) {
4890
+ // 1. we need to generate labelmaps2D from labelmaps3D, a labelmap2D is for each
4891
+ // slice
4892
+ var scalarData = labelmap3D.scalarData, dimensions = labelmap3D.dimensions;
4893
+ // scalarData is a flat array of all the pixels in the volume.
4894
+ var labelmaps2D = [];
4895
+ var segmentsOnLabelmap3D = new Set();
4896
+ // X-Y are the row and column dimensions, Z is the number of slices.
4897
+ for (var z = 0; z < dimensions[2]; z++) {
4898
+ var pixelData = scalarData.slice(z * dimensions[0] * dimensions[1], (z + 1) * dimensions[0] * dimensions[1]);
4899
+ var segmentsOnLabelmap = [];
4900
+ for (var i = 0; i < pixelData.length; i++) {
4901
+ var segment = pixelData[i];
4902
+ if (!segmentsOnLabelmap.includes(segment) && segment !== 0) {
4903
+ segmentsOnLabelmap.push(segment);
4904
+ }
4905
+ }
4906
+ var labelmap2D = {
4907
+ segmentsOnLabelmap: segmentsOnLabelmap,
4908
+ pixelData: pixelData,
4909
+ rows: dimensions[1],
4910
+ columns: dimensions[0]
4911
+ };
4912
+ if (segmentsOnLabelmap.length === 0) {
4913
+ continue;
4914
+ }
4915
+ segmentsOnLabelmap.forEach(function (segmentIndex) {
4916
+ segmentsOnLabelmap3D.add(segmentIndex);
4917
+ });
4918
+ labelmaps2D[dimensions[2] - 1 - z] = labelmap2D;
4919
+ }
4920
+ // remove segment 0 from segmentsOnLabelmap3D
4921
+ labelmap3D.segmentsOnLabelmap = Array.from(segmentsOnLabelmap3D);
4922
+ labelmap3D.labelmaps2D = labelmaps2D;
4923
+ return labelmap3D;
4924
+ }
4925
+
4926
+ var Segmentation$2 = CornerstoneSEG.Segmentation;
4927
+ var generateToolStateCornerstoneLegacy = Segmentation$2.generateToolState;
4928
+ /**
4929
+ * generateToolState - Given a set of cornerstoneTools imageIds and a Segmentation buffer,
4930
+ * derive cornerstoneTools toolState and brush metadata.
4931
+ *
4932
+ * @param imageIds - An array of the imageIds.
4933
+ * @param arrayBuffer - The SEG arrayBuffer.
4934
+ * @param skipOverlapping - skip checks for overlapping segs, default value false.
4935
+ * @param tolerance - default value 1.e-3.
4936
+ *
4937
+ * @returns a list of array buffer for each labelMap
4938
+ * an object from which the segment metadata can be derived
4939
+ * list containing the track of segments per frame
4940
+ * list containing the track of segments per frame for each labelMap (available only for the overlapping case).
4941
+ */
4942
+ function generateToolState(imageIds, arrayBuffer, metadataProvider, skipOverlapping, tolerance) {
4943
+ if (skipOverlapping === void 0) { skipOverlapping = false; }
4944
+ if (tolerance === void 0) { tolerance = 1e-3; }
4945
+ return generateToolStateCornerstoneLegacy(imageIds, arrayBuffer, metadataProvider, skipOverlapping, tolerance);
4946
+ }
4947
+
4948
+ var Segmentation$1 = /*#__PURE__*/Object.freeze({
4949
+ __proto__: null,
4950
+ generateLabelMaps2DFrom3D: generateLabelMaps2DFrom3D,
4951
+ generateSegmentation: generateSegmentation,
4952
+ generateToolState: generateToolState
4953
+ });
4954
+
4955
+ var Cornerstone3DSR = {
4317
4956
  Bidirectional: Bidirectional,
4318
4957
  CobbAngle: CobbAngle,
4319
4958
  Angle: Angle,
@@ -4328,6 +4967,9 @@ var Cornerstone3D = {
4328
4967
  CodeScheme: CodingScheme,
4329
4968
  CORNERSTONE_3D_TAG: CORNERSTONE_3D_TAG
4330
4969
  };
4970
+ var Cornerstone3DSEG = {
4971
+ Segmentation: Segmentation$1
4972
+ };
4331
4973
 
4332
4974
  var Colors = data.Colors,
4333
4975
  BitArray = data.BitArray;
@@ -4512,15 +5154,19 @@ var Segmentation = /*#__PURE__*/function () {
4512
5154
  return Segmentation;
4513
5155
  }();
4514
5156
 
4515
- var VTKjs = {
5157
+ var VTKjsSEG = {
4516
5158
  Segmentation: Segmentation
4517
5159
  };
4518
5160
 
4519
- var adapters = {
4520
- Cornerstone: Cornerstone,
4521
- Cornerstone3D: Cornerstone3D,
4522
- VTKjs: VTKjs
5161
+ var adaptersSR = {
5162
+ Cornerstone: CornerstoneSR,
5163
+ Cornerstone3D: Cornerstone3DSR
5164
+ };
5165
+ var adaptersSEG = {
5166
+ Cornerstone: CornerstoneSR,
5167
+ Cornerstone3D: Cornerstone3DSEG,
5168
+ VTKjs: VTKjsSEG
4523
5169
  };
4524
5170
 
4525
- export { adapters as adaptersSR, adapters as default };
5171
+ export { index as Enums, adaptersSEG, adaptersSR, index$1 as helpers };
4526
5172
  //# sourceMappingURL=adapters.es.js.map