@cornerstonejs/adapters 4.15.16 → 4.15.18
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/Cornerstone3D/ArrowAnnotate.js +2 -2
- package/dist/esm/adapters/Cornerstone3D/Bidirectional.d.ts +1 -0
- package/dist/esm/adapters/Cornerstone3D/Bidirectional.js +6 -2
- package/dist/esm/adapters/Cornerstone3D/CircleROI.d.ts +7 -0
- package/dist/esm/adapters/Cornerstone3D/CircleROI.js +21 -2
- package/dist/esm/adapters/Cornerstone3D/EllipticalROI.d.ts +6 -0
- package/dist/esm/adapters/Cornerstone3D/EllipticalROI.js +19 -2
- package/dist/esm/adapters/Cornerstone3D/LabelData.js +23 -19
- package/dist/esm/adapters/Cornerstone3D/Length.js +2 -1
- package/dist/esm/adapters/Cornerstone3D/MeasurementReport.d.ts +3 -0
- package/dist/esm/adapters/Cornerstone3D/PlanarFreehandROI.js +9 -3
- package/dist/esm/adapters/Cornerstone3D/RectangleROI.d.ts +5 -0
- package/dist/esm/adapters/Cornerstone3D/RectangleROI.js +17 -2
- package/dist/esm/adapters/Cornerstone3D/metricHandler.d.ts +13 -0
- package/dist/esm/adapters/Cornerstone3D/metricHandler.js +74 -0
- package/dist/esm/version.d.ts +1 -1
- package/package.json +5 -5
|
@@ -6,7 +6,7 @@ import { toScoord } from '../helpers/toScoordType.js';
|
|
|
6
6
|
|
|
7
7
|
var _ArrowAnnotate;
|
|
8
8
|
const {
|
|
9
|
-
|
|
9
|
+
ArrowAnnotate: TID300ArrowAnnotate
|
|
10
10
|
} = utilities.TID300;
|
|
11
11
|
const {
|
|
12
12
|
imageToWorldCoords
|
|
@@ -89,7 +89,7 @@ class ArrowAnnotate extends BaseAdapter3D {
|
|
|
89
89
|
}
|
|
90
90
|
_ArrowAnnotate = ArrowAnnotate;
|
|
91
91
|
(() => {
|
|
92
|
-
_ArrowAnnotate.init("ArrowAnnotate",
|
|
92
|
+
_ArrowAnnotate.init("ArrowAnnotate", TID300ArrowAnnotate);
|
|
93
93
|
_ArrowAnnotate.registerLegacy();
|
|
94
94
|
})();
|
|
95
95
|
|
|
@@ -41,7 +41,9 @@ class Bidirectional extends BaseAdapter3D {
|
|
|
41
41
|
state.annotation.data.cachedStats = {
|
|
42
42
|
[`imageId:${referencedImageId}`]: {
|
|
43
43
|
length: longAxisNUMGroup.MeasuredValueSequence.NumericValue,
|
|
44
|
-
width: shortAxisNUMGroup.MeasuredValueSequence.NumericValue
|
|
44
|
+
width: shortAxisNUMGroup.MeasuredValueSequence.NumericValue,
|
|
45
|
+
unit: longAxisNUMGroup.MeasuredValueSequence.MeasurementUnitsCodeSequence.CodeValue,
|
|
46
|
+
widthUnit: shortAxisNUMGroup.MeasuredValueSequence.MeasurementUnitsCodeSequence.CodeValue
|
|
45
47
|
}
|
|
46
48
|
};
|
|
47
49
|
}
|
|
@@ -88,7 +90,8 @@ class Bidirectional extends BaseAdapter3D {
|
|
|
88
90
|
const shortAxisEndImage = toScoord(scoordProps, longAxisPoints[1]);
|
|
89
91
|
const {
|
|
90
92
|
length,
|
|
91
|
-
width
|
|
93
|
+
width,
|
|
94
|
+
unit
|
|
92
95
|
} = cachedStats[`imageId:${referencedImageId}`] || {};
|
|
93
96
|
return {
|
|
94
97
|
longAxis: {
|
|
@@ -101,6 +104,7 @@ class Bidirectional extends BaseAdapter3D {
|
|
|
101
104
|
},
|
|
102
105
|
longAxisLength: length,
|
|
103
106
|
shortAxisLength: width,
|
|
107
|
+
unit,
|
|
104
108
|
trackingIdentifierTextValue: this.trackingIdentifierTextValue,
|
|
105
109
|
finding: finding,
|
|
106
110
|
findingSites: findingSites || [],
|
|
@@ -11,8 +11,15 @@ declare class CircleROI extends BaseAdapter3D {
|
|
|
11
11
|
};
|
|
12
12
|
static getTID300RepresentationArguments(tool: any, is3DMeasurement?: boolean): {
|
|
13
13
|
area: any;
|
|
14
|
+
areaUnit: any;
|
|
14
15
|
perimeter: number;
|
|
16
|
+
modalityUnit: any;
|
|
17
|
+
radiusUnit: any;
|
|
15
18
|
radius: any;
|
|
19
|
+
max: any;
|
|
20
|
+
min: any;
|
|
21
|
+
stdDev: any;
|
|
22
|
+
mean: any;
|
|
16
23
|
points: ({
|
|
17
24
|
x: any;
|
|
18
25
|
y: any;
|
|
@@ -3,6 +3,7 @@ import MeasurementReport from './MeasurementReport.js';
|
|
|
3
3
|
import BaseAdapter3D from './BaseAdapter3D.js';
|
|
4
4
|
import { toScoord } from '../helpers/toScoordType.js';
|
|
5
5
|
import '@cornerstonejs/core';
|
|
6
|
+
import { extractAllNUMGroups, restoreAdditionalMetrics } from './metricHandler.js';
|
|
6
7
|
|
|
7
8
|
var _CircleROI;
|
|
8
9
|
const {
|
|
@@ -17,6 +18,9 @@ class CircleROI extends BaseAdapter3D {
|
|
|
17
18
|
referencedImageId,
|
|
18
19
|
ReferencedFrameNumber
|
|
19
20
|
} = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, this.toolType);
|
|
21
|
+
const referencedSOPInstanceUID = state.sopInstanceUid;
|
|
22
|
+
const allNUMGroups = extractAllNUMGroups(MeasurementGroup, referencedSOPInstanceUID);
|
|
23
|
+
const measurementNUMGroups = allNUMGroups[referencedSOPInstanceUID] || {};
|
|
20
24
|
state.annotation.data = {
|
|
21
25
|
...state.annotation.data,
|
|
22
26
|
handles: {
|
|
@@ -30,7 +34,8 @@ class CircleROI extends BaseAdapter3D {
|
|
|
30
34
|
[`imageId:${referencedImageId}`]: {
|
|
31
35
|
area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0,
|
|
32
36
|
radius: 0,
|
|
33
|
-
perimeter: 0
|
|
37
|
+
perimeter: 0,
|
|
38
|
+
...restoreAdditionalMetrics(measurementNUMGroups)
|
|
34
39
|
}
|
|
35
40
|
};
|
|
36
41
|
}
|
|
@@ -59,13 +64,27 @@ class CircleROI extends BaseAdapter3D {
|
|
|
59
64
|
const end = toScoord(scoordProps, handles.points[1]);
|
|
60
65
|
const {
|
|
61
66
|
area,
|
|
62
|
-
radius
|
|
67
|
+
radius,
|
|
68
|
+
max,
|
|
69
|
+
min,
|
|
70
|
+
stdDev,
|
|
71
|
+
mean,
|
|
72
|
+
modalityUnit,
|
|
73
|
+
radiusUnit,
|
|
74
|
+
areaUnit
|
|
63
75
|
} = cachedStats[`imageId:${referencedImageId}`] || {};
|
|
64
76
|
const perimeter = 2 * Math.PI * radius;
|
|
65
77
|
return {
|
|
66
78
|
area,
|
|
79
|
+
areaUnit,
|
|
67
80
|
perimeter,
|
|
81
|
+
modalityUnit,
|
|
82
|
+
radiusUnit,
|
|
68
83
|
radius,
|
|
84
|
+
max,
|
|
85
|
+
min,
|
|
86
|
+
stdDev,
|
|
87
|
+
mean,
|
|
69
88
|
points: [center, end],
|
|
70
89
|
trackingIdentifierTextValue: this.trackingIdentifierTextValue,
|
|
71
90
|
finding,
|
|
@@ -11,6 +11,12 @@ declare class EllipticalROI extends BaseAdapter3D {
|
|
|
11
11
|
};
|
|
12
12
|
static getTID300RepresentationArguments(tool: any, is3DMeasurement?: boolean): {
|
|
13
13
|
area: any;
|
|
14
|
+
areaUnit: any;
|
|
15
|
+
max: any;
|
|
16
|
+
min: any;
|
|
17
|
+
mean: any;
|
|
18
|
+
stdDev: any;
|
|
19
|
+
modalityUnit: any;
|
|
14
20
|
points: ({
|
|
15
21
|
x: any;
|
|
16
22
|
y: any;
|
|
@@ -3,6 +3,7 @@ import MeasurementReport from './MeasurementReport.js';
|
|
|
3
3
|
import BaseAdapter3D from './BaseAdapter3D.js';
|
|
4
4
|
import { toScoord } from '../helpers/toScoordType.js';
|
|
5
5
|
import '@cornerstonejs/core';
|
|
6
|
+
import { extractAllNUMGroups, restoreAdditionalMetrics } from './metricHandler.js';
|
|
6
7
|
|
|
7
8
|
var _EllipticalROI;
|
|
8
9
|
const {
|
|
@@ -17,6 +18,9 @@ class EllipticalROI extends BaseAdapter3D {
|
|
|
17
18
|
referencedImageId,
|
|
18
19
|
ReferencedFrameNumber
|
|
19
20
|
} = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, EllipticalROI.toolType);
|
|
21
|
+
const referencedSOPInstanceUID = state.sopInstanceUid;
|
|
22
|
+
const allNUMGroups = extractAllNUMGroups(MeasurementGroup, referencedSOPInstanceUID);
|
|
23
|
+
const measurementNUMGroups = allNUMGroups[referencedSOPInstanceUID] || {};
|
|
20
24
|
state.annotation.data = {
|
|
21
25
|
...state.annotation.data,
|
|
22
26
|
handles: {
|
|
@@ -27,7 +31,8 @@ class EllipticalROI extends BaseAdapter3D {
|
|
|
27
31
|
};
|
|
28
32
|
state.annotation.data.cachedStats = referencedImageId ? {
|
|
29
33
|
[`imageId:${referencedImageId}`]: {
|
|
30
|
-
area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0
|
|
34
|
+
area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0,
|
|
35
|
+
...restoreAdditionalMetrics(measurementNUMGroups)
|
|
31
36
|
}
|
|
32
37
|
} : {};
|
|
33
38
|
return state;
|
|
@@ -73,11 +78,23 @@ class EllipticalROI extends BaseAdapter3D {
|
|
|
73
78
|
points.push(left, right, top, bottom);
|
|
74
79
|
}
|
|
75
80
|
const {
|
|
76
|
-
area
|
|
81
|
+
area,
|
|
82
|
+
max,
|
|
83
|
+
min,
|
|
84
|
+
mean,
|
|
85
|
+
stdDev,
|
|
86
|
+
modalityUnit,
|
|
87
|
+
areaUnit
|
|
77
88
|
} = cachedStats[`imageId:${referencedImageId}`] || {};
|
|
78
89
|
const convertedPoints = points.map(point => toScoord(scoordProps, point));
|
|
79
90
|
return {
|
|
80
91
|
area,
|
|
92
|
+
areaUnit,
|
|
93
|
+
max,
|
|
94
|
+
min,
|
|
95
|
+
mean,
|
|
96
|
+
stdDev,
|
|
97
|
+
modalityUnit,
|
|
81
98
|
points: convertedPoints,
|
|
82
99
|
trackingIdentifierTextValue: this.trackingIdentifierTextValue,
|
|
83
100
|
finding,
|
|
@@ -7,9 +7,11 @@ const {
|
|
|
7
7
|
sr: {
|
|
8
8
|
valueTypes,
|
|
9
9
|
coding
|
|
10
|
+
},
|
|
11
|
+
adapters: {
|
|
12
|
+
Cornerstone3D
|
|
10
13
|
}
|
|
11
14
|
} = dcmjs;
|
|
12
|
-
const CORNERSTONEFREETEXT = "CORNERSTONEFREETEXT";
|
|
13
15
|
class LabelData {
|
|
14
16
|
constructor(tid300Item, annotation) {
|
|
15
17
|
this.tid300Item = tid300Item;
|
|
@@ -32,12 +34,16 @@ class LabelData {
|
|
|
32
34
|
return contentEntries;
|
|
33
35
|
}
|
|
34
36
|
filterCornerstoneFreeText(contentEntries) {
|
|
37
|
+
const {
|
|
38
|
+
codeValues
|
|
39
|
+
} = Cornerstone3D.CodeScheme;
|
|
40
|
+
const freeTextCodes = [codeValues.FREE_TEXT_CODE_VALUE, codeValues.CORNERSTONEFREETEXT];
|
|
35
41
|
for (let i = 0; i < contentEntries.length; i++) {
|
|
36
42
|
const group = contentEntries[i];
|
|
37
43
|
if (!group.ConceptCodeSequence) {
|
|
38
44
|
continue;
|
|
39
45
|
}
|
|
40
|
-
const csLabel = group.ConceptCodeSequence.
|
|
46
|
+
const csLabel = group.ConceptCodeSequence.findIndex(item => freeTextCodes.includes(item.CodeValue));
|
|
41
47
|
if (csLabel !== -1) {
|
|
42
48
|
group.ConceptCodeSequence.splice(csLabel, 1);
|
|
43
49
|
if (group.ConceptCodeSequence.length === 0) {
|
|
@@ -64,9 +70,6 @@ class LabelData {
|
|
|
64
70
|
FrameOfReferenceUID: frameOfReferenceUID
|
|
65
71
|
} = annotation.metadata;
|
|
66
72
|
const is3DMeasurement = !referencedImageId;
|
|
67
|
-
const {
|
|
68
|
-
worldPosition
|
|
69
|
-
} = textBox;
|
|
70
73
|
const {
|
|
71
74
|
x,
|
|
72
75
|
y,
|
|
@@ -74,27 +77,28 @@ class LabelData {
|
|
|
74
77
|
} = toScoord({
|
|
75
78
|
is3DMeasurement,
|
|
76
79
|
referencedImageId
|
|
77
|
-
}, worldPosition);
|
|
80
|
+
}, textBox.worldPosition);
|
|
78
81
|
const graphicType = valueTypes.GraphicTypes.POINT;
|
|
79
82
|
const relationshipType = valueTypes.RelationshipTypes.CONTAINS;
|
|
80
83
|
const name = new coding.CodedConcept(TEXT_ANNOTATION_POSITION);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
graphicData
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
const graphicData = [x, y];
|
|
92
|
-
return new valueTypes.ScoordContentItem({
|
|
84
|
+
const scoord = is3DMeasurement ? new valueTypes.Scoord3DContentItem({
|
|
85
|
+
name,
|
|
86
|
+
relationshipType,
|
|
87
|
+
graphicType,
|
|
88
|
+
graphicData: [x, y, z],
|
|
89
|
+
frameOfReferenceUID
|
|
90
|
+
}) : new valueTypes.ScoordContentItem({
|
|
93
91
|
name,
|
|
94
92
|
relationshipType,
|
|
95
93
|
graphicType,
|
|
96
|
-
graphicData
|
|
94
|
+
graphicData: [x, y]
|
|
97
95
|
});
|
|
96
|
+
scoord.ContentSequence = [{
|
|
97
|
+
RelationshipType: valueTypes.RelationshipTypes.SELECTED_FROM,
|
|
98
|
+
ValueType: valueTypes.ValueTypes.IMAGE,
|
|
99
|
+
ReferencedSOPSequence: this.ReferencedSOPSequence
|
|
100
|
+
}];
|
|
101
|
+
return scoord;
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
104
|
|
|
@@ -20,7 +20,8 @@ class Length extends BaseAdapter3D {
|
|
|
20
20
|
} = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, this.toolType);
|
|
21
21
|
const cachedStats = referencedImageId ? {
|
|
22
22
|
[`imageId:${referencedImageId}`]: {
|
|
23
|
-
length: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0
|
|
23
|
+
length: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0,
|
|
24
|
+
unit: NUMGroup.MeasuredValueSequence.MeasurementUnitsCodeSequence.CodeValue
|
|
24
25
|
}
|
|
25
26
|
} : {};
|
|
26
27
|
state.annotation.data = {
|
|
@@ -4,6 +4,7 @@ import { vec3 } from 'gl-matrix';
|
|
|
4
4
|
import BaseAdapter3D from './BaseAdapter3D.js';
|
|
5
5
|
import { toScoords } from '../helpers/toScoordType.js';
|
|
6
6
|
import '@cornerstonejs/core';
|
|
7
|
+
import { extractAllNUMGroups, restoreAdditionalMetrics } from './metricHandler.js';
|
|
7
8
|
|
|
8
9
|
var _PlanarFreehandROI;
|
|
9
10
|
const {
|
|
@@ -28,6 +29,9 @@ class PlanarFreehandROI extends BaseAdapter3D {
|
|
|
28
29
|
if (isOpenContour) {
|
|
29
30
|
points.push(worldCoords[0], worldCoords[worldCoords.length - 1]);
|
|
30
31
|
}
|
|
32
|
+
const referencedSOPInstanceUID = state.sopInstanceUid;
|
|
33
|
+
const allNUMGroups = extractAllNUMGroups(MeasurementGroup, referencedSOPInstanceUID);
|
|
34
|
+
const measurementNUMGroups = allNUMGroups[referencedSOPInstanceUID] || {};
|
|
31
35
|
state.annotation.data = {
|
|
32
36
|
...state.annotation.data,
|
|
33
37
|
contour: {
|
|
@@ -43,7 +47,8 @@ class PlanarFreehandROI extends BaseAdapter3D {
|
|
|
43
47
|
if (referencedImageId) {
|
|
44
48
|
state.annotation.data.cachedStats = {
|
|
45
49
|
[`imageId:${referencedImageId}`]: {
|
|
46
|
-
area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : null
|
|
50
|
+
area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : null,
|
|
51
|
+
...restoreAdditionalMetrics(measurementNUMGroups)
|
|
47
52
|
}
|
|
48
53
|
};
|
|
49
54
|
}
|
|
@@ -81,13 +86,14 @@ class PlanarFreehandROI extends BaseAdapter3D {
|
|
|
81
86
|
perimeter,
|
|
82
87
|
mean,
|
|
83
88
|
max,
|
|
84
|
-
stdDev
|
|
89
|
+
stdDev,
|
|
90
|
+
length
|
|
85
91
|
} = data.cachedStats[`imageId:${referencedImageId}`] || {};
|
|
86
92
|
return {
|
|
87
93
|
points,
|
|
88
94
|
area,
|
|
89
95
|
areaUnit,
|
|
90
|
-
perimeter,
|
|
96
|
+
perimeter: perimeter ?? length,
|
|
91
97
|
modalityUnit,
|
|
92
98
|
mean,
|
|
93
99
|
max,
|
|
@@ -22,6 +22,11 @@ export declare class RectangleROI extends BaseAdapter3D {
|
|
|
22
22
|
})[];
|
|
23
23
|
area: any;
|
|
24
24
|
perimeter: any;
|
|
25
|
+
max: any;
|
|
26
|
+
mean: any;
|
|
27
|
+
stdDev: any;
|
|
28
|
+
areaUnit: any;
|
|
29
|
+
modalityUnit: any;
|
|
25
30
|
trackingIdentifierTextValue: string;
|
|
26
31
|
finding: any;
|
|
27
32
|
findingSites: any;
|
|
@@ -3,6 +3,7 @@ import { toScoords } from '../helpers/toScoordType.js';
|
|
|
3
3
|
import '@cornerstonejs/core';
|
|
4
4
|
import MeasurementReport from './MeasurementReport.js';
|
|
5
5
|
import BaseAdapter3D from './BaseAdapter3D.js';
|
|
6
|
+
import { extractAllNUMGroups, restoreAdditionalMetrics } from './metricHandler.js';
|
|
6
7
|
|
|
7
8
|
var _RectangleROI;
|
|
8
9
|
const {
|
|
@@ -23,10 +24,14 @@ class RectangleROI extends BaseAdapter3D {
|
|
|
23
24
|
} = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, this.toolType);
|
|
24
25
|
const points = worldCoords.length === 5 ? worldCoords.slice(0, 4) : worldCoords;
|
|
25
26
|
const areaGroup = MeasurementGroup.ContentSequence.find(g => g.ValueType === "NUM" && g.ConceptNameCodeSequence[0].CodeMeaning === "Area");
|
|
27
|
+
const referencedSOPInstanceUID = state.sopInstanceUid;
|
|
28
|
+
const allNUMGroups = extractAllNUMGroups(MeasurementGroup, referencedSOPInstanceUID);
|
|
29
|
+
const measurementNUMGroups = allNUMGroups[referencedSOPInstanceUID] || {};
|
|
26
30
|
const cachedStats = referencedImageId ? {
|
|
27
31
|
[`imageId:${referencedImageId}`]: {
|
|
28
32
|
area: areaGroup?.MeasuredValueSequence?.[0]?.NumericValue || 0,
|
|
29
|
-
areaUnit: areaGroup?.MeasuredValueSequence?.[0]?.MeasurementUnitsCodeSequence?.CodeValue
|
|
33
|
+
areaUnit: areaGroup?.MeasuredValueSequence?.[0]?.MeasurementUnitsCodeSequence?.CodeValue,
|
|
34
|
+
...restoreAdditionalMetrics(measurementNUMGroups)
|
|
30
35
|
}
|
|
31
36
|
} : {};
|
|
32
37
|
state.annotation.data = {
|
|
@@ -58,12 +63,22 @@ class RectangleROI extends BaseAdapter3D {
|
|
|
58
63
|
const corners = toScoords(scoordProps, data.handles.points);
|
|
59
64
|
const {
|
|
60
65
|
area,
|
|
61
|
-
perimeter
|
|
66
|
+
perimeter,
|
|
67
|
+
max,
|
|
68
|
+
mean,
|
|
69
|
+
stdDev,
|
|
70
|
+
areaUnit,
|
|
71
|
+
modalityUnit
|
|
62
72
|
} = data.cachedStats[`imageId:${referencedImageId}`] || {};
|
|
63
73
|
return {
|
|
64
74
|
points: [corners[0], corners[1], corners[3], corners[2], corners[0]],
|
|
65
75
|
area,
|
|
66
76
|
perimeter,
|
|
77
|
+
max,
|
|
78
|
+
mean,
|
|
79
|
+
stdDev,
|
|
80
|
+
areaUnit,
|
|
81
|
+
modalityUnit,
|
|
67
82
|
trackingIdentifierTextValue: this.trackingIdentifierTextValue,
|
|
68
83
|
finding,
|
|
69
84
|
findingSites: findingSites || [],
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface AdditionalMetrics {
|
|
2
|
+
mean?: number;
|
|
3
|
+
stdDev?: number;
|
|
4
|
+
max?: number;
|
|
5
|
+
min?: number;
|
|
6
|
+
area?: number;
|
|
7
|
+
radius?: number;
|
|
8
|
+
modalityUnit?: string;
|
|
9
|
+
areaUnit?: string;
|
|
10
|
+
[key: string]: number | string | undefined;
|
|
11
|
+
}
|
|
12
|
+
export declare function extractAllNUMGroups(MeasurementGroup: any, referencedSOPInstanceUID: any): {};
|
|
13
|
+
export declare function restoreAdditionalMetrics(numGroups: any): AdditionalMetrics;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
function extractAllNUMGroups(MeasurementGroup, referencedSOPInstanceUID) {
|
|
2
|
+
const numGroupsBySOPInstanceUID = {};
|
|
3
|
+
if (MeasurementGroup.ContentSequence) {
|
|
4
|
+
MeasurementGroup.ContentSequence.forEach(item => {
|
|
5
|
+
if (item.ValueType === "NUM" && item.ConceptNameCodeSequence) {
|
|
6
|
+
const codeMeaning = item.ConceptNameCodeSequence.CodeMeaning;
|
|
7
|
+
const numericValue = item.MeasuredValueSequence?.NumericValue;
|
|
8
|
+
const unitCode = item.MeasuredValueSequence?.MeasurementUnitsCodeSequence?.CodeValue;
|
|
9
|
+
if (numericValue !== undefined && referencedSOPInstanceUID) {
|
|
10
|
+
if (!numGroupsBySOPInstanceUID[referencedSOPInstanceUID]) {
|
|
11
|
+
numGroupsBySOPInstanceUID[referencedSOPInstanceUID] = {};
|
|
12
|
+
}
|
|
13
|
+
numGroupsBySOPInstanceUID[referencedSOPInstanceUID][codeMeaning] = {
|
|
14
|
+
value: numericValue,
|
|
15
|
+
unit: unitCode || ""
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return numGroupsBySOPInstanceUID;
|
|
22
|
+
}
|
|
23
|
+
function restoreAdditionalMetrics(numGroups) {
|
|
24
|
+
const additionalMetrics = {};
|
|
25
|
+
let modalityUnit = "";
|
|
26
|
+
const metricMapping = {
|
|
27
|
+
Mean: "mean",
|
|
28
|
+
"Standard Deviation": "stdDev",
|
|
29
|
+
Maximum: "max",
|
|
30
|
+
Minimum: "min",
|
|
31
|
+
Area: "area",
|
|
32
|
+
Radius: "radius",
|
|
33
|
+
Perimeter: "perimeter",
|
|
34
|
+
Length: "length",
|
|
35
|
+
Width: "width"
|
|
36
|
+
};
|
|
37
|
+
const unitCategory = {
|
|
38
|
+
area: "areaUnit",
|
|
39
|
+
radius: "radiusUnit",
|
|
40
|
+
width: "widthUnit"
|
|
41
|
+
};
|
|
42
|
+
for (const [codeMeaning, metricKey] of Object.entries(metricMapping)) {
|
|
43
|
+
const group = numGroups[codeMeaning];
|
|
44
|
+
if (!group) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const {
|
|
48
|
+
value,
|
|
49
|
+
unit
|
|
50
|
+
} = group;
|
|
51
|
+
if (value == null) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
additionalMetrics[metricKey] = value;
|
|
55
|
+
if (!unit) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (!modalityUnit) {
|
|
59
|
+
modalityUnit = unit;
|
|
60
|
+
}
|
|
61
|
+
const category = unitCategory[metricKey];
|
|
62
|
+
if (category) {
|
|
63
|
+
if (!additionalMetrics[category]) {
|
|
64
|
+
additionalMetrics[category] = unit;
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
additionalMetrics[`${metricKey}Unit`] = unit;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
additionalMetrics.modalityUnit = modalityUnit;
|
|
71
|
+
return additionalMetrics;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { extractAllNUMGroups, restoreAdditionalMetrics };
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "4.15.
|
|
1
|
+
export declare const version = "4.15.18";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/adapters",
|
|
3
|
-
"version": "4.15.
|
|
3
|
+
"version": "4.15.18",
|
|
4
4
|
"description": "Adapters for Cornerstone3D to/from formats including DICOM SR and others",
|
|
5
5
|
"module": "./dist/esm/index.js",
|
|
6
6
|
"types": "./dist/esm/index.d.ts",
|
|
@@ -84,13 +84,13 @@
|
|
|
84
84
|
"dependencies": {
|
|
85
85
|
"@babel/runtime-corejs2": "7.26.10",
|
|
86
86
|
"buffer": "6.0.3",
|
|
87
|
-
"dcmjs": "0.
|
|
87
|
+
"dcmjs": "0.48.0",
|
|
88
88
|
"gl-matrix": "3.4.3",
|
|
89
89
|
"ndarray": "1.0.19"
|
|
90
90
|
},
|
|
91
91
|
"peerDependencies": {
|
|
92
|
-
"@cornerstonejs/core": "4.15.
|
|
93
|
-
"@cornerstonejs/tools": "4.15.
|
|
92
|
+
"@cornerstonejs/core": "4.15.18",
|
|
93
|
+
"@cornerstonejs/tools": "4.15.18"
|
|
94
94
|
},
|
|
95
|
-
"gitHead": "
|
|
95
|
+
"gitHead": "2198d2e21481dd9f7e77148f98693ef0c2e5bdbc"
|
|
96
96
|
}
|