Skip to content

Commit 9318609

Browse files
committed
Merge branch 'master' into enh/NewDipyInterfaces
2 parents 0a1f066 + e8e18ef commit 9318609

File tree

10 files changed

+389
-3
lines changed

10 files changed

+389
-3
lines changed

.noserc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[nosetests]
2+
verbosity=3
3+
4+
with-coverage=1
5+
cover-branches=1
6+
cover-xml=1
7+
cover-xml-file=./coverage.xml
8+
cover-min-percentage=50
9+
10+
11+
with-xunit=1

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Next release
33

44
* ENH: New interfaces in dipy: RESTORE, EstimateResponseSH, CSD and StreamlineTractography
55
(https://github.com/nipy/nipype/pull/1090)
6+
* ENH: Added support for PETPVC (https://github.com/nipy/nipype/pull/1335)
67
* ENH: Merge S3DataSink into DataSink, added AWS documentation (https://github.com/nipy/nipype/pull/1316)
78
* TST: Cache APT in CircleCI (https://github.com/nipy/nipype/pull/1333)
89
* ENH: Add new flags to the BRAINSABC for new features (https://github.com/nipy/nipype/pull/1322)

circle.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ dependencies:
2121
# Set up python environment
2222
- pip install --upgrade pip
2323
- pip install -e .
24-
- pip install matplotlib sphinx ipython boto dipy
24+
- pip install matplotlib sphinx ipython boto coverage dipy
2525
- gem install fakes3
2626
- if [[ ! -d ~/examples/data ]]; then wget "http://tcpdiag.dl.sourceforge.net/project/nipy/nipype/nipype-0.2/nipype-tutorial.tar.bz2" && tar jxvf nipype-tutorial.tar.bz2 && mv nipype-tutorial/* ~/examples/; fi
2727
- if [[ ! -d ~/examples/fsl_course_data ]]; then wget -c "http://fsl.fmrib.ox.ac.uk/fslcourse/fdt1.tar.gz" && wget -c "http://fsl.fmrib.ox.ac.uk/fslcourse/fdt2.tar.gz" && wget -c "http://fsl.fmrib.ox.ac.uk/fslcourse/tbss.tar.gz" && mkdir ~/examples/fsl_course_data && tar zxvf fdt1.tar.gz -C ~/examples/fsl_course_data && tar zxvf fdt2.tar.gz -C ~/examples/fsl_course_data && tar zxvf tbss.tar.gz -C ~/examples/fsl_course_data; fi
@@ -32,7 +32,8 @@ machine:
3232
FSLOUTPUTTYPE: NIFTI_GZ
3333
test:
3434
override:
35-
- source $HOME/.profile; nosetests --with-doctest --logging-level=DEBUG --verbosity=3:
35+
- mkdir -p ${CIRCLE_TEST_REPORTS}/nose
36+
- source $HOME/.profile; nosetests --with-doctest --xunit-file="${CIRCLE_TEST_REPORTS}/nose/${CIRCLE_PROJECT_REPONAME}.xml" -c ./.noserc --logging-level=DEBUG --verbosity=3:
3637
environment:
3738
SPMMCRCMD: "$HOME/spm12/run_spm12.sh $HOME/mcr/v85/ script"
3839
FORCE_SPMMCR: 1
@@ -66,3 +67,5 @@ general:
6667
artifacts:
6768
- "doc/_build/html"
6869
- "~/log.txt"
70+
- "nosetests.xml"
71+
- "coverage.xml"

nipype/algorithms/misc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ def _run_interface(self, runtime):
302302
vollist = [nb.load(filename) for filename in self.inputs.in_file]
303303
data = np.concatenate([vol.get_data().reshape(
304304
vol.get_shape()[:3] + (-1,)) for vol in vollist], axis=3)
305-
data = data.nan_to_num()
305+
data = np.nan_to_num(data)
306306

307307
if data.dtype.kind == 'i':
308308
header.set_data_dtype(np.float32)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from ...testing import assert_equal
3+
from ..metrics import ErrorMap
4+
5+
6+
def test_ErrorMap_inputs():
7+
input_map = dict(ignore_exception=dict(nohash=True,
8+
usedefault=True,
9+
),
10+
in_ref=dict(mandatory=True,
11+
),
12+
in_tst=dict(mandatory=True,
13+
),
14+
mask=dict(),
15+
metric=dict(mandatory=True,
16+
usedefault=True,
17+
),
18+
out_map=dict(),
19+
)
20+
inputs = ErrorMap.input_spec()
21+
22+
for key, metadata in list(input_map.items()):
23+
for metakey, value in list(metadata.items()):
24+
yield assert_equal, getattr(inputs.traits()[key], metakey), value
25+
26+
27+
def test_ErrorMap_outputs():
28+
output_map = dict(distance=dict(),
29+
out_map=dict(),
30+
)
31+
outputs = ErrorMap.output_spec()
32+
33+
for key, metadata in list(output_map.items()):
34+
for metakey, value in list(metadata.items()):
35+
yield assert_equal, getattr(outputs.traits()[key], metakey), value
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from ...testing import assert_equal
3+
from ..misc import Overlap
4+
5+
6+
def test_Overlap_inputs():
7+
input_map = dict(bg_overlap=dict(mandatory=True,
8+
usedefault=True,
9+
),
10+
ignore_exception=dict(nohash=True,
11+
usedefault=True,
12+
),
13+
mask_volume=dict(),
14+
out_file=dict(usedefault=True,
15+
),
16+
vol_units=dict(mandatory=True,
17+
usedefault=True,
18+
),
19+
volume1=dict(mandatory=True,
20+
),
21+
volume2=dict(mandatory=True,
22+
),
23+
weighting=dict(usedefault=True,
24+
),
25+
)
26+
inputs = Overlap.input_spec()
27+
28+
for key, metadata in list(input_map.items()):
29+
for metakey, value in list(metadata.items()):
30+
yield assert_equal, getattr(inputs.traits()[key], metakey), value
31+
32+
33+
def test_Overlap_outputs():
34+
output_map = dict(dice=dict(),
35+
diff_file=dict(),
36+
jaccard=dict(),
37+
labels=dict(),
38+
roi_di=dict(),
39+
roi_ji=dict(),
40+
roi_voldiff=dict(),
41+
volume_difference=dict(),
42+
)
43+
outputs = Overlap.output_spec()
44+
45+
for key, metadata in list(output_map.items()):
46+
for metakey, value in list(metadata.items()):
47+
yield assert_equal, getattr(outputs.traits()[key], metakey), value

nipype/interfaces/petpvc.py

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
2+
# vi: set ft=python sts=4 ts=4 sw=4 et:
3+
"""
4+
Change directory to provide relative paths for doctests
5+
>>> import os
6+
>>> filepath = os.path.dirname( os.path.realpath( __file__ ) )
7+
>>> datadir = os.path.realpath(os.path.join(filepath, '../testing/data'))
8+
>>> os.chdir(datadir)
9+
10+
Nipype interface for PETPVC.
11+
12+
PETPVC is a software from the Nuclear Medicine Department
13+
of the UCL University Hospital, London, UK.
14+
15+
Its source code is here: https://github.com/UCL/PETPVC
16+
17+
The methods that it implement are explained here:
18+
K. Erlandsson, I. Buvat, P. H. Pretorius, B. A. Thomas, and B. F. Hutton,
19+
"A review of partial volume correction techniques for emission tomography
20+
and their applications in neurology, cardiology and oncology," Phys. Med.
21+
Biol., vol. 57, no. 21, p. R119, 2012.
22+
23+
There is a publication waiting to be accepted for this software tool.
24+
25+
26+
Its command line help shows this:
27+
28+
-i --input < filename >
29+
= PET image file
30+
-o --output < filename >
31+
= Output file
32+
[ -m --mask < filename > ]
33+
= Mask image file
34+
-p --pvc < keyword >
35+
= Desired PVC method
36+
-x < X >
37+
= The full-width at half maximum in mm along x-axis
38+
-y < Y >
39+
= The full-width at half maximum in mm along y-axis
40+
-z < Z >
41+
= The full-width at half maximum in mm along z-axis
42+
[ -d --debug ]
43+
= Prints debug information
44+
[ -n --iter [ Val ] ]
45+
= Number of iterations
46+
With: Val (Default = 10)
47+
[ -k [ Val ] ]
48+
= Number of deconvolution iterations
49+
With: Val (Default = 10)
50+
[ -a --alpha [ aval ] ]
51+
= Alpha value
52+
With: aval (Default = 1.5)
53+
[ -s --stop [ stopval ] ]
54+
= Stopping criterion
55+
With: stopval (Default = 0.01)
56+
57+
----------------------------------------------
58+
Technique - keyword
59+
60+
Geometric transfer matrix - "GTM"
61+
Labbe approach - "LABBE"
62+
Richardson-Lucy - "RL"
63+
Van-Cittert - "VC"
64+
Region-based voxel-wise correction - "RBV"
65+
RBV with Labbe - "LABBE+RBV"
66+
RBV with Van-Cittert - "RBV+VC"
67+
RBV with Richardson-Lucy - "RBV+RL"
68+
RBV with Labbe and Van-Cittert - "LABBE+RBV+VC"
69+
RBV with Labbe and Richardson-Lucy- "LABBE+RBV+RL"
70+
Multi-target correction - "MTC"
71+
MTC with Labbe - "LABBE+MTC"
72+
MTC with Van-Cittert - "MTC+VC"
73+
MTC with Richardson-Lucy - "MTC+RL"
74+
MTC with Labbe and Van-Cittert - "LABBE+MTC+VC"
75+
MTC with Labbe and Richardson-Lucy- "LABBE+MTC+RL"
76+
Iterative Yang - "IY"
77+
Iterative Yang with Van-Cittert - "IY+VC"
78+
Iterative Yang with Richardson-Lucy - "IY+RL"
79+
Muller Gartner - "MG"
80+
Muller Gartner with Van-Cittert - "MG+VC"
81+
Muller Gartner with Richardson-Lucy - "MG+RL"
82+
83+
"""
84+
from __future__ import print_function
85+
from __future__ import division
86+
87+
import os
88+
import warnings
89+
90+
from nipype.interfaces.base import (
91+
TraitedSpec,
92+
CommandLineInputSpec,
93+
CommandLine,
94+
File,
95+
isdefined,
96+
traits,
97+
)
98+
99+
warn = warnings.warn
100+
101+
pvc_methods = ['GTM',
102+
'IY',
103+
'IY+RL',
104+
'IY+VC',
105+
'LABBE',
106+
'LABBE+MTC',
107+
'LABBE+MTC+RL',
108+
'LABBE+MTC+VC',
109+
'LABBE+RBV',
110+
'LABBE+RBV+RL',
111+
'LABBE+RBV+VC',
112+
'MG',
113+
'MG+RL',
114+
'MG+VC',
115+
'MTC',
116+
'MTC+RL',
117+
'MTC+VC',
118+
'RBV',
119+
'RBV+RL',
120+
'RBV+VC',
121+
'RL',
122+
'VC']
123+
124+
125+
class PETPVCInputSpec(CommandLineInputSpec):
126+
in_file = File(desc="PET image file", exists=True, mandatory=True, argstr="-i %s")
127+
out_file = File(desc="Output file", genfile=True, hash_files=False, argstr="-o %s")
128+
mask_file = File(desc="Mask image file", exists=True, mandatory=True, argstr="-m %s")
129+
pvc = traits.Enum(pvc_methods, desc="Desired PVC method", mandatory=True, argstr="-p %s")
130+
fwhm_x = traits.Float(desc="The full-width at half maximum in mm along x-axis", mandatory=True, argstr="-x %.4f")
131+
fwhm_y = traits.Float(desc="The full-width at half maximum in mm along y-axis", mandatory=True, argstr="-y %.4f")
132+
fwhm_z = traits.Float(desc="The full-width at half maximum in mm along z-axis", mandatory=True, argstr="-z %.4f")
133+
debug = traits.Bool (desc="Prints debug information", usedefault=True, default_value=False, argstr="-d")
134+
n_iter = traits.Int (desc="Number of iterations", default_value=10, argstr="-n %d")
135+
n_deconv = traits.Int (desc="Number of deconvolution iterations", default_value=10, argstr="-k %d")
136+
alpha = traits.Float(desc="Alpha value", default_value=1.5, argstr="-a %.4f")
137+
stop_crit = traits.Float(desc="Stopping criterion", default_value=0.01, argstr="-a %.4f")
138+
139+
140+
class PETPVCOutputSpec(TraitedSpec):
141+
out_file = File(desc = "Output file")
142+
143+
144+
class PETPVC(CommandLine):
145+
""" Use PETPVC for partial volume correction of PET images.
146+
147+
Examples
148+
--------
149+
>>> from ..testing import example_data
150+
>>> #TODO get data for PETPVC
151+
>>> pvc = PETPVC()
152+
>>> pvc.inputs.in_file = 'pet.nii.gz'
153+
>>> pvc.inputs.mask_file = 'tissues.nii.gz'
154+
>>> pvc.inputs.out_file = 'pet_pvc_rbv.nii.gz'
155+
>>> pvc.inputs.pvc = 'RBV'
156+
>>> pvc.inputs.fwhm_x = 2.0
157+
>>> pvc.inputs.fwhm_y = 2.0
158+
>>> pvc.inputs.fwhm_z = 2.0
159+
>>> outs = pvc.run() #doctest: +SKIP
160+
"""
161+
input_spec = PETPVCInputSpec
162+
output_spec = PETPVCOutputSpec
163+
_cmd = 'petpvc'
164+
165+
def _list_outputs(self):
166+
outputs = self.output_spec().get()
167+
outputs['out_file'] = self.inputs.out_file
168+
if not isdefined(outputs['out_file']):
169+
method_name = self.inputs.pvc.lower()
170+
outputs['out_file'] = self._gen_fname(self.inputs.in_file,
171+
suffix='_{}_pvc'.format(method_name))
172+
173+
outputs['out_file'] = os.path.abspath(outputs['out_file'])
174+
return outputs
175+
176+
def _gen_fname(self, basename, cwd=None, suffix=None, change_ext=True,
177+
ext='.nii.gz'):
178+
"""Generate a filename based on the given parameters.
179+
180+
The filename will take the form: cwd/basename<suffix><ext>.
181+
If change_ext is True, it will use the extentions specified in
182+
<instance>intputs.output_type.
183+
184+
Parameters
185+
----------
186+
basename : str
187+
Filename to base the new filename on.
188+
cwd : str
189+
Path to prefix to the new filename. (default is os.getcwd())
190+
suffix : str
191+
Suffix to add to the `basename`. (defaults is '' )
192+
change_ext : bool
193+
Flag to change the filename extension to the given `ext`.
194+
(Default is False)
195+
196+
Returns
197+
-------
198+
fname : str
199+
New filename based on given parameters.
200+
201+
"""
202+
from nipype.utils.filemanip import fname_presuffix
203+
204+
if basename == '':
205+
msg = 'Unable to generate filename for command %s. ' % self.cmd
206+
msg += 'basename is not set!'
207+
raise ValueError(msg)
208+
if cwd is None:
209+
cwd = os.getcwd()
210+
if change_ext:
211+
if suffix:
212+
suffix = ''.join((suffix, ext))
213+
else:
214+
suffix = ext
215+
if suffix is None:
216+
suffix = ''
217+
fname = fname_presuffix(basename, suffix=suffix,
218+
use_ext=False, newpath=cwd)
219+
return fname
220+
221+
def _gen_filename(self, name):
222+
if name == 'out_file':
223+
return self._list_outputs()['out_file']
224+
return None

0 commit comments

Comments
 (0)