44import os
55
66import nipype .pipeline .engine as pe
7+ from nipype .interfaces .io import JSONFileGrabber
78from nipype .interfaces import utility as niu
89from nipype .interfaces import freesurfer as fs
910from nipype .interfaces import ants
@@ -42,17 +43,19 @@ def all_fmb_pipeline(name='hmc_sdc_ecc',
4243 >>> allcorr.run() # doctest: +SKIP
4344
4445 """
45- inputnode = pe .Node (niu .IdentityInterface (fields = ['in_file' , 'in_bvec' ,
46- 'in_bval' , 'bmap_pha' , 'bmap_mag' ]), name = 'inputnode' )
47-
48- outputnode = pe .Node (niu .IdentityInterface (fields = ['out_file' , 'out_mask' ,
49- 'out_bvec' ]), name = 'outputnode' )
50- avg_b0_0 = pe .Node (niu .Function (input_names = ['in_dwi' , 'in_bval' ],
51- output_names = ['out_file' ], function = b0_average ),
52- name = 'b0_avg_pre' )
53- avg_b0_1 = pe .Node (niu .Function (input_names = ['in_dwi' , 'in_bval' ],
54- output_names = ['out_file' ], function = b0_average ),
55- name = 'b0_avg_post' )
46+ inputnode = pe .Node (niu .IdentityInterface (
47+ fields = ['in_file' , 'in_bvec' , 'in_bval' , 'bmap_pha' , 'bmap_mag' ]),
48+ name = 'inputnode' )
49+
50+ outputnode = pe .Node (niu .IdentityInterface (
51+ fields = ['out_file' , 'out_mask' , 'out_bvec' ]), name = 'outputnode' )
52+
53+ avg_b0_0 = pe .Node (niu .Function (
54+ input_names = ['in_dwi' , 'in_bval' ], output_names = ['out_file' ],
55+ function = b0_average ), name = 'b0_avg_pre' )
56+ avg_b0_1 = pe .Node (niu .Function (
57+ input_names = ['in_dwi' , 'in_bval' ], output_names = ['out_file' ],
58+ function = b0_average ), name = 'b0_avg_post' )
5659 bet_dwi0 = pe .Node (fsl .BET (frac = 0.3 , mask = True , robust = True ),
5760 name = 'bet_dwi_pre' )
5861 bet_dwi1 = pe .Node (fsl .BET (frac = 0.3 , mask = True , robust = True ),
@@ -128,18 +131,19 @@ def all_peb_pipeline(name='hmc_sdc_ecc',
128131 >>> allcorr.run() # doctest: +SKIP
129132
130133 """
131- inputnode = pe .Node (niu .IdentityInterface (fields = ['in_file' , 'in_bvec' ,
132- 'in_bval' , 'alt_file' ]), name = 'inputnode' )
133-
134- outputnode = pe .Node (niu .IdentityInterface (fields = ['out_file' , 'out_mask' ,
135- 'out_bvec' ]), name = 'outputnode' )
136-
137- avg_b0_0 = pe .Node (niu .Function (input_names = ['in_dwi' , 'in_bval' ],
138- output_names = ['out_file' ], function = b0_average ),
139- name = 'b0_avg_pre' )
140- avg_b0_1 = pe .Node (niu .Function (input_names = ['in_dwi' , 'in_bval' ],
141- output_names = ['out_file' ], function = b0_average ),
142- name = 'b0_avg_post' )
134+ inputnode = pe .Node (niu .IdentityInterface (
135+ fields = ['in_file' , 'in_bvec' , 'in_bval' , 'alt_file' ]),
136+ name = 'inputnode' )
137+
138+ outputnode = pe .Node (niu .IdentityInterface (
139+ fields = ['out_file' , 'out_mask' , 'out_bvec' ]), name = 'outputnode' )
140+
141+ avg_b0_0 = pe .Node (niu .Function (
142+ input_names = ['in_dwi' , 'in_bval' ], output_names = ['out_file' ],
143+ function = b0_average ), name = 'b0_avg_pre' )
144+ avg_b0_1 = pe .Node (niu .Function (
145+ input_names = ['in_dwi' , 'in_bval' ], output_names = ['out_file' ],
146+ function = b0_average ), name = 'b0_avg_post' )
143147 bet_dwi0 = pe .Node (fsl .BET (frac = 0.3 , mask = True , robust = True ),
144148 name = 'bet_dwi_pre' )
145149 bet_dwi1 = pe .Node (fsl .BET (frac = 0.3 , mask = True , robust = True ),
@@ -216,11 +220,12 @@ def all_fsl_pipeline(name='fsl_all_correct',
216220
217221 """
218222
219- inputnode = pe .Node (niu .IdentityInterface (fields = ['in_file' , 'in_bvec' ,
220- 'in_bval' , 'alt_file' ]), name = 'inputnode' )
223+ inputnode = pe .Node (niu .IdentityInterface (
224+ fields = ['in_file' , 'in_bvec' , 'in_bval' , 'alt_file' ]),
225+ name = 'inputnode' )
221226
222- outputnode = pe .Node (niu .IdentityInterface (fields = [ 'out_file' , 'out_mask' ,
223- 'out_bvec' ]), name = 'outputnode' )
227+ outputnode = pe .Node (niu .IdentityInterface (
228+ fields = [ 'out_file' , 'out_mask' , 'out_bvec' ]), name = 'outputnode' )
224229
225230 def _gen_index (in_file ):
226231 import numpy as np
@@ -231,20 +236,20 @@ def _gen_index(in_file):
231236 np .savetxt (out_file , np .ones ((vols ,)).T )
232237 return out_file
233238
234- avg_b0_0 = pe .Node (niu .Function (input_names = [ 'in_dwi' , 'in_bval' ],
235- output_names = ['out_file' ], function = b0_average ) ,
236- name = 'b0_avg_pre' )
239+ avg_b0_0 = pe .Node (niu .Function (
240+ input_names = [ 'in_dwi' , 'in_bval' ], output_names = ['out_file' ],
241+ function = b0_average ), name = 'b0_avg_pre' )
237242 bet_dwi0 = pe .Node (fsl .BET (frac = 0.3 , mask = True , robust = True ),
238243 name = 'bet_dwi_pre' )
239244
240245 sdc = sdc_peb (epi_params = epi_params , altepi_params = altepi_params )
241246 ecc = pe .Node (fsl .Eddy (method = 'jac' ), name = 'fsl_eddy' )
242- rot_bvec = pe .Node (niu .Function (input_names = [ 'in_bvec' , 'eddy_params' ],
243- output_names = ['out_file' ], function = eddy_rotate_bvecs ) ,
244- name = 'Rotate_Bvec' )
245- avg_b0_1 = pe .Node (niu .Function (input_names = [ 'in_dwi' , 'in_bval' ],
246- output_names = ['out_file' ], function = b0_average ) ,
247- name = 'b0_avg_post' )
247+ rot_bvec = pe .Node (niu .Function (
248+ input_names = [ 'in_bvec' , 'eddy_params' ], output_names = ['out_file' ],
249+ function = eddy_rotate_bvecs ), name = 'Rotate_Bvec' )
250+ avg_b0_1 = pe .Node (niu .Function (
251+ input_names = [ 'in_dwi' , 'in_bval' ], output_names = ['out_file' ],
252+ function = b0_average ), name = 'b0_avg_post' )
248253 bet_dwi1 = pe .Node (fsl .BET (frac = 0.3 , mask = True , robust = True ),
249254 name = 'bet_dwi_post' )
250255
@@ -349,22 +354,22 @@ def hmc_pipeline(name='motion_correct'):
349354 # cost='mutualinfo', cost_func='mutualinfo', bins=64,
350355 schedule = get_flirt_schedule ('hmc' ))
351356
352- inputnode = pe .Node (niu .IdentityInterface (fields = ['in_file' , 'ref_num' ,
353- 'in_bvec' , 'in_bval' , 'in_mask' ]), name = 'inputnode' )
354- split = pe .Node (niu .Function (function = hmc_split ,
355- input_names = ['in_file' , 'in_bval' , 'ref_num' ],
356- output_names = ['out_ref' , 'out_mov' , 'out_bval' , 'volid' ]),
357- name = 'SplitDWI' )
357+ inputnode = pe .Node (niu .IdentityInterface (
358+ fields = ['in_file' , 'ref_num' , 'in_bvec' , 'in_bval' , 'in_mask' ]),
359+ name = 'inputnode' )
360+ split = pe .Node (niu .Function (
361+ output_names = ['out_ref' , 'out_mov' , 'out_bval' , 'volid' ],
362+ input_names = ['in_file' , 'in_bval' , 'ref_num' ], function = hmc_split ),
363+ name = 'SplitDWI' )
358364 flirt = dwi_flirt (flirt_param = params )
359365 insmat = pe .Node (niu .Function (input_names = ['inlist' , 'volid' ],
360366 output_names = ['out' ], function = insert_mat ),
361367 name = 'InsertRefmat' )
362- rot_bvec = pe .Node (niu .Function (input_names = ['in_bvec' , 'in_matrix' ],
363- output_names = ['out_file' ], function = rotate_bvecs ),
364- name = 'Rotate_Bvec' )
365- outputnode = pe .Node (niu .IdentityInterface (fields = ['out_file' ,
366- 'out_bvec' , 'out_xfms' ]),
367- name = 'outputnode' )
368+ rot_bvec = pe .Node (niu .Function (
369+ function = rotate_bvecs , input_names = ['in_bvec' , 'in_matrix' ],
370+ output_names = ['out_file' ]), name = 'Rotate_Bvec' )
371+ outputnode = pe .Node (niu .IdentityInterface (
372+ fields = ['out_file' , 'out_bvec' , 'out_xfms' ]), name = 'outputnode' )
368373
369374 wf = pe .Workflow (name = name )
370375 wf .connect ([
@@ -450,14 +455,14 @@ def ecc_pipeline(name='eddy_correct'):
450455 schedule = get_flirt_schedule ('ecc' ))
451456 # cost='normmi', cost_func='normmi', bins=64,
452457
453- inputnode = pe .Node (niu .IdentityInterface (fields = [ 'in_file' , 'in_bval' ,
454- 'in_mask' , 'in_xfms' ]), name = 'inputnode' )
455- avg_b0 = pe .Node (niu .Function (input_names = [ 'in_dwi' , 'in_bval' ],
456- output_names = ['out_file' ], function = b0_average ) ,
457- name = 'b0_avg' )
458- pick_dws = pe .Node (niu .Function (input_names = [ 'in_dwi' , 'in_bval' , 'b' ],
459- output_names = ['out_file' ], function = extract_bval ) ,
460- name = 'ExtractDWI' )
458+ inputnode = pe .Node (niu .IdentityInterface (
459+ fields = [ 'in_file' , 'in_bval' , 'in_mask' , 'in_xfms' ]), name = 'inputnode' )
460+ avg_b0 = pe .Node (niu .Function (
461+ input_names = [ 'in_dwi' , 'in_bval' ], output_names = ['out_file' ],
462+ function = b0_average ), name = 'b0_avg' )
463+ pick_dws = pe .Node (niu .Function (
464+ input_names = [ 'in_dwi' , 'in_bval' , 'b' ], output_names = ['out_file' ],
465+ function = extract_bval ), name = 'ExtractDWI' )
461466 pick_dws .inputs .b = 'diff'
462467
463468 flirt = dwi_flirt (flirt_param = params , excl_nodiff = True )
@@ -468,14 +473,15 @@ def ecc_pipeline(name='eddy_correct'):
468473 name = 'RemoveNegative' )
469474
470475 split = pe .Node (fsl .Split (dimension = 't' ), name = 'SplitDWIs' )
471- get_mat = pe .Node (niu .Function (input_names = ['in_bval' , 'in_xfms' ],
472- output_names = ['out_files' ], function = recompose_xfm ),
473- name = 'GatherMatrices' )
474- merge = pe .Node (niu .Function (input_names = ['in_dwi' , 'in_bval' , 'in_corrected' ],
475- output_names = ['out_file' ], function = recompose_dwi ), name = 'MergeDWIs' )
476+ get_mat = pe .Node (niu .Function (
477+ input_names = ['in_bval' , 'in_xfms' ], output_names = ['out_files' ],
478+ function = recompose_xfm ), name = 'GatherMatrices' )
479+ merge = pe .Node (niu .Function (
480+ input_names = ['in_dwi' , 'in_bval' , 'in_corrected' ],
481+ output_names = ['out_file' ], function = recompose_dwi ), name = 'MergeDWIs' )
476482
477- outputnode = pe .Node (niu .IdentityInterface (fields = [ 'out_file' , 'out_xfms' ]),
478- name = 'outputnode' )
483+ outputnode = pe .Node (niu .IdentityInterface (
484+ fields = [ 'out_file' , 'out_xfms' ]), name = 'outputnode' )
479485
480486 wf = pe .Workflow (name = name )
481487 wf .connect ([
@@ -505,11 +511,7 @@ def ecc_pipeline(name='eddy_correct'):
505511
506512
507513def sdc_fmb (name = 'fmb_correction' ,
508- fugue_params = dict (smooth3d = 2.0 ),
509- bmap_params = dict (delta_te = 2.46e-3 ),
510- epi_params = dict (echospacing = 0.77e-3 ,
511- acc_factor = 3 ,
512- enc_dir = 'AP' )):
514+ fugue_params = dict (smooth3d = 2.0 )):
513515 """
514516 SDC stands for susceptibility distortion correction. FMB stands for
515517 fieldmap-based.
@@ -523,14 +525,6 @@ def sdc_fmb(name='fmb_correction',
523525 script in FSL `fsl_prepare_fieldmap
524526 <http://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FUGUE/Guide#SIEMENS_data>`_.
525527
526- Default settings
527- ----------------
528-
529- >>> fugue_params=dict(smooth3d=2.0),
530- >>> bmap_params=dict(delta_te=2.46e-3),
531- >>> epi_params=dict(echospacing=0.77e-3,
532- ... acc_factor=3,
533- ... enc_dir='AP')
534528
535529
536530 Example
@@ -560,24 +554,35 @@ def sdc_fmb(name='fmb_correction',
560554
561555 """
562556
563- if epi_params [ 'enc_dir' ]. upper () == 'LR' :
564- epi_params [ 'enc_dir' ] = 'x-'
557+ defaults = dict ( delta_te = 2.46e-3 , echospacing = 0.77e-3 , acc_factor = 3 ,
558+ enc_dir = 'AP' )
565559
566- if epi_params ['enc_dir' ].upper () == 'RL' :
567- epi_params ['enc_dir' ] = 'x'
560+ delta_te = epi_params ['echospacing' ] / (1.0 * epi_params ['acc_factor' ])
568561
569- if epi_params ['enc_dir' ].upper () == 'AP' :
570- epi_params ['enc_dir' ] = 'y-'
562+ def _fix_enc_dir (enc_dir ):
563+ enc_dir = enc_dir .lower ()
564+ if enc_dir == 'lr' :
565+ return 'x-'
566+ if enc_dir == 'rl' :
567+ return 'x'
571568
572- if epi_params ['enc_dir' ].upper () == 'PA' :
573- epi_params ['enc_dir' ] = 'y'
569+ if enc_dir == 'ap' :
570+ return 'y-'
571+ if enc_dir == 'pa' :
572+ return 'y'
573+ return enc_dir
574574
575575 inputnode = pe .Node (niu .IdentityInterface (
576- fields = ['in_file' , 'in_bval' , 'in_mask' , 'bmap_pha' , 'bmap_mag' ]),
577- name = 'inputnode' )
576+ fields = ['in_file' , 'in_bval' , 'in_mask' , 'bmap_pha' , 'bmap_mag' ,
577+ 'settings' ]), name = 'inputnode' )
578+
578579 outputnode = pe .Node (niu .IdentityInterface (
579580 fields = ['out_file' , 'out_vsm' , 'out_warp' ]), name = 'outputnode' )
580- delta_te = epi_params ['echospacing' ] / (1.0 * epi_params ['acc_factor' ])
581+
582+ r_params = pe .Node (JSONFileGrabber (), name = 'SettingsGrabber' )
583+ eff_echo = pe .Node (niu .Function (function = _eff_t_echo ,
584+ input_names = ['echospacing' , 'acc_factor' ],
585+ output_names = ['eff_echo' ]), name = 'EffEcho' )
581586
582587 firstmag = pe .Node (fsl .ExtractROI (t_min = 0 , t_size = 1 ), name = 'GetFirst' )
583588 n4 = pe .Node (ants .N4BiasFieldCorrection (dimension = 3 ), name = 'Bias' )
@@ -591,7 +596,6 @@ def sdc_fmb(name='fmb_correction',
591596 rad2rsec = pe .Node (niu .Function (
592597 input_names = ['in_file' , 'delta_te' ], output_names = ['out_file' ],
593598 function = rads2radsec ), name = 'ToRadSec' )
594- rad2rsec .inputs .delta_te = bmap_params ['delta_te' ]
595599
596600 avg_b0 = pe .Node (niu .Function (
597601 input_names = ['in_dwi' , 'in_bval' ], output_names = ['out_file' ],
@@ -623,9 +627,9 @@ def sdc_fmb(name='fmb_correction',
623627 dimension = 3 , interpolation = 'BSpline' ), name = 'FMp_to_B0' )
624628
625629 pre_fugue = pe .Node (fsl .FUGUE (save_fmap = True ), name = 'PreliminaryFugue' )
626- demean = pe .Node (niu .Function (input_names = [ 'in_file' , 'in_mask' ],
627- output_names = ['out_file' ], function = demean_image ) ,
628- name = 'DemeanFmap' )
630+ demean = pe .Node (niu .Function (
631+ input_names = [ 'in_file' , 'in_mask' ], output_names = ['out_file' ],
632+ function = demean_image ), name = 'DemeanFmap' )
629633
630634 cleanup = cleanup_edge_pipeline ()
631635
@@ -635,8 +639,6 @@ def sdc_fmb(name='fmb_correction',
635639
636640 vsm = pe .Node (fsl .FUGUE (save_shift = True , ** fugue_params ),
637641 name = "ComputeVSM" )
638- vsm .inputs .asym_se_time = bmap_params ['delta_te' ]
639- vsm .inputs .dwell_time = delta_te
640642
641643 split = pe .Node (fsl .Split (dimension = 't' ), name = 'SplitDWIs' )
642644 merge = pe .Node (fsl .Merge (dimension = 't' ), name = 'MergeDWIs' )
@@ -647,10 +649,12 @@ def sdc_fmb(name='fmb_correction',
647649 name = 'RemoveNegative' )
648650 vsm2dfm = vsm2warp ()
649651 vsm2dfm .inputs .inputnode .scaling = 1.0
650- vsm2dfm .inputs .inputnode .enc_dir = epi_params ['enc_dir' ]
651652
652653 wf = pe .Workflow (name = name )
653654 wf .connect ([
655+ (inputnode , r_params , [('settings' , 'in_file' )]),
656+ (r_params , eff_echo , [('echospacing' , 'echospacing' ),
657+ ('acc_factor' , 'acc_factor' )]),
654658 (inputnode , pha2rads , [('bmap_pha' , 'in_file' )]),
655659 (inputnode , firstmag , [('bmap_mag' , 'in_file' )]),
656660 (inputnode , avg_b0 , [('in_file' , 'in_dwi' ),
@@ -661,6 +665,7 @@ def sdc_fmb(name='fmb_correction',
661665 (pha2rads , prelude , [('out_file' , 'phase_file' )]),
662666 (n4 , prelude , [('output_image' , 'magnitude_file' )]),
663667 (dilate , prelude , [('out_file' , 'mask_file' )]),
668+ (r_params , rad2rsec , [('delta_te' , 'delta_te' )]),
664669 (prelude , rad2rsec , [('unwrapped_phase_file' , 'in_file' )]),
665670
666671 (avg_b0 , fmm2b0 , [('out_file' , 'fixed_image' )]),
@@ -683,11 +688,14 @@ def sdc_fmb(name='fmb_correction',
683688 (cleanup , addvol , [('outputnode.out_file' , 'in_file' )]),
684689 (inputnode , vsm , [('in_mask' , 'mask_file' )]),
685690 (addvol , vsm , [('out_file' , 'fmap_in_file' )]),
691+ (r_params , vsm , [('delta_te' , 'asym_se_time' )]),
692+ (eff_echo , vsm , [('eff_echo' , 'dwell_time' )]),
686693 (inputnode , split , [('in_file' , 'in_file' )]),
687694 (split , unwarp , [('out_files' , 'in_file' )]),
688695 (vsm , unwarp , [('shift_out_file' , 'shift_in_file' )]),
689696 (unwarp , thres , [('unwarped_file' , 'in_file' )]),
690697 (thres , merge , [('out_file' , 'in_files' )]),
698+ (r_params , vsm2dfm , [(('enc_dir' , _fix_enc_dir ), 'enc_dir' )]),
691699 (merge , vsm2dfm , [('merged_file' , 'inputnode.in_ref' )]),
692700 (vsm , vsm2dfm , [('shift_out_file' , 'inputnode.in_vsm' )]),
693701 (merge , outputnode , [('merged_file' , 'out_file' )]),
@@ -748,11 +756,11 @@ def sdc_peb(name='peb_correction',
748756
749757 """
750758
751- inputnode = pe .Node (niu .IdentityInterface (fields = [ 'in_file' , 'in_bval' ,
752- 'in_mask' , 'alt_file' , 'ref_num' ]),
753- name = 'inputnode' )
754- outputnode = pe .Node (niu .IdentityInterface (fields = [ 'out_file' , 'out_vsm' ,
755- 'out_warp' ]), name = 'outputnode' )
759+ inputnode = pe .Node (niu .IdentityInterface (
760+ fields = [ 'in_file' , 'in_bval' , 'in_mask' , 'alt_file' , 'ref_num' ]),
761+ name = 'inputnode' )
762+ outputnode = pe .Node (niu .IdentityInterface (
763+ fields = [ 'out_file' , 'out_vsm' , 'out_warp' ]), name = 'outputnode' )
756764
757765 b0_ref = pe .Node (fsl .ExtractROI (t_size = 1 ), name = 'b0_ref' )
758766 b0_alt = pe .Node (fsl .ExtractROI (t_size = 1 ), name = 'b0_alt' )
@@ -826,17 +834,18 @@ def remove_bias(name='bias_correct'):
826834 >>> bias.run() # doctest: +SKIP
827835
828836 """
829- inputnode = pe .Node (niu .IdentityInterface (fields = [ 'in_file' , 'in_bval' ,
830- 'in_mask' ]), name = 'inputnode' )
837+ inputnode = pe .Node (niu .IdentityInterface (
838+ fields = [ 'in_file' , 'in_bval' , 'in_mask' ]), name = 'inputnode' )
831839
832840 outputnode = pe .Node (niu .IdentityInterface (fields = ['out_file' ]),
833841 name = 'outputnode' )
834842
835- avg_b0 = pe .Node (niu .Function (input_names = ['in_dwi' , 'in_bval' ],
836- output_names = ['out_file' ], function = b0_average ),
837- name = 'b0_avg' )
838- n4 = pe .Node (ants .N4BiasFieldCorrection (dimension = 3 ,
839- save_bias = True , bspline_fitting_distance = 600 ), name = 'Bias_b0' )
843+ avg_b0 = pe .Node (niu .Function (
844+ input_names = ['in_dwi' , 'in_bval' ], output_names = ['out_file' ],
845+ function = b0_average ), name = 'b0_avg' )
846+ n4 = pe .Node (ants .N4BiasFieldCorrection (
847+ dimension = 3 , save_bias = True , bspline_fitting_distance = 600 ),
848+ name = 'Bias_b0' )
840849 split = pe .Node (fsl .Split (dimension = 't' ), name = 'SplitDWIs' )
841850 mult = pe .MapNode (fsl .MultiImageMaths (op_string = '-div %s' ),
842851 iterfield = ['in_file' ], name = 'RemoveBiasOfDWIs' )
@@ -860,6 +869,11 @@ def remove_bias(name='bias_correct'):
860869 return wf
861870
862871
872+ def _eff_t_echo (echospacing , acc_factor ):
873+ eff_echo = echospacing / (1.0 * acc_factor )
874+ return eff_echo
875+
876+
863877def _checkrnum (ref_num ):
864878 from nipype .interfaces .base import isdefined
865879 if (ref_num is None ) or not isdefined (ref_num ):
0 commit comments