Skip to content

Commit 654f35e

Browse files
committed
- add nthreads option
- update workflow docstrings - move resizing back to artifact workflow - update eddy workflow
1 parent cdfed73 commit 654f35e

File tree

8 files changed

+155
-127
lines changed

8 files changed

+155
-127
lines changed

dmriprep/cli.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,18 @@
6262
multiple=True
6363
)
6464
# specific options for eddy
65+
@click.option(
66+
'--nthreads',
67+
default=1,
68+
show_default=True,
69+
help='Maximum number of threads across all processes',
70+
type=int,
71+
)
6572
@click.option(
6673
'--omp_nthreads',
6774
default=1,
6875
show_default=True,
69-
help='Maximum number of threads for eddy',
76+
help='Maximum number of threads per process',
7077
type=int,
7178
)
7279
@click.option(
@@ -136,6 +143,7 @@ def main(
136143
output_resolution,
137144
bet_dwi,
138145
bet_mag,
146+
nthreads,
139147
omp_nthreads,
140148
eddy_niter,
141149
synb0_dir,

dmriprep/workflows/base.py

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def init_dmriprep_wf(
3131
synb0_dir
3232
):
3333
"""
34-
This workflow organizes the execusion of dMRIPrep, with a sub-workflow for
34+
This workflow organizes the execusion of dMRIprep, with a sub-workflow for
3535
each subject.
3636
3737
.. workflow::
@@ -41,7 +41,19 @@ def init_dmriprep_wf(
4141
from collections import namedtuple
4242
from dmriprep.workflows.base import init_dmriprep_wf
4343
BIDSLayout = namedtuple('BIDSLayout', ['root'])
44-
wf = init_dmriprep_wf(subject_list=['dmripreptest'], layout=BIDSLayout('.'), output_dir='.', work_dir='.', ignore=[], b0_thresh=5, output_resolution=(1, 1, 1), bet_dwi=0.3, bet_mag=0.3, omp_nthreads=1, synb0_dir='')
44+
wf = init_dmriprep_wf(
45+
subject_list=['dmripreptest'],
46+
layout=BIDSLayout('.'),
47+
output_dir='.',
48+
work_dir='.',
49+
ignore=[],
50+
b0_thresh=5,
51+
output_resolution=(1, 1, 1),
52+
bet_dwi=0.3,
53+
bet_mag=0.3,
54+
omp_nthreads=1,
55+
synb0_dir=''
56+
)
4557
4658
Parameters
4759
@@ -137,7 +149,20 @@ def init_single_subject_wf(
137149
from collections import namedtuple
138150
from dmriprep.workflows.base import init_single_subject_wf
139151
BIDSLayout = namedtuple('BIDSLayout', ['root'])
140-
wf = init_single_subject_wf(subject_id='test', name='single_subject_wf', layout=BIDSLayout, output_dir='.', work_dir='.', ignore=[], b0_thresh=5, output_resolution=(1, 1, 1), bet_dwi=0.3, bet_mag=0.3, omp_nthreads=1, synb0_dir='')
152+
wf = init_single_subject_wf(
153+
subject_id='test',
154+
name='single_subject_wf',
155+
layout=BIDSLayout,
156+
output_dir='.',
157+
work_dir='.',
158+
ignore=[],
159+
b0_thresh=5,
160+
output_resolution=(1, 1, 1),
161+
bet_dwi=0.3,
162+
bet_mag=0.3,
163+
omp_nthreads=1,
164+
synb0_dir=''
165+
)
141166
142167
Parameters
143168
@@ -167,14 +192,19 @@ def init_single_subject_wf(
167192
Direction in which synb0 derivatives are saved
168193
169194
"""
170-
171-
dwi_files = layout.get(
172-
subject=subject_id,
173-
datatype='dwi',
174-
suffix='dwi',
175-
extensions=['.nii', '.nii.gz'],
176-
return_type='filename'
177-
)
195+
# for documentation purposes
196+
if name in ('single_subject_wf', 'single_subject_dmripreptest_wf'):
197+
dwi_files = ['/madeup/path/sub-01_dwi.nii.gz']
198+
else:
199+
sessions = layout.get_sessions(subject=subject_id)
200+
201+
dwi_files = layout.get(
202+
subject=subject_id,
203+
datatype='dwi',
204+
suffix='dwi',
205+
extensions=['.nii', '.nii.gz'],
206+
return_type='filename'
207+
)
178208

179209
if not dwi_files:
180210
raise Exception(
@@ -184,7 +214,7 @@ def init_single_subject_wf(
184214

185215
subject_wf = pe.Workflow(name=name)
186216

187-
dwi_files = group_dwis(dwi_files, concat_dwis)
217+
dwi_files = group_dwis(dwi_files, sessions, concat_dwis)
188218

189219
for dwi_file in dwi_files:
190220
entities = layout.parse_file_entities(dwi_file)
@@ -268,7 +298,7 @@ def init_single_subject_wf(
268298
return subject_wf
269299

270300

271-
def group_dwis(dwi_files, concat_dwis):
301+
def group_dwis(dwi_files, sessions, concat_dwis):
272302

273303
all_dwis = []
274304

dmriprep/workflows/dwi/__init__.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
88
.. automodule:: dmriprep.workflows.dwi.base
99
.. automodule:: dmriprep.workflows.dwi.artifacts
10-
.. automodule:: dmriprep.workflows.dwi.util
1110
.. automodule:: dmriprep.workflows.dwi.eddy
1211
.. automodule:: dmriprep.workflows.dwi.tensor
1312
.. automodule:: dmriprep.workflows.dwi.outputs
@@ -16,15 +15,13 @@
1615

1716
from .base import init_dwi_preproc_wf
1817
from .artifacts import init_dwi_artifacts_wf
19-
from .util import init_dwi_resize_wf
2018
from .eddy import init_dwi_eddy_wf
2119
from .tensor import init_dwi_tensor_wf
2220
from .outputs import init_dwi_derivatives_wf
2321

2422
__all__ = [
2523
'init_dwi_preproc_wf',
2624
'init_dwi_artifacts_wf',
27-
'init_dwi_resize_wf',
2825
'init_dwi_eddy_wf',
2926
'init_dwi_tensor_wf',
3027
'init_dwi_derivatives_wf'

dmriprep/workflows/dwi/artifacts.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# -*- coding: utf-8 -*-
22

33
"""
4-
Artefact removal
5-
^^^^^^^^^^^^^^^^
4+
Artefact removal and resizing
5+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
77
.. autofunction:: init_dwi_artifacts_wf
88
@@ -12,7 +12,7 @@
1212
from nipype.interfaces import mrtrix3, utility as niu
1313

1414

15-
def init_dwi_artifacts_wf(ignore):
15+
def init_dwi_artifacts_wf(ignore, output_resolution):
1616
"""
1717
This workflow performs denoising and unringing on the input dwi image.
1818
@@ -25,7 +25,7 @@ def init_dwi_artifacts_wf(ignore):
2525
:simple_form: yes
2626
2727
from dmriprep.workflows.dwi import init_dwi_artifacts_wf
28-
wf = init_dwi_artifacts_wf(ignore=[])
28+
wf = init_dwi_artifacts_wf(ignore=[], output_resolution=(1, 1, 1))
2929
3030
**Parameters**
3131
@@ -50,10 +50,14 @@ def init_dwi_artifacts_wf(ignore):
5050

5151
outputnode = pe.Node(niu.IdentityInterface(fields=['out_file']), name='outputnode')
5252

53+
dwibuffer = pe.Node(niu.IdentityInterface(fields=['dwi_file']), name='dwibuffer')
54+
5355
denoise = pe.Node(mrtrix3.DWIDenoise(), name='denoise')
5456

5557
unring = pe.Node(mrtrix3.MRDeGibbs(), name='unring')
5658

59+
resize = pe.Node(mrtrix3.MRResize(voxel_size=output_resolution), name='resize')
60+
5761
if ignore == ['denoise']:
5862
wf.connect([
5963
(inputnode, unring, [('dwi_file', 'in_file')]),

dmriprep/workflows/dwi/base.py

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from numba import cuda
1515

1616
from .artifacts import init_dwi_artifacts_wf
17-
from .util import init_dwi_resize_wf
1817
from .tensor import init_dwi_tensor_wf
1918

2019
from ..fieldmap.base import init_sdc_prep_wf
@@ -46,8 +45,8 @@ def init_dwi_preproc_wf(
4645
from dmriprep.workflows.dwi import init_dwi_preproc_wf
4746
BIDSLayout = namedtuple('BIDSLayout', ['root'])
4847
wf = init_dwi_preproc_wf(
49-
subjectid=,
50-
dwi_file=,
48+
subjectid='dmripreptest',
49+
dwi_file='/madeup/path/sub-01_dwi.nii.gz',
5150
metadata=,
5251
layout=BIDSLayout('.'),
5352
ignore=[],
@@ -56,7 +55,7 @@ def init_dwi_preproc_wf(
5655
bet_dwi=0.3,
5756
bet_mag=0.3,
5857
omp_nthreads=1,
59-
synb0_dir='.'
58+
synb0_dir=''
6059
)
6160
6261
"""
@@ -140,26 +139,13 @@ def init_dwi_preproc_wf(
140139

141140
dwi_artifacts_wf = init_dwi_artifacts_wf(ignore)
142141

143-
if output_resolution:
144-
dwi_resize_wf = init_dwi_resize_wf(output_resolution)
145-
146-
dwi_wf.connect(
147-
[
148-
(inputnode, dwi_artifacts_wf, [("dwi_file", "inputnode.dwi_file")]),
149-
(dwi_artifacts_wf, dwi_resize_wf, [("outputnode.out_file", "inputnode.in_file")]),
150-
(dwi_resize_wf, avg_b0_0, [("outputnode.out_file", "in_dwi")]),
151-
(dwi_resize_wf, ecc, [("outputnode.out_file", "in_file")])
152-
]
153-
)
154-
155-
else:
156-
dwi_wf.connect(
157-
[
158-
(inputnode, dwi_artifacts_wf, [("dwi_file", "inputnode.dwi_file")]),
159-
(dwi_artifacts_wf, avg_b0_0, [("outputnode.out_file", "in_dwi")]),
160-
(dwi_artifacts_wf, ecc, [("outputnode.out_file", "in_file")])
161-
]
162-
)
142+
dwi_wf.connect(
143+
[
144+
(inputnode, dwi_artifacts_wf, [("dwi_file", "inputnode.dwi_file")]),
145+
(dwi_artifacts_wf, avg_b0_0, [("outputnode.out_file", "in_dwi")]),
146+
(dwi_artifacts_wf, ecc, [("outputnode.out_file", "in_file")])
147+
]
148+
)
163149

164150
def gen_index(in_file):
165151
"""

dmriprep/workflows/dwi/eddy.py

Lines changed: 79 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,46 +13,99 @@
1313
from numba import cuda
1414

1515

16-
def init_dwi_eddy_wf(omp_nthreads):
16+
def init_dwi_eddy_wf(omp_nthreads, fmap_type):
17+
"""
18+
This workflow runs eddy on the input dwi image.
1719
18-
wf = pe.Workflow(name="dwi_eddy_wf")
20+
.. workflow::
21+
:graph2use: orig
22+
:simple_form: yes
1923
20-
inputnode = pe.Node(niu.IdentityInterface(fields=["dwi_file",
21-
"bvec_file",
22-
"bval_file",
23-
"mask_file",
24-
"acqp",
25-
"index"]),
26-
name="inputnode")
24+
from dmriprep.workflows.dwi import init_dwi_eddy_wf
25+
wf = init_dwi_eddy_wf(omp_nthreads=1)
2726
28-
outputnode = pe.Node(niu.IdentityInterface(fields=["out_file", "out_bvec"]),
29-
name="outputnode")
27+
**Parameters**
28+
29+
omp_nthreads: int
30+
Number of threads to run eddy
31+
32+
**Inputs**
33+
34+
dwi_file
35+
dwi NIfTI file
36+
bvec_file
37+
bvec file
38+
bval_file
39+
bval file
40+
mask_file
41+
brain mask file
42+
fieldmap_file
43+
fieldmap file
44+
topup_fieldcoef
45+
topup file containing field coefficients
46+
topup_movpar
47+
topup movpar.txt file
48+
acqp
49+
acquisition parameters file
50+
index
51+
index file
52+
53+
**Outputs**
54+
55+
out_file
56+
output eddy-corrected dwi image
57+
out_bvec
58+
output rotated bvecs after eddy correction
59+
60+
"""
61+
62+
wf = pe.Workflow(name='dwi_eddy_wf')
63+
64+
inputnode = pe.Node(niu.IdentityInterface(fields=['dwi_file',
65+
'bvec_file',
66+
'bval_file',
67+
'mask_file',
68+
'fieldmap_file',
69+
'topup_fieldcoef',
70+
'topup_movpar',
71+
'acqp',
72+
'index']),
73+
name='inputnode')
74+
75+
outputnode = pe.Node(niu.IdentityInterface(fields=['out_file', 'out_bvec']),
76+
name='outputnode')
3077

3178
ecc = pe.Node(
32-
fsl.Eddy(num_threads=1, repol=True, cnr_maps=True, residuals=True),
33-
name="fsl_eddy",
79+
fsl.Eddy(num_threads=omp_nthreads, repol=True, cnr_maps=True, residuals=True),
80+
name='fsl_eddy',
3481
)
3582

36-
if omp_nthreads:
37-
ecc.inputs.num_threads = omp_nthreads
38-
39-
# this doesn't work well
40-
# recognizes that a computer is cuda capable but failed if cuda isn't loaded
4183
try:
4284
if cuda.gpus:
4385
ecc.inputs.use_cuda = True
4486
except:
4587
ecc.inputs.use_cuda = False
4688

4789
wf.connect([
48-
(inputnode, ecc, [("dwi_file", "in_file"),
49-
("bval_file", "in_bval"),
50-
("bvec_file", "in_bvec"),
51-
("acqp", "in_acqp"),
52-
("index", "in_index"),
53-
("mask_file", "in_mask")]),
54-
(ecc, outputnode, [("out_corrected", "out_file"),
55-
("out_rotated_bvecs", "out_bvec")])
90+
(inputnode, ecc, [('dwi_file', 'in_file'),
91+
('bval_file', 'in_bval'),
92+
('bvec_file', 'in_bvec'),
93+
('acqp', 'in_acqp'),
94+
('index', 'in_index'),
95+
('mask_file', 'in_mask')]),
96+
(ecc, outputnode, [('out_corrected', 'out_file'),
97+
('out_rotated_bvecs', 'out_bvec')])
98+
])
99+
100+
if fmap_type == 'fieldmap':
101+
wf.connect([
102+
(inputnode, ecc, [('fieldmap_file', 'field')])
103+
])
104+
105+
if fmap_type == 'topup':
106+
wf.connect([
107+
(inputnode, ecc, [('topup_fieldcoef', 'in_topup_fieldcoef'),
108+
('topup_movpar', 'in_topup_movpar')])
56109
])
57110

58111
return wf

0 commit comments

Comments
 (0)