Skip to content

Commit 2af47dd

Browse files
committed
rf: Split resampling and masking out from morphometrics workflow
1 parent 09c5cef commit 2af47dd

File tree

1 file changed

+148
-51
lines changed

1 file changed

+148
-51
lines changed

src/smriprep/workflows/surfaces.py

Lines changed: 148 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
)
5555

5656
import smriprep
57+
from smriprep.interfaces.cifti import GenerateDScalar
5758
from smriprep.interfaces.surf import MakeRibbon
5859
from smriprep.interfaces.workbench import SurfaceResample
5960

@@ -1476,19 +1477,14 @@ def init_morph_grayords_wf(
14761477
thickness_fsLR
14771478
HCP-style thickness file in CIFTI-2 format, resampled to fsLR
14781479
"""
1479-
import templateflow.api as tf
14801480
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
14811481

1482-
from smriprep.interfaces.cifti import GenerateDScalar
1483-
14841482
workflow = Workflow(name=name)
14851483
workflow.__desc__ = f"""\
14861484
*Grayordinate* "dscalar" files containing {grayord_density} samples were
14871485
resampled onto fsLR using the Connectome Workbench [@hcppipelines].
14881486
"""
14891487

1490-
fslr_density = '32k' if grayord_density == '91k' else '59k'
1491-
14921488
inputnode = pe.Node(
14931489
niu.IdentityInterface(
14941490
fields=[
@@ -1527,18 +1523,138 @@ def init_morph_grayords_wf(
15271523
name='outputnode',
15281524
)
15291525

1530-
atlases = smriprep.load_data('atlases')
1526+
metrics = ['curv', 'sulc', 'thickness']
1527+
select_surfaces = pe.Node(
1528+
KeySelect(fields=metrics, keys=['L', 'R']),
1529+
name='select_surfaces',
1530+
run_without_submitting=True,
1531+
)
1532+
1533+
workflow.connect([
1534+
(hemisource, select_surfaces, [('hemi', 'key')]),
1535+
]) # fmt:skip
1536+
1537+
for metric in metrics:
1538+
resample_and_mask_wf = init_resample_and_mask_wf(
1539+
grayord_density=grayord_density,
1540+
omp_nthreads=omp_nthreads,
1541+
mem_gb=1,
1542+
name=f'resample_and_mask_{metric}_wf',
1543+
)
1544+
cifti_metric = pe.JoinNode(
1545+
GenerateDScalar(grayordinates=grayord_density, scalar_name=metric),
1546+
name=f'cifti_{metric}',
1547+
joinfield=['scalar_surfs'],
1548+
joinsource='hemisource',
1549+
)
1550+
1551+
workflow.connect([
1552+
(inputnode, select_surfaces, [(metric, metric)]),
1553+
(inputnode, resample_and_mask_wf, [
1554+
('midthickness', 'inputnode.midthickness'),
1555+
('midthickness_fsLR', 'inputnode.midthickness_fsLR'),
1556+
('sphere_reg_fsLR', 'inputnode.sphere_reg_fsLR'),
1557+
('roi', 'inputnode.cortex_mask'),
1558+
]),
1559+
(hemisource, resample_and_mask_wf, [('hemi', 'inputnode.hemi')]),
1560+
(select_surfaces, resample_and_mask_wf, [(metric, 'inputnode.in_file')]),
1561+
(resample_and_mask_wf, cifti_metric, [('outputnode.out_file', 'scalar_surfs')]),
1562+
(cifti_metric, outputnode, [
1563+
('out_file', f'{metric}_fsLR'),
1564+
('out_metadata', f'{metric}_metadata'),
1565+
]),
1566+
]) # fmt:skip
1567+
1568+
return workflow
1569+
1570+
1571+
def init_resample_and_mask_wf(
1572+
grayord_density: ty.Literal['91k', '170k'],
1573+
omp_nthreads: int,
1574+
mem_gb: float,
1575+
name: str = 'resample_and_mask_wf',
1576+
):
1577+
"""Resample GIFTI surfaces to fsLR space and mask with fsLR ROI.
1578+
1579+
Workflow Graph
1580+
.. workflow::
1581+
:graph2use: colored
1582+
:simple_form: yes
1583+
1584+
from smriprep.workflows.surfaces import init_resample_and_mask_wf
1585+
wf = init_resample_and_mask_wf(
1586+
grayord_density='91k',
1587+
omp_nthreads=1,
1588+
mem_gb=1,
1589+
)
1590+
1591+
Parameters
1592+
----------
1593+
grayord_density : :class:`str`
1594+
Either ``"91k"`` or ``"170k"``, representing the total *grayordinates*.
1595+
omp_nthreads : :class:`int`
1596+
Maximum number of threads an individual process may use
1597+
mem_gb : :class:`float`
1598+
Size of BOLD file in GB
1599+
name : :class:`str`
1600+
Name of workflow (default: ``"resample_and_mask_wf"``)
1601+
1602+
Inputs
1603+
------
1604+
in_file : :class:`str`
1605+
Path to metric file in subject space
1606+
hemi : :class:`str`
1607+
Hemisphere identifier (``"L"`` or ``"R"``)
1608+
midthickness : :class:`list` of :class:`str`
1609+
Path to left and right hemisphere midthickness GIFTI surfaces.
1610+
midthickness_fsLR : :class:`list` of :class:`str`
1611+
Path to left and right hemisphere midthickness GIFTI surfaces in fsLR space.
1612+
sphere_reg_fsLR : :class:`list` of :class:`str`
1613+
Path to left and right hemisphere sphere.reg GIFTI surfaces, mapping from subject to fsLR
1614+
cortex_mask : :class:`list` of :class:`str`
1615+
Path to left and right hemisphere cortex mask GIFTI files
1616+
1617+
Outputs
1618+
-------
1619+
metric_fsLR : :class:`str`
1620+
Path to metric resampled as GIFTI file in fsLR space
1621+
1622+
"""
1623+
import templateflow.api as tf
1624+
from nipype.pipeline import engine as pe
1625+
from niworkflows.interfaces.utility import KeySelect
1626+
1627+
fslr_density = '32k' if grayord_density == '91k' else '59k'
1628+
1629+
workflow = pe.Workflow(name=name)
1630+
1631+
inputnode = pe.Node(
1632+
niu.IdentityInterface(
1633+
fields=[
1634+
'in_file',
1635+
'hemi',
1636+
'midthickness',
1637+
'midthickness_fsLR',
1638+
'sphere_reg_fsLR',
1639+
'cortex_mask',
1640+
]
1641+
),
1642+
name='inputnode',
1643+
)
1644+
1645+
outputnode = pe.Node(
1646+
niu.IdentityInterface(fields=['out_file']),
1647+
name='outputnode',
1648+
)
1649+
15311650
select_surfaces = pe.Node(
15321651
KeySelect(
15331652
fields=[
1534-
'curv',
1535-
'sulc',
1536-
'thickness',
1537-
'roi',
15381653
'midthickness',
15391654
'midthickness_fsLR',
15401655
'sphere_reg_fsLR',
15411656
'template_sphere',
1657+
'cortex_mask',
15421658
'template_roi',
15431659
],
15441660
keys=['L', 'R'],
@@ -1559,60 +1675,41 @@ def init_morph_grayords_wf(
15591675
)
15601676
for hemi in ['L', 'R']
15611677
]
1678+
atlases = smriprep.load_data('atlases')
15621679
select_surfaces.inputs.template_roi = [
15631680
str(atlases / f'L.atlasroi.{fslr_density}_fs_LR.shape.gii'),
15641681
str(atlases / f'R.atlasroi.{fslr_density}_fs_LR.shape.gii'),
15651682
]
15661683

1684+
resample_to_fsLR = pe.Node(
1685+
MetricResample(method='ADAP_BARY_AREA', area_surfs=True),
1686+
name='resample_to_fsLR',
1687+
mem_gb=1,
1688+
n_procs=omp_nthreads,
1689+
)
1690+
mask_fsLR = pe.Node(MetricMask(), name='mask_fsLR')
1691+
15671692
workflow.connect([
15681693
(inputnode, select_surfaces, [
1569-
('curv', 'curv'),
1570-
('sulc', 'sulc'),
1571-
('thickness', 'thickness'),
1572-
('roi', 'roi'),
15731694
('midthickness', 'midthickness'),
15741695
('midthickness_fsLR', 'midthickness_fsLR'),
15751696
('sphere_reg_fsLR', 'sphere_reg_fsLR'),
1697+
('cortex_mask', 'cortex_mask'),
1698+
('hemi', 'key'),
15761699
]),
1577-
(hemisource, select_surfaces, [('hemi', 'key')]),
1700+
(inputnode, resample_to_fsLR, [('in_file', 'in_file')]),
1701+
(select_surfaces, resample_to_fsLR, [
1702+
('sphere_reg_fsLR', 'current_sphere'),
1703+
('template_sphere', 'new_sphere'),
1704+
('midthickness', 'current_area'),
1705+
('midthickness_fsLR', 'new_area'),
1706+
('cortex_mask', 'roi_metric'),
1707+
]),
1708+
(select_surfaces, mask_fsLR, [('template_roi', 'mask')]),
1709+
(resample_to_fsLR, mask_fsLR, [('out_file', 'in_file')]),
1710+
(mask_fsLR, outputnode, [('out_file', 'out_file')]),
15781711
]) # fmt:skip
15791712

1580-
for metric in ('curv', 'sulc', 'thickness'):
1581-
resampler = pe.Node(
1582-
MetricResample(method='ADAP_BARY_AREA', area_surfs=True),
1583-
name=f'resample_{metric}',
1584-
n_procs=omp_nthreads,
1585-
)
1586-
mask_fsLR = pe.Node(
1587-
MetricMask(),
1588-
name=f'mask_{metric}',
1589-
n_procs=omp_nthreads,
1590-
)
1591-
cifti_metric = pe.JoinNode(
1592-
GenerateDScalar(grayordinates=grayord_density, scalar_name=metric),
1593-
name=f'cifti_{metric}',
1594-
joinfield=['scalar_surfs'],
1595-
joinsource='hemisource',
1596-
)
1597-
1598-
workflow.connect([
1599-
(select_surfaces, resampler, [
1600-
(metric, 'in_file'),
1601-
('sphere_reg_fsLR', 'current_sphere'),
1602-
('template_sphere', 'new_sphere'),
1603-
('midthickness', 'current_area'),
1604-
('midthickness_fsLR', 'new_area'),
1605-
('roi', 'roi_metric'),
1606-
]),
1607-
(select_surfaces, mask_fsLR, [('template_roi', 'mask')]),
1608-
(resampler, mask_fsLR, [('out_file', 'in_file')]),
1609-
(mask_fsLR, cifti_metric, [('out_file', 'scalar_surfs')]),
1610-
(cifti_metric, outputnode, [
1611-
('out_file', f'{metric}_fsLR'),
1612-
('out_metadata', f'{metric}_metadata'),
1613-
]),
1614-
]) # fmt:skip
1615-
16161713
return workflow
16171714

16181715

0 commit comments

Comments
 (0)