Ejemplo n.º 1
0
def init_bold_grayords_wf(grayord_density,
                          mem_gb,
                          repetition_time,
                          name="bold_grayords_wf"):
    """
    Sample Grayordinates files onto the fsLR atlas.

    Outputs are in CIFTI2 format.

    Workflow Graph
        .. workflow::
            :graph2use: colored
            :simple_form: yes

            from fprodents.workflows.bold.resampling import init_bold_grayords_wf
            wf = init_bold_grayords_wf(mem_gb=0.1, grayord_density='91k')

    Parameters
    ----------
    grayord_density : :obj:`str`
        Either `91k` or `170k`, representing the total of vertices or *grayordinates*.
    mem_gb : :obj:`float`
        Size of BOLD file in GB
    name : :obj:`str`
        Unique name for the subworkflow (default: ``'bold_grayords_wf'``)

    Inputs
    ------
    bold_std : :obj:`str`
        List of BOLD conversions to standard spaces.
    spatial_reference :obj:`str`
        List of unique identifiers corresponding to the BOLD standard-conversions.
    subjects_dir : :obj:`str`
        FreeSurfer's subjects directory.
    surf_files : :obj:`str`
        List of BOLD files resampled on the fsaverage (ico7) surfaces.
    surf_refs :
        List of unique identifiers corresponding to the BOLD surface-conversions.

    Outputs
    -------
    cifti_bold : :obj:`str`
        List of BOLD grayordinates files - (L)eft and (R)ight.
    cifti_variant : :obj:`str`
        Only ``'HCP Grayordinates'`` is currently supported.
    cifti_metadata : :obj:`str`
        Path of metadata files corresponding to ``cifti_bold``.
    cifti_density : :obj:`str`
        Density (i.e., either `91k` or `170k`) of ``cifti_bold``.

    """
    import templateflow.api as tf
    from niworkflows.engine.workflows import LiterateWorkflow as Workflow
    from niworkflows.interfaces.cifti import GenerateCifti
    from niworkflows.interfaces.utility import KeySelect

    workflow = Workflow(name=name)
    workflow.__desc__ = """\
*Grayordinates* files [@hcppipelines] containing {density} samples were also
generated using the highest-resolution ``fsaverage`` as intermediate standardized
surface space.
""".format(density=grayord_density)

    fslr_density, mni_density = (("32k", "2") if grayord_density == "91k" else
                                 ("59k", "1"))

    inputnode = pe.Node(
        niu.IdentityInterface(fields=[
            "bold_std",
            "spatial_reference",
            "subjects_dir",
            "surf_files",
            "surf_refs",
        ]),
        name="inputnode",
    )

    outputnode = pe.Node(
        niu.IdentityInterface(fields=[
            "cifti_bold", "cifti_variant", "cifti_metadata", "cifti_density"
        ]),
        name="outputnode",
    )

    # extract out to BOLD base
    select_std = pe.Node(
        KeySelect(fields=["bold_std"]),
        name="select_std",
        run_without_submitting=True,
        nohash=True,
    )
    select_std.inputs.key = "MNI152NLin6Asym_res-%s" % mni_density

    select_fs_surf = pe.Node(
        KeySelect(fields=["surf_files"]),
        name="select_fs_surf",
        run_without_submitting=True,
        mem_gb=DEFAULT_MEMORY_MIN_GB,
    )
    select_fs_surf.inputs.key = "fsaverage"

    # Setup Workbench command. LR ordering for hemi can be assumed, as it is imposed
    # by the iterfield of the MapNode in the surface sampling workflow above.
    resample = pe.MapNode(
        wb.MetricResample(method="ADAP_BARY_AREA", area_metrics=True),
        name="resample",
        iterfield=[
            "in_file",
            "out_file",
            "new_sphere",
            "new_area",
            "current_sphere",
            "current_area",
        ],
    )
    resample.inputs.current_sphere = [
        str(
            tf.get("fsaverage",
                   hemi=hemi,
                   density="164k",
                   desc="std",
                   suffix="sphere")) for hemi in "LR"
    ]
    resample.inputs.current_area = [
        str(
            tf.get(
                "fsaverage",
                hemi=hemi,
                density="164k",
                desc="vaavg",
                suffix="midthickness",
            )) for hemi in "LR"
    ]
    resample.inputs.new_sphere = [
        str(
            tf.get(
                "fsLR",
                space="fsaverage",
                hemi=hemi,
                density=fslr_density,
                suffix="sphere",
            )) for hemi in "LR"
    ]
    resample.inputs.new_area = [
        str(
            tf.get(
                "fsLR",
                hemi=hemi,
                density=fslr_density,
                desc="vaavg",
                suffix="midthickness",
            )) for hemi in "LR"
    ]
    resample.inputs.out_file = [
        "space-fsLR_hemi-%s_den-%s_bold.gii" % (h, grayord_density)
        for h in "LR"
    ]

    gen_cifti = pe.Node(
        GenerateCifti(
            volume_target="MNI152NLin6Asym",
            surface_target="fsLR",
            TR=repetition_time,
            surface_density=fslr_density,
        ),
        name="gen_cifti",
    )

    # fmt:off
    workflow.connect([
        (inputnode, gen_cifti, [('subjects_dir', 'subjects_dir')]),
        (inputnode, select_std, [('bold_std', 'bold_std'),
                                 ('spatial_reference', 'keys')]),
        (inputnode, select_fs_surf, [('surf_files', 'surf_files'),
                                     ('surf_refs', 'keys')]),
        (select_fs_surf, resample, [('surf_files', 'in_file')]),
        (select_std, gen_cifti, [('bold_std', 'bold_file')]),
        (resample, gen_cifti, [('out_file', 'surface_bolds')]),
        (gen_cifti, outputnode, [('out_file', 'cifti_bold'),
                                 ('variant', 'cifti_variant'),
                                 ('out_metadata', 'cifti_metadata'),
                                 ('density', 'cifti_density')]),
    ])
    # fmt:on
    return workflow
Ejemplo n.º 2
0
def init_asl_grayords_wf(grayord_density,
                         mem_gb,
                         repetition_time,
                         name='asl_grayords_wf'):
    """
    Sample Grayordinates files onto the fsLR atlas.

    Outputs are in CIFTI2 format.

    Workflow Graph
        .. workflow::
            :graph2use: colored
            :simple_form: yes

            from aslprep.workflows.asl import init_asl_grayords_wf
            wf = init_asl_grayords_wf(mem_gb=0.1, grayord_density='91k')

    Parameters
    ----------
    grayord_density : :obj:`str`
        Either `91k` or `170k`, representing the total of vertices or *grayordinates*.
    mem_gb : :obj:`float`
        Size of asl file in GB
    name : :obj:`str`
        Unique name for the subworkflow (default: ``'asl_grayords_wf'``)

    Inputs
    ------
    asl_std : :obj:`str`
        List of asl conversions to standard spaces.
    spatial_reference :obj:`str`
        List of unique identifiers corresponding to the asl standard-conversions.
    subjects_dir : :obj:`str`
        FreeSurfer's subjects directory.
    surf_files : :obj:`str`
        List of asl files resampled on the fsaverage (ico7) surfaces.
    surf_refs :
        List of unique identifiers corresponding to the asl surface-conversions.

    Outputs
    -------
    cifti_asl : :obj:`str`
        List of asl grayordinates files - (L)eft and (R)ight.
    cifti_variant : :obj:`str`
        Only ``'HCP Grayordinates'`` is currently supported.
    cifti_metadata : :obj:`str`
        Path of metadata files corresponding to ``cifti_asl``.
    cifti_density : :obj:`str`
        Density (i.e., either `91k` or `170k`) of ``cifti_asl``.

    """
    import templateflow.api as tf
    from ...niworkflows.engine.workflows import LiterateWorkflow as Workflow
    from ...niworkflows.interfaces.cifti import GenerateCifti
    from ...niworkflows.interfaces.utility import KeySelect

    workflow = Workflow(name=name)
    workflow.__desc__ = """\
*Grayordinates* files [@hcppipelines] containing {density} samples were also
generated using the highest-resolution ``fsaverage`` as intermediate standardized
surface space.
""".format(density=grayord_density)

    fslr_density, mni_density = ('32k',
                                 '2') if grayord_density == '91k' else ('59k',
                                                                        '1')

    inputnode = pe.Node(niu.IdentityInterface(fields=[
        'asl_std',
        'spatial_reference',
        'subjects_dir',
        'surf_files',
        'surf_refs',
    ]),
                        name='inputnode')

    outputnode = pe.Node(niu.IdentityInterface(fields=[
        'cifti_asl',
        'cifti_variant',
        'cifti_metadata',
        'cifti_density',
    ]),
                         name='outputnode')

    # extract out to asl base
    select_std = pe.Node(KeySelect(fields=['asl_std']),
                         name='select_std',
                         run_without_submitting=True,
                         nohash=True)
    select_std.inputs.key = 'MNI152NLin6Asym_res-%s' % mni_density

    select_fs_surf = pe.Node(KeySelect(fields=['surf_files']),
                             name='select_fs_surf',
                             run_without_submitting=True,
                             mem_gb=DEFAULT_MEMORY_MIN_GB)
    select_fs_surf.inputs.key = 'fsaverage'

    # Setup Workbench command. LR ordering for hemi can be assumed, as it is imposed
    # by the iterfield of the MapNode in the surface sampling workflow above.
    resample = pe.MapNode(wb.MetricResample(method='ADAP_BARY_AREA',
                                            area_metrics=True),
                          name='resample',
                          iterfield=[
                              'in_file', 'out_file', 'new_sphere', 'new_area',
                              'current_sphere', 'current_area'
                          ])
    resample.inputs.current_sphere = [
        str(
            tf.get('fsaverage',
                   hemi=hemi,
                   density='164k',
                   desc='std',
                   suffix='sphere')) for hemi in 'LR'
    ]
    resample.inputs.current_area = [
        str(
            tf.get('fsaverage',
                   hemi=hemi,
                   density='164k',
                   desc='vaavg',
                   suffix='midthickness')) for hemi in 'LR'
    ]
    resample.inputs.new_sphere = [
        str(
            tf.get('fsLR',
                   space='fsaverage',
                   hemi=hemi,
                   density=fslr_density,
                   suffix='sphere')) for hemi in 'LR'
    ]
    resample.inputs.new_area = [
        str(
            tf.get('fsLR',
                   hemi=hemi,
                   density=fslr_density,
                   desc='vaavg',
                   suffix='midthickness')) for hemi in 'LR'
    ]
    resample.inputs.out_file = [
        'space-fsLR_hemi-%s_den-%s_asl.gii' % (h, grayord_density)
        for h in 'LR'
    ]

    gen_cifti = pe.Node(GenerateCifti(
        volume_target='MNI152NLin6Asym',
        surface_target='fsLR',
        TR=repetition_time,
        surface_density=fslr_density,
    ),
                        name="gen_cifti")

    workflow.connect([
        (inputnode, gen_cifti, [('subjects_dir', 'subjects_dir')]),
        (inputnode, select_std, [('asl_std', 'asl_std'),
                                 ('spatial_reference', 'keys')]),
        (inputnode, select_fs_surf, [('surf_files', 'surf_files'),
                                     ('surf_refs', 'keys')]),
        (select_fs_surf, resample, [('surf_files', 'in_file')]),
        (select_std, gen_cifti, [('asl_std', 'asl_file')]),
        (resample, gen_cifti, [('out_file', 'surface_asls')]),
        (gen_cifti, outputnode, [('out_file', 'cifti_asl'),
                                 ('variant', 'cifti_variant'),
                                 ('out_metadata', 'cifti_metadata'),
                                 ('density', 'cifti_density')]),
    ])
    return workflow
Ejemplo n.º 3
0
def init_bold_surf_wf(mem_gb,
                      output_spaces,
                      medial_surface_nan,
                      fslr_density=None,
                      name='bold_surf_wf'):
    """
    Sample functional images to FreeSurfer surfaces.

    For each vertex, the cortical ribbon is sampled at six points (spaced 20% of thickness apart)
    and averaged.
    Outputs are in GIFTI format.

    Workflow Graph
        .. workflow::
            :graph2use: colored
            :simple_form: yes

            from fmriprep.workflows.bold import init_bold_surf_wf
            wf = init_bold_surf_wf(mem_gb=0.1,
                                   output_spaces=['T1w', 'fsnative',
                                                 'template', 'fsaverage5'],
                                   medial_surface_nan=False)

    Parameters
    ----------
    output_spaces : list
        List of output spaces functional images are to be resampled to
        Target spaces beginning with ``fs`` will be selected for resampling,
        such as ``fsaverage`` or related template spaces
        If the list contains ``fsnative``, images will be resampled to the
        individual subject's native surface
        If the list contains ``fsLR``, images will be resampled twice;
        first to ``fsaverage`` and then to ``fsLR``.
    medial_surface_nan : bool
        Replace medial wall values with NaNs on functional GIFTI files
    fslr_density : str, optional
        Density of fsLR surface (32k or 59k)


    Inputs
    ------
    source_file
        Motion-corrected BOLD series in T1 space
    t1w_preproc
        Bias-corrected structural template image
    subjects_dir
        FreeSurfer SUBJECTS_DIR
    subject_id
        FreeSurfer subject ID
    t1w2fsnative_xfm
        LTA-style affine matrix translating from T1w to FreeSurfer-conformed subject space

    Outputs
    -------
    surfaces
        BOLD series, resampled to FreeSurfer surfaces

    """
    # Ensure volumetric spaces do not sneak into this workflow
    spaces = [space for space in output_spaces if space.startswith('fs')]

    workflow = Workflow(name=name)

    if spaces:
        workflow.__desc__ = """\
The BOLD time-series, were resampled to surfaces on the following
spaces: {out_spaces}.
""".format(out_spaces=', '.join(['*%s*' % s for s in spaces]))
    inputnode = pe.Node(niu.IdentityInterface(fields=[
        'source_file', 't1w_preproc', 'subject_id', 'subjects_dir',
        't1w2fsnative_xfm'
    ]),
                        name='inputnode')

    to_fslr = False
    if 'fsLR' in output_spaces:
        to_fslr = 'fsaverage' in output_spaces and fslr_density
        spaces.pop(spaces.index('fsLR'))

    outputnode = pe.Node(niu.IdentityInterface(fields=['surfaces']),
                         name='outputnode')

    def select_target(subject_id, space):
        """Get the target subject ID, given a source subject ID and a target space."""
        return subject_id if space == 'fsnative' else space

    targets = pe.MapNode(niu.Function(function=select_target),
                         iterfield=['space'],
                         name='targets',
                         mem_gb=DEFAULT_MEMORY_MIN_GB)
    targets.inputs.space = spaces

    # Rename the source file to the output space to simplify naming later
    rename_src = pe.MapNode(niu.Rename(format_string='%(subject)s',
                                       keep_ext=True),
                            iterfield='subject',
                            name='rename_src',
                            run_without_submitting=True,
                            mem_gb=DEFAULT_MEMORY_MIN_GB)
    rename_src.inputs.subject = spaces

    resampling_xfm = pe.Node(LTAConvert(in_lta='identity.nofile',
                                        out_lta=True),
                             name='resampling_xfm')
    set_xfm_source = pe.Node(ConcatenateLTA(out_type='RAS2RAS'),
                             name='set_xfm_source')

    sampler = pe.MapNode(fs.SampleToSurface(sampling_method='average',
                                            sampling_range=(0, 1, 0.2),
                                            sampling_units='frac',
                                            interp_method='trilinear',
                                            cortex_mask=True,
                                            override_reg_subj=True,
                                            out_type='gii'),
                         iterfield=['source_file', 'target_subject'],
                         iterables=('hemi', ['lh', 'rh']),
                         name='sampler',
                         mem_gb=mem_gb * 3)

    if to_fslr:
        filter_fsavg = pe.Node(niu.Function(
            function=_select_fsaverage_hemi,
            output_names=['fsaverage_bold', 'hemi']),
                               name='filter_fsavg',
                               mem_gb=DEFAULT_MEMORY_MIN_GB,
                               run_without_submitting=True)

        rename_fslr = pe.Node(niu.Rename(format_string="%(hemi)s.fsLR",
                                         keep_ext=True,
                                         parse_string=r'^(?P<hemi>\w+)'),
                              name='rename_fslr',
                              mem_gb=DEFAULT_MEMORY_MIN_GB,
                              run_without_submitting=True)

        fetch_fslr_tpls = pe.Node(niu.Function(function=_fetch_fslr_templates,
                                               output_names=[
                                                   'fsaverage_sphere',
                                                   'fslr_sphere',
                                                   'fsaverage_midthick',
                                                   'fslr_midthick'
                                               ]),
                                  name='fetch_fslr_tpls',
                                  mem_gb=DEFAULT_MEMORY_MIN_GB,
                                  overwrite=True)
        fetch_fslr_tpls.inputs.den = fslr_density

        resample_fslr = pe.Node(wb.MetricResample(method='ADAP_BARY_AREA',
                                                  area_metrics=True),
                                name='resample_fslr')

        merge_fslr = pe.Node(niu.Merge(2),
                             name='merge_fslr',
                             mem_gb=DEFAULT_MEMORY_MIN_GB,
                             run_without_submitting=True)

        def _basename(in_file):
            import os
            return os.path.basename(in_file)

        workflow.connect([
            (sampler, filter_fsavg, [('out_file', 'in_files')]),
            (filter_fsavg, fetch_fslr_tpls, [('hemi', 'hemi')]),
            (filter_fsavg, rename_fslr, [('fsaverage_bold', 'in_file')]),
            (rename_fslr, resample_fslr, [('out_file', 'in_file')]),
            (rename_fslr, resample_fslr, [(('out_file', _basename), 'out_file')
                                          ]),
            (fetch_fslr_tpls, resample_fslr,
             [('fsaverage_sphere', 'current_sphere'),
              ('fslr_sphere', 'new_sphere'),
              ('fsaverage_midthick', 'current_area'),
              ('fslr_midthick', 'new_area')]),
            (sampler, merge_fslr, [('out_file', 'in1')]),
            (resample_fslr, merge_fslr, [('out_file', 'in2')]),
        ])

    merger = pe.JoinNode(niu.Merge(1, ravel_inputs=True),
                         name='merger',
                         joinsource='sampler',
                         joinfield=['in1'],
                         run_without_submitting=True,
                         mem_gb=DEFAULT_MEMORY_MIN_GB)

    if medial_surface_nan:
        medial_nans = pe.MapNode(MedialNaNs(),
                                 iterfield=['in_file'],
                                 name='medial_nans',
                                 mem_gb=DEFAULT_MEMORY_MIN_GB)

        workflow.connect([
            (inputnode, medial_nans, [('subjects_dir', 'subjects_dir')]),
            (medial_nans, merger, [('out_file', 'in1')]),
        ])

    update_metadata = pe.MapNode(GiftiSetAnatomicalStructure(),
                                 iterfield='in_file',
                                 name='update_metadata',
                                 mem_gb=DEFAULT_MEMORY_MIN_GB)

    workflow.connect([
        (inputnode, targets, [('subject_id', 'subject_id')]),
        (inputnode, rename_src, [('source_file', 'in_file')]),
        (inputnode, resampling_xfm, [('source_file', 'source_file'),
                                     ('t1w_preproc', 'target_file')]),
        (inputnode, set_xfm_source, [('t1w2fsnative_xfm', 'in_lta2')]),
        (resampling_xfm, set_xfm_source, [('out_lta', 'in_lta1')]),
        (inputnode, sampler, [('subjects_dir', 'subjects_dir'),
                              ('subject_id', 'subject_id')]),
        (set_xfm_source, sampler, [('out_file', 'reg_file')]),
        (targets, sampler, [('out', 'target_subject')]),
        (rename_src, sampler, [('out_file', 'source_file')]),
        (merger, update_metadata, [('out', 'in_file')]),
        (update_metadata, outputnode, [('out_file', 'surfaces')]),
    ])

    if to_fslr and medial_surface_nan:
        medial_nans.inputs.density = fslr_density
        workflow.connect(merge_fslr, 'out', medial_nans, 'in_file')
    elif to_fslr:
        workflow.connect(merge_fslr, 'out', merger, 'in1')
    elif medial_surface_nan:
        workflow.connect(sampler, 'out_file', medial_nans, 'in_file')
    else:
        workflow.connect(sampler, 'out_file', merger, 'in1')

    return workflow