@@ -12,36 +12,86 @@ def transpose(samples_over_fibres):
12
12
a = a .reshape (- 1 ,1 )
13
13
return a .T .tolist ()
14
14
15
- def create_dmri_preprocessing (name = "dMRI_preprocessing" ):
15
+ def create_dmri_preprocessing (name = "dMRI_preprocessing" , fieldmap_registration = False ):
16
16
"""Creates a workflow that chains the necessary pipelines to
17
- correct for motion, eddy currents, and susceptibility
18
- artifacts in EPI dMRI sequences.
17
+ correct for motion, eddy currents, and susceptibility
18
+ artifacts in EPI dMRI sequences.
19
19
20
20
Example
21
21
-------
22
22
23
23
>>> nipype_dmri_preprocess = create_dmri_preprocessing("nipype_dmri_prep")
24
- >>> nipype_dmri_preprocess.inputs.inputnode. =
25
- >>> nipype_dmri_preprocess.inputs.inputnode. =
26
- >>> nipype_dmri_preprocess.inputs.inputnode. =
27
- >>> nipype_dmri_preprocess.inputs.inputnode. =
28
- >>> nipype_dmri_preprocess.inputs.inputnode. =
29
- >>> nipype_dmri_preprocess.inputs.inputnode. =
30
- >>> nipype_dmri_preprocess.inputs.inputnode. =
31
- >>> nipype_dmri_preprocess.inputs.inputnode. =
24
+ >>> nipype_dmri_preprocess.inputs.inputnode.in_file = 'diffusion.nii'
25
+ >>> nipype_dmri_preprocess.inputs.inputnode.in_bvec = 'diffusion.bvec'
26
+ >>> nipype_dmri_preprocess.inputs.inputnode.ref_num = 0
27
+ >>> nipype_dmri_preprocess.inputs.inputnode.fieldmap_mag = 'magnitude.nii'
28
+ >>> nipype_dmri_preprocess.inputs.inputnode.fieldmap_pha = 'phase.nii'
29
+ >>> nipype_dmri_preprocess.inputs.inputnode.te_diff = 2.46
30
+ >>> nipype_dmri_preprocess.inputs.inputnode.epi_echospacing = 0.77
31
+ >>> nipype_dmri_preprocess.inputs.inputnode.epi_rev_encoding = False
32
+ >>> nipype_dmri_preprocess.inputs.inputnode.pi_accel_factor = True
32
33
>>> nipype_dmri_preprocess.run() # doctest: +SKIP
33
34
35
+
34
36
Inputs::
35
37
36
- inputnode.
38
+ inputnode.in_file
39
+ inputnode.in_bvec
40
+ inputnode.ref_num
41
+ inputnode.fieldmap_mag
42
+ inputnode.fieldmap_pha
43
+ inputnode.te_diff
44
+ inputnode.epi_echospacing
45
+ inputnode.epi_rev_encoding
46
+ inputnode.pi_accel_factor
47
+ inputnode.vsm_sigma
48
+
37
49
38
50
Outputs::
39
51
40
52
outputnode.dmri_corrected
53
+ outputnode.bvec_rotated
54
+
55
+
56
+ Optional arguments::
57
+
58
+ fieldmap_registration - True if registration to fieldmap should be done (default False)
59
+
41
60
42
61
"""
43
62
44
63
pipeline = pe .Workflow (name = name )
64
+
65
+ inputnode = pe .Node (interface = util .IdentityInterface (
66
+ fields = ['in_file' , 'in_bvec' ,'ref_num' ,'fieldmap_mag' ,
67
+ 'fieldmap_pha' ,'te_diff' ,'epi_echospacing' ,
68
+ 'epi_rev_encoding' ,'pi_accel_factor' ,'vsm_sigma' ]),
69
+ name = 'inputnode' )
70
+
71
+ outputnode = pe .Node (interface = util .IdentityInterface (
72
+ fields = ['dmri_corrected' ,'bvec_rotated' ]),
73
+ name = 'outputnode' )
74
+
75
+ motion = create_motion_correct_pipeline ()
76
+ eddy = create_eddy_correct_pipeline ()
77
+ susceptibility = create_susceptibility_correct_pipeline (fieldmap_registration = fieldmap_registration )
78
+
79
+ pipeline .connect ([
80
+ (inputnode , motion , [('in_file' ,'inputnode.in_file' ),('in_bvec' ,'inputnode.in_bvec' ),('ref_num' ,'inputnode.ref_num' )])
81
+ ,(inputnode , eddy , [('ref_num' ,'inputnode.ref_num' )])
82
+ ,(motion , eddy , [('outputnode.motion_corrected' ,'inputnode.in_file' )])
83
+ ,(eddy , susceptibility , [('outputnode.eddy_corrected' ,'inputnode.in_file' )])
84
+ ,(inputnode , susceptibility , [('ref_num' ,'inputnode.ref_num' )
85
+ ,('fieldmap_mag' ,'inputnode.fieldmap_mag' )
86
+ ,('fieldmap_pha' ,'inputnode.fieldmap_pha' )
87
+ ,('te_diff' ,'inputnode.te_diff' )
88
+ ,('epi_echospacing' ,'inputnode.epi_echospacing' )
89
+ ,('epi_rev_encoding' ,'inputnode.epi_rev_encoding' )
90
+ ,('pi_accel_factor' ,'inputnode.pi_accel_factor' )
91
+ ,('vsm_sigma' ,'inputnode.vsm_sigma' ) ])
92
+ ,(motion , outputnode , [('outputnode.out_bvec' , 'bvec_rotated' )])
93
+ ,(susceptibility , outputnode , [('outputnode.epi_corrected' ,'dmri_corrected' )])
94
+ ])
45
95
46
96
return pipeline
47
97
@@ -206,7 +256,8 @@ def create_bedpostx_pipeline(name="bedpostx"):
206
256
def create_motion_correct_pipeline (name = "motion_correct" ):
207
257
"""Creates a pipeline that corrects for motion artifact in dMRI sequences.
208
258
It takes a series of diffusion weighted images and rigidly corregisters
209
- them to one reference image. Finally, the b-matrix is rotated accordingly,
259
+ them to one reference image. Finally, the b-matrix is rotated accordingly
260
+ (Leemans et al. 2009 - http://www.ncbi.nlm.nih.gov/pubmed/19319973),
210
261
making use of the rotation matrix obtained by FLIRT.
211
262
212
263
Example
@@ -227,6 +278,8 @@ def create_motion_correct_pipeline(name="motion_correct"):
227
278
Outputs::
228
279
229
280
outputnode.motion_corrected
281
+ outputnode.out_bvec
282
+
230
283
"""
231
284
232
285
inputnode = pe .Node (interface = util .IdentityInterface (fields = ["in_file" , "ref_num" ,"in_bvec" ]),
@@ -260,8 +313,9 @@ def create_motion_correct_pipeline(name="motion_correct"):
260
313
261
314
def create_eddy_correct_pipeline (name = "eddy_correct" ):
262
315
"""Creates a pipeline that replaces eddy_correct script in FSL. It takes a
263
- series of diffusion weighted images and linearly corregisters them to one
264
- reference image.
316
+ series of diffusion weighted images and linearly co-registers them to one
317
+ reference image. No rotation of the B-matrix is performed, so this pipeline
318
+ should be executed after the motion correction pipeline.
265
319
266
320
Example
267
321
-------
@@ -288,7 +342,7 @@ def create_eddy_correct_pipeline(name="eddy_correct"):
288
342
289
343
split = pe .Node (fsl .Split (dimension = 't' ), name = "split" )
290
344
pick_ref = pe .Node (util .Select (), name = "pick_ref" )
291
- coregistration = pe .MapNode (fsl .FLIRT (no_search = True , padding_size = 1 ), name = "coregistration" , iterfield = ["in_file" ])
345
+ coregistration = pe .MapNode (fsl .FLIRT (no_search = True , padding_size = 1 , dof = 12 ), name = "coregistration" , iterfield = ["in_file" ])
292
346
merge = pe .Node (fsl .Merge (dimension = "t" ), name = "merge" )
293
347
outputnode = pe .Node (interface = util .IdentityInterface (fields = ["eddy_corrected" ]),
294
348
name = "outputnode" )
@@ -304,23 +358,24 @@ def create_eddy_correct_pipeline(name="eddy_correct"):
304
358
])
305
359
return pipeline
306
360
307
- def create_susceptibility_correct_pipeline (name = "susceptibility_correct" , register_to_ref = False ):
361
+ def create_susceptibility_correct_pipeline (name = "susceptibility_correct" , fieldmap_registration = False ):
308
362
""" Replaces the epidewarp.fsl script (http://www.nmr.mgh.harvard.edu/~greve/fbirn/b0/epidewarp.fsl)
309
- for susceptibility distortion correction in EPI sequences with the fieldmap information in
310
- dMRI and fMRI (Jezzard et al., MRM 1995 ) using FSL's FUGUE.
363
+ for susceptibility distortion correction of dMRI & fMRI acquired with EPI sequences and the fieldmap
364
+ information (Jezzard et al., 1995) using FSL's FUGUE. The registration to the (warped) fieldmap
365
+ (strictly following the original script) is available using fieldmap_registration=True.
311
366
312
367
Example
313
368
-------
314
369
315
- >>> nipype_epicorrect = create_epi_correct_pipeline ("nipype_epicorrect")
316
- >>> nipype_epicorrect.inputs.inputnode.in_file = 'epi_data .nii'
370
+ >>> nipype_epicorrect = create_susceptibility_correct_pipeline ("nipype_epicorrect", fieldmap_registration=False )
371
+ >>> nipype_epicorrect.inputs.inputnode.in_file = 'diffusion .nii'
317
372
>>> nipype_epicorrect.inputs.inputnode.fieldmap_mag = 'magnitude.nii'
318
373
>>> nipype_epicorrect.inputs.inputnode.fieldmap_pha = 'phase.nii'
319
374
>>> nipype_epicorrect.inputs.inputnode.te_diff = 2.46
320
- >>> nipype_epicorrect.inputs.inputnode.epi_echospacing = 0.51
375
+ >>> nipype_epicorrect.inputs.inputnode.epi_echospacing = 0.77
321
376
>>> nipype_epicorrect.inputs.inputnode.epi_rev_encoding = False
322
- >>> nipype_epicorrect.inputs.inputnode.ref_volume = 0
323
- >>> nipype_epicorrect.inputs.inputnode.epi_parallel = True
377
+ >>> nipype_epicorrect.inputs.inputnode.ref_num = 0
378
+ >>> nipype_epicorrect.inputs.inputnode.pi_accel_factor = 1.0
324
379
>>> nipype_epicorrect.run() # doctest: +SKIP
325
380
326
381
Inputs::
@@ -332,14 +387,20 @@ def create_susceptibility_correct_pipeline(name="susceptibility_correct", regist
332
387
inputnode.epi_echospacing - The echo spacing (aka dwell time) in the EPI sequence
333
388
inputnode.epi_ph_encoding_dir - The phase encoding direction in EPI acquisition (default y)
334
389
inputnode.epi_rev_encoding - True if it is acquired with reverse encoding
335
- inputnode.epi_parallel - True if EPI was acquired in a parallel imaging scheme
390
+ inputnode.pi_accel_factor - Acceleration factor used for EPI parallel imaging (GRAPPA)
336
391
inputnode.vsm_sigma - Sigma value of the gaussian smoothing filter applied to the vsm (voxel shift map)
337
- inputnode.ref_volume - The reference volume (B=0 in dMRI or a central frame in fMRI)
392
+ inputnode.ref_num - The reference volume (B=0 in dMRI or a central frame in fMRI)
338
393
339
394
340
395
Outputs::
341
396
342
397
outputnode.epi_corrected
398
+
399
+
400
+ Optional arguments::
401
+
402
+ fieldmap_registration - True if registration to fieldmap should be done (default False)
403
+
343
404
"""
344
405
345
406
inputnode = pe .Node (interface = util .IdentityInterface (fields = ["in_file" ,
@@ -349,9 +410,9 @@ def create_susceptibility_correct_pipeline(name="susceptibility_correct", regist
349
410
"epi_echospacing" ,
350
411
"epi_ph_encoding_dir" ,
351
412
"epi_rev_encoding" ,
352
- "epi_parallel " ,
413
+ "pi_accel_factor " ,
353
414
"vsm_sigma" ,
354
- "ref_volume " ,
415
+ "ref_num " ,
355
416
"unwarp_direction"
356
417
]), name = "inputnode" )
357
418
@@ -365,7 +426,7 @@ def create_susceptibility_correct_pipeline(name="susceptibility_correct", regist
365
426
mask_mag_dil = pe .Node ( interface = util .Function ( input_names = ["in_file" ], output_names = ["out_file" ], function = _dilate_mask ), name = 'mask_dilate' )
366
427
367
428
# Compute dwell time
368
- dwell_time = pe .Node ( interface = util .Function ( input_names = ["dwell_time" ,"is_parallel " ,"is_reverse_encoding" ], output_names = ["dwell_time" ], function = _compute_dwelltime ), name = 'dwell_time' )
429
+ dwell_time = pe .Node ( interface = util .Function ( input_names = ["dwell_time" ,"pi_factor " ,"is_reverse_encoding" ], output_names = ["dwell_time" ], function = _compute_dwelltime ), name = 'dwell_time' )
369
430
370
431
# Normalize phase diff to be [-pi, pi)
371
432
norm_pha = pe .Node ( interface = util .Function ( input_names = ["in_file" ], output_names = ["out_file" ], function = _prepare_phasediff ), name = 'normalize_phasediff' )
@@ -392,7 +453,7 @@ def create_susceptibility_correct_pipeline(name="susceptibility_correct", regist
392
453
393
454
394
455
pipeline .connect ([
395
- (inputnode , dwell_time , [('epi_echospacing' ,'dwell_time' ), ('epi_parallel ' ,'is_parallel ' ),('epi_rev_encoding' ,'is_reverse_encoding' ) ])
456
+ (inputnode , dwell_time , [('epi_echospacing' ,'dwell_time' ), ('pi_accel_factor ' ,'pi_factor ' ),('epi_rev_encoding' ,'is_reverse_encoding' ) ])
396
457
,(inputnode , select_mag , [('fieldmap_mag' ,'in_file' )] )
397
458
,(inputnode , norm_pha , [('fieldmap_pha' ,'in_file' )] )
398
459
,(select_mag , mask_mag , [('roi_file' , 'in_file' )] )
@@ -414,8 +475,7 @@ def create_susceptibility_correct_pipeline(name="susceptibility_correct", regist
414
475
,(dwi_merge , outputnode , [('merged_file' ,'epi_corrected' )])
415
476
])
416
477
417
- if register_to_ref :
418
- # register to ref volume
478
+ if fieldmap_registration :
419
479
""" Register magfw to example epi. There are some parameters here that may need to be tweaked. Should probably strip the mag
420
480
Pre-condition: forward warp the mag in order to reg with func. What does mask do here?
421
481
"""
@@ -431,7 +491,7 @@ def create_susceptibility_correct_pipeline(name="susceptibility_correct", regist
431
491
msk_applyxfm = pe .Node ( interface = fsl .ApplyXfm (), name = 'msk_apply_xfm' )
432
492
433
493
pipeline .connect ([
434
- (inputnode , select_epi , [('in_file' ,'in_file' ), ('ref_volume ' ,'t_min' )] )
494
+ (inputnode , select_epi , [('in_file' ,'in_file' ), ('ref_num ' ,'t_min' )] )
435
495
,(select_epi , vsm_reg , [('roi_file' ,'reference' )])
436
496
,(vsm , vsm_fwd , [('shift_out_file' ,'shift_in_file' )])
437
497
,(mask_mag_dil , vsm_fwd , [('out_file' ,'mask_file' )] )
@@ -488,9 +548,8 @@ def _cat_logs( in_files ):
488
548
totallog .write (line )
489
549
return out_file
490
550
491
- def _compute_dwelltime ( dwell_time = 0.68 , is_parallel = False , is_reverse_encoding = False ):
492
- if is_parallel :
493
- dwell_time *= 0.5
551
+ def _compute_dwelltime ( dwell_time = 0.68 , pi_factor = 1.0 , is_reverse_encoding = False ):
552
+ dwell_time *= (1.0 / pi_factor )
494
553
495
554
if is_reverse_encoding :
496
555
dwell_time *= - 1.0
0 commit comments