Skip to content

Commit 27a69d6

Browse files
authored
Merge pull request #487 from nipreps/enh/cortex-mask
ENH: Add cortex mask
2 parents 2e1e2de + f7a1d01 commit 27a69d6

File tree

8 files changed

+104
-28
lines changed

8 files changed

+104
-28
lines changed

.circleci/bcp_anat_outputs.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-T1w_to-fsnative_mode-image_xfm.t
2121
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-T2w_to-T1w_mode-image_xfm.h5
2222
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-fsnative_to-T1w_mode-image_xfm.txt
2323
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_curv.shape.gii
24+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_desc-cortex_mask.json
25+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_desc-cortex_mask.label.gii
2426
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_inflated.surf.gii
2527
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_midthickness.surf.gii
2628
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_pial.surf.gii
@@ -31,6 +33,8 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_sulc.shape.gii
3133
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_thickness.shape.gii
3234
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_white.surf.gii
3335
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_curv.shape.gii
36+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_desc-cortex_mask.json
37+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_desc-cortex_mask.label.gii
3438
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_inflated.surf.gii
3539
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_midthickness.surf.gii
3640
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_pial.surf.gii

.circleci/bcp_anat_t2only_outputs.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-T2w_to-MNIInfant+1_mode-image_xf
1919
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-T2w_to-fsnative_mode-image_xfm.txt
2020
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-fsnative_to-T2w_mode-image_xfm.txt
2121
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_curv.shape.gii
22+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_desc-cortex_mask.json
23+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_desc-cortex_mask.label.gii
2224
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_inflated.surf.gii
2325
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_midthickness.surf.gii
2426
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_pial.surf.gii
@@ -32,6 +34,8 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_sulc.shape.gii
3234
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_thickness.shape.gii
3335
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_white.surf.gii
3436
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_curv.shape.gii
37+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_desc-cortex_mask.json
38+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_desc-cortex_mask.label.gii
3539
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_inflated.surf.gii
3640
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_midthickness.surf.gii
3741
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_pial.surf.gii

.circleci/bcp_full_outputs.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-T1w_to-fsnative_mode-image_xfm.t
2121
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-T2w_to-T1w_mode-image_xfm.h5
2222
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-fsnative_to-T1w_mode-image_xfm.txt
2323
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_curv.shape.gii
24+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_desc-cortex_mask.json
25+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_desc-cortex_mask.label.gii
2426
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_inflated.surf.gii
2527
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_midthickness.surf.gii
2628
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_pial.surf.gii
@@ -31,6 +33,8 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_sulc.shape.gii
3133
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_thickness.shape.gii
3234
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_white.surf.gii
3335
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_curv.shape.gii
36+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_desc-cortex_mask.json
37+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_desc-cortex_mask.label.gii
3438
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_inflated.surf.gii
3539
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_midthickness.surf.gii
3640
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_pial.surf.gii

nibabies/data/io_spec_anat.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,14 @@
232232
"desc": "msmsulc",
233233
"suffix": "sphere",
234234
"extension": ".surf.gii"
235+
},
236+
"cortex_mask": {
237+
"datatype": "anat",
238+
"hemi": ["L", "R"],
239+
"space": null,
240+
"desc": "cortex",
241+
"suffix": "mask",
242+
"extension": ".label.gii"
235243
}
236244
},
237245
"masks": {

nibabies/workflows/anatomical/apply.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def init_infant_anat_apply_wf(
6262
'white',
6363
'pial',
6464
'midthickness',
65+
'cortex_mask',
6566
reg_sphere,
6667
# template workflow inputs
6768
'std_t1w',
@@ -75,7 +76,7 @@ def init_infant_anat_apply_wf(
7576
)
7677

7778
outputnode = pe.Node(
78-
niu.IdentityInterface(fields=['anat_aseg', 'anat_aparc', 'midthickness_fsLR', 'roi']),
79+
niu.IdentityInterface(fields=['anat_aseg', 'anat_aparc', 'midthickness_fsLR']),
7980
name='outputnode',
8081
)
8182

@@ -235,17 +236,14 @@ def init_infant_anat_apply_wf(
235236
(reg_sphere, 'inputnode.sphere_reg_fsLR'),
236237
]),
237238
(inputnode, morph_grayords_wf, [
239+
('cortex_mask', 'inputnode.roi'),
238240
('midthickness', 'inputnode.midthickness'),
239241
(reg_sphere, 'inputnode.sphere_reg_fsLR'),
240242
]),
241243
(hcp_morphometrics_wf, morph_grayords_wf, [
242244
('outputnode.curv', 'inputnode.curv'),
243245
('outputnode.sulc', 'inputnode.sulc'),
244246
('outputnode.thickness', 'inputnode.thickness'),
245-
('outputnode.roi', 'inputnode.roi'),
246-
]),
247-
(hcp_morphometrics_wf, outputnode, [
248-
('outputnode.roi', 'roi'),
249247
]),
250248
(resample_surfaces_wf, morph_grayords_wf, [
251249
('outputnode.midthickness_fsLR', 'inputnode.midthickness_fsLR'),

nibabies/workflows/anatomical/fit.py

Lines changed: 75 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,23 @@
1313
from niworkflows.utils.connections import pop_file
1414
from smriprep.workflows.anatomical import (
1515
_is_skull_stripped,
16-
init_anat_ribbon_wf,
1716
init_anat_template_wf,
1817
)
1918
from smriprep.workflows.fit.registration import init_register_template_wf
2019
from smriprep.workflows.outputs import (
2120
init_ds_dseg_wf,
2221
init_ds_fs_registration_wf,
2322
init_ds_mask_wf,
23+
init_ds_surface_masks_wf,
2424
init_ds_surface_metrics_wf,
2525
init_ds_surfaces_wf,
2626
init_ds_template_registration_wf,
2727
init_ds_template_wf,
2828
init_ds_tpms_wf,
2929
)
3030
from smriprep.workflows.surfaces import (
31+
init_anat_ribbon_wf,
32+
init_cortex_masks_wf,
3133
init_fsLR_reg_wf,
3234
init_gifti_morphometrics_wf,
3335
init_gifti_surfaces_wf,
@@ -147,6 +149,7 @@ def init_infant_anat_fit_wf(
147149
'sphere_reg',
148150
'sphere_reg_fsLR',
149151
'sphere_reg_msm',
152+
'cortex_mask',
150153
'anat_ribbon',
151154
# Reverse transform; not computable from forward transform
152155
'std2anat_xfm',
@@ -1273,13 +1276,13 @@ def init_infant_anat_fit_wf(
12731276
(fsnative_buffer, gifti_surfaces_wf, [
12741277
('fsnative2anat_xfm', 'inputnode.fsnative2anat_xfm'),
12751278
]),
1276-
(gifti_surfaces_wf, surfaces_buffer, [
1277-
(f'outputnode.{surf}', surf) for surf in surfs
1278-
]),
12791279
(sourcefile_buffer, ds_surfaces_wf, [('anat_source_files', 'inputnode.source_files')]),
12801280
(gifti_surfaces_wf, ds_surfaces_wf, [
12811281
(f'outputnode.{surf}', f'inputnode.{surf}') for surf in surfs
12821282
]),
1283+
(ds_surfaces_wf, surfaces_buffer, [
1284+
(f'outputnode.{surf}', surf) for surf in surfs
1285+
]),
12831286
]) # fmt:skip
12841287
if spheres:
12851288
gifti_spheres_wf = init_gifti_surfaces_wf(
@@ -1297,13 +1300,13 @@ def init_infant_anat_fit_wf(
12971300
('outputnode.subjects_dir', 'inputnode.subjects_dir'),
12981301
# No transform for spheres, following HCP pipelines' lead
12991302
]),
1300-
(gifti_spheres_wf, surfaces_buffer, [
1301-
(f'outputnode.{sphere}', sphere) for sphere in spheres
1302-
]),
13031303
(sourcefile_buffer, ds_spheres_wf, [('anat_source_files', 'inputnode.source_files')]),
13041304
(gifti_spheres_wf, ds_spheres_wf, [
13051305
(f'outputnode.{sphere}', f'inputnode.{sphere}') for sphere in spheres
13061306
]),
1307+
(ds_spheres_wf, surfaces_buffer, [
1308+
(f'outputnode.{sphere}', sphere) for sphere in spheres
1309+
]),
13071310
]) # fmt:skip
13081311
metrics = [metric for metric in needed_metrics if metric not in found_surfs]
13091312
if metrics:
@@ -1321,13 +1324,13 @@ def init_infant_anat_fit_wf(
13211324
('outputnode.subject_id', 'inputnode.subject_id'),
13221325
('outputnode.subjects_dir', 'inputnode.subjects_dir'),
13231326
]),
1324-
(gifti_morph_wf, surfaces_buffer, [
1325-
(f'outputnode.{metric}', metric) for metric in metrics
1326-
]),
13271327
(sourcefile_buffer, ds_morph_wf, [('anat_source_files', 'inputnode.source_files')]),
13281328
(gifti_morph_wf, ds_morph_wf, [
13291329
(f'outputnode.{metric}', f'inputnode.{metric}') for metric in metrics
13301330
]),
1331+
(ds_morph_wf, surfaces_buffer, [
1332+
(f'outputnode.{metric}', metric) for metric in metrics
1333+
]),
13311334
]) # fmt:skip
13321335

13331336
if 'anat_ribbon' not in precomputed:
@@ -1413,6 +1416,32 @@ def init_infant_anat_fit_wf(
14131416
else:
14141417
LOGGER.info('ANAT Stage 9: Found pre-computed fsLR registration sphere')
14151418
fsLR_buffer.inputs.sphere_reg_fsLR = sorted(precomputed['sphere_reg_fsLR'])
1419+
1420+
# Stage 10: Cortical surface mask
1421+
if len(precomputed.get('cortex_mask', [])) < 2:
1422+
LOGGER.info('ANAT Stage 11: Creating cortical surface mask')
1423+
1424+
cortex_masks_wf = init_cortex_masks_wf()
1425+
ds_cortex_masks_wf = init_ds_surface_masks_wf(
1426+
output_dir=output_dir,
1427+
mask_type='cortex',
1428+
name='ds_cortex_masks_wf',
1429+
)
1430+
1431+
workflow.connect([
1432+
(surfaces_buffer, cortex_masks_wf, [
1433+
('midthickness', 'inputnode.midthickness'),
1434+
('thickness', 'inputnode.thickness'),
1435+
]),
1436+
(cortex_masks_wf, ds_cortex_masks_wf, [
1437+
('outputnode.cortex_masks', 'inputnode.mask_files'),
1438+
('outputnode.source_files', 'inputnode.source_files'),
1439+
]),
1440+
(ds_cortex_masks_wf, outputnode, [('outputnode.mask_files', 'cortex_mask')]),
1441+
]) # fmt:skip
1442+
else:
1443+
LOGGER.info('ANAT Stage 11: Found pre-computed cortical surface mask')
1444+
outputnode.inputs.cortex_mask = sorted(precomputed['cortex_mask'])
14161445
return workflow
14171446

14181447

@@ -1476,6 +1505,7 @@ def init_infant_single_anat_fit_wf(
14761505
'sphere_reg',
14771506
'sphere_reg_fsLR',
14781507
'sphere_reg_msm',
1508+
'cortex_mask',
14791509
'anat_ribbon',
14801510
# Reverse transform; not computable from forward transform
14811511
'std2anat_xfm',
@@ -2202,13 +2232,13 @@ def init_infant_single_anat_fit_wf(
22022232
(fsnative_buffer, gifti_surfaces_wf, [
22032233
('fsnative2anat_xfm', 'inputnode.fsnative2anat_xfm'),
22042234
]),
2205-
(gifti_surfaces_wf, surfaces_buffer, [
2206-
(f'outputnode.{surf}', surf) for surf in surfs
2207-
]),
22082235
(sourcefile_buffer, ds_surfaces_wf, [('anat_source_files', 'inputnode.source_files')]),
22092236
(gifti_surfaces_wf, ds_surfaces_wf, [
22102237
(f'outputnode.{surf}', f'inputnode.{surf}') for surf in surfs
22112238
]),
2239+
(ds_surfaces_wf, surfaces_buffer, [
2240+
(f'outputnode.{surf}', surf) for surf in surfs
2241+
]),
22122242
]) # fmt:skip
22132243
if spheres:
22142244
gifti_spheres_wf = init_gifti_surfaces_wf(
@@ -2226,13 +2256,13 @@ def init_infant_single_anat_fit_wf(
22262256
('outputnode.subjects_dir', 'inputnode.subjects_dir'),
22272257
# No transform for spheres, following HCP pipelines' lead
22282258
]),
2229-
(gifti_spheres_wf, surfaces_buffer, [
2230-
(f'outputnode.{sphere}', sphere) for sphere in spheres
2231-
]),
22322259
(sourcefile_buffer, ds_spheres_wf, [('anat_source_files', 'inputnode.source_files')]),
22332260
(gifti_spheres_wf, ds_spheres_wf, [
22342261
(f'outputnode.{sphere}', f'inputnode.{sphere}') for sphere in spheres
22352262
]),
2263+
(ds_spheres_wf, surfaces_buffer, [
2264+
(f'outputnode.{sphere}', sphere) for sphere in spheres
2265+
]),
22362266
]) # fmt:skip
22372267
metrics = [metric for metric in needed_metrics if metric not in found_surfs]
22382268
if metrics:
@@ -2250,13 +2280,13 @@ def init_infant_single_anat_fit_wf(
22502280
('outputnode.subject_id', 'inputnode.subject_id'),
22512281
('outputnode.subjects_dir', 'inputnode.subjects_dir'),
22522282
]),
2253-
(gifti_morph_wf, surfaces_buffer, [
2254-
(f'outputnode.{metric}', metric) for metric in metrics
2255-
]),
22562283
(sourcefile_buffer, ds_morph_wf, [('anat_source_files', 'inputnode.source_files')]),
22572284
(gifti_morph_wf, ds_morph_wf, [
22582285
(f'outputnode.{metric}', f'inputnode.{metric}') for metric in metrics
22592286
]),
2287+
(ds_morph_wf, surfaces_buffer, [
2288+
(f'outputnode.{metric}', metric) for metric in metrics
2289+
]),
22602290
]) # fmt:skip
22612291

22622292
if 'anat_ribbon' not in precomputed:
@@ -2342,4 +2372,30 @@ def init_infant_single_anat_fit_wf(
23422372
else:
23432373
LOGGER.info('ANAT Stage 9: Found pre-computed fsLR registration sphere')
23442374
fsLR_buffer.inputs.sphere_reg_fsLR = sorted(precomputed['sphere_reg_fsLR'])
2375+
2376+
# Stage 10: Cortical surface mask
2377+
if len(precomputed.get('cortex_mask', [])) < 2:
2378+
LOGGER.info('ANAT Stage 11: Creating cortical surface mask')
2379+
2380+
cortex_masks_wf = init_cortex_masks_wf()
2381+
ds_cortex_masks_wf = init_ds_surface_masks_wf(
2382+
output_dir=output_dir,
2383+
mask_type='cortex',
2384+
name='ds_cortex_masks_wf',
2385+
)
2386+
2387+
workflow.connect([
2388+
(surfaces_buffer, cortex_masks_wf, [
2389+
('midthickness', 'inputnode.midthickness'),
2390+
('thickness', 'inputnode.thickness'),
2391+
]),
2392+
(cortex_masks_wf, ds_cortex_masks_wf, [
2393+
('outputnode.cortex_masks', 'inputnode.mask_files'),
2394+
('outputnode.source_files', 'inputnode.source_files'),
2395+
]),
2396+
(ds_cortex_masks_wf, outputnode, [('outputnode.mask_files', 'cortex_mask')]),
2397+
]) # fmt:skip
2398+
else:
2399+
LOGGER.info('ANAT Stage 11: Found pre-computed cortical surface mask')
2400+
outputnode.inputs.cortex_mask = sorted(precomputed['cortex_mask'])
23452401
return workflow

nibabies/workflows/base.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ def init_single_subject_wf(
534534
('outputnode.white', 'inputnode.white'),
535535
('outputnode.pial', 'inputnode.pial'),
536536
('outputnode.midthickness', 'inputnode.midthickness'),
537+
('outputnode.cortex_mask', 'inputnode.cortex_mask'),
537538
(f'outputnode.{reg_sphere}', f'inputnode.{reg_sphere}'),
538539
('outputnode.sulc', 'inputnode.sulc'),
539540
('outputnode.subjects_dir', 'inputnode.subjects_dir'),
@@ -809,8 +810,10 @@ def init_single_subject_wf(
809810

810811
if config.workflow.cifti_output:
811812
workflow.connect([
813+
(anat_fit_wf, bold_wf, [
814+
('outputnode.cortex_mask', 'inputnode.cortex_mask'),
815+
]),
812816
(anat_apply_wf, bold_wf, [
813-
('outputnode.roi', 'inputnode.cortex_mask'),
814817
('outputnode.midthickness_fsLR', 'inputnode.midthickness_fsLR'),
815818
('outputnode.anat_aseg', 'inputnode.anat_aseg'),
816819
]),

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ dependencies = [
2525
"nireports >= 23.2.0",
2626
"nitime",
2727
"nitransforms >= 24.1.1",
28-
#"niworkflows >= 1.13.1",
29-
"niworkflows @ git+https://github.com/nipreps/niworkflows.git@master",
28+
"niworkflows >= 1.14.1",
3029
"numpy >= 1.21.0",
3130
"packaging",
3231
"pandas < 3",
@@ -35,7 +34,7 @@ dependencies = [
3534
"pybids >= 0.15.0",
3635
"requests",
3736
"sdcflows >= 2.13.0",
38-
"smriprep >= 0.17.0",
37+
"smriprep >= 0.19.1",
3938
"tedana >= 23.0.2",
4039
"templateflow >= 24.2.0",
4140
"toml",

0 commit comments

Comments
 (0)