Skip to content
This repository was archived by the owner on Dec 27, 2022. It is now read-only.

Commit f6a1b11

Browse files
author
Adam Richie-Halford
committed
Add drop_outliers_node and consolidate outputs
1 parent af16c3f commit f6a1b11

File tree

1 file changed

+87
-42
lines changed

1 file changed

+87
-42
lines changed

dmriprep/run.py

Lines changed: 87 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ def run_dmriprep_pe(dwi_file, dwi_file_AP, dwi_file_PA, bvec_file, bval_file,
266266
eddy.inputs.repol = True
267267
eddy.inputs.niter = 1 # TODO: make this a parameter to the function with default 5
268268

269-
def drop_outliers_fn(outlier_report, threshold, dwi_file):
269+
def id_outliers_fn(outlier_report, threshold, dwi_file):
270270
"""Get list of scans that exceed threshold for number of outliers
271271
272272
Parameters
@@ -309,75 +309,116 @@ def num_outliers(scan, outliers):
309309
return len([d for d in outliers if d['scan'] == scan])
310310

311311
if 0 < threshold < 1:
312-
threshold *= threshold * nib.load(dwi_file).shape[2]
312+
threshold *= nib.load(dwi_file).shape[2]
313313

314314
drop_scans = np.array([
315315
s for s in scans
316316
if num_outliers(s, outliers) > threshold
317317
])
318318

319-
return drop_scans
319+
outpath = op.abspath("dropped_scans.txt")
320+
np.savetxt(outpath, drop_scans, fmt="%d")
320321

321-
drop_outliers_node = pe.Node(niu.Function(
322+
return drop_scans, outpath
323+
324+
id_outliers_node = pe.Node(niu.Function(
322325
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"
326329
)
327330

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
330334
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")
332343

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
335354
336355
Parameters
337356
----------
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+
338366
drop_scans: numpy.ndarray
339-
Path to the fsl_eddy outlier report
367+
List of scan indices to drop
340368
341369
Returns
342370
-------
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
345379
"""
380+
import nibabel as nib
346381
import numpy as np
347382
import os.path as op
348-
outpath = op.abspath("dropped_scans.txt")
349-
np.savetxt(outpath, drop_scans, fmt="%d")
350-
return outpath
351383

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)
358388

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))
361393

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)
365398

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)
368403

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")
376417

377418
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")
381422

382423
scale_tensor = pe.Node(name='scale_tensor', interface=fsl.BinaryMaths())
383424
scale_tensor.inputs.operation = 'mul'
@@ -464,6 +505,10 @@ def get_orig(subjects_dir, sub):
464505
("derivatives/dmriprep", "derivatives/{}/dmriprep".format(bids_sub_name))
465506
]
466507

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+
467512
wf.connect(prep, "outputnode.out_file", datasink, "dmriprep.dwi.@corrected")
468513
wf.connect(prep, "outputnode.out_bvec", datasink, "dmriprep.dwi.@rotated")
469514
wf.connect(prep, "fsl_eddy.out_parameter",
@@ -478,7 +523,7 @@ def get_orig(subjects_dir, sub):
478523
wf.connect(prep, "fsl_eddy.out_shell_alignment_parameters",
479524
datasink, "dmriprep.qc.@eddyparamsshellalign")
480525

481-
wf.connect(save_outlier_list_node, "outpath", datasink, "dmriprep.qc.@droppedscans")
526+
wf.connect(id_outliers_node, "outpath", datasink, "dmriprep.qc.@droppedscans")
482527

483528
wf.connect(get_tensor, "out_file", datasink, "dmriprep.dti.@tensor")
484529
wf.connect(get_tensor, "fa_file", datasink, "dmriprep.dti.@fa")

0 commit comments

Comments
 (0)