@cornerstonejs/tools 1.40.2 → 1.41.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/cjs/drawingSvg/drawHandle.d.ts +4 -0
- package/dist/cjs/drawingSvg/drawHandle.js +66 -0
- package/dist/cjs/drawingSvg/drawHandle.js.map +1 -0
- package/dist/cjs/drawingSvg/drawHandles.js +4 -60
- package/dist/cjs/drawingSvg/drawHandles.js.map +1 -1
- package/dist/cjs/drawingSvg/index.d.ts +2 -1
- package/dist/cjs/drawingSvg/index.js +3 -1
- package/dist/cjs/drawingSvg/index.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/tools/annotation/AngleTool.js.map +1 -1
- package/dist/cjs/tools/annotation/LengthTool.js +4 -3
- package/dist/cjs/tools/annotation/LengthTool.js.map +1 -1
- package/dist/cjs/tools/annotation/ProbeTool.js +24 -3
- package/dist/cjs/tools/annotation/ProbeTool.js.map +1 -1
- package/dist/cjs/tools/annotation/UltrasoundDirectionalTool.d.ts +36 -0
- package/dist/cjs/tools/annotation/UltrasoundDirectionalTool.js +483 -0
- package/dist/cjs/tools/annotation/UltrasoundDirectionalTool.js.map +1 -0
- package/dist/cjs/tools/index.d.ts +2 -1
- package/dist/cjs/tools/index.js +3 -1
- package/dist/cjs/tools/index.js.map +1 -1
- package/dist/cjs/types/ToolSpecificAnnotationTypes.d.ts +28 -0
- package/dist/cjs/utilities/getCalibratedUnits.d.ts +16 -2
- package/dist/cjs/utilities/getCalibratedUnits.js +127 -5
- package/dist/cjs/utilities/getCalibratedUnits.js.map +1 -1
- package/dist/esm/drawingSvg/drawHandle.js +61 -0
- package/dist/esm/drawingSvg/drawHandle.js.map +1 -0
- package/dist/esm/drawingSvg/drawHandles.js +4 -60
- package/dist/esm/drawingSvg/drawHandles.js.map +1 -1
- package/dist/esm/drawingSvg/index.js +2 -1
- package/dist/esm/drawingSvg/index.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tools/annotation/AngleTool.js.map +1 -1
- package/dist/esm/tools/annotation/LengthTool.js +5 -4
- package/dist/esm/tools/annotation/LengthTool.js.map +1 -1
- package/dist/esm/tools/annotation/ProbeTool.js +24 -3
- package/dist/esm/tools/annotation/ProbeTool.js.map +1 -1
- package/dist/esm/tools/annotation/UltrasoundDirectionalTool.js +478 -0
- package/dist/esm/tools/annotation/UltrasoundDirectionalTool.js.map +1 -0
- package/dist/esm/tools/index.js +2 -1
- package/dist/esm/tools/index.js.map +1 -1
- package/dist/esm/utilities/getCalibratedUnits.js +125 -6
- package/dist/esm/utilities/getCalibratedUnits.js.map +1 -1
- package/dist/types/drawingSvg/drawHandle.d.ts +5 -0
- package/dist/types/drawingSvg/drawHandle.d.ts.map +1 -0
- package/dist/types/drawingSvg/drawHandles.d.ts.map +1 -1
- package/dist/types/drawingSvg/index.d.ts +2 -1
- package/dist/types/drawingSvg/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/tools/annotation/AngleTool.d.ts.map +1 -1
- package/dist/types/tools/annotation/LengthTool.d.ts.map +1 -1
- package/dist/types/tools/annotation/ProbeTool.d.ts.map +1 -1
- package/dist/types/tools/annotation/UltrasoundDirectionalTool.d.ts +37 -0
- package/dist/types/tools/annotation/UltrasoundDirectionalTool.d.ts.map +1 -0
- package/dist/types/tools/index.d.ts +2 -1
- package/dist/types/tools/index.d.ts.map +1 -1
- package/dist/types/types/ToolSpecificAnnotationTypes.d.ts +28 -0
- package/dist/types/types/ToolSpecificAnnotationTypes.d.ts.map +1 -1
- package/dist/types/utilities/getCalibratedUnits.d.ts +16 -2
- package/dist/types/utilities/getCalibratedUnits.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -3
- package/src/drawingSvg/drawHandle.ts +88 -0
- package/src/drawingSvg/drawHandles.ts +9 -75
- package/src/drawingSvg/index.ts +2 -0
- package/src/index.ts +2 -0
- package/src/tools/annotation/AngleTool.ts +0 -1
- package/src/tools/annotation/LengthTool.ts +6 -8
- package/src/tools/annotation/ProbeTool.ts +31 -7
- package/src/tools/annotation/UltrasoundDirectionalTool.ts +916 -0
- package/src/tools/index.ts +2 -0
- package/src/types/ToolSpecificAnnotationTypes.ts +29 -0
- package/src/utilities/getCalibratedUnits.ts +203 -7
package/src/tools/index.ts
CHANGED
|
@@ -32,6 +32,7 @@ import LivewireContourTool from './annotation/LivewireContourTool';
|
|
|
32
32
|
import ArrowAnnotateTool from './annotation/ArrowAnnotateTool';
|
|
33
33
|
import AngleTool from './annotation/AngleTool';
|
|
34
34
|
import CobbAngleTool from './annotation/CobbAngleTool';
|
|
35
|
+
import UltrasoundDirectionalTool from './annotation/UltrasoundDirectionalTool';
|
|
35
36
|
import KeyImageTool from './annotation/KeyImageTool';
|
|
36
37
|
|
|
37
38
|
// Segmentation DisplayTool
|
|
@@ -81,6 +82,7 @@ export {
|
|
|
81
82
|
ArrowAnnotateTool,
|
|
82
83
|
AngleTool,
|
|
83
84
|
CobbAngleTool,
|
|
85
|
+
UltrasoundDirectionalTool,
|
|
84
86
|
KeyImageTool,
|
|
85
87
|
// Segmentations Display
|
|
86
88
|
SegmentationDisplayTool,
|
|
@@ -346,6 +346,35 @@ export interface AngleAnnotation extends Annotation {
|
|
|
346
346
|
};
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
+
export interface UltrasoundDirectionalAnnotation extends Annotation {
|
|
350
|
+
data: {
|
|
351
|
+
handles: {
|
|
352
|
+
points: Types.Point3[];
|
|
353
|
+
activeHandleIndex: number | null;
|
|
354
|
+
textBox: {
|
|
355
|
+
hasMoved: boolean;
|
|
356
|
+
worldPosition: Types.Point3;
|
|
357
|
+
worldBoundingBox: {
|
|
358
|
+
topLeft: Types.Point3;
|
|
359
|
+
topRight: Types.Point3;
|
|
360
|
+
bottomLeft: Types.Point3;
|
|
361
|
+
bottomRight: Types.Point3;
|
|
362
|
+
};
|
|
363
|
+
};
|
|
364
|
+
};
|
|
365
|
+
label: string;
|
|
366
|
+
cachedStats: {
|
|
367
|
+
[targetId: string]: {
|
|
368
|
+
xValues: number[];
|
|
369
|
+
yValues: number[];
|
|
370
|
+
units: string[];
|
|
371
|
+
isHorizontal: boolean;
|
|
372
|
+
isUnitless: boolean;
|
|
373
|
+
};
|
|
374
|
+
};
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
349
378
|
export interface CobbAngleAnnotation extends Annotation {
|
|
350
379
|
data: {
|
|
351
380
|
handles: {
|
|
@@ -1,12 +1,31 @@
|
|
|
1
|
-
import { Enums } from '@cornerstonejs/core';
|
|
1
|
+
import { Enums, utilities } from '@cornerstonejs/core';
|
|
2
2
|
|
|
3
3
|
const { CalibrationTypes } = Enums;
|
|
4
4
|
const PIXEL_UNITS = 'px';
|
|
5
5
|
|
|
6
|
+
const SUPPORTED_REGION_DATA_TYPES = [
|
|
7
|
+
1, // Tissue
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
const SUPPORTED_LENGTH_VARIANT = [
|
|
11
|
+
'3,3', // x: cm & y:cm
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const SUPPORTED_PROBE_VARIANT = [
|
|
15
|
+
'4,3', // x: seconds & y : cm
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const UNIT_MAPPING = {
|
|
19
|
+
3: 'cm',
|
|
20
|
+
4: 'seconds',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const EPS = 1e-3;
|
|
24
|
+
|
|
6
25
|
/**
|
|
7
26
|
* Extracts the length units and the type of calibration for those units
|
|
8
27
|
* into the response. The length units will typically be either mm or px
|
|
9
|
-
* while the calibration type can be any of a number of different
|
|
28
|
+
* while the calibration type can be any of a number of different calibration types.
|
|
10
29
|
*
|
|
11
30
|
* Volumetric images have no calibration type, so are just the raw mm.
|
|
12
31
|
*
|
|
@@ -23,14 +42,16 @@ const getCalibratedLengthUnits = (handles, image): string => {
|
|
|
23
42
|
const { calibration, hasPixelSpacing } = image;
|
|
24
43
|
// Anachronistic - moving to using calibration consistently, but not completed yet
|
|
25
44
|
const units = hasPixelSpacing ? 'mm' : PIXEL_UNITS;
|
|
26
|
-
if (
|
|
45
|
+
if (
|
|
46
|
+
!calibration ||
|
|
47
|
+
(!calibration.type && !calibration.sequenceOfUltrasoundRegions)
|
|
48
|
+
) {
|
|
27
49
|
return units;
|
|
28
50
|
}
|
|
29
51
|
if (calibration.type === CalibrationTypes.UNCALIBRATED) {
|
|
30
52
|
return PIXEL_UNITS;
|
|
31
53
|
}
|
|
32
|
-
|
|
33
|
-
if (calibration.SequenceOfUltrasoundRegions) {
|
|
54
|
+
if (calibration.sequenceOfUltrasoundRegions) {
|
|
34
55
|
return 'US Region';
|
|
35
56
|
}
|
|
36
57
|
return `${units} ${calibration.type}`;
|
|
@@ -46,7 +67,7 @@ const getCalibratedAreaUnits = (handles, image): string => {
|
|
|
46
67
|
if (!calibration || !calibration.type) {
|
|
47
68
|
return units;
|
|
48
69
|
}
|
|
49
|
-
if (calibration.
|
|
70
|
+
if (calibration.sequenceOfUltrasoundRegions) {
|
|
50
71
|
return 'US Region';
|
|
51
72
|
}
|
|
52
73
|
return `${units} ${calibration.type}`;
|
|
@@ -56,7 +77,180 @@ const getCalibratedAreaUnits = (handles, image): string => {
|
|
|
56
77
|
* Gets the scale divisor for converting from internal spacing to
|
|
57
78
|
* image spacing for calibrated images.
|
|
58
79
|
*/
|
|
59
|
-
const getCalibratedScale = (image) =>
|
|
80
|
+
const getCalibratedScale = (image, handles = []) => {
|
|
81
|
+
if (image.calibration?.sequenceOfUltrasoundRegions) {
|
|
82
|
+
// image.spacing / image.us.space
|
|
83
|
+
} else if (image.calibration?.scale) {
|
|
84
|
+
return image.calibration.scale;
|
|
85
|
+
} else {
|
|
86
|
+
return 1;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Extracts the calibrated length units, area units, and the scale
|
|
92
|
+
* for converting from internal spacing to image spacing.
|
|
93
|
+
*
|
|
94
|
+
* @param handles - to detect if spacing information is different between points
|
|
95
|
+
* @param image - to extract the calibration from
|
|
96
|
+
* @returns Object containing the units, area units, and scale
|
|
97
|
+
*/
|
|
98
|
+
const getCalibratedLengthUnitsAndScale = (image, handles) => {
|
|
99
|
+
const [imageIndex1, imageIndex2] = handles;
|
|
100
|
+
const { calibration, hasPixelSpacing } = image;
|
|
101
|
+
let units = hasPixelSpacing ? 'mm' : PIXEL_UNITS;
|
|
102
|
+
const areaUnits = units + SQUARE;
|
|
103
|
+
let scale = 1;
|
|
104
|
+
let calibrationType = '';
|
|
105
|
+
|
|
106
|
+
if (
|
|
107
|
+
!calibration ||
|
|
108
|
+
(!calibration.type && !calibration.sequenceOfUltrasoundRegions)
|
|
109
|
+
) {
|
|
110
|
+
return { units, areaUnits, scale };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (calibration.type === CalibrationTypes.UNCALIBRATED) {
|
|
114
|
+
return { units: PIXEL_UNITS, areaUnits: PIXEL_UNITS + SQUARE, scale };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (calibration.sequenceOfUltrasoundRegions) {
|
|
118
|
+
let regions = calibration.sequenceOfUltrasoundRegions.filter(
|
|
119
|
+
(region) =>
|
|
120
|
+
imageIndex1[0] >= region.regionLocationMinX0 &&
|
|
121
|
+
imageIndex1[0] <= region.regionLocationMaxX1 &&
|
|
122
|
+
imageIndex1[1] >= region.regionLocationMinY0 &&
|
|
123
|
+
imageIndex1[1] <= region.regionLocationMaxY1 &&
|
|
124
|
+
imageIndex2[0] >= region.regionLocationMinX0 &&
|
|
125
|
+
imageIndex2[0] <= region.regionLocationMaxX1 &&
|
|
126
|
+
imageIndex2[1] >= region.regionLocationMinY0 &&
|
|
127
|
+
imageIndex2[1] <= region.regionLocationMaxY1
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
// If we are not in a region at all we should show the underlying calibration
|
|
131
|
+
// which might be the mm spacing for the image
|
|
132
|
+
if (!regions?.length) {
|
|
133
|
+
return { units, areaUnits, scale };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// if we are in a region then it is the question of whether we support it
|
|
137
|
+
// or not. If we do not support it we should show px
|
|
138
|
+
|
|
139
|
+
regions = regions.filter(
|
|
140
|
+
(region) =>
|
|
141
|
+
SUPPORTED_REGION_DATA_TYPES.includes(region.regionDataType) &&
|
|
142
|
+
SUPPORTED_LENGTH_VARIANT.includes(
|
|
143
|
+
`${region.physicalUnitXDirection},${region.physicalUnitYDirection}`
|
|
144
|
+
)
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
if (!regions.length) {
|
|
148
|
+
return { units: PIXEL_UNITS, areaUnits: PIXEL_UNITS + SQUARE, scale };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Todo: expand on this logic
|
|
152
|
+
const region = regions[0];
|
|
153
|
+
|
|
154
|
+
const physicalDeltaX = Math.abs(region.physicalDeltaX);
|
|
155
|
+
const physicalDeltaY = Math.abs(region.physicalDeltaY);
|
|
156
|
+
|
|
157
|
+
// if we are in a supported region then we should check if the
|
|
158
|
+
// physicalDeltaX and physicalDeltaY are the same. If they are not
|
|
159
|
+
// then we should show px again, but if they are the same then we should
|
|
160
|
+
// show the units
|
|
161
|
+
const isSamePhysicalDelta = utilities.isEqual(
|
|
162
|
+
physicalDeltaX,
|
|
163
|
+
physicalDeltaY,
|
|
164
|
+
EPS
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
if (isSamePhysicalDelta) {
|
|
168
|
+
scale = 1 / (physicalDeltaX * physicalDeltaY * 100);
|
|
169
|
+
calibrationType = 'US Region';
|
|
170
|
+
units = 'mm';
|
|
171
|
+
} else {
|
|
172
|
+
return { units: PIXEL_UNITS, areaUnits: PIXEL_UNITS + SQUARE, scale };
|
|
173
|
+
}
|
|
174
|
+
} else if (calibration.scale) {
|
|
175
|
+
scale = calibration.scale;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
units: units + (calibrationType ? ` ${calibrationType}` : ''),
|
|
180
|
+
areaUnits: areaUnits + (calibrationType ? ` ${calibrationType}` : ''),
|
|
181
|
+
scale,
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const getCalibratedProbeUnitsAndValue = (image, handles) => {
|
|
186
|
+
const [imageIndex] = handles;
|
|
187
|
+
const { calibration } = image;
|
|
188
|
+
let units = ['raw'];
|
|
189
|
+
let values = [null];
|
|
190
|
+
let calibrationType = '';
|
|
191
|
+
|
|
192
|
+
if (
|
|
193
|
+
!calibration ||
|
|
194
|
+
(!calibration.type && !calibration.sequenceOfUltrasoundRegions)
|
|
195
|
+
) {
|
|
196
|
+
return { units, values };
|
|
197
|
+
// Todo: add support for other scenarios
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (calibration.sequenceOfUltrasoundRegions) {
|
|
201
|
+
// for Probe tool
|
|
202
|
+
const supportedRegionsMetadata =
|
|
203
|
+
calibration.sequenceOfUltrasoundRegions.filter(
|
|
204
|
+
(region) =>
|
|
205
|
+
SUPPORTED_REGION_DATA_TYPES.includes(region.regionDataType) &&
|
|
206
|
+
SUPPORTED_PROBE_VARIANT.includes(
|
|
207
|
+
`${region.physicalUnitXDirection},${region.physicalUnitYDirection}`
|
|
208
|
+
)
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
if (!supportedRegionsMetadata?.length) {
|
|
212
|
+
return { units, values };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const region = supportedRegionsMetadata.find(
|
|
216
|
+
(region) =>
|
|
217
|
+
imageIndex[0] >= region.regionLocationMinX0 &&
|
|
218
|
+
imageIndex[0] <= region.regionLocationMaxX1 &&
|
|
219
|
+
imageIndex[1] >= region.regionLocationMinY0 &&
|
|
220
|
+
imageIndex[1] <= region.regionLocationMaxY1
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
if (!region) {
|
|
224
|
+
return { units, values };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Todo: I think this is a ok assumption for now that if the referencePixelX0 and referencePixelY0
|
|
228
|
+
// are not defined, then we can assume 0 for them
|
|
229
|
+
const { referencePixelX0 = 0, referencePixelY0 = 0 } = region;
|
|
230
|
+
const { physicalDeltaX, physicalDeltaY } = region;
|
|
231
|
+
|
|
232
|
+
const yValue =
|
|
233
|
+
(imageIndex[1] - region.regionLocationMinY0 - referencePixelY0) *
|
|
234
|
+
physicalDeltaY;
|
|
235
|
+
|
|
236
|
+
const xValue =
|
|
237
|
+
(imageIndex[0] - region.regionLocationMinX0 - referencePixelX0) *
|
|
238
|
+
physicalDeltaX;
|
|
239
|
+
|
|
240
|
+
calibrationType = 'US Region';
|
|
241
|
+
values = [xValue, yValue];
|
|
242
|
+
units = [
|
|
243
|
+
UNIT_MAPPING[region.physicalUnitXDirection],
|
|
244
|
+
UNIT_MAPPING[region.physicalUnitYDirection],
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
units,
|
|
250
|
+
values,
|
|
251
|
+
calibrationType,
|
|
252
|
+
};
|
|
253
|
+
};
|
|
60
254
|
|
|
61
255
|
/** Gets the aspect ratio of the screen display relative to the image
|
|
62
256
|
* display in order to square up measurement values.
|
|
@@ -71,6 +265,8 @@ export default getCalibratedLengthUnits;
|
|
|
71
265
|
export {
|
|
72
266
|
getCalibratedAreaUnits,
|
|
73
267
|
getCalibratedLengthUnits,
|
|
268
|
+
getCalibratedLengthUnitsAndScale,
|
|
74
269
|
getCalibratedScale,
|
|
75
270
|
getCalibratedAspect,
|
|
271
|
+
getCalibratedProbeUnitsAndValue,
|
|
76
272
|
};
|