NF: volume computation function for nifti masks
Showing 2 of 5 files from the diff.
nibabel/cmdline/stats.py
created.
nibabel/imagestats.py
created.
Other files ignored by Codecov
setup.cfg
has changed.
nibabel/tests/test_imagestats.py
is new.
@@ -0,0 +1,45 @@
Loading
1 | + | #!python |
|
2 | + | # emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*- |
|
3 | + | # vi: set ft=python sts=4 ts=4 sw=4 et: |
|
4 | + | ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## |
|
5 | + | # |
|
6 | + | # See COPYING file distributed along with the NiBabel package for the |
|
7 | + | # copyright and license terms. |
|
8 | + | # |
|
9 | + | ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## |
|
10 | + | """ |
|
11 | + | Compute image statistics |
|
12 | + | """ |
|
13 | + | ||
14 | + | import argparse |
|
15 | + | from nibabel.loadsave import load |
|
16 | + | from nibabel.imagestats import mask_volume, count_nonzero_voxels |
|
17 | + | ||
18 | + | ||
19 | + | def _get_parser(): |
|
20 | + | """Return command-line argument parser.""" |
|
21 | + | p = argparse.ArgumentParser(description=__doc__) |
|
22 | + | p.add_argument("infile", |
|
23 | + | help="Neuroimaging volume to compute statistics on.") |
|
24 | + | p.add_argument("-V", "--Volume", action="store_true", required=False, |
|
25 | + | help="Compute mask volume of a given mask image.") |
|
26 | + | p.add_argument("--units", default="mm3", required=False, |
|
27 | + | choices=("mm3", "vox"), help="Preferred output units") |
|
28 | + | return p |
|
29 | + | ||
30 | + | ||
31 | + | def main(args=None): |
|
32 | + | """Main program function.""" |
|
33 | + | parser = _get_parser() |
|
34 | + | opts = parser.parse_args(args) |
|
35 | + | from_img = load(opts.infile) |
|
36 | + | ||
37 | + | if opts.Volume: |
|
38 | + | if opts.units == 'mm3': |
|
39 | + | computed_volume = mask_volume(from_img) |
|
40 | + | elif opts.units == 'vox': |
|
41 | + | computed_volume = count_nonzero_voxels(from_img) |
|
42 | + | else: |
|
43 | + | raise ValueError(f'{opts.units} is not a valid unit. Choose "mm3" or "vox".') |
|
44 | + | print(computed_volume) |
|
45 | + | return 0 |
@@ -0,0 +1,66 @@
Loading
1 | + | # emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*- |
|
2 | + | # vi: set ft=python sts=4 ts=4 sw=4 et: |
|
3 | + | ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## |
|
4 | + | # |
|
5 | + | # See COPYING file distributed along with the NiBabel package for the |
|
6 | + | # copyright and license terms. |
|
7 | + | # |
|
8 | + | ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## |
|
9 | + | """ |
|
10 | + | Functions for computing image statistics |
|
11 | + | """ |
|
12 | + | ||
13 | + | import numpy as np |
|
14 | + | from nibabel.imageclasses import spatial_axes_first |
|
15 | + | ||
16 | + | ||
17 | + | def count_nonzero_voxels(img): |
|
18 | + | """ |
|
19 | + | Count number of non-zero voxels |
|
20 | + | ||
21 | + | Parameters |
|
22 | + | ---------- |
|
23 | + | img : ``SpatialImage`` |
|
24 | + | All voxels of the mask should be of value 1, background should have value 0. |
|
25 | + | ||
26 | + | Returns |
|
27 | + | ------- |
|
28 | + | count : int |
|
29 | + | Number of non-zero voxels |
|
30 | + | ||
31 | + | """ |
|
32 | + | return np.count_nonzero(img.dataobj) |
|
33 | + | ||
34 | + | ||
35 | + | def mask_volume(img): |
|
36 | + | """ Compute volume of mask image. |
|
37 | + | ||
38 | + | Equivalent to "fslstats /path/file.nii -V" |
|
39 | + | ||
40 | + | Parameters |
|
41 | + | ---------- |
|
42 | + | img : ``SpatialImage`` |
|
43 | + | All voxels of the mask should be of value 1, background should have value 0. |
|
44 | + | ||
45 | + | ||
46 | + | Returns |
|
47 | + | ------- |
|
48 | + | volume : float |
|
49 | + | Volume of mask expressed in mm3. |
|
50 | + | ||
51 | + | Examples |
|
52 | + | -------- |
|
53 | + | >>> import numpy as np |
|
54 | + | >>> import nibabel as nb |
|
55 | + | >>> mask_data = np.zeros((20, 20, 20), dtype='u1') |
|
56 | + | >>> mask_data[5:15, 5:15, 5:15] = 1 |
|
57 | + | >>> nb.imagestats.mask_volume(nb.Nifti1Image(mask_data, np.eye(4))) |
|
58 | + | 1000.0 |
|
59 | + | """ |
|
60 | + | if not spatial_axes_first(img): |
|
61 | + | raise ValueError("Cannot calculate voxel volume for image with unknown spatial axes") |
|
62 | + | voxel_volume_mm3 = np.prod(img.header.get_zooms()[:3]) |
|
63 | + | mask_volume_vx = count_nonzero_voxels(img) |
|
64 | + | mask_volume_mm3 = mask_volume_vx * voxel_volume_mm3 |
|
65 | + | ||
66 | + | return mask_volume_mm3 |
Files | Coverage |
---|---|
nibabel | 91.90% |
Project Totals (101 files) | 91.90% |
Untitled
3939.8
TRAVIS_PYTHON_VERSION=3.6 TRAVIS_OS_NAME=linux
3939.10
TRAVIS_PYTHON_VERSION=3.8 TRAVIS_OS_NAME=linux
3939.9
TRAVIS_PYTHON_VERSION=3.6 TRAVIS_OS_NAME=linux
3939.3
TRAVIS_PYTHON_VERSION=3.6 TRAVIS_OS_NAME=linux
3939.13
TRAVIS_PYTHON_VERSION=3.6 TRAVIS_OS_NAME=linux
3939.11
TRAVIS_OS_NAME=osx
3939.12
TRAVIS_OS_NAME=osx
3939.15
TRAVIS_PYTHON_VERSION=3.6 TRAVIS_OS_NAME=linux
3939.14
TRAVIS_PYTHON_VERSION=3.6 TRAVIS_OS_NAME=linux
3939.1
TRAVIS_PYTHON_VERSION=3.7 TRAVIS_OS_NAME=linux
3939.4
TRAVIS_PYTHON_VERSION=3.6 TRAVIS_OS_NAME=linux
Untitled
3939.2
TRAVIS_PYTHON_VERSION=3.8 TRAVIS_OS_NAME=linux
Untitled
Untitled
3939.6
TRAVIS_PYTHON_VERSION=3.6 TRAVIS_OS_NAME=linux
Untitled
Untitled
3939.7
TRAVIS_PYTHON_VERSION=3.6 TRAVIS_OS_NAME=linux
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file.
The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files.
The size and color of each slice is representing the number of statements and the coverage, respectively.