diff --git a/.circleci/bcp_anat_outputs.txt b/.circleci/bcp_anat_outputs.txt index afcc591c..8a7bed83 100644 --- a/.circleci/bcp_anat_outputs.txt +++ b/.circleci/bcp_anat_outputs.txt @@ -44,14 +44,14 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_sphere.surf.gii sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_sulc.shape.gii sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_thickness.shape.gii sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_white.surf.gii -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-brain_mask.json -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-brain_mask.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-preproc_T1w.json -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-preproc_T1w.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_dseg.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_label-CSF_probseg.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_label-GM_probseg.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_label-WM_probseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-brain_mask.json +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-brain_mask.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-preproc_T1w.json +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-preproc_T1w.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_dseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_label-CSF_probseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_label-GM_probseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_label-WM_probseg.nii.gz sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T1w_desc-aparcaseg_dseg.nii.gz sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T1w_desc-aseg_dseg.nii.gz sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T1w_desc-ribbon_mask.json diff --git a/.circleci/bcp_anat_t2only_outputs.txt b/.circleci/bcp_anat_t2only_outputs.txt index 9aea211d..61aa9e55 100644 --- a/.circleci/bcp_anat_t2only_outputs.txt +++ b/.circleci/bcp_anat_t2only_outputs.txt @@ -48,14 +48,14 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_sphere.surf.gii sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_sulc.shape.gii sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_thickness.shape.gii sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_white.surf.gii -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-brain_mask.json -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-brain_mask.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-preproc_T2w.json -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-preproc_T2w.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_dseg.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_label-CSF_probseg.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_label-GM_probseg.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_label-WM_probseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-brain_mask.json +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-brain_mask.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-preproc_T2w.json +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-preproc_T2w.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_dseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_label-CSF_probseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_label-GM_probseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_label-WM_probseg.nii.gz sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T2w_desc-aparcaseg_dseg.nii.gz sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T2w_desc-aseg_dseg.nii.gz sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T2w_desc-ribbon_mask.json diff --git a/.circleci/bcp_full_outputs.txt b/.circleci/bcp_full_outputs.txt index 9376cf50..f546c5f6 100644 --- a/.circleci/bcp_full_outputs.txt +++ b/.circleci/bcp_full_outputs.txt @@ -44,14 +44,14 @@ sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_sphere.surf.gii sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_sulc.shape.gii sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_thickness.shape.gii sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_hemi-R_white.surf.gii -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-brain_mask.json -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-brain_mask.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-preproc_T1w.json -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_desc-preproc_T1w.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_dseg.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_label-CSF_probseg.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_label-GM_probseg.nii.gz -sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant_cohort-1_label-WM_probseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-brain_mask.json +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-brain_mask.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-preproc_T1w.json +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_desc-preproc_T1w.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_dseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_label-CSF_probseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_label-GM_probseg.nii.gz +sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-MNIInfant+1_label-WM_probseg.nii.gz sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T1w_desc-aparcaseg_dseg.nii.gz sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T1w_desc-aseg_dseg.nii.gz sub-01/ses-1mo/anat/sub-01_ses-1mo_run-001_space-T1w_desc-ribbon_mask.json @@ -82,10 +82,10 @@ sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_from-boldref_to-auto sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_from-boldref_to-auto00000_mode-image_desc-fmap_xfm.txt sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_from-orig_to-boldref_mode-image_desc-hmc_xfm.json sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_from-orig_to-boldref_mode-image_desc-hmc_xfm.txt -sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant_cohort-1_boldref.json -sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant_cohort-1_boldref.nii.gz -sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant_cohort-1_desc-brain_mask.json -sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant_cohort-1_desc-brain_mask.nii.gz -sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant_cohort-1_desc-preproc_bold.json -sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant_cohort-1_desc-preproc_bold.nii.gz +sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant+1_boldref.json +sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant+1_boldref.nii.gz +sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant+1_desc-brain_mask.json +sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant+1_desc-brain_mask.nii.gz +sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant+1_desc-preproc_bold.json +sub-01/ses-1mo/func/sub-01_ses-1mo_task-rest_acq-PA_run-001_space-MNIInfant+1_desc-preproc_bold.nii.gz sub-01_ses-1mo.html diff --git a/docs/outputs.md b/docs/outputs.md index 6b1ab209..c242d3c1 100644 --- a/docs/outputs.md +++ b/docs/outputs.md @@ -240,8 +240,8 @@ these will be indicated with `[specifiers]` ``` sub-/[ses-/] func/ - sub-_[specifiers]_space-_desc-brain_mask.nii.gz - sub-_[specifiers]_space-_desc-preproc_bold.nii.gz + sub-_[specifiers]_space-+_desc-brain_mask.nii.gz + sub-_[specifiers]_space-+_desc-preproc_bold.nii.gz ``` :::{note} @@ -311,6 +311,8 @@ Fieldmap registration outputs are part of the *minimal* processing level. Volumetric output spaces labels (`` above, and in the following) include `T1w` and `MNI152NLin2009cAsym` (default). +For space labels that include a cohort, the cohort is included in the space label, +for example `MNIInfant+1`. #### Surfaces, segmentations and parcellations from FreeSurfer diff --git a/nibabies/utils/bids.py b/nibabies/utils/bids.py index 06a3f404..55097e9d 100644 --- a/nibabies/utils/bids.py +++ b/nibabies/utils/bids.py @@ -360,3 +360,17 @@ def age_to_months(age: int | float, units: ty.Literal['weeks', 'months', 'years' elif units == 'years': age *= YEARS_TO_MONTH return round(age) + + +def combine_space(space, cohort) -> str: + """Combine space and cohort into a single string. + + If cohort is not defined, return the space as is. + """ + if space.startswith('space-'): + space = space.split('-')[1] + if cohort: + if cohort.startswith('cohort-'): + cohort = cohort.split('-')[1] + return f'{space}+{cohort}' + return space diff --git a/nibabies/utils/tests/full-derivatives.yml b/nibabies/utils/tests/full-derivatives.yml index 81abdcd8..969daf18 100644 --- a/nibabies/utils/tests/full-derivatives.yml +++ b/nibabies/utils/tests/full-derivatives.yml @@ -102,15 +102,12 @@ dataset_description: mode: image desc: hmc - suffix: boldref - space: MNIInfant - cohort: 1 + space: MNIInfant+1 - suffix: mask - space: MNIInfant - cohort: 1 + space: MNIInfant+1 desc: brain - suffix: bold - space: MNIInfant - cohort: 1 + space: MNIInfant+1 desc: preproc - suffix: bold space: fsLR diff --git a/nibabies/workflows/anatomical/apply.py b/nibabies/workflows/anatomical/apply.py index ca504679..d6b33266 100644 --- a/nibabies/workflows/anatomical/apply.py +++ b/nibabies/workflows/anatomical/apply.py @@ -68,7 +68,6 @@ def init_infant_anat_apply_wf( 'std_t1w', 'anat2std_xfm', 'std_space', - 'std_cohort', 'std_resolution', ] ), @@ -94,12 +93,11 @@ def init_infant_anat_apply_wf( ('anat_mask', 'inputnode.anat_mask'), ('anat_dseg', 'inputnode.anat_dseg'), ('anat_tpms', 'inputnode.anat_tpms'), + ('std_space', 'inputnode.space'), ]), (inputnode, ds_std_volumes_wf, [ ('std_t1w', 'inputnode.ref_file'), ('anat2std_xfm', 'inputnode.anat2std_xfm'), - ('std_space', 'inputnode.space'), - ('std_cohort', 'inputnode.cohort'), ('std_resolution', 'inputnode.resolution'), ]), ]) # fmt:skip diff --git a/nibabies/workflows/anatomical/outputs.py b/nibabies/workflows/anatomical/outputs.py index 4cf5df3f..03d47b6e 100644 --- a/nibabies/workflows/anatomical/outputs.py +++ b/nibabies/workflows/anatomical/outputs.py @@ -590,12 +590,22 @@ def init_anat_derivatives_wf( from niworkflows.interfaces.space import SpaceDataSource from smriprep.interfaces.templateflow import TemplateFlowSelect + from nibabies.utils.bids import combine_space + spacesource = pe.Node(SpaceDataSource(), name='spacesource', run_without_submitting=True) spacesource.iterables = ( 'in_tuple', [(s.fullname, s.spec) for s in spaces.cached.get_standard(dim=(3,))], ) + combine_space_entity = pe.Node( + niu.Function(function=combine_space), + name='combine_space_entity', + run_without_submitting=True, + input_names=['space', 'cohort'], + output_names=['space'], + ) + gen_tplid = pe.Node( niu.Function(function=_fmt_cohort), name='gen_tplid', @@ -690,6 +700,10 @@ def init_anat_derivatives_wf( (inputnode, select_xfm, [ ('anat2std_xfm', 'anat2std_xfm'), ('template', 'keys')]), + (spacesource, combine_space_entity, [ + ('space', 'space'), + ('cohort', 'cohort'), + ]), (spacesource, gen_tplid, [('space', 'template'), ('cohort', 'cohort')]), (gen_tplid, select_xfm, [('out', 'key')]), @@ -724,11 +738,12 @@ def init_anat_derivatives_wf( ] # Connect the space input of these datasinks + [ - ( - spacesource, - n, - [('space', 'space'), ('cohort', 'cohort'), ('resolution', 'resolution')], - ) + (combine_space_entity, n, [('space', 'space')]) + for n in (ds_std_t1w, ds_std_mask, ds_std_dseg, ds_std_tpms) + ] + # Connect the resolution input of these datasinks + + [ + (spacesource, n, [('resolution', 'resolution')]) for n in (ds_std_t1w, ds_std_mask, ds_std_dseg, ds_std_tpms) ] ) diff --git a/nibabies/workflows/base.py b/nibabies/workflows/base.py index e6d27aa3..9cee2e6a 100644 --- a/nibabies/workflows/base.py +++ b/nibabies/workflows/base.py @@ -575,7 +575,6 @@ def init_single_subject_wf( ('outputnode.std_t1w', 'inputnode.std_t1w',), ('outputnode.anat2std_xfm', 'inputnode.anat2std_xfm'), ('outputnode.space', 'inputnode.std_space'), - ('outputnode.cohort', 'inputnode.std_cohort'), ('outputnode.resolution', 'inputnode.std_resolution'), ]), ]) # fmt:skip @@ -792,7 +791,6 @@ def init_single_subject_wf( (template_iterator_wf, bold_wf, [ ('outputnode.space', 'inputnode.std_space'), ('outputnode.resolution', 'inputnode.std_resolution'), - ('outputnode.cohort', 'inputnode.std_cohort'), ('outputnode.std_t1w', 'inputnode.std_t1w'), ('outputnode.std_mask', 'inputnode.std_mask'), ('outputnode.anat2std_xfm', 'inputnode.anat2std_xfm'), diff --git a/nibabies/workflows/bold/base.py b/nibabies/workflows/bold/base.py index b9f20d92..782f8277 100644 --- a/nibabies/workflows/bold/base.py +++ b/nibabies/workflows/bold/base.py @@ -144,8 +144,6 @@ def init_bold_wf( Value of space entity to be used in standard space output filenames std_resolution Value of resolution entity to be used in standard space output filenames - std_cohort - Value of cohort entity to be used in standard space output filenames anat2mni6_xfm Transform from anatomical space to MNI152NLin6Asym space mni6_mask @@ -154,7 +152,7 @@ def init_bold_wf( Transform from MNI152NLin2009cAsym to anatomical space Note that ``anat2std_xfm``, ``std_space``, ``std_resolution``, - ``std_cohort``, ``std_t1w`` and ``std_mask`` are treated as single + ``std_t1w`` and ``std_mask`` are treated as single inputs. In order to resample to multiple target spaces, connect these fields to an iterable. @@ -244,7 +242,6 @@ def init_bold_wf( 'std_mask', 'std_space', 'std_resolution', - 'std_cohort', # MNI152NLin6Asym warp, for CIFTI use # 'anat2mni6_xfm', # 'mni6_mask', @@ -498,7 +495,6 @@ def init_bold_wf( ('std_t1w', 'inputnode.template'), ('std_space', 'inputnode.space'), ('std_resolution', 'inputnode.resolution'), - ('std_cohort', 'inputnode.cohort'), ]), (bold_fit_wf, ds_bold_std_wf, [ ('outputnode.bold_mask', 'inputnode.bold_mask'), diff --git a/nibabies/workflows/bold/outputs.py b/nibabies/workflows/bold/outputs.py index 65e3bf8f..d5d356c0 100644 --- a/nibabies/workflows/bold/outputs.py +++ b/nibabies/workflows/bold/outputs.py @@ -728,7 +728,6 @@ def init_ds_volumes_wf( 'anat2std_xfm', # Entities 'space', - 'cohort', 'resolution', # Transforms previously used to generate the outputs 'motion_xfm', @@ -781,7 +780,6 @@ def init_ds_volumes_wf( ('source_files', 'source_file'), ('bold', 'in_file'), ('space', 'space'), - ('cohort', 'cohort'), ('resolution', 'resolution'), ]), (sources, ds_bold, [('out', 'Sources')]), @@ -872,7 +870,6 @@ def init_ds_volumes_wf( (inputnode, datasink, [ ('source_files', 'source_file'), ('space', 'space'), - ('cohort', 'cohort'), ('resolution', 'resolution'), ]) for datasink in datasinks diff --git a/pyproject.toml b/pyproject.toml index 13c3af36..4f86bfd4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,7 @@ dependencies = [ "pybids >= 0.15.0", "requests", "sdcflows >= 2.14.0", - "smriprep >= 0.19.1", + "smriprep @ git+https://github.com/nipreps/smriprep.git@master", "tedana >= 23.0.2", "templateflow >= 25.0.3", "toml",