@cornerstonejs/adapters 2.0.0-beta.7 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +493 -0
- package/dist/esm/adapters/Cornerstone/Angle.d.ts +42 -0
- package/dist/esm/adapters/Cornerstone/Angle.js +93 -0
- package/dist/esm/adapters/Cornerstone/ArrowAnnotate.d.ts +49 -0
- package/dist/esm/adapters/Cornerstone/ArrowAnnotate.js +97 -0
- package/dist/esm/adapters/Cornerstone/Bidirectional.d.ts +89 -0
- package/dist/esm/adapters/Cornerstone/Bidirectional.js +170 -0
- package/dist/esm/adapters/Cornerstone/CircleRoi.d.ts +58 -0
- package/dist/esm/adapters/Cornerstone/CircleRoi.js +115 -0
- package/dist/esm/adapters/Cornerstone/CobbAngle.d.ts +49 -0
- package/dist/esm/adapters/Cornerstone/CobbAngle.js +98 -0
- package/dist/esm/adapters/Cornerstone/EllipticalRoi.d.ts +57 -0
- package/dist/esm/adapters/Cornerstone/EllipticalRoi.js +178 -0
- package/dist/esm/adapters/Cornerstone/FreehandRoi.d.ts +42 -0
- package/dist/esm/adapters/Cornerstone/FreehandRoi.js +89 -0
- package/dist/esm/adapters/Cornerstone/Length.d.ts +39 -0
- package/dist/esm/adapters/Cornerstone/Length.js +82 -0
- package/dist/esm/adapters/Cornerstone/MeasurementReport.d.ts +29 -0
- package/dist/esm/adapters/Cornerstone/MeasurementReport.js +276 -0
- package/dist/esm/adapters/Cornerstone/ParametricMap.d.ts +7 -0
- package/dist/esm/adapters/Cornerstone/ParametricMap.js +210 -0
- package/dist/esm/adapters/Cornerstone/RectangleRoi.d.ts +44 -0
- package/dist/esm/adapters/Cornerstone/RectangleRoi.js +97 -0
- package/dist/esm/adapters/Cornerstone/Segmentation.d.ts +7 -0
- package/dist/esm/adapters/Cornerstone/Segmentation.js +73 -0
- package/dist/esm/adapters/Cornerstone/Segmentation_3X.d.ts +13 -0
- package/dist/esm/adapters/Cornerstone/Segmentation_3X.js +411 -0
- package/dist/esm/adapters/Cornerstone/Segmentation_4X.d.ts +13 -0
- package/dist/esm/adapters/Cornerstone/Segmentation_4X.js +1152 -0
- package/dist/esm/adapters/Cornerstone/cornerstone4Tag.d.ts +2 -0
- package/dist/esm/adapters/Cornerstone/cornerstone4Tag.js +3 -0
- package/dist/esm/adapters/Cornerstone/index.d.ts +34 -0
- package/dist/esm/adapters/Cornerstone/index.js +33 -0
- package/dist/esm/adapters/Cornerstone3D/Angle.js +109 -0
- package/dist/esm/adapters/Cornerstone3D/ArrowAnnotate.d.ts +35 -0
- package/dist/esm/adapters/Cornerstone3D/ArrowAnnotate.js +123 -0
- package/dist/esm/adapters/Cornerstone3D/Bidirectional.js +147 -0
- package/dist/{types → esm}/adapters/Cornerstone3D/CircleROI.d.ts +0 -7
- package/dist/esm/adapters/Cornerstone3D/CircleROI.js +96 -0
- package/dist/esm/adapters/Cornerstone3D/CobbAngle.js +113 -0
- package/dist/esm/adapters/Cornerstone3D/CodingScheme.d.ts +9 -0
- package/dist/esm/adapters/Cornerstone3D/CodingScheme.js +15 -0
- package/dist/esm/adapters/Cornerstone3D/EllipticalROI.js +160 -0
- package/dist/esm/adapters/Cornerstone3D/Length.d.ts +41 -0
- package/dist/esm/adapters/Cornerstone3D/Length.js +101 -0
- package/dist/{types → esm}/adapters/Cornerstone3D/MeasurementReport.d.ts +1 -8
- package/dist/esm/adapters/Cornerstone3D/MeasurementReport.js +281 -0
- package/dist/esm/adapters/Cornerstone3D/ParametricMap/generateToolState.d.ts +3 -0
- package/dist/esm/adapters/Cornerstone3D/ParametricMap/generateToolState.js +11 -0
- package/dist/esm/adapters/Cornerstone3D/ParametricMap/index.d.ts +1 -0
- package/dist/esm/adapters/Cornerstone3D/ParametricMap/index.js +1 -0
- package/dist/{types → esm}/adapters/Cornerstone3D/PlanarFreehandROI.d.ts +0 -2
- package/dist/esm/adapters/Cornerstone3D/PlanarFreehandROI.js +126 -0
- package/dist/esm/adapters/Cornerstone3D/Probe.d.ts +33 -0
- package/dist/esm/adapters/Cornerstone3D/Probe.js +87 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/RTSS.d.ts +67 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/RTSS.js +175 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/index.js +6 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getPatientModule.d.ts +13 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getPatientModule.js +22 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getRTROIObservationsSequence.d.ts +6 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getRTROIObservationsSequence.js +10 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getRTSeriesModule.d.ts +4 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getRTSeriesModule.js +9 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getReferencedFrameOfReferenceSequence.d.ts +11 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getReferencedFrameOfReferenceSequence.js +22 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getReferencedSeriesSequence.d.ts +4 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getReferencedSeriesSequence.js +27 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getStructureSetModule.d.ts +7 -0
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getStructureSetModule.js +12 -0
- package/dist/esm/adapters/Cornerstone3D/RectangleROI.js +94 -0
- package/dist/{types → esm}/adapters/Cornerstone3D/Segmentation/generateLabelMaps2DFrom3D.d.ts +0 -6
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateLabelMaps2DFrom3D.js +34 -0
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateSegmentation.d.ts +2 -0
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateSegmentation.js +29 -0
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateToolState.d.ts +2 -0
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateToolState.js +9 -0
- package/dist/esm/adapters/Cornerstone3D/Segmentation/index.js +3 -0
- package/dist/esm/adapters/Cornerstone3D/UltrasoundDirectional.js +93 -0
- package/dist/esm/adapters/Cornerstone3D/cornerstone3DTag.d.ts +2 -0
- package/dist/esm/adapters/Cornerstone3D/cornerstone3DTag.js +3 -0
- package/dist/{types → esm}/adapters/Cornerstone3D/index.d.ts +18 -6
- package/dist/esm/adapters/Cornerstone3D/index.js +45 -0
- package/dist/esm/adapters/Cornerstone3D/isValidCornerstoneTrackingIdentifier.js +18 -0
- package/dist/esm/adapters/VTKjs/Segmentation.d.ts +3 -0
- package/dist/esm/adapters/VTKjs/Segmentation.js +186 -0
- package/dist/esm/adapters/VTKjs/index.d.ts +5 -0
- package/dist/esm/adapters/VTKjs/index.js +7 -0
- package/dist/{types → esm}/adapters/enums/Events.d.ts +0 -6
- package/dist/esm/adapters/enums/Events.js +7 -0
- package/dist/esm/adapters/enums/index.js +1 -0
- package/dist/esm/adapters/helpers/checkIfPerpendicular.d.ts +1 -0
- package/dist/esm/adapters/helpers/checkIfPerpendicular.js +7 -0
- package/dist/esm/adapters/helpers/checkOrientation.d.ts +1 -0
- package/dist/esm/adapters/helpers/checkOrientation.js +22 -0
- package/dist/esm/adapters/helpers/codeMeaningEquals.d.ts +2 -0
- package/dist/esm/adapters/helpers/codeMeaningEquals.js +7 -0
- package/dist/esm/adapters/helpers/compareArrays.d.ts +1 -0
- package/dist/esm/adapters/helpers/compareArrays.js +16 -0
- package/dist/esm/adapters/helpers/downloadDICOMData.d.ts +5 -0
- package/dist/esm/adapters/helpers/downloadDICOMData.js +26 -0
- package/dist/esm/adapters/helpers/getDatasetsFromImages.d.ts +1 -0
- package/dist/esm/adapters/helpers/getDatasetsFromImages.js +33 -0
- package/dist/esm/adapters/helpers/graphicTypeEquals.d.ts +2 -0
- package/dist/esm/adapters/helpers/graphicTypeEquals.js +7 -0
- package/dist/esm/adapters/helpers/index.js +4 -0
- package/dist/esm/adapters/helpers/toArray.js +5 -0
- package/dist/esm/adapters/index.d.ts +66 -0
- package/dist/esm/adapters/index.js +24 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +5 -0
- package/dist/umd/adapters.umd.js +5769 -0
- package/dist/umd/adapters.umd.js.map +1 -0
- package/package.json +47 -11
- package/dist/adapters.es.js +0 -5623
- package/dist/adapters.es.js.map +0 -1
- package/dist/types/adapters/Cornerstone/index.d.ts +0 -16
- package/dist/types/adapters/Cornerstone3D/RTStruct/RTSS.d.ts +0 -26
- package/dist/types/adapters/Cornerstone3D/Segmentation/generateSegmentation.d.ts +0 -8
- package/dist/types/adapters/Cornerstone3D/Segmentation/generateToolState.d.ts +0 -16
- package/dist/types/adapters/VTKjs/index.d.ts +0 -4
- package/dist/types/adapters/helpers/codeMeaningEquals.d.ts +0 -9
- package/dist/types/adapters/helpers/downloadDICOMData.d.ts +0 -10
- package/dist/types/adapters/helpers/graphicTypeEquals.d.ts +0 -7
- package/dist/types/adapters/index.d.ts +0 -49
- package/dist/types/index.d.ts +0 -2
- /package/dist/{types → esm}/adapters/Cornerstone3D/Angle.d.ts +0 -0
- /package/dist/{types → esm}/adapters/Cornerstone3D/Bidirectional.d.ts +0 -0
- /package/dist/{types → esm}/adapters/Cornerstone3D/CobbAngle.d.ts +0 -0
- /package/dist/{types → esm}/adapters/Cornerstone3D/EllipticalROI.d.ts +0 -0
- /package/dist/{types → esm}/adapters/Cornerstone3D/RTStruct/index.d.ts +0 -0
- /package/dist/{types → esm}/adapters/Cornerstone3D/RectangleROI.d.ts +0 -0
- /package/dist/{types → esm}/adapters/Cornerstone3D/Segmentation/index.d.ts +0 -0
- /package/dist/{types → esm}/adapters/Cornerstone3D/UltrasoundDirectional.d.ts +0 -0
- /package/dist/{types → esm}/adapters/Cornerstone3D/isValidCornerstoneTrackingIdentifier.d.ts +0 -0
- /package/dist/{types → esm}/adapters/enums/index.d.ts +0 -0
- /package/dist/{types → esm}/adapters/helpers/index.d.ts +0 -0
- /package/dist/{types → esm}/adapters/helpers/toArray.d.ts +0 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import Segmentation$1 from './Segmentation_3X.js';
|
|
2
|
+
import Segmentation from './Segmentation_4X.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* generateSegmentation - Generates a DICOM Segmentation object given cornerstoneTools data.
|
|
6
|
+
*
|
|
7
|
+
* @param {object[]} images An array of the cornerstone image objects.
|
|
8
|
+
* @param {Object|Object[]} labelmaps3DorBrushData For 4.X: The cornerstone `Labelmap3D` object, or an array of objects.
|
|
9
|
+
* For 3.X: the BrushData.
|
|
10
|
+
* @param {number} cornerstoneToolsVersion The cornerstoneTools major version to map against.
|
|
11
|
+
* @returns {Object}
|
|
12
|
+
*/
|
|
13
|
+
function generateSegmentation(images, labelmaps3DorBrushData) {
|
|
14
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
|
|
15
|
+
includeSliceSpacing: true
|
|
16
|
+
};
|
|
17
|
+
var cornerstoneToolsVersion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 4;
|
|
18
|
+
if (cornerstoneToolsVersion === 4) {
|
|
19
|
+
return Segmentation.generateSegmentation(images, labelmaps3DorBrushData, options);
|
|
20
|
+
}
|
|
21
|
+
if (cornerstoneToolsVersion === 3) {
|
|
22
|
+
return Segmentation$1.generateSegmentation(images, labelmaps3DorBrushData, options);
|
|
23
|
+
}
|
|
24
|
+
console.warn("No generateSegmentation adapter for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* generateToolState - Given a set of cornerstoneTools imageIds and a Segmentation buffer,
|
|
29
|
+
* derive cornerstoneTools toolState and brush metadata.
|
|
30
|
+
*
|
|
31
|
+
* @param {string[]} imageIds An array of the imageIds.
|
|
32
|
+
* @param {ArrayBuffer} arrayBuffer The SEG arrayBuffer.
|
|
33
|
+
* @param {*} metadataProvider
|
|
34
|
+
* @param {boolean} skipOverlapping - skip checks for overlapping segs, default value false.
|
|
35
|
+
* @param {number} tolerance - default value 1.e-3.
|
|
36
|
+
* @param {number} cornerstoneToolsVersion - default value 4.
|
|
37
|
+
*
|
|
38
|
+
* @returns {Object} The toolState and an object from which the
|
|
39
|
+
* segment metadata can be derived.
|
|
40
|
+
*/
|
|
41
|
+
function generateToolState(imageIds, arrayBuffer, metadataProvider) {
|
|
42
|
+
var skipOverlapping = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
43
|
+
var tolerance = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1e-3;
|
|
44
|
+
var cornerstoneToolsVersion = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 4;
|
|
45
|
+
if (cornerstoneToolsVersion === 4) {
|
|
46
|
+
return Segmentation.generateToolState(imageIds, arrayBuffer, metadataProvider, skipOverlapping, tolerance);
|
|
47
|
+
}
|
|
48
|
+
if (cornerstoneToolsVersion === 3) {
|
|
49
|
+
return Segmentation$1.generateToolState(imageIds, arrayBuffer, metadataProvider);
|
|
50
|
+
}
|
|
51
|
+
console.warn("No generateToolState adapter for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* fillSegmentation - Fills a derived segmentation dataset with cornerstoneTools `LabelMap3D` data.
|
|
56
|
+
*
|
|
57
|
+
* @param {object[]} segmentation An empty segmentation derived dataset.
|
|
58
|
+
* @param {Object|Object[]} inputLabelmaps3D The cornerstone `Labelmap3D` object, or an array of objects.
|
|
59
|
+
* @param {Object} userOptions Options object to override default options.
|
|
60
|
+
* @returns {Blob} description
|
|
61
|
+
*/
|
|
62
|
+
function fillSegmentation(segmentation, inputLabelmaps3D) {
|
|
63
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
|
|
64
|
+
includeSliceSpacing: true
|
|
65
|
+
};
|
|
66
|
+
var cornerstoneToolsVersion = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 4;
|
|
67
|
+
if (cornerstoneToolsVersion === 4) {
|
|
68
|
+
return Segmentation.fillSegmentation(segmentation, inputLabelmaps3D, options);
|
|
69
|
+
}
|
|
70
|
+
console.warn("No generateSegmentation adapter for cornerstone version ".concat(cornerstoneToolsVersion, ", exiting."));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { fillSegmentation, generateSegmentation, generateToolState };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default Segmentation;
|
|
2
|
+
export type BrushData = {
|
|
3
|
+
toolState: any;
|
|
4
|
+
segments: any[];
|
|
5
|
+
};
|
|
6
|
+
declare namespace Segmentation {
|
|
7
|
+
export { generateSegmentation };
|
|
8
|
+
export { generateToolState };
|
|
9
|
+
}
|
|
10
|
+
declare function generateSegmentation(images: object[], brushData: BrushData, options?: {
|
|
11
|
+
includeSliceSpacing: boolean;
|
|
12
|
+
}): type;
|
|
13
|
+
declare function generateToolState(imageIds: string[], arrayBuffer: ArrayBuffer, metadataProvider: any): any;
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { toConsumableArray as _toConsumableArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
+
import { utilities, normalizers, derivations, log } from 'dcmjs';
|
|
3
|
+
import ndarray from 'ndarray';
|
|
4
|
+
import getDatasetsFromImages from '../helpers/getDatasetsFromImages.js';
|
|
5
|
+
|
|
6
|
+
var _utilities$orientatio = utilities.orientation,
|
|
7
|
+
rotateDirectionCosinesInPlane = _utilities$orientatio.rotateDirectionCosinesInPlane,
|
|
8
|
+
flipIOP = _utilities$orientatio.flipImageOrientationPatient,
|
|
9
|
+
flipMatrix2D = _utilities$orientatio.flipMatrix2D,
|
|
10
|
+
rotateMatrix902D = _utilities$orientatio.rotateMatrix902D;
|
|
11
|
+
var datasetToBlob = utilities.datasetToBlob,
|
|
12
|
+
BitArray = utilities.BitArray,
|
|
13
|
+
DicomMessage = utilities.DicomMessage,
|
|
14
|
+
DicomMetaDictionary = utilities.DicomMetaDictionary;
|
|
15
|
+
var Normalizer = normalizers.Normalizer;
|
|
16
|
+
var SegmentationDerivation = derivations.Segmentation;
|
|
17
|
+
var Segmentation = {
|
|
18
|
+
generateSegmentation: generateSegmentation,
|
|
19
|
+
generateToolState: generateToolState
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @typedef {Object} BrushData
|
|
25
|
+
* @property {Object} toolState - The cornerstoneTools global toolState.
|
|
26
|
+
* @property {Object[]} segments - The cornerstoneTools segment metadata that corresponds to the
|
|
27
|
+
* seriesInstanceUid.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* generateSegmentation - Generates cornerstoneTools brush data, given a stack of
|
|
32
|
+
* imageIds, images and the cornerstoneTools brushData.
|
|
33
|
+
*
|
|
34
|
+
* @param {object[]} images An array of the cornerstone image objects.
|
|
35
|
+
* @param {BrushData} brushData and object containing the brushData.
|
|
36
|
+
* @returns {type} description
|
|
37
|
+
*/
|
|
38
|
+
function generateSegmentation(images, brushData) {
|
|
39
|
+
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
|
|
40
|
+
includeSliceSpacing: true
|
|
41
|
+
};
|
|
42
|
+
var toolState = brushData.toolState,
|
|
43
|
+
segments = brushData.segments;
|
|
44
|
+
|
|
45
|
+
// Calculate the dimensions of the data cube.
|
|
46
|
+
var image0 = images[0];
|
|
47
|
+
var dims = {
|
|
48
|
+
x: image0.columns,
|
|
49
|
+
y: image0.rows,
|
|
50
|
+
z: images.length
|
|
51
|
+
};
|
|
52
|
+
dims.xy = dims.x * dims.y;
|
|
53
|
+
var numSegments = _getSegCount(seg, segments);
|
|
54
|
+
if (!numSegments) {
|
|
55
|
+
throw new Error("No segments to export!");
|
|
56
|
+
}
|
|
57
|
+
var isMultiframe = image0.imageId.includes("?frame");
|
|
58
|
+
var seg = _createSegFromImages(images, isMultiframe, options);
|
|
59
|
+
var _getNumberOfFramesPer = _getNumberOfFramesPerSegment(toolState, images, segments),
|
|
60
|
+
referencedFramesPerSegment = _getNumberOfFramesPer.referencedFramesPerSegment,
|
|
61
|
+
segmentIndicies = _getNumberOfFramesPer.segmentIndicies;
|
|
62
|
+
var NumberOfFrames = 0;
|
|
63
|
+
for (var i = 0; i < referencedFramesPerSegment.length; i++) {
|
|
64
|
+
NumberOfFrames += referencedFramesPerSegment[i].length;
|
|
65
|
+
}
|
|
66
|
+
seg.setNumberOfFrames(NumberOfFrames);
|
|
67
|
+
for (var _i = 0; _i < segmentIndicies.length; _i++) {
|
|
68
|
+
var segmentIndex = segmentIndicies[_i];
|
|
69
|
+
var referencedFrameIndicies = referencedFramesPerSegment[_i];
|
|
70
|
+
|
|
71
|
+
// Frame numbers start from 1.
|
|
72
|
+
var referencedFrameNumbers = referencedFrameIndicies.map(function (element) {
|
|
73
|
+
return element + 1;
|
|
74
|
+
});
|
|
75
|
+
var segment = segments[segmentIndex];
|
|
76
|
+
seg.addSegment(segment, _extractCornerstoneToolsPixelData(segmentIndex, referencedFrameIndicies, toolState, images, dims), referencedFrameNumbers);
|
|
77
|
+
}
|
|
78
|
+
seg.bitPackPixelData();
|
|
79
|
+
var segBlob = datasetToBlob(seg.dataset);
|
|
80
|
+
return segBlob;
|
|
81
|
+
}
|
|
82
|
+
function _extractCornerstoneToolsPixelData(segmentIndex, referencedFrames, toolState, images, dims) {
|
|
83
|
+
var pixelData = new Uint8Array(dims.xy * referencedFrames.length);
|
|
84
|
+
var pixelDataIndex = 0;
|
|
85
|
+
for (var i = 0; i < referencedFrames.length; i++) {
|
|
86
|
+
var frame = referencedFrames[i];
|
|
87
|
+
var imageId = images[frame].imageId;
|
|
88
|
+
var imageIdSpecificToolState = toolState[imageId];
|
|
89
|
+
var brushPixelData = imageIdSpecificToolState.brush.data[segmentIndex].pixelData;
|
|
90
|
+
for (var p = 0; p < brushPixelData.length; p++) {
|
|
91
|
+
pixelData[pixelDataIndex] = brushPixelData[p];
|
|
92
|
+
pixelDataIndex++;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return pixelData;
|
|
96
|
+
}
|
|
97
|
+
function _getNumberOfFramesPerSegment(toolState, images, segments) {
|
|
98
|
+
var segmentIndicies = [];
|
|
99
|
+
var referencedFramesPerSegment = [];
|
|
100
|
+
for (var i = 0; i < segments.length; i++) {
|
|
101
|
+
if (segments[i]) {
|
|
102
|
+
segmentIndicies.push(i);
|
|
103
|
+
referencedFramesPerSegment.push([]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
for (var z = 0; z < images.length; z++) {
|
|
107
|
+
var imageId = images[z].imageId;
|
|
108
|
+
var imageIdSpecificToolState = toolState[imageId];
|
|
109
|
+
for (var _i2 = 0; _i2 < segmentIndicies.length; _i2++) {
|
|
110
|
+
var segIdx = segmentIndicies[_i2];
|
|
111
|
+
if (imageIdSpecificToolState && imageIdSpecificToolState.brush && imageIdSpecificToolState.brush.data && imageIdSpecificToolState.brush.data[segIdx] && imageIdSpecificToolState.brush.data[segIdx].pixelData) {
|
|
112
|
+
referencedFramesPerSegment[_i2].push(z);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
referencedFramesPerSegment: referencedFramesPerSegment,
|
|
118
|
+
segmentIndicies: segmentIndicies
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function _getSegCount(seg, segments) {
|
|
122
|
+
var numSegments = 0;
|
|
123
|
+
for (var i = 0; i < segments.length; i++) {
|
|
124
|
+
if (segments[i]) {
|
|
125
|
+
numSegments++;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return numSegments;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* _createSegFromImages - description
|
|
133
|
+
*
|
|
134
|
+
* @param {Object[]} images An array of the cornerstone image objects.
|
|
135
|
+
* @param {Boolean} isMultiframe Whether the images are multiframe.
|
|
136
|
+
* @returns {Object} The Seg derived dataSet.
|
|
137
|
+
*/
|
|
138
|
+
function _createSegFromImages(images, isMultiframe, options) {
|
|
139
|
+
var multiframe = getDatasetsFromImages(images, isMultiframe);
|
|
140
|
+
return new SegmentationDerivation([multiframe], options);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* generateToolState - Given a set of cornrstoneTools imageIds and a Segmentation buffer,
|
|
145
|
+
* derive cornerstoneTools toolState and brush metadata.
|
|
146
|
+
*
|
|
147
|
+
* @param {string[]} imageIds An array of the imageIds.
|
|
148
|
+
* @param {ArrayBuffer} arrayBuffer The SEG arrayBuffer.
|
|
149
|
+
* @param {*} metadataProvider
|
|
150
|
+
* @returns {Object} The toolState and an object from which the
|
|
151
|
+
* segment metadata can be derived.
|
|
152
|
+
*/
|
|
153
|
+
function generateToolState(imageIds, arrayBuffer, metadataProvider) {
|
|
154
|
+
var dicomData = DicomMessage.readFile(arrayBuffer);
|
|
155
|
+
var dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
|
|
156
|
+
dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
|
|
157
|
+
var multiframe = Normalizer.normalizeToDataset([dataset]);
|
|
158
|
+
var imagePlaneModule = metadataProvider.get("imagePlaneModule", imageIds[0]);
|
|
159
|
+
if (!imagePlaneModule) {
|
|
160
|
+
console.warn("Insufficient metadata, imagePlaneModule missing.");
|
|
161
|
+
}
|
|
162
|
+
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];
|
|
163
|
+
|
|
164
|
+
// Get IOP from ref series, compute supported orientations:
|
|
165
|
+
var validOrientations = getValidOrientations(ImageOrientationPatient);
|
|
166
|
+
var SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence;
|
|
167
|
+
var sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
|
|
168
|
+
var sliceLength = multiframe.Columns * multiframe.Rows;
|
|
169
|
+
var segMetadata = getSegmentMetadata(multiframe);
|
|
170
|
+
var pixelData = unpackPixelData(multiframe);
|
|
171
|
+
var PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence;
|
|
172
|
+
var toolState = {};
|
|
173
|
+
var inPlane = true;
|
|
174
|
+
for (var i = 0; i < PerFrameFunctionalGroupsSequence.length; i++) {
|
|
175
|
+
var PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[i];
|
|
176
|
+
var ImageOrientationPatientI = sharedImageOrientationPatient || PerFrameFunctionalGroups.PlaneOrientationSequence.ImageOrientationPatient;
|
|
177
|
+
var pixelDataI2D = ndarray(new Uint8Array(pixelData.buffer, i * sliceLength, sliceLength), [multiframe.Rows, multiframe.Columns]);
|
|
178
|
+
var alignedPixelDataI = alignPixelDataWithSourceData(pixelDataI2D, ImageOrientationPatientI, validOrientations);
|
|
179
|
+
if (!alignedPixelDataI) {
|
|
180
|
+
console.warn("This segmentation object is not in-plane with the source data. Bailing out of IO. It'd be better to render this with vtkjs. ");
|
|
181
|
+
inPlane = false;
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
var segmentIndex = PerFrameFunctionalGroups.SegmentIdentificationSequence.ReferencedSegmentNumber - 1;
|
|
185
|
+
var SourceImageSequence = void 0;
|
|
186
|
+
if (SharedFunctionalGroupsSequence.DerivationImageSequence && SharedFunctionalGroupsSequence.DerivationImageSequence.SourceImageSequence) {
|
|
187
|
+
SourceImageSequence = SharedFunctionalGroupsSequence.DerivationImageSequence.SourceImageSequence[i];
|
|
188
|
+
} else {
|
|
189
|
+
SourceImageSequence = PerFrameFunctionalGroups.DerivationImageSequence.SourceImageSequence;
|
|
190
|
+
}
|
|
191
|
+
var imageId = getImageIdOfSourceImage(SourceImageSequence, imageIds, metadataProvider);
|
|
192
|
+
addImageIdSpecificBrushToolState(toolState, imageId, segmentIndex, alignedPixelDataI);
|
|
193
|
+
}
|
|
194
|
+
if (!inPlane) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
toolState: toolState,
|
|
199
|
+
segMetadata: segMetadata
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* unpackPixelData - Unpacks bitpacked pixelData if the Segmentation is BINARY.
|
|
205
|
+
*
|
|
206
|
+
* @param {Object} multiframe The multiframe dataset.
|
|
207
|
+
* @return {Uint8Array} The unpacked pixelData.
|
|
208
|
+
*/
|
|
209
|
+
function unpackPixelData(multiframe) {
|
|
210
|
+
var segType = multiframe.SegmentationType;
|
|
211
|
+
if (segType === "BINARY") {
|
|
212
|
+
return BitArray.unpack(multiframe.PixelData);
|
|
213
|
+
}
|
|
214
|
+
var pixelData = new Uint8Array(multiframe.PixelData);
|
|
215
|
+
var max = multiframe.MaximumFractionalValue;
|
|
216
|
+
var onlyMaxAndZero = pixelData.find(function (element) {
|
|
217
|
+
return element !== 0 && element !== max;
|
|
218
|
+
}) === undefined;
|
|
219
|
+
if (!onlyMaxAndZero) {
|
|
220
|
+
log.warn("This is a fractional segmentation, which is not currently supported.");
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
log.warn("This segmentation object is actually binary... processing as such.");
|
|
224
|
+
return pixelData;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* addImageIdSpecificBrushToolState - Adds brush pixel data to cornerstoneTools
|
|
229
|
+
* formatted toolState object.
|
|
230
|
+
*
|
|
231
|
+
* @param {Object} toolState The toolState object to modify
|
|
232
|
+
* @param {String} imageId The imageId of the toolState to add the data.
|
|
233
|
+
* @param {Number} segmentIndex The index of the segment data being added.
|
|
234
|
+
* @param {Ndarray} pixelData2D The pixelData in Ndarry 2D format.
|
|
235
|
+
*/
|
|
236
|
+
function addImageIdSpecificBrushToolState(toolState, imageId, segmentIndex, pixelData2D) {
|
|
237
|
+
if (!toolState[imageId]) {
|
|
238
|
+
toolState[imageId] = {};
|
|
239
|
+
toolState[imageId].brush = {};
|
|
240
|
+
toolState[imageId].brush.data = [];
|
|
241
|
+
} else if (!toolState[imageId].brush) {
|
|
242
|
+
toolState[imageId].brush = {};
|
|
243
|
+
toolState[imageId].brush.data = [];
|
|
244
|
+
} else if (!toolState[imageId].brush.data) {
|
|
245
|
+
toolState[imageId].brush.data = [];
|
|
246
|
+
}
|
|
247
|
+
toolState[imageId].brush.data[segmentIndex] = {};
|
|
248
|
+
var brushDataI = toolState[imageId].brush.data[segmentIndex];
|
|
249
|
+
brushDataI.pixelData = new Uint8Array(pixelData2D.data.length);
|
|
250
|
+
var cToolsPixelData = brushDataI.pixelData;
|
|
251
|
+
for (var p = 0; p < cToolsPixelData.length; p++) {
|
|
252
|
+
if (pixelData2D.data[p]) {
|
|
253
|
+
cToolsPixelData[p] = 1;
|
|
254
|
+
} else {
|
|
255
|
+
cToolsPixelData[p] = 0;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* getImageIdOfSourceImage - Returns the Cornerstone imageId of the source image.
|
|
262
|
+
*
|
|
263
|
+
* @param {Object} SourceImageSequence Sequence describing the source image.
|
|
264
|
+
* @param {String[]} imageIds A list of imageIds.
|
|
265
|
+
* @param {Object} metadataProvider A Cornerstone metadataProvider to query
|
|
266
|
+
* metadata from imageIds.
|
|
267
|
+
* @return {String} The corresponding imageId.
|
|
268
|
+
*/
|
|
269
|
+
function getImageIdOfSourceImage(SourceImageSequence, imageIds, metadataProvider) {
|
|
270
|
+
var ReferencedSOPInstanceUID = SourceImageSequence.ReferencedSOPInstanceUID,
|
|
271
|
+
ReferencedFrameNumber = SourceImageSequence.ReferencedFrameNumber;
|
|
272
|
+
return ReferencedFrameNumber ? getImageIdOfReferencedFrame(ReferencedSOPInstanceUID, ReferencedFrameNumber, imageIds, metadataProvider) : getImageIdOfReferencedSingleFramedSOPInstance(ReferencedSOPInstanceUID, imageIds, metadataProvider);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* getImageIdOfReferencedSingleFramedSOPInstance - Returns the imageId
|
|
277
|
+
* corresponding to the specified sopInstanceUid for single-frame images.
|
|
278
|
+
*
|
|
279
|
+
* @param {String} sopInstanceUid The sopInstanceUid of the desired image.
|
|
280
|
+
* @param {String[]} imageIds The list of imageIds.
|
|
281
|
+
* @param {Object} metadataProvider The metadataProvider to obtain sopInstanceUids
|
|
282
|
+
* from the cornerstone imageIds.
|
|
283
|
+
* @return {String} The imageId that corresponds to the sopInstanceUid.
|
|
284
|
+
*/
|
|
285
|
+
function getImageIdOfReferencedSingleFramedSOPInstance(sopInstanceUid, imageIds, metadataProvider) {
|
|
286
|
+
return imageIds.find(function (imageId) {
|
|
287
|
+
var sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
|
|
288
|
+
if (!sopCommonModule) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
return sopCommonModule.sopInstanceUID === sopInstanceUid;
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* getImageIdOfReferencedFrame - Returns the imageId corresponding to the
|
|
297
|
+
* specified sopInstanceUid and frameNumber for multi-frame images.
|
|
298
|
+
*
|
|
299
|
+
* @param {String} sopInstanceUid The sopInstanceUid of the desired image.
|
|
300
|
+
* @param {Number} frameNumber The frame number.
|
|
301
|
+
* @param {String} imageIds The list of imageIds.
|
|
302
|
+
* @param {Object} metadataProvider The metadataProvider to obtain sopInstanceUids
|
|
303
|
+
* from the cornerstone imageIds.
|
|
304
|
+
* @return {String} The imageId that corresponds to the sopInstanceUid.
|
|
305
|
+
*/
|
|
306
|
+
function getImageIdOfReferencedFrame(sopInstanceUid, frameNumber, imageIds, metadataProvider) {
|
|
307
|
+
var imageId = imageIds.find(function (imageId) {
|
|
308
|
+
var sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
|
|
309
|
+
if (!sopCommonModule) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
var imageIdFrameNumber = Number(imageId.split("frame=")[1]);
|
|
313
|
+
return (
|
|
314
|
+
//frameNumber is zero indexed for cornerstoneDICOMImageLoader image Ids.
|
|
315
|
+
sopCommonModule.sopInstanceUID === sopInstanceUid && imageIdFrameNumber === frameNumber - 1
|
|
316
|
+
);
|
|
317
|
+
});
|
|
318
|
+
return imageId;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* getValidOrientations - returns an array of valid orientations.
|
|
323
|
+
*
|
|
324
|
+
* @param iop - The row (0..2) an column (3..5) direction cosines.
|
|
325
|
+
* @return An array of valid orientations.
|
|
326
|
+
*/
|
|
327
|
+
function getValidOrientations(iop) {
|
|
328
|
+
var orientations = [];
|
|
329
|
+
|
|
330
|
+
// [0, 1, 2]: 0, 0hf, 0vf
|
|
331
|
+
// [3, 4, 5]: 90, 90hf, 90vf
|
|
332
|
+
// [6, 7]: 180, 270
|
|
333
|
+
|
|
334
|
+
orientations[0] = iop;
|
|
335
|
+
orientations[1] = flipIOP.h(iop);
|
|
336
|
+
orientations[2] = flipIOP.v(iop);
|
|
337
|
+
var iop90 = rotateDirectionCosinesInPlane(iop, Math.PI / 2);
|
|
338
|
+
orientations[3] = iop90;
|
|
339
|
+
orientations[4] = flipIOP.h(iop90);
|
|
340
|
+
orientations[5] = flipIOP.v(iop90);
|
|
341
|
+
orientations[6] = rotateDirectionCosinesInPlane(iop, Math.PI);
|
|
342
|
+
orientations[7] = rotateDirectionCosinesInPlane(iop, 1.5 * Math.PI);
|
|
343
|
+
return orientations;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* alignPixelDataWithSourceData -
|
|
348
|
+
*
|
|
349
|
+
* @param pixelData2D - The data to align.
|
|
350
|
+
* @param iop - The orientation of the image slice.
|
|
351
|
+
* @param orientations - An array of valid imageOrientationPatient values.
|
|
352
|
+
* @return The aligned pixelData.
|
|
353
|
+
*/
|
|
354
|
+
function alignPixelDataWithSourceData(pixelData2D, iop, orientations) {
|
|
355
|
+
if (compareIOP(iop, orientations[0])) {
|
|
356
|
+
//Same orientation.
|
|
357
|
+
return pixelData2D;
|
|
358
|
+
} else if (compareIOP(iop, orientations[1])) {
|
|
359
|
+
//Flipped vertically.
|
|
360
|
+
return flipMatrix2D.v(pixelData2D);
|
|
361
|
+
} else if (compareIOP(iop, orientations[2])) {
|
|
362
|
+
//Flipped horizontally.
|
|
363
|
+
return flipMatrix2D.h(pixelData2D);
|
|
364
|
+
} else if (compareIOP(iop, orientations[3])) {
|
|
365
|
+
//Rotated 90 degrees.
|
|
366
|
+
return rotateMatrix902D(pixelData2D);
|
|
367
|
+
} else if (compareIOP(iop, orientations[4])) {
|
|
368
|
+
//Rotated 90 degrees and fliped horizontally.
|
|
369
|
+
return flipMatrix2D.h(rotateMatrix902D(pixelData2D));
|
|
370
|
+
} else if (compareIOP(iop, orientations[5])) {
|
|
371
|
+
//Rotated 90 degrees and fliped vertically.
|
|
372
|
+
return flipMatrix2D.v(rotateMatrix902D(pixelData2D));
|
|
373
|
+
} else if (compareIOP(iop, orientations[6])) {
|
|
374
|
+
//Rotated 180 degrees. // TODO -> Do this more effeciently, there is a 1:1 mapping like 90 degree rotation.
|
|
375
|
+
return rotateMatrix902D(rotateMatrix902D(pixelData2D));
|
|
376
|
+
} else if (compareIOP(iop, orientations[7])) {
|
|
377
|
+
//Rotated 270 degrees. // TODO -> Do this more effeciently, there is a 1:1 mapping like 90 degree rotation.
|
|
378
|
+
return rotateMatrix902D(rotateMatrix902D(rotateMatrix902D(pixelData2D)));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
var dx = 1e-5;
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* compareIOP - Returns true if iop1 and iop2 are equal
|
|
385
|
+
* within a tollerance, dx.
|
|
386
|
+
*
|
|
387
|
+
* @param iop1 - An ImageOrientationPatient array.
|
|
388
|
+
* @param iop2 - An ImageOrientationPatient array.
|
|
389
|
+
* @return True if iop1 and iop2 are equal.
|
|
390
|
+
*/
|
|
391
|
+
function compareIOP(iop1, iop2) {
|
|
392
|
+
return Math.abs(iop1[0] - iop2[0]) < dx && Math.abs(iop1[1] - iop2[1]) < dx && Math.abs(iop1[2] - iop2[2]) < dx && Math.abs(iop1[3] - iop2[3]) < dx && Math.abs(iop1[4] - iop2[4]) < dx && Math.abs(iop1[5] - iop2[5]) < dx;
|
|
393
|
+
}
|
|
394
|
+
function getSegmentMetadata(multiframe) {
|
|
395
|
+
var data = [];
|
|
396
|
+
var segmentSequence = multiframe.SegmentSequence;
|
|
397
|
+
if (Array.isArray(segmentSequence)) {
|
|
398
|
+
for (var segIdx = 0; segIdx < segmentSequence.length; segIdx++) {
|
|
399
|
+
data.push(segmentSequence[segIdx]);
|
|
400
|
+
}
|
|
401
|
+
} else {
|
|
402
|
+
// Only one segment, will be stored as an object.
|
|
403
|
+
data.push(segmentSequence);
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
seriesInstanceUid: multiframe.ReferencedSeriesSequence.SeriesInstanceUID,
|
|
407
|
+
data: data
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export { Segmentation as default };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default Segmentation;
|
|
2
|
+
export type BrushData = {
|
|
3
|
+
toolState: any;
|
|
4
|
+
segments: any[];
|
|
5
|
+
};
|
|
6
|
+
declare namespace Segmentation {
|
|
7
|
+
export { generateSegmentation };
|
|
8
|
+
export { generateToolState };
|
|
9
|
+
export { fillSegmentation };
|
|
10
|
+
}
|
|
11
|
+
export function fillSegmentation(segmentation: any, inputLabelmaps3D: any, userOptions?: {}): object;
|
|
12
|
+
export function generateSegmentation(images: object[], inputLabelmaps3D: any | any[], userOptions?: any): Blob;
|
|
13
|
+
export function generateToolState(imageIds: string[], arrayBuffer: ArrayBuffer, metadataProvider: any, options: obj): [];
|