Skip to content

Commit 6b4d702

Browse files
committed
feat(vtkimagedata.computehistogram): add numOfPixels to return value
Added the number of pixels involved in the calculation of the various values as part of the return object. Also, added test cases to test computeHistogram().
1 parent ed07178 commit 6b4d702

File tree

4 files changed

+110
-1
lines changed

4 files changed

+110
-1
lines changed

Sources/Common/DataModel/ImageData/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ interface IComputeHistogram {
2222
export interface vtkImageData extends vtkDataSet {
2323

2424
/**
25-
* Returns an object with `{ minimum, maximum, average, variance, sigma }`
25+
* Returns an object with `{ minimum, maximum, average, variance, sigma, count }`
2626
* of the imageData points found within the provided `worldBounds`.
2727
*
2828
* `voxelFunc(index, bounds)` is an optional function that is called with

Sources/Common/DataModel/ImageData/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ function vtkImageData(publicAPI, model) {
421421
average,
422422
variance,
423423
sigma,
424+
count: inum,
424425
};
425426
};
426427

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import test from 'tape-catch';
2+
import vtkImageData from 'vtk.js/Sources/Common/DataModel/ImageData';
3+
import vtkRTAnalyticSource from 'vtk.js/Sources/Filters/Sources/RTAnalyticSource';
4+
5+
test('Test vtkImageData instance', (t) => {
6+
t.ok(vtkImageData, 'Make sure the class definition exists');
7+
const instance = vtkImageData.newInstance();
8+
t.ok(instance);
9+
t.end();
10+
});
11+
12+
test('Test vtkImageData histogram', (t) => {
13+
const spacing = 0.7;
14+
const size = 50;
15+
const compareFloat = (a, b) => Math.abs(a - b) < Number.EPSILON;
16+
17+
const source = vtkRTAnalyticSource.newInstance();
18+
source.setWholeExtent([0, size, 0, size, 0, size]);
19+
source.update();
20+
21+
const image = source.getOutputData();
22+
image.setSpacing([spacing, spacing, spacing]);
23+
24+
const bounds = image.getBounds();
25+
const hist = image.computeHistogram(bounds);
26+
27+
const baseline1 = {
28+
minimum: 9,
29+
maximum: 185,
30+
average: 64.65,
31+
variance: 782.87,
32+
sigma: 27.98,
33+
count: 132651,
34+
};
35+
36+
t.ok(
37+
hist.minimum === baseline1.minimum,
38+
'computeHistogram return value test: minimum'
39+
);
40+
t.ok(
41+
hist.maximum === baseline1.maximum,
42+
'computeHistogram return value test: maximum'
43+
);
44+
t.ok(
45+
compareFloat(hist.average.toFixed(2), baseline1.average),
46+
'computeHistogram return value test: average'
47+
);
48+
t.ok(
49+
compareFloat(hist.variance.toFixed(2), baseline1.variance),
50+
'computeHistogram return value test: variance'
51+
);
52+
t.ok(
53+
compareFloat(hist.sigma.toFixed(2), baseline1.sigma),
54+
'computeHistogram return value test: sigma'
55+
);
56+
t.ok(
57+
hist.count === baseline1.count,
58+
'computeHistogram return value test: count'
59+
);
60+
61+
// masking function that ignores the bottom 10 and top 10 rows of voxels.
62+
const voxelFunc = (idx) => idx[0] > 9 && idx[0] < 40;
63+
64+
const baseline2 = {
65+
minimum: 9,
66+
maximum: 173,
67+
average: 65.29,
68+
variance: 676.51,
69+
sigma: 26.01,
70+
count: 78030,
71+
};
72+
73+
const histWithMask = image.computeHistogram(bounds, voxelFunc);
74+
75+
t.ok(
76+
histWithMask.minimum === baseline2.minimum &&
77+
histWithMask.maximum === baseline2.maximum &&
78+
compareFloat(histWithMask.average.toFixed(2), baseline2.average) &&
79+
compareFloat(histWithMask.variance.toFixed(2), baseline2.variance) &&
80+
compareFloat(histWithMask.sigma.toFixed(2), baseline2.sigma) &&
81+
histWithMask.count === baseline2.count,
82+
'computeHistogram test with masking function'
83+
);
84+
85+
const voxelFuncNone = (idx) => false;
86+
const baseline3 = {
87+
minimum: Infinity,
88+
maximum: -Infinity,
89+
average: 0,
90+
variance: 0,
91+
sigma: 0,
92+
count: 0,
93+
};
94+
const histNone = image.computeHistogram(bounds, voxelFuncNone);
95+
96+
t.ok(
97+
histNone.minimum === baseline3.minimum &&
98+
histNone.maximum === baseline3.maximum &&
99+
compareFloat(histNone.average.toFixed(2), baseline3.average) &&
100+
compareFloat(histNone.variance.toFixed(2), baseline3.variance) &&
101+
compareFloat(histNone.sigma.toFixed(2), baseline3.sigma) &&
102+
histNone.count === baseline3.count,
103+
'computeHistogram test with zero number of voxels that qualify'
104+
);
105+
106+
t.end();
107+
});

Sources/tests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import './Common/DataModel/Box/test/testBox';
1717
import './Common/DataModel/Cell/test/testCell';
1818
import './Common/DataModel/Cone/test/testConeImplicitFunction';
1919
import './Common/DataModel/DataSetAttributes/test/testDataSetAttributes';
20+
import './Common/DataModel/ImageData/test/testImageData';
2021
import './Common/DataModel/Line/test/testLine';
2122
import './Common/DataModel/Plane/test/testPlane';
2223
import './Common/DataModel/PolyData/test/testPolyData';

0 commit comments

Comments
 (0)