From 42e8525cd1743bc52ec7f3beaf7518c041cecd6a Mon Sep 17 00:00:00 2001 From: jdkent Date: Tue, 17 Oct 2017 01:07:12 -0500 Subject: [PATCH 1/3] ENH: allow create_susan_smooth to take in a list of fwhms --- nipype/workflows/fmri/fsl/preprocess.py | 64 +++++++++++++++++++++---- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/nipype/workflows/fmri/fsl/preprocess.py b/nipype/workflows/fmri/fsl/preprocess.py index ea67667294..921ceb5119 100644 --- a/nipype/workflows/fmri/fsl/preprocess.py +++ b/nipype/workflows/fmri/fsl/preprocess.py @@ -757,7 +757,7 @@ def create_featreg_preproc(name='featpreproc', highpass=True, whichvol='middle', return featpreproc -def create_susan_smooth(name="susan_smooth", separate_masks=True): +def create_susan_smooth(name="susan_smooth", separate_masks=True, list_fwhms=False): """Create a SUSAN smoothing workflow Parameters @@ -767,11 +767,12 @@ def create_susan_smooth(name="susan_smooth", separate_masks=True): name : name of workflow (default: susan_smooth) separate_masks : separate masks for each run + list_fwhms : multiple full wide half maximum smoothing kernels Inputs:: inputnode.in_files : functional runs (filename or list of filenames) - inputnode.fwhm : fwhm for smoothing with SUSAN + inputnode.fwhm : fwhm for smoothing with SUSAN (float or list of floats) inputnode.mask_file : mask used for estimating SUSAN thresholds (but not for smoothing) Outputs:: @@ -788,6 +789,18 @@ def create_susan_smooth(name="susan_smooth", separate_masks=True): >>> smooth.run() # doctest: +SKIP """ + def cartesian_product(fwhms, in_files, mask_files, merge_out, median_out): + if type(in_files) == str: + in_files = [in_files] + if type(mask_files) == str: + mask_files = [mask_files] + multi_in_files = [in_file for in_file in in_files for fwhm in fwhms] + multi_mask_files = [mask_file for mask_file in mask_files for fwhm in fwhms] + multi_fwhms = [fwhm for fwhm in fwhms for in_file in in_files] + multi_merge_out = [merge for merge in merge_out for fwhm in fwhms] + multi_median_out = [median for median in median_out for fwhm in fwhms] + + return multi_in_files, multi_mask_files, multi_fwhms, multi_merge_out, multi_median_out susan_smooth = pe.Workflow(name=name) @@ -806,10 +819,27 @@ def create_susan_smooth(name="susan_smooth", separate_masks=True): of the median value for each run and a mask consituting the mean functional """ - - smooth = pe.MapNode(interface=fsl.SUSAN(), - iterfield=['in_file', 'brightness_threshold', 'usans'], - name='smooth') + if list_fwhms: + multi_inputs = pe.Node(util.Function(input_names=['fwhms', + 'in_files', + 'mask_files', + 'merge_out', + 'median_out'], + output_names=['multi_in_files', + 'multi_mask_files', + 'multi_fwhms', + 'multi_merge_out', + 'multi_median_out'], + function=cartesian_product), + name='multi_inputs') + + smooth = pe.MapNode(interface=fsl.SUSAN(), + iterfield=['in_file', 'brightness_threshold', 'usans', 'fwhm'], + name='smooth') + else: + smooth = pe.MapNode(interface=fsl.SUSAN(), + iterfield=['in_file', 'brightness_threshold', 'usans'], + name='smooth') """ Determine the median value of the functional runs using the mask @@ -865,10 +895,24 @@ def create_susan_smooth(name="susan_smooth", separate_masks=True): """ Define a function to get the brightness threshold for SUSAN """ - susan_smooth.connect(inputnode, 'fwhm', smooth, 'fwhm') - susan_smooth.connect(inputnode, 'in_files', smooth, 'in_file') - susan_smooth.connect(median, ('out_stat', getbtthresh), smooth, 'brightness_threshold') - susan_smooth.connect(merge, ('out', getusans), smooth, 'usans') + # if you are going to iterate over multiple values of fwhm + if list_fwhms: + susan_smooth.connect([ + (inputnode, multi_inputs, [('in_files', 'in_files'), + ('fwhm', 'fwhms'), + ('mask_file', 'mask_files')]), + ]) + susan_smooth.connect(median, ('out_stat', getbtthresh), multi_inputs, 'median_out') + susan_smooth.connect(merge, ('out', getusans), multi_inputs, 'merge_out') + susan_smooth.connect(multi_inputs, 'multi_fwhms', smooth, 'fwhm') + susan_smooth.connect(multi_inputs, 'multi_in_files', smooth, 'in_file') + susan_smooth.connect(multi_inputs, 'multi_median_out', smooth, 'brightness_threshold') + susan_smooth.connect(multi_inputs, 'multi_merge_out', smooth, 'usans') + else: + susan_smooth.connect(inputnode, 'in_files', smooth, 'in_file') + susan_smooth.connect(inputnode, 'fwhm', smooth, 'fwhm') + susan_smooth.connect(median, ('out_stat', getbtthresh), smooth, 'brightness_threshold') + susan_smooth.connect(merge, ('out', getusans), smooth, 'usans') outputnode = pe.Node(interface=util.IdentityInterface(fields=['smoothed_files']), name='outputnode') From 11d6a5528fd429f90b30803f1626220a324e532d Mon Sep 17 00:00:00 2001 From: jdkent Date: Tue, 17 Oct 2017 01:11:39 -0500 Subject: [PATCH 2/3] ENH: added comment --- nipype/workflows/fmri/fsl/preprocess.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nipype/workflows/fmri/fsl/preprocess.py b/nipype/workflows/fmri/fsl/preprocess.py index 921ceb5119..4e75d903c7 100644 --- a/nipype/workflows/fmri/fsl/preprocess.py +++ b/nipype/workflows/fmri/fsl/preprocess.py @@ -789,6 +789,7 @@ def create_susan_smooth(name="susan_smooth", separate_masks=True, list_fwhms=Fal >>> smooth.run() # doctest: +SKIP """ + # replaces the functionality of a "for loop" def cartesian_product(fwhms, in_files, mask_files, merge_out, median_out): if type(in_files) == str: in_files = [in_files] From ed5e1b9f69a6d0d0dbadcf98df228c0f3ceecb07 Mon Sep 17 00:00:00 2001 From: jdkent Date: Tue, 17 Oct 2017 11:51:45 -0500 Subject: [PATCH 3/3] FIX: effigies review --- nipype/workflows/fmri/fsl/preprocess.py | 89 ++++++++++--------------- 1 file changed, 35 insertions(+), 54 deletions(-) diff --git a/nipype/workflows/fmri/fsl/preprocess.py b/nipype/workflows/fmri/fsl/preprocess.py index 4e75d903c7..aa8ac03673 100644 --- a/nipype/workflows/fmri/fsl/preprocess.py +++ b/nipype/workflows/fmri/fsl/preprocess.py @@ -4,7 +4,6 @@ from __future__ import division import os - from ....interfaces import fsl as fsl # fsl from ....interfaces import utility as util # utility from ....pipeline import engine as pe # pypeline engine @@ -757,7 +756,7 @@ def create_featreg_preproc(name='featpreproc', highpass=True, whichvol='middle', return featpreproc -def create_susan_smooth(name="susan_smooth", separate_masks=True, list_fwhms=False): +def create_susan_smooth(name="susan_smooth", separate_masks=True): """Create a SUSAN smoothing workflow Parameters @@ -767,7 +766,6 @@ def create_susan_smooth(name="susan_smooth", separate_masks=True, list_fwhms=Fal name : name of workflow (default: susan_smooth) separate_masks : separate masks for each run - list_fwhms : multiple full wide half maximum smoothing kernels Inputs:: @@ -790,18 +788,18 @@ def create_susan_smooth(name="susan_smooth", separate_masks=True, list_fwhms=Fal """ # replaces the functionality of a "for loop" - def cartesian_product(fwhms, in_files, mask_files, merge_out, median_out): - if type(in_files) == str: - in_files = [in_files] - if type(mask_files) == str: - mask_files = [mask_files] - multi_in_files = [in_file for in_file in in_files for fwhm in fwhms] - multi_mask_files = [mask_file for mask_file in mask_files for fwhm in fwhms] - multi_fwhms = [fwhm for fwhm in fwhms for in_file in in_files] - multi_merge_out = [merge for merge in merge_out for fwhm in fwhms] - multi_median_out = [median for median in median_out for fwhm in fwhms] - - return multi_in_files, multi_mask_files, multi_fwhms, multi_merge_out, multi_median_out + def cartesian_product(fwhms, in_files, usans, btthresh): + from nipype.utils.filemanip import filename_to_list + # ensure all inputs are lists + in_files = filename_to_list(in_files) + fwhms = [fwhms] if isinstance(fwhms, (int, float)) else fwhms + # create cartesian product lists (s_ = single element of list) + cart_in_file = [s_in_file for s_in_file in in_files for s_fwhm in fwhms] + cart_fwhm = [s_fwhm for s_in_file in in_files for s_fwhm in fwhms] + cart_usans = [s_usans for s_usans in usans for s_fwhm in fwhms] + cart_btthresh = [s_btthresh for s_btthresh in btthresh for s_fwhm in fwhms] + + return cart_in_file, cart_fwhm, cart_usans, cart_btthresh susan_smooth = pe.Workflow(name=name) @@ -820,27 +818,17 @@ def cartesian_product(fwhms, in_files, mask_files, merge_out, median_out): of the median value for each run and a mask consituting the mean functional """ - if list_fwhms: - multi_inputs = pe.Node(util.Function(input_names=['fwhms', - 'in_files', - 'mask_files', - 'merge_out', - 'median_out'], - output_names=['multi_in_files', - 'multi_mask_files', - 'multi_fwhms', - 'multi_merge_out', - 'multi_median_out'], - function=cartesian_product), - name='multi_inputs') - - smooth = pe.MapNode(interface=fsl.SUSAN(), - iterfield=['in_file', 'brightness_threshold', 'usans', 'fwhm'], - name='smooth') - else: - smooth = pe.MapNode(interface=fsl.SUSAN(), - iterfield=['in_file', 'brightness_threshold', 'usans'], - name='smooth') + + multi_inputs = pe.Node(util.Function(function=cartesian_product, + output_names=['cart_in_file', + 'cart_fwhm', + 'cart_usans', + 'cart_btthresh']), + name='multi_inputs') + + smooth = pe.MapNode(interface=fsl.SUSAN(), + iterfield=['in_file', 'brightness_threshold', 'usans', 'fwhm'], + name='smooth') """ Determine the median value of the functional runs using the mask @@ -896,24 +884,17 @@ def cartesian_product(fwhms, in_files, mask_files, merge_out, median_out): """ Define a function to get the brightness threshold for SUSAN """ - # if you are going to iterate over multiple values of fwhm - if list_fwhms: - susan_smooth.connect([ - (inputnode, multi_inputs, [('in_files', 'in_files'), - ('fwhm', 'fwhms'), - ('mask_file', 'mask_files')]), - ]) - susan_smooth.connect(median, ('out_stat', getbtthresh), multi_inputs, 'median_out') - susan_smooth.connect(merge, ('out', getusans), multi_inputs, 'merge_out') - susan_smooth.connect(multi_inputs, 'multi_fwhms', smooth, 'fwhm') - susan_smooth.connect(multi_inputs, 'multi_in_files', smooth, 'in_file') - susan_smooth.connect(multi_inputs, 'multi_median_out', smooth, 'brightness_threshold') - susan_smooth.connect(multi_inputs, 'multi_merge_out', smooth, 'usans') - else: - susan_smooth.connect(inputnode, 'in_files', smooth, 'in_file') - susan_smooth.connect(inputnode, 'fwhm', smooth, 'fwhm') - susan_smooth.connect(median, ('out_stat', getbtthresh), smooth, 'brightness_threshold') - susan_smooth.connect(merge, ('out', getusans), smooth, 'usans') + + susan_smooth.connect([ + (inputnode, multi_inputs, [('in_files', 'in_files'), + ('fwhm', 'fwhms')]), + (median, multi_inputs, [(('out_stat', getbtthresh), 'btthresh')]), + (merge, multi_inputs, [(('out', getusans), 'usans')]), + (multi_inputs, smooth, [('cart_in_file', 'in_file'), + ('cart_fwhm', 'fwhm'), + ('cart_btthresh', 'brightness_threshold'), + ('cart_usans', 'usans')]), + ]) outputnode = pe.Node(interface=util.IdentityInterface(fields=['smoothed_files']), name='outputnode')