Skip to content

Commit 64dd263

Browse files
committed
WIP
1 parent c07a57c commit 64dd263

File tree

2 files changed

+185
-9
lines changed

2 files changed

+185
-9
lines changed

src/smriprep/workflows/anatomical.py

+13
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
import smriprep
5858

5959
from ..interfaces import DerivativesDataSink
60+
61+
# from ..interfaces.calc import T1T2Ratio
6062
from ..utils.misc import apply_lut as _apply_bids_lut
6163
from ..utils.misc import fs_isRunning as _fs_isRunning
6264
from .fit.registration import init_register_template_wf
@@ -667,6 +669,7 @@ def init_anat_fit_wf(
667669
'sphere_reg_fsLR',
668670
'sphere_reg_msm',
669671
'anat_ribbon',
672+
't1t2_ratio',
670673
# Reverse transform; not computable from forward transform
671674
'std2anat_xfm',
672675
# Metadata
@@ -1330,6 +1333,16 @@ def init_anat_fit_wf(
13301333
LOGGER.info('ANAT Stage 8a: Found pre-computed cortical ribbon mask')
13311334
outputnode.inputs.anat_ribbon = precomputed['anat_ribbon']
13321335

1336+
if t2w and 't1t2ratio' not in precomputed:
1337+
LOGGER.info('ANAT Stage 8b: Creating T1w/T2w ratio map')
1338+
# Commented out to pacify linter.
1339+
# t1t2_ratio = pe.Node(T1T2Ratio(), name='t1t2_ratio')
1340+
1341+
elif not t2w:
1342+
LOGGER.info('ANAT No T2w images provided - skipping Stage 8b')
1343+
else:
1344+
LOGGER.info('ANAT Found precomputed T1w/T2w ratio map - skipping Stage 8b')
1345+
13331346
# Stage 9: Baseline fsLR registration
13341347
if len(precomputed.get('sphere_reg_fsLR', [])) < 2:
13351348
LOGGER.info('ANAT Stage 9: Creating fsLR registration sphere')

src/smriprep/workflows/surfaces.py

+172-9
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
import typing as ty
3232

33+
from nibabel.processing import fwhm2sigma
3334
from nipype.interfaces import freesurfer as fs
3435
from nipype.interfaces import io as nio
3536
from nipype.interfaces import utility as niu
@@ -54,6 +55,7 @@
5455
)
5556

5657
import smriprep
58+
from smriprep.interfaces.cifti import GenerateDScalar
5759
from smriprep.interfaces.surf import MakeRibbon
5860
from smriprep.interfaces.workbench import SurfaceResample
5961

@@ -1478,8 +1480,6 @@ def init_morph_grayords_wf(
14781480
"""
14791481
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
14801482

1481-
from smriprep.interfaces.cifti import GenerateDScalar
1482-
14831483
workflow = Workflow(name=name)
14841484
workflow.__desc__ = f"""\
14851485
*Grayordinate* "dscalar" files containing {grayord_density} samples were
@@ -1524,7 +1524,14 @@ def init_morph_grayords_wf(
15241524
name='outputnode',
15251525
)
15261526

1527-
for metric in ('curv', 'sulc', 'thickness'):
1527+
metrics = ['curv', 'sulc', 'thickness']
1528+
select_surfaces = pe.Node(
1529+
KeySelect(fields=metrics, keys=['L', 'R']),
1530+
name='select_surfaces',
1531+
run_without_submitting=True,
1532+
)
1533+
1534+
for metric in metrics:
15281535
resample_and_mask_wf = init_resample_and_mask_wf(
15291536
grayord_density=grayord_density,
15301537
omp_nthreads=omp_nthreads,
@@ -1539,14 +1546,16 @@ def init_morph_grayords_wf(
15391546
)
15401547

15411548
workflow.connect([
1549+
(inputnode, select_surfaces, [(metric, metric)]),
1550+
(hemisource, select_surfaces, [('hemi', 'key')]),
15421551
(inputnode, resample_and_mask_wf, [
1543-
(metric, 'inputnode.in_file'),
15441552
('midthickness', 'inputnode.midthickness'),
15451553
('midthickness_fsLR', 'inputnode.midthickness_fsLR'),
15461554
('sphere_reg_fsLR', 'inputnode.sphere_reg_fsLR'),
15471555
('roi', 'inputnode.cortex_mask'),
15481556
]),
15491557
(hemisource, resample_and_mask_wf, [('hemi', 'inputnode.hemi')]),
1558+
(select_surfaces, resample_and_mask_wf, [(metric, 'inputnode.in_file')]),
15501559
(resample_and_mask_wf, cifti_metric, [('outputnode.out_file', 'scalar_surfs')]),
15511560
(cifti_metric, outputnode, [
15521561
('out_file', f'{metric}_fsLR'),
@@ -1557,6 +1566,156 @@ def init_morph_grayords_wf(
15571566
return workflow
15581567

15591568

1569+
def init_myelinmap_fsLR_wf(
1570+
grayord_density: ty.Literal['91k', '170k'],
1571+
omp_nthreads: int,
1572+
mem_gb: float,
1573+
name: str = 'myelinmap_fsLR_wf',
1574+
):
1575+
"""Resample myelinmap volume to fsLR surface.
1576+
1577+
Workflow Graph
1578+
.. workflow::
1579+
:graph2use: colored
1580+
:simple_form: yes
1581+
1582+
from smriprep.workflows.surfaces import init_myelinmap_fsLR_wf
1583+
wf = init_myelinmap_fsLR_wf(grayord_density='91k', omp_nthreads=1, mem_gb=1)
1584+
1585+
Parameters
1586+
----------
1587+
grayord_density : :class:`str`
1588+
Either ``"91k"`` or ``"170k"``, representing the total *grayordinates*.
1589+
omp_nthreads : :class:`int`
1590+
Maximum number of threads an individual process may use
1591+
mem_gb : :class:`float`
1592+
Size of BOLD file in GB
1593+
name : :class:`str`
1594+
Name of workflow (default: ``"myelinmap_fsLR_wf"``)
1595+
1596+
Inputs
1597+
------
1598+
in_file : :class:`str`
1599+
Path to the myelin map in subject volume space
1600+
thickness : :class:`list` of :class:`str`
1601+
Path to left and right hemisphere thickness GIFTI shape files
1602+
midthickness : :class:`list` of :class:`str`
1603+
Path to left and right hemisphere midthickness GIFTI surface files
1604+
midthickness_fsLR : :class:`list` of :class:`str`
1605+
Path to left and right hemisphere midthickness GIFTI surface files in fsLR space
1606+
sphere_reg_fsLR : :class:`list` of :class:`str`
1607+
Path to left and right hemisphere sphere.reg GIFTI surface files,
1608+
mapping from subject to fsLR
1609+
cortex_mask : :class:`list` of :class:`str`
1610+
Path to left and right hemisphere cortex mask GIFTI files
1611+
1612+
Outputs
1613+
-------
1614+
out_fsLR : :class:`str`
1615+
Path to the resampled myelin map in fsLR space
1616+
1617+
"""
1618+
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
1619+
from niworkflows.interfaces.utility import KeySelect
1620+
from niworkflows.interfaces.workbench import VolumeToSurfaceMapping
1621+
1622+
workflow = Workflow(name=name)
1623+
1624+
inputnode = pe.Node(
1625+
niu.IdentityInterface(
1626+
fields=[
1627+
'in_file',
1628+
'thickness',
1629+
'midthickness',
1630+
'midthickness_fsLR',
1631+
'sphere_reg_fsLR',
1632+
'cortex_mask',
1633+
'volume_roi',
1634+
]
1635+
),
1636+
name='inputnode',
1637+
)
1638+
1639+
outputnode = pe.Node(
1640+
niu.IdentityInterface(fields=['out_file', 'out_metadata']),
1641+
name='outputnode',
1642+
)
1643+
1644+
hemisource = pe.Node(
1645+
niu.IdentityInterface(fields=['hemi']),
1646+
name='hemisource',
1647+
iterables=[('hemi', ['L', 'R'])],
1648+
)
1649+
1650+
select_surfaces = pe.Node(
1651+
KeySelect(
1652+
fields=[
1653+
'thickness',
1654+
'midthickness',
1655+
],
1656+
keys=['L', 'R'],
1657+
),
1658+
name='select_surfaces',
1659+
run_without_submitting=True,
1660+
)
1661+
1662+
volume_to_surface = pe.Node(
1663+
VolumeToSurfaceMapping(method='myelin-style', sigma=fwhm2sigma(5)),
1664+
name='volume_to_surface',
1665+
mem_gb=mem_gb * 3,
1666+
n_procs=omp_nthreads,
1667+
)
1668+
# smooth = pe.Node(
1669+
# MetricSmooth(sigma=fwhm2sigma(4), nearest=True),
1670+
# name='metric_dilate',
1671+
# mem_gb=1,
1672+
# n_procs=omp_nthreads,
1673+
# )
1674+
resample_and_mask_wf = init_resample_and_mask_wf(
1675+
grayord_density=grayord_density,
1676+
omp_nthreads=omp_nthreads,
1677+
mem_gb=mem_gb,
1678+
)
1679+
cifti_myelinmap = pe.JoinNode(
1680+
GenerateDScalar(grayordinates=grayord_density, scalar_name='MyelinMap'),
1681+
name='cifti_myelinmap',
1682+
joinfield=['scalar_surfs'],
1683+
joinsource='hemisource',
1684+
)
1685+
1686+
workflow.connect([
1687+
(inputnode, select_surfaces, [
1688+
('midthickness', 'midthickness'),
1689+
('thickness', 'thickness'),
1690+
]),
1691+
(hemisource, select_surfaces, [('hemi', 'key')]),
1692+
# Resample volume to native surface
1693+
(inputnode, volume_to_surface, [
1694+
('in_file', 'volume_file'),
1695+
('ribbon_file', 'ribbon_roi'),
1696+
]),
1697+
(select_surfaces, volume_to_surface, [
1698+
('midthickness', 'surface_file'),
1699+
('thickness', 'thickness'),
1700+
]),
1701+
(inputnode, resample_and_mask_wf, [
1702+
('midthickness', 'inputnode.midthickness'),
1703+
('midthickness_fsLR', 'inputnode.midthickness_fsLR'),
1704+
('sphere_reg_fsLR', 'inputnode.sphere_reg_fsLR'),
1705+
('cortex_mask', 'inputnode.cortex_mask'),
1706+
]),
1707+
(hemisource, resample_and_mask_wf, [('hemi', 'inputnode.hemi')]),
1708+
(volume_to_surface, resample_and_mask_wf, [('out_file', 'inputnode.in_file')]),
1709+
(resample_and_mask_wf, cifti_myelinmap, [('outputnode.out_file', 'scalar_surfs')]),
1710+
(cifti_myelinmap, outputnode, [
1711+
('out_file', 'out_file'),
1712+
('out_metadata', 'out_metadata'),
1713+
]),
1714+
]) # fmt:skip
1715+
1716+
return workflow
1717+
1718+
15601719
def init_resample_and_mask_wf(
15611720
grayord_density: ty.Literal['91k', '170k'],
15621721
omp_nthreads: int,
@@ -1590,17 +1749,23 @@ def init_resample_and_mask_wf(
15901749
15911750
Inputs
15921751
------
1752+
in_file : :class:`str`
1753+
Path to metric file in subject space
1754+
hemi : :class:`str`
1755+
Hemisphere identifier (``"L"`` or ``"R"``)
15931756
midthickness : :class:`list` of :class:`str`
15941757
Path to left and right hemisphere midthickness GIFTI surfaces.
15951758
midthickness_fsLR : :class:`list` of :class:`str`
15961759
Path to left and right hemisphere midthickness GIFTI surfaces in fsLR space.
15971760
sphere_reg_fsLR : :class:`list` of :class:`str`
15981761
Path to left and right hemisphere sphere.reg GIFTI surfaces, mapping from subject to fsLR
1762+
cortex_mask : :class:`list` of :class:`str`
1763+
Path to left and right hemisphere cortex mask GIFTI files
15991764
16001765
Outputs
16011766
-------
1602-
metric_fsLR : :class:`list` of :class:`str`
1603-
Path to metrics resampled as GIFTI files in fsLR space
1767+
metric_fsLR : :class:`str`
1768+
Path to metric resampled as GIFTI file in fsLR space
16041769
16051770
"""
16061771
import templateflow.api as tf
@@ -1633,7 +1798,6 @@ def init_resample_and_mask_wf(
16331798
select_surfaces = pe.Node(
16341799
KeySelect(
16351800
fields=[
1636-
'in_file',
16371801
'midthickness',
16381802
'midthickness_fsLR',
16391803
'sphere_reg_fsLR',
@@ -1675,15 +1839,14 @@ def init_resample_and_mask_wf(
16751839

16761840
workflow.connect([
16771841
(inputnode, select_surfaces, [
1678-
('in_file', 'in_file'),
16791842
('midthickness', 'midthickness'),
16801843
('midthickness_fsLR', 'midthickness_fsLR'),
16811844
('sphere_reg_fsLR', 'sphere_reg_fsLR'),
16821845
('cortex_mask', 'cortex_mask'),
16831846
('hemi', 'key'),
16841847
]),
1848+
(inputnode, resample_to_fsLR, [('in_file', 'in_file')]),
16851849
(select_surfaces, resample_to_fsLR, [
1686-
('in_file', 'in_file'),
16871850
('sphere_reg_fsLR', 'current_sphere'),
16881851
('template_sphere', 'new_sphere'),
16891852
('midthickness', 'current_area'),

0 commit comments

Comments
 (0)