@cornerstonejs/tools 1.4.3 → 1.4.5
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/tools/annotation/CircleROITool.d.ts +3 -2
- package/dist/cjs/tools/annotation/CircleROITool.js +15 -12
- package/dist/cjs/tools/annotation/CircleROITool.js.map +1 -1
- package/dist/cjs/tools/annotation/DragProbeTool.js +7 -5
- package/dist/cjs/tools/annotation/DragProbeTool.js.map +1 -1
- package/dist/cjs/tools/annotation/EllipticalROITool.d.ts +3 -2
- package/dist/cjs/tools/annotation/EllipticalROITool.js +15 -12
- package/dist/cjs/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/cjs/tools/annotation/PlanarFreehandROITool.d.ts +3 -2
- package/dist/cjs/tools/annotation/PlanarFreehandROITool.js +15 -12
- package/dist/cjs/tools/annotation/PlanarFreehandROITool.js.map +1 -1
- package/dist/cjs/tools/annotation/ProbeTool.d.ts +3 -3
- package/dist/cjs/tools/annotation/ProbeTool.js +19 -45
- package/dist/cjs/tools/annotation/ProbeTool.js.map +1 -1
- package/dist/cjs/tools/annotation/RectangleROITool.d.ts +2 -2
- package/dist/cjs/tools/annotation/RectangleROITool.js +15 -12
- package/dist/cjs/tools/annotation/RectangleROITool.js.map +1 -1
- package/dist/cjs/utilities/getModalityUnit.d.ts +6 -2
- package/dist/cjs/utilities/getModalityUnit.js +14 -5
- package/dist/cjs/utilities/getModalityUnit.js.map +1 -1
- package/dist/esm/tools/annotation/CircleROITool.d.ts +3 -2
- package/dist/esm/tools/annotation/CircleROITool.js +16 -13
- package/dist/esm/tools/annotation/CircleROITool.js.map +1 -1
- package/dist/esm/tools/annotation/DragProbeTool.js +7 -5
- package/dist/esm/tools/annotation/DragProbeTool.js.map +1 -1
- package/dist/esm/tools/annotation/EllipticalROITool.d.ts +3 -2
- package/dist/esm/tools/annotation/EllipticalROITool.js +16 -13
- package/dist/esm/tools/annotation/EllipticalROITool.js.map +1 -1
- package/dist/esm/tools/annotation/PlanarFreehandROITool.d.ts +3 -2
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js +16 -13
- package/dist/esm/tools/annotation/PlanarFreehandROITool.js.map +1 -1
- package/dist/esm/tools/annotation/ProbeTool.d.ts +3 -3
- package/dist/esm/tools/annotation/ProbeTool.js +16 -45
- package/dist/esm/tools/annotation/ProbeTool.js.map +1 -1
- package/dist/esm/tools/annotation/RectangleROITool.d.ts +2 -2
- package/dist/esm/tools/annotation/RectangleROITool.js +15 -12
- package/dist/esm/tools/annotation/RectangleROITool.js.map +1 -1
- package/dist/esm/utilities/getModalityUnit.d.ts +6 -2
- package/dist/esm/utilities/getModalityUnit.js +14 -5
- package/dist/esm/utilities/getModalityUnit.js.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/tools/annotation/CircleROITool.ts +33 -28
- package/src/tools/annotation/DragProbeTool.ts +23 -16
- package/src/tools/annotation/EllipticalROITool.ts +33 -29
- package/src/tools/annotation/PlanarFreehandROITool.ts +32 -27
- package/src/tools/annotation/ProbeTool.ts +44 -71
- package/src/tools/annotation/RectangleROITool.ts +30 -28
- package/src/utilities/getModalityUnit.ts +25 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.5",
|
|
4
4
|
"description": "Cornerstone3D Tools",
|
|
5
5
|
"main": "dist/umd/index.js",
|
|
6
6
|
"types": "dist/esm/index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@cornerstonejs/core": "^1.4.
|
|
30
|
+
"@cornerstonejs/core": "^1.4.5",
|
|
31
31
|
"lodash.clonedeep": "4.5.0",
|
|
32
32
|
"lodash.get": "^4.4.2"
|
|
33
33
|
},
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"type": "individual",
|
|
51
51
|
"url": "https://ohif.org/donate"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "bc26a72527d7473667954583db78dfb755e457e7"
|
|
54
54
|
}
|
|
@@ -51,7 +51,10 @@ import {
|
|
|
51
51
|
import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
|
|
52
52
|
import { pointInShapeCallback } from '../../utilities';
|
|
53
53
|
import { StyleSpecifier } from '../../types/AnnotationStyle';
|
|
54
|
-
import {
|
|
54
|
+
import {
|
|
55
|
+
ModalityUnitOptions,
|
|
56
|
+
getModalityUnit,
|
|
57
|
+
} from '../../utilities/getModalityUnit';
|
|
55
58
|
import { isViewportPreScaled } from '../../utilities/viewport/isViewportPreScaled';
|
|
56
59
|
import {
|
|
57
60
|
getCanvasCircleCorners,
|
|
@@ -661,6 +664,16 @@ class CircleROITool extends AnnotationTool {
|
|
|
661
664
|
|
|
662
665
|
const { centerPointRadius } = this.configuration;
|
|
663
666
|
|
|
667
|
+
const modalityUnitOptions = {
|
|
668
|
+
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
669
|
+
|
|
670
|
+
isSuvScaled: this.isSuvScaled(
|
|
671
|
+
viewport,
|
|
672
|
+
targetId,
|
|
673
|
+
annotation.metadata.referencedImageId
|
|
674
|
+
),
|
|
675
|
+
};
|
|
676
|
+
|
|
664
677
|
// If cachedStats does not exist, or the unit is missing (as part of import/hydration etc.),
|
|
665
678
|
// force to recalculate the stats from the points
|
|
666
679
|
if (
|
|
@@ -683,14 +696,16 @@ class CircleROITool extends AnnotationTool {
|
|
|
683
696
|
annotation,
|
|
684
697
|
viewport,
|
|
685
698
|
renderingEngine,
|
|
686
|
-
enabledElement
|
|
699
|
+
enabledElement,
|
|
700
|
+
modalityUnitOptions
|
|
687
701
|
);
|
|
688
702
|
} else if (annotation.invalidated) {
|
|
689
703
|
this._throttledCalculateCachedStats(
|
|
690
704
|
annotation,
|
|
691
705
|
viewport,
|
|
692
706
|
renderingEngine,
|
|
693
|
-
enabledElement
|
|
707
|
+
enabledElement,
|
|
708
|
+
modalityUnitOptions
|
|
694
709
|
);
|
|
695
710
|
// If the invalidated data is as a result of volumeViewport manipulation
|
|
696
711
|
// of the tools, we need to invalidate the related viewports data, so that
|
|
@@ -797,20 +812,7 @@ class CircleROITool extends AnnotationTool {
|
|
|
797
812
|
|
|
798
813
|
renderStatus = true;
|
|
799
814
|
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
const isSuvScaled = this.isSuvScaled(
|
|
803
|
-
viewport,
|
|
804
|
-
targetId,
|
|
805
|
-
annotation.metadata.referencedImageId
|
|
806
|
-
);
|
|
807
|
-
|
|
808
|
-
const textLines = this._getTextLines(
|
|
809
|
-
data,
|
|
810
|
-
targetId,
|
|
811
|
-
isPreScaled,
|
|
812
|
-
isSuvScaled
|
|
813
|
-
);
|
|
815
|
+
const textLines = this._getTextLines(data, targetId);
|
|
814
816
|
if (!textLines || textLines.length === 0) {
|
|
815
817
|
continue;
|
|
816
818
|
}
|
|
@@ -854,12 +856,7 @@ class CircleROITool extends AnnotationTool {
|
|
|
854
856
|
return renderStatus;
|
|
855
857
|
};
|
|
856
858
|
|
|
857
|
-
_getTextLines = (
|
|
858
|
-
data,
|
|
859
|
-
targetId: string,
|
|
860
|
-
isPreScaled: boolean,
|
|
861
|
-
isSuvScaled: boolean
|
|
862
|
-
): string[] => {
|
|
859
|
+
_getTextLines = (data, targetId: string): string[] => {
|
|
863
860
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
864
861
|
const {
|
|
865
862
|
radius,
|
|
@@ -871,10 +868,10 @@ class CircleROITool extends AnnotationTool {
|
|
|
871
868
|
isEmptyArea,
|
|
872
869
|
Modality,
|
|
873
870
|
areaUnit,
|
|
871
|
+
modalityUnit,
|
|
874
872
|
} = cachedVolumeStats;
|
|
875
873
|
|
|
876
874
|
const textLines: string[] = [];
|
|
877
|
-
const unit = getModalityUnit(Modality, isPreScaled, isSuvScaled);
|
|
878
875
|
|
|
879
876
|
if (radius) {
|
|
880
877
|
const radiusLine = isEmptyArea
|
|
@@ -891,15 +888,15 @@ class CircleROITool extends AnnotationTool {
|
|
|
891
888
|
}
|
|
892
889
|
|
|
893
890
|
if (mean) {
|
|
894
|
-
textLines.push(`Mean: ${mean.toFixed(2)} ${
|
|
891
|
+
textLines.push(`Mean: ${mean.toFixed(2)} ${modalityUnit}`);
|
|
895
892
|
}
|
|
896
893
|
|
|
897
894
|
if (max) {
|
|
898
|
-
textLines.push(`Max: ${max.toFixed(2)} ${
|
|
895
|
+
textLines.push(`Max: ${max.toFixed(2)} ${modalityUnit}`);
|
|
899
896
|
}
|
|
900
897
|
|
|
901
898
|
if (stdDev) {
|
|
902
|
-
textLines.push(`Std Dev: ${stdDev.toFixed(2)} ${
|
|
899
|
+
textLines.push(`Std Dev: ${stdDev.toFixed(2)} ${modalityUnit}`);
|
|
903
900
|
}
|
|
904
901
|
|
|
905
902
|
return textLines;
|
|
@@ -909,7 +906,8 @@ class CircleROITool extends AnnotationTool {
|
|
|
909
906
|
annotation,
|
|
910
907
|
viewport,
|
|
911
908
|
renderingEngine,
|
|
912
|
-
enabledElement
|
|
909
|
+
enabledElement,
|
|
910
|
+
modalityUnitOptions: ModalityUnitOptions
|
|
913
911
|
) => {
|
|
914
912
|
const data = annotation.data;
|
|
915
913
|
const { viewportId, renderingEngineId } = enabledElement;
|
|
@@ -1037,6 +1035,12 @@ class CircleROITool extends AnnotationTool {
|
|
|
1037
1035
|
stdDev /= count;
|
|
1038
1036
|
stdDev = Math.sqrt(stdDev);
|
|
1039
1037
|
|
|
1038
|
+
const modalityUnit = getModalityUnit(
|
|
1039
|
+
metadata.Modality,
|
|
1040
|
+
annotation.metadata.referencedImageId,
|
|
1041
|
+
modalityUnitOptions
|
|
1042
|
+
);
|
|
1043
|
+
|
|
1040
1044
|
cachedStats[targetId] = {
|
|
1041
1045
|
Modality: metadata.Modality,
|
|
1042
1046
|
area,
|
|
@@ -1048,6 +1052,7 @@ class CircleROITool extends AnnotationTool {
|
|
|
1048
1052
|
radius: worldWidth / 2,
|
|
1049
1053
|
radiusUnit: hasPixelSpacing ? 'mm' : 'px',
|
|
1050
1054
|
perimeter: 2 * Math.PI * (worldWidth / 2),
|
|
1055
|
+
modalityUnit,
|
|
1051
1056
|
};
|
|
1052
1057
|
} else {
|
|
1053
1058
|
this.isHandleOutsideImage = true;
|
|
@@ -155,6 +155,16 @@ class DragProbeTool extends ProbeTool {
|
|
|
155
155
|
|
|
156
156
|
const color = this.getStyle('color', styleSpecifier, annotation);
|
|
157
157
|
|
|
158
|
+
const modalityUnitOptions = {
|
|
159
|
+
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
160
|
+
|
|
161
|
+
isSuvScaled: this.isSuvScaled(
|
|
162
|
+
viewport,
|
|
163
|
+
targetId,
|
|
164
|
+
annotation.metadata.referencedImageId
|
|
165
|
+
),
|
|
166
|
+
};
|
|
167
|
+
|
|
158
168
|
if (!data.cachedStats[targetId]) {
|
|
159
169
|
data.cachedStats[targetId] = {
|
|
160
170
|
Modality: null,
|
|
@@ -162,9 +172,19 @@ class DragProbeTool extends ProbeTool {
|
|
|
162
172
|
value: null,
|
|
163
173
|
};
|
|
164
174
|
|
|
165
|
-
this._calculateCachedStats(
|
|
175
|
+
this._calculateCachedStats(
|
|
176
|
+
annotation,
|
|
177
|
+
renderingEngine,
|
|
178
|
+
enabledElement,
|
|
179
|
+
modalityUnitOptions
|
|
180
|
+
);
|
|
166
181
|
} else if (annotation.invalidated) {
|
|
167
|
-
this._calculateCachedStats(
|
|
182
|
+
this._calculateCachedStats(
|
|
183
|
+
annotation,
|
|
184
|
+
renderingEngine,
|
|
185
|
+
enabledElement,
|
|
186
|
+
modalityUnitOptions
|
|
187
|
+
);
|
|
168
188
|
}
|
|
169
189
|
|
|
170
190
|
// If rendering engine has been destroyed while rendering
|
|
@@ -185,20 +205,7 @@ class DragProbeTool extends ProbeTool {
|
|
|
185
205
|
|
|
186
206
|
renderStatus = true;
|
|
187
207
|
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
const isSuvScaled = this.isSuvScaled(
|
|
191
|
-
viewport,
|
|
192
|
-
targetId,
|
|
193
|
-
annotation.metadata.referencedImageId
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
const textLines = this._getTextLines(
|
|
197
|
-
data,
|
|
198
|
-
targetId,
|
|
199
|
-
isPreScaled,
|
|
200
|
-
isSuvScaled
|
|
201
|
-
);
|
|
208
|
+
const textLines = this._getTextLines(data, targetId);
|
|
202
209
|
if (textLines) {
|
|
203
210
|
const textCanvasCoordinates = [
|
|
204
211
|
canvasCoordinates[0] + 6,
|
|
@@ -56,7 +56,10 @@ import {
|
|
|
56
56
|
import triggerAnnotationRenderForViewportIds from '../../utilities/triggerAnnotationRenderForViewportIds';
|
|
57
57
|
import { pointInShapeCallback } from '../../utilities/';
|
|
58
58
|
import { StyleSpecifier } from '../../types/AnnotationStyle';
|
|
59
|
-
import {
|
|
59
|
+
import {
|
|
60
|
+
ModalityUnitOptions,
|
|
61
|
+
getModalityUnit,
|
|
62
|
+
} from '../../utilities/getModalityUnit';
|
|
60
63
|
import { isViewportPreScaled } from '../../utilities/viewport/isViewportPreScaled';
|
|
61
64
|
|
|
62
65
|
const { transformWorldToIndex } = csUtils;
|
|
@@ -787,6 +790,16 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
787
790
|
|
|
788
791
|
const { centerPointRadius } = this.configuration;
|
|
789
792
|
|
|
793
|
+
const modalityUnitOptions = {
|
|
794
|
+
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
795
|
+
|
|
796
|
+
isSuvScaled: this.isSuvScaled(
|
|
797
|
+
viewport,
|
|
798
|
+
targetId,
|
|
799
|
+
annotation.metadata.referencedImageId
|
|
800
|
+
),
|
|
801
|
+
};
|
|
802
|
+
|
|
790
803
|
// If cachedStats does not exist, or the unit is missing (as part of import/hydration etc.),
|
|
791
804
|
// force to recalculate the stats from the points
|
|
792
805
|
if (
|
|
@@ -806,14 +819,16 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
806
819
|
annotation,
|
|
807
820
|
viewport,
|
|
808
821
|
renderingEngine,
|
|
809
|
-
enabledElement
|
|
822
|
+
enabledElement,
|
|
823
|
+
modalityUnitOptions
|
|
810
824
|
);
|
|
811
825
|
} else if (annotation.invalidated) {
|
|
812
826
|
this._throttledCalculateCachedStats(
|
|
813
827
|
annotation,
|
|
814
828
|
viewport,
|
|
815
829
|
renderingEngine,
|
|
816
|
-
enabledElement
|
|
830
|
+
enabledElement,
|
|
831
|
+
modalityUnitOptions
|
|
817
832
|
);
|
|
818
833
|
// If the invalidated data is as a result of volumeViewport manipulation
|
|
819
834
|
// of the tools, we need to invalidate the related viewports data, so that
|
|
@@ -925,20 +940,7 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
925
940
|
|
|
926
941
|
renderStatus = true;
|
|
927
942
|
|
|
928
|
-
const
|
|
929
|
-
|
|
930
|
-
const isSuvScaled = this.isSuvScaled(
|
|
931
|
-
viewport,
|
|
932
|
-
targetId,
|
|
933
|
-
annotation.metadata.referencedImageId
|
|
934
|
-
);
|
|
935
|
-
|
|
936
|
-
const textLines = this._getTextLines(
|
|
937
|
-
data,
|
|
938
|
-
targetId,
|
|
939
|
-
isPreScaled,
|
|
940
|
-
isSuvScaled
|
|
941
|
-
);
|
|
943
|
+
const textLines = this._getTextLines(data, targetId);
|
|
942
944
|
if (!textLines || textLines.length === 0) {
|
|
943
945
|
continue;
|
|
944
946
|
}
|
|
@@ -982,18 +984,12 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
982
984
|
return renderStatus;
|
|
983
985
|
};
|
|
984
986
|
|
|
985
|
-
_getTextLines = (
|
|
986
|
-
data,
|
|
987
|
-
targetId: string,
|
|
988
|
-
isPreScaled: boolean,
|
|
989
|
-
isSuvScaled: boolean
|
|
990
|
-
): string[] => {
|
|
987
|
+
_getTextLines = (data, targetId: string): string[] => {
|
|
991
988
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
992
|
-
const { area, mean, stdDev, max, isEmptyArea,
|
|
989
|
+
const { area, mean, stdDev, max, isEmptyArea, areaUnit, modalityUnit } =
|
|
993
990
|
cachedVolumeStats;
|
|
994
991
|
|
|
995
992
|
const textLines: string[] = [];
|
|
996
|
-
const unit = getModalityUnit(Modality, isPreScaled, isSuvScaled);
|
|
997
993
|
|
|
998
994
|
if (area) {
|
|
999
995
|
const areaLine = isEmptyArea
|
|
@@ -1003,15 +999,15 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
1003
999
|
}
|
|
1004
1000
|
|
|
1005
1001
|
if (mean) {
|
|
1006
|
-
textLines.push(`Mean: ${mean.toFixed(2)} ${
|
|
1002
|
+
textLines.push(`Mean: ${mean.toFixed(2)} ${modalityUnit}`);
|
|
1007
1003
|
}
|
|
1008
1004
|
|
|
1009
1005
|
if (max) {
|
|
1010
|
-
textLines.push(`Max: ${max.toFixed(2)} ${
|
|
1006
|
+
textLines.push(`Max: ${max.toFixed(2)} ${modalityUnit}`);
|
|
1011
1007
|
}
|
|
1012
1008
|
|
|
1013
1009
|
if (stdDev) {
|
|
1014
|
-
textLines.push(`Std Dev: ${stdDev.toFixed(2)} ${
|
|
1010
|
+
textLines.push(`Std Dev: ${stdDev.toFixed(2)} ${modalityUnit}`);
|
|
1015
1011
|
}
|
|
1016
1012
|
|
|
1017
1013
|
return textLines;
|
|
@@ -1021,7 +1017,8 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
1021
1017
|
annotation,
|
|
1022
1018
|
viewport,
|
|
1023
1019
|
renderingEngine,
|
|
1024
|
-
enabledElement
|
|
1020
|
+
enabledElement,
|
|
1021
|
+
modalityUnitOptions: ModalityUnitOptions
|
|
1025
1022
|
) => {
|
|
1026
1023
|
const data = annotation.data;
|
|
1027
1024
|
const { viewportId, renderingEngineId } = enabledElement;
|
|
@@ -1149,6 +1146,12 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
1149
1146
|
stdDev /= count;
|
|
1150
1147
|
stdDev = Math.sqrt(stdDev);
|
|
1151
1148
|
|
|
1149
|
+
const modalityUnit = getModalityUnit(
|
|
1150
|
+
metadata.Modality,
|
|
1151
|
+
annotation.metadata.referencedImageId,
|
|
1152
|
+
modalityUnitOptions
|
|
1153
|
+
);
|
|
1154
|
+
|
|
1152
1155
|
cachedStats[targetId] = {
|
|
1153
1156
|
Modality: metadata.Modality,
|
|
1154
1157
|
area,
|
|
@@ -1157,6 +1160,7 @@ class EllipticalROITool extends AnnotationTool {
|
|
|
1157
1160
|
stdDev,
|
|
1158
1161
|
isEmptyArea,
|
|
1159
1162
|
areaUnit: hasPixelSpacing ? 'mm' : 'px',
|
|
1163
|
+
modalityUnit,
|
|
1160
1164
|
};
|
|
1161
1165
|
} else {
|
|
1162
1166
|
this.isHandleOutsideImage = true;
|
|
@@ -49,7 +49,10 @@ import pointInPolyline from '../../utilities/math/polyline/pointInPolyline';
|
|
|
49
49
|
import { getIntersectionCoordinatesWithPolyline } from '../../utilities/math/polyline/getIntersectionWithPolyline';
|
|
50
50
|
import pointInShapeCallback from '../../utilities/pointInShapeCallback';
|
|
51
51
|
import { isViewportPreScaled } from '../../utilities/viewport/isViewportPreScaled';
|
|
52
|
-
import {
|
|
52
|
+
import {
|
|
53
|
+
ModalityUnitOptions,
|
|
54
|
+
getModalityUnit,
|
|
55
|
+
} from '../../utilities/getModalityUnit';
|
|
53
56
|
|
|
54
57
|
const { pointCanProjectOnLine } = polyline;
|
|
55
58
|
const { EPSILON } = CONSTANTS;
|
|
@@ -663,6 +666,15 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
663
666
|
)
|
|
664
667
|
return;
|
|
665
668
|
|
|
669
|
+
const modalityUnitOptions = {
|
|
670
|
+
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
671
|
+
isSuvScaled: this.isSuvScaled(
|
|
672
|
+
viewport,
|
|
673
|
+
targetId,
|
|
674
|
+
annotation.metadata.referencedImageId
|
|
675
|
+
),
|
|
676
|
+
};
|
|
677
|
+
|
|
666
678
|
if (!this.commonData?.movingTextBox) {
|
|
667
679
|
const { data } = annotation;
|
|
668
680
|
if (
|
|
@@ -682,14 +694,16 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
682
694
|
annotation,
|
|
683
695
|
viewport,
|
|
684
696
|
renderingEngine,
|
|
685
|
-
enabledElement
|
|
697
|
+
enabledElement,
|
|
698
|
+
modalityUnitOptions
|
|
686
699
|
);
|
|
687
700
|
} else if (annotation.invalidated) {
|
|
688
701
|
this._throttledCalculateCachedStats(
|
|
689
702
|
annotation,
|
|
690
703
|
viewport,
|
|
691
704
|
renderingEngine,
|
|
692
|
-
enabledElement
|
|
705
|
+
enabledElement,
|
|
706
|
+
modalityUnitOptions
|
|
693
707
|
);
|
|
694
708
|
}
|
|
695
709
|
}
|
|
@@ -704,7 +718,8 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
704
718
|
annotation,
|
|
705
719
|
viewport,
|
|
706
720
|
renderingEngine,
|
|
707
|
-
enabledElement
|
|
721
|
+
enabledElement,
|
|
722
|
+
modalityUnitOptions: ModalityUnitOptions
|
|
708
723
|
) => {
|
|
709
724
|
const data = annotation.data;
|
|
710
725
|
const { cachedStats, polyline: points } = data;
|
|
@@ -841,6 +856,12 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
841
856
|
let stdDev = sumSquares / count - mean ** 2;
|
|
842
857
|
stdDev = Math.sqrt(stdDev);
|
|
843
858
|
|
|
859
|
+
const modalityUnit = getModalityUnit(
|
|
860
|
+
metadata.Modality,
|
|
861
|
+
annotation.metadata.referencedImageId,
|
|
862
|
+
modalityUnitOptions
|
|
863
|
+
);
|
|
864
|
+
|
|
844
865
|
cachedStats[targetId] = {
|
|
845
866
|
Modality: metadata.Modality,
|
|
846
867
|
area,
|
|
@@ -848,6 +869,7 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
848
869
|
max,
|
|
849
870
|
stdDev,
|
|
850
871
|
areaUnit: hasPixelSpacing ? 'mm' : 'px',
|
|
872
|
+
modalityUnit,
|
|
851
873
|
};
|
|
852
874
|
}
|
|
853
875
|
|
|
@@ -861,19 +883,8 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
861
883
|
_renderStats = (annotation, viewport, enabledElement, svgDrawingHelper) => {
|
|
862
884
|
const data = annotation.data;
|
|
863
885
|
const targetId = this.getTargetId(viewport);
|
|
864
|
-
const isPreScaled = isViewportPreScaled(viewport, targetId);
|
|
865
|
-
const isSuvScaled = this.isSuvScaled(
|
|
866
|
-
viewport,
|
|
867
|
-
targetId,
|
|
868
|
-
annotation.metadata.referencedImageId
|
|
869
|
-
);
|
|
870
886
|
|
|
871
|
-
const textLines = this._getTextLines(
|
|
872
|
-
data,
|
|
873
|
-
targetId,
|
|
874
|
-
isPreScaled,
|
|
875
|
-
isSuvScaled
|
|
876
|
-
);
|
|
887
|
+
const textLines = this._getTextLines(data, targetId);
|
|
877
888
|
if (!textLines || textLines.length === 0) return;
|
|
878
889
|
|
|
879
890
|
const canvasCoordinates = data.polyline.map((p) =>
|
|
@@ -918,18 +929,12 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
918
929
|
};
|
|
919
930
|
};
|
|
920
931
|
|
|
921
|
-
_getTextLines = (
|
|
922
|
-
data,
|
|
923
|
-
targetId: string,
|
|
924
|
-
isPreScaled: boolean,
|
|
925
|
-
isSuvScaled: boolean
|
|
926
|
-
): string[] => {
|
|
932
|
+
_getTextLines = (data, targetId: string): string[] => {
|
|
927
933
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
928
|
-
const { area, mean, stdDev, max, isEmptyArea,
|
|
934
|
+
const { area, mean, stdDev, max, isEmptyArea, areaUnit, modalityUnit } =
|
|
929
935
|
cachedVolumeStats;
|
|
930
936
|
|
|
931
937
|
const textLines: string[] = [];
|
|
932
|
-
const unit = getModalityUnit(Modality, isPreScaled, isSuvScaled);
|
|
933
938
|
|
|
934
939
|
if (area) {
|
|
935
940
|
const areaLine = isEmptyArea
|
|
@@ -939,15 +944,15 @@ class PlanarFreehandROITool extends AnnotationTool {
|
|
|
939
944
|
}
|
|
940
945
|
|
|
941
946
|
if (mean) {
|
|
942
|
-
textLines.push(`Mean: ${mean.toFixed(2)} ${
|
|
947
|
+
textLines.push(`Mean: ${mean.toFixed(2)} ${modalityUnit}`);
|
|
943
948
|
}
|
|
944
949
|
|
|
945
950
|
if (max) {
|
|
946
|
-
textLines.push(`Max: ${max.toFixed(2)} ${
|
|
951
|
+
textLines.push(`Max: ${max.toFixed(2)} ${modalityUnit}`);
|
|
947
952
|
}
|
|
948
953
|
|
|
949
954
|
if (stdDev) {
|
|
950
|
-
textLines.push(`Std Dev: ${stdDev.toFixed(2)} ${
|
|
955
|
+
textLines.push(`Std Dev: ${stdDev.toFixed(2)} ${modalityUnit}`);
|
|
951
956
|
}
|
|
952
957
|
|
|
953
958
|
return textLines;
|
|
@@ -44,7 +44,10 @@ import {
|
|
|
44
44
|
} from '../../types';
|
|
45
45
|
import { ProbeAnnotation } from '../../types/ToolSpecificAnnotationTypes';
|
|
46
46
|
import { StyleSpecifier } from '../../types/AnnotationStyle';
|
|
47
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
ModalityUnitOptions,
|
|
49
|
+
getModalityUnit,
|
|
50
|
+
} from '../../utilities/getModalityUnit';
|
|
48
51
|
import { isViewportPreScaled } from '../../utilities/viewport/isViewportPreScaled';
|
|
49
52
|
|
|
50
53
|
const { transformWorldToIndex } = csUtils;
|
|
@@ -437,6 +440,16 @@ class ProbeTool extends AnnotationTool {
|
|
|
437
440
|
|
|
438
441
|
const color = this.getStyle('color', styleSpecifier, annotation);
|
|
439
442
|
|
|
443
|
+
const modalityUnitOptions = {
|
|
444
|
+
isPreScaled: isViewportPreScaled(viewport, targetId),
|
|
445
|
+
|
|
446
|
+
isSuvScaled: this.isSuvScaled(
|
|
447
|
+
viewport,
|
|
448
|
+
targetId,
|
|
449
|
+
annotation.metadata.referencedImageId
|
|
450
|
+
),
|
|
451
|
+
};
|
|
452
|
+
|
|
440
453
|
if (!data.cachedStats[targetId]) {
|
|
441
454
|
data.cachedStats[targetId] = {
|
|
442
455
|
Modality: null,
|
|
@@ -444,9 +457,19 @@ class ProbeTool extends AnnotationTool {
|
|
|
444
457
|
value: null,
|
|
445
458
|
};
|
|
446
459
|
|
|
447
|
-
this._calculateCachedStats(
|
|
460
|
+
this._calculateCachedStats(
|
|
461
|
+
annotation,
|
|
462
|
+
renderingEngine,
|
|
463
|
+
enabledElement,
|
|
464
|
+
modalityUnitOptions
|
|
465
|
+
);
|
|
448
466
|
} else if (annotation.invalidated) {
|
|
449
|
-
this._calculateCachedStats(
|
|
467
|
+
this._calculateCachedStats(
|
|
468
|
+
annotation,
|
|
469
|
+
renderingEngine,
|
|
470
|
+
enabledElement,
|
|
471
|
+
modalityUnitOptions
|
|
472
|
+
);
|
|
450
473
|
|
|
451
474
|
// If the invalidated data is as a result of volumeViewport manipulation
|
|
452
475
|
// of the tools, we need to invalidate the related stackViewports data if
|
|
@@ -502,20 +525,7 @@ class ProbeTool extends AnnotationTool {
|
|
|
502
525
|
|
|
503
526
|
renderStatus = true;
|
|
504
527
|
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
const isSuvScaled = this.isSuvScaled(
|
|
508
|
-
viewport,
|
|
509
|
-
targetId,
|
|
510
|
-
annotation.metadata.referencedImageId
|
|
511
|
-
);
|
|
512
|
-
|
|
513
|
-
const textLines = this._getTextLines(
|
|
514
|
-
data,
|
|
515
|
-
targetId,
|
|
516
|
-
isPreScaled,
|
|
517
|
-
isSuvScaled
|
|
518
|
-
);
|
|
528
|
+
const textLines = this._getTextLines(data, targetId);
|
|
519
529
|
if (textLines) {
|
|
520
530
|
const textCanvasCoordinates = [
|
|
521
531
|
canvasCoordinates[0] + 6,
|
|
@@ -537,71 +547,29 @@ class ProbeTool extends AnnotationTool {
|
|
|
537
547
|
return renderStatus;
|
|
538
548
|
};
|
|
539
549
|
|
|
540
|
-
_getTextLines(
|
|
541
|
-
data,
|
|
542
|
-
targetId: string,
|
|
543
|
-
isPreScaled: boolean,
|
|
544
|
-
isSuvScaled: boolean
|
|
545
|
-
): string[] | undefined {
|
|
550
|
+
_getTextLines(data, targetId: string): string[] | undefined {
|
|
546
551
|
const cachedVolumeStats = data.cachedStats[targetId];
|
|
547
|
-
const { index,
|
|
552
|
+
const { index, value, modalityUnit } = cachedVolumeStats;
|
|
548
553
|
|
|
549
|
-
if (value === undefined
|
|
554
|
+
if (value === undefined) {
|
|
550
555
|
return;
|
|
551
556
|
}
|
|
552
557
|
|
|
553
558
|
const textLines = [];
|
|
554
|
-
const unit = getModalityUnit(Modality, isPreScaled, isSuvScaled);
|
|
555
559
|
|
|
556
560
|
textLines.push(`(${index[0]}, ${index[1]}, ${index[2]})`);
|
|
557
561
|
|
|
558
|
-
|
|
559
|
-
if (Modality === 'PT' && isPreScaled === true && SUVBw !== undefined) {
|
|
560
|
-
textLines.push(`${SUVBw.toFixed(2)} SUV bw`);
|
|
561
|
-
if (SUVLbm) {
|
|
562
|
-
textLines.push(`${SUVLbm.toFixed(2)} SUV lbm`);
|
|
563
|
-
}
|
|
564
|
-
if (SUVBsa) {
|
|
565
|
-
textLines.push(`${SUVBsa.toFixed(2)} SUV bsa`);
|
|
566
|
-
}
|
|
567
|
-
} else {
|
|
568
|
-
textLines.push(`${value.toFixed(2)} ${unit}`);
|
|
569
|
-
}
|
|
562
|
+
textLines.push(`${value.toFixed(2)} ${modalityUnit}`);
|
|
570
563
|
|
|
571
564
|
return textLines;
|
|
572
565
|
}
|
|
573
566
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
if (
|
|
581
|
-
modality === 'PT' &&
|
|
582
|
-
imageVolume.scaling?.PT &&
|
|
583
|
-
(imageVolume.scaling.PT.suvbwToSuvbsa ||
|
|
584
|
-
imageVolume.scaling.PT.suvbwToSuvlbm)
|
|
585
|
-
) {
|
|
586
|
-
const { suvbwToSuvlbm, suvbwToSuvbsa } = imageVolume.scaling.PT;
|
|
587
|
-
|
|
588
|
-
values['SUVBw'] = value;
|
|
589
|
-
|
|
590
|
-
if (suvbwToSuvlbm) {
|
|
591
|
-
const SUVLbm = value * suvbwToSuvlbm;
|
|
592
|
-
values['SUVLbm'] = SUVLbm;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
if (suvbwToSuvbsa) {
|
|
596
|
-
const SUVBsa = value * suvbwToSuvbsa;
|
|
597
|
-
values['SUVBsa'] = SUVBsa;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
return values;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
_calculateCachedStats(annotation, renderingEngine, enabledElement) {
|
|
567
|
+
_calculateCachedStats(
|
|
568
|
+
annotation,
|
|
569
|
+
renderingEngine,
|
|
570
|
+
enabledElement,
|
|
571
|
+
modalityUnitOptions: ModalityUnitOptions
|
|
572
|
+
) {
|
|
605
573
|
const data = annotation.data;
|
|
606
574
|
const { viewportId, renderingEngineId } = enabledElement;
|
|
607
575
|
|
|
@@ -656,12 +624,17 @@ class ProbeTool extends AnnotationTool {
|
|
|
656
624
|
index[2] = viewport.getCurrentImageIdIndex();
|
|
657
625
|
}
|
|
658
626
|
|
|
659
|
-
const
|
|
627
|
+
const modalityUnit = getModalityUnit(
|
|
628
|
+
modality,
|
|
629
|
+
annotation.metadata.referencedImageId,
|
|
630
|
+
modalityUnitOptions
|
|
631
|
+
);
|
|
660
632
|
|
|
661
633
|
cachedStats[targetId] = {
|
|
662
634
|
index,
|
|
663
|
-
|
|
635
|
+
value,
|
|
664
636
|
Modality: modality,
|
|
637
|
+
modalityUnit,
|
|
665
638
|
};
|
|
666
639
|
} else {
|
|
667
640
|
this.isHandleOutsideImage = true;
|