@@ -12,6 +12,41 @@ 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" ):
16
+ """Creates a workflow that chains the necessary pipelines to
17
+ correct for motion, eddy currents, and susceptibility
18
+ artifacts in EPI dMRI sequences.
19
+
20
+ Example
21
+ -------
22
+
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. =
32
+ >>> nipype_dmri_preprocess.run() # doctest: +SKIP
33
+
34
+ Inputs::
35
+
36
+ inputnode.
37
+
38
+ Outputs::
39
+
40
+ outputnode.dmri_corrected
41
+
42
+ """
43
+
44
+ pipeline = pe .Workflow (name = name )
45
+
46
+ return pipeline
47
+
48
+
49
+
15
50
def create_bedpostx_pipeline (name = "bedpostx" ):
16
51
"""Creates a pipeline that does the same as bedpostx script from FSL -
17
52
calculates diffusion model parameters (distributions not MLE) voxelwise for
@@ -168,6 +203,61 @@ def create_bedpostx_pipeline(name="bedpostx"):
168
203
])
169
204
return bedpostx
170
205
206
+ def create_motion_correct_pipeline (name = "motion_correct" ):
207
+ """Creates a pipeline that corrects for motion artifact in dMRI sequences.
208
+ It takes a series of diffusion weighted images and rigidly corregisters
209
+ them to one reference image. Finally, the b-matrix is rotated accordingly,
210
+ making use of the rotation matrix obtained by FLIRT.
211
+
212
+ Example
213
+ -------
214
+
215
+ >>> nipype_motioncorrect = create_motion_correct_pipeline("nipype_motioncorrect")
216
+ >>> nipype_motioncorrect.inputs.inputnode.in_file = 'diffusion.nii'
217
+ >>> nipype_motioncorrect.inputs.inputnode.in_bvec = 'diffusion.bvec'
218
+ >>> nipype_motioncorrect.inputs.inputnode.ref_num = 0
219
+ >>> nipype_motioncorrect.run() # doctest: +SKIP
220
+
221
+ Inputs::
222
+
223
+ inputnode.in_file
224
+ inputnode.ref_num
225
+ inputnode.in_bvec
226
+
227
+ Outputs::
228
+
229
+ outputnode.motion_corrected
230
+ """
231
+
232
+ inputnode = pe .Node (interface = util .IdentityInterface (fields = ["in_file" , "ref_num" ,"in_bvec" ]),
233
+ name = "inputnode" )
234
+
235
+ pipeline = pe .Workflow (name = name )
236
+
237
+ split = pe .Node (fsl .Split (dimension = 't' ), name = "split" )
238
+ pick_ref = pe .Node (util .Select (), name = "pick_ref" )
239
+ coregistration = pe .MapNode (fsl .FLIRT (no_search = True , padding_size = 1 , dof = 6 ), name = "coregistration" , iterfield = ["in_file" ])
240
+ rotate_bvecs = pe .Node ( util .Function ( input_names = ["in_bvec" , "in_matrix" ], output_names = ["out_file" ], function = _rotate_bvecs ), name = "rotate_b_matrix" )
241
+ merge = pe .Node (fsl .Merge (dimension = "t" ), name = "merge" )
242
+ outputnode = pe .Node (interface = util .IdentityInterface (fields = ["motion_corrected" ,"out_bvec" ]),
243
+ name = "outputnode" )
244
+
245
+ pipeline .connect ([
246
+ (inputnode , split , [("in_file" , "in_file" )])
247
+ ,(split , pick_ref , [("out_files" , "inlist" )])
248
+ ,(inputnode , pick_ref , [("ref_num" , "index" )])
249
+ ,(split , coregistration , [("out_files" , "in_file" )])
250
+ ,(inputnode , rotate_bvecs , [("in_bvec" ,"in_bvec" )])
251
+ ,(coregistration , rotate_bvecs , [("out_matrix_file" ,"in_matrix" )])
252
+ ,(pick_ref , coregistration , [("out" , "reference" )])
253
+ ,(coregistration , merge , [("out_file" , "in_files" )])
254
+ ,(merge , outputnode , [("merged_file" , "motion_corrected" )])
255
+ ,(rotate_bvecs , outputnode , [("out_file" ,"out_bvec" )])
256
+ ])
257
+
258
+ return pipeline
259
+
260
+
171
261
def create_eddy_correct_pipeline (name = "eddy_correct" ):
172
262
"""Creates a pipeline that replaces eddy_correct script in FSL. It takes a
173
263
series of diffusion weighted images and linearly corregisters them to one
@@ -197,30 +287,26 @@ def create_eddy_correct_pipeline(name="eddy_correct"):
197
287
pipeline = pe .Workflow (name = name )
198
288
199
289
split = pe .Node (fsl .Split (dimension = 't' ), name = "split" )
200
- pipeline .connect ([(inputnode , split , [("in_file" , "in_file" )])])
201
-
202
290
pick_ref = pe .Node (util .Select (), name = "pick_ref" )
203
- pipeline .connect ([(split , pick_ref , [("out_files" , "inlist" )]),
204
- (inputnode , pick_ref , [("ref_num" , "index" )])])
205
-
206
- coregistration = pe .MapNode (fsl .FLIRT (no_search = True , padding_size = 1 ), name = "coregistration" , iterfield = ["in_file" ])
207
- pipeline .connect ([(split , coregistration , [("out_files" , "in_file" )]),
208
- (pick_ref , coregistration , [("out" , "reference" )])])
209
-
291
+ coregistration = pe .MapNode (fsl .FLIRT (no_search = True , padding_size = 1 ), name = "coregistration" , iterfield = ["in_file" ])
210
292
merge = pe .Node (fsl .Merge (dimension = "t" ), name = "merge" )
211
- pipeline .connect ([(coregistration , merge , [("out_file" , "in_files" )])
212
- ])
213
-
214
293
outputnode = pe .Node (interface = util .IdentityInterface (fields = ["eddy_corrected" ]),
215
294
name = "outputnode" )
216
295
217
- pipeline .connect ([(merge , outputnode , [("merged_file" , "eddy_corrected" )])])
218
-
296
+ pipeline .connect ([
297
+ (inputnode , split , [("in_file" , "in_file" )])
298
+ ,(split , pick_ref , [("out_files" , "inlist" )])
299
+ ,(inputnode , pick_ref , [("ref_num" , "index" )])
300
+ ,(split , coregistration , [("out_files" , "in_file" )])
301
+ ,(pick_ref , coregistration , [("out" , "reference" )])
302
+ ,(coregistration , merge , [("out_file" , "in_files" )])
303
+ ,(merge , outputnode , [("merged_file" , "eddy_corrected" )])
304
+ ])
219
305
return pipeline
220
306
221
- def create_epi_correct_pipeline (name = "epi_correct " , register_to_ref = False ):
307
+ def create_susceptibility_correct_pipeline (name = "susceptibility_correct " , register_to_ref = False ):
222
308
""" Replaces the epidewarp.fsl script (http://www.nmr.mgh.harvard.edu/~greve/fbirn/b0/epidewarp.fsl)
223
- for EPI distortion correction with the fieldmap information in
309
+ for susceptibility distortion correction in EPI sequences with the fieldmap information in
224
310
dMRI and fMRI (Jezzard et al., MRM 1995 ) using FSL's FUGUE.
225
311
226
312
Example
@@ -271,9 +357,6 @@ def create_epi_correct_pipeline(name="epi_correct", register_to_ref=False ):
271
357
272
358
pipeline = pe .Workflow (name = name )
273
359
274
-
275
- matrix_file = os .path .abspath ( './flirt.txt' )
276
-
277
360
# Keep first frame from magnitude
278
361
select_mag = pe .Node ( interface = fsl .utils .ExtractROI (t_size = 1 ,t_min = 0 ), name = "select_magnitude" )
279
362
@@ -372,6 +455,39 @@ def create_epi_correct_pipeline(name="epi_correct", register_to_ref=False ):
372
455
373
456
return pipeline
374
457
458
+ def _rotate_bvecs ( in_bvec , in_matrix ):
459
+ import os
460
+ import numpy as np
461
+
462
+ name ,fext = os .path .splitext ( os .path .basename (in_bvec ) )
463
+ if fext == '.gz' : name ,_ = os .path .splitext (name )
464
+ out_file = os .path .abspath ( './%s_rotated.bvec' % name )
465
+ bvecs = np .loadtxt ( in_bvec )
466
+ new_bvecs = [ bvecs [:,0 ] ]
467
+
468
+ for i ,vol_matrix in enumerate (in_matrix [1 ::]):
469
+ bvec = np .matrix ( bvecs [:,i ] )
470
+ rot = np .matrix (np .loadtxt ( vol_matrix )[0 :3 ,0 :3 ])
471
+ new_bvecs .append ( (np .array ( rot * bvec .T ).T )[0 ] )
472
+ np .savetxt ( out_file , np .array (new_bvecs ).T , fmt = '%0.15f' )
473
+ return out_file
474
+
475
+ def _cat_logs ( in_files ):
476
+ import shutil
477
+ import os
478
+
479
+ name ,fext = os .path .splitext ( os .path .basename (in_files [0 ]) )
480
+ if fext == '.gz' : name ,_ = os .path .splitext (name )
481
+ out_file = os .path .abspath ( './%s_ecclog.log' % name )
482
+ out_str = ""
483
+ with open ( out_file , 'wb' ) as totallog :
484
+ for i ,fname in enumerate (in_files ):
485
+ totallog .write ( "\n \n preprocessing %d\n " % i )
486
+ with open (fname ) as inlog :
487
+ for line in inlog :
488
+ totallog .write (line )
489
+ return out_file
490
+
375
491
def _compute_dwelltime ( dwell_time = 0.68 , is_parallel = False , is_reverse_encoding = False ):
376
492
if is_parallel :
377
493
dwell_time *= 0.5
0 commit comments