Skip to content

Commit e98e51b

Browse files
authored
Merge branch 'master' into pep8_violation_Nov2017
2 parents 730c1a1 + 9be816e commit e98e51b

29 files changed

+1663
-1152
lines changed

.zenodo.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,11 @@
563563
"affiliation": "MIT, HMS",
564564
"name": "Ghosh, Satrajit",
565565
"orcid": "0000-0002-5312-6729"
566+
},
567+
{
568+
"affiliation": "University College London",
569+
"name": "Mancini, Matteo",
570+
"orcid": "0000-0001-7194-4568"
566571
}
567572
],
568573
"keywords": [

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Upcoming release (0.14.1)
22
================
33

4+
* MAINT: Cleaning / simplify ``Node`` (https://github.com/nipy/nipype/pull/#2325)
45

56
0.14.0 (November 29, 2017)
67
==========================

nipype/interfaces/freesurfer/tests/test_FSSurfaceCommand.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ def test_FSSurfaceCommand_inputs():
2424

2525

2626
@pytest.mark.skipif(fs.no_freesurfer(), reason="freesurfer is not installed")
27-
def test_associated_file():
27+
def test_associated_file(tmpdir):
2828
fssrc = FreeSurferSource(subjects_dir=fs.Info.subjectsdir(),
2929
subject_id='fsaverage', hemi='lh')
30+
fssrc.base_dir = tmpdir.strpath
31+
fssrc.resource_monitor = False
3032

3133
fsavginfo = fssrc.run().outputs.get()
3234

nipype/interfaces/mrtrix3/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# -*- coding: utf-8 -*-
55

66
from .utils import (Mesh2PVE, Generate5tt, BrainMask, TensorMetrics,
7-
ComputeTDI, TCK2VTK)
7+
ComputeTDI, TCK2VTK, MRMath, MRConvert, DWIExtract)
88
from .preprocess import ResponseSD, ACTPrepareFSL, ReplaceFSwithFIRST
99
from .tracking import Tractography
1010
from .reconst import FitTensor, EstimateFOD

nipype/interfaces/mrtrix3/preprocess.py

Lines changed: 23 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -17,87 +17,47 @@
1717
import os.path as op
1818

1919
from ..base import (CommandLineInputSpec, CommandLine, traits, TraitedSpec,
20-
File, isdefined)
20+
File, isdefined, Undefined)
2121
from .base import MRTrix3BaseInputSpec, MRTrix3Base
2222

2323

2424
class ResponseSDInputSpec(MRTrix3BaseInputSpec):
25-
in_file = File(exists=True, argstr='%s', mandatory=True, position=-2,
26-
desc='input diffusion weighted images')
27-
28-
out_file = File(
29-
'response.txt', argstr='%s', mandatory=True, position=-1,
30-
usedefault=True, desc='output file containing SH coefficients')
31-
32-
# DW Shell selection options
33-
shell = traits.List(traits.Float, sep=',', argstr='-shell %s',
34-
desc='specify one or more dw gradient shells')
25+
algorithm = traits.Enum('msmt_5tt','dhollander','tournier','tax', argstr='%s', position=-6,
26+
mandatory=True, desc='response estimation algorithm (multi-tissue)')
27+
in_file = File(exists=True, argstr='%s', position=-5,
28+
mandatory=True, desc='input DWI image')
29+
mtt_file = File(argstr='%s', position=-4, desc='input 5tt image')
30+
wm_file = File('wm.txt', argstr='%s', position=-3, usedefault=True,
31+
desc='output WM response text file')
32+
gm_file = File(argstr='%s', position=-2, desc='output GM response text file')
33+
csf_file = File(argstr='%s', position=-1, desc='output CSF response text file')
3534
in_mask = File(exists=True, argstr='-mask %s',
36-
desc='provide initial mask image')
35+
desc='provide initial mask image')
3736
max_sh = traits.Int(8, argstr='-lmax %d',
38-
desc='maximum harmonic degree of response function')
39-
out_sf = File('sf_mask.nii.gz', argstr='-sf %s',
40-
desc='write a mask containing single-fibre voxels')
41-
test_all = traits.Bool(False, argstr='-test_all',
42-
desc='re-test all voxels at every iteration')
43-
44-
# Optimization
45-
iterations = traits.Int(0, argstr='-max_iters %d',
46-
desc='maximum number of iterations per pass')
47-
max_change = traits.Float(
48-
argstr='-max_change %f',
49-
desc=('maximum percentile change in any response function coefficient;'
50-
' if no individual coefficient changes by more than this '
51-
'fraction, the algorithm is terminated.'))
52-
53-
# Thresholds
54-
vol_ratio = traits.Float(
55-
.15, argstr='-volume_ratio %f',
56-
desc=('maximal volume ratio between the sum of all other positive'
57-
' lobes in the voxel and the largest FOD lobe'))
58-
disp_mult = traits.Float(
59-
1., argstr='-dispersion_multiplier %f',
60-
desc=('dispersion of FOD lobe must not exceed some threshold as '
61-
'determined by this multiplier and the FOD dispersion in other '
62-
'single-fibre voxels. The threshold is: (mean + (multiplier * '
63-
'(mean - min))); default = 1.0. Criterion is only applied in '
64-
'second pass of RF estimation.'))
65-
int_mult = traits.Float(
66-
2., argstr='-integral_multiplier %f',
67-
desc=('integral of FOD lobe must not be outside some range as '
68-
'determined by this multiplier and FOD lobe integral in other'
69-
' single-fibre voxels. The range is: (mean +- (multiplier * '
70-
'stdev)); default = 2.0. Criterion is only applied in second '
71-
'pass of RF estimation.'))
37+
desc='maximum harmonic degree of response function')
7238

7339

7440
class ResponseSDOutputSpec(TraitedSpec):
75-
out_file = File(exists=True, desc='the output response file')
76-
out_sf = File(desc=('mask containing single-fibre voxels'))
41+
wm_file = File(argstr='%s', desc='output WM response text file')
42+
gm_file = File(argstr='%s', desc='output GM response text file')
43+
csf_file = File(argstr='%s', desc='output CSF response text file')
7744

7845

7946
class ResponseSD(MRTrix3Base):
8047

8148
"""
82-
Generate an appropriate response function from the image data for
83-
spherical deconvolution.
84-
85-
.. [1] Tax, C. M.; Jeurissen, B.; Vos, S. B.; Viergever, M. A. and
86-
Leemans, A., Recursive calibration of the fiber response function
87-
for spherical deconvolution of diffusion MRI data. NeuroImage,
88-
2014, 86, 67-80
89-
49+
Estimate response function(s) for spherical deconvolution using the specified algorithm.
9050
9151
Example
9252
-------
9353
9454
>>> import nipype.interfaces.mrtrix3 as mrt
9555
>>> resp = mrt.ResponseSD()
9656
>>> resp.inputs.in_file = 'dwi.mif'
97-
>>> resp.inputs.in_mask = 'mask.nii.gz'
57+
>>> resp.inputs.algorithm = 'tournier'
9858
>>> resp.inputs.grad_fsl = ('bvecs', 'bvals')
9959
>>> resp.cmdline # doctest: +ELLIPSIS
100-
'dwi2response -fslgrad bvecs bvals -mask mask.nii.gz dwi.mif response.txt'
60+
'dwi2response -fslgrad bvecs bvals tournier dwi.mif wm.txt'
10161
>>> resp.run() # doctest: +SKIP
10262
"""
10363

@@ -107,10 +67,11 @@ class ResponseSD(MRTrix3Base):
10767

10868
def _list_outputs(self):
10969
outputs = self.output_spec().get()
110-
outputs['out_file'] = op.abspath(self.inputs.out_file)
111-
112-
if isdefined(self.inputs.out_sf):
113-
outputs['out_sf'] = op.abspath(self.inputs.out_sf)
70+
outputs['wm_file'] = op.abspath(self.inputs.wm_file)
71+
if self.inputs.gm_file != Undefined:
72+
outputs['gm_file'] = op.abspath(self.inputs.gm_file)
73+
if self.inputs.csf_file != Undefined:
74+
outputs['csf_file'] = op.abspath(self.inputs.csf_file)
11475
return outputs
11576

11677

nipype/interfaces/mrtrix3/reconst.py

Lines changed: 29 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import os.path as op
1818

19-
from ..base import traits, TraitedSpec, File
19+
from ..base import traits, TraitedSpec, File, Undefined
2020
from .base import MRTrix3BaseInputSpec, MRTrix3Base
2121

2222

@@ -75,108 +75,55 @@ def _list_outputs(self):
7575

7676

7777
class EstimateFODInputSpec(MRTrix3BaseInputSpec):
78-
in_file = File(exists=True, argstr='%s', mandatory=True, position=-3,
79-
desc='input diffusion weighted images')
80-
response = File(
81-
exists=True, argstr='%s', mandatory=True, position=-2,
82-
desc=('a text file containing the diffusion-weighted signal response '
83-
'function coefficients for a single fibre population'))
84-
out_file = File(
85-
'fods.mif', argstr='%s', mandatory=True, position=-1,
86-
usedefault=True, desc=('the output spherical harmonics coefficients'
87-
' image'))
78+
algorithm = traits.Enum('csd','msmt_csd', argstr='%s', position=-8,
79+
mandatory=True, desc='FOD algorithm')
80+
in_file = File(exists=True, argstr='%s', position=-7,
81+
mandatory=True, desc='input DWI image')
82+
wm_txt = File(argstr='%s', position=-6,
83+
mandatory=True, desc='WM response text file')
84+
wm_odf = File('wm.mif', argstr='%s', position=-5, usedefault=True,
85+
mandatory=True, desc='output WM ODF')
86+
gm_txt = File(argstr='%s', position=-4, desc='GM response text file')
87+
gm_odf = File('gm.mif', argstr='%s', position=-3, desc='output GM ODF')
88+
csf_txt = File(argstr='%s', position=-2, desc='CSF response text file')
89+
csf_odf = File('csf.mif', argstr='%s', position=-1, desc='output CSF ODF')
90+
mask_file = File(exists=True, argstr='-mask %s', desc='mask image')
8891

8992
# DW Shell selection options
9093
shell = traits.List(traits.Float, sep=',', argstr='-shell %s',
9194
desc='specify one or more dw gradient shells')
92-
93-
# Spherical deconvolution options
9495
max_sh = traits.Int(8, argstr='-lmax %d',
9596
desc='maximum harmonic degree of response function')
96-
in_mask = File(exists=True, argstr='-mask %s',
97-
desc='provide initial mask image')
9897
in_dirs = File(
9998
exists=True, argstr='-directions %s',
10099
desc=('specify the directions over which to apply the non-negativity '
101100
'constraint (by default, the built-in 300 direction set is '
102101
'used). These should be supplied as a text file containing the '
103102
'[ az el ] pairs for the directions.'))
104-
sh_filter = File(
105-
exists=True, argstr='-filter %s',
106-
desc=('the linear frequency filtering parameters used for the initial '
107-
'linear spherical deconvolution step (default = [ 1 1 1 0 0 ]). '
108-
'These should be supplied as a text file containing the '
109-
'filtering coefficients for each even harmonic order.'))
110-
111-
neg_lambda = traits.Float(
112-
1.0, argstr='-neg_lambda %f',
113-
desc=('the regularisation parameter lambda that controls the strength'
114-
' of the non-negativity constraint'))
115-
thres = traits.Float(
116-
0.0, argstr='-threshold %f',
117-
desc=('the threshold below which the amplitude of the FOD is assumed '
118-
'to be zero, expressed as an absolute amplitude'))
119-
120-
n_iter = traits.Int(
121-
50, argstr='-niter %d', desc=('the maximum number of iterations '
122-
'to perform for each voxel'))
123103

124104

125105
class EstimateFODOutputSpec(TraitedSpec):
126-
out_file = File(exists=True, desc='the output response file')
106+
wm_odf = File(argstr='%s', desc='output WM ODF')
107+
gm_odf = File(argstr='%s', desc='output GM ODF')
108+
csf_odf = File(argstr='%s', desc='output CSF ODF')
127109

128110

129111
class EstimateFOD(MRTrix3Base):
130112

131113
"""
132-
Convert diffusion-weighted images to tensor images
133-
134-
Note that this program makes use of implied symmetries in the diffusion
135-
profile. First, the fact the signal attenuation profile is real implies
136-
that it has conjugate symmetry, i.e. Y(l,-m) = Y(l,m)* (where * denotes
137-
the complex conjugate). Second, the diffusion profile should be
138-
antipodally symmetric (i.e. S(x) = S(-x)), implying that all odd l
139-
components should be zero. Therefore, this program only computes the even
140-
elements.
141-
142-
Note that the spherical harmonics equations used here differ slightly from
143-
those conventionally used, in that the (-1)^m factor has been omitted.
144-
This should be taken into account in all subsequent calculations.
145-
The spherical harmonic coefficients are stored as follows. First, since
146-
the signal attenuation profile is real, it has conjugate symmetry, i.e.
147-
Y(l,-m) = Y(l,m)* (where * denotes the complex conjugate). Second, the
148-
diffusion profile should be antipodally symmetric (i.e. S(x) = S(-x)),
149-
implying that all odd l components should be zero. Therefore, only the
150-
even elements are computed.
151-
152-
Note that the spherical harmonics equations used here differ slightly from
153-
those conventionally used, in that the (-1)^m factor has been omitted.
154-
This should be taken into account in all subsequent calculations.
155-
Each volume in the output image corresponds to a different spherical
156-
harmonic component. Each volume will correspond to the following:
157-
158-
volume 0: l = 0, m = 0
159-
volume 1: l = 2, m = -2 (imaginary part of m=2 SH)
160-
volume 2: l = 2, m = -1 (imaginary part of m=1 SH)
161-
volume 3: l = 2, m = 0
162-
volume 4: l = 2, m = 1 (real part of m=1 SH)
163-
volume 5: l = 2, m = 2 (real part of m=2 SH)
164-
etc...
165-
166-
114+
Estimate fibre orientation distributions from diffusion data using spherical deconvolution
167115
168116
Example
169117
-------
170118
171119
>>> import nipype.interfaces.mrtrix3 as mrt
172120
>>> fod = mrt.EstimateFOD()
121+
>>> fod.inputs.algorithm = 'csd'
173122
>>> fod.inputs.in_file = 'dwi.mif'
174-
>>> fod.inputs.response = 'response.txt'
175-
>>> fod.inputs.in_mask = 'mask.nii.gz'
123+
>>> fod.inputs.wm_txt = 'wm.txt'
176124
>>> fod.inputs.grad_fsl = ('bvecs', 'bvals')
177125
>>> fod.cmdline # doctest: +ELLIPSIS
178-
'dwi2fod -fslgrad bvecs bvals -mask mask.nii.gz dwi.mif response.txt\
179-
fods.mif'
126+
'dwi2fod -fslgrad bvecs bvals csd dwi.mif wm.txt wm.mif'
180127
>>> fod.run() # doctest: +SKIP
181128
"""
182129

@@ -186,5 +133,12 @@ class EstimateFOD(MRTrix3Base):
186133

187134
def _list_outputs(self):
188135
outputs = self.output_spec().get()
189-
outputs['out_file'] = op.abspath(self.inputs.out_file)
136+
outputs['wm_odf'] = op.abspath(self.inputs.wm_odf)
137+
if self.inputs.gm_odf != Undefined:
138+
outputs['gm_odf'] = op.abspath(self.inputs.gm_odf)
139+
if self.inputs.csf_odf != Undefined:
140+
outputs['csf_odf'] = op.abspath(self.inputs.csf_odf)
190141
return outputs
142+
143+
144+
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from __future__ import unicode_literals
3+
from ..utils import DWIExtract
4+
5+
6+
def test_DWIExtract_inputs():
7+
input_map = dict(args=dict(argstr='%s',
8+
),
9+
bval_scale=dict(argstr='-bvalue_scaling %s',
10+
),
11+
bzero=dict(argstr='-bzero',
12+
),
13+
environ=dict(nohash=True,
14+
usedefault=True,
15+
),
16+
grad_file=dict(argstr='-grad %s',
17+
),
18+
grad_fsl=dict(argstr='-fslgrad %s %s',
19+
),
20+
ignore_exception=dict(deprecated='1.0.0',
21+
nohash=True,
22+
usedefault=True,
23+
),
24+
in_bval=dict(),
25+
in_bvec=dict(argstr='-fslgrad %s %s',
26+
),
27+
in_file=dict(argstr='%s',
28+
mandatory=True,
29+
position=-2,
30+
),
31+
nobzero=dict(argstr='-nobzero',
32+
),
33+
nthreads=dict(argstr='-nthreads %d',
34+
nohash=True,
35+
),
36+
out_file=dict(argstr='%s',
37+
mandatory=True,
38+
position=-1,
39+
),
40+
shell=dict(argstr='-shell %s',
41+
sep=',',
42+
),
43+
singleshell=dict(argstr='-singleshell',
44+
),
45+
terminal_output=dict(deprecated='1.0.0',
46+
nohash=True,
47+
),
48+
)
49+
inputs = DWIExtract.input_spec()
50+
51+
for key, metadata in list(input_map.items()):
52+
for metakey, value in list(metadata.items()):
53+
assert getattr(inputs.traits()[key], metakey) == value
54+
55+
56+
def test_DWIExtract_outputs():
57+
output_map = dict(out_file=dict(),
58+
)
59+
outputs = DWIExtract.output_spec()
60+
61+
for key, metadata in list(output_map.items()):
62+
for metakey, value in list(metadata.items()):
63+
assert getattr(outputs.traits()[key], metakey) == value

0 commit comments

Comments
 (0)