def get_norm_wf(name="norm_wf"): wf = Workflow(name=name) inputnode = pe.Node(niu.IdentityInterface(fields=['t1w', 't1w_brain']), name='inputnode') outputnode = pe.Node(niu.IdentityInterface( fields=['t1w_2_MNI_mat', 't1w_2_MNI_warp', 't1w_MNIspace']), name='outputnode') # otherwise fnirt is trying to write to the sourcedata dir t1w_dummy = pe.Node(fsl.ImageMaths(), name="t1w_dummy") wf.connect(inputnode, "t1w", t1w_dummy, "in_file") t1w_2_MNI_flirt = pe.Node(fsl.FLIRT(dof=12), name='t1w_2_MNI_flirt') t1w_2_MNI_flirt.inputs.reference = fsl.Info.standard_image( 'MNI152_T1_1mm_brain.nii.gz') wf.connect(inputnode, 't1w_brain', t1w_2_MNI_flirt, 'in_file') wf.connect(t1w_2_MNI_flirt, 'out_matrix_file', outputnode, 't1w_2_MNI_mat') # 2. CALC. WARP STRUCT -> MNI with FNIRT # cf. wrt. 2mm # https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind1311&L=FSL&P=R86108&1=FSL&9=A&J=on&d=No+Match%3BMatch%3BMatches&z=4 t1w_2_MNI_fnirt = pe.Node(fsl.FNIRT(), name='t1w_2_MNI_fnirt') t1w_2_MNI_fnirt.inputs.config_file = 'T1_2_MNI152_2mm' t1w_2_MNI_fnirt.inputs.ref_file = fsl.Info.standard_image( 'MNI152_T1_2mm.nii.gz') t1w_2_MNI_fnirt.inputs.field_file = True t1w_2_MNI_fnirt.plugin_args = {'submit_specs': 'request_memory = 4000'} wf.connect(t1w_dummy, 'out_file', t1w_2_MNI_fnirt, 'in_file') wf.connect(t1w_2_MNI_flirt, 'out_matrix_file', t1w_2_MNI_fnirt, 'affine_file') wf.connect(t1w_2_MNI_fnirt, 'field_file', outputnode, 't1w_2_MNI_warp') wf.connect(t1w_2_MNI_fnirt, 'warped_file', outputnode, 't1w_MNIspace') return wf
def register(ref_img, in_img, cmd=None): """Find the 4D affine transform that registers in_img to ref_img Args: ref_img -- (type: ndarray) reference image in_img -- (type: ndarray) input image to be registered cmd -- (default: None) override default flirt parameters an instance of nipype.interfaces.fsl.FLIRT Returns: warped input image """ assert in_img.ndim == ref_img.ndim, 'Input and reference images must have the same '\ 'number of dimensions' in_file = _ndarray_to_nifti(in_img) ref_file = _ndarray_to_nifti(ref_img) out_file = NamedTemporaryFile(suffix='.nii.gz') log_file = NamedTemporaryFile(suffix='.txt') cmd = cmd or fsl.FNIRT() cmd.inputs.in_file = in_file.name cmd.inputs.ref_file = ref_file.name cmd.inputs.output_type = 'NIFTI_GZ' cmd.inputs.log_file = log_file.name cmd.inputs.warped_file = out_file.name log.debug('cmdline: {}'.format(cmd.cmdline)) res = cmd.run() out_img = nib.load(out_file.name).get_data() return out_img
def FNIRT(self, in_file: str, ref: str, out_dir: str, type: int, aff: str): """ FNIRT non-linear transformation @param in_file: image to be transformed @param ref: image to transform into @param out_dir: directory for outputs @param type: 0 for highres2lowres, 1 for atlasHighres2highres, 2 for atlasLabels2highres @return: """ fnt = fsl.FNIRT() fnt.inputs.in_file = in_file fnt.inputs.ref_file = ref fnt.inputs.affine_file = aff if type == 0: fnt.inputs.warped_file = f"{out_dir}/Highres2Lowres.nii" print("Running non-linear transformation from Highres to Lowres:") elif type == 1: fnt.inputs.warped_file = f"{out_dir}/HighresAtlas2Highres.nii" print("Running non-linear transformation from Atlas to Highres:") elif type == 2: fnt.inputs.warped_file = f"{out_dir}/LabelsAtlas2Highres.nii" print("Running nonlinear transformation from Atlas to Highres:") fnt.inputs.output_type = "NIFTI" print(fnt.cmdline) fnt.run() return fnt.inputs.warped_file
def __init__(self, in_file='path', ref_file='path', **options): from nipype.interfaces import fsl fnt = fsl.FNIRT() fnt.inputs.in_file = in_file fnt.inputs.ref_file = ref_file for ef in options: setattr(fnt.inputs, ef, options[ef]) self.res = fnt.run()
def init_fsl(self): fnt = fsl.FNIRT() fnt.inputs.in_file = self.atlas fnt.inputs.affine_file = self.aff fnt.inputs.ref_file = self.highres fnt.inputs.warped_file = str(self.out_dir / "atlas2highres.nii") fnt.inputs.fieldcoeff_file = str(self.out_dir / "atlas2highres_fieldcoeff.nii") fnt.inputs.field_file = str(self.out_dir / "atlas2highres_field.nii") return fnt
def create_workflow(config: AttrDict, resource_pool: ResourcePool, context: Context): for _, rp in resource_pool[['brain', 'label-reorient_T1w']]: # TODO: disable skullstrip linear_reg = NipypeJob(interface=fsl.FLIRT(cost='corratio'), reference='linear_reg_0') inv_flirt_xfm = NipypeJob( interface=fsl.utils.ConvertXFM(invert_xfm=True), reference='inv_linear_reg0_xfm') linear_reg.in_file = rp[R('brain')] linear_reg.reference = config.template_brain linear_reg.interp = config.interpolation inv_flirt_xfm.in_file = linear_reg.out_matrix_file if config.linear_only: rp[R('brain', space='MNI')] = linear_reg.out_file # other xfm return else: nonlinear_reg = NipypeJob(interface=fsl.FNIRT(fieldcoeff_file=True, jacobian_file=True), reference='nonlinear_reg_1') brain_warp = NipypeJob(interface=fsl.ApplyWarp(), reference='brain_warp') nonlinear_reg.in_file = rp[R('T1w', label='reorient')] nonlinear_reg.ref_file = config.template_skull nonlinear_reg.refmask_file = config.ref_mask nonlinear_reg.config_file = config.fnirt_config nonlinear_reg.affine_file = linear_reg.out_matrix_file brain_warp.interp = config.interpolation brain_warp.in_file = rp[R('brain')] brain_warp.field_file = nonlinear_reg.fieldcoeff_file brain_warp.ref_file = config.template_brain rp[R('brain', space='MNI')] = brain_warp.out_file
def register_atlas(atlas_file, reference_file, output_dir, recalculate=True): """Registers the atlas to your reference image. This uses FNIRT to register the atlas to your reference image (for example the mean FA of the TBSS results). Args: atlas_file (str): the location of the atlas file we will register to the reference image. reference_file (str): the location of the reference image. output_dir (str): where to write the output recalculate (boolean): if we recalculate if the output already exists. Set this to False to easily get the results dictionary. Returns: dict: a dictionary with the filenames of the results. All files are in the output dir. Dir content: fieldcoeff_file: the path to the field coefficients file. To be used input to the 'warp' parameter of 'applywarp'. warped_image: the warped image. """ fieldcoeff_file = os.path.join(output_dir, 'fieldcoeff.nii.gz') warped_image = os.path.join(output_dir, 'warped.nii.gz') results_dict = { 'fieldcoeff_file': fieldcoeff_file, 'warped_image': warped_image } if not recalculate: if all(os.path.isfile(f) for f in [fieldcoeff_file, warped_image]): return results_dict fnirt = pe.Node(fsl.FNIRT(ref_file=reference_file, in_file=atlas_file, fieldcoeff_file=fieldcoeff_file, warped_file=warped_image), name='fnirt') fnirt.base_dir = os.path.join(output_dir, '_nipype_work_dir') fnirt.run() return results_dict
def create_register_func_to_epi(name='register_func_to_epi', reg_option='ANTS'): register_func_to_epi = pe.Workflow(name=name) inputspec = pe.Node( util.IdentityInterface(fields=['func_4d', 'func_3d', 'epi']), name='inputspec') outputspec = pe.Node(util.IdentityInterface(fields=[ 'ants_initial_xfm', 'ants_rigid_xfm', 'ants_affine_xfm', 'ants_nonlinear_xfm', 'fsl_flirt_xfm', 'fsl_fnirt_xfm', 'invlinear_xfm', 'func_in_epi' ]), name='outputspec') if reg_option == 'ANTS': # linear + non-linear registration func_to_epi_ants = create_wf_calculate_ants_warp( name='func_to_epi_ants') func_to_epi_ants.inputs.inputspec.interp = 'LanczosWindowedSinc' register_func_to_epi.connect([ (inputspec, func_to_epi_ants, [ ('func_3d', 'inputspec.anatomical_brain'), ('epi', 'inputspec.reference_brain'), ('func_3d', 'inputspec.anatomical_skull'), ('epi', 'inputspec.reference_skull'), ]), ]) func_to_epi_ants.inputs.inputspec.set( dimension=3, use_histogram_matching=True, winsorize_lower_quantile=0.01, winsorize_upper_quantile=0.99, metric=['MI', 'MI', 'CC'], metric_weight=[[1, 32], [1, 32], [1, 5]], radius_or_number_of_bins=[32, 32, 4], sampling_strategy=['Regular', 'Regular', None], sampling_percentage=[0.25, 0.25, None], number_of_iterations=[[1000, 500, 250, 100], [1000, 500, 250, 100], [100, 100, 70, 20]], convergence_threshold=[1e-8, 1e-8, 1e-9], convergence_window_size=[10, 10, 15], transforms=['Rigid', 'Affine', 'SyN'], transform_parameters=[[0.1], [0.1], [0.1, 3, 0]], shrink_factors=[[8, 4, 2, 1], [8, 4, 2, 1], [4, 2, 1]], smoothing_sigmas=[[3, 2, 1, 0], [3, 2, 1, 0], [0.6, 0.2, 0.0]]) register_func_to_epi.connect([ (func_to_epi_ants, outputspec, [ ('outputspec.ants_initial_xfm', 'ants_initial_xfm'), ('outputspec.ants_rigid_xfm', 'ants_rigid_xfm'), ('outputspec.ants_affine_xfm', 'ants_affine_xfm'), ('outputspec.warp_field', 'ants_nonlinear_xfm'), ]), ]) # combine transforms collect_transforms = pe.Node(util.Merge(4), name='collect_transforms_ants') register_func_to_epi.connect([ (func_to_epi_ants, collect_transforms, [ ('outputspec.ants_initial_xfm', 'in1'), ('outputspec.ants_rigid_xfm', 'in2'), ('outputspec.ants_affine_xfm', 'in3'), ('outputspec.warp_field', 'in4'), ]), ]) # apply transform func_in_epi = pe.Node(interface=ants.ApplyTransforms(), name='func_in_epi_ants') func_in_epi.inputs.input_image_type = 3 func_in_epi.inputs.interpolation = 'LanczosWindowedSinc' register_func_to_epi.connect(inputspec, 'func_4d', func_in_epi, 'input_image') register_func_to_epi.connect(inputspec, 'epi', func_in_epi, 'reference_image') register_func_to_epi.connect(collect_transforms, 'out', func_in_epi, 'transforms') register_func_to_epi.connect(func_in_epi, 'output_image', outputspec, 'func_in_epi') elif reg_option == 'FSL': # flirt linear registration func_to_epi_linear = pe.Node(interface=fsl.FLIRT(), name='func_to_epi_linear_fsl') func_to_epi_linear.inputs.dof = 6 register_func_to_epi.connect(inputspec, 'func_3d', func_to_epi_linear, 'in_file') register_func_to_epi.connect(inputspec, 'epi', func_to_epi_linear, 'reference') register_func_to_epi.connect(func_to_epi_linear, 'out_matrix_file', outputspec, 'fsl_flirt_xfm') inv_flirt_xfm = pe.Node(interface=fsl.utils.ConvertXFM(), name='inv_linear_reg0_xfm') inv_flirt_xfm.inputs.invert_xfm = True # fnirt non-linear registration func_to_epi_nonlinear = pe.Node(interface=fsl.FNIRT(), name='func_to_epi_nonlinear_fsl') func_to_epi_nonlinear.inputs.fieldcoeff_file = True register_func_to_epi.connect(inputspec, 'func_3d', func_to_epi_nonlinear, 'in_file') register_func_to_epi.connect(inputspec, 'epi', func_to_epi_nonlinear, 'ref_file') register_func_to_epi.connect(func_to_epi_linear, 'out_matrix_file', func_to_epi_nonlinear, 'affine_file') register_func_to_epi.connect(func_to_epi_nonlinear, 'fieldcoeff_file', outputspec, 'fsl_fnirt_xfm') register_func_to_epi.connect(func_to_epi_linear, 'out_matrix_file', inv_flirt_xfm, 'in_file') register_func_to_epi.connect(inv_flirt_xfm, 'out_file', outputspec, 'invlinear_xfm') # apply warp func_in_epi = pe.Node(interface=fsl.ApplyWarp(), name='func_in_epi_fsl') func_in_epi.inputs.interp = 'sinc' register_func_to_epi.connect(inputspec, 'func_4d', func_in_epi, 'in_file') register_func_to_epi.connect(inputspec, 'epi', func_in_epi, 'ref_file') # --premat input disabled because it was throwing off the transform # application quality --- why, though? #register_func_to_epi.connect(func_to_epi_linear, 'out_matrix_file', func_in_epi, 'premat') register_func_to_epi.connect(func_to_epi_nonlinear, 'fieldcoeff_file', func_in_epi, 'field_file') register_func_to_epi.connect(func_in_epi, 'out_file', outputspec, 'func_in_epi') return register_func_to_epi
def create_tbss_2_reg(name="tbss_2_reg"): """TBSS nonlinear registration: A pipeline that does the same as 'tbss_2_reg -t' script in FSL. '-n' option is not supported at the moment. Example ------- >>> from nipype.workflows.dmri.fsl import tbss >>> tbss2 = create_tbss_2_reg(name="tbss2") >>> tbss2.inputs.inputnode.target = fsl.Info.standard_image("FMRIB58_FA_1mm.nii.gz") # doctest: +SKIP >>> tbss2.inputs.inputnode.fa_list = ['s1_FA.nii', 's2_FA.nii', 's3_FA.nii'] >>> tbss2.inputs.inputnode.mask_list = ['s1_mask.nii', 's2_mask.nii', 's3_mask.nii'] Inputs:: inputnode.fa_list inputnode.mask_list inputnode.target Outputs:: outputnode.field_list """ # Define the inputnode inputnode = pe.Node(interface=util.IdentityInterface( fields=["fa_list", "mask_list", "target"]), name="inputnode") # Flirt the FA image to the target flirt = pe.MapNode(interface=fsl.FLIRT(dof=12), iterfield=['in_file', 'in_weight'], name="flirt") fnirt = pe.MapNode(interface=fsl.FNIRT(fieldcoeff_file=True), iterfield=['in_file', 'inmask_file', 'affine_file'], name="fnirt") # Fnirt the FA image to the target if fsl.no_fsl(): warn('NO FSL found') else: config_file = os.path.join(os.environ["FSLDIR"], "etc/flirtsch/FA_2_FMRIB58_1mm.cnf") fnirt.inputs.config_file = config_file # Define the registration workflow tbss2 = pe.Workflow(name=name) # Connect up the registration workflow tbss2.connect([ (inputnode, flirt, [("fa_list", "in_file"), ("target", "reference"), ("mask_list", "in_weight")]), (inputnode, fnirt, [("fa_list", "in_file"), ("mask_list", "inmask_file"), ("target", "ref_file")]), (flirt, fnirt, [("out_matrix_file", "affine_file")]), ]) # Define the outputnode outputnode = pe.Node( interface=util.IdentityInterface(fields=['field_list']), name="outputnode") tbss2.connect([(fnirt, outputnode, [('fieldcoeff_file', 'field_list')])]) return tbss2
def img2img_register( img_file, ref_file, wf_base_dir, wf_name, input_reorient2std=False, ref_reorient2std=False, method='linear', flirt_out_reg_file='linear_reg.mat', flirt_out_file='img2img_linear.nii.gz', fnirt_out_file='img2img_nonlinear.nii.gz', fnirt_fieldcoeff_file='img2img_nonlinear_fieldcoeff.nii.gz'): img_file = os.path.abspath(img_file) ref_file = os.path.abspath(ref_file) wf_base_dir = os.path.abspath(wf_base_dir) if not img_file.endswith(('.nii', '.nii.gz')): raise ("input file should be in nifti format (.nii or .nii.gz)!") if not ref_file.endswith(('.nii', '.nii.gz')): raise ( "destination file (ref_file) should be in nifti format (.nii or .nii.gz)!" ) ### reorient2std ### reorient img_file if input_reorient2std: reorient = fsl.Reorient2Std() reorient.inputs.in_file = img_file reorient.inputs.out_file = 'input_img_reorient2std.nii.gz' reorient_Node = pe.Node(reorient, 'input_file') wf = pe.Workflow(name='reorient2std', base_dir=wf_base_dir) wf.add_nodes([reorient_Node]) wf.run() img_file = os.path.join(wf_base_dir, 'reorient2std', 'input_file', 'input_img_reorient2std.nii.gz') ### reorient ref_file if config is not MNI if ref_reorient2std and config != 'MNI': reorient = fsl.Reorient2Std() reorient.inputs.in_file = ref_file reorient.inputs.out_file = 'ref_img_reorient2std.nii.gz' reorient_Node = pe.Node(reorient, 'ref_file') wf = pe.Workflow(name='reorient2std', base_dir=wf_base_dir) wf.add_nodes([reorient_Node]) wf.run() ref_file = os.path.join(wf_base_dir, 'reorient2std', 'ref_file', 'ref_img_reorient2std.nii.gz') if method == 'linear': flirt = pe.Node(interface=fsl.FLIRT(in_file=img_file, reference=ref_file, out_matrix_file=flirt_out_reg_file, out_file=flirt_out_file), name='linear') wf = pe.Workflow(name=wf_name, base_dir=wf_base_dir) wf.add_nodes([flirt]) wf.run() if method == 'nonlinear': flirt = pe.Node(interface=fsl.FLIRT(in_file=img_file, reference=ref_file, out_matrix_file=flirt_out_reg_file, out_file=flirt_out_file), name='linear') fnirt = pe.Node(interface=fsl.FNIRT( in_file=img_file, ref_file=ref_file, warped_file=fnirt_out_file, fieldcoeff_file=fnirt_fieldcoeff_file), name='nonlinear') wf = pe.Workflow(name=wf_name, base_dir=wf_base_dir) ## adding nodes to workflows wf.add_nodes([flirt, fnirt]) wf.connect([(flirt, fnirt, [('out_matrix_file', 'affine_file')])]) wf.run() linear_reg_file = os.path.join(wf_base_dir, wf_name, method, flirt_out_reg_file) nonlinear_warp_field_file = os.path.join(wf_base_dir, wf_name, method, fnirt_fieldcoeff_file) return { 'img_file': img_file, 'ref_file': ref_file, 'linear_reg_file': linear_reg_file, 'warp_field_file': nonlinear_warp_field_file }
# Segment with FSL FAST #tissue priors #tissue_path = '/usr/share/fsl/5.0/data/standard/tissuepriors/2mm/' #csf_prior = tissue_path + 'avg152T1_csf_bin.nii.gz' #white_prior = tissue_path + 'avg152T1_white_bin.nii.gz' #gray_prior = tissue_path + 'avg152T1_gray_bin.nii.gz' #segmentation = pe.Node(interface=fsl.FAST(number_classes=3, use_priors=True, img_type=1), name='segmentation') #workflow.connect(skullstrip, 'out_file', segmentation, 'in_files') # Register to standard MNI template #1. linear linear_reg = pe.Node(interface=fsl.FLIRT(cost='corratio', reference=ref_brain), name='linear_reg') #2.nonlinear nonlinear_reg = pe.Node(interface=fsl.FNIRT(fieldcoeff_file=True, jacobian_file=True, ref_file=ref_brain, refmask_file=ref_mask), name='nonlinear_reg') inv_flirt_xfm = pe.Node(interface=fsl.utils.ConvertXFM(invert_xfm=True), name='inv_linear_xfm') workflow.connect(reorient, 'out_file', linear_reg, 'in_file') workflow.connect(linear_reg, 'out_matrix_file', nonlinear_reg, 'affine_file') workflow.connect(reorient, 'out_file', nonlinear_reg, 'in_file') workflow.connect(linear_reg, 'out_matrix_file', inv_flirt_xfm, 'in_file') # Run workflow workflow.write_graph() workflow.run() print "ANATOMICAL PREPROCESSING DONE! Results in ", results_path+subj
def create_register_func_to_epi(name='register_func_to_epi', reg_option='ANTS', reg_ants_skull=1): register_func_to_epi = pe.Workflow(name=name) inputspec = pe.Node(util.IdentityInterface(fields=['func_4d', 'func_3d', 'func_3d_mask', 'epi', 'interp', 'ants_para']), name='inputspec') outputspec = pe.Node(util.IdentityInterface(fields=['ants_initial_xfm', 'ants_rigid_xfm', 'ants_affine_xfm', 'warp_field', 'inverse_warp_field', 'fsl_flirt_xfm', 'fsl_fnirt_xfm', 'invlinear_xfm', 'func_in_epi']), # 'func_mask_in_epi']), name='outputspec') if reg_option == 'ANTS': # linear + non-linear registration func_to_epi_ants = \ create_wf_calculate_ants_warp( name='func_to_epi_ants', num_threads=1, reg_ants_skull=1) register_func_to_epi.connect([ (inputspec, func_to_epi_ants, [ ('func_3d', 'inputspec.moving_brain'), ('epi', 'inputspec.reference_brain'), ('func_3d', 'inputspec.moving_skull'), ('epi', 'inputspec.reference_skull'), ('interp', 'inputspec.interp'), ('ants_para', 'inputspec.ants_para') ]), ]) register_func_to_epi.connect([ (func_to_epi_ants, outputspec, [ ('outputspec.ants_initial_xfm', 'ants_initial_xfm'), ('outputspec.ants_rigid_xfm', 'ants_rigid_xfm'), ('outputspec.ants_affine_xfm', 'ants_affine_xfm'), ('outputspec.warp_field', 'warp_field'), ('outputspec.inverse_warp_field', 'inverse_warp_field'), ]), ]) # combine transforms collect_transforms = pe.Node(util.Merge(4), name='collect_transforms_ants') register_func_to_epi.connect([ (func_to_epi_ants, collect_transforms, [ ('outputspec.ants_initial_xfm', 'in1'), ('outputspec.ants_rigid_xfm', 'in2'), ('outputspec.ants_affine_xfm', 'in3'), ('outputspec.warp_field', 'in4'), ]), ]) # check transform list to exclude Nonetype (missing) init/rig/affine check_transform = pe.Node(util.Function(input_names=['transform_list'], output_names=['checked_transform_list', 'list_length'], function=check_transforms), name='{0}_check_transforms'.format(name)) register_func_to_epi.connect(collect_transforms, 'out', check_transform, 'transform_list') # apply transform to func func_in_epi = pe.Node(interface=ants.ApplyTransforms(), name='func_in_epi_ants') func_in_epi.inputs.dimension = 3 func_in_epi.inputs.input_image_type = 3 register_func_to_epi.connect(inputspec, 'func_4d', func_in_epi, 'input_image') register_func_to_epi.connect(inputspec, 'epi', func_in_epi, 'reference_image') register_func_to_epi.connect(check_transform, 'checked_transform_list', func_in_epi, 'transforms') register_func_to_epi.connect(func_in_epi, 'output_image', outputspec, 'func_in_epi') # # apply transform to functional mask # func_mask_in_epi = pe.Node(interface=ants.ApplyTransforms(), name='func_mask_in_epi_ants') # func_mask_in_epi.inputs.dimension = 3 # func_mask_in_epi.inputs.input_image_type = 0 # register_func_to_epi.connect(inputspec, 'func_3d_mask', func_mask_in_epi, 'input_image') # register_func_to_epi.connect(inputspec, 'epi', func_mask_in_epi, 'reference_image') # register_func_to_epi.connect(check_transform, 'checked_transform_list', func_mask_in_epi, 'transforms') # register_func_to_epi.connect(func_mask_in_epi, 'output_image', outputspec, 'func_mask_in_epi') elif reg_option == 'FSL': # flirt linear registration func_to_epi_linear = pe.Node(interface=fsl.FLIRT(), name='func_to_epi_linear_fsl') func_to_epi_linear.inputs.dof = 6 register_func_to_epi.connect(inputspec, 'func_3d', func_to_epi_linear, 'in_file') register_func_to_epi.connect(inputspec, 'epi', func_to_epi_linear, 'reference') register_func_to_epi.connect(func_to_epi_linear, 'out_matrix_file', outputspec, 'fsl_flirt_xfm') inv_flirt_xfm = pe.Node(interface=fsl.utils.ConvertXFM(), name='inv_linear_reg0_xfm') inv_flirt_xfm.inputs.invert_xfm = True # fnirt non-linear registration func_to_epi_nonlinear = pe.Node(interface=fsl.FNIRT(), name='func_to_epi_nonlinear_fsl') func_to_epi_nonlinear.inputs.fieldcoeff_file = True register_func_to_epi.connect(inputspec, 'func_3d', func_to_epi_nonlinear, 'in_file') register_func_to_epi.connect(inputspec, 'epi', func_to_epi_nonlinear, 'ref_file') register_func_to_epi.connect(func_to_epi_linear, 'out_matrix_file', func_to_epi_nonlinear, 'affine_file') register_func_to_epi.connect(func_to_epi_nonlinear, 'fieldcoeff_file', outputspec, 'fsl_fnirt_xfm') register_func_to_epi.connect(func_to_epi_linear, 'out_matrix_file', inv_flirt_xfm, 'in_file') register_func_to_epi.connect(inv_flirt_xfm, 'out_file', outputspec, 'invlinear_xfm') # apply warp func_in_epi = pe.Node(interface=fsl.ApplyWarp(), name='func_in_epi_fsl') func_in_epi.inputs.interp = 'sinc' register_func_to_epi.connect(inputspec, 'func_4d', func_in_epi, 'in_file') register_func_to_epi.connect(inputspec, 'epi', func_in_epi, 'ref_file') # --premat input disabled because it was throwing off the transform # application quality --- why, though? #register_func_to_epi.connect(func_to_epi_linear, 'out_matrix_file', func_in_epi, 'premat') register_func_to_epi.connect(func_to_epi_nonlinear, 'fieldcoeff_file', func_in_epi, 'field_file') register_func_to_epi.connect(func_in_epi, 'out_file', outputspec, 'func_in_epi') return register_func_to_epi
def create_reg_workflow(name='registration'): """Create a FEAT preprocessing workflow together with freesurfer Parameters ---------- :: name : name of workflow (default: 'registration') Inputs:: inputspec.source_files : files (filename or list of filenames to register) inputspec.mean_image : reference image to use inputspec.anatomical_image : anatomical image to coregister to inputspec.target_image : registration target Outputs:: outputspec.func2anat_transform : FLIRT transform outputspec.anat2target_transform : FLIRT+FNIRT transform outputspec.transformed_files : transformed files in target space outputspec.transformed_mean : mean image in target space Example ------- """ register = pe.Workflow(name=name) inputnode = pe.Node(interface=util.IdentityInterface(fields=['source_files', 'mean_image', 'anatomical_image', 'target_image']), name='inputspec') outputnode = pe.Node(interface=util.IdentityInterface(fields=['func2anat_transform', 'anat2target_transform', 'transformed_files', 'transformed_mean', ]), name='outputspec') """ Estimate the tissue classes from the anatomical image. But use spm's segment as FSL appears to be breaking. """ #fast = pe.Node(fsl.FAST(), name='fast') #fast.config = {'execution': {'keep_unncessary_outputs': True}} #register.connect(inputnode, 'anatomical_image', fast, 'in_files') convert = pe.Node(fs.MRIConvert(out_type='nii'), name='convert') register.connect(inputnode, 'anatomical_image', convert, 'in_file') segment = pe.Node(spm.Segment(), name='segment') segment.inputs.wm_output_type = [False, False, True] segment.config = {'execution': {'keep_unnecessary_outputs': 'true'}} register.connect(convert, 'out_file', segment, 'data') """ Binarize the segmentation """ binarize = pe.Node(fsl.ImageMaths(op_string='-nan -thr 0.5 -bin'), name='binarize') #pickindex = lambda x, i: x[i] #register.connect(fast, ('partial_volume_files', pickindex, 1), # binarize, 'in_file') register.connect(segment, 'native_wm_image', binarize, 'in_file') """ Calculate rigid transform from mean image to anatomical image """ mean2anat = pe.Node(fsl.FLIRT(), name='mean2anat') mean2anat.inputs.dof = 6 register.connect(inputnode, 'mean_image', mean2anat, 'in_file') register.connect(inputnode, 'anatomical_image', mean2anat, 'reference') """ Now use bbr cost function to improve the transform """ mean2anatbbr = pe.Node(fsl.FLIRT(), name='mean2anatbbr') mean2anatbbr.inputs.dof = 6 mean2anatbbr.inputs.cost = 'bbr' os.environ['FSLDIR'] mean2anatbbr.inputs.schedule = os.path.join(os.environ['FSLDIR'],'etc/flirtsch/bbr.sch') register.connect(inputnode, 'mean_image', mean2anatbbr, 'in_file') register.connect(binarize, 'out_file', mean2anatbbr, 'wm_seg') register.connect(inputnode, 'anatomical_image', mean2anatbbr, 'reference') register.connect(mean2anat, 'out_matrix_file', mean2anatbbr, 'in_matrix_file') """ Calculate affine transform from anatomical to target """ anat2target_affine = pe.Node(fsl.FLIRT(), name='anat2target_linear') register.connect(inputnode, 'anatomical_image', anat2target_affine, 'in_file') register.connect(inputnode, 'target_image', anat2target_affine, 'reference') """ Calculate nonlinear transform from anatomical to target """ anat2target_nonlinear = pe.Node(fsl.FNIRT(), name='anat2target_nonlinear') register.connect(anat2target_affine, 'out_matrix_file', anat2target_nonlinear, 'affine_file') #anat2target_nonlinear.inputs.in_fwhm = [8, 4, 2, 2] #anat2target_nonlinear.inputs.subsampling_scheme = [4, 2, 1, 1] anat2target_nonlinear.inputs.warp_resolution = (8, 8, 8) register.connect(inputnode, 'anatomical_image', anat2target_nonlinear, 'in_file') register.connect(inputnode, 'target_image', anat2target_nonlinear, 'ref_file') """ Transform the mean image. First to anatomical and then to target """ warp2anat = pe.Node(fsl.ApplyWarp(interp='spline'), name='warp2anat') register.connect(inputnode, 'mean_image', warp2anat, 'in_file') register.connect(inputnode, 'anatomical_image', warp2anat, 'ref_file') register.connect(mean2anatbbr, 'out_matrix_file', warp2anat, 'premat') warpmean = pe.Node(fsl.ApplyWarp(interp='spline'), name='warpmean') register.connect(warp2anat, 'out_file', warpmean, 'in_file') register.connect(inputnode, 'target_image', warpmean, 'ref_file') register.connect(anat2target_affine, 'out_matrix_file', warpmean, 'premat') register.connect(anat2target_nonlinear, 'field_file', warpmean, 'field_file') """ Transform the remaining images. First to anatomical and then to target """ warpall2anat = pe.MapNode(fsl.ApplyWarp(interp='spline'), iterfield=['in_file'], name='warpall2anat') register.connect(inputnode, 'source_files', warpall2anat, 'in_file') register.connect(inputnode, 'anatomical_image', warpall2anat, 'ref_file') register.connect(mean2anatbbr, 'out_matrix_file', warpall2anat, 'premat') warpall = pe.MapNode(fsl.ApplyWarp(interp='spline'), name='warpall', iterfield=['in_file']) register.connect(warpall2anat, 'out_file', warpall, 'in_file') register.connect(inputnode, 'target_image', warpall, 'ref_file') register.connect(anat2target_affine, 'out_matrix_file', warpall, 'premat') register.connect(anat2target_nonlinear, 'field_file', warpall, 'field_file') """ Assign all the output files """ register.connect(warpmean, 'out_file', outputnode, 'transformed_mean') register.connect(warpall, 'out_file', outputnode, 'transformed_files') register.connect(mean2anatbbr, 'out_matrix_file', outputnode, 'func2anat_transform') register.connect(anat2target_nonlinear, 'field_file', outputnode, 'anat2target_transform') return register
def create_reg_workflow(name='registration'): """Create a FEAT preprocessing workflow together with freesurfer Parameters ---------- :: name : name of workflow (default: 'registration') Inputs:: inputspec.source_files : files (filename or list of filenames to register) inputspec.mean_image : reference image to use inputspec.anatomical_image : anatomical image to coregister to inputspec.target_image : registration target Outputs:: outputspec.func2anat_transform : FLIRT transform outputspec.anat2target_transform : FLIRT+FNIRT transform outputspec.transformed_files : transformed files in target space outputspec.transformed_mean : mean image in target space Example ------- """ register = pe.Workflow(name=name) inputnode = pe.Node(interface=util.IdentityInterface(fields=['source_files', 'mean_image', 'anatomical_image', 'target_image']), name='inputspec') outputnode = pe.Node(interface=util.IdentityInterface(fields=['func2anat_transform', 'anat2target_transform', 'transformed_files', 'transformed_mean', ]), name='outputspec') """ Estimate the tissue classes from the anatomical image. But use spm's segment as FSL appears to be breaking. """ stripper = pe.Node(fsl.BET(), name='stripper') register.connect(inputnode, 'anatomical_image', stripper, 'in_file') fast = pe.Node(fsl.FAST(), name='fast') register.connect(stripper, 'out_file', fast, 'in_files') """ Binarize the segmentation """ binarize = pe.Node(fsl.ImageMaths(op_string='-nan -thr 0.5 -bin'), name='binarize') pickindex = lambda x, i: x[i] register.connect(fast, ('partial_volume_files', pickindex, 2), binarize, 'in_file') """ Calculate rigid transform from mean image to anatomical image """ mean2anat = pe.Node(fsl.FLIRT(), name='mean2anat') mean2anat.inputs.dof = 6 register.connect(inputnode, 'mean_image', mean2anat, 'in_file') register.connect(stripper, 'out_file', mean2anat, 'reference') """ Now use bbr cost function to improve the transform """ mean2anatbbr = pe.Node(fsl.FLIRT(), name='mean2anatbbr') mean2anatbbr.inputs.dof = 6 mean2anatbbr.inputs.cost = 'bbr' mean2anatbbr.inputs.schedule = os.path.join(os.getenv('FSLDIR'), 'etc/flirtsch/bbr.sch') register.connect(inputnode, 'mean_image', mean2anatbbr, 'in_file') register.connect(binarize, 'out_file', mean2anatbbr, 'wm_seg') register.connect(inputnode, 'anatomical_image', mean2anatbbr, 'reference') register.connect(mean2anat, 'out_matrix_file', mean2anatbbr, 'in_matrix_file') """ Calculate affine transform from anatomical to target """ anat2target_affine = pe.Node(fsl.FLIRT(), name='anat2target_linear') register.connect(inputnode, 'anatomical_image', anat2target_affine, 'in_file') register.connect(inputnode, 'target_image', anat2target_affine, 'reference') """ Calculate nonlinear transform from anatomical to target """ anat2target_nonlinear = pe.Node(fsl.FNIRT(), name='anat2target_nonlinear') anat2target_nonlinear.inputs.fieldcoeff_file=True register.connect(anat2target_affine, 'out_matrix_file', anat2target_nonlinear, 'affine_file') anat2target_nonlinear.inputs.warp_resolution = (8, 8, 8) register.connect(inputnode, 'anatomical_image', anat2target_nonlinear, 'in_file') register.connect(inputnode, 'target_image', anat2target_nonlinear, 'ref_file') """ Transform the mean image. First to anatomical and then to target """ warp2anat = pe.Node(fsl.ApplyWarp(interp='spline'), name='warp2anat') register.connect(inputnode, 'mean_image', warp2anat, 'in_file') register.connect(inputnode, 'anatomical_image', warp2anat, 'ref_file') register.connect(mean2anatbbr, 'out_matrix_file', warp2anat, 'premat') warpmean = warp2anat.clone(name='warpmean') register.connect(warp2anat, 'out_file', warpmean, 'in_file') register.connect(inputnode, 'target_image', warpmean, 'ref_file') register.connect(anat2target_nonlinear, 'fieldcoeff_file', warpmean, 'field_file') """ Transform the remaining images. First to anatomical and then to target """ warpall2anat = pe.MapNode(fsl.ApplyWarp(interp='spline'), iterfield=['in_file'], name='warpall2anat') register.connect(inputnode, 'source_files', warpall2anat, 'in_file') register.connect(inputnode, 'anatomical_image', warpall2anat, 'ref_file') register.connect(mean2anatbbr, 'out_matrix_file', warpall2anat, 'premat') warpall = warpall2anat.clone(name='warpall') register.connect(warpall2anat, 'out_file', warpall, 'in_file') register.connect(inputnode, 'target_image', warpall, 'ref_file') register.connect(anat2target_nonlinear, 'fieldcoeff_file', warpall, 'field_file') """ Assign all the output files """ register.connect(warpmean, 'out_file', outputnode, 'transformed_mean') register.connect(warpall, 'out_file', outputnode, 'transformed_files') register.connect(mean2anatbbr, 'out_matrix_file', outputnode, 'func2anat_transform') register.connect(anat2target_nonlinear, 'fieldcoeff_file', outputnode, 'anat2target_transform') return register
def create_nonlinear_register(name='nonlinear_register'): """ Performs non-linear registration of an input file to a reference file. Parameters ---------- name : string, optional Name of the workflow. Returns ------- nonlinear_register : nipype.pipeline.engine.Workflow Notes ----- Workflow Inputs:: inputspec.input_brain : string (nifti file) File of brain to be normalized (registered) inputspec.input_skull : string (nifti file) File of input brain with skull inputspec.reference_brain : string (nifti file) Target brain file to normalize to inputspec.reference_skull : string (nifti file) Target brain with skull to normalize to inputspec.fnirt_config : string (fsl fnirt config file) Configuration file containing parameters that can be specified in fnirt Workflow Outputs:: outputspec.output_brain : string (nifti file) Normalizion of input brain file outputspec.linear_xfm : string (.mat file) Affine matrix of linear transformation of brain file outputspec.invlinear_xfm : string Inverse of affine matrix of linear transformation of brain file outputspec.nonlinear_xfm : string Nonlinear field coefficients file of nonlinear transformation Registration Procedure: 1. Perform a linear registration to get affine transformation matrix. 2. Perform a nonlinear registration on an input file to the reference file utilizing affine transformation from the previous step as a starting point. 3. Invert the affine transformation to provide the user a transformation (affine only) from the space of the reference file to the input file. Workflow Graph: .. image:: ../images/nonlinear_register.dot.png :width: 500 Detailed Workflow Graph: .. image:: ../images/nonlinear_register_detailed.dot.png :width: 500 """ nonlinear_register = pe.Workflow(name=name) inputspec = pe.Node(util.IdentityInterface(fields=[ 'input_brain', 'input_skull', 'reference_brain', 'reference_skull', 'fnirt_config' ]), name='inputspec') outputspec = pe.Node(util.IdentityInterface(fields=[ 'output_brain', 'linear_xfm', 'invlinear_xfm', 'nonlinear_xfm' ]), name='outputspec') linear_reg = pe.Node(interface=fsl.FLIRT(), name='linear_reg_0') linear_reg.inputs.cost = 'corratio' nonlinear_reg = pe.Node(interface=fsl.FNIRT(), name='nonlinear_reg_1') nonlinear_reg.inputs.fieldcoeff_file = True nonlinear_reg.inputs.jacobian_file = True brain_warp = pe.Node(interface=fsl.ApplyWarp(), name='brain_warp') inv_flirt_xfm = pe.Node(interface=fsl.utils.ConvertXFM(), name='inv_linear_reg0_xfm') inv_flirt_xfm.inputs.invert_xfm = True nonlinear_register.connect(inputspec, 'input_brain', linear_reg, 'in_file') nonlinear_register.connect(inputspec, 'reference_brain', linear_reg, 'reference') nonlinear_register.connect(inputspec, 'input_skull', nonlinear_reg, 'in_file') nonlinear_register.connect(inputspec, 'reference_skull', nonlinear_reg, 'ref_file') # FNIRT parameters are specified by FSL config file # ${FSLDIR}/etc/flirtsch/TI_2_MNI152_2mm.cnf (or user-specified) nonlinear_register.connect(inputspec, 'fnirt_config', nonlinear_reg, 'config_file') nonlinear_register.connect(linear_reg, 'out_matrix_file', nonlinear_reg, 'affine_file') nonlinear_register.connect(nonlinear_reg, 'fieldcoeff_file', outputspec, 'nonlinear_xfm') nonlinear_register.connect(inputspec, 'input_brain', brain_warp, 'in_file') nonlinear_register.connect(nonlinear_reg, 'fieldcoeff_file', brain_warp, 'field_file') nonlinear_register.connect(inputspec, 'reference_brain', brain_warp, 'ref_file') nonlinear_register.connect(brain_warp, 'out_file', outputspec, 'output_brain') nonlinear_register.connect(linear_reg, 'out_matrix_file', inv_flirt_xfm, 'in_file') nonlinear_register.connect(inv_flirt_xfm, 'out_file', outputspec, 'invlinear_xfm') nonlinear_register.connect(linear_reg, 'out_matrix_file', outputspec, 'linear_xfm') return nonlinear_register
def create_tbss_2_reg(name="tbss_2_reg"): """TBSS nonlinear registration: A pipeline that does the same as tbss_2_reg script in FSL. Example ------ >>> tbss2 = create_tbss_2_reg(name="tbss2") >>> tbss2.inputs.inputnode.target = fsl.Info.standard_image("FMRIB58_FA_1mm.nii.gz") >>> ... Inputs:: inputnode.fa_list inputnode.mask_list inputnode.target Outputs:: outputnode.field_list """ # Define the inputnode inputnode = pe.Node(interface = util.IdentityInterface(fields=["fa_list", "mask_list", "target"]), name="inputnode") # Flirt the FA image to the target flirt = pe.MapNode(interface=fsl.FLIRT(dof=12), iterfield=['in_file','in_weight'], name="flirt") # Fnirt the FA image to the target config_file = os.path.join(os.environ["FSLDIR"], "etc/flirtsch/FA_2_FMRIB58_1mm.cnf") fnirt = pe.MapNode(interface=fsl.FNIRT(config_file=config_file, fieldcoeff_file=True), iterfield=['in_file', 'inmask_file', 'affine_file'], name="fnirt") # Define the registration workflow tbss2 = pe.Workflow(name=name) # Connect up the registration workflow tbss2.connect([ (inputnode,flirt,[("fa_list", "in_file"), ("target","reference"), ("mask_list","in_weight")]), (inputnode,fnirt,[("fa_list", "in_file"), ("mask_list","inmask_file"), ("target","ref_file")]), (flirt,fnirt,[("out_matrix_file", "affine_file")]), ]) # Define the outputnode outputnode = pe.Node(interface = util.IdentityInterface(fields=['field_list']), name="outputnode") tbss2.connect([ (fnirt,outputnode, [('fieldcoeff_file','field_list')]) ]) return tbss2
def modulation_( self ): """Modulation funcion is a correction of the volume change multiplying the voxel by the Jacobian determinant derived from the normalization process.""" try: # # Use the non-linear template built in the non-linear_registration_ funstion temp_T1_brain_nlin = os.path.join(self.ana_dir_, "temp_T1_brain_nlin.nii.gz") # # Loop on the tasks while True: # get the item item = self.queue_[2].get() # registration estimation flt = fsl.FLIRT() flt.inputs.in_file = os.path.join(self.T1_brain_dir_, item ) flt.inputs.reference = temp_T1_brain_nlin flt.inputs.out_file = os.path.join( self.template_dir_, "%s_li_template.nii.gz"%item[:-7] ) flt.inputs.out_matrix_file = os.path.join( self.template_dir_, "%s_li_template.mat"%item[:-7] ) flt.inputs.dof = 12 res = flt.run() # # Find the matching T1 image PIDN = [int(s) for s in item.split("_") if s.isdigit()] # T1_item = [ s for s in self.list_T1_ if str(PIDN[0]) in s] # # apply registration using T1_2_MNI152_2mm configuration file T1_2_MNI152_2mm = "" if os.environ.get('FSLDIR'): T1_2_MNI152_2mm = os.path.join( os.environ.get('FSLDIR'), "etc","flirtsch","T1_2_MNI152_2mm.cnf" ) # fnt = fsl.FNIRT() fnt.inputs.in_file = os.path.join(self.T1_dir_, T1_item[0]) fnt.inputs.ref_file = self.template_ fnt.inputs.warped_file = os.path.join( self.template_dir_, "%s_non_li_template_fnirt.nii.gz"%item[:-7] ) fnt.inputs.affine_file = os.path.join( self.template_dir_, "%s_li_template.mat"%item[:-7] ) fnt.inputs.config_file = T1_2_MNI152_2mm fnt.inputs.fieldcoeff_file = os.path.join( self.template_dir_, "%s_non_li_template_coeff.nii.gz"%item[:-7] ) fnt.inputs.jacobian_file = os.path.join( self.template_dir_, "%s_non_li_template_jac.nii.gz"%item[:-7] ) res = fnt.run() # apply warp aw = fsl.ApplyWarp() aw.inputs.in_file = os.path.join(self.T1_dir_, T1_item[0]) aw.inputs.ref_file = self.template_ aw.inputs.out_file = os.path.join( self.template_dir_, "%s_non_li_template_warped.nii.gz"%item[:-7] ) aw.inputs.field_file = os.path.join( self.template_dir_, "%s_non_li_template_coeff.nii.gz"%item[:-7] ) res = aw.run() # modulation maths = fsl.ImageMaths() maths.inputs.in_file = os.path.join(self.template_dir_, "%s_non_li_template_warped.nii.gz"%item[:-7]) maths.inputs.op_string = '-mul %s'%(os.path.join(self.template_dir_, "%s_non_li_template_jac.nii.gz"%item[:-7])) maths.inputs.out_file = os.path.join( self.template_dir_, "%s_modulated.nii.gz"%item[:-7] ) maths.inputs.out_data_type = "float" maths.run(); # lock and add the file singlelock.acquire() self.warped_template_.append( aw.inputs.out_file ) self.modulated_template_.append( os.path.join(self.template_dir_, "%s_modulated.nii.gz"%item[:-7]) ) singlelock.release() # job is done self.queue_[2].task_done() # # except Exception as inst: print inst _log.error(inst) quit(-1) except IOError as e: print "I/O error({0}): {1}".format(e.errno, e.strerror) quit(-1) except: print "Unexpected error:", sys.exc_info()[0] quit(-1)
def create_vmhc(use_ants): """ Compute the map of brain functional homotopy, the high degree of synchrony in spontaneous activity between geometrically corresponding interhemispheric (i.e., homotopic) regions. Parameters ---------- None Returns ------- vmhc_workflow : workflow Voxel Mirrored Homotopic Connectivity Analysis Workflow Notes ----- `Source <https://github.com/FCP-INDI/C-PAC/blob/master/CPAC/vmhc/vmhc.py>`_ Workflow Inputs:: inputspec.brain : string (existing nifti file) Anatomical image(without skull) inputspec.symmetric_brain : string (existing nifti file) MNI152_T1_2mm_brain_symmetric.nii.gz inputspec.rest_res_filt : string (existing nifti file) Band passed Image with nuisance signal regressed out(and optionally scrubbed). Recommended bandpass filter (0.001,0.1) ) inputspec.reorient : string (existing nifti file) RPI oriented anatomical data inputspec.example_func2highres_mat : string (existing affine transformation .mat file) Specifies an affine transform that should be applied to the example_func before non linear warping inputspec.standard_for_func : string (existing nifti file) MNI152_T1_standard_resolution_brain.nii.gz inputspec.symmetric_skull : string (existing nifti file) MNI152_T1_2mm_symmetric.nii.gz inputspec.twomm_brain_mask_dil : string (existing nifti file) MNI152_T1_2mm_brain_mask_symmetric_dil.nii.gz inputspec.config_file_twomm_symmetric : string (existing .cnf file) T1_2_MNI152_2mm_symmetric.cnf inputspec.rest_mask : string (existing nifti file) A mask functional volume(derived by dilation from motion corrected functional volume) fwhm_input.fwhm : list (float) For spatial smoothing the Z-transformed correlations in MNI space. Generally the value of this parameter is 1.5 or 2 times the voxel size of the input Image. inputspec.mean_functional : string (existing nifti file) The mean functional image for use in the func-to-anat registration matrix conversion to ITK (ANTS) format, if the user selects to use ANTS. Workflow Outputs:: outputspec.highres2symmstandard : string (nifti file) Linear registration of T1 image to symmetric standard image outputspec.highres2symmstandard_mat : string (affine transformation .mat file) An affine transformation .mat file from linear registration and used in non linear registration outputspec.highres2symmstandard_warp : string (nifti file) warp file from Non Linear registration of T1 to symmetrical standard brain outputspec.fnirt_highres2symmstandard : string (nifti file) Non Linear registration of T1 to symmetrical standard brain outputspec.highres2symmstandard_jac : string (nifti file) jacobian determinant image from Non Linear registration of T1 to symmetrical standard brain outputspec.rest_res_2symmstandard : string (nifti file) nonlinear registration (func to standard) image outputspec.VMHC_FWHM_img : string (nifti file) pearson correlation between res2standard and flipped res2standard outputspec.VMHC_Z_FWHM_img : string (nifti file) Fisher Z transform map outputspec.VMHC_Z_stat_FWHM_img : string (nifti file) Z statistic map Order of commands: - Perform linear registration of Anatomical brain in T1 space to symmetric standard space. For details see `flirt <http://www.fmrib.ox.ac.uk/fsl/flirt/index.html>`_:: flirt -ref MNI152_T1_2mm_brain_symmetric.nii.gz -in mprage_brain.nii.gz -out highres2symmstandard.nii.gz -omat highres2symmstandard.mat -cost corratio -searchcost corratio -dof 12 -interp trilinear - Perform nonlinear registration (higres to standard) to symmetric standard brain. For details see `fnirt <http://fsl.fmrib.ox.ac.uk/fsl/fnirt/>`_:: fnirt --in=head.nii.gz --aff=highres2symmstandard.mat --cout=highres2symmstandard_warp.nii.gz --iout=fnirt_highres2symmstandard.nii.gz --jout=highres2symmstandard_jac.nii.gz --config=T1_2_MNI152_2mm_symmetric.cnf --ref=MNI152_T1_2mm_symmetric.nii.gz --refmask=MNI152_T1_2mm_brain_mask_symmetric_dil.nii.gz --warpres=10,10,10 - Perform spatial smoothing on the input functional image(inputspec.rest_res_filt). For details see `PrinciplesSmoothing <http://imaging.mrc-cbu.cam.ac.uk/imaging/PrinciplesSmoothing>`_ `fslmaths <http://www.fmrib.ox.ac.uk/fslcourse/lectures/practicals/intro/index.htm>`_:: fslmaths rest_res_filt.nii.gz -kernel gauss FWHM/ sqrt(8-ln(2)) -fmean -mas rest_mask.nii.gz rest_res_filt_FWHM.nii.gz - Apply nonlinear registration (func to standard). For details see `applywarp <http://www.fmrib.ox.ac.uk/fsl/fnirt/warp_utils.html#applywarp>`_:: applywarp --ref=MNI152_T1_2mm_symmetric.nii.gz --in=rest_res_filt_FWHM.nii.gz --out=rest_res_2symmstandard.nii.gz --warp=highres2symmstandard_warp.nii.gz --premat=example_func2highres.mat - Copy and L/R swap the output of applywarp command (rest_res_2symmstandard.nii.gz). For details see `fslswapdim <http://fsl.fmrib.ox.ac.uk/fsl/fsl4.0/avwutils/index.html>`_:: fslswapdim rest_res_2symmstandard.nii.gz -x y z tmp_LRflipped.nii.gz - Calculate pearson correlation between rest_res_2symmstandard.nii.gz and flipped rest_res_2symmstandard.nii.gz(tmp_LRflipped.nii.gz). For details see `3dTcorrelate <http://afni.nimh.nih.gov/pub/dist/doc/program_help/3dTcorrelate.html>`_:: 3dTcorrelate -pearson -polort -1 -prefix VMHC_FWHM.nii.gz rest_res_2symmstandard.nii.gz tmp_LRflipped.nii.gz - Fisher Z Transform the correlation. For details see `3dcalc <http://afni.nimh.nih.gov/pub/dist/doc/program_help/3dcalc.html>`_:: 3dcalc -a VMHC_FWHM.nii.gz -expr 'log((a+1)/(1-a))/2' -prefix VMHC_FWHM_Z.nii.gz - Calculate the number of volumes(nvols) in flipped rest_res_2symmstandard.nii.gz(tmp_LRflipped.nii.gz) :: -Use Nibabel to do this - Compute the Z statistic map :: 3dcalc -a VMHC_FWHM_Z.nii.gz -expr 'a*sqrt('${nvols}'-3)' -prefix VMHC_FWHM_Z_stat.nii.gz Workflow: .. image:: ../images/vmhc_graph.dot.png :width: 500 Workflow Detailed: .. image:: ../images/vmhc_detailed_graph.dot.png :width: 500 References ---------- .. [1] Zuo, X.-N., Kelly, C., Di Martino, A., Mennes, M., Margulies, D. S., Bangaru, S., Grzadzinski, R., et al. (2010). Growing together and growing apart: regional and sex differences in the lifespan developmental trajectories of functional homotopy. The Journal of neuroscience : the official journal of the Society for Neuroscience, 30(45), 15034-43. doi:10.1523/JNEUROSCI.2612-10.2010 Examples -------- >>> vmhc_w = create_vmhc() >>> vmhc_w.inputs.inputspec.symmetric_brain = 'MNI152_T1_2mm_brain_symmetric.nii.gz' >>> vmhc_w.inputs.inputspec.symmetric_skull = 'MNI152_T1_2mm_symmetric.nii.gz' >>> vmhc_w.inputs.inputspec.twomm_brain_mask_dil = 'MNI152_T1_2mm_brain_mask_symmetric_dil.nii.gz' >>> vmhc_w.inputs.inputspec.config_file_twomm = 'T1_2_MNI152_2mm_symmetric.cnf' >>> vmhc_w.inputs.inputspec.standard_for_func = 'MNI152_T1_2mm.nii.gz' >>> vmhc_w.inputs.fwhm_input.fwhm = [4.5, 6] >>> vmhc_w.get_node('fwhm_input').iterables = ('fwhm', [4.5, 6]) >>> vmhc_w.inputs.inputspec.rest_res = os.path.abspath('/home/data/Projects/Pipelines_testing/Dickstein/subjects/s1001/func/original/rest_res_filt.nii.gz') >>> vmhc_w.inputs.inputspec.reorient = os.path.abspath('/home/data/Projects/Pipelines_testing/Dickstein/subjects/s1001/anat/mprage_RPI.nii.gz') >>> vmhc_w.inputs.inputspec.brain = os.path.abspath('/home/data/Projects/Pipelines_testing/Dickstein/subjects/s1001/anat/mprage_brain.nii.gz') >>> vmhc_w.inputs.inputspec.example_func2highres_mat = os.path.abspath('/home/data/Projects/Pipelines_testing/Dickstein/subjects/s1001/func/original/reg/example_func2highres.mat') >>> vmhc_w.inputs.inputspec.rest_mask = os.path.abspath('/home/data/Projects/Pipelines_testing/Dickstein/subjects/s1001/func/original/rest_mask.nii.gz') >>> vmhc_w.run() # doctest: +SKIP """ vmhc = pe.Workflow(name='vmhc_workflow') inputNode = pe.Node(util.IdentityInterface(fields=['brain', 'symmetric_brain', 'rest_res', 'reorient', 'example_func2highres_mat', 'symmetric_skull', 'twomm_brain_mask_dil', 'config_file_twomm', 'rest_mask', 'standard_for_func', 'mean_functional']), name='inputspec') outputNode = pe.Node(util.IdentityInterface(fields=['highres2symmstandard', 'highres2symmstandard_mat', 'highres2symmstandard_warp', 'fnirt_highres2symmstandard', 'highres2symmstandard_jac', 'rest_res_2symmstandard', 'VMHC_FWHM_img', 'VMHC_Z_FWHM_img', 'VMHC_Z_stat_FWHM_img' ]), name='outputspec') inputnode_fwhm = pe.Node(util.IdentityInterface(fields=['fwhm']), name='fwhm_input') if use_ants == False: ## Linear registration of T1 --> symmetric standard linear_T1_to_symmetric_standard = pe.Node(interface=fsl.FLIRT(), name='linear_T1_to_symmetric_standard') linear_T1_to_symmetric_standard.inputs.cost = 'corratio' linear_T1_to_symmetric_standard.inputs.cost_func = 'corratio' linear_T1_to_symmetric_standard.inputs.dof = 12 linear_T1_to_symmetric_standard.inputs.interp = 'trilinear' ## Perform nonlinear registration ##(higres to standard) to symmetric standard brain nonlinear_highres_to_symmetric_standard = pe.Node(interface=fsl.FNIRT(), name='nonlinear_highres_to_symmetric_standard') nonlinear_highres_to_symmetric_standard.inputs.fieldcoeff_file = True nonlinear_highres_to_symmetric_standard.inputs.jacobian_file = True nonlinear_highres_to_symmetric_standard.inputs.warp_resolution = (10, 10, 10) # needs new inputs. needs input from resources for the field coeff of the template->symmetric. # and needs the field coeff of the anatomical-to-template registration ## Apply nonlinear registration (func to standard) nonlinear_func_to_standard = pe.Node(interface=fsl.ApplyWarp(), name='nonlinear_func_to_standard') elif use_ants == True: # ANTS warp image etc. calculate_ants_xfm_vmhc = create_wf_calculate_ants_warp(name='calculate_ants_xfm_vmhc') fsl_to_itk_vmhc = create_wf_c3d_fsl_to_itk(0, name='fsl_to_itk_vmhc') collect_transforms_vmhc = create_wf_collect_transforms(0, name='collect_transforms_vmhc') apply_ants_xfm_vmhc = create_wf_apply_ants_warp(0,name='apply_ants_xfm_vmhc') calculate_ants_xfm_vmhc.inputs.inputspec.dimension = 3 calculate_ants_xfm_vmhc.inputs.inputspec. \ use_histogram_matching = True calculate_ants_xfm_vmhc.inputs.inputspec. \ winsorize_lower_quantile = 0.01 calculate_ants_xfm_vmhc.inputs.inputspec. \ winsorize_upper_quantile = 0.99 calculate_ants_xfm_vmhc.inputs.inputspec. \ metric = ['MI','MI','CC'] calculate_ants_xfm_vmhc.inputs.inputspec.metric_weight = [1,1,1] calculate_ants_xfm_vmhc.inputs.inputspec. \ radius_or_number_of_bins = [32,32,4] calculate_ants_xfm_vmhc.inputs.inputspec. \ sampling_strategy = ['Regular','Regular',None] calculate_ants_xfm_vmhc.inputs.inputspec. \ sampling_percentage = [0.25,0.25,None] calculate_ants_xfm_vmhc.inputs.inputspec. \ number_of_iterations = [[1000,500,250,100], \ [1000,500,250,100], [100,100,70,20]] calculate_ants_xfm_vmhc.inputs.inputspec. \ convergence_threshold = [1e-8,1e-8,1e-9] calculate_ants_xfm_vmhc.inputs.inputspec. \ convergence_window_size = [10,10,15] calculate_ants_xfm_vmhc.inputs.inputspec. \ transforms = ['Rigid','Affine','SyN'] calculate_ants_xfm_vmhc.inputs.inputspec. \ transform_parameters = [[0.1],[0.1],[0.1,3,0]] calculate_ants_xfm_vmhc.inputs.inputspec. \ shrink_factors = [[8,4,2,1],[8,4,2,1],[6,4,2,1]] calculate_ants_xfm_vmhc.inputs.inputspec. \ smoothing_sigmas = [[3,2,1,0],[3,2,1,0],[3,2,1,0]] apply_ants_xfm_vmhc.inputs.inputspec.interpolation = 'Linear' apply_ants_xfm_vmhc.inputs.inputspec.input_image_type = 3 ## copy and L/R swap file copy_and_L_R_swap = pe.Node(interface=fsl.SwapDimensions(), name='copy_and_L_R_swap') copy_and_L_R_swap.inputs.new_dims = ('-x', 'y', 'z') ## caculate vmhc pearson_correlation = pe.Node(interface=preprocess.TCorrelate(), name='pearson_correlation') pearson_correlation.inputs.pearson = True pearson_correlation.inputs.polort = -1 pearson_correlation.inputs.outputtype = 'NIFTI_GZ' z_trans = pe.Node(interface=preprocess.Calc(), name='z_trans') z_trans.inputs.expr = 'log((1+a)/(1-a))/2' z_trans.inputs.outputtype = 'NIFTI_GZ' z_stat = pe.Node(interface=preprocess.Calc(), name='z_stat') z_stat.inputs.outputtype = 'NIFTI_GZ' NVOLS = pe.Node(util.Function(input_names=['in_files'], output_names=['nvols'], function=get_img_nvols), name='NVOLS') generateEXP = pe.Node(util.Function(input_names=['nvols'], output_names=['expr'], function=get_operand_expression), name='generateEXP') smooth = pe.Node(interface=fsl.MultiImageMaths(), name='smooth') if use_ants == False: vmhc.connect(inputNode, 'brain', linear_T1_to_symmetric_standard, 'in_file') vmhc.connect(inputNode, 'symmetric_brain', linear_T1_to_symmetric_standard, 'reference') vmhc.connect(inputNode, 'reorient', nonlinear_highres_to_symmetric_standard, 'in_file') vmhc.connect(linear_T1_to_symmetric_standard, 'out_matrix_file', nonlinear_highres_to_symmetric_standard, 'affine_file') vmhc.connect(inputNode, 'symmetric_skull', nonlinear_highres_to_symmetric_standard, 'ref_file') vmhc.connect(inputNode, 'twomm_brain_mask_dil', nonlinear_highres_to_symmetric_standard, 'refmask_file') vmhc.connect(inputNode, 'config_file_twomm', nonlinear_highres_to_symmetric_standard, 'config_file') vmhc.connect(inputNode, 'rest_res', smooth, 'in_file') vmhc.connect(inputnode_fwhm, ('fwhm', set_gauss), smooth, 'op_string') vmhc.connect(inputNode, 'rest_mask', smooth, 'operand_files') vmhc.connect(smooth, 'out_file', nonlinear_func_to_standard, 'in_file') vmhc.connect(inputNode, 'standard_for_func', nonlinear_func_to_standard, 'ref_file') vmhc.connect(nonlinear_highres_to_symmetric_standard, 'fieldcoeff_file', nonlinear_func_to_standard, 'field_file') ## func->anat matrix (bbreg) vmhc.connect(inputNode, 'example_func2highres_mat', nonlinear_func_to_standard, 'premat') vmhc.connect(nonlinear_func_to_standard, 'out_file', copy_and_L_R_swap, 'in_file') vmhc.connect(nonlinear_func_to_standard, 'out_file', pearson_correlation, 'xset') elif use_ants == True: # connections for ANTS stuff # registration calculation stuff -- might go out the window vmhc.connect(inputNode, 'brain', calculate_ants_xfm_vmhc, 'inputspec.anatomical_brain') vmhc.connect(inputNode, 'symmetric_brain', calculate_ants_xfm_vmhc, 'inputspec.reference_brain') # functional apply warp stuff vmhc.connect(inputNode, 'rest_res', smooth, 'in_file') vmhc.connect(inputnode_fwhm, ('fwhm', set_gauss), smooth, 'op_string') vmhc.connect(inputNode, 'rest_mask', smooth, 'operand_files') vmhc.connect(smooth, 'out_file', apply_ants_xfm_vmhc, 'inputspec.input_image') vmhc.connect(calculate_ants_xfm_vmhc, 'outputspec.ants_rigid_xfm', collect_transforms_vmhc, 'inputspec.linear_rigid') vmhc.connect(calculate_ants_xfm_vmhc, 'outputspec.ants_affine_xfm', collect_transforms_vmhc, 'inputspec.linear_affine') vmhc.connect(calculate_ants_xfm_vmhc, 'outputspec.warp_field', collect_transforms_vmhc, 'inputspec.warp_file') ## func->anat matrix (bbreg) vmhc.connect(inputNode, 'example_func2highres_mat', fsl_to_itk_vmhc, 'inputspec.affine_file') vmhc.connect(inputNode, 'brain', fsl_to_itk_vmhc, 'inputspec.reference_file') vmhc.connect(inputNode, 'mean_functional', fsl_to_itk_vmhc, 'inputspec.source_file') vmhc.connect(fsl_to_itk_vmhc, 'outputspec.itk_transform', collect_transforms_vmhc, 'inputspec.fsl_to_itk_affine') ''' vmhc.connect(inputNode, 'brain', apply_ants_xfm_vmhc, 'inputspec.conversion_reference') vmhc.connect(inputNode, 'mean_functional', apply_ants_xfm_vmhc, 'inputspec.conversion_source') ''' vmhc.connect(inputNode, 'standard_for_func', apply_ants_xfm_vmhc, 'inputspec.reference_image') vmhc.connect(collect_transforms_vmhc, \ 'outputspec.transformation_series', \ apply_ants_xfm_vmhc, 'inputspec.transforms') vmhc.connect(apply_ants_xfm_vmhc, 'outputspec.output_image', copy_and_L_R_swap, 'in_file') vmhc.connect(apply_ants_xfm_vmhc, 'outputspec.output_image', pearson_correlation, 'xset') vmhc.connect(copy_and_L_R_swap, 'out_file', pearson_correlation, 'yset') vmhc.connect(pearson_correlation, 'out_file', z_trans, 'in_file_a') vmhc.connect(copy_and_L_R_swap, 'out_file', NVOLS, 'in_files') vmhc.connect(NVOLS, 'nvols', generateEXP, 'nvols') vmhc.connect(z_trans, 'out_file', z_stat, 'in_file_a') vmhc.connect(generateEXP, 'expr', z_stat, 'expr') if use_ants == False: vmhc.connect(linear_T1_to_symmetric_standard, 'out_file', outputNode, 'highres2symmstandard') vmhc.connect(linear_T1_to_symmetric_standard, 'out_matrix_file', outputNode, 'highres2symmstandard_mat') vmhc.connect(nonlinear_highres_to_symmetric_standard, 'jacobian_file', outputNode, 'highres2symmstandard_jac') vmhc.connect(nonlinear_highres_to_symmetric_standard, 'fieldcoeff_file', outputNode, 'highres2symmstandard_warp') vmhc.connect(nonlinear_highres_to_symmetric_standard, 'warped_file', outputNode, 'fnirt_highres2symmstandard') vmhc.connect(nonlinear_func_to_standard, 'out_file', outputNode, 'rest_res_2symmstandard') elif use_ants == True: # ANTS warp outputs to outputnode vmhc.connect(calculate_ants_xfm_vmhc, 'outputspec.ants_affine_xfm', outputNode, 'highres2symmstandard_mat') vmhc.connect(calculate_ants_xfm_vmhc, 'outputspec.warp_field', outputNode, 'highres2symmstandard_warp') vmhc.connect(calculate_ants_xfm_vmhc, 'outputspec.normalized_output_brain', outputNode, 'fnirt_highres2symmstandard') vmhc.connect(apply_ants_xfm_vmhc, 'outputspec.output_image', outputNode, 'rest_res_2symmstandard') vmhc.connect(pearson_correlation, 'out_file', outputNode, 'VMHC_FWHM_img') vmhc.connect(z_trans, 'out_file', outputNode, 'VMHC_Z_FWHM_img') vmhc.connect(z_stat, 'out_file', outputNode, 'VMHC_Z_stat_FWHM_img') return vmhc
parameter_source = 'FSL', mask_type = 'file'), iterfield=['realigned_files', 'realignment_parameters'], name="art") # Register structurals to a mni reference brain # Use FLIRT first without skulls mniFLIRT = pe.Node(interface=fsl.FLIRT(reference = strippedmfxTemplateBrain), name = 'mniFLIRT') # THen leave the skulls on both brains # But apply the trasnformation to striped functionals later mniFNIRT = pe.Node(interface=fsl.FNIRT(ref_file=mfxTemplateBrain, config_file = mniConfig, field_file = True, fieldcoeff_file = True), name = 'mniFNIRT') func2MNI = pe.MapNode(interface = fsl.ApplyWarp(ref_file = mfxTemplateBrain), iterfield=['in_file','premat'], name = 'func2MNI') #Generate a mean functional (it's quicker to check a mean then a timesearies) meanfunc3 = pe.MapNode(interface=fsl.ImageMaths(op_string='-Tmean', suffix='_mean'), iterfield=['in_file'], name='meanfunc3') #Generate a mean functional (it's quicker to check a mean then a timesearies)
def create_registration_pipeline(working_dir, freesurfer_dir, ds_dir, name='registration'): """ find transformations between struct, funct, and MNI """ # initiate workflow reg_wf = Workflow(name=name) reg_wf.base_dir = os.path.join(working_dir, 'LeiCA_resting', 'rsfMRI_preprocessing') # set fsl output fsl.FSLCommand.set_default_output_type('NIFTI_GZ') freesurfer.FSCommand.set_default_subjects_dir(freesurfer_dir) # inputnode inputnode = Node(util.IdentityInterface(fields=[ 'initial_mean_epi_moco', 't1w', 't1w_brain', 'subject_id', 'wm_mask_4_bbr', 'struct_brain_mask' ]), name='inputnode') outputnode = Node(util.IdentityInterface(fields=[ 'struct_2_MNI_warp', 'epi_2_struct_mat', 'struct_2_epi_mat', 'epi_2_MNI_warp', 'MNI_2_epi_warp', 'fs_2_struct_mat', 'mean_epi_structSpace', 'mean_epi_MNIspace', 'struct_MNIspace' ]), name='outputnode') ds = Node(nio.DataSink(base_directory=ds_dir), name='ds') ds.inputs.substitutions = [('_TR_id_', 'TR_')] ########################################## # TOC REGISTRATION MATS AND WARPS ########################################## # I. STRUCT -> MNI ## 1. STRUCT -> MNI with FLIRT ## 2. CALC. WARP STRUCT -> MNI with FNIRT # II.EPI -> STRUCT ## 3. calc EPI->STRUCT initial registration ## 4. run EPI->STRUCT via bbr ## 5. INVERT to get: STRUCT -> EPI # III. COMBINE I. & II.: EPI -> MNI ## 6. COMBINE MATS: EPI -> MNI ## 7. MNI -> EPI ########################################## # CREATE REGISTRATION MATS AND WARPS ########################################## # I. STRUCT -> MNI ########################################## # 1. REGISTER STRUCT -> MNI with FLIRT struct_2_MNI_mat = Node(fsl.FLIRT(dof=12), name='struct_2_MNI_mat') struct_2_MNI_mat.inputs.reference = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') reg_wf.connect(inputnode, 't1w_brain', struct_2_MNI_mat, 'in_file') reg_wf.connect(struct_2_MNI_mat, 'out_matrix_file', outputnode, 'struct_2_MNI_mat_flirt') # 2. CALC. WARP STRUCT -> MNI with FNIRT # cf. wrt. 2mm # https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind1311&L=FSL&P=R86108&1=FSL&9=A&J=on&d=No+Match%3BMatch%3BMatches&z=4 struct_2_MNI_warp = Node(fsl.FNIRT(), name='struct_2_MNI_warp') struct_2_MNI_warp.inputs.config_file = 'T1_2_MNI152_2mm' struct_2_MNI_warp.inputs.ref_file = fsl.Info.standard_image( 'MNI152_T1_2mm.nii.gz') struct_2_MNI_warp.inputs.field_file = 'struct_2_MNI_warp.nii.gz' struct_2_MNI_warp.plugin_args = {'submit_specs': 'request_memory = 4000'} reg_wf.connect(inputnode, 't1w', struct_2_MNI_warp, 'in_file') reg_wf.connect(struct_2_MNI_mat, 'out_matrix_file', struct_2_MNI_warp, 'affine_file') reg_wf.connect(struct_2_MNI_warp, 'field_file', ds, 'registration.struct_2_MNI_warp') reg_wf.connect(struct_2_MNI_warp, 'field_file', outputnode, 'struct_2_MNI_warp') reg_wf.connect(struct_2_MNI_warp, 'warped_file', outputnode, 'struct_MNIspace') reg_wf.connect(struct_2_MNI_warp, 'warped_file', ds, 'registration.struct_MNIspace') # II.EPI -> STRUCT (via bbr) ########################################## # 3. calc EPI->STRUCT initial registration with flirt dof=6 and corratio epi_2_struct_flirt6_mat = Node(fsl.FLIRT(dof=6, cost='corratio'), name='epi_2_struct_flirt6_mat') epi_2_struct_flirt6_mat.inputs.out_file = 'epi_structSpace_flirt6.nii.gz' reg_wf.connect(inputnode, 't1w_brain', epi_2_struct_flirt6_mat, 'reference') reg_wf.connect(inputnode, 'initial_mean_epi_moco', epi_2_struct_flirt6_mat, 'in_file') # 4. run EPI->STRUCT via bbr bbr_shedule = os.path.join(os.getenv('FSLDIR'), 'etc/flirtsch/bbr.sch') epi_2_struct_bbr_mat = Node(interface=fsl.FLIRT(dof=6, cost='bbr'), name='epi_2_struct_bbr_mat') epi_2_struct_bbr_mat.inputs.schedule = bbr_shedule epi_2_struct_bbr_mat.inputs.out_file = 'epi_structSpace.nii.gz' reg_wf.connect(inputnode, 'initial_mean_epi_moco', epi_2_struct_bbr_mat, 'in_file') reg_wf.connect(inputnode, 't1w_brain', epi_2_struct_bbr_mat, 'reference') reg_wf.connect(epi_2_struct_flirt6_mat, 'out_matrix_file', epi_2_struct_bbr_mat, 'in_matrix_file') reg_wf.connect(inputnode, 'wm_mask_4_bbr', epi_2_struct_bbr_mat, 'wm_seg') reg_wf.connect(epi_2_struct_bbr_mat, 'out_matrix_file', ds, 'registration.epi_2_struct_mat') reg_wf.connect(epi_2_struct_bbr_mat, 'out_file', outputnode, 'mean_epi_structSpace') # 5. INVERT to get: STRUCT -> EPI struct_2_epi_mat = Node(fsl.ConvertXFM(invert_xfm=True), name='struct_2_epi_mat') reg_wf.connect(epi_2_struct_bbr_mat, 'out_matrix_file', struct_2_epi_mat, 'in_file') reg_wf.connect(struct_2_epi_mat, 'out_file', outputnode, 'struct_2_epi_mat') # III. COMBINE I. & II.: EPI -> MNI ########################################## # 6. COMBINE MATS: EPI -> MNI epi_2_MNI_warp = Node(fsl.ConvertWarp(), name='epi_2_MNI_warp') epi_2_MNI_warp.inputs.reference = fsl.Info.standard_image( 'MNI152_T1_2mm.nii.gz') reg_wf.connect(epi_2_struct_bbr_mat, 'out_matrix_file', epi_2_MNI_warp, 'premat') # epi2struct reg_wf.connect(struct_2_MNI_warp, 'field_file', epi_2_MNI_warp, 'warp1') # struct2mni reg_wf.connect(epi_2_MNI_warp, 'out_file', outputnode, 'epi_2_MNI_warp') reg_wf.connect(epi_2_MNI_warp, 'out_file', ds, 'registration.epi_2_MNI_warp') # output: out_file # 7. MNI -> EPI MNI_2_epi_warp = Node(fsl.InvWarp(), name='MNI_2_epi_warp') MNI_2_epi_warp.inputs.reference = fsl.Info.standard_image( 'MNI152_T1_2mm.nii.gz') reg_wf.connect(epi_2_MNI_warp, 'out_file', MNI_2_epi_warp, 'warp') reg_wf.connect(inputnode, 'initial_mean_epi_moco', MNI_2_epi_warp, 'reference') reg_wf.connect(MNI_2_epi_warp, 'inverse_warp', outputnode, 'MNI_2_epi_warp') # output: inverse_warp ########################################## # TRANSFORM VOLUMES ########################################## # CREATE STRUCT IN EPI SPACE FOR DEBUGGING struct_epiSpace = Node(fsl.ApplyXfm(), name='struct_epiSpace') struct_epiSpace.inputs.out_file = 'struct_brain_epiSpace.nii.gz' reg_wf.connect(inputnode, 't1w_brain', struct_epiSpace, 'in_file') reg_wf.connect(inputnode, 'initial_mean_epi_moco', struct_epiSpace, 'reference') reg_wf.connect(struct_2_epi_mat, 'out_file', struct_epiSpace, 'in_matrix_file') reg_wf.connect(struct_epiSpace, 'out_file', ds, 'QC.struct_brain_epiSpace') # CREATE EPI IN MNI SPACE mean_epi_MNIspace = Node(fsl.ApplyWarp(), name='mean_epi_MNIspace') mean_epi_MNIspace.inputs.ref_file = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') mean_epi_MNIspace.inputs.out_file = 'mean_epi_MNIspace.nii.gz' reg_wf.connect(inputnode, 'initial_mean_epi_moco', mean_epi_MNIspace, 'in_file') reg_wf.connect(epi_2_MNI_warp, 'out_file', mean_epi_MNIspace, 'field_file') reg_wf.connect(mean_epi_MNIspace, 'out_file', ds, 'registration.mean_epi_MNIspace') reg_wf.connect(mean_epi_MNIspace, 'out_file', outputnode, 'mean_epi_MNIspace') # CREATE MNI IN EPI SPACE FOR DEBUGGING MNI_epiSpace = Node(fsl.ApplyWarp(), name='MNI_epiSpace') MNI_epiSpace.inputs.in_file = fsl.Info.standard_image( 'MNI152_T1_2mm_brain.nii.gz') MNI_epiSpace.inputs.out_file = 'MNI_epiSpace.nii.gz' reg_wf.connect(inputnode, 'initial_mean_epi_moco', MNI_epiSpace, 'ref_file') reg_wf.connect(MNI_2_epi_warp, 'inverse_warp', MNI_epiSpace, 'field_file') reg_wf.connect(MNI_epiSpace, 'out_file', ds, 'registration.MNI_epiSpace') reg_wf.write_graph(dotfilename=reg_wf.name, graph2use='flat', format='pdf') return reg_wf
def create_fsl_workflow(data_dir=None, subjects=None, name="fslwarp"): """Set up the anatomical normalzation workflow using FNIRT. Your anatomical data must have been processed in Freesurfer. Unlike most lyman workflows, the DataGrabber and DataSink nodes are hardwired within the returned workflow, as this tightly integrates with the Freesurfer subjects directory structure. Parameters ---------- data_dir : path top level of data hierarchy/FS subjects directory subjects : list of strings list of subject IDs name : alphanumeric string, optional workflow name """ if data_dir is None: data_dir = os.environ["SUBJECTS_DIR"] if subjects is None: subjects = [] # Get target images target_brain = fsl.Info.standard_image("avg152T1_brain.nii.gz") target_head = fsl.Info.standard_image("avg152T1.nii.gz") hires_head = fsl.Info.standard_image("MNI152_T1_1mm.nii.gz") target_mask = fsl.Info.standard_image( "MNI152_T1_2mm_brain_mask_dil.nii.gz") fnirt_cfg = os.path.join(os.environ["FSLDIR"], "etc/flirtsch/T1_2_MNI152_2mm.cnf") # Subject source node subjectsource = Node(IdentityInterface(fields=["subject_id"]), iterables=("subject_id", subjects), name="subjectsource") # Grab recon-all outputs head_image = "T1" templates = dict(aseg="{subject_id}/mri/aparc+aseg.mgz", head="{subject_id}/mri/" + head_image + ".mgz") datasource = Node(SelectFiles(templates, base_directory=data_dir), "datasource") # Convert images to nifti storage and float representation cvtaseg = Node(fs.MRIConvert(out_type="niigz"), "convertaseg") cvthead = Node(fs.MRIConvert(out_type="niigz", out_datatype="float"), "converthead") # Turn the aparc+aseg into a brainmask makemask = Node(fs.Binarize(dilate=1, min=0.5), "makemask") # Extract the brain from the orig.mgz using the mask skullstrip = Node(fsl.ApplyMask(), "skullstrip") # FLIRT brain to MNI152_brain flirt = Node(fsl.FLIRT(reference=target_brain), "flirt") sw = [-180, 180] for dim in ["x", "y", "z"]: setattr(flirt.inputs, "searchr_%s" % dim, sw) # FNIRT head to MNI152 fnirt = Node( fsl.FNIRT(ref_file=target_head, refmask_file=target_mask, config_file=fnirt_cfg, fieldcoeff_file=True), "fnirt") # Warp and rename the images warpbrain = Node( fsl.ApplyWarp(ref_file=target_head, interp="spline", out_file="brain_warp.nii.gz"), "warpbrain") warpbrainhr = Node( fsl.ApplyWarp(ref_file=hires_head, interp="spline", out_file="brain_warp_hires.nii.gz"), "warpbrainhr") # Generate a png summarizing the registration warpreport = Node(WarpReport(), "warpreport") # Save relevant files to the data directory fnirt_subs = [(head_image + "_out_masked_flirt.mat", "affine.mat"), (head_image + "_out_fieldwarp", "warpfield"), (head_image + "_out_masked", "brain"), (head_image + "_out", "T1")] datasink = Node( DataSink(base_directory=data_dir, parameterization=False, substitutions=fnirt_subs), "datasink") # Define and connect the workflow # ------------------------------- normalize = Workflow(name=name) normalize.connect([ (subjectsource, datasource, [("subject_id", "subject_id")]), (datasource, cvtaseg, [("aseg", "in_file")]), (datasource, cvthead, [("head", "in_file")]), (cvtaseg, makemask, [("out_file", "in_file")]), (cvthead, skullstrip, [("out_file", "in_file")]), (makemask, skullstrip, [("binary_file", "mask_file")]), (skullstrip, flirt, [("out_file", "in_file")]), (flirt, fnirt, [("out_matrix_file", "affine_file")]), (cvthead, fnirt, [("out_file", "in_file")]), (skullstrip, warpbrain, [("out_file", "in_file")]), (fnirt, warpbrain, [("fieldcoeff_file", "field_file")]), (skullstrip, warpbrainhr, [("out_file", "in_file")]), (fnirt, warpbrainhr, [("fieldcoeff_file", "field_file")]), (warpbrain, warpreport, [("out_file", "in_file")]), (subjectsource, datasink, [("subject_id", "container")]), (skullstrip, datasink, [("out_file", "normalization.@brain")]), (cvthead, datasink, [("out_file", "normalization.@t1")]), (flirt, datasink, [("out_file", "normalization.@brain_flirted")]), (flirt, datasink, [("out_matrix_file", "normalization.@affine")]), (warpbrain, datasink, [("out_file", "normalization.@brain_warped")]), (warpbrainhr, datasink, [("out_file", "normalization.@brain_hires")]), (fnirt, datasink, [("fieldcoeff_file", "normalization.@warpfield")]), (warpreport, datasink, [("out_file", "normalization.@report")]), ]) return normalize
def non_linear_registration_( self ): """Non-linear registration. Second part in the study template creation. Estimation of the registration parameters of brain to study oriented standard brain template.""" try: # # # # Use the linear template built in the linear_registration_ funstion template_linear = os.path.join(self.ana_dir_, "temp_T1_lin.nii.gz") template_T1_brain_lin = os.path.join(self.ana_dir_, "temp_T1_brain_lin.nii.gz") # check if it has been built if not os.path.exists(template_linear): raise Exception( "Template %s has not been built yet. User has to process the linear step first"%template_linear ) # # Loop on the tasks while True: # get the item item = self.queue_[1].get() # registration estimation flt = fsl.FLIRT() flt.inputs.in_file = os.path.join(self.T1_brain_dir_, item ) flt.inputs.reference = template_T1_brain_lin flt.inputs.out_file = os.path.join( self.template_dir_, "%s_non_li_MNI.nii.gz"%item[:-7] ) flt.inputs.out_matrix_file = os.path.join( self.template_dir_, "%s_non_li_MNI.mat"%item[:-7] ) flt.inputs.dof = 12 res = flt.run() # # Find the matching T1 image PIDN = [int(s) for s in item.split("_") if s.isdigit()] # T1_item = [ s for s in self.list_T1_ if str(PIDN[0]) in s] # # apply registration using T1_2_MNI152_2mm.cnf configuration file T1_2_MNI152_2mm = "" if os.environ.get('FSLDIR'): T1_2_MNI152_2mm = os.path.join( os.environ.get('FSLDIR'), "etc","flirtsch","T1_2_MNI152_2mm.cnf" ) # fnt = fsl.FNIRT() fnt.inputs.in_file = os.path.join( self.T1_dir_, T1_item[0] ) fnt.inputs.ref_file = template_linear fnt.inputs.warped_file = os.path.join( self.template_dir_, "%s_non_li_MNI_fnirt.nii.gz"%item[:-7] ) fnt.inputs.affine_file = os.path.join( self.template_dir_, "%s_non_li_MNI.mat"%item[:-7] ) fnt.inputs.config_file = T1_2_MNI152_2mm fnt.inputs.fieldcoeff_file = os.path.join( self.template_dir_, "%s_non_li_MNI_coeff.nii.gz"%item[:-7] ) res = fnt.run() # apply warp aw = fsl.ApplyWarp() aw.inputs.in_file = os.path.join( self.T1_dir_, T1_item[0] ) aw.inputs.ref_file = template_linear aw.inputs.out_file = os.path.join( self.template_dir_, "%s_non_li_MNI_warped.nii.gz"%item[:-7] ) aw.inputs.field_file = os.path.join( self.template_dir_, "%s_non_li_MNI_coeff.nii.gz"%item[:-7] ) res = aw.run() # lock and add the file singlelock.acquire() self.non_linear_MNI_.append( aw.inputs.out_file ) singlelock.release() # job is done self.queue_[1].task_done() # # except Exception as inst: print inst _log.error(inst) quit(-1) except IOError as e: print "I/O error({0}): {1}".format(e.errno, e.strerror) quit(-1) except: print "Unexpected error:", sys.exc_info()[0] quit(-1)
def create_resting(): # main workflow func_preproc = Workflow(name='resting') inputnode = Node(util.IdentityInterface(fields=[ 'subject_id', 'out_dir', 'freesurfer_dir', 'func', 'rs_mag', 'rs_ph', 'anat_head', 'anat_brain', 'anat_brain_mask', 'wmseg', 'csfseg', 'vol_to_remove', 'TR', 'highpass_freq', 'epi_resolution', 'echo_space', 'te_diff', 'fwhm', 'pe_dir', 'composite_transform', 'standard_brain', 'standard_downsampled' ]), name='inputnode') #Use correct subject ID from long timepoint for bbregister def change_subject_id(subject): import re [subj, ses] = re.split("_", subject) new_subject_id = subject + '.long.' + subj return new_subject_id change_subject_id = Node(util.Function(input_names=["subject"], output_names=["new_subject_id"], function=change_subject_id), name="change_subject_id") outputnode = Node(util.IdentityInterface(fields=[ 'brain', 'brainmask', 'anat2std_transforms', 'std2anat_transforms', 'anat2std', 'anat_head', 'wmseg', 'csfseg', 'wmedge', 'subject_id' ]), name='outputnode') ##PREPROCESSING FOR AROMA (Steps 1 - 7) def merge_if_list(in_file): if type(in_file) == list: import numpy as np import nibabel as nb import os from nipype.utils.filemanip import split_filename nii1 = nb.load(in_file[0]) nii1d = nii1.get_data() nii2 = nb.load(in_file[1]) nii2d = nii2.get_data() x = np.concatenate((nii1d, nii2d), axis=3) new_nii = nb.Nifti1Image(x, nii1.get_affine(), nii1.get_header()) new_nii.set_data_dtype(np.float32) _, base, _ = split_filename(in_file[0]) nb.save(new_nii, base + "_merged.nii.gz") return os.path.abspath(base + "_merged.nii.gz") else: return in_file #if rsfmri is a list -> merge files, otherwise return single list. merge_rs = Node(util.Function(input_names=['in_file'], output_names=["out_file"], function=merge_if_list), name='merge_rs') # node to remove first volumes remove_vol = Node(util.Function(input_names=['in_file', 't_min'], output_names=["out_file"], function=strip_rois_func), name='remove_vol') # workflow for motion correction moco = create_moco_pipeline() # workflow for fieldmap correction and coregistration fmap_coreg = create_fmap_coreg_pipeline() # workflow for applying transformations to timeseries transform_ts = create_transform_pipeline() #mean intensity normalization meanintensnorm = Node(fsl.ImageMaths(op_string='-ing 10000'), name='meanintensnorm') smoothing = create_smoothing_pipeline() # connections func_preproc.connect([ (inputnode, merge_rs, [('func', 'in_file')]), (merge_rs, remove_vol, [('out_file', 'in_file')]), (inputnode, remove_vol, [('vol_to_remove', 't_min')]), (inputnode, moco, [('anat_brain_mask', 'inputnode.brainmask')]), (remove_vol, moco, [('out_file', 'inputnode.epi')]), (inputnode, change_subject_id, [('subject_id', 'subject')]), (change_subject_id, fmap_coreg, [('new_subject_id', 'inputnode.fs_subject_id')]), (inputnode, fmap_coreg, [('rs_mag', 'inputnode.mag'), ('rs_ph', 'inputnode.phase'), ('freesurfer_dir', 'inputnode.fs_subjects_dir'), ('echo_space', 'inputnode.echo_space'), ('te_diff', 'inputnode.te_diff'), ('pe_dir', 'inputnode.pe_dir'), ('anat_head', 'inputnode.anat_head'), ('anat_brain', 'inputnode.anat_brain')]), (moco, fmap_coreg, [('outputnode.epi_mean', 'inputnode.epi_mean')]), (remove_vol, transform_ts, [('out_file', 'inputnode.orig_ts')]), (inputnode, transform_ts, [('anat_head', 'inputnode.anat_head')]), (inputnode, transform_ts, [('anat_brain_mask', 'inputnode.brain_mask') ]), (inputnode, transform_ts, [('epi_resolution', 'inputnode.resolution') ]), (moco, transform_ts, [('outputnode.mat_moco', 'inputnode.mat_moco')]), (fmap_coreg, transform_ts, [('outputnode.fmap_fullwarp', 'inputnode.fullwarp')]), (transform_ts, meanintensnorm, [('outputnode.trans_ts', 'in_file')]), (meanintensnorm, smoothing, [('out_file', 'inputnode.ts_transformed') ]), (inputnode, smoothing, [('fwhm', 'inputnode.fwhm')]) ]) ##CALCULATE TRANSFORM from anatomical to standard space with FSL tools # Anat > Standard # register high-resolution to standard template with non-linear transform # flirt serves as preparation for fnirt) #reorient brain to standard (because Freesurfer space can cause problems) reorient2std = Node(fsl.Reorient2Std(), name="reorient2std") reorient2std_rs = Node(fsl.Reorient2Std(), name="reorient2std_rs") reorient2std_mask = Node(fsl.Reorient2Std(), name="reorient2std_mask") flirt_prep = Node(fsl.FLIRT(cost_func='mutualinfo', interp='trilinear'), name='flirt_prep') flirt_prep.inputs.interp = 'trilinear' flirt_prep.inputs.dof = 12 fnirt = Node(fsl.FNIRT(), name='fnirt') fnirt.inputs.field_file = True fnirt.inputs.fieldcoeff_file = True func_preproc.connect([ (inputnode, reorient2std, [('anat_brain', 'in_file')]), (reorient2std, flirt_prep, [('out_file', 'in_file')]), #(inputnode, flirt_prep, [('anat_brain', 'in_file')]), (inputnode, flirt_prep, [('standard_brain', 'reference')]), (flirt_prep, fnirt, [('out_matrix_file', 'affine_file')]), (reorient2std, fnirt, [('out_file', 'in_file')]), (inputnode, fnirt, [('standard_brain', 'ref_file')]), ]) def getcwd(subject_id): import os tmp = os.getcwd() tmp = tmp[:-6] tmp = tmp + 'ica_aroma/out' #%(subject_id) return tmp get_wd = Node(util.Function(input_names=['subject_id'], output_names=["d"], function=getcwd), name='get_wd') ica_aroma = Node(ICA_AROMA(), name="ica_aroma") ica_aroma.inputs.denoise_type = 'both' #ica_aroma.inputs.out_dir = os.getcwd() func_preproc.connect([ (moco, ica_aroma, [('outputnode.par_moco', 'motion_parameters')]), (smoothing, reorient2std_rs, [('outputnode.ts_smoothed', 'in_file')]), (reorient2std_rs, ica_aroma, [('out_file', 'in_file')]), (fnirt, ica_aroma, [('field_file', 'fnirt_warp_file')]), (transform_ts, reorient2std_mask, [('outputnode.comb_mask_resamp', 'in_file')]), (reorient2std_mask, ica_aroma, [('out_file', 'mask')]), (inputnode, get_wd, [('subject_id', 'subject_id')]), (get_wd, ica_aroma, [('d', 'out_dir')]) ]) ##POSTPROCESSING postprocess = create_denoise_pipeline() func_preproc.connect([ (reorient2std_mask, postprocess, [ ('out_file', 'inputnode.brain_mask') ]), #use the correctly oriented mask (ica_aroma, postprocess, [ ('nonaggr_denoised_file', 'inputnode.epi_coreg') ]), #use the nonaggr_denoised_file (inputnode, postprocess, [('TR', 'inputnode.tr')]), (inputnode, postprocess, [('highpass_freq', 'inputnode.highpass_freq') ]), (inputnode, postprocess, [('wmseg', 'inputnode.wmseg')]), (inputnode, postprocess, [('csfseg', 'inputnode.csfseg')]), ]) #outputnode outputnode = Node(util.IdentityInterface(fields=[ 'par', 'rms', 'mean_epi', 'tsnr', 'stddev_file', 'realigned_ts', 'fmap', 'unwarped_mean_epi2fmap', 'coregistered_epi2fmap', 'fmap_fullwarp', 'epi2anat', 'epi2anat_mat', 'epi2anat_dat', 'epi2anat_mincost', 'full_transform_ts', 'full_transform_mean', 'resamp_t1', 'comb_mask_resamp', 'dvars_file', 'out_flirt_prep', 'out_matrix_flirt_prep', 'out_warped', 'out_warp_field', 'aggr_denoised_file', 'nonaggr_denoised_file', 'out_dir', 'wmcsf_mask', 'combined_motion', 'comp_regressor', 'comp_F', 'comp_pF', 'out_betas', 'ts_fullspectrum', 'ts_filtered' ]), name='outputnode') # connections func_preproc.connect([ ( moco, outputnode, [ #('outputnode.epi_moco', 'realign.@realigned_ts'), ('outputnode.par_moco', 'par'), ('outputnode.rms_moco', 'rms'), ('outputnode.epi_moco', 'realigned_ts'), ('outputnode.epi_mean', 'mean_epi'), ('outputnode.tsnr_file', 'tsnr'), ('outputnode.stddev_file', 'stddev'), ]), (fmap_coreg, outputnode, [('outputnode.fmap', 'fmap'), ('outputnode.unwarped_mean_epi2fmap', 'unwarped_mean_epi2fmap'), ('outputnode.epi2fmap', 'coregistered_epi2fmap'), ('outputnode.fmap_fullwarp', 'fmap_fullwarp'), ('outputnode.epi2anat', 'epi2anat'), ('outputnode.epi2anat_mat', 'epi2anat_mat'), ('outputnode.epi2anat_dat', 'epi2anat_dat'), ('outputnode.epi2anat_mincost', 'epi2anat_mincost')]), (transform_ts, outputnode, [('outputnode.trans_ts', 'full_transform_ts'), ('outputnode.trans_ts_mean', 'full_transform_mean'), ('outputnode.resamp_t1', 'resamp_t1'), ('outputnode.comb_mask_resamp', 'comb_mask_resamp'), ('outputnode.out_dvars', 'dvars_file')]), (flirt_prep, outputnode, [('out_file', 'out_flirt_prep'), ('out_matrix_file', 'out_matrix_flirt_prep') ]), (fnirt, outputnode, [('warped_file', 'out_warped'), ('field_file', 'out_warp_field')]), (ica_aroma, outputnode, [('aggr_denoised_file', 'aggr_denoised_file'), ('nonaggr_denoised_file', 'nonaggr_denoised_file'), ('out_dir', 'out_dir')]), (postprocess, outputnode, [('outputnode.wmcsf_mask', 'wmcsf_mask'), ('outputnode.combined_motion', 'combined_motion'), ('outputnode.comp_regressor', 'comp_regressor'), ('outputnode.comp_F', 'comp_F'), ('outputnode.comp_pF', 'comp_pF'), ('outputnode.out_betas', 'out_betas'), ('outputnode.ts_fullspectrum', 'ts_fullspectrum'), ('outputnode.ts_filtered', 'ts_filtered')]) ]) return func_preproc
def get_ADC(LinADC): """ in the future, users will be able to specify which time point to use as reference """ return LinADC[0] get_Ref = pe.JoinNode(interface=util.Function(input_names=['LinADC'], output_names=['REF'], function=get_ADC), name='get_Ref', joinsource='data', joinfield='LinADC') ADCwarpHighRes = pe.Node(interface=fsl.FNIRT(), name='ADCwarpHighRes') ADCwarpHighRes.inputs.field_file = True ADCwarpHighRes.inputs.config_file = fnirt_config TumorwarpHighRes = pe.Node(interface=fsl.ApplyWarp(), name='TumorwarpHighRes') REFwarpHighRes = pe.Node(interface=fsl.ApplyWarp(), name='REFwarpHighRes') NormalwarpHighRes = pe.Node(interface=fsl.ApplyWarp(), name='NormalwarpHighRes') Warp = pe.Workflow(name='Warp') Warp.base_dir = parent_dir + '/FDM' Warp.connect([ (get_Ref, ADCwarpHighRes, [('REF', 'ref_file')]),
def anatomical_registration(self, subject, standard_image_name='MNI152_T1_2mm_brain.nii.gz' ): """ Anatomical Registration 1) Runs FLIRT on the brain extracted anatomy image with MNI152_T1_2mm_brain.nii.gz as reference 2) Runs FNIRT on the anatomy image Outputs: anatomy/reg/highres2standard.nii.gz anatomy/reg/highres2standard.mat anatomy/reg/highres2highres_jac anatomy/reg/highres2standard_warp.nii.gz Parameters subject = Subject Dir object standard_image_name = The anatomy reference image """ print ">>> Anatomical registration" brain_image = subject.anatomical_nii('brain') reg_dir = os.path.join(subject.anatomical_dir(), 'reg') out_file = os.path.join(reg_dir, 'highres2standard.nii.gz') out_mat_file = os.path.join(reg_dir, 'highres2standard.mat') standard_image = fsl.Info.standard_image(standard_image_name) if not os.path.isfile(out_mat_file): print ">>>> FLIRT" os.mkdir(reg_dir) flirt = fsl.FLIRT(in_file=brain_image, reference=standard_image, out_file=out_file, out_matrix_file=out_mat_file, cost='corratio', # ('mutualinfo' or 'corratio' or 'normcorr' or 'normmi' or 'leastsq' or 'labeldiff' or 'bbr') dof=12, # number of transform degrees of freedom searchr_x=[-90, 90], # search angles along x-axis, in degrees searchr_y=[-90, 90], # search angles along y-axis, in degrees searchr_z=[-90, 90], # search angles along z-axis, in degrees interp='trilinear') # 'trilinear' or 'nearestneighbour' or 'sinc' or 'spline' flirt.run() else: print(">>>> FLIRT has already been performed") anatomical_head = subject.anatomical_nii() output_fielf_coeff = os.path.join( reg_dir, 'highres2standard_warp.nii.gz') output_jacobian = os.path.join(reg_dir, 'highres2highres_jac') standard_head = fsl.Info.standard_image('MNI152_T1_2mm.nii.gz') standard_mask = fsl.Info.standard_image( 'MNI152_T1_2mm_brain_mask_dil.nii.gz') if not os.path.isfile(output_fielf_coeff): print ">>>> FNIRT" # non-linear registration. fnirt = fsl.FNIRT(warped_file=out_file, # warped image in_file=anatomical_head, affine_file=out_mat_file, # Affine matrix to use fieldcoeff_file=output_fielf_coeff, # name of output file with field coefficients or true jacobian_file=output_jacobian, # name of file for writing out the Jacobianof the field (for diagnostic or VBM purposes) config_file='T1_2_MNI152_2mm', # 'T1_2_MNI152_2mm' or 'FA_2_FMRIB58_1mm' ref_file=standard_head, # name of reference image refmask_file=standard_mask) # name of file with mask in reference space fnirt.run() cmd = 'fslview {} {} -t 0.5 '.format(standard_image, out_file) pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid) else: print(">>>> FNIRT has already been performed")
'reference') register_flow.connect(func2highres, 'out_matrix_file', func2highres_bbr, 'in_matrix_file') # Calculate affine transform from anatomical to target (default interpolation is trilinear) highres2standard = Node(fsl.FLIRT(), name='highres2standard_affine') highres2standard.inputs.dof = 12 highres2standard.inputs.searchr_x = [-90, 90] highres2standard.inputs.searchr_y = [-90, 90] highres2standard.inputs.searchr_z = [-90, 90] register_flow.connect(stripper, 'out_file', highres2standard, 'in_file') register_flow.connect(reg_inputnode, 'target_image_brain', highres2standard, 'reference') # Calculate nonlinear transform from anatomical to target (default warp resolution is 10,10,10) highres2standard_warp = Node(fsl.FNIRT(), name='highres2standard_nonlinear') highres2standard_warp.inputs.fieldcoeff_file = True register_flow.connect(highres2standard, 'out_matrix_file', highres2standard_warp, 'affine_file') register_flow.connect(reg_inputnode, 'anatomical_image', highres2standard_warp, 'in_file') register_flow.connect(reg_inputnode, 'config_file', highres2standard_warp, 'config_file') register_flow.connect(reg_inputnode, 'target_image', highres2standard_warp, 'ref_file') register_flow.connect(reg_inputnode, 'target_mask', highres2standard_warp, 'refmask_file') # Combine linear FLIRT transformations into one to create a transformation matrix from functional to target func2standard = Node(fsl.ConvertXFM(concat_xfm=True), name='func2standard_linear')
def FNIRT(in_file: str, ref: str, out_file: str, aff: str = None): fnt = fsl.FNIRT() fnt.inputs.in_file = in_file fnt.inputs.ref_file = ref
#extract_b0.inputs.t_min = 0 get_T1_template.inputs.t_size = 1 get_T1_template.inputs.in_file = T1_Template T1linTemplate = pe.Node(interface=fsl.FLIRT(), name='T1linTemplate') #T1linTemplate.inputs.reference=Template T1linTemplate.inputs.dof = 12 T1linTemplate.inputs.searchr_x = [-180, 180] T1linTemplate.inputs.searchr_y = [-180, 180] T1linTemplate.inputs.searchr_z = [-180, 180] inverse_T1_matrix = pe.Node(interface=fsl.ConvertXFM(), name='inverse_T1_matrix') inverse_T1_matrix.inputs.invert_xfm = True T1warpTemplate=pe.Node(interface=fsl.FNIRT(), name='T1warpTemplate') T1warpTemplate.inputs.field_file=True T1warpTemplate.inputs.config_file=configfile inverse_T1_warp=pe.Node(interface=tools.InvWarp(), name='inverse_T1_warp') apply_T1_warp=pe.MapNode(interface=fsl.ApplyWarp(), name='apply_T1_warp', iterfield=['in_file']) apply_T1_warp.inputs.interp='nn' get_masks = pe.MapNode(interface=fsl.ExtractROI(), name = 'get_masks', iterfield=['in_file']) get_masks.inputs.t_size = 1 get_masks.inputs.in_file = TissueList
def reg2std(name='standardization'): """ Linear and non-linear standardization for structural rat MRI images Input: upscaled data """ reg = pe.Workflow(name=name) """ Set up a node to define all inputs required for the preprocessing workflow """ inputnode = pe.Node(interface=util.IdentityInterface(fields=['in_file_head', 'in_file_brain'], mandatory_inputs=True), name='inputspec') """ Set up a node to define outputs for the preprocessing workflow """ outputnode = pe.Node(interface=util.IdentityInterface(fields=['out_nonlin_head', 'out_nonlin_brain', 'out_warpfield', 'out_lin_brain'], mandatory_inputs=True), name='outputspec') """ Node for linear (12-param) reg flirt -in $in -ref $std -dof 12 -omat $omat -bins 256 -cost $type -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -interp trilinear """ flirt=pe.MapNode(interface=fsl.FLIRT(reference='/opt/shared/etc/std/new/standard-wistar_2mm_brain.nii.gz', dof=12, bins=256, cost='corratio', interp='trilinear'), name='linear_standardization', iterfield=['in_file']) #out_matrix_file?, searchr? """ Non-linear reg fnirt --in=$in --ref=$std --aff=$init --iout=$out --miter=2,3 --infwhm=4,1 --reffwhm=2,0 --subsamp=8,1 --estint=1,1 --applyrefmask=1,1 --applyinmask=0,0 --lambda=200,500 --warpres=10,10,10 --intmod=global_non_linear --refmask=$refmask --fout=$warpingfield --interp=spline """ #TODO: parametrize standard template fnirt=pe.MapNode(interface=fsl.FNIRT( \ ref_file='/opt/shared/etc/std/new/standard-wistar_2mm_brain.nii.gz', \ refmask_file='/opt/shared/etc/std/new/standard-wistar_2mm_brain_mask.nii.gz', \ max_nonlin_iter=[2,3], \ in_fwhm=[2,0], \ ref_fwhm=[2,0], \ subsampling_scheme=[8,1],\ apply_intensity_mapping=[1,1],\ apply_refmask=[1,1],\ apply_inmask=[0,0],\ regularization_lambda=[200,500],\ warp_resolution=(10,10,10),\ intensity_mapping_model='global_non_linear_with_bias',\ field_file=True), name='nonlinear_standardization', iterfield=['in_file', 'affine_file' ]) """ Non-linear reg fnirt --in=$in --ref=$std --aff=$init --iout=$out --miter=2,3 --infwhm=4,1 --reffwhm=2,0 --subsamp=8,1 --estint=1,1 --applyrefmask=1,1 --applyinmask=0,0 --lambda=200,500 --warpres=10,10,10 --intmod=global_non_linear --refmask=$refmask --fout=$warpingfield --interp=spline """ applyWarp=pe.MapNode(interface=fsl.ApplyWarp(), name="warp_brain", iterfield=['in_file', 'ref_file', 'field_file']) # TODO applywarp: brain reg.connect(inputnode, "in_file_brain", flirt, "in_file") reg.connect(flirt, "out_file", outputnode, "out_lin_brain") reg.connect(inputnode, "in_file_head", fnirt, "in_file") reg.connect(flirt, "out_matrix_file", fnirt, "affine_file") reg.connect(inputnode, "in_file_brain", applyWarp, "in_file") reg.connect(fnirt, "warped_file", applyWarp, "ref_file") reg.connect(fnirt, "field_file", applyWarp, "field_file") reg.connect(fnirt, "warped_file", outputnode, "out_nonlin_head") reg.connect(applyWarp, "out_file", outputnode, "out_nonlin_brain") reg.connect(fnirt, "field_file", outputnode, "out_warpfield") return reg
def create_iterative_register_pipe(template_file, template_brain_file, template_mask_file, gm_prob_file, wm_prob_file, csf_prob_file, n_iter, name="register_pipe"): """ Registration of template (NMT or other) according to Regis: - The iterative FLIRT is between NMT_SS and subject's anat after a quick skull-stripping but the anat is more and more refined to corresponds to the brain - there is also a FNIRT done once, for comparison of the quality of the template on the subject's brain Not used anymore: corresponds to the IterREGBET provided by Regis in bash and wrapped node IterREGBET in nodes/register.py #TODO: test if gives the same results as IterREGBET """ register_pipe = pe.Workflow(name=name) # creating inputnode inputnode = pe.Node( niu.IdentityInterface(fields=['anat_file_BET', 'anat_file']), name='inputnode') # register node register = pe.Node(niu.Function( input_names=[ "anat_file", "anat_file_BET", "template_brain_file", "template_mask_file", 'n_iter' ], output_names=["anat_file_brain", "template_to_anat_file"], function=interative_flirt), name="register") register.inputs.template_brain_file = template_brain_file register.inputs.template_mask_file = template_mask_file register.inputs.n_iter = n_iter register_pipe.connect(inputnode, 'anat_file', register, 'anat_file') register_pipe.connect(inputnode, 'anat_file_BET', register, "anat_file_BET") # apply transfo over the 3 tissues: # gm register_gm = pe.Node(fsl.ApplyXFM(), name="register_gm") register_gm.inputs.in_file = gm_prob_file register_gm.inputs.apply_xfm = True register_gm.inputs.interp = "nearestneighbour" register_gm.inputs.output_type = "NIFTI" # for SPM segment register_pipe.connect(register, 'anat_file_brain', register_gm, 'reference') register_pipe.connect(register, 'template_to_anat_file', register_gm, "in_matrix_file") # wm register_wm = pe.Node(fsl.ApplyXFM(), name="register_wm") register_wm.inputs.in_file = wm_prob_file register_wm.inputs.apply_xfm = True register_wm.inputs.interp = "nearestneighbour" register_wm.inputs.output_type = "NIFTI" # for SPM segment register_pipe.connect(register, 'anat_file_brain', register_wm, 'reference') register_pipe.connect(register, 'template_to_anat_file', register_wm, "in_matrix_file") # csf register_csf = pe.Node(fsl.ApplyXFM(), name="register_csf") register_csf.inputs.in_file = csf_prob_file register_csf.inputs.apply_xfm = True register_csf.inputs.interp = "nearestneighbour" register_csf.inputs.output_type = "NIFTI" # for SPM segment register_pipe.connect(register, 'anat_file_brain', register_csf, 'reference') register_pipe.connect(register, 'template_to_anat_file', register_csf, "in_matrix_file") def return_list(file1, file2, file3): return [file1, file2, file3] # merge 3 outputs to a list (...) merge_3_files = pe.Node(niu.Function( input_names=["file1", "file2", "file3"], output_names=["list3files"], function=return_list), name="merge_3_files") register_pipe.connect(register_gm, 'out_file', merge_3_files, "file1") register_pipe.connect(register_wm, 'out_file', merge_3_files, "file2") register_pipe.connect(register_csf, 'out_file', merge_3_files, "file3") # same with non linear # non linear register between anat and head # (FNIRT work directly on head? # I thought FLIRT was only skull-stripped brain, is it different? ) nl_register = pe.Node(fsl.FNIRT(), name="nl_register") nl_register.inputs.in_file = template_file register_pipe.connect(inputnode, 'anat_file', nl_register, 'ref_file') register_pipe.connect(register, 'template_to_anat_file', nl_register, 'affine_file') # apply non linear warp to NMT_SS nl_apply = pe.Node(fsl.ApplyWarp(), name="nl_apply") nl_apply.inputs.in_file = template_brain_file register_pipe.connect(inputnode, 'anat_file', nl_apply, 'ref_file') register_pipe.connect(nl_register, 'fieldcoeff_file', nl_apply, 'field_file') # iout from fnirt return register_pipe