invert_transform_flags=[True]), name='applyTransInvWM') createWMmask = pe.Node(fsl.Threshold(thresh=WMthresh, output_type='NIFTI_GZ'), name='createWMmask') epiMaskWM = pe.Node(fsl.maths.ApplyMask(output_type='NIFTI_GZ'), name='epiMaskWM') merge_compCor = pe.Node(util.Merge(3), infields=['in1', 'in2', 'in3'], name='merge_compCor') aCompCor = pe.Node(conf.ACompCor(merge_method='union', variance_threshold=aCompCor_varThresh, repetition_time=TR, pre_filter='cosine', failure_mode='NaN'), name='aCompCor') tCompCor = pe.Node(conf.TCompCor(merge_method='union', variance_threshold=tCompCor_varThresh, repetition_time=TR, pre_filter='cosine', percentile_threshold=0.05, failure_mode='NaN'), name='tCompCor') WMmeanTS = pe.Node(fsl.ImageMeants(), name='WMmeanTS') CSFmeanTS = pe.Node(fsl.ImageMeants(), name='CSFmeanTS')
def create_denoise_pipeline(name='denoise'): # workflow denoise = Workflow(name='denoise') # Define nodes inputnode = Node(interface=util.IdentityInterface(fields=['brain_mask', 'epi_coreg', 'wmseg', 'csfseg', 'highpass_freq', 'tr']), name='inputnode') outputnode = Node(interface=util.IdentityInterface(fields=['wmcsf_mask', 'combined_motion', 'comp_regressor', 'comp_F', 'comp_pF', 'out_betas', 'ts_fullspectrum', 'ts_filtered']), name='outputnode') # combine tissue classes to noise mask wmcsf_mask = Node(fsl.BinaryMaths(operation='add', out_file='wmcsf_mask.nii'), name='wmcsf_mask') denoise.connect([(inputnode, wmcsf_mask, [('wmseg', 'in_file'), ('csfseg', 'operand_file')])]) #resample + binarize wm_csf mask to epi resolution. resample_wmcsf= Node(afni.Resample(resample_mode='NN', outputtype='NIFTI_GZ', out_file='wmcsf_mask_lowres.nii.gz'), name = 'resample_wmcsf') bin_wmcsf_mask=Node(fsl.utils.ImageMaths(), name="bin_wmcsf_mask") bin_wmcsf_mask.inputs.op_string='-nan -thr 0.99 -ero -bin' denoise.connect([(wmcsf_mask, resample_wmcsf, [('out_file', 'in_file')]), (inputnode, resample_wmcsf, [('brain_mask', 'master')]), (resample_wmcsf, bin_wmcsf_mask,[('out_file', 'in_file')]), (bin_wmcsf_mask, outputnode, [('out_file', 'wmcsf_mask')]) ]) #no other denoising filters created here because AROMA performs already well. compcor=Node(conf.ACompCor(), name="compcor") compcor.inputs.num_components=5 #https://www.sciencedirect.com/science/article/pii/S105381191400175X?via%3Dihub denoise.connect([ (inputnode, compcor, [('epi_coreg', 'realigned_file')]), (bin_wmcsf_mask, compcor, [('out_file', 'mask_files')]), ]) def create_designs(compcor_regressors,epi_coreg,mask): import numpy as np import pandas as pd import os from nilearn.input_data import NiftiMasker brain_masker = NiftiMasker(mask_img = mask, smoothing_fwhm=None, standardize=False, memory='nilearn_cache', memory_level=5, verbose=2) whole_brain = brain_masker.fit_transform(epi_coreg) avg_signal = np.mean(whole_brain,axis=1) all_regressors=pd.read_csv(compcor_regressors,sep='\t') #add global signal. all_regressors['global_signal']=avg_signal fn=os.getcwd()+'/all_regressors.txt' all_regressors.to_csv(fn, sep='\t', index=False) return [fn, compcor_regressors] #create a list of design to loop over. create_design = Node(util.Function(input_names=['compcor_regressors','epi_coreg','mask'], output_names=['reg_list'], function=create_designs), name='create_design') denoise.connect([ (compcor, create_design, [('components_file', 'compcor_regressors')]), (inputnode, create_design, [('epi_coreg', 'epi_coreg')]), (inputnode, create_design, [('brain_mask', 'mask')]) ]) # regress compcor and other noise components filter2 = MapNode(fsl.GLM(out_f_name='F_noise.nii.gz', out_pf_name='pF_noise.nii.gz', out_res_name='rest2anat_denoised.nii.gz', output_type='NIFTI_GZ', demean=True), iterfield=['design'], name='filternoise') filter2.plugin_args = {'submit_specs': 'request_memory = 17000'} denoise.connect([(inputnode, filter2, [('epi_coreg', 'in_file')]), #(createfilter2, filter2, [('out_files', 'design')]), #(compcor, filter2, [('components_file', 'design')]), (create_design, filter2, [('reg_list', 'design')]), (inputnode, filter2, [('brain_mask', 'mask')]), (filter2, outputnode, [('out_f', 'comp_F'), ('out_pf', 'comp_pF'), ('out_file', 'out_betas'), ('out_res', 'ts_fullspectrum'), ]) ]) def calc_sigma(TR,highpass): # https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind1205&L=FSL&P=R57592&1=FSL&9=A&I=-3&J=on&d=No+Match%3BMatch%3BMatches&z=4 sigma=1. / (2 * TR * highpass) return sigma calc_s=Node(util.Function(input_names=['TR', 'highpass'], output_names=['sigma'], function=calc_sigma), name='calc_s') denoise.connect(inputnode, 'tr', calc_s, 'TR') denoise.connect(inputnode, 'highpass_freq', calc_s, 'highpass') #use only highpass filter (because high-frequency content is already somewhat filtered in AROMA)) highpass_filter = MapNode(fsl.TemporalFilter(out_file='rest_denoised_highpassed.nii'), name='highpass_filter', iterfield=['in_file']) highpass_filter.plugin_args = {'submit_specs': 'request_memory = 17000'} denoise.connect([(calc_s, highpass_filter, [('sigma', 'highpass_sigma')]), (filter2, highpass_filter, [('out_res', 'in_file')]), (highpass_filter, outputnode, [('out_file', 'ts_filtered')]) ]) return denoise
def compcor_workflow(SinkTag="func_preproc", wf_name="compcor"): """ `source: -` Component based noise reduction method (Behzadi et al.,2007): Regressing out principal components from noise ROIs. Here the aCompCor is used. Workflow inputs: :param func_aligned: The reoriented and realigned functional image. :param mask_files: Mask files which determine ROI(s). The default mask is the :param components_file :param num_componenets: :param pre_filter: Detrend time series prior to component extraction. :param TR :param SinkDir: :param SinkTag: The output directory in which the returned images (see workflow outputs) could be found in a subdirectory directory specific for this workflow. Workflow outputs: :return: slt_workflow - workflow Balint Kincses [email protected] 2018 """ import os import nipype import nipype.pipeline as pe import nipype.algorithms.confounds as cnf import PUMI.func_preproc.info.info_get as info_get import PUMI.utils.utils_convert as utils_convert import nipype.interfaces.io as io import nipype.interfaces.utility as utility import nipype.interfaces.fsl as fsl import PUMI.utils.QC as qc import PUMI.utils.globals as globals SinkDir = os.path.abspath(globals._SinkDir_ + "/" + SinkTag) if not os.path.exists(SinkDir): os.makedirs(SinkDir) # Basic interface class generates identity mappings inputspec = pe.Node( utility.IdentityInterface(fields=['func_aligned', 'mask_file']), name='inputspec') myqc = qc.vol2png("compcor_noiseroi") # Save outputs which are important ds_nii = pe.Node(interface=io.DataSink(), name='ds_nii') ds_nii.inputs.base_directory = SinkDir ds_nii.inputs.regexp_substitutions = [("(\/)[^\/]*$", ".nii.gz")] # standardize timeseries prior to compcor. added by tspisak scale = pe.MapNode(interface=utility.Function(input_names=['in_file'], output_names=['scaled_file'], function=scale_vol), iterfield=['in_file'], name='scale_func') # Calculate compcor files compcor = pe.MapNode( interface=cnf.ACompCor(pre_filter='polynomial', header_prefix="", num_components=5), iterfield=['realigned_file', 'repetition_time', 'mask_files'], name='compcor') # Custom interface wrapping function Float2Str func_str2float = pe.MapNode(interface=utils_convert.Str2Float, iterfield=['str'], name='func_str2float') # Drop first line of the Acompcor function output drop_firstline = pe.MapNode(interface=utils_convert.DropFirstLine, iterfield=['txt'], name='drop_firstline') # Custom interface wrapping function TR TRvalue = pe.MapNode(interface=info_get.TR, iterfield=['in_file'], name='TRvalue') # Basic interface class generates identity mappings outputspec = pe.Node(utility.IdentityInterface(fields=['components_file']), name='outputspec') # save data out with Datasink ds_text = pe.Node(interface=io.DataSink(), name='ds_txt') ds_text.inputs.regexp_substitutions = [("(\/)[^\/]*$", ".txt")] ds_text.inputs.base_directory = SinkDir # Create a workflow to connect all those nodes analysisflow = nipype.Workflow(wf_name) analysisflow.connect(inputspec, 'func_aligned', scale, 'in_file') analysisflow.connect(scale, 'scaled_file', compcor, 'realigned_file') analysisflow.connect(inputspec, 'func_aligned', TRvalue, 'in_file') analysisflow.connect(TRvalue, 'TR', func_str2float, 'str') analysisflow.connect(func_str2float, 'float', compcor, 'repetition_time') #analysisflow.connect(TRvalue, 'TR', compcor, 'repetition_time') analysisflow.connect(inputspec, 'mask_file', compcor, 'mask_files') analysisflow.connect(compcor, 'components_file', drop_firstline, 'txt') analysisflow.connect(drop_firstline, 'droppedtxtfloat', outputspec, 'components_file') analysisflow.connect(compcor, 'components_file', ds_text, 'compcor_noise') analysisflow.connect(inputspec, 'func_aligned', myqc, 'inputspec.bg_image') analysisflow.connect(inputspec, 'mask_file', myqc, 'inputspec.overlay_image') analysisflow.connect(inputspec, 'mask_file', ds_nii, 'compcor_noise_mask') return analysisflow
NodeHash_22f2e80 = pe.Node(interface=fsl.MCFLIRT(), name='NodeName_22f2e80') #Computes the time-course SNR for a time series NodeHash_50c02c0 = pe.Node(interface=confounds.TSNR(), name='NodeName_50c02c0') NodeHash_50c02c0.inputs.regress_poly = 3 #Wraps command **fslstats** NodeHash_3ac27f0 = pe.Node(interface=fsl.ImageStats(), name='NodeName_3ac27f0') NodeHash_3ac27f0.inputs.op_string = '-p 98' #Wraps command **fslmaths** NodeHash_30f6760 = pe.Node(interface=fsl.Threshold(), name='NodeName_30f6760') NodeHash_30f6760.inputs.args = '-bin' #Anatomical compcor: for inputs and outputs, see CompCor. NodeHash_325da10 = pe.Node(interface=confounds.ACompCor(), name='NodeName_325da10') NodeHash_325da10.inputs.num_components = 2 #Wraps command **fsl_regfilt** NodeHash_430d1e0 = pe.Node(interface=fsl.FilterRegressor(), name='NodeName_430d1e0') NodeHash_430d1e0.inputs.filter_columns = [1, 2] #Wraps command **fslmaths** NodeHash_77e3220 = pe.Node(interface=fsl.TemporalFilter(), name='NodeName_77e3220') NodeHash_77e3220.inputs.highpass_sigma = 25 #Generic datasink module to store structured outputs NodeHash_99576b0 = pe.Node(interface=io.DataSink(), name='NodeName_99576b0')
my_confounds_TSNR.inputs.regress_poly = 3 #Wraps command **fslstats** my_fsl_ImageStats = pe.Node(interface=fsl.ImageStats(), name='my_fsl_ImageStats', iterfield=['']) my_fsl_ImageStats.inputs.op_string = '-p 98' #Wraps command **fslmaths** my_fsl_Threshold = pe.Node(interface=fsl.Threshold(), name='my_fsl_Threshold', iterfield=['']) my_fsl_Threshold.inputs.args = '-bin' #Anatomical compcor: for inputs and outputs, see CompCor. my_confounds_ACompCor = pe.Node(interface=confounds.ACompCor(), name='my_confounds_ACompCor', iterfield=['']) my_confounds_ACompCor.inputs.num_components = 2 #Wraps command **fsl_regfilt** my_fsl_FilterRegressor = pe.Node(interface=fsl.FilterRegressor(), name='my_fsl_FilterRegressor', iterfield=['']) my_fsl_FilterRegressor.inputs.filter_columns = [1, 2] #Wraps command **fslmaths** my_fsl_TemporalFilter = pe.Node(interface=fsl.TemporalFilter(), name='my_fsl_TemporalFilter', iterfield=['']) my_fsl_TemporalFilter.inputs.highpass_sigma = 25
flirt_EPItoMNI.inputs.reference = $FSLDIR/data/standard/MNI152_T1_2mm_brain.nii.gz #Wraps the executable command ``3dBlurToFWHM``. afni_blur_to_fwhm = pe.Node(interface = afni.BlurToFWHM(), name='afni_blur_to_fwhm') afni_blur_to_fwhm.inputs.fwhm = 6 #Calculate the :abbr:`FD (framewise displacement)` as in [Power2012]_. confounds_framewise_displacement = pe.MapNode(interface = confounds.FramewiseDisplacement(), name='confounds_framewise_displacement', iterfield = ['in_file']) confounds_framewise_displacement.inputs.parameter_source = 'FSL' #Wraps the executable command ``fast``. fsl_fast = pe.MapNode(interface = fsl.FAST(), name='fsl_fast', iterfield = ['in_files']) fsl_fast.inputs.number_classes = 3 #Anatomical compcor: for inputs and outputs, see CompCor. confounds_acomp_cor = pe.MapNode(interface = confounds.ACompCor(), name='confounds_acomp_cor', iterfield = ['realigned_file', 'mask_files']) confounds_acomp_cor.inputs.merge_method = 'union' #Generic datasink module to store structured outputs io_data_sink = pe.MapNode(interface = io.DataSink(), name='io_data_sink', iterfield = ['smoothedEPI', 'framewiseDisplacement', 'mcflirtPar', 'aCompCorComponents']) io_data_sink.inputs.base_directory = out_dir io_data_sink.inputs.parameterization = True #Create a workflow to connect all those nodes analysisflow = nipype.Workflow('MyWorkflow') analysisflow.connect(io_select_files, "func", fsl_mcflirt, "in_file") analysisflow.connect(io_select_files, "anat", fsl_bet, "in_file") analysisflow.connect(fsl_bet, "out_file", flirt_EPItoT1, "reference") analysisflow.connect(fsl_mcflirt, "mean_img", flirt_EPItoT1, "in_file") analysisflow.connect(fsl_bet, "out_file", flirt_T1toMNI, "in_file") analysisflow.connect(flirt_EPItoT1, "out_matrix_file", fsl_convert_xfm, "in_file")
TSNR.inputs.regress_poly = 3 #Wraps command **fslstats** ComputeLowTsnr = pe.MapNode(interface=fsl.ImageStats(), name='ComputeLowTsnr', iterfield=['in_file']) ComputeLowTsnr.inputs.op_string = '-p 98' #Wraps command **fslmaths** Threshold = pe.MapNode(interface=fsl.Threshold(), name='Threshold', iterfield=['thresh', 'in_file']) Threshold.inputs.args = '-bin' #Anatomical compcor: for inputs and outputs, see CompCor. NoiseComponents = pe.MapNode(interface=confounds.ACompCor(), name='NoiseComponents', iterfield=['realigned_file', 'mask_files']) NoiseComponents.inputs.num_components = 2 #Wraps command **fsl_regfilt** RegressionFilter = pe.MapNode(interface=fsl.FilterRegressor(), name='RegressionFilter', iterfield=['in_file', 'design_file']) RegressionFilter.inputs.filter_columns = [1, 2] #Wraps command **fslmaths** BandpassFilter = pe.MapNode(interface=fsl.TemporalFilter(), name='BandpassFilter', iterfield=['in_file']) BandpassFilter.inputs.highpass_sigma = 25
def create_resting_preproc(name='restpreproc', base_dir=None): """Create a "resting" time series preprocessing workflow The noise removal is based on Behzadi et al. (2007) Parameters ---------- name : name of workflow (default: restpreproc) Inputs:: inputspec.func : functional run (filename or list of filenames) Outputs:: outputspec.noise_mask_file : voxels used for PCA to derive noise components outputspec.filtered_file : bandpass filtered and noise-reduced time series Example ------- >>> TR = 3.0 >>> wf = create_resting_preproc() >>> wf.inputs.inputspec.func = 'f3.nii' >>> wf.inputs.inputspec.num_noise_components = 6 >>> wf.inputs.inputspec.highpass_sigma = 100/(2*TR) >>> wf.inputs.inputspec.lowpass_sigma = 12.5/(2*TR) >>> wf.run() # doctest: +SKIP """ restpreproc = pe.Workflow(name=name, base_dir=base_dir) # Define nodes inputnode = pe.Node(interface=util.IdentityInterface(fields=[ 'func', 'num_noise_components', 'highpass_sigma', 'lowpass_sigma' ]), name='inputspec') outputnode = pe.Node(interface=util.IdentityInterface(fields=[ 'noise_mask_file', 'filtered_file', ]), name='outputspec') slicetimer = pe.Node(fsl.SliceTimer(), name='slicetimer') realigner = create_realign_flow() tsnr = pe.Node(confounds.TSNR(regress_poly=2), name='tsnr') getthresh = pe.Node(interface=fsl.ImageStats(op_string='-p 98'), name='getthreshold') threshold_stddev = pe.Node(fsl.Threshold(), name='threshold') compcor = pe.Node(confounds.ACompCor( components_file="noise_components.txt", pre_filter=False), name='compcor') remove_noise = pe.Node(fsl.FilterRegressor(filter_all=True), name='remove_noise') bandpass_filter = pe.Node(fsl.TemporalFilter(), name='bandpass_filter') # Define connections restpreproc.connect(inputnode, 'func', slicetimer, 'in_file') restpreproc.connect(slicetimer, 'slice_time_corrected_file', realigner, 'inputspec.func') restpreproc.connect(realigner, 'outputspec.realigned_file', tsnr, 'in_file') restpreproc.connect(tsnr, 'stddev_file', threshold_stddev, 'in_file') restpreproc.connect(tsnr, 'stddev_file', getthresh, 'in_file') restpreproc.connect(getthresh, 'out_stat', threshold_stddev, 'thresh') restpreproc.connect(realigner, 'outputspec.realigned_file', compcor, 'realigned_file') restpreproc.connect(threshold_stddev, 'out_file', compcor, 'mask_files') restpreproc.connect(inputnode, 'num_noise_components', compcor, 'num_components') restpreproc.connect(tsnr, 'detrended_file', remove_noise, 'in_file') restpreproc.connect(compcor, 'components_file', remove_noise, 'design_file') restpreproc.connect(inputnode, 'highpass_sigma', bandpass_filter, 'highpass_sigma') restpreproc.connect(inputnode, 'lowpass_sigma', bandpass_filter, 'lowpass_sigma') restpreproc.connect(remove_noise, 'out_file', bandpass_filter, 'in_file') restpreproc.connect(threshold_stddev, 'out_file', outputnode, 'noise_mask_file') restpreproc.connect(bandpass_filter, 'out_file', outputnode, 'filtered_file') return restpreproc
def get_nuisance_regressors_wf(outdir, timepoints, subject_id, global_signal=False, order=0, derivatives=1, comp=3): """Creates nipype workflow for nuisance correction composed by: Intercept + Drift (cosine transform) + Motion Correction + WhiteMatter&CSF Nuisance Regressors (CompCor) Parameters ---------- outdir: subject_id: global_signal: timepoints: order: derivatives: comp: Returns ------- wf_reg: """ from nipype.algorithms import confounds from nipype import Workflow, Node from nipype.interfaces import utility, fsl import os if global_signal: gb='_GB' else: gb='' wf_reg=Workflow(name=subject_id+gb,base_dir=outdir); print ("Setting INPUT node..."); node_input = Node(utility.IdentityInterface(fields=[ "realign_movpar_txt", 'rfmri_unwarped_imgs', 'mask_wm', 'mask_csf', 'global_mask_img', 'bold_img' ]), name='input_node' ) #Merging wm and csf masks node_merge_wm_csf = Node(utility.base.Merge(2),name='Merge_wm_csf') #AcompCor node_ACompCor=Node(confounds.ACompCor( num_components=3, #save_pre_filter='high_pass_filter.txt', pre_filter=False, # high_pass_cutoff=128, repetition_time=0.8, merge_method='none', #use_regress_poly=False, #realigned_file= fMRI_BOLD_unwarped, # mask_files='/institut/processed_data/BBHI_func/output2/sub-41064/GetMasksInT1Space/binarize_mask/MNI152_WM_09_warp_thresh.nii.gz', ), name="AcompCor_mask") #node_ACompCor.inputs.save_pre_filter=os.path.join(os.path.join(os.path.join(wf_reg.base_dir,wf_reg.name),node_ACompCor.name), 'high_pass_filter.txt') #cosine_filter node_cosine_filter_reg=Node(utility.Function(input_names=["timepoints", "timestep","period_cut","output_dir"], output_names=["cosine_filter_txt"], function=cosine_filter_txt), name="cosine_filter") node_cosine_filter_reg.inputs.output_dir=os.path.join(os.path.join(os.path.join(wf_reg.base_dir,wf_reg.name)),node_cosine_filter_reg.name) node_cosine_filter_reg.inputs.timepoints=timepoints node_cosine_filter_reg.inputs.timestep=0.8 #node_cosine_filter_reg.overwrite=True #global_signal # if global_signal : # node_global_signal=Node(utility.Function(input_names=["timeseries_file", "label_file", "filename"], # output_names=["global_signal_txt"], # function=extract_subrois), # name="global_signal") # node_global_signal.inputs.filename=os.path.join(os.path.join(os.path.join(os.path.join(wf_reg.base_dir,wf_reg.name)),node_global_signal.name),'global_signal.txt') # #node_global_signal.overwrite=True #motion regressors motion_regressors_interface = utility.Function(input_names=["realign_movpar_txt", "output_dir","order","derivatives"], output_names=["motion_reg_txt"], function=motion_regressors) node_motion_regressors=Node(motion_regressors_interface, name="motion_regressors_txt") node_motion_regressors.inputs.output_dir=os.path.join(os.path.join(os.path.join(wf_reg.base_dir,wf_reg.name)),node_motion_regressors.name) #node_motion_regressors.overwrite=True #merges all regressors node_merge_txts = Node(utility.base.Merge(4),name='Merge_txt_inputs') node_merge_regressors = Node(utility.Function(input_names=["nuisance_txts", "output_dir"], output_names=["nuisance_txt"], function=merge_nuisance_regressors), name="merge_nuisance_txt") node_merge_regressors.inputs.output_dir=os.path.join(os.path.join(wf_reg.base_dir,wf_reg.name),node_merge_regressors.name) node_filter_regressor = Node(fsl.FilterRegressor( #design_file (-d) nuissance_txt filter_all=True, #in_file (-i) bold after SPM coregistration to T1 #out_file ), name="filter_regressors_bold") node_output = Node(utility.IdentityInterface(fields=[ 'nuisance_txt', 'bold_nuisance_filtered' ]), name='output_node') wf_reg.connect([ (node_input, node_merge_wm_csf, [('mask_wm','in1'), ('mask_csf', 'in2')]), (node_input, node_ACompCor,[('rfmri_unwarped_imgs', 'realigned_file')]), (node_merge_wm_csf, node_ACompCor, [('out', 'mask_files')]), (node_input, node_motion_regressors,[('realign_movpar_txt', 'realign_movpar_txt')]), (node_motion_regressors,node_merge_txts, [('motion_reg_txt', 'in1')]), (node_ACompCor,node_merge_txts, [('components_file', 'in2')]), (node_cosine_filter_reg,node_merge_txts, [('cosine_filter_txt', 'in3')]), (node_merge_txts, node_merge_regressors, [('out', 'nuisance_txts')]), ]) # if global_signal: # wf_reg.connect([ # (node_input, node_global_signal,[('rfmri_unwarped_imgs', 'timeseries_file'), # ('global_mask_img', 'label_file')]), # (node_global_signal, node_merge_txts, [('global_signal_txt', 'in4')]) # ]) wf_reg.connect([ (node_merge_regressors, node_filter_regressor, [('nuisance_txt','design_file')]), (node_input, node_filter_regressor, [('bold_img','in_file')]), (node_filter_regressor, node_output, [('out_file','bold_nuisance_filtered')]), (node_merge_regressors, node_output,[('nuisance_txt', 'nuisance_txt')]) ]) return wf_reg