@@ -266,6 +266,92 @@ 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: change back to 5 when running for real
268
268
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
+
269
355
merge = pe .Node (fsl .Merge (dimension = 't' ), name = "mergeAPPA" )
270
356
merge .inputs .in_files = [dwi_file_AP , dwi_file_PA ]
271
357
wf .connect (merge , 'merged_file' , prep , 'inputnode.alt_file' )
@@ -430,6 +516,7 @@ def reportNodeFunc(dwi_corrected_file, eddy_rms, eddy_report,
430
516
431
517
wf .connect (reportNode , 'report' , datasink , 'dmriprep.report.@report' )
432
518
519
+ wf .write_graph ()
433
520
wf .run ()
434
521
435
522
copyfile (bval_file , op .join (
0 commit comments