@cornerstonejs/tools 2.19.14 → 3.0.0-beta.3

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 (117) hide show
  1. package/dist/esm/config.d.ts +29 -0
  2. package/dist/esm/config.js +23 -0
  3. package/dist/esm/enums/StrategyCallbacks.d.ts +3 -1
  4. package/dist/esm/enums/StrategyCallbacks.js +2 -0
  5. package/dist/esm/enums/WorkerTypes.d.ts +3 -1
  6. package/dist/esm/enums/WorkerTypes.js +2 -0
  7. package/dist/esm/init.d.ts +2 -1
  8. package/dist/esm/init.js +2 -0
  9. package/dist/esm/stateManagement/segmentation/helpers/normalizeSegmentationInput.js +1 -1
  10. package/dist/esm/stateManagement/segmentation/helpers/validateSegmentationInput.js +1 -1
  11. package/dist/esm/stateManagement/segmentation/index.d.ts +3 -2
  12. package/dist/esm/stateManagement/segmentation/index.js +3 -2
  13. package/dist/esm/tools/displayTools/Contour/contourDisplay.js +8 -6
  14. package/dist/esm/tools/displayTools/Labelmap/index.d.ts +1 -1
  15. package/dist/esm/tools/displayTools/Labelmap/index.js +1 -1
  16. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +14 -5
  17. package/dist/esm/tools/displayTools/Surface/surfaceDisplay.js +13 -8
  18. package/dist/esm/tools/segmentation/BrushTool.js +1 -9
  19. package/dist/esm/tools/segmentation/CircleScissorsTool.js +0 -1
  20. package/dist/esm/tools/segmentation/LabelmapBaseTool.d.ts +1 -2
  21. package/dist/esm/tools/segmentation/LabelmapBaseTool.js +10 -49
  22. package/dist/esm/tools/segmentation/RectangleScissorsTool.js +0 -1
  23. package/dist/esm/tools/segmentation/SphereScissorsTool.js +0 -1
  24. package/dist/esm/tools/segmentation/strategies/BrushStrategy.d.ts +21 -10
  25. package/dist/esm/tools/segmentation/strategies/BrushStrategy.js +8 -8
  26. package/dist/esm/tools/segmentation/strategies/compositions/determineSegmentIndex.js +7 -10
  27. package/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js +15 -14
  28. package/dist/esm/tools/segmentation/strategies/compositions/ensureImageVolume.d.ts +4 -0
  29. package/dist/esm/tools/segmentation/strategies/compositions/ensureImageVolume.js +35 -0
  30. package/dist/esm/tools/segmentation/strategies/compositions/ensureSegmentationVolume.d.ts +4 -0
  31. package/dist/esm/tools/segmentation/strategies/compositions/ensureSegmentationVolume.js +20 -0
  32. package/dist/esm/tools/segmentation/strategies/compositions/index.d.ts +7 -10
  33. package/dist/esm/tools/segmentation/strategies/compositions/index.js +4 -2
  34. package/dist/esm/tools/segmentation/strategies/compositions/islandRemovalComposition.js +3 -2
  35. package/dist/esm/tools/segmentation/strategies/compositions/labelmapStatistics.d.ts +1 -1
  36. package/dist/esm/tools/segmentation/strategies/compositions/labelmapStatistics.js +6 -97
  37. package/dist/esm/tools/segmentation/strategies/compositions/preview.js +3 -3
  38. package/dist/esm/tools/segmentation/strategies/compositions/threshold.js +5 -6
  39. package/dist/esm/tools/segmentation/strategies/fillCircle.js +2 -2
  40. package/dist/esm/tools/segmentation/strategies/fillSphere.js +3 -3
  41. package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.d.ts +7 -3
  42. package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js +78 -34
  43. package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.d.ts +2 -7
  44. package/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js +5 -4
  45. package/dist/esm/types/CalculatorTypes.d.ts +2 -0
  46. package/dist/esm/types/LabelmapToolOperationData.d.ts +1 -1
  47. package/dist/esm/types/index.d.ts +3 -4
  48. package/dist/esm/utilities/getPixelValueUnits.d.ts +2 -1
  49. package/dist/esm/utilities/getPixelValueUnits.js +5 -1
  50. package/dist/esm/utilities/index.d.ts +3 -2
  51. package/dist/esm/utilities/index.js +3 -2
  52. package/dist/esm/utilities/math/basic/BasicStatsCalculator.d.ts +6 -1
  53. package/dist/esm/utilities/math/basic/BasicStatsCalculator.js +27 -2
  54. package/dist/esm/utilities/math/vec2/liangBarksyClip.d.ts +1 -1
  55. package/dist/esm/utilities/registerComputeWorker.d.ts +1 -0
  56. package/dist/esm/{stateManagement/segmentation/polySeg/registerPolySegWorker.js → utilities/registerComputeWorker.js} +4 -4
  57. package/dist/esm/utilities/segmentation/brushThresholdForToolGroup.d.ts +5 -1
  58. package/dist/esm/utilities/segmentation/brushThresholdForToolGroup.js +12 -13
  59. package/dist/esm/{stateManagement/segmentation/polySeg → utilities/segmentation}/computeAndAddRepresentation.d.ts +1 -1
  60. package/dist/esm/{stateManagement/segmentation/polySeg → utilities/segmentation}/computeAndAddRepresentation.js +4 -6
  61. package/dist/esm/utilities/segmentation/getOrCreateSegmentationVolume.d.ts +2 -0
  62. package/dist/esm/utilities/segmentation/getOrCreateSegmentationVolume.js +21 -0
  63. package/dist/esm/utilities/segmentation/getStatistics.d.ts +5 -0
  64. package/dist/esm/utilities/segmentation/getStatistics.js +210 -0
  65. package/dist/esm/utilities/segmentation/index.d.ts +6 -1
  66. package/dist/esm/utilities/segmentation/index.js +6 -1
  67. package/dist/esm/{tools/displayTools/Labelmap → utilities/segmentation}/validateLabelmap.d.ts +2 -2
  68. package/dist/esm/workers/computeWorker.js +78 -0
  69. package/package.json +3 -3
  70. package/dist/esm/stateManagement/segmentation/helpers/clipAndCacheSurfacesForViewport.d.ts +0 -16
  71. package/dist/esm/stateManagement/segmentation/helpers/clipAndCacheSurfacesForViewport.js +0 -88
  72. package/dist/esm/stateManagement/segmentation/polySeg/Contour/computeAndAddContourRepresentation.d.ts +0 -4
  73. package/dist/esm/stateManagement/segmentation/polySeg/Contour/computeAndAddContourRepresentation.js +0 -6
  74. package/dist/esm/stateManagement/segmentation/polySeg/Contour/contourComputationStrategies.d.ts +0 -8
  75. package/dist/esm/stateManagement/segmentation/polySeg/Contour/contourComputationStrategies.js +0 -103
  76. package/dist/esm/stateManagement/segmentation/polySeg/Contour/utils/createAndAddContourSegmentationsFromClippedSurfaces.d.ts +0 -3
  77. package/dist/esm/stateManagement/segmentation/polySeg/Contour/utils/createAndAddContourSegmentationsFromClippedSurfaces.js +0 -71
  78. package/dist/esm/stateManagement/segmentation/polySeg/Contour/utils/extractContourData.d.ts +0 -3
  79. package/dist/esm/stateManagement/segmentation/polySeg/Contour/utils/extractContourData.js +0 -16
  80. package/dist/esm/stateManagement/segmentation/polySeg/Contour/utils/updateContoursOnCameraModified.d.ts +0 -1
  81. package/dist/esm/stateManagement/segmentation/polySeg/Contour/utils/updateContoursOnCameraModified.js +0 -25
  82. package/dist/esm/stateManagement/segmentation/polySeg/Labelmap/computeAndAddLabelmapRepresentation.d.ts +0 -2
  83. package/dist/esm/stateManagement/segmentation/polySeg/Labelmap/computeAndAddLabelmapRepresentation.js +0 -13
  84. package/dist/esm/stateManagement/segmentation/polySeg/Labelmap/convertContourToLabelmap.d.ts +0 -7
  85. package/dist/esm/stateManagement/segmentation/polySeg/Labelmap/convertContourToLabelmap.js +0 -143
  86. package/dist/esm/stateManagement/segmentation/polySeg/Labelmap/convertSurfaceToLabelmap.d.ts +0 -6
  87. package/dist/esm/stateManagement/segmentation/polySeg/Labelmap/convertSurfaceToLabelmap.js +0 -49
  88. package/dist/esm/stateManagement/segmentation/polySeg/Labelmap/labelmapComputationStrategies.d.ts +0 -6
  89. package/dist/esm/stateManagement/segmentation/polySeg/Labelmap/labelmapComputationStrategies.js +0 -96
  90. package/dist/esm/stateManagement/segmentation/polySeg/Surface/computeAndAddSurfaceRepresentation.d.ts +0 -4
  91. package/dist/esm/stateManagement/segmentation/polySeg/Surface/computeAndAddSurfaceRepresentation.js +0 -7
  92. package/dist/esm/stateManagement/segmentation/polySeg/Surface/convertContourToSurface.d.ts +0 -3
  93. package/dist/esm/stateManagement/segmentation/polySeg/Surface/convertContourToSurface.js +0 -37
  94. package/dist/esm/stateManagement/segmentation/polySeg/Surface/convertLabelmapToSurface.d.ts +0 -3
  95. package/dist/esm/stateManagement/segmentation/polySeg/Surface/convertLabelmapToSurface.js +0 -44
  96. package/dist/esm/stateManagement/segmentation/polySeg/Surface/createAndCacheSurfacesFromRaw.d.ts +0 -5
  97. package/dist/esm/stateManagement/segmentation/polySeg/Surface/createAndCacheSurfacesFromRaw.js +0 -33
  98. package/dist/esm/stateManagement/segmentation/polySeg/Surface/surfaceComputationStrategies.d.ts +0 -12
  99. package/dist/esm/stateManagement/segmentation/polySeg/Surface/surfaceComputationStrategies.js +0 -75
  100. package/dist/esm/stateManagement/segmentation/polySeg/Surface/updateSurfaceData.d.ts +0 -1
  101. package/dist/esm/stateManagement/segmentation/polySeg/Surface/updateSurfaceData.js +0 -59
  102. package/dist/esm/stateManagement/segmentation/polySeg/canComputeRequestedRepresentation.d.ts +0 -3
  103. package/dist/esm/stateManagement/segmentation/polySeg/canComputeRequestedRepresentation.js +0 -58
  104. package/dist/esm/stateManagement/segmentation/polySeg/index.d.ts +0 -5
  105. package/dist/esm/stateManagement/segmentation/polySeg/index.js +0 -5
  106. package/dist/esm/stateManagement/segmentation/polySeg/registerPolySegWorker.d.ts +0 -1
  107. package/dist/esm/tools/segmentation/strategies/compositions/labelmapInterpolation.d.ts +0 -12
  108. package/dist/esm/tools/segmentation/strategies/compositions/labelmapInterpolation.js +0 -60
  109. package/dist/esm/tools/segmentation/strategies/utils/getItkImage.d.ts +0 -1
  110. package/dist/esm/tools/segmentation/strategies/utils/getItkImage.js +0 -49
  111. package/dist/esm/types/PolySeg.d.ts +0 -6
  112. package/dist/esm/types/PolySeg.js +0 -0
  113. package/dist/esm/workers/polySegConverters.js +0 -382
  114. /package/dist/esm/{geometricSurfaceUtils.d.ts → utilities/geometricSurfaceUtils.d.ts} +0 -0
  115. /package/dist/esm/{geometricSurfaceUtils.js → utilities/geometricSurfaceUtils.js} +0 -0
  116. /package/dist/esm/{tools/displayTools/Labelmap → utilities/segmentation}/validateLabelmap.js +0 -0
  117. /package/dist/esm/workers/{polySegConverters.d.ts → computeWorker.d.ts} +0 -0
@@ -2,9 +2,8 @@ import { vec3 } from 'gl-matrix';
2
2
  import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
3
3
  export default {
4
4
  [StrategyCallbacks.Initialize]: (operationData) => {
5
- const { operationName, centerIJK, strategySpecificConfiguration, segmentationVoxelManager, imageVoxelManager, segmentIndex, viewport, } = operationData;
6
- const { THRESHOLD } = strategySpecificConfiguration;
7
- if (!THRESHOLD?.isDynamic || !centerIJK || !segmentIndex) {
5
+ const { operationName, centerIJK, segmentationVoxelManager, imageVoxelManager, configuration, segmentIndex, viewport, } = operationData;
6
+ if (!configuration?.threshold?.isDynamic || !centerIJK || !segmentIndex) {
8
7
  return;
9
8
  }
10
9
  if (operationName === StrategyCallbacks.RejectPreview ||
@@ -12,7 +11,7 @@ export default {
12
11
  return;
13
12
  }
14
13
  const boundsIJK = segmentationVoxelManager.getBoundsIJK();
15
- const { threshold: oldThreshold, dynamicRadius = 0 } = THRESHOLD;
14
+ const { range: oldThreshold, dynamicRadius = 0 } = configuration.threshold;
16
15
  const useDelta = oldThreshold ? 0 : dynamicRadius;
17
16
  const { viewPlaneNormal } = viewport.getCamera();
18
17
  const nestedBounds = boundsIJK.map((ijk, idx) => {
@@ -43,18 +42,22 @@ export default {
43
42
  threshold[1] = Math.max(gray, threshold[1]);
44
43
  };
45
44
  imageVoxelManager.forEach(callback, { boundsIJK: nestedBounds });
46
- operationData.strategySpecificConfiguration.THRESHOLD.threshold = threshold;
45
+ configuration.threshold.range = threshold;
47
46
  },
48
47
  [StrategyCallbacks.OnInteractionStart]: (operationData) => {
49
- const { strategySpecificConfiguration, preview } = operationData;
50
- if (!strategySpecificConfiguration?.THRESHOLD?.isDynamic && !preview) {
48
+ const { configuration } = operationData;
49
+ if (!configuration?.threshold?.isDynamic) {
51
50
  return;
52
51
  }
53
- strategySpecificConfiguration.THRESHOLD.threshold = null;
52
+ configuration.threshold.range = null;
54
53
  },
55
54
  [StrategyCallbacks.ComputeInnerCircleRadius]: (operationData) => {
56
55
  const { configuration, viewport } = operationData;
57
- const { THRESHOLD: { dynamicRadius = 0 } = {} } = configuration.strategySpecificConfiguration || {};
56
+ const { dynamicRadius = 0, isDynamic } = configuration.threshold;
57
+ if (!isDynamic) {
58
+ configuration.threshold.dynamicRadiusInCanvas = 0;
59
+ return;
60
+ }
58
61
  if (dynamicRadius === 0) {
59
62
  return;
60
63
  }
@@ -72,11 +75,9 @@ export default {
72
75
  const offSetCenterInWorld = centerCursorInWorld.map((coord) => coord + radiusInWorld);
73
76
  const offSetCenterCanvas = viewport.worldToCanvas(offSetCenterInWorld);
74
77
  const dynamicRadiusInCanvas = Math.abs(centerCanvas[0] - offSetCenterCanvas[0]);
75
- const { strategySpecificConfiguration, activeStrategy } = configuration;
76
- if (!strategySpecificConfiguration[activeStrategy]) {
77
- strategySpecificConfiguration[activeStrategy] = {};
78
+ if (!configuration.threshold.dynamicRadiusInCanvas) {
79
+ configuration.threshold.dynamicRadiusInCanvas = 0;
78
80
  }
79
- strategySpecificConfiguration[activeStrategy].dynamicRadiusInCanvas =
80
- 3 + dynamicRadiusInCanvas;
81
+ configuration.threshold.dynamicRadiusInCanvas = 3 + dynamicRadiusInCanvas;
81
82
  },
82
83
  };
@@ -0,0 +1,4 @@
1
+ declare const _default: {
2
+ ensureImageVolumeFor3DManipulation: (data: any) => void;
3
+ };
4
+ export default _default;
@@ -0,0 +1,35 @@
1
+ import { cache, utilities as csUtils, volumeLoader } from '@cornerstonejs/core';
2
+ import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
3
+ import { getSegmentation } from '../../../../stateManagement/segmentation/getSegmentation';
4
+ export default {
5
+ [StrategyCallbacks.EnsureImageVolumeFor3DManipulation]: (data) => {
6
+ const { operationData, viewport } = data;
7
+ let referencedImageIds;
8
+ if (viewport) {
9
+ const referencedImageIds = viewport.getImageIds();
10
+ const isValidVolumeForSphere = csUtils.isValidVolume(referencedImageIds);
11
+ if (!isValidVolumeForSphere) {
12
+ throw new Error('Volume is not reconstructable for sphere manipulation');
13
+ }
14
+ }
15
+ else {
16
+ const segmentation = getSegmentation(operationData.segmentationId);
17
+ const imageIds = segmentation.representationData
18
+ .Labelmap.imageIds;
19
+ referencedImageIds = imageIds.map((imageId) => {
20
+ const image = cache.getImage(imageId);
21
+ return image.referencedImageId;
22
+ });
23
+ }
24
+ const volumeId = cache.generateVolumeId(referencedImageIds);
25
+ let imageVolume = cache.getVolume(volumeId);
26
+ if (imageVolume) {
27
+ operationData.imageVoxelManager = imageVolume.voxelManager;
28
+ operationData.imageData = imageVolume.imageData;
29
+ return;
30
+ }
31
+ imageVolume = volumeLoader.createAndCacheVolumeFromImagesSync(volumeId, referencedImageIds);
32
+ operationData.imageVoxelManager = imageVolume.voxelManager;
33
+ operationData.imageData = imageVolume.imageData;
34
+ },
35
+ };
@@ -0,0 +1,4 @@
1
+ declare const _default: {
2
+ ensureSegmentationVolumeFor3DManipulation: (data: any) => void;
3
+ };
4
+ export default _default;
@@ -0,0 +1,20 @@
1
+ import { utilities, cache } from '@cornerstonejs/core';
2
+ import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
3
+ import getOrCreateSegmentationVolume from '../../../../utilities/segmentation/getOrCreateSegmentationVolume';
4
+ export default {
5
+ [StrategyCallbacks.EnsureSegmentationVolumeFor3DManipulation]: (data) => {
6
+ const { operationData, viewport } = data;
7
+ const { segmentationId, imageIds: segImageIds } = operationData;
8
+ const referencedImageIds = viewport
9
+ ? viewport.getImageIds()
10
+ : segImageIds.map((imageId) => cache.getImage(imageId).referencedImageId);
11
+ const isValidVolumeForSphere = utilities.isValidVolume(referencedImageIds);
12
+ if (!isValidVolumeForSphere) {
13
+ throw new Error('Volume is not reconstructable for sphere manipulation');
14
+ }
15
+ const segVolume = getOrCreateSegmentationVolume(segmentationId);
16
+ operationData.segmentationVoxelManager = segVolume.voxelManager;
17
+ operationData.segmentationImageData = segVolume.imageData;
18
+ return;
19
+ },
20
+ };
@@ -35,16 +35,13 @@ declare const _default: {
35
35
  labelmapStatistics: {
36
36
  getStatistics: (enabledElement: any, operationData: import("../BrushStrategy").InitializedOperationData, options?: {
37
37
  indices?: number | number[];
38
- }) => import("../../../../types").NamedStatistics;
39
- };
40
- labelmapInterpolation: {
41
- interpolate: (operationData: import("../BrushStrategy").InitializedOperationData, configuration: {
42
- label?: number;
43
- axis?: number;
44
- noHeuristicAlignment?: boolean;
45
- noUseDistanceTransform?: boolean;
46
- useCustomSlicePositions?: boolean;
47
- }) => Promise<import("../BrushStrategy").InitializedOperationData>;
38
+ }) => void;
39
+ };
40
+ ensureSegmentationVolumeFor3DManipulation: {
41
+ ensureSegmentationVolumeFor3DManipulation: (data: any) => void;
42
+ };
43
+ ensureImageVolumeFor3DManipulation: {
44
+ ensureImageVolumeFor3DManipulation: (data: any) => void;
48
45
  };
49
46
  };
50
47
  export default _default;
@@ -7,7 +7,8 @@ import regionFill from './regionFill';
7
7
  import setValue from './setValue';
8
8
  import threshold from './threshold';
9
9
  import labelmapStatistics from './labelmapStatistics';
10
- import labelmapInterpolation from './labelmapInterpolation';
10
+ import ensureSegmentationVolumeFor3DManipulation from './ensureSegmentationVolume';
11
+ import ensureImageVolumeFor3DManipulation from './ensureImageVolume';
11
12
  export default {
12
13
  determineSegmentIndex,
13
14
  dynamicThreshold,
@@ -18,5 +19,6 @@ export default {
18
19
  setValue,
19
20
  threshold,
20
21
  labelmapStatistics,
21
- labelmapInterpolation,
22
+ ensureSegmentationVolumeFor3DManipulation,
23
+ ensureImageVolumeFor3DManipulation,
22
24
  };
@@ -3,8 +3,9 @@ import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
3
3
  import IslandRemoval from '../../../../utilities/segmentation/islandRemoval';
4
4
  export default {
5
5
  [StrategyCallbacks.OnInteractionEnd]: (operationData) => {
6
- const { strategySpecificConfiguration, previewSegmentIndex, segmentIndex, viewport, previewVoxelManager, segmentationVoxelManager, } = operationData;
7
- if (!strategySpecificConfiguration.THRESHOLD || segmentIndex === null) {
6
+ const { previewSegmentIndex, segmentIndex, viewport, previewVoxelManager, segmentationVoxelManager, activeStrategy, } = operationData;
7
+ if (activeStrategy !== 'THRESHOLD_INSIDE_SPHERE_WITH_ISLAND_REMOVAL' ||
8
+ segmentIndex === null) {
8
9
  return;
9
10
  }
10
11
  const islandRemoval = new IslandRemoval();
@@ -2,6 +2,6 @@ import type { InitializedOperationData } from '../BrushStrategy';
2
2
  declare const _default: {
3
3
  getStatistics: (enabledElement: any, operationData: InitializedOperationData, options?: {
4
4
  indices?: number | number[];
5
- }) => import("../../../../types").NamedStatistics;
5
+ }) => void;
6
6
  };
7
7
  export default _default;
@@ -1,103 +1,12 @@
1
1
  import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
2
- import VolumetricCalculator from '../../../../utilities/segmentation/VolumetricCalculator';
3
- import { getActiveSegmentIndex } from '../../../../stateManagement/segmentation/getActiveSegmentIndex';
4
- import { getStrategyData } from '../utils/getStrategyData';
5
- import { utilities } from '@cornerstonejs/core';
6
- import { getPixelValueUnits } from '../../../../utilities/getPixelValueUnits';
7
- import { AnnotationTool } from '../../../base';
8
- import { isViewportPreScaled } from '../../../../utilities/viewport/isViewportPreScaled';
9
- const radiusForVol1 = Math.pow((3 * 1000) / (4 * Math.PI), 1 / 3);
2
+ import getStatistics from '../../../../utilities/segmentation/getStatistics';
10
3
  export default {
11
4
  [StrategyCallbacks.GetStatistics]: function (enabledElement, operationData, options) {
12
- const { viewport } = enabledElement;
13
- let { indices } = options;
14
- const { segmentationId } = operationData;
15
- if (!indices) {
16
- indices = [getActiveSegmentIndex(segmentationId)];
17
- }
18
- else if (!Array.isArray(indices)) {
19
- indices = [indices, 255];
20
- }
21
- const indicesArr = indices;
22
- const { segmentationVoxelManager, imageVoxelManager, segmentationImageData, } = getStrategyData({
23
- operationData,
24
- viewport,
5
+ const { indices } = options;
6
+ const { segmentationId, viewport } = operationData;
7
+ getStatistics({
8
+ segmentationId,
9
+ segmentIndices: indices,
25
10
  });
26
- const spacing = segmentationImageData.getSpacing();
27
- const { boundsIJK: boundsOrig } = segmentationVoxelManager;
28
- if (!boundsOrig) {
29
- return VolumetricCalculator.getStatistics({ spacing });
30
- }
31
- segmentationVoxelManager.forEach((voxel) => {
32
- const { value, pointIJK } = voxel;
33
- if (indicesArr.indexOf(value) === -1) {
34
- return;
35
- }
36
- const imageValue = imageVoxelManager.getAtIJKPoint(pointIJK);
37
- VolumetricCalculator.statsCallback({ value: imageValue, pointIJK });
38
- });
39
- const targetId = viewport.getViewReferenceId();
40
- const modalityUnitOptions = {
41
- isPreScaled: isViewportPreScaled(viewport, targetId),
42
- isSuvScaled: AnnotationTool.isSuvScaled(viewport, targetId, viewport.getCurrentImageId()),
43
- };
44
- const imageData = viewport.getImageData();
45
- const unit = getPixelValueUnits(imageData.metadata.Modality, viewport.getCurrentImageId(), modalityUnitOptions);
46
- const stats = VolumetricCalculator.getStatistics({ spacing, unit });
47
- const { maxIJKs } = stats;
48
- if (!maxIJKs?.length) {
49
- return stats;
50
- }
51
- stats.mean.unit = unit;
52
- stats.max.unit = unit;
53
- stats.min.unit = unit;
54
- if (unit !== 'SUV') {
55
- return stats;
56
- }
57
- const radiusIJK = spacing.map((s) => Math.max(1, Math.round((1.1 * radiusForVol1) / s)));
58
- for (const testMax of maxIJKs) {
59
- const testStats = getSphereStats(testMax, radiusIJK, segmentationImageData, imageVoxelManager, spacing);
60
- if (!testStats) {
61
- continue;
62
- }
63
- const { mean } = testStats;
64
- if (!stats.peakValue || stats.peakValue.value <= mean.value) {
65
- stats.peakValue = {
66
- name: 'peakValue',
67
- label: 'Peak Value',
68
- value: mean.value,
69
- unit,
70
- };
71
- }
72
- }
73
- return stats;
74
11
  },
75
12
  };
76
- function getSphereStats(testMax, radiusIJK, segData, imageVoxels, spacing) {
77
- const { pointIJK: centerIJK } = testMax;
78
- const boundsIJK = centerIJK.map((ijk, idx) => [
79
- ijk - radiusIJK[idx],
80
- ijk + radiusIJK[idx],
81
- ]);
82
- const testFunction = (_pointLPS, pointIJK) => {
83
- const i = (pointIJK[0] - centerIJK[0]) / radiusIJK[0];
84
- const j = (pointIJK[1] - centerIJK[1]) / radiusIJK[1];
85
- const k = (pointIJK[2] - centerIJK[2]) / radiusIJK[2];
86
- const radius = i * i + j * j + k * k;
87
- return radius <= 1;
88
- };
89
- const statsFunction = ({ pointIJK, pointLPS }) => {
90
- const value = imageVoxels.getAtIJKPoint(pointIJK);
91
- if (value === undefined) {
92
- return;
93
- }
94
- VolumetricCalculator.statsCallback({ value, pointLPS, pointIJK });
95
- };
96
- VolumetricCalculator.statsInit({ storePointData: false });
97
- utilities.pointInShapeCallback(segData, {
98
- pointInShapeFn: testFunction,
99
- callback: statsFunction,
100
- boundsIJK,
101
- });
102
- return VolumetricCalculator.getStatistics({ spacing });
103
- }
@@ -12,14 +12,14 @@ function lightenColor(r, g, b, a, factor = 0.4) {
12
12
  }
13
13
  export default {
14
14
  [StrategyCallbacks.Preview]: function (operationData) {
15
- const { previewColors, strategySpecificConfiguration, enabledElement } = operationData;
16
- if (!previewColors || !strategySpecificConfiguration) {
15
+ const { previewColors, configuration, enabledElement } = operationData;
16
+ if (!previewColors || !configuration) {
17
17
  return;
18
18
  }
19
19
  if (operationData.preview) {
20
20
  delete operationData.preview;
21
21
  }
22
- delete strategySpecificConfiguration.centerSegmentIndex;
22
+ delete configuration.centerSegmentIndex;
23
23
  this.onInteractionStart?.(enabledElement, operationData);
24
24
  const preview = this.fill(enabledElement, operationData);
25
25
  if (preview) {
@@ -2,21 +2,20 @@ import { vec3 } from 'gl-matrix';
2
2
  import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
3
3
  export default {
4
4
  [StrategyCallbacks.CreateIsInThreshold]: (operationData) => {
5
- const { imageVoxelManager, strategySpecificConfiguration, segmentIndex } = operationData;
6
- if (!strategySpecificConfiguration || !segmentIndex) {
5
+ const { imageVoxelManager, segmentIndex, configuration } = operationData;
6
+ if (!configuration || !segmentIndex) {
7
7
  return;
8
8
  }
9
9
  return (index) => {
10
- const { THRESHOLD, THRESHOLD_INSIDE_CIRCLE } = strategySpecificConfiguration;
11
10
  const voxelValue = imageVoxelManager.getAtIndex(index);
12
11
  const gray = Array.isArray(voxelValue)
13
12
  ? vec3.length(voxelValue)
14
13
  : voxelValue;
15
- const { threshold } = THRESHOLD || THRESHOLD_INSIDE_CIRCLE || {};
16
- if (!threshold?.length) {
14
+ const { threshold } = configuration || {};
15
+ if (!threshold?.range?.length) {
17
16
  return true;
18
17
  }
19
- return threshold[0] <= gray && gray <= threshold[1];
18
+ return threshold.range[0] <= gray && gray <= threshold.range[1];
20
19
  };
21
20
  },
22
21
  };
@@ -61,8 +61,8 @@ function createPointInEllipse(worldInfo) {
61
61
  const { precalculated } = precalculatePointInEllipse(ellipseObj, {});
62
62
  return precalculated;
63
63
  }
64
- const CIRCLE_STRATEGY = new BrushStrategy('Circle', compositions.regionFill, compositions.setValue, initializeCircle, compositions.determineSegmentIndex, compositions.preview, compositions.labelmapStatistics, compositions.labelmapInterpolation);
65
- const CIRCLE_THRESHOLD_STRATEGY = new BrushStrategy('CircleThreshold', compositions.regionFill, compositions.setValue, initializeCircle, compositions.determineSegmentIndex, compositions.dynamicThreshold, compositions.threshold, compositions.preview, compositions.islandRemoval, compositions.labelmapStatistics, compositions.labelmapInterpolation);
64
+ const CIRCLE_STRATEGY = new BrushStrategy('Circle', compositions.regionFill, compositions.setValue, initializeCircle, compositions.determineSegmentIndex, compositions.preview, compositions.labelmapStatistics);
65
+ const CIRCLE_THRESHOLD_STRATEGY = new BrushStrategy('CircleThreshold', compositions.regionFill, compositions.setValue, initializeCircle, compositions.determineSegmentIndex, compositions.dynamicThreshold, compositions.threshold, compositions.preview, compositions.islandRemoval, compositions.labelmapStatistics);
66
66
  const fillInsideCircle = CIRCLE_STRATEGY.strategyFunction;
67
67
  const thresholdInsideCircle = CIRCLE_THRESHOLD_STRATEGY.strategyFunction;
68
68
  export function fillOutsideCircle() {
@@ -28,10 +28,10 @@ const sphereComposition = {
28
28
  });
29
29
  },
30
30
  };
31
- const SPHERE_STRATEGY = new BrushStrategy('Sphere', compositions.regionFill, compositions.setValue, sphereComposition, compositions.determineSegmentIndex, compositions.preview, compositions.labelmapStatistics);
31
+ const SPHERE_STRATEGY = new BrushStrategy('Sphere', compositions.regionFill, compositions.setValue, sphereComposition, compositions.determineSegmentIndex, compositions.preview, compositions.labelmapStatistics, compositions.ensureSegmentationVolumeFor3DManipulation);
32
32
  const fillInsideSphere = SPHERE_STRATEGY.strategyFunction;
33
- const SPHERE_THRESHOLD_STRATEGY = new BrushStrategy('SphereThreshold', ...SPHERE_STRATEGY.compositions, compositions.dynamicThreshold, compositions.threshold);
34
- const SPHERE_THRESHOLD_STRATEGY_ISLAND = new BrushStrategy('SphereThreshold', ...SPHERE_STRATEGY.compositions, compositions.dynamicThreshold, compositions.threshold, compositions.islandRemoval);
33
+ const SPHERE_THRESHOLD_STRATEGY = new BrushStrategy('SphereThreshold', ...SPHERE_STRATEGY.compositions, compositions.dynamicThreshold, compositions.threshold, compositions.ensureSegmentationVolumeFor3DManipulation, compositions.ensureImageVolumeFor3DManipulation);
34
+ const SPHERE_THRESHOLD_STRATEGY_ISLAND = new BrushStrategy('SphereThreshold', ...SPHERE_STRATEGY.compositions, compositions.dynamicThreshold, compositions.threshold, compositions.islandRemoval, compositions.ensureSegmentationVolumeFor3DManipulation, compositions.ensureImageVolumeFor3DManipulation);
35
35
  const thresholdInsideSphere = SPHERE_THRESHOLD_STRATEGY.strategyFunction;
36
36
  const thresholdInsideSphereIsland = SPHERE_THRESHOLD_STRATEGY_ISLAND.strategyFunction;
37
37
  export function fillOutsideSphere() {
@@ -1,11 +1,15 @@
1
- declare function getStrategyData({ operationData, viewport }: {
2
- operationData: any;
3
- viewport: any;
1
+ import { type Types } from '@cornerstonejs/core';
2
+ import type { LabelmapToolOperationDataStack, LabelmapToolOperationDataVolume } from '../../../../types';
3
+ declare function getStrategyData({ operationData, viewport, strategy, }: {
4
+ operationData: LabelmapToolOperationDataStack | LabelmapToolOperationDataVolume;
5
+ viewport?: Types.IStackViewport | Types.IVolumeViewport;
6
+ strategy: unknown;
4
7
  }): {
5
8
  segmentationImageData: any;
6
9
  segmentationScalarData: any;
7
10
  imageScalarData: any;
8
11
  segmentationVoxelManager: any;
9
12
  imageVoxelManager: any;
13
+ imageData: any;
10
14
  };
11
15
  export { getStrategyData };
@@ -1,47 +1,67 @@
1
1
  import { BaseVolumeViewport, cache, Enums, eventTarget, } from '@cornerstonejs/core';
2
2
  import { getCurrentLabelmapImageIdForViewport } from '../../../../stateManagement/segmentation/segmentationState';
3
3
  import { getLabelmapActorEntry } from '../../../../stateManagement/segmentation/helpers';
4
- function getStrategyData({ operationData, viewport }) {
5
- let segmentationImageData, segmentationScalarData, imageScalarData;
4
+ function getStrategyDataForVolumeViewport({ operationData }) {
5
+ const { volumeId } = operationData;
6
+ if (!volumeId) {
7
+ const event = new CustomEvent(Enums.Events.ERROR_EVENT, {
8
+ detail: {
9
+ type: 'Segmentation',
10
+ message: 'No volume id found for the segmentation',
11
+ },
12
+ cancelable: true,
13
+ });
14
+ eventTarget.dispatchEvent(event);
15
+ return null;
16
+ }
17
+ const segmentationVolume = cache.getVolume(volumeId);
18
+ if (!segmentationVolume) {
19
+ return null;
20
+ }
21
+ const referencedVolumeId = segmentationVolume.referencedVolumeId;
22
+ const segmentationVoxelManager = segmentationVolume.voxelManager;
6
23
  let imageVoxelManager;
24
+ let imageData;
25
+ if (referencedVolumeId) {
26
+ const imageVolume = cache.getVolume(referencedVolumeId);
27
+ imageVoxelManager = imageVolume.voxelManager;
28
+ imageData = imageVolume.imageData;
29
+ }
30
+ const { imageData: segmentationImageData } = segmentationVolume;
31
+ return {
32
+ segmentationImageData,
33
+ segmentationVoxelManager,
34
+ segmentationScalarData: null,
35
+ imageScalarData: null,
36
+ imageVoxelManager,
37
+ imageData,
38
+ };
39
+ }
40
+ function getStrategyDataForStackViewport({ operationData, viewport, strategy, }) {
41
+ const { segmentationId } = operationData;
42
+ let segmentationImageData;
7
43
  let segmentationVoxelManager;
8
- if (viewport instanceof BaseVolumeViewport) {
9
- const { volumeId, referencedVolumeId } = operationData;
10
- if (!volumeId) {
11
- const event = new CustomEvent(Enums.Events.ERROR_EVENT, {
12
- detail: {
13
- type: 'Segmentation',
14
- message: 'No volume id found for the segmentation',
15
- },
16
- cancelable: true,
17
- });
18
- eventTarget.dispatchEvent(event);
19
- return null;
20
- }
21
- const segmentationVolume = cache.getVolume(volumeId);
22
- if (!segmentationVolume) {
23
- return;
24
- }
25
- segmentationVoxelManager = segmentationVolume.voxelManager;
26
- if (referencedVolumeId) {
27
- const imageVolume = cache.getVolume(referencedVolumeId);
28
- imageVoxelManager = imageVolume.voxelManager;
29
- }
30
- ({ imageData: segmentationImageData } = segmentationVolume);
44
+ let segmentationScalarData;
45
+ let imageScalarData;
46
+ let imageVoxelManager;
47
+ let imageData;
48
+ if (strategy.ensureSegmentationVolumeFor3DManipulation) {
49
+ strategy.ensureSegmentationVolumeFor3DManipulation({
50
+ operationData,
51
+ viewport,
52
+ });
53
+ segmentationVoxelManager = operationData.segmentationVoxelManager;
54
+ segmentationImageData = operationData.segmentationImageData;
55
+ segmentationScalarData = null;
31
56
  }
32
57
  else {
33
- const { segmentationId } = operationData;
34
58
  const labelmapImageId = getCurrentLabelmapImageIdForViewport(viewport.id, segmentationId);
35
59
  if (!labelmapImageId) {
36
- return;
37
- }
38
- const currentImageId = viewport.getCurrentImageId();
39
- if (!currentImageId) {
40
- return;
60
+ return null;
41
61
  }
42
62
  const actorEntry = getLabelmapActorEntry(viewport.id, segmentationId);
43
63
  if (!actorEntry) {
44
- return;
64
+ return null;
45
65
  }
46
66
  const currentSegImage = cache.getImage(labelmapImageId);
47
67
  segmentationImageData = actorEntry.actor.getMapper().getInputData();
@@ -49,11 +69,26 @@ function getStrategyData({ operationData, viewport }) {
49
69
  const currentSegmentationImageId = operationData.imageId;
50
70
  const segmentationImage = cache.getImage(currentSegmentationImageId);
51
71
  if (!segmentationImage) {
52
- return;
72
+ return null;
53
73
  }
54
74
  segmentationScalarData = segmentationImage.getPixelData?.();
75
+ }
76
+ if (strategy.ensureImageVolumeFor3DManipulation) {
77
+ strategy.ensureImageVolumeFor3DManipulation({
78
+ operationData,
79
+ viewport,
80
+ });
81
+ imageVoxelManager = operationData.imageVoxelManager;
82
+ imageScalarData = operationData.imageScalarData;
83
+ imageData = operationData.imageData;
84
+ }
85
+ else {
86
+ const currentImageId = viewport.getCurrentImageId();
87
+ if (!currentImageId) {
88
+ return null;
89
+ }
55
90
  const image = cache.getImage(currentImageId);
56
- const imageData = image ? null : viewport.getImageData();
91
+ imageData = image ? null : viewport.getImageData();
57
92
  imageScalarData = image?.getPixelData() || imageData.getScalarData();
58
93
  imageVoxelManager = image?.voxelManager;
59
94
  }
@@ -63,6 +98,15 @@ function getStrategyData({ operationData, viewport }) {
63
98
  imageScalarData,
64
99
  segmentationVoxelManager,
65
100
  imageVoxelManager,
101
+ imageData,
66
102
  };
67
103
  }
104
+ function getStrategyData({ operationData, viewport, strategy, }) {
105
+ if (('volumeId' in operationData && operationData.volumeId !== undefined) ||
106
+ ('referencedVolumeId' in operationData &&
107
+ operationData.referencedVolumeId !== undefined)) {
108
+ return getStrategyDataForVolumeViewport({ operationData });
109
+ }
110
+ return getStrategyDataForStackViewport({ operationData, viewport, strategy });
111
+ }
68
112
  export { getStrategyData };
@@ -1,10 +1,5 @@
1
1
  import type { Types } from '@cornerstonejs/core';
2
- declare function isWithinThreshold(index: number, imageScalarData: Types.PixelDataTypedArray, strategySpecificConfiguration: {
3
- THRESHOLD?: {
4
- threshold: number[];
5
- };
6
- THRESHOLD_INSIDE_CIRCLE?: {
7
- threshold: number[];
8
- };
2
+ declare function isWithinThreshold(index: number, imageScalarData: Types.PixelDataTypedArray, threshold: {
3
+ range: number[];
9
4
  }): boolean;
10
5
  export default isWithinThreshold;
@@ -1,7 +1,8 @@
1
- function isWithinThreshold(index, imageScalarData, strategySpecificConfiguration) {
2
- const { THRESHOLD, THRESHOLD_INSIDE_CIRCLE } = strategySpecificConfiguration;
1
+ function isWithinThreshold(index, imageScalarData, threshold) {
2
+ if (!threshold) {
3
+ return true;
4
+ }
3
5
  const voxelValue = imageScalarData[index];
4
- const { threshold } = THRESHOLD || THRESHOLD_INSIDE_CIRCLE;
5
- return threshold[0] <= voxelValue && voxelValue <= threshold[1];
6
+ return threshold.range[0] <= voxelValue && voxelValue <= threshold.range[1];
6
7
  }
7
8
  export default isWithinThreshold;
@@ -4,6 +4,8 @@ type Statistics = {
4
4
  label?: string;
5
5
  value: number | number[];
6
6
  unit: null | string;
7
+ pointIJK?: Types.Point3;
8
+ pointLPS?: Types.Point3;
7
9
  };
8
10
  type NamedStatistics = {
9
11
  mean: Statistics & {
@@ -9,7 +9,7 @@ type LabelmapToolOperationData = {
9
9
  segmentsLocked: number[];
10
10
  viewPlaneNormal: number[];
11
11
  viewUp: number[];
12
- strategySpecificConfiguration: any;
12
+ activeStrategy: string;
13
13
  points: Types.Point3[];
14
14
  voxelManager: any;
15
15
  override: {
@@ -42,9 +42,8 @@ import type { SplineCurveSegment } from './SplineCurveSegment';
42
42
  import type { SplineLineSegment } from './SplineLineSegment';
43
43
  import type { SplineProps } from './SplineProps';
44
44
  import type { BidirectionalData } from '../utilities/segmentation/createBidirectionalToolData';
45
- import type { PolySegConversionOptions } from './PolySeg';
46
45
  import type { IBaseTool } from './IBaseTool';
47
46
  import type { RepresentationStyle } from './../stateManagement/segmentation/SegmentationStyle';
48
- import type { LabelmapStyle } from './LabelmapTypes';
49
- import type { SurfaceStyle } from './SurfaceTypes';
50
- export type { Annotation, Annotations, ContourAnnotationData, ContourAnnotation, ContourSegmentationAnnotationData, ContourSegmentationAnnotation, BidirectionalData, CanvasCoordinates, IAnnotationManager, InterpolationViewportData, ImageInterpolationData, GroupSpecificAnnotations, AnnotationState, AnnotationStyle, ToolSpecificAnnotationTypes, AnnotationGroupSelector, AnnotationRenderContext, PlanarBoundingBox, ToolProps, PublicToolProps, ToolConfiguration, EventTypes, IPoints, ITouchPoints, IDistance, IToolBinding, SetToolBindingsType, ToolOptionsType, InteractionTypes, ToolAction, IToolGroup, IToolClassReference, ISynchronizerEventHandler, ToolHandle, AnnotationHandle, TextBoxHandle, Segmentation, SegmentationRepresentation, SegmentationState, RepresentationData, RepresentationsData, SVGCursorDescriptor, SVGPoint, CINETypes, BoundsIJK, SVGDrawingHelper, FloodFillResult, FloodFillGetter, FloodFillOptions, ContourSegmentationData, ISculptToolShape, Statistics, NamedStatistics, LabelmapToolOperationData, LabelmapToolOperationDataStack, LabelmapToolOperationDataVolume, CardinalSplineProps, ClosestControlPoint, ClosestPoint, ClosestSplinePoint, ControlPointInfo, ISpline, SplineCurveSegment, SplineLineSegment, SplineProps, PolySegConversionOptions, IBaseTool, RepresentationStyle, Segment, SegmentationPublicInput, LabelmapStyle, ContourStyle, SurfaceStyle, };
47
+ import type { LabelmapStyle, LabelmapSegmentationData, LabelmapSegmentationDataStack, LabelmapSegmentationDataVolume, BaseLabelmapStyle, InactiveLabelmapStyle } from './LabelmapTypes';
48
+ import type { SurfaceStyle, SurfaceSegmentationData, SurfaceStateStyles } from './SurfaceTypes';
49
+ export type { Annotation, Annotations, ContourAnnotationData, ContourAnnotation, ContourSegmentationAnnotationData, ContourSegmentationAnnotation, BidirectionalData, CanvasCoordinates, IAnnotationManager, InterpolationViewportData, ImageInterpolationData, GroupSpecificAnnotations, AnnotationState, AnnotationStyle, ToolSpecificAnnotationTypes, AnnotationGroupSelector, AnnotationRenderContext, PlanarBoundingBox, ToolProps, PublicToolProps, ToolConfiguration, EventTypes, IPoints, ITouchPoints, IDistance, IToolBinding, SetToolBindingsType, ToolOptionsType, InteractionTypes, ToolAction, IToolGroup, IToolClassReference, ISynchronizerEventHandler, ToolHandle, AnnotationHandle, TextBoxHandle, Segmentation, SegmentationRepresentation, SegmentationState, RepresentationData, RepresentationsData, SVGCursorDescriptor, SVGPoint, CINETypes, BoundsIJK, SVGDrawingHelper, FloodFillResult, FloodFillGetter, FloodFillOptions, ContourSegmentationData, ISculptToolShape, Statistics, NamedStatistics, LabelmapToolOperationData, LabelmapToolOperationDataStack, LabelmapToolOperationDataVolume, CardinalSplineProps, ClosestControlPoint, ClosestPoint, ClosestSplinePoint, ControlPointInfo, ISpline, SplineCurveSegment, SplineLineSegment, SplineProps, IBaseTool, RepresentationStyle, Segment, SegmentationPublicInput, LabelmapStyle, ContourStyle, SurfaceStyle, SurfaceSegmentationData, SurfaceStateStyles, LabelmapSegmentationData, LabelmapSegmentationDataStack, LabelmapSegmentationDataVolume, BaseLabelmapStyle, InactiveLabelmapStyle, };
@@ -2,6 +2,7 @@ type pixelUnitsOptions = {
2
2
  isPreScaled: boolean;
3
3
  isSuvScaled: boolean;
4
4
  };
5
+ declare function getPixelValueUnitsImageId(imageId: string, options: pixelUnitsOptions): string;
5
6
  declare function getPixelValueUnits(modality: string, imageId: string, options: pixelUnitsOptions): string;
6
7
  export type { pixelUnitsOptions };
7
- export { getPixelValueUnits };
8
+ export { getPixelValueUnits, getPixelValueUnitsImageId };
@@ -1,4 +1,8 @@
1
1
  import { metaData } from '@cornerstonejs/core';
2
+ function getPixelValueUnitsImageId(imageId, options) {
3
+ const generalSeriesModule = metaData.get('generalSeriesModule', imageId);
4
+ return getPixelValueUnits(generalSeriesModule.modality, imageId, options);
5
+ }
2
6
  function getPixelValueUnits(modality, imageId, options) {
3
7
  if (modality === 'CT') {
4
8
  return 'HU';
@@ -24,4 +28,4 @@ function _handlePTModality(imageId, options) {
24
28
  }
25
29
  return 'unknown';
26
30
  }
27
- export { getPixelValueUnits };
31
+ export { getPixelValueUnits, getPixelValueUnitsImageId };