@cornerstonejs/tools 2.0.0-beta.22 → 2.0.0-beta.23
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/index.d.ts +2 -2
- package/dist/esm/index.js +2 -2
- package/dist/esm/stateManagement/index.d.ts +2 -0
- package/dist/esm/stateManagement/index.js +2 -2
- package/dist/esm/tools/annotation/BidirectionalTool.js +6 -6
- package/dist/esm/tools/annotation/CircleROITool.js +12 -12
- package/dist/esm/tools/annotation/DragProbeTool.js +2 -2
- package/dist/esm/tools/annotation/EllipticalROITool.js +11 -11
- package/dist/esm/tools/annotation/HeightTool.js +4 -4
- package/dist/esm/tools/annotation/LengthTool.js +4 -4
- package/dist/esm/tools/annotation/PlanarFreehandROITool.d.ts +4 -4
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js +19 -19
- package/dist/esm/tools/annotation/ProbeTool.js +8 -8
- package/dist/esm/tools/annotation/RectangleROITool.js +11 -11
- package/dist/esm/tools/annotation/SplineROITool.js +6 -6
- package/dist/esm/tools/index.d.ts +1 -3
- package/dist/esm/tools/index.js +1 -3
- package/dist/esm/tools/segmentation/CircleROIStartEndThresholdTool.js +8 -8
- package/dist/esm/tools/segmentation/RectangleROIStartEndThresholdTool.js +8 -8
- package/dist/esm/types/ToolSpecificAnnotationTypes.d.ts +2 -2
- package/dist/esm/utilities/getCalibratedUnits.d.ts +2 -2
- package/dist/esm/utilities/getCalibratedUnits.js +13 -13
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/esm/tools/StackScrollToolMouseWheelTool.d.ts +0 -16
- package/dist/esm/tools/StackScrollToolMouseWheelTool.js +0 -33
package/dist/esm/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import * as cursors from './cursors';
|
|
|
9
9
|
import * as Types from './types';
|
|
10
10
|
import * as annotation from './stateManagement/annotation';
|
|
11
11
|
import * as segmentation from './stateManagement/segmentation';
|
|
12
|
-
import { BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, ZoomTool, StackScrollTool, PlanarRotateTool,
|
|
12
|
+
import { BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, ZoomTool, StackScrollTool, PlanarRotateTool, VolumeRotateMouseWheelTool, MIPJumpToClickTool, LengthTool, HeightTool, ProbeTool, RectangleROITool, EllipticalROITool, CircleROITool, SplineROITool, SplineContourSegmentationTool, BidirectionalTool, PlanarFreehandROITool, PlanarFreehandContourSegmentationTool, LivewireContourTool, LivewireContourSegmentationTool, ArrowAnnotateTool, KeyImageTool, CrosshairsTool, ReferenceLinesTool, RectangleScissorsTool, CircleScissorsTool, SphereScissorsTool, RectangleROIThresholdTool, RectangleROIStartEndThresholdTool, CircleROIStartEndThresholdTool, BrushTool, AngleTool, CobbAngleTool, UltrasoundDirectionalTool, MagnifyTool, AdvancedMagnifyTool, ReferenceCursors, PaintFillTool, ScaleOverlayTool, OrientationMarkerTool, OverlayGridTool, SegmentationIntersectionTool, EraserTool, SculptorTool, SegmentSelectTool, WindowLevelRegionTool } from './tools';
|
|
13
13
|
import VideoRedactionTool from './tools/annotation/VideoRedactionTool';
|
|
14
14
|
import * as Enums from './enums';
|
|
15
|
-
export { VideoRedactionTool, init, destroy, addTool, removeTool, cancelActiveManipulations, BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, WindowLevelRegionTool, ZoomTool, StackScrollTool, PlanarRotateTool,
|
|
15
|
+
export { VideoRedactionTool, init, destroy, addTool, removeTool, cancelActiveManipulations, BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, WindowLevelRegionTool, ZoomTool, StackScrollTool, PlanarRotateTool, VolumeRotateMouseWheelTool, MIPJumpToClickTool, LengthTool, HeightTool, CrosshairsTool, ReferenceLinesTool, OverlayGridTool, SegmentationIntersectionTool, ProbeTool, RectangleROITool, EllipticalROITool, CircleROITool, SplineROITool, SplineContourSegmentationTool, BidirectionalTool, PlanarFreehandROITool, PlanarFreehandContourSegmentationTool, LivewireContourTool, LivewireContourSegmentationTool, ArrowAnnotateTool, AngleTool, CobbAngleTool, UltrasoundDirectionalTool, KeyImageTool, MagnifyTool, AdvancedMagnifyTool, ReferenceCursors, ScaleOverlayTool, SculptorTool, EraserTool, RectangleScissorsTool, CircleScissorsTool, SphereScissorsTool, RectangleROIThresholdTool, RectangleROIStartEndThresholdTool, CircleROIStartEndThresholdTool, BrushTool, OrientationMarkerTool, SegmentSelectTool, synchronizers, Synchronizer, SynchronizerManager, PaintFillTool, Types, state, ToolGroupManager, Enums, CONSTANTS, drawing, annotation, segmentation, utilities, cursors, };
|
package/dist/esm/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import * as cursors from './cursors';
|
|
|
9
9
|
import * as Types from './types';
|
|
10
10
|
import * as annotation from './stateManagement/annotation';
|
|
11
11
|
import * as segmentation from './stateManagement/segmentation';
|
|
12
|
-
import { BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, ZoomTool, StackScrollTool, PlanarRotateTool,
|
|
12
|
+
import { BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, ZoomTool, StackScrollTool, PlanarRotateTool, VolumeRotateMouseWheelTool, MIPJumpToClickTool, LengthTool, HeightTool, ProbeTool, RectangleROITool, EllipticalROITool, CircleROITool, SplineROITool, SplineContourSegmentationTool, BidirectionalTool, PlanarFreehandROITool, PlanarFreehandContourSegmentationTool, LivewireContourTool, LivewireContourSegmentationTool, ArrowAnnotateTool, KeyImageTool, CrosshairsTool, ReferenceLinesTool, RectangleScissorsTool, CircleScissorsTool, SphereScissorsTool, RectangleROIThresholdTool, RectangleROIStartEndThresholdTool, CircleROIStartEndThresholdTool, BrushTool, AngleTool, CobbAngleTool, UltrasoundDirectionalTool, MagnifyTool, AdvancedMagnifyTool, ReferenceCursors, PaintFillTool, ScaleOverlayTool, OrientationMarkerTool, OverlayGridTool, SegmentationIntersectionTool, EraserTool, SculptorTool, SegmentSelectTool, WindowLevelRegionTool, } from './tools';
|
|
13
13
|
import VideoRedactionTool from './tools/annotation/VideoRedactionTool';
|
|
14
14
|
import * as Enums from './enums';
|
|
15
|
-
export { VideoRedactionTool, init, destroy, addTool, removeTool, cancelActiveManipulations, BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, WindowLevelRegionTool, ZoomTool, StackScrollTool, PlanarRotateTool,
|
|
15
|
+
export { VideoRedactionTool, init, destroy, addTool, removeTool, cancelActiveManipulations, BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, WindowLevelRegionTool, ZoomTool, StackScrollTool, PlanarRotateTool, VolumeRotateMouseWheelTool, MIPJumpToClickTool, LengthTool, HeightTool, CrosshairsTool, ReferenceLinesTool, OverlayGridTool, SegmentationIntersectionTool, ProbeTool, RectangleROITool, EllipticalROITool, CircleROITool, SplineROITool, SplineContourSegmentationTool, BidirectionalTool, PlanarFreehandROITool, PlanarFreehandContourSegmentationTool, LivewireContourTool, LivewireContourSegmentationTool, ArrowAnnotateTool, AngleTool, CobbAngleTool, UltrasoundDirectionalTool, KeyImageTool, MagnifyTool, AdvancedMagnifyTool, ReferenceCursors, ScaleOverlayTool, SculptorTool, EraserTool, RectangleScissorsTool, CircleScissorsTool, SphereScissorsTool, RectangleROIThresholdTool, RectangleROIStartEndThresholdTool, CircleROIStartEndThresholdTool, BrushTool, OrientationMarkerTool, SegmentSelectTool, synchronizers, Synchronizer, SynchronizerManager, PaintFillTool, Types, state, ToolGroupManager, Enums, CONSTANTS, drawing, annotation, segmentation, utilities, cursors, };
|
|
@@ -15,4 +15,6 @@ import { setAnnotationManager } from './annotation/annotationState';
|
|
|
15
15
|
import { getAnnotationManager } from './annotation/annotationState';
|
|
16
16
|
import { resetAnnotationManager } from './annotation/annotationState';
|
|
17
17
|
import { invalidateAnnotation } from './annotation/annotationState';
|
|
18
|
+
import addSegmentationRepresentations from './segmentation/addSegmentationRepresentations';
|
|
19
|
+
import removeSegmentationRepresentations from './segmentation/removeSegmentationRepresentations';
|
|
18
20
|
export { FrameOfReferenceSpecificAnnotationManager, defaultFrameOfReferenceSpecificAnnotationManager, annotationLocking, annotationSelection, getAnnotations, addAnnotation, getNumberOfAnnotations, removeAnnotation, getAnnotation, getParentAnnotation, getChildAnnotations, clearParentAnnotation, addChildAnnotation, setAnnotationManager, getAnnotationManager, resetAnnotationManager, invalidateAnnotation, addSegmentationRepresentations, removeSegmentationRepresentations };
|
|
@@ -2,6 +2,6 @@ import FrameOfReferenceSpecificAnnotationManager, { defaultFrameOfReferenceSpeci
|
|
|
2
2
|
import * as annotationLocking from './annotation/annotationLocking';
|
|
3
3
|
import * as annotationSelection from './annotation/annotationSelection';
|
|
4
4
|
import { getAnnotations, addAnnotation, removeAnnotation, getAnnotation, getParentAnnotation, getChildAnnotations, clearParentAnnotation, addChildAnnotation, getNumberOfAnnotations, setAnnotationManager, getAnnotationManager, resetAnnotationManager, invalidateAnnotation, } from './annotation/annotationState';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import addSegmentationRepresentations from './segmentation/addSegmentationRepresentations';
|
|
6
|
+
import removeSegmentationRepresentations from './segmentation/removeSegmentationRepresentations';
|
|
7
7
|
export { FrameOfReferenceSpecificAnnotationManager, defaultFrameOfReferenceSpecificAnnotationManager, annotationLocking, annotationSelection, getAnnotations, addAnnotation, getNumberOfAnnotations, removeAnnotation, getAnnotation, getParentAnnotation, getChildAnnotations, clearParentAnnotation, addChildAnnotation, setAnnotationManager, getAnnotationManager, resetAnnotationManager, invalidateAnnotation, addSegmentationRepresentations, removeSegmentationRepresentations, };
|
|
@@ -608,13 +608,13 @@ class BidirectionalTool extends AnnotationTool {
|
|
|
608
608
|
const index4 = transformWorldToIndex(imageData, worldPos4);
|
|
609
609
|
const handles1 = [index1, index2];
|
|
610
610
|
const handles2 = [index3, index4];
|
|
611
|
-
const { scale: scale1,
|
|
612
|
-
const { scale: scale2,
|
|
611
|
+
const { scale: scale1, unit: units1 } = getCalibratedLengthUnitsAndScale(image, handles1);
|
|
612
|
+
const { scale: scale2, unit: units2 } = getCalibratedLengthUnitsAndScale(image, handles2);
|
|
613
613
|
const dist1 = this._calculateLength(worldPos1, worldPos2) / scale1;
|
|
614
614
|
const dist2 = this._calculateLength(worldPos3, worldPos4) / scale2;
|
|
615
615
|
const length = dist1 > dist2 ? dist1 : dist2;
|
|
616
616
|
const width = dist1 > dist2 ? dist2 : dist1;
|
|
617
|
-
const
|
|
617
|
+
const unit = dist1 > dist2 ? units1 : units2;
|
|
618
618
|
const widthUnit = dist1 > dist2 ? units2 : units1;
|
|
619
619
|
this._isInsideVolume(index1, index2, index3, index4, dimensions)
|
|
620
620
|
? (this.isHandleOutsideImage = false)
|
|
@@ -622,7 +622,7 @@ class BidirectionalTool extends AnnotationTool {
|
|
|
622
622
|
cachedStats[targetId] = {
|
|
623
623
|
length,
|
|
624
624
|
width,
|
|
625
|
-
|
|
625
|
+
unit,
|
|
626
626
|
widthUnit,
|
|
627
627
|
};
|
|
628
628
|
}
|
|
@@ -712,7 +712,7 @@ class BidirectionalTool extends AnnotationTool {
|
|
|
712
712
|
}
|
|
713
713
|
function defaultGetTextLines(data, targetId) {
|
|
714
714
|
const { cachedStats, label } = data;
|
|
715
|
-
const { length, width, unit
|
|
715
|
+
const { length, width, unit } = cachedStats[targetId];
|
|
716
716
|
const textLines = [];
|
|
717
717
|
if (label) {
|
|
718
718
|
textLines.push(label);
|
|
@@ -720,7 +720,7 @@ function defaultGetTextLines(data, targetId) {
|
|
|
720
720
|
if (length === undefined) {
|
|
721
721
|
return textLines;
|
|
722
722
|
}
|
|
723
|
-
textLines.push(`L: ${csUtils.roundNumber(length)} ${
|
|
723
|
+
textLines.push(`L: ${csUtils.roundNumber(length)} ${unit || unit}`, `W: ${csUtils.roundNumber(width)} ${unit}`);
|
|
724
724
|
return textLines;
|
|
725
725
|
}
|
|
726
726
|
BidirectionalTool.toolName = 'Bidirectional';
|
|
@@ -346,14 +346,14 @@ class CircleROITool extends AnnotationTool {
|
|
|
346
346
|
const canvasCorners = getCanvasCircleCorners(canvasCoordinates);
|
|
347
347
|
const { centerPointRadius } = this.configuration;
|
|
348
348
|
if (!data.cachedStats[targetId] ||
|
|
349
|
-
data.cachedStats[targetId].
|
|
349
|
+
data.cachedStats[targetId].areaUnit == null) {
|
|
350
350
|
data.cachedStats[targetId] = {
|
|
351
351
|
Modality: null,
|
|
352
352
|
area: null,
|
|
353
353
|
max: null,
|
|
354
354
|
mean: null,
|
|
355
355
|
stdDev: null,
|
|
356
|
-
|
|
356
|
+
areaUnit: null,
|
|
357
357
|
radius: null,
|
|
358
358
|
radiusUnit: null,
|
|
359
359
|
perimeter: null,
|
|
@@ -507,7 +507,7 @@ class CircleROITool extends AnnotationTool {
|
|
|
507
507
|
const { worldWidth, worldHeight } = getWorldWidthAndHeightFromTwoPoints(viewPlaneNormal, viewUp, worldPos1, worldPos2);
|
|
508
508
|
const isEmptyArea = worldWidth === 0 && worldHeight === 0;
|
|
509
509
|
const handles = [pos1Index, pos2Index];
|
|
510
|
-
const { scale,
|
|
510
|
+
const { scale, unit, areaUnit } = getCalibratedLengthUnitsAndScale(image, handles);
|
|
511
511
|
const aspect = getCalibratedAspect(image);
|
|
512
512
|
const area = Math.abs(Math.PI *
|
|
513
513
|
(worldWidth / scale / 2) *
|
|
@@ -516,7 +516,7 @@ class CircleROITool extends AnnotationTool {
|
|
|
516
516
|
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
517
517
|
isSuvScaled: this.isSuvScaled(viewport, targetId, annotation.metadata.referencedImageId),
|
|
518
518
|
};
|
|
519
|
-
const
|
|
519
|
+
const modalityUnit = getPixelValueUnits(metadata.Modality, annotation.metadata.referencedImageId, pixelUnitsOptions);
|
|
520
520
|
const pointsInShape = voxelManager.forEach(this.configuration.statsCalculator.statsCallback, {
|
|
521
521
|
isInObject: (pointLPS) => pointInEllipse(ellipseObj, pointLPS, { fast: true }),
|
|
522
522
|
boundsIJK,
|
|
@@ -533,11 +533,11 @@ class CircleROITool extends AnnotationTool {
|
|
|
533
533
|
statsArray: stats.array,
|
|
534
534
|
pointsInShape: pointsInShape,
|
|
535
535
|
isEmptyArea,
|
|
536
|
-
|
|
536
|
+
areaUnit,
|
|
537
537
|
radius: worldWidth / 2 / scale,
|
|
538
|
-
radiusUnit:
|
|
538
|
+
radiusUnit: unit,
|
|
539
539
|
perimeter: (2 * Math.PI * (worldWidth / 2)) / scale,
|
|
540
|
-
|
|
540
|
+
modalityUnit,
|
|
541
541
|
};
|
|
542
542
|
}
|
|
543
543
|
else {
|
|
@@ -560,7 +560,7 @@ class CircleROITool extends AnnotationTool {
|
|
|
560
560
|
}
|
|
561
561
|
function defaultGetTextLines(data, targetId) {
|
|
562
562
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
563
|
-
const { radius, radiusUnit, area, mean, stdDev, max, isEmptyArea,
|
|
563
|
+
const { radius, radiusUnit, area, mean, stdDev, max, isEmptyArea, areaUnit, modalityUnit, } = cachedVolumeStats;
|
|
564
564
|
const textLines = [];
|
|
565
565
|
if (radius) {
|
|
566
566
|
const radiusLine = isEmptyArea
|
|
@@ -571,17 +571,17 @@ function defaultGetTextLines(data, targetId) {
|
|
|
571
571
|
if (area) {
|
|
572
572
|
const areaLine = isEmptyArea
|
|
573
573
|
? `Area: Oblique not supported`
|
|
574
|
-
: `Area: ${csUtils.roundNumber(area)} ${
|
|
574
|
+
: `Area: ${csUtils.roundNumber(area)} ${areaUnit}`;
|
|
575
575
|
textLines.push(areaLine);
|
|
576
576
|
}
|
|
577
577
|
if (mean) {
|
|
578
|
-
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${
|
|
578
|
+
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${modalityUnit}`);
|
|
579
579
|
}
|
|
580
580
|
if (max) {
|
|
581
|
-
textLines.push(`Max: ${csUtils.roundNumber(max)} ${
|
|
581
|
+
textLines.push(`Max: ${csUtils.roundNumber(max)} ${modalityUnit}`);
|
|
582
582
|
}
|
|
583
583
|
if (stdDev) {
|
|
584
|
-
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${
|
|
584
|
+
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${modalityUnit}`);
|
|
585
585
|
}
|
|
586
586
|
return textLines;
|
|
587
587
|
}
|
|
@@ -117,13 +117,13 @@ class DragProbeTool extends ProbeTool {
|
|
|
117
117
|
}
|
|
118
118
|
function defaultGetTextLines(data, targetId) {
|
|
119
119
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
120
|
-
const { index, value,
|
|
120
|
+
const { index, value, modalityUnit } = cachedVolumeStats;
|
|
121
121
|
if (value === undefined) {
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
124
124
|
const textLines = [];
|
|
125
125
|
textLines.push(`(${index[0]}, ${index[1]}, ${index[2]})`);
|
|
126
|
-
textLines.push(`${value.toFixed(2)} ${
|
|
126
|
+
textLines.push(`${value.toFixed(2)} ${modalityUnit}`);
|
|
127
127
|
return textLines;
|
|
128
128
|
}
|
|
129
129
|
DragProbeTool.toolName = 'DragProbe';
|
|
@@ -427,14 +427,14 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
427
427
|
const canvasCorners = (getCanvasEllipseCorners(canvasCoordinates));
|
|
428
428
|
const { centerPointRadius } = this.configuration;
|
|
429
429
|
if (!data.cachedStats[targetId] ||
|
|
430
|
-
data.cachedStats[targetId].
|
|
430
|
+
data.cachedStats[targetId].areaUnit == null) {
|
|
431
431
|
data.cachedStats[targetId] = {
|
|
432
432
|
Modality: null,
|
|
433
433
|
area: null,
|
|
434
434
|
max: null,
|
|
435
435
|
mean: null,
|
|
436
436
|
stdDev: null,
|
|
437
|
-
|
|
437
|
+
areaUnit: null,
|
|
438
438
|
};
|
|
439
439
|
this._calculateCachedStats(annotation, viewport, renderingEngine);
|
|
440
440
|
}
|
|
@@ -587,7 +587,7 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
587
587
|
const { worldWidth, worldHeight } = getWorldWidthAndHeightFromTwoPoints(viewPlaneNormal, viewUp, worldPos1, worldPos2);
|
|
588
588
|
const isEmptyArea = worldWidth === 0 && worldHeight === 0;
|
|
589
589
|
const handles = [pos1Index, post2Index];
|
|
590
|
-
const { scale,
|
|
590
|
+
const { scale, areaUnit } = getCalibratedLengthUnitsAndScale(image, handles);
|
|
591
591
|
const area = Math.abs(Math.PI * (worldWidth / 2) * (worldHeight / 2)) /
|
|
592
592
|
scale /
|
|
593
593
|
scale;
|
|
@@ -595,7 +595,7 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
595
595
|
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
596
596
|
isSuvScaled: this.isSuvScaled(viewport, targetId, annotation.metadata.referencedImageId),
|
|
597
597
|
};
|
|
598
|
-
const
|
|
598
|
+
const modalityUnit = getPixelValueUnits(metadata.Modality, annotation.metadata.referencedImageId, pixelUnitsOptions);
|
|
599
599
|
const pointsInShape = voxelManager.forEach(this.configuration.statsCalculator.statsCallback, {
|
|
600
600
|
boundsIJK,
|
|
601
601
|
imageData,
|
|
@@ -612,8 +612,8 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
612
612
|
statsArray: stats.array,
|
|
613
613
|
pointsInShape,
|
|
614
614
|
isEmptyArea,
|
|
615
|
-
|
|
616
|
-
|
|
615
|
+
areaUnit,
|
|
616
|
+
modalityUnit,
|
|
617
617
|
};
|
|
618
618
|
}
|
|
619
619
|
annotation.invalidated = false;
|
|
@@ -651,22 +651,22 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
651
651
|
}
|
|
652
652
|
function defaultGetTextLines(data, targetId) {
|
|
653
653
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
654
|
-
const { area, mean, stdDev, max, isEmptyArea,
|
|
654
|
+
const { area, mean, stdDev, max, isEmptyArea, areaUnit, modalityUnit } = cachedVolumeStats;
|
|
655
655
|
const textLines = [];
|
|
656
656
|
if (area) {
|
|
657
657
|
const areaLine = isEmptyArea
|
|
658
658
|
? `Area: Oblique not supported`
|
|
659
|
-
: `Area: ${csUtils.roundNumber(area)} ${
|
|
659
|
+
: `Area: ${csUtils.roundNumber(area)} ${areaUnit}`;
|
|
660
660
|
textLines.push(areaLine);
|
|
661
661
|
}
|
|
662
662
|
if (mean) {
|
|
663
|
-
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${
|
|
663
|
+
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${modalityUnit}`);
|
|
664
664
|
}
|
|
665
665
|
if (max) {
|
|
666
|
-
textLines.push(`Max: ${csUtils.roundNumber(max)} ${
|
|
666
|
+
textLines.push(`Max: ${csUtils.roundNumber(max)} ${modalityUnit}`);
|
|
667
667
|
}
|
|
668
668
|
if (stdDev) {
|
|
669
|
-
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${
|
|
669
|
+
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${modalityUnit}`);
|
|
670
670
|
}
|
|
671
671
|
return textLines;
|
|
672
672
|
}
|
|
@@ -403,13 +403,13 @@ class HeightTool extends AnnotationTool {
|
|
|
403
403
|
const index1 = transformWorldToIndex(imageData, worldPos1);
|
|
404
404
|
const index2 = transformWorldToIndex(imageData, worldPos2);
|
|
405
405
|
const handles = [index1, index2];
|
|
406
|
-
const { scale,
|
|
406
|
+
const { scale, unit } = getCalibratedLengthUnitsAndScale(image, handles);
|
|
407
407
|
const height = this._calculateHeight(worldPos1, worldPos2) / scale;
|
|
408
408
|
const outside = this._isInsideVolume(index1, index2, dimensions);
|
|
409
409
|
this.isHandleOutsideImage = outside;
|
|
410
410
|
cachedStats[targetId] = {
|
|
411
411
|
height,
|
|
412
|
-
|
|
412
|
+
unit,
|
|
413
413
|
};
|
|
414
414
|
}
|
|
415
415
|
annotation.invalidated = false;
|
|
@@ -423,11 +423,11 @@ class HeightTool extends AnnotationTool {
|
|
|
423
423
|
}
|
|
424
424
|
function defaultGetTextLines(data, targetId) {
|
|
425
425
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
426
|
-
const { height,
|
|
426
|
+
const { height, unit } = cachedVolumeStats;
|
|
427
427
|
if (height === undefined || height === null || isNaN(height)) {
|
|
428
428
|
return;
|
|
429
429
|
}
|
|
430
|
-
const textLines = [`${csUtils.roundNumber(height)} ${
|
|
430
|
+
const textLines = [`${csUtils.roundNumber(height)} ${unit}`];
|
|
431
431
|
return textLines;
|
|
432
432
|
}
|
|
433
433
|
HeightTool.toolName = 'Height';
|
|
@@ -394,14 +394,14 @@ class LengthTool extends AnnotationTool {
|
|
|
394
394
|
const index1 = transformWorldToIndex(imageData, worldPos1);
|
|
395
395
|
const index2 = transformWorldToIndex(imageData, worldPos2);
|
|
396
396
|
const handles = [index1, index2];
|
|
397
|
-
const { scale,
|
|
397
|
+
const { scale, unit } = getCalibratedLengthUnitsAndScale(image, handles);
|
|
398
398
|
const length = this._calculateLength(worldPos1, worldPos2) / scale;
|
|
399
399
|
this._isInsideVolume(index1, index2, dimensions)
|
|
400
400
|
? (this.isHandleOutsideImage = false)
|
|
401
401
|
: (this.isHandleOutsideImage = true);
|
|
402
402
|
cachedStats[targetId] = {
|
|
403
403
|
length,
|
|
404
|
-
|
|
404
|
+
unit,
|
|
405
405
|
};
|
|
406
406
|
}
|
|
407
407
|
annotation.invalidated = false;
|
|
@@ -415,11 +415,11 @@ class LengthTool extends AnnotationTool {
|
|
|
415
415
|
}
|
|
416
416
|
function defaultGetTextLines(data, targetId) {
|
|
417
417
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
418
|
-
const { length,
|
|
418
|
+
const { length, unit } = cachedVolumeStats;
|
|
419
419
|
if (length === undefined || length === null || isNaN(length)) {
|
|
420
420
|
return;
|
|
421
421
|
}
|
|
422
|
-
const textLines = [`${csUtils.roundNumber(length)} ${
|
|
422
|
+
const textLines = [`${csUtils.roundNumber(length)} ${unit}`];
|
|
423
423
|
return textLines;
|
|
424
424
|
}
|
|
425
425
|
LengthTool.toolName = 'Length';
|
|
@@ -35,23 +35,23 @@ declare class PlanarFreehandROITool extends ContourSegmentationBaseTool {
|
|
|
35
35
|
protected renderAnnotationInstance(renderContext: AnnotationRenderContext): boolean;
|
|
36
36
|
_calculateStatsIfActive(annotation: PlanarFreehandROIAnnotation, targetId: string, viewport: any, renderingEngine: any, enabledElement: any): void;
|
|
37
37
|
private _calculateCachedStats;
|
|
38
|
-
protected updateClosedCachedStats({ viewport, points, imageData, metadata, cachedStats, targetId,
|
|
38
|
+
protected updateClosedCachedStats({ viewport, points, imageData, metadata, cachedStats, targetId, modalityUnit, canvasCoordinates, calibratedScale, }: {
|
|
39
39
|
viewport: any;
|
|
40
40
|
points: any;
|
|
41
41
|
imageData: any;
|
|
42
42
|
metadata: any;
|
|
43
43
|
cachedStats: any;
|
|
44
44
|
targetId: any;
|
|
45
|
-
|
|
45
|
+
modalityUnit: any;
|
|
46
46
|
canvasCoordinates: any;
|
|
47
47
|
calibratedScale: any;
|
|
48
48
|
}): void;
|
|
49
|
-
protected updateOpenCachedStats({ targetId, metadata, canvasCoordinates, cachedStats,
|
|
49
|
+
protected updateOpenCachedStats({ targetId, metadata, canvasCoordinates, cachedStats, modalityUnit, calibratedScale, }: {
|
|
50
50
|
targetId: any;
|
|
51
51
|
metadata: any;
|
|
52
52
|
canvasCoordinates: any;
|
|
53
53
|
cachedStats: any;
|
|
54
|
-
|
|
54
|
+
modalityUnit: any;
|
|
55
55
|
calibratedScale: any;
|
|
56
56
|
}): void;
|
|
57
57
|
private _renderStats;
|
|
@@ -148,7 +148,7 @@ class PlanarFreehandROITool extends ContourSegmentationBaseTool {
|
|
|
148
148
|
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
149
149
|
isSuvScaled: this.isSuvScaled(viewport, targetId, annotation.metadata.referencedImageId),
|
|
150
150
|
};
|
|
151
|
-
const
|
|
151
|
+
const modalityUnit = getPixelValueUnits(metadata.Modality, annotation.metadata.referencedImageId, modalityUnitOptions);
|
|
152
152
|
const calibratedScale = getCalibratedLengthUnitsAndScale(image, () => {
|
|
153
153
|
const polyline = data.contour.polyline;
|
|
154
154
|
const numPoints = polyline.length;
|
|
@@ -175,7 +175,7 @@ class PlanarFreehandROITool extends ContourSegmentationBaseTool {
|
|
|
175
175
|
imageData,
|
|
176
176
|
metadata,
|
|
177
177
|
cachedStats,
|
|
178
|
-
|
|
178
|
+
modalityUnit,
|
|
179
179
|
calibratedScale,
|
|
180
180
|
});
|
|
181
181
|
}
|
|
@@ -185,7 +185,7 @@ class PlanarFreehandROITool extends ContourSegmentationBaseTool {
|
|
|
185
185
|
canvasCoordinates,
|
|
186
186
|
targetId,
|
|
187
187
|
cachedStats,
|
|
188
|
-
|
|
188
|
+
modalityUnit,
|
|
189
189
|
calibratedScale,
|
|
190
190
|
});
|
|
191
191
|
}
|
|
@@ -365,14 +365,14 @@ class PlanarFreehandROITool extends ContourSegmentationBaseTool {
|
|
|
365
365
|
if (!this.commonData?.movingTextBox) {
|
|
366
366
|
const { data } = annotation;
|
|
367
367
|
if (!data.cachedStats[targetId] ||
|
|
368
|
-
data.cachedStats[targetId].
|
|
368
|
+
data.cachedStats[targetId].areaUnit == null) {
|
|
369
369
|
data.cachedStats[targetId] = {
|
|
370
370
|
Modality: null,
|
|
371
371
|
area: null,
|
|
372
372
|
max: null,
|
|
373
373
|
mean: null,
|
|
374
374
|
stdDev: null,
|
|
375
|
-
|
|
375
|
+
areaUnit: null,
|
|
376
376
|
};
|
|
377
377
|
this._calculateCachedStats(annotation, viewport, renderingEngine, enabledElement);
|
|
378
378
|
}
|
|
@@ -381,8 +381,8 @@ class PlanarFreehandROITool extends ContourSegmentationBaseTool {
|
|
|
381
381
|
}
|
|
382
382
|
}
|
|
383
383
|
}
|
|
384
|
-
updateClosedCachedStats({ viewport, points, imageData, metadata, cachedStats, targetId,
|
|
385
|
-
const { scale,
|
|
384
|
+
updateClosedCachedStats({ viewport, points, imageData, metadata, cachedStats, targetId, modalityUnit, canvasCoordinates, calibratedScale, }) {
|
|
385
|
+
const { scale, areaUnit, units } = calibratedScale;
|
|
386
386
|
const { voxelManager } = viewport.getImageData();
|
|
387
387
|
const canvasPoint = canvasCoordinates[0];
|
|
388
388
|
const originalWorldPoint = viewport.canvasToWorld(canvasPoint);
|
|
@@ -484,45 +484,45 @@ class PlanarFreehandROITool extends ContourSegmentationBaseTool {
|
|
|
484
484
|
stdDev: stats.stdDev?.value,
|
|
485
485
|
statsArray: stats.array,
|
|
486
486
|
pointsInShape: pointsInShape,
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
487
|
+
areaUnit,
|
|
488
|
+
modalityUnit,
|
|
489
|
+
unit: units,
|
|
490
490
|
};
|
|
491
491
|
}
|
|
492
|
-
updateOpenCachedStats({ targetId, metadata, canvasCoordinates, cachedStats,
|
|
492
|
+
updateOpenCachedStats({ targetId, metadata, canvasCoordinates, cachedStats, modalityUnit, calibratedScale, }) {
|
|
493
493
|
const { scale, units } = calibratedScale;
|
|
494
494
|
cachedStats[targetId] = {
|
|
495
495
|
Modality: metadata.Modality,
|
|
496
496
|
length: calculatePerimeter(canvasCoordinates, false) / scale,
|
|
497
|
-
|
|
497
|
+
modalityUnit,
|
|
498
498
|
getPixelValueUnitunit: units,
|
|
499
499
|
};
|
|
500
500
|
}
|
|
501
501
|
}
|
|
502
502
|
function defaultGetTextLines(data, targetId) {
|
|
503
503
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
504
|
-
const { area, mean, stdDev, length, perimeter, max, isEmptyArea,
|
|
504
|
+
const { area, mean, stdDev, length, perimeter, max, isEmptyArea, unit, areaUnit, modalityUnit, } = cachedVolumeStats || {};
|
|
505
505
|
const textLines = [];
|
|
506
506
|
if (area) {
|
|
507
507
|
const areaLine = isEmptyArea
|
|
508
508
|
? `Area: Oblique not supported`
|
|
509
|
-
: `Area: ${csUtils.roundNumber(area)} ${
|
|
509
|
+
: `Area: ${csUtils.roundNumber(area)} ${areaUnit}`;
|
|
510
510
|
textLines.push(areaLine);
|
|
511
511
|
}
|
|
512
512
|
if (mean) {
|
|
513
|
-
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${
|
|
513
|
+
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${modalityUnit}`);
|
|
514
514
|
}
|
|
515
515
|
if (Number.isFinite(max)) {
|
|
516
|
-
textLines.push(`Max: ${csUtils.roundNumber(max)} ${
|
|
516
|
+
textLines.push(`Max: ${csUtils.roundNumber(max)} ${modalityUnit}`);
|
|
517
517
|
}
|
|
518
518
|
if (stdDev) {
|
|
519
|
-
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${
|
|
519
|
+
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${modalityUnit}`);
|
|
520
520
|
}
|
|
521
521
|
if (perimeter) {
|
|
522
|
-
textLines.push(`Perimeter: ${csUtils.roundNumber(perimeter)} ${
|
|
522
|
+
textLines.push(`Perimeter: ${csUtils.roundNumber(perimeter)} ${unit}`);
|
|
523
523
|
}
|
|
524
524
|
if (length) {
|
|
525
|
-
textLines.push(`${csUtils.roundNumber(length)} ${
|
|
525
|
+
textLines.push(`${csUtils.roundNumber(length)} ${unit}`);
|
|
526
526
|
}
|
|
527
527
|
return textLines;
|
|
528
528
|
}
|
|
@@ -278,25 +278,25 @@ class ProbeTool extends AnnotationTool {
|
|
|
278
278
|
const viewport = viewports[0];
|
|
279
279
|
ijk[2] = viewport.getCurrentImageIdIndex();
|
|
280
280
|
}
|
|
281
|
-
let
|
|
281
|
+
let modalityUnit;
|
|
282
282
|
if (modality === 'US') {
|
|
283
283
|
const calibratedResults = getCalibratedProbeUnitsAndValue(image, [
|
|
284
284
|
ijk,
|
|
285
285
|
]);
|
|
286
286
|
const hasEnhancedRegionValues = calibratedResults.values.every((value) => value !== null);
|
|
287
287
|
value = (hasEnhancedRegionValues ? calibratedResults.values : value);
|
|
288
|
-
|
|
288
|
+
modalityUnit = hasEnhancedRegionValues
|
|
289
289
|
? calibratedResults.units
|
|
290
290
|
: 'raw';
|
|
291
291
|
}
|
|
292
292
|
else {
|
|
293
|
-
|
|
293
|
+
modalityUnit = getPixelValueUnits(modality, annotation.metadata.referencedImageId, pixelUnitsOptions);
|
|
294
294
|
}
|
|
295
295
|
cachedStats[targetId] = {
|
|
296
296
|
index: ijk,
|
|
297
297
|
value,
|
|
298
298
|
Modality: modality,
|
|
299
|
-
|
|
299
|
+
modalityUnit,
|
|
300
300
|
};
|
|
301
301
|
}
|
|
302
302
|
else {
|
|
@@ -314,19 +314,19 @@ class ProbeTool extends AnnotationTool {
|
|
|
314
314
|
}
|
|
315
315
|
function defaultGetTextLines(data, targetId) {
|
|
316
316
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
317
|
-
const { index, value,
|
|
317
|
+
const { index, value, modalityUnit } = cachedVolumeStats;
|
|
318
318
|
if (value === undefined) {
|
|
319
319
|
return;
|
|
320
320
|
}
|
|
321
321
|
const textLines = [];
|
|
322
322
|
textLines.push(`(${index[0]}, ${index[1]}, ${index[2]})`);
|
|
323
|
-
if (value instanceof Array &&
|
|
323
|
+
if (value instanceof Array && modalityUnit instanceof Array) {
|
|
324
324
|
for (let i = 0; i < value.length; i++) {
|
|
325
|
-
textLines.push(`${csUtils.roundNumber(value[i])} ${
|
|
325
|
+
textLines.push(`${csUtils.roundNumber(value[i])} ${modalityUnit[i]}`);
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
328
|
else {
|
|
329
|
-
textLines.push(`${csUtils.roundNumber(value)} ${
|
|
329
|
+
textLines.push(`${csUtils.roundNumber(value)} ${modalityUnit}`);
|
|
330
330
|
}
|
|
331
331
|
return textLines;
|
|
332
332
|
}
|
|
@@ -346,14 +346,14 @@ class RectangleROITool extends AnnotationTool {
|
|
|
346
346
|
});
|
|
347
347
|
const { viewPlaneNormal, viewUp } = viewport.getCamera();
|
|
348
348
|
if (!data.cachedStats[targetId] ||
|
|
349
|
-
data.cachedStats[targetId].
|
|
349
|
+
data.cachedStats[targetId].areaUnit == null) {
|
|
350
350
|
data.cachedStats[targetId] = {
|
|
351
351
|
Modality: null,
|
|
352
352
|
area: null,
|
|
353
353
|
max: null,
|
|
354
354
|
mean: null,
|
|
355
355
|
stdDev: null,
|
|
356
|
-
|
|
356
|
+
areaUnit: null,
|
|
357
357
|
};
|
|
358
358
|
this._calculateCachedStats(annotation, viewPlaneNormal, viewUp, renderingEngine, enabledElement);
|
|
359
359
|
}
|
|
@@ -487,13 +487,13 @@ class RectangleROITool extends AnnotationTool {
|
|
|
487
487
|
];
|
|
488
488
|
const { worldWidth, worldHeight } = getWorldWidthAndHeightFromCorners(viewPlaneNormal, viewUp, worldPos1, worldPos2);
|
|
489
489
|
const handles = [pos1Index, pos2Index];
|
|
490
|
-
const { scale,
|
|
490
|
+
const { scale, areaUnit } = getCalibratedLengthUnitsAndScale(image, handles);
|
|
491
491
|
const area = Math.abs(worldWidth * worldHeight) / (scale * scale);
|
|
492
492
|
const pixelUnitsOptions = {
|
|
493
493
|
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
494
494
|
isSuvScaled: this.isSuvScaled(viewport, targetId, annotation.metadata.referencedImageId),
|
|
495
495
|
};
|
|
496
|
-
const
|
|
496
|
+
const modalityUnit = getPixelValueUnits(metadata.Modality, annotation.metadata.referencedImageId, pixelUnitsOptions);
|
|
497
497
|
const pointsInShape = voxelManager.forEach(this.configuration.statsCalculator.statsCallback, {
|
|
498
498
|
boundsIJK,
|
|
499
499
|
imageData,
|
|
@@ -508,8 +508,8 @@ class RectangleROITool extends AnnotationTool {
|
|
|
508
508
|
max: stats.max?.value,
|
|
509
509
|
statsArray: stats.array,
|
|
510
510
|
pointsInShape: pointsInShape,
|
|
511
|
-
|
|
512
|
-
|
|
511
|
+
areaUnit,
|
|
512
|
+
modalityUnit,
|
|
513
513
|
};
|
|
514
514
|
}
|
|
515
515
|
else {
|
|
@@ -532,15 +532,15 @@ class RectangleROITool extends AnnotationTool {
|
|
|
532
532
|
}
|
|
533
533
|
function defaultGetTextLines(data, targetId) {
|
|
534
534
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
535
|
-
const { area, mean, max, stdDev,
|
|
535
|
+
const { area, mean, max, stdDev, areaUnit, modalityUnit } = cachedVolumeStats;
|
|
536
536
|
if (mean === undefined) {
|
|
537
537
|
return;
|
|
538
538
|
}
|
|
539
539
|
const textLines = [];
|
|
540
|
-
textLines.push(`Area: ${csUtils.roundNumber(area)} ${
|
|
541
|
-
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${
|
|
542
|
-
textLines.push(`Max: ${csUtils.roundNumber(max)} ${
|
|
543
|
-
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${
|
|
540
|
+
textLines.push(`Area: ${csUtils.roundNumber(area)} ${areaUnit}`);
|
|
541
|
+
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${modalityUnit}`);
|
|
542
|
+
textLines.push(`Max: ${csUtils.roundNumber(max)} ${modalityUnit}`);
|
|
543
|
+
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${modalityUnit}`);
|
|
544
544
|
return textLines;
|
|
545
545
|
}
|
|
546
546
|
RectangleROITool.toolName = 'RectangleROI';
|