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
@@ -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+
15601719def 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