Skip to content

Commit 109cf78

Browse files
authored
Merge pull request #1910 from mmodat/adding_niftyfit
Inital commit to add niftyfit interfaces
2 parents f39e222 + a74e966 commit 109cf78

28 files changed

+1923
-142
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
"""
5+
The niftyfit module provides classes for interfacing with the `NiftyFit`_
6+
command line tools.
7+
8+
Top-level namespace for niftyfit.
9+
"""
10+
11+
from .asl import FitAsl
12+
from .dwi import FitDwi, DwiTool
13+
from .qt1 import FitQt1

nipype/interfaces/niftyfit/asl.py

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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+
"""
5+
The ASL module of niftyfit, which wraps the fitting methods in NiftyFit.
6+
7+
Change directory to provide relative paths for doctests
8+
>>> import os
9+
>>> filepath = os.path.dirname( os.path.realpath( __file__ ) )
10+
>>> datadir = os.path.realpath(os.path.join(filepath, '../../testing/\
11+
data'))
12+
>>> os.chdir(datadir)
13+
"""
14+
15+
from ..base import TraitedSpec, traits, CommandLineInputSpec
16+
from .base import NiftyFitCommand
17+
from ..niftyreg.base import get_custom_path
18+
19+
20+
class FitAslInputSpec(CommandLineInputSpec):
21+
""" Input Spec for FitAsl. """
22+
desc = 'Filename of the 4D ASL (control/label) source image (mandatory).'
23+
source_file = traits.File(position=1,
24+
exists=True,
25+
argstr='-source %s',
26+
mandatory=True,
27+
desc=desc)
28+
pasl = traits.Bool(desc='Fit PASL ASL data [default]', argstr='-pasl')
29+
pcasl = traits.Bool(desc='Fit PCASL ASL data', argstr='-pcasl')
30+
31+
# *** Output options:
32+
desc = 'Filename of the Cerebral Blood Flow map (in ml/100g/min).'
33+
cbf_file = traits.File(name_source=['source_file'],
34+
name_template='%s_cbf.nii.gz',
35+
argstr='-cbf %s', desc=desc)
36+
error_file = traits.File(name_source=['source_file'],
37+
name_template='%s_error.nii.gz',
38+
argstr='-error %s',
39+
desc='Filename of the CBF error map.')
40+
syn_file = traits.File(name_source=['source_file'],
41+
name_template='%s_syn.nii.gz',
42+
argstr='-syn %s',
43+
desc='Filename of the synthetic ASL data.')
44+
45+
# *** Input options (see also fit_qt1 for generic T1 fitting):
46+
desc = 'Filename of the estimated input T1 map (in ms).'
47+
t1map = traits.File(exists=True, argstr='-t1map %s', desc=desc)
48+
desc = 'Filename of the estimated input M0 map.'
49+
m0map = traits.File(exists=True, argstr='-m0map %s', desc=desc)
50+
desc = 'Filename of the estimated input M0 map error.'
51+
m0mape = traits.File(exists=True, argstr='-m0mape %s', desc=desc)
52+
desc = 'Filename of a [1,2,5]s Inversion Recovery volume (T1/M0 fitting \
53+
carried out internally).'
54+
ir_volume = traits.File(exists=True, argstr='-IRvolume %s', desc=desc)
55+
desc = 'Output of [1,2,5]s Inversion Recovery fitting.'
56+
ir_output = traits.File(exists=True, argstr='-IRoutput %s', desc=desc)
57+
58+
# *** Experimental options (Choose those suitable for the model!):
59+
mask = traits.File(position=2,
60+
exists=True,
61+
desc='Filename of image mask.',
62+
argstr='-mask %s')
63+
t1_art_cmp = traits.Float(desc='T1 of arterial component [1650ms].',
64+
argstr='-T1a %f')
65+
desc = 'Single plasma/tissue partition coefficient [0.9ml/g].'
66+
plasma_coeff = traits.Float(desc=desc, argstr='-L %f')
67+
desc = 'Labelling efficiency [0.99 (pasl), 0.85 (pcasl)], ensure any \
68+
background suppression pulses are included in -eff'
69+
eff = traits.Float(desc=desc, argstr='-eff %f')
70+
desc = 'Outlier rejection for multi CL volumes (enter z-score threshold \
71+
(e.g. 2.5)) [off].'
72+
out = traits.Float(desc=desc, argstr='-out %f')
73+
74+
# *** PCASL options (Choose those suitable for the model!):
75+
pld = traits.Float(desc='Post Labelling Delay [2000ms].', argstr='-PLD %f')
76+
ldd = traits.Float(desc='Labelling Duration [1800ms].', argstr='-LDD %f')
77+
desc = 'Difference in labelling delay per slice [0.0 ms/slice.'
78+
dpld = traits.Float(desc=desc, argstr='-dPLD %f')
79+
80+
# *** PASL options (Choose those suitable for the model!):
81+
t_inv1 = traits.Float(desc='Saturation pulse time [800ms].',
82+
argstr='-Tinv1 %f')
83+
t_inv2 = traits.Float(desc='Inversion time [2000ms].', argstr='-Tinv2 %f')
84+
desc = 'Difference in inversion time per slice [0ms/slice].'
85+
dt_inv2 = traits.Float(desc=desc, argstr='-dTinv2 %f')
86+
87+
# *** Other experimental assumptions:
88+
89+
# Not programmed yet
90+
# desc = 'Slope and intercept for Arterial Transit Time.'
91+
# ATT = traits.Float(desc=desc, argstr='-ATT %f')
92+
93+
gm_t1 = traits.Float(desc='T1 of GM [1150ms].', argstr='-gmT1 %f')
94+
gm_plasma = traits.Float(desc='Plasma/GM water partition [0.95ml/g].',
95+
argstr='-gmL %f')
96+
gm_ttt = traits.Float(desc='Time to GM [ATT+0ms].', argstr='-gmTTT %f')
97+
wm_t1 = traits.Float(desc='T1 of WM [800ms].', argstr='-wmT1 %f')
98+
wm_plasma = traits.Float(desc='Plasma/WM water partition [0.82ml/g].',
99+
argstr='-wmL %f')
100+
wm_ttt = traits.Float(desc='Time to WM [ATT+0ms].', argstr='-wmTTT %f')
101+
102+
# *** Segmentation options:
103+
desc = 'Filename of the 4D segmentation (in ASL space) for L/T1 \
104+
estimation and PV correction {WM,GM,CSF}.'
105+
seg = traits.File(exists=True, argstr='-seg %s', desc=desc)
106+
desc = 'Use sigmoid to estimate L from T1: L(T1|gmL,wmL) [Off].'
107+
sig = traits.Bool(desc=desc, argstr='-sig')
108+
desc = 'Simple PV correction (CBF=vg*CBFg + vw*CBFw, with CBFw=f*CBFg) \
109+
[0.25].'
110+
pv0 = traits.Int(desc=desc, argstr='-pv0 %d')
111+
pv2 = traits.Int(desc='In plane PV kernel size [3x3].', argstr='-pv2 %d')
112+
pv3 = traits.Tuple(traits.Int, traits.Int, traits.Int,
113+
desc='3D kernel size [3x3x1].',
114+
argstr='-pv3 %d %d %d')
115+
desc = 'Multiply CBF by this value (e.g. if CL are mislabelled use -1.0).'
116+
mul = traits.Float(desc=desc, argstr='-mul %f')
117+
mulgm = traits.Bool(desc='Multiply CBF by segmentation [Off].',
118+
argstr='-sig')
119+
desc = 'Set PV threshold for switching off LSQR [O.05].'
120+
pv_threshold = traits.Bool(desc=desc, argstr='-pvthreshold')
121+
segstyle = traits.Bool(desc='Set CBF as [gm,wm] not [wm,gm].',
122+
argstr='-segstyle')
123+
124+
125+
class FitAslOutputSpec(TraitedSpec):
126+
""" Output Spec for FitAsl. """
127+
desc = 'Filename of the Cerebral Blood Flow map (in ml/100g/min).'
128+
cbf_file = traits.File(exists=True, desc=desc)
129+
desc = 'Filename of the CBF error map.'
130+
error_file = traits.File(exists=True, desc=desc)
131+
desc = 'Filename of the synthetic ASL data.'
132+
syn_file = traits.File(exists=True, desc=desc)
133+
134+
135+
class FitAsl(NiftyFitCommand):
136+
"""Interface for executable fit_asl from Niftyfit platform.
137+
138+
Use NiftyFit to perform ASL fitting.
139+
140+
ASL fitting routines (following EU Cost Action White Paper recommendations)
141+
Fits Cerebral Blood Flow maps in the first instance.
142+
143+
`Source code <https://cmiclab.cs.ucl.ac.uk/CMIC/NiftyFit-Release>`_
144+
145+
Examples
146+
--------
147+
>>> from nipype.interfaces import niftyfit
148+
>>> node = niftyfit.FitAsl()
149+
>>> node.inputs.source_file = 'asl.nii.gz'
150+
>>> node.cmdline # doctest: +ALLOW_UNICODE
151+
'fit_asl -source asl.nii.gz -cbf asl_cbf.nii.gz -error asl_error.nii.gz \
152+
-syn asl_syn.nii.gz'
153+
154+
"""
155+
_cmd = get_custom_path('fit_asl', env_dir='NIFTYFITDIR')
156+
input_spec = FitAslInputSpec
157+
output_spec = FitAslOutputSpec
158+
_suffix = '_fit_asl'

nipype/interfaces/niftyfit/base.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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+
"""
5+
The niftyfit module provide an interface with the niftyfit software
6+
developed in TIG, UCL.
7+
8+
Software available at:
9+
https://cmiclab.cs.ucl.ac.uk/CMIC/NiftyFit-Release
10+
11+
Version used for this version of the interfaces (git):
12+
13+
commit c6232e4c4223c3d19f7a32906409da5af36299a2
14+
Date: Fri Jan 6 13:34:02 2017 +0000
15+
16+
Examples
17+
--------
18+
See the docstrings of the individual classes for examples.
19+
"""
20+
21+
import os
22+
import warnings
23+
24+
from ..base import CommandLine
25+
from ...utils.filemanip import split_filename
26+
27+
28+
warn = warnings.warn
29+
warnings.filterwarnings('always', category=UserWarning)
30+
31+
32+
class NiftyFitCommand(CommandLine):
33+
"""
34+
Base support interface for NiftyFit commands.
35+
"""
36+
_suffix = '_nf'
37+
38+
def __init__(self, **inputs):
39+
""" Init method calling super. No version to be checked."""
40+
super(NiftyFitCommand, self).__init__(**inputs)
41+
42+
def _gen_fname(self, basename, out_dir=None, suffix=None, ext=None):
43+
if basename == '':
44+
msg = 'Unable to generate filename for command %s. ' % self.cmd
45+
msg += 'basename is not set!'
46+
raise ValueError(msg)
47+
_, final_bn, final_ext = split_filename(basename)
48+
if out_dir is None:
49+
out_dir = os.getcwd()
50+
if ext is not None:
51+
final_ext = ext
52+
if suffix is not None:
53+
final_bn = ''.join((final_bn, suffix))
54+
return os.path.abspath(os.path.join(out_dir, final_bn + final_ext))

0 commit comments

Comments
 (0)