@cornerstonejs/tools 2.16.1 → 2.17.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.
- package/dist/esm/utilities/dynamicVolume/generateImageFromTimeData.d.ts +2 -0
- package/dist/esm/utilities/dynamicVolume/generateImageFromTimeData.js +36 -26
- package/dist/esm/utilities/dynamicVolume/getDataInTime.d.ts +4 -3
- package/dist/esm/utilities/dynamicVolume/getDataInTime.js +21 -18
- package/package.json +3 -3
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { Types } from '@cornerstonejs/core';
|
|
2
2
|
import { Enums } from '@cornerstonejs/core';
|
|
3
3
|
declare function generateImageFromTimeData(dynamicVolume: Types.IDynamicImageVolume, operation: Enums.GenerateImageType, options: {
|
|
4
|
+
dimensionGroupNumbers?: number[];
|
|
4
5
|
frameNumbers?: number[];
|
|
5
6
|
}): Float32Array;
|
|
6
7
|
declare function updateVolumeFromTimeData(dynamicVolume: Types.IDynamicImageVolume, operation: Enums.GenerateImageType, options: {
|
|
8
|
+
dimensionGroupNumbers?: number[];
|
|
7
9
|
frameNumbers?: number[];
|
|
8
10
|
targetVolume: Types.IImageVolume;
|
|
9
11
|
}): void;
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
import { Enums } from '@cornerstonejs/core';
|
|
2
|
-
function
|
|
2
|
+
function sumOverDimensionGroups(voxelManager, dimensionGroups) {
|
|
3
3
|
const arrayLength = voxelManager.getScalarDataLength();
|
|
4
4
|
const resultArray = new Float32Array(arrayLength);
|
|
5
|
-
for (const
|
|
6
|
-
const scalarData = voxelManager.
|
|
5
|
+
for (const dimensionGroupNumber of dimensionGroups) {
|
|
6
|
+
const scalarData = voxelManager.getDimensionGroupScalarData(dimensionGroupNumber);
|
|
7
7
|
for (let i = 0; i < arrayLength; i++) {
|
|
8
8
|
resultArray[i] += scalarData[i];
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
return resultArray;
|
|
12
12
|
}
|
|
13
|
-
function
|
|
14
|
-
const sumArray =
|
|
15
|
-
const
|
|
13
|
+
function averageOverDimensionGroups(voxelManager, dimensionGroups) {
|
|
14
|
+
const sumArray = sumOverDimensionGroups(voxelManager, dimensionGroups);
|
|
15
|
+
const numDimensionGroups = dimensionGroups.length;
|
|
16
16
|
for (let i = 0; i < sumArray.length; i++) {
|
|
17
|
-
sumArray[i] /=
|
|
17
|
+
sumArray[i] /= numDimensionGroups;
|
|
18
18
|
}
|
|
19
19
|
return sumArray;
|
|
20
20
|
}
|
|
21
21
|
const operationFunctions = {
|
|
22
|
-
[Enums.GenerateImageType.SUM]: (voxelManager,
|
|
23
|
-
const resultArray =
|
|
22
|
+
[Enums.GenerateImageType.SUM]: (voxelManager, dimensionGroups, callback) => {
|
|
23
|
+
const resultArray = sumOverDimensionGroups(voxelManager, dimensionGroups);
|
|
24
24
|
for (let i = 0; i < resultArray.length; i++) {
|
|
25
25
|
callback(i, resultArray[i]);
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
|
-
[Enums.GenerateImageType.AVERAGE]: (voxelManager,
|
|
29
|
-
const resultArray =
|
|
28
|
+
[Enums.GenerateImageType.AVERAGE]: (voxelManager, dimensionGroups, callback) => {
|
|
29
|
+
const resultArray = averageOverDimensionGroups(voxelManager, dimensionGroups);
|
|
30
30
|
for (let i = 0; i < resultArray.length; i++) {
|
|
31
31
|
callback(i, resultArray[i]);
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
|
-
[Enums.GenerateImageType.SUBTRACT]: (voxelManager,
|
|
35
|
-
if (
|
|
36
|
-
throw new Error('Please provide only 2
|
|
34
|
+
[Enums.GenerateImageType.SUBTRACT]: (voxelManager, dimensionGroups, callback) => {
|
|
35
|
+
if (dimensionGroups.length !== 2) {
|
|
36
|
+
throw new Error('Please provide only 2 dimension groups for subtraction.');
|
|
37
37
|
}
|
|
38
38
|
const arrayLength = voxelManager.getScalarDataLength();
|
|
39
|
-
const scalarData1 = voxelManager.
|
|
40
|
-
const scalarData2 = voxelManager.
|
|
39
|
+
const scalarData1 = voxelManager.getDimensionGroupScalarData(dimensionGroups[0]);
|
|
40
|
+
const scalarData2 = voxelManager.getDimensionGroupScalarData(dimensionGroups[1]);
|
|
41
41
|
for (let i = 0; i < arrayLength; i++) {
|
|
42
42
|
const difference = scalarData1[i] - scalarData2[i];
|
|
43
43
|
callback(i, difference);
|
|
@@ -45,10 +45,15 @@ const operationFunctions = {
|
|
|
45
45
|
},
|
|
46
46
|
};
|
|
47
47
|
function generateImageFromTimeData(dynamicVolume, operation, options) {
|
|
48
|
-
const { frameNumbers } = options;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
const { dimensionGroupNumbers, frameNumbers } = options;
|
|
49
|
+
if (frameNumbers) {
|
|
50
|
+
console.warn('Warning: frameNumbers parameter is deprecated. Please use dimensionGroupNumbers instead.');
|
|
51
|
+
}
|
|
52
|
+
const dimensionGroups = dimensionGroupNumbers ||
|
|
53
|
+
frameNumbers ||
|
|
54
|
+
Array.from({ length: dynamicVolume.numDimensionGroups }, (_, i) => i + 1);
|
|
55
|
+
if (dimensionGroups.length <= 1) {
|
|
56
|
+
throw new Error('Please provide two or more dimension groups');
|
|
52
57
|
}
|
|
53
58
|
const voxelManager = dynamicVolume.voxelManager;
|
|
54
59
|
const arrayLength = voxelManager.getScalarDataLength();
|
|
@@ -57,19 +62,24 @@ function generateImageFromTimeData(dynamicVolume, operation, options) {
|
|
|
57
62
|
throw new Error(`Unsupported operation: ${operation}`);
|
|
58
63
|
}
|
|
59
64
|
const resultArray = new Float32Array(arrayLength);
|
|
60
|
-
operationFunction(voxelManager,
|
|
65
|
+
operationFunction(voxelManager, dimensionGroups, (index, value) => {
|
|
61
66
|
resultArray[index] = value;
|
|
62
67
|
});
|
|
63
68
|
return resultArray;
|
|
64
69
|
}
|
|
65
70
|
function updateVolumeFromTimeData(dynamicVolume, operation, options) {
|
|
66
|
-
const { frameNumbers, targetVolume } = options;
|
|
71
|
+
const { dimensionGroupNumbers, frameNumbers, targetVolume } = options;
|
|
67
72
|
if (!targetVolume) {
|
|
68
73
|
throw new Error('A target volume must be provided');
|
|
69
74
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
if (frameNumbers) {
|
|
76
|
+
console.warn('Warning: frameNumbers parameter is deprecated. Please use dimensionGroupNumbers instead.');
|
|
77
|
+
}
|
|
78
|
+
const dimensionGroups = dimensionGroupNumbers ||
|
|
79
|
+
frameNumbers ||
|
|
80
|
+
Array.from({ length: dynamicVolume.numDimensionGroups }, (_, i) => i + 1);
|
|
81
|
+
if (dimensionGroups.length <= 1) {
|
|
82
|
+
throw new Error('Please provide two or more dimension groups');
|
|
73
83
|
}
|
|
74
84
|
const voxelManager = dynamicVolume.voxelManager;
|
|
75
85
|
const targetVoxelManager = targetVolume.voxelManager;
|
|
@@ -77,7 +87,7 @@ function updateVolumeFromTimeData(dynamicVolume, operation, options) {
|
|
|
77
87
|
if (!operationFunction) {
|
|
78
88
|
throw new Error(`Unsupported operation: ${operation}`);
|
|
79
89
|
}
|
|
80
|
-
operationFunction(voxelManager,
|
|
90
|
+
operationFunction(voxelManager, dimensionGroups, (index, value) => {
|
|
81
91
|
targetVoxelManager.setAtIndex(index, value);
|
|
82
92
|
});
|
|
83
93
|
targetVoxelManager.resetModifiedSlices();
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Types } from '@cornerstonejs/core';
|
|
2
2
|
declare function getDataInTime(dynamicVolume: Types.IDynamicImageVolume, options: {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
dimensionGroupNumbers?: number[];
|
|
4
|
+
frameNumbers?: number[];
|
|
5
|
+
maskVolumeId?: string;
|
|
6
|
+
worldCoordinate?: Types.Point3;
|
|
6
7
|
}): number[] | number[][];
|
|
7
8
|
export default getDataInTime;
|
|
@@ -2,9 +2,12 @@ import { utilities, cache } from '@cornerstonejs/core';
|
|
|
2
2
|
import { getVoxelOverlap } from '../segmentation/utilities';
|
|
3
3
|
function getDataInTime(dynamicVolume, options) {
|
|
4
4
|
let dataInTime;
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
const dimensionGroups = options.dimensionGroupNumbers ||
|
|
6
|
+
options.frameNumbers ||
|
|
7
|
+
Array.from({ length: dynamicVolume.numDimensionGroups }, (_, i) => i + 1);
|
|
8
|
+
if (options.frameNumbers) {
|
|
9
|
+
console.warn('Warning: frameNumbers parameter is deprecated. Please use dimensionGroupNumbers instead.');
|
|
10
|
+
}
|
|
8
11
|
if (!options.maskVolumeId && !options.worldCoordinate) {
|
|
9
12
|
throw new Error('You should provide either maskVolumeId or imageCoordinate');
|
|
10
13
|
}
|
|
@@ -16,16 +19,16 @@ function getDataInTime(dynamicVolume, options) {
|
|
|
16
19
|
if (!segmentationVolume) {
|
|
17
20
|
throw new Error('Segmentation volume not found');
|
|
18
21
|
}
|
|
19
|
-
const [dataInTime, ijkCoords] =
|
|
22
|
+
const [dataInTime, ijkCoords] = _getDimensionGroupDataMask(dimensionGroups, dynamicVolume, segmentationVolume);
|
|
20
23
|
return [dataInTime, ijkCoords];
|
|
21
24
|
}
|
|
22
25
|
if (options.worldCoordinate) {
|
|
23
|
-
const dataInTime =
|
|
26
|
+
const dataInTime = _getDimensionGroupDataCoordinate(dimensionGroups, options.worldCoordinate, dynamicVolume);
|
|
24
27
|
return dataInTime;
|
|
25
28
|
}
|
|
26
29
|
return dataInTime;
|
|
27
30
|
}
|
|
28
|
-
function
|
|
31
|
+
function _getDimensionGroupDataCoordinate(dimensionGroups, coordinate, volume) {
|
|
29
32
|
const { dimensions, imageData } = volume;
|
|
30
33
|
const index = imageData.worldToIndex(coordinate);
|
|
31
34
|
index[0] = Math.floor(index[0]);
|
|
@@ -37,13 +40,13 @@ function _getTimePointDataCoordinate(frames, coordinate, volume) {
|
|
|
37
40
|
const yMultiple = dimensions[0];
|
|
38
41
|
const zMultiple = dimensions[0] * dimensions[1];
|
|
39
42
|
const value = [];
|
|
40
|
-
|
|
43
|
+
dimensionGroups.forEach((dimensionGroupNumber) => {
|
|
41
44
|
const scalarIndex = index[2] * zMultiple + index[1] * yMultiple + index[0];
|
|
42
|
-
value.push(volume.voxelManager.
|
|
45
|
+
value.push(volume.voxelManager.getAtIndexAndDimensionGroup(scalarIndex, dimensionGroupNumber));
|
|
43
46
|
});
|
|
44
47
|
return value;
|
|
45
48
|
}
|
|
46
|
-
function
|
|
49
|
+
function _getDimensionGroupDataMask(dimensionGroups, dynamicVolume, segmentationVolume) {
|
|
47
50
|
const { imageData: maskImageData } = segmentationVolume;
|
|
48
51
|
const segVoxelManager = segmentationVolume.voxelManager;
|
|
49
52
|
const scalarDataLength = segVoxelManager.getScalarDataLength();
|
|
@@ -65,8 +68,8 @@ function _getTimePointDataMask(frames, dynamicVolume, segmentationVolume) {
|
|
|
65
68
|
for (let i = 0; i < nonZeroVoxelIndices.length; i++) {
|
|
66
69
|
const valuesInTime = [];
|
|
67
70
|
const index = nonZeroVoxelIndices[i];
|
|
68
|
-
for (let j = 0; j <
|
|
69
|
-
valuesInTime.push(dynamicVolume.voxelManager.
|
|
71
|
+
for (let j = 0; j < dimensionGroups.length; j++) {
|
|
72
|
+
valuesInTime.push(dynamicVolume.voxelManager.getAtIndexAndDimensionGroup(index, dimensionGroups[j]));
|
|
70
73
|
}
|
|
71
74
|
nonZeroVoxelValuesInTime.push(valuesInTime);
|
|
72
75
|
ijkCoords.push(segVoxelManager.toIJK(index));
|
|
@@ -79,13 +82,13 @@ function _getTimePointDataMask(frames, dynamicVolume, segmentationVolume) {
|
|
|
79
82
|
}
|
|
80
83
|
const overlapIJKMinMax = getVoxelOverlap(dynamicVolume.imageData, dynamicVolume.dimensions, dynamicVolume.spacing, segPointLPS);
|
|
81
84
|
let count = 0;
|
|
82
|
-
const
|
|
83
|
-
|
|
85
|
+
const perDimensionGroupSum = new Map();
|
|
86
|
+
dimensionGroups.forEach((dimensionGroupNumber) => perDimensionGroupSum.set(dimensionGroupNumber, 0));
|
|
84
87
|
const averageCallback = ({ index }) => {
|
|
85
|
-
for (let i = 0; i <
|
|
86
|
-
const value = dynamicVolume.voxelManager.
|
|
87
|
-
const
|
|
88
|
-
|
|
88
|
+
for (let i = 0; i < dimensionGroups.length; i++) {
|
|
89
|
+
const value = dynamicVolume.voxelManager.getAtIndexAndDimensionGroup(index, dimensionGroups[i]);
|
|
90
|
+
const dimensionGroupNumber = dimensionGroups[i];
|
|
91
|
+
perDimensionGroupSum.set(dimensionGroupNumber, perDimensionGroupSum.get(dimensionGroupNumber) + value);
|
|
89
92
|
}
|
|
90
93
|
count++;
|
|
91
94
|
};
|
|
@@ -94,7 +97,7 @@ function _getTimePointDataMask(frames, dynamicVolume, segmentationVolume) {
|
|
|
94
97
|
boundsIJK: overlapIJKMinMax,
|
|
95
98
|
});
|
|
96
99
|
const averageValues = [];
|
|
97
|
-
|
|
100
|
+
perDimensionGroupSum.forEach((sum) => {
|
|
98
101
|
averageValues.push(sum / count);
|
|
99
102
|
});
|
|
100
103
|
ijkCoords.push(segPointIJK);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.17.0",
|
|
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.
|
|
107
|
+
"@cornerstonejs/core": "^2.17.0",
|
|
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": "
|
|
126
|
+
"gitHead": "912559cd9b86ddac21f2e0d6087980fc02343f52"
|
|
127
127
|
}
|