Source code for macapype.pipelines.surface


import nipype.interfaces.utility as niu
import nipype.pipeline.engine as pe

import nipype.interfaces.fsl as fsl
import nipype.interfaces.afni as afni
import nipype.interfaces.freesurfer as fs

import macapype.nodes.register as reg
from macapype.nodes.surface import Meshify, split_LR_mask
from macapype.utils.utils_nodes import parse_key, NodeParams


[docs]def _create_split_hemi_pipe(params, params_template, name="split_hemi_pipe"): """Description: Split segmentated tissus according hemisheres after \ removal of cortical structure Processing steps: - TODO Params: - None so far Inputs: inputnode: warpinv_file: non-linear transformation (from NMT_subject_align) inv_transfo_file: inverse transformation aff_file: affine transformation file t1_ref_file: preprocessd T1 segmented_file: from atropos segmentation, with all the tissues segmented arguments: params: dictionary of node sub-parameters (from a json file) name: pipeline name (default = "split_hemi_pipe") Outputs: """ split_hemi_pipe = pe.Workflow(name=name) # creating inputnode inputnode = pe.Node( niu.IdentityInterface(fields=['warpinv_file', 'inv_transfo_file', 'aff_file', 't1_ref_file', 'segmented_file']), name='inputnode') # get values if "cereb_template" in params_template.keys(): cereb_template_file = params_template["cereb_template"] # ### cereb # Binarize cerebellum bin_cereb = pe.Node(interface=fsl.UnaryMaths(), name='bin_cereb') bin_cereb.inputs.operation = "bin" bin_cereb.inputs.in_file = cereb_template_file # Warp cereb brainmask to subject space warp_cereb = pe.Node(interface=reg.NwarpApplyPriors(), name='warp_cereb') warp_cereb.inputs.in_file = cereb_template_file warp_cereb.inputs.out_file = cereb_template_file warp_cereb.inputs.interp = "NN" warp_cereb.inputs.args = "-overwrite" split_hemi_pipe.connect(bin_cereb, 'out_file', warp_cereb, 'in_file') split_hemi_pipe.connect(inputnode, 'aff_file', warp_cereb, 'master') split_hemi_pipe.connect(inputnode, 'warpinv_file', warp_cereb, "warp") # Align cereb template align_cereb = pe.Node(interface=afni.Allineate(), name='align_cereb') align_cereb.inputs.final_interpolation = "nearestneighbour" align_cereb.inputs.overwrite = True align_cereb.inputs.outputtype = "NIFTI_GZ" split_hemi_pipe.connect(warp_cereb, 'out_file', align_cereb, "in_file") # -source split_hemi_pipe.connect(inputnode, 't1_ref_file', align_cereb, "reference") # -base split_hemi_pipe.connect(inputnode, 'inv_transfo_file', align_cereb, "in_matrix") # -1Dmatrix_apply if "L_hemi_template" in params_template.keys() and \ "R_hemi_template" in params_template.keys(): L_hemi_template_file = params_template["L_hemi_template"] R_hemi_template_file = params_template["R_hemi_template"] # Warp L hemi template brainmask to subject space warp_L_hemi = pe.Node(interface=reg.NwarpApplyPriors(), name='warp_L_hemi') warp_L_hemi.inputs.in_file = L_hemi_template_file warp_L_hemi.inputs.out_file = L_hemi_template_file warp_L_hemi.inputs.interp = "NN" warp_L_hemi.inputs.args = "-overwrite" split_hemi_pipe.connect(inputnode, 'aff_file', warp_L_hemi, 'master') split_hemi_pipe.connect(inputnode, 'warpinv_file', warp_L_hemi, "warp") # Align L hemi template align_L_hemi = pe.Node(interface=afni.Allineate(), name='align_L_hemi') align_L_hemi.inputs.final_interpolation = "nearestneighbour" align_L_hemi.inputs.overwrite = True align_L_hemi.inputs.outputtype = "NIFTI_GZ" split_hemi_pipe.connect(warp_L_hemi, 'out_file', align_L_hemi, "in_file") # -source split_hemi_pipe.connect(inputnode, 't1_ref_file', align_L_hemi, "reference") # -base split_hemi_pipe.connect(inputnode, 'inv_transfo_file', align_L_hemi, "in_matrix") # -1Dmatrix_apply # Warp R hemi template brainmask to subject space warp_R_hemi = pe.Node(interface=reg.NwarpApplyPriors(), name='warp_R_hemi') warp_R_hemi.inputs.in_file = R_hemi_template_file warp_R_hemi.inputs.out_file = R_hemi_template_file warp_R_hemi.inputs.interp = "NN" warp_R_hemi.inputs.args = "-overwrite" split_hemi_pipe.connect(inputnode, 'aff_file', warp_R_hemi, 'master') split_hemi_pipe.connect(inputnode, 'warpinv_file', warp_R_hemi, "warp") # Align R hemi template align_R_hemi = pe.Node(interface=afni.Allineate(), name='align_R_hemi') align_R_hemi.inputs.final_interpolation = "nearestneighbour" align_R_hemi.inputs.overwrite = True align_R_hemi.inputs.outputtype = "NIFTI_GZ" split_hemi_pipe.connect(warp_R_hemi, 'out_file', align_R_hemi, "in_file") # -source split_hemi_pipe.connect(inputnode, 't1_ref_file', align_R_hemi, "reference") # -base split_hemi_pipe.connect(inputnode, 'inv_transfo_file', align_R_hemi, "in_matrix") # -1Dmatrix_apply elif "LR_hemi_template" in params_template.keys(): LR_hemi_template_file = params_template["LR_hemi_template"] # Warp LR hemi template brainmask to subject space warp_LR_hemi = pe.Node(interface=reg.NwarpApplyPriors(), name='warp_LR_hemi') warp_LR_hemi.inputs.in_file = LR_hemi_template_file warp_LR_hemi.inputs.out_file = LR_hemi_template_file warp_LR_hemi.inputs.interp = "NN" warp_LR_hemi.inputs.args = "-overwrite" split_hemi_pipe.connect(inputnode, 'aff_file', warp_LR_hemi, 'master') split_hemi_pipe.connect(inputnode, 'warpinv_file', warp_LR_hemi, "warp") # Align LR hemi template align_LR_hemi = pe.Node(interface=afni.Allineate(), name='align_LR_hemi') align_LR_hemi.inputs.final_interpolation = "nearestneighbour" align_LR_hemi.inputs.overwrite = True align_LR_hemi.inputs.outputtype = "NIFTI_GZ" split_hemi_pipe.connect(warp_LR_hemi, 'out_file', align_LR_hemi, "in_file") # -source split_hemi_pipe.connect(inputnode, 't1_ref_file', align_LR_hemi, "reference") # -base split_hemi_pipe.connect(inputnode, 'inv_transfo_file', align_LR_hemi, "in_matrix") # -1Dmatrix_apply split_LR = pe.Node( interface=niu.Function( input_names=["LR_mask_file"], output_names=["L_mask_file", "R_mask_file"], function=split_LR_mask), name="split_LR") split_hemi_pipe.connect(align_LR_hemi, "out_file", split_LR, 'LR_mask_file') else: print("Error, could not find LR_hemi_template or L_hemi_template and \ R_hemi_template, skipping") print(params_template.keys()) exit() # Using LH and RH masks to obtain hemisphere segmentation masks calc_L_hemi = pe.Node(interface=afni.Calc(), name='calc_L_hemi') calc_L_hemi.inputs.expr = 'a*b/b' calc_L_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 'segmented_file', calc_L_hemi, "in_file_a") if "LR_hemi_template" in params_template.keys(): split_hemi_pipe.connect(split_LR, 'L_mask_file', calc_L_hemi, "in_file_b") else: split_hemi_pipe.connect(align_L_hemi, 'out_file', calc_L_hemi, "in_file_b") # R_hemi calc_R_hemi = pe.Node(interface=afni.Calc(), name='calc_R_hemi') calc_R_hemi.inputs.expr = 'a*b/b' calc_R_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 'segmented_file', calc_R_hemi, "in_file_a") if "LR_hemi_template" in params_template.keys(): split_hemi_pipe.connect(split_LR, 'R_mask_file', calc_R_hemi, "in_file_b") else: split_hemi_pipe.connect(align_R_hemi, 'out_file', calc_R_hemi, "in_file_b") # remove cerebellum from left and right brain segmentations calc_nocb_L_hemi = pe.Node(interface=afni.Calc(), name='calc_nocb_L_hemi') calc_nocb_L_hemi.inputs.expr = '(a*(not (b)))' calc_nocb_L_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_L_hemi, 'out_file', calc_nocb_L_hemi, "in_file_a") split_hemi_pipe.connect(align_cereb, 'out_file', calc_nocb_L_hemi, "in_file_b") calc_nocb_R_hemi = pe.Node(interface=afni.Calc(), name='calc_nocb_R_hemi') calc_nocb_R_hemi.inputs.expr = '(a*(not (b)))' calc_nocb_R_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_R_hemi, 'out_file', calc_nocb_R_hemi, "in_file_a") split_hemi_pipe.connect(align_cereb, 'out_file', calc_nocb_R_hemi, "in_file_b") # create L/R GM and WM no-cerebellum masks from subject brain segmentation calc_GM_nocb_L_hemi = pe.Node(interface=afni.Calc(), name='calc_GM_nocb_L_hemi') calc_GM_nocb_L_hemi.inputs.expr = 'iszero(a-2)' calc_GM_nocb_L_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_nocb_L_hemi, 'out_file', calc_GM_nocb_L_hemi, "in_file_a") calc_WM_nocb_L_hemi = pe.Node(interface=afni.Calc(), name='calc_WM_nocb_L_hemi') calc_WM_nocb_L_hemi.inputs.expr = 'iszero(a-3)' calc_WM_nocb_L_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_nocb_L_hemi, 'out_file', calc_WM_nocb_L_hemi, "in_file_a") calc_GM_nocb_R_hemi = pe.Node(interface=afni.Calc(), name='calc_GM_nocb_R_hemi') calc_GM_nocb_R_hemi.inputs.expr = 'iszero(a-2)' calc_GM_nocb_R_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_nocb_R_hemi, 'out_file', calc_GM_nocb_R_hemi, "in_file_a") calc_WM_nocb_R_hemi = pe.Node(interface=afni.Calc(), name='calc_WM_nocb_R_hemi') calc_WM_nocb_R_hemi.inputs.expr = 'iszero(a-3)' calc_WM_nocb_R_hemi.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(calc_nocb_R_hemi, 'out_file', calc_WM_nocb_R_hemi, "in_file_a") # Extract Cerebellum using template mask transformed to subject space extract_cereb = pe.Node(interface=afni.Calc(), name='extract_cereb') extract_cereb.inputs.expr = 'a*b/b' extract_cereb.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 't1_ref_file', extract_cereb, "in_file_a") split_hemi_pipe.connect(align_cereb, 'out_file', extract_cereb, "in_file_b") # Extract L.GM using template mask transformed to subject space extract_L_GM = pe.Node(interface=afni.Calc(), name='extract_L_GM') extract_L_GM.inputs.expr = 'a*b/b' extract_L_GM.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 't1_ref_file', extract_L_GM, "in_file_a") split_hemi_pipe.connect(calc_GM_nocb_L_hemi, 'out_file', extract_L_GM, "in_file_b") # Extract L.WM using template mask transformed to subject space extract_L_WM = pe.Node(interface=afni.Calc(), name='extract_L_WM') extract_L_WM.inputs.expr = 'a*b/b' extract_L_WM.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 't1_ref_file', extract_L_WM, "in_file_a") split_hemi_pipe.connect(calc_WM_nocb_L_hemi, 'out_file', extract_L_WM, "in_file_b") # Extract L.GM using template mask transformed to subject space extract_R_GM = pe.Node(interface=afni.Calc(), name='extract_R_GM') extract_R_GM.inputs.expr = 'a*b/b' extract_R_GM.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 't1_ref_file', extract_R_GM, "in_file_a") split_hemi_pipe.connect(calc_GM_nocb_R_hemi, 'out_file', extract_R_GM, "in_file_b") # Extract L.WM using template mask transformed to subject space extract_R_WM = pe.Node(interface=afni.Calc(), name='extract_R_WM') extract_R_WM.inputs.expr = 'a*b/b' extract_R_WM.inputs.outputtype = 'NIFTI_GZ' split_hemi_pipe.connect(inputnode, 't1_ref_file', extract_R_WM, "in_file_a") split_hemi_pipe.connect(calc_WM_nocb_R_hemi, 'out_file', extract_R_WM, "in_file_b") return split_hemi_pipe
[docs]def create_nii_to_mesh_pipe(params, params_template, name="nii_to_mesh_pipe"): """ Description: basic nii to mesh pipeline after segmentation Processing steps: - split in hemisphere after removal of the subcortical structures - using scipy marching cube methods to compute mesh - some smoothing (using brain-slam) Params: - split_hemi_pipe (see :class:`_create_split_hemi_pipe \ <macapype.pipelines.surface._create_split_hemi_pipe>` for arguments) - mesh_L_GM, mesh_R_GM, mesh_L_WM, mesh_R_WM (see :class:`Meshify \ <macapype.nodes.surface.Meshify>` for arguments) Inputs: inputnode: warpinv_file: non-linear transformation (from NMT_subject_align) inv_transfo_file: inverse transformation aff_file: affine transformation file t1_ref_file: preprocessd T1 segmented_file: from atropos segmentation, with all the tissues segmented arguments: params: dictionary of node sub-parameters (from a json file) name: pipeline name (default = "nii_to_mesh_pipe") Outputs: """ # creating pipeline mesh_to_seg_pipe = pe.Workflow(name=name) # creating inputnode inputnode = pe.Node( niu.IdentityInterface(fields=['warpinv_file', 'inv_transfo_file', 'aff_file', 't1_ref_file', 'segmented_file']), name='inputnode') # split hemi pipe (+ cerebellum) split_hemi_pipe = _create_split_hemi_pipe( params=parse_key(params, "split_hemi_pipe"), params_template=params_template) mesh_to_seg_pipe.connect(inputnode, 'warpinv_file', split_hemi_pipe, 'inputnode.warpinv_file') mesh_to_seg_pipe.connect(inputnode, 'inv_transfo_file', split_hemi_pipe, 'inputnode.inv_transfo_file') mesh_to_seg_pipe.connect(inputnode, 'aff_file', split_hemi_pipe, 'inputnode.aff_file') mesh_to_seg_pipe.connect(inputnode, 't1_ref_file', split_hemi_pipe, 'inputnode.t1_ref_file') mesh_to_seg_pipe.connect(inputnode, 'segmented_file', split_hemi_pipe, 'inputnode.segmented_file') # meshify L GM hemisphere mesh_L_GM = NodeParams(interface=Meshify(), params=parse_key(params, "mesh_L_GM"), name="mesh_L_GM") mesh_to_seg_pipe.connect(split_hemi_pipe, 'extract_L_GM.out_file', mesh_L_GM, "image_file") # meshify R GM hemisphere mesh_R_GM = NodeParams(interface=Meshify(), params=parse_key(params, "mesh_R_GM"), name="mesh_R_GM") mesh_to_seg_pipe.connect(split_hemi_pipe, 'extract_R_GM.out_file', mesh_R_GM, "image_file") # meshify L WM hemisphere mesh_L_WM = NodeParams(interface=Meshify(), params=parse_key(params, "mesh_L_WM"), name="mesh_L_WM") mesh_to_seg_pipe.connect(split_hemi_pipe, 'extract_L_WM.out_file', mesh_L_WM, "image_file") # meshify R WM hemisphere mesh_R_WM = NodeParams(interface=Meshify(), params=parse_key(params, "mesh_R_WM"), name="mesh_R_WM") mesh_to_seg_pipe.connect(split_hemi_pipe, 'extract_R_WM.out_file', mesh_R_WM, "image_file") return mesh_to_seg_pipe
############################################################################### # using freesurfer tools to build the mesh through tesselation
[docs]def create_nii_to_mesh_fs_pipe(params, name="nii_to_mesh_fs_pipe"): """ Description: surface generation using freesurfer tools Params: - fill_wm (see `MRIFill <https://nipype.readthedocs.io/en/0.12.1/\ interfaces/generated/nipype.interfaces.freesurfer.utils.html#mrifill>`_) \ - also available as :ref:`indiv_params <indiv_params>` Inputs: inputnode: wm_mask_file: segmented white matter mask (binary) in template space reg_brain_file: preprocessd T1, registered to template indiv_params (opt): dict with individuals parameters for some nodes arguments: params: dictionary of node sub-parameters (from a json file) name: pipeline name (default = "nii_to_mesh_fs_pipe") Outputs: """ # creating pipeline nii_to_mesh_fs_pipe = pe.Workflow(name=name) # creating inputnode inputnode = pe.Node( niu.IdentityInterface(fields=['wm_mask_file', 'reg_brain_file', 'indiv_params']), name='inputnode') # bin_wm bin_wm = pe.Node(interface=fsl.UnaryMaths(), name="bin_wm") bin_wm.inputs.operation = "fillh" nii_to_mesh_fs_pipe.connect(inputnode, 'wm_mask_file', bin_wm, 'in_file') # resample everything refit_wm = pe.Node(interface=afni.Refit(), name="refit_wm") refit_wm.inputs.args = "-xdel 1.0 -ydel 1.0 -zdel 1.0 -keepcen" nii_to_mesh_fs_pipe.connect(bin_wm, 'out_file', refit_wm, 'in_file') # resample everything refit_reg = pe.Node(interface=afni.Refit(), name="refit_reg") refit_reg.inputs.args = "-xdel 1.0 -ydel 1.0 -zdel 1.0 -keepcen" nii_to_mesh_fs_pipe.connect(inputnode, 'reg_brain_file', refit_reg, 'in_file') # mri_convert wm to freesurfer mgz convert_wm = pe.Node(interface=fs.MRIConvert(), name="convert_wm") convert_wm.inputs.out_type = "mgz" convert_wm.inputs.conform = True nii_to_mesh_fs_pipe.connect(refit_wm, 'out_file', convert_wm, 'in_file') # mri_convert reg to freesurfer mgz convert_reg = pe.Node(interface=fs.MRIConvert(), name="convert_reg") convert_reg.inputs.out_type = "mgz" convert_reg.inputs.conform = True nii_to_mesh_fs_pipe.connect(refit_reg, 'out_file', convert_reg, 'in_file') # mri_fill fill_wm = NodeParams(interface=fs.MRIFill(), params=parse_key(params, "fill_wm"), name="fill_wm") fill_wm.inputs.out_file = "filled.mgz" nii_to_mesh_fs_pipe.connect(convert_wm, 'out_file', fill_wm, 'in_file') nii_to_mesh_fs_pipe.connect( inputnode, ("indiv_params", parse_key, "fill_wm"), fill_wm, 'indiv_params') # pretesselate wm pretess_wm = pe.Node(interface=fs.MRIPretess(), name="pretess_wm") pretess_wm.inputs.label = 255 nii_to_mesh_fs_pipe.connect(fill_wm, 'out_file', pretess_wm, 'in_filled') nii_to_mesh_fs_pipe.connect(convert_reg, 'out_file', pretess_wm, 'in_norm') # tesselate wm lh tess_wm_lh = pe.Node(interface=fs.MRITessellate(), name="tess_wm_lh") tess_wm_lh.inputs.label_value = 255 tess_wm_lh.inputs.out_file = "lh_tess" nii_to_mesh_fs_pipe.connect(pretess_wm, 'out_file', tess_wm_lh, 'in_file') # tesselate wm rh tess_wm_rh = pe.Node(interface=fs.MRITessellate(), name="tess_wm_rh") tess_wm_rh.inputs.label_value = 127 tess_wm_rh.inputs.out_file = "rh_tess" nii_to_mesh_fs_pipe.connect(pretess_wm, 'out_file', tess_wm_rh, 'in_file') # ExtractMainComponent lh extract_mc_lh = pe.Node(interface=fs.ExtractMainComponent(), name="extract_mc_lh") nii_to_mesh_fs_pipe.connect(tess_wm_lh, 'surface', extract_mc_lh, 'in_file') extract_mc_lh.inputs.out_file = "lh.lh_tess.maincmp" # ExtractMainComponent rh extract_mc_rh = pe.Node(interface=fs.ExtractMainComponent(), name="extract_mc_rh") nii_to_mesh_fs_pipe.connect(tess_wm_rh, 'surface', extract_mc_rh, 'in_file') extract_mc_rh.inputs.out_file = "rh.rh_tess.maincmp" # SmoothTessellation lh smooth_tess_lh = pe.Node(interface=fs.SmoothTessellation(), name="smooth_tess_lh") smooth_tess_lh.inputs.disable_estimates = True nii_to_mesh_fs_pipe.connect(extract_mc_lh, 'out_file', smooth_tess_lh, 'in_file') # SmoothTessellation rh smooth_tess_rh = pe.Node(interface=fs.SmoothTessellation(), name="smooth_tess_rh") smooth_tess_rh.inputs.disable_estimates = True nii_to_mesh_fs_pipe.connect(extract_mc_rh, 'out_file', smooth_tess_rh, 'in_file') return nii_to_mesh_fs_pipe