Skip to content

Commit b280be7

Browse files
authored
Merge pull request #427 from mgxd/enh/smriprep-master
ENH: Output fsLR meshes on subject surfaces
2 parents 9acda6b + 8845606 commit b280be7

File tree

6 files changed

+96
-33
lines changed

6 files changed

+96
-33
lines changed

.circleci/bcp_anat_t2only_outputs.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,19 @@ sub-01/ses-1mo
1212
sub-01/ses-1mo/anat
1313
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_desc-preproc_T2w.json
1414
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_desc-preproc_T2w.nii.gz
15+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-MNI152NLin6Asym_to-T2w_mode-image_xfm.h5
1516
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-MNIInfant+1_to-T2w_mode-image_xfm.h5
17+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-T2w_to-MNI152NLin6Asym_mode-image_xfm.h5
1618
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-T2w_to-MNIInfant+1_mode-image_xfm.h5
1719
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-T2w_to-fsnative_mode-image_xfm.txt
1820
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_from-fsnative_to-T2w_mode-image_xfm.txt
1921
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_curv.shape.gii
2022
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_inflated.surf.gii
2123
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_midthickness.surf.gii
2224
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_pial.surf.gii
25+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_space-fsLR_den-32k_midthickness.surf.gii
26+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_space-fsLR_den-32k_pial.surf.gii
27+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_space-fsLR_den-32k_white.surf.gii
2328
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_space-fsLR_desc-reg_sphere.surf.gii
2429
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_space-fsaverage_desc-reg_sphere.surf.gii
2530
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-L_sphere.surf.gii
@@ -30,6 +35,9 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_curv.shape.gii
3035
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_inflated.surf.gii
3136
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_midthickness.surf.gii
3237
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_pial.surf.gii
38+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_space-fsLR_den-32k_midthickness.surf.gii
39+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_space-fsLR_den-32k_pial.surf.gii
40+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_space-fsLR_den-32k_white.surf.gii
3341
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_space-fsLR_desc-reg_sphere.surf.gii
3442
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_space-fsaverage_desc-reg_sphere.surf.gii
3543
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_sphere.surf.gii
@@ -52,4 +60,10 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T2w_dseg.nii.gz
5260
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T2w_label-CSF_probseg.nii.gz
5361
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T2w_label-GM_probseg.nii.gz
5462
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T2w_label-WM_probseg.nii.gz
63+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-fsLR_den-91k_curv.dscalar.nii
64+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-fsLR_den-91k_curv.json
65+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-fsLR_den-91k_sulc.dscalar.nii
66+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-fsLR_den-91k_sulc.json
67+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-fsLR_den-91k_thickness.dscalar.nii
68+
sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-fsLR_den-91k_thickness.json
5569
sub-01_ses-1mo.html

.circleci/config.yml

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ _python_defaults: &python_defaults
1616
password: $DOCKER_PAT
1717
working_directory: /tmp/src/nibabies
1818

19-
2019
_docker_auth: &docker_auth
2120
name: Docker authentication
2221
command: |
@@ -160,7 +159,6 @@ jobs:
160159
- /tmp/docker
161160
- /tmp/images
162161

163-
164162
get_data:
165163
!!merge <<: *python_defaults
166164
working_directory: /home/circleci/data
@@ -279,7 +277,6 @@ jobs:
279277
- store_artifacts:
280278
path: /tmp/data/reports
281279

282-
283280
test_bcp:
284281
!!merge <<: *machine_defaults
285282
environment:
@@ -412,7 +409,7 @@ jobs:
412409
--nthreads 4 -vv --age-months 2 --sloppy \
413410
--surface-recon-method infantfs \
414411
--derivatives precomputed=/tmp/data/${DATASET}-t2only/derivatives/bibsnet \
415-
--output-layout bids --anat-only
412+
--output-layout bids --anat-only --cifti-output
416413
- run:
417414
name: Checking outputs of T2-only nibabies anat
418415
command: |
@@ -427,7 +424,6 @@ jobs:
427424
- store_artifacts:
428425
path: /tmp/bcp/derivatives
429426

430-
431427
deploy_docker_patches:
432428
!!merge <<: *machine_defaults
433429
working_directory: *src
@@ -464,7 +460,6 @@ jobs:
464460
docker tag nipreps/nibabies:dev nipreps/nibabies:${CIRCLE_BRANCH#docker/}
465461
docker push nipreps/nibabies:${CIRCLE_BRANCH#docker/}
466462
467-
468463
deploy_docker:
469464
!!merge <<: *machine_defaults
470465
steps:
@@ -503,7 +498,6 @@ jobs:
503498
fi
504499
fi
505500
506-
507501
test_deploy_pypi:
508502
!!merge <<: *python_defaults
509503
steps:
@@ -559,7 +553,6 @@ jobs:
559553
- store_artifacts:
560554
path: /tmp/src/nibabies/wrapper/dist
561555

562-
563556
deploy_pypi:
564557
!!merge <<: *python_defaults
565558
steps:
@@ -584,14 +577,12 @@ jobs:
584577
# upload wrapper
585578
python -m twine upload wrapper/dist/nibabies*
586579
587-
588580
deployable:
589581
docker:
590582
- image: busybox:latest
591583
steps:
592584
- run: echo Deploying!
593585

594-
595586
workflows:
596587
version: 2
597588
build_test_deploy:

nibabies/workflows/anatomical/apply.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
from smriprep.workflows.surfaces import (
1212
init_hcp_morphometrics_wf,
1313
init_morph_grayords_wf,
14-
init_resample_midthickness_wf,
14+
init_resample_surfaces_wf,
1515
init_surface_derivatives_wf,
1616
)
1717

1818
from nibabies import config
1919
from nibabies.workflows.anatomical.outputs import init_ds_seg_wf
20-
from nibabies.workflows.anatomical.surfaces import init_resample_midthickness_dhcp_wf
20+
from nibabies.workflows.anatomical.surfaces import init_resample_surfaces_dhcp_wf
2121

2222
if ty.TYPE_CHECKING:
2323
from niworkflows.utils.spaces import SpatialReferences
@@ -57,6 +57,8 @@ def init_infant_anat_apply_wf(
5757
'sulc',
5858
'template',
5959
'thickness',
60+
'white',
61+
'pial',
6062
'midthickness',
6163
reg_sphere,
6264
# template workflow inputs
@@ -185,17 +187,28 @@ def init_infant_anat_apply_wf(
185187
if cifti_output:
186188
hcp_morphometrics_wf = init_hcp_morphometrics_wf(omp_nthreads=omp_nthreads)
187189
if recon_method == 'mcribs':
188-
resample_midthickness_wf = init_resample_midthickness_dhcp_wf(
189-
grayord_density=cifti_output
190+
resample_surfaces_wf = init_resample_surfaces_dhcp_wf(
191+
surfaces=['white', 'pial', 'midthickness'],
192+
grayord_density=cifti_output,
190193
)
191194
else:
192-
resample_midthickness_wf = init_resample_midthickness_wf(
193-
grayord_density=cifti_output
195+
resample_surfaces_wf = init_resample_surfaces_wf(
196+
surfaces=['white', 'pial', 'midthickness'], grayord_density=cifti_output
194197
)
195198
morph_grayords_wf = init_morph_grayords_wf(
196199
grayord_density=cifti_output, omp_nthreads=omp_nthreads
197200
)
198201

202+
ds_fsLR_surfaces_wf = init_ds_surfaces_wf(
203+
output_dir=output_dir,
204+
surfaces=['white', 'pial', 'midthickness'],
205+
entities={
206+
'space': 'dhcpAsym' if recon_method == 'mcribs' else 'fsLR',
207+
'density': '32k' if cifti_output == '91k' else '59k',
208+
},
209+
name='ds_fsLR_surfaces_wf',
210+
)
211+
199212
ds_grayord_metrics_wf = init_ds_grayord_metrics_wf(
200213
bids_root=bids_root,
201214
output_dir=output_dir,
@@ -213,7 +226,9 @@ def init_infant_anat_apply_wf(
213226
(surface_derivatives_wf, hcp_morphometrics_wf, [
214227
('outputnode.curv', 'inputnode.curv'),
215228
]),
216-
(inputnode, resample_midthickness_wf, [
229+
(inputnode, resample_surfaces_wf, [
230+
('white', 'inputnode.white'),
231+
('pial', 'inputnode.pial'),
217232
('midthickness', 'inputnode.midthickness'),
218233
(reg_sphere, 'inputnode.sphere_reg_fsLR'),
219234
]),
@@ -230,12 +245,20 @@ def init_infant_anat_apply_wf(
230245
(hcp_morphometrics_wf, outputnode, [
231246
('outputnode.roi', 'roi'),
232247
]),
233-
(resample_midthickness_wf, morph_grayords_wf, [
248+
(resample_surfaces_wf, morph_grayords_wf, [
234249
('outputnode.midthickness_fsLR', 'inputnode.midthickness_fsLR'),
235250
]),
236-
(resample_midthickness_wf, outputnode, [
251+
(inputnode, ds_fsLR_surfaces_wf, [
252+
('anat_valid_list', 'inputnode.source_files'),
253+
]),
254+
(resample_surfaces_wf, outputnode, [
237255
('outputnode.midthickness_fsLR', 'midthickness_fsLR'),
238256
]),
257+
(resample_surfaces_wf, ds_fsLR_surfaces_wf, [
258+
('outputnode.white_fsLR', 'inputnode.white'),
259+
('outputnode.pial_fsLR', 'inputnode.pial'),
260+
('outputnode.midthickness_fsLR', 'inputnode.midthickness'),
261+
]),
239262
(inputnode, ds_grayord_metrics_wf, [
240263
('anat_valid_list', 'inputnode.source_files'),
241264
]),

nibabies/workflows/anatomical/surfaces.py

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,10 @@ def init_make_midthickness_wf(
415415
return workflow
416416

417417

418-
def init_resample_midthickness_dhcp_wf(
418+
def init_resample_surfaces_dhcp_wf(
419+
surfaces: list[str],
419420
grayord_density: ty.Literal['91k', '170k'],
420-
name: str = 'resample_midthickness_wf',
421+
name: str = 'resample_surfaces_dhcp_wf',
421422
):
422423
"""
423424
Resample subject midthickness surface to specified density.
@@ -427,20 +428,20 @@ def init_resample_midthickness_dhcp_wf(
427428
:graph2use: colored
428429
:simple_form: yes
429430
430-
from nibabies.workflows.anatomical.surfaces import init_resample_midthickness_wf
431-
wf = init_resample_midthickness_wf(grayord_density="91k")
431+
from nibabies.workflows.anatomical.surfaces import init_resample_surfaces_dhcp_wf
432+
wf = init_resample_surfaces_dhcp_wf(surfaces=['white', grayord_density='91k')
432433
433434
Parameters
434435
----------
435436
grayord_density : :obj:`str`
436437
Either `91k` or `170k`, representing the total of vertices or *grayordinates*.
437438
name : :obj:`str`
438-
Unique name for the subworkflow (default: ``"resample_midthickness_wf"``)
439+
Unique name for the subworkflow (default: ``"resample_surfaces_dhcp_wf``)
439440
440441
Inputs
441442
------
442-
midthickness
443-
GIFTI surface mesh corresponding to the midthickness surface
443+
``<surface>``
444+
Left and right GIFTIs for each surface name passed to ``surfaces``
444445
sphere_reg_fsLR
445446
GIFTI surface mesh corresponding to the subject's fsLR registration sphere
446447
@@ -454,11 +455,19 @@ def init_resample_midthickness_dhcp_wf(
454455
fslr_density = '32k' if grayord_density == '91k' else '59k'
455456

456457
inputnode = pe.Node(
457-
niu.IdentityInterface(fields=['midthickness', 'sphere_reg_fsLR']),
458+
niu.IdentityInterface(fields=[*surfaces, 'sphere_reg_fsLR']),
458459
name='inputnode',
459460
)
460461

461-
outputnode = pe.Node(niu.IdentityInterface(fields=['midthickness_fsLR']), name='outputnode')
462+
outputnode = pe.Node(
463+
niu.IdentityInterface(fields=[f'{surf}_fsLR' for surf in surfaces]), name='outputnode'
464+
)
465+
466+
surface_list = pe.Node(
467+
niu.Merge(len(surfaces), ravel_inputs=True),
468+
name='surface_list',
469+
run_without_submitting=True,
470+
)
462471

463472
resampler = pe.MapNode(
464473
SurfaceResample(method='BARYCENTRIC'),
@@ -477,20 +486,45 @@ def init_resample_midthickness_dhcp_wf(
477486
extension='.surf.gii',
478487
)
479488
)
489+
# Order matters. Iterate over surfaces, then hemis to get L R L R L R
490+
for _surf in surfaces
480491
for hemi in ['L', 'R']
481492
]
482493

494+
surface_groups = pe.Node(
495+
niu.Split(splits=[2] * len(surfaces)),
496+
name='surface_groups',
497+
run_without_submitting=True,
498+
)
499+
483500
workflow.connect([
501+
(inputnode, surface_list, [
502+
((surf, _sorted_by_basename), f'in{i}')
503+
for i, surf in enumerate(surfaces, start=1)
504+
]),
484505
(inputnode, resampler, [
485-
('midthickness', 'surface_in'),
486-
('sphere_reg_fsLR', 'current_sphere'),
506+
(('sphere_reg_fsLR', _repeat, len(surfaces)), 'current_sphere'),
507+
]),
508+
(surface_list, resampler, [('out', 'surface_in')]),
509+
(resampler, surface_groups, [('surface_out', 'inlist')]),
510+
(surface_groups, outputnode, [
511+
(f'out{i}', f'{surf}_fsLR') for i, surf in enumerate(surfaces, start=1)
487512
]),
488-
(resampler, outputnode, [('surface_out', 'midthickness_fsLR')]),
489513
]) # fmt:skip
490514

491515
return workflow
492516

493517

518+
def _sorted_by_basename(inlist):
519+
from os.path import basename
520+
521+
return sorted(inlist, key=lambda x: str(basename(x)))
522+
523+
524+
def _repeat(seq: list, count: int) -> list:
525+
return seq * count
526+
527+
494528
def _parent(p):
495529
from pathlib import Path
496530

nibabies/workflows/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,8 @@ def init_single_subject_wf(
513513
('outputnode.anat_dseg', 'inputnode.anat_dseg'),
514514
('outputnode.anat_tpms', 'inputnode.anat_tpms'),
515515
('outputnode.fsnative2anat_xfm', 'inputnode.fsnative2anat_xfm'),
516+
('outputnode.white', 'inputnode.white'),
517+
('outputnode.pial', 'inputnode.pial'),
516518
('outputnode.midthickness', 'inputnode.midthickness'),
517519
(f'outputnode.{reg_sphere}', f'inputnode.{reg_sphere}'),
518520
('outputnode.sulc', 'inputnode.sulc'),

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ dependencies = [
3434
"pybids >= 0.15.0",
3535
"requests",
3636
"sdcflows >= 2.10.0",
37-
# "smriprep >= 0.16.1",
38-
"smriprep @ git+https://github.com/nipreps/smriprep.git@dev-nibabies",
37+
"smriprep >= 0.17.0",
3938
"tedana >= 23.0.2",
4039
"templateflow >= 24.2.0",
4140
"toml",

0 commit comments

Comments
 (0)