@cornerstonejs/tools 2.8.6 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/esm/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.js +1 -1
  2. package/dist/esm/eventDispatchers/shared/getToolsWithActionsForMouseEvent.js +1 -1
  3. package/dist/esm/index.d.ts +2 -2
  4. package/dist/esm/index.js +2 -2
  5. package/dist/esm/stateManagement/segmentation/activeSegmentation.d.ts +1 -1
  6. package/dist/esm/stateManagement/segmentation/activeSegmentation.js +1 -1
  7. package/dist/esm/stateManagement/segmentation/index.d.ts +3 -1
  8. package/dist/esm/stateManagement/segmentation/index.js +3 -1
  9. package/dist/esm/stateManagement/segmentation/internalAddSegmentationRepresentation.js +1 -0
  10. package/dist/esm/stateManagement/segmentation/polySeg/Contour/utils/createAndAddContourSegmentationsFromClippedSurfaces.js +1 -1
  11. package/dist/esm/stateManagement/segmentation/polySeg/Labelmap/labelmapComputationStrategies.js +4 -2
  12. package/dist/esm/tools/annotation/RegionSegmentPlusTool.d.ts +3 -2
  13. package/dist/esm/tools/annotation/RegionSegmentPlusTool.js +27 -12
  14. package/dist/esm/tools/annotation/RegionSegmentTool.d.ts +1 -1
  15. package/dist/esm/tools/annotation/RegionSegmentTool.js +7 -8
  16. package/dist/esm/tools/annotation/SplineROITool.js +7 -1
  17. package/dist/esm/tools/annotation/WholeBodySegmentTool.d.ts +3 -2
  18. package/dist/esm/tools/annotation/WholeBodySegmentTool.js +40 -5
  19. package/dist/esm/tools/base/AnnotationTool.d.ts +2 -1
  20. package/dist/esm/tools/base/AnnotationTool.js +6 -3
  21. package/dist/esm/tools/base/ContourSegmentationBaseTool.d.ts +1 -0
  22. package/dist/esm/tools/base/ContourSegmentationBaseTool.js +1 -0
  23. package/dist/esm/tools/base/GrowCutBaseTool.d.ts +25 -10
  24. package/dist/esm/tools/base/GrowCutBaseTool.js +124 -21
  25. package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.d.ts +5 -1
  26. package/dist/esm/tools/displayTools/Labelmap/addLabelmapToElement.js +17 -3
  27. package/dist/esm/tools/displayTools/Labelmap/addVolumesAsIndependentComponents.d.ts +10 -0
  28. package/dist/esm/tools/displayTools/Labelmap/addVolumesAsIndependentComponents.js +123 -0
  29. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.d.ts +1 -0
  30. package/dist/esm/tools/displayTools/Labelmap/labelmapDisplay.js +17 -10
  31. package/dist/esm/tools/index.d.ts +3 -1
  32. package/dist/esm/tools/index.js +3 -1
  33. package/dist/esm/tools/segmentation/BrushTool.d.ts +0 -1
  34. package/dist/esm/tools/segmentation/LabelmapBaseTool.d.ts +5 -1
  35. package/dist/esm/tools/segmentation/LabelmapBaseTool.js +107 -12
  36. package/dist/esm/tools/segmentation/SegmentSelectTool.js +0 -1
  37. package/dist/esm/tools/segmentation/strategies/compositions/index.js +1 -1
  38. package/dist/esm/tools/segmentation/strategies/compositions/islandRemovalComposition.d.ts +5 -0
  39. package/dist/esm/tools/segmentation/strategies/compositions/islandRemovalComposition.js +27 -0
  40. package/dist/esm/tools/segmentation/strategies/compositions/labelmapStatistics.js +69 -2
  41. package/dist/esm/types/CalculatorTypes.d.ts +4 -0
  42. package/dist/esm/types/SegmentationStateTypes.d.ts +3 -1
  43. package/dist/esm/utilities/contourSegmentation/addContourSegmentationAnnotation.js +5 -2
  44. package/dist/esm/utilities/index.d.ts +3 -1
  45. package/dist/esm/utilities/index.js +3 -1
  46. package/dist/esm/utilities/planar/filterAnnotationsWithinSlice.js +2 -2
  47. package/dist/esm/utilities/planar/getPointInLineOfSightWithCriteria.d.ts +5 -1
  48. package/dist/esm/utilities/planar/getPointInLineOfSightWithCriteria.js +40 -29
  49. package/dist/esm/utilities/planar/index.d.ts +3 -2
  50. package/dist/esm/utilities/planar/index.js +3 -2
  51. package/dist/esm/utilities/segmentation/VolumetricCalculator.d.ts +7 -0
  52. package/dist/esm/utilities/segmentation/VolumetricCalculator.js +28 -0
  53. package/dist/esm/utilities/segmentation/growCut/runGrowCutForBoundingBox.d.ts +0 -2
  54. package/dist/esm/utilities/segmentation/growCut/runOneClickGrowCut.d.ts +0 -4
  55. package/dist/esm/utilities/segmentation/index.d.ts +2 -1
  56. package/dist/esm/utilities/segmentation/index.js +2 -1
  57. package/dist/esm/utilities/segmentation/islandRemoval.d.ts +28 -0
  58. package/dist/esm/utilities/segmentation/islandRemoval.js +181 -0
  59. package/package.json +3 -3
  60. package/dist/esm/tools/segmentation/strategies/compositions/islandRemoval.d.ts +0 -16
  61. package/dist/esm/tools/segmentation/strategies/compositions/islandRemoval.js +0 -159
  62. /package/dist/esm/{tools/segmentation/strategies/utils → utilities}/normalizeViewportPlane.d.ts +0 -0
  63. /package/dist/esm/{tools/segmentation/strategies/utils → utilities}/normalizeViewportPlane.js +0 -0
@@ -1,13 +1,25 @@
1
- import { getEnabledElement, utilities as csUtils, cache, } from '@cornerstonejs/core';
1
+ import { getEnabledElement, utilities as csUtils, cache, getRenderingEngine, StackViewport, } from '@cornerstonejs/core';
2
2
  import { BaseTool } from '../base';
3
3
  import { SegmentationRepresentations } from '../../enums';
4
4
  import { segmentIndex as segmentIndexController, state as segmentationState, activeSegmentation, } from '../../stateManagement/segmentation';
5
5
  import { triggerSegmentationDataModified } from '../../stateManagement/segmentation/triggerSegmentationEvents';
6
6
  import { getSVGStyleForSegment } from '../../utilities/segmentation/getSVGStyleForSegment';
7
+ import IslandRemoval from '../../utilities/segmentation/islandRemoval';
7
8
  const { transformWorldToIndex, transformIndexToWorld } = csUtils;
8
9
  class GrowCutBaseTool extends BaseTool {
10
+ static { this.lastGrowCutCommand = null; }
9
11
  constructor(toolProps, defaultToolProps) {
10
- super(toolProps, defaultToolProps);
12
+ const baseToolProps = csUtils.deepMerge({
13
+ configuration: {
14
+ positiveSeedVariance: 0.1,
15
+ negativeSeedVariance: 0.9,
16
+ shrinkExpandIncrement: 0.05,
17
+ islandRemoval: {
18
+ enabled: false,
19
+ },
20
+ },
21
+ }, defaultToolProps);
22
+ super(toolProps, baseToolProps);
11
23
  }
12
24
  async preMouseDownCallback(evt) {
13
25
  const eventData = evt.detail;
@@ -16,7 +28,7 @@ class GrowCutBaseTool extends BaseTool {
16
28
  const enabledElement = getEnabledElement(element);
17
29
  const { viewport, renderingEngine } = enabledElement;
18
30
  const { viewUp } = viewport.getCamera();
19
- const { segmentationId, segmentIndex, labelmapVolumeId, referencedVolumeId, } = this.getLabelmapSegmentationData(viewport);
31
+ const { segmentationId, segmentIndex, labelmapVolumeId, referencedVolumeId, } = await this.getLabelmapSegmentationData(viewport);
20
32
  if (!this._isOrthogonalView(viewport, referencedVolumeId)) {
21
33
  throw new Error('Oblique view is not supported yet');
22
34
  }
@@ -37,18 +49,59 @@ class GrowCutBaseTool extends BaseTool {
37
49
  evt.preventDefault();
38
50
  return true;
39
51
  }
40
- async getGrowCutLabelmap() {
52
+ shrink() {
53
+ this._runLastCommand({
54
+ shrinkExpandAmount: -this.configuration.shrinkExpandIncrement,
55
+ });
56
+ }
57
+ expand() {
58
+ this._runLastCommand({
59
+ shrinkExpandAmount: this.configuration.shrinkExpandIncrement,
60
+ });
61
+ }
62
+ refresh() {
63
+ this._runLastCommand();
64
+ }
65
+ async getGrowCutLabelmap(_growCutData) {
41
66
  throw new Error('Not implemented');
42
67
  }
43
68
  async runGrowCut() {
44
- const { segmentation: { segmentationId, segmentIndex, labelmapVolumeId }, } = this.growCutData;
69
+ const { growCutData, configuration: config } = this;
70
+ const { segmentation: { segmentationId, segmentIndex, labelmapVolumeId }, } = growCutData;
71
+ const hasSeedVarianceData = config.positiveSeedVariance !== undefined &&
72
+ config.negativeSeedVariance !== undefined;
45
73
  const labelmap = cache.getVolume(labelmapVolumeId);
46
- const growcutLabelmap = await this.getGrowCutLabelmap();
47
- this.applyGrowCutLabelmap(segmentationId, segmentIndex, labelmap, growcutLabelmap);
74
+ let shrinkExpandValue = 0;
75
+ const growCutCommand = async ({ shrinkExpandAmount = 0 } = {}) => {
76
+ const { positiveSeedVariance, negativeSeedVariance } = config;
77
+ let newPositiveSeedVariance = undefined;
78
+ let newNegativeSeedVariance = undefined;
79
+ shrinkExpandValue += shrinkExpandAmount;
80
+ if (hasSeedVarianceData) {
81
+ newPositiveSeedVariance = positiveSeedVariance + shrinkExpandValue;
82
+ newNegativeSeedVariance = negativeSeedVariance + shrinkExpandValue;
83
+ }
84
+ const updatedGrowCutData = Object.assign({}, growCutData, {
85
+ options: {
86
+ positiveSeedValue: segmentIndex,
87
+ negativeSeedValue: 255,
88
+ positiveSeedVariance: newPositiveSeedVariance,
89
+ negativeSeedVariance: newNegativeSeedVariance,
90
+ },
91
+ });
92
+ const growcutLabelmap = await this.getGrowCutLabelmap(updatedGrowCutData);
93
+ this.applyGrowCutLabelmap(segmentationId, segmentIndex, labelmap, growcutLabelmap);
94
+ this._removeIslands(growCutData);
95
+ };
96
+ await growCutCommand();
97
+ if (hasSeedVarianceData) {
98
+ GrowCutBaseTool.lastGrowCutCommand = growCutCommand;
99
+ }
100
+ this.growCutData = null;
48
101
  }
49
102
  applyGrowCutLabelmap(segmentationId, segmentIndex, targetLabelmap, sourceLabelmap) {
50
103
  const srcLabelmapData = sourceLabelmap.voxelManager.getCompleteScalarDataArray();
51
- const targetLabelmapData = targetLabelmap.voxelManager.getCompleteScalarDataArray();
104
+ const tgtVoxelManager = targetLabelmap.voxelManager;
52
105
  const [srcColumns, srcRows, srcNumSlices] = sourceLabelmap.dimensions;
53
106
  const [tgtColumns, tgtRows] = targetLabelmap.dimensions;
54
107
  const srcPixelsPerSlice = srcColumns * srcRows;
@@ -62,29 +115,34 @@ class GrowCutBaseTool extends BaseTool {
62
115
  const srcOffset = srcRow * srcColumns + srcSlice * srcPixelsPerSlice;
63
116
  const tgtOffset = tgtColumn + tgtRow * tgtColumns + tgtSlice * tgtPixelsPerSlice;
64
117
  for (let column = 0; column < srcColumns; column++) {
65
- targetLabelmapData[tgtOffset + column] =
66
- srcLabelmapData[srcOffset + column] === segmentIndex
67
- ? segmentIndex
68
- : 0;
118
+ const labelmapValue = srcLabelmapData[srcOffset + column] === segmentIndex
119
+ ? segmentIndex
120
+ : 0;
121
+ tgtVoxelManager.setAtIndex(tgtOffset + column, labelmapValue);
69
122
  }
70
123
  }
71
124
  }
72
- targetLabelmap.voxelManager.setCompleteScalarDataArray(targetLabelmapData);
73
125
  triggerSegmentationDataModified(segmentationId);
74
126
  }
75
- getSegmentStyle({ segmentationId, viewportId, segmentIndex }) {
76
- return getSVGStyleForSegment({
77
- segmentationId,
78
- segmentIndex,
79
- viewportId,
80
- });
127
+ _runLastCommand({ shrinkExpandAmount = 0 } = {}) {
128
+ const cmd = GrowCutBaseTool.lastGrowCutCommand;
129
+ if (cmd) {
130
+ cmd({ shrinkExpandAmount });
131
+ }
81
132
  }
82
- getLabelmapSegmentationData(viewport) {
83
- const { segmentationId } = activeSegmentation.getActiveSegmentation(viewport.id);
133
+ async getLabelmapSegmentationData(viewport) {
134
+ const activeSeg = activeSegmentation.getActiveSegmentation(viewport.id);
135
+ if (!activeSeg) {
136
+ throw new Error('No active segmentation found');
137
+ }
138
+ const { segmentationId } = activeSeg;
84
139
  const segmentIndex = segmentIndexController.getActiveSegmentIndex(segmentationId);
85
140
  const { representationData } = segmentationState.getSegmentation(segmentationId);
86
141
  const labelmapData = representationData[SegmentationRepresentations.Labelmap];
87
142
  const { volumeId: labelmapVolumeId, referencedVolumeId } = labelmapData;
143
+ if (!labelmapVolumeId) {
144
+ throw new Error('Labelmap volume id not found - not implemented');
145
+ }
88
146
  return {
89
147
  segmentationId,
90
148
  segmentIndex,
@@ -101,6 +159,51 @@ class GrowCutBaseTool extends BaseTool {
101
159
  csUtils.isEqual(Math.abs(vec[1]), 1) ||
102
160
  csUtils.isEqual(Math.abs(vec[2]), 1));
103
161
  }
162
+ getRemoveIslandData(_growCutData) {
163
+ return;
164
+ }
165
+ _removeIslands(growCutData) {
166
+ const { islandRemoval: config } = this.configuration;
167
+ if (!config.enabled) {
168
+ return;
169
+ }
170
+ const { segmentation: { segmentIndex, labelmapVolumeId }, renderingEngineId, viewportId, } = growCutData;
171
+ const labelmap = cache.getVolume(labelmapVolumeId);
172
+ const removeIslandData = this.getRemoveIslandData(growCutData);
173
+ if (!removeIslandData) {
174
+ return;
175
+ }
176
+ const [width, height] = labelmap.dimensions;
177
+ const numPixelsPerSlice = width * height;
178
+ const { worldIslandPoints = [], islandPointIndexes = [] } = removeIslandData;
179
+ let ijkIslandPoints = [...(removeIslandData?.ijkIslandPoints ?? [])];
180
+ const renderingEngine = getRenderingEngine(renderingEngineId);
181
+ const viewport = renderingEngine.getViewport(viewportId);
182
+ const { voxelManager } = labelmap;
183
+ const islandRemoval = new IslandRemoval();
184
+ ijkIslandPoints = ijkIslandPoints.concat(worldIslandPoints.map((worldPoint) => transformWorldToIndex(labelmap.imageData, worldPoint)));
185
+ ijkIslandPoints = ijkIslandPoints.concat(islandPointIndexes.map((pointIndex) => {
186
+ const x = pointIndex % width;
187
+ const y = Math.floor(pointIndex / width) % height;
188
+ const z = Math.floor(pointIndex / numPixelsPerSlice);
189
+ return [x, y, z];
190
+ }));
191
+ islandRemoval.initialize(viewport, voxelManager, {
192
+ points: ijkIslandPoints,
193
+ previewSegmentIndex: segmentIndex,
194
+ segmentIndex,
195
+ });
196
+ islandRemoval.floodFillSegmentIsland();
197
+ islandRemoval.removeExternalIslands();
198
+ islandRemoval.removeInternalIslands();
199
+ }
200
+ getSegmentStyle({ segmentationId, viewportId, segmentIndex }) {
201
+ return getSVGStyleForSegment({
202
+ segmentationId,
203
+ segmentIndex,
204
+ viewportId,
205
+ });
206
+ }
104
207
  }
105
208
  GrowCutBaseTool.toolName = 'GrowCutBaseTool';
106
209
  export default GrowCutBaseTool;
@@ -1,3 +1,7 @@
1
1
  import type { LabelmapSegmentationData } from '../../../types/LabelmapTypes';
2
- declare function addLabelmapToElement(element: HTMLDivElement, labelMapData: LabelmapSegmentationData, segmentationId: string): Promise<void>;
2
+ import type { LabelmapRenderingConfig } from '../../../types/SegmentationStateTypes';
3
+ declare function addLabelmapToElement(element: HTMLDivElement, labelMapData: LabelmapSegmentationData, segmentationId: string, config: LabelmapRenderingConfig): Promise<void | {
4
+ uid: string;
5
+ actor: any;
6
+ }>;
3
7
  export default addLabelmapToElement;
@@ -3,8 +3,9 @@ import { getCurrentLabelmapImageIdForViewport } from '../../../stateManagement/s
3
3
  import { getSegmentation } from '../../../stateManagement/segmentation/getSegmentation';
4
4
  import { triggerSegmentationDataModified, triggerSegmentationModified, } from '../../../stateManagement/segmentation/triggerSegmentationEvents';
5
5
  import { SegmentationRepresentations } from '../../../enums';
6
+ import { addVolumesAsIndependentComponents } from './addVolumesAsIndependentComponents';
6
7
  const { uuidv4 } = utilities;
7
- async function addLabelmapToElement(element, labelMapData, segmentationId) {
8
+ async function addLabelmapToElement(element, labelMapData, segmentationId, config) {
8
9
  const enabledElement = getEnabledElement(element);
9
10
  const { renderingEngine, viewport } = enabledElement;
10
11
  const { id: viewportId } = viewport;
@@ -17,15 +18,28 @@ async function addLabelmapToElement(element, labelMapData, segmentationId) {
17
18
  if (!cache.getVolume(volumeId)) {
18
19
  await _handleMissingVolume(labelMapData);
19
20
  }
21
+ const blendMode = config?.blendMode ?? Enums.BlendModes.MAXIMUM_INTENSITY_BLEND;
22
+ const useIndependentComponents = blendMode === Enums.BlendModes.LABELMAP_EDGE_PROJECTION_BLEND;
20
23
  const volumeInputs = [
21
24
  {
22
25
  volumeId,
23
26
  visibility,
24
- blendMode: Enums.BlendModes.MAXIMUM_INTENSITY_BLEND,
25
27
  representationUID: `${segmentationId}-${SegmentationRepresentations.Labelmap}`,
28
+ useIndependentComponents,
29
+ blendMode,
26
30
  },
27
31
  ];
28
- await addVolumesToViewports(renderingEngine, volumeInputs, [viewportId], immediateRender, suppressEvents);
32
+ if (!volumeInputs[0].useIndependentComponents) {
33
+ await addVolumesToViewports(renderingEngine, volumeInputs, [viewportId], immediateRender, suppressEvents);
34
+ }
35
+ else {
36
+ const result = await addVolumesAsIndependentComponents({
37
+ viewport,
38
+ volumeInputs,
39
+ segmentationId,
40
+ });
41
+ return result;
42
+ }
29
43
  }
30
44
  else {
31
45
  const segmentationImageId = getCurrentLabelmapImageIdForViewport(viewport.id, segmentationId);
@@ -0,0 +1,10 @@
1
+ import { type Types } from '@cornerstonejs/core';
2
+ import type vtkVolume from '@kitware/vtk.js/Rendering/Core/Volume';
3
+ export declare function addVolumesAsIndependentComponents({ viewport, volumeInputs, segmentationId, }: {
4
+ viewport: Types.IVolumeViewport;
5
+ volumeInputs: Types.IVolumeInput[];
6
+ segmentationId: string;
7
+ }): Promise<{
8
+ uid: string;
9
+ actor: vtkVolume;
10
+ }>;
@@ -0,0 +1,123 @@
1
+ import { cache, Enums, convertMapperToNotSharedMapper, volumeLoader, eventTarget, createVolumeActor, } from '@cornerstonejs/core';
2
+ import { Events, SegmentationRepresentations } from '../../../enums';
3
+ import { getSegmentation } from '../../../stateManagement/segmentation/getSegmentation';
4
+ const internalCache = new Map();
5
+ const load = ({ cfun, ofun, actor }) => {
6
+ actor.getProperty().setRGBTransferFunction(1, cfun);
7
+ actor.getProperty().setScalarOpacity(1, ofun);
8
+ };
9
+ export async function addVolumesAsIndependentComponents({ viewport, volumeInputs, segmentationId, }) {
10
+ const defaultActor = viewport.getDefaultActor();
11
+ const { actor } = defaultActor;
12
+ const { uid, callback } = defaultActor;
13
+ const referenceVolumeId = viewport.getVolumeId();
14
+ if (internalCache.get(uid)?.added) {
15
+ return {
16
+ uid,
17
+ actor,
18
+ };
19
+ }
20
+ const volumeInputArray = volumeInputs;
21
+ const firstImageVolume = cache.getVolume(volumeInputArray[0].volumeId);
22
+ if (!firstImageVolume) {
23
+ throw new Error(`imageVolume with id: ${firstImageVolume.volumeId} does not exist`);
24
+ }
25
+ const { volumeId } = volumeInputArray[0];
26
+ const segImageVolume = await volumeLoader.loadVolume(volumeId);
27
+ if (!segImageVolume) {
28
+ throw new Error(`segImageVolume with id: ${segImageVolume.volumeId} does not exist`);
29
+ }
30
+ const segVoxelManager = segImageVolume.voxelManager;
31
+ const { imageData: segImageData } = segImageVolume;
32
+ const baseVolume = cache.getVolume(referenceVolumeId);
33
+ const baseVoxelManager = baseVolume.voxelManager;
34
+ const newComp = 2;
35
+ const cubeData = new Float32Array(newComp * baseVolume.voxelManager.getScalarDataLength());
36
+ const dims = segImageData.getDimensions();
37
+ for (let z = 0; z < dims[2]; ++z) {
38
+ for (let y = 0; y < dims[1]; ++y) {
39
+ for (let x = 0; x < dims[0]; ++x) {
40
+ const iTuple = x + dims[0] * (y + dims[1] * z);
41
+ cubeData[iTuple * newComp + 0] = baseVoxelManager.getAtIndex(iTuple);
42
+ cubeData[iTuple * newComp + 1] = segVoxelManager.getAtIndex(iTuple);
43
+ }
44
+ }
45
+ }
46
+ viewport.removeActors([uid]);
47
+ const oldMapper = actor.getMapper();
48
+ const mapper = convertMapperToNotSharedMapper(oldMapper);
49
+ actor.setMapper(mapper);
50
+ mapper.setBlendMode(Enums.BlendModes.LABELMAP_EDGE_PROJECTION_BLEND);
51
+ const arrayAgain = mapper.getInputData().getPointData().getArray(0);
52
+ arrayAgain.setData(cubeData);
53
+ arrayAgain.setNumberOfComponents(2);
54
+ actor.getProperty().setColorMixPreset(1);
55
+ actor.getProperty().setForceNearestInterpolation(1, true);
56
+ actor.getProperty().setIndependentComponents(true);
57
+ viewport.addActor({
58
+ actor,
59
+ uid,
60
+ callback,
61
+ referencedId: referenceVolumeId,
62
+ representationUID: `${segmentationId}-${SegmentationRepresentations.Labelmap}`,
63
+ });
64
+ internalCache.set(uid, {
65
+ added: true,
66
+ segmentationRepresentationUID: `${segmentationId}`,
67
+ originalBlendMode: viewport.getBlendMode(),
68
+ });
69
+ actor.set({
70
+ preLoad: load,
71
+ });
72
+ function onSegmentationDataModified(evt) {
73
+ const { segmentationId, modifiedSlicesToUse } = evt.detail;
74
+ const { representationData } = getSegmentation(segmentationId);
75
+ const { volumeId: segVolumeId } = representationData.Labelmap;
76
+ if (segVolumeId !== segImageVolume.volumeId) {
77
+ return;
78
+ }
79
+ const segmentationVolume = cache.getVolume(segVolumeId);
80
+ const segVoxelManager = segmentationVolume.voxelManager;
81
+ const array = mapper.getInputData().getPointData().getArray(0);
82
+ const baseData = array.getData();
83
+ const newComp = 2;
84
+ const dims = segImageData.getDimensions();
85
+ const slices = modifiedSlicesToUse?.length
86
+ ? modifiedSlicesToUse
87
+ : Array.from({ length: dims[2] }, (_, i) => i);
88
+ for (const z of slices) {
89
+ for (let y = 0; y < dims[1]; ++y) {
90
+ for (let x = 0; x < dims[0]; ++x) {
91
+ const iTuple = x + dims[0] * (y + dims[1] * z);
92
+ baseData[iTuple * newComp + 1] = segVoxelManager.getAtIndex(iTuple);
93
+ }
94
+ }
95
+ }
96
+ array.setData(baseData);
97
+ }
98
+ eventTarget.addEventListener(Events.SEGMENTATION_DATA_MODIFIED, onSegmentationDataModified);
99
+ eventTarget.addEventListener(Events.SEGMENTATION_REPRESENTATION_REMOVED, async (evt) => {
100
+ eventTarget.removeEventListener(Events.SEGMENTATION_DATA_MODIFIED, onSegmentationDataModified);
101
+ const actorEntry = viewport.getActor(uid);
102
+ const { element, id } = viewport;
103
+ viewport.removeActors([uid]);
104
+ const actor = await createVolumeActor({
105
+ volumeId: uid,
106
+ blendMode: Enums.BlendModes.MAXIMUM_INTENSITY_BLEND,
107
+ callback: ({ volumeActor }) => {
108
+ if (actorEntry.callback) {
109
+ actorEntry.callback({
110
+ volumeActor,
111
+ volumeId,
112
+ });
113
+ }
114
+ },
115
+ }, element, id);
116
+ viewport.addActor({ actor, uid });
117
+ viewport.render();
118
+ });
119
+ return {
120
+ uid,
121
+ actor,
122
+ };
123
+ }
@@ -1,5 +1,6 @@
1
1
  import type { Types } from '@cornerstonejs/core';
2
2
  import type { LabelmapRepresentation } from '../../../types/SegmentationStateTypes';
3
+ export declare const MAX_NUMBER_COLORS = 255;
3
4
  declare function removeRepresentation(viewportId: string, segmentationId: string, renderImmediate?: boolean): void;
4
5
  declare function render(viewport: Types.IStackViewport | Types.IVolumeViewport, representation: LabelmapRepresentation): Promise<void>;
5
6
  declare const _default: {
@@ -12,7 +12,7 @@ import SegmentationRepresentations from '../../../enums/SegmentationRepresentati
12
12
  import { internalGetHiddenSegmentIndices } from '../../../stateManagement/segmentation/helpers/internalGetHiddenSegmentIndices';
13
13
  import { getActiveSegmentIndex } from '../../../stateManagement/segmentation/getActiveSegmentIndex';
14
14
  import { getLabelmapActorEntry } from '../../../stateManagement/segmentation/helpers/getSegmentationActor';
15
- const MAX_NUMBER_COLORS = 255;
15
+ export const MAX_NUMBER_COLORS = 255;
16
16
  const labelMapConfigCache = new Map();
17
17
  let polySegConversionInProgress = false;
18
18
  function removeRepresentation(viewportId, segmentationId, renderImmediate = false) {
@@ -33,7 +33,7 @@ function removeRepresentation(viewportId, segmentationId, renderImmediate = fals
33
33
  viewport.render();
34
34
  }
35
35
  async function render(viewport, representation) {
36
- const { segmentationId } = representation;
36
+ const { segmentationId, config } = representation;
37
37
  const segmentation = getSegmentation(segmentationId);
38
38
  if (!segmentation) {
39
39
  console.warn('No segmentation found for segmentationId: ', segmentationId);
@@ -58,7 +58,7 @@ async function render(viewport, representation) {
58
58
  }
59
59
  if (viewport instanceof VolumeViewport) {
60
60
  if (!labelmapActorEntry) {
61
- await _addLabelmapToViewport(viewport, labelmapData, segmentationId);
61
+ await _addLabelmapToViewport(viewport, labelmapData, segmentationId, config);
62
62
  }
63
63
  labelmapActorEntry = getLabelmapActorEntry(viewport.id, segmentationId);
64
64
  }
@@ -68,7 +68,7 @@ async function render(viewport, representation) {
68
68
  return;
69
69
  }
70
70
  if (!labelmapActorEntry) {
71
- await _addLabelmapToViewport(viewport, labelmapData, segmentationId);
71
+ await _addLabelmapToViewport(viewport, labelmapData, segmentationId, config);
72
72
  }
73
73
  labelmapActorEntry = getLabelmapActorEntry(viewport.id, segmentationId);
74
74
  }
@@ -133,11 +133,17 @@ function _setLabelmapColorAndOpacity(viewportId, labelmapActorEntry, segmentatio
133
133
  }
134
134
  }
135
135
  }
136
- const labelmapActor = labelmapActorEntry.actor;
137
- labelmapActor.getProperty().setRGBTransferFunction(0, cfun);
138
136
  ofun.setClamping(false);
139
- labelmapActor.getProperty().setScalarOpacity(0, ofun);
140
- labelmapActor.getProperty().setInterpolationTypeToNearest();
137
+ const labelmapActor = labelmapActorEntry.actor;
138
+ const { preLoad } = labelmapActor.get('preLoad') || { preLoad: null };
139
+ if (preLoad) {
140
+ preLoad({ cfun, ofun, actor: labelmapActor });
141
+ }
142
+ else {
143
+ labelmapActor.getProperty().setRGBTransferFunction(0, cfun);
144
+ labelmapActor.getProperty().setScalarOpacity(0, ofun);
145
+ labelmapActor.getProperty().setInterpolationTypeToNearest();
146
+ }
141
147
  if (renderOutline) {
142
148
  labelmapActor.getProperty().setUseLabelOutline(renderOutline);
143
149
  labelmapActor.getProperty().setLabelOutlineOpacity(outlineOpacity);
@@ -241,8 +247,9 @@ function _needsTransferFunctionUpdate(viewportId, segmentationId, segmentIndex,
241
247
  forceColorUpdate,
242
248
  };
243
249
  }
244
- async function _addLabelmapToViewport(viewport, labelmapData, segmentationId) {
245
- await addLabelmapToElement(viewport.element, labelmapData, segmentationId);
250
+ async function _addLabelmapToViewport(viewport, labelmapData, segmentationId, config) {
251
+ const result = await addLabelmapToElement(viewport.element, labelmapData, segmentationId, config);
252
+ return result || undefined;
246
253
  }
247
254
  export default {
248
255
  render,
@@ -41,6 +41,7 @@ import AnnotationEraserTool from './AnnotationEraserTool';
41
41
  import RegionSegmentTool from './annotation/RegionSegmentTool';
42
42
  import RegionSegmentPlusTool from './annotation/RegionSegmentPlusTool';
43
43
  import WholeBodySegmentTool from './annotation/WholeBodySegmentTool';
44
+ import LabelmapBaseTool from './segmentation/LabelmapBaseTool';
44
45
  import RectangleScissorsTool from './segmentation/RectangleScissorsTool';
45
46
  import CircleScissorsTool from './segmentation/CircleScissorsTool';
46
47
  import SphereScissorsTool from './segmentation/SphereScissorsTool';
@@ -51,4 +52,5 @@ import BrushTool from './segmentation/BrushTool';
51
52
  import PaintFillTool from './segmentation/PaintFillTool';
52
53
  import OrientationMarkerTool from './OrientationMarkerTool';
53
54
  import SegmentSelectTool from './segmentation/SegmentSelectTool';
54
- export { BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, WindowLevelRegionTool, StackScrollTool, PlanarRotateTool, ZoomTool, MIPJumpToClickTool, ReferenceCursors, CrosshairsTool, ReferenceLinesTool, OverlayGridTool, SegmentationIntersectionTool, BidirectionalTool, LengthTool, HeightTool, ProbeTool, RectangleROITool, EllipticalROITool, CircleROITool, ETDRSGridTool, SplineROITool, PlanarFreehandROITool, PlanarFreehandContourSegmentationTool, LivewireContourTool, LivewireContourSegmentationTool, ArrowAnnotateTool, AngleTool, CobbAngleTool, UltrasoundDirectionalTool, KeyImageTool, AnnotationEraserTool as EraserTool, RectangleScissorsTool, CircleScissorsTool, SphereScissorsTool, RectangleROIThresholdTool, RectangleROIStartEndThresholdTool, CircleROIStartEndThresholdTool, SplineContourSegmentationTool, BrushTool, MagnifyTool, AdvancedMagnifyTool, PaintFillTool, ScaleOverlayTool, OrientationMarkerTool, SculptorTool, SegmentSelectTool, VolumeRotateTool, RegionSegmentTool, RegionSegmentPlusTool, WholeBodySegmentTool, };
55
+ import * as strategies from './segmentation/strategies';
56
+ export { BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, WindowLevelRegionTool, StackScrollTool, PlanarRotateTool, ZoomTool, MIPJumpToClickTool, ReferenceCursors, CrosshairsTool, ReferenceLinesTool, OverlayGridTool, SegmentationIntersectionTool, BidirectionalTool, LengthTool, HeightTool, ProbeTool, RectangleROITool, EllipticalROITool, CircleROITool, ETDRSGridTool, SplineROITool, PlanarFreehandROITool, PlanarFreehandContourSegmentationTool, LivewireContourTool, LivewireContourSegmentationTool, ArrowAnnotateTool, AngleTool, CobbAngleTool, UltrasoundDirectionalTool, KeyImageTool, AnnotationEraserTool as EraserTool, RectangleScissorsTool, CircleScissorsTool, SphereScissorsTool, RectangleROIThresholdTool, RectangleROIStartEndThresholdTool, CircleROIStartEndThresholdTool, SplineContourSegmentationTool, BrushTool, MagnifyTool, AdvancedMagnifyTool, PaintFillTool, ScaleOverlayTool, OrientationMarkerTool, SculptorTool, SegmentSelectTool, VolumeRotateTool, RegionSegmentTool, RegionSegmentPlusTool, WholeBodySegmentTool, LabelmapBaseTool, strategies, };
@@ -41,6 +41,7 @@ import AnnotationEraserTool from './AnnotationEraserTool';
41
41
  import RegionSegmentTool from './annotation/RegionSegmentTool';
42
42
  import RegionSegmentPlusTool from './annotation/RegionSegmentPlusTool';
43
43
  import WholeBodySegmentTool from './annotation/WholeBodySegmentTool';
44
+ import LabelmapBaseTool from './segmentation/LabelmapBaseTool';
44
45
  import RectangleScissorsTool from './segmentation/RectangleScissorsTool';
45
46
  import CircleScissorsTool from './segmentation/CircleScissorsTool';
46
47
  import SphereScissorsTool from './segmentation/SphereScissorsTool';
@@ -51,4 +52,5 @@ import BrushTool from './segmentation/BrushTool';
51
52
  import PaintFillTool from './segmentation/PaintFillTool';
52
53
  import OrientationMarkerTool from './OrientationMarkerTool';
53
54
  import SegmentSelectTool from './segmentation/SegmentSelectTool';
54
- export { BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, WindowLevelRegionTool, StackScrollTool, PlanarRotateTool, ZoomTool, MIPJumpToClickTool, ReferenceCursors, CrosshairsTool, ReferenceLinesTool, OverlayGridTool, SegmentationIntersectionTool, BidirectionalTool, LengthTool, HeightTool, ProbeTool, RectangleROITool, EllipticalROITool, CircleROITool, ETDRSGridTool, SplineROITool, PlanarFreehandROITool, PlanarFreehandContourSegmentationTool, LivewireContourTool, LivewireContourSegmentationTool, ArrowAnnotateTool, AngleTool, CobbAngleTool, UltrasoundDirectionalTool, KeyImageTool, AnnotationEraserTool as EraserTool, RectangleScissorsTool, CircleScissorsTool, SphereScissorsTool, RectangleROIThresholdTool, RectangleROIStartEndThresholdTool, CircleROIStartEndThresholdTool, SplineContourSegmentationTool, BrushTool, MagnifyTool, AdvancedMagnifyTool, PaintFillTool, ScaleOverlayTool, OrientationMarkerTool, SculptorTool, SegmentSelectTool, VolumeRotateTool, RegionSegmentTool, RegionSegmentPlusTool, WholeBodySegmentTool, };
55
+ import * as strategies from './segmentation/strategies';
56
+ export { BaseTool, AnnotationTool, AnnotationDisplayTool, PanTool, TrackballRotateTool, DragProbeTool, WindowLevelTool, WindowLevelRegionTool, StackScrollTool, PlanarRotateTool, ZoomTool, MIPJumpToClickTool, ReferenceCursors, CrosshairsTool, ReferenceLinesTool, OverlayGridTool, SegmentationIntersectionTool, BidirectionalTool, LengthTool, HeightTool, ProbeTool, RectangleROITool, EllipticalROITool, CircleROITool, ETDRSGridTool, SplineROITool, PlanarFreehandROITool, PlanarFreehandContourSegmentationTool, LivewireContourTool, LivewireContourSegmentationTool, ArrowAnnotateTool, AngleTool, CobbAngleTool, UltrasoundDirectionalTool, KeyImageTool, AnnotationEraserTool as EraserTool, RectangleScissorsTool, CircleScissorsTool, SphereScissorsTool, RectangleROIThresholdTool, RectangleROIStartEndThresholdTool, CircleROIStartEndThresholdTool, SplineContourSegmentationTool, BrushTool, MagnifyTool, AdvancedMagnifyTool, PaintFillTool, ScaleOverlayTool, OrientationMarkerTool, SculptorTool, SegmentSelectTool, VolumeRotateTool, RegionSegmentTool, RegionSegmentPlusTool, WholeBodySegmentTool, LabelmapBaseTool, strategies, };
@@ -3,7 +3,6 @@ import type { PublicToolProps, ToolProps, EventTypes, SVGDrawingHelper } from '.
3
3
  import LabelmapBaseTool from './LabelmapBaseTool';
4
4
  declare class BrushTool extends LabelmapBaseTool {
5
5
  static toolName: any;
6
- prg: any;
7
6
  constructor(toolProps?: PublicToolProps, defaultToolProps?: ToolProps);
8
7
  onSetToolPassive: (evt: any) => void;
9
8
  onSetToolEnabled: () => void;
@@ -31,8 +31,9 @@ export default class LabelmapBaseTool extends BaseTool {
31
31
  centerCanvas?: Array<number>;
32
32
  viewport: Types.IViewport;
33
33
  };
34
- protected _previewData?: PreviewData;
34
+ static previewData?: PreviewData;
35
35
  constructor(toolProps: any, defaultToolProps: any);
36
+ protected get _previewData(): PreviewData;
36
37
  createMemo(segmentId: string, segmentationVoxelManager: any, preview: any): LabelmapMemo.LabelmapMemo;
37
38
  createEditData(element: any): {
38
39
  volumeId: string;
@@ -157,4 +158,7 @@ export default class LabelmapBaseTool extends BaseTool {
157
158
  }): unknown;
158
159
  rejectPreview(element?: HTMLDivElement): void;
159
160
  acceptPreview(element?: HTMLDivElement): void;
161
+ static viewportContoursToLabelmap(viewport: Types.IViewport, options?: {
162
+ removeContours: boolean;
163
+ }): void;
160
164
  }