Skip to content

Commit c07a57c

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

File tree

1 file changed

+131
-49
lines changed

1 file changed

+131
-49
lines changed

src/smriprep/workflows/surfaces.py

+131-49
Original file line numberDiff line numberDiff line change
@@ -1476,7 +1476,6 @@ def init_morph_grayords_wf(
14761476
thickness_fsLR
14771477
HCP-style thickness file in CIFTI-2 format, resampled to fsLR
14781478
"""
1479-
import templateflow.api as tf
14801479
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
14811480

14821481
from smriprep.interfaces.cifti import GenerateDScalar
@@ -1487,8 +1486,6 @@ def init_morph_grayords_wf(
14871486
resampled onto fsLR using the Connectome Workbench [@hcppipelines].
14881487
"""
14891488

1490-
fslr_density = '32k' if grayord_density == '91k' else '59k'
1491-
14921489
inputnode = pe.Node(
14931490
niu.IdentityInterface(
14941491
fields=[
@@ -1527,18 +1524,121 @@ def init_morph_grayords_wf(
15271524
name='outputnode',
15281525
)
15291526

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

1668+
resample_to_fsLR = pe.Node(
1669+
MetricResample(method='ADAP_BARY_AREA', area_surfs=True),
1670+
name='resample_to_fsLR',
1671+
mem_gb=1,
1672+
n_procs=omp_nthreads,
1673+
)
1674+
mask_fsLR = pe.Node(MetricMask(), name='mask_fsLR')
1675+
15671676
workflow.connect([
15681677
(inputnode, select_surfaces, [
1569-
('curv', 'curv'),
1570-
('sulc', 'sulc'),
1571-
('thickness', 'thickness'),
1572-
('roi', 'roi'),
1678+
('in_file', 'in_file'),
15731679
('midthickness', 'midthickness'),
15741680
('midthickness_fsLR', 'midthickness_fsLR'),
15751681
('sphere_reg_fsLR', 'sphere_reg_fsLR'),
1682+
('cortex_mask', 'cortex_mask'),
1683+
('hemi', 'key'),
1684+
]),
1685+
(select_surfaces, resample_to_fsLR, [
1686+
('in_file', 'in_file'),
1687+
('sphere_reg_fsLR', 'current_sphere'),
1688+
('template_sphere', 'new_sphere'),
1689+
('midthickness', 'current_area'),
1690+
('midthickness_fsLR', 'new_area'),
1691+
('cortex_mask', 'roi_metric'),
15761692
]),
1577-
(hemisource, select_surfaces, [('hemi', 'key')]),
1693+
(select_surfaces, mask_fsLR, [('template_roi', 'mask')]),
1694+
(resample_to_fsLR, mask_fsLR, [('out_file', 'in_file')]),
1695+
(mask_fsLR, outputnode, [('out_file', 'out_file')]),
15781696
]) # fmt:skip
15791697

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-
16161698
return workflow
16171699

16181700

0 commit comments

Comments
 (0)