larvitar 2.0.5 → 2.0.6

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 (71) hide show
  1. package/README.md +2 -2
  2. package/dist/larvitar.js +1 -1
  3. package/package.json +6 -2
  4. package/.github/workflows/build-docs.yml +0 -59
  5. package/.github/workflows/codeql-analysis.yml +0 -71
  6. package/.github/workflows/deploy.yml +0 -37
  7. package/.vscode/settings.json +0 -4
  8. package/CODE_OF_CONDUCT.md +0 -76
  9. package/MIGRATION.md +0 -25
  10. package/bundler/webpack.common.js +0 -27
  11. package/bundler/webpack.dev.js +0 -23
  12. package/bundler/webpack.prod.js +0 -19
  13. package/decs.d.ts +0 -12
  14. package/imaging/MetaDataReadable.ts +0 -42
  15. package/imaging/MetaDataTypes.ts +0 -3491
  16. package/imaging/dataDictionary.json +0 -21866
  17. package/imaging/imageAnonymization.ts +0 -135
  18. package/imaging/imageColormaps.ts +0 -217
  19. package/imaging/imageContours.ts +0 -196
  20. package/imaging/imageIo.ts +0 -251
  21. package/imaging/imageLayers.ts +0 -121
  22. package/imaging/imageLoading.ts +0 -299
  23. package/imaging/imageParsing.ts +0 -444
  24. package/imaging/imagePresets.ts +0 -156
  25. package/imaging/imageRendering.ts +0 -1091
  26. package/imaging/imageReslice.ts +0 -87
  27. package/imaging/imageStore.ts +0 -487
  28. package/imaging/imageTags.ts +0 -609
  29. package/imaging/imageTools.js +0 -708
  30. package/imaging/imageUtils.ts +0 -1079
  31. package/imaging/loaders/commonLoader.ts +0 -275
  32. package/imaging/loaders/dicomLoader.ts +0 -66
  33. package/imaging/loaders/fileLoader.ts +0 -71
  34. package/imaging/loaders/multiframeLoader.ts +0 -435
  35. package/imaging/loaders/nrrdLoader.ts +0 -630
  36. package/imaging/loaders/resliceLoader.ts +0 -205
  37. package/imaging/monitors/memory.ts +0 -151
  38. package/imaging/monitors/performance.ts +0 -34
  39. package/imaging/parsers/ecg.ts +0 -54
  40. package/imaging/parsers/nrrd.js +0 -485
  41. package/imaging/tools/README.md +0 -27
  42. package/imaging/tools/custom/4dSliceScrollTool.js +0 -146
  43. package/imaging/tools/custom/BorderMagnifyTool.js +0 -99
  44. package/imaging/tools/custom/contourTool.js +0 -1884
  45. package/imaging/tools/custom/diameterTool.js +0 -141
  46. package/imaging/tools/custom/editMaskTool.js +0 -141
  47. package/imaging/tools/custom/ellipticalRoiOverlayTool.js +0 -534
  48. package/imaging/tools/custom/polygonSegmentationMixin.js +0 -245
  49. package/imaging/tools/custom/polylineScissorsTool.js +0 -59
  50. package/imaging/tools/custom/rectangleRoiOverlayTool.js +0 -564
  51. package/imaging/tools/custom/seedTool.js +0 -342
  52. package/imaging/tools/custom/setLabelMap3D.ts +0 -242
  53. package/imaging/tools/custom/thresholdsBrushTool.js +0 -161
  54. package/imaging/tools/default.ts +0 -594
  55. package/imaging/tools/interaction.ts +0 -266
  56. package/imaging/tools/io.ts +0 -229
  57. package/imaging/tools/main.ts +0 -427
  58. package/imaging/tools/segmentation.ts +0 -532
  59. package/imaging/tools/segmentations.md +0 -38
  60. package/imaging/tools/state.ts +0 -74
  61. package/imaging/tools/strategies/eraseFreehand.js +0 -76
  62. package/imaging/tools/strategies/fillFreehand.js +0 -79
  63. package/imaging/tools/strategies/index.js +0 -2
  64. package/imaging/tools/types.d.ts +0 -243
  65. package/imaging/types.d.ts +0 -200
  66. package/imaging/waveforms/ecg.ts +0 -191
  67. package/index.ts +0 -431
  68. package/jsdoc.json +0 -52
  69. package/rollup.config.js +0 -51
  70. package/template/.gitkeep +0 -0
  71. package/tsconfig.json +0 -102
@@ -1,564 +0,0 @@
1
- import cornerstoneTools from "cornerstone-tools";
2
-
3
- const external = cornerstoneTools.external;
4
- const BaseAnnotationTool = cornerstoneTools.importInternal(
5
- "base/BaseAnnotationTool"
6
- );
7
-
8
- // State
9
- const getToolState = cornerstoneTools.getToolState;
10
- const toolStyle = cornerstoneTools.toolStyle;
11
- const toolColors = cornerstoneTools.toolColors;
12
-
13
- // Drawing
14
- const getNewContext = cornerstoneTools.importInternal("drawing/getNewContext");
15
- const draw = cornerstoneTools.importInternal("drawing/draw");
16
- const drawHandles = cornerstoneTools.importInternal("drawing/drawHandles");
17
- const drawRect = cornerstoneTools.importInternal("drawing/drawRect");
18
- const drawLinkedTextBox = cornerstoneTools.importInternal(
19
- "drawing/drawLinkedTextBox"
20
- );
21
- const setShadow = cornerstoneTools.importInternal("drawing/setShadow");
22
-
23
- // Util
24
- const calculateSUV = cornerstoneTools.importInternal("util/calculateSUV");
25
- const getROITextBoxCoords = cornerstoneTools.importInternal(
26
- "util/getROITextBoxCoords"
27
- );
28
- const numbersWithCommas = cornerstoneTools.importInternal(
29
- "util/numbersWithCommas"
30
- );
31
- const throttle = cornerstoneTools.importInternal("util/throttle");
32
- const { rectangleRoiCursor } = cornerstoneTools.importInternal("tools/cursors");
33
- const getLogger = cornerstoneTools.importInternal("util/getLogger");
34
- const getPixelSpacing = cornerstoneTools.importInternal("util/getPixelSpacing");
35
- const getModule = cornerstoneTools.getModule;
36
-
37
- const logger = getLogger("tools:annotation:RectangleRoiTool");
38
-
39
- /**
40
- * @public
41
- * @class RectangleRoiTool
42
- * @memberof Tools.Annotation
43
- * @classdesc Tool for drawing rectangular regions of interest, and measuring
44
- * the statistics of the enclosed pixels.
45
- * @extends Tools.Base.BaseAnnotationTool
46
- */
47
- export default class RectangleRoiOverlayTool extends BaseAnnotationTool {
48
- constructor(props = {}) {
49
- const defaultProps = {
50
- name: "RectangleRoiOverlay",
51
- supportedInteractionTypes: ["Mouse", "Touch"],
52
- configuration: {
53
- drawHandles: true,
54
- drawHandlesOnHover: false,
55
- hideHandlesIfMoving: false,
56
- renderDashed: false
57
- // showMinMax: false,
58
- // showHounsfieldUnits: true,
59
- },
60
- svgCursor: rectangleRoiCursor
61
- };
62
-
63
- super(props, defaultProps);
64
-
65
- this.throttledUpdateCachedStats = throttle(this.updateCachedStats, 110);
66
- }
67
-
68
- createNewMeasurement(eventData) {
69
- const goodEventData =
70
- eventData && eventData.currentPoints && eventData.currentPoints.image;
71
-
72
- if (!goodEventData) {
73
- logger.error(
74
- `required eventData not supplied to tool ${this.name}'s createNewMeasurement`
75
- );
76
-
77
- return;
78
- }
79
-
80
- return {
81
- computeMeasurements: this.options.computeMeasurements,
82
- visible: true,
83
- active: true,
84
- color: undefined,
85
- invalidated: true,
86
- handles: {
87
- start: {
88
- x: eventData.currentPoints.image.x,
89
- y: eventData.currentPoints.image.y,
90
- highlight: true,
91
- active: false
92
- },
93
- end: {
94
- x: eventData.currentPoints.image.x,
95
- y: eventData.currentPoints.image.y,
96
- highlight: true,
97
- active: true
98
- },
99
- initialRotation: eventData.viewport.rotation,
100
- textBox: {
101
- active: false,
102
- hasMoved: false,
103
- movesIndependently: false,
104
- drawnIndependently: true,
105
- allowedOutsideImage: true,
106
- hasBoundingBox: true
107
- }
108
- }
109
- };
110
- }
111
-
112
- pointNearTool(element, data, coords, interactionType) {
113
- const hasStartAndEndHandles =
114
- data && data.handles && data.handles.start && data.handles.end;
115
- const validParameters = hasStartAndEndHandles;
116
-
117
- if (!validParameters) {
118
- logger.warn(
119
- `invalid parameters supplied to tool ${this.name}'s pointNearTool`
120
- );
121
- }
122
-
123
- if (!validParameters || data.visible === false) {
124
- return false;
125
- }
126
-
127
- const distance = interactionType === "mouse" ? 15 : 25;
128
- const startCanvas = external.cornerstone.pixelToCanvas(
129
- element,
130
- data.handles.start
131
- );
132
- const endCanvas = external.cornerstone.pixelToCanvas(
133
- element,
134
- data.handles.end
135
- );
136
-
137
- const rect = {
138
- left: Math.min(startCanvas.x, endCanvas.x),
139
- top: Math.min(startCanvas.y, endCanvas.y),
140
- width: Math.abs(startCanvas.x - endCanvas.x),
141
- height: Math.abs(startCanvas.y - endCanvas.y)
142
- };
143
-
144
- const distanceToPoint = external.cornerstoneMath.rect.distanceToPoint(
145
- rect,
146
- coords
147
- );
148
-
149
- return distanceToPoint < distance;
150
- }
151
-
152
- updateCachedStats(image, element, data) {
153
- if (data.computeMeasurements) {
154
- const seriesModule =
155
- external.cornerstone.metaData.get(
156
- "generalSeriesModule",
157
- image.imageId
158
- ) || {};
159
- const modality = seriesModule.modality;
160
- const pixelSpacing = getPixelSpacing(image);
161
-
162
- const stats = _calculateStats(
163
- image,
164
- element,
165
- data.handles,
166
- modality,
167
- pixelSpacing
168
- );
169
-
170
- data.cachedStats = stats;
171
- }
172
-
173
- data.invalidated = false;
174
- }
175
-
176
- renderToolData(evt) {
177
- const toolData = getToolState(evt.currentTarget, this.name);
178
-
179
- if (!toolData) {
180
- return;
181
- }
182
-
183
- const eventData = evt.detail;
184
- const { image, element } = eventData;
185
- const lineWidth = toolStyle.getToolWidth();
186
- const lineDash = getModule("globalConfiguration").configuration.lineDash;
187
- const {
188
- handleRadius,
189
- drawHandlesOnHover,
190
- hideHandlesIfMoving,
191
- renderDashed
192
- } = this.configuration;
193
- const context = getNewContext(eventData.canvasContext.canvas);
194
- const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image);
195
-
196
- // Meta
197
- const seriesModule =
198
- external.cornerstone.metaData.get("generalSeriesModule", image.imageId) ||
199
- {};
200
-
201
- // Pixel Spacing
202
- const modality = seriesModule.modality;
203
- const hasPixelSpacing = rowPixelSpacing && colPixelSpacing;
204
-
205
- draw(context, context => {
206
- // If we have tool data for this element - iterate over each set and draw it
207
- for (let i = 0; i < toolData.data.length; i++) {
208
- const data = toolData.data[i];
209
-
210
- if (data.visible === false) {
211
- continue;
212
- }
213
-
214
- // Configure
215
- const color = toolColors.getColorIfActive(data);
216
- const handleOptions = {
217
- color,
218
- handleRadius,
219
- drawHandlesIfActive: drawHandlesOnHover,
220
- hideHandlesIfMoving
221
- };
222
-
223
- setShadow(context, this.configuration);
224
-
225
- const rectOptions = { color };
226
-
227
- if (renderDashed) {
228
- rectOptions.lineDash = lineDash;
229
- }
230
-
231
- // Draw
232
- drawRect(
233
- context,
234
- element,
235
- data.handles.start,
236
- data.handles.end,
237
- rectOptions,
238
- "pixel",
239
- data.handles.initialRotation
240
- );
241
-
242
- if (this.configuration.drawHandles) {
243
- drawHandles(context, eventData, data.handles, handleOptions);
244
- }
245
-
246
- if (data.computeMeasurements) {
247
- // Update textbox stats
248
- if (data.invalidated === true) {
249
- if (data.cachedStats) {
250
- this.throttledUpdateCachedStats(image, element, data);
251
- } else {
252
- this.updateCachedStats(image, element, data);
253
- }
254
- }
255
-
256
- // Default to textbox on right side of ROI
257
- if (!data.handles.textBox.hasMoved) {
258
- const defaultCoords = getROITextBoxCoords(
259
- eventData.viewport,
260
- data.handles
261
- );
262
-
263
- Object.assign(data.handles.textBox, defaultCoords);
264
- }
265
-
266
- const textBoxAnchorPoints = handles =>
267
- _findTextBoxAnchorPoints(handles.start, handles.end);
268
- const textBoxContent = _createTextBoxContent(
269
- context,
270
- image.color,
271
- data.cachedStats,
272
- modality,
273
- hasPixelSpacing,
274
- this.configuration
275
- );
276
-
277
- data.unit = _getUnit(
278
- modality,
279
- this.configuration.showHounsfieldUnits
280
- );
281
-
282
- drawLinkedTextBox(
283
- context,
284
- element,
285
- data.handles.textBox,
286
- textBoxContent,
287
- data.handles,
288
- textBoxAnchorPoints,
289
- color,
290
- lineWidth,
291
- 10,
292
- true
293
- );
294
- }
295
- }
296
- });
297
- }
298
- }
299
-
300
- /**
301
- * TODO: This is the same method (+ GetPixels) for the other ROIs
302
- * TODO: The pixel filtering is the unique bit
303
- *
304
- * @param {*} startHandle
305
- * @param {*} endHandle
306
- * @returns {{ left: number, top: number, width: number, height: number}}
307
- */
308
- function _getRectangleImageCoordinates(startHandle, endHandle) {
309
- return {
310
- left: Math.min(startHandle.x, endHandle.x),
311
- top: Math.min(startHandle.y, endHandle.y),
312
- width: Math.abs(startHandle.x - endHandle.x),
313
- height: Math.abs(startHandle.y - endHandle.y)
314
- };
315
- }
316
-
317
- /**
318
- *
319
- *
320
- * @param {*} image
321
- * @param {*} element
322
- * @param {*} handles
323
- * @param {*} modality
324
- * @param {*} pixelSpacing
325
- * @returns {Object} The Stats object
326
- */
327
- function _calculateStats(image, element, handles, modality, pixelSpacing) {
328
- // Retrieve the bounds of the rectangle in image coordinates
329
- const roiCoordinates = _getRectangleImageCoordinates(
330
- handles.start,
331
- handles.end
332
- );
333
-
334
- // Retrieve the array of pixels that the rectangle bounds cover
335
- const pixels = external.cornerstone.getPixels(
336
- element,
337
- roiCoordinates.left,
338
- roiCoordinates.top,
339
- roiCoordinates.width,
340
- roiCoordinates.height
341
- );
342
-
343
- // Calculate the mean & standard deviation from the pixels and the rectangle details
344
- const roiMeanStdDev = _calculateRectangleStats(pixels, roiCoordinates);
345
-
346
- let meanStdDevSUV;
347
-
348
- if (modality === "PT") {
349
- meanStdDevSUV = {
350
- mean: calculateSUV(image, roiMeanStdDev.mean, true) || 0,
351
- stdDev: calculateSUV(image, roiMeanStdDev.stdDev, true) || 0
352
- };
353
- }
354
-
355
- // Calculate the image area from the rectangle dimensions and pixel spacing
356
- const area =
357
- roiCoordinates.width *
358
- (pixelSpacing.colPixelSpacing || 1) *
359
- (roiCoordinates.height * (pixelSpacing.rowPixelSpacing || 1));
360
-
361
- const perimeter =
362
- roiCoordinates.width * 2 * (pixelSpacing.colPixelSpacing || 1) +
363
- roiCoordinates.height * 2 * (pixelSpacing.rowPixelSpacing || 1);
364
-
365
- return {
366
- area: area || 0,
367
- perimeter,
368
- count: roiMeanStdDev.count || 0,
369
- mean: roiMeanStdDev.mean || 0,
370
- variance: roiMeanStdDev.variance || 0,
371
- stdDev: roiMeanStdDev.stdDev || 0,
372
- min: roiMeanStdDev.min || 0,
373
- max: roiMeanStdDev.max || 0,
374
- meanStdDevSUV
375
- };
376
- }
377
-
378
- /**
379
- *
380
- *
381
- * @param {*} sp
382
- * @param {*} rectangle
383
- * @returns {{ count, number, mean: number, variance: number, stdDev: number, min: number, max: number }}
384
- */
385
- function _calculateRectangleStats(sp, rectangle) {
386
- let sum = 0;
387
- let sumSquared = 0;
388
- let count = 0;
389
- let index = 0;
390
- let min = sp ? sp[0] : null;
391
- let max = sp ? sp[0] : null;
392
-
393
- for (let y = rectangle.top; y < rectangle.top + rectangle.height; y++) {
394
- for (let x = rectangle.left; x < rectangle.left + rectangle.width; x++) {
395
- sum += sp[index];
396
- sumSquared += sp[index] * sp[index];
397
- min = Math.min(min, sp[index]);
398
- max = Math.max(max, sp[index]);
399
- count++; // TODO: Wouldn't this just be sp.length?
400
- index++;
401
- }
402
- }
403
-
404
- if (count === 0) {
405
- return {
406
- count,
407
- mean: 0.0,
408
- variance: 0.0,
409
- stdDev: 0.0,
410
- min: 0.0,
411
- max: 0.0
412
- };
413
- }
414
-
415
- const mean = sum / count;
416
- const variance = sumSquared / count - mean * mean;
417
-
418
- return {
419
- count,
420
- mean,
421
- variance,
422
- stdDev: Math.sqrt(variance),
423
- min,
424
- max
425
- };
426
- }
427
-
428
- /**
429
- *
430
- *
431
- * @param {*} startHandle
432
- * @param {*} endHandle
433
- * @returns {Array.<{x: number, y: number}>}
434
- */
435
- function _findTextBoxAnchorPoints(startHandle, endHandle) {
436
- const { left, top, width, height } = _getRectangleImageCoordinates(
437
- startHandle,
438
- endHandle
439
- );
440
-
441
- return [
442
- {
443
- // Top middle point of rectangle
444
- x: left + width / 2,
445
- y: top
446
- },
447
- {
448
- // Left middle point of rectangle
449
- x: left,
450
- y: top + height / 2
451
- },
452
- {
453
- // Bottom middle point of rectangle
454
- x: left + width / 2,
455
- y: top + height
456
- },
457
- {
458
- // Right middle point of rectangle
459
- x: left + width,
460
- y: top + height / 2
461
- }
462
- ];
463
- }
464
-
465
- /**
466
- *
467
- *
468
- * @param {*} area
469
- * @param {*} hasPixelSpacing
470
- * @returns {string} The formatted label for showing area
471
- */
472
- function _formatArea(area, hasPixelSpacing) {
473
- // This uses Char code 178 for a superscript 2
474
- const suffix = hasPixelSpacing
475
- ? ` mm${String.fromCharCode(178)}`
476
- : ` px${String.fromCharCode(178)}`;
477
-
478
- return `Area: ${numbersWithCommas(area.toFixed(2))}${suffix}`;
479
- }
480
-
481
- function _getUnit(modality, showHounsfieldUnits) {
482
- return modality === "CT" && showHounsfieldUnits !== false ? "HU" : "";
483
- }
484
-
485
- /**
486
- * TODO: This is identical to EllipticalROI's same fn
487
- * TODO: We may want to make this a utility for ROIs with these values?
488
- *
489
- * @param {*} context
490
- * @param {*} isColorImage
491
- * @param {*} { area, mean, stdDev, min, max, meanStdDevSUV }
492
- * @param {*} modality
493
- * @param {*} hasPixelSpacing
494
- * @param {*} [options={}]
495
- * @returns {string[]}
496
- */
497
- function _createTextBoxContent(
498
- context,
499
- isColorImage,
500
- { area = 0, mean = 0, stdDev = 0, min = 0, max = 0, meanStdDevSUV = 0 } = {},
501
- modality,
502
- hasPixelSpacing,
503
- options = {}
504
- ) {
505
- const showMinMax = options.showMinMax || false;
506
- const textLines = [];
507
-
508
- const otherLines = [];
509
-
510
- if (!isColorImage) {
511
- const hasStandardUptakeValues = meanStdDevSUV && meanStdDevSUV.mean !== 0;
512
- const unit = _getUnit(modality, options.showHounsfieldUnits);
513
-
514
- let meanString = `Mean: ${numbersWithCommas(mean.toFixed(2))} ${unit}`;
515
- const stdDevString = `Std Dev: ${numbersWithCommas(
516
- stdDev.toFixed(2)
517
- )} ${unit}`;
518
-
519
- // If this image has SUV values to display, concatenate them to the text line
520
- if (hasStandardUptakeValues) {
521
- const SUVtext = " SUV: ";
522
-
523
- const meanSuvString = `${SUVtext}${numbersWithCommas(
524
- meanStdDevSUV.mean.toFixed(2)
525
- )}`;
526
- const stdDevSuvString = `${SUVtext}${numbersWithCommas(
527
- meanStdDevSUV.stdDev.toFixed(2)
528
- )}`;
529
-
530
- const targetStringLength = Math.floor(
531
- context.measureText(`${stdDevString} `).width
532
- );
533
-
534
- while (context.measureText(meanString).width < targetStringLength) {
535
- meanString += " ";
536
- }
537
-
538
- otherLines.push(`${meanString}${meanSuvString}`);
539
- otherLines.push(`${stdDevString} ${stdDevSuvString}`);
540
- } else {
541
- otherLines.push(`${meanString}`);
542
- otherLines.push(`${stdDevString}`);
543
- }
544
-
545
- if (showMinMax) {
546
- let minString = `Min: ${min} ${unit}`;
547
- const maxString = `Max: ${max} ${unit}`;
548
- const targetStringLength = hasStandardUptakeValues
549
- ? Math.floor(context.measureText(`${stdDevString} `).width)
550
- : Math.floor(context.measureText(`${meanString} `).width);
551
-
552
- while (context.measureText(minString).width < targetStringLength) {
553
- minString += " ";
554
- }
555
-
556
- otherLines.push(`${minString}${maxString}`);
557
- }
558
- }
559
-
560
- textLines.push(_formatArea(area, hasPixelSpacing));
561
- otherLines.forEach(x => textLines.push(x));
562
-
563
- return textLines;
564
- }