Exemplo n.º 1
0
def test_Eddy_inputs():
    input_map = dict(args=dict(argstr='%s',
    ),
    environ=dict(nohash=True,
    usedefault=True,
    ),
    flm=dict(argstr='--flm=%s',
    ),
    fwhm=dict(argstr='--fwhm=%s',
    ),
    ignore_exception=dict(nohash=True,
    usedefault=True,
    ),
    in_acqp=dict(argstr='--acqp=%s',
    mandatory=True,
    ),
    in_bval=dict(argstr='--bvals=%s',
    mandatory=True,
    ),
    in_bvec=dict(argstr='--bvecs=%s',
    mandatory=True,
    ),
    in_file=dict(argstr='--imain=%s',
    mandatory=True,
    ),
    in_index=dict(argstr='--index=%s',
    mandatory=True,
    ),
    in_mask=dict(argstr='--mask=%s',
    mandatory=True,
    ),
    in_topup_fieldcoef=dict(argstr='--topup=%s',
    requires=['in_topup_movpar'],
    ),
    in_topup_movpar=dict(requires=['in_topup_fieldcoef'],
    ),
    method=dict(argstr='--resamp=%s',
    ),
    niter=dict(argstr='--niter=%s',
    ),
    num_threads=dict(nohash=True,
    usedefault=True,
    ),
    out_base=dict(argstr='--out=%s',
    usedefault=True,
    ),
    output_type=dict(),
    repol=dict(argstr='--repol',
    ),
    session=dict(argstr='--session=%s',
    ),
    terminal_output=dict(mandatory=True,
    nohash=True,
    ),
    )
    inputs = Eddy.input_spec()

    for key, metadata in input_map.items():
        for metakey, value in metadata.items():
            yield assert_equal, getattr(inputs.traits()[key], metakey), value
Exemplo n.º 2
0
def test_Eddy_outputs():
    output_map = dict(out_corrected=dict(),
    out_parameter=dict(),
    )
    outputs = Eddy.output_spec()

    for key, metadata in output_map.items():
        for metakey, value in metadata.items():
            yield assert_equal, getattr(outputs.traits()[key], metakey), value
Exemplo n.º 3
0
def test_Eddy_outputs():
    output_map = dict(
        out_corrected=dict(),
        out_parameter=dict(),
    )
    outputs = Eddy.output_spec()

    for key, metadata in output_map.items():
        for metakey, value in metadata.items():
            yield assert_equal, getattr(outputs.traits()[key], metakey), value
Exemplo n.º 4
0
def test_Eddy_inputs():
    input_map = dict(
        args=dict(argstr='%s', ),
        environ=dict(
            nohash=True,
            usedefault=True,
        ),
        flm=dict(argstr='--flm=%s', ),
        fwhm=dict(argstr='--fwhm=%s', ),
        ignore_exception=dict(
            nohash=True,
            usedefault=True,
        ),
        in_acqp=dict(
            argstr='--acqp=%s',
            mandatory=True,
        ),
        in_bval=dict(
            argstr='--bvals=%s',
            mandatory=True,
        ),
        in_bvec=dict(
            argstr='--bvecs=%s',
            mandatory=True,
        ),
        in_file=dict(
            argstr='--imain=%s',
            mandatory=True,
        ),
        in_index=dict(
            argstr='--index=%s',
            mandatory=True,
        ),
        in_mask=dict(
            argstr='--mask=%s',
            mandatory=True,
        ),
        in_topup=dict(argstr='--topup=%s', ),
        method=dict(argstr='--resamp=%s', ),
        niter=dict(argstr='--niter=%s', ),
        out_base=dict(argstr='--out=%s', ),
        output_type=dict(),
        repol=dict(argstr='--repol', ),
        session=dict(argstr='--session=%s', ),
        terminal_output=dict(
            mandatory=True,
            nohash=True,
        ),
    )
    inputs = Eddy.input_spec()

    for key, metadata in input_map.items():
        for metakey, value in metadata.items():
            yield assert_equal, getattr(inputs.traits()[key], metakey), value
    def build_core_nodes(self):
        """Build and connect the core nodes of the pipeline."""
        import nipype.interfaces.ants as ants
        import nipype.interfaces.fsl as fsl
        import nipype.interfaces.mrtrix3 as mrtrix3
        import nipype.interfaces.utility as nutil
        import nipype.interfaces.utility as niu
        import nipype.pipeline.engine as npe
        from nipype.interfaces.fsl.epi import Eddy

        from clinica.utils.dwi import (
            compute_average_b0,
            generate_acq_file,
            generate_index_file,
        )

        from .dwi_preprocessing_using_phasediff_fmap_utils import (
            get_grad_fsl,
            init_input_node,
            print_end_pipeline,
        )
        from .dwi_preprocessing_using_phasediff_fmap_workflows import (
            prepare_phasediff_fmap, )

        # Step 0: Initialization
        # ======================
        # Initialize input parameters and print begin message
        init_node = npe.Node(
            interface=nutil.Function(
                input_names=self.get_input_fields(),
                output_names=[
                    "image_id",
                    "dwi",
                    "bvec",
                    "bval",
                    "total_readout_time",
                    "phase_encoding_direction",
                    "fmap_magnitude",
                    "fmap_phasediff",
                    "delta_echo_time",
                ],
                function=init_input_node,
            ),
            name="0-InitNode",
        )

        # Generate (bvec, bval) tuple for MRtrix interfaces
        get_grad_fsl = npe.Node(
            nutil.Function(
                input_names=["bval", "bvec"],
                output_names=["grad_fsl"],
                function=get_grad_fsl,
            ),
            name="0-GetFslGrad",
        )

        # Generate <image_id>_acq.txt for eddy
        gen_acq_txt = npe.Node(
            nutil.Function(
                input_names=[
                    "in_dwi",
                    "fsl_phase_encoding_direction",
                    "total_readout_time",
                    "image_id",
                ],
                output_names=["out_acq"],
                function=generate_acq_file,
            ),
            name="0-GenerateAcqFile",
        )

        # Generate <image_id>_index.txt for eddy
        gen_index_txt = npe.Node(
            nutil.Function(
                input_names=["in_bval", "low_bval", "image_id"],
                output_names=["out_index"],
                function=generate_index_file,
            ),
            name="0-GenerateIndexFile",
        )
        gen_index_txt.inputs.low_bval = self.parameters["low_bval"]

        # Step 1: Computation of the reference b0 (i.e. average b0 but with EPI distortions)
        # =======================================
        # Compute whole brain mask
        pre_mask_b0 = npe.Node(mrtrix3.BrainMask(), name="1a-PreMaskB0")
        pre_mask_b0.inputs.out_file = (
            "brainmask.nii.gz"  # On default, .mif file is generated
        )

        # Run eddy without calibrated fmap
        pre_eddy = npe.Node(name="1b-PreEddy", interface=Eddy())
        pre_eddy.inputs.repol = True
        pre_eddy.inputs.use_cuda = self.parameters["use_cuda"]
        pre_eddy.inputs.initrand = self.parameters["initrand"]

        # Compute the reference b0
        compute_ref_b0 = npe.Node(
            niu.Function(
                input_names=["in_dwi", "in_bval"],
                output_names=["out_b0_average"],
                function=compute_average_b0,
            ),
            name="1c-ComputeReferenceB0",
        )
        compute_ref_b0.inputs.low_bval = self.parameters["low_bval"]

        # Compute brain mask from reference b0
        mask_ref_b0 = npe.Node(fsl.BET(mask=True, robust=True),
                               name="1d-MaskReferenceB0")

        # Step 2: Calibrate and register FMap
        # ===================================
        # Bias field correction of the magnitude image
        bias_mag_fmap = npe.Node(ants.N4BiasFieldCorrection(dimension=3),
                                 name="2a-N4MagnitudeFmap")
        # Brain extraction of the magnitude image
        bet_mag_fmap = npe.Node(fsl.BET(frac=0.4, mask=True),
                                name="2b-BetN4MagnitudeFmap")

        # Calibrate FMap
        calibrate_fmap = prepare_phasediff_fmap(name="2c-CalibrateFMap")

        # Register the BET magnitude fmap onto the BET b0
        bet_mag_fmap2b0 = npe.Node(interface=fsl.FLIRT(),
                                   name="2d-RegistrationBetMagToB0")
        bet_mag_fmap2b0.inputs.dof = 6
        bet_mag_fmap2b0.inputs.output_type = "NIFTI_GZ"

        # Apply the transformation on the calibrated fmap
        fmap2b0 = npe.Node(interface=fsl.ApplyXFM(), name="2e-1-FMapToB0")
        fmap2b0.inputs.output_type = "NIFTI_GZ"

        # Apply the transformation on the magnitude image
        mag_fmap2b0 = fmap2b0.clone("2e-2-MagFMapToB0")

        # Smooth the registered (calibrated) fmap
        smoothing = npe.Node(interface=fsl.maths.IsotropicSmooth(),
                             name="2f-Smoothing")
        smoothing.inputs.sigma = 4.0

        # Step 3: Run FSL eddy
        # ====================
        eddy = pre_eddy.clone("3-Eddy")

        # Step 4: Bias correction
        # =======================
        # Use implementation detailed in (Jeurissen et al., 2014)
        bias = npe.Node(mrtrix3.DWIBiasCorrect(use_ants=True),
                        name="4-RemoveBias")

        # Step 5: Final brainmask
        # =======================
        # Compute average b0 on corrected dataset (for brain mask extraction)
        compute_avg_b0 = compute_ref_b0.clone("5a-ComputeB0Average")

        # Compute b0 mask on corrected avg b0
        mask_avg_b0 = mask_ref_b0.clone("5b-MaskB0")

        # Print end message
        print_end_message = npe.Node(
            interface=nutil.Function(input_names=["image_id", "final_file"],
                                     function=print_end_pipeline),
            name="99-WriteEndMessage",
        )

        # Connection
        # ==========
        # fmt: off
        self.connect([
            # Step 0: Initialization
            # ======================
            # Initialize input parameters and print begin message
            (self.input_node, init_node, [("dwi", "dwi"), ("bvec", "bvec"),
                                          ("bval", "bval"),
                                          ("dwi_json", "dwi_json"),
                                          ("fmap_magnitude", "fmap_magnitude"),
                                          ("fmap_phasediff", "fmap_phasediff"),
                                          ("fmap_phasediff_json",
                                           "fmap_phasediff_json")]),
            # Generate (bvec, bval) tuple for MRtrix interfaces
            (init_node, get_grad_fsl, [("bval", "bval"), ("bvec", "bvec")]),
            # Generate <image_id>_acq.txt for eddy
            (init_node, gen_acq_txt,
             [("dwi", "in_dwi"), ("total_readout_time", "total_readout_time"),
              ("phase_encoding_direction", "fsl_phase_encoding_direction"),
              ("image_id", "image_id")]),
            # Generate <image_id>_index.txt for eddy
            (init_node, gen_index_txt, [("bval", "in_bval"),
                                        ("image_id", "image_id")]),

            # Step 1: Computation of the reference b0 (i.e. average b0 but with EPI distortions)
            # =======================================
            # Compute whole brain mask
            (get_grad_fsl, pre_mask_b0, [("grad_fsl", "grad_fsl")]),
            (init_node, pre_mask_b0, [("dwi", "in_file")]),
            # Run eddy without calibrated fmap
            (init_node, pre_eddy, [("dwi", "in_file"), ("bval", "in_bval"),
                                   ("bvec", "in_bvec"),
                                   ("image_id", "out_base")]),
            (gen_acq_txt, pre_eddy, [("out_acq", "in_acqp")]),
            (gen_index_txt, pre_eddy, [("out_index", "in_index")]),
            (pre_mask_b0, pre_eddy, [("out_file", "in_mask")]),
            # Compute the reference b0
            (init_node, compute_ref_b0, [("bval", "in_bval")]),
            (pre_eddy, compute_ref_b0, [("out_corrected", "in_dwi")]),
            # Compute brain mask from reference b0
            (compute_ref_b0, mask_ref_b0, [("out_b0_average", "in_file")]),

            # Step 2: Calibrate and register FMap
            # ===================================
            # Bias field correction of the magnitude image
            (init_node, bias_mag_fmap, [("fmap_magnitude", "input_image")]),
            # Brain extraction of the magnitude image
            (bias_mag_fmap, bet_mag_fmap, [("output_image", "in_file")]),
            # Calibration of the FMap
            (bet_mag_fmap, calibrate_fmap,
             [("mask_file", "input_node.fmap_mask"),
              ("out_file", "input_node.fmap_magnitude")]),
            (init_node, calibrate_fmap,
             [("fmap_phasediff", "input_node.fmap_phasediff"),
              ("delta_echo_time", "input_node.delta_echo_time")]),
            # Register the BET magnitude fmap onto the BET b0
            (bet_mag_fmap, bet_mag_fmap2b0, [("out_file", "in_file")]),
            (mask_ref_b0, bet_mag_fmap2b0, [("out_file", "reference")]),
            # Apply the transformation on the magnitude image
            (bet_mag_fmap2b0, mag_fmap2b0, [("out_matrix_file",
                                             "in_matrix_file")]),
            (bias_mag_fmap, mag_fmap2b0, [("output_image", "in_file")]),
            (mask_ref_b0, mag_fmap2b0, [("out_file", "reference")]),
            # Apply the transformation on the calibrated fmap
            (bet_mag_fmap2b0, fmap2b0, [("out_matrix_file", "in_matrix_file")]
             ),
            (calibrate_fmap, fmap2b0, [("output_node.calibrated_fmap",
                                        "in_file")]),
            (mask_ref_b0, fmap2b0, [("out_file", "reference")]),
            # # Smooth the registered (calibrated) fmap
            (fmap2b0, smoothing, [("out_file", "in_file")]),

            # Step 3: Run FSL eddy
            # ====================
            (init_node, eddy, [("dwi", "in_file"), ("bval", "in_bval"),
                               ("bvec", "in_bvec"), ("image_id", "out_base")]),
            (gen_acq_txt, eddy, [("out_acq", "in_acqp")]),
            (gen_index_txt, eddy, [("out_index", "in_index")]),
            (smoothing, eddy, [("out_file", "field")]),
            (pre_mask_b0, eddy, [("out_file", "in_mask")]),

            # Step 4: Bias correction
            # =======================
            (init_node, bias, [("bval", "in_bval")]),
            (eddy, bias, [("out_rotated_bvecs", "in_bvec"),
                          ("out_corrected", "in_file")]),
            # Step 5: Final brainmask
            # =======================
            # Compute average b0 on corrected dataset (for brain mask extraction)
            (init_node, compute_avg_b0, [("bval", "in_bval")]),
            (bias, compute_avg_b0, [("out_file", "in_dwi")]),
            # Compute b0 mask on corrected avg b0
            (compute_avg_b0, mask_avg_b0, [("out_b0_average", "in_file")]),

            # Print end message
            (init_node, print_end_message, [("image_id", "image_id")]),
            (mask_avg_b0, print_end_message, [("mask_file", "final_file")]),

            # Output node
            (init_node, self.output_node, [("bval", "preproc_bval")]),
            (eddy, self.output_node, [("out_rotated_bvecs", "preproc_bvec")]),
            (bias, self.output_node, [("out_file", "preproc_dwi")]),
            (mask_avg_b0, self.output_node, [("mask_file", "b0_mask")]),
            (bet_mag_fmap2b0, self.output_node, [("out_file",
                                                  "magnitude_on_b0")]),
            (fmap2b0, self.output_node, [("out_file", "calibrated_fmap_on_b0")
                                         ]),
            (smoothing, self.output_node, [("out_file", "smoothed_fmap_on_b0")
                                           ]),
        ])
def eddy_fsl_pipeline(low_bval, use_cuda, initrand, name="eddy_fsl"):
    """Use FSL eddy for head motion correction and eddy current distortion correction."""
    import nipype.interfaces.utility as niu
    import nipype.pipeline.engine as pe
    from nipype.interfaces.fsl.epi import Eddy
    from clinica.utils.dwi import generate_acq_file, generate_index_file

    inputnode = pe.Node(
        niu.IdentityInterface(fields=[
            "in_file",
            "in_bvec",
            "in_bval",
            "in_mask",
            "ref_b0",
            "total_readout_time",
            "phase_encoding_direction",
        ]),
        name="inputnode",
    )

    generate_acq = pe.Node(
        niu.Function(
            input_names=[
                "in_dwi",
                "fsl_phase_encoding_direction",
                "total_readout_time",
            ],
            output_names=["out_file"],
            function=generate_acq_file,
        ),
        name="generate_acq",
    )

    generate_index = pe.Node(
        niu.Function(
            input_names=["in_bval", "low_bval"],
            output_names=["out_file"],
            function=generate_index_file,
        ),
        name="generate_index",
    )
    generate_index.inputs.low_bval = low_bval

    eddy = pe.Node(interface=Eddy(), name="eddy_fsl")
    eddy.inputs.repol = True
    eddy.inputs.use_cuda = use_cuda
    eddy.inputs.initrand = initrand

    outputnode = pe.Node(
        niu.IdentityInterface(
            fields=["out_parameter", "out_corrected", "out_rotated_bvecs"]),
        name="outputnode",
    )

    wf = pe.Workflow(name=name)
    # fmt: off
    wf.connect([(inputnode, generate_acq, [('in_file', 'in_dwi')]),
                (inputnode, generate_acq, [('total_readout_time',
                                            'total_readout_time')]),
                (inputnode, generate_acq, [('phase_encoding_direction',
                                            'fsl_phase_encoding_direction')]),
                (inputnode, generate_index, [('in_bval', 'in_bval')]),
                (inputnode, eddy, [('in_bvec', 'in_bvec')]),
                (inputnode, eddy, [('in_bval', 'in_bval')]),
                (inputnode, eddy, [('in_file', 'in_file')]),
                (inputnode, eddy, [('in_mask', 'in_mask')]),
                (generate_acq, eddy, [('out_file', 'in_acqp')]),
                (generate_index, eddy, [('out_file', 'in_index')]),
                (eddy, outputnode, [('out_parameter', 'out_parameter')]),
                (eddy, outputnode, [('out_corrected', 'out_corrected')]),
                (eddy, outputnode, [('out_rotated_bvecs', 'out_rotated_bvecs')
                                    ])])
    # fmt: on
    return wf