@cornerstonejs/adapters 4.22.7 → 4.22.9
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/adapters/Cornerstone/Angle.js +22 -15
- package/dist/esm/adapters/Cornerstone/ArrowAnnotate.js +13 -18
- package/dist/esm/adapters/Cornerstone/Bidirectional.js +22 -27
- package/dist/esm/adapters/Cornerstone/CircleRoi.js +20 -26
- package/dist/esm/adapters/Cornerstone/CobbAngle.js +22 -15
- package/dist/esm/adapters/Cornerstone/EllipticalRoi.js +19 -25
- package/dist/esm/adapters/Cornerstone/FreehandRoi.js +21 -25
- package/dist/esm/adapters/Cornerstone/Length.js +18 -15
- package/dist/esm/adapters/Cornerstone/MeasurementReport.js +20 -40
- package/dist/esm/adapters/Cornerstone/ParametricMap.js +15 -26
- package/dist/esm/adapters/Cornerstone/RectangleRoi.js +26 -25
- package/dist/esm/adapters/Cornerstone/Segmentation_3X.js +19 -31
- package/dist/esm/adapters/Cornerstone/Segmentation_4X.js +69 -90
- package/dist/esm/adapters/Cornerstone3D/Angle.js +17 -24
- package/dist/esm/adapters/Cornerstone3D/ArrowAnnotate.js +21 -35
- package/dist/esm/adapters/Cornerstone3D/BaseAdapter3D.js +12 -23
- package/dist/esm/adapters/Cornerstone3D/Bidirectional.js +21 -33
- package/dist/esm/adapters/Cornerstone3D/CircleROI.js +27 -35
- package/dist/esm/adapters/Cornerstone3D/CobbAngle.js +25 -28
- package/dist/esm/adapters/Cornerstone3D/ControlPointPolyline.js +10 -17
- package/dist/esm/adapters/Cornerstone3D/EllipticalROI.js +25 -33
- package/dist/esm/adapters/Cornerstone3D/KeyImage.js +3 -9
- package/dist/esm/adapters/Cornerstone3D/LabelData.js +22 -33
- package/dist/esm/adapters/Cornerstone3D/Length.js +19 -27
- package/dist/esm/adapters/Cornerstone3D/MeasurementReport.js +73 -116
- package/dist/esm/adapters/Cornerstone3D/ParametricMap/generateToolState.js +2 -6
- package/dist/esm/adapters/Cornerstone3D/PlanarFreehandROI.js +26 -35
- package/dist/esm/adapters/Cornerstone3D/Probe.js +16 -27
- package/dist/esm/adapters/Cornerstone3D/RTStruct/RTSS.js +13 -29
- package/dist/esm/adapters/Cornerstone3D/RTStruct/index.js +1 -3
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getReferencedFrameOfReferenceSequence.js +1 -3
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getReferencedSeriesSequence.js +7 -13
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getStructureSetModule.js +1 -3
- package/dist/esm/adapters/Cornerstone3D/RectangleROI.js +21 -28
- package/dist/esm/adapters/Cornerstone3D/Segmentation/compactMergeSegData.js +5 -9
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateLabelMaps2DFrom3D.js +2 -4
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateSegmentation.js +5 -15
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateToolState.js +3 -4
- package/dist/esm/adapters/Cornerstone3D/Segmentation/labelmapImagesFromBuffer.js +124 -156
- package/dist/esm/adapters/Cornerstone3D/UltrasoundDirectional.js +12 -23
- package/dist/esm/adapters/Cornerstone3D/metricHandler.js +8 -5
- package/dist/esm/adapters/VTKjs/Segmentation.js +2 -4
- package/dist/esm/adapters/helpers/checkOrientation.js +2 -4
- package/dist/esm/adapters/helpers/downloadDICOMData.js +1 -3
- package/dist/esm/adapters/helpers/getDatasetsFromImages.js +3 -7
- package/dist/esm/adapters/helpers/scoordToWorld.js +5 -13
- package/dist/esm/adapters/helpers/toPoint3.js +1 -3
- package/dist/esm/adapters/helpers/toScoordType.js +3 -7
- package/dist/esm/adapters/index.js +3 -2
- package/dist/esm/utilities/createInstance.js +9 -8
- package/dist/esm/utilities/referencedMetadataProvider.js +7 -13
- package/dist/esm/version.d.ts +1 -1
- package/package.json +6 -6
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
import { utilities, derivations, normalizers, data } from 'dcmjs';
|
|
2
2
|
import { toArray } from '../helpers/toArray.js';
|
|
3
3
|
import { codeMeaningEquals } from '../helpers/codeMeaningEquals.js';
|
|
4
|
-
import '
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} = normalizers;
|
|
16
|
-
const {
|
|
17
|
-
TID1500MeasurementReport,
|
|
18
|
-
TID1501MeasurementGroup
|
|
19
|
-
} = TID1500;
|
|
20
|
-
const {
|
|
21
|
-
DicomMetaDictionary
|
|
22
|
-
} = data;
|
|
4
|
+
import '../helpers/downloadDICOMData.js';
|
|
5
|
+
import '../helpers/toScoordType.js';
|
|
6
|
+
import '../helpers/scoordToWorld.js';
|
|
7
|
+
|
|
8
|
+
const TID1500 = utilities.TID1500,
|
|
9
|
+
addAccessors = utilities.addAccessors;
|
|
10
|
+
const StructuredReport = derivations.StructuredReport;
|
|
11
|
+
const Normalizer = normalizers.Normalizer;
|
|
12
|
+
const TID1500MeasurementReport = TID1500.TID1500MeasurementReport,
|
|
13
|
+
TID1501MeasurementGroup = TID1500.TID1501MeasurementGroup;
|
|
14
|
+
const DicomMetaDictionary = data.DicomMetaDictionary;
|
|
23
15
|
const FINDING = {
|
|
24
16
|
CodingSchemeDesignator: 'DCM',
|
|
25
17
|
CodeValue: '121071'
|
|
@@ -33,16 +25,12 @@ const FINDING_SITE_OLD = {
|
|
|
33
25
|
CodeValue: 'G-C0E3'
|
|
34
26
|
};
|
|
35
27
|
const codeValueMatch = (group, code, oldCode) => {
|
|
36
|
-
const
|
|
37
|
-
ConceptNameCodeSequence
|
|
38
|
-
} = group;
|
|
28
|
+
const ConceptNameCodeSequence = group.ConceptNameCodeSequence;
|
|
39
29
|
if (!ConceptNameCodeSequence) {
|
|
40
30
|
return;
|
|
41
31
|
}
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
CodeValue
|
|
45
|
-
} = ConceptNameCodeSequence;
|
|
32
|
+
const CodingSchemeDesignator = ConceptNameCodeSequence.CodingSchemeDesignator,
|
|
33
|
+
CodeValue = ConceptNameCodeSequence.CodeValue;
|
|
46
34
|
return CodingSchemeDesignator == code.CodingSchemeDesignator && CodeValue == code.CodeValue || oldCode && CodingSchemeDesignator == oldCode.CodingSchemeDesignator && CodeValue == oldCode.CodeValue;
|
|
47
35
|
};
|
|
48
36
|
function getTID300ContentItem(tool, ReferencedSOPSequence, adapterClass) {
|
|
@@ -68,21 +56,15 @@ function getMeasurementGroup(toolType, toolData, ReferencedSOPSequence) {
|
|
|
68
56
|
}
|
|
69
57
|
class MeasurementReport {
|
|
70
58
|
static getSetupMeasurementData(MeasurementGroup) {
|
|
71
|
-
const
|
|
72
|
-
ContentSequence
|
|
73
|
-
} = MeasurementGroup;
|
|
59
|
+
const ContentSequence = MeasurementGroup.ContentSequence;
|
|
74
60
|
const contentSequenceArr = toArray(ContentSequence);
|
|
75
61
|
const findingGroup = contentSequenceArr.find(group => codeValueMatch(group, FINDING));
|
|
76
62
|
const findingSiteGroups = contentSequenceArr.filter(group => codeValueMatch(group, FINDING_SITE, FINDING_SITE_OLD)) || [];
|
|
77
63
|
const NUMGroup = contentSequenceArr.find(group => group.ValueType === 'NUM');
|
|
78
64
|
const SCOORDGroup = toArray(NUMGroup.ContentSequence).find(group => group.ValueType === 'SCOORD');
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const {
|
|
83
|
-
ReferencedSOPInstanceUID,
|
|
84
|
-
ReferencedFrameNumber
|
|
85
|
-
} = ReferencedSOPSequence;
|
|
65
|
+
const ReferencedSOPSequence = SCOORDGroup.ContentSequence.ReferencedSOPSequence;
|
|
66
|
+
const ReferencedSOPInstanceUID = ReferencedSOPSequence.ReferencedSOPInstanceUID,
|
|
67
|
+
ReferencedFrameNumber = ReferencedSOPSequence.ReferencedFrameNumber;
|
|
86
68
|
const defaultState = {
|
|
87
69
|
sopInstanceUid: ReferencedSOPInstanceUID,
|
|
88
70
|
frameIndex: ReferencedFrameNumber || 1,
|
|
@@ -133,10 +115,8 @@ class MeasurementReport {
|
|
|
133
115
|
// NOTE: We are getting the Series and Study UIDs from the first imageId of the toolState
|
|
134
116
|
// which means that if the toolState is for multiple series, the report will have the incorrect
|
|
135
117
|
// SeriesInstanceUIDs
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
seriesInstanceUID
|
|
139
|
-
} = generalSeriesModule;
|
|
118
|
+
const studyInstanceUID = generalSeriesModule.studyInstanceUID,
|
|
119
|
+
seriesInstanceUID = generalSeriesModule.seriesInstanceUID;
|
|
140
120
|
|
|
141
121
|
// Loop through each image in the toolData
|
|
142
122
|
Object.keys(toolState).forEach(imageId => {
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { data, normalizers, log } from 'dcmjs';
|
|
2
2
|
import checkOrientation from '../helpers/checkOrientation.js';
|
|
3
3
|
import { utilities } from '@cornerstonejs/core';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} = data;
|
|
9
|
-
const {
|
|
10
|
-
Normalizer
|
|
11
|
-
} = normalizers;
|
|
5
|
+
const DicomMessage = data.DicomMessage,
|
|
6
|
+
DicomMetaDictionary = data.DicomMetaDictionary;
|
|
7
|
+
const Normalizer = normalizers.Normalizer;
|
|
12
8
|
async function generateToolState(imageIds, arrayBuffer, metadataProvider) {
|
|
13
9
|
let tolerance = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1e-3;
|
|
14
10
|
const dicomData = DicomMessage.readFile(arrayBuffer);
|
|
@@ -24,9 +20,8 @@ async function generateToolState(imageIds, arrayBuffer, metadataProvider) {
|
|
|
24
20
|
const pixelData = getPixelData(multiframe);
|
|
25
21
|
const orientation = checkOrientation(multiframe, validOrientations, [imagePlaneModule.rows, imagePlaneModule.columns, imageIds.length], tolerance);
|
|
26
22
|
const sopUIDImageIdIndexMap = imageIds.reduce((acc, imageId) => {
|
|
27
|
-
const
|
|
28
|
-
sopInstanceUID
|
|
29
|
-
} = metadataProvider.get('generalImageModule', imageId);
|
|
23
|
+
const _metadataProvider$get = metadataProvider.get('generalImageModule', imageId),
|
|
24
|
+
sopInstanceUID = _metadataProvider$get.sopInstanceUID;
|
|
30
25
|
acc[sopInstanceUID] = imageId;
|
|
31
26
|
return acc;
|
|
32
27
|
}, {});
|
|
@@ -52,11 +47,9 @@ async function generateToolState(imageIds, arrayBuffer, metadataProvider) {
|
|
|
52
47
|
}
|
|
53
48
|
function insertPixelDataPlanar(sourcePixelData, multiframe, imageIds, metadataProvider, tolerance, sopUIDImageIdIndexMap, imageIdMaps) {
|
|
54
49
|
const targetPixelData = new sourcePixelData.constructor(sourcePixelData.length);
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
Columns
|
|
59
|
-
} = multiframe;
|
|
50
|
+
const PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
51
|
+
Rows = multiframe.Rows,
|
|
52
|
+
Columns = multiframe.Columns;
|
|
60
53
|
const sliceLength = Columns * Rows;
|
|
61
54
|
const numSlices = PerFrameFunctionalGroupsSequence.length;
|
|
62
55
|
for (let i = 0; i < numSlices; i++) {
|
|
@@ -105,12 +98,10 @@ function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadata
|
|
|
105
98
|
if (!multiframe) {
|
|
106
99
|
return imageId;
|
|
107
100
|
}
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
ReferencedSeriesSequence
|
|
113
|
-
} = multiframe;
|
|
101
|
+
const FrameOfReferenceUID = multiframe.FrameOfReferenceUID,
|
|
102
|
+
PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
103
|
+
SourceImageSequence = multiframe.SourceImageSequence,
|
|
104
|
+
ReferencedSeriesSequence = multiframe.ReferencedSeriesSequence;
|
|
114
105
|
if (!PerFrameFunctionalGroupsSequence || PerFrameFunctionalGroupsSequence.length === 0) {
|
|
115
106
|
return imageId;
|
|
116
107
|
}
|
|
@@ -153,10 +144,8 @@ function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadata
|
|
|
153
144
|
return imageId;
|
|
154
145
|
}
|
|
155
146
|
function getImageIdOfSourceImageBySourceImageSequence(SourceImageSequence, sopUIDImageIdIndexMap) {
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
ReferencedFrameNumber
|
|
159
|
-
} = SourceImageSequence;
|
|
147
|
+
const ReferencedSOPInstanceUID = SourceImageSequence.ReferencedSOPInstanceUID,
|
|
148
|
+
ReferencedFrameNumber = SourceImageSequence.ReferencedFrameNumber;
|
|
160
149
|
return ReferencedFrameNumber ? getImageIdOfReferencedFrame(ReferencedSOPInstanceUID, ReferencedFrameNumber, sopUIDImageIdIndexMap) : sopUIDImageIdIndexMap[ReferencedSOPInstanceUID];
|
|
161
150
|
}
|
|
162
151
|
function getImageIdOfSourceImagebyGeometry(ReferencedSeriesInstanceUID, FrameOfReferenceUID, PerFrameFunctionalGroup, imageIds, metadataProvider, tolerance) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
1
2
|
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
2
3
|
import { utilities } from 'dcmjs';
|
|
3
4
|
import MeasurementReport from './MeasurementReport.js';
|
|
@@ -5,16 +6,13 @@ import CORNERSTONE_4_TAG from './cornerstone4Tag.js';
|
|
|
5
6
|
|
|
6
7
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
7
8
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
8
|
-
const
|
|
9
|
-
Polyline: TID300Polyline
|
|
10
|
-
} = utilities.TID300;
|
|
9
|
+
const TID300Polyline = utilities.TID300.Polyline;
|
|
11
10
|
class RectangleRoi {
|
|
12
11
|
static getMeasurementData(MeasurementGroup) {
|
|
13
|
-
const
|
|
14
|
-
defaultState,
|
|
15
|
-
SCOORDGroup,
|
|
16
|
-
NUMGroup
|
|
17
|
-
} = MeasurementReport.getSetupMeasurementData(MeasurementGroup);
|
|
12
|
+
const _MeasurementReport$ge = MeasurementReport.getSetupMeasurementData(MeasurementGroup),
|
|
13
|
+
defaultState = _MeasurementReport$ge.defaultState,
|
|
14
|
+
SCOORDGroup = _MeasurementReport$ge.SCOORDGroup,
|
|
15
|
+
NUMGroup = _MeasurementReport$ge.NUMGroup;
|
|
18
16
|
const state = _objectSpread(_objectSpread({}, defaultState), {}, {
|
|
19
17
|
toolType: RectangleRoi.toolType,
|
|
20
18
|
handles: {
|
|
@@ -36,21 +34,23 @@ class RectangleRoi {
|
|
|
36
34
|
color: undefined,
|
|
37
35
|
invalidated: true
|
|
38
36
|
});
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
var _SCOORDGroup$GraphicD = _slicedToArray(SCOORDGroup.GraphicData, 6);
|
|
38
|
+
state.handles.start.x = _SCOORDGroup$GraphicD[0];
|
|
39
|
+
state.handles.start.y = _SCOORDGroup$GraphicD[1];
|
|
40
|
+
_SCOORDGroup$GraphicD[2];
|
|
41
|
+
_SCOORDGroup$GraphicD[3];
|
|
42
|
+
state.handles.end.x = _SCOORDGroup$GraphicD[4];
|
|
43
|
+
state.handles.end.y = _SCOORDGroup$GraphicD[5];
|
|
41
44
|
return state;
|
|
42
45
|
}
|
|
43
46
|
static getTID300RepresentationArguments(tool) {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
cachedStats = {},
|
|
48
|
-
handles
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
start,
|
|
52
|
-
end
|
|
53
|
-
} = handles;
|
|
47
|
+
const finding = tool.finding,
|
|
48
|
+
findingSites = tool.findingSites,
|
|
49
|
+
_tool$cachedStats = tool.cachedStats,
|
|
50
|
+
cachedStats = _tool$cachedStats === void 0 ? {} : _tool$cachedStats,
|
|
51
|
+
handles = tool.handles;
|
|
52
|
+
const start = handles.start,
|
|
53
|
+
end = handles.end;
|
|
54
54
|
const points = [start, {
|
|
55
55
|
x: start.x,
|
|
56
56
|
y: end.y
|
|
@@ -58,10 +58,8 @@ class RectangleRoi {
|
|
|
58
58
|
x: end.x,
|
|
59
59
|
y: start.y
|
|
60
60
|
}];
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
perimeter
|
|
64
|
-
} = cachedStats;
|
|
61
|
+
const area = cachedStats.area,
|
|
62
|
+
perimeter = cachedStats.perimeter;
|
|
65
63
|
const trackingIdentifierTextValue = 'cornerstoneTools@^4.0.0:RectangleRoi';
|
|
66
64
|
return {
|
|
67
65
|
points,
|
|
@@ -80,7 +78,10 @@ RectangleRoi.isValidCornerstoneTrackingIdentifier = TrackingIdentifier => {
|
|
|
80
78
|
if (!TrackingIdentifier.includes(':')) {
|
|
81
79
|
return false;
|
|
82
80
|
}
|
|
83
|
-
const
|
|
81
|
+
const _TrackingIdentifier$s = TrackingIdentifier.split(':'),
|
|
82
|
+
_TrackingIdentifier$s2 = _slicedToArray(_TrackingIdentifier$s, 2),
|
|
83
|
+
cornerstone4Tag = _TrackingIdentifier$s2[0],
|
|
84
|
+
toolType = _TrackingIdentifier$s2[1];
|
|
84
85
|
if (cornerstone4Tag !== CORNERSTONE_4_TAG) {
|
|
85
86
|
return false;
|
|
86
87
|
}
|
|
@@ -1,25 +1,18 @@
|
|
|
1
|
-
import { utilities,
|
|
1
|
+
import { utilities, normalizers, derivations, log } from 'dcmjs';
|
|
2
2
|
import ndarray from 'ndarray';
|
|
3
3
|
import getDatasetsFromImages from '../helpers/getDatasetsFromImages.js';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
rotateDirectionCosinesInPlane,
|
|
7
|
-
flipImageOrientationPatient
|
|
8
|
-
flipMatrix2D,
|
|
9
|
-
rotateMatrix902D
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} = utilities;
|
|
17
|
-
const {
|
|
18
|
-
Normalizer
|
|
19
|
-
} = normalizers;
|
|
20
|
-
const {
|
|
21
|
-
Segmentation: SegmentationDerivation
|
|
22
|
-
} = derivations;
|
|
5
|
+
const _utilities$orientatio = utilities.orientation,
|
|
6
|
+
rotateDirectionCosinesInPlane = _utilities$orientatio.rotateDirectionCosinesInPlane,
|
|
7
|
+
flipIOP = _utilities$orientatio.flipImageOrientationPatient,
|
|
8
|
+
flipMatrix2D = _utilities$orientatio.flipMatrix2D,
|
|
9
|
+
rotateMatrix902D = _utilities$orientatio.rotateMatrix902D;
|
|
10
|
+
const datasetToBlob = utilities.datasetToBlob,
|
|
11
|
+
BitArray = utilities.BitArray,
|
|
12
|
+
DicomMessage = utilities.DicomMessage,
|
|
13
|
+
DicomMetaDictionary = utilities.DicomMetaDictionary;
|
|
14
|
+
const Normalizer = normalizers.Normalizer;
|
|
15
|
+
const SegmentationDerivation = derivations.Segmentation;
|
|
23
16
|
const Segmentation = {
|
|
24
17
|
generateSegmentation,
|
|
25
18
|
generateToolState
|
|
@@ -45,10 +38,8 @@ function generateSegmentation(images, brushData) {
|
|
|
45
38
|
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
|
|
46
39
|
includeSliceSpacing: true
|
|
47
40
|
};
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
segments
|
|
51
|
-
} = brushData;
|
|
41
|
+
const toolState = brushData.toolState,
|
|
42
|
+
segments = brushData.segments;
|
|
52
43
|
|
|
53
44
|
// Calculate the dimensions of the data cube.
|
|
54
45
|
const image0 = images[0];
|
|
@@ -64,10 +55,9 @@ function generateSegmentation(images, brushData) {
|
|
|
64
55
|
}
|
|
65
56
|
const isMultiframe = image0.imageId.includes('?frame');
|
|
66
57
|
const seg = _createSegFromImages(images, isMultiframe, options);
|
|
67
|
-
const
|
|
68
|
-
referencedFramesPerSegment,
|
|
69
|
-
segmentIndicies
|
|
70
|
-
} = _getNumberOfFramesPerSegment(toolState, images, segments);
|
|
58
|
+
const _getNumberOfFramesPer = _getNumberOfFramesPerSegment(toolState, images, segments),
|
|
59
|
+
referencedFramesPerSegment = _getNumberOfFramesPer.referencedFramesPerSegment,
|
|
60
|
+
segmentIndicies = _getNumberOfFramesPer.segmentIndicies;
|
|
71
61
|
let NumberOfFrames = 0;
|
|
72
62
|
for (let i = 0; i < referencedFramesPerSegment.length; i++) {
|
|
73
63
|
NumberOfFrames += referencedFramesPerSegment[i].length;
|
|
@@ -274,10 +264,8 @@ function addImageIdSpecificBrushToolState(toolState, imageId, segmentIndex, pixe
|
|
|
274
264
|
* @return {String} The corresponding imageId.
|
|
275
265
|
*/
|
|
276
266
|
function getImageIdOfSourceImage(SourceImageSequence, imageIds, metadataProvider) {
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
ReferencedFrameNumber
|
|
280
|
-
} = SourceImageSequence;
|
|
267
|
+
const ReferencedSOPInstanceUID = SourceImageSequence.ReferencedSOPInstanceUID,
|
|
268
|
+
ReferencedFrameNumber = SourceImageSequence.ReferencedFrameNumber;
|
|
281
269
|
return ReferencedFrameNumber ? getImageIdOfReferencedFrame(ReferencedSOPInstanceUID, ReferencedFrameNumber, imageIds, metadataProvider) : getImageIdOfReferencedSingleFramedSOPInstance(ReferencedSOPInstanceUID, imageIds, metadataProvider);
|
|
282
270
|
}
|
|
283
271
|
|
|
@@ -1,31 +1,24 @@
|
|
|
1
|
-
import
|
|
1
|
+
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
2
|
+
import { utilities, data, normalizers, derivations, log } from 'dcmjs';
|
|
2
3
|
import ndarray from 'ndarray';
|
|
3
4
|
import getDatasetsFromImages from '../helpers/getDatasetsFromImages.js';
|
|
4
5
|
import checkOrientation from '../helpers/checkOrientation.js';
|
|
5
6
|
import { utilities as utilities$1 } from '@cornerstonejs/core';
|
|
6
7
|
import { Events } from '../enums/Events.js';
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
-
rotateDirectionCosinesInPlane,
|
|
10
|
-
flipImageOrientationPatient
|
|
11
|
-
flipMatrix2D,
|
|
12
|
-
rotateMatrix902D
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} = normalizers;
|
|
22
|
-
const {
|
|
23
|
-
Segmentation: SegmentationDerivation
|
|
24
|
-
} = derivations;
|
|
25
|
-
const {
|
|
26
|
-
encode,
|
|
27
|
-
decode
|
|
28
|
-
} = utilities.compression;
|
|
9
|
+
const _utilities$orientatio = utilities.orientation,
|
|
10
|
+
rotateDirectionCosinesInPlane = _utilities$orientatio.rotateDirectionCosinesInPlane,
|
|
11
|
+
flipIOP = _utilities$orientatio.flipImageOrientationPatient,
|
|
12
|
+
flipMatrix2D = _utilities$orientatio.flipMatrix2D,
|
|
13
|
+
rotateMatrix902D = _utilities$orientatio.rotateMatrix902D;
|
|
14
|
+
const BitArray = data.BitArray,
|
|
15
|
+
DicomMessage = data.DicomMessage,
|
|
16
|
+
DicomMetaDictionary = data.DicomMetaDictionary;
|
|
17
|
+
const Normalizer = normalizers.Normalizer;
|
|
18
|
+
const SegmentationDerivation = derivations.Segmentation;
|
|
19
|
+
const _utilities$compressio = utilities.compression,
|
|
20
|
+
encode = _utilities$compressio.encode,
|
|
21
|
+
decode = _utilities$compressio.decode;
|
|
29
22
|
|
|
30
23
|
/**
|
|
31
24
|
*
|
|
@@ -75,10 +68,8 @@ function fillSegmentation(segmentation, inputLabelmaps3D) {
|
|
|
75
68
|
const referencedFramesPerLabelmap = [];
|
|
76
69
|
for (let labelmapIndex = 0; labelmapIndex < labelmaps3D.length; labelmapIndex++) {
|
|
77
70
|
const labelmap3D = labelmaps3D[labelmapIndex];
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
metadata
|
|
81
|
-
} = labelmap3D;
|
|
71
|
+
const labelmaps2D = labelmap3D.labelmaps2D,
|
|
72
|
+
metadata = labelmap3D.metadata;
|
|
82
73
|
const referencedFramesPerSegment = [];
|
|
83
74
|
for (let i = 1; i < metadata.length; i++) {
|
|
84
75
|
if (metadata[i]) {
|
|
@@ -88,9 +79,7 @@ function fillSegmentation(segmentation, inputLabelmaps3D) {
|
|
|
88
79
|
for (let i = 0; i < labelmaps2D.length; i++) {
|
|
89
80
|
const labelmap2D = labelmaps2D[i];
|
|
90
81
|
if (labelmaps2D[i]) {
|
|
91
|
-
const
|
|
92
|
-
segmentsOnLabelmap
|
|
93
|
-
} = labelmap2D;
|
|
82
|
+
const segmentsOnLabelmap = labelmap2D.segmentsOnLabelmap;
|
|
94
83
|
segmentsOnLabelmap.forEach(segmentIndex => {
|
|
95
84
|
if (segmentIndex !== 0) {
|
|
96
85
|
referencedFramesPerSegment[segmentIndex].push(i);
|
|
@@ -105,9 +94,7 @@ function fillSegmentation(segmentation, inputLabelmaps3D) {
|
|
|
105
94
|
for (let labelmapIndex = 0; labelmapIndex < labelmaps3D.length; labelmapIndex++) {
|
|
106
95
|
const referencedFramesPerSegment = referencedFramesPerLabelmap[labelmapIndex];
|
|
107
96
|
const labelmap3D = labelmaps3D[labelmapIndex];
|
|
108
|
-
const
|
|
109
|
-
metadata
|
|
110
|
-
} = labelmap3D;
|
|
97
|
+
const metadata = labelmap3D.metadata;
|
|
111
98
|
for (let segmentIndex = 1; segmentIndex < referencedFramesPerSegment.length; segmentIndex++) {
|
|
112
99
|
const referencedFrameIndicies = referencedFramesPerSegment[segmentIndex];
|
|
113
100
|
if (referencedFrameIndicies) {
|
|
@@ -149,9 +136,7 @@ function fillSegmentation(segmentation, inputLabelmaps3D) {
|
|
|
149
136
|
return segmentation;
|
|
150
137
|
}
|
|
151
138
|
function _getLabelmapsFromReferencedFrameIndicies(labelmap3D, referencedFrameIndicies) {
|
|
152
|
-
const
|
|
153
|
-
labelmaps2D
|
|
154
|
-
} = labelmap3D;
|
|
139
|
+
const labelmaps2D = labelmap3D.labelmaps2D;
|
|
155
140
|
const labelmaps = [];
|
|
156
141
|
for (let i = 0; i < referencedFrameIndicies.length; i++) {
|
|
157
142
|
const frame = referencedFrameIndicies[i];
|
|
@@ -188,14 +173,18 @@ function _createSegFromImages(images, isMultiframe, options) {
|
|
|
188
173
|
* (available only for the overlapping case).
|
|
189
174
|
*/
|
|
190
175
|
async function generateToolState(referencedImageIds, arrayBuffer, metadataProvider, options) {
|
|
191
|
-
const
|
|
192
|
-
skipOverlapping = false,
|
|
193
|
-
tolerance =
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
176
|
+
const _options$skipOverlapp = options.skipOverlapping,
|
|
177
|
+
skipOverlapping = _options$skipOverlapp === void 0 ? false : _options$skipOverlapp,
|
|
178
|
+
_options$tolerance = options.tolerance,
|
|
179
|
+
tolerance = _options$tolerance === void 0 ? 1e-3 : _options$tolerance,
|
|
180
|
+
_options$TypedArrayCo = options.TypedArrayConstructor,
|
|
181
|
+
TypedArrayConstructor = _options$TypedArrayCo === void 0 ? Uint8Array : _options$TypedArrayCo,
|
|
182
|
+
_options$maxBytesPerC = options.maxBytesPerChunk,
|
|
183
|
+
maxBytesPerChunk = _options$maxBytesPerC === void 0 ? 199000000 : _options$maxBytesPerC,
|
|
184
|
+
_options$eventTarget = options.eventTarget,
|
|
185
|
+
eventTarget = _options$eventTarget === void 0 ? null : _options$eventTarget,
|
|
186
|
+
_options$triggerEvent = options.triggerEvent,
|
|
187
|
+
triggerEvent = _options$triggerEvent === void 0 ? null : _options$triggerEvent;
|
|
199
188
|
const dicomData = DicomMessage.readFile(arrayBuffer);
|
|
200
189
|
const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
|
|
201
190
|
dataset._meta = DicomMetaDictionary.namifyDataset(dicomData.meta);
|
|
@@ -239,9 +228,8 @@ async function generateToolState(referencedImageIds, arrayBuffer, metadataProvid
|
|
|
239
228
|
// we don't have to call metadataProvider.get() for each imageId over
|
|
240
229
|
// and over again.
|
|
241
230
|
const sopUIDImageIdIndexMap = referencedImageIds.reduce((acc, imageId) => {
|
|
242
|
-
const
|
|
243
|
-
sopInstanceUID
|
|
244
|
-
} = metadataProvider.get('generalImageModule', imageId);
|
|
231
|
+
const _metadataProvider$get = metadataProvider.get('generalImageModule', imageId),
|
|
232
|
+
sopInstanceUID = _metadataProvider$get.sopInstanceUID;
|
|
245
233
|
acc[sopInstanceUID] = imageId;
|
|
246
234
|
return acc;
|
|
247
235
|
}, {});
|
|
@@ -499,12 +487,10 @@ function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadata
|
|
|
499
487
|
if (!multiframe) {
|
|
500
488
|
return imageId;
|
|
501
489
|
}
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
ReferencedSeriesSequence
|
|
507
|
-
} = multiframe;
|
|
490
|
+
const FrameOfReferenceUID = multiframe.FrameOfReferenceUID,
|
|
491
|
+
PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
492
|
+
SourceImageSequence = multiframe.SourceImageSequence,
|
|
493
|
+
ReferencedSeriesSequence = multiframe.ReferencedSeriesSequence;
|
|
508
494
|
if (!PerFrameFunctionalGroupsSequence || PerFrameFunctionalGroupsSequence.length === 0) {
|
|
509
495
|
return imageId;
|
|
510
496
|
}
|
|
@@ -553,13 +539,11 @@ function findReferenceSourceImageId(multiframe, frameSegment, imageIds, metadata
|
|
|
553
539
|
*/
|
|
554
540
|
|
|
555
541
|
function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance, TypedArrayConstructor, sopUIDImageIdIndexMap) {
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
Columns
|
|
562
|
-
} = multiframe;
|
|
542
|
+
const SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
|
|
543
|
+
PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
544
|
+
SegmentSequence = multiframe.SegmentSequence,
|
|
545
|
+
Rows = multiframe.Rows,
|
|
546
|
+
Columns = multiframe.Columns;
|
|
563
547
|
let numberOfSegs = SegmentSequence.length;
|
|
564
548
|
if (numberOfSegs < 2) {
|
|
565
549
|
return false;
|
|
@@ -597,7 +581,9 @@ function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations
|
|
|
597
581
|
frameSegmentsMapping.set(imageIdIndex, [frameSegment]);
|
|
598
582
|
}
|
|
599
583
|
}
|
|
600
|
-
for (let
|
|
584
|
+
for (let _ref of frameSegmentsMapping.entries()) {
|
|
585
|
+
var _ref2 = _slicedToArray(_ref, 2);
|
|
586
|
+
let role = _ref2[1];
|
|
601
587
|
let temp2DArray = new TypedArrayConstructor(sliceLength).fill(0);
|
|
602
588
|
for (let i = 0; i < role.length; ++i) {
|
|
603
589
|
const frameSegment = role[i];
|
|
@@ -624,12 +610,10 @@ function checkSEGsOverlapping(pixelData, multiframe, imageIds, validOrientations
|
|
|
624
610
|
return false;
|
|
625
611
|
}
|
|
626
612
|
function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance, TypedArrayConstructor, segmentsPixelIndices, sopUIDImageIdIndexMap) {
|
|
627
|
-
const
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
Columns
|
|
632
|
-
} = multiframe;
|
|
613
|
+
const SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
|
|
614
|
+
PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
615
|
+
Rows = multiframe.Rows,
|
|
616
|
+
Columns = multiframe.Columns;
|
|
633
617
|
const sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
|
|
634
618
|
const sliceLength = Columns * Rows;
|
|
635
619
|
const arrayBufferLength = sliceLength * imageIds.length * TypedArrayConstructor.BYTES_PER_ELEMENT;
|
|
@@ -728,20 +712,16 @@ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray,
|
|
|
728
712
|
}
|
|
729
713
|
}
|
|
730
714
|
const getSegmentIndex = (multiframe, frame) => {
|
|
731
|
-
const
|
|
732
|
-
|
|
733
|
-
SharedFunctionalGroupsSequence
|
|
734
|
-
} = multiframe;
|
|
715
|
+
const PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
716
|
+
SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence;
|
|
735
717
|
const PerFrameFunctionalGroups = PerFrameFunctionalGroupsSequence[frame];
|
|
736
718
|
return PerFrameFunctionalGroups && PerFrameFunctionalGroups.SegmentIdentificationSequence ? PerFrameFunctionalGroups.SegmentIdentificationSequence.ReferencedSegmentNumber : SharedFunctionalGroupsSequence.SegmentIdentificationSequence ? SharedFunctionalGroupsSequence.SegmentIdentificationSequence.ReferencedSegmentNumber : undefined;
|
|
737
719
|
};
|
|
738
720
|
function insertPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray, labelmapBufferArray, pixelData, multiframe, imageIds, validOrientations, metadataProvider, tolerance, TypedArrayConstructor, segmentsPixelIndices, sopUIDImageIdIndexMap, imageIdMaps, eventTarget, triggerEvent) {
|
|
739
|
-
const
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
Columns
|
|
744
|
-
} = multiframe;
|
|
721
|
+
const SharedFunctionalGroupsSequence = multiframe.SharedFunctionalGroupsSequence,
|
|
722
|
+
PerFrameFunctionalGroupsSequence = multiframe.PerFrameFunctionalGroupsSequence,
|
|
723
|
+
Rows = multiframe.Rows,
|
|
724
|
+
Columns = multiframe.Columns;
|
|
745
725
|
const sharedImageOrientationPatient = SharedFunctionalGroupsSequence.PlaneOrientationSequence ? SharedFunctionalGroupsSequence.PlaneOrientationSequence.ImageOrientationPatient : undefined;
|
|
746
726
|
const sliceLength = Columns * Rows;
|
|
747
727
|
let i = 0;
|
|
@@ -901,10 +881,8 @@ function getUnpackedChunks(data, maxBytesPerChunk) {
|
|
|
901
881
|
* @return {String} The corresponding imageId.
|
|
902
882
|
*/
|
|
903
883
|
function getImageIdOfSourceImageBySourceImageSequence(SourceImageSequence, sopUIDImageIdIndexMap) {
|
|
904
|
-
const
|
|
905
|
-
|
|
906
|
-
ReferencedFrameNumber
|
|
907
|
-
} = SourceImageSequence;
|
|
884
|
+
const ReferencedSOPInstanceUID = SourceImageSequence.ReferencedSOPInstanceUID,
|
|
885
|
+
ReferencedFrameNumber = SourceImageSequence.ReferencedFrameNumber;
|
|
908
886
|
const baseImageId = sopUIDImageIdIndexMap[ReferencedSOPInstanceUID];
|
|
909
887
|
if (!baseImageId) {
|
|
910
888
|
console.warn("No imageId found for SOPInstanceUID: ".concat(ReferencedSOPInstanceUID));
|
|
@@ -970,8 +948,8 @@ function getImageIdOfSourceImagebyGeometry(ReferencedSeriesInstanceUID, FrameOfR
|
|
|
970
948
|
|
|
971
949
|
// For multiframe images, check each frame's position
|
|
972
950
|
if (isMultiframe) {
|
|
973
|
-
var _metadataProvider$
|
|
974
|
-
const framePosition = (_metadataProvider$
|
|
951
|
+
var _metadataProvider$get2;
|
|
952
|
+
const framePosition = (_metadataProvider$get2 = metadataProvider.get('imagePlaneModule', imageId)) === null || _metadataProvider$get2 === void 0 ? void 0 : _metadataProvider$get2.imagePositionPatient;
|
|
975
953
|
if (framePosition && utilities$1.isEqual(segFramePosition, framePosition, tolerance)) {
|
|
976
954
|
return imageId;
|
|
977
955
|
}
|
|
@@ -1134,7 +1112,10 @@ function calculateCentroid(imageIdIndexBufferIndex, multiframe, metadataProvider
|
|
|
1134
1112
|
let worldYAcc = 0;
|
|
1135
1113
|
let worldZAcc = 0;
|
|
1136
1114
|
let count = 0;
|
|
1137
|
-
for (const
|
|
1115
|
+
for (const _ref3 of Object.entries(imageIdIndexBufferIndex)) {
|
|
1116
|
+
var _ref4 = _slicedToArray(_ref3, 2);
|
|
1117
|
+
const imageIdIndex = _ref4[0];
|
|
1118
|
+
const bufferIndices = _ref4[1];
|
|
1138
1119
|
const z = Number(imageIdIndex);
|
|
1139
1120
|
if (!bufferIndices || bufferIndices.length === 0) {
|
|
1140
1121
|
continue;
|
|
@@ -1147,13 +1128,11 @@ function calculateCentroid(imageIdIndexBufferIndex, multiframe, metadataProvider
|
|
|
1147
1128
|
console.debug('Missing imagePlaneModule metadata for centroid calculation');
|
|
1148
1129
|
continue;
|
|
1149
1130
|
}
|
|
1150
|
-
const
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
columnPixelSpacing
|
|
1156
|
-
} = imagePlaneModule;
|
|
1131
|
+
const imagePositionPatient = imagePlaneModule.imagePositionPatient,
|
|
1132
|
+
rowCosines = imagePlaneModule.rowCosines,
|
|
1133
|
+
columnCosines = imagePlaneModule.columnCosines,
|
|
1134
|
+
rowPixelSpacing = imagePlaneModule.rowPixelSpacing,
|
|
1135
|
+
columnPixelSpacing = imagePlaneModule.columnPixelSpacing;
|
|
1157
1136
|
for (const bufferIndex of bufferIndices) {
|
|
1158
1137
|
const y = Math.floor(bufferIndex / multiframe.Rows);
|
|
1159
1138
|
const x = bufferIndex % multiframe.Rows;
|