Skip to content

Commit 5e60fd8

Browse files
authored
Merge pull request #359 from mgxd/enh/split-surfaces
ENH: Separate surfaces and morphometrics into standalone outputs
2 parents 23f9dc4 + cf49b5b commit 5e60fd8

File tree

2 files changed

+98
-3
lines changed

2 files changed

+98
-3
lines changed

smriprep/interfaces/surf.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
SimpleInterface,
3434
File,
3535
isdefined,
36+
InputMultiObject,
37+
traits,
3638
)
3739

3840

@@ -114,6 +116,45 @@ def _run_interface(self, runtime):
114116
return runtime
115117

116118

119+
class AggregateSurfacesInputSpec(TraitedSpec):
120+
surfaces = InputMultiObject(File(exists=True), desc="Input surfaces")
121+
morphometrics = InputMultiObject(File(exists=True), desc="Input morphometrics")
122+
123+
124+
class AggregateSurfacesOutputSpec(TraitedSpec):
125+
pial = traits.List(File(), maxlen=2, desc="Pial surfaces")
126+
white = traits.List(File(), maxlen=2, desc="White surfaces")
127+
inflated = traits.List(File(), maxlen=2, desc="Inflated surfaces")
128+
midthickness = traits.List(File(), maxlen=2, desc="Midthickness (or graymid) surfaces")
129+
thickness = traits.List(File(), maxlen=2, desc="Cortical thickness maps")
130+
sulc = traits.List(File(), maxlen=2, desc="Sulcal depth maps")
131+
curv = traits.List(File(), maxlen=2, desc="Curvature maps")
132+
133+
134+
class AggregateSurfaces(SimpleInterface):
135+
"""Aggregate and group surfaces & morphometrics into left/right pairs."""
136+
input_spec = AggregateSurfacesInputSpec
137+
output_spec = AggregateSurfacesOutputSpec
138+
139+
def _run_interface(self, runtime):
140+
from collections import defaultdict
141+
import os
142+
import re
143+
144+
container = defaultdict(list)
145+
inputs = (self.inputs.surfaces or []) + (self.inputs.morphometrics or [])
146+
findre = re.compile(
147+
r'(?:^|[^d])(?P<name>white|pial|inflated|midthickness|thickness|sulc|curv)'
148+
)
149+
for surface in sorted(inputs, key=os.path.basename):
150+
match = findre.search(os.path.basename(surface))
151+
if match:
152+
container[match.group('name')].append(surface)
153+
for name, files in container.items():
154+
self._results[name] = files
155+
return runtime
156+
157+
117158
def normalize_surfs(in_file: str, transform_file: str, newpath: Optional[str] = None) -> str:
118159
"""
119160
Update GIFTI metadata and apply rigid coordinate correction.

smriprep/workflows/surfaces.py

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,13 @@ def init_surface_recon_wf(*, omp_nthreads, hires, name="surface_recon_wf"):
209209
"out_aseg",
210210
"out_aparc",
211211
"morphometrics",
212+
"midthickness",
213+
"pial",
214+
"white",
215+
"inflated",
216+
"thickness",
217+
"sulc",
218+
"curv",
212219
]
213220
),
214221
name="outputnode",
@@ -294,7 +301,14 @@ def init_surface_recon_wf(*, omp_nthreads, hires, name="surface_recon_wf"):
294301
(autorecon_resume_wf, outputnode, [('outputnode.subjects_dir', 'subjects_dir'),
295302
('outputnode.subject_id', 'subject_id')]),
296303
(gifti_surface_wf, outputnode, [('outputnode.surfaces', 'surfaces'),
297-
('outputnode.morphometrics', 'morphometrics')]),
304+
('outputnode.morphometrics', 'morphometrics'),
305+
('outputnode.midthickness', 'midthickness'),
306+
('outputnode.pial', 'pial'),
307+
('outputnode.white', 'white'),
308+
('outputnode.inflated', 'inflated'),
309+
('outputnode.thickness', 'thickness'),
310+
('outputnode.sulc', 'sulc'),
311+
('outputnode.curv', 'curv')]),
298312
(t1w2fsnative_xfm, outputnode, [('out_lta', 't1w2fsnative_xfm')]),
299313
(fsnative2t1w_xfm, outputnode, [('out_reg_file', 'fsnative2t1w_xfm')]),
300314
(refine, outputnode, [('out_file', 'out_brainmask')]),
@@ -574,23 +588,51 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
574588
575589
Outputs
576590
-------
591+
midthickness
592+
Left and right midthickness (or graymid) surface GIFTIs
593+
pial
594+
Left and right pial surface GIFTIs
595+
white
596+
Left and right white surface GIFTIs
597+
inflated
598+
Left and right inflated surface GIFTIs
577599
surfaces
578600
GIFTI surfaces for gray/white matter boundary, pial surface,
579601
midthickness (or graymid) surface, and inflated surfaces
602+
thickness
603+
Left and right cortical thickness GIFTIs
604+
sulc
605+
Left and right sulcal depth map GIFTIs
606+
curv
607+
Left and right curvature map GIFTIs
580608
morphometrics
581609
GIFTIs of cortical thickness, curvature, and sulcal depth
582610
583611
"""
584612
from ..interfaces.freesurfer import MRIsConvertData
585-
from ..interfaces.surf import NormalizeSurf
613+
from ..interfaces.surf import NormalizeSurf, AggregateSurfaces
586614

587615
workflow = Workflow(name=name)
588616

589617
inputnode = pe.Node(
590618
niu.IdentityInterface(["subjects_dir", "subject_id", "fsnative2t1w_xfm"]),
591619
name="inputnode",
592620
)
593-
outputnode = pe.Node(niu.IdentityInterface(["surfaces", "morphometrics"]), name="outputnode")
621+
outputnode = pe.Node(
622+
niu.IdentityInterface([
623+
"pial",
624+
"white",
625+
"inflated",
626+
"midthickness",
627+
"thickness",
628+
"sulc",
629+
"curv",
630+
# Preserve grouping
631+
"surfaces",
632+
"morphometrics",
633+
]),
634+
name="outputnode"
635+
)
594636

595637
get_surfaces = pe.Node(nio.FreeSurferSource(), name="get_surfaces")
596638

@@ -624,6 +666,8 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
624666
name="morphs2gii",
625667
)
626668

669+
agg_surfaces = pe.Node(AggregateSurfaces(), name="agg_surfaces")
670+
627671
# fmt:off
628672
workflow.connect([
629673
(inputnode, get_surfaces, [('subjects_dir', 'subjects_dir'),
@@ -648,6 +692,16 @@ def init_gifti_surface_wf(*, name="gifti_surface_wf"):
648692
('curv', 'in3')]),
649693
(surfmorph_list, morphs2gii, [('out', 'scalarcurv_file')]),
650694
(morphs2gii, outputnode, [('converted', 'morphometrics')]),
695+
# Output individual surfaces as well
696+
(fix_surfs, agg_surfaces, [('out_file', 'surfaces')]),
697+
(morphs2gii, agg_surfaces, [('converted', 'morphometrics')]),
698+
(agg_surfaces, outputnode, [('pial', 'pial'),
699+
('white', 'white'),
700+
('inflated', 'inflated'),
701+
('midthickness', 'midthickness'),
702+
('thickness', 'thickness'),
703+
('sulc', 'sulc'),
704+
('curv', 'curv')]),
651705
])
652706
# fmt:on
653707
return workflow

0 commit comments

Comments
 (0)