Skip to content

Commit d15d89c

Browse files
committed
enh: add PETPVC wrapper
1 parent 6ca964d commit d15d89c

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed

nipype/interfaces/petpvc.py

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

0 commit comments

Comments
 (0)