Skip to content

Resample surfaces to any space/density using Connectome Workbench. #473

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 100 additions & 20 deletions src/smriprep/workflows/surfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -1316,60 +1316,63 @@ def init_anat_ribbon_wf(name='anat_ribbon_wf'):
return workflow


def init_resample_surfaces_wf(
def init_resample_surfaces_wb_wf(
surfaces: list[str],
grayord_density: ty.Literal['91k', '170k'],
name: str = 'resample_surfaces_wf',
space: str,
density: str,
name: str = 'resample_surfaces_wb_wf',
):
"""
Resample subject surfaces surface to specified density.
Resample subject surfaces surface to specified space and density.

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

from smriprep.workflows.surfaces import init_resample_surfaces_wf
wf = init_resample_surfaces_wf(
from smriprep.workflows.surfaces import init_resample_surfaces_wb_wf
wf = init_resample_surfaces_wb_wf(
surfaces=['white', 'pial', 'midthickness'],
grayord_density='91k',
space='onavg',
density='10k',
)

Parameters
----------
surfaces : :class:`list` of :class:`str`
Names of surfaces (e.g., ``'white'``) to resample. Both hemispheres will be resampled.
grayord_density : :class:`str`
Either `91k` or `170k`, representing the total of vertices or *grayordinates*.
space : :class:`str`
The space to resample to, e.g., ``'onavg'``, ``'fsLR'``.
density : :class:`str`
The density to resample to, e.g., ``'10k'``, ``'41k'``. Number of vertices per hemisphere.
name : :class:`str`
Unique name for the subworkflow (default: ``"resample_surfaces_wf"``)
Unique name for the subworkflow (default: ``"resample_surfaces_wb_wf"``)

Inputs
------
``<surface>``
Left and right GIFTIs for each surface name passed to ``surfaces``
Left and right GIFTIs for each surface name passed to ``surfaces``.
sphere_reg_fsLR
GIFTI surface mesh corresponding to the subject's fsLR registration sphere
GIFTI surface mesh corresponding to the subject's fsLR registration sphere.

Outputs
-------
``<surface>``
Left and right GIFTI surface mesh corresponding to the input surface, resampled to fsLR
Left and right GIFTI surface mesh corresponding to the input surface, resampled to the
specified space and density.
"""
import templateflow.api as tf
from niworkflows.engine.workflows import LiterateWorkflow as Workflow

workflow = Workflow(name=name)

fslr_density = '32k' if grayord_density == '91k' else '59k'

inputnode = pe.Node(
niu.IdentityInterface(fields=[*surfaces, 'sphere_reg_fsLR']),
name='inputnode',
)

outputnode = pe.Node(
niu.IdentityInterface(fields=[f'{surf}_fsLR' for surf in surfaces]), name='outputnode'
niu.IdentityInterface(fields=[f'{surf}_resampled' for surf in surfaces]), name='outputnode'
)

surface_list = pe.Node(
Expand All @@ -1386,11 +1389,11 @@ def init_resample_surfaces_wf(
resampler.inputs.new_sphere = [
str(
tf.get(
template='fsLR',
density=fslr_density,
template=space,
density=density,
suffix='sphere',
hemi=hemi,
space=None,
space=(None if space == 'fsLR' else 'fsLR'),
extension='.surf.gii',
)
)
Expand All @@ -1416,7 +1419,84 @@ def init_resample_surfaces_wf(
(surface_list, resampler, [('out', 'surface_in')]),
(resampler, surface_groups, [('surface_out', 'inlist')]),
(surface_groups, outputnode, [
(f'out{i}', f'{surf}_fsLR') for i, surf in enumerate(surfaces, start=1)
(f'out{i}', f'{surf}_resampled') for i, surf in enumerate(surfaces, start=1)
]),
]) # fmt:skip

return workflow


def init_resample_surfaces_wf(
surfaces: list[str],
grayord_density: ty.Literal['91k', '170k'],
name: str = 'resample_surfaces_wf',
):
"""
Resample subject surfaces surface to specified density.

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

from smriprep.workflows.surfaces import init_resample_surfaces_wf
wf = init_resample_surfaces_wf(
surfaces=['white', 'pial', 'midthickness'],
grayord_density='91k',
)

Parameters
----------
surfaces : :class:`list` of :class:`str`
Names of surfaces (e.g., ``'white'``) to resample. Both hemispheres will be resampled.
grayord_density : :class:`str`
Either `91k` or `170k`, representing the total of vertices or *grayordinates*.
name : :class:`str`
Unique name for the subworkflow (default: ``"resample_surfaces_wf"``)

Inputs
------
``<surface>``
Left and right GIFTIs for each surface name passed to ``surfaces``
sphere_reg_fsLR
GIFTI surface mesh corresponding to the subject's fsLR registration sphere

Outputs
-------
``<surface>``
Left and right GIFTI surface mesh corresponding to the input surface, resampled to fsLR
"""
# import templateflow.api as tf
from niworkflows.engine.workflows import LiterateWorkflow as Workflow

workflow = Workflow(name=name)

fslr_density = '32k' if grayord_density == '91k' else '59k'

inputnode = pe.Node(
niu.IdentityInterface(fields=[*surfaces, 'sphere_reg_fsLR']),
name='inputnode',
)

outputnode = pe.Node(
niu.IdentityInterface(fields=[f'{surf}_fsLR' for surf in surfaces]), name='outputnode'
)

resample_surfaces_wb_wf = init_resample_surfaces_wb_wf(
surfaces=surfaces,
space='fsLR',
density=fslr_density,
name='resample_surfaces_fslr_wb_wf',
)
workflow.connect([
(inputnode, resample_surfaces_wb_wf, [
(surf, 'inputnode.'+surf) for surf in surfaces
]),
(inputnode, resample_surfaces_wb_wf, [
('sphere_reg_fsLR', 'inputnode.sphere_reg_fsLR'),
]),
(resample_surfaces_wb_wf, outputnode, [
(f'outputnode.{surf}_resampled', f'{surf}_fsLR') for surf in surfaces
]),
]) # fmt:skip

Expand Down
Loading