@cornerstonejs/tools 2.17.6 → 2.18.1

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.
@@ -5,6 +5,7 @@ declare enum StrategyCallbacks {
5
5
  RejectPreview = "rejectPreview",
6
6
  AcceptPreview = "acceptPreview",
7
7
  Fill = "fill",
8
+ Interpolate = "interpolate",
8
9
  StrategyFunction = "strategyFunction",
9
10
  CreateIsInThreshold = "createIsInThreshold",
10
11
  Initialize = "initialize",
@@ -6,6 +6,7 @@ var StrategyCallbacks;
6
6
  StrategyCallbacks["RejectPreview"] = "rejectPreview";
7
7
  StrategyCallbacks["AcceptPreview"] = "acceptPreview";
8
8
  StrategyCallbacks["Fill"] = "fill";
9
+ StrategyCallbacks["Interpolate"] = "interpolate";
9
10
  StrategyCallbacks["StrategyFunction"] = "strategyFunction";
10
11
  StrategyCallbacks["CreateIsInThreshold"] = "createIsInThreshold";
11
12
  StrategyCallbacks["Initialize"] = "initialize";
@@ -16,6 +16,9 @@ declare class BrushTool extends LabelmapBaseTool {
16
16
  private _calculateCursor;
17
17
  private _endCallback;
18
18
  getStatistics(element: any, segmentIndices?: any): any;
19
+ rejectPreview(element?: HTMLDivElement): void;
20
+ interpolate(element: any, config: any): void;
21
+ acceptPreview(element?: HTMLDivElement): void;
19
22
  private _activateDraw;
20
23
  private _deactivateDraw;
21
24
  invalidateBrushCursor(): void;
@@ -48,6 +48,36 @@ class BrushTool extends LabelmapBaseTool {
48
48
  },
49
49
  ],
50
50
  },
51
+ [StrategyCallbacks.RejectPreview]: {
52
+ method: StrategyCallbacks.RejectPreview,
53
+ bindings: [
54
+ {
55
+ key: 'Escape',
56
+ },
57
+ ],
58
+ },
59
+ [StrategyCallbacks.Interpolate]: {
60
+ method: StrategyCallbacks.Interpolate,
61
+ bindings: [
62
+ {
63
+ key: 'i',
64
+ },
65
+ ],
66
+ configuration: {
67
+ useBallStructuringElement: true,
68
+ noUseDistanceTransform: true,
69
+ noUseExtrapolation: true,
70
+ },
71
+ },
72
+ interpolateExtrapolation: {
73
+ method: StrategyCallbacks.Interpolate,
74
+ bindings: [
75
+ {
76
+ key: 'e',
77
+ },
78
+ ],
79
+ configuration: {},
80
+ },
51
81
  },
52
82
  },
53
83
  }) {
@@ -239,6 +269,32 @@ class BrushTool extends LabelmapBaseTool {
239
269
  const stats = this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.GetStatistics, segmentIndices);
240
270
  return stats;
241
271
  }
272
+ rejectPreview(element = this._previewData.element) {
273
+ if (!element || !this._previewData.preview) {
274
+ return;
275
+ }
276
+ const enabledElement = getEnabledElement(element);
277
+ this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.RejectPreview);
278
+ this._previewData.preview = null;
279
+ this._previewData.isDrag = false;
280
+ }
281
+ interpolate(element, config) {
282
+ if (!element) {
283
+ return;
284
+ }
285
+ const enabledElement = getEnabledElement(element);
286
+ this._previewData.preview = this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.Interpolate, config.configuration);
287
+ this._previewData.isDrag = true;
288
+ }
289
+ acceptPreview(element = this._previewData.element) {
290
+ if (!element) {
291
+ return;
292
+ }
293
+ const enabledElement = getEnabledElement(element);
294
+ this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), StrategyCallbacks.AcceptPreview);
295
+ this._previewData.isDrag = false;
296
+ this._previewData.preview = null;
297
+ }
242
298
  invalidateBrushCursor() {
243
299
  if (this._hoverData === undefined) {
244
300
  return;
@@ -66,6 +66,9 @@ export default class BrushStrategy {
66
66
  indices?: number | number[];
67
67
  }) => import("../../../types").NamedStatistics;
68
68
  };
69
+ labelmapInterpolation: {
70
+ interpolate: (operationData: InitializedOperationData, configuration: import("@itk-wasm/morphological-contour-interpolation").MorphologicalContourInterpolationOptions) => InitializedOperationData;
71
+ };
69
72
  };
70
73
  protected static childFunctions: {
71
74
  onInteractionStart: (brushStrategy: any, func: any) => void;
@@ -73,6 +76,7 @@ export default class BrushStrategy {
73
76
  fill: (brushStrategy: any, func: any) => void;
74
77
  initialize: (brushStrategy: any, func: any) => void;
75
78
  createIsInThreshold: (brushStrategy: any, func: any) => void;
79
+ interpolate: (brushStrategy: any, func: any) => void;
76
80
  acceptPreview: (brushStrategy: any, func: any) => void;
77
81
  rejectPreview: (brushStrategy: any, func: any) => void;
78
82
  setValue: (brushStrategy: any, func: any) => void;
@@ -98,6 +102,7 @@ export default class BrushStrategy {
98
102
  addPreview: (enabledElement: any, operationData: LabelmapToolOperationDataAny) => any;
99
103
  acceptPreview: (enabledElement: Types.IEnabledElement, operationData: LabelmapToolOperationDataAny) => void;
100
104
  preview: (enabledElement: Types.IEnabledElement, operationData: LabelmapToolOperationDataAny) => unknown;
105
+ interpolate: (enabledElement: Types.IEnabledElement, operationData: LabelmapToolOperationDataAny) => unknown;
101
106
  setValue: (operationData: InitializedOperationData, data: any) => void;
102
107
  createIsInThreshold: (operationData: InitializedOperationData) => any;
103
108
  }
@@ -12,6 +12,7 @@ export default class BrushStrategy {
12
12
  [StrategyCallbacks.Fill]: addListMethod(StrategyCallbacks.Fill),
13
13
  [StrategyCallbacks.Initialize]: addListMethod(StrategyCallbacks.Initialize),
14
14
  [StrategyCallbacks.CreateIsInThreshold]: addSingletonMethod(StrategyCallbacks.CreateIsInThreshold),
15
+ [StrategyCallbacks.Interpolate]: addListMethod(StrategyCallbacks.Interpolate, StrategyCallbacks.Initialize),
15
16
  [StrategyCallbacks.AcceptPreview]: addListMethod(StrategyCallbacks.AcceptPreview, StrategyCallbacks.Initialize),
16
17
  [StrategyCallbacks.RejectPreview]: addListMethod(StrategyCallbacks.RejectPreview, StrategyCallbacks.Initialize),
17
18
  [StrategyCallbacks.INTERNAL_setValue]: addSingletonMethod(StrategyCallbacks.INTERNAL_setValue),
@@ -126,12 +127,17 @@ function addListMethod(name, createInitialized) {
126
127
  brushStrategy[listName] ||= [];
127
128
  brushStrategy[listName].push(func);
128
129
  brushStrategy[name] ||= createInitialized
129
- ? (enabledElement, operationData) => {
130
+ ? (enabledElement, operationData, ...args) => {
130
131
  const initializedData = brushStrategy[createInitialized](enabledElement, operationData, name);
131
- brushStrategy[listName].forEach((func) => func.call(brushStrategy, initializedData));
132
+ let returnValue;
133
+ brushStrategy[listName].forEach((func) => {
134
+ const value = func.call(brushStrategy, initializedData, ...args);
135
+ returnValue ||= value;
136
+ });
137
+ return returnValue;
132
138
  }
133
- : (operationData) => {
134
- brushStrategy[listName].forEach((func) => func.call(brushStrategy, operationData));
139
+ : (operationData, ...args) => {
140
+ brushStrategy[listName].forEach((func) => func.call(brushStrategy, operationData, ...args));
135
141
  };
136
142
  };
137
143
  }
@@ -37,5 +37,8 @@ declare const _default: {
37
37
  indices?: number | number[];
38
38
  }) => import("../../../../types").NamedStatistics;
39
39
  };
40
+ labelmapInterpolation: {
41
+ interpolate: (operationData: import("../BrushStrategy").InitializedOperationData, configuration: import("@itk-wasm/morphological-contour-interpolation").MorphologicalContourInterpolationOptions) => import("../BrushStrategy").InitializedOperationData;
42
+ };
40
43
  };
41
44
  export default _default;
@@ -7,6 +7,7 @@ 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
11
  export default {
11
12
  determineSegmentIndex,
12
13
  dynamicThreshold,
@@ -17,4 +18,5 @@ export default {
17
18
  setValue,
18
19
  threshold,
19
20
  labelmapStatistics,
21
+ labelmapInterpolation,
20
22
  };
@@ -0,0 +1,6 @@
1
+ import type { MorphologicalContourInterpolationOptions } from '@itk-wasm/morphological-contour-interpolation';
2
+ import type { InitializedOperationData } from '../BrushStrategy';
3
+ declare const _default: {
4
+ interpolate: (operationData: InitializedOperationData, configuration: MorphologicalContourInterpolationOptions) => InitializedOperationData;
5
+ };
6
+ export default _default;
@@ -0,0 +1,41 @@
1
+ import { morphologicalContourInterpolation } from '@itk-wasm/morphological-contour-interpolation';
2
+ import { utilities } from '@cornerstonejs/core';
3
+ import StrategyCallbacks from '../../../../enums/StrategyCallbacks';
4
+ import getItkImage from '../utils/getItkImage';
5
+ import { triggerSegmentationDataModified } from '../../../../stateManagement/segmentation/triggerSegmentationEvents';
6
+ import PreviewMethods from './preview';
7
+ const { VoxelManager } = utilities;
8
+ export default {
9
+ [StrategyCallbacks.Interpolate]: (operationData, configuration) => {
10
+ const { segmentationImageData, segmentIndex, preview, segmentationVoxelManager, previewSegmentIndex, previewVoxelManager, } = operationData;
11
+ if (preview) {
12
+ const callback = ({ index }) => {
13
+ segmentationVoxelManager.setAtIndex(index, segmentIndex);
14
+ };
15
+ previewVoxelManager.forEach(callback);
16
+ }
17
+ const inputImage = getItkImage(segmentationImageData, 'interpolation');
18
+ const outputPromise = morphologicalContourInterpolation(inputImage, {
19
+ ...configuration,
20
+ label: segmentIndex,
21
+ webWorker: false,
22
+ });
23
+ outputPromise.then((value) => {
24
+ const { outputImage } = value;
25
+ const previewColors = operationData.configuration?.preview?.previewColors;
26
+ const assignIndex = previewSegmentIndex ?? (previewColors ? 255 : segmentIndex);
27
+ operationData.previewColors ||= previewColors;
28
+ operationData.previewSegmentIndex ||= previewColors ? 255 : undefined;
29
+ PreviewMethods[StrategyCallbacks.Initialize](operationData);
30
+ segmentationVoxelManager.forEach(({ value: originalValue, index }) => {
31
+ const newValue = outputImage.data[index];
32
+ if (newValue === originalValue) {
33
+ return;
34
+ }
35
+ previewVoxelManager.setAtIndex(index, assignIndex);
36
+ });
37
+ triggerSegmentationDataModified(operationData.segmentationId, previewVoxelManager.getArrayOfModifiedSlices(), assignIndex);
38
+ });
39
+ return operationData;
40
+ },
41
+ };
@@ -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);
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);
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);
66
66
  const fillInsideCircle = CIRCLE_STRATEGY.strategyFunction;
67
67
  const thresholdInsideCircle = CIRCLE_THRESHOLD_STRATEGY.strategyFunction;
68
68
  export function fillOutsideCircle() {
@@ -0,0 +1,2 @@
1
+ import { Image } from 'itk-wasm';
2
+ export default function getItkImage(imageData: any, imageName?: string): Image;
@@ -0,0 +1,37 @@
1
+ import { Image, ImageType, IntTypes, FloatTypes, PixelTypes } from 'itk-wasm';
2
+ const dataTypesMap = {
3
+ Int8: IntTypes.Int8,
4
+ UInt8: IntTypes.UInt8,
5
+ Int16: IntTypes.Int16,
6
+ UInt16: IntTypes.UInt16,
7
+ Int32: IntTypes.Int32,
8
+ UInt32: IntTypes.UInt32,
9
+ Int64: IntTypes.Int64,
10
+ UInt64: IntTypes.UInt64,
11
+ Float32: FloatTypes.Float32,
12
+ Float64: FloatTypes.Float64,
13
+ };
14
+ export default function getItkImage(imageData, imageName) {
15
+ const { voxelManager } = imageData.get('voxelManager');
16
+ const { numberOfComponents } = imageData.get('numberOfComponents');
17
+ const scalarData = voxelManager.getCompleteScalarDataArray();
18
+ const dimensions = imageData.getDimensions();
19
+ const origin = imageData.getOrigin();
20
+ const spacing = imageData.getSpacing();
21
+ const directionArray = imageData.getDirection();
22
+ const direction = new Float64Array(directionArray);
23
+ const dataType = scalarData.constructor.name
24
+ .replace(/^Ui/, 'UI')
25
+ .replace(/Array$/, '');
26
+ const metadata = undefined;
27
+ const imageType = new ImageType(dimensions.length, dataTypesMap[dataType], PixelTypes.Scalar, numberOfComponents);
28
+ const image = new Image(imageType);
29
+ image.name = imageName;
30
+ image.origin = origin;
31
+ image.spacing = spacing;
32
+ image.direction = direction;
33
+ image.size = dimensions;
34
+ image.metadata = metadata;
35
+ image.data = scalarData;
36
+ return image;
37
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "2.17.6",
3
+ "version": "2.18.1",
4
4
  "description": "Cornerstone3D Tools",
5
5
  "types": "./dist/esm/index.d.ts",
6
6
  "module": "./dist/esm/index.js",
@@ -104,7 +104,7 @@
104
104
  "canvas": "^2.11.2"
105
105
  },
106
106
  "peerDependencies": {
107
- "@cornerstonejs/core": "^2.17.6",
107
+ "@cornerstonejs/core": "^2.18.1",
108
108
  "@kitware/vtk.js": "32.9.0",
109
109
  "@types/d3-array": "^3.0.4",
110
110
  "@types/d3-interpolate": "^3.0.1",
@@ -123,5 +123,5 @@
123
123
  "type": "individual",
124
124
  "url": "https://ohif.org/donate"
125
125
  },
126
- "gitHead": "ed6fea9289da25d37aefe5a551e6aada36101d2f"
126
+ "gitHead": "c3f5e7dfc0681ce4dfa53d762c3675379856ac22"
127
127
  }