Exemplo n.º 1
0
 def test_BBRegisterRPT(self):
     """ the BBRegister report capable test """
     subject_id = 'fsaverage'
     bbregister_rpt = BBRegisterRPT(generate_report=True,
                                    contrast_type='t1',
                                    init='fsl',
                                    source_file=self.moving,
                                    subject_id=subject_id,
                                    registered_file=True)
     _smoke_test_report(bbregister_rpt, 'testBBRegister.svg')
Exemplo n.º 2
0
def test_BBRegisterRPT(monkeypatch, moving):
    """ the BBRegister report capable test """
    def _agg(objekt, runtime):
        outputs = Bunch(out_lta_file=os.path.join(
            datadir, 'testBBRegisterRPT-out_lta_file.lta'), )
        return outputs

    # Patch the _run_interface method
    monkeypatch.setattr(BBRegisterRPT, '_run_interface', _run_interface_mock)
    monkeypatch.setattr(BBRegisterRPT, 'aggregate_outputs', _agg)

    subject_id = 'fsaverage'
    bbregister_rpt = BBRegisterRPT(generate_report=True,
                                   contrast_type='t1',
                                   init='fsl',
                                   source_file=moving,
                                   subject_id=subject_id,
                                   registered_file=True)
    _smoke_test_report(bbregister_rpt, 'testBBRegister.svg')
Exemplo n.º 3
0
def test_BBRegisterRPT(monkeypatch, moving):
    """ the BBRegister report capable test """
    def _agg(objekt, runtime):
        outputs = objekt.output_spec()
        outputs.out_lta_file = os.path.join(
            datadir, "testBBRegisterRPT-out_lta_file.lta")
        outputs.out_report = os.path.join(runtime.cwd,
                                          objekt.inputs.out_report)
        return outputs

    # Patch the _run_interface method
    monkeypatch.setattr(BBRegisterRPT, "_run_interface", _run_interface_mock)
    monkeypatch.setattr(BBRegisterRPT, "aggregate_outputs", _agg)

    subject_id = "fsaverage"
    bbregister_rpt = BBRegisterRPT(
        generate_report=True,
        contrast_type="t1",
        init="fsl",
        source_file=moving,
        subject_id=subject_id,
        registered_file=True,
    )
    _smoke_test_report(bbregister_rpt, "testBBRegister.svg")
Exemplo n.º 4
0
def init_bbreg_wf(use_bbr, bold2t1w_dof, omp_nthreads, name='bbreg_wf'):
    """
    This workflow uses FreeSurfer's ``bbregister`` to register a BOLD image to
    a T1-weighted structural image.

    It is a counterpart to :py:func:`~fmriprep.workflows.util.init_fsl_bbr_wf`,
    which performs the same task using FSL's FLIRT with a BBR cost function.

    The ``use_bbr`` option permits a high degree of control over registration.
    If ``False``, standard, affine coregistration will be performed using
    FreeSurfer's ``mri_coreg`` tool.
    If ``True``, ``bbregister`` will be seeded with the initial transform found
    by ``mri_coreg`` (equivalent to running ``bbregister --init-coreg``).
    If ``None``, after ``bbregister`` is run, the resulting affine transform
    will be compared to the initial transform found by ``mri_coreg``.
    Excessive deviation will result in rejecting the BBR refinement and
    accepting the original, affine registration.

    .. workflow ::
        :graph2use: orig
        :simple_form: yes

        from fmriprep.workflows.bold.registration import init_bbreg_wf
        wf = init_bbreg_wf(use_bbr=True, bold2t1w_dof=9, omp_nthreads=1)


    Parameters

        use_bbr : bool or None
            Enable/disable boundary-based registration refinement.
            If ``None``, test BBR result for distortion before accepting.
        bold2t1w_dof : 6, 9 or 12
            Degrees-of-freedom for BOLD-T1w registration
        name : str, optional
            Workflow name (default: bbreg_wf)


    Inputs

        in_file
            Reference BOLD image to be registered
        t1_2_fsnative_reverse_transform
            FSL-style affine matrix translating from FreeSurfer T1.mgz to T1w
        subjects_dir
            FreeSurfer SUBJECTS_DIR
        subject_id
            FreeSurfer subject ID (must have folder in SUBJECTS_DIR)
        t1_brain
            Unused (see :py:func:`~fmriprep.workflows.util.init_fsl_bbr_wf`)
        t1_seg
            Unused (see :py:func:`~fmriprep.workflows.util.init_fsl_bbr_wf`)


    Outputs

        itk_bold_to_t1
            Affine transform from ``ref_bold_brain`` to T1 space (ITK format)
        itk_t1_to_bold
            Affine transform from T1 space to BOLD space (ITK format)
        out_report
            Reportlet for assessing registration quality
        fallback
            Boolean indicating whether BBR was rejected (mri_coreg registration returned)

    """
    workflow = Workflow(name=name)
    workflow.__desc__ = """\
The BOLD reference was then co-registered to the T1w reference using
`bbregister` (FreeSurfer) which implements boundary-based registration [@bbr].
Co-registration was configured with nine degrees of freedom to account
for distortions remaining in the BOLD reference.
"""

    inputnode = pe.Node(
        niu.IdentityInterface([
            'in_file',
            't1_2_fsnative_reverse_transform',
            'subjects_dir',
            'subject_id',  # BBRegister
            't1_seg',
            't1_brain'
        ]),  # FLIRT BBR
        name='inputnode')
    outputnode = pe.Node(niu.IdentityInterface(
        ['itk_bold_to_t1', 'itk_t1_to_bold', 'out_report', 'fallback']),
                         name='outputnode')

    mri_coreg = pe.Node(MRICoregRPT(dof=bold2t1w_dof,
                                    sep=[4],
                                    ftol=0.0001,
                                    linmintol=0.01,
                                    generate_report=not use_bbr),
                        name='mri_coreg',
                        n_procs=omp_nthreads,
                        mem_gb=5)

    lta_concat = pe.Node(ConcatenateLTA(out_file='out.lta'), name='lta_concat')
    # XXX LTA-FSL-ITK may ultimately be able to be replaced with a straightforward
    # LTA-ITK transform, but right now the translation parameters are off.
    lta2fsl_fwd = pe.Node(fs.utils.LTAConvert(out_fsl=True),
                          name='lta2fsl_fwd')
    lta2fsl_inv = pe.Node(fs.utils.LTAConvert(out_fsl=True, invert=True),
                          name='lta2fsl_inv')
    fsl2itk_fwd = pe.Node(c3.C3dAffineTool(fsl2ras=True, itk_transform=True),
                          name='fsl2itk_fwd',
                          mem_gb=DEFAULT_MEMORY_MIN_GB)
    fsl2itk_inv = pe.Node(c3.C3dAffineTool(fsl2ras=True, itk_transform=True),
                          name='fsl2itk_inv',
                          mem_gb=DEFAULT_MEMORY_MIN_GB)

    workflow.connect([
        (inputnode, mri_coreg, [('subjects_dir', 'subjects_dir'),
                                ('subject_id', 'subject_id'),
                                ('in_file', 'source_file')]),
        # Output ITK transforms
        (inputnode, lta_concat, [('t1_2_fsnative_reverse_transform', 'in_lta2')
                                 ]),
        (lta_concat, lta2fsl_fwd, [('out_file', 'in_lta')]),
        (lta_concat, lta2fsl_inv, [('out_file', 'in_lta')]),
        (inputnode, fsl2itk_fwd, [('t1_brain', 'reference_file'),
                                  ('in_file', 'source_file')]),
        (inputnode, fsl2itk_inv, [('in_file', 'reference_file'),
                                  ('t1_brain', 'source_file')]),
        (lta2fsl_fwd, fsl2itk_fwd, [('out_fsl', 'transform_file')]),
        (lta2fsl_inv, fsl2itk_inv, [('out_fsl', 'transform_file')]),
        (fsl2itk_fwd, outputnode, [('itk_transform', 'itk_bold_to_t1')]),
        (fsl2itk_inv, outputnode, [('itk_transform', 'itk_t1_to_bold')]),
    ])

    # Short-circuit workflow building, use initial registration
    if use_bbr is False:
        workflow.connect([
            (mri_coreg, outputnode, [('out_report', 'out_report')]),
            (mri_coreg, lta_concat, [('out_lta_file', 'in_lta1')])
        ])
        outputnode.inputs.fallback = True

        return workflow

    bbregister = pe.Node(BBRegisterRPT(dof=bold2t1w_dof,
                                       contrast_type='t2',
                                       registered_file=True,
                                       out_lta_file=True,
                                       generate_report=True),
                         name='bbregister',
                         mem_gb=12)

    workflow.connect([
        (inputnode, bbregister, [('subjects_dir', 'subjects_dir'),
                                 ('subject_id', 'subject_id'),
                                 ('in_file', 'source_file')]),
        (mri_coreg, bbregister, [('out_lta_file', 'init_reg_file')]),
    ])

    # Short-circuit workflow building, use boundary-based registration
    if use_bbr is True:
        workflow.connect([
            (bbregister, outputnode, [('out_report', 'out_report')]),
            (bbregister, lta_concat, [('out_lta_file', 'in_lta1')])
        ])
        outputnode.inputs.fallback = False

        return workflow

    transforms = pe.Node(niu.Merge(2),
                         run_without_submitting=True,
                         name='transforms')
    reports = pe.Node(niu.Merge(2),
                      run_without_submitting=True,
                      name='reports')

    lta_ras2ras = pe.MapNode(fs.utils.LTAConvert(out_lta=True),
                             iterfield=['in_lta'],
                             name='lta_ras2ras',
                             mem_gb=2)
    compare_transforms = pe.Node(niu.Function(function=compare_xforms),
                                 name='compare_transforms')

    select_transform = pe.Node(niu.Select(),
                               run_without_submitting=True,
                               name='select_transform')
    select_report = pe.Node(niu.Select(),
                            run_without_submitting=True,
                            name='select_report')

    workflow.connect([
        (bbregister, transforms, [('out_lta_file', 'in1')]),
        (mri_coreg, transforms, [('out_lta_file', 'in2')]),
        # Normalize LTA transforms to RAS2RAS (inputs are VOX2VOX) and compare
        (transforms, lta_ras2ras, [('out', 'in_lta')]),
        (lta_ras2ras, compare_transforms, [('out_lta', 'lta_list')]),
        (compare_transforms, outputnode, [('out', 'fallback')]),
        # Select output transform
        (transforms, select_transform, [('out', 'inlist')]),
        (compare_transforms, select_transform, [('out', 'index')]),
        (select_transform, lta_concat, [('out', 'in_lta1')]),
        # Select output report
        (bbregister, reports, [('out_report', 'in1')]),
        (mri_coreg, reports, [('out_report', 'in2')]),
        (reports, select_report, [('out', 'inlist')]),
        (compare_transforms, select_report, [('out', 'index')]),
        (select_report, outputnode, [('out', 'out_report')]),
    ])

    return workflow
Exemplo n.º 5
0
def init_epi_reg_wf(freesurfer, bold2t1w_dof,
                    bold_file_size_gb, output_spaces, output_dir,
                    name='epi_reg_wf', use_fieldwarp=False):
    """
    Uses FSL FLIRT with the BBR cost function to find the transform that
    maps the EPI space into the T1-space
    """
    workflow = pe.Workflow(name=name)
    inputnode = pe.Node(
        niu.IdentityInterface(fields=['name_source', 'ref_epi_brain', 'ref_epi_mask',
                                      't1_preproc', 't1_brain', 't1_mask',
                                      't1_seg', 'epi_split', 'hmc_xforms',
                                      'subjects_dir', 'subject_id', 'fs_2_t1_transform',
                                      'fieldwarp']),
        name='inputnode'
    )
    outputnode = pe.Node(
        niu.IdentityInterface(fields=['mat_epi_to_t1', 'mat_t1_to_epi',
                                      'itk_epi_to_t1', 'itk_t1_to_epi',
                                      'epi_t1', 'epi_mask_t1', 'fs_reg_file',
                                      'out_report']),
        name='outputnode'
    )

    if freesurfer:
        bbregister = pe.Node(
            BBRegisterRPT(
                dof=bold2t1w_dof,
                contrast_type='t2',
                init='coreg',
                registered_file=True,
                out_fsl_file=True,
                generate_report=True),
            name='bbregister'
            )

        def apply_fs_transform(fs_2_t1_transform, bbreg_transform):
            import os
            import numpy as np
            out_file = os.path.abspath('transform.mat')
            fs_xfm = np.loadtxt(fs_2_t1_transform)
            bbrxfm = np.loadtxt(bbreg_transform)
            out_xfm = fs_xfm.dot(bbrxfm)
            assert np.allclose(out_xfm[3], [0, 0, 0, 1])
            out_xfm[3] = [0, 0, 0, 1]
            np.savetxt(out_file, out_xfm, fmt='%.12g')
            return out_file

        transformer = pe.Node(niu.Function(function=apply_fs_transform),
                              name='transformer', run_without_submitting=True)
    else:
        wm_mask = pe.Node(niu.Function(function=_extract_wm), name='wm_mask')
        flt_bbr_init = pe.Node(FLIRTRPT(generate_report=True, dof=6), name='flt_bbr_init')
        flt_bbr = pe.Node(
            FLIRTRPT(generate_report=True, cost_func='bbr',
                     dof=bold2t1w_dof),
            name='flt_bbr')
        flt_bbr.inputs.schedule = op.join(os.getenv('FSLDIR'),
                                          'etc/flirtsch/bbr.sch')

    # make equivalent warp fields
    invt_bbr = pe.Node(fsl.ConvertXFM(invert_xfm=True), name='invt_bbr')

    #  EPI to T1 transform matrix is from fsl, using c3 tools to convert to
    #  something ANTs will like.
    fsl2itk_fwd = pe.Node(c3.C3dAffineTool(fsl2ras=True, itk_transform=True),
                          name='fsl2itk_fwd')
    fsl2itk_inv = pe.Node(c3.C3dAffineTool(fsl2ras=True, itk_transform=True),
                          name='fsl2itk_inv')

    workflow.connect([
        (inputnode, fsl2itk_fwd, [('t1_preproc', 'reference_file'),
                                  ('ref_epi_brain', 'source_file')]),
        (inputnode, fsl2itk_inv, [('ref_epi_brain', 'reference_file'),
                                  ('t1_preproc', 'source_file')]),
        (invt_bbr, outputnode, [('out_file', 'mat_t1_to_epi')]),
        (invt_bbr, fsl2itk_inv, [('out_file', 'transform_file')]),
        (fsl2itk_fwd, outputnode, [('itk_transform', 'itk_epi_to_t1')]),
        (fsl2itk_inv, outputnode, [('itk_transform', 'itk_t1_to_epi')]),
    ])

    gen_ref = pe.Node(GenerateSamplingReference(), name='gen_ref')

    mask_t1w_tfm = pe.Node(
        ants.ApplyTransforms(interpolation='NearestNeighbor',
                             float=True),
        name='mask_t1w_tfm'
    )

    workflow.connect([
        (inputnode, gen_ref, [('ref_epi_brain', 'moving_image'),
                              ('t1_brain', 'fixed_image')]),
        (gen_ref, mask_t1w_tfm, [('out_file', 'reference_image')]),
        (fsl2itk_fwd, mask_t1w_tfm, [('itk_transform', 'transforms')]),
        (inputnode, mask_t1w_tfm, [('ref_epi_mask', 'input_image')]),
        (mask_t1w_tfm, outputnode, [('output_image', 'epi_mask_t1')])
    ])

    if use_fieldwarp:
        merge_transforms = pe.MapNode(niu.Merge(3), iterfield=['in3'],
                                      name='merge_transforms', run_without_submitting=True)
        workflow.connect([
            (inputnode, merge_transforms, [('fieldwarp', 'in2'),
                                           ('hmc_xforms', 'in3')])
            ])
    else:
        merge_transforms = pe.MapNode(niu.Merge(2), iterfield=['in2'],
                                      name='merge_transforms', run_without_submitting=True)
        workflow.connect([
            (inputnode, merge_transforms, [('hmc_xforms', 'in2')])
        ])

    merge = pe.Node(Merge(), name='merge')
    merge.interface.estimated_memory_gb = bold_file_size_gb * 3

    epi_to_t1w_transform = pe.MapNode(
        ants.ApplyTransforms(interpolation="LanczosWindowedSinc",
                             float=True),
        iterfield=['input_image', 'transforms'],
        name='epi_to_t1w_transform')
    epi_to_t1w_transform.terminal_output = 'file'

    workflow.connect([
        (fsl2itk_fwd, merge_transforms, [('itk_transform', 'in1')]),
        (merge_transforms, epi_to_t1w_transform, [('out', 'transforms')]),
        (epi_to_t1w_transform, merge, [('output_image', 'in_files')]),
        (inputnode, merge, [('name_source', 'header_source')]),
        (merge, outputnode, [('out_file', 'epi_t1')]),
        (inputnode, epi_to_t1w_transform, [('epi_split', 'input_image')]),
        (gen_ref, epi_to_t1w_transform, [('out_file', 'reference_image')]),
    ])

    if freesurfer:
        workflow.connect([
            (inputnode, bbregister, [('subjects_dir', 'subjects_dir'),
                                     ('subject_id', 'subject_id')]),
            (inputnode, bbregister, [('ref_epi_brain', 'source_file')]),
            (inputnode, transformer, [('fs_2_t1_transform', 'fs_2_t1_transform')]),
            (bbregister, transformer, [('out_fsl_file', 'bbreg_transform')]),
            (transformer, invt_bbr, [('out', 'in_file')]),
            (transformer, fsl2itk_fwd, [('out', 'transform_file')]),
            (transformer, outputnode, [('out', 'mat_epi_to_t1')]),
            (bbregister, outputnode, [('out_reg_file', 'fs_reg_file'),
                                      ('out_report', 'out_report')]),
        ])
    else:
        workflow.connect([
            (inputnode, wm_mask, [('t1_seg', 'in_file')]),
            (inputnode, flt_bbr_init, [('ref_epi_brain', 'in_file')]),
            (inputnode, flt_bbr_init, [('t1_brain', 'reference')]),
            (flt_bbr_init, flt_bbr, [('out_matrix_file', 'in_matrix_file')]),
            (inputnode, flt_bbr, [('t1_brain', 'reference')]),
            (inputnode, flt_bbr, [('ref_epi_brain', 'in_file')]),
            (wm_mask, flt_bbr, [('out', 'wm_seg')]),
            (flt_bbr, invt_bbr, [('out_matrix_file', 'in_file')]),
            (flt_bbr, fsl2itk_fwd, [('out_matrix_file', 'transform_file')]),
            (flt_bbr, outputnode, [('out_matrix_file', 'mat_epi_to_t1'),
                                   ('out_report', 'out_report')]),
        ])

    return workflow