@cornerstonejs/adapters 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/@cornerstonejs/adapters.es.js +3472 -28871
  2. package/dist/@cornerstonejs/adapters.es.js.map +1 -1
  3. package/dist/@cornerstonejs/dts/adapters/Cornerstone3D/Angle.d.ts +44 -0
  4. package/dist/@cornerstonejs/dts/adapters/Cornerstone3D/Bidirectional.d.ts +49 -0
  5. package/dist/@cornerstonejs/dts/adapters/Cornerstone3D/CobbAngle.d.ts +44 -0
  6. package/dist/@cornerstonejs/dts/adapters/Cornerstone3D/MeasurementReport.d.ts +53 -0
  7. package/dist/@cornerstonejs/dts/adapters/Cornerstone3D/PlanarFreehandROI.d.ts +30 -0
  8. package/dist/@cornerstonejs/dts/adapters/Cornerstone3D/RectangleROI.d.ts +30 -0
  9. package/dist/@cornerstonejs/dts/adapters/Cornerstone3D/index.d.ts +21 -0
  10. package/dist/@cornerstonejs/dts/index.d.ts +3 -0
  11. package/package.json +10 -35
  12. package/src/{index.js → index.ts} +0 -0
  13. package/dist/@cornerstonejs/adapters.js +0 -30195
  14. package/dist/@cornerstonejs/adapters.js.map +0 -1
  15. package/src/adapters/Cornerstone/Angle.js +0 -92
  16. package/src/adapters/Cornerstone/ArrowAnnotate.js +0 -106
  17. package/src/adapters/Cornerstone/Bidirectional.js +0 -187
  18. package/src/adapters/Cornerstone/CircleRoi.js +0 -109
  19. package/src/adapters/Cornerstone/CobbAngle.js +0 -96
  20. package/src/adapters/Cornerstone/EllipticalRoi.js +0 -149
  21. package/src/adapters/Cornerstone/FreehandRoi.js +0 -82
  22. package/src/adapters/Cornerstone/Length.js +0 -80
  23. package/src/adapters/Cornerstone/MeasurementReport.js +0 -352
  24. package/src/adapters/Cornerstone/RectangleRoi.js +0 -92
  25. package/src/adapters/Cornerstone/Segmentation.js +0 -118
  26. package/src/adapters/Cornerstone/Segmentation_3X.js +0 -632
  27. package/src/adapters/Cornerstone/Segmentation_4X.js +0 -1543
  28. package/src/adapters/Cornerstone/cornerstone4Tag.js +0 -1
  29. package/src/adapters/Cornerstone/index.js +0 -27
  30. package/src/adapters/Cornerstone3D/ArrowAnnotate.js +0 -155
  31. package/src/adapters/Cornerstone3D/Bidirectional.js +0 -196
  32. package/src/adapters/Cornerstone3D/CobbAngle.js +0 -125
  33. package/src/adapters/Cornerstone3D/CodingScheme.js +0 -16
  34. package/src/adapters/Cornerstone3D/EllipticalROI.js +0 -204
  35. package/src/adapters/Cornerstone3D/Length.js +0 -113
  36. package/src/adapters/Cornerstone3D/MeasurementReport.js +0 -445
  37. package/src/adapters/Cornerstone3D/PlanarFreehandROI.js +0 -137
  38. package/src/adapters/Cornerstone3D/Probe.js +0 -106
  39. package/src/adapters/Cornerstone3D/cornerstone3DTag.js +0 -1
  40. package/src/adapters/Cornerstone3D/index.js +0 -26
  41. package/src/adapters/VTKjs/Segmentation.js +0 -223
  42. package/src/adapters/VTKjs/index.js +0 -7
  43. package/src/adapters/helpers.js +0 -19
  44. package/src/adapters/index.js +0 -11
@@ -1,632 +0,0 @@
1
- import { log, utilities, normalizers, derivations } from "dcmjs";
2
- import ndarray from "ndarray";
3
-
4
- const {
5
- rotateDirectionCosinesInPlane,
6
- flipImageOrientationPatient: flipIOP,
7
- flipMatrix2D,
8
- rotateMatrix902D
9
- } = utilities.orientation;
10
-
11
- const { datasetToBlob, BitArray, DicomMessage, DicomMetaDictionary } =
12
- utilities;
13
-
14
- const { Normalizer } = normalizers;
15
- const { Segmentation: SegmentationDerivation } = derivations;
16
-
17
- const Segmentation = {
18
- generateSegmentation,
19
- generateToolState
20
- };
21
-
22
- export default Segmentation;
23
-
24
- /**
25
- *
26
- * @typedef {Object} BrushData
27
- * @property {Object} toolState - The cornerstoneTools global toolState.
28
- * @property {Object[]} segments - The cornerstoneTools segment metadata that corresponds to the
29
- * seriesInstanceUid.
30
- */
31
-
32
- /**
33
- * generateSegmentation - Generates cornerstoneTools brush data, given a stack of
34
- * imageIds, images and the cornerstoneTools brushData.
35
- *
36
- * @param {object[]} images An array of the cornerstone image objects.
37
- * @param {BrushData} brushData and object containing the brushData.
38
- * @returns {type} description
39
- */
40
- function generateSegmentation(
41
- images,
42
- brushData,
43
- options = { includeSliceSpacing: true }
44
- ) {
45
- const { toolState, segments } = brushData;
46
-
47
- // Calculate the dimensions of the data cube.
48
- const image0 = images[0];
49
-
50
- const dims = {
51
- x: image0.columns,
52
- y: image0.rows,
53
- z: images.length
54
- };
55
-
56
- dims.xy = dims.x * dims.y;
57
-
58
- const numSegments = _getSegCount(seg, segments);
59
-
60
- if (!numSegments) {
61
- throw new Error("No segments to export!");
62
- }
63
-
64
- const isMultiframe = image0.imageId.includes("?frame");
65
- const seg = _createSegFromImages(images, isMultiframe, options);
66
-
67
- const { referencedFramesPerSegment, segmentIndicies } =
68
- _getNumberOfFramesPerSegment(toolState, images, segments);
69
-
70
- let NumberOfFrames = 0;
71
-
72
- for (let i = 0; i < referencedFramesPerSegment.length; i++) {
73
- NumberOfFrames += referencedFramesPerSegment[i].length;
74
- }
75
-
76
- seg.setNumberOfFrames(NumberOfFrames);
77
-
78
- for (let i = 0; i < segmentIndicies.length; i++) {
79
- const segmentIndex = segmentIndicies[i];
80
- const referencedFrameIndicies = referencedFramesPerSegment[i];
81
-
82
- // Frame numbers start from 1.
83
- const referencedFrameNumbers = referencedFrameIndicies.map(element => {
84
- return element + 1;
85
- });
86
-
87
- const segment = segments[segmentIndex];
88
-
89
- seg.addSegment(
90
- segment,
91
- _extractCornerstoneToolsPixelData(
92
- segmentIndex,
93
- referencedFrameIndicies,
94
- toolState,
95
- images,
96
- dims
97
- ),
98
- referencedFrameNumbers
99
- );
100
- }
101
-
102
- seg.bitPackPixelData();
103
-
104
- const segBlob = datasetToBlob(seg.dataset);
105
-
106
- return segBlob;
107
- }
108
-
109
- function _extractCornerstoneToolsPixelData(
110
- segmentIndex,
111
- referencedFrames,
112
- toolState,
113
- images,
114
- dims
115
- ) {
116
- const pixelData = new Uint8Array(dims.xy * referencedFrames.length);
117
-
118
- let pixelDataIndex = 0;
119
-
120
- for (let i = 0; i < referencedFrames.length; i++) {
121
- const frame = referencedFrames[i];
122
-
123
- const imageId = images[frame].imageId;
124
- const imageIdSpecificToolState = toolState[imageId];
125
-
126
- const brushPixelData =
127
- imageIdSpecificToolState.brush.data[segmentIndex].pixelData;
128
-
129
- for (let p = 0; p < brushPixelData.length; p++) {
130
- pixelData[pixelDataIndex] = brushPixelData[p];
131
- pixelDataIndex++;
132
- }
133
- }
134
-
135
- return pixelData;
136
- }
137
-
138
- function _getNumberOfFramesPerSegment(toolState, images, segments) {
139
- const segmentIndicies = [];
140
- const referencedFramesPerSegment = [];
141
-
142
- for (let i = 0; i < segments.length; i++) {
143
- if (segments[i]) {
144
- segmentIndicies.push(i);
145
- referencedFramesPerSegment.push([]);
146
- }
147
- }
148
-
149
- for (let z = 0; z < images.length; z++) {
150
- const imageId = images[z].imageId;
151
- const imageIdSpecificToolState = toolState[imageId];
152
-
153
- for (let i = 0; i < segmentIndicies.length; i++) {
154
- const segIdx = segmentIndicies[i];
155
-
156
- if (
157
- imageIdSpecificToolState &&
158
- imageIdSpecificToolState.brush &&
159
- imageIdSpecificToolState.brush.data &&
160
- imageIdSpecificToolState.brush.data[segIdx] &&
161
- imageIdSpecificToolState.brush.data[segIdx].pixelData
162
- ) {
163
- referencedFramesPerSegment[i].push(z);
164
- }
165
- }
166
- }
167
-
168
- return {
169
- referencedFramesPerSegment,
170
- segmentIndicies
171
- };
172
- }
173
-
174
- function _getSegCount(seg, segments) {
175
- let numSegments = 0;
176
-
177
- for (let i = 0; i < segments.length; i++) {
178
- if (segments[i]) {
179
- numSegments++;
180
- }
181
- }
182
-
183
- return numSegments;
184
- }
185
-
186
- /**
187
- * _createSegFromImages - description
188
- *
189
- * @param {Object[]} images An array of the cornerstone image objects.
190
- * @param {Boolean} isMultiframe Whether the images are multiframe.
191
- * @returns {Object} The Seg derived dataSet.
192
- */
193
- function _createSegFromImages(images, isMultiframe, options) {
194
- const datasets = [];
195
-
196
- if (isMultiframe) {
197
- const image = images[0];
198
- const arrayBuffer = image.data.byteArray.buffer;
199
-
200
- const dicomData = DicomMessage.readFile(arrayBuffer);
201
- const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
202
-
203
- dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
204
-
205
- datasets.push(dataset);
206
- } else {
207
- for (let i = 0; i < images.length; i++) {
208
- const image = images[i];
209
- const arrayBuffer = image.data.byteArray.buffer;
210
- const dicomData = DicomMessage.readFile(arrayBuffer);
211
- const dataset = DicomMetaDictionary.naturalizeDataset(
212
- dicomData.dict
213
- );
214
-
215
- dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
216
- datasets.push(dataset);
217
- }
218
- }
219
-
220
- const multiframe = Normalizer.normalizeToDataset(datasets);
221
-
222
- return new SegmentationDerivation([multiframe], options);
223
- }
224
-
225
- /**
226
- * generateToolState - Given a set of cornrstoneTools imageIds and a Segmentation buffer,
227
- * derive cornerstoneTools toolState and brush metadata.
228
- *
229
- * @param {string[]} imageIds An array of the imageIds.
230
- * @param {ArrayBuffer} arrayBuffer The SEG arrayBuffer.
231
- * @param {*} metadataProvider
232
- * @returns {Object} The toolState and an object from which the
233
- * segment metadata can be derived.
234
- */
235
- function generateToolState(imageIds, arrayBuffer, metadataProvider) {
236
- const dicomData = DicomMessage.readFile(arrayBuffer);
237
- const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
238
- dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
239
- const multiframe = Normalizer.normalizeToDataset([dataset]);
240
-
241
- const imagePlaneModule = metadataProvider.get(
242
- "imagePlaneModule",
243
- imageIds[0]
244
- );
245
-
246
- if (!imagePlaneModule) {
247
- console.warn("Insufficient metadata, imagePlaneModule missing.");
248
- }
249
-
250
- const ImageOrientationPatient = Array.isArray(imagePlaneModule.rowCosines)
251
- ? [...imagePlaneModule.rowCosines, ...imagePlaneModule.columnCosines]
252
- : [
253
- imagePlaneModule.rowCosines.x,
254
- imagePlaneModule.rowCosines.y,
255
- imagePlaneModule.rowCosines.z,
256
- imagePlaneModule.columnCosines.x,
257
- imagePlaneModule.columnCosines.y,
258
- imagePlaneModule.columnCosines.z
259
- ];
260
-
261
- // Get IOP from ref series, compute supported orientations:
262
- const validOrientations = getValidOrientations(ImageOrientationPatient);
263
-
264
- const SharedFunctionalGroupsSequence =
265
- multiframe.SharedFunctionalGroupsSequence;
266
-
267
- const sharedImageOrientationPatient =
268
- SharedFunctionalGroupsSequence.PlaneOrientationSequence
269
- ? SharedFunctionalGroupsSequence.PlaneOrientationSequence
270
- .ImageOrientationPatient
271
- : undefined;
272
-
273
- const sliceLength = multiframe.Columns * multiframe.Rows;
274
- const segMetadata = getSegmentMetadata(multiframe);
275
- const pixelData = unpackPixelData(multiframe);
276
-
277
- const PerFrameFunctionalGroupsSequence =
278
- multiframe.PerFrameFunctionalGroupsSequence;
279
-
280
- const toolState = {};
281
-
282
- let inPlane = true;
283
-
284
- for (let i = 0; i < PerFrameFunctionalGroupsSequence.length; i++) {
285
- const PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[i];
286
-
287
- const ImageOrientationPatientI =
288
- sharedImageOrientationPatient ||
289
- PerFrameFunctionalGroups.PlaneOrientationSequence
290
- .ImageOrientationPatient;
291
-
292
- const pixelDataI2D = ndarray(
293
- new Uint8Array(pixelData.buffer, i * sliceLength, sliceLength),
294
- [multiframe.Rows, multiframe.Columns]
295
- );
296
-
297
- const alignedPixelDataI = alignPixelDataWithSourceData(
298
- pixelDataI2D,
299
- ImageOrientationPatientI,
300
- validOrientations
301
- );
302
-
303
- if (!alignedPixelDataI) {
304
- console.warn(
305
- "This segmentation object is not in-plane with the source data. Bailing out of IO. It'd be better to render this with vtkjs. "
306
- );
307
- inPlane = false;
308
- break;
309
- }
310
-
311
- const segmentIndex =
312
- PerFrameFunctionalGroups.SegmentIdentificationSequence
313
- .ReferencedSegmentNumber - 1;
314
-
315
- let SourceImageSequence;
316
- if (
317
- SharedFunctionalGroupsSequence.DerivationImageSequence &&
318
- SharedFunctionalGroupsSequence.DerivationImageSequence
319
- .SourceImageSequence
320
- ) {
321
- SourceImageSequence =
322
- SharedFunctionalGroupsSequence.DerivationImageSequence
323
- .SourceImageSequence[i];
324
- } else {
325
- SourceImageSequence =
326
- PerFrameFunctionalGroups.DerivationImageSequence
327
- .SourceImageSequence;
328
- }
329
-
330
- const imageId = getImageIdOfSourceImage(
331
- SourceImageSequence,
332
- imageIds,
333
- metadataProvider
334
- );
335
-
336
- addImageIdSpecificBrushToolState(
337
- toolState,
338
- imageId,
339
- segmentIndex,
340
- alignedPixelDataI
341
- );
342
- }
343
-
344
- if (!inPlane) {
345
- return;
346
- }
347
-
348
- return { toolState, segMetadata };
349
- }
350
-
351
- /**
352
- * unpackPixelData - Unpacks bitpacked pixelData if the Segmentation is BINARY.
353
- *
354
- * @param {Object} multiframe The multiframe dataset.
355
- * @return {Uint8Array} The unpacked pixelData.
356
- */
357
- function unpackPixelData(multiframe) {
358
- const segType = multiframe.SegmentationType;
359
-
360
- if (segType === "BINARY") {
361
- return BitArray.unpack(multiframe.PixelData);
362
- }
363
-
364
- const pixelData = new Uint8Array(multiframe.PixelData);
365
-
366
- const max = multiframe.MaximumFractionalValue;
367
- const onlyMaxAndZero =
368
- pixelData.find(element => element !== 0 && element !== max) ===
369
- undefined;
370
-
371
- if (!onlyMaxAndZero) {
372
- log.warn(
373
- "This is a fractional segmentation, which is not currently supported."
374
- );
375
- return;
376
- }
377
-
378
- log.warn(
379
- "This segmentation object is actually binary... processing as such."
380
- );
381
-
382
- return pixelData;
383
- }
384
-
385
- /**
386
- * addImageIdSpecificBrushToolState - Adds brush pixel data to cornerstoneTools
387
- * formatted toolState object.
388
- *
389
- * @param {Object} toolState The toolState object to modify
390
- * @param {String} imageId The imageId of the toolState to add the data.
391
- * @param {Number} segmentIndex The index of the segment data being added.
392
- * @param {Ndarray} pixelData2D The pixelData in Ndarry 2D format.
393
- */
394
- function addImageIdSpecificBrushToolState(
395
- toolState,
396
- imageId,
397
- segmentIndex,
398
- pixelData2D
399
- ) {
400
- if (!toolState[imageId]) {
401
- toolState[imageId] = {};
402
- toolState[imageId].brush = {};
403
- toolState[imageId].brush.data = [];
404
- } else if (!toolState[imageId].brush) {
405
- toolState[imageId].brush = {};
406
- toolState[imageId].brush.data = [];
407
- } else if (!toolState[imageId].brush.data) {
408
- toolState[imageId].brush.data = [];
409
- }
410
-
411
- toolState[imageId].brush.data[segmentIndex] = {};
412
-
413
- const brushDataI = toolState[imageId].brush.data[segmentIndex];
414
-
415
- brushDataI.pixelData = new Uint8Array(pixelData2D.data.length);
416
-
417
- const cToolsPixelData = brushDataI.pixelData;
418
-
419
- for (let p = 0; p < cToolsPixelData.length; p++) {
420
- if (pixelData2D.data[p]) {
421
- cToolsPixelData[p] = 1;
422
- } else {
423
- cToolsPixelData[p] = 0;
424
- }
425
- }
426
- }
427
-
428
- /**
429
- * getImageIdOfSourceImage - Returns the Cornerstone imageId of the source image.
430
- *
431
- * @param {Object} SourceImageSequence Sequence describing the source image.
432
- * @param {String[]} imageIds A list of imageIds.
433
- * @param {Object} metadataProvider A Cornerstone metadataProvider to query
434
- * metadata from imageIds.
435
- * @return {String} The corresponding imageId.
436
- */
437
- function getImageIdOfSourceImage(
438
- SourceImageSequence,
439
- imageIds,
440
- metadataProvider
441
- ) {
442
- const { ReferencedSOPInstanceUID, ReferencedFrameNumber } =
443
- SourceImageSequence;
444
-
445
- return ReferencedFrameNumber
446
- ? getImageIdOfReferencedFrame(
447
- ReferencedSOPInstanceUID,
448
- ReferencedFrameNumber,
449
- imageIds,
450
- metadataProvider
451
- )
452
- : getImageIdOfReferencedSingleFramedSOPInstance(
453
- ReferencedSOPInstanceUID,
454
- imageIds,
455
- metadataProvider
456
- );
457
- }
458
-
459
- /**
460
- * getImageIdOfReferencedSingleFramedSOPInstance - Returns the imageId
461
- * corresponding to the specified sopInstanceUid for single-frame images.
462
- *
463
- * @param {String} sopInstanceUid The sopInstanceUid of the desired image.
464
- * @param {String[]} imageIds The list of imageIds.
465
- * @param {Object} metadataProvider The metadataProvider to obtain sopInstanceUids
466
- * from the cornerstone imageIds.
467
- * @return {String} The imageId that corresponds to the sopInstanceUid.
468
- */
469
- function getImageIdOfReferencedSingleFramedSOPInstance(
470
- sopInstanceUid,
471
- imageIds,
472
- metadataProvider
473
- ) {
474
- return imageIds.find(imageId => {
475
- const sopCommonModule = metadataProvider.get(
476
- "sopCommonModule",
477
- imageId
478
- );
479
- if (!sopCommonModule) {
480
- return;
481
- }
482
-
483
- return sopCommonModule.sopInstanceUID === sopInstanceUid;
484
- });
485
- }
486
-
487
- /**
488
- * getImageIdOfReferencedFrame - Returns the imageId corresponding to the
489
- * specified sopInstanceUid and frameNumber for multi-frame images.
490
- *
491
- * @param {String} sopInstanceUid The sopInstanceUid of the desired image.
492
- * @param {Number} frameNumber The frame number.
493
- * @param {String} imageIds The list of imageIds.
494
- * @param {Object} metadataProvider The metadataProvider to obtain sopInstanceUids
495
- * from the cornerstone imageIds.
496
- * @return {String} The imageId that corresponds to the sopInstanceUid.
497
- */
498
- function getImageIdOfReferencedFrame(
499
- sopInstanceUid,
500
- frameNumber,
501
- imageIds,
502
- metadataProvider
503
- ) {
504
- const imageId = imageIds.find(imageId => {
505
- const sopCommonModule = metadataProvider.get(
506
- "sopCommonModule",
507
- imageId
508
- );
509
- if (!sopCommonModule) {
510
- return;
511
- }
512
-
513
- const imageIdFrameNumber = Number(imageId.split("frame=")[1]);
514
-
515
- return (
516
- //frameNumber is zero indexed for cornerstoneWADOImageLoader image Ids.
517
- sopCommonModule.sopInstanceUID === sopInstanceUid &&
518
- imageIdFrameNumber === frameNumber - 1
519
- );
520
- });
521
-
522
- return imageId;
523
- }
524
-
525
- /**
526
- * getValidOrientations - returns an array of valid orientations.
527
- *
528
- * @param iop - The row (0..2) an column (3..5) direction cosines.
529
- * @return An array of valid orientations.
530
- */
531
- function getValidOrientations(iop) {
532
- const orientations = [];
533
-
534
- // [0, 1, 2]: 0, 0hf, 0vf
535
- // [3, 4, 5]: 90, 90hf, 90vf
536
- // [6, 7]: 180, 270
537
-
538
- orientations[0] = iop;
539
- orientations[1] = flipIOP.h(iop);
540
- orientations[2] = flipIOP.v(iop);
541
-
542
- const iop90 = rotateDirectionCosinesInPlane(iop, Math.PI / 2);
543
-
544
- orientations[3] = iop90;
545
- orientations[4] = flipIOP.h(iop90);
546
- orientations[5] = flipIOP.v(iop90);
547
-
548
- orientations[6] = rotateDirectionCosinesInPlane(iop, Math.PI);
549
- orientations[7] = rotateDirectionCosinesInPlane(iop, 1.5 * Math.PI);
550
-
551
- return orientations;
552
- }
553
-
554
- /**
555
- * alignPixelDataWithSourceData -
556
- *
557
- * @param pixelData2D - The data to align.
558
- * @param iop - The orientation of the image slice.
559
- * @param orientations - An array of valid imageOrientationPatient values.
560
- * @return The aligned pixelData.
561
- */
562
- function alignPixelDataWithSourceData(pixelData2D, iop, orientations) {
563
- if (compareIOP(iop, orientations[0])) {
564
- //Same orientation.
565
- return pixelData2D;
566
- } else if (compareIOP(iop, orientations[1])) {
567
- //Flipped vertically.
568
- return flipMatrix2D.v(pixelData2D);
569
- } else if (compareIOP(iop, orientations[2])) {
570
- //Flipped horizontally.
571
- return flipMatrix2D.h(pixelData2D);
572
- } else if (compareIOP(iop, orientations[3])) {
573
- //Rotated 90 degrees.
574
- return rotateMatrix902D(pixelData2D);
575
- } else if (compareIOP(iop, orientations[4])) {
576
- //Rotated 90 degrees and fliped horizontally.
577
- return flipMatrix2D.h(rotateMatrix902D(pixelData2D));
578
- } else if (compareIOP(iop, orientations[5])) {
579
- //Rotated 90 degrees and fliped vertically.
580
- return flipMatrix2D.v(rotateMatrix902D(pixelData2D));
581
- } else if (compareIOP(iop, orientations[6])) {
582
- //Rotated 180 degrees. // TODO -> Do this more effeciently, there is a 1:1 mapping like 90 degree rotation.
583
- return rotateMatrix902D(rotateMatrix902D(pixelData2D));
584
- } else if (compareIOP(iop, orientations[7])) {
585
- //Rotated 270 degrees. // TODO -> Do this more effeciently, there is a 1:1 mapping like 90 degree rotation.
586
- return rotateMatrix902D(
587
- rotateMatrix902D(rotateMatrix902D(pixelData2D))
588
- );
589
- }
590
- }
591
-
592
- const dx = 1e-5;
593
-
594
- /**
595
- * compareIOP - Returns true if iop1 and iop2 are equal
596
- * within a tollerance, dx.
597
- *
598
- * @param iop1 - An ImageOrientationPatient array.
599
- * @param iop2 - An ImageOrientationPatient array.
600
- * @return True if iop1 and iop2 are equal.
601
- */
602
- function compareIOP(iop1, iop2) {
603
- return (
604
- Math.abs(iop1[0] - iop2[0]) < dx &&
605
- Math.abs(iop1[1] - iop2[1]) < dx &&
606
- Math.abs(iop1[2] - iop2[2]) < dx &&
607
- Math.abs(iop1[3] - iop2[3]) < dx &&
608
- Math.abs(iop1[4] - iop2[4]) < dx &&
609
- Math.abs(iop1[5] - iop2[5]) < dx
610
- );
611
- }
612
-
613
- function getSegmentMetadata(multiframe) {
614
- const data = [];
615
-
616
- const segmentSequence = multiframe.SegmentSequence;
617
-
618
- if (Array.isArray(segmentSequence)) {
619
- for (let segIdx = 0; segIdx < segmentSequence.length; segIdx++) {
620
- data.push(segmentSequence[segIdx]);
621
- }
622
- } else {
623
- // Only one segment, will be stored as an object.
624
- data.push(segmentSequence);
625
- }
626
-
627
- return {
628
- seriesInstanceUid:
629
- multiframe.ReferencedSeriesSequence.SeriesInstanceUID,
630
- data
631
- };
632
- }