@cornerstonejs/adapters 3.0.0-beta.5 → 3.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/adapters/Cornerstone/Angle.js +61 -74
- package/dist/esm/adapters/Cornerstone/ArrowAnnotate.js +76 -76
- package/dist/esm/adapters/Cornerstone/Bidirectional.js +130 -146
- package/dist/esm/adapters/Cornerstone/CircleRoi.js +96 -95
- package/dist/esm/adapters/Cornerstone/CobbAngle.js +66 -79
- package/dist/esm/adapters/Cornerstone/EllipticalRoi.js +152 -152
- package/dist/esm/adapters/Cornerstone/FreehandRoi.js +68 -69
- package/dist/esm/adapters/Cornerstone/Length.js +54 -63
- package/dist/esm/adapters/Cornerstone/MeasurementReport.js +221 -224
- package/dist/esm/adapters/Cornerstone/ParametricMap.js +88 -110
- package/dist/esm/adapters/Cornerstone/RectangleRoi.js +72 -78
- package/dist/esm/adapters/Cornerstone/Segmentation.js +7 -7
- package/dist/esm/adapters/Cornerstone/Segmentation_3X.js +113 -104
- package/dist/esm/adapters/Cornerstone/Segmentation_4X.js +434 -462
- package/dist/esm/adapters/Cornerstone/index.js +14 -14
- package/dist/esm/adapters/Cornerstone3D/Angle.d.ts +2 -5
- package/dist/esm/adapters/Cornerstone3D/Angle.js +89 -100
- package/dist/esm/adapters/Cornerstone3D/ArrowAnnotate.d.ts +5 -11
- package/dist/esm/adapters/Cornerstone3D/ArrowAnnotate.js +106 -118
- package/dist/esm/adapters/Cornerstone3D/BaseAdapter3D.d.ts +43 -0
- package/dist/esm/adapters/Cornerstone3D/BaseAdapter3D.js +92 -0
- package/dist/esm/adapters/Cornerstone3D/Bidirectional.d.ts +2 -5
- package/dist/esm/adapters/Cornerstone3D/Bidirectional.js +118 -133
- package/dist/esm/adapters/Cornerstone3D/CircleROI.d.ts +2 -7
- package/dist/esm/adapters/Cornerstone3D/CircleROI.js +85 -85
- package/dist/esm/adapters/Cornerstone3D/CobbAngle.d.ts +2 -5
- package/dist/esm/adapters/Cornerstone3D/CobbAngle.js +93 -104
- package/dist/esm/adapters/Cornerstone3D/CodingScheme.js +5 -5
- package/dist/esm/adapters/Cornerstone3D/EllipticalROI.d.ts +2 -7
- package/dist/esm/adapters/Cornerstone3D/EllipticalROI.js +148 -149
- package/dist/esm/adapters/Cornerstone3D/KeyImage.d.ts +24 -0
- package/dist/esm/adapters/Cornerstone3D/KeyImage.js +49 -0
- package/dist/esm/adapters/Cornerstone3D/Length.d.ts +2 -10
- package/dist/esm/adapters/Cornerstone3D/Length.js +83 -93
- package/dist/esm/adapters/Cornerstone3D/MeasurementReport.d.ts +23 -4
- package/dist/esm/adapters/Cornerstone3D/MeasurementReport.js +259 -240
- package/dist/esm/adapters/Cornerstone3D/ParametricMap/generateToolState.js +8 -4
- package/dist/esm/adapters/Cornerstone3D/PlanarFreehandROI.d.ts +3 -5
- package/dist/esm/adapters/Cornerstone3D/PlanarFreehandROI.js +99 -115
- package/dist/esm/adapters/Cornerstone3D/Probe.d.ts +4 -17
- package/dist/esm/adapters/Cornerstone3D/Probe.js +38 -79
- package/dist/esm/adapters/Cornerstone3D/RTStruct/RTSS.js +60 -52
- package/dist/esm/adapters/Cornerstone3D/RTStruct/index.js +3 -1
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getPatientModule.js +5 -5
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getReferencedFrameOfReferenceSequence.js +14 -10
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getReferencedSeriesSequence.js +17 -11
- package/dist/esm/adapters/Cornerstone3D/RTStruct/utilities/getStructureSetModule.js +3 -1
- package/dist/esm/adapters/Cornerstone3D/RectangleROI.d.ts +2 -5
- package/dist/esm/adapters/Cornerstone3D/RectangleROI.js +73 -85
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateLabelMaps2DFrom3D.js +15 -13
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateSegmentation.js +15 -9
- package/dist/esm/adapters/Cornerstone3D/Segmentation/generateToolState.js +10 -10
- package/dist/esm/adapters/Cornerstone3D/Segmentation/labelmapImagesFromBuffer.js +134 -151
- package/dist/esm/adapters/Cornerstone3D/UltrasoundDirectional.d.ts +2 -5
- package/dist/esm/adapters/Cornerstone3D/UltrasoundDirectional.js +68 -84
- package/dist/esm/adapters/Cornerstone3D/index.d.ts +4 -0
- package/dist/esm/adapters/Cornerstone3D/index.js +21 -17
- package/dist/esm/adapters/VTKjs/Segmentation.js +66 -72
- package/dist/esm/adapters/VTKjs/index.js +2 -2
- package/dist/esm/adapters/helpers/checkIfPerpendicular.js +2 -2
- package/dist/esm/adapters/helpers/checkOrientation.js +8 -8
- package/dist/esm/adapters/helpers/codeMeaningEquals.js +2 -2
- package/dist/esm/adapters/helpers/compareArrays.js +4 -2
- package/dist/esm/adapters/helpers/downloadDICOMData.js +6 -4
- package/dist/esm/adapters/helpers/getDatasetsFromImages.js +20 -18
- package/dist/esm/adapters/helpers/graphicTypeEquals.js +2 -2
- package/dist/esm/adapters/helpers/toArray.js +1 -3
- package/dist/esm/adapters/index.d.ts +2 -0
- package/dist/esm/adapters/index.js +6 -5
- package/dist/esm/node_modules/@babel/runtime/helpers/esm/defineProperty.js +18 -0
- package/dist/esm/node_modules/@babel/runtime/helpers/esm/toPrimitive.js +14 -0
- package/dist/esm/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js +9 -0
- package/dist/esm/node_modules/@babel/runtime/helpers/esm/typeof.js +11 -0
- package/package.json +4 -4
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +0 -493
- package/dist/esm/adapters/Cornerstone3D/isValidCornerstoneTrackingIdentifier.js +0 -18
|
@@ -1,274 +1,271 @@
|
|
|
1
|
-
import { createClass as _createClass, classCallCheck as _classCallCheck } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
1
|
import { utilities, derivations, normalizers, data } from 'dcmjs';
|
|
3
2
|
import { toArray } from '../helpers/toArray.js';
|
|
4
3
|
import { codeMeaningEquals } from '../helpers/codeMeaningEquals.js';
|
|
5
|
-
import '
|
|
4
|
+
import 'buffer';
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
const {
|
|
7
|
+
TID1500,
|
|
8
|
+
addAccessors
|
|
9
|
+
} = utilities;
|
|
10
|
+
const {
|
|
11
|
+
StructuredReport
|
|
12
|
+
} = derivations;
|
|
13
|
+
const {
|
|
14
|
+
Normalizer
|
|
15
|
+
} = normalizers;
|
|
16
|
+
const {
|
|
17
|
+
TID1500MeasurementReport,
|
|
18
|
+
TID1501MeasurementGroup
|
|
19
|
+
} = TID1500;
|
|
20
|
+
const {
|
|
21
|
+
DicomMetaDictionary
|
|
22
|
+
} = data;
|
|
23
|
+
const FINDING = {
|
|
15
24
|
CodingSchemeDesignator: "DCM",
|
|
16
25
|
CodeValue: "121071"
|
|
17
26
|
};
|
|
18
|
-
|
|
27
|
+
const FINDING_SITE = {
|
|
19
28
|
CodingSchemeDesignator: "SCT",
|
|
20
29
|
CodeValue: "363698007"
|
|
21
30
|
};
|
|
22
|
-
|
|
31
|
+
const FINDING_SITE_OLD = {
|
|
23
32
|
CodingSchemeDesignator: "SRT",
|
|
24
33
|
CodeValue: "G-C0E3"
|
|
25
34
|
};
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
const codeValueMatch = (group, code, oldCode) => {
|
|
36
|
+
const {
|
|
37
|
+
ConceptNameCodeSequence
|
|
38
|
+
} = group;
|
|
28
39
|
if (!ConceptNameCodeSequence) {
|
|
29
40
|
return;
|
|
30
41
|
}
|
|
31
|
-
|
|
32
|
-
|
|
42
|
+
const {
|
|
43
|
+
CodingSchemeDesignator,
|
|
44
|
+
CodeValue
|
|
45
|
+
} = ConceptNameCodeSequence;
|
|
33
46
|
return CodingSchemeDesignator == code.CodingSchemeDesignator && CodeValue == code.CodeValue || oldCode && CodingSchemeDesignator == oldCode.CodingSchemeDesignator && CodeValue == oldCode.CodeValue;
|
|
34
47
|
};
|
|
35
|
-
function getTID300ContentItem(tool,
|
|
36
|
-
|
|
48
|
+
function getTID300ContentItem(tool, ReferencedSOPSequence, adapterClass) {
|
|
49
|
+
const args = adapterClass.getTID300RepresentationArguments(tool);
|
|
37
50
|
args.ReferencedSOPSequence = ReferencedSOPSequence;
|
|
38
|
-
|
|
51
|
+
const TID300Measurement = new adapterClass.TID300Representation(args);
|
|
39
52
|
return TID300Measurement;
|
|
40
53
|
}
|
|
41
54
|
function getMeasurementGroup(toolType, toolData, ReferencedSOPSequence) {
|
|
42
|
-
|
|
43
|
-
|
|
55
|
+
const toolTypeData = toolData[toolType];
|
|
56
|
+
const toolClass = MeasurementReport.CORNERSTONE_TOOL_CLASSES_BY_TOOL_TYPE[toolType];
|
|
44
57
|
if (!toolTypeData || !toolTypeData.data || !toolTypeData.data.length || !toolClass) {
|
|
45
58
|
return;
|
|
46
59
|
}
|
|
47
60
|
|
|
48
61
|
// Loop through the array of tool instances
|
|
49
62
|
// for this tool
|
|
50
|
-
|
|
51
|
-
return getTID300ContentItem(tool,
|
|
63
|
+
const Measurements = toolTypeData.data.map(tool => {
|
|
64
|
+
return getTID300ContentItem(tool, ReferencedSOPSequence, toolClass);
|
|
52
65
|
});
|
|
53
66
|
return new TID1501MeasurementGroup(Measurements);
|
|
54
67
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
class MeasurementReport {
|
|
69
|
+
static getSetupMeasurementData(MeasurementGroup) {
|
|
70
|
+
const {
|
|
71
|
+
ContentSequence
|
|
72
|
+
} = MeasurementGroup;
|
|
73
|
+
const contentSequenceArr = toArray(ContentSequence);
|
|
74
|
+
const findingGroup = contentSequenceArr.find(group => codeValueMatch(group, FINDING));
|
|
75
|
+
const findingSiteGroups = contentSequenceArr.filter(group => codeValueMatch(group, FINDING_SITE, FINDING_SITE_OLD)) || [];
|
|
76
|
+
const NUMGroup = contentSequenceArr.find(group => group.ValueType === "NUM");
|
|
77
|
+
const SCOORDGroup = toArray(NUMGroup.ContentSequence).find(group => group.ValueType === "SCOORD");
|
|
78
|
+
const {
|
|
79
|
+
ReferencedSOPSequence
|
|
80
|
+
} = SCOORDGroup.ContentSequence;
|
|
81
|
+
const {
|
|
82
|
+
ReferencedSOPInstanceUID,
|
|
83
|
+
ReferencedFrameNumber
|
|
84
|
+
} = ReferencedSOPSequence;
|
|
85
|
+
const defaultState = {
|
|
86
|
+
sopInstanceUid: ReferencedSOPInstanceUID,
|
|
87
|
+
frameIndex: ReferencedFrameNumber || 1,
|
|
88
|
+
complete: true,
|
|
89
|
+
finding: findingGroup ? addAccessors(findingGroup.ConceptCodeSequence) : undefined,
|
|
90
|
+
findingSites: findingSiteGroups.map(fsg => {
|
|
91
|
+
return addAccessors(fsg.ConceptCodeSequence);
|
|
92
|
+
})
|
|
93
|
+
};
|
|
94
|
+
if (defaultState.finding) {
|
|
95
|
+
defaultState.description = defaultState.finding.CodeMeaning;
|
|
96
|
+
}
|
|
97
|
+
const findingSite = defaultState.findingSites && defaultState.findingSites[0];
|
|
98
|
+
if (findingSite) {
|
|
99
|
+
defaultState.location = findingSite[0] && findingSite[0].CodeMeaning || findingSite.CodeMeaning;
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
defaultState,
|
|
103
|
+
findingGroup,
|
|
104
|
+
findingSiteGroups,
|
|
105
|
+
NUMGroup,
|
|
106
|
+
SCOORDGroup,
|
|
107
|
+
ReferencedSOPSequence,
|
|
108
|
+
ReferencedSOPInstanceUID,
|
|
109
|
+
ReferencedFrameNumber
|
|
110
|
+
};
|
|
58
111
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
var findingSiteGroups = contentSequenceArr.filter(function (group) {
|
|
68
|
-
return codeValueMatch(group, FINDING_SITE, FINDING_SITE_OLD);
|
|
69
|
-
}) || [];
|
|
70
|
-
var NUMGroup = contentSequenceArr.find(function (group) {
|
|
71
|
-
return group.ValueType === "NUM";
|
|
72
|
-
});
|
|
73
|
-
var SCOORDGroup = toArray(NUMGroup.ContentSequence).find(function (group) {
|
|
74
|
-
return group.ValueType === "SCOORD";
|
|
75
|
-
});
|
|
76
|
-
var ReferencedSOPSequence = SCOORDGroup.ContentSequence.ReferencedSOPSequence;
|
|
77
|
-
var ReferencedSOPInstanceUID = ReferencedSOPSequence.ReferencedSOPInstanceUID,
|
|
78
|
-
ReferencedFrameNumber = ReferencedSOPSequence.ReferencedFrameNumber;
|
|
79
|
-
var defaultState = {
|
|
80
|
-
sopInstanceUid: ReferencedSOPInstanceUID,
|
|
81
|
-
frameIndex: ReferencedFrameNumber || 1,
|
|
82
|
-
complete: true,
|
|
83
|
-
finding: findingGroup ? addAccessors(findingGroup.ConceptCodeSequence) : undefined,
|
|
84
|
-
findingSites: findingSiteGroups.map(function (fsg) {
|
|
85
|
-
return addAccessors(fsg.ConceptCodeSequence);
|
|
86
|
-
})
|
|
87
|
-
};
|
|
88
|
-
if (defaultState.finding) {
|
|
89
|
-
defaultState.description = defaultState.finding.CodeMeaning;
|
|
90
|
-
}
|
|
91
|
-
var findingSite = defaultState.findingSites && defaultState.findingSites[0];
|
|
92
|
-
if (findingSite) {
|
|
93
|
-
defaultState.location = findingSite[0] && findingSite[0].CodeMeaning || findingSite.CodeMeaning;
|
|
94
|
-
}
|
|
95
|
-
return {
|
|
96
|
-
defaultState: defaultState,
|
|
97
|
-
findingGroup: findingGroup,
|
|
98
|
-
findingSiteGroups: findingSiteGroups,
|
|
99
|
-
NUMGroup: NUMGroup,
|
|
100
|
-
SCOORDGroup: SCOORDGroup,
|
|
101
|
-
ReferencedSOPSequence: ReferencedSOPSequence,
|
|
102
|
-
ReferencedSOPInstanceUID: ReferencedSOPInstanceUID,
|
|
103
|
-
ReferencedFrameNumber: ReferencedFrameNumber
|
|
104
|
-
};
|
|
112
|
+
static generateReport(toolState, metadataProvider, options) {
|
|
113
|
+
// ToolState for array of imageIDs to a Report
|
|
114
|
+
// Assume Cornerstone metadata provider has access to Study / Series / Sop Instance UID
|
|
115
|
+
|
|
116
|
+
let allMeasurementGroups = [];
|
|
117
|
+
const firstImageId = Object.keys(toolState)[0];
|
|
118
|
+
if (!firstImageId) {
|
|
119
|
+
throw new Error("No measurements provided.");
|
|
105
120
|
}
|
|
106
|
-
}, {
|
|
107
|
-
key: "generateReport",
|
|
108
|
-
value: function generateReport(toolState, metadataProvider, options) {
|
|
109
|
-
// ToolState for array of imageIDs to a Report
|
|
110
|
-
// Assume Cornerstone metadata provider has access to Study / Series / Sop Instance UID
|
|
111
121
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
/* Patient ID
|
|
123
|
+
Warning - Missing attribute or value that would be needed to build DICOMDIR - Patient ID
|
|
124
|
+
Warning - Missing attribute or value that would be needed to build DICOMDIR - Study Date
|
|
125
|
+
Warning - Missing attribute or value that would be needed to build DICOMDIR - Study Time
|
|
126
|
+
Warning - Missing attribute or value that would be needed to build DICOMDIR - Study ID
|
|
127
|
+
*/
|
|
128
|
+
const generalSeriesModule = metadataProvider.get("generalSeriesModule", firstImageId);
|
|
117
129
|
|
|
118
|
-
|
|
119
|
-
Warning - Missing attribute or value that would be needed to build DICOMDIR - Patient ID
|
|
120
|
-
Warning - Missing attribute or value that would be needed to build DICOMDIR - Study Date
|
|
121
|
-
Warning - Missing attribute or value that would be needed to build DICOMDIR - Study Time
|
|
122
|
-
Warning - Missing attribute or value that would be needed to build DICOMDIR - Study ID
|
|
123
|
-
*/
|
|
124
|
-
var generalSeriesModule = metadataProvider.get("generalSeriesModule", firstImageId);
|
|
130
|
+
//const sopCommonModule = metadataProvider.get('sopCommonModule', firstImageId);
|
|
125
131
|
|
|
126
|
-
|
|
132
|
+
// NOTE: We are getting the Series and Study UIDs from the first imageId of the toolState
|
|
133
|
+
// which means that if the toolState is for multiple series, the report will have the incorrect
|
|
134
|
+
// SeriesInstanceUIDs
|
|
135
|
+
const {
|
|
136
|
+
studyInstanceUID,
|
|
137
|
+
seriesInstanceUID
|
|
138
|
+
} = generalSeriesModule;
|
|
127
139
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
140
|
+
// Loop through each image in the toolData
|
|
141
|
+
Object.keys(toolState).forEach(imageId => {
|
|
142
|
+
const sopCommonModule = metadataProvider.get("sopCommonModule", imageId);
|
|
143
|
+
const frameNumber = metadataProvider.get("frameNumber", imageId);
|
|
144
|
+
const toolData = toolState[imageId];
|
|
145
|
+
const toolTypes = Object.keys(toolData);
|
|
146
|
+
const ReferencedSOPSequence = {
|
|
147
|
+
ReferencedSOPClassUID: sopCommonModule.sopClassUID,
|
|
148
|
+
ReferencedSOPInstanceUID: sopCommonModule.sopInstanceUID
|
|
149
|
+
};
|
|
150
|
+
if (Normalizer.isMultiframeSOPClassUID(sopCommonModule.sopClassUID)) {
|
|
151
|
+
ReferencedSOPSequence.ReferencedFrameNumber = frameNumber;
|
|
152
|
+
}
|
|
133
153
|
|
|
134
|
-
// Loop through each
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
var ReferencedSOPSequence = {
|
|
141
|
-
ReferencedSOPClassUID: sopCommonModule.sopClassUID,
|
|
142
|
-
ReferencedSOPInstanceUID: sopCommonModule.sopInstanceUID
|
|
143
|
-
};
|
|
144
|
-
if (Normalizer.isMultiframeSOPClassUID(sopCommonModule.sopClassUID)) {
|
|
145
|
-
ReferencedSOPSequence.ReferencedFrameNumber = frameNumber;
|
|
154
|
+
// Loop through each tool type for the image
|
|
155
|
+
const measurementGroups = [];
|
|
156
|
+
toolTypes.forEach(toolType => {
|
|
157
|
+
const group = getMeasurementGroup(toolType, toolData, ReferencedSOPSequence);
|
|
158
|
+
if (group) {
|
|
159
|
+
measurementGroups.push(group);
|
|
146
160
|
}
|
|
147
|
-
|
|
148
|
-
// Loop through each tool type for the image
|
|
149
|
-
var measurementGroups = [];
|
|
150
|
-
toolTypes.forEach(function (toolType) {
|
|
151
|
-
var group = getMeasurementGroup(toolType, toolData, ReferencedSOPSequence);
|
|
152
|
-
if (group) {
|
|
153
|
-
measurementGroups.push(group);
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
allMeasurementGroups = allMeasurementGroups.concat(measurementGroups);
|
|
157
161
|
});
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
162
|
+
allMeasurementGroups = allMeasurementGroups.concat(measurementGroups);
|
|
163
|
+
});
|
|
164
|
+
const MeasurementReport = new TID1500MeasurementReport({
|
|
165
|
+
TID1501MeasurementGroups: allMeasurementGroups
|
|
166
|
+
}, options);
|
|
161
167
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
168
|
+
// TODO: what is the correct metaheader
|
|
169
|
+
// http://dicom.nema.org/medical/Dicom/current/output/chtml/part10/chapter_7.html
|
|
170
|
+
// TODO: move meta creation to happen in derivations.js
|
|
171
|
+
const fileMetaInformationVersionArray = new Uint8Array(2);
|
|
172
|
+
fileMetaInformationVersionArray[1] = 1;
|
|
173
|
+
const derivationSourceDataset = {
|
|
174
|
+
StudyInstanceUID: studyInstanceUID,
|
|
175
|
+
SeriesInstanceUID: seriesInstanceUID
|
|
176
|
+
//SOPInstanceUID: sopInstanceUID, // TODO: Necessary?
|
|
177
|
+
//SOPClassUID: sopClassUID,
|
|
178
|
+
};
|
|
179
|
+
const _meta = {
|
|
180
|
+
FileMetaInformationVersion: {
|
|
181
|
+
Value: [fileMetaInformationVersionArray.buffer],
|
|
182
|
+
vr: "OB"
|
|
183
|
+
},
|
|
184
|
+
//MediaStorageSOPClassUID
|
|
185
|
+
//MediaStorageSOPInstanceUID: sopCommonModule.sopInstanceUID,
|
|
186
|
+
TransferSyntaxUID: {
|
|
187
|
+
Value: ["1.2.840.10008.1.2.1"],
|
|
188
|
+
vr: "UI"
|
|
189
|
+
},
|
|
190
|
+
ImplementationClassUID: {
|
|
191
|
+
Value: [DicomMetaDictionary.uid()],
|
|
192
|
+
// TODO: could be git hash or other valid id
|
|
193
|
+
vr: "UI"
|
|
194
|
+
},
|
|
195
|
+
ImplementationVersionName: {
|
|
196
|
+
Value: ["dcmjs"],
|
|
197
|
+
vr: "SH"
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
const _vrMap = {
|
|
201
|
+
PixelData: "OW"
|
|
202
|
+
};
|
|
203
|
+
derivationSourceDataset._meta = _meta;
|
|
204
|
+
derivationSourceDataset._vrMap = _vrMap;
|
|
205
|
+
const report = new StructuredReport([derivationSourceDataset]);
|
|
206
|
+
const contentItem = MeasurementReport.contentItem(derivationSourceDataset);
|
|
201
207
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
+
// Merge the derived dataset with the content from the Measurement Report
|
|
209
|
+
report.dataset = Object.assign(report.dataset, contentItem);
|
|
210
|
+
report.dataset._meta = _meta;
|
|
211
|
+
report.dataset.SpecificCharacterSet = "ISO_IR 192";
|
|
212
|
+
return report;
|
|
213
|
+
}
|
|
208
214
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
var GROUP = "Measurement Group";
|
|
226
|
-
var TRACKING_IDENTIFIER = "Tracking Identifier";
|
|
215
|
+
/**
|
|
216
|
+
* Generate Cornerstone tool state from dataset
|
|
217
|
+
* @param {object} dataset dataset
|
|
218
|
+
* @param {object} hooks
|
|
219
|
+
* @param {function} hooks.getToolClass Function to map dataset to a tool class
|
|
220
|
+
* @returns
|
|
221
|
+
*/
|
|
222
|
+
static generateToolState(dataset) {
|
|
223
|
+
let hooks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
224
|
+
// For now, bail out if the dataset is not a TID1500 SR with length measurements
|
|
225
|
+
if (dataset.ContentTemplateSequence.TemplateIdentifier !== "1500") {
|
|
226
|
+
throw new Error("This package can currently only interpret DICOM SR TID 1500");
|
|
227
|
+
}
|
|
228
|
+
const REPORT = "Imaging Measurements";
|
|
229
|
+
const GROUP = "Measurement Group";
|
|
230
|
+
const TRACKING_IDENTIFIER = "Tracking Identifier";
|
|
227
231
|
|
|
228
|
-
|
|
229
|
-
|
|
232
|
+
// Identify the Imaging Measurements
|
|
233
|
+
const imagingMeasurementContent = toArray(dataset.ContentSequence).find(codeMeaningEquals(REPORT));
|
|
230
234
|
|
|
231
|
-
|
|
232
|
-
|
|
235
|
+
// Retrieve the Measurements themselves
|
|
236
|
+
const measurementGroups = toArray(imagingMeasurementContent.ContentSequence).filter(codeMeaningEquals(GROUP));
|
|
233
237
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
console.log(measurement);
|
|
255
|
-
measurementData[toolClass.toolType].push(measurement);
|
|
256
|
-
}
|
|
257
|
-
});
|
|
238
|
+
// For each of the supported measurement types, compute the measurement data
|
|
239
|
+
const measurementData = {};
|
|
240
|
+
const cornerstoneToolClasses = MeasurementReport.CORNERSTONE_TOOL_CLASSES_BY_UTILITY_TYPE;
|
|
241
|
+
const registeredToolClasses = [];
|
|
242
|
+
Object.keys(cornerstoneToolClasses).forEach(key => {
|
|
243
|
+
registeredToolClasses.push(cornerstoneToolClasses[key]);
|
|
244
|
+
measurementData[key] = [];
|
|
245
|
+
});
|
|
246
|
+
measurementGroups.forEach(measurementGroup => {
|
|
247
|
+
const measurementGroupContentSequence = toArray(measurementGroup.ContentSequence);
|
|
248
|
+
const TrackingIdentifierGroup = measurementGroupContentSequence.find(contentItem => contentItem.ConceptNameCodeSequence.CodeMeaning === TRACKING_IDENTIFIER);
|
|
249
|
+
const TrackingIdentifierValue = TrackingIdentifierGroup.TextValue;
|
|
250
|
+
const toolClass = hooks.getToolClass ? hooks.getToolClass(measurementGroup, dataset, registeredToolClasses) : registeredToolClasses.find(tc => tc.isValidCornerstoneTrackingIdentifier(TrackingIdentifierValue));
|
|
251
|
+
if (toolClass) {
|
|
252
|
+
const measurement = toolClass.getMeasurementData(measurementGroup);
|
|
253
|
+
console.log("=== ".concat(toolClass.toolType, " ==="));
|
|
254
|
+
console.log(measurement);
|
|
255
|
+
measurementData[toolClass.toolType].push(measurement);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
258
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
}]);
|
|
271
|
-
}();
|
|
259
|
+
// NOTE: There is no way of knowing the cornerstone imageIds as that could be anything.
|
|
260
|
+
// That is up to the consumer to derive from the SOPInstanceUIDs.
|
|
261
|
+
return measurementData;
|
|
262
|
+
}
|
|
263
|
+
static registerTool(toolClass) {
|
|
264
|
+
MeasurementReport.CORNERSTONE_TOOL_CLASSES_BY_UTILITY_TYPE[toolClass.utilityToolType] = toolClass;
|
|
265
|
+
MeasurementReport.CORNERSTONE_TOOL_CLASSES_BY_TOOL_TYPE[toolClass.toolType] = toolClass;
|
|
266
|
+
MeasurementReport.MEASUREMENT_BY_TOOLTYPE[toolClass.toolType] = toolClass.utilityToolType;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
272
269
|
MeasurementReport.MEASUREMENT_BY_TOOLTYPE = {};
|
|
273
270
|
MeasurementReport.CORNERSTONE_TOOL_CLASSES_BY_UTILITY_TYPE = {};
|
|
274
271
|
MeasurementReport.CORNERSTONE_TOOL_CLASSES_BY_TOOL_TYPE = {};
|