def mask_zstats(mask_file, zstats, zfstats): #it is much easier to apply the masks to zstats and zfstats all inside the same function #rather than creating a seperate node for each one #plus the input is in the form of a list, which will require you to create a node select # fslmaths stats/zstat1 -mas mask thresh_zstat1 #If you have many contrasts, you can create a loop and iterate over each contrast import nipype.interfaces.fsl as fsl import os mask_zstat1 = fsl.ApplyMask() mask_zstat1.inputs.in_file = zstats[0] mask_zstat1.inputs.mask_file = mask_file mask_zstat1.inputs.out_file = 'thresh_zstat1.nii.gz' mask_zstat1.run() mask_zstat2 = fsl.ApplyMask() mask_zstat2.inputs.in_file = zstats[1] mask_zstat2.inputs.mask_file = mask_file mask_zstat2.inputs.out_file = 'thresh_zstat2.nii.gz' mask_zstat2.run() mask_zfstat1 = fsl.ApplyMask() mask_zfstat1.inputs.in_file = zfstats mask_zfstat1.inputs.mask_file = mask_file mask_zfstat1.inputs.out_file = 'thresh_zfstat1.nii.gz' mask_zfstat1.run() thresh_zstat1 = os.path.abspath('thresh_zstat1.nii.gz') thresh_zstat2 = os.path.abspath('thresh_zstat2.nii.gz') thresh_zfstat1 = os.path.abspath('thresh_zfstat1.nii.gz') return thresh_zstat1, thresh_zstat2, thresh_zfstat1
def epi_mni_align(name='SpatialNormalization', ants_nthreads=6, testing=False, resolution=2): """ Uses FSL FLIRT with the BBR cost function to find the transform that maps the EPI space into the MNI152-nonlinear-symmetric atlas. The input epi_mean is the averaged and brain-masked EPI timeseries Returns the EPI mean resampled in MNI space (for checking out registration) and the associated "lobe" parcellation in EPI space. """ from nipype.interfaces.ants import ApplyTransforms, N4BiasFieldCorrection from niworkflows.data import get_mni_icbm152_nlin_asym_09c as get_template from niworkflows.interfaces.registration import RobustMNINormalizationRPT as RobustMNINormalization mni_template = get_template() workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['epi_mean', 'epi_mask']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['epi_mni', 'epi_parc', 'report']), name='outputnode') epimask = pe.Node(fsl.ApplyMask(), name='EPIApplyMask') n4itk = pe.Node(N4BiasFieldCorrection(dimension=3), name='SharpenEPI') # Mask T2 template image brainmask = pe.Node(fsl.ApplyMask( in_file=op.join(mni_template, '%dmm_T2.nii.gz' % resolution), mask_file=op.join(mni_template, '%dmm_brainmask.nii.gz' % resolution)), name='MNIApplyMask') norm = pe.Node(RobustMNINormalization( num_threads=ants_nthreads, template='mni_icbm152_nlin_asym_09c', testing=testing, moving='EPI', generate_report=True), name='EPI2MNI') # Warp segmentation into EPI space invt = pe.Node(ApplyTransforms( input_image=op.join(mni_template, '%dmm_parc.nii.gz' % resolution), dimension=3, default_value=0, interpolation='NearestNeighbor'), name='ResampleSegmentation') workflow.connect([ (inputnode, invt, [('epi_mean', 'reference_image')]), (inputnode, n4itk, [('epi_mean', 'input_image')]), (inputnode, epimask, [('epi_mask', 'mask_file')]), (n4itk, epimask, [('output_image', 'in_file')]), (brainmask, norm, [('out_file', 'reference_image')]), (epimask, norm, [('out_file', 'moving_image')]), (norm, invt, [ ('reverse_transforms', 'transforms'), ('reverse_invert_flags', 'invert_transform_flags')]), (invt, outputnode, [('output_image', 'epi_parc')]), (norm, outputnode, [('warped_image', 'epi_mni'), ('out_report', 'report')]), ]) return workflow
def smooth_mask_pipeline(self, **name_maps): pipeline = self.new_pipeline('smooth_mask', desc="Smooths and masks a brain image", name_maps=name_maps, citations=[fsl_cite]) # Smoothing process smooth = pipeline.add( 'smooth', fsl.IsotropicSmooth(fwhm=self.parameter('smoothing_fwhm')), inputs={'in_file': ('magnitude', nifti_gz_format)}, outputs={'smooth': ('out_file', nifti_gz_format)}, requirements=[fsl_req.v('5.0.10')]) pipeline.add('mask', fsl.ApplyMask(), inputs={ 'in_file': (smooth, 'out_file'), 'mask_file': ('brain_mask', nifti_gz_format) }, outputs={'smooth_masked': ('out_file', nifti_gz_format)}, requirements=[fsl_req.v('5.0.10')]) return pipeline
def mask_heatmap(input_map, brainmask, output_file): # requires image map to mask, full path to brainmask, and the name of the output file to save apply_mask = fsl.ApplyMask() apply_mask.inputs.in_file = input_map apply_mask.inputs.mask_file = brainmask apply_mask.inputs.out_file = output_file mask_result = apply_mask.run()
def create_mgzconvert_pipeline(name='mgzconvert'): # workflow mgzconvert = Workflow(name='mgzconvert') # inputnode inputnode = Node( util.IdentityInterface(fields=['fs_subjects_dir', 'fs_subject_id']), name='inputnode') # outputnode outputnode = Node(util.IdentityInterface(fields=[ 'anat_head', 'anat_brain', 'anat_brain_mask', 'wmseg', 'wmedge' ]), name='outputnode') # import files from freesurfer fs_import = Node(interface=nio.FreeSurferSource(), name='fs_import') # convert Freesurfer T1 file to nifti head_convert = Node(fs.MRIConvert(out_type='niigz', out_file='T1.nii.gz'), name='head_convert') # create brainmask from aparc+aseg with single dilation def get_aparc_aseg(files): for name in files: if 'aparc+aseg' in name: return name # create brain by converting only freesurfer output brain_convert = Node(fs.MRIConvert(out_type='niigz', out_file='brain.nii.gz'), name='brain_convert') brain_binarize = Node(fsl.ImageMaths(op_string='-bin -fillh', out_file='T1_brain_mask.nii.gz'), name='brain_binarize') # cortical and cerebellar white matter volumes to construct wm edge # [lh cerebral wm, lh cerebellar wm, rh cerebral wm, rh cerebellar wm, brain stem] wmseg = Node(fs.Binarize(out_type='nii.gz', match=[2, 7, 41, 46, 16], binary_file='T1_brain_wmseg.nii.gz'), name='wmseg') # make edge from wmseg to visualize coregistration quality edge = Node(fsl.ApplyMask(args='-edge -bin', out_file='T1_brain_wmedge.nii.gz'), name='edge') # connections mgzconvert.connect([ (inputnode, fs_import, [('fs_subjects_dir', 'subjects_dir'), ('fs_subject_id', 'subject_id')]), (fs_import, head_convert, [('T1', 'in_file')]), (fs_import, wmseg, [(('aparc_aseg', get_aparc_aseg), 'in_file')]), (fs_import, brain_convert, [('brainmask', 'in_file')]), (wmseg, edge, [('binary_file', 'in_file'), ('binary_file', 'mask_file')]), (head_convert, outputnode, [('out_file', 'anat_head')]), (brain_convert, outputnode, [('out_file', 'anat_brain')]), (brain_convert, brain_binarize, [('out_file', 'in_file')]), (brain_binarize, outputnode, [('out_file', 'anat_brain_mask')]), (wmseg, outputnode, [('binary_file', 'wmseg')]), (edge, outputnode, [('out_file', 'wmedge')]) ]) return mgzconvert
def preprocess(aroma_config, fwhm_config, input_img, mask_file, taskdir, task): # Resample to mask space # This is for AROMA images. Does it hurt non-AROMA? resample_path = os.path.join(taskdir, task + '_resample.nii.gz') resample = afni.Resample(master=mask_file, out_file=resample_path, in_file=input_img) resample_run = resample.run() # Apply fmriprep-calculated brain mask to the functional image masked_file_path = os.path.join(taskdir, task + "_input_functional_masked.nii.gz") applymask = fsl.ApplyMask(mask_file=mask_file, out_file=masked_file_path) applymask.inputs.in_file = resample_run.outputs.out_file mask_run = applymask.run() masked_input = masked_file_path if aroma_config: print("No smoothing required.") processed_image = masked_input else: # smoothing print("Smoothing the skull-stripped BOLD.") smooth = fsl.Smooth(in_file=masked_input, fwhm=fwhm_config) smooth_run = smooth.run() processed_image = smooth_run.outputs.smoothed_file return processed_image
def init_skullstrip_b0_wf(name='skullstrip_b0_wf'): """ This workflow applies skull-stripping to a DWI image. It is intended to be used on an image that has previously been bias-corrected with :py:func:`~qsiprep.workflows.bold.util.init_enhance_and_skullstrip_bold_wf` .. workflow :: :graph2use: orig :simple_form: yes from qsiprep.workflows.bold.util import init_skullstrip_b0_wf wf = init_skullstrip_b0_wf() Inputs in_file b0 image (single volume) Outputs skull_stripped_file the ``in_file`` after skull-stripping mask_file mask of the skull-stripped input file out_report reportlet for the skull-stripping """ workflow = Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['mask_file', 'skull_stripped_file', 'out_report']), name='outputnode') automask_dilate = pe.Node(afni.Automask(dilate=3, outputtype='NIFTI_GZ'), name='automask_dilate') apply_mask = pe.Node(fsl.ApplyMask(), name='apply_mask') mask_reportlet = pe.Node(SimpleShowMaskRPT(), name='mask_reportlet') workflow.connect([ (inputnode, automask_dilate, [('in_file', 'in_file')]), (automask_dilate, outputnode, [('out_file', 'mask_file')]), # Masked file (inputnode, apply_mask, [('in_file', 'in_file')]), (automask_dilate, apply_mask, [('out_file', 'mask_file')]), (apply_mask, outputnode, [('out_file', 'skull_stripped_file')]), # Reportlet (inputnode, mask_reportlet, [('in_file', 'background_file')]), (automask_dilate, mask_reportlet, [('out_file', 'mask_file')]), (mask_reportlet, outputnode, [('out_report', 'out_report')]), ]) return workflow
def applyMask(input_file, mask_file, appendix): output_file = os.path.join( os.path.dirname(input_file), os.path.basename(input_file).split('.')[0]) + appendix + '.nii.gz' myMaskapply = fsl.ApplyMask(in_file=input_file, out_file=output_file, mask_file=mask_file) print(myMaskapply.cmdline) myMaskapply.run() return output_file
def init_asl_geref_wf(omp_nthreads, mem_gb, metadata, bids_dir, smooth_kernel=5, brainmask_thresh=0.5, pre_mask=False, name="asl_gereference_wf", gen_report=False): workflow = Workflow(name=name) workflow.__desc__ = """\ First, a reference volume and its skull-stripped version were generated. """ inputnode = pe.Node( niu.IdentityInterface(fields=["asl_file"]), name="inputnode", ) outputnode = pe.Node( niu.IdentityInterface(fields=[ "raw_ref_image", "ref_image_brain", "asl_mask", "m0_file", "mask_report", ]), name="outputnode", ) gen_ref = pe.Node(GeReferenceFile(bids_dir=bids_dir, fwhm=smooth_kernel, in_metadata=metadata), omp_nthreads=1, mem_gb=1, name='gen_ge_ref') gen_ref.base_dir = os.getcwd() skull_strip_wf = pe.Node(fsl.BET(frac=0.5, mask=True), name="fslbet") apply_mask = pe.Node(fsl.ApplyMask(), name="apply_mask") mask_reportlet = pe.Node(SimpleShowMaskRPT(), name="mask_reportlet") workflow.connect([ (inputnode, gen_ref, [('asl_file', 'in_file')]), (gen_ref, skull_strip_wf, [('ref_file', 'in_file')]), (gen_ref, outputnode, [("ref_file", "raw_ref_image")]), (gen_ref, apply_mask, [("ref_file", "in_file")]), (skull_strip_wf, outputnode, [("mask_file", "asl_mask")]), (skull_strip_wf, apply_mask, [("mask_file", "mask_file")]), (apply_mask, outputnode, [("out_file", "ref_image_brain")]), (gen_ref, mask_reportlet, [("ref_file", "background_file")]), (skull_strip_wf, mask_reportlet, [('mask_file', 'mask_file')]), (gen_ref, outputnode, [("m0_file", "m0_file")]), ]) return workflow
def init_fmriprep_adapter_wf( name: str = "fmriprep_adapter_wf", memcalc: MemoryCalculator = MemoryCalculator.default(), ): workflow = pe.Workflow(name=name) inputnode = pe.Node( niu.IdentityInterface( fields=[ "bold_std", "bold_mask_std", "spatial_reference", "confounds", "vals", ] ), name="inputnode", ) outputnode = pe.Node( niu.IdentityInterface(fields=["files", "mask", "vals"]), name="outputnode", ) select_std = pe.Node( KeySelect(fields=["bold_std", "bold_mask_std"]), name="select_std", run_without_submitting=True, nohash=True, ) select_std.inputs.key = f"{constants.reference_space}_res-{constants.reference_res}" workflow.connect(inputnode, "bold_std", select_std, "bold_std") workflow.connect(inputnode, "bold_mask_std", select_std, "bold_mask_std") workflow.connect(inputnode, "spatial_reference", select_std, "keys") # applymask = pe.Node( interface=fsl.ApplyMask(), name="applymask", mem_gb=memcalc.series_std_gb, ) workflow.connect(select_std, "bold_std", applymask, "in_file") workflow.connect(select_std, "bold_mask_std", applymask, "mask_file") # merge = pe.Node(niu.Merge(2), name="merge") workflow.connect(applymask, "out_file", merge, "in1") workflow.connect(inputnode, "confounds", merge, "in2") # workflow.connect(merge, "out", outputnode, "files") workflow.connect(select_std, "bold_mask_std", outputnode, "mask") workflow.connect(inputnode, "vals", outputnode, "vals") return workflow
def __init__(self, name, base_dir=None): super(BrainExtractionWorkflow, self).__init__(name, base_dir) # Segmentation # ============ seg_node = npe.MapNode(name="Segmentation", iterfield="data", interface=spm.Segment()) seg_node.inputs.gm_output_type = [False, False, True] seg_node.inputs.wm_output_type = [False, False, True] seg_node.inputs.csf_output_type = [False, False, True] add1_node = npe.MapNode(name="AddGMWM", iterfield=["in_file", "operand_file"], interface=fsl.BinaryMaths()) add1_node.inputs.operation = 'add' add2_node = npe.MapNode(name="AddGMWMCSF", iterfield=["in_file", "operand_file"], interface=fsl.BinaryMaths()) add2_node.inputs.operation = 'add' dil_node = npe.MapNode(name="Dilate", iterfield="in_file", interface=fsl.DilateImage()) dil_node.inputs.operation = 'mean' ero_node = npe.MapNode(name="Erode", iterfield="in_file", interface=fsl.ErodeImage()) thre_node = npe.MapNode(name="Threshold", iterfield="in_file", interface=fsl.Threshold()) thre_node.inputs.thresh = 0.5 fill_node = npe.MapNode(name="Fill", iterfield="in_file", interface=fsl.UnaryMaths()) fill_node.inputs.operation = 'fillh' mask_node = npe.MapNode(name="ApplyMask", iterfield=["in_file", "mask_file"], interface=fsl.ApplyMask()) mask_node.inputs.output_type = str("NIFTI") self.connect([ (seg_node, add1_node, [('native_gm_image', 'in_file')]), (seg_node, add1_node, [('native_wm_image', 'operand_file')]), (seg_node, add2_node, [('native_csf_image', 'in_file')]), (add1_node, add2_node, [('out_file', 'operand_file')]), (add2_node, dil_node, [('out_file', 'in_file')]), (dil_node, ero_node, [('out_file', 'in_file')]), (ero_node, thre_node, [('out_file', 'in_file')]), (thre_node, fill_node, [('out_file', 'in_file')]), (fill_node, mask_node, [('out_file', 'mask_file')]), ])
def cbf_cl_preprocessing_initialize(): """ 1) Extracts control/label pairs from raw pCASL data 2) Motion correction with mcflirt 3) Control/Label pairwise subtraction """ cl_preproc = pe.Workflow(name='cl_preproc') cl_preproc.base_dir = (os.getcwd()) cl_inputnode = pe.Node( interface=util.IdentityInterface(fields=['func', 'm0', 'm0_mask']), name='cl_inputnode') print(cl_inputnode.inputs) cl_datasink = pe.Node(nio.DataSink(), name='cl_sinker') cl_datasink.inputs.base_directory = results_dir # Extract Control Label Pairs cl_fslroi = pe.Node(fsl.ExtractROI(roi_file='cl.nii.gz', t_min=1, t_size=-1), name='cl_fslroi') # Align Control/Label Pairs to M0 image cl_mcflirt = pe.Node(fsl.MCFLIRT(save_mats=True, save_plots=True), name='cl_mcflirt') # Mask Control Label Pairs cl_mask = pe.Node(fsl.ApplyMask(), name="cl_mask") cl_outputnode = pe.Node(interface=util.IdentityInterface( fields=['cl', 'cl_brain', 'cl_mcf', 'cl_mcf_par']), name='cl_outputnode') cl_preproc.connect([ (cl_inputnode, cl_fslroi, [('func', 'in_file')]), (cl_fslroi, cl_mcflirt, [['roi_file', 'in_file']]), (cl_inputnode, cl_mcflirt, [['m0', 'ref_file']]), (cl_mcflirt, cl_mask, [('out_file', 'in_file')]), (cl_inputnode, cl_mask, [('m0_mask', 'mask_file')]), (cl_fslroi, cl_datasink, [['roi_file', 'results.@cl']]), (cl_mcflirt, cl_datasink, [['out_file', 'results.@mcfcl']]), (cl_mask, cl_datasink, [['out_file', 'results.@cl_mask']]), (cl_fslroi, cl_outputnode, [['roi_file', 'cl']]), (cl_mcflirt, cl_outputnode, [['par_file', 'cl_mcf_par']]), (cl_mcflirt, cl_outputnode, [['out_file', 'cl_mcf']]), (cl_mask, cl_outputnode, [['out_file', 'cl_brain']]) ]) return cl_preproc
def cluster_zstats(zstat, volume, dlh): import nipype.interfaces.fsl as fsl import os template_mask = '/media/amr/Amr_4TB/Work/October_Acquistion/Anat_Template_Enhanced_Mask.nii.gz' cope_no = zstat[-8] #number of the zstat file after taking into account .nii.gz if zstat[-25:-21] == '05Hz': cope = '/media/amr/Amr_4TB/Work/stimulation/stimulation_3rd_level_CA3/05Hz/flameo/cope{0}.nii.gz'.format(cope_no) elif zstat[-25:-21] == '10Hz': cope = '/media/amr/Amr_4TB/Work/stimulation/stimulation_3rd_level_CA3/10Hz/flameo/cope{0}.nii.gz'.format(cope_no) elif zstat[-25:-21] == '20Hz': cope = '/media/amr/Amr_4TB/Work/stimulation/stimulation_3rd_level_CA3/20Hz/flameo/cope{0}.nii.gz'.format(cope_no) elif zstat[-25:-21] == '40Hz': cope = '/media/amr/Amr_4TB/Work/stimulation/stimulation_3rd_level_CA3/40Hz/flameo/cope{0}.nii.gz'.format(cope_no) #mask here not in a seperate node, because I need the original zstat to get the number mask_zstat = fsl.ApplyMask() mask_zstat.inputs.in_file = zstat mask_zstat.inputs.mask_file = template_mask mask_zstat_outputs = mask_zstat.run() masked_zstat = mask_zstat_outputs.outputs.out_file cluster_zstats = fsl.model.Cluster() cluster_zstats.inputs.in_file = masked_zstat cluster_zstats.inputs.cope_file = cope cluster_zstats.inputs.threshold = 3.1 cluster_zstats.inputs.pthreshold = 0.05 cluster_zstats.inputs.connectivity = 26 cluster_zstats.inputs.volume = volume cluster_zstats.inputs.dlh = dlh cluster_zstats.inputs.out_threshold_file = 'thresh_zstat.nii.gz' cluster_zstats.inputs.out_index_file = 'cluster_mask_zstat' cluster_zstats.inputs.out_localmax_txt_file = 'lmax_zstat_std.txt' cluster_zstats.inputs.use_mm = True cluster_zstats.cmdline cluster_zstats_outputs = cluster_zstats.run() threshold_file = cluster_zstats_outputs.outputs.threshold_file return threshold_file
def applyMask(input_file, mask_file): fslPath = scaleBy10(input_file, inv=False) # maks apply output_file = os.path.join( os.path.dirname(input_file), os.path.basename(input_file).split('.')[0]) + 'BET.nii.gz' myMaskapply = fsl.ApplyMask(in_file=fslPath, out_file=output_file, mask_file=mask_file) print(myMaskapply.cmdline) myMaskapply.run() os.remove(fslPath) # unscale result data by factor 10ˆ(-1) output_file = scaleBy10(output_file, inv=True) return output_file
def cluster_zstats(zstat, volume, dlh): import nipype.interfaces.fsl as fsl import os study_mask = '/Volumes/Amr_1TB/NARPS/narps_templateBrainExtractionMask.nii.gz' cope_no = zstat[ -8] #number of the zstat file after taking into account .nii.gz if zstat[-36:-32] == 'gain': cope = '/media/amr/Amr_4TB/NARPS/output_narps_proc_3rd_level/gain_stat_flameo_neg/+/cope{0}.nii.gz'.format( cope_no) elif zstat[-36:-32] == 'loss': cope = '/media/amr/Amr_4TB/NARPS/output_narps_proc_3rd_level/loss_stat_flameo_neg/+/cope{0}.nii.gz'.format( cope_no) #mask here not in a seperate node, because I need the original zstat to get the number mask_zstat = fsl.ApplyMask() mask_zstat.inputs.in_file = zstat mask_zstat.inputs.mask_file = study_mask mask_zstat_outputs = mask_zstat.run() masked_zstat = mask_zstat_outputs.outputs.out_file cluster_zstats = fsl.Cluster() cluster_zstats.inputs.in_file = masked_zstat cluster_zstats.inputs.cope_file = cope cluster_zstats.inputs.threshold = 3.1 cluster_zstats.inputs.pthreshold = 0.001 cluster_zstats.inputs.connectivity = 26 cluster_zstats.inputs.volume = volume cluster_zstats.inputs.dlh = dlh cluster_zstats.inputs.out_threshold_file = 'thresh_zstat.nii.gz' cluster_zstats.inputs.out_index_file = 'cluster_mask_zstat.nii.gz' cluster_zstats.inputs.out_localmax_txt_file = 'lmax_zstat_std.txt' cluster_zstats.inputs.use_mm = True print(cluster_zstats.cmdline) cluster_zstats_outputs = cluster_zstats.run() threshold_file = cluster_zstats_outputs.outputs.threshold_file return masked_zstat, threshold_file
def init_enhance_and_skullstrip_epi_wf(name='enhance_and_skullstrip_epi_wf'): workflow = pe.Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=[ 'mask_file', 'skull_stripped_file', 'bias_corrected_file', 'out_report' ]), name='outputnode') n4_correct = pe.Node(ants.N4BiasFieldCorrection(dimension=3, copy_header=True), name='n4_correct') skullstrip_first_pass = pe.Node(fsl.BET(frac=0.2, mask=True), name='skullstrip_first_pass') unifize = pe.Node(afni.Unifize(t2=True, outputtype='NIFTI_GZ', args='-clfrac 0.4', out_file="uni.nii.gz"), name='unifize') skullstrip_second_pass = pe.Node(afni.Automask(dilate=1, outputtype='NIFTI_GZ'), name='skullstrip_second_pass') combine_masks = pe.Node(fsl.BinaryMaths(operation='mul'), name='combine_masks') apply_mask = pe.Node(fsl.ApplyMask(), name='apply_mask') mask_reportlet = pe.Node(SimpleShowMaskRPT(), name='mask_reportlet') workflow.connect([ (inputnode, n4_correct, [('in_file', 'input_image')]), (n4_correct, skullstrip_first_pass, [('output_image', 'in_file')]), (skullstrip_first_pass, unifize, [('out_file', 'in_file')]), (unifize, skullstrip_second_pass, [('out_file', 'in_file')]), (skullstrip_first_pass, combine_masks, [('mask_file', 'in_file')]), (skullstrip_second_pass, combine_masks, [('out_file', 'operand_file') ]), (unifize, apply_mask, [('out_file', 'in_file')]), (combine_masks, apply_mask, [('out_file', 'mask_file')]), (n4_correct, mask_reportlet, [('output_image', 'background_file')]), (combine_masks, mask_reportlet, [('out_file', 'mask_file')]), (combine_masks, outputnode, [('out_file', 'mask_file')]), (mask_reportlet, outputnode, [('out_report', 'out_report')]), (apply_mask, outputnode, [('out_file', 'skull_stripped_file')]), (n4_correct, outputnode, [('output_image', 'bias_corrected_file')]), ]) return workflow
def cleanup_edge_pipeline(name='Cleanup'): """ Perform some de-spiking filtering to clean up the edge of the fieldmap (copied from fsl_prepare_fieldmap) """ inputnode = pe.Node(niu.IdentityInterface(fields=['in_file', 'in_mask']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface(fields=['out_file']), name='outputnode') fugue = pe.Node(fsl.FUGUE(save_fmap=True, despike_2dfilter=True, despike_threshold=2.1), name='Despike') erode = pe.Node(fsl.maths.MathsCommand(nan2zeros=True, args='-kernel 2D -ero'), name='MskErode') newmsk = pe.Node(fsl.MultiImageMaths(op_string='-sub %s -thr 0.5 -bin'), name='NewMask') applymsk = pe.Node(fsl.ApplyMask(nan2zeros=True), name='ApplyMask') join = pe.Node(niu.Merge(2), name='Merge') addedge = pe.Node(fsl.MultiImageMaths(op_string='-mas %s -add %s'), name='AddEdge') wf = pe.Workflow(name=name) wf.connect([(inputnode, fugue, [('in_file', 'fmap_in_file'), ('in_mask', 'mask_file')]), (inputnode, erode, [('in_mask', 'in_file')]), (inputnode, newmsk, [('in_mask', 'in_file')]), (erode, newmsk, [('out_file', 'operand_files')]), (fugue, applymsk, [('fmap_out_file', 'in_file')]), (newmsk, applymsk, [('out_file', 'mask_file')]), (erode, join, [('out_file', 'in1')]), (applymsk, join, [('out_file', 'in2')]), (inputnode, addedge, [('in_file', 'in_file')]), (join, addedge, [('out', 'operand_files')]), (addedge, outputnode, [('out_file', 'out_file')])]) return wf
def doApplyMasking(infile, maskfile, outfile): # Doing Masking of input image with a given mask ''' Parameters ---------- infile : str path containing the image to be masked. maskfile : str path to store mask of the input image. outfile : str path to store masked version of the input image. Returns ------- both mask and masked version of input image ''' print('doing masking of', infile) mask = fsl.ApplyMask() mask.inputs.in_file = infile mask.inputs.mask_file = maskfile mask.inputs.out_file = outfile mask.run() print('masking finished', outfile, '\n')
def make_func_mask_workflow(name='funcmask', base_dir=None): brainmask = Workflow(name=name, base_dir=base_dir) inputnode = Node(utility.IdentityInterface(fields=['mean_file']), name='inputnode') outputnode = Node(utility.IdentityInterface(fields=['masked_file', 'mask']), name='outputnode') skullstrip1 = MapNode(fsl.BET(frac=0.2, mask=True, output_type='NIFTI_GZ'), name='skullstrip_first_pass', iterfield=['in_file']) brainmask.connect(inputnode, 'mean_file', skullstrip1, 'in_file') skullstrip2 = MapNode(afni.Automask(dilate=1, outputtype='NIFTI_GZ'), name='skullstrip_second_pass', iterfield=['in_file']) brainmask.connect(skullstrip1, 'out_file', skullstrip2, 'in_file') combine_masks = MapNode(fsl.BinaryMaths(operation='mul'), name='combine_masks', iterfield=['in_file', 'operand_file']) brainmask.connect(skullstrip1, 'mask_file', combine_masks, 'in_file') brainmask.connect(skullstrip2, 'out_file', combine_masks, 'operand_file') apply_mask = MapNode(fsl.ApplyMask(), name='apply_mask', iterfield=['in_file', 'mask_file']) brainmask.connect(inputnode, 'mean_file', apply_mask, 'in_file') brainmask.connect(combine_masks, 'out_file', apply_mask, 'mask_file') brainmask.connect(apply_mask, 'out_file', outputnode, 'masked_file') brainmask.connect(combine_masks, 'out_file', outputnode, 'mask') return brainmask
def init_fmriprep_adapter_wf(name="fmriprep_adapter_wf", memcalc=MemoryCalculator()): """ """ workflow = pe.Workflow(name=name) inputnode = pe.Node( Exec(fieldtpls=[("bold_std", "firststr"), ("bold_mask_std", "firststr"), ("confounds", "firststr"), ("vals", None)]), name="inputnode", run_without_submitting=True) outputnode = pe.Node( niu.IdentityInterface(fields=["files", "mask", "vals"]), name="outputnode") # applymask = pe.Node(interface=fsl.ApplyMask(), name="applymask", mem_gb=memcalc.volume_std_gb) workflow.connect(inputnode, "bold_std", applymask, "in_file") workflow.connect(inputnode, "bold_mask_std", applymask, "mask_file") # merge = pe.Node(niu.Merge(2), name="merge", run_without_submitting=True) workflow.connect(applymask, "out_file", merge, "in1") workflow.connect(inputnode, "confounds", merge, "in2") # workflow.connect(merge, "out", outputnode, "files") workflow.connect(inputnode, "bold_mask_std", outputnode, "mask") workflow.connect(inputnode, "vals", outputnode, "vals") return workflow
def bruker( measurements_base, template, DEBUG=False, exclude={}, functional_match={}, structural_match={}, sessions=[], subjects=[], actual_size=True, functional_blur_xy=False, functional_registration_method="structural", highpass_sigma=225, lowpass_sigma=None, negative_contrast_agent=False, n_procs=N_PROCS, realign="time", registration_mask=False, tr=1, very_nasty_bruker_delay_hack=False, workflow_name="generic", keep_work=False, autorotate=False, strict=False, verbose=False, ): ''' realign: {"space","time","spacetime",""} Parameter that dictates slictiming correction and realignment of slices. "time" (FSL.SliceTimer) is default, since it works safely. Use others only with caution! ''' if template: if template == "mouse": template = fetch_mouse_DSURQE()['template'] registration_mask = fetch_mouse_DSURQE()['mask'] elif template == "rat": template = fetch_rat_waxholm()['template'] registration_mask = fetch_rat_waxholm()['mask'] else: pass else: raise ValueError("No species or template specified") return -1 measurements_base = path.abspath(path.expanduser(measurements_base)) # add subject and session filters if present if subjects: structural_scan_types['subject'] = subjects if sessions: structural_scan_types['session'] = sessions # define measurement directories to be processed, and populate the list either with the given include_measurements, or with an intelligent selection data_selection = pd.DataFrame([]) if structural_match: s_data_selection = get_data_selection( measurements_base, match=structural_match, exclude=exclude, ) structural_scan_types = s_data_selection['scan_type'].unique() data_selection = pd.concat([data_selection, s_data_selection]) if functional_match: f_data_selection = get_data_selection( measurements_base, match=functional_match, exclude=exclude, ) functional_scan_types = f_data_selection['scan_type'].unique() data_selection = pd.concat([data_selection, f_data_selection]) # we currently only support one structural scan type per session #if functional_registration_method in ("structural", "composite") and structural_scan_types: # structural_scan_types = [structural_scan_types[0]] # we start to define nipype workflow elements (nodes, connections, meta) subjects_sessions = data_selection[["subject", "session" ]].drop_duplicates().values.tolist() if debug: print('Data selection:') print(data_selection) print('Iterating over:') print(subjects_sessions) infosource = pe.Node(interface=util.IdentityInterface( fields=['subject_session'], mandatory_inputs=False), name="infosource") infosource.iterables = [('subject_session', subjects_sessions)] get_f_scan = pe.Node(name='get_f_scan', interface=util.Function( function=get_scan, input_names=inspect.getargspec(get_scan)[0], output_names=['scan_path', 'scan_type', 'trial'])) if not strict: get_f_scan.inputs.ignore_exception = True get_f_scan.inputs.data_selection = data_selection get_f_scan.inputs.measurements_base = measurements_base get_f_scan.iterables = ("scan_type", functional_scan_types) f_bru2nii = pe.Node(interface=bru2nii.Bru2(), name="f_bru2nii") f_bru2nii.inputs.actual_size = actual_size dummy_scans = pe.Node( name='dummy_scans', interface=util.Function( function=force_dummy_scans, input_names=inspect.getargspec(force_dummy_scans)[0], output_names=['out_file'])) dummy_scans.inputs.desired_dummy_scans = DUMMY_SCANS bandpass = pe.Node(interface=fsl.maths.TemporalFilter(), name="bandpass") bandpass.inputs.highpass_sigma = highpass_sigma if lowpass_sigma: bandpass.inputs.lowpass_sigma = lowpass_sigma else: bandpass.inputs.lowpass_sigma = tr #bids_filename = pe.Node(name='bids_filename', interface=util.Function(function=sss_filename,input_names=inspect.getargspec(sss_filename)[0], output_names=['filename'])) bids_filename = pe.Node(name='bids_filename', interface=util.Function( function=bids_naming, input_names=inspect.getargspec(bids_naming)[0], output_names=['filename'])) bids_filename.inputs.metadata = data_selection #bids_stim_filename = pe.Node(name='bids_stim_filename', interface=util.Function(function=sss_filename,input_names=inspect.getargspec(sss_filename)[0], output_names=['filename'])) bids_stim_filename = pe.Node( name='bids_stim_filename', interface=util.Function(function=bids_naming, input_names=inspect.getargspec(bids_naming)[0], output_names=['filename'])) bids_stim_filename.inputs.suffix = "events" bids_stim_filename.inputs.extension = ".tsv" bids_stim_filename.inputs.metadata = data_selection events_file = pe.Node( name='events_file', interface=util.Function( function=write_events_file, input_names=inspect.getargspec(write_events_file)[0], output_names=['out_file'])) events_file.inputs.dummy_scans_ms = DUMMY_SCANS * tr * 1000 events_file.inputs.stim_protocol_dictionary = STIM_PROTOCOL_DICTIONARY events_file.inputs.very_nasty_bruker_delay_hack = very_nasty_bruker_delay_hack if not (strict or verbose): events_file.inputs.ignore_exception = True datasink = pe.Node(nio.DataSink(), name='datasink') datasink.inputs.base_directory = path.join(measurements_base, "preprocessing", workflow_name) datasink.inputs.parameterization = False if not (strict or verbose): datasink.inputs.ignore_exception = True workflow_connections = [ (infosource, get_f_scan, [('subject_session', 'selector')]), (infosource, bids_stim_filename, [('subject_session', 'subject_session')]), (get_f_scan, bids_stim_filename, [('scan_type', 'scan_type')]), (get_f_scan, f_bru2nii, [('scan_path', 'input_dir')]), (f_bru2nii, dummy_scans, [('nii_file', 'in_file')]), (get_f_scan, dummy_scans, [('scan_path', 'scan_dir')]), (get_f_scan, events_file, [('trial', 'trial'), ('scan_path', 'scan_dir')]), (events_file, datasink, [('out_file', 'func.@events')]), (bids_stim_filename, events_file, [('filename', 'out_file')]), (infosource, datasink, [(('subject_session', ss_to_path), 'container') ]), (infosource, bids_filename, [('subject_session', 'subject_session')]), (get_f_scan, bids_filename, [('scan_type', 'scan_type')]), (bids_filename, bandpass, [('filename', 'out_file')]), (bandpass, datasink, [('out_file', 'func')]), ] if realign == "space": realigner = pe.Node(interface=spm.Realign(), name="realigner") realigner.inputs.register_to_mean = True workflow_connections.extend([ (dummy_scans, realigner, [('out_file', 'in_file')]), ]) elif realign == "spacetime": realigner = pe.Node(interface=nipy.SpaceTimeRealigner(), name="realigner") realigner.inputs.slice_times = "asc_alt_2" realigner.inputs.tr = tr realigner.inputs.slice_info = 3 #3 for coronal slices (2 for horizontal, 1 for sagittal) workflow_connections.extend([ (dummy_scans, realigner, [('out_file', 'in_file')]), ]) elif realign == "time": realigner = pe.Node(interface=fsl.SliceTimer(), name="slicetimer") realigner.inputs.time_repetition = tr workflow_connections.extend([ (dummy_scans, realigner, [('out_file', 'in_file')]), ]) #ADDING SELECTABLE NODES AND EXTENDING WORKFLOW AS APPROPRIATE: if actual_size: s_biascorrect, f_biascorrect = real_size_nodes() else: s_biascorrect, f_biascorrect = inflated_size_nodes() if structural_scan_types.any(): get_s_scan = pe.Node( name='get_s_scan', interface=util.Function( function=get_scan, input_names=inspect.getargspec(get_scan)[0], output_names=['scan_path', 'scan_type', 'trial'])) if not strict: get_s_scan.inputs.ignore_exception = True get_s_scan.inputs.data_selection = data_selection get_s_scan.inputs.measurements_base = measurements_base get_s_scan.iterables = ("scan_type", structural_scan_types) s_bru2nii = pe.Node(interface=bru2nii.Bru2(), name="s_bru2nii") s_bru2nii.inputs.force_conversion = True s_bru2nii.inputs.actual_size = actual_size #s_bids_filename = pe.Node(name='s_bids_filename', interface=util.Function(function=sss_filename,input_names=inspect.getargspec(sss_filename)[0], output_names=['filename'])) s_bids_filename = pe.Node( name='s_bids_filename', interface=util.Function( function=bids_naming, input_names=inspect.getargspec(bids_naming)[0], output_names=['filename'])) s_bids_filename.inputs.metadata = data_selection if actual_size: s_register, s_warp, _, _ = DSURQEc_structural_registration( template, registration_mask) #TODO: incl. in func registration if autorotate: workflow_connections.extend([ (s_biascorrect, s_rotated, [('output_image', 'out_file')]), (s_rotated, s_register, [('out_file', 'moving_image')]), ]) else: workflow_connections.extend([ (s_biascorrect, s_register, [('output_image', 'moving_image')]), (s_register, s_warp, [('composite_transform', 'transforms') ]), (s_bru2nii, s_warp, [('nii_file', 'input_image')]), (s_warp, datasink, [('output_image', 'anat')]), ]) else: s_reg_biascorrect = pe.Node(interface=ants.N4BiasFieldCorrection(), name="s_reg_biascorrect") s_reg_biascorrect.inputs.dimension = 3 s_reg_biascorrect.inputs.bspline_fitting_distance = 95 s_reg_biascorrect.inputs.shrink_factor = 2 s_reg_biascorrect.inputs.n_iterations = [500, 500, 500, 500] s_reg_biascorrect.inputs.convergence_threshold = 1e-14 s_cutoff = pe.Node(interface=fsl.ImageMaths(), name="s_cutoff") s_cutoff.inputs.op_string = "-thrP 20 -uthrp 98" s_BET = pe.Node(interface=fsl.BET(), name="s_BET") s_BET.inputs.mask = True s_BET.inputs.frac = 0.3 s_BET.inputs.robust = True s_mask = pe.Node(interface=fsl.ApplyMask(), name="s_mask") s_register, s_warp, f_warp = structural_registration(template) workflow_connections.extend([ (s_bru2nii, s_reg_biascorrect, [('nii_file', 'input_image')]), (s_reg_biascorrect, s_cutoff, [('output_image', 'in_file')]), (s_cutoff, s_BET, [('out_file', 'in_file')]), (s_biascorrect, s_mask, [('output_image', 'in_file')]), (s_BET, s_mask, [('mask_file', 'mask_file')]), ]) #TODO: incl. in func registration if autorotate: workflow_connections.extend([ (s_mask, s_rotated, [('out_file', 'out_file')]), (s_rotated, s_register, [('out_file', 'moving_image')]), ]) else: workflow_connections.extend([ (s_mask, s_register, [('out_file', 'moving_image')]), (s_register, s_warp, [('composite_transform', 'transforms') ]), (s_bru2nii, s_warp, [('nii_file', 'input_image')]), (s_warp, datasink, [('output_image', 'anat')]), ]) if autorotate: s_rotated = autorotate(template) workflow_connections.extend([ (infosource, get_s_scan, [('subject_session', 'selector')]), (infosource, s_bids_filename, [('subject_session', 'subject_session')]), (get_s_scan, s_bru2nii, [('scan_path', 'input_dir')]), (get_s_scan, s_bids_filename, [('scan_type', 'scan_type')]), (s_bids_filename, s_warp, [('filename', 'output_image')]), (s_bru2nii, s_biascorrect, [('nii_file', 'input_image')]), ]) if functional_registration_method == "structural": if not structural_scan_types: raise ValueError( 'The option `registration="structural"` requires there to be a structural scan type.' ) workflow_connections.extend([ (s_register, f_warp, [('composite_transform', 'transforms')]), ]) if realign == "space": workflow_connections.extend([ (realigner, f_warp, [('realigned_files', 'input_image')]), ]) elif realign == "spacetime": workflow_connections.extend([ (realigner, f_warp, [('out_file', 'input_image')]), ]) elif realign == "time": workflow_connections.extend([ (realigner, f_warp, [('slice_time_corrected_file', 'input_image')]), ]) else: workflow_connections.extend([ (dummy_scans, f_warp, [('out_file', 'input_image')]), ]) if functional_registration_method == "composite": if not structural_scan_types.any(): raise ValueError( 'The option `registration="composite"` requires there to be a structural scan type.' ) _, _, f_register, f_warp = DSURQEc_structural_registration( template, registration_mask) temporal_mean = pe.Node(interface=fsl.MeanImage(), name="temporal_mean") merge = pe.Node(util.Merge(2), name='merge') workflow_connections.extend([ (temporal_mean, f_biascorrect, [('out_file', 'input_image')]), (f_biascorrect, f_register, [('output_image', 'moving_image')]), (s_biascorrect, f_register, [('output_image', 'fixed_image')]), (f_register, merge, [('composite_transform', 'in1')]), (s_register, merge, [('composite_transform', 'in2')]), (merge, f_warp, [('out', 'transforms')]), ]) if realign == "space": workflow_connections.extend([ (realigner, temporal_mean, [('realigned_files', 'in_file')]), (realigner, f_warp, [('realigned_files', 'input_image')]), ]) elif realign == "spacetime": workflow_connections.extend([ (realigner, temporal_mean, [('out_file', 'in_file')]), (realigner, f_warp, [('out_file', 'input_image')]), ]) elif realign == "time": workflow_connections.extend([ (realigner, temporal_mean, [('slice_time_corrected_file', 'in_file')]), (realigner, f_warp, [('slice_time_corrected_file', 'input_image')]), ]) else: workflow_connections.extend([ (dummy_scans, temporal_mean, [('out_file', 'in_file')]), (dummy_scans, f_warp, [('out_file', 'input_image')]), ]) elif functional_registration_method == "functional": f_register, f_warp = functional_registration(template) temporal_mean = pe.Node(interface=fsl.MeanImage(), name="temporal_mean") #f_cutoff = pe.Node(interface=fsl.ImageMaths(), name="f_cutoff") #f_cutoff.inputs.op_string = "-thrP 30" #f_BET = pe.Node(interface=fsl.BET(), name="f_BET") #f_BET.inputs.mask = True #f_BET.inputs.frac = 0.5 workflow_connections.extend([ (temporal_mean, f_biascorrect, [('out_file', 'input_image')]), #(f_biascorrect, f_cutoff, [('output_image', 'in_file')]), #(f_cutoff, f_BET, [('out_file', 'in_file')]), #(f_BET, f_register, [('out_file', 'moving_image')]), (f_biascorrect, f_register, [('output_image', 'moving_image')]), (f_register, f_warp, [('composite_transform', 'transforms')]), ]) if realign == "space": workflow_connections.extend([ (realigner, temporal_mean, [('realigned_files', 'in_file')]), (realigner, f_warp, [('realigned_files', 'input_image')]), ]) elif realign == "spacetime": workflow_connections.extend([ (realigner, temporal_mean, [('out_file', 'in_file')]), (realigner, f_warp, [('out_file', 'input_image')]), ]) elif realign == "time": workflow_connections.extend([ (realigner, temporal_mean, [('slice_time_corrected_file', 'in_file')]), (realigner, f_warp, [('slice_time_corrected_file', 'input_image')]), ]) else: workflow_connections.extend([ (dummy_scans, temporal_mean, [('out_file', 'in_file')]), (dummy_scans, f_warp, [('out_file', 'input_image')]), ]) invert = pe.Node(interface=fsl.ImageMaths(), name="invert") if functional_blur_xy and negative_contrast_agent: blur = pe.Node(interface=afni.preprocess.BlurToFWHM(), name="blur") blur.inputs.fwhmxy = functional_blur_xy workflow_connections.extend([ (f_warp, blur, [('output_image', 'in_file')]), (blur, invert, [(('out_file', fslmaths_invert_values), 'op_string') ]), (blur, invert, [('out_file', 'in_file')]), (invert, bandpass, [('out_file', 'in_file')]), ]) elif functional_blur_xy: blur = pe.Node(interface=afni.preprocess.BlurToFWHM(), name="blur") blur.inputs.fwhmxy = functional_blur_xy workflow_connections.extend([ (f_warp, blur, [('output_image', 'in_file')]), (blur, bandpass, [('out_file', 'in_file')]), ]) elif negative_contrast_agent: blur = pe.Node(interface=afni.preprocess.BlurToFWHM(), name="blur") blur.inputs.fwhmxy = functional_blur_xy workflow_connections.extend([ (f_warp, invert, [(('output_image', fslmaths_invert_values), 'op_string')]), (f_warp, invert, [('output_image', 'in_file')]), (invert, bandpass, [('out_file', 'in_file')]), ]) else: workflow_connections.extend([ (f_warp, bandpass, [('output_image', 'in_file')]), ]) workflow_config = { 'execution': { 'crashdump_dir': path.join(measurements_base, 'preprocessing/crashdump'), } } if debug: workflow_config['logging'] = { 'workflow_level': 'DEBUG', 'utils_level': 'DEBUG', 'interface_level': 'DEBUG', 'filemanip_level': 'DEBUG', 'log_to_file': 'true', } workdir_name = workflow_name + "_work" workflow = pe.Workflow(name=workdir_name) workflow.connect(workflow_connections) workflow.base_dir = path.join(measurements_base, "preprocessing") workflow.config = workflow_config workflow.write_graph(dotfilename=path.join(workflow.base_dir, workdir_name, "graph.dot"), graph2use="hierarchical", format="png") workflow.run(plugin="MultiProc", plugin_args={'n_procs': n_procs}) if not keep_work: shutil.rmtree(path.join(workflow.base_dir, workdir_name))
def create_nonlinear_pipeline(name='nonlinear'): # workflow nonlinear = Workflow(name='nonlinear') # inputnode inputnode = Node(util.IdentityInterface(fields=[ 't1_highres', 'epi2highres_lin', 'epi2highres_lin_itk', 'fov_mask', 'brain_mask', 'wmcsf_mask', 'highres2lowres_itk' ]), name='inputnode') # outputnode outputnode = Node(util.IdentityInterface(fields=[ 'epi2highres_warp', 'epi2highres_invwarp', 'epi2highres_nonlin', 'brainmask_highres', 'wmcsfmask_highres' ]), name='outputnode') # project brainmask and wmcsf mask from lowres to highres mp2rage space brainmask = Node(ants.ApplyTransforms(dimension=3, invert_transform_flags=[True], interpolation='NearestNeighbor'), name='brainmask') wmcsf_mask = Node(ants.ApplyTransforms(dimension=3, invert_transform_flags=[True], interpolation='NearestNeighbor'), name='wmcsf_mask') # mask t1 #dilate brainmask dil_brainmask = Node(fs.Binarize(min=0.5, out_type='nii.gz', dilate=15), name='dil_brainmask') mask_epi = Node(fsl.ApplyMask(out_file='epi2highres_lin_masked.nii.gz'), name='mask_epi') nonlinear.connect([ (inputnode, brainmask, [('brain_mask', 'input_image'), ('t1_highres', 'reference_image'), ('highres2lowres_itk', 'transforms')]), (brainmask, outputnode, [('output_image', 'brainmask_highres')]), (inputnode, wmcsf_mask, [('wmcsf_mask', 'input_image'), ('t1_highres', 'reference_image'), ('highres2lowres_itk', 'transforms')]), (wmcsf_mask, outputnode, [('output_image', 'wmcsfmask_highres')]), (brainmask, dil_brainmask, [('output_image', 'in_file')]), (dil_brainmask, mask_epi, [('binary_file', 'mask_file')]), (inputnode, mask_epi, [('epi2highres_lin', 'in_file')]) ]) # transform fov mask, dilate and apply to t1 transform_fov = Node( ants.ApplyTransforms(dimension=3, output_image='fov_mask_highres.nii.gz', interpolation='NearestNeighbor'), 'transform_fov') dilate_fov = Node(fs.Binarize(min=0.5, dilate=5, binary_file='fov_mask_highres_dil.nii.gz'), name='dilate_fov') #mask t1 twice mask_t1_1 = Node(fsl.ApplyMask(out_file='t1_brain_masked.nii.gz'), name='mask_t1_1') mask_t1_2 = Node(fsl.ApplyMask(out_file='t1_brain_fov_masked.nii.gz'), name='mask_t1_2') nonlinear.connect([ (inputnode, transform_fov, [('fov_mask', 'input_image'), ('t1_highres', 'reference_image'), ('epi2highres_lin_itk', 'transforms')]), (transform_fov, dilate_fov, [('output_image', 'in_file')]), (brainmask, mask_t1_1, [('output_image', 'mask_file')]), (inputnode, mask_t1_1, [('t1_highres', 'in_file')]), (dilate_fov, mask_t1_2, [('binary_file', 'mask_file')]), (mask_t1_1, mask_t1_2, [('out_file', 'in_file')]), ]) # normalization with ants antsreg = Node(interface=ants.registration.Registration( dimension=3, metric=['CC'], metric_weight=[1.0], radius_or_number_of_bins=[4], sampling_strategy=['None'], transforms=['SyN'], args='-g 0.1x1x0.1', transform_parameters=[(0.10, 3, 0)], number_of_iterations=[[50, 20, 10]], convergence_threshold=[1e-06], convergence_window_size=[10], shrink_factors=[[4, 2, 1]], smoothing_sigmas=[[2, 1, 0]], sigma_units=['vox'], use_estimate_learning_rate_once=[True], use_histogram_matching=[True], collapse_output_transforms=True, output_inverse_warped_image=True, output_warped_image=True, interpolation='BSpline'), name='antsreg') antsreg.plugin_args = {'override_specs': 'request_memory = 40000'} nonlinear.connect([(mask_epi, antsreg, [('out_file', 'moving_image')]), (mask_t1_2, antsreg, [('out_file', 'fixed_image')]), (antsreg, outputnode, [('reverse_transforms', 'epi2highres_invwarp'), ('forward_transforms', 'epi2highres_warp'), ('warped_image', 'epi2highres_nonlin')])]) return nonlinear
def create_workflow(files, target_file, subject_id, TR, slice_times, norm_threshold=1, num_components=5, vol_fwhm=None, surf_fwhm=None, lowpass_freq=-1, highpass_freq=-1, subjects_dir=None, sink_directory=os.getcwd(), target_subject=['fsaverage3', 'fsaverage4'], name='resting'): wf = Workflow(name=name) # Rename files in case they are named identically name_unique = MapNode(Rename(format_string='rest_%(run)02d'), iterfield=['in_file', 'run'], name='rename') name_unique.inputs.keep_ext = True name_unique.inputs.run = list(range(1, len(files) + 1)) name_unique.inputs.in_file = files realign = Node(interface=spm.Realign(), name="realign") realign.inputs.jobtype = 'estwrite' num_slices = len(slice_times) slice_timing = Node(interface=spm.SliceTiming(), name="slice_timing") slice_timing.inputs.num_slices = num_slices slice_timing.inputs.time_repetition = TR slice_timing.inputs.time_acquisition = TR - TR / float(num_slices) slice_timing.inputs.slice_order = (np.argsort(slice_times) + 1).tolist() slice_timing.inputs.ref_slice = int(num_slices / 2) # Comute TSNR on realigned data regressing polynomials upto order 2 tsnr = MapNode(TSNR(regress_poly=2), iterfield=['in_file'], name='tsnr') wf.connect(slice_timing, 'timecorrected_files', tsnr, 'in_file') # Compute the median image across runs calc_median = Node(Function(input_names=['in_files'], output_names=['median_file'], function=median, imports=imports), name='median') wf.connect(tsnr, 'detrended_file', calc_median, 'in_files') """Segment and Register """ registration = create_reg_workflow(name='registration') wf.connect(calc_median, 'median_file', registration, 'inputspec.mean_image') registration.inputs.inputspec.subject_id = subject_id registration.inputs.inputspec.subjects_dir = subjects_dir registration.inputs.inputspec.target_image = target_file """Use :class:`nipype.algorithms.rapidart` to determine which of the images in the functional series are outliers based on deviations in intensity or movement. """ art = Node(interface=ArtifactDetect(), name="art") art.inputs.use_differences = [True, True] art.inputs.use_norm = True art.inputs.norm_threshold = norm_threshold art.inputs.zintensity_threshold = 9 art.inputs.mask_type = 'spm_global' art.inputs.parameter_source = 'SPM' """Here we are connecting all the nodes together. Notice that we add the merge node only if you choose to use 4D. Also `get_vox_dims` function is passed along the input volume of normalise to set the optimal voxel sizes. """ wf.connect([ (name_unique, realign, [('out_file', 'in_files')]), (realign, slice_timing, [('realigned_files', 'in_files')]), (slice_timing, art, [('timecorrected_files', 'realigned_files')]), (realign, art, [('realignment_parameters', 'realignment_parameters')]), ]) def selectindex(files, idx): import numpy as np from nipype.utils.filemanip import filename_to_list, list_to_filename return list_to_filename( np.array(filename_to_list(files))[idx].tolist()) mask = Node(fsl.BET(), name='getmask') mask.inputs.mask = True wf.connect(calc_median, 'median_file', mask, 'in_file') # get segmentation in normalized functional space def merge_files(in1, in2): out_files = filename_to_list(in1) out_files.extend(filename_to_list(in2)) return out_files # filter some noise # Compute motion regressors motreg = Node(Function( input_names=['motion_params', 'order', 'derivatives'], output_names=['out_files'], function=motion_regressors, imports=imports), name='getmotionregress') wf.connect(realign, 'realignment_parameters', motreg, 'motion_params') # Create a filter to remove motion and art confounds createfilter1 = Node(Function( input_names=['motion_params', 'comp_norm', 'outliers', 'detrend_poly'], output_names=['out_files'], function=build_filter1, imports=imports), name='makemotionbasedfilter') createfilter1.inputs.detrend_poly = 2 wf.connect(motreg, 'out_files', createfilter1, 'motion_params') wf.connect(art, 'norm_files', createfilter1, 'comp_norm') wf.connect(art, 'outlier_files', createfilter1, 'outliers') filter1 = MapNode(fsl.GLM(out_f_name='F_mcart.nii', out_pf_name='pF_mcart.nii', demean=True), iterfield=['in_file', 'design', 'out_res_name'], name='filtermotion') wf.connect(slice_timing, 'timecorrected_files', filter1, 'in_file') wf.connect(slice_timing, ('timecorrected_files', rename, '_filtermotart'), filter1, 'out_res_name') wf.connect(createfilter1, 'out_files', filter1, 'design') createfilter2 = MapNode(Function(input_names=[ 'realigned_file', 'mask_file', 'num_components', 'extra_regressors' ], output_names=['out_files'], function=extract_noise_components, imports=imports), iterfield=['realigned_file', 'extra_regressors'], name='makecompcorrfilter') createfilter2.inputs.num_components = num_components wf.connect(createfilter1, 'out_files', createfilter2, 'extra_regressors') wf.connect(filter1, 'out_res', createfilter2, 'realigned_file') wf.connect(registration, ('outputspec.segmentation_files', selectindex, [0, 2]), createfilter2, 'mask_file') filter2 = MapNode(fsl.GLM(out_f_name='F.nii', out_pf_name='pF.nii', demean=True), iterfield=['in_file', 'design', 'out_res_name'], name='filter_noise_nosmooth') wf.connect(filter1, 'out_res', filter2, 'in_file') wf.connect(filter1, ('out_res', rename, '_cleaned'), filter2, 'out_res_name') wf.connect(createfilter2, 'out_files', filter2, 'design') wf.connect(mask, 'mask_file', filter2, 'mask') bandpass = Node(Function( input_names=['files', 'lowpass_freq', 'highpass_freq', 'fs'], output_names=['out_files'], function=bandpass_filter, imports=imports), name='bandpass_unsmooth') bandpass.inputs.fs = 1. / TR bandpass.inputs.highpass_freq = highpass_freq bandpass.inputs.lowpass_freq = lowpass_freq wf.connect(filter2, 'out_res', bandpass, 'files') """Smooth the functional data using :class:`nipype.interfaces.spm.Smooth`. """ smooth = Node(interface=spm.Smooth(), name="smooth") smooth.inputs.fwhm = vol_fwhm wf.connect(bandpass, 'out_files', smooth, 'in_files') collector = Node(Merge(2), name='collect_streams') wf.connect(smooth, 'smoothed_files', collector, 'in1') wf.connect(bandpass, 'out_files', collector, 'in2') """ Transform the remaining images. First to anatomical and then to target """ warpall = MapNode(ants.ApplyTransforms(), iterfield=['input_image'], name='warpall') warpall.inputs.input_image_type = 3 warpall.inputs.interpolation = 'Linear' warpall.inputs.invert_transform_flags = [False, False] warpall.inputs.terminal_output = 'file' warpall.inputs.reference_image = target_file warpall.inputs.args = '--float' warpall.inputs.num_threads = 1 # transform to target wf.connect(collector, 'out', warpall, 'input_image') wf.connect(registration, 'outputspec.transforms', warpall, 'transforms') mask_target = Node(fsl.ImageMaths(op_string='-bin'), name='target_mask') wf.connect(registration, 'outputspec.anat2target', mask_target, 'in_file') maskts = MapNode(fsl.ApplyMask(), iterfield=['in_file'], name='ts_masker') wf.connect(warpall, 'output_image', maskts, 'in_file') wf.connect(mask_target, 'out_file', maskts, 'mask_file') # map to surface # extract aparc+aseg ROIs # extract subcortical ROIs # extract target space ROIs # combine subcortical and cortical rois into a single cifti file ####### # Convert aparc to subject functional space # Sample the average time series in aparc ROIs sampleaparc = MapNode( freesurfer.SegStats(default_color_table=True), iterfield=['in_file', 'summary_file', 'avgwf_txt_file'], name='aparc_ts') sampleaparc.inputs.segment_id = ([8] + list(range(10, 14)) + [17, 18, 26, 47] + list(range(49, 55)) + [58] + list(range(1001, 1036)) + list(range(2001, 2036))) wf.connect(registration, 'outputspec.aparc', sampleaparc, 'segmentation_file') wf.connect(collector, 'out', sampleaparc, 'in_file') def get_names(files, suffix): """Generate appropriate names for output files """ from nipype.utils.filemanip import (split_filename, filename_to_list, list_to_filename) out_names = [] for filename in files: _, name, _ = split_filename(filename) out_names.append(name + suffix) return list_to_filename(out_names) wf.connect(collector, ('out', get_names, '_avgwf.txt'), sampleaparc, 'avgwf_txt_file') wf.connect(collector, ('out', get_names, '_summary.stats'), sampleaparc, 'summary_file') # Sample the time series onto the surface of the target surface. Performs # sampling into left and right hemisphere target = Node(IdentityInterface(fields=['target_subject']), name='target') target.iterables = ('target_subject', filename_to_list(target_subject)) samplerlh = MapNode(freesurfer.SampleToSurface(), iterfield=['source_file'], name='sampler_lh') samplerlh.inputs.sampling_method = "average" samplerlh.inputs.sampling_range = (0.1, 0.9, 0.1) samplerlh.inputs.sampling_units = "frac" samplerlh.inputs.interp_method = "trilinear" samplerlh.inputs.smooth_surf = surf_fwhm # samplerlh.inputs.cortex_mask = True samplerlh.inputs.out_type = 'niigz' samplerlh.inputs.subjects_dir = subjects_dir samplerrh = samplerlh.clone('sampler_rh') samplerlh.inputs.hemi = 'lh' wf.connect(collector, 'out', samplerlh, 'source_file') wf.connect(registration, 'outputspec.out_reg_file', samplerlh, 'reg_file') wf.connect(target, 'target_subject', samplerlh, 'target_subject') samplerrh.set_input('hemi', 'rh') wf.connect(collector, 'out', samplerrh, 'source_file') wf.connect(registration, 'outputspec.out_reg_file', samplerrh, 'reg_file') wf.connect(target, 'target_subject', samplerrh, 'target_subject') # Combine left and right hemisphere to text file combiner = MapNode(Function(input_names=['left', 'right'], output_names=['out_file'], function=combine_hemi, imports=imports), iterfield=['left', 'right'], name="combiner") wf.connect(samplerlh, 'out_file', combiner, 'left') wf.connect(samplerrh, 'out_file', combiner, 'right') # Sample the time series file for each subcortical roi ts2txt = MapNode(Function( input_names=['timeseries_file', 'label_file', 'indices'], output_names=['out_file'], function=extract_subrois, imports=imports), iterfield=['timeseries_file'], name='getsubcortts') ts2txt.inputs.indices = [8] + list(range(10, 14)) + [17, 18, 26, 47] +\ list(range(49, 55)) + [58] ts2txt.inputs.label_file = \ os.path.abspath(('OASIS-TRT-20_jointfusion_DKT31_CMA_labels_in_MNI152_' '2mm_v2.nii.gz')) wf.connect(maskts, 'out_file', ts2txt, 'timeseries_file') ###### substitutions = [('_target_subject_', ''), ('_filtermotart_cleaned_bp_trans_masked', ''), ('_filtermotart_cleaned_bp', '')] regex_subs = [ ('_ts_masker.*/sar', '/smooth/'), ('_ts_masker.*/ar', '/unsmooth/'), ('_combiner.*/sar', '/smooth/'), ('_combiner.*/ar', '/unsmooth/'), ('_aparc_ts.*/sar', '/smooth/'), ('_aparc_ts.*/ar', '/unsmooth/'), ('_getsubcortts.*/sar', '/smooth/'), ('_getsubcortts.*/ar', '/unsmooth/'), ('series/sar', 'series/smooth/'), ('series/ar', 'series/unsmooth/'), ('_inverse_transform./', ''), ] # Save the relevant data into an output directory datasink = Node(interface=DataSink(), name="datasink") datasink.inputs.base_directory = sink_directory datasink.inputs.container = subject_id datasink.inputs.substitutions = substitutions datasink.inputs.regexp_substitutions = regex_subs # (r'(/_.*(\d+/))', r'/run\2') wf.connect(realign, 'realignment_parameters', datasink, 'resting.qa.motion') wf.connect(art, 'norm_files', datasink, 'resting.qa.art.@norm') wf.connect(art, 'intensity_files', datasink, 'resting.qa.art.@intensity') wf.connect(art, 'outlier_files', datasink, 'resting.qa.art.@outlier_files') wf.connect(registration, 'outputspec.segmentation_files', datasink, 'resting.mask_files') wf.connect(registration, 'outputspec.anat2target', datasink, 'resting.qa.ants') wf.connect(mask, 'mask_file', datasink, 'resting.mask_files.@brainmask') wf.connect(mask_target, 'out_file', datasink, 'resting.mask_files.target') wf.connect(filter1, 'out_f', datasink, 'resting.qa.compmaps.@mc_F') wf.connect(filter1, 'out_pf', datasink, 'resting.qa.compmaps.@mc_pF') wf.connect(filter2, 'out_f', datasink, 'resting.qa.compmaps') wf.connect(filter2, 'out_pf', datasink, 'resting.qa.compmaps.@p') wf.connect(bandpass, 'out_files', datasink, 'resting.timeseries.@bandpassed') wf.connect(smooth, 'smoothed_files', datasink, 'resting.timeseries.@smoothed') wf.connect(createfilter1, 'out_files', datasink, 'resting.regress.@regressors') wf.connect(createfilter2, 'out_files', datasink, 'resting.regress.@compcorr') wf.connect(maskts, 'out_file', datasink, 'resting.timeseries.target') wf.connect(sampleaparc, 'summary_file', datasink, 'resting.parcellations.aparc') wf.connect(sampleaparc, 'avgwf_txt_file', datasink, 'resting.parcellations.aparc.@avgwf') wf.connect(ts2txt, 'out_file', datasink, 'resting.parcellations.grayo.@subcortical') datasink2 = Node(interface=DataSink(), name="datasink2") datasink2.inputs.base_directory = sink_directory datasink2.inputs.container = subject_id datasink2.inputs.substitutions = substitutions datasink2.inputs.regexp_substitutions = regex_subs # (r'(/_.*(\d+/))', r'/run\2') wf.connect(combiner, 'out_file', datasink2, 'resting.parcellations.grayo.@surface') return wf
def init_skullstrip_bold_wf(name="skullstrip_bold_wf"): """ Apply skull-stripping to a BOLD image. It is intended to be used on an image that has previously been bias-corrected with :py:func:`~niworkflows.func.util.init_enhance_and_skullstrip_bold_wf` Workflow Graph .. workflow :: :graph2use: orig :simple_form: yes from niworkflows.func.util import init_skullstrip_bold_wf wf = init_skullstrip_bold_wf() Inputs ------ in_file : str BOLD image (single volume) Outputs ------- skull_stripped_file : str the ``in_file`` after skull-stripping mask_file : str mask of the skull-stripped input file out_report : str reportlet for the skull-stripping """ workflow = Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=["in_file"]), name="inputnode") outputnode = pe.Node( niu.IdentityInterface( fields=["mask_file", "skull_stripped_file", "out_report"]), name="outputnode", ) skullstrip_first_pass = pe.Node(fsl.BET(frac=0.2, mask=True), name="skullstrip_first_pass") skullstrip_second_pass = pe.Node(afni.Automask(dilate=1, outputtype="NIFTI_GZ"), name="skullstrip_second_pass") combine_masks = pe.Node(fsl.BinaryMaths(operation="mul"), name="combine_masks") apply_mask = pe.Node(fsl.ApplyMask(), name="apply_mask") mask_reportlet = pe.Node(SimpleShowMaskRPT(), name="mask_reportlet") # fmt: off workflow.connect([ (inputnode, skullstrip_first_pass, [("in_file", "in_file")]), (skullstrip_first_pass, skullstrip_second_pass, [("out_file", "in_file")]), (skullstrip_first_pass, combine_masks, [("mask_file", "in_file")]), (skullstrip_second_pass, combine_masks, [("out_file", "operand_file") ]), (combine_masks, outputnode, [("out_file", "mask_file")]), # Masked file (inputnode, apply_mask, [("in_file", "in_file")]), (combine_masks, apply_mask, [("out_file", "mask_file")]), (apply_mask, outputnode, [("out_file", "skull_stripped_file")]), # Reportlet (inputnode, mask_reportlet, [("in_file", "background_file")]), (combine_masks, mask_reportlet, [("out_file", "mask_file")]), (mask_reportlet, outputnode, [("out_report", "out_report")]), ]) # fmt: on return workflow
def create_transform_pipeline(name='transfrom_timeseries'): # set fsl output type fsl.FSLCommand.set_default_output_type('NIFTI_GZ') # initiate workflow transform_ts = Workflow(name='transform_timeseries') # inputnode inputnode=Node(util.IdentityInterface(fields=['orig_ts', 'anat_head', 'mat_moco', 'fullwarp', 'resolution', 'brain_mask' ]), name='inputnode') # outputnode outputnode=Node(util.IdentityInterface(fields=['trans_ts', 'trans_ts_mean', 'trans_ts_masked', 'resamp_brain', 'brain_mask_resamp', 'out_dvars' ]), name='outputnode') #resample anatomy resample = Node(fsl.FLIRT(datatype='float', out_file='T1_resampled.nii.gz'), name = 'resample_anat') transform_ts.connect([(inputnode, resample, [('anat_head', 'in_file'), ('anat_head', 'reference'), ('resolution', 'apply_isoxfm') ]), (resample, outputnode, [('out_file', 'resamp_brain')]) ]) # split timeseries in single volumes split=Node(fsl.Split(dimension='t', out_base_name='timeseries'), name='split') transform_ts.connect([(inputnode, split, [('orig_ts','in_file')])]) # applymoco premat and fullwarpfield applywarp = MapNode(fsl.ApplyWarp(interp='spline', relwarp=True, out_file='rest2anat.nii.gz', datatype='float'), iterfield=['in_file', 'premat'], name='applywarp') transform_ts.connect([(split, applywarp, [('out_files', 'in_file')]), (inputnode, applywarp, [('mat_moco', 'premat'), ('fullwarp','field_file')]), (resample, applywarp, [('out_file', 'ref_file')]) ]) # re-concatenate volumes merge=Node(fsl.Merge(dimension='t', merged_file='rest2anat.nii.gz'), name='merge') transform_ts.connect([(applywarp,merge,[('out_file','in_files')]), (merge, outputnode, [('merged_file', 'trans_ts')])]) # calculate new mean tmean = Node(fsl.maths.MeanImage(dimension='T', out_file='rest_mean2anat_lowres.nii.gz'), name='tmean') transform_ts.connect([(merge, tmean, [('merged_file', 'in_file')]), (tmean, outputnode, [('out_file', 'trans_ts_mean')]) ]) # resample brain mask resample_brain = Node(afni.Resample(resample_mode='NN', outputtype='NIFTI_GZ', out_file='T1_brain_mask_lowres.nii.gz'), name = 'resample_brain') transform_ts.connect([(inputnode, resample_brain, [('brain_mask', 'in_file')]), (tmean, resample_brain, [('out_file', 'master')]), (resample_brain, outputnode, [('out_file', 'brain_mask_resamp')]) ]) #mask the transformed file mask = Node(fsl.ApplyMask(), name="mask") transform_ts.connect([(resample_brain,mask, [('out_file', 'mask_file')]), (merge, mask, [('merged_file', 'in_file')]), (mask, outputnode, [('out_file', 'trans_ts_masked')]) ]) #calculate DVARS dvars = Node(confounds.ComputeDVARS(save_all=True, save_plot=True), name="dvars") transform_ts.connect([(resample_brain, dvars, [('out_file', 'in_mask')]), (merge, dvars, [('merged_file', 'in_file')]), (dvars, outputnode, [('out_all', 'out_dvars')]) ]) return transform_ts
def init_fmap_wf(omp_nthreads, fmap_bspline, name='fmap_wf'): """ Fieldmap workflow - when we have a sequence that directly measures the fieldmap we just need to mask it (using the corresponding magnitude image) to remove the noise in the surrounding air region, and ensure that units are Hz. .. workflow :: :graph2use: orig :simple_form: yes from fmriprep.workflows.fieldmap.fmap import init_fmap_wf wf = init_fmap_wf(omp_nthreads=6, fmap_bspline=False) """ workflow = pe.Workflow(name=name) inputnode = pe.Node( niu.IdentityInterface(fields=['magnitude', 'fieldmap']), name='inputnode') outputnode = pe.Node( niu.IdentityInterface(fields=['fmap', 'fmap_ref', 'fmap_mask']), name='outputnode') # Merge input magnitude images magmrg = pe.Node(IntraModalMerge(), name='magmrg') # Merge input fieldmap images fmapmrg = pe.Node(IntraModalMerge(zero_based_avg=False, hmc=False), name='fmapmrg') # de-gradient the fields ("bias/illumination artifact") n4_correct = pe.Node(ants.N4BiasFieldCorrection(dimension=3, copy_header=True), name='n4_correct', n_procs=omp_nthreads) bet = pe.Node(BETRPT(generate_report=True, frac=0.6, mask=True), name='bet') ds_fmap_mask = pe.Node(DerivativesDataSink(suffix='fmap_mask'), name='ds_report_fmap_mask', run_without_submitting=True) workflow.connect([ (inputnode, magmrg, [('magnitude', 'in_files')]), (inputnode, fmapmrg, [('fieldmap', 'in_files')]), (magmrg, n4_correct, [('out_file', 'input_image')]), (n4_correct, bet, [('output_image', 'in_file')]), (bet, outputnode, [('mask_file', 'fmap_mask'), ('out_file', 'fmap_ref')]), (inputnode, ds_fmap_mask, [('fieldmap', 'source_file')]), (bet, ds_fmap_mask, [('out_report', 'in_file')]), ]) if fmap_bspline: # despike_threshold=1.0, mask_erode=1), fmapenh = pe.Node(FieldEnhance(unwrap=False, despike=False), name='fmapenh', mem_gb=4, n_procs=omp_nthreads) workflow.connect([ (bet, fmapenh, [('mask_file', 'in_mask'), ('out_file', 'in_magnitude')]), (fmapmrg, fmapenh, [('out_file', 'in_file')]), (fmapenh, outputnode, [('out_file', 'fmap')]), ]) else: torads = pe.Node(FieldToRadS(), name='torads') prelude = pe.Node(fsl.PRELUDE(), name='prelude') tohz = pe.Node(FieldToHz(), name='tohz') denoise = pe.Node(fsl.SpatialFilter(operation='median', kernel_shape='sphere', kernel_size=3), name='denoise') demean = pe.Node(niu.Function(function=demean_image), name='demean') cleanup_wf = cleanup_edge_pipeline(name='cleanup_wf') applymsk = pe.Node(fsl.ApplyMask(), name='applymsk') workflow.connect([ (bet, prelude, [('mask_file', 'mask_file'), ('out_file', 'magnitude_file')]), (fmapmrg, torads, [('out_file', 'in_file')]), (torads, tohz, [('fmap_range', 'range_hz')]), (torads, prelude, [('out_file', 'phase_file')]), (prelude, tohz, [('unwrapped_phase_file', 'in_file')]), (tohz, denoise, [('out_file', 'in_file')]), (denoise, demean, [('out_file', 'in_file')]), (demean, cleanup_wf, [('out', 'inputnode.in_file')]), (bet, cleanup_wf, [('mask_file', 'inputnode.in_mask')]), (cleanup_wf, applymsk, [('outputnode.out_file', 'in_file')]), (bet, applymsk, [('mask_file', 'mask_file')]), (applymsk, outputnode, [('out_file', 'fmap')]), ]) return workflow
# FMRI PREPROCESSING NODES # ########### # skip dummy scans extract = Node(fsl.ExtractROI(t_min=nDelfMRI, # first volumes to be deleted t_size=-1), name="extract") # smoothing with SUSAN susan = Node(fsl.SUSAN(brightness_threshold = 2000.0, fwhm=6.0), # smoothing filter width (6mm, isotropic) name='susan') # masking the fMRI with a brain mask applymask = Node(fsl.ApplyMask(), name='applymask') ########### # # READ TASK INFO IN PREPRARATION FOR THE ANALYSIS # ########### # Creating the layout object for this BIDS data set layout = BIDSLayout(dataDir) # task information file fileEvent = layout.get(suffix='events', task=task_name,
biasfield_correction_anat.inputs.dimension = 3 biasfield_correction_anat.inputs.save_bias = True # biasfield_correction_anat.inputs.output_image = 'anat_bet_biasfield_corrected.nii.gz' #better not to, # it confuses the Registration # ====================================================================================================== # In[8]: # Extract one fmri image to use fro brain extraction, the same one you will use for mcflirt as reference roi = Node(fsl.ExtractROI(), name='extract_one_fMRI_volume') roi.inputs.t_min = 75 roi.inputs.t_size = 1 # ====================================================================================================== brain_extraction_roi = Node(fsl.ApplyMask(), name='brain_extraction_roi') # ====================================================================================================== # Remove skull of func using antsBrainExtraction.sh, i am using the study-based template that I build and remove # the skull manually using ITKsnap brain_extraction_bold = Node(fsl.ApplyMask(), name='brain_extraction_bold') # ======================================================================================================== # In[10]: # normalizing the anatomical_bias_corrected image to the common anatomical template # Here only we are calculating the paramters, we apply them later. reg_T1_2_temp = Node(ants.Registration(), name='reg_T1_2_temp') reg_T1_2_temp.inputs.args = '--float' reg_T1_2_temp.inputs.collapse_output_transforms = True
def init_skullstrip_bold_wf(name='skullstrip_bold_wf'): """ This workflow applies skull-stripping to a BOLD image. It is intended to be used on an image that has previously been bias-corrected with :py:func:`~niworkflows.func.util.init_enhance_and_skullstrip_bold_wf` .. workflow :: :graph2use: orig :simple_form: yes from niworkflows.func.util import init_skullstrip_bold_wf wf = init_skullstrip_bold_wf() Inputs in_file BOLD image (single volume) Outputs skull_stripped_file the ``in_file`` after skull-stripping mask_file mask of the skull-stripped input file out_report reportlet for the skull-stripping """ workflow = Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['in_file']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['mask_file', 'skull_stripped_file', 'out_report']), name='outputnode') skullstrip_first_pass = pe.Node(fsl.BET(frac=0.2, mask=True), name='skullstrip_first_pass') skullstrip_second_pass = pe.Node(afni.Automask(dilate=1, outputtype='NIFTI_GZ'), name='skullstrip_second_pass') combine_masks = pe.Node(fsl.BinaryMaths(operation='mul'), name='combine_masks') apply_mask = pe.Node(fsl.ApplyMask(), name='apply_mask') mask_reportlet = pe.Node(SimpleShowMaskRPT(), name='mask_reportlet') workflow.connect([ (inputnode, skullstrip_first_pass, [('in_file', 'in_file')]), (skullstrip_first_pass, skullstrip_second_pass, [('out_file', 'in_file')]), (skullstrip_first_pass, combine_masks, [('mask_file', 'in_file')]), (skullstrip_second_pass, combine_masks, [('out_file', 'operand_file') ]), (combine_masks, outputnode, [('out_file', 'mask_file')]), # Masked file (inputnode, apply_mask, [('in_file', 'in_file')]), (combine_masks, apply_mask, [('out_file', 'mask_file')]), (apply_mask, outputnode, [('out_file', 'skull_stripped_file')]), # Reportlet (inputnode, mask_reportlet, [('in_file', 'background_file')]), (combine_masks, mask_reportlet, [('out_file', 'mask_file')]), (mask_reportlet, outputnode, [('out_report', 'out_report')]), ]) return workflow
def init_enhance_and_skullstrip_bold_wf(name='enhance_and_skullstrip_bold_wf', pre_mask=False, omp_nthreads=1): """ This workflow takes in a :abbr:`BOLD (blood-oxygen level-dependant)` :abbr:`fMRI (functional MRI)` average/summary (e.g., a reference image averaging non-steady-state timepoints), and sharpens the histogram with the application of the N4 algorithm for removing the :abbr:`INU (intensity non-uniformity)` bias field and calculates a signal mask. Steps of this workflow are: 1. Calculate a tentative mask by registering (9-parameters) to *fMRIPrep*'s :abbr:`EPI (echo-planar imaging)` -*boldref* template, which is in MNI space. The tentative mask is obtained by resampling the MNI template's brainmask into *boldref*-space. 2. Binary dilation of the tentative mask with a sphere of 3mm diameter. 3. Run ANTs' ``N4BiasFieldCorrection`` on the input :abbr:`BOLD (blood-oxygen level-dependant)` average, using the mask generated in 1) instead of the internal Otsu thresholding. 4. Calculate a loose mask using FSL's ``bet``, with one mathematical morphology dilation of one iteration and a sphere of 6mm as structuring element. 5. Mask the :abbr:`INU (intensity non-uniformity)`-corrected image with the latest mask calculated in 3), then use AFNI's ``3dUnifize`` to *standardize* the T2* contrast distribution. 6. Calculate a mask using AFNI's ``3dAutomask`` after the contrast enhancement of 4). 7. Calculate a final mask as the intersection of 4) and 6). 8. Apply final mask on the enhanced reference. Step 1 can be skipped if the ``pre_mask`` argument is set to ``True`` and a tentative mask is passed in to the workflow throught the ``pre_mask`` Nipype input. .. workflow :: :graph2use: orig :simple_form: yes from niworkflows.func.util import init_enhance_and_skullstrip_bold_wf wf = init_enhance_and_skullstrip_bold_wf(omp_nthreads=1) **Parameters** name : str Name of workflow (default: ``enhance_and_skullstrip_bold_wf``) pre_mask : bool Indicates whether the ``pre_mask`` input will be set (and thus, step 1 should be skipped). omp_nthreads : int number of threads available to parallel nodes **Inputs** in_file BOLD image (single volume) pre_mask : bool A tentative brain mask to initialize the workflow (requires ``pre_mask`` parameter set ``True``). **Outputs** bias_corrected_file the ``in_file`` after `N4BiasFieldCorrection`_ skull_stripped_file the ``bias_corrected_file`` after skull-stripping mask_file mask of the skull-stripped input file out_report reportlet for the skull-stripping .. _N4BiasFieldCorrection: https://hdl.handle.net/10380/3053 """ workflow = Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['in_file', 'pre_mask']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['mask_file', 'skull_stripped_file', 'bias_corrected_file']), name='outputnode') # Dilate pre_mask pre_dilate = pe.Node(fsl.DilateImage(operation='max', kernel_shape='sphere', kernel_size=3.0, internal_datatype='char'), name='pre_mask_dilate') # Ensure mask's header matches reference's check_hdr = pe.Node(MatchHeader(), name='check_hdr', run_without_submitting=True) # Run N4 normally, force num_threads=1 for stability (images are small, no need for >1) n4_correct = pe.Node(ants.N4BiasFieldCorrection( dimension=3, copy_header=True, bspline_fitting_distance=200), name='n4_correct', n_procs=1) # Create a generous BET mask out of the bias-corrected EPI skullstrip_first_pass = pe.Node(fsl.BET(frac=0.2, mask=True), name='skullstrip_first_pass') bet_dilate = pe.Node(fsl.DilateImage(operation='max', kernel_shape='sphere', kernel_size=6.0, internal_datatype='char'), name='skullstrip_first_dilate') bet_mask = pe.Node(fsl.ApplyMask(), name='skullstrip_first_mask') # Use AFNI's unifize for T2 constrast & fix header unifize = pe.Node( afni.Unifize( t2=True, outputtype='NIFTI_GZ', # Default -clfrac is 0.1, 0.4 was too conservative # -rbt because I'm a Jedi AFNI Master (see 3dUnifize's documentation) args='-clfrac 0.2 -rbt 18.3 65.0 90.0', out_file="uni.nii.gz"), name='unifize') fixhdr_unifize = pe.Node(CopyXForm(), name='fixhdr_unifize', mem_gb=0.1) # Run ANFI's 3dAutomask to extract a refined brain mask skullstrip_second_pass = pe.Node(afni.Automask(dilate=1, outputtype='NIFTI_GZ'), name='skullstrip_second_pass') fixhdr_skullstrip2 = pe.Node(CopyXForm(), name='fixhdr_skullstrip2', mem_gb=0.1) # Take intersection of both masks combine_masks = pe.Node(fsl.BinaryMaths(operation='mul'), name='combine_masks') # Compute masked brain apply_mask = pe.Node(fsl.ApplyMask(), name='apply_mask') if not pre_mask: bold_template = get_template('MNI152NLin2009cAsym', resolution=2, desc='fMRIPrep', suffix='boldref') brain_mask = get_template('MNI152NLin2009cAsym', resolution=2, desc='brain', suffix='mask') # Initialize transforms with antsAI init_aff = pe.Node(AI(fixed_image=str(bold_template), fixed_image_mask=str(brain_mask), metric=('Mattes', 32, 'Regular', 0.2), transform=('Affine', 0.1), search_factor=(20, 0.12), principal_axes=False, convergence=(10, 1e-6, 10), verbose=True), name='init_aff', n_procs=omp_nthreads) # Registration().version may be None if parseversion(Registration().version or '0.0.0') > Version('2.2.0'): init_aff.inputs.search_grid = (40, (0, 40, 40)) # Set up spatial normalization norm = pe.Node(Registration(from_file=pkgr_fn( 'fmriprep.data', 'epi_atlasbased_brainmask.json')), name='norm', n_procs=omp_nthreads) norm.inputs.fixed_image = str(bold_template) map_brainmask = pe.Node(ApplyTransforms(interpolation='MultiLabel', float=True, input_image=str(brain_mask)), name='map_brainmask') workflow.connect([ (inputnode, init_aff, [('in_file', 'moving_image')]), (inputnode, map_brainmask, [('in_file', 'reference_image')]), (inputnode, norm, [('in_file', 'moving_image')]), (init_aff, norm, [('output_transform', 'initial_moving_transform') ]), (norm, map_brainmask, [('reverse_invert_flags', 'invert_transform_flags'), ('reverse_transforms', 'transforms')]), (map_brainmask, pre_dilate, [('output_image', 'in_file')]), ]) else: workflow.connect([ (inputnode, pre_dilate, [('pre_mask', 'in_file')]), ]) workflow.connect([ (inputnode, check_hdr, [('in_file', 'reference')]), (pre_dilate, check_hdr, [('out_file', 'in_file')]), (check_hdr, n4_correct, [('out_file', 'mask_image')]), (inputnode, n4_correct, [('in_file', 'input_image')]), (inputnode, fixhdr_unifize, [('in_file', 'hdr_file')]), (inputnode, fixhdr_skullstrip2, [('in_file', 'hdr_file')]), (n4_correct, skullstrip_first_pass, [('output_image', 'in_file')]), (skullstrip_first_pass, bet_dilate, [('mask_file', 'in_file')]), (bet_dilate, bet_mask, [('out_file', 'mask_file')]), (skullstrip_first_pass, bet_mask, [('out_file', 'in_file')]), (bet_mask, unifize, [('out_file', 'in_file')]), (unifize, fixhdr_unifize, [('out_file', 'in_file')]), (fixhdr_unifize, skullstrip_second_pass, [('out_file', 'in_file')]), (skullstrip_first_pass, combine_masks, [('mask_file', 'in_file')]), (skullstrip_second_pass, fixhdr_skullstrip2, [('out_file', 'in_file') ]), (fixhdr_skullstrip2, combine_masks, [('out_file', 'operand_file')]), (fixhdr_unifize, apply_mask, [('out_file', 'in_file')]), (combine_masks, apply_mask, [('out_file', 'mask_file')]), (combine_masks, outputnode, [('out_file', 'mask_file')]), (apply_mask, outputnode, [('out_file', 'skull_stripped_file')]), (n4_correct, outputnode, [('output_image', 'bias_corrected_file')]), ]) return workflow