3030
3131import typing as ty
3232
33+ from nibabel .processing import fwhm2sigma
3334from nipype .interfaces import freesurfer as fs
3435from nipype .interfaces import io as nio
3536from nipype .interfaces import utility as niu
5455)
5556
5657import smriprep
58+ from smriprep .interfaces .cifti import GenerateDScalar
5759from smriprep .interfaces .surf import MakeRibbon
5860from 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+
15311690def 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