30
30
31
31
import typing as ty
32
32
33
+ from nibabel .processing import fwhm2sigma
33
34
from nipype .interfaces import freesurfer as fs
34
35
from nipype .interfaces import io as nio
35
36
from nipype .interfaces import utility as niu
54
55
)
55
56
56
57
import smriprep
58
+ from smriprep .interfaces .cifti import GenerateDScalar
57
59
from smriprep .interfaces .surf import MakeRibbon
58
60
from smriprep .interfaces .workbench import SurfaceResample
59
61
@@ -1478,8 +1480,6 @@ def init_morph_grayords_wf(
1478
1480
"""
1479
1481
from niworkflows .engine .workflows import LiterateWorkflow as Workflow
1480
1482
1481
- from smriprep .interfaces .cifti import GenerateDScalar
1482
-
1483
1483
workflow = Workflow (name = name )
1484
1484
workflow .__desc__ = f"""\
1485
1485
*Grayordinate* "dscalar" files containing { grayord_density } samples were
@@ -1524,7 +1524,14 @@ def init_morph_grayords_wf(
1524
1524
name = 'outputnode' ,
1525
1525
)
1526
1526
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 :
1528
1535
resample_and_mask_wf = init_resample_and_mask_wf (
1529
1536
grayord_density = grayord_density ,
1530
1537
omp_nthreads = omp_nthreads ,
@@ -1539,14 +1546,16 @@ def init_morph_grayords_wf(
1539
1546
)
1540
1547
1541
1548
workflow .connect ([
1549
+ (inputnode , select_surfaces , [(metric , metric )]),
1550
+ (hemisource , select_surfaces , [('hemi' , 'key' )]),
1542
1551
(inputnode , resample_and_mask_wf , [
1543
- (metric , 'inputnode.in_file' ),
1544
1552
('midthickness' , 'inputnode.midthickness' ),
1545
1553
('midthickness_fsLR' , 'inputnode.midthickness_fsLR' ),
1546
1554
('sphere_reg_fsLR' , 'inputnode.sphere_reg_fsLR' ),
1547
1555
('roi' , 'inputnode.cortex_mask' ),
1548
1556
]),
1549
1557
(hemisource , resample_and_mask_wf , [('hemi' , 'inputnode.hemi' )]),
1558
+ (select_surfaces , resample_and_mask_wf , [(metric , 'inputnode.in_file' )]),
1550
1559
(resample_and_mask_wf , cifti_metric , [('outputnode.out_file' , 'scalar_surfs' )]),
1551
1560
(cifti_metric , outputnode , [
1552
1561
('out_file' , f'{ metric } _fsLR' ),
@@ -1557,6 +1566,156 @@ def init_morph_grayords_wf(
1557
1566
return workflow
1558
1567
1559
1568
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
+
1560
1719
def init_resample_and_mask_wf (
1561
1720
grayord_density : ty .Literal ['91k' , '170k' ],
1562
1721
omp_nthreads : int ,
@@ -1590,17 +1749,23 @@ def init_resample_and_mask_wf(
1590
1749
1591
1750
Inputs
1592
1751
------
1752
+ in_file : :class:`str`
1753
+ Path to metric file in subject space
1754
+ hemi : :class:`str`
1755
+ Hemisphere identifier (``"L"`` or ``"R"``)
1593
1756
midthickness : :class:`list` of :class:`str`
1594
1757
Path to left and right hemisphere midthickness GIFTI surfaces.
1595
1758
midthickness_fsLR : :class:`list` of :class:`str`
1596
1759
Path to left and right hemisphere midthickness GIFTI surfaces in fsLR space.
1597
1760
sphere_reg_fsLR : :class:`list` of :class:`str`
1598
1761
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
1599
1764
1600
1765
Outputs
1601
1766
-------
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
1604
1769
1605
1770
"""
1606
1771
import templateflow .api as tf
@@ -1633,7 +1798,6 @@ def init_resample_and_mask_wf(
1633
1798
select_surfaces = pe .Node (
1634
1799
KeySelect (
1635
1800
fields = [
1636
- 'in_file' ,
1637
1801
'midthickness' ,
1638
1802
'midthickness_fsLR' ,
1639
1803
'sphere_reg_fsLR' ,
@@ -1675,15 +1839,14 @@ def init_resample_and_mask_wf(
1675
1839
1676
1840
workflow .connect ([
1677
1841
(inputnode , select_surfaces , [
1678
- ('in_file' , 'in_file' ),
1679
1842
('midthickness' , 'midthickness' ),
1680
1843
('midthickness_fsLR' , 'midthickness_fsLR' ),
1681
1844
('sphere_reg_fsLR' , 'sphere_reg_fsLR' ),
1682
1845
('cortex_mask' , 'cortex_mask' ),
1683
1846
('hemi' , 'key' ),
1684
1847
]),
1848
+ (inputnode , resample_to_fsLR , [('in_file' , 'in_file' )]),
1685
1849
(select_surfaces , resample_to_fsLR , [
1686
- ('in_file' , 'in_file' ),
1687
1850
('sphere_reg_fsLR' , 'current_sphere' ),
1688
1851
('template_sphere' , 'new_sphere' ),
1689
1852
('midthickness' , 'current_area' ),
0 commit comments