@@ -266,7 +266,7 @@ def run_dmriprep_pe(dwi_file, dwi_file_AP, dwi_file_PA, bvec_file, bval_file,
266
266
eddy .inputs .repol = True
267
267
eddy .inputs .niter = 1 # TODO: make this a parameter to the function with default 5
268
268
269
- def drop_outliers_fn (outlier_report , threshold , dwi_file ):
269
+ def id_outliers_fn (outlier_report , threshold , dwi_file ):
270
270
"""Get list of scans that exceed threshold for number of outliers
271
271
272
272
Parameters
@@ -309,75 +309,116 @@ def num_outliers(scan, outliers):
309
309
return len ([d for d in outliers if d ['scan' ] == scan ])
310
310
311
311
if 0 < threshold < 1 :
312
- threshold *= threshold * nib .load (dwi_file ).shape [2 ]
312
+ threshold *= nib .load (dwi_file ).shape [2 ]
313
313
314
314
drop_scans = np .array ([
315
315
s for s in scans
316
316
if num_outliers (s , outliers ) > threshold
317
317
])
318
318
319
- return drop_scans
319
+ outpath = op .abspath ("dropped_scans.txt" )
320
+ np .savetxt (outpath , drop_scans , fmt = "%d" )
320
321
321
- drop_outliers_node = pe .Node (niu .Function (
322
+ return drop_scans , outpath
323
+
324
+ id_outliers_node = pe .Node (niu .Function (
322
325
input_names = ["outlier_report" , "threshold" , "dwi_file" ],
323
- output_names = ["drop_scans" ],
324
- function = drop_outliers_fn ),
325
- name = "drop_outliers_node "
326
+ output_names = ["drop_scans" , "outpath" ],
327
+ function = id_outliers_fn ),
328
+ name = "id_outliers_node "
326
329
)
327
330
328
- drop_outliers_node .inputs .threshold = 0.02
329
- drop_outliers_node .inputs .dwi_file = dwi_file
331
+ # TODO: make this a parameter to the function
332
+ id_outliers_node .inputs .threshold = 0.02
333
+ id_outliers_node .inputs .dwi_file = dwi_file
330
334
wf .connect (prep , "fsl_eddy.out_outlier_report" ,
331
- drop_outliers_node , "outlier_report" )
335
+ id_outliers_node , "outlier_report" )
336
+
337
+ merge = pe .Node (fsl .Merge (dimension = 't' ), name = "mergeAPPA" )
338
+ merge .inputs .in_files = [dwi_file_AP , dwi_file_PA ]
339
+ wf .connect (merge , 'merged_file' , prep , 'inputnode.alt_file' )
340
+
341
+ fslroi = pe .Node (fsl .ExtractROI (t_min = 0 , t_size = 1 ), name = "fslroi" )
342
+ wf .connect (prep , "outputnode.out_file" , fslroi , "in_file" )
332
343
333
- def save_outlier_list_fn (drop_scans ):
334
- """Save list of outlier scans to file
344
+ bbreg = pe .Node (fs .BBRegister (contrast_type = "t2" , init = "coreg" ,
345
+ out_fsl_file = True ,
346
+ subjects_dir = subjects_dir ,
347
+ epi_mask = True ),
348
+ name = "bbreg" )
349
+ bbreg .inputs .subject_id = 'freesurfer' # bids_sub_name
350
+ wf .connect (fslroi , "roi_file" , bbreg , "source_file" )
351
+
352
+ def drop_outliers_fn (in_file , in_bval , in_bvec , drop_scans ):
353
+ """Drop outlier volumes from dwi file
335
354
336
355
Parameters
337
356
----------
357
+ in_file: string
358
+ Path to nii dwi file to drop outlier volumes from
359
+
360
+ in_bval: string
361
+ Path to bval file to drop outlier volumes from
362
+
363
+ in_bvec: string
364
+ Path to bvec file to drop outlier volumes from
365
+
338
366
drop_scans: numpy.ndarray
339
- Path to the fsl_eddy outlier report
367
+ List of scan indices to drop
340
368
341
369
Returns
342
370
-------
343
- outpath: string
344
- Path to output file where list is saved
371
+ out_file: string
372
+ Path to "thinned" output dwi file
373
+
374
+ out_bval: string
375
+ Path to "thinned" output bval file
376
+
377
+ out_bvec: string
378
+ Path to "thinned" output bvec file
345
379
"""
380
+ import nibabel as nib
346
381
import numpy as np
347
382
import os .path as op
348
- outpath = op .abspath ("dropped_scans.txt" )
349
- np .savetxt (outpath , drop_scans , fmt = "%d" )
350
- return outpath
351
383
352
- save_outlier_list_node = pe .Node (niu .Function (
353
- input_names = ["drop_scans" ],
354
- output_names = ["outpath" ],
355
- function = save_outlier_list_fn ),
356
- name = "save_outlier_list_node"
357
- )
384
+ img = nib .load (op .abspath (in_file ))
385
+ img_data = img .get_fdata ()
386
+ img_data_thinned = np .delete (img_data , drop_scans , axis = 3 )
387
+ img_thinned = nib .Nifti1Image (img_data_thinned .astype (np .float64 ), img .affine )
358
388
359
- wf .connect (drop_outliers_node , "drop_scans" ,
360
- save_outlier_list_node , "drop_scans" )
389
+ root , ext1 = op .splitext (in_file )
390
+ root , ext0 = op .splitext (root )
391
+ out_file = '' .join ([root + "_thinned" , ext0 , ext1 ])
392
+ nib .save (img_thinned , op .abspath (out_file ))
361
393
362
- merge = pe .Node (fsl .Merge (dimension = 't' ), name = "mergeAPPA" )
363
- merge .inputs .in_files = [dwi_file_AP , dwi_file_PA ]
364
- wf .connect (merge , 'merged_file' , prep , 'inputnode.alt_file' )
394
+ bval = np .loadtxt (in_bval )
395
+ bval_thinned = np .delete (bval , drop_scans , axis = 0 )
396
+ out_bval = '_thinned' .join (op .splitext (in_bval ))
397
+ np .savetxt (out_bval , bval_thinned )
365
398
366
- fslroi = pe .Node (fsl .ExtractROI (t_min = 0 , t_size = 1 ), name = "fslroi" )
367
- wf .connect (prep , "outputnode.out_file" , fslroi , "in_file" )
399
+ bvec = np .loadtxt (in_bvec )
400
+ bvec_thinned = np .delete (bvec , drop_scans , axis = 1 )
401
+ out_bvec = '_thinned' .join (op .splitext (in_bvec ))
402
+ np .savetxt (out_bvec , bvec_thinned )
368
403
369
- bbreg = pe .Node (fs .BBRegister (contrast_type = "t2" , init = "coreg" ,
370
- out_fsl_file = True ,
371
- subjects_dir = subjects_dir ,
372
- epi_mask = True ),
373
- name = "bbreg" )
374
- bbreg .inputs .subject_id = 'freesurfer' # bids_sub_name
375
- wf .connect (fslroi , "roi_file" , bbreg , "source_file" )
404
+ return out_file , out_bval , out_bvec
405
+
406
+ drop_outliers_node = pe .Node (niu .Function (
407
+ input_names = ["in_file" , "in_bval" , "in_bvec" , "drop_scans" ],
408
+ output_names = ["out_file" , "out_bval" , "out_bvec" ],
409
+ function = drop_outliers_fn ),
410
+ name = "drop_outliers_node"
411
+ )
412
+
413
+ wf .connect (id_outliers_node , "drop_scans" , drop_outliers_node , "drop_scans" )
414
+ wf .connect (prep , "outputnode.out_file" , drop_outliers_node , "in_file" )
415
+ drop_outliers_node .inputs .in_bval = bval_file
416
+ wf .connect (prep , "outputnode.out_bvec" , drop_outliers_node , "in_bvec" )
376
417
377
418
get_tensor = pe .Node (DTI (), name = "dipy_tensor" )
378
- wf .connect (prep , "outputnode. out_file" , get_tensor , "in_file" )
379
- get_tensor . inputs . in_bval = bval_file
380
- wf .connect (prep , "outputnode. out_bvec" , get_tensor , "in_bvec" )
419
+ wf .connect (drop_outliers_node , "out_file" , get_tensor , "in_file" )
420
+ wf . connect ( drop_outliers_node , "out_bval" , get_tensor , "in_bval" )
421
+ wf .connect (drop_outliers_node , "out_bvec" , get_tensor , "in_bvec" )
381
422
382
423
scale_tensor = pe .Node (name = 'scale_tensor' , interface = fsl .BinaryMaths ())
383
424
scale_tensor .inputs .operation = 'mul'
@@ -464,6 +505,10 @@ def get_orig(subjects_dir, sub):
464
505
("derivatives/dmriprep" , "derivatives/{}/dmriprep" .format (bids_sub_name ))
465
506
]
466
507
508
+ wf .connect (drop_outliers_node , "out_file" , datasink , "dmriprep.dwi.@thinned" )
509
+ wf .connect (drop_outliers_node , "out_bval" , datasink , "dmriprep.dwi.@bval_thinned" )
510
+ wf .connect (drop_outliers_node , "out_bvec" , datasink , "dmriprep.dwi.@bvec_thinned" )
511
+
467
512
wf .connect (prep , "outputnode.out_file" , datasink , "dmriprep.dwi.@corrected" )
468
513
wf .connect (prep , "outputnode.out_bvec" , datasink , "dmriprep.dwi.@rotated" )
469
514
wf .connect (prep , "fsl_eddy.out_parameter" ,
@@ -478,7 +523,7 @@ def get_orig(subjects_dir, sub):
478
523
wf .connect (prep , "fsl_eddy.out_shell_alignment_parameters" ,
479
524
datasink , "dmriprep.qc.@eddyparamsshellalign" )
480
525
481
- wf .connect (save_outlier_list_node , "outpath" , datasink , "dmriprep.qc.@droppedscans" )
526
+ wf .connect (id_outliers_node , "outpath" , datasink , "dmriprep.qc.@droppedscans" )
482
527
483
528
wf .connect (get_tensor , "out_file" , datasink , "dmriprep.dti.@tensor" )
484
529
wf .connect (get_tensor , "fa_file" , datasink , "dmriprep.dti.@fa" )
0 commit comments