Skip to content

Commit b8415b4

Browse files
committed
add new files for EPI preprocessing
1 parent bdb50ce commit b8415b4

File tree

9 files changed

+1782
-0
lines changed

9 files changed

+1782
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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+
from bias import remove_bias
6+
from eddy import ecc_fsl
7+
from susceptibility import sdc_fmb, sdc_peb
8+
from motion import hmc_flirt
9+
10+
from fsl import all_dmri
11+
from complete import all_fmb_pipeline, all_peb_pipeline
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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+
import os
5+
6+
import nipype.pipeline.engine as pe
7+
from nipype.interfaces.io import JSONFileGrabber
8+
from nipype.interfaces import utility as niu
9+
from nipype.interfaces import freesurfer as fs
10+
from nipype.interfaces import ants
11+
from nipype.interfaces import fsl
12+
from .utils import *
13+
14+
def remove_bias(name='bias_correct'):
15+
"""
16+
This workflow estimates a single multiplicative bias field from the
17+
averaged *b0* image, as suggested in [Jeurissen2014]_.
18+
19+
.. admonition:: References
20+
21+
.. [Jeurissen2014] Jeurissen B. et al., `Multi-tissue constrained
22+
spherical deconvolution for improved analysis of multi-shell diffusion
23+
MRI data <http://dx.doi.org/10.1016/j.neuroimage.2014.07.061>`_.
24+
NeuroImage (2014). doi: 10.1016/j.neuroimage.2014.07.061
25+
26+
27+
Example
28+
-------
29+
30+
>>> from nipype.workflows.dmri.fsl.artifacts import remove_bias
31+
>>> bias = remove_bias()
32+
>>> bias.inputs.inputnode.in_file = 'epi.nii'
33+
>>> bias.inputs.inputnode.in_bval = 'diffusion.bval'
34+
>>> bias.inputs.inputnode.in_mask = 'mask.nii'
35+
>>> bias.run() # doctest: +SKIP
36+
37+
"""
38+
inputnode = pe.Node(niu.IdentityInterface(
39+
fields=['in_file', 'in_bval', 'in_mask']), name='inputnode')
40+
41+
outputnode = pe.Node(niu.IdentityInterface(fields=['out_file']),
42+
name='outputnode')
43+
44+
avg_b0 = pe.Node(niu.Function(
45+
input_names=['in_dwi', 'in_bval'], output_names=['out_file'],
46+
function=b0_average), name='b0_avg')
47+
n4 = pe.Node(ants.N4BiasFieldCorrection(
48+
dimension=3, save_bias=True, bspline_fitting_distance=600),
49+
name='Bias_b0')
50+
split = pe.Node(fsl.Split(dimension='t'), name='SplitDWIs')
51+
mult = pe.MapNode(fsl.MultiImageMaths(op_string='-div %s'),
52+
iterfield=['in_file'], name='RemoveBiasOfDWIs')
53+
thres = pe.MapNode(fsl.Threshold(thresh=0.0), iterfield=['in_file'],
54+
name='RemoveNegative')
55+
merge = pe.Node(fsl.utils.Merge(dimension='t'), name='MergeDWIs')
56+
57+
wf = pe.Workflow(name=name)
58+
wf.connect([
59+
(inputnode, avg_b0, [('in_file', 'in_dwi'),
60+
('in_bval', 'in_bval')]),
61+
(avg_b0, n4, [('out_file', 'input_image')]),
62+
(inputnode, n4, [('in_mask', 'mask_image')]),
63+
(inputnode, split, [('in_file', 'in_file')]),
64+
(n4, mult, [('bias_image', 'operand_files')]),
65+
(split, mult, [('out_files', 'in_file')]),
66+
(mult, thres, [('out_file', 'in_file')]),
67+
(thres, merge, [('out_file', 'in_files')]),
68+
(merge, outputnode, [('merged_file', 'out_file')])
69+
])
70+
return wf
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
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+
import os
5+
6+
import nipype.pipeline.engine as pe
7+
from nipype.interfaces.io import JSONFileGrabber
8+
from nipype.interfaces import utility as niu
9+
from nipype.interfaces import freesurfer as fs
10+
from nipype.interfaces import ants
11+
from nipype.interfaces import fsl
12+
from .utils import *
13+
14+
def all_fmb_pipeline(name='hmc_sdc_ecc', fugue_params=dict(smooth3d=2.0)):
15+
"""
16+
Builds a pipeline including three artifact corrections: head-motion
17+
correction (HMC), susceptibility-derived distortion correction (SDC),
18+
and Eddy currents-derived distortion correction (ECC).
19+
20+
The displacement fields from each kind of distortions are combined. Thus,
21+
only one interpolation occurs between input data and result.
22+
23+
.. warning:: this workflow rotates the gradients table (*b*-vectors)
24+
[Leemans09]_.
25+
26+
27+
Examples
28+
--------
29+
30+
>>> from nipype.workflows.dmri.fsl.artifacts import all_fmb_pipeline
31+
>>> allcorr = all_fmb_pipeline()
32+
>>> allcorr.inputs.inputnode.in_file = 'epi.nii'
33+
>>> allcorr.inputs.inputnode.in_bval = 'diffusion.bval'
34+
>>> allcorr.inputs.inputnode.in_bvec = 'diffusion.bvec'
35+
>>> allcorr.inputs.inputnode.bmap_mag = 'magnitude.nii'
36+
>>> allcorr.inputs.inputnode.bmap_pha = 'phase.nii'
37+
>>> allcorr.inputs.inputnode.epi_param = 'epi_param.txt'
38+
>>> allcorr.run() # doctest: +SKIP
39+
40+
"""
41+
inputnode = pe.Node(niu.IdentityInterface(
42+
fields=['in_file', 'in_bvec', 'in_bval', 'bmap_pha', 'bmap_mag',
43+
'epi_param']), name='inputnode')
44+
45+
outputnode = pe.Node(niu.IdentityInterface(
46+
fields=['out_file', 'out_mask', 'out_bvec']), name='outputnode')
47+
48+
list_b0 = pe.Node(niu.Function(
49+
input_names=['in_bval'], output_names=['out_idx'],
50+
function=b0_indices), name='B0indices')
51+
52+
avg_b0_0 = pe.Node(niu.Function(
53+
input_names=['in_file', 'index'], output_names=['out_file'],
54+
function=time_avg), name='b0_avg_pre')
55+
avg_b0_1 = pe.Node(niu.Function(
56+
input_names=['in_file', 'index'], output_names=['out_file'],
57+
function=time_avg), name='b0_avg_post')
58+
59+
bet_dwi0 = pe.Node(fsl.BET(frac=0.3, mask=True, robust=True),
60+
name='bet_dwi_pre')
61+
bet_dwi1 = pe.Node(fsl.BET(frac=0.3, mask=True, robust=True),
62+
name='bet_dwi_post')
63+
64+
hmc = hmc_pipeline()
65+
sdc = sdc_fmb(fugue_params=fugue_params)
66+
ecc = ecc_pipeline()
67+
unwarp = apply_all_corrections()
68+
69+
wf = pe.Workflow(name=name)
70+
wf.connect([
71+
(inputnode, hmc, [('in_file', 'inputnode.in_file'),
72+
('in_bvec', 'inputnode.in_bvec'),
73+
('in_bval', 'inputnode.in_bval')]),
74+
(inputnode, list_b0, [('in_bval', 'in_bval')]),
75+
(inputnode, avg_b0_0, [('in_file', 'in_file')]),
76+
(list_b0, avg_b0_0, [('out_idx', 'index')]),
77+
(avg_b0_0, bet_dwi0, [('out_file', 'in_file')]),
78+
(bet_dwi0, hmc, [('mask_file', 'inputnode.in_mask')]),
79+
(hmc, sdc, [
80+
('outputnode.out_file', 'inputnode.in_file')]),
81+
(bet_dwi0, sdc, [('mask_file', 'inputnode.in_mask')]),
82+
(inputnode, sdc, [('bmap_pha', 'inputnode.bmap_pha'),
83+
('bmap_mag', 'inputnode.bmap_mag'),
84+
('epi_param', 'inputnode.settings')]),
85+
(list_b0, sdc, [('out_idx', 'inputnode.in_ref')]),
86+
(hmc, ecc, [
87+
('outputnode.out_xfms', 'inputnode.in_xfms')]),
88+
(inputnode, ecc, [('in_file', 'inputnode.in_file'),
89+
('in_bval', 'inputnode.in_bval')]),
90+
(bet_dwi0, ecc, [('mask_file', 'inputnode.in_mask')]),
91+
(ecc, avg_b0_1, [('outputnode.out_file', 'in_file')]),
92+
(list_b0, avg_b0_1, [('out_idx', 'index')]),
93+
(avg_b0_1, bet_dwi1, [('out_file', 'in_file')]),
94+
(inputnode, unwarp, [('in_file', 'inputnode.in_dwi')]),
95+
(hmc, unwarp, [('outputnode.out_xfms', 'inputnode.in_hmc')]),
96+
(ecc, unwarp, [('outputnode.out_xfms', 'inputnode.in_ecc')]),
97+
(sdc, unwarp, [('outputnode.out_warp', 'inputnode.in_sdc')]),
98+
(hmc, outputnode, [('outputnode.out_bvec', 'out_bvec')]),
99+
(unwarp, outputnode, [('outputnode.out_file', 'out_file')]),
100+
(bet_dwi1, outputnode, [('mask_file', 'out_mask')])
101+
])
102+
return wf
103+
104+
105+
def all_peb_pipeline(name='hmc_sdc_ecc',
106+
epi_params=dict(echospacing=0.77e-3,
107+
acc_factor=3,
108+
enc_dir='y-',
109+
epi_factor=1),
110+
altepi_params=dict(echospacing=0.77e-3,
111+
acc_factor=3,
112+
enc_dir='y',
113+
epi_factor=1)):
114+
"""
115+
Builds a pipeline including three artifact corrections: head-motion
116+
correction (HMC), susceptibility-derived distortion correction (SDC),
117+
and Eddy currents-derived distortion correction (ECC).
118+
119+
.. warning:: this workflow rotates the gradients table (*b*-vectors)
120+
[Leemans09]_.
121+
122+
123+
Examples
124+
--------
125+
126+
>>> from nipype.workflows.dmri.fsl.artifacts import all_peb_pipeline
127+
>>> allcorr = all_peb_pipeline()
128+
>>> allcorr.inputs.inputnode.in_file = 'epi.nii'
129+
>>> allcorr.inputs.inputnode.alt_file = 'epi_rev.nii'
130+
>>> allcorr.inputs.inputnode.in_bval = 'diffusion.bval'
131+
>>> allcorr.inputs.inputnode.in_bvec = 'diffusion.bvec'
132+
>>> allcorr.run() # doctest: +SKIP
133+
134+
"""
135+
inputnode = pe.Node(niu.IdentityInterface(
136+
fields=['in_file', 'in_bvec', 'in_bval', 'alt_file']),
137+
name='inputnode')
138+
139+
outputnode = pe.Node(niu.IdentityInterface(
140+
fields=['out_file', 'out_mask', 'out_bvec']), name='outputnode')
141+
142+
avg_b0_0 = pe.Node(niu.Function(
143+
input_names=['in_dwi', 'in_bval'], output_names=['out_file'],
144+
function=b0_average), name='b0_avg_pre')
145+
avg_b0_1 = pe.Node(niu.Function(
146+
input_names=['in_dwi', 'in_bval'], output_names=['out_file'],
147+
function=b0_average), name='b0_avg_post')
148+
bet_dwi0 = pe.Node(fsl.BET(frac=0.3, mask=True, robust=True),
149+
name='bet_dwi_pre')
150+
bet_dwi1 = pe.Node(fsl.BET(frac=0.3, mask=True, robust=True),
151+
name='bet_dwi_post')
152+
153+
hmc = hmc_pipeline()
154+
sdc = sdc_peb(epi_params=epi_params, altepi_params=altepi_params)
155+
ecc = ecc_pipeline()
156+
157+
unwarp = apply_all_corrections()
158+
159+
wf = pe.Workflow(name=name)
160+
wf.connect([
161+
(inputnode, hmc, [('in_file', 'inputnode.in_file'),
162+
('in_bvec', 'inputnode.in_bvec'),
163+
('in_bval', 'inputnode.in_bval')]),
164+
(inputnode, avg_b0_0, [('in_file', 'in_dwi'),
165+
('in_bval', 'in_bval')]),
166+
(avg_b0_0, bet_dwi0, [('out_file', 'in_file')]),
167+
(bet_dwi0, hmc, [('mask_file', 'inputnode.in_mask')]),
168+
(hmc, sdc, [
169+
('outputnode.out_file', 'inputnode.in_file')]),
170+
(bet_dwi0, sdc, [('mask_file', 'inputnode.in_mask')]),
171+
(inputnode, sdc, [('in_bval', 'inputnode.in_bval'),
172+
('alt_file', 'inputnode.alt_file')]),
173+
(inputnode, ecc, [('in_file', 'inputnode.in_file'),
174+
('in_bval', 'inputnode.in_bval')]),
175+
(bet_dwi0, ecc, [('mask_file', 'inputnode.in_mask')]),
176+
(hmc, ecc, [
177+
('outputnode.out_xfms', 'inputnode.in_xfms')]),
178+
(ecc, avg_b0_1, [('outputnode.out_file', 'in_dwi')]),
179+
(inputnode, avg_b0_1, [('in_bval', 'in_bval')]),
180+
(avg_b0_1, bet_dwi1, [('out_file', 'in_file')]),
181+
(inputnode, unwarp, [('in_file', 'inputnode.in_dwi')]),
182+
(hmc, unwarp, [('outputnode.out_xfms', 'inputnode.in_hmc')]),
183+
(ecc, unwarp, [('outputnode.out_xfms', 'inputnode.in_ecc')]),
184+
(sdc, unwarp, [('outputnode.out_warp', 'inputnode.in_sdc')]),
185+
(hmc, outputnode, [('outputnode.out_bvec', 'out_bvec')]),
186+
(unwarp, outputnode, [('outputnode.out_file', 'out_file')]),
187+
(bet_dwi1, outputnode, [('mask_file', 'out_mask')])
188+
])
189+
return wf

0 commit comments

Comments
 (0)