@cornerstonejs/tools 2.1.6 → 2.1.7

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.
@@ -22,6 +22,7 @@ function playClip(element, playClipOptions) {
22
22
  playClipOptions.dynamicCineEnabled =
23
23
  playClipOptions.dynamicCineEnabled ?? true;
24
24
  const { viewport } = enabledElement;
25
+ const volume = _getVolumeFromViewport(viewport);
25
26
  const playClipContext = _createCinePlayContext(viewport, playClipOptions);
26
27
  let playClipData = getToolState(element);
27
28
  const isDynamicCinePlaying = playClipOptions.dynamicCineEnabled;
@@ -211,17 +212,11 @@ function _stopClipWithData(playClipData) {
211
212
  }
212
213
  }
213
214
  }
214
- function _getVolumesFromViewport(viewport) {
215
- if (!viewport || !viewport.getVolumeId) {
216
- return [];
217
- }
218
- const volumeId = viewport.getVolumeId();
219
- return [cache.getVolume(volumeId)];
220
- }
221
215
  function _getVolumeFromViewport(viewport) {
222
- const volumes = _getVolumesFromViewport(viewport);
223
- const dynamicVolume = volumes.find((volume) => volume.isDynamicVolume());
224
- return dynamicVolume ?? volumes[0];
216
+ const volumeIds = viewport.getAllVolumeIds();
217
+ const dynamicVolumeId = volumeIds.find((volumeId) => cache.getVolume(volumeId)?.isDynamicVolume());
218
+ const volumeId = dynamicVolumeId ?? volumeIds[0];
219
+ return cache.getVolume(volumeId);
225
220
  }
226
221
  function _createStackViewportCinePlayContext(viewport, waitForRendered) {
227
222
  const imageIds = viewport.getImageIds();
@@ -13,6 +13,9 @@ function getDataInTime(dynamicVolume, options) {
13
13
  }
14
14
  if (options.maskVolumeId) {
15
15
  const segmentationVolume = cache.getVolume(options.maskVolumeId);
16
+ if (!segmentationVolume) {
17
+ throw new Error('Segmentation volume not found');
18
+ }
16
19
  const [dataInTime, ijkCoords] = _getTimePointDataMask(frames, dynamicVolume, segmentationVolume);
17
20
  return [dataInTime, ijkCoords];
18
21
  }
@@ -33,12 +36,10 @@ function _getTimePointDataCoordinate(frames, coordinate, volume) {
33
36
  }
34
37
  const yMultiple = dimensions[0];
35
38
  const zMultiple = dimensions[0] * dimensions[1];
36
- const allScalarData = volume.getScalarDataArrays();
37
39
  const value = [];
38
40
  frames.forEach((frame) => {
39
- const activeScalarData = allScalarData[frame];
40
41
  const scalarIndex = index[2] * zMultiple + index[1] * yMultiple + index[0];
41
- value.push(activeScalarData[scalarIndex]);
42
+ value.push(volume.voxelManager.getAtIndexAndTimePoint(scalarIndex, frame));
42
43
  });
43
44
  return value;
44
45
  }
@@ -48,35 +49,29 @@ function _getTimePointDataMask(frames, dynamicVolume, segmentationVolume) {
48
49
  const scalarDataLength = segVoxelManager.getScalarDataLength();
49
50
  const nonZeroVoxelIndices = [];
50
51
  nonZeroVoxelIndices.length = scalarDataLength;
51
- const ijkCoords = [];
52
- const dimensions = segmentationVolume.dimensions;
53
52
  let actualLen = 0;
54
53
  for (let i = 0, len = scalarDataLength; i < len; i++) {
55
54
  if (segVoxelManager.getAtIndex(i) !== 0) {
56
- ijkCoords.push([
57
- i % dimensions[0],
58
- Math.floor((i / dimensions[0]) % dimensions[1]),
59
- Math.floor(i / (dimensions[0] * dimensions[1])),
60
- ]);
61
55
  nonZeroVoxelIndices[actualLen++] = i;
62
56
  }
63
57
  }
64
58
  nonZeroVoxelIndices.length = actualLen;
65
- const dynamicVolumeScalarDataArray = dynamicVolume.getScalarDataArrays();
66
- const values = [];
67
- const isSameVolume = dynamicVolumeScalarDataArray[0].length === scalarDataLength &&
59
+ const nonZeroVoxelValuesInTime = [];
60
+ const isSameVolume = dynamicVolume.voxelManager.getScalarDataLength() === scalarDataLength &&
68
61
  JSON.stringify(dynamicVolume.spacing) ===
69
62
  JSON.stringify(segmentationVolume.spacing);
63
+ const ijkCoords = [];
70
64
  if (isSameVolume) {
71
65
  for (let i = 0; i < nonZeroVoxelIndices.length; i++) {
72
- const indexValues = [];
73
- frames.forEach((frame) => {
74
- const activeScalarData = dynamicVolumeScalarDataArray[frame];
75
- indexValues.push(activeScalarData[nonZeroVoxelIndices[i]]);
76
- });
77
- values.push(indexValues);
66
+ const valuesInTime = [];
67
+ const index = nonZeroVoxelIndices[i];
68
+ for (let j = 0; j < frames.length; j++) {
69
+ valuesInTime.push(dynamicVolume.voxelManager.getAtIndexAndTimePoint(index, frames[j]));
70
+ }
71
+ nonZeroVoxelValuesInTime.push(valuesInTime);
72
+ ijkCoords.push(segVoxelManager.toIJK(index));
78
73
  }
79
- return [values, ijkCoords];
74
+ return [nonZeroVoxelValuesInTime, ijkCoords];
80
75
  }
81
76
  const callback = ({ pointLPS: segPointLPS, value: segValue, pointIJK: segPointIJK, }) => {
82
77
  if (segValue === 0) {
@@ -88,7 +83,7 @@ function _getTimePointDataMask(frames, dynamicVolume, segmentationVolume) {
88
83
  frames.forEach((frame) => perFrameSum.set(frame, 0));
89
84
  const averageCallback = ({ index }) => {
90
85
  for (let i = 0; i < frames.length; i++) {
91
- const value = dynamicVolumeScalarDataArray[i][index];
86
+ const value = dynamicVolume.voxelManager.getAtIndexAndTimePoint(index, frames[i]);
92
87
  const frame = frames[i];
93
88
  perFrameSum.set(frame, perFrameSum.get(frame) + value);
94
89
  }
@@ -103,12 +98,11 @@ function _getTimePointDataMask(frames, dynamicVolume, segmentationVolume) {
103
98
  averageValues.push(sum / count);
104
99
  });
105
100
  ijkCoords.push(segPointIJK);
106
- values.push(averageValues);
101
+ nonZeroVoxelValuesInTime.push(averageValues);
107
102
  };
108
- const { voxelManager } = maskImageData.get('voxelManager');
109
- voxelManager.forEach(callback, {
103
+ segmentationVolume.voxelManager.forEach(callback, {
110
104
  imageData: maskImageData,
111
105
  });
112
- return [values, ijkCoords];
106
+ return [nonZeroVoxelValuesInTime, ijkCoords];
113
107
  }
114
108
  export default getDataInTime;
@@ -4,21 +4,33 @@ const equalsCheck = (a, b) => {
4
4
  return JSON.stringify(a) === JSON.stringify(b);
5
5
  };
6
6
  export function getVoxelOverlap(imageData, dimensions, voxelSpacing, voxelCenter) {
7
- const voxelCornersWorld = [];
8
- for (let i = 0; i < 2; i++) {
9
- for (let j = 0; j < 2; j++) {
10
- for (let k = 0; k < 2; k++) {
11
- const point = [...voxelCenter];
12
- point[0] = point[0] + ((i * 2 - 1) * voxelSpacing[0]) / 2;
13
- point[1] = point[1] + ((j * 2 - 1) * voxelSpacing[1]) / 2;
14
- point[2] = point[2] + ((k * 2 - 1) * voxelSpacing[2]) / 2;
15
- voxelCornersWorld.push(point);
16
- }
17
- }
7
+ const halfSpacingX = voxelSpacing[0] / 2;
8
+ const halfSpacingY = voxelSpacing[1] / 2;
9
+ const halfSpacingZ = voxelSpacing[2] / 2;
10
+ const voxelCornersIJK = new Array(8);
11
+ voxelCornersIJK[0] = csUtils.transformWorldToIndex(imageData, [
12
+ voxelCenter[0] - halfSpacingX,
13
+ voxelCenter[1] - halfSpacingY,
14
+ voxelCenter[2] - halfSpacingZ,
15
+ ]);
16
+ const offsets = [
17
+ [1, -1, -1],
18
+ [-1, 1, -1],
19
+ [1, 1, -1],
20
+ [-1, -1, 1],
21
+ [1, -1, 1],
22
+ [-1, 1, 1],
23
+ [1, 1, 1],
24
+ ];
25
+ for (let i = 0; i < 7; i++) {
26
+ const [xOff, yOff, zOff] = offsets[i];
27
+ voxelCornersIJK[i + 1] = csUtils.transformWorldToIndex(imageData, [
28
+ voxelCenter[0] + xOff * halfSpacingX,
29
+ voxelCenter[1] + yOff * halfSpacingY,
30
+ voxelCenter[2] + zOff * halfSpacingZ,
31
+ ]);
18
32
  }
19
- const voxelCornersIJK = voxelCornersWorld.map((world) => csUtils.transformWorldToIndex(imageData, world));
20
- const overlapBounds = getBoundingBoxAroundShapeIJK(voxelCornersIJK, dimensions);
21
- return overlapBounds;
33
+ return getBoundingBoxAroundShapeIJK(voxelCornersIJK, dimensions);
22
34
  }
23
35
  export function processVolumes(segmentationVolume, thresholdVolumeInformation) {
24
36
  const { spacing: segmentationSpacing } = segmentationVolume;
@@ -1,4 +1,4 @@
1
- import { eventTarget, VolumeViewport, StackViewport, Enums, utilities, getEnabledElement, } from '@cornerstonejs/core';
1
+ import { eventTarget, VolumeViewport, StackViewport, Enums, utilities, getEnabledElement, cache, } from '@cornerstonejs/core';
2
2
  import { Colorbar } from './Colorbar';
3
3
  import { getVOIMultipliers } from '../../getVOIMultipliers';
4
4
  const { Events } = Enums;
@@ -88,14 +88,24 @@ class ViewportColorbar extends Colorbar {
88
88
  static _getImageRange(element, volumeId) {
89
89
  const enabledElement = getEnabledElement(element);
90
90
  const { viewport } = enabledElement;
91
- const actor = volumeId
92
- ? viewport.getActor(volumeId)
93
- : viewport.getDefaultActor();
91
+ const actor = viewport.getImageActor(volumeId);
94
92
  if (!actor) {
95
93
  return defaultImageRange;
96
94
  }
97
- const imageData = actor.actor.getMapper().getInputData();
98
- const imageRange = imageData.getPointData().getScalars().getRange();
95
+ const imageData = actor.getMapper().getInputData();
96
+ const scalarData = imageData.getPointData().getScalars();
97
+ let imageRange;
98
+ if (!scalarData) {
99
+ if (!volumeId) {
100
+ throw new Error('volumeId is required when scalarData is not available');
101
+ }
102
+ const volume = cache.getVolume(volumeId);
103
+ const [minValue, maxValue] = volume.voxelManager.getRange();
104
+ imageRange = [minValue, maxValue];
105
+ }
106
+ else {
107
+ imageRange = scalarData.getRange();
108
+ }
99
109
  return imageRange[0] === 0 && imageRange[1] === 0
100
110
  ? defaultImageRange
101
111
  : { lower: imageRange[0], upper: imageRange[1] };
@@ -103,16 +113,11 @@ class ViewportColorbar extends Colorbar {
103
113
  static _getVOIRange(element, volumeId) {
104
114
  const enabledElement = getEnabledElement(element);
105
115
  const { viewport } = enabledElement;
106
- const volumeActor = volumeId
107
- ? viewport.getActor(volumeId)
108
- : viewport.getDefaultActor();
109
- if (!volumeActor || !utilities.isImageActor(volumeActor)) {
116
+ const actor = viewport.getImageActor(volumeId);
117
+ if (!actor) {
110
118
  return defaultImageRange;
111
119
  }
112
- const voiRange = volumeActor.actor
113
- .getProperty()
114
- .getRGBTransferFunction(0)
115
- .getRange();
120
+ const voiRange = actor.getProperty().getRGBTransferFunction(0).getRange();
116
121
  return voiRange[0] === 0 && voiRange[1] === 0
117
122
  ? defaultImageRange
118
123
  : { lower: voiRange[0], upper: voiRange[1] };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "2.1.6",
3
+ "version": "2.1.7",
4
4
  "description": "Cornerstone3D Tools",
5
5
  "main": "./dist/esm/index.js",
6
6
  "types": "./dist/esm/index.d.ts",
@@ -105,7 +105,7 @@
105
105
  "canvas": "^2.11.2"
106
106
  },
107
107
  "peerDependencies": {
108
- "@cornerstonejs/core": "^2.1.6",
108
+ "@cornerstonejs/core": "^2.1.7",
109
109
  "@kitware/vtk.js": "32.1.0",
110
110
  "@types/d3-array": "^3.0.4",
111
111
  "@types/d3-interpolate": "^3.0.1",
@@ -124,5 +124,5 @@
124
124
  "type": "individual",
125
125
  "url": "https://ohif.org/donate"
126
126
  },
127
- "gitHead": "a3934ba53f46d7cb5d23151d83f69bea9fe90009"
127
+ "gitHead": "079eb63faace4c72556559fc1ce272c2a9a910ca"
128
128
  }