Skip to content

Commit 47469d8

Browse files
committed
WIP
1 parent 58c4758 commit 47469d8

File tree

2 files changed

+185
-9
lines changed

2 files changed

+185
-9
lines changed

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
@@ -645,6 +647,7 @@ def init_anat_fit_wf(
645647
'sphere_reg_fsLR',
646648
'sphere_reg_msm',
647649
'anat_ribbon',
650+
't1t2_ratio',
648651
# Reverse transform; not computable from forward transform
649652
'std2anat_xfm',
650653
# Metadata
@@ -1308,6 +1311,16 @@ def init_anat_fit_wf(
13081311
LOGGER.info('ANAT Stage 8a: Found pre-computed cortical ribbon mask')
13091312
outputnode.inputs.anat_ribbon = precomputed['anat_ribbon']
13101313

1314+
if t2w and 't1t2ratio' not in precomputed:
1315+
LOGGER.info('ANAT Stage 8b: Creating T1w/T2w ratio map')
1316+
# Commented out to pacify linter.
1317+
# t1t2_ratio = pe.Node(T1T2Ratio(), name='t1t2_ratio')
1318+
1319+
elif not t2w:
1320+
LOGGER.info('ANAT No T2w images provided - skipping Stage 8b')
1321+
else:
1322+
LOGGER.info('ANAT Found precomputed T1w/T2w ratio map - skipping Stage 8b')
1323+
13111324
# Stage 9: Baseline fsLR registration
13121325
if len(precomputed.get('sphere_reg_fsLR', [])) < 2:
13131326
LOGGER.info('ANAT Stage 9: Creating fsLR registration sphere')

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

@@ -1449,8 +1451,6 @@ def init_morph_grayords_wf(
14491451
"""
14501452
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
14511453

1452-
from smriprep.interfaces.cifti import GenerateDScalar
1453-
14541454
workflow = Workflow(name=name)
14551455
workflow.__desc__ = f"""\
14561456
*Grayordinate* "dscalar" files containing {grayord_density} samples were
@@ -1495,7 +1495,14 @@ def init_morph_grayords_wf(
14951495
name='outputnode',
14961496
)
14971497

1498-
for metric in ('curv', 'sulc', 'thickness'):
1498+
metrics = ['curv', 'sulc', 'thickness']
1499+
select_surfaces = pe.Node(
1500+
KeySelect(fields=metrics, keys=['L', 'R']),
1501+
name='select_surfaces',
1502+
run_without_submitting=True,
1503+
)
1504+
1505+
for metric in metrics:
14991506
resample_and_mask_wf = init_resample_and_mask_wf(
15001507
grayord_density=grayord_density,
15011508
omp_nthreads=omp_nthreads,
@@ -1510,14 +1517,16 @@ def init_morph_grayords_wf(
15101517
)
15111518

15121519
workflow.connect([
1520+
(inputnode, select_surfaces, [(metric, metric)]),
1521+
(hemisource, select_surfaces, [('hemi', 'key')]),
15131522
(inputnode, resample_and_mask_wf, [
1514-
(metric, 'inputnode.in_file'),
15151523
('midthickness', 'inputnode.midthickness'),
15161524
('midthickness_fsLR', 'inputnode.midthickness_fsLR'),
15171525
('sphere_reg_fsLR', 'inputnode.sphere_reg_fsLR'),
15181526
('roi', 'inputnode.cortex_mask'),
15191527
]),
15201528
(hemisource, resample_and_mask_wf, [('hemi', 'inputnode.hemi')]),
1529+
(select_surfaces, resample_and_mask_wf, [(metric, 'inputnode.in_file')]),
15211530
(resample_and_mask_wf, cifti_metric, [('outputnode.out_file', 'scalar_surfs')]),
15221531
(cifti_metric, outputnode, [
15231532
('out_file', f'{metric}_fsLR'),
@@ -1528,6 +1537,156 @@ def init_morph_grayords_wf(
15281537
return workflow
15291538

15301539

1540+
def init_myelinmap_fsLR_wf(
1541+
grayord_density: ty.Literal['91k', '170k'],
1542+
omp_nthreads: int,
1543+
mem_gb: float,
1544+
name: str = 'myelinmap_fsLR_wf',
1545+
):
1546+
"""Resample myelinmap volume to fsLR surface.
1547+
1548+
Workflow Graph
1549+
.. workflow::
1550+
:graph2use: colored
1551+
:simple_form: yes
1552+
1553+
from smriprep.workflows.surfaces import init_myelinmap_fsLR_wf
1554+
wf = init_myelinmap_fsLR_wf(grayord_density='91k', omp_nthreads=1, mem_gb=1)
1555+
1556+
Parameters
1557+
----------
1558+
grayord_density : :class:`str`
1559+
Either ``"91k"`` or ``"170k"``, representing the total *grayordinates*.
1560+
omp_nthreads : :class:`int`
1561+
Maximum number of threads an individual process may use
1562+
mem_gb : :class:`float`
1563+
Size of BOLD file in GB
1564+
name : :class:`str`
1565+
Name of workflow (default: ``"myelinmap_fsLR_wf"``)
1566+
1567+
Inputs
1568+
------
1569+
in_file : :class:`str`
1570+
Path to the myelin map in subject volume space
1571+
thickness : :class:`list` of :class:`str`
1572+
Path to left and right hemisphere thickness GIFTI shape files
1573+
midthickness : :class:`list` of :class:`str`
1574+
Path to left and right hemisphere midthickness GIFTI surface files
1575+
midthickness_fsLR : :class:`list` of :class:`str`
1576+
Path to left and right hemisphere midthickness GIFTI surface files in fsLR space
1577+
sphere_reg_fsLR : :class:`list` of :class:`str`
1578+
Path to left and right hemisphere sphere.reg GIFTI surface files,
1579+
mapping from subject to fsLR
1580+
cortex_mask : :class:`list` of :class:`str`
1581+
Path to left and right hemisphere cortex mask GIFTI files
1582+
1583+
Outputs
1584+
-------
1585+
out_fsLR : :class:`str`
1586+
Path to the resampled myelin map in fsLR space
1587+
1588+
"""
1589+
from niworkflows.engine.workflows import LiterateWorkflow as Workflow
1590+
from niworkflows.interfaces.utility import KeySelect
1591+
from niworkflows.interfaces.workbench import VolumeToSurfaceMapping
1592+
1593+
workflow = Workflow(name=name)
1594+
1595+
inputnode = pe.Node(
1596+
niu.IdentityInterface(
1597+
fields=[
1598+
'in_file',
1599+
'thickness',
1600+
'midthickness',
1601+
'midthickness_fsLR',
1602+
'sphere_reg_fsLR',
1603+
'cortex_mask',
1604+
'volume_roi',
1605+
]
1606+
),
1607+
name='inputnode',
1608+
)
1609+
1610+
outputnode = pe.Node(
1611+
niu.IdentityInterface(fields=['out_file', 'out_metadata']),
1612+
name='outputnode',
1613+
)
1614+
1615+
hemisource = pe.Node(
1616+
niu.IdentityInterface(fields=['hemi']),
1617+
name='hemisource',
1618+
iterables=[('hemi', ['L', 'R'])],
1619+
)
1620+
1621+
select_surfaces = pe.Node(
1622+
KeySelect(
1623+
fields=[
1624+
'thickness',
1625+
'midthickness',
1626+
],
1627+
keys=['L', 'R'],
1628+
),
1629+
name='select_surfaces',
1630+
run_without_submitting=True,
1631+
)
1632+
1633+
volume_to_surface = pe.Node(
1634+
VolumeToSurfaceMapping(method='myelin-style', sigma=fwhm2sigma(5)),
1635+
name='volume_to_surface',
1636+
mem_gb=mem_gb * 3,
1637+
n_procs=omp_nthreads,
1638+
)
1639+
# smooth = pe.Node(
1640+
# MetricSmooth(sigma=fwhm2sigma(4), nearest=True),
1641+
# name='metric_dilate',
1642+
# mem_gb=1,
1643+
# n_procs=omp_nthreads,
1644+
# )
1645+
resample_and_mask_wf = init_resample_and_mask_wf(
1646+
grayord_density=grayord_density,
1647+
omp_nthreads=omp_nthreads,
1648+
mem_gb=mem_gb,
1649+
)
1650+
cifti_myelinmap = pe.JoinNode(
1651+
GenerateDScalar(grayordinates=grayord_density, scalar_name='MyelinMap'),
1652+
name='cifti_myelinmap',
1653+
joinfield=['scalar_surfs'],
1654+
joinsource='hemisource',
1655+
)
1656+
1657+
workflow.connect([
1658+
(inputnode, select_surfaces, [
1659+
('midthickness', 'midthickness'),
1660+
('thickness', 'thickness'),
1661+
]),
1662+
(hemisource, select_surfaces, [('hemi', 'key')]),
1663+
# Resample volume to native surface
1664+
(inputnode, volume_to_surface, [
1665+
('in_file', 'volume_file'),
1666+
('ribbon_file', 'ribbon_roi'),
1667+
]),
1668+
(select_surfaces, volume_to_surface, [
1669+
('midthickness', 'surface_file'),
1670+
('thickness', 'thickness'),
1671+
]),
1672+
(inputnode, resample_and_mask_wf, [
1673+
('midthickness', 'inputnode.midthickness'),
1674+
('midthickness_fsLR', 'inputnode.midthickness_fsLR'),
1675+
('sphere_reg_fsLR', 'inputnode.sphere_reg_fsLR'),
1676+
('cortex_mask', 'inputnode.cortex_mask'),
1677+
]),
1678+
(hemisource, resample_and_mask_wf, [('hemi', 'inputnode.hemi')]),
1679+
(volume_to_surface, resample_and_mask_wf, [('out_file', 'inputnode.in_file')]),
1680+
(resample_and_mask_wf, cifti_myelinmap, [('outputnode.out_file', 'scalar_surfs')]),
1681+
(cifti_myelinmap, outputnode, [
1682+
('out_file', 'out_file'),
1683+
('out_metadata', 'out_metadata'),
1684+
]),
1685+
]) # fmt:skip
1686+
1687+
return workflow
1688+
1689+
15311690
def init_resample_and_mask_wf(
15321691
grayord_density: ty.Literal['91k', '170k'],
15331692
omp_nthreads: int,
@@ -1561,17 +1720,23 @@ def init_resample_and_mask_wf(
15611720
15621721
Inputs
15631722
------
1723+
in_file : :class:`str`
1724+
Path to metric file in subject space
1725+
hemi : :class:`str`
1726+
Hemisphere identifier (``"L"`` or ``"R"``)
15641727
midthickness : :class:`list` of :class:`str`
15651728
Path to left and right hemisphere midthickness GIFTI surfaces.
15661729
midthickness_fsLR : :class:`list` of :class:`str`
15671730
Path to left and right hemisphere midthickness GIFTI surfaces in fsLR space.
15681731
sphere_reg_fsLR : :class:`list` of :class:`str`
15691732
Path to left and right hemisphere sphere.reg GIFTI surfaces, mapping from subject to fsLR
1733+
cortex_mask : :class:`list` of :class:`str`
1734+
Path to left and right hemisphere cortex mask GIFTI files
15701735
15711736
Outputs
15721737
-------
1573-
metric_fsLR : :class:`list` of :class:`str`
1574-
Path to metrics resampled as GIFTI files in fsLR space
1738+
metric_fsLR : :class:`str`
1739+
Path to metric resampled as GIFTI file in fsLR space
15751740
15761741
"""
15771742
import templateflow.api as tf
@@ -1604,7 +1769,6 @@ def init_resample_and_mask_wf(
16041769
select_surfaces = pe.Node(
16051770
KeySelect(
16061771
fields=[
1607-
'in_file',
16081772
'midthickness',
16091773
'midthickness_fsLR',
16101774
'sphere_reg_fsLR',
@@ -1646,15 +1810,14 @@ def init_resample_and_mask_wf(
16461810

16471811
workflow.connect([
16481812
(inputnode, select_surfaces, [
1649-
('in_file', 'in_file'),
16501813
('midthickness', 'midthickness'),
16511814
('midthickness_fsLR', 'midthickness_fsLR'),
16521815
('sphere_reg_fsLR', 'sphere_reg_fsLR'),
16531816
('cortex_mask', 'cortex_mask'),
16541817
('hemi', 'key'),
16551818
]),
1819+
(inputnode, resample_to_fsLR, [('in_file', 'in_file')]),
16561820
(select_surfaces, resample_to_fsLR, [
1657-
('in_file', 'in_file'),
16581821
('sphere_reg_fsLR', 'current_sphere'),
16591822
('template_sphere', 'new_sphere'),
16601823
('midthickness', 'current_area'),

0 commit comments

Comments
 (0)