Skip to content

Commit 68ab056

Browse files
committed
fixed XFibres
1 parent 0f1c179 commit 68ab056

File tree

5 files changed

+86
-201
lines changed

5 files changed

+86
-201
lines changed

nipype/interfaces/fsl/base.py

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,6 @@ def _overload_extension(self, value, name=None):
246246

247247

248248
class FSLXCommandInputSpec(FSLCommandInputSpec):
249-
out_dir = Directory('.', mandatory=True, desc='output directory',
250-
usedefault=True, position=1, argstr='%s')
251249
dwi = File(exists=True, argstr='--data=%s', mandatory=True,
252250
desc='diffusion weighted image data file')
253251
mask = File(exists=True, argstr='--mask=%s', mandatory=True,
@@ -307,39 +305,39 @@ class FSLXCommandInputSpec(FSLCommandInputSpec):
307305
f0_ard = traits.Bool(argstr='--f0 --ardf0', xor=_xor_inputs3 + ['all_ard'],
308306
desc=('Noise floor model: add to the model an '
309307
'unattenuated signal compartment f0'))
310-
force_dir = traits.Bool(False, argstr='--forcedir', usedefault=True,
308+
force_dir = traits.Bool(True, argstr='--forcedir', usedefault=True,
311309
desc=('use the actual directory name given '
312310
'(do not add + to make a new directory)'))
313311

314312

315313
class FSLXCommandOutputSpec(TraitedSpec):
316-
merged_thsamples = OutputMultiPath(File(exists=True), desc=('Samples from '
314+
merged_thsamples = OutputMultiPath(File(), desc=('Samples from '
317315
'the distribution on theta'))
318-
merged_phsamples = OutputMultiPath(File(exists=True), desc=('Samples from '
316+
merged_phsamples = OutputMultiPath(File(), desc=('Samples from '
319317
'the distribution on phi'))
320-
merged_fsamples = OutputMultiPath(File(exists=True),
318+
merged_fsamples = OutputMultiPath(File(),
321319
desc=('Samples from the distribution on '
322320
'anisotropic volume fraction.'))
323321

324-
mean_thsamples = OutputMultiPath(File(exists=True), desc=('Mean of '
322+
mean_thsamples = OutputMultiPath(File(), desc=('Mean of '
325323
'distribution on theta'))
326-
mean_phsamples = OutputMultiPath(File(exists=True), desc=('Mean of '
324+
mean_phsamples = OutputMultiPath(File(), desc=('Mean of '
327325
'distribution on phi'))
328-
mean_fsamples = OutputMultiPath(File(exists=True), desc=('Mean of '
326+
mean_fsamples = OutputMultiPath(File(), desc=('Mean of '
329327
'distribution on f anisotropy'))
330328

331-
mean_dsamples = File(exists=True, desc='Mean of distribution on '
329+
mean_dsamples = File(desc='Mean of distribution on '
332330
'diffusivity d')
333-
mean_S0samples = File(exists=True, desc='Mean of distribution on T2w'
331+
mean_S0samples = File(desc='Mean of distribution on T2w'
334332
'baseline signal intensity S0')
335-
mean_tausamples = File(exists=True, desc='Mean of distribution on '
333+
mean_tausamples = File(desc='Mean of distribution on '
336334
'tau samples (only with rician noise)')
337335

338-
dyads = OutputMultiPath(File(exists=True), desc=('Mean of PDD distribution'
336+
dyads = OutputMultiPath(File(), desc=('Mean of PDD distribution'
339337
' in vector form.'))
340-
dyads_disp = OutputMultiPath(File(exists=True), desc=('Uncertainty on the '
338+
dyads_disp = OutputMultiPath(File(), desc=('Uncertainty on the '
341339
' estimated fiber orientation'))
342-
fsamples = OutputMultiPath(File(exists=True), desc=('Samples from the '
340+
fsamples = OutputMultiPath(File(), desc=('Samples from the '
343341
'distribution on anisotropic volume fraction'))
344342

345343

@@ -351,28 +349,7 @@ class FSLXCommand(FSLCommand):
351349
output_spec = FSLXCommandOutputSpec
352350

353351
def _run_interface(self, runtime):
354-
subjectdir = os.path.abspath(self.inputs.out_dir)
355-
out_dir = subjectdir + '.bedpostX'
356-
357-
if isdefined(self.inputs.force_dir) and self.inputs.force_dir:
358-
out_dir = os.path.abspath(self.inputs.out_dir)
359-
self._out_dir = out_dir
360-
361-
if not os.path.exists(out_dir):
362-
os.makedirs(out_dir)
363-
364-
_, _, ext = split_filename(self.inputs.mask)
365-
copyfile(self.inputs.mask,
366-
os.path.join(subjectdir,
367-
'nodif_brain_mask' + ext))
368-
_, _, ext = split_filename(self.inputs.dwi)
369-
copyfile(self.inputs.dwi,
370-
os.path.join(subjectdir, 'data' + ext))
371-
copyfile(self.inputs.bvals,
372-
os.path.join(subjectdir, 'bvals'))
373-
copyfile(self.inputs.bvecs,
374-
os.path.join(subjectdir, 'bvecs'))
375-
352+
self._out_dir = os.getcwd()
376353
runtime = super(FSLXCommand, self)._run_interface(runtime)
377354
if runtime.stderr:
378355
self.raise_exception(runtime)

nipype/interfaces/fsl/dti.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ def _list_outputs(self):
101101

102102

103103
class BEDPOSTXInputSpec(FSLXCommandInputSpec):
104+
out_dir = Directory('.', mandatory=True, desc='output directory',
105+
usedefault=True, position=1, argstr='%s')
104106
gradnonlin = traits.Bool(False, argstr='-g', desc=('consider gradient '
105107
'nonlinearities, default off'))
106108

@@ -137,6 +139,31 @@ class BEDPOSTX(FSLXCommand):
137139
output_spec = FSLXCommandOutputSpec
138140
_can_resume = True
139141

142+
def _run_interface(self, runtime):
143+
subjectdir = os.path.abspath(self.inputs.out_dir)
144+
out_dir = subjectdir + '.bedpostX'
145+
146+
if isdefined(self.inputs.force_dir) and self.inputs.force_dir:
147+
out_dir = os.path.abspath(self.inputs.out_dir)
148+
self._out_dir = out_dir
149+
150+
if not os.path.exists(out_dir):
151+
os.makedirs(out_dir)
152+
153+
_, _, ext = split_filename(self.inputs.mask)
154+
copyfile(self.inputs.mask,
155+
os.path.join(subjectdir,
156+
'nodif_brain_mask' + ext))
157+
_, _, ext = split_filename(self.inputs.dwi)
158+
copyfile(self.inputs.dwi,
159+
os.path.join(subjectdir, 'data' + ext))
160+
copyfile(self.inputs.bvals,
161+
os.path.join(subjectdir, 'bvals'))
162+
copyfile(self.inputs.bvecs,
163+
os.path.join(subjectdir, 'bvecs'))
164+
165+
return super(BEDPOSTX, self)._run_interface(runtime)
166+
140167

141168
class XFibresInputSpec(FSLXCommandInputSpec):
142169
gradnonlin = File(exists=True, argstr='--gradnonlin=%s',

nipype/interfaces/fsl/tests/test_auto_FSLXCommand.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,6 @@ def test_FSLXCommand_inputs():
6262
non_linear=dict(argstr='--nonlinear',
6363
xor=('no_spat', 'non_linear', 'cnlinear'),
6464
),
65-
out_dir=dict(argstr='%s',
66-
mandatory=True,
67-
position=1,
68-
usedefault=True,
69-
),
7065
output_type=dict(),
7166
rician=dict(argstr='--rician',
7267
),

nipype/interfaces/fsl/tests/test_auto_XFibres.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,6 @@ def test_XFibres_inputs():
6464
non_linear=dict(argstr='--nonlinear',
6565
xor=('no_spat', 'non_linear', 'cnlinear'),
6666
),
67-
out_dir=dict(argstr='%s',
68-
mandatory=True,
69-
position=1,
70-
usedefault=True,
71-
),
7267
output_type=dict(),
7368
rician=dict(argstr='--rician',
7469
),

nipype/workflows/dmri/fsl/dti.py

Lines changed: 45 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -1,189 +1,80 @@
11
# coding: utf-8
22

33
import nipype.pipeline.engine as pe
4-
import nipype.interfaces.utility as util
5-
import nipype.interfaces.fsl as fsl
4+
from nipype.interfaces import utility as niu
5+
from nipype.interfaces import fsl
66
import os
77

88
#backwards compatibility
99
from epi import create_eddy_correct_pipeline
1010

11+
1112
def transpose(samples_over_fibres):
1213
import numpy as np
1314
a = np.array(samples_over_fibres)
14-
if len(a.shape) == 1:
15-
a = a.reshape(-1, 1)
16-
return a.T.tolist()
15+
return np.squeeze(a.T).tolist()
16+
1717

18-
def create_bedpostx_pipeline(name="bedpostx"):
19-
"""Creates a pipeline that does the same as bedpostx script from FSL -
18+
def create_bedpostx_pipeline(name='bedpostx', params={}):
19+
"""
20+
Creates a pipeline that does the same as bedpostx script from FSL -
2021
calculates diffusion model parameters (distributions not MLE) voxelwise for
2122
the whole volume (by splitting it slicewise).
2223
2324
Example
2425
-------
2526
26-
>>> nipype_bedpostx = create_bedpostx_pipeline("nipype_bedpostx")
27-
>>> nipype_bedpostx.inputs.inputnode.dwi = 'diffusion.nii'
28-
>>> nipype_bedpostx.inputs.inputnode.mask = 'mask.nii'
29-
>>> nipype_bedpostx.inputs.inputnode.bvecs = 'bvecs'
30-
>>> nipype_bedpostx.inputs.inputnode.bvals = 'bvals'
31-
>>> nipype_bedpostx.inputs.xfibres.n_fibres = 2
32-
>>> nipype_bedpostx.inputs.xfibres.fudge = 1
33-
>>> nipype_bedpostx.inputs.xfibres.burn_in = 1000
34-
>>> nipype_bedpostx.inputs.xfibres.n_jumps = 1250
35-
>>> nipype_bedpostx.inputs.xfibres.sample_every = 25
36-
>>> nipype_bedpostx.run() # doctest: +SKIP
27+
>>> from nipype.workflows.dmri.fsl.dti import create_bedpostx_pipeline
28+
>>> params = dict(n_fibres = 2, fudge = 1, burn_in = 1000,
29+
... n_jumps = 1250, sample_every = 25)
30+
>>> bpwf = create_bedpostx_pipeline('nipype_bedpostx', params)
31+
>>> bpwf.inputs.inputnode.dwi = 'diffusion.nii'
32+
>>> bpwf.inputs.inputnode.mask = 'mask.nii'
33+
>>> bpwf.inputs.inputnode.bvecs = 'bvecs'
34+
>>> bpwf.inputs.inputnode.bvals = 'bvals'
35+
>>> bpwf.run() # doctest: +SKIP
3736
3837
Inputs::
3938
4039
inputnode.dwi
4140
inputnode.mask
41+
inputnode.bvecs
42+
inputnode.bvals
4243
4344
Outputs::
4445
45-
outputnode.thsamples
46-
outputnode.phsamples
47-
outputnode.fsamples
48-
outputnode.mean_thsamples
49-
outputnode.mean_phsamples
50-
outputnode.mean_fsamples
51-
outputnode.dyads
52-
outputnode.dyads_dispersion
46+
outputnode wraps all XFibres outputs
5347
5448
"""
5549

56-
inputnode = pe.Node(
57-
interface=util.IdentityInterface(fields=["dwi", "mask"]),
58-
name="inputnode")
50+
inputnode = pe.Node(niu.IdentityInterface(fields=['dwi', 'mask',
51+
'bvecs', 'bvals']), name='inputnode')
5952

60-
mask_dwi = pe.Node(interface=fsl.ImageMaths(op_string="-mas"),
61-
name="mask_dwi")
62-
slice_dwi = pe.Node(interface=fsl.Split(dimension="z"), name="slice_dwi")
63-
slice_mask = pe.Node(interface=fsl.Split(dimension="z"),
64-
name="slice_mask")
53+
slice_dwi = pe.Node(fsl.Split(dimension='z'), name='slice_dwi')
54+
slice_msk = pe.Node(fsl.Split(dimension='z'), name='slice_msk')
55+
mask_dwi = pe.MapNode(fsl.ImageMaths(op_string='-mas'),
56+
iterfield=['in_file', 'in_file2'], name='mask_dwi')
6557

66-
preproc = pe.Workflow(name="preproc")
67-
68-
preproc.connect([(inputnode, mask_dwi, [('dwi', 'in_file')]),
69-
(inputnode, mask_dwi, [('mask', 'in_file2')]),
70-
(mask_dwi, slice_dwi, [('out_file', 'in_file')]),
71-
(inputnode, slice_mask, [('mask', 'in_file')])
72-
])
73-
74-
xfibres = pe.MapNode(interface=fsl.OldXFibres(), name="xfibres",
58+
xfib_if = fsl.XFibres(**params)
59+
xfibres = pe.MapNode(xfib_if, name='xfibres',
7560
iterfield=['dwi', 'mask'])
7661

77-
# Normal set of parameters
78-
xfibres.inputs.n_fibres = 2
79-
xfibres.inputs.fudge = 1
80-
xfibres.inputs.burn_in = 1000
81-
xfibres.inputs.n_jumps = 1250
82-
xfibres.inputs.sample_every = 25
83-
xfibres.inputs.model = 1
84-
xfibres.inputs.non_linear = True
85-
xfibres.inputs.update_proposal_every = 24
86-
87-
inputnode = pe.Node(interface=util.IdentityInterface(fields=["thsamples",
88-
"phsamples",
89-
"fsamples",
90-
"dyads",
91-
"mean_dsamples",
92-
"mask"]),
93-
name="inputnode")
94-
95-
merge_thsamples = pe.MapNode(fsl.Merge(dimension="z"),
96-
name="merge_thsamples", iterfield=['in_files'])
97-
merge_phsamples = pe.MapNode(fsl.Merge(dimension="z"),
98-
name="merge_phsamples", iterfield=['in_files'])
99-
merge_fsamples = pe.MapNode(fsl.Merge(dimension="z"),
100-
name="merge_fsamples", iterfield=['in_files'])
101-
102-
merge_mean_dsamples = pe.Node(fsl.Merge(dimension="z"),
103-
name="merge_mean_dsamples")
104-
105-
mean_thsamples = pe.MapNode(fsl.ImageMaths(op_string="-Tmean"),
106-
name="mean_thsamples", iterfield=['in_file'])
107-
mean_phsamples = pe.MapNode(fsl.ImageMaths(op_string="-Tmean"),
108-
name="mean_phsamples", iterfield=['in_file'])
109-
mean_fsamples = pe.MapNode(fsl.ImageMaths(op_string="-Tmean"),
110-
name="mean_fsamples", iterfield=['in_file'])
111-
make_dyads = pe.MapNode(fsl.MakeDyadicVectors(), name="make_dyads",
112-
iterfield=['theta_vol', 'phi_vol'])
113-
114-
postproc = pe.Workflow(name="postproc")
115-
116-
postproc.connect(
117-
[(inputnode, merge_thsamples, [(('thsamples', transpose), 'in_files')]),
118-
(inputnode, merge_phsamples, [((
119-
'phsamples', transpose), 'in_files')]),
120-
(inputnode, merge_fsamples, [((
121-
'fsamples', transpose), 'in_files')]),
122-
(inputnode, merge_mean_dsamples, [
123-
('mean_dsamples', 'in_files')]),
124-
125-
(merge_thsamples, mean_thsamples, [
126-
('merged_file', 'in_file')]),
127-
(merge_phsamples, mean_phsamples, [
128-
('merged_file', 'in_file')]),
129-
(merge_fsamples, mean_fsamples, [
130-
('merged_file', 'in_file')]),
131-
(merge_thsamples, make_dyads, [
132-
('merged_file', 'theta_vol')]),
133-
(merge_phsamples, make_dyads, [
134-
('merged_file', 'phi_vol')]),
135-
(inputnode, make_dyads, [('mask', 'mask')]),
136-
])
137-
138-
inputnode = pe.Node(interface=util.IdentityInterface(fields=["dwi",
139-
"mask",
140-
"bvecs",
141-
"bvals"]),
142-
name="inputnode")
143-
144-
bedpostx = pe.Workflow(name=name)
145-
bedpostx.connect([(inputnode, preproc, [('mask', 'inputnode.mask')]),
146-
(inputnode, preproc, [('dwi', 'inputnode.dwi')]),
147-
148-
(preproc, xfibres, [('slice_dwi.out_files', 'dwi'),
149-
('slice_mask.out_files', 'mask')]),
150-
(inputnode, xfibres, [('bvals', 'bvals')]),
151-
(inputnode, xfibres, [('bvecs', 'bvecs')]),
152-
153-
(inputnode, postproc, [('mask', 'inputnode.mask')]),
154-
(xfibres, postproc, [
155-
('thsamples', 'inputnode.thsamples'),
156-
('phsamples',
157-
'inputnode.phsamples'),
158-
('fsamples', 'inputnode.fsamples'),
159-
('dyads', 'inputnode.dyads'),
160-
('mean_dsamples', 'inputnode.mean_dsamples')]),
62+
out_fields = xfib_if.output_spec().get().keys()
63+
64+
outputnode = pe.Node(niu.IdentityInterface(fields=out_fields),
65+
name='outputnode')
66+
67+
wf = pe.Workflow(name=name)
68+
wf.connect([
69+
(inputnode, slice_dwi, [('dwi', 'in_file')]),
70+
(inputnode, slice_msk, [('mask', 'in_file')]),
71+
(slice_dwi, mask_dwi, [('out_files', 'in_file')]),
72+
(slice_msk, mask_dwi, [('out_files', 'in_file2')]),
73+
(slice_dwi, xfibres, [('out_files', 'dwi')]),
74+
(mask_dwi, xfibres, [('out_file', 'mask')]),
75+
(inputnode, xfibres, [('bvecs', 'bvecs'),
76+
('bvals', 'bvals')]),
77+
(xfibres, outputnode, [((f, transpose), f) for f in out_fields])
16178
])
16279

163-
outputnode = pe.Node(
164-
interface=util.IdentityInterface(fields=["thsamples",
165-
"phsamples",
166-
"fsamples",
167-
"mean_thsamples",
168-
"mean_phsamples",
169-
"mean_fsamples",
170-
"dyads",
171-
"dyads_dispersion"]),
172-
name="outputnode")
173-
bedpostx.connect(
174-
[(postproc, outputnode, [("merge_thsamples.merged_file", "thsamples"),
175-
("merge_phsamples.merged_file",
176-
"phsamples"),
177-
("merge_fsamples.merged_file",
178-
"fsamples"),
179-
("mean_thsamples.out_file",
180-
"mean_thsamples"),
181-
("mean_phsamples.out_file",
182-
"mean_phsamples"),
183-
("mean_fsamples.out_file",
184-
"mean_fsamples"),
185-
("make_dyads.dyads", "dyads"),
186-
("make_dyads.dispersion", "dyads_dispersion")])
187-
])
188-
return bedpostx
189-
80+
return wf

0 commit comments

Comments
 (0)