Skip to content

Commit 3a54270

Browse files
committed
add ants and brainsuite cli options and move eddy to separate workflow
1 parent 24e20a6 commit 3a54270

File tree

5 files changed

+149
-94
lines changed

5 files changed

+149
-94
lines changed

dmriprep/cli.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,20 @@
128128
type=click.Choice(['denoising', 'unringing', 'fieldmaps']),
129129
multiple=True
130130
)
131+
@click.option(
132+
'--use_ants',
133+
is_flag=True,
134+
default=False,
135+
help='Use ANTs SDC',
136+
type=bool
137+
)
138+
@click.option(
139+
'--use_brainsuite',
140+
is_flag=True,
141+
default=False,
142+
help='Use BrainSuite SDC',
143+
type=bool
144+
)
131145
@click.option(
132146
'--work_dir',
133147
'-w',
@@ -163,6 +177,8 @@ def main(
163177
nthreads,
164178
omp_nthreads,
165179
ignore,
180+
use_ants,
181+
use_syn,
166182
work_dir,
167183
synb0_dir,
168184
write_graph
@@ -247,6 +263,8 @@ def main(
247263
acqp_file=acqp_file,
248264
omp_nthreads=omp_nthreads,
249265
ignore=list(ignore),
266+
use_ants=use_ants,
267+
use_brainsuite=use_brainsuite,
250268
work_dir=work_dir,
251269
synb0_dir=synb0_dir
252270
)

dmriprep/workflows/base.py

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ def init_dmriprep_wf(
3131
acqp_file,
3232
omp_nthreads,
3333
ignore,
34+
use_ants,
35+
use_brainsuite,
3436
work_dir,
3537
synb0_dir
3638
):
@@ -58,6 +60,8 @@ def init_dmriprep_wf(
5860
acqp_file='',
5961
omp_nthreads=1,
6062
ignore=[],
63+
use_ants=False,
64+
use_brainsuite=False,
6165
work_dir='.',
6266
synb0_dir=''
6367
)
@@ -114,6 +118,8 @@ def init_dmriprep_wf(
114118
acqp_file=acqp_file,
115119
omp_nthreads=omp_nthreads,
116120
ignore=ignore,
121+
use_ants=use_ants,
122+
use_brainsuite=use_brainsuite,
117123
work_dir=work_dir,
118124
synb0_dir=synb0_dir
119125
)
@@ -144,6 +150,8 @@ def init_single_subject_wf(
144150
omp_nthreads,
145151
acqp_file,
146152
ignore,
153+
use_ants,
154+
use_brainsuite,
147155
work_dir,
148156
synb0_dir
149157
):
@@ -176,6 +184,8 @@ def init_single_subject_wf(
176184
acqp_file='',
177185
omp_nthreads=1,
178186
ignore=[],
187+
use_ants=False,
188+
use_brainsuite=False,
179189
work_dir='.',
180190
synb0_dir=''
181191
)
@@ -263,6 +273,8 @@ def init_single_subject_wf(
263273
omp_nthreads=omp_nthreads,
264274
acqp_file=acqp_file,
265275
ignore=ignore,
276+
use_ants=use_ants,
277+
use_brainsuite=use_brainsuite,
266278
synb0_dir=synb0_dir
267279
)
268280

@@ -276,9 +288,10 @@ def init_single_subject_wf(
276288
inputspec.inputs.out_dir = os.path.abspath(output_dir)
277289

278290
subject_wf.connect([
279-
(dwi_concat_wf, dwi_preproc_wf, [('outputnode.dwi_file', 'inputnode.dwi_file'),
280-
('outputnode.bvec_file', 'inputnode.bvec_file'),
281-
('outputnode.bval_file', 'inputnode.bval_file')])
291+
(dwi_concat_wf, dwi_preproc_wf,
292+
[('outputnode.dwi_file', 'inputnode.dwi_file'),
293+
('outputnode.bvec_file', 'inputnode.bvec_file'),
294+
('outputnode.bval_file', 'inputnode.bval_file')])
282295
])
283296

284297
else:
@@ -299,6 +312,8 @@ def init_single_subject_wf(
299312
omp_nthreads=omp_nthreads,
300313
acqp_file=acqp_file,
301314
ignore=ignore,
315+
use_ants=use_ants,
316+
use_brainsuite=use_brainsuite,
302317
synb0_dir=synb0_dir
303318
)
304319

@@ -332,37 +347,22 @@ def init_single_subject_wf(
332347
ds_inputspec.inputs.output_folder = output_dir
333348
ds_inputspec.inputs.metadata = metadata
334349

335-
if session_id:
336-
wf_name = 'sub_' + subject_id + '_ses_' + session_id + '_preproc_wf'
337-
else:
338-
wf_name = 'sub_' + subject_id + '_preproc_wf'
339-
full_wf = pe.Workflow(name=wf_name)
340-
341-
full_wf.connect(
342-
[
343-
(
344-
dwi_preproc_wf,
345-
datasink_wf,
346-
[
347-
('outputnode.out_dwi', 'inputnode.dwi'),
348-
('outputnode.out_bval', 'inputnode.bval'),
349-
('outputnode.out_bvec', 'inputnode.bvec'),
350-
('outputnode.index', 'inputnode.index'),
351-
('outputnode.acq_params', 'inputnode.acq_params'),
352-
('outputnode.out_mask', 'inputnode.mask'),
353-
('outputnode.out_b0_pre', 'inputnode.b0'),
354-
('outputnode.out_b0_mask_pre', 'inputnode.b0_mask'),
355-
('outputnode.out_eddy_quad_json', 'inputnode.eddy_quad_json'),
356-
('outputnode.out_eddy_quad_pdf', 'inputnode.eddy_quad_pdf'),
357-
('outputnode.out_dtifit_FA', 'inputnode.dtifit_FA'),
358-
('outputnode.out_dtifit_V1', 'inputnode.dtifit_V1'),
359-
('outputnode.out_dtifit_sse', 'inputnode.dtifit_sse'),
360-
('outputnode.out_noise', 'inputnode.noise')
361-
]
362-
)
363-
]
364-
)
365-
366-
subject_wf.add_nodes([full_wf])
350+
subject_wf.connect([
351+
(dwi_preproc_wf, datasink_wf,
352+
[('outputnode.out_dwi', 'inputnode.dwi'),
353+
('outputnode.out_bval', 'inputnode.bval'),
354+
('outputnode.out_bvec', 'inputnode.bvec'),
355+
('outputnode.index', 'inputnode.index'),
356+
('outputnode.acq_params', 'inputnode.acq_params'),
357+
('outputnode.out_mask', 'inputnode.mask'),
358+
('outputnode.out_b0_pre', 'inputnode.b0'),
359+
('outputnode.out_b0_mask_pre', 'inputnode.b0_mask'),
360+
('outputnode.out_eddy_quad_json', 'inputnode.eddy_quad_json'),
361+
('outputnode.out_eddy_quad_pdf', 'inputnode.eddy_quad_pdf'),
362+
('outputnode.out_dtifit_FA', 'inputnode.dtifit_FA'),
363+
('outputnode.out_dtifit_V1', 'inputnode.dtifit_V1'),
364+
('outputnode.out_dtifit_sse', 'inputnode.dtifit_sse'),
365+
('outputnode.out_noise', 'inputnode.noise')])
366+
])
367367

368368
return subject_wf

dmriprep/workflows/dwi/base.py

Lines changed: 88 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010

1111
from nipype.pipeline import engine as pe
1212
from nipype.interfaces import fsl, mrtrix3, utility as niu
13-
from numba import cuda
1413

1514
from .artifacts import init_dwi_artifacts_wf
15+
from .eddy import init_dwi_eddy_wf
1616
from .tensor import init_dwi_tensor_wf
17-
from ..fieldmap.base import init_sdc_prep_wf
17+
from ..fieldmap.base import init_sdc_wf
1818

1919
FMAP_PRIORITY = {'epi': 0, 'fieldmap': 1, 'phasediff': 2, 'phase': 3, 'syn': 4}
2020

@@ -32,6 +32,8 @@ def init_dwi_preproc_wf(
3232
acqp_file,
3333
omp_nthreads,
3434
ignore,
35+
use_ants,
36+
use_brainsuite,
3537
synb0_dir
3638
):
3739
"""
@@ -50,6 +52,37 @@ def init_dwi_preproc_wf(
5052

5153
wf_name = _get_wf_name(dwi_file)
5254

55+
if isinstance(dwi_file, list):
56+
ref_file = dwi_file[0]
57+
else:
58+
ref_file = dwi_file
59+
60+
# For doc building purposes
61+
if not hasattr(layout, 'parse_file_entities'):
62+
metadata = {
63+
'PhaseEncodingDirection': 'j-',
64+
'TotalReadoutTime': 0.05
65+
}
66+
fmaps = [{
67+
'suffix': 'phasediff',
68+
'phasediff': 'sub-01/fmap/sub-01_phasediff.nii.gz',
69+
'magnitude1': 'sub-01/fmap/sub-01_magnitude1.nii.gz',
70+
'magnitude2': 'sub-01/fmap/sub-01_magnitude2.nii.gz'
71+
}]
72+
else:
73+
metadata = layout.get_metadata(ref_file)
74+
# Find fieldmaps. Options: (epi|fieldmap|phasediff|phase1|phase2|syn)
75+
fmaps = []
76+
if 'fieldmaps' not in ignore:
77+
for fmap in layout.get_fieldmap(ref_file, return_list=True):
78+
fmap['metadata'] = layout.get_metadata(fmap[fmap['suffix']])
79+
fmaps.append(fmap)
80+
81+
if (use_ants and not fmaps):
82+
fmaps.append({'suffix': 'ants'})
83+
if (use_brainsuite and not fmaps):
84+
fmaps.append({'suffix': 'brainsuite'})
85+
5386
dwi_wf = pe.Workflow(name=wf_name)
5487

5588
# # If use_synb0 set, get synb0 from files
@@ -69,7 +102,7 @@ def init_dwi_preproc_wf(
69102
)
70103
fmaps.append(fmap)
71104

72-
sdc_wf = init_sdc_prep_wf(
105+
dwi_sdc_wf = init_sdc_wf(
73106
subject_id,
74107
fmaps,
75108
metadata,
@@ -246,14 +279,16 @@ def b0_average(in_dwi, in_bval, b0_thresh, out_file=None):
246279
fsl.BET(frac=bet_dwi, mask=True, robust=True), name='bet_dwi_pre'
247280
)
248281

249-
ecc = pe.Node(
250-
fsl.Eddy(num_threads=omp_nthreads, repol=True, cnr_maps=True, residuals=True),
251-
name='fsl_eddy')
252-
try:
253-
if cuda.gpus:
254-
ecc.inputs.use_cuda = True
255-
except:
256-
ecc.inputs.use_cuda = False
282+
dwi_eddy_wf = init_dwi_eddy_wf()
283+
284+
# ecc = pe.Node(
285+
# fsl.Eddy(num_threads=omp_nthreads, repol=True, cnr_maps=True, residuals=True),
286+
# name='fsl_eddy')
287+
# try:
288+
# if cuda.gpus:
289+
# ecc.inputs.use_cuda = True
290+
# except:
291+
# ecc.inputs.use_cuda = False
257292

258293
denoise_eddy = pe.Node(mrtrix3.DWIDenoise(), name='denoise_eddy')
259294

@@ -286,44 +321,45 @@ def get_b0_mask_fn(b0_file):
286321
input_names=['b0_file'], output_names=['mask_file'], function=get_b0_mask_fn),
287322
name='getB0Mask')
288323

289-
tensor_wf = init_dwi_tensor_wf()
324+
dwi_tensor_wf = init_dwi_tensor_wf()
290325

291326
dwi_wf.connect([
292327
(inputnode, gen_idx, [('dwi_file', 'in_file')]),
293328
(inputnode, acqp, [('dwi_file', 'in_file'), ('dwi_meta', 'metadata')]),
294329
(inputnode, dwi_artifacts_wf, [('dwi_file', 'inputnode.dwi_file')]),
295330
(dwi_artifacts_wf, avg_b0_0, [('outputnode.out_file', 'in_dwi')]),
296-
(dwi_artifacts_wf, ecc, [('outputnode.out_file', 'in_file')]),
331+
(dwi_artifacts_wf, dwi_eddy_wf, [('outputnode.out_file', 'inputnode.dwi_file')]),
297332
(inputnode, avg_b0_0, [('bval_file', 'in_bval')]),
298333
(avg_b0_0, bet_dwi0, [('out_file', 'in_file')]),
299-
(inputnode, ecc, [('bval_file', 'in_bval'),
300-
('bvec_file', 'in_bvec')]),
301-
(bet_dwi0, ecc, [('mask_file', 'in_mask')]),
302-
(gen_idx, ecc, [('out_file', 'in_index')]),
303-
(ecc, denoise_eddy, [('out_corrected', 'in_file')]),
304-
(ecc, bias_correct, [('out_corrected', 'in_file'),
305-
('out_rotated_bvecs', 'in_bvec')]),
334+
(inputnode, dwi_eddy_wf, [('bval_file', 'inputnode.bval_file'),
335+
('bvec_file', 'inputnode.bvec_file')]),
336+
(bet_dwi0, dwi_eddy_wf, [('mask_file', 'inputnode.mask_file')]),
337+
(gen_idx, dwi_eddy_wf, [('out_file', 'inputnode.index')]),
338+
(dwi_eddy_wf, denoise_eddy, [('outputnode.out_file', 'in_file')]),
339+
(dwi_eddy_wf, bias_correct, [('outputnode.out_file', 'in_file'),
340+
('outputnode.out_bvec', 'in_bvec')]),
306341
(inputnode, bias_correct, [('bval_file', 'in_bval')]),
307342
(bias_correct, fslroi, [('out_file', 'in_file')]),
308343
(fslroi, b0mask_node, [('roi_file', 'b0_file')]),
309-
(ecc, eddy_quad, [(('out_corrected', get_path), 'base_name'),
310-
(('out_corrected', get_qc_path), 'output_dir'),
311-
('out_rotated_bvecs', 'bvec_file')]),
344+
(dwi_eddy_wf, eddy_quad, [(('outputnode.out_file', get_path), 'base_name'),
345+
(('outputnode.out_file', get_qc_path), 'output_dir'),
346+
('outputnode.out_bvec', 'bvec_file')]),
312347
(inputnode, eddy_quad, [('bval_file', 'bval_file')]),
313348
(b0mask_node, eddy_quad, [('mask_file', 'mask_file')]),
314349
(gen_idx, eddy_quad, [('out_file', 'idx_file')]),
315-
(inputnode, tensor_wf, [('bval_file', 'inputnode.bval_file')]),
316-
(b0mask_node, tensor_wf, [('mask_file', 'inputnode.mask_file')]),
317-
(ecc, tensor_wf, [('out_corrected', 'inputnode.dwi_file'),
318-
('out_rotated_bvecs', 'inputnode.bvec_file')])
350+
(inputnode, dwi_tensor_wf, [('bval_file', 'inputnode.bval_file')]),
351+
(b0mask_node, dwi_tensor_wf, [('mask_file', 'inputnode.mask_file')]),
352+
(dwi_eddy_wf, dwi_tensor_wf, [('outputnode.out_file', 'inputnode.dwi_file'),
353+
('outputnode.out_bvec', 'inputnode.bvec_file')])
319354
])
320355

321356
if acqp_file:
322-
ecc.inputs.in_acqp = acqp_file
357+
eddy_inputspec = dwi_eddy_wf.get_node('inputnode')
358+
eddy_inputspec.inputs.acqp = acqp_file
323359
eddy_quad.inputs.param_file = acqp_file
324360
else:
325361
dwi_wf.connect([
326-
(acqp, ecc, [('out_file', 'in_acqp')]),
362+
(acqp, dwi_eddy_wf, [('out_file', 'inputnode.acqp')]),
327363
(acqp, eddy_quad, [('out_file', 'param_file')])
328364
])
329365

@@ -349,38 +385,39 @@ def get_b0_mask_fn(b0_file):
349385
# ecc.inputs.in_acqp = acqp_file
350386
# else:
351387
# Decide what ecc will take: topup or fmap
352-
fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap['suffix']])
353-
fmap = fmaps[0]
354-
# Else If epi files detected
355-
if fmap['suffix'] == 'epi':
356-
dwi_wf.connect([
357-
(sdc_wf, ecc, [('outputnode.out_topup', 'in_topup_fieldcoef'),
358-
('outputnode.out_movpar', 'in_topup_movpar')])
359-
])
360-
# Otherwise (fieldmaps)
361-
else:
362-
dwi_wf.connect([
363-
(bet_dwi0, sdc_wf, [('out_file', 'inputnode.b0_stripped')]),
364-
(sdc_wf, ecc, [('outputnode.out_fmap', 'field')])
365-
])
388+
if fmaps:
389+
fmaps.sort(key=lambda fmap: FMAP_PRIORITY[fmap['suffix']])
390+
fmap = fmaps[0]
391+
# Else If epi files detected
392+
if fmap['suffix'] == 'epi':
393+
dwi_wf.connect([
394+
(dwi_sdc_wf, dwi_eddy_wf, [('outputnode.out_topup', 'inputnode.topup_fieldcoef'),
395+
('outputnode.out_movpar', 'inputnode.topup_movpar')])
396+
])
397+
# Otherwise (fieldmaps)
398+
else:
399+
dwi_wf.connect([
400+
(bet_dwi0, dwi_sdc_wf, [('out_file', 'inputnode.b0_stripped')]),
401+
(dwi_sdc_wf, dwi_eddy_wf, [('outputnode.out_fmap', 'inputnode.fieldmap_file')])
402+
])
366403

367404
dwi_wf.connect([
368-
(ecc, outputnode, [('out_corrected', 'out_dwi')]),
405+
(dwi_eddy_wf, outputnode, [('outputnode.out_file', 'out_dwi')]),
369406
(inputnode, outputnode, [('bval_file', 'out_bval')]),
370-
(ecc, outputnode, [('out_rotated_bvecs', 'out_bvec')]),
407+
(dwi_eddy_wf, outputnode, [('outputnode.out_bvec', 'out_bvec')]),
371408
(gen_idx, outputnode, [('out_file', 'index')]),
372409
(acqp, outputnode, [('out_file', 'acq_params')]),
373410
(b0mask_node, outputnode, [('mask_file', 'out_mask')]),
374411
(avg_b0_0, outputnode, [('out_file', 'out_b0_pre')]),
375412
(bet_dwi0, outputnode, [('mask_file', 'out_b0_mask_pre')]),
376413
(eddy_quad, outputnode, [('qc_json', 'out_eddy_quad_json'),
377414
('qc_pdf', 'out_eddy_quad_pdf')]),
378-
(tensor_wf, outputnode, [('outputnode.FA_file', 'out_dtifit_FA'),
379-
('outputnode.MD_file', 'out_dtifit_MD'),
380-
('outputnode.AD_file', 'out_dtifit_AD'),
381-
('outputnode.RD_file', 'out_dtifit_RD'),
382-
('outputnode.V1_file', 'out_dtifit_V1'),
383-
('outputnode.sse_file', 'out_dtifit_sse')])
415+
(dwi_tensor_wf, outputnode, [('outputnode.FA_file', 'out_dtifit_FA'),
416+
('outputnode.MD_file', 'out_dtifit_MD'),
417+
('outputnode.AD_file', 'out_dtifit_AD'),
418+
('outputnode.RD_file', 'out_dtifit_RD'),
419+
('outputnode.V1_file', 'out_dtifit_V1'),
420+
('outputnode.sse_file', 'out_dtifit_sse')])
384421
])
385422

386423
return dwi_wf

dmriprep/workflows/fieldmap/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22

3-
from .base import init_sdc_prep_wf
3+
from .base import init_sdc_wf
44
from .pepolar import init_pepolar_wf
55
from .fmap import init_fmap_wf
66
from .phasediff import init_phase_wf, init_phdiff_wf

0 commit comments

Comments
 (0)