Source code for cmp.stages.registration.registration

# Copyright (C) 2009-2021, Ecole Polytechnique Federale de Lausanne (EPFL) and
# Hospital Center and University of Lausanne (UNIL-CHUV), Switzerland, and CMP3 contributors
# All rights reserved.
#
#  This software is distributed under the open-source license Modified BSD.

"""Definition of config and stage classes for MRI co-registration"""

# General imports
import os
from traits.api import *

# Nipype imports
import nipype.interfaces.utility as util
import nipype.pipeline.engine as pe
import nipype.interfaces.freesurfer as fs
import nipype.interfaces.fsl as fsl
from nipype.interfaces.mrtrix3.utils import TensorMetrics
import nipype.interfaces.ants as ants

# Own imports
from cmp.stages.common import Stage
from cmtklib.interfaces.mrtrix3 import DWI2Tensor, MRConvert, ExtractMRTrixGrad
from cmtklib.interfaces.fsl import ApplymultipleXfm, ApplymultipleWarp
import cmtklib.interfaces.freesurfer as cmp_fs
import cmtklib.interfaces.fsl as cmp_fsl
from cmtklib.interfaces.ants import MultipleANTsApplyTransforms
from cmtklib.util import get_pipeline_dictionary_outputs


[docs]class RegistrationConfig(HasTraits): """Class used to store configuration parameters of a :class:`~cmp.stages.registration.registration.RegistrationStage` instance. Attributes ---------- pipeline : traits.Enum(["Diffusion", "fMRI"]) Pipeline type (Default: "Diffusion") registration_mode_trait : traits.List(['FSL', 'ANTs', 'BBregister (FS)']) Choices of registration tools updated depending on the ``pipeline`` type. (Default: ['FSL', 'ANTs'] if "Diffusion", ['FSL', 'BBregister (FS)'] if "fMRI") registration_mode : traits.Str Registration tool used from the `registration_mode_trait` list (Default: 'ANTs') diffusion_imaging_model : traits.Str Diffusion imaging model ('DTI' for instance) use_float_precision : traits.Bool Use 'single' instead of 'double' float representation to reduce memory usage of ANTs (Default: False) ants_interpolation : traits.Enum Interpolation type used by ANTs that can be: 'Linear', 'NearestNeighbor', 'CosineWindowedSinc', 'WelchWindowedSinc', 'HammingWindowedSinc', 'LanczosWindowedSinc', 'BSpline', 'MultiLabel', or 'Gaussian' (Default: 'Linear') ants_bspline_interpolation_parameters : traits.Tuple ANTs BSpline interpolation parameters (Default: traits.Tuple(Int(3))) ants_gauss_interpolation_parameters : traits.Tuple ANTs Gaussian interpolation parameters (Default: traits.Tuple(Float(5), Float(5))) ants_multilab_interpolation_parameters : traits.Tuple ANTs Multi-label interpolation parameters (Default: traits.Tuple(Float(5), Float(5))) ants_lower_quantile : traits.Float ANTs lower quantile (Default: 0.005) ants_upper_quantile : traits.Float ANTs upper quantile (Default: 0.995) ants_convergence_thresh : traits.Float ANTs convergence threshold (Default: 1e-06) ants_convergence_winsize : traits.Int ANTs convergence window size (Default: 10) ants_linear_gradient_step : traits.Float ANTS linear gradient step size (Default: 0.1) ants_linear_cost : traits.Enum Metric used by ANTs linear registration phase that can be 'CC', 'MeanSquares', 'Demons', 'GC', 'MI', or 'Mattes' (Default: 'MI') ants_linear_sampling_strategy : traits.Enum ANTS sampling strategy for the linear registration phase that can be 'None', 'Regular', or 'Random' (Default: 'Regular') ants_linear_sampling_perc : traits.Float Percentage used if random sampling strategy is employed in the linear registration phase (Default: 0.25) ants_perform_syn : traits.Bool (Default: True) ants_nonlinear_gradient_step : traits.Float (Default: 0.1) ants_nonlinear_cost : traits.Enum Metric used by ANTs nonlinear (SyN) registration phase that can be 'CC', 'MeanSquares', 'Demons', 'GC', 'MI', or 'Mattes' (Default: 'CC') ants_nonlinear_update_field_variance : traits.Float Weight to update field variance in ANTs nonlinear (SyN) registration phase (Default: 3.0) ants_nonlinear_total_field_variance : traits.Float Weight to give to total field variance in ANTs nonlinear (SyN) registration phase (Default: 0.0) flirt_args : traits.Str FLIRT extra arguments that will be append to the FSL FLIRT command (Default: None) uses_qform : traits.Bool FSL FLIRT uses qform (Default: True) dof : traits.Int Specify number of degree-of-freedom to FSL FLIRT (Default: 6) fsl_cost : traits.Enum Metric used by FSL registration that can be 'mutualinfo', 'corratio', 'normcorr', 'normmi', 'leastsq', or 'labeldiff' (Default: 'normmi') no_search : traits.Bool Enable FSL FLIRT "no search" option (Default: True) init : traits.Enum('header', ['spm', 'fsl', 'header']) Initialization type of FSL registration: 'spm', 'fsl', or 'header' (Default: 'smp') contrast_type : traits.Enum('dti', ['t1', 't2', 'dti']) Contrast type specified to BBRegister: 't1', 't2', or 'dti' (Default: 'dti') apply_to_eroded_wm : traits.Bool Apply estimated transform to eroded white-matter mask (Default: True) apply_to_eroded_csf : traits.Bool Apply estimated transform to eroded cortico spinal fluid mask (Default: True) apply_to_eroded_brain : traits.Bool Apply estimated transform to eroded brain mask (Default: False) See Also -------- cmp.stages.registration.registration.RegistrationStage """ # Pipeline mode pipeline = Enum(["Diffusion", "fMRI"]) # Registration selection registration_mode = Str('ANTs') # Str('FSL') registration_mode_trait = List(['FSL', 'ANTs']) # ,'BBregister (FS)']) diffusion_imaging_model = Str use_float_precision = Bool(False) # ANTS ants_interpolation = Enum('Linear', ['Linear', 'NearestNeighbor', 'CosineWindowedSinc', 'WelchWindowedSinc', 'HammingWindowedSinc', 'LanczosWindowedSinc', 'BSpline', 'MultiLabel', 'Gaussian']) ants_bspline_interpolation_parameters = Tuple(Int(3)) ants_gauss_interpolation_parameters = Tuple(Float(5), Float(5)) ants_multilab_interpolation_parameters = Tuple(Float(5), Float(5)) ants_lower_quantile = Float(0.005) ants_upper_quantile = Float(0.995) ants_convergence_thresh = Float(1e-06) ants_convergence_winsize = Int(10) ants_linear_gradient_step = Float(0.1) ants_linear_cost = Enum( 'MI', ['CC', 'MeanSquares', 'Demons', 'GC', 'MI', 'Mattes']) ants_linear_sampling_perc = Float(0.25) ants_linear_sampling_strategy = Enum( 'Regular', ['None', 'Regular', 'Random']) ants_perform_syn = Bool(True) ants_nonlinear_gradient_step = Float(0.1) ants_nonlinear_cost = Enum( 'CC', ['CC', 'MeanSquares', 'Demons', 'GC', 'MI', 'Mattes']) ants_nonlinear_update_field_variance = Float(3.0) ants_nonlinear_total_field_variance = Float(0.0) # FLIRT flirt_args = Str uses_qform = Bool(True) dof = Int(6) fsl_cost = Enum('normmi', ['mutualinfo', 'corratio', 'normcorr', 'normmi', 'leastsq', 'labeldiff']) no_search = Bool(True) # BBRegister init = Enum('header', ['spm', 'fsl', 'header']) contrast_type = Enum('dti', ['t1', 't2', 'dti']) # Apply transform apply_to_eroded_wm = Bool(True) apply_to_eroded_csf = Bool(True) apply_to_eroded_brain = Bool(False)
[docs]def unicode2str(text): """Convert a unicode to a string using system's encoding. (This methods should be moved to utils in the upcoming future.) Parameters ---------- text : bytes Unicode bytes representation of a string Returns ------- out_str : str Output string """ out_str = str(text) return out_str
[docs]class RegistrationStage(Stage): """Class that represents the registration stage of both `DiffusionPipeline` and `fMRIPipeline`. Attributes ---------- fs_subjects_dir : traits.Directory Freesurfer subjects directory (needed by BBRegister) fs_subject_id : traits.Str Freesurfer subject (being processed) directory (needed by BBRegister) Methods ------- create_workflow() Create the workflow of the `RegistrationStage` See Also -------- cmp.pipelines.diffusion.diffusion.DiffusionPipeline cmp.pipelines.functional.fMRI.fMRIPipeline cmp.stages.registration.registration.RegistrationConfig """ # Freesurfer informations (for BBregister) fs_subjects_dir = Directory(exists=False, resolve=False, mandatory=False) fs_subject_id = Str(mandatory=False) def __init__(self, pipeline_mode, fs_subjects_dir=None, fs_subject_id=None, bids_dir="", output_dir=""): """Constructor of a :class:`~cmp.stages.registration.registration.RegistrationStage` instance.""" self.name = 'registration_stage' self.bids_dir = bids_dir self.output_dir = output_dir self.config = RegistrationConfig() self.config.pipeline = pipeline_mode if pipeline_mode == 'fMRI': self.config.registration_mode = 'FSL (Linear)' self.config.registration_mode_trait = [ 'FSL (Linear)', 'BBregister (FS)'] if fs_subjects_dir is not None: self.fs_subjects_dir = fs_subjects_dir if fs_subject_id is not None: self.fs_subject_id = fs_subject_id self.inputs = ["T1", "act_5TT", "gmwmi", "target", "T2", "subjects_dir", "subject_id", "wm_mask", "partial_volume_files", "roi_volumes", "brain", "brain_mask", "brain_mask_full", "target_mask", "bvecs", "bvals"] self.outputs = ["T1_registered_crop", "act_5tt_registered_crop", "affine_transform", "warp_field", "gmwmi_registered_crop", "brain_registered_crop", "brain_mask_registered_crop", "wm_mask_registered_crop", "partial_volumes_registered_crop", "roi_volumes_registered_crop", "target_epicorrected", "grad", "bvecs", "bvals"] if self.config.pipeline == "fMRI": self.inputs = self.inputs + \ ["eroded_csf", "eroded_wm", "eroded_brain"] self.outputs = self.outputs + ["eroded_wm_registered_crop", "eroded_csf_registered_crop", "eroded_brain_registered_crop"]
[docs] def create_workflow(self, flow, inputnode, outputnode): """Create the stage worflow. Parameters ---------- flow : nipype.pipeline.engine.Workflow The nipype.pipeline.engine.Workflow instance of either the Diffusion pipeline or the fMRI pipeline inputnode : nipype.interfaces.utility.IdentityInterface Identity interface describing the inputs of the stage outputnode : nipype.interfaces.utility.IdentityInterface Identity interface describing the outputs of the stage """ # Extract first volume and resample it to 1x1x1mm3 if self.config.pipeline == "Diffusion": extract_first = pe.Node(interface=fsl.ExtractROI(t_min=0, t_size=1, roi_file='first.nii.gz'), name='extract_first') flow.connect([ (inputnode, extract_first, [("target", "in_file")]) ]) fs_mriconvert = pe.Node(interface=fs.MRIConvert(out_file="target_first.nii.gz", vox_size=(1, 1, 1)), name="target_resample") flow.connect( [(extract_first, fs_mriconvert, [('roi_file', 'in_file')])]) elif self.config.pipeline == "fMRI": fmri_bet = pe.Node(interface=fsl.BET(), name="fMRI_skullstrip") T1_bet = pe.Node(interface=fsl.BET(), name="T1_skullstrip") flow.connect([ (inputnode, fmri_bet, [("target", "in_file")]), (inputnode, T1_bet, [("T1", "in_file")]) ]) if self.config.registration_mode == 'FSL': # [SUB-STEP 1] Linear register "T1" onto"Target_FA_resampled" # [1.1] Convert diffusion data to mrtrix format using rotated bvecs mr_convert = pe.Node(interface=MRConvert(out_filename='diffusion.mif', stride=[+1, +2, +3, +4]), name='mr_convert') mr_convert.inputs.quiet = True mr_convert.inputs.force_writing = True concatnode = pe.Node(interface=util.Merge(2), name='concatnode') def convertList2Tuple(lists): """Convert list of files to tuple of files. (Duplicated with preprocessing, could be moved to utils in the future) Parameters ---------- lists : [bvecs, bvals] List of files containing bvecs and bvals Returns ------- out_tuple : (bvecs, bvals) Tuple of files containing bvecs and bvals """ out_tuple = tuple(lists) return out_tuple flow.connect([ (inputnode, concatnode, [('bvecs', 'in1')]), (inputnode, concatnode, [('bvals', 'in2')]), (concatnode, mr_convert, [ (('out', convertList2Tuple), 'grad_fsl')]), (inputnode, mr_convert, [('target', 'in_file')]) ]) grad_mrtrix = pe.Node(ExtractMRTrixGrad( out_grad_mrtrix='grad.txt'), name='extract_grad') flow.connect([ (mr_convert, grad_mrtrix, [("converted", "in_file")]), (grad_mrtrix, outputnode, [("out_grad_mrtrix", "grad")]) ]) flow.connect([ (inputnode, outputnode, [("bvals", "bvals")]), (inputnode, outputnode, [("bvecs", "bvecs")]) ]) mr_convert_b0 = pe.Node(interface=MRConvert(out_filename='b0.nii.gz', stride=[+1, +2, +3]), name='mr_convert_b0') mr_convert_b0.inputs.extract_at_axis = 3 mr_convert_b0.inputs.extract_at_coordinate = [0] flow.connect([ (inputnode, mr_convert_b0, [('target', 'in_file')]) ]) dwi2tensor = pe.Node(interface=DWI2Tensor( out_filename='dt_corrected.mif'), name='dwi2tensor') dwi2tensor_unmasked = pe.Node(interface=DWI2Tensor(out_filename='dt_corrected_unmasked.mif'), name='dwi2tensor_unmasked') tensor2FA = pe.Node(interface=TensorMetrics( out_fa='fa_corrected.mif'), name='tensor2FA') tensor2FA_unmasked = pe.Node(interface=TensorMetrics(out_fa='fa_corrected_unmasked.mif'), name='tensor2FA_unmasked') mr_convert_FA = pe.Node(interface=MRConvert(out_filename='fa_corrected.nii.gz', stride=[+1, +2, +3]), name='mr_convert_FA') mr_convert_FA_unmasked = pe.Node( interface=MRConvert( out_filename='fa_corrected_unmasked.nii.gz', stride=[+1, +2, +3]), name='mr_convert_FA_unmasked') FA_noNaN = pe.Node(interface=cmp_fsl.MathsCommand(out_file='fa_corrected_nonan.nii.gz', nan2zeros=True), name='FA_noNaN') FA_noNaN_unmasked = pe.Node( interface=cmp_fsl.MathsCommand( out_file='fa_corrected_unmasked_nonan.nii.gz', nan2zeros=True), name='FA_noNaN_unmasked') flow.connect([ (mr_convert, dwi2tensor, [('converted', 'in_file')]), (inputnode, dwi2tensor, [('target_mask', 'in_mask_file')]), (dwi2tensor, tensor2FA, [('tensor', 'in_file')]), (inputnode, tensor2FA, [('target_mask', 'in_mask')]), (tensor2FA, mr_convert_FA, [('out_fa', 'in_file')]), (mr_convert_FA, FA_noNaN, [('converted', 'in_file')]) ]) flow.connect([ (mr_convert, dwi2tensor_unmasked, [('converted', 'in_file')]), (dwi2tensor_unmasked, tensor2FA_unmasked, [('tensor', 'in_file')]), (tensor2FA_unmasked, mr_convert_FA_unmasked, [('out_fa', 'in_file')]), (mr_convert_FA_unmasked, FA_noNaN_unmasked, [('converted', 'in_file')]) ]) # [1.2] Linear registration of the DW data to the T1 data fsl_flirt = pe.Node(interface=fsl.FLIRT(out_file='T1-TO-B0.nii.gz', out_matrix_file='T12DWIaff.mat'), name="linear_registration") fsl_flirt.inputs.dof = self.config.dof fsl_flirt.inputs.cost = self.config.fsl_cost fsl_flirt.inputs.cost_func = self.config.fsl_cost fsl_flirt.inputs.no_search = self.config.no_search fsl_flirt.inputs.verbose = False flow.connect([ (inputnode, fsl_flirt, [('brain', 'in_file')]), (mr_convert_b0, fsl_flirt, [('converted', 'reference')]) ]) # [1.3] Transforming T1-space images to avoid rotation of bvecs T12DWIaff = pe.Node(interface=fsl.ConvertXFM( invert_xfm=False), name='T12DWIaff') flow.connect([ (fsl_flirt, T12DWIaff, [('out_matrix_file', 'in_file')]), (T12DWIaff, outputnode, [('out_file', 'affine_transform')]) ]) fsl_applyxfm_wm = pe.Node( interface=fsl.ApplyXFM( apply_xfm=True, interp="nearestneighbour", out_file="wm_mask_registered.nii.gz"), name="apply_registration_wm") fsl_applyxfm_rois = pe.Node( interface=ApplymultipleXfm(), name="apply_registration_roivs") fsl_applyxfm_brain_mask = pe.Node( interface=fsl.ApplyXFM( apply_xfm=True, interp="spline", out_file="brain_mask_registered_temp.nii.gz"), name="apply_registration_brain_mask") fsl_applyxfm_brain_mask_full = pe.Node(interface=fsl.ApplyXFM(apply_xfm=True, interp="spline", out_file="brain_mask_full_registered_temp.nii.gz"), name="apply_registration_brain_mask_full") fsl_applyxfm_brain = pe.Node( interface=fsl.ApplyXFM( apply_xfm=True, interp="spline", out_file="brain_registered.nii.gz"), name="apply_registration_brain") fsl_applyxfm_T1 = pe.Node( interface=fsl.ApplyXFM( apply_xfm=True, interp="spline", out_file="T1_registered.nii.gz"), name="apply_registration_T1") fsl_applyxfm_5tt = pe.Node( interface=fsl.ApplyXFM( apply_xfm=True, interp="spline", out_file="5tt_registered.nii.gz"), name="apply_registration_5tt") fsl_applyxfm_gmwmi = pe.Node( interface=fsl.ApplyXFM( apply_xfm=True, interp="spline", out_file="gmwmi_registered.nii.gz"), name="apply_registration_gmwmi") # fsl_create_HD = pe.Node(interface=FSLCreateHD(im_size=[256,256,256,1], # vox_size=[1,1,1],origin=[0,0,0], # tr=1,datatype='16',out_filename='tempref.nii.gz'), # name='fsl_create_HD') flow.connect([ (inputnode, fsl_applyxfm_wm, [('wm_mask', 'in_file')]), (T12DWIaff, fsl_applyxfm_wm, [('out_file', 'in_matrix_file')]), # (fsl_create_HD, fsl_applyxfm_wm, [('out_file','reference')]), (mr_convert_b0, fsl_applyxfm_wm, [('converted', 'reference')]), (inputnode, fsl_applyxfm_rois, [('roi_volumes', 'in_files')]), (T12DWIaff, fsl_applyxfm_rois, [('out_file', 'xfm_file')]), # (fsl_create_HD, fsl_applyxfm_rois, [('out_file','reference')]), (mr_convert_b0, fsl_applyxfm_rois, [('converted', 'reference')]), (inputnode, fsl_applyxfm_brain_mask, [('brain_mask', 'in_file')]), (T12DWIaff, fsl_applyxfm_brain_mask, [('out_file', 'in_matrix_file')]), # (fsl_create_HD, fsl_applyxfm_brain_mask, [('out_file','reference')]), (mr_convert_b0, fsl_applyxfm_brain_mask, [('converted', 'reference')]), (inputnode, fsl_applyxfm_brain_mask_full, [('brain_mask_full', 'in_file')]), (T12DWIaff, fsl_applyxfm_brain_mask_full, [('out_file', 'in_matrix_file')]), # (fsl_create_HD, fsl_applyxfm_brain_mask_full, [('out_file','reference')]), (mr_convert_b0, fsl_applyxfm_brain_mask_full, [('converted', 'reference')]), (inputnode, fsl_applyxfm_brain, [('brain', 'in_file')]), (T12DWIaff, fsl_applyxfm_brain, [ ('out_file', 'in_matrix_file')]), # (fsl_create_HD, fsl_applyxfm_brain, [('out_file','reference')]), (mr_convert_b0, fsl_applyxfm_brain, [('converted', 'reference')]), (inputnode, fsl_applyxfm_T1, [('T1', 'in_file')]), (T12DWIaff, fsl_applyxfm_T1, [('out_file', 'in_matrix_file')]), # (fsl_create_HD, fsl_applyxfm_T1, [('out_file','reference')]), (mr_convert_b0, fsl_applyxfm_T1, [('converted', 'reference')]), (inputnode, fsl_applyxfm_5tt, [('act_5TT', 'in_file')]), (T12DWIaff, fsl_applyxfm_5tt, [ ('out_file', 'in_matrix_file')]), (mr_convert_b0, fsl_applyxfm_5tt, [('converted', 'reference')]), (inputnode, fsl_applyxfm_gmwmi, [('gmwmi', 'in_file')]), (T12DWIaff, fsl_applyxfm_gmwmi, [ ('out_file', 'in_matrix_file')]), (mr_convert_b0, fsl_applyxfm_gmwmi, [('converted', 'reference')]), ]) flow.connect([ (fsl_applyxfm_brain_mask, outputnode, [ ('out_file', 'brain_mask_registered_crop')]), ]) fsl_fnirt_crop = pe.Node(interface=fsl.FNIRT( fieldcoeff_file=True), name='fsl_fnirt_crop') flow.connect([ (mr_convert_b0, fsl_fnirt_crop, [('converted', 'ref_file')]), (inputnode, fsl_fnirt_crop, [('brain', 'in_file')]), (fsl_flirt, fsl_fnirt_crop, [ ('out_matrix_file', 'affine_file')]), (fsl_fnirt_crop, outputnode, [ ('fieldcoeff_file', 'warp_field')]), # (inputnode, fsl_fnirt_crop, [('target_mask','refmask_file')]) ]) fsl_applywarp_T1 = pe.Node(interface=fsl.ApplyWarp(interp="spline", out_file="T1_warped.nii.gz"), name="apply_warp_T1") fsl_applywarp_5tt = pe.Node(interface=fsl.ApplyWarp(interp="spline", out_file="5tt_warped.nii.gz"), name="apply_warp_5tt") fsl_applywarp_gmwmi = pe.Node(interface=fsl.ApplyWarp(interp="spline", out_file="gmwmi_warped.nii.gz"), name="apply_warp_gmwmi") fsl_applywarp_brain = pe.Node(interface=fsl.ApplyWarp(interp="spline", out_file="brain_warped.nii.gz"), name="apply_warp_brain") fsl_applywarp_wm = pe.Node(interface=fsl.ApplyWarp(interp='nn', out_file="wm_mask_warped.nii.gz"), name="apply_warp_wm") fsl_applywarp_rois = pe.Node(interface=ApplymultipleWarp( interp='nn'), name="apply_warp_roivs") flow.connect([ (inputnode, fsl_applywarp_T1, [('T1', 'in_file')]), (inputnode, fsl_applywarp_T1, [('target', 'ref_file')]), (fsl_fnirt_crop, fsl_applywarp_T1, [ ('fieldcoeff_file', 'field_file')]), (fsl_applywarp_T1, outputnode, [ ('out_file', 'T1_registered_crop')]), ]) flow.connect([ (inputnode, fsl_applywarp_5tt, [('act_5TT', 'in_file')]), (inputnode, fsl_applywarp_5tt, [('target', 'ref_file')]), (fsl_fnirt_crop, fsl_applywarp_5tt, [ ('fieldcoeff_file', 'field_file')]), (fsl_applywarp_5tt, outputnode, [ ('out_file', 'act_5tt_registered_crop')]), ]) flow.connect([ (inputnode, fsl_applywarp_gmwmi, [('gmwmi', 'in_file')]), (inputnode, fsl_applywarp_gmwmi, [('target', 'ref_file')]), (fsl_fnirt_crop, fsl_applywarp_gmwmi, [('fieldcoeff_file', 'field_file')]), (fsl_applywarp_gmwmi, outputnode, [ ('out_file', 'gmwmi_registered_crop')]), ]) flow.connect([ (inputnode, fsl_applywarp_brain, [('brain', 'in_file')]), (inputnode, fsl_applywarp_brain, [('target', 'ref_file')]), (fsl_fnirt_crop, fsl_applywarp_brain, [('fieldcoeff_file', 'field_file')]), (fsl_applywarp_brain, outputnode, [ ('out_file', 'brain_registered_crop')]), ]) flow.connect([ (inputnode, fsl_applywarp_wm, [('wm_mask', 'in_file')]), (inputnode, fsl_applywarp_wm, [('target', 'ref_file')]), (fsl_fnirt_crop, fsl_applywarp_wm, [ ('fieldcoeff_file', 'field_file')]), (fsl_applywarp_wm, outputnode, [ ('out_file', 'wm_mask_registered_crop')]), ]) flow.connect([ (inputnode, fsl_applywarp_rois, [('roi_volumes', 'in_files')]), (inputnode, fsl_applywarp_rois, [('target', 'ref_file')]), (fsl_fnirt_crop, fsl_applywarp_rois, [ ('fieldcoeff_file', 'field_file')]), (fsl_applywarp_rois, outputnode, [ ('out_files', 'roi_volumes_registered_crop')]), ]) flow.connect([ (inputnode, outputnode, [('target', 'target_epicorrected')]), ]) elif self.config.registration_mode == 'ANTs': # [SUB-STEP 1] Linear register "T1" onto"Target_FA_resampled" # [1.1] Convert diffusion data to mrtrix format using rotated bvecs mr_convert = pe.Node(interface=MRConvert(out_filename='diffusion.mif', stride=[+1, +2, +3, +4]), name='mr_convert') mr_convert.inputs.quiet = True mr_convert.inputs.force_writing = True concatnode = pe.Node(interface=util.Merge(2), name='concatnode') def convertList2Tuple(lists): """Convert list of files to tuple of files. (Duplicated with preprocessing, and here line 355; could be moved to utils in the future) Parameters ---------- lists : [bvecs, bvals] List of files containing bvecs and bvals Returns ------- out_tuple : (bvecs, bvals) Tuple of files containing bvecs and bvals """ # print "******************************************",tuple(lists) return tuple(lists) flow.connect([ (inputnode, concatnode, [('bvecs', 'in1')]), (inputnode, concatnode, [('bvals', 'in2')]), (concatnode, mr_convert, [ (('out', convertList2Tuple), 'grad_fsl')]), (inputnode, mr_convert, [('target', 'in_file')]) ]) grad_mrtrix = pe.Node(ExtractMRTrixGrad( out_grad_mrtrix='grad.txt'), name='extract_grad') flow.connect([ (mr_convert, grad_mrtrix, [("converted", "in_file")]), (grad_mrtrix, outputnode, [("out_grad_mrtrix", "grad")]) ]) flow.connect([ (inputnode, outputnode, [("bvals", "bvals")]), (inputnode, outputnode, [("bvecs", "bvecs")]) ]) mr_convert_b0 = pe.Node(interface=MRConvert(out_filename='b0.nii.gz', stride=[+1, +2, +3]), name='mr_convert_b0') mr_convert_b0.inputs.extract_at_axis = 3 mr_convert_b0.inputs.extract_at_coordinate = [0] flow.connect([ (inputnode, mr_convert_b0, [('target', 'in_file')]) ]) dwi2tensor = pe.Node(interface=DWI2Tensor( out_filename='dt_corrected.mif'), name='dwi2tensor') dwi2tensor_unmasked = pe.Node(interface=DWI2Tensor(out_filename='dt_corrected_unmasked.mif'), name='dwi2tensor_unmasked') tensor2FA = pe.Node(interface=TensorMetrics( out_fa='fa_corrected.mif'), name='tensor2FA') tensor2FA_unmasked = pe.Node(interface=TensorMetrics(out_fa='fa_corrected_unmasked.mif'), name='tensor2FA_unmasked') mr_convert_FA = pe.Node(interface=MRConvert(out_filename='fa_corrected.nii.gz', stride=[+1, +2, +3]), name='mr_convert_FA') mr_convert_FA_unmasked = pe.Node( interface=MRConvert( out_filename='fa_corrected_unmasked.nii.gz', stride=[+1, +2, +3]), name='mr_convert_FA_unmasked') FA_noNaN = pe.Node(interface=cmp_fsl.MathsCommand(out_file='fa_corrected_nonan.nii.gz', nan2zeros=True), name='FA_noNaN') FA_noNaN_unmasked = pe.Node( interface=cmp_fsl.MathsCommand( out_file='fa_corrected_unmasked_nonan.nii.gz', nan2zeros=True), name='FA_noNaN_unmasked') flow.connect([ (mr_convert, dwi2tensor, [('converted', 'in_file')]), (inputnode, dwi2tensor, [('target_mask', 'in_mask_file')]), (dwi2tensor, tensor2FA, [('tensor', 'in_file')]), (inputnode, tensor2FA, [('target_mask', 'in_mask')]), (tensor2FA, mr_convert_FA, [('out_fa', 'in_file')]), (mr_convert_FA, FA_noNaN, [('converted', 'in_file')]) ]) flow.connect([ (mr_convert, dwi2tensor_unmasked, [('converted', 'in_file')]), (dwi2tensor_unmasked, tensor2FA_unmasked, [('tensor', 'in_file')]), (tensor2FA_unmasked, mr_convert_FA_unmasked, [('out_fa', 'in_file')]), (mr_convert_FA_unmasked, FA_noNaN_unmasked, [('converted', 'in_file')]) ]) from nipype.interfaces.fsl.maths import ApplyMask b0_masking = pe.Node(interface=ApplyMask( out_file='b0_masked.nii.gz'), name='b0_masking') flow.connect([ (mr_convert_b0, b0_masking, [('converted', 'in_file')]), (inputnode, b0_masking, [('target_mask', 'mask_file')]) ]) # [1.2] Linear registration of the DW data to the T1 data affine_registration = pe.Node( interface=ants.Registration(), name='linear_registration') affine_registration.inputs.collapse_output_transforms = True # affine_registration.inputs.initialize_transforms_per_stage=True affine_registration.inputs.initial_moving_transform_com = True affine_registration.inputs.output_transform_prefix = 'initial' affine_registration.inputs.num_threads = 8 affine_registration.inputs.output_inverse_warped_image = True affine_registration.inputs.output_warped_image = 'linear_warped_image.nii.gz' affine_registration.inputs.sigma_units = ['vox'] * 2 affine_registration.inputs.transforms = ['Rigid', 'Affine'] affine_registration.inputs.interpolation = self.config.ants_interpolation if self.config.ants_interpolation == "BSpline": # (3,) affine_registration.inputs.interpolation_parameters = self.config.ants_bspline_interpolation_parameters elif self.config.ants_interpolation == "Gaussian": # (5,5,) affine_registration.inputs.interpolation_parameters = self.config.ants_gauss_interpolation_parameters elif self.config.ants_interpolation == "MultiLabel": # (5,5,) affine_registration.inputs.interpolation_parameters = self.config.ants_multilab_interpolation_parameters # affine_registration.inputs.terminal_output='file' affine_registration.inputs.winsorize_lower_quantile = self.config.ants_lower_quantile # 0.005 affine_registration.inputs.winsorize_upper_quantile = self.config.ants_upper_quantile # 0.995 affine_registration.inputs.convergence_threshold = [ self.config.ants_convergence_thresh] * 2 # [1e-06]*2 affine_registration.inputs.convergence_window_size = [ self.config.ants_convergence_winsize] * 2 # [10]*2 affine_registration.inputs.metric = [self.config.ants_linear_cost, self.config.ants_linear_cost] # ['MI','MI'] affine_registration.inputs.metric_weight = [1.0] * 2 affine_registration.inputs.number_of_iterations = [[1000, 500, 250, 100], [1000, 500, 250, 100]] affine_registration.inputs.radius_or_number_of_bins = [32, 32] affine_registration.inputs.sampling_percentage = [self.config.ants_linear_sampling_perc, self.config.ants_linear_sampling_perc] # [0.25, 0.25] affine_registration.inputs.sampling_strategy = [self.config.ants_linear_sampling_strategy, self.config.ants_linear_sampling_strategy] # ['Regular','Regular'] affine_registration.inputs.shrink_factors = [[8, 4, 2, 1]] * 2 affine_registration.inputs.smoothing_sigmas = [[3, 2, 1, 0]] * 2 affine_registration.inputs.transform_parameters = [(self.config.ants_linear_gradient_step,), ( self.config.ants_linear_gradient_step,)] # [(0.1,),(0.1,)] affine_registration.inputs.use_histogram_matching = True if self.config.ants_perform_syn: affine_registration.inputs.write_composite_transform = True affine_registration.inputs.verbose = True affine_registration.inputs.float = self.config.use_float_precision flow.connect([ (b0_masking, affine_registration, [('out_file', 'fixed_image')]), (inputnode, affine_registration, [('brain', 'moving_image')]), # (inputnode, affine_registration, [('T1','moving_image')]), # (mr_convert_b0, affine_registration, [('converted','fixed_image')]), # (inputnode, affine_registration, [('brain_mask','moving_image_mask')]), # (inputnode, affine_registration, [('target_mask','fixed_image_mask')]) ]) SyN_registration = pe.Node( interface=ants.Registration(), name='SyN_registration') if self.config.ants_perform_syn: SyN_registration.inputs.collapse_output_transforms = True SyN_registration.inputs.write_composite_transform = False SyN_registration.inputs.output_transform_prefix = 'final' # SyN_registration.inputs.initial_moving_transform_com=True SyN_registration.inputs.num_threads = 8 SyN_registration.inputs.output_inverse_warped_image = True SyN_registration.inputs.output_warped_image = 'Syn_warped_image.nii.gz' SyN_registration.inputs.sigma_units = ['vox'] * 1 SyN_registration.inputs.transforms = ['SyN'] SyN_registration.inputs.restrict_deformation = [[0, 1, 0]] SyN_registration.inputs.interpolation = self.config.ants_interpolation # 'BSpline' if self.config.ants_interpolation == "BSpline": # (3,) SyN_registration.inputs.interpolation_parameters = self.config.ants_bspline_interpolation_parameters elif self.config.ants_interpolation == "Gaussian": # (5,5,) SyN_registration.inputs.interpolation_parameters = self.config.ants_gauss_interpolation_parameters elif self.config.ants_interpolation == "MultiLabel": # (5,5,) SyN_registration.inputs.interpolation_parameters = self.config.ants_multilab_interpolation_parameters # SyN_registration.inputs.terminal_output='file' SyN_registration.inputs.winsorize_lower_quantile = self.config.ants_lower_quantile # 0.005 SyN_registration.inputs.winsorize_upper_quantile = self.config.ants_upper_quantile # 0.995 SyN_registration.inputs.convergence_threshold = [ self.config.ants_convergence_thresh] * 1 # [1e-06]*1 SyN_registration.inputs.convergence_window_size = [ self.config.ants_convergence_winsize] * 1 # [10]*1 SyN_registration.inputs.metric = [ self.config.ants_nonlinear_cost] # ['CC'] SyN_registration.inputs.metric_weight = [1.0] * 1 SyN_registration.inputs.number_of_iterations = [[20]] SyN_registration.inputs.radius_or_number_of_bins = [4] SyN_registration.inputs.sampling_percentage = [1] SyN_registration.inputs.sampling_strategy = ['None'] SyN_registration.inputs.shrink_factors = [[1]] * 1 SyN_registration.inputs.smoothing_sigmas = [[0]] * 1 SyN_registration.inputs.transform_parameters = [(self.config.ants_nonlinear_gradient_step, self.config.ants_nonlinear_update_field_variance, self.config.ants_nonlinear_total_field_variance)] # [(0.1, 3.0, 0.0)] SyN_registration.inputs.use_histogram_matching = True SyN_registration.inputs.verbose = True SyN_registration.inputs.float = self.config.use_float_precision # SyN_registration = pe.Node(interface=ants.Registration(),name='SyN_registration') # SyN_registration.inputs.collapse_output_transforms=True # SyN_registration.inputs.write_composite_transform=False # SyN_registration.inputs.output_transform_prefix = 'final' # #SyN_registration.inputs.initial_moving_transform_com=True # SyN_registration.inputs.num_threads=8 # SyN_registration.inputs.output_inverse_warped_image=True # SyN_registration.inputs.output_warped_image='Syn_warped_image.nii.gz' # SyN_registration.inputs.sigma_units=['vox']*1 # SyN_registration.inputs.transforms=['SyN'] # SyN_registration.inputs.restrict_deformation=[[1,1,0]] # SyN_registration.inputs.interpolation='BSpline' # SyN_registration.inputs.interpolation_parameters=(3,) # SyN_registration.inputs.terminal_output='file' # SyN_registration.inputs.winsorize_lower_quantile=0.005 # SyN_registration.inputs.winsorize_upper_quantile=0.995 # SyN_registration.inputs.convergence_threshold=[1e-06]*1 # SyN_registration.inputs.convergence_window_size=[10]*1 # SyN_registration.inputs.metric=['CC'] # SyN_registration.inputs.metric_weight=[1.0]*1 # SyN_registration.inputs.number_of_iterations=[[100, 70, 50, 20]] # SyN_registration.inputs.radius_or_number_of_bins=[4] # SyN_registration.inputs.sampling_percentage=[1] # SyN_registration.inputs.sampling_strategy=['None'] # SyN_registration.inputs.shrink_factors=[[8, 4, 2, 1]]*1 # SyN_registration.inputs.smoothing_sigmas=[[3, 2, 1, 0]]*1 # SyN_registration.inputs.transform_parameters=[(0.1, 3.0, 0.0)] # SyN_registration.inputs.use_histogram_matching=True # SyN_registration.inputs.verbose = True # BSplineSyN_registration = pe.Node(interface=ants.Registration(),name='BSplineSyN_registration') # BSplineSyN_registration.inputs.collapse_output_transforms=True # BSplineSyN_registration.inputs.write_composite_transform=False # BSplineSyN_registration.inputs.output_transform_prefix = 'final' # #BSplineSyN_registration.inputs.initial_moving_transform_com=True # BSplineSyN_registration.inputs.num_threads=8 # BSplineSyN_registration.inputs.output_inverse_warped_image=True # BSplineSyN_registration.inputs.output_warped_image='Syn_warped_image.nii.gz' # BSplineSyN_registration.inputs.sigma_units=['vox']*1 # BSplineSyN_registration.inputs.transforms=['BSplineSyN'] # BSplineSyN_registration.inputs.interpolation='BSpline' # BSplineSyN_registration.inputs.interpolation_parameters=(3,) # BSplineSyN_registration.inputs.terminal_output='file' # BSplineSyN_registration.inputs.winsorize_lower_quantile=0.005 # BSplineSyN_registration.inputs.winsorize_upper_quantile=0.995 # BSplineSyN_registration.inputs.convergence_threshold=[1e-06]*1 # BSplineSyN_registration.inputs.convergence_window_size=[10]*1 # BSplineSyN_registration.inputs.metric=['CC'] # BSplineSyN_registration.inputs.metric_weight=[1.0]*1 # BSplineSyN_registration.inputs.number_of_iterations=[[100, 70, 50, 20]] # BSplineSyN_registration.inputs.radius_or_number_of_bins=[4] # BSplineSyN_registration.inputs.sampling_percentage=[1] # BSplineSyN_registration.inputs.sampling_strategy=['None'] # BSplineSyN_registration.inputs.shrink_factors=[[8, 4, 2, 1]]*1 # BSplineSyN_registration.inputs.smoothing_sigmas=[[3, 2, 1, 0]]*1 # BSplineSyN_registration.inputs.transform_parameters=[(0.25, 26, 0, 3)] # BSplineSyN_registration.inputs.use_histogram_matching=True # BSplineSyN_registration.inputs.verbose = True flow.connect([ (affine_registration, SyN_registration, [ ('composite_transform', 'initial_moving_transform')]), (b0_masking, SyN_registration, [ ('out_file', 'fixed_image')]), (inputnode, SyN_registration, [('brain', 'moving_image')]) # (inputnode, SyN_registration, [('T1','moving_image')]), # (mr_convert_b0, SyN_registration, [('converted','fixed_image')]), # (inputnode, SyN_registration, [('brain_mask','moving_image_mask')]), # (inputnode, SyN_registration, [('target_mask','fixed_image_mask')]) ]) # multitransforms = pe.Node(interface=util.Merge(2),name='multitransforms') # # def convertList2Tuple(lists): # print "******************************************",tuple(lists) # return tuple(lists) # # flow.connect([ # (ants_registration,multitransforms,[('warp_transform','in1')]), # (ants_registration,multitransforms,[('affine_transform','in2')]) # #(concatnode,mr_convert,[(('out',convertList2Tuple),'grad_fsl')]) # ]) ants_applywarp_T1 = pe.Node( interface=ants.ApplyTransforms( default_value=0, interpolation="Gaussian", out_postfix="_warped"), name="apply_warp_T1") ants_applywarp_brain = pe.Node( interface=ants.ApplyTransforms( default_value=0, interpolation="Gaussian", out_postfix="_warped"), name="apply_warp_brain") ants_applywarp_brainmask = pe.Node( interface=ants.ApplyTransforms( default_value=0, interpolation="NearestNeighbor", out_postfix="_warped"), name="apply_warp_brainmask") ants_applywarp_wm = pe.Node( interface=ants.ApplyTransforms( default_value=0, interpolation="NearestNeighbor", out_postfix="_warped"), name="apply_warp_wm") ants_applywarp_rois = pe.Node( interface=MultipleANTsApplyTransforms(interpolation="NearestNeighbor", default_value=0, out_postfix="_warped"), name="apply_warp_roivs") ants_applywarp_pves = pe.Node( interface=MultipleANTsApplyTransforms( interpolation="Gaussian", default_value=0, out_postfix="_warped"), name="apply_warp_pves") ants_applywarp_5tt = pe.Node( interface=ants.ApplyTransforms( default_value=0, interpolation="Gaussian", out_postfix="_warped"), name="apply_warp_5tt") ants_applywarp_5tt.inputs.dimension = 3 ants_applywarp_5tt.inputs.input_image_type = 3 ants_applywarp_5tt.inputs.float = True ants_applywarp_gmwmi = pe.Node( interface=ants.ApplyTransforms( default_value=0, interpolation="Gaussian", out_postfix="_warped"), name="apply_warp_gmwmi") ants_applywarp_gmwmi.inputs.dimension = 3 ants_applywarp_gmwmi.inputs.input_image_type = 3 ants_applywarp_gmwmi.inputs.float = True def reverse_order_transforms(transforms): """Reverse the order of the transformations estimated by linear and SyN registration. Parameters ---------- transforms : list of File List of transformation files Returns ------- out_transforms : list of File Reversed list of transformation files (``transforms[::-1]``) """ out_transforms = transforms[::-1] return out_transforms def extract_affine_transform(transforms): """Extract affine transformation file from a list a transformation files generated by linear and SyN registration. Parameters ---------- transforms : list of File List of transformation files Returns ------- t : File Affine transformation file """ for t in transforms: if 'Affine' in t: return t def extract_warp_field(transforms): """Extract the warpfield file from a list a transformation files generated by linear and SyN registration. Parameters ---------- transforms : list of File List of transformation files Returns ------- t : File Warp field (Non-linear transformation) file """ for t in transforms: if 'Warp' in t: return t if self.config.ants_perform_syn: flow.connect([ (SyN_registration, ants_applywarp_T1, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (SyN_registration, ants_applywarp_5tt, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (SyN_registration, ants_applywarp_gmwmi, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (SyN_registration, ants_applywarp_brain, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (SyN_registration, ants_applywarp_brainmask, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (SyN_registration, ants_applywarp_wm, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (SyN_registration, ants_applywarp_rois, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (SyN_registration, ants_applywarp_pves, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (SyN_registration, outputnode, [(('forward_transforms', extract_affine_transform), 'affine_transform')]), (SyN_registration, outputnode, [ (('forward_transforms', extract_warp_field), 'warp_field')]), ]) else: flow.connect([ (affine_registration, ants_applywarp_T1, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (affine_registration, ants_applywarp_5tt, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (affine_registration, ants_applywarp_gmwmi, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (affine_registration, ants_applywarp_brain, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (affine_registration, ants_applywarp_brainmask, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (affine_registration, ants_applywarp_wm, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (affine_registration, ants_applywarp_rois, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (affine_registration, ants_applywarp_pves, [(('forward_transforms', reverse_order_transforms), 'transforms')]), (affine_registration, outputnode, [(('forward_transforms', extract_affine_transform), 'affine_transform')]), ]) flow.connect([ (inputnode, ants_applywarp_T1, [('T1', 'input_image')]), (mr_convert_b0, ants_applywarp_T1, [ ('converted', 'reference_image')]), # (multitransforms, ants_applywarp_T1, [('out','transforms')]), (ants_applywarp_T1, outputnode, [ ('output_image', 'T1_registered_crop')]), ]) flow.connect([ (inputnode, ants_applywarp_5tt, [('act_5TT', 'input_image')]), (mr_convert_b0, ants_applywarp_5tt, [ ('converted', 'reference_image')]), # (multitransforms, ants_applywarp_T1, [('out','transforms')]), (ants_applywarp_5tt, outputnode, [ ('output_image', 'act_5tt_registered_crop')]), ]) flow.connect([ (inputnode, ants_applywarp_gmwmi, [('gmwmi', 'input_image')]), (mr_convert_b0, ants_applywarp_gmwmi, [('converted', 'reference_image')]), # (multitransforms, ants_applywarp_T1, [('out','transforms')]), (ants_applywarp_gmwmi, outputnode, [ ('output_image', 'gmwmi_registered_crop')]), ]) flow.connect([ (inputnode, ants_applywarp_brain, [('brain', 'input_image')]), (mr_convert_b0, ants_applywarp_brain, [('converted', 'reference_image')]), # (multitransforms, ants_applywarp_brain, [('out','transforms')]), (ants_applywarp_brain, outputnode, [ ('output_image', 'brain_registered_crop')]), ]) flow.connect([ (inputnode, ants_applywarp_brainmask, [('brain_mask', 'input_image')]), (mr_convert_b0, ants_applywarp_brainmask, [('converted', 'reference_image')]), # (multitransforms, ants_applywarp_brainmask, [('out','transforms')]), (ants_applywarp_brainmask, outputnode, [ ('output_image', 'brain_mask_registered_crop')]), ]) flow.connect([ (inputnode, ants_applywarp_wm, [('wm_mask', 'input_image')]), (mr_convert_b0, ants_applywarp_wm, [ ('converted', 'reference_image')]), # (multitransforms, ants_applywarp_wm, [('out','transforms')]), (ants_applywarp_wm, outputnode, [ ('output_image', 'wm_mask_registered_crop')]), ]) flow.connect([ (inputnode, ants_applywarp_rois, [ ('roi_volumes', 'input_images')]), (mr_convert_b0, ants_applywarp_rois, [('converted', 'reference_image')]), (ants_applywarp_rois, outputnode, [ ('output_images', 'roi_volumes_registered_crop')]), ]) flow.connect([ (inputnode, ants_applywarp_pves, [ ('partial_volume_files', 'input_images')]), (mr_convert_b0, ants_applywarp_pves, [('converted', 'reference_image')]), (ants_applywarp_pves, outputnode, [ ('output_images', 'partial_volumes_registered_crop')]), ]) flow.connect([ # (inputnode, outputnode, [('roi_volumes','roi_volumes_registered_crop')]), (inputnode, outputnode, [('target', 'target_epicorrected')]), ]) if self.config.registration_mode == 'FSL (Linear)': fsl_flirt = pe.Node(interface=fsl.FLIRT(out_file='T1-TO-TARGET.nii.gz', out_matrix_file='T1-TO-TARGET.mat'), name="linear_registration") fsl_flirt.inputs.uses_qform = self.config.uses_qform fsl_flirt.inputs.dof = self.config.dof fsl_flirt.inputs.cost = self.config.fsl_cost fsl_flirt.inputs.no_search = self.config.no_search fsl_flirt.inputs.args = self.config.flirt_args fsl_applyxfm_wm = pe.Node( interface=fsl.ApplyXFM( apply_xfm=True, interp="nearestneighbour", out_file="wm_mask_registered.nii.gz"), name="apply_registration_wm") fsl_applyxfm_rois = pe.Node( interface=ApplymultipleXfm(), name="apply_registration_roivs") # TODO apply xfm to gmwmi / 5tt and pves flow.connect([ (inputnode, fsl_applyxfm_wm, [('wm_mask', 'in_file')]), (fsl_flirt, outputnode, [("out_file", "T1_registered_crop")]), (fsl_flirt, fsl_applyxfm_wm, [ ('out_matrix_file', 'in_matrix_file')]), (fsl_applyxfm_wm, outputnode, [ ('out_file', 'wm_mask_registered_crop')]), (inputnode, fsl_applyxfm_rois, [('roi_volumes', 'in_files')]), (fsl_flirt, fsl_applyxfm_rois, [ ('out_matrix_file', 'xfm_file')]), (fsl_flirt, outputnode, [ ('out_matrix_file', 'affine_transform')]), (fsl_applyxfm_rois, outputnode, [ ('out_files', 'roi_volumes_registered_crop')]) ]) if self.config.pipeline == "fMRI": flow.connect([ (T1_bet, fsl_flirt, [('out_file', 'in_file')]), (fmri_bet, fsl_flirt, [('out_file', 'reference')]), (fmri_bet, fsl_applyxfm_wm, [('out_file', 'reference')]), (fmri_bet, fsl_applyxfm_rois, [('out_file', 'reference')]) ]) fsl_applyxfm_eroded_wm = pe.Node(interface=fsl.ApplyXFM(apply_xfm=True, interp="nearestneighbour", out_file="eroded_wm_registered.nii.gz"), name="apply_registration_wm_eroded") if self.config.apply_to_eroded_csf: fsl_applyxfm_eroded_csf = pe.Node(interface=fsl.ApplyXFM(apply_xfm=True, interp="nearestneighbour", out_file="eroded_csf_registered.nii.gz"), name="apply_registration_csf_eroded") flow.connect([ (inputnode, fsl_applyxfm_eroded_csf, [('eroded_csf', 'in_file')]), (fmri_bet, fsl_applyxfm_eroded_csf, [('out_file', 'reference')]), (fsl_flirt, fsl_applyxfm_eroded_csf, [ ('out_matrix_file', 'in_matrix_file')]), (fsl_applyxfm_eroded_csf, outputnode, [ ('out_file', 'eroded_csf_registered_crop')]) ]) if self.config.apply_to_eroded_brain: fsl_applyxfm_eroded_brain = pe.Node( interface=fsl.ApplyXFM(apply_xfm=True, interp="nearestneighbour", out_file="eroded_brain_registered.nii.gz"), name="apply_registration_brain_eroded") flow.connect([ (inputnode, fsl_applyxfm_eroded_brain, [('eroded_brain', 'in_file')]), (fmri_bet, fsl_applyxfm_eroded_brain, [('out_file', 'reference')]), (fsl_flirt, fsl_applyxfm_eroded_brain, [ ('out_matrix_file', 'in_matrix_file')]), (fsl_applyxfm_eroded_brain, outputnode, [ ('out_file', 'eroded_brain_registered_crop')]) ]) flow.connect([ (inputnode, fsl_applyxfm_eroded_wm, [('eroded_wm', 'in_file')]), (fmri_bet, fsl_applyxfm_eroded_wm, [('out_file', 'reference')]), (fsl_flirt, fsl_applyxfm_eroded_wm, [ ('out_matrix_file', 'in_matrix_file')]), (fsl_applyxfm_eroded_wm, outputnode, [ ('out_file', 'eroded_wm_registered_crop')]) ]) else: flow.connect([ (inputnode, fsl_flirt, [('T1', 'in_file')]), (fs_mriconvert, fsl_flirt, [('out_file', 'reference')]), (fs_mriconvert, fsl_applyxfm_wm, [('out_file', 'reference')]), (fs_mriconvert, fsl_applyxfm_rois, [('out_file', 'reference')]), ]) if self.config.pipeline == "fMRI" and self.config.registration_mode == 'BBregister (FS)': fs_bbregister = pe.Node(interface=cmp_fs.BBRegister( out_fsl_file="target-TO-orig.mat"), name="bbregister") fs_bbregister.inputs.init = self.config.init fs_bbregister.inputs.contrast_type = self.config.contrast_type fs_bbregister.inputs.subjects_dir = self.fs_subjects_dir fs_bbregister.inputs.subject_id = self.fs_subject_id fsl_invertxfm = pe.Node(interface=fsl.ConvertXFM( invert_xfm=True), name="fsl_invertxfm") fs_source = pe.Node( interface=fs.preprocess.FreeSurferSource(), name="get_fs_files") fs_source.inputs.subjects_dir = self.fs_subjects_dir fs_source.inputs.subject_id = self.fs_subject_id fs_tkregister2 = pe.Node(interface=cmp_fs.Tkregister2( regheader=True, noedit=True), name="fs_tkregister2") fs_tkregister2.inputs.reg_out = 'T1-TO-orig.dat' fs_tkregister2.inputs.fslreg_out = 'T1-TO-orig.mat' fs_tkregister2.inputs.subjects_dir = self.fs_subjects_dir fs_tkregister2.inputs.subject_id = self.fs_subject_id fsl_concatxfm = pe.Node(interface=fsl.ConvertXFM( concat_xfm=True), name="fsl_concatxfm") fsl_applyxfm = pe.Node(interface=fsl.ApplyXFM(apply_xfm=True, out_file="T1-TO-TARGET.nii.gz"), name="linear_registration") fsl_applyxfm_wm = pe.Node( interface=fsl.ApplyXFM( apply_xfm=True, interp="nearestneighbour", out_file="wm_mask_registered.nii.gz"), name="apply_registration_wm") fsl_applyxfm_rois = pe.Node( interface=ApplymultipleXfm(), name="apply_registration_roivs") flow.connect([ (fs_bbregister, fsl_invertxfm, [('out_fsl_file', 'in_file')]), (fsl_invertxfm, fsl_concatxfm, [('out_file', 'in_file2')]), (fs_source, fs_tkregister2, [ ("orig", "target_file"), ("rawavg", "in_file")]), (fs_tkregister2, fsl_concatxfm, [ ('fslregout_file', 'in_file')]), # (inputnode, fsl_applyxfm, [('T1', 'in_file')]), (T1_bet, fsl_applyxfm, [('out_file', 'in_file')]), (fsl_concatxfm, fsl_applyxfm, [ ('out_file', 'in_matrix_file')]), (fsl_applyxfm, outputnode, [ ("out_file", "T1_registered_crop")]), (inputnode, fsl_applyxfm_wm, [('wm_mask', 'in_file')]), (fsl_concatxfm, fsl_applyxfm_wm, [ ('out_file', 'in_matrix_file')]), (fsl_applyxfm_wm, outputnode, [ ('out_file', 'wm_mask_registered_crop')]), (inputnode, fsl_applyxfm_rois, [('roi_volumes', 'in_files')]), (fsl_concatxfm, fsl_applyxfm_rois, [('out_file', 'xfm_file')]), (fsl_applyxfm_rois, outputnode, [ ('out_files', 'roi_volumes_registered_crop')]) ]) flow.connect([ # (inputnode, fs_bbregister, [('target', 'source_file')]), (fmri_bet, fs_bbregister, [('out_file', 'source_file')]), (inputnode, fsl_applyxfm, [('target', 'reference')]), (inputnode, fsl_applyxfm_wm, [('target', 'reference')]), (inputnode, fsl_applyxfm_rois, [('target', 'reference')]), ]) fsl_applyxfm_eroded_wm = pe.Node(interface=fsl.ApplyXFM(apply_xfm=True, interp="nearestneighbour", out_file="eroded_wm_registered.nii.gz"), name="apply_registration_wm_eroded") if self.config.apply_to_eroded_csf: fsl_applyxfm_eroded_csf = pe.Node(interface=fsl.ApplyXFM(apply_xfm=True, interp="nearestneighbour", out_file="eroded_csf_registered.nii.gz"), name="apply_registration_csf_eroded") flow.connect([ (inputnode, fsl_applyxfm_eroded_csf, [('eroded_csf', 'in_file')]), (inputnode, fsl_applyxfm_eroded_csf, [('target', 'reference')]), (fsl_concatxfm, fsl_applyxfm_eroded_csf, [('out_file', 'in_matrix_file')]), (fsl_applyxfm_eroded_csf, outputnode, [ ('out_file', 'eroded_csf_registered_crop')]) ]) if self.config.apply_to_eroded_brain: fsl_applyxfm_eroded_brain = pe.Node( interface=fsl.ApplyXFM(apply_xfm=True, interp="nearestneighbour", out_file="eroded_brain_registered.nii.gz"), name="apply_registration_brain_eroded") flow.connect([ (inputnode, fsl_applyxfm_eroded_brain, [('eroded_brain', 'in_file')]), (inputnode, fsl_applyxfm_eroded_brain, [('target', 'reference')]), (fsl_concatxfm, fsl_applyxfm_eroded_brain, [('out_file', 'in_matrix_file')]), (fsl_applyxfm_eroded_brain, outputnode, [ ('out_file', 'eroded_brain_registered_crop')]) ]) flow.connect([ (inputnode, fsl_applyxfm_eroded_wm, [('eroded_wm', 'in_file')]), (inputnode, fsl_applyxfm_eroded_wm, [('target', 'reference')]), (fsl_concatxfm, fsl_applyxfm_eroded_wm, [('out_file', 'in_matrix_file')]), (fsl_applyxfm_eroded_wm, outputnode, [ ('out_file', 'eroded_wm_registered_crop')]) ])
# if self.config.registration_mode == 'FSL (Nonlinear)': # # [SUB-STEP 1] LINEAR register "T2" onto "Target_resampled # # [1.1] linear register "T1" onto "T2" # fsl_flirt_1 = pe.Node(interface=fsl.FLIRT(out_file='T1-TO-T2.nii.gz',out_matrix_file='T1-TO-T2.mat'),name="t1tot2_lin_registration") # fsl_flirt_1.inputs.dof = 6 # fsl_flirt_1.inputs.cost = "mutualinfo" # fsl_flirt_1.inputs.no_search = True # #[1.2] -> linear register "T2" onto "target_resampled" # fsl_flirt_2 = pe.Node(interface=fsl.FLIRT(out_file='T2-TO-TARGET.nii.gz',out_matrix_file='T2-TO-TARGET.mat'),name="t2totarget_lin_registration") # fsl_flirt_2.inputs.dof = 12 # fsl_flirt_2.inputs.cost = "normmi" # fsl_flirt_2.inputs.no_search = True # #[1.3] -> apply the linear registration "T1" --> "target" (for comparison) # fsl_concatxfm = pe.Node(interface=fsl.ConvertXFM(concat_xfm=True),name="fsl_concatxfm") # fsl_applyxfm = pe.Node(interface=fsl.ApplyXFM(apply_xfm=True, interp="sinc",out_file='T1-TO-target.nii.gz',out_matrix_file='T1-TO-TARGET.mat'), # name="linear_registration") # #"[SUB-STEP 2] Create BINARY MASKS for nonlinear registration" # # [2.1] -> create a T2 brain mask # fsl_bet_1 = pe.Node(interface=fsl.BET(out_file='T2-brain',mask=True,no_output=True,robust=True),name="t2_brain_mask") # fsl_bet_1.inputs.frac = 0.35 # fsl_bet_1.inputs.vertical_gradient = 0.15 # #[2.2] -> create a DSI_target brain mask # fsl_bet_2 = pe.Node(interface=fsl.BET(out_file='target-brain',mask=True,no_output=True,robust=True),name="target_brain_mask") # fsl_bet_2.inputs.frac = 0.2 # fsl_bet_2.inputs.vertical_gradient = 0.2 # # [SUB-STEP 3] NONLINEAR register "T2" onto "target_resampled" # # [3.1] 'Started FNIRT to find 'T2 --> target' nonlinear transformation at # fsl_fnirt = pe.Node(interface=fsl.FNIRT(field_file='T2-TO-target_warp.nii.gz'),name="t2totarget_nlin_registration") # fsl_fnirt.inputs.subsampling_scheme = [8,4,2,2] # fsl_fnirt.inputs.max_nonlin_iter = [5,5,5,5] # fsl_fnirt.inputs.regularization_lambda = [240,120,90,30] # fsl_fnirt.inputs.spline_order = 3 # fsl_fnirt.inputs.apply_inmask = [0,0,1,1] # fsl_fnirt.inputs.apply_refmask = [0,0,1,1] # #[3.2] -> apply the warp found for "T2" also onto "T1" # fsl_applywarp = pe.Node(interface=fsl.ApplyWarp(out_file='T1_warped.nii.gz'),name="nonlinear_registration") # fsl_applywarp_wm = pe.Node(interface=fsl.ApplyWarp(interp="nn",out_file="wm_mask_registered.nii.gz"),name="apply_registration_wm") # fsl_applywarp_rois = pe.Node(interface=Applynlinmultiplewarps(),name="apply_registration_roivs") # TO FIX: Applynlinmultiplewarps() done because applying MapNode to fsl.ApplyWarp crashes # #fsl_applywarp_rois = pe.MapNode(interface=fsl.ApplyWarp(interp="nn"),name="apply_registration_roivs",iterfield=["in_file"]) # # flow.connect([ # (inputnode,fsl_flirt_1,[('T1','in_file'),('T2','reference')]), # (inputnode,fsl_flirt_2,[('T2','in_file')]), # (fsl_flirt_1,fsl_concatxfm,[('out_matrix_file','in_file')]), # (fsl_flirt_2,fsl_concatxfm,[('out_matrix_file','in_file2')]), # (inputnode,fsl_applyxfm,[('T1','in_file')]), # (fsl_concatxfm,fsl_applyxfm,[('out_file','in_matrix_file')]), # (inputnode,fsl_bet_1,[('T2','in_file')]), # (inputnode,fsl_fnirt,[('T2','in_file')]), # (fsl_flirt_2,fsl_fnirt,[('out_matrix_file','affine_file')]), # (fsl_bet_1,fsl_fnirt,[('mask_file','inmask_file')]), # (fsl_bet_2,fsl_fnirt,[('mask_file','refmask_file')]), # (inputnode,fsl_applywarp,[('T1','in_file')]), # (fsl_flirt_1,fsl_applywarp,[('out_matrix_file','premat')]), # (fsl_fnirt,fsl_applywarp,[('field_file','field_file')]), # (inputnode, fsl_applywarp_wm, [('wm_mask','in_file')]), # (fsl_flirt_1, fsl_applywarp_wm, [('out_matrix_file','premat')]), # (fsl_fnirt,fsl_applywarp_wm,[('field_file','field_file')]), # (fsl_applywarp_wm, outputnode, [('out_file','wm_mask_registered_crop')]), # (inputnode, fsl_applywarp_rois, [('roi_volumes','in_files')]), # (fsl_flirt_1, fsl_applywarp_rois, [('out_matrix_file','premat_file')]), # (fsl_fnirt,fsl_applywarp_rois,[('field_file','field_file')]), # (fsl_applywarp_rois, outputnode, [('warped_files','roi_volumes_registered_crop')]) # ]) # if self.config.pipeline == "fMRI": # flow.connect([ # (inputnode,fsl_flirt_2,[('target','reference')]), # (inputnode,fsl_applyxfm,[('target','reference')]), # (inputnode,fsl_bet_2,[('target','in_file')]), # (inputnode,fsl_fnirt,[('target','ref_file')]), # (inputnode,fsl_applywarp,[('target','ref_file')]), # (inputnode, fsl_applywarp_wm, [('target','ref_file')]), # (inputnode, fsl_applywarp_rois, [('target','ref_file')]), # ]) # fsl_applywarp_eroded_wm = pe.Node(interface=fsl.ApplyWarp(interp="nn",out_file="eroded_wm_registered.nii.gz"), # name="apply_registration_eroded_wm") # if self.config.apply_to_eroded_csf: # fsl_applywarp_eroded_csf = pe.Node(interface=fsl.ApplyWarp(interp="nn",out_file="eroded_csf_registered.nii.gz"), # name="apply_registration_eroded_csf") # flow.connect([ # (inputnode, fsl_applywarp_eroded_csf, [('eroded_csf','in_file')]), # (inputnode, fsl_applywarp_eroded_csf, [('target','ref_file')]), # (fsl_flirt_1, fsl_applywarp_eroded_csf, [('out_matrix_file','premat')]), # (fsl_fnirt,fsl_applywarp_eroded_csf,[('field_file','field_file')]), # (fsl_applywarp_eroded_csf, outputnode, [('out_file','eroded_csf_registered_crop')]) # ]) # if self.config.apply_to_eroded_brain: # fsl_applywarp_eroded_brain = pe.Node(interface=fsl.ApplyWarp(interp="nn",out_file="eroded_brain_registered.nii.gz"), # name="apply_registration_eroded_brain") # flow.connect([ # (inputnode, fsl_applywarp_eroded_brain, [('eroded_brain','in_file')]), # (inputnode, fsl_applywarp_eroded_brain, [('target','ref_file')]), # (fsl_flirt_1, fsl_applywarp_eroded_brain, [('out_matrix_file','premat')]), # (fsl_fnirt,fsl_applywarp_eroded_brain,[('field_file','field_file')]), # (fsl_applywarp_eroded_brain, outputnode, [('out_file','eroded_brain_registered_crop')]) # ]) # flow.connect([ # (inputnode, fsl_applywarp_eroded_wm, [('eroded_wm','in_file')]), # (inputnode, fsl_applywarp_eroded_wm, [('target','ref_file')]), # (fsl_flirt_1, fsl_applywarp_eroded_wm, [('out_matrix_file','premat')]), # (fsl_fnirt,fsl_applywarp_eroded_wm,[('field_file','field_file')]), # (fsl_applywarp_eroded_wm, outputnode, [('out_file','eroded_wm_registered_crop')]) # ]) # else: # flow.connect([ # (fs_mriconvert,fsl_flirt_2,[('out_file','reference')]), # (fs_mriconvert,fsl_applyxfm,[('out_file','reference')]), # (fs_mriconvert,fsl_bet_2,[('out_file','in_file')]), # (fs_mriconvert,fsl_fnirt,[('out_file','ref_file')]), # (fs_mriconvert,fsl_applywarp,[('out_file','ref_file')]), # (fs_mriconvert, fsl_applywarp_wm, [('out_file','ref_file')]), # (fs_mriconvert, fsl_applywarp_rois, [('out_file','ref_file')]), # ])
[docs] def define_inspect_outputs(self): """Update the `inspect_outputs' class attribute. It contains a dictionary of stage outputs with corresponding commands for visual inspection. """ # print("stage_dir : %s" % self.stage_dir) if self.config.pipeline == "Diffusion": dwi_sinker_dir = os.path.join(os.path.dirname(self.stage_dir), 'diffusion_sinker') dwi_sinker_report = os.path.join(dwi_sinker_dir, '_report', 'report.rst') if os.path.exists(dwi_sinker_report): dwi_outputs = get_pipeline_dictionary_outputs(dwi_sinker_report, self.output_dir) tool = self.config.registration_mode ref = dwi_outputs['dwi.@bdiffusion_reg_crop'] out = dwi_outputs['anat.@brain_reg_crop'] if os.path.exists(ref) and os.path.exists(out): self.inspect_outputs_dict['Linear T1-to-b0 (%s)' % tool] = ['fsleyes', '-sdefault', ref, out, '-cm', "copper", '-a', '50'] out = dwi_outputs['anat.@act_5tt_reg_crop'] if os.path.exists(ref) and os.path.exists(out): self.inspect_outputs_dict['Wrapped 5TT-to-b0 (%s)' % tool] = ['fsleyes', '-sdefault', ref, out, '-cm', "hot", '-a', '50'] out = dwi_outputs['anat.@gmwmi_reg_crop'] if os.path.exists(ref) and os.path.exists(out): self.inspect_outputs_dict['Wrapped GMWMi-to-b0 (%s)' % tool] = ['fsleyes', '-sdefault', ref, out, '-cm', "hot", '-a', '50'] field = dwi_outputs['xfm.@warp_field'] if os.path.exists(field): self.inspect_outputs_dict['Deformation field (%s)' % tool] = ['fsleyes', '-sdefault', field] if isinstance(dwi_outputs['anat.@roivs_reg_crop'], str) and os.path.exists(dwi_outputs['anat.@roivs_reg_crop']): roiv = dwi_outputs['anat.@roivs_reg_crop'] if os.path.exists(roiv): self.inspect_outputs_dict['%s-to-b0 (%s)' % (os.path.basename(roiv), tool)] = [ 'fsleyes', '-sdefault', ref, roiv, '-cm', 'random', '-a', '50'] else: for roi_output in dwi_outputs['anat.@roivs_reg_crop']: roiv = roi_output if os.path.exists(roiv): self.inspect_outputs_dict['%s-to-b0 (%s)' % (os.path.basename(roiv), tool)] = ['fsleyes', '-sdefault', ref, roiv, '-cm', 'random', '-a', '50'] if isinstance(dwi_outputs['anat.@pves_reg_crop'], str): pves = dwi_outputs['anat.@pves_reg_crop'] if os.path.exists(pves): self.inspect_outputs_dict['%s-to-b0 (%s)' % (os.path.basename(pves), tool)] = ['fsleyes', '-sdefault', ref, pves, '-cm', 'hot', '-a', '50'] else: for pve_output in dwi_outputs['anat.@pves_reg_crop']: pves = pve_output if os.path.exists(pves): self.inspect_outputs_dict['%s-to-b0 (%s)' % (os.path.basename(pves), tool)] = ['fsleyes', '-sdefault', ref, pves, '-cm', 'hot', '-a', '50'] else: func_sinker_dir = os.path.join(os.path.dirname(self.stage_dir), 'bold_sinker') func_sinker_report = os.path.join(func_sinker_dir, '_report', 'report.rst') if os.path.exists(func_sinker_report): func_outputs = get_pipeline_dictionary_outputs(func_sinker_report, self.output_dir) tool = self.config.registration_mode if isinstance(func_outputs['anat.@registered_roi_volumes'], str): ref = func_outputs['func.@mean_vol'] out = func_outputs['anat.@registered_roi_volumes'] if os.path.exists(ref) and os.path.exists(out): self.inspect_outputs_dict['Mean-fMRI/%s (%s)' % (os.path.basename(out), tool)] = [ 'fsleyes', '-sdefault', ref, out, '-cm', 'random', '-a', '50'] else: for roi_output in func_outputs['anat.@registered_roi_volumes']: ref = func_outputs['func.@mean_vol'] out = roi_output if os.path.exists(ref) and os.path.exists(out): self.inspect_outputs_dict['Mean-fMRI/%s (%s)' % (os.path.basename(out), tool)] = ['fsleyes', '-sdefault', ref, out, '-cm', 'random', '-a', '50'] self.inspect_outputs = sorted([key for key in list(self.inspect_outputs_dict.keys())], key=str.lower)
[docs] def has_run(self): """Function that returns `True` if the stage has been run successfully. Returns ------- `True` if the stage has been run successfully """ if self.config.registration_mode == 'ANTs': if self.config.ants_perform_syn: return os.path.exists(os.path.join(self.stage_dir, "SyN_registration", "result_SyN_registration.pklz")) else: return os.path.exists( os.path.join(self.stage_dir, "linear_registration", "result_linear_registration.pklz")) elif self.config.registration_mode != 'Nonlinear (FSL)': return os.path.exists( os.path.join(self.stage_dir, "linear_registration", "result_linear_registration.pklz")) elif self.config.registration_mode == 'Nonlinear (FSL)': return os.path.exists( os.path.join(self.stage_dir, "nonlinear_registration", "result_nonlinear_registration.pklz"))