예제 #1
0
def run_matlab(caps_dir, output_dir, subjects_visits_tsv, pipeline_parameters):
    """
    Wrap the call of SurfStat using clinicasurfstat.m Matlab script.

    Args:
        caps_dir (str): CAPS directory containing surface-based features
        output_dir (str): Output directory that will contain outputs of clinicasurfstat.m
        subjects_visits_tsv (str): TSV file containing the GLM information
        pipeline_parameters (dict): parameters of StatisticsSurface pipeline
    """
    import os
    from nipype.interfaces.matlab import MatlabCommand, get_matlab_command
    import clinica.pipelines as clinica_pipelines
    from clinica.utils.check_dependency import check_environment_variable
    from clinica.pipelines.statistics_surface.statistics_surface_utils import covariates_to_design_matrix, get_string_format_from_tsv

    path_to_matlab_script = os.path.join(
        os.path.dirname(clinica_pipelines.__path__[0]), 'lib',
        'clinicasurfstat')
    freesurfer_home = check_environment_variable('FREESURFER_HOME',
                                                 'FreeSurfer')

    MatlabCommand.set_default_matlab_cmd(get_matlab_command())
    matlab = MatlabCommand()
    matlab.inputs.paths = path_to_matlab_script
    matlab.inputs.script = """
    clinicasurfstat('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', %.3f, '%s', %.3f, '%s', %.3f);
    """ % (os.path.join(caps_dir, 'subjects'), output_dir, subjects_visits_tsv,
           covariates_to_design_matrix(pipeline_parameters['contrast'],
                                       pipeline_parameters['covariates']),
           pipeline_parameters['contrast'],
           get_string_format_from_tsv(subjects_visits_tsv),
           pipeline_parameters['glm_type'], pipeline_parameters['group_label'],
           freesurfer_home, pipeline_parameters['custom_file'],
           pipeline_parameters['measure_label'], 'sizeoffwhm',
           pipeline_parameters['full_width_at_half_maximum'],
           'thresholduncorrectedpvalue', 0.001, 'thresholdcorrectedpvalue',
           0.05, 'clusterthreshold', pipeline_parameters['cluster_threshold'])
    # This will create a file: pyscript.m , the pyscript.m is the default name
    matlab.inputs.mfile = True
    # This will stop running with single thread
    matlab.inputs.single_comp_thread = False
    matlab.inputs.logfile = 'group-' + pipeline_parameters[
        'group_label'] + '_matlab.log'

    # cprint("Matlab logfile is located at the following path: %s" % matlab.inputs.logfile)
    # cprint("Matlab script command = %s" % matlab.inputs.script)
    # cprint("MatlabCommand inputs flag: single_comp_thread = %s" % matlab.inputs.single_comp_thread)
    # cprint("MatlabCommand choose which matlab to use(matlab_cmd): %s" % get_matlab_command())
    matlab.run()

    return output_dir
예제 #2
0
    def build_core_nodes(self):
        """Build and connect the core nodes of the pipeline."""
        import os

        import nipype.interfaces.fsl as fsl
        import nipype.interfaces.mrtrix as mrtrix
        import nipype.interfaces.utility as nutil
        import nipype.pipeline.engine as npe
        from nipype.interfaces.ants import ApplyTransforms, RegistrationSynQuick
        from nipype.interfaces.mrtrix.preprocess import DWI2Tensor

        from clinica.lib.nipype.interfaces.mrtrix3.utils import TensorMetrics
        from clinica.utils.check_dependency import check_environment_variable

        from .dwi_dti_utils import (
            extract_bids_identifier_from_caps_filename,
            get_ants_transforms,
            get_caps_filenames,
            print_begin_pipeline,
            print_end_pipeline,
            statistics_on_atlases,
        )

        # Nodes creation
        # ==============
        get_bids_identifier = npe.Node(
            interface=nutil.Function(
                input_names=["caps_dwi_filename"],
                output_names=["bids_identifier"],
                function=extract_bids_identifier_from_caps_filename,
            ),
            name="0-Get_BIDS_Identifier",
        )

        get_caps_filenames = npe.Node(
            interface=nutil.Function(
                input_names=["caps_dwi_filename"],
                output_names=[
                    "bids_source",
                    "out_dti",
                    "out_fa",
                    "out_md",
                    "out_ad",
                    "out_rd",
                    "out_evec",
                ],
                function=get_caps_filenames,
            ),
            name="0-CAPS_Filenames",
        )

        convert_gradients = npe.Node(interface=mrtrix.FSL2MRTrix(),
                                     name="0-Convert_FSL_Gradient")

        dwi_to_dti = npe.Node(interface=DWI2Tensor(), name="1-Compute_DTI")

        dti_to_metrics = npe.Node(interface=TensorMetrics(),
                                  name="2-DTI-based_Metrics")

        register_fa = npe.Node(interface=RegistrationSynQuick(),
                               name="3a-Register_FA")
        fsl_dir = check_environment_variable("FSLDIR", "FSL")
        fa_map = os.path.join(fsl_dir, "data", "atlases", "JHU",
                              "JHU-ICBM-FA-1mm.nii.gz")
        register_fa.inputs.fixed_image = fa_map

        ants_transforms = npe.Node(
            interface=nutil.Function(
                input_names=[
                    "in_affine_transformation", "in_bspline_transformation"
                ],
                output_names=["transforms"],
                function=get_ants_transforms,
            ),
            name="combine_ants_transforms",
        )

        apply_ants_registration = npe.Node(interface=ApplyTransforms(),
                                           name="apply_ants_registration")
        apply_ants_registration.inputs.dimension = 3
        apply_ants_registration.inputs.input_image_type = 0
        apply_ants_registration.inputs.interpolation = "Linear"
        apply_ants_registration.inputs.reference_image = fa_map

        apply_ants_registration_for_md = apply_ants_registration.clone(
            "3b-Apply_ANTs_Registration_MD")
        apply_ants_registration_for_ad = apply_ants_registration.clone(
            "3b-Apply_ANTs_Registration_AD")
        apply_ants_registration_for_rd = apply_ants_registration.clone(
            "3b-Apply_ANTs_Registration_RD")

        thres_map = npe.Node(fsl.Threshold(thresh=0.0),
                             iterfield=["in_file"],
                             name="RemoveNegative")
        thres_norm_fa = thres_map.clone("3c-RemoveNegative_FA")
        thres_norm_md = thres_map.clone("3c-RemoveNegative_MD")
        thres_norm_ad = thres_map.clone("3c-RemoveNegative_AD")
        thres_norm_rd = thres_map.clone("3c-RemoveNegative_RD")

        scalar_analysis = npe.Node(
            interface=nutil.Function(
                input_names=["in_registered_map", "name_map", "prefix_file"],
                output_names=["atlas_statistics_list"],
                function=statistics_on_atlases,
            ),
            name="4-Scalar_Analysis",
        )
        scalar_analysis_fa = scalar_analysis.clone("4-Scalar_Analysis_FA")
        scalar_analysis_fa.inputs.name_map = "FA"
        scalar_analysis_md = scalar_analysis.clone("4-Scalar_Analysis_MD")
        scalar_analysis_md.inputs.name_map = "MD"
        scalar_analysis_ad = scalar_analysis.clone("4-Scalar_Analysis_AD")
        scalar_analysis_ad.inputs.name_map = "AD"
        scalar_analysis_rd = scalar_analysis.clone("4-Scalar_Analysis_RD")
        scalar_analysis_rd.inputs.name_map = "RD"

        thres_map = npe.Node(fsl.Threshold(thresh=0.0),
                             iterfield=["in_file"],
                             name="5-Remove_Negative")
        thres_fa = thres_map.clone("5-Remove_Negative_FA")
        thres_md = thres_map.clone("5-Remove_Negative_MD")
        thres_ad = thres_map.clone("5-Remove_Negative_AD")
        thres_rd = thres_map.clone("5-Remove_Negative_RD")
        thres_decfa = thres_map.clone("5-Remove_Negative_DECFA")

        print_begin_message = npe.Node(
            interface=nutil.Function(input_names=["in_bids_or_caps_file"],
                                     function=print_begin_pipeline),
            name="Write-Begin_Message",
        )

        print_end_message = npe.Node(
            interface=nutil.Function(
                input_names=[
                    "in_bids_or_caps_file", "final_file_1", "final_file_2"
                ],
                function=print_end_pipeline,
            ),
            name="Write-End_Message",
        )

        # Connection
        # ==========
        # fmt: off
        self.connect([
            (self.input_node, get_caps_filenames, [("preproc_dwi",
                                                    "caps_dwi_filename")]),
            # Print begin message
            (self.input_node, print_begin_message, [("preproc_dwi",
                                                     "in_bids_or_caps_file")]),
            # Get BIDS/CAPS identifier from filename
            (self.input_node, get_bids_identifier, [("preproc_dwi",
                                                     "caps_dwi_filename")]),
            # Convert FSL gradient files (bval/bvec) to MRtrix format
            (self.input_node, convert_gradients,
             [("preproc_bval", "bval_file"), ("preproc_bvec", "bvec_file")]),
            # Computation of the DTI model
            (self.input_node, dwi_to_dti, [("b0_mask", "mask"),
                                           ("preproc_dwi", "in_file")]),
            (convert_gradients, dwi_to_dti, [("encoding_file", "encoding_file")
                                             ]),
            (get_caps_filenames, dwi_to_dti, [("out_dti", "out_filename")]),
            # Computation of the different metrics from the DTI
            (get_caps_filenames, dti_to_metrics, [("out_fa", "out_fa")]),
            (get_caps_filenames, dti_to_metrics, [("out_md", "out_adc")]),
            (get_caps_filenames, dti_to_metrics, [("out_ad", "out_ad")]),
            (get_caps_filenames, dti_to_metrics, [("out_rd", "out_rd")]),
            (get_caps_filenames, dti_to_metrics, [("out_evec", "out_evec")]),
            (self.input_node, dti_to_metrics, [("b0_mask", "in_mask")]),
            (dwi_to_dti, dti_to_metrics, [("tensor", "in_file")]),
            # Registration of FA-map onto the atlas:
            (dti_to_metrics, register_fa, [("out_fa", "moving_image")]),
            # Apply deformation field on MD, AD & RD:
            (register_fa, ants_transforms, [("out_matrix",
                                             "in_affine_transformation")]),
            (register_fa, ants_transforms, [("forward_warp_field",
                                             "in_bspline_transformation")]),
            (dti_to_metrics, apply_ants_registration_for_md,
             [("out_adc", "input_image")]),
            (ants_transforms, apply_ants_registration_for_md,
             [("transforms", "transforms")]),
            (dti_to_metrics, apply_ants_registration_for_ad,
             [("out_ad", "input_image")]),
            (ants_transforms, apply_ants_registration_for_ad,
             [("transforms", "transforms")]),
            (dti_to_metrics, apply_ants_registration_for_rd,
             [("out_rd", "input_image")]),
            (ants_transforms, apply_ants_registration_for_rd,
             [("transforms", "transforms")]),
            # Remove negative values from the DTI maps:
            (register_fa, thres_norm_fa, [("warped_image", "in_file")]),
            (apply_ants_registration_for_md, thres_norm_md, [("output_image",
                                                              "in_file")]),
            (apply_ants_registration_for_rd, thres_norm_rd, [("output_image",
                                                              "in_file")]),
            (apply_ants_registration_for_ad, thres_norm_ad, [("output_image",
                                                              "in_file")]),
            # Generate regional TSV files
            (get_bids_identifier, scalar_analysis_fa, [("bids_identifier",
                                                        "prefix_file")]),
            (thres_norm_fa, scalar_analysis_fa, [("out_file",
                                                  "in_registered_map")]),
            (get_bids_identifier, scalar_analysis_md, [("bids_identifier",
                                                        "prefix_file")]),
            (thres_norm_md, scalar_analysis_md, [("out_file",
                                                  "in_registered_map")]),
            (get_bids_identifier, scalar_analysis_ad, [("bids_identifier",
                                                        "prefix_file")]),
            (thres_norm_ad, scalar_analysis_ad, [("out_file",
                                                  "in_registered_map")]),
            (get_bids_identifier, scalar_analysis_rd, [("bids_identifier",
                                                        "prefix_file")]),
            (thres_norm_rd, scalar_analysis_rd, [("out_file",
                                                  "in_registered_map")]),
            # Remove negative values from the DTI maps:
            (get_caps_filenames, thres_fa, [("out_fa", "out_file")]),
            (dti_to_metrics, thres_fa, [("out_fa", "in_file")]),
            (get_caps_filenames, thres_md, [("out_md", "out_file")]),
            (dti_to_metrics, thres_md, [("out_adc", "in_file")]),
            (get_caps_filenames, thres_ad, [("out_ad", "out_file")]),
            (dti_to_metrics, thres_ad, [("out_ad", "in_file")]),
            (get_caps_filenames, thres_rd, [("out_rd", "out_file")]),
            (dti_to_metrics, thres_rd, [("out_rd", "in_file")]),
            (get_caps_filenames, thres_decfa, [("out_evec", "out_file")]),
            (dti_to_metrics, thres_decfa, [("out_evec", "in_file")]),
            # Outputnode
            (dwi_to_dti, self.output_node, [("tensor", "dti")]),
            (thres_fa, self.output_node, [("out_file", "fa")]),
            (thres_md, self.output_node, [("out_file", "md")]),
            (thres_ad, self.output_node, [("out_file", "ad")]),
            (thres_rd, self.output_node, [("out_file", "rd")]),
            (thres_decfa, self.output_node, [("out_file", "decfa")]),
            (register_fa, self.output_node, [("out_matrix", "affine_matrix")]),
            (register_fa, self.output_node, [("forward_warp_field",
                                              "b_spline_transform")]),
            (thres_norm_fa, self.output_node, [("out_file", "registered_fa")]),
            (thres_norm_md, self.output_node, [("out_file", "registered_md")]),
            (thres_norm_ad, self.output_node, [("out_file", "registered_ad")]),
            (thres_norm_rd, self.output_node, [("out_file", "registered_rd")]),
            (scalar_analysis_fa, self.output_node, [("atlas_statistics_list",
                                                     "statistics_fa")]),
            (scalar_analysis_md, self.output_node, [("atlas_statistics_list",
                                                     "statistics_md")]),
            (scalar_analysis_ad, self.output_node, [("atlas_statistics_list",
                                                     "statistics_ad")]),
            (scalar_analysis_rd, self.output_node, [("atlas_statistics_list",
                                                     "statistics_rd")]),
            # Print end message
            (self.input_node, print_end_message, [("preproc_dwi",
                                                   "in_bids_or_caps_file")]),
            (thres_rd, print_end_message, [("out_file", "final_file_1")]),
            (scalar_analysis_rd, print_end_message, [("atlas_statistics_list",
                                                      "final_file_2")]),
        ])
예제 #3
0
def register_dti_maps_on_atlas(
        working_directory=None,
        name="register_dti_maps_on_atlas"):
    """
    Register FA-map on a subject towards a FA atlas and apply the estimated
    deformation to MD, AD & RD.

    This pipelines performs the analysis of tracts using a white matter atlas
    and computes mean value of the scalar on each tracts of this atlas. The
    pipelines registers the FA-map of a subject onto the FA-map of the atlas
    thanks to antsRegistrationSyNQuick. Then, the estimated deformation is
    applied to the MD-map, AD-map and RD-map. Finally, the labelled atlas
    is used to compute the statistics of each scalar on each tract of the white
    matter atlas.

    Args:
        working_directory (Optional[str]): Directory where the temporary
            results are stored. If not specified, it is
            automatically generated (generally in /tmp/).
        name (Optional[str]): Name of the pipelines.

    Inputnode:
        in_fa (str): FA-map of the subject in native space.
        in_md (str): MD-map of the subject in native space.
        in_ad (str): AD-map of the subject in native space.
        in_rd (str): RD-map of the subject in native space.

    Outputnode:
        out_affine_transform (str): Affine transformation matrix obtained by
            antsRegistrationSyNQuick after registration towards <atlas_name>.
        out_b_spline_transform (str): BSpline transformation obtained by
            antsRegistrationSyNQuick after registration towards <atlas_name>.
        out_norm_fa (str): FA-map registered on <atlas_name>.
        out_norm_md (str): MD-map registered on <atlas_name>.
        out_norm_ad (str): AD-map registered on <atlas_name>.
        out_norm_rd (str): RD-map registered on <atlas_name>.
    """
    import os
    import tempfile
    import nipype.interfaces.fsl as fsl
    import nipype.interfaces.utility as niu
    import nipype.pipeline.engine as pe
    from nipype.interfaces.ants import RegistrationSynQuick
    from clinica.utils.atlas import AtlasAbstract, JHUDTI811mm
    from clinica.utils.mri_registration import apply_ants_registration_syn_quick_transformation
    from clinica.utils.check_dependency import check_environment_variable

    atlas = JHUDTI811mm()

    if not isinstance(atlas, AtlasAbstract):
        raise Exception("Atlas element must be an AtlasAbstract type")

    if working_directory is None:
        working_directory = tempfile.mkdtemp()

    inputnode = pe.Node(niu.IdentityInterface(
        fields=['in_fa', 'in_md', 'in_ad', 'in_rd', 'in_atlas_scalar_image']),
        name='inputnode')
    fsl_dir = check_environment_variable('FSLDIR', 'FSL')
    fa_map = os.path.join(fsl_dir, 'data', 'atlases', 'JHU', 'JHU-ICBM-FA-1mm.nii.gz')
    inputnode.inputs.in_atlas_scalar_image = fa_map

    register_fa = pe.Node(
        interface=RegistrationSynQuick(),
        name='register_fa')

    apply_ants_registration_for_md = pe.Node(interface=niu.Function(
        input_names=['in_image', 'in_reference_image',
                     'in_affine_transformation', 'in_bspline_transformation',
                     'name_output_image'],
        output_names=['out_deformed_image'],
        function=apply_ants_registration_syn_quick_transformation),
        name='apply_ants_registration_for_md')
    apply_ants_registration_for_md.inputs.name_output_image = \
        'space-' + atlas.get_name_atlas() + '_res-' + atlas.get_spatial_resolution() + '_MD.nii.gz'
    apply_ants_registration_for_ad = pe.Node(interface=niu.Function(
        input_names=['in_image', 'in_reference_image',
                     'in_affine_transformation', 'in_bspline_transformation',
                     'name_output_image'],
        output_names=['out_deformed_image'],
        function=apply_ants_registration_syn_quick_transformation),
        name='apply_ants_registration_for_ad')
    apply_ants_registration_for_ad.inputs.name_output_image = \
        'space-' + atlas.get_name_atlas() + '_res-' + atlas.get_spatial_resolution() + '_AD.nii.gz'
    apply_ants_registration_for_rd = pe.Node(interface=niu.Function(
        input_names=['in_image', 'in_reference_image',
                     'in_affine_transformation', 'in_bspline_transformation',
                     'name_output_image'],
        output_names=['out_deformed_image'],
        function=apply_ants_registration_syn_quick_transformation),
        name='apply_ants_registration_for_rd')
    apply_ants_registration_for_rd.inputs.name_output_image = \
        'space-' + atlas.get_name_atlas() + '_res-' + atlas.get_spatial_resolution() + '_RD.nii.gz'

    thres_map = pe.Node(fsl.Threshold(thresh=0.0),
                        iterfield=['in_file'],
                        name='RemoveNegative')
    thres_fa = thres_map.clone('RemoveNegative_FA')
    thres_md = thres_map.clone('RemoveNegative_MD')
    thres_ad = thres_map.clone('RemoveNegative_AD')
    thres_rd = thres_map.clone('RemoveNegative_RD')

    outputnode = pe.Node(niu.IdentityInterface(
        fields=['out_norm_fa', 'out_norm_md', 'out_norm_ad', 'out_norm_rd',
                'out_affine_matrix', 'out_b_spline_transform']),
        name='outputnode')

    wf = pe.Workflow(name=name, base_dir=working_directory)
    wf.connect([
        # Registration of FA-map onto the atlas:
        (inputnode, register_fa, [('in_fa',                 'moving_image'),  # noqa
                                  ('in_atlas_scalar_image', 'fixed_image')]),  # noqa
        # Apply deformation field on MD, AD & RD:
        (inputnode,   apply_ants_registration_for_md, [('in_md',                 'in_image')]),  # noqa
        (inputnode,   apply_ants_registration_for_md, [('in_atlas_scalar_image', 'in_reference_image')]),  # noqa
        (register_fa, apply_ants_registration_for_md, [('out_matrix',            'in_affine_transformation')]),  # noqa
        (register_fa, apply_ants_registration_for_md, [('forward_warp_field',    'in_bspline_transformation')]),  # noqa

        (inputnode,   apply_ants_registration_for_ad, [('in_ad',                 'in_image')]),  # noqa
        (inputnode,   apply_ants_registration_for_ad, [('in_atlas_scalar_image', 'in_reference_image')]),  # noqa
        (register_fa, apply_ants_registration_for_ad, [('out_matrix',            'in_affine_transformation')]),  # noqa
        (register_fa, apply_ants_registration_for_ad, [('forward_warp_field',    'in_bspline_transformation')]),  # noqa

        (inputnode,   apply_ants_registration_for_rd, [('in_rd',                 'in_image')]),  # noqa
        (inputnode,   apply_ants_registration_for_rd, [('in_atlas_scalar_image', 'in_reference_image')]),  # noqa
        (register_fa, apply_ants_registration_for_rd, [('out_matrix',            'in_affine_transformation')]),  # noqa
        (register_fa, apply_ants_registration_for_rd, [('forward_warp_field',    'in_bspline_transformation')]),  # noqa
        # Remove negative values from the DTI maps:
        (register_fa,                    thres_fa, [('warped_image',       'in_file')]),  # noqa
        (apply_ants_registration_for_md, thres_md, [('out_deformed_image', 'in_file')]),  # noqa
        (apply_ants_registration_for_rd, thres_rd, [('out_deformed_image', 'in_file')]),  # noqa
        (apply_ants_registration_for_ad, thres_ad, [('out_deformed_image', 'in_file')]),  # noqa
        # Outputnode:
        (thres_fa,    outputnode, [('out_file',           'out_norm_fa')]),  # noqa
        (register_fa, outputnode, [('out_matrix',         'out_affine_matrix'),  # noqa
                                   ('forward_warp_field', 'out_b_spline_transform'),  # noqa
                                   ('inverse_warp_field', 'out_inverse_warp')]),  # noqa
        (thres_md,    outputnode,  [('out_file',          'out_norm_md')]),  # noqa
        (thres_ad,    outputnode,  [('out_file',          'out_norm_ad')]),  # noqa
        (thres_rd,    outputnode,  [('out_file',          'out_norm_rd')])   # noqa
    ])

    return wf