@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.
Files changed (77) hide show
  1. package/dist/cjs/drawingSvg/drawHandle.d.ts +4 -0
  2. package/dist/cjs/drawingSvg/drawHandle.js +66 -0
  3. package/dist/cjs/drawingSvg/drawHandle.js.map +1 -0
  4. package/dist/cjs/drawingSvg/drawHandles.js +4 -60
  5. package/dist/cjs/drawingSvg/drawHandles.js.map +1 -1
  6. package/dist/cjs/drawingSvg/index.d.ts +2 -1
  7. package/dist/cjs/drawingSvg/index.js +3 -1
  8. package/dist/cjs/drawingSvg/index.js.map +1 -1
  9. package/dist/cjs/index.d.ts +2 -2
  10. package/dist/cjs/index.js +3 -2
  11. package/dist/cjs/index.js.map +1 -1
  12. package/dist/cjs/tools/annotation/AngleTool.js.map +1 -1
  13. package/dist/cjs/tools/annotation/LengthTool.js +4 -3
  14. package/dist/cjs/tools/annotation/LengthTool.js.map +1 -1
  15. package/dist/cjs/tools/annotation/ProbeTool.js +24 -3
  16. package/dist/cjs/tools/annotation/ProbeTool.js.map +1 -1
  17. package/dist/cjs/tools/annotation/UltrasoundDirectionalTool.d.ts +36 -0
  18. package/dist/cjs/tools/annotation/UltrasoundDirectionalTool.js +483 -0
  19. package/dist/cjs/tools/annotation/UltrasoundDirectionalTool.js.map +1 -0
  20. package/dist/cjs/tools/index.d.ts +2 -1
  21. package/dist/cjs/tools/index.js +3 -1
  22. package/dist/cjs/tools/index.js.map +1 -1
  23. package/dist/cjs/types/ToolSpecificAnnotationTypes.d.ts +28 -0
  24. package/dist/cjs/utilities/getCalibratedUnits.d.ts +16 -2
  25. package/dist/cjs/utilities/getCalibratedUnits.js +127 -5
  26. package/dist/cjs/utilities/getCalibratedUnits.js.map +1 -1
  27. package/dist/esm/drawingSvg/drawHandle.js +61 -0
  28. package/dist/esm/drawingSvg/drawHandle.js.map +1 -0
  29. package/dist/esm/drawingSvg/drawHandles.js +4 -60
  30. package/dist/esm/drawingSvg/drawHandles.js.map +1 -1
  31. package/dist/esm/drawingSvg/index.js +2 -1
  32. package/dist/esm/drawingSvg/index.js.map +1 -1
  33. package/dist/esm/index.js +2 -2
  34. package/dist/esm/index.js.map +1 -1
  35. package/dist/esm/tools/annotation/AngleTool.js.map +1 -1
  36. package/dist/esm/tools/annotation/LengthTool.js +5 -4
  37. package/dist/esm/tools/annotation/LengthTool.js.map +1 -1
  38. package/dist/esm/tools/annotation/ProbeTool.js +24 -3
  39. package/dist/esm/tools/annotation/ProbeTool.js.map +1 -1
  40. package/dist/esm/tools/annotation/UltrasoundDirectionalTool.js +478 -0
  41. package/dist/esm/tools/annotation/UltrasoundDirectionalTool.js.map +1 -0
  42. package/dist/esm/tools/index.js +2 -1
  43. package/dist/esm/tools/index.js.map +1 -1
  44. package/dist/esm/utilities/getCalibratedUnits.js +125 -6
  45. package/dist/esm/utilities/getCalibratedUnits.js.map +1 -1
  46. package/dist/types/drawingSvg/drawHandle.d.ts +5 -0
  47. package/dist/types/drawingSvg/drawHandle.d.ts.map +1 -0
  48. package/dist/types/drawingSvg/drawHandles.d.ts.map +1 -1
  49. package/dist/types/drawingSvg/index.d.ts +2 -1
  50. package/dist/types/drawingSvg/index.d.ts.map +1 -1
  51. package/dist/types/index.d.ts +2 -2
  52. package/dist/types/index.d.ts.map +1 -1
  53. package/dist/types/tools/annotation/AngleTool.d.ts.map +1 -1
  54. package/dist/types/tools/annotation/LengthTool.d.ts.map +1 -1
  55. package/dist/types/tools/annotation/ProbeTool.d.ts.map +1 -1
  56. package/dist/types/tools/annotation/UltrasoundDirectionalTool.d.ts +37 -0
  57. package/dist/types/tools/annotation/UltrasoundDirectionalTool.d.ts.map +1 -0
  58. package/dist/types/tools/index.d.ts +2 -1
  59. package/dist/types/tools/index.d.ts.map +1 -1
  60. package/dist/types/types/ToolSpecificAnnotationTypes.d.ts +28 -0
  61. package/dist/types/types/ToolSpecificAnnotationTypes.d.ts.map +1 -1
  62. package/dist/types/utilities/getCalibratedUnits.d.ts +16 -2
  63. package/dist/types/utilities/getCalibratedUnits.d.ts.map +1 -1
  64. package/dist/umd/index.js +1 -1
  65. package/dist/umd/index.js.map +1 -1
  66. package/package.json +3 -3
  67. package/src/drawingSvg/drawHandle.ts +88 -0
  68. package/src/drawingSvg/drawHandles.ts +9 -75
  69. package/src/drawingSvg/index.ts +2 -0
  70. package/src/index.ts +2 -0
  71. package/src/tools/annotation/AngleTool.ts +0 -1
  72. package/src/tools/annotation/LengthTool.ts +6 -8
  73. package/src/tools/annotation/ProbeTool.ts +31 -7
  74. package/src/tools/annotation/UltrasoundDirectionalTool.ts +916 -0
  75. package/src/tools/index.ts +2 -0
  76. package/src/types/ToolSpecificAnnotationTypes.ts +29 -0
  77. package/src/utilities/getCalibratedUnits.ts +203 -7
@@ -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 calibraiton types.
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 (!calibration || !calibration.type) {
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
- // TODO - handle US regions properly
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.SequenceOfUltrasoundRegions) {
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) => image.calibration?.scale || 1;
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
  };