Skip to content

Commit f11e960

Browse files
committed
Merge branch 'alexsavio-petpvc'
2 parents c4fc236 + e7b059f commit f11e960

File tree

4 files changed

+289
-0
lines changed

4 files changed

+289
-0
lines changed

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
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from ...testing import assert_equal
3+
from ..petpvc import PETPVC
4+
5+
6+
def test_PETPVC_inputs():
7+
input_map = dict(alpha=dict(argstr='-a %.4f',
8+
),
9+
args=dict(argstr='%s',
10+
),
11+
debug=dict(argstr='-d',
12+
usedefault=True,
13+
),
14+
environ=dict(nohash=True,
15+
usedefault=True,
16+
),
17+
fwhm_x=dict(argstr='-x %.4f',
18+
mandatory=True,
19+
),
20+
fwhm_y=dict(argstr='-y %.4f',
21+
mandatory=True,
22+
),
23+
fwhm_z=dict(argstr='-z %.4f',
24+
mandatory=True,
25+
),
26+
ignore_exception=dict(nohash=True,
27+
usedefault=True,
28+
),
29+
in_file=dict(argstr='-i %s',
30+
mandatory=True,
31+
),
32+
mask_file=dict(argstr='-m %s',
33+
mandatory=True,
34+
),
35+
n_deconv=dict(argstr='-k %d',
36+
),
37+
n_iter=dict(argstr='-n %d',
38+
),
39+
out_file=dict(argstr='-o %s',
40+
genfile=True,
41+
hash_files=False,
42+
),
43+
pvc=dict(argstr='-p %s',
44+
mandatory=True,
45+
),
46+
stop_crit=dict(argstr='-a %.4f',
47+
),
48+
terminal_output=dict(nohash=True,
49+
),
50+
)
51+
inputs = PETPVC.input_spec()
52+
53+
for key, metadata in list(input_map.items()):
54+
for metakey, value in list(metadata.items()):
55+
yield assert_equal, getattr(inputs.traits()[key], metakey), value
56+
57+
58+
def test_PETPVC_outputs():
59+
output_map = dict(out_file=dict(),
60+
)
61+
outputs = PETPVC.output_spec()
62+
63+
for key, metadata in list(output_map.items()):
64+
for metakey, value in list(metadata.items()):
65+
yield assert_equal, getattr(outputs.traits()[key], metakey), value

nipype/testing/data/pet.nii.gz

Whitespace-only changes.

nipype/testing/data/tissues.nii.gz

Whitespace-only changes.

0 commit comments

Comments
 (0)