Skip to content

Commit ce09d87

Browse files
committed
RF: Generalize anatomical reference used in surface workflows
1 parent 3889004 commit ce09d87

File tree

1 file changed

+45
-53
lines changed

1 file changed

+45
-53
lines changed

smriprep/workflows/surfaces.py

Lines changed: 45 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
)
4444
from niworkflows.interfaces.freesurfer import PatchedRobustRegister as RobustRegister
4545
from niworkflows.interfaces.nitransforms import ConcatenateXFMs
46+
from niworkflows.interfaces.patches import FreeSurferSource
4647
from niworkflows.interfaces.utility import KeySelect
4748
from niworkflows.interfaces.workbench import (
4849
MetricDilate,
@@ -228,7 +229,7 @@ def init_surface_recon_wf(
228229

229230
autorecon_resume_wf = init_autorecon_resume_wf(omp_nthreads=omp_nthreads)
230231

231-
get_surfaces = pe.Node(nio.FreeSurferSource(), name='get_surfaces')
232+
get_surfaces = pe.Node(FreeSurferSource(), name='get_surfaces')
232233

233234
midthickness = pe.MapNode(
234235
MakeMidthickness(thickness=True, distance=0.5, out_name='midthickness'),
@@ -284,7 +285,7 @@ def init_surface_recon_wf(
284285
]) # fmt:skip
285286
else:
286287
# Pretend to be the autorecon1 node so fsnative2t1w_xfm gets run ASAP
287-
fs_base_inputs = autorecon1 = pe.Node(nio.FreeSurferSource(), name='fs_base_inputs')
288+
fs_base_inputs = autorecon1 = pe.Node(FreeSurferSource(), name='fs_base_inputs')
288289

289290
workflow.connect([
290291
(inputnode, fs_base_inputs, [
@@ -328,7 +329,9 @@ def init_surface_recon_wf(
328329
return workflow
329330

330331

331-
def init_refinement_wf(*, name='refinement_wf'):
332+
def init_refinement_wf(
333+
*, image_type: ty.Literal['T1w', 'T2w'] = 'T1w', name: str = 'refinement_wf'
334+
) -> Workflow:
332335
r"""
333336
Refine ANTs brain extraction with FreeSurfer segmentation
334337
@@ -346,35 +349,19 @@ def init_refinement_wf(*, name='refinement_wf'):
346349
FreeSurfer SUBJECTS_DIR
347350
subject_id
348351
FreeSurfer subject ID
349-
fsnative2t1w_xfm
350-
LTA-style affine matrix translating from FreeSurfer-conformed subject space to T1w
352+
fsnative2anat_xfm
353+
LTA-style affine matrix translating from FreeSurfer-conformed subject space to anatomical
351354
reference_image
352355
Input
353-
t2w
354-
List of T2-weighted structural images (only first used)
355-
flair
356-
List of FLAIR images
357-
skullstripped_t1
358-
Skull-stripped T1-weighted image (or mask of image)
359356
ants_segs
360357
Brain tissue segmentation from ANTS ``antsBrainExtraction.sh``
361-
corrected_t1
362-
INU-corrected, merged T1-weighted image
363358
subjects_dir
364359
FreeSurfer SUBJECTS_DIR
365360
subject_id
366361
FreeSurfer subject ID
367362
368363
Outputs
369364
-------
370-
subjects_dir
371-
FreeSurfer SUBJECTS_DIR
372-
subject_id
373-
FreeSurfer subject ID
374-
t1w2fsnative_xfm
375-
LTA-style affine matrix translating from T1w to FreeSurfer-conformed subject space
376-
fsnative2t1w_xfm
377-
LTA-style affine matrix translating from FreeSurfer-conformed subject space to T1w
378365
out_brainmask
379366
Refined brainmask, derived from FreeSurfer's ``aseg`` volume
380367
@@ -397,7 +384,7 @@ def init_refinement_wf(*, name='refinement_wf'):
397384
fields=[
398385
'reference_image',
399386
'ants_segs',
400-
'fsnative2t1w_xfm',
387+
'fsnative2anat_xfm',
401388
'subjects_dir',
402389
'subject_id',
403390
]
@@ -413,24 +400,22 @@ def init_refinement_wf(*, name='refinement_wf'):
413400
name='outputnode',
414401
)
415402

416-
aseg_to_native_wf = init_segs_to_native_wf()
403+
aseg_to_native_wf = init_segs_to_native_wf(image_type=image_type)
417404
refine = pe.Node(RefineBrainMask(), name='refine')
418405

419-
# fmt:off
420406
workflow.connect([
421407
# Refine ANTs mask, deriving new mask from FS' aseg
422408
(inputnode, aseg_to_native_wf, [
423409
('subjects_dir', 'inputnode.subjects_dir'),
424410
('subject_id', 'inputnode.subject_id'),
425411
('reference_image', 'inputnode.in_file'),
426-
('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
412+
('fsnative2t1w_xfm', 'inputnode.fsnative2anat_xfm'),
427413
]),
428414
(inputnode, refine, [('reference_image', 'in_anat'),
429415
('ants_segs', 'in_ants')]),
430416
(aseg_to_native_wf, refine, [('outputnode.out_file', 'in_aseg')]),
431417
(refine, outputnode, [('out_file', 'out_brainmask')]),
432-
])
433-
# fmt:on
418+
]) # fmt:skip
434419

435420
return workflow
436421

@@ -610,8 +595,8 @@ def _dedup(in_list):
610595

611596
def init_surface_derivatives_wf(
612597
*,
613-
cifti_output: ty.Literal['91k', '170k', False] = False,
614-
name='surface_derivatives_wf',
598+
image_type: ty.Literal['T1w', 'T2w'] = 'T1w',
599+
name: str = 'surface_derivatives_wf',
615600
):
616601
r"""
617602
Generate sMRIPrep derivatives from FreeSurfer derivatives
@@ -627,9 +612,9 @@ def init_surface_derivatives_wf(
627612
Inputs
628613
------
629614
reference
630-
Reference image in native T1w space, for defining a resampling grid
631-
fsnative2t1w_xfm
632-
LTA-style affine matrix translating from FreeSurfer-conformed subject space to T1w
615+
Reference image in native anatomical space, for defining a resampling grid
616+
fsnative2anat_xfm
617+
LTA-style affine matrix translating from FreeSurfer-conformed subject space to anatomical
633618
subjects_dir
634619
FreeSurfer SUBJECTS_DIR
635620
subject_id
@@ -643,9 +628,9 @@ def init_surface_derivatives_wf(
643628
morphometrics
644629
GIFTIs of cortical thickness, curvature, and sulcal depth
645630
out_aseg
646-
FreeSurfer's aseg segmentation, in native T1w space
631+
FreeSurfer's aseg segmentation, in native anatomical space
647632
out_aparc
648-
FreeSurfer's aparc+aseg segmentation, in native T1w space
633+
FreeSurfer's aparc+aseg segmentation, in native anatomical space
649634
650635
See also
651636
--------
@@ -659,7 +644,7 @@ def init_surface_derivatives_wf(
659644
fields=[
660645
'subjects_dir',
661646
'subject_id',
662-
'fsnative2t1w_xfm',
647+
'fsnative2anat_xfm',
663648
'reference',
664649
]
665650
),
@@ -679,16 +664,16 @@ def init_surface_derivatives_wf(
679664

680665
gifti_surfaces_wf = init_gifti_surfaces_wf(surfaces=['inflated'])
681666
gifti_morph_wf = init_gifti_morphometrics_wf(morphometrics=['curv'])
682-
aseg_to_native_wf = init_segs_to_native_wf()
683-
aparc_to_native_wf = init_segs_to_native_wf(segmentation='aparc_aseg')
667+
aseg_to_native_wf = init_segs_to_native_wf(image_type=image_type)
668+
aparc_to_native_wf = init_segs_to_native_wf(image_type=image_type, segmentation='aparc_aseg')
684669

685670
# fmt:off
686671
workflow.connect([
687672
# Configuration
688673
(inputnode, gifti_surfaces_wf, [
689674
('subjects_dir', 'inputnode.subjects_dir'),
690675
('subject_id', 'inputnode.subject_id'),
691-
('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
676+
('fsnative2anat_xfm', 'inputnode.fsnative2anat_xfm'),
692677
]),
693678
(inputnode, gifti_morph_wf, [
694679
('subjects_dir', 'inputnode.subjects_dir'),
@@ -698,13 +683,13 @@ def init_surface_derivatives_wf(
698683
('subjects_dir', 'inputnode.subjects_dir'),
699684
('subject_id', 'inputnode.subject_id'),
700685
('reference', 'inputnode.in_file'),
701-
('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
686+
('fsnative2anat_xfm', 'inputnode.fsnative2anat_xfm'),
702687
]),
703688
(inputnode, aparc_to_native_wf, [
704689
('subjects_dir', 'inputnode.subjects_dir'),
705690
('subject_id', 'inputnode.subject_id'),
706691
('reference', 'inputnode.in_file'),
707-
('fsnative2t1w_xfm', 'inputnode.fsnative2t1w_xfm'),
692+
('fsnative2anat_xfm', 'inputnode.fsnative2anat_xfm'),
708693
]),
709694

710695
# Output
@@ -1000,7 +985,7 @@ def init_gifti_morphometrics_wf(
1000985
name='outputnode',
1001986
)
1002987

1003-
get_subject = pe.Node(nio.FreeSurferSource(), name='get_surfaces')
988+
get_subject = pe.Node(FreeSurferSource(), name='get_surfaces')
1004989

1005990
morphometry_list = pe.Node(
1006991
niu.Merge(len(morphometrics), ravel_inputs=True),
@@ -1182,7 +1167,12 @@ def init_hcp_morphometrics_wf(
11821167
return workflow
11831168

11841169

1185-
def init_segs_to_native_wf(*, name='segs_to_native', segmentation='aseg'):
1170+
def init_segs_to_native_wf(
1171+
*,
1172+
image_type: ty.Literal['T1w', 'T2w'] = 'T1w',
1173+
segmentation: ty.Literal['aseg', 'aparc_aseg', 'wmparc'] = 'aseg',
1174+
name: str = 'segs_to_native_wf',
1175+
) -> Workflow:
11861176
"""
11871177
Get a segmentation from FreeSurfer conformed space into native T1w space.
11881178
@@ -1196,19 +1186,21 @@ def init_segs_to_native_wf(*, name='segs_to_native', segmentation='aseg'):
11961186
11971187
Parameters
11981188
----------
1189+
image_type
1190+
MR anatomical image type ('T1w' or 'T2w')
11991191
segmentation
12001192
The name of a segmentation ('aseg' or 'aparc_aseg' or 'wmparc')
12011193
12021194
Inputs
12031195
------
12041196
in_file
1205-
Anatomical, merged T1w image after INU correction
1197+
Anatomical, merged anatomical image after INU correction
12061198
subjects_dir
12071199
FreeSurfer SUBJECTS_DIR
12081200
subject_id
12091201
FreeSurfer subject ID
1210-
fsnative2t1w_xfm
1211-
LTA-style affine matrix translating from FreeSurfer-conformed subject space to T1w
1202+
fsnative2anat_xfm
1203+
LTA-style affine matrix translating from FreeSurfer-conformed subject space to anatomical
12121204
12131205
Outputs
12141206
-------
@@ -1218,16 +1210,16 @@ def init_segs_to_native_wf(*, name='segs_to_native', segmentation='aseg'):
12181210
"""
12191211
workflow = Workflow(name=f'{name}_{segmentation}')
12201212
inputnode = pe.Node(
1221-
niu.IdentityInterface(['in_file', 'subjects_dir', 'subject_id', 'fsnative2t1w_xfm']),
1213+
niu.IdentityInterface(['in_file', 'subjects_dir', 'subject_id', 'fsnative2anat_xfm']),
12221214
name='inputnode',
12231215
)
12241216
outputnode = pe.Node(niu.IdentityInterface(['out_file']), name='outputnode')
12251217
# Extract the aseg and aparc+aseg outputs
1226-
fssource = pe.Node(nio.FreeSurferSource(), name='fs_datasource')
1218+
fssource = pe.Node(FreeSurferSource(), name='fs_datasource')
12271219

12281220
lta = pe.Node(ConcatenateXFMs(out_fmt='fs'), name='lta', run_without_submitting=True)
12291221

1230-
# Resample from T1.mgz to T1w.nii.gz, applying any offset in fsnative2t1w_xfm,
1222+
# Resample from T1.mgz to T1w.nii.gz, applying any offset in fsnative2anat_xfm,
12311223
# and convert to NIfTI while we're at it
12321224
resample = pe.Node(
12331225
fs.ApplyVolTransform(transformed_file='seg.nii.gz', interp='nearest'),
@@ -1252,20 +1244,20 @@ def _sel(x):
12521244

12531245
segmentation = (segmentation, _sel)
12541246

1255-
# fmt:off
1247+
anat = 'T2' if image_type == 'T2w' else 'T1'
1248+
12561249
workflow.connect([
12571250
(inputnode, fssource, [
12581251
('subjects_dir', 'subjects_dir'),
12591252
('subject_id', 'subject_id')]),
12601253
(inputnode, lta, [('in_file', 'reference'),
1261-
('fsnative2t1w_xfm', 'in_xfms')]),
1262-
(fssource, lta, [('T1', 'moving')]),
1254+
('fsnative2anat_xfm', 'in_xfms')]),
1255+
(fssource, lta, [(anat, 'moving')]),
12631256
(inputnode, resample, [('in_file', 'target_file')]),
12641257
(fssource, resample, [(segmentation, 'source_file')]),
12651258
(lta, resample, [('out_xfm', 'lta_file')]),
12661259
(resample, outputnode, [('transformed_file', 'out_file')]),
1267-
])
1268-
# fmt:on
1260+
]) # fmt:skip
12691261
return workflow
12701262

12711263

0 commit comments

Comments
 (0)