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

Commit 9a02b6d

Browse files
author
Adam Richie-Halford
committed
Add node to identifier scans with too many outlier slices
1 parent 48c2de8 commit 9a02b6d

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

dmriprep/run.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,92 @@ 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: change back to 5 when running for real
268268

269+
def drop_eddy_outliers(outlier_report, threshold):
270+
"""Get list of scans that exceed threshold for number of outliers
271+
272+
Parameters
273+
----------
274+
outlier_report: string
275+
Path to the fsl_eddy outlier report
276+
277+
threshold: int or float
278+
If threshold is an int, it is treated as number of allowed outlier
279+
slices. If threshold is a float between 0 and 1 (exclusive), it is
280+
treated the fraction of allowed outlier slices before we drop the
281+
whole volume. Float param in not yet implemented
282+
283+
Returns
284+
-------
285+
drop_scans: numpy.ndarray
286+
List of scan indices to drop
287+
"""
288+
import numpy as np
289+
import os.path as op
290+
import parse
291+
with open(op.abspath(outlier_report), 'r') as fp:
292+
lines = fp.readlines()
293+
294+
p = parse.compile(
295+
"Slice {slice:d} in scan {scan:d} is an outlier with "
296+
"mean {mean_sd:f} standard deviations off, and mean "
297+
"squared {mean_sq_sd:f} standard deviations off."
298+
)
299+
300+
outliers = [p.parse(l).named for l in lines]
301+
scans = {d['scan'] for d in outliers}
302+
303+
def num_outliers(scan, outliers):
304+
return len([d for d in outliers if d['scan'] == scan])
305+
306+
drop_scans = np.array([
307+
s for s in scans
308+
if num_outliers(s, outliers) > threshold
309+
])
310+
311+
return drop_scans
312+
313+
drop_outliers = pe.Node(niu.Function(
314+
input_names=["outlier_report", "threshold"],
315+
output_names=["drop_scans"],
316+
function=drop_eddy_outliers),
317+
name="drop_outliers"
318+
)
319+
320+
drop_outliers.inputs.threshold = 1
321+
wf.connect(prep, "fsl_eddy.out_outlier_report",
322+
drop_outliers, "outlier_report")
323+
324+
def save_outlier_list(drop_scans, outpath):
325+
"""Save list of outlier scans to file
326+
327+
Parameters
328+
----------
329+
drop_scans: numpy.ndarray
330+
Path to the fsl_eddy outlier report
331+
332+
outpath: string
333+
Path to output file where list is saved
334+
335+
Returns
336+
-------
337+
outpath: string
338+
Path to output file where list is saved
339+
"""
340+
import numpy as np
341+
np.savetxt(outpath, drop_scans, fmt="%d")
342+
return outpath
343+
344+
save_drop_scans = pe.Node(niu.Function(
345+
input_names=["drop_scans", "outpath"],
346+
output_names=["outpath"],
347+
function=save_outlier_list),
348+
name="save_drop_scans"
349+
)
350+
351+
wf.connect(drop_outliers, "drop_scans",
352+
save_drop_scans, "drop_scans")
353+
save_drop_scans.inputs.outpath = op.join(working_dir, 'outlier_report.txt')
354+
269355
merge = pe.Node(fsl.Merge(dimension='t'), name="mergeAPPA")
270356
merge.inputs.in_files = [dwi_file_AP, dwi_file_PA]
271357
wf.connect(merge, 'merged_file', prep, 'inputnode.alt_file')
@@ -430,6 +516,7 @@ def reportNodeFunc(dwi_corrected_file, eddy_rms, eddy_report,
430516

431517
wf.connect(reportNode, 'report', datasink, 'dmriprep.report.@report')
432518

519+
wf.write_graph()
433520
wf.run()
434521

435522
copyfile(bval_file, op.join(

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
'Click>=6.0',
1616
'nipype',
1717
'dipy',
18+
'parse',
1819
]
1920

2021
setup_requirements = ['pytest-runner', ]

0 commit comments

Comments
 (0)