From 9dea9cb103ae0148356de70c49b2f19af8eaadd0 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Fri, 4 Oct 2024 16:47:03 -0400 Subject: [PATCH] Accept external atlases by searching BIDS-Atlas datasets (#1265) --- .circleci/config.yml | 30 ++ .vscode/settings.json | 2 - README.rst | 2 +- docs/usage.rst | 169 +++++++---- xcp_d/cli/combineqc.py | 2 +- xcp_d/cli/parser.py | 18 +- xcp_d/cli/parser_utils.py | 8 +- xcp_d/cli/workflow.py | 2 +- xcp_d/config.py | 2 +- xcp_d/data/atlas_bids_config.json | 44 +++ .../atlas-Glasser_dseg.tsv | 0 ...s-Glasser_space-MNI152NLin6Asym_dseg.json} | 0 ..._space-MNI152NLin6Asym_res-01_dseg.nii.gz} | Bin ...lasser_space-fsLR_den-32k_dseg.dlabel.nii} | Bin .../atlas-Glasser_space-fsLR_dseg.json} | 0 .../{ => atlas-Gordon}/atlas-Gordon_dseg.tsv | 0 ...as-Gordon_space-MNI152NLin6Asym_dseg.json} | 0 ..._space-MNI152NLin6Asym_res-01_dseg.nii.gz} | Bin ...Gordon_space-fsLR_den-32k_dseg.dlabel.nii} | Bin .../atlas-Gordon_space-fsLR_dseg.json} | 0 .../{ => atlas-HCP}/atlas-HCP_dseg.tsv | 0 ...atlas-HCP_space-MNI152NLin6Asym_dseg.json} | 0 ..._space-MNI152NLin6Asym_res-02_dseg.nii.gz} | Bin ...as-HCP_space-fsLR_den-32k_dseg.dlabel.nii} | Bin .../atlas-HCP_space-fsLR_dseg.json} | 0 .../{ => atlas-MIDB}/atlas-MIDB_dseg.tsv | 0 ...den-32k_desc-abcdThresh75_dseg.dlabel.nii} | Bin ...-fsLR_den-32k_desc-abcdThresh75_dseg.json} | 0 .../atlas-MyersLabonte_desc-thresh50_dseg.tsv | 0 ...sLR_den-32k_desc-thresh50_dseg.dlabel.nii} | Bin ...pace-fsLR_den-32k_desc-thresh50_dseg.json} | 0 .../{ => atlas-Tian}/atlas-Tian_dseg.tsv | 0 ...tlas-Tian_space-MNI152NLin6Asym_dseg.json} | 0 ..._space-MNI152NLin6Asym_res-02_dseg.nii.gz} | Bin ...s-Tian_space-fsLR_den-32k_dseg.dlabel.nii} | Bin .../atlas-Tian_space-fsLR_dseg.json} | 0 xcp_d/data/atlases/dataset_description.json | 5 + ...atlas-MyersLabonte_den-32k_dseg.dlabel.nii | Bin 607712 -> 0 bytes xcp_d/interfaces/bids.py | 28 +- xcp_d/interfaces/connectivity.py | 16 +- xcp_d/tests/conftest.py | 1 + .../data/test_ds001419_cifti_outputs.txt | 8 +- ...st_fmriprep_without_freesurfer_outputs.txt | 281 ++---------------- xcp_d/tests/data/test_nibabies_outputs.txt | 28 +- xcp_d/tests/data/test_pnc_cifti_outputs.txt | 6 +- .../data/test_pnc_cifti_t2wonly_outputs.txt | 4 +- xcp_d/tests/data/test_ukbiobank_outputs.txt | 28 +- xcp_d/tests/test_cli.py | 12 + xcp_d/tests/test_cli_run.py | 1 + xcp_d/tests/test_cli_utils.py | 68 +++++ xcp_d/tests/test_interfaces_bids.py | 56 ++-- xcp_d/tests/test_utils_atlas.py | 140 ++++++--- xcp_d/tests/test_utils_boilerplate.py | 4 +- xcp_d/tests/test_utils_utils.py | 63 ++-- xcp_d/tests/test_workflows_connectivity.py | 48 ++- xcp_d/tests/utils.py | 3 + xcp_d/utils/atlas.py | 220 +++++++------- xcp_d/utils/boilerplate.py | 8 +- xcp_d/utils/utils.py | 92 ++++-- xcp_d/workflows/anatomical/parcellation.py | 74 +++-- xcp_d/workflows/anatomical/volume.py | 5 +- xcp_d/workflows/base.py | 1 + xcp_d/workflows/bold/cifti.py | 8 +- xcp_d/workflows/bold/connectivity.py | 9 +- xcp_d/workflows/bold/nifti.py | 8 +- xcp_d/workflows/bold/outputs.py | 55 ++-- xcp_d/workflows/bold/plotting.py | 34 +-- xcp_d/workflows/parcellation.py | 121 +++++--- 68 files changed, 973 insertions(+), 741 deletions(-) create mode 100644 xcp_d/data/atlas_bids_config.json rename xcp_d/data/atlases/{ => atlas-Glasser}/atlas-Glasser_dseg.tsv (100%) rename xcp_d/data/atlases/{tpl-MNI152NLin6Asym_atlas-Glasser_dseg.json => atlas-Glasser/atlas-Glasser_space-MNI152NLin6Asym_dseg.json} (100%) rename xcp_d/data/atlases/{tpl-MNI152NLin6Asym_atlas-Glasser_res-01_dseg.nii.gz => atlas-Glasser/atlas-Glasser_space-MNI152NLin6Asym_res-01_dseg.nii.gz} (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-Glasser_den-32k_dseg.dlabel.nii => atlas-Glasser/atlas-Glasser_space-fsLR_den-32k_dseg.dlabel.nii} (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-Glasser_dseg.json => atlas-Glasser/atlas-Glasser_space-fsLR_dseg.json} (100%) rename xcp_d/data/atlases/{ => atlas-Gordon}/atlas-Gordon_dseg.tsv (100%) rename xcp_d/data/atlases/{tpl-MNI152NLin6Asym_atlas-Gordon_dseg.json => atlas-Gordon/atlas-Gordon_space-MNI152NLin6Asym_dseg.json} (100%) rename xcp_d/data/atlases/{tpl-MNI152NLin6Asym_atlas-Gordon_res-01_dseg.nii.gz => atlas-Gordon/atlas-Gordon_space-MNI152NLin6Asym_res-01_dseg.nii.gz} (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-Gordon_den-32k_dseg.dlabel.nii => atlas-Gordon/atlas-Gordon_space-fsLR_den-32k_dseg.dlabel.nii} (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-Gordon_dseg.json => atlas-Gordon/atlas-Gordon_space-fsLR_dseg.json} (100%) rename xcp_d/data/atlases/{ => atlas-HCP}/atlas-HCP_dseg.tsv (100%) rename xcp_d/data/atlases/{tpl-MNI152NLin6Asym_atlas-HCP_dseg.json => atlas-HCP/atlas-HCP_space-MNI152NLin6Asym_dseg.json} (100%) rename xcp_d/data/atlases/{tpl-MNI152NLin6Asym_atlas-HCP_res-02_dseg.nii.gz => atlas-HCP/atlas-HCP_space-MNI152NLin6Asym_res-02_dseg.nii.gz} (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-HCP_den-32k_dseg.dlabel.nii => atlas-HCP/atlas-HCP_space-fsLR_den-32k_dseg.dlabel.nii} (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-HCP_dseg.json => atlas-HCP/atlas-HCP_space-fsLR_dseg.json} (100%) rename xcp_d/data/atlases/{ => atlas-MIDB}/atlas-MIDB_dseg.tsv (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-MIDB_den-32k_desc-abcdThresh75_dseg.dlabel.nii => atlas-MIDB/atlas-MIDB_space-fsLR_den-32k_desc-abcdThresh75_dseg.dlabel.nii} (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-MIDB_den-32k_desc-abcdThresh75_dseg.json => atlas-MIDB/atlas-MIDB_space-fsLR_den-32k_desc-abcdThresh75_dseg.json} (100%) rename xcp_d/data/atlases/{ => atlas-MyersLabonte}/atlas-MyersLabonte_desc-thresh50_dseg.tsv (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-MyersLabonte_den-32k_desc-thresh50_dseg.dlabel.nii => atlas-MyersLabonte/atlas-MyersLabonte_space-fsLR_den-32k_desc-thresh50_dseg.dlabel.nii} (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-MyersLabonte_den-32k_desc-thresh50_dseg.json => atlas-MyersLabonte/atlas-MyersLabonte_space-fsLR_den-32k_desc-thresh50_dseg.json} (100%) rename xcp_d/data/atlases/{ => atlas-Tian}/atlas-Tian_dseg.tsv (100%) rename xcp_d/data/atlases/{tpl-MNI152NLin6Asym_atlas-Tian_dseg.json => atlas-Tian/atlas-Tian_space-MNI152NLin6Asym_dseg.json} (100%) rename xcp_d/data/atlases/{tpl-MNI152NLin6Asym_atlas-Tian_res-02_dseg.nii.gz => atlas-Tian/atlas-Tian_space-MNI152NLin6Asym_res-02_dseg.nii.gz} (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-Tian_den-32k_dseg.dlabel.nii => atlas-Tian/atlas-Tian_space-fsLR_den-32k_dseg.dlabel.nii} (100%) rename xcp_d/data/atlases/{tpl-fsLR_atlas-Tian_dseg.json => atlas-Tian/atlas-Tian_space-fsLR_dseg.json} (100%) create mode 100644 xcp_d/data/atlases/dataset_description.json delete mode 100644 xcp_d/data/atlases/tpl-fsLR_atlas-MyersLabonte_den-32k_dseg.dlabel.nii diff --git a/.circleci/config.yml b/.circleci/config.yml index 52ea57ca6..8851f5815 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -72,6 +72,23 @@ jobs: paths: - /src/xcp_d/.circleci/data/ds001419-aroma + download_data_schaefer100: + <<: *dockersetup + steps: + - checkout + - restore_cache: + key: schaefer100-02 + - run: *runinstall + - run: + name: Download BIDS-Atlas dataset + command: | + cd /src/xcp_d/.circleci + python get_data.py $PWD/data schaefer100 + - save_cache: + key: schaefer100-02 + paths: + - /src/xcp_d/.circleci/data/schaefer100 + download_data_pnc: <<: *dockersetup steps: @@ -161,6 +178,8 @@ jobs: fi - restore_cache: key: fmriprepwithoutfreesurfer-03 + - restore_cache: + key: schaefer100-02 - run: *runinstall - run: name: Run full xcp_d on nifti without freesurfer @@ -505,6 +524,8 @@ jobs: key: fmriprepwithoutfreesurfer-03 - restore_cache: key: nibabies-04 + - restore_cache: + key: schaefer100-02 - run: *runinstall - run: name: Run pytest on the tests directory @@ -648,6 +669,13 @@ workflows: tags: only: /.*/ + - download_data_schaefer100: + requires: + - build + filters: + tags: + only: /.*/ + - pnc_cifti: requires: - download_data_pnc @@ -718,6 +746,7 @@ workflows: - nifti_without_freesurfer: requires: - download_data_fmriprepwithoutfreesurfer + - download_data_schaefer100 filters: branches: ignore: @@ -743,6 +772,7 @@ workflows: - download_data_fmriprepwithoutfreesurfer - download_data_ds001419 - download_data_nibabies + - download_data_schaefer100 filters: branches: ignore: diff --git a/.vscode/settings.json b/.vscode/settings.json index 7cf249081..3e91b9ae7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,7 +6,5 @@ "[python]": { "editor.rulers": [99] }, - "python.linting.flake8Enabled": true, - "python.linting.enabled": true, "python.analysis.typeCheckingMode": "off", } diff --git a/README.rst b/README.rst index ad10c8df8..6cc85389d 100644 --- a/README.rst +++ b/README.rst @@ -88,7 +88,7 @@ and other postprocessing/analysis tools are better suited for many types of data XCP-D derivatives are not particularly useful for task-dependent functional connectivity analyses, such as psychophysiological interactions (PPIs) or beta series analyses. It is also not suitable for general task-based analyses, such as standard task GLMs, -as we recommend included nuisance regressors in the GLM step, +as we recommend including nuisance regressors in the GLM step, rather than denoising data prior to the GLM. diff --git a/docs/usage.rst b/docs/usage.rst index 800baf802..818724c90 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -469,42 +469,42 @@ plot_design_matrix.html#create-design-matrices>`_. Then, create a confounds config file to include derivatives from ``custom_confounds``. Something like this should work: -```yaml -name: my_custom_confounds -description: | - Nuisance regressors were task regressors convolved with an HRF and motion parameters. -confounds: - motion: - dataset: preprocessed - query: - space: null - cohort: null - res: null - den: null - desc: confounds - extension: .tsv - suffix: timeseries - columns: - - trans_x - - trans_y - - trans_z - - rot_x - - rot_y - - rot_z - task: - dataset: custom - query: - space: null - cohort: null - res: null - den: null - desc: confounds - extension: .tsv - suffix: timeseries - columns: - - condition1 - - condition2 -``` +.. code-block:: yaml + + name: my_custom_confounds + description: | + Nuisance regressors were task regressors convolved with an HRF and motion parameters. + confounds: + motion: + dataset: preprocessed + query: + space: null + cohort: null + res: null + den: null + desc: confounds + extension: .tsv + suffix: timeseries + columns: + - trans_x + - trans_y + - trans_z + - rot_x + - rot_y + - rot_z + task: + dataset: custom + query: + space: null + cohort: null + res: null + den: null + desc: confounds + extension: .tsv + suffix: timeseries + columns: + - condition1 + - condition2 Command Line XCP-D with Custom Confounds @@ -523,38 +523,89 @@ Last, run XCP-D with your custom configuration file and the path to the custom d --nuisance-regressors /mnt/custom_config.yaml -******************** -Custom Parcellations -******************** +**************** +External Atlases +**************** -While XCP-D comes with many built in parcellations, we understand that many users will want to use -custom parcellations. -If you use the ``-cifti`` option, you can use the Human Connectome Project's ``wb_command`` to -generate the time series: +While XCP-D comes with many built-in parcellations, +we understand that many users will want to use different ones. -.. code-block:: bash +As long as the parcellation is organized in a BIDS-Atlas dataset and is in +fsLR-32k space (for CIFTI processing) or +MNIInfant, MNI152NLin6Asym, or MNI152NLin2009cAsym space (for NIfTI processing), +you can use it with XCP-D. + +.. warning:: + BIDS Extension Proposal 38 (Atlas Specification) has not been integrated in BIDS yet, + so the organization and naming for atlas datasets may change in the future. + + We have attempted to follow the proposed structure in XCP-D, + but we cannot guarantee that this will not change. + +.. tip:: + The main elements from the BIDS-Atlas dataset that XCP-D uses are: + + 1. There must be a dataset_description.json file with DatasetType set to "atlas". + 2. The atlas metadata files must have the same entities as the atlas image files, + as PyBIDS does not support the inheritance principle when querying BIDS-Atlas datasets (yet). + 3. There must be a TSV file for the atlas, with "index" and "label" columns. - wb_command \ - -cifti-parcellate \ - {SUB}_ses-{SESSION}_task-{TASK}_run-{RUN}_space-fsLR_den-91k_desc-residual_bold.dtseries.nii \ - your_parcels.dlabel \ - {SUB}_ses-{SESSION}_task-{TASK}_run-{RUN}_space-fsLR_den-91k_desc-residual_timeseries.ptseries.nii +To do this, use the ``--datasets`` and ``--atlases`` parameters. +The ``--datasets`` parameter should point to the directory containing the BIDS-Atlas dataset, +and the ``--atlases`` parameter should include the names of the atlases in the dataset to use. -After this, if one wishes to have a connectivity matrix: +For example, consider a scenario where you have two BIDS-Atlas datasets, one containing all of the +Schaefer 2018 resolutions and one containing the AAL atlas. +These datasets are in ``/data/atlases/schaefer`` and ``/data/atlases/aal``, respectively. +The file structure for these two datasets might look like this: + +.. code-block:: + + /data/atlases/ + schaefer/ + dataset_description.json + atlas-Schaefer100/ + atlas-Schaefer100_dseg.tsv + atlas-Schaefer100_space-fsLR_den-32k_dseg.dlabel.nii + atlas-Schaefer100_space-fsLR_den-32k_dseg.json + atlas-Schaefer200/ + atlas-Schaefer200_dseg.tsv + atlas-Schaefer200_space-fsLR_den-32k_dseg.dlabel.nii + atlas-Schaefer200_space-fsLR_den-32k_dseg.json + ... + atlas-Schaefer1000/ + atlas-Schaefer1000_dseg.tsv + atlas-Schaefer1000_space-fsLR_den-32k_dseg.dlabel.nii + atlas-Schaefer1000_space-fsLR_den-32k_dseg.json + aal/ + dataset_description.json + atlas-AAL/ + atlas-AAL_dseg.tsv + atlas-AAL_space-fsLR_den-32k_dseg.dlabel.nii + atlas-AAL_space-fsLR_den-32k_dseg.json + +You may want to only apply the Schaefer100 atlas from the ``schaefer`` dataset and the AAL atlas +from the ``aal`` dataset, along with one of XCP-D's built-in atlases (``4S156Parcels``). +Here's what the XCP-D call might look like: .. code-block:: bash - wb_command \ - -cifti-correlation \ - {SUB}_ses-{SESSION}_task-{TASK}_run-{RUN}_space-fsLR_den-91k_desc-residual_timeseries.ptseries.nii \ - {SUB}_ses-{SESSION}_task-{TASK}_run-{RUN}_space-fsLR_den-91k_desc-residual_boldmap.pconn.nii + apptainer run --cleanenv -B /data:/data xcpd_latest.sif \ + /data/dataset/derivatives/fmriprep \ + /data/dataset/derivatives/xcp_d \ + participant \ + --mode linc \ + --datasets schaefer=/data/atlases/schaefer aal==/data/atlases/aal \ + --atlases Schaefer100 AAL 4S156Parcels + +XCP-D will search for ``atlas-Schaefer100``, ``atlas-AAL``, and ``atlas-4S156Parcels`` across the +``schaefer``, ``aal``, and XCP-D's built-in atlas datasets. +If the atlases are found, then they will be used for parcellation. -More information can be found at the HCP -`documentation `_. +.. important:: -If you use the default NIFTI processing pipeline, you can use Nilearn's -`NiftiLabelsMasker `_ + Atlas names must be unique across BIDS-Atlas datasets. + If two atlases have the same name, XCP-D will raise an error. ********************* diff --git a/xcp_d/cli/combineqc.py b/xcp_d/cli/combineqc.py index c689c5e90..8854bfce5 100644 --- a/xcp_d/cli/combineqc.py +++ b/xcp_d/cli/combineqc.py @@ -47,4 +47,4 @@ def main(args=None): if __name__ == "__main__": - raise RuntimeError("this should be run after xcp_d;\nrun XCP-D first") + raise RuntimeError("this should be run after XCP-D;\nrun XCP-D first") diff --git a/xcp_d/cli/parser.py b/xcp_d/cli/parser.py index 8968703ee..b229afe89 100644 --- a/xcp_d/cli/parser.py +++ b/xcp_d/cli/parser.py @@ -134,7 +134,7 @@ def _build_parser(): type=str, nargs="+", help=( - "Search PATH(s) for pre-computed derivatives. " + "Search PATH(s) for derivatives or atlas datasets. " "These may be provided as named folders " "(e.g., `--datasets smriprep=/path/to/smriprep`)." ), @@ -503,10 +503,12 @@ def _build_parser(): action="store", nargs="+", metavar="ATLAS", - choices=all_atlases, default=all_atlases, dest="atlases", - help="Selection of atlases to apply to the data. All are used by default.", + help=( + "Selection of atlases to apply to the data. " + "All of XCP-D's built-in atlases are used by default." + ), ) g_atlases.add_argument( "--skip-parcellation", @@ -934,6 +936,16 @@ def _validate_parameters(opts, build_log, parser): assert opts.output_type in ("censored", "interpolated", "auto") assert opts.process_surfaces in (True, False, "auto") + # Add internal atlas datasets to the list of datasets + opts.datasets = opts.datasets or {} + if opts.atlases: + if "xcpdatlases" not in opts.datasets: + opts.datasets["xcpdatlases"] = load_data("atlases") + + if any(atlas.startswith("4S") for atlas in opts.atlases): + if "xcpd4s" not in opts.datasets: + opts.datasets["xcpd4s"] = Path("/AtlasPack") + # Check parameters based on the mode if opts.mode == "abcd": opts.abcc_qc = True if (opts.abcc_qc == "auto") else opts.abcc_qc diff --git a/xcp_d/cli/parser_utils.py b/xcp_d/cli/parser_utils.py index c0cf81ee1..3e8f168c1 100644 --- a/xcp_d/cli/parser_utils.py +++ b/xcp_d/cli/parser_utils.py @@ -140,7 +140,9 @@ class YesNoAction(Action): def __call__(self, parser, namespace, values, option_string=None): # noqa: U100 """Call the argument.""" lookup = {"y": True, "n": False, None: True, "auto": "auto"} - assert values in lookup.keys(), f"Invalid value '{values}' for {self.dest}" + if values not in lookup: + raise parser.error(f"Invalid value '{values}' for {self.dest}") + setattr(namespace, self.dest, lookup[values]) @@ -159,9 +161,9 @@ def __call__(self, parser, namespace, values, option_string=None): # noqa: U100 name = loc.name if name in d: - raise ValueError(f"Received duplicate derivative name: {name}") + raise parser.error(f"Received duplicate derivative name: {name}") elif name == "preprocessed": - raise ValueError("The 'preprocessed' derivative is reserved for internal use.") + raise parser.error("The 'preprocessed' derivative is reserved for internal use.") d[name] = loc setattr(namespace, self.dest, d) diff --git a/xcp_d/cli/workflow.py b/xcp_d/cli/workflow.py index f9974d501..6e92b220d 100644 --- a/xcp_d/cli/workflow.py +++ b/xcp_d/cli/workflow.py @@ -93,7 +93,7 @@ def build_workflow(config_file, retval): ] if config.execution.datasets: - init_msg += [f"Searching for derivatives: {config.execution.datasets}."] + init_msg += [f"Searching for derivatives and atlases: {config.execution.datasets}."] build_log.log(25, f"\n{' ' * 11}* ".join(init_msg)) diff --git a/xcp_d/config.py b/xcp_d/config.py index c74d91eac..306345773 100644 --- a/xcp_d/config.py +++ b/xcp_d/config.py @@ -380,7 +380,7 @@ class execution(_Config): fmri_dir = None """An existing path to the preprocessing derivatives dataset, which must be BIDS-compliant.""" datasets = {} - """Path(s) to search for pre-computed derivatives""" + """Path(s) to search for other datasets (either derivatives or atlases).""" aggr_ses_reports = None """Maximum number of sessions aggregated in one subject's visual report.""" bids_database_dir = None diff --git a/xcp_d/data/atlas_bids_config.json b/xcp_d/data/atlas_bids_config.json new file mode 100644 index 000000000..f1677f2fe --- /dev/null +++ b/xcp_d/data/atlas_bids_config.json @@ -0,0 +1,44 @@ +{ + "name": "atlas", + "entities": [ + { + "name": "atlas", + "pattern": "[/\\\\]+atlas-([a-zA-Z0-9]+)", + "directory": "{atlas}" + }, + { + "name": "space", + "pattern": "[_/\\\\]+space-([a-zA-Z0-9]+)" + }, + { + "name": "hemi", + "pattern": "hemi-(L|R)" + }, + { + "name": "res", + "pattern": "res-([a-zA-Z0-9]+)" + }, + { + "name": "den", + "pattern": "den-([a-zA-Z0-9]+)" + }, + { + "name": "desc", + "pattern": "desc-([a-zA-Z0-9]+)" + }, + { + "name": "suffix", + "pattern": "(?:^|[_/\\\\])([a-zA-Z0-9]+)\\.[^/\\\\]+$" + }, + { + "name": "extension", + "pattern": "[^./\\\\](\\.[^/\\\\]+)$" + } + ], + "default_path_patterns": [ + "atlas-{atlas}/atlas-{atlas}[_space-{space}][_res-{res}][_desc-{desc}]_{suffix}.{extension|nii.gz}", + "atlas-{atlas}/atlas-{atlas}[_space-{space}][_res-{res}][_den-{den}][_desc-{desc}]_{suffix}.{extension|dlabel.nii}", + "atlas-{atlas}/atlas-{atlas}[_hemi-{hemi}][_space-{space}][_den-{den}][_desc-{desc}]_{suffix}.{extension|label.gii}", + "atlas-{atlas}/atlas-{atlas}[_space-{space}][_desc-{desc}]_{suffix}.{extension|tsv}" + ] +} diff --git a/xcp_d/data/atlases/atlas-Glasser_dseg.tsv b/xcp_d/data/atlases/atlas-Glasser/atlas-Glasser_dseg.tsv similarity index 100% rename from xcp_d/data/atlases/atlas-Glasser_dseg.tsv rename to xcp_d/data/atlases/atlas-Glasser/atlas-Glasser_dseg.tsv diff --git a/xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Glasser_dseg.json b/xcp_d/data/atlases/atlas-Glasser/atlas-Glasser_space-MNI152NLin6Asym_dseg.json similarity index 100% rename from xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Glasser_dseg.json rename to xcp_d/data/atlases/atlas-Glasser/atlas-Glasser_space-MNI152NLin6Asym_dseg.json diff --git a/xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Glasser_res-01_dseg.nii.gz b/xcp_d/data/atlases/atlas-Glasser/atlas-Glasser_space-MNI152NLin6Asym_res-01_dseg.nii.gz similarity index 100% rename from xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Glasser_res-01_dseg.nii.gz rename to xcp_d/data/atlases/atlas-Glasser/atlas-Glasser_space-MNI152NLin6Asym_res-01_dseg.nii.gz diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-Glasser_den-32k_dseg.dlabel.nii b/xcp_d/data/atlases/atlas-Glasser/atlas-Glasser_space-fsLR_den-32k_dseg.dlabel.nii similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-Glasser_den-32k_dseg.dlabel.nii rename to xcp_d/data/atlases/atlas-Glasser/atlas-Glasser_space-fsLR_den-32k_dseg.dlabel.nii diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-Glasser_dseg.json b/xcp_d/data/atlases/atlas-Glasser/atlas-Glasser_space-fsLR_dseg.json similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-Glasser_dseg.json rename to xcp_d/data/atlases/atlas-Glasser/atlas-Glasser_space-fsLR_dseg.json diff --git a/xcp_d/data/atlases/atlas-Gordon_dseg.tsv b/xcp_d/data/atlases/atlas-Gordon/atlas-Gordon_dseg.tsv similarity index 100% rename from xcp_d/data/atlases/atlas-Gordon_dseg.tsv rename to xcp_d/data/atlases/atlas-Gordon/atlas-Gordon_dseg.tsv diff --git a/xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Gordon_dseg.json b/xcp_d/data/atlases/atlas-Gordon/atlas-Gordon_space-MNI152NLin6Asym_dseg.json similarity index 100% rename from xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Gordon_dseg.json rename to xcp_d/data/atlases/atlas-Gordon/atlas-Gordon_space-MNI152NLin6Asym_dseg.json diff --git a/xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Gordon_res-01_dseg.nii.gz b/xcp_d/data/atlases/atlas-Gordon/atlas-Gordon_space-MNI152NLin6Asym_res-01_dseg.nii.gz similarity index 100% rename from xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Gordon_res-01_dseg.nii.gz rename to xcp_d/data/atlases/atlas-Gordon/atlas-Gordon_space-MNI152NLin6Asym_res-01_dseg.nii.gz diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-Gordon_den-32k_dseg.dlabel.nii b/xcp_d/data/atlases/atlas-Gordon/atlas-Gordon_space-fsLR_den-32k_dseg.dlabel.nii similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-Gordon_den-32k_dseg.dlabel.nii rename to xcp_d/data/atlases/atlas-Gordon/atlas-Gordon_space-fsLR_den-32k_dseg.dlabel.nii diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-Gordon_dseg.json b/xcp_d/data/atlases/atlas-Gordon/atlas-Gordon_space-fsLR_dseg.json similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-Gordon_dseg.json rename to xcp_d/data/atlases/atlas-Gordon/atlas-Gordon_space-fsLR_dseg.json diff --git a/xcp_d/data/atlases/atlas-HCP_dseg.tsv b/xcp_d/data/atlases/atlas-HCP/atlas-HCP_dseg.tsv similarity index 100% rename from xcp_d/data/atlases/atlas-HCP_dseg.tsv rename to xcp_d/data/atlases/atlas-HCP/atlas-HCP_dseg.tsv diff --git a/xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-HCP_dseg.json b/xcp_d/data/atlases/atlas-HCP/atlas-HCP_space-MNI152NLin6Asym_dseg.json similarity index 100% rename from xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-HCP_dseg.json rename to xcp_d/data/atlases/atlas-HCP/atlas-HCP_space-MNI152NLin6Asym_dseg.json diff --git a/xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-HCP_res-02_dseg.nii.gz b/xcp_d/data/atlases/atlas-HCP/atlas-HCP_space-MNI152NLin6Asym_res-02_dseg.nii.gz similarity index 100% rename from xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-HCP_res-02_dseg.nii.gz rename to xcp_d/data/atlases/atlas-HCP/atlas-HCP_space-MNI152NLin6Asym_res-02_dseg.nii.gz diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-HCP_den-32k_dseg.dlabel.nii b/xcp_d/data/atlases/atlas-HCP/atlas-HCP_space-fsLR_den-32k_dseg.dlabel.nii similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-HCP_den-32k_dseg.dlabel.nii rename to xcp_d/data/atlases/atlas-HCP/atlas-HCP_space-fsLR_den-32k_dseg.dlabel.nii diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-HCP_dseg.json b/xcp_d/data/atlases/atlas-HCP/atlas-HCP_space-fsLR_dseg.json similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-HCP_dseg.json rename to xcp_d/data/atlases/atlas-HCP/atlas-HCP_space-fsLR_dseg.json diff --git a/xcp_d/data/atlases/atlas-MIDB_dseg.tsv b/xcp_d/data/atlases/atlas-MIDB/atlas-MIDB_dseg.tsv similarity index 100% rename from xcp_d/data/atlases/atlas-MIDB_dseg.tsv rename to xcp_d/data/atlases/atlas-MIDB/atlas-MIDB_dseg.tsv diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-MIDB_den-32k_desc-abcdThresh75_dseg.dlabel.nii b/xcp_d/data/atlases/atlas-MIDB/atlas-MIDB_space-fsLR_den-32k_desc-abcdThresh75_dseg.dlabel.nii similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-MIDB_den-32k_desc-abcdThresh75_dseg.dlabel.nii rename to xcp_d/data/atlases/atlas-MIDB/atlas-MIDB_space-fsLR_den-32k_desc-abcdThresh75_dseg.dlabel.nii diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-MIDB_den-32k_desc-abcdThresh75_dseg.json b/xcp_d/data/atlases/atlas-MIDB/atlas-MIDB_space-fsLR_den-32k_desc-abcdThresh75_dseg.json similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-MIDB_den-32k_desc-abcdThresh75_dseg.json rename to xcp_d/data/atlases/atlas-MIDB/atlas-MIDB_space-fsLR_den-32k_desc-abcdThresh75_dseg.json diff --git a/xcp_d/data/atlases/atlas-MyersLabonte_desc-thresh50_dseg.tsv b/xcp_d/data/atlases/atlas-MyersLabonte/atlas-MyersLabonte_desc-thresh50_dseg.tsv similarity index 100% rename from xcp_d/data/atlases/atlas-MyersLabonte_desc-thresh50_dseg.tsv rename to xcp_d/data/atlases/atlas-MyersLabonte/atlas-MyersLabonte_desc-thresh50_dseg.tsv diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-MyersLabonte_den-32k_desc-thresh50_dseg.dlabel.nii b/xcp_d/data/atlases/atlas-MyersLabonte/atlas-MyersLabonte_space-fsLR_den-32k_desc-thresh50_dseg.dlabel.nii similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-MyersLabonte_den-32k_desc-thresh50_dseg.dlabel.nii rename to xcp_d/data/atlases/atlas-MyersLabonte/atlas-MyersLabonte_space-fsLR_den-32k_desc-thresh50_dseg.dlabel.nii diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-MyersLabonte_den-32k_desc-thresh50_dseg.json b/xcp_d/data/atlases/atlas-MyersLabonte/atlas-MyersLabonte_space-fsLR_den-32k_desc-thresh50_dseg.json similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-MyersLabonte_den-32k_desc-thresh50_dseg.json rename to xcp_d/data/atlases/atlas-MyersLabonte/atlas-MyersLabonte_space-fsLR_den-32k_desc-thresh50_dseg.json diff --git a/xcp_d/data/atlases/atlas-Tian_dseg.tsv b/xcp_d/data/atlases/atlas-Tian/atlas-Tian_dseg.tsv similarity index 100% rename from xcp_d/data/atlases/atlas-Tian_dseg.tsv rename to xcp_d/data/atlases/atlas-Tian/atlas-Tian_dseg.tsv diff --git a/xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Tian_dseg.json b/xcp_d/data/atlases/atlas-Tian/atlas-Tian_space-MNI152NLin6Asym_dseg.json similarity index 100% rename from xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Tian_dseg.json rename to xcp_d/data/atlases/atlas-Tian/atlas-Tian_space-MNI152NLin6Asym_dseg.json diff --git a/xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Tian_res-02_dseg.nii.gz b/xcp_d/data/atlases/atlas-Tian/atlas-Tian_space-MNI152NLin6Asym_res-02_dseg.nii.gz similarity index 100% rename from xcp_d/data/atlases/tpl-MNI152NLin6Asym_atlas-Tian_res-02_dseg.nii.gz rename to xcp_d/data/atlases/atlas-Tian/atlas-Tian_space-MNI152NLin6Asym_res-02_dseg.nii.gz diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-Tian_den-32k_dseg.dlabel.nii b/xcp_d/data/atlases/atlas-Tian/atlas-Tian_space-fsLR_den-32k_dseg.dlabel.nii similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-Tian_den-32k_dseg.dlabel.nii rename to xcp_d/data/atlases/atlas-Tian/atlas-Tian_space-fsLR_den-32k_dseg.dlabel.nii diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-Tian_dseg.json b/xcp_d/data/atlases/atlas-Tian/atlas-Tian_space-fsLR_dseg.json similarity index 100% rename from xcp_d/data/atlases/tpl-fsLR_atlas-Tian_dseg.json rename to xcp_d/data/atlases/atlas-Tian/atlas-Tian_space-fsLR_dseg.json diff --git a/xcp_d/data/atlases/dataset_description.json b/xcp_d/data/atlases/dataset_description.json new file mode 100644 index 000000000..5858f2f9a --- /dev/null +++ b/xcp_d/data/atlases/dataset_description.json @@ -0,0 +1,5 @@ +{ + "BIDSVersion": "1.9.0", + "DatasetType": "atlas", + "Name": "XCP-D atlases" +} \ No newline at end of file diff --git a/xcp_d/data/atlases/tpl-fsLR_atlas-MyersLabonte_den-32k_dseg.dlabel.nii b/xcp_d/data/atlases/tpl-fsLR_atlas-MyersLabonte_den-32k_dseg.dlabel.nii deleted file mode 100644 index eb28f5fa9b06c15fb351d488db7edd4900b0f92c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 607712 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
~{#B^t0@D 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

>v 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 diff --git a/xcp_d/interfaces/bids.py b/xcp_d/interfaces/bids.py index 5fd4b8fe2..eaba8e81d 100644 --- a/xcp_d/interfaces/bids.py +++ b/xcp_d/interfaces/bids.py @@ -2,7 +2,7 @@ import os import shutil -from json import loads +from json import dump, loads import nibabel as nb import numpy as np @@ -178,6 +178,12 @@ class _CopyAtlasInputSpec(BaseInterfaceInputSpec): desc="The atlas file to copy.", mandatory=True, ) + meta_dict = traits.Either( + traits.Dict(), + None, + desc="The atlas metadata dictionary.", + mandatory=False, + ) output_dir = Directory( exists=True, desc="The output directory.", @@ -234,15 +240,15 @@ class CopyAtlas(SimpleInterface): def _run_interface(self, runtime): output_dir = self.inputs.output_dir in_file = self.inputs.in_file + meta_dict = self.inputs.meta_dict name_source = self.inputs.name_source atlas = self.inputs.atlas atlas_out_dir = os.path.join(output_dir, f"atlases/atlas-{atlas}") - if in_file.endswith(".json"): - out_basename = f"atlas-{atlas}_dseg.json" - elif in_file.endswith(".tsv"): - out_basename = f"atlas-{atlas}_dseg.tsv" + if in_file.endswith(".tsv"): + out_basename = f"atlas-{atlas}_dseg" + extension = ".tsv" else: extension = ".nii.gz" if name_source.endswith(".nii.gz") else ".dlabel.nii" space = get_entity(name_source, "space") @@ -254,12 +260,12 @@ def _run_interface(self, runtime): res_str = f"_res-{res}" if res else "" den_str = f"_den-{den}" if den else "" if extension == ".dlabel.nii": - out_basename = f"atlas-{atlas}_space-{space}{den_str}{cohort_str}_dseg{extension}" + out_basename = f"atlas-{atlas}_space-{space}{den_str}{cohort_str}_dseg" elif extension == ".nii.gz": - out_basename = f"atlas-{atlas}_space-{space}{res_str}{cohort_str}_dseg{extension}" + out_basename = f"atlas-{atlas}_space-{space}{res_str}{cohort_str}_dseg" os.makedirs(atlas_out_dir, exist_ok=True) - out_file = os.path.join(atlas_out_dir, out_basename) + out_file = os.path.join(atlas_out_dir, f"{out_basename}{extension}") if out_file.endswith(".nii.gz") and os.path.isfile(out_file): # Check that native-resolution atlas doesn't have a different resolution from the last @@ -277,6 +283,12 @@ def _run_interface(self, runtime): if not os.path.isfile(out_file): shutil.copyfile(in_file, out_file) + # Only write out a sidecar if metadata are provided + if meta_dict: + meta_file = os.path.join(atlas_out_dir, f"{out_basename}.json") + with open(meta_file, "w") as fo: + dump(meta_dict, fo, sort_keys=True, indent=4) + self._results["out_file"] = out_file return runtime diff --git a/xcp_d/interfaces/connectivity.py b/xcp_d/interfaces/connectivity.py index a309a13fd..430a597b7 100644 --- a/xcp_d/interfaces/connectivity.py +++ b/xcp_d/interfaces/connectivity.py @@ -423,6 +423,8 @@ def _run_interface(self, runtime): "4S956Parcels", "4S1056Parcels", ] + external_atlases = [a for a in self.inputs.atlases if a not in priority_list] + priority_list += external_atlases selected_atlases = [] c = 0 for atlas in priority_list: @@ -569,14 +571,16 @@ def _run_interface(self, runtime): if "cifti_label" in node_labels_df.columns: parcel_label_mapper = dict(zip(node_labels_df["cifti_label"], node_labels_df["label"])) elif "label_7network" in node_labels_df.columns: - node_labels_df["label_7network"] = node_labels_df["label_7network"].fillna( + node_labels_df["cifti_label"] = node_labels_df["label_7network"].fillna( node_labels_df["label"] ) - parcel_label_mapper = dict( - zip(node_labels_df["label_7network"], node_labels_df["label"]) - ) + parcel_label_mapper = dict(zip(node_labels_df["cifti_label"], node_labels_df["label"])) else: - raise Exception(atlas_labels) + LOGGER.warning( + "No 'cifti_label' column found in atlas labels file. " + "Assuming labels in TSV exactly match node names in CIFTI atlas." + ) + parcel_label_mapper = dict(zip(node_labels_df["label"], node_labels_df["label"])) if in_file.endswith(".pconn.nii"): ax0 = img.header.get_axis(0) @@ -592,7 +596,7 @@ def _run_interface(self, runtime): df = pd.DataFrame(columns=ax1.name, data=img.get_fdata()) check_axes = [1] - # Check that all labels in the atlas labels DF are present in the TSV file, and vice versa. + # Check that all node labels in the CIFTI are present in the TSV, and vice versa. if 0 in check_axes: # Replace values in index, which should match the keys in the parcel_label_mapper # dictionary, with the corresponding values in the dictionary. diff --git a/xcp_d/tests/conftest.py b/xcp_d/tests/conftest.py index bf80131e0..42f71290f 100644 --- a/xcp_d/tests/conftest.py +++ b/xcp_d/tests/conftest.py @@ -67,6 +67,7 @@ def datasets(data_dir): data_dir, "fmriprepwithoutfreesurfer", ) + dsets["schaefer100"] = os.path.join(data_dir, "schaefer100") return dsets diff --git a/xcp_d/tests/data/test_ds001419_cifti_outputs.txt b/xcp_d/tests/data/test_ds001419_cifti_outputs.txt index a9c124110..16c3e9c6f 100644 --- a/xcp_d/tests/data/test_ds001419_cifti_outputs.txt +++ b/xcp_d/tests/data/test_ds001419_cifti_outputs.txt @@ -1,20 +1,20 @@ atlases atlases/atlas-4S156Parcels -atlases/atlas-4S156Parcels/atlas-4S156Parcels_dseg.json atlases/atlas-4S156Parcels/atlas-4S156Parcels_dseg.tsv atlases/atlas-4S156Parcels/atlas-4S156Parcels_space-fsLR_den-91k_dseg.dlabel.nii +atlases/atlas-4S156Parcels/atlas-4S156Parcels_space-fsLR_den-91k_dseg.json atlases/atlas-4S256Parcels -atlases/atlas-4S256Parcels/atlas-4S256Parcels_dseg.json atlases/atlas-4S256Parcels/atlas-4S256Parcels_dseg.tsv atlases/atlas-4S256Parcels/atlas-4S256Parcels_space-fsLR_den-91k_dseg.dlabel.nii +atlases/atlas-4S256Parcels/atlas-4S256Parcels_space-fsLR_den-91k_dseg.json atlases/atlas-4S356Parcels -atlases/atlas-4S356Parcels/atlas-4S356Parcels_dseg.json atlases/atlas-4S356Parcels/atlas-4S356Parcels_dseg.tsv atlases/atlas-4S356Parcels/atlas-4S356Parcels_space-fsLR_den-91k_dseg.dlabel.nii +atlases/atlas-4S356Parcels/atlas-4S356Parcels_space-fsLR_den-91k_dseg.json atlases/atlas-4S456Parcels -atlases/atlas-4S456Parcels/atlas-4S456Parcels_dseg.json atlases/atlas-4S456Parcels/atlas-4S456Parcels_dseg.tsv atlases/atlas-4S456Parcels/atlas-4S456Parcels_space-fsLR_den-91k_dseg.dlabel.nii +atlases/atlas-4S456Parcels/atlas-4S456Parcels_space-fsLR_den-91k_dseg.json atlases/dataset_description.json dataset_description.json desc-linc_qc.json diff --git a/xcp_d/tests/data/test_fmriprep_without_freesurfer_outputs.txt b/xcp_d/tests/data/test_fmriprep_without_freesurfer_outputs.txt index f1c261373..158582ae5 100644 --- a/xcp_d/tests/data/test_fmriprep_without_freesurfer_outputs.txt +++ b/xcp_d/tests/data/test_fmriprep_without_freesurfer_outputs.txt @@ -1,60 +1,11 @@ atlases -atlases/atlas-4S1056Parcels -atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_dseg.json -atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_dseg.tsv -atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_space-MNI152NLin2009cAsym_dseg.nii.gz atlases/atlas-4S156Parcels -atlases/atlas-4S156Parcels/atlas-4S156Parcels_dseg.json atlases/atlas-4S156Parcels/atlas-4S156Parcels_dseg.tsv +atlases/atlas-4S156Parcels/atlas-4S156Parcels_space-MNI152NLin2009cAsym_dseg.json atlases/atlas-4S156Parcels/atlas-4S156Parcels_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-4S256Parcels -atlases/atlas-4S256Parcels/atlas-4S256Parcels_dseg.json -atlases/atlas-4S256Parcels/atlas-4S256Parcels_dseg.tsv -atlases/atlas-4S256Parcels/atlas-4S256Parcels_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-4S356Parcels -atlases/atlas-4S356Parcels/atlas-4S356Parcels_dseg.json -atlases/atlas-4S356Parcels/atlas-4S356Parcels_dseg.tsv -atlases/atlas-4S356Parcels/atlas-4S356Parcels_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-4S456Parcels -atlases/atlas-4S456Parcels/atlas-4S456Parcels_dseg.json -atlases/atlas-4S456Parcels/atlas-4S456Parcels_dseg.tsv -atlases/atlas-4S456Parcels/atlas-4S456Parcels_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-4S556Parcels -atlases/atlas-4S556Parcels/atlas-4S556Parcels_dseg.json -atlases/atlas-4S556Parcels/atlas-4S556Parcels_dseg.tsv -atlases/atlas-4S556Parcels/atlas-4S556Parcels_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-4S656Parcels -atlases/atlas-4S656Parcels/atlas-4S656Parcels_dseg.json -atlases/atlas-4S656Parcels/atlas-4S656Parcels_dseg.tsv -atlases/atlas-4S656Parcels/atlas-4S656Parcels_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-4S756Parcels -atlases/atlas-4S756Parcels/atlas-4S756Parcels_dseg.json -atlases/atlas-4S756Parcels/atlas-4S756Parcels_dseg.tsv -atlases/atlas-4S756Parcels/atlas-4S756Parcels_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-4S856Parcels -atlases/atlas-4S856Parcels/atlas-4S856Parcels_dseg.json -atlases/atlas-4S856Parcels/atlas-4S856Parcels_dseg.tsv -atlases/atlas-4S856Parcels/atlas-4S856Parcels_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-4S956Parcels -atlases/atlas-4S956Parcels/atlas-4S956Parcels_dseg.json -atlases/atlas-4S956Parcels/atlas-4S956Parcels_dseg.tsv -atlases/atlas-4S956Parcels/atlas-4S956Parcels_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-Glasser -atlases/atlas-Glasser/atlas-Glasser_dseg.json -atlases/atlas-Glasser/atlas-Glasser_dseg.tsv -atlases/atlas-Glasser/atlas-Glasser_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-Gordon -atlases/atlas-Gordon/atlas-Gordon_dseg.json -atlases/atlas-Gordon/atlas-Gordon_dseg.tsv -atlases/atlas-Gordon/atlas-Gordon_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-HCP -atlases/atlas-HCP/atlas-HCP_dseg.json -atlases/atlas-HCP/atlas-HCP_dseg.tsv -atlases/atlas-HCP/atlas-HCP_space-MNI152NLin2009cAsym_dseg.nii.gz -atlases/atlas-Tian -atlases/atlas-Tian/atlas-Tian_dseg.json -atlases/atlas-Tian/atlas-Tian_dseg.tsv -atlases/atlas-Tian/atlas-Tian_space-MNI152NLin2009cAsym_dseg.nii.gz +atlases/atlas-Schaefer100 +atlases/atlas-Schaefer100/atlas-Schaefer100_dseg.tsv +atlases/atlas-Schaefer100/atlas-Schaefer100_space-MNI152NLin2009cAsym_dseg.nii.gz atlases/dataset_description.json dataset_description.json desc-linc_qc.json @@ -80,14 +31,6 @@ sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_desc-de sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_desc-denoised_bold.json sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_desc-denoised_bold.nii.gz sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_desc-linc_qc.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-reho_bold.tsv sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-coverage_bold.json sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-coverage_bold.tsv sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-mean_timeseries.json @@ -96,102 +39,14 @@ sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S1 sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-pearsoncorrelation_relmat.tsv sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-reho_bold.json sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Glasser_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Glasser_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Glasser_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Glasser_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Glasser_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Glasser_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Glasser_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Glasser_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Gordon_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Gordon_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Gordon_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Gordon_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Gordon_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Gordon_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Gordon_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Gordon_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-HCP_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-HCP_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-HCP_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-HCP_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-HCP_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-HCP_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-HCP_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-HCP_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Tian_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Tian_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Tian_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Tian_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Tian_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Tian_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Tian_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Tian_stat-reho_bold.tsv +sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-coverage_bold.json +sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-coverage_bold.tsv +sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-mean_timeseries.json +sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-mean_timeseries.tsv +sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-pearsoncorrelation_relmat.json +sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-pearsoncorrelation_relmat.tsv +sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-reho_bold.json +sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-reho_bold.tsv sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_stat-reho_boldmap.json sub-01/func/sub-01_task-mixedgamblestask_run-1_space-MNI152NLin2009cAsym_stat-reho_boldmap.nii.gz sub-01/func/sub-01_task-mixedgamblestask_run-2_desc-abcc_qc.hdf5 @@ -206,14 +61,6 @@ sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_desc-de sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_desc-denoised_bold.json sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_desc-denoised_bold.nii.gz sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_desc-linc_qc.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S1056Parcels_stat-reho_bold.tsv sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-coverage_bold.json sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-coverage_bold.tsv sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-mean_timeseries.json @@ -222,102 +69,14 @@ sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S1 sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-pearsoncorrelation_relmat.tsv sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-reho_bold.json sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S156Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S256Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S356Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S456Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S556Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S656Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S756Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S856Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-4S956Parcels_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Glasser_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Glasser_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Glasser_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Glasser_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Glasser_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Glasser_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Glasser_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Glasser_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Gordon_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Gordon_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Gordon_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Gordon_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Gordon_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Gordon_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Gordon_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Gordon_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-HCP_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-HCP_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-HCP_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-HCP_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-HCP_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-HCP_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-HCP_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-HCP_stat-reho_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Tian_stat-coverage_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Tian_stat-coverage_bold.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Tian_stat-mean_timeseries.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Tian_stat-mean_timeseries.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Tian_stat-pearsoncorrelation_relmat.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Tian_stat-pearsoncorrelation_relmat.tsv -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Tian_stat-reho_bold.json -sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Tian_stat-reho_bold.tsv +sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-coverage_bold.json +sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-coverage_bold.tsv +sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-mean_timeseries.json +sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-mean_timeseries.tsv +sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-pearsoncorrelation_relmat.json +sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-pearsoncorrelation_relmat.tsv +sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-reho_bold.json +sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_seg-Schaefer100_stat-reho_bold.tsv sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_stat-reho_boldmap.json sub-01/func/sub-01_task-mixedgamblestask_run-2_space-MNI152NLin2009cAsym_stat-reho_boldmap.nii.gz sub-01_executive_summary.html diff --git a/xcp_d/tests/data/test_nibabies_outputs.txt b/xcp_d/tests/data/test_nibabies_outputs.txt index 72199ec3a..eafc8c104 100644 --- a/xcp_d/tests/data/test_nibabies_outputs.txt +++ b/xcp_d/tests/data/test_nibabies_outputs.txt @@ -1,59 +1,59 @@ atlases atlases/atlas-4S1056Parcels -atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_dseg.json atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_dseg.tsv +atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_space-MNIInfant_cohort-1_dseg.json atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-4S156Parcels -atlases/atlas-4S156Parcels/atlas-4S156Parcels_dseg.json atlases/atlas-4S156Parcels/atlas-4S156Parcels_dseg.tsv +atlases/atlas-4S156Parcels/atlas-4S156Parcels_space-MNIInfant_cohort-1_dseg.json atlases/atlas-4S156Parcels/atlas-4S156Parcels_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-4S256Parcels -atlases/atlas-4S256Parcels/atlas-4S256Parcels_dseg.json atlases/atlas-4S256Parcels/atlas-4S256Parcels_dseg.tsv +atlases/atlas-4S256Parcels/atlas-4S256Parcels_space-MNIInfant_cohort-1_dseg.json atlases/atlas-4S256Parcels/atlas-4S256Parcels_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-4S356Parcels -atlases/atlas-4S356Parcels/atlas-4S356Parcels_dseg.json atlases/atlas-4S356Parcels/atlas-4S356Parcels_dseg.tsv +atlases/atlas-4S356Parcels/atlas-4S356Parcels_space-MNIInfant_cohort-1_dseg.json atlases/atlas-4S356Parcels/atlas-4S356Parcels_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-4S456Parcels -atlases/atlas-4S456Parcels/atlas-4S456Parcels_dseg.json atlases/atlas-4S456Parcels/atlas-4S456Parcels_dseg.tsv +atlases/atlas-4S456Parcels/atlas-4S456Parcels_space-MNIInfant_cohort-1_dseg.json atlases/atlas-4S456Parcels/atlas-4S456Parcels_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-4S556Parcels -atlases/atlas-4S556Parcels/atlas-4S556Parcels_dseg.json atlases/atlas-4S556Parcels/atlas-4S556Parcels_dseg.tsv +atlases/atlas-4S556Parcels/atlas-4S556Parcels_space-MNIInfant_cohort-1_dseg.json atlases/atlas-4S556Parcels/atlas-4S556Parcels_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-4S656Parcels -atlases/atlas-4S656Parcels/atlas-4S656Parcels_dseg.json atlases/atlas-4S656Parcels/atlas-4S656Parcels_dseg.tsv +atlases/atlas-4S656Parcels/atlas-4S656Parcels_space-MNIInfant_cohort-1_dseg.json atlases/atlas-4S656Parcels/atlas-4S656Parcels_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-4S756Parcels -atlases/atlas-4S756Parcels/atlas-4S756Parcels_dseg.json atlases/atlas-4S756Parcels/atlas-4S756Parcels_dseg.tsv +atlases/atlas-4S756Parcels/atlas-4S756Parcels_space-MNIInfant_cohort-1_dseg.json atlases/atlas-4S756Parcels/atlas-4S756Parcels_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-4S856Parcels -atlases/atlas-4S856Parcels/atlas-4S856Parcels_dseg.json atlases/atlas-4S856Parcels/atlas-4S856Parcels_dseg.tsv +atlases/atlas-4S856Parcels/atlas-4S856Parcels_space-MNIInfant_cohort-1_dseg.json atlases/atlas-4S856Parcels/atlas-4S856Parcels_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-4S956Parcels -atlases/atlas-4S956Parcels/atlas-4S956Parcels_dseg.json atlases/atlas-4S956Parcels/atlas-4S956Parcels_dseg.tsv +atlases/atlas-4S956Parcels/atlas-4S956Parcels_space-MNIInfant_cohort-1_dseg.json atlases/atlas-4S956Parcels/atlas-4S956Parcels_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-Glasser -atlases/atlas-Glasser/atlas-Glasser_dseg.json atlases/atlas-Glasser/atlas-Glasser_dseg.tsv +atlases/atlas-Glasser/atlas-Glasser_space-MNIInfant_cohort-1_dseg.json atlases/atlas-Glasser/atlas-Glasser_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-Gordon -atlases/atlas-Gordon/atlas-Gordon_dseg.json atlases/atlas-Gordon/atlas-Gordon_dseg.tsv +atlases/atlas-Gordon/atlas-Gordon_space-MNIInfant_cohort-1_dseg.json atlases/atlas-Gordon/atlas-Gordon_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-HCP -atlases/atlas-HCP/atlas-HCP_dseg.json atlases/atlas-HCP/atlas-HCP_dseg.tsv +atlases/atlas-HCP/atlas-HCP_space-MNIInfant_cohort-1_dseg.json atlases/atlas-HCP/atlas-HCP_space-MNIInfant_cohort-1_dseg.nii.gz atlases/atlas-Tian -atlases/atlas-Tian/atlas-Tian_dseg.json atlases/atlas-Tian/atlas-Tian_dseg.tsv +atlases/atlas-Tian/atlas-Tian_space-MNIInfant_cohort-1_dseg.json atlases/atlas-Tian/atlas-Tian_space-MNIInfant_cohort-1_dseg.nii.gz atlases/dataset_description.json dataset_description.json diff --git a/xcp_d/tests/data/test_pnc_cifti_outputs.txt b/xcp_d/tests/data/test_pnc_cifti_outputs.txt index 41c5cae2a..90c1e7e43 100644 --- a/xcp_d/tests/data/test_pnc_cifti_outputs.txt +++ b/xcp_d/tests/data/test_pnc_cifti_outputs.txt @@ -1,16 +1,16 @@ atlases atlases/atlas-HCP -atlases/atlas-HCP/atlas-HCP_dseg.json atlases/atlas-HCP/atlas-HCP_dseg.tsv atlases/atlas-HCP/atlas-HCP_space-fsLR_den-91k_dseg.dlabel.nii +atlases/atlas-HCP/atlas-HCP_space-fsLR_den-91k_dseg.json atlases/atlas-MyersLabonte -atlases/atlas-MyersLabonte/atlas-MyersLabonte_dseg.json atlases/atlas-MyersLabonte/atlas-MyersLabonte_dseg.tsv atlases/atlas-MyersLabonte/atlas-MyersLabonte_space-fsLR_den-91k_dseg.dlabel.nii +atlases/atlas-MyersLabonte/atlas-MyersLabonte_space-fsLR_den-91k_dseg.json atlases/atlas-Tian -atlases/atlas-Tian/atlas-Tian_dseg.json atlases/atlas-Tian/atlas-Tian_dseg.tsv atlases/atlas-Tian/atlas-Tian_space-fsLR_den-91k_dseg.dlabel.nii +atlases/atlas-Tian/atlas-Tian_space-fsLR_den-91k_dseg.json atlases/dataset_description.json dataset_description.json logs diff --git a/xcp_d/tests/data/test_pnc_cifti_t2wonly_outputs.txt b/xcp_d/tests/data/test_pnc_cifti_t2wonly_outputs.txt index c8ae9972e..45f6ccebb 100644 --- a/xcp_d/tests/data/test_pnc_cifti_t2wonly_outputs.txt +++ b/xcp_d/tests/data/test_pnc_cifti_t2wonly_outputs.txt @@ -1,12 +1,12 @@ atlases atlases/atlas-4S156Parcels -atlases/atlas-4S156Parcels/atlas-4S156Parcels_dseg.json atlases/atlas-4S156Parcels/atlas-4S156Parcels_dseg.tsv atlases/atlas-4S156Parcels/atlas-4S156Parcels_space-fsLR_den-91k_dseg.dlabel.nii +atlases/atlas-4S156Parcels/atlas-4S156Parcels_space-fsLR_den-91k_dseg.json atlases/atlas-MIDB -atlases/atlas-MIDB/atlas-MIDB_dseg.json atlases/atlas-MIDB/atlas-MIDB_dseg.tsv atlases/atlas-MIDB/atlas-MIDB_space-fsLR_den-91k_dseg.dlabel.nii +atlases/atlas-MIDB/atlas-MIDB_space-fsLR_den-91k_dseg.json atlases/dataset_description.json dataset_description.json logs diff --git a/xcp_d/tests/data/test_ukbiobank_outputs.txt b/xcp_d/tests/data/test_ukbiobank_outputs.txt index 0d94a8fc4..805c61aa6 100644 --- a/xcp_d/tests/data/test_ukbiobank_outputs.txt +++ b/xcp_d/tests/data/test_ukbiobank_outputs.txt @@ -1,59 +1,59 @@ atlases atlases/atlas-4S1056Parcels -atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_dseg.json atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_dseg.tsv +atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_space-MNI152NLin6Asym_dseg.json atlases/atlas-4S1056Parcels/atlas-4S1056Parcels_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-4S156Parcels -atlases/atlas-4S156Parcels/atlas-4S156Parcels_dseg.json atlases/atlas-4S156Parcels/atlas-4S156Parcels_dseg.tsv +atlases/atlas-4S156Parcels/atlas-4S156Parcels_space-MNI152NLin6Asym_dseg.json atlases/atlas-4S156Parcels/atlas-4S156Parcels_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-4S256Parcels -atlases/atlas-4S256Parcels/atlas-4S256Parcels_dseg.json atlases/atlas-4S256Parcels/atlas-4S256Parcels_dseg.tsv +atlases/atlas-4S256Parcels/atlas-4S256Parcels_space-MNI152NLin6Asym_dseg.json atlases/atlas-4S256Parcels/atlas-4S256Parcels_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-4S356Parcels -atlases/atlas-4S356Parcels/atlas-4S356Parcels_dseg.json atlases/atlas-4S356Parcels/atlas-4S356Parcels_dseg.tsv +atlases/atlas-4S356Parcels/atlas-4S356Parcels_space-MNI152NLin6Asym_dseg.json atlases/atlas-4S356Parcels/atlas-4S356Parcels_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-4S456Parcels -atlases/atlas-4S456Parcels/atlas-4S456Parcels_dseg.json atlases/atlas-4S456Parcels/atlas-4S456Parcels_dseg.tsv +atlases/atlas-4S456Parcels/atlas-4S456Parcels_space-MNI152NLin6Asym_dseg.json atlases/atlas-4S456Parcels/atlas-4S456Parcels_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-4S556Parcels -atlases/atlas-4S556Parcels/atlas-4S556Parcels_dseg.json atlases/atlas-4S556Parcels/atlas-4S556Parcels_dseg.tsv +atlases/atlas-4S556Parcels/atlas-4S556Parcels_space-MNI152NLin6Asym_dseg.json atlases/atlas-4S556Parcels/atlas-4S556Parcels_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-4S656Parcels -atlases/atlas-4S656Parcels/atlas-4S656Parcels_dseg.json atlases/atlas-4S656Parcels/atlas-4S656Parcels_dseg.tsv +atlases/atlas-4S656Parcels/atlas-4S656Parcels_space-MNI152NLin6Asym_dseg.json atlases/atlas-4S656Parcels/atlas-4S656Parcels_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-4S756Parcels -atlases/atlas-4S756Parcels/atlas-4S756Parcels_dseg.json atlases/atlas-4S756Parcels/atlas-4S756Parcels_dseg.tsv +atlases/atlas-4S756Parcels/atlas-4S756Parcels_space-MNI152NLin6Asym_dseg.json atlases/atlas-4S756Parcels/atlas-4S756Parcels_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-4S856Parcels -atlases/atlas-4S856Parcels/atlas-4S856Parcels_dseg.json atlases/atlas-4S856Parcels/atlas-4S856Parcels_dseg.tsv +atlases/atlas-4S856Parcels/atlas-4S856Parcels_space-MNI152NLin6Asym_dseg.json atlases/atlas-4S856Parcels/atlas-4S856Parcels_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-4S956Parcels -atlases/atlas-4S956Parcels/atlas-4S956Parcels_dseg.json atlases/atlas-4S956Parcels/atlas-4S956Parcels_dseg.tsv +atlases/atlas-4S956Parcels/atlas-4S956Parcels_space-MNI152NLin6Asym_dseg.json atlases/atlas-4S956Parcels/atlas-4S956Parcels_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-Glasser -atlases/atlas-Glasser/atlas-Glasser_dseg.json atlases/atlas-Glasser/atlas-Glasser_dseg.tsv +atlases/atlas-Glasser/atlas-Glasser_space-MNI152NLin6Asym_dseg.json atlases/atlas-Glasser/atlas-Glasser_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-Gordon -atlases/atlas-Gordon/atlas-Gordon_dseg.json atlases/atlas-Gordon/atlas-Gordon_dseg.tsv +atlases/atlas-Gordon/atlas-Gordon_space-MNI152NLin6Asym_dseg.json atlases/atlas-Gordon/atlas-Gordon_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-HCP -atlases/atlas-HCP/atlas-HCP_dseg.json atlases/atlas-HCP/atlas-HCP_dseg.tsv +atlases/atlas-HCP/atlas-HCP_space-MNI152NLin6Asym_dseg.json atlases/atlas-HCP/atlas-HCP_space-MNI152NLin6Asym_dseg.nii.gz atlases/atlas-Tian -atlases/atlas-Tian/atlas-Tian_dseg.json atlases/atlas-Tian/atlas-Tian_dseg.tsv +atlases/atlas-Tian/atlas-Tian_space-MNI152NLin6Asym_dseg.json atlases/atlas-Tian/atlas-Tian_space-MNI152NLin6Asym_dseg.nii.gz atlases/dataset_description.json dataset_description.json diff --git a/xcp_d/tests/test_cli.py b/xcp_d/tests/test_cli.py index f582a7e0a..16003d087 100644 --- a/xcp_d/tests/test_cli.py +++ b/xcp_d/tests/test_cli.py @@ -290,6 +290,7 @@ def test_fmriprep_without_freesurfer(data_dir, output_dir, working_dir): test_name = "test_fmriprep_without_freesurfer" dataset_dir = download_test_data("fmriprepwithoutfreesurfer", data_dir) + atlas_dir = download_test_data("schaefer100", data_dir) tmpdir = os.path.join(output_dir, test_name) out_dir = os.path.join(tmpdir, "xcp_d") work_dir = os.path.join(working_dir, test_name) @@ -301,6 +302,11 @@ def test_fmriprep_without_freesurfer(data_dir, output_dir, working_dir): "--mode=linc", f"-w={work_dir}", "--file-format=nifti", + "--datasets", + f"schaefer={atlas_dir}", + "--atlases", + "4S156Parcels", + "Schaefer100", "--nthreads=2", "--omp-nthreads=2", "--head_radius=40", @@ -338,6 +344,7 @@ def test_fmriprep_without_freesurfer_with_main(data_dir, output_dir, working_dir test_name = "test_fmriprep_without_freesurfer" dataset_dir = download_test_data("fmriprepwithoutfreesurfer", data_dir) + atlas_dir = download_test_data("schaefer100", data_dir) tmpdir = os.path.join(output_dir, f"{test_name}_with_main") out_dir = os.path.join(tmpdir, "xcp_d") work_dir = os.path.join(working_dir, f"{test_name}_with_main") @@ -349,6 +356,11 @@ def test_fmriprep_without_freesurfer_with_main(data_dir, output_dir, working_dir "--mode=linc", f"-w={work_dir}", "--file-format=nifti", + "--datasets", + f"schaefer={atlas_dir}", + "--atlases", + "4S156Parcels", + "Schaefer100", "--nthreads=2", "--omp-nthreads=2", "--head_radius=40", diff --git a/xcp_d/tests/test_cli_run.py b/xcp_d/tests/test_cli_run.py index 9019dcc27..1ad18a867 100644 --- a/xcp_d/tests/test_cli_run.py +++ b/xcp_d/tests/test_cli_run.py @@ -29,6 +29,7 @@ def base_opts(): "output_dir": Path("out"), "work_dir": Path("work"), "analysis_level": "participant", + "datasets": {}, "mode": "linc", "file_format": "auto", "input_type": "auto", diff --git a/xcp_d/tests/test_cli_utils.py b/xcp_d/tests/test_cli_utils.py index 8d6ec3b1c..9c2494ac4 100644 --- a/xcp_d/tests/test_cli_utils.py +++ b/xcp_d/tests/test_cli_utils.py @@ -164,3 +164,71 @@ def test_bids_filter(tmp_path_factory): parser = ArgumentParser() result = parser_utils._bids_filter(None, parser) assert result is None + + +def test_yes_no_action(): + """Test parser_utils.YesNoAction.""" + parser = ArgumentParser() + parser.add_argument("--option", nargs="?", action=parser_utils.YesNoAction) + + # A value of y should be True + args = parser.parse_args(["--option", "y"]) + assert args.option is True + + # A value of n should be False + args = parser.parse_args(["--option", "n"]) + assert args.option is False + + # The parameter without a value should default to True + args = parser.parse_args(["--option"]) + assert args.option is True + + # Auto is an option + args = parser.parse_args(["--option", "auto"]) + assert args.option == "auto" + + # Invalid value raises an error + with pytest.raises(SystemExit): + parser.parse_args(["--option", "invalid"]) + + +def test_to_dict(): + """Test parser_utils.ToDict.""" + parser = ArgumentParser() + parser.add_argument("--option", action=parser_utils.ToDict, nargs="+") + + # Two key-value pairs + args = parser.parse_args(["--option", "key1=value1", "key2=value2"]) + assert args.option == {"key1": Path("value1"), "key2": Path("value2")} + + # Providing the same key twice + with pytest.raises(SystemExit): + parser.parse_args(["--option", "key1=value1", "key1=value2"]) + + # Trying to use one of the reserved keys + with pytest.raises(SystemExit): + parser.parse_args(["--option", "preprocessed=value1"]) + + # Dataset with no name + args = parser.parse_args(["--option", "value1"]) + assert args.option == {"value1": Path("value1")} + + +def test_confounds_action(tmp_path): + """Test parser_utils.ConfoundsAction.""" + parser = ArgumentParser() + parser.add_argument("--confounds", action=parser_utils.ConfoundsAction) + + # A value of auto should be "auto" + args = parser.parse_args(["--confounds", "auto"]) + assert args.confounds == "auto" + + # A valid custom confounds option + valid_path = tmp_path / "valid_confounds.yml" + valid_path.touch() # Create the file + args = parser.parse_args(["--confounds", str(valid_path)]) + assert args.confounds == valid_path + + # Path to a non-existent file should raise an error + with pytest.raises(SystemExit): + parser.parse_args(["--confounds", "/invalid/path/to/confounds.yml"]) diff --git a/xcp_d/tests/test_interfaces_bids.py b/xcp_d/tests/test_interfaces_bids.py index e71b185f4..55d39ea4b 100644 --- a/xcp_d/tests/test_interfaces_bids.py +++ b/xcp_d/tests/test_interfaces_bids.py @@ -5,7 +5,7 @@ import pytest from xcp_d.interfaces import bids -from xcp_d.utils import atlas +from xcp_d.data import load as load_data def test_copy_atlas(tmp_path_factory): @@ -14,13 +14,25 @@ def test_copy_atlas(tmp_path_factory): os.makedirs(os.path.join(tmpdir, "xcp_d"), exist_ok=True) # NIfTI - atlas_file, _, _ = atlas.get_atlas_nifti("Gordon") + atlas_info = { + "image": load_data( + "atlases/atlas-Gordon/atlas-Gordon_space-MNI152NLin6Asym_res-01_dseg.nii.gz" + ), + "labels": load_data("atlases/atlas-Gordon/atlas-Gordon_dseg.tsv"), + "metadata": {"thing": "stuff"}, + "dataset": "xcpdatlases", + } name_source = "sub-01_task-A_run-01_space-MNI152NLin2009cAsym_res-2_desc-z_bold.nii.gz" copyatlas = bids.CopyAtlas( - name_source=name_source, in_file=atlas_file, output_dir=tmpdir, atlas="Y" + name_source=name_source, + in_file=atlas_info["image"], + output_dir=tmpdir, + atlas="Y", + meta_dict=atlas_info["metadata"], ) result = copyatlas.run(cwd=tmpdir) assert os.path.isfile(result.outputs.out_file) + assert os.path.isfile(result.outputs.out_file.replace(".nii.gz", ".json")) assert ( os.path.basename(result.outputs.out_file) == "atlas-Y_space-MNI152NLin2009cAsym_res-2_dseg.nii.gz" @@ -28,24 +40,39 @@ def test_copy_atlas(tmp_path_factory): # Check that the NIfTI file raises an error if the resolution varies # Gordon atlas is 1mm, HCP is 2mm - atlas_file_diff_affine, _, _ = atlas.get_atlas_nifti("HCP") + atlas_info_diff_affine = { + "image": load_data("atlases/atlas-HCP/atlas-HCP_space-MNI152NLin6Asym_res-02_dseg.nii.gz"), + "labels": load_data("atlases/atlas-HCP/atlas-HCP_dseg.tsv"), + "metadata": {"thing": "stuff"}, + "dataset": "xcpdatlases", + } with pytest.raises(ValueError, match="is different from the input file affine"): copyatlas = bids.CopyAtlas( name_source=name_source, - in_file=atlas_file_diff_affine, + in_file=atlas_info_diff_affine["image"], output_dir=tmpdir, atlas="Y", ) copyatlas.run(cwd=tmpdir) # CIFTI - atlas_file, atlas_labels_file, atlas_metadata_file = atlas.get_atlas_cifti("Gordon") + atlas_info = { + "image": load_data("atlases/atlas-Gordon/atlas-Gordon_space-fsLR_den-32k_dseg.dlabel.nii"), + "labels": load_data("atlases/atlas-Gordon/atlas-Gordon_dseg.tsv"), + "metadata": {"thing": "stuff"}, + "dataset": "xcpdatlases", + } name_source = "sub-01_task-imagery_run-01_space-fsLR_den-91k_desc-denoised_bold.dtseries.nii" copyatlas = bids.CopyAtlas( - name_source=name_source, in_file=atlas_file, output_dir=tmpdir, atlas="Y" + name_source=name_source, + in_file=atlas_info["image"], + output_dir=tmpdir, + atlas="Y", + meta_dict=atlas_info["metadata"], ) result = copyatlas.run(cwd=tmpdir) assert os.path.isfile(result.outputs.out_file) + assert os.path.isfile(result.outputs.out_file.replace(".dlabel.nii", ".json")) assert ( os.path.basename(result.outputs.out_file) == "atlas-Y_space-fsLR_den-91k_dseg.dlabel.nii" ) @@ -53,23 +80,14 @@ def test_copy_atlas(tmp_path_factory): # TSV name_source = "sub-01_task-imagery_run-01_space-fsLR_den-91k_desc-denoised_bold.dtseries.nii" copyatlas = bids.CopyAtlas( - name_source=name_source, in_file=atlas_labels_file, output_dir=tmpdir, atlas="Y" + name_source=name_source, in_file=atlas_info["labels"], output_dir=tmpdir, atlas="Y" ) result = copyatlas.run(cwd=tmpdir) assert os.path.isfile(result.outputs.out_file) assert os.path.basename(result.outputs.out_file) == "atlas-Y_dseg.tsv" - # JSON - name_source = "sub-01_task-imagery_run-01_space-fsLR_den-91k_desc-denoised_bold.dtseries.nii" - copyatlas = bids.CopyAtlas( - name_source=name_source, in_file=atlas_metadata_file, output_dir=tmpdir, atlas="Y" - ) - result = copyatlas.run(cwd=tmpdir) - assert os.path.isfile(result.outputs.out_file) - assert os.path.basename(result.outputs.out_file) == "atlas-Y_dseg.json" - # Ensure that out_file isn't overwritten if it already exists - fake_in_file = os.path.join(tmpdir, "fake.json") + fake_in_file = os.path.join(tmpdir, "fake.tsv") with open(fake_in_file, "w") as fo: fo.write("fake") @@ -78,7 +96,7 @@ def test_copy_atlas(tmp_path_factory): ) result = copyatlas.run(cwd=tmpdir) assert os.path.isfile(result.outputs.out_file) - assert os.path.basename(result.outputs.out_file) == "atlas-Y_dseg.json" + assert os.path.basename(result.outputs.out_file) == "atlas-Y_dseg.tsv" # The file should not be overwritten, so the contents shouldn't be "fake" with open(result.outputs.out_file, "r") as fo: assert fo.read() != "fake" diff --git a/xcp_d/tests/test_utils_atlas.py b/xcp_d/tests/test_utils_atlas.py index 0ddfee7e8..9e06adaf4 100644 --- a/xcp_d/tests/test_utils_atlas.py +++ b/xcp_d/tests/test_utils_atlas.py @@ -1,9 +1,10 @@ """Tests for the xcp_d.utils.atlas module.""" -import os +import json import pytest +from xcp_d.data import load as load_data from xcp_d.utils import atlas @@ -15,39 +16,108 @@ def test_get_atlas_names(): assert len(selected_atlases) == 2 -def test_get_atlas_nifti(): - """Test xcp_d.utils.atlas.get_atlas_nifti.""" - selected_atlases = atlas.select_atlases( - atlases=["4S156Parcels", "4S256Parcels", "Tian"], - subset="all", +def test_collect_atlases(datasets, caplog, tmp_path_factory): + """Test xcp_d.utils.atlas.collect_atlases.""" + schaefer_dset = datasets["schaefer100"] + + atlas_datasets = { + "xcpdatlases": str(load_data("atlases")), + } + atlas_cache = atlas.collect_atlases( + datasets=atlas_datasets, + atlases=["Gordon", "Schaefer100"], + file_format="nifti", + bids_filters={}, + ) + assert "Gordon" in atlas_cache + assert "Schaefer100" not in atlas_cache + assert "No atlas images found for Schaefer100" in caplog.text + + # Add the schaefer dataset + atlas_datasets["schaefer100"] = schaefer_dset + atlas_cache = atlas.collect_atlases( + datasets=atlas_datasets, + atlases=["Gordon", "Schaefer100"], + file_format="nifti", + bids_filters={}, + ) + assert "Gordon" in atlas_cache + assert "Schaefer100" in atlas_cache + + # Skip over the schaefer dataset + atlas_datasets["schaefer100"] = schaefer_dset + atlas_cache = atlas.collect_atlases( + datasets=atlas_datasets, + atlases=["Gordon"], + file_format="cifti", + bids_filters={}, + ) + assert "Gordon" in atlas_cache + assert "Schaefer100" not in atlas_cache + + # Add a duplicate atlas + atlas_datasets["duplicate"] = str(load_data("atlases")) + with pytest.raises(ValueError, match="Multiple datasets contain the same atlas 'Gordon'"): + atlas.collect_atlases( + datasets=atlas_datasets, + atlases=["Gordon"], + file_format="nifti", + bids_filters={}, + ) + + # Create a dataset that has atlases, but is missing information + tmpdir = tmp_path_factory.mktemp("test_collect_atlases") + # Make the dataset_description.json + with open(tmpdir / "dataset_description.json", "w") as fo: + json.dump({"DatasetType": "atlas", "BIDSVersion": "1.9.0", "Name": "Test"}, fo) + + # Create fake atlas file + (tmpdir / "atlas-TEST").mkdir() + (tmpdir / "atlas-TEST" / "atlas-TEST_space-MNI152NLin6Asym_res-01_dseg.nii.gz").write_text( + "test" ) - for selected_atlas in selected_atlases: - atlas_file, atlas_labels_file, metadata_file = atlas.get_atlas_nifti(selected_atlas) - assert isinstance(atlas_file, str) - assert isinstance(atlas_labels_file, str) - assert isinstance(metadata_file, str) - assert os.path.isfile(atlas_file) - assert os.path.isfile(atlas_labels_file) - assert os.path.isfile(metadata_file) - - with pytest.raises(FileNotFoundError, match="DNE"): - atlas.get_atlas_nifti("tofail") - - -def test_get_atlas_cifti(): - """Test xcp_d.utils.atlas.get_atlas_cifti.""" - selected_atlases = atlas.select_atlases( - atlases=["4S156Parcels", "4S256Parcels", "MIDB", "MyersLabonte", "Tian"], - subset="all", + + # First there's an image, but no TSV or metadata + with pytest.raises(FileNotFoundError, match="No TSV file found for"): + atlas.collect_atlases( + datasets={"test": tmpdir}, + atlases=["TEST"], + file_format="nifti", + bids_filters={}, + ) + + # Now there's an image and a TSV, but the TSV doesn't have a "label" column + with open(tmpdir / "atlas-TEST" / "atlas-TEST_dseg.tsv", "w") as fo: + fo.write("index\n1\n") + + with pytest.raises(ValueError, match="'label' column not found"): + atlas.collect_atlases( + datasets={"test": tmpdir}, + atlases=["TEST"], + file_format="nifti", + bids_filters={}, + ) + + # Now there's an image and a TSV, but the TSV doesn't have an "index" column + with open(tmpdir / "atlas-TEST" / "atlas-TEST_dseg.tsv", "w") as fo: + fo.write("label\ntest\n") + + with pytest.raises(ValueError, match="'index' column not found"): + atlas.collect_atlases( + datasets={"test": tmpdir}, + atlases=["TEST"], + file_format="nifti", + bids_filters={}, + ) + + # Now there's an image, a TSV, and metadata + with open(tmpdir / "atlas-TEST" / "atlas-TEST_dseg.tsv", "w") as fo: + fo.write("index\tlabel\n1\ttest\n") + + atlas_cache = atlas.collect_atlases( + datasets={"test": tmpdir}, + atlases=["TEST"], + file_format="nifti", + bids_filters={}, ) - for selected_atlas in selected_atlases: - atlas_file, atlas_labels_file, metadata_file = atlas.get_atlas_cifti(selected_atlas) - assert isinstance(atlas_file, str) - assert isinstance(atlas_labels_file, str) - assert isinstance(metadata_file, str) - assert os.path.isfile(atlas_file) - assert os.path.isfile(atlas_labels_file) - assert os.path.isfile(metadata_file) - - with pytest.raises(FileNotFoundError, match="DNE"): - atlas.get_atlas_cifti("tofail") + assert "TEST" in atlas_cache diff --git a/xcp_d/tests/test_utils_boilerplate.py b/xcp_d/tests/test_utils_boilerplate.py index dbe7912c5..808e26332 100644 --- a/xcp_d/tests/test_utils_boilerplate.py +++ b/xcp_d/tests/test_utils_boilerplate.py @@ -191,6 +191,6 @@ def test_describe_atlases(): assert "Tian" in atlas_desc assert "Glasser" in atlas_desc + # This no longer fails. It just adds the missing atlas to the description. atlases = ["4S156Parcels", "4S256Parcels", "Glasser", "fail"] - with pytest.raises(ValueError, match="Unrecognized atlas"): - boilerplate.describe_atlases(atlases) + assert "the fail atlas" in boilerplate.describe_atlases(atlases) diff --git a/xcp_d/tests/test_utils_utils.py b/xcp_d/tests/test_utils_utils.py index 5d85a3897..26bd24b7b 100644 --- a/xcp_d/tests/test_utils_utils.py +++ b/xcp_d/tests/test_utils_utils.py @@ -454,34 +454,63 @@ def test_get_bold2std_and_t1w_xfms(ds001419_data): def test_get_std2bold_xfms(ds001419_data): """Test get_std2bold_xfms. - get_std2bold_xfms finds transforms to go from the input file's space to MNI152NLin6Asym. + get_std2bold_xfms finds transforms to go from a source file's space to the BOLD file's space. """ bold_file_nlin6asym = ds001419_data["nifti_file"] - # MNI152NLin6Asym --> MNI152NLin6Asym - xforms_to_mni = utils.get_std2bold_xfms(bold_file_nlin6asym) + # MNI152NLin6Asym --> MNI152NLin6Asym with source file containing tpl entity + xforms_to_mni = utils.get_std2bold_xfms( + bold_file_nlin6asym, + source_file="tpl-MNI152NLin6Asym_T1w.nii.gz", + source_space=None, + ) assert len(xforms_to_mni) == 1 - # MNI152NLin6Asym --> MNI152NLin2009cAsym - bold_file_nlin2009c = bold_file_nlin6asym.replace( - "space-MNI152NLin6Asym_", - "space-MNI152NLin2009cAsym_", + # MNI152NLin6Asym --> MNI152NLin6Asym with source file containing space entity + xforms_to_mni = utils.get_std2bold_xfms( + bold_file_nlin6asym, + source_file="space-MNI152NLin6Asym_T1w.nii.gz", + source_space=None, ) - xforms_to_mni = utils.get_std2bold_xfms(bold_file_nlin2009c) assert len(xforms_to_mni) == 1 - # MNI152NLin6Asym --> MNIInfant - bold_file_infant = bold_file_nlin6asym.replace( - "space-MNI152NLin6Asym_", - "space-MNIInfant_cohort-1_", - ) - xforms_to_mni = utils.get_std2bold_xfms(bold_file_infant) - assert len(xforms_to_mni) == 2 + SPACES = [ + ("MNI152NLin6Asym", "MNI152NLin6Asym", 1), + ("MNI152NLin6Asym", "MNI152NLin2009cAsym", 1), + ("MNI152NLin6Asym", "MNIInfant", 2), + ("MNI152NLin2009cAsym", "MNI152NLin2009cAsym", 1), + ("MNI152NLin2009cAsym", "MNI152NLin6Asym", 1), + ("MNI152NLin2009cAsym", "MNIInfant", 1), + ("MNIInfant", "MNIInfant", 1), + ("MNIInfant", "MNI152NLin2009cAsym", 1), + ("MNIInfant", "MNI152NLin6Asym", 2), + ] + for space_check in SPACES: + target_space, source_space, n_xforms = space_check + bold_file_target_space = bold_file_nlin6asym.replace( + "space-MNI152NLin6Asym_", + f"space-{target_space}_", + ) + xforms_to_mni = utils.get_std2bold_xfms( + bold_file_target_space, + source_file=None, + source_space=source_space, + ) + assert len(xforms_to_mni) == n_xforms + + # Outside of the supported spaces, we expect an error + # No space or tpl entity in source file + with pytest.raises(ValueError, match="Unknown space"): + utils.get_std2bold_xfms(bold_file_nlin6asym, source_file="T1w.nii.gz", source_space=None) # MNI152NLin6Asym --> tofail bold_file_tofail = bold_file_nlin6asym.replace("space-MNI152NLin6Asym_", "space-tofail_") - with pytest.raises(ValueError, match="Space 'tofail'"): - utils.get_std2bold_xfms(bold_file_tofail) + with pytest.raises(ValueError, match="BOLD space 'tofail' not supported"): + utils.get_std2bold_xfms(bold_file_tofail, source_file=None, source_space="MNI152NLin6Asym") + + # tofail --> MNI152NLin6Asym + with pytest.raises(ValueError, match="Source space 'tofail' not supported"): + utils.get_std2bold_xfms(bold_file_nlin6asym, source_file=None, source_space="tofail") def test_fwhm2sigma(): diff --git a/xcp_d/tests/test_workflows_connectivity.py b/xcp_d/tests/test_workflows_connectivity.py index f8c7420cd..276ed6a25 100644 --- a/xcp_d/tests/test_workflows_connectivity.py +++ b/xcp_d/tests/test_workflows_connectivity.py @@ -9,11 +9,11 @@ from nilearn.maskers import NiftiLabelsMasker from xcp_d import config +from xcp_d.data import load as load_data from xcp_d.interfaces.ants import ApplyTransforms from xcp_d.interfaces.connectivity import _sanitize_nifti_atlas from xcp_d.tests.tests import mock_config from xcp_d.tests.utils import get_nodes -from xcp_d.utils.atlas import get_atlas_cifti, get_atlas_nifti from xcp_d.utils.bids import _get_tr from xcp_d.utils.utils import _create_mem_gb, get_std2bold_xfms from xcp_d.utils.write_save import read_ndata, write_ndata @@ -37,6 +37,10 @@ def test_init_load_atlases_wf_nifti(ds001419_data, tmp_path_factory): config.execution.output_dir = tmpdir config.workflow.file_format = "nifti" config.execution.atlases = ["4S156Parcels", "Glasser"] + config.execution.datasets = { + "xcpdatlases": str(load_data("atlases")), + "xcpd4s": "/AtlasPack", + } config.nipype.omp_nthreads = 1 load_atlases_wf = init_load_atlases_wf(name="load_atlases_wf") @@ -62,6 +66,10 @@ def test_init_load_atlases_wf_cifti(ds001419_data, tmp_path_factory): config.execution.output_dir = tmpdir config.workflow.file_format = "cifti" config.execution.atlases = ["4S156Parcels", "Glasser"] + config.execution.datasets = { + "xcpdatlases": str(load_data("atlases")), + "xcpd4s": "/AtlasPack", + } config.nipype.omp_nthreads = 1 load_atlases_wf = init_load_atlases_wf(name="load_atlases_wf") @@ -111,13 +119,29 @@ def test_init_functional_connectivity_nifti_wf(ds001419_data, tmp_path_factory): # Load atlases atlas_names = ["Gordon", "Glasser"] - atlas_files = [get_atlas_nifti(atlas_name)[0] for atlas_name in atlas_names] - atlas_labels_files = [get_atlas_nifti(atlas_name)[1] for atlas_name in atlas_names] + atlas_files = [ + str( + load_data("atlases/atlas-Gordon/atlas-Gordon_space-MNI152NLin6Asym_res-01_dseg.nii.gz") + ), + str( + load_data( + "atlases/atlas-Glasser/atlas-Glasser_space-MNI152NLin6Asym_res-01_dseg.nii.gz" + ) + ), + ] + atlas_labels_files = [ + str(load_data("atlases/atlas-Gordon/atlas-Gordon_dseg.tsv")), + str(load_data("atlases/atlas-Glasser/atlas-Glasser_dseg.tsv")), + ] # Perform the resampling and parcellation done by init_load_atlases_wf warped_atlases = [] # Get transform(s) from MNI152NLin6Asym to BOLD file's space - transforms_from_MNI152NLin6Asym = get_std2bold_xfms(bold_file) + transforms_from_MNI152NLin6Asym = get_std2bold_xfms( + bold_file, + source_file=None, + source_space="MNI152NLin6Asym", + ) for atlas_file in atlas_files: # Using the generated transforms, apply them to get everything in the correct MNI form warp_atlases_to_bold_space = ApplyTransforms( @@ -262,8 +286,20 @@ def test_init_functional_connectivity_cifti_wf(ds001419_data, tmp_path_factory): # Load atlases atlas_names = ["4S1056Parcels", "4S156Parcels", "4S456Parcels", "Gordon", "Glasser"] - atlas_files = [get_atlas_cifti(atlas_name)[0] for atlas_name in atlas_names] - atlas_labels_files = [get_atlas_cifti(atlas_name)[1] for atlas_name in atlas_names] + atlas_files = [ + "/AtlasPack/atlas-4S1056Parcels/atlas-4S1056Parcels_space-fsLR_den-91k_dseg.dlabel.nii", + "/AtlasPack/atlas-4S156Parcels/atlas-4S156Parcels_space-fsLR_den-91k_dseg.dlabel.nii", + "/AtlasPack/atlas-4S456Parcels/atlas-4S456Parcels_space-fsLR_den-91k_dseg.dlabel.nii", + str(load_data("atlases/atlas-Gordon/atlas-Gordon_space-fsLR_den-32k_dseg.dlabel.nii")), + str(load_data("atlases/atlas-Glasser/atlas-Glasser_space-fsLR_den-32k_dseg.dlabel.nii")), + ] + atlas_labels_files = [ + "/AtlasPack/atlas-4S1056Parcels/atlas-4S1056Parcels_dseg.tsv", + "/AtlasPack/atlas-4S156Parcels/atlas-4S156Parcels_dseg.tsv", + "/AtlasPack/atlas-4S456Parcels/atlas-4S456Parcels_dseg.tsv", + str(load_data("atlases/atlas-Gordon/atlas-Gordon_dseg.tsv")), + str(load_data("atlases/atlas-Glasser/atlas-Glasser_dseg.tsv")), + ] # Create the node and a tmpdir to write its results out to with mock_config(): diff --git a/xcp_d/tests/utils.py b/xcp_d/tests/utils.py index 0cd3d88bb..d1851e390 100644 --- a/xcp_d/tests/utils.py +++ b/xcp_d/tests/utils.py @@ -66,6 +66,9 @@ def download_test_data(dset, data_dir=None): ), "pnc": "https://upenn.box.com/shared/static/ui2847ys49d82pgn5ewai1mowcmsv2br.tar.gz", "ukbiobank": "https://upenn.box.com/shared/static/p5h1eg4p5cd2ef9ehhljlyh1uku0xe97.tar.gz", + "schaefer100": ( + "https://upenn.box.com/shared/static/b9pn9qebr41kteant4ym2q5u4kcbgiy6.tar.gz" + ), } if dset == "*": for k in URLS: diff --git a/xcp_d/utils/atlas.py b/xcp_d/utils/atlas.py index 41c21558a..557b466ea 100644 --- a/xcp_d/utils/atlas.py +++ b/xcp_d/utils/atlas.py @@ -1,5 +1,9 @@ """Functions for working with atlases.""" +from nipype import logging + +LOGGER = logging.getLogger("nipype.utils") + def select_atlases(atlases, subset): """Get a list of atlases to be used for parcellation and functional connectivity analyses. @@ -54,126 +58,122 @@ def select_atlases(atlases, subset): return selected_atlases -def get_atlas_nifti(atlas): - """Select atlas by name from xcp_d/data using load_data. +def collect_atlases(datasets, atlases, file_format, bids_filters={}): + """Collect atlases from a list of BIDS-Atlas datasets. - All atlases are in MNI space. - - NOTE: This is a Node function. + Selection of labels files and metadata does not leverage the inheritance principle. + That probably won't be possible until PyBIDS supports the BIDS-Atlas extension natively. Parameters ---------- - atlas : {"4S156Parcels", "4S256Parcels", "4S356Parcels", "4S456Parcels", \ - "4S556Parcels", "4S656Parcels", "4S756Parcels", "4S856Parcels", \ - "4S956Parcels", "4S1056Parcels", "Glasser", "Gordon", \ - "Tian", "HCP"} - The name of the NIFTI atlas to fetch. + datasets : dict of str:str or str:BIDSLayout pairs + Dictionary of BIDS datasets to search for atlases. + atlases : list of str + List of atlases to collect from across the datasets. + file_format : {"nifti", "cifti"} + The file format of the atlases. + bids_filters : dict + Additional filters to apply to the BIDS query. Returns ------- - atlas_file : :obj:`str` - Path to the atlas file. - atlas_labels_file : :obj:`str` - Path to the atlas labels file. - atlas_metadata_file : :obj:`str` - Path to the atlas metadata file. + atlas_cache : dict + Dictionary of atlases with metadata. + Keys are the atlas names, values are dictionaries with keys: + + - "dataset" : str + Name of the dataset containing the atlas. + - "image" : str + Path to the atlas image. + - "labels" : str + Path to the atlas labels file. + - "metadata" : dict + Metadata associated with the atlas. """ - from os.path import isfile, join - - from xcp_d.data import load as load_data - - if "4S" in atlas: - # 1 mm3 atlases - atlas_fname = f"atlas-{atlas}_space-MNI152NLin6Asym_res-01_dseg.nii.gz" - tsv_fname = f"atlas-{atlas}_dseg.tsv" - elif atlas in ("Glasser", "Gordon"): - # 1 mm3 atlases - atlas_fname = f"tpl-MNI152NLin6Asym_atlas-{atlas}_res-01_dseg.nii.gz" - tsv_fname = f"atlas-{atlas}_dseg.tsv" - else: - # 2 mm3 atlases - atlas_fname = f"tpl-MNI152NLin6Asym_atlas-{atlas}_res-02_dseg.nii.gz" - tsv_fname = f"atlas-{atlas}_dseg.tsv" - - if "4S" in atlas: - atlas_file = join(f"/AtlasPack/atlas-{atlas}", atlas_fname) - atlas_labels_file = join(f"/AtlasPack/atlas-{atlas}", tsv_fname) - atlas_metadata_file = ( - f"/AtlasPack/atlas-{atlas}/atlas-{atlas}_space-MNI152NLin6Asym_res-01_dseg.json" - ) - else: - atlas_file = str(load_data(f"atlases/{atlas_fname}")) - atlas_labels_file = str(load_data(f"atlases/{tsv_fname}")) - atlas_metadata_file = str( - load_data(f"atlases/tpl-MNI152NLin6Asym_atlas-{atlas}_dseg.json") - ) - - if not (isfile(atlas_file) and isfile(atlas_labels_file) and isfile(atlas_metadata_file)): - raise FileNotFoundError( - f"File(s) DNE:\n\t{atlas_file}\n\t{atlas_labels_file}\n\t{atlas_metadata_file}" - ) - - return atlas_file, atlas_labels_file, atlas_metadata_file - - -def get_atlas_cifti(atlas): - """Select atlas by name from xcp_d/data. + import json - All atlases are in 91K space. - - NOTE: This is a Node function. - - Parameters - ---------- - atlas : {"4S156Parcels", "4S256Parcels", "4S356Parcels", "4S456Parcels", \ - "4S556Parcels", "4S656Parcels", "4S756Parcels", "4S856Parcels", \ - "4S956Parcels", "4S1056Parcels", "Glasser", "Gordon", \ - "Tian", "HCP", "MIDB", "MyersLabonte"} - The name of the CIFTI atlas to fetch. - - Returns - ------- - atlas_file : :obj:`str` - Path to the atlas file. - atlas_labels_file : :obj:`str` - The labels TSV file associated with the atlas. - atlas_metadata_file : :obj:`str` - The metadata JSON file associated with the atlas. - """ - from os.path import isfile + import pandas as pd + from bids.layout import BIDSLayout from xcp_d.data import load as load_data - if "4S" in atlas: - atlas_file = f"/AtlasPack/atlas-{atlas}/atlas-{atlas}_space-fsLR_den-91k_dseg.dlabel.nii" - atlas_labels_file = f"/AtlasPack/atlas-{atlas}/atlas-{atlas}_dseg.tsv" - atlas_metadata_file = ( - f"/AtlasPack/atlas-{atlas}/atlas-{atlas}_space-fsLR_den-91k_dseg.json" - ) - elif "MIDB" in atlas: - atlas_file = str( - load_data("atlases/tpl-fsLR_atlas-MIDB_den-32k_desc-abcdThresh75_dseg.dlabel.nii") - ) - atlas_labels_file = str(load_data(f"atlases/atlas-{atlas}_dseg.tsv")) - atlas_metadata_file = str( - load_data("atlases/tpl-fsLR_atlas-MIDB_den-32k_desc-abcdThresh75_dseg.json") - ) - elif "MyersLabonte" in atlas: - atlas_file = str( - load_data("atlases/tpl-fsLR_atlas-MyersLabonte_den-32k_desc-thresh50_dseg.dlabel.nii") - ) - atlas_labels_file = str(load_data("atlases/atlas-MyersLabonte_desc-thresh50_dseg.tsv")) - atlas_metadata_file = str( - load_data("atlases/tpl-fsLR_atlas-MyersLabonte_den-32k_desc-thresh50_dseg.json") - ) - else: - atlas_file = str(load_data(f"atlases/tpl-fsLR_atlas-{atlas}_den-32k_dseg.dlabel.nii")) - atlas_labels_file = str(load_data(f"atlases/atlas-{atlas}_dseg.tsv")) - atlas_metadata_file = str(load_data(f"atlases/tpl-fsLR_atlas-{atlas}_dseg.json")) - - if not (isfile(atlas_file) and isfile(atlas_labels_file) and isfile(atlas_metadata_file)): - raise FileNotFoundError( - f"File(s) DNE:\n\t{atlas_file}\n\t{atlas_labels_file}\n\t{atlas_metadata_file}" - ) + atlas_cfg = load_data("atlas_bids_config.json") + bids_filters = bids_filters or {} - return atlas_file, atlas_labels_file, atlas_metadata_file + atlas_filter = bids_filters.get("atlas", {}) + atlas_filter["extension"] = [".nii.gz", ".nii"] if file_format == "nifti" else ".dlabel.nii" + # Hardcoded spaces for now + if file_format == "cifti": + atlas_filter["space"] = atlas_filter.get("space") or "fsLR" + atlas_filter["den"] = atlas_filter.get("den") or ["32k", "91k"] + else: + atlas_filter["space"] = atlas_filter.get("space") or [ + "MNI152NLin6Asym", + "MNI152NLin2009cAsym", + "MNIInfant", + ] + + atlas_cache = {} + for dataset_name, dataset_path in datasets.items(): + if not isinstance(dataset_path, BIDSLayout): + layout = BIDSLayout(dataset_path, config=[atlas_cfg], validate=False) + else: + layout = dataset_path + + if layout.get_dataset_description().get("DatasetType") != "atlas": + continue + + for atlas in atlases: + atlas_images = layout.get( + atlas=atlas, + **atlas_filter, + return_type="file", + ) + if not atlas_images: + continue + elif len(atlas_images) > 1: + bulleted_list = "\n".join([f" - {img}" for img in atlas_images]) + LOGGER.warning( + f"Multiple atlas images found for {atlas} with query {atlas_filter}:\n" + f"{bulleted_list}\nUsing {atlas_images[0]}." + ) + + if atlas in atlas_cache: + raise ValueError(f"Multiple datasets contain the same atlas '{atlas}'") + + atlas_image = atlas_images[0] + atlas_labels = layout.get_nearest(atlas_image, extension=".tsv", strict=False) + atlas_metadata_file = layout.get_nearest(atlas_image, extension=".json", strict=True) + + if not atlas_labels: + raise FileNotFoundError(f"No TSV file found for {atlas_image}") + + atlas_metadata = None + if atlas_metadata_file: + with open(atlas_metadata_file, "r") as fo: + atlas_metadata = json.load(fo) + + atlas_cache[atlas] = { + "dataset": dataset_name, + "image": atlas_image, + "labels": atlas_labels, + "metadata": atlas_metadata, + } + + for atlas in atlases: + if atlas not in atlas_cache: + LOGGER.warning(f"No atlas images found for {atlas} with query {atlas_filter}") + + for atlas, atlas_info in atlas_cache.items(): + if not atlas_info["labels"]: + raise FileNotFoundError(f"No TSV file found for {atlas_info['image']}") + + # Check the contents of the labels file + df = pd.read_table(atlas_info["labels"]) + if "label" not in df.columns: + raise ValueError(f"'label' column not found in {atlas_info['labels']}") + + if "index" not in df.columns: + raise ValueError(f"'index' column not found in {atlas_info['labels']}") + + return atlas_cache diff --git a/xcp_d/utils/boilerplate.py b/xcp_d/utils/boilerplate.py index 089e288b6..4661fec91 100644 --- a/xcp_d/utils/boilerplate.py +++ b/xcp_d/utils/boilerplate.py @@ -188,10 +188,10 @@ def describe_atlases(atlases): atlas_strings = [] described_atlases = [] - atlases_4s = [atlas for atlas in atlases if atlas.startswith("4S")] + atlases_4s = [atlas for atlas in atlases if str(atlas).startswith("4S")] described_atlases += atlases_4s if atlases_4s: - parcels = [int(atlas[2:-7]) for atlas in atlases_4s] + parcels = [int(str(atlas[2:-7])) for atlas in atlases_4s] s = ( "the Schaefer Supplemented with Subcortical Structures (4S) atlas " "[@Schaefer_2017;@pauli2018high;@king2019functional;@najdenovska2018vivo;" @@ -206,7 +206,7 @@ def describe_atlases(atlases): described_atlases.append(k) undescribed_atlases = [atlas for atlas in atlases if atlas not in described_atlases] - if undescribed_atlases: - raise ValueError(f"Unrecognized atlas(es) in the list: {', '.join(undescribed_atlases)}.") + for atlas in undescribed_atlases: + atlas_strings.append(f"the {atlas} atlas") return list_to_str(atlas_strings) diff --git a/xcp_d/utils/utils.py b/xcp_d/utils/utils.py index a409f11b0..0446a7a9c 100644 --- a/xcp_d/utils/utils.py +++ b/xcp_d/utils/utils.py @@ -130,8 +130,8 @@ def get_bold2std_and_t1w_xfms(bold_file, template_to_anat_xfm): return xforms_to_MNI, xforms_to_MNI_invert, xforms_to_T1w, xforms_to_T1w_invert -def get_std2bold_xfms(bold_file): - """Obtain transforms to warp atlases from MNI152NLin6Asym to the same template as the BOLD. +def get_std2bold_xfms(bold_file, source_file, source_space=None): + """Obtain transforms to warp atlases from a source space to the same template as the BOLD. Since ANTSApplyTransforms takes in the transform files as a stack, these are applied in the reverse order of which they are specified. @@ -142,10 +142,14 @@ def get_std2bold_xfms(bold_file): ---------- bold_file : :obj:`str` The preprocessed BOLD file. + source_file : :obj:`str` + The source file to warp to the BOLD space. + source_space : :obj:`str`, optional + The space of the source file. If None, the space of the source file is inferred and used. Returns ------- - transform_list : list of str + transforms : list of str A list of paths to transform files. Notes @@ -159,8 +163,6 @@ def get_std2bold_xfms(bold_file): Does not include inversion flag output because there is no need (yet). Can easily be added in the future. """ - import os - from templateflow.api import get as get_template from xcp_d.data import load as load_data @@ -169,7 +171,22 @@ def get_std2bold_xfms(bold_file): # Extract the space of the BOLD file bold_space = get_entity(bold_file, "space") - # Load useful inter-template transforms from templateflow + if source_space is None: + # If a source space is not provided, extract the space of the source file + # First try tpl because that won't raise an error + source_space = get_entity(source_file, "tpl") + if source_space is None: + # If tpl isn't available, try space. + # get_entity will raise an error if space isn't there. + source_space = get_entity(source_file, "space") + + if source_space not in ("MNI152NLin6Asym", "MNI152NLin2009cAsym", "MNIInfant"): + raise ValueError(f"Source space '{source_space}' not supported.") + + if bold_space not in ("MNI152NLin6Asym", "MNI152NLin2009cAsym", "MNIInfant"): + raise ValueError(f"BOLD space '{bold_space}' not supported.") + + # Load useful inter-template transforms from templateflow and package data MNI152NLin6Asym_to_MNI152NLin2009cAsym = str( get_template( template="MNI152NLin2009cAsym", @@ -179,33 +196,54 @@ def get_std2bold_xfms(bold_file): **{"from": "MNI152NLin6Asym"}, ), ) + MNI152NLin2009cAsym_to_MNI152NLin6Asym = str( + get_template( + template="MNI152NLin6Asym", + mode="image", + suffix="xfm", + extension=".h5", + **{"from": "MNI152NLin2009cAsym"}, + ), + ) + MNIInfant_to_MNI152NLin2009cAsym = str( + load_data( + "transform/tpl-MNIInfant_from-MNI152NLin2009cAsym_mode-image_xfm.h5", + ) + ) + MNI152NLin2009cAsym_to_MNIInfant = str( + load_data( + "transform/tpl-MNI152NLin2009cAsym_from-MNIInfant_mode-image_xfm.h5", + ) + ) - # Find the appropriate transform(s) - if bold_space == "MNI152NLin6Asym": - # NLin6 --> NLin6 (identity) - transform_list = ["identity"] + if bold_space == source_space: + transforms = ["identity"] + + elif bold_space == "MNI152NLin6Asym": + if source_space == "MNI152NLin2009cAsym": + transforms = [MNI152NLin2009cAsym_to_MNI152NLin6Asym] + elif source_space == "MNIInfant": + transforms = [ + MNI152NLin2009cAsym_to_MNI152NLin6Asym, + MNIInfant_to_MNI152NLin2009cAsym, + ] elif bold_space == "MNI152NLin2009cAsym": - # NLin6 --> NLin2009c - transform_list = [MNI152NLin6Asym_to_MNI152NLin2009cAsym] + if source_space == "MNI152NLin6Asym": + transforms = [MNI152NLin6Asym_to_MNI152NLin2009cAsym] + elif source_space == "MNIInfant": + transforms = [MNIInfant_to_MNI152NLin2009cAsym] elif bold_space == "MNIInfant": - # NLin6 --> NLin2009c --> MNIInfant - MNI152NLin2009cAsym_to_MNI152Infant = str( - load_data( - "transform/tpl-MNIInfant_from-MNI152NLin2009cAsym_mode-image_xfm.h5", - ) - ) - transform_list = [ - MNI152NLin2009cAsym_to_MNI152Infant, - MNI152NLin6Asym_to_MNI152NLin2009cAsym, - ] - - else: - file_base = os.path.basename(bold_file) - raise ValueError(f"Space '{bold_space}' in {file_base} not supported.") + if source_space == "MNI152NLin6Asym": + transforms = [ + MNI152NLin2009cAsym_to_MNIInfant, + MNI152NLin6Asym_to_MNI152NLin2009cAsym, + ] + elif source_space == "MNI152NLin2009cAsym": + transforms = [MNI152NLin2009cAsym_to_MNIInfant] - return transform_list + return transforms def fwhm2sigma(fwhm): diff --git a/xcp_d/workflows/anatomical/parcellation.py b/xcp_d/workflows/anatomical/parcellation.py index eed2dcb27..5e4537ae5 100644 --- a/xcp_d/workflows/anatomical/parcellation.py +++ b/xcp_d/workflows/anatomical/parcellation.py @@ -1,13 +1,13 @@ """Workflows for parcellating anatomical data.""" -from nipype import Function, logging +from nipype import logging from nipype.interfaces import utility as niu from nipype.pipeline import engine as pe from niworkflows.engine.workflows import LiterateWorkflow as Workflow from xcp_d import config from xcp_d.interfaces.bids import DerivativesDataSink -from xcp_d.utils.atlas import get_atlas_cifti, select_atlases +from xcp_d.utils.atlas import select_atlases from xcp_d.utils.doc import fill_doc from xcp_d.workflows.parcellation import init_parcellate_cifti_wf @@ -50,11 +50,10 @@ def init_parcellate_surfaces_wf(files_to_parcellate, name="parcellate_surfaces_w myelin_smoothed """ from xcp_d.interfaces.workbench import CiftiCreateDenseFromTemplate + from xcp_d.utils.atlas import collect_atlases workflow = Workflow(name=name) - atlases = config.execution.atlases - SURF_DESCS = { "sulcal_depth": "sulc", "sulcal_curv": "curv", @@ -73,14 +72,46 @@ def init_parcellate_surfaces_wf(files_to_parcellate, name="parcellate_surfaces_w "cortical_thickness_corr", "myelin", "myelin_smoothed", + # atlases + "atlas_names", + "atlas_datasets", + "atlas_files", + "atlas_labels_files", + "atlas_metadata_files", ], ), name="inputnode", ) - selected_atlases = select_atlases(atlases=atlases, subset="cortical") + builtin_atlases = select_atlases(atlases=config.execution.atlases, subset="all") + external_atlases = sorted(list(set(config.execution.atlases) - set(builtin_atlases))) + builtin_cortical_atlases = select_atlases(atlases=builtin_atlases, subset="cortical") + selected_atlases = builtin_cortical_atlases + external_atlases + atlases = collect_atlases( + datasets=config.execution.datasets, + atlases=selected_atlases, + file_format=config.workflow.file_format, + bids_filters=config.execution.bids_filters, + ) - if not selected_atlases: + # Reorganize the atlas file information + atlas_names, atlas_files, atlas_labels_files, atlas_metadata_files = [], [], [], [] + atlas_datasets = [] + for atlas, atlas_dict in atlases.items(): + config.loggers.workflow.info(f"Loading atlas: {atlas}") + atlas_names.append(atlas) + atlas_datasets.append(atlas_dict["dataset"]) + atlas_files.append(atlas_dict["image"]) + atlas_labels_files.append(atlas_dict["labels"]) + atlas_metadata_files.append(atlas_dict["metadata"]) + + inputnode.inputs.atlas_names = atlas_names + inputnode.inputs.atlas_datasets = atlas_datasets + inputnode.inputs.atlas_files = atlas_files + inputnode.inputs.atlas_labels_files = atlas_labels_files + inputnode.inputs.atlas_metadata_files = atlas_metadata_files + + if not atlases: LOGGER.warning( "No cortical atlases have been selected, so surface metrics will not be parcellated." ) @@ -89,18 +120,6 @@ def init_parcellate_surfaces_wf(files_to_parcellate, name="parcellate_surfaces_w return workflow - # Get CIFTI atlases via load_data - atlas_file_grabber = pe.MapNode( - Function( - input_names=["atlas"], - output_names=["atlas_file", "atlas_labels_file", "atlas_metadata_file"], - function=get_atlas_cifti, - ), - name="atlas_file_grabber", - iterfield=["atlas"], - ) - atlas_file_grabber.inputs.atlas = selected_atlases - for file_to_parcellate in files_to_parcellate: resample_atlas_to_surface = pe.MapNode( CiftiCreateDenseFromTemplate( @@ -112,8 +131,10 @@ def init_parcellate_surfaces_wf(files_to_parcellate, name="parcellate_surfaces_w n_procs=config.nipype.omp_nthreads, ) workflow.connect([ - (inputnode, resample_atlas_to_surface, [(file_to_parcellate, "template_cifti")]), - (atlas_file_grabber, resample_atlas_to_surface, [("atlas_file", "label")]), + (inputnode, resample_atlas_to_surface, [ + ("atlas_files", "label"), + (file_to_parcellate, "template_cifti"), + ]), ]) # fmt:skip parcellate_surface_wf = init_parcellate_cifti_wf( @@ -122,9 +143,9 @@ def init_parcellate_surfaces_wf(files_to_parcellate, name="parcellate_surfaces_w name=f"parcellate_{file_to_parcellate}_wf", ) workflow.connect([ - (inputnode, parcellate_surface_wf, [(file_to_parcellate, "inputnode.in_file")]), - (atlas_file_grabber, parcellate_surface_wf, [ - ("atlas_labels_file", "inputnode.atlas_labels_files"), + (inputnode, parcellate_surface_wf, [ + (file_to_parcellate, "inputnode.in_file"), + ("atlas_labels_files", "inputnode.atlas_labels_files"), ]), (resample_atlas_to_surface, parcellate_surface_wf, [ ("out_file", "inputnode.atlas_files"), @@ -145,10 +166,11 @@ def init_parcellate_surfaces_wf(files_to_parcellate, name="parcellate_surfaces_w mem_gb=1, iterfield=["segmentation", "in_file"], ) - ds_parcellated_surface.inputs.segmentation = selected_atlases - workflow.connect([ - (inputnode, ds_parcellated_surface, [(file_to_parcellate, "source_file")]), + (inputnode, ds_parcellated_surface, [ + (file_to_parcellate, "source_file"), + ("atlas_names", "segmentation"), + ]), (parcellate_surface_wf, ds_parcellated_surface, [ ("outputnode.parcellated_tsv", "in_file"), ]), diff --git a/xcp_d/workflows/anatomical/volume.py b/xcp_d/workflows/anatomical/volume.py index 2260265c3..e9137ec2e 100644 --- a/xcp_d/workflows/anatomical/volume.py +++ b/xcp_d/workflows/anatomical/volume.py @@ -148,7 +148,10 @@ def init_postprocess_anat_wf( else: out = ["T1w"] if t1w_available else [] + ["T2w"] if t2w_available else [] - workflow.__desc__ = f"""\ + workflow.__desc__ = f""" + +#### Anatomical data + Native-space {list_to_str(out)} images were transformed to {target_space} space at 1 mm3 resolution. """ diff --git a/xcp_d/workflows/base.py b/xcp_d/workflows/base.py index 3de5d6d14..7294dca9f 100644 --- a/xcp_d/workflows/base.py +++ b/xcp_d/workflows/base.py @@ -494,6 +494,7 @@ def init_single_subject_wf(subject_id: str): if config.execution.atlases: workflow.connect([ (load_atlases_wf, postprocess_bold_wf, [ + ("outputnode.atlas_names", "inputnode.atlases"), ("outputnode.atlas_files", "inputnode.atlas_files"), ("outputnode.atlas_labels_files", "inputnode.atlas_labels_files"), ]), diff --git a/xcp_d/workflows/bold/cifti.py b/xcp_d/workflows/bold/cifti.py index 03bb716e4..cac45e074 100644 --- a/xcp_d/workflows/bold/cifti.py +++ b/xcp_d/workflows/bold/cifti.py @@ -132,7 +132,6 @@ def init_postprocess_cifti_wf( bandpass_filter = config.workflow.bandpass_filter dummy_scans = config.workflow.dummy_scans despike = config.workflow.despike - atlases = config.execution.atlases TR = run_data["bold_metadata"]["RepetitionTime"] @@ -166,11 +165,11 @@ def init_postprocess_cifti_wf( inputnode.inputs.motion_json = run_data["motion_json"] inputnode.inputs.confounds_files = run_data["confounds"] inputnode.inputs.dummy_scans = dummy_scans - inputnode.inputs.atlases = atlases workflow = Workflow(name=name) - workflow.__desc__ = f"""\ + workflow.__desc__ = f""" +#### Functional data For each of the {num2words(n_runs)} BOLD runs found per subject (across all tasks and sessions), the following post-processing was performed. @@ -324,6 +323,7 @@ def init_postprocess_cifti_wf( (inputnode, postproc_derivatives_wf, [ ("motion_file", "inputnode.preproc_confounds_file"), ("atlas_files", "inputnode.atlas_files"), + ("atlases", "inputnode.atlas_names"), ]), (denoise_bold_wf, postproc_derivatives_wf, [ ("outputnode.denoised_bold", "inputnode.denoised_bold"), @@ -357,7 +357,7 @@ def init_postprocess_cifti_wf( ]), ]) # fmt:skip - if atlases: + if config.execution.atlases: connectivity_wf = init_functional_connectivity_cifti_wf( mem_gb=mem_gbx, exact_scans=exact_scans, diff --git a/xcp_d/workflows/bold/connectivity.py b/xcp_d/workflows/bold/connectivity.py index b51f2e087..9d5db3638 100644 --- a/xcp_d/workflows/bold/connectivity.py +++ b/xcp_d/workflows/bold/connectivity.py @@ -10,7 +10,6 @@ from xcp_d import config from xcp_d.interfaces.bids import DerivativesDataSink from xcp_d.utils.atlas import select_atlases -from xcp_d.utils.boilerplate import describe_atlases from xcp_d.utils.doc import fill_doc from xcp_d.workflows.parcellation import init_parcellate_cifti_wf @@ -72,11 +71,9 @@ def init_functional_connectivity_nifti_wf(mem_gb, name="connectivity_wf"): bandpass_filter = config.workflow.bandpass_filter min_coverage = config.workflow.min_coverage - atlas_str = describe_atlases(config.execution.atlases) - workflow.__desc__ = f""" Processed functional timeseries were extracted from the residual BOLD signal -with *Nilearn's* *NiftiLabelsMasker* for the following atlases: {atlas_str}. +with *Nilearn's* *NiftiLabelsMasker* for the atlases. Corresponding pair-wise functional connectivity between all regions was computed for each atlas, which was operationalized as the Pearson's correlation of each parcel's unsmoothed timeseries. In cases of partial coverage, uncovered voxels (values of all zeros or NaNs) were either @@ -281,11 +278,9 @@ def init_functional_connectivity_cifti_wf(mem_gb, exact_scans, name="connectivit bandpass_filter = config.workflow.bandpass_filter min_coverage = config.workflow.min_coverage - atlas_str = describe_atlases(config.execution.atlases) - workflow.__desc__ = f""" Processed functional timeseries were extracted from residual BOLD using -Connectome Workbench [@marcus2011informatics] for the following atlases: {atlas_str}. +Connectome Workbench [@marcus2011informatics] for the atlases. Corresponding pair-wise functional connectivity between all regions was computed for each atlas, which was operationalized as the Pearson's correlation of each parcel's unsmoothed timeseries with the Connectome Workbench. diff --git a/xcp_d/workflows/bold/nifti.py b/xcp_d/workflows/bold/nifti.py index 430ed84b9..f64b9e94e 100644 --- a/xcp_d/workflows/bold/nifti.py +++ b/xcp_d/workflows/bold/nifti.py @@ -143,7 +143,6 @@ def init_postprocess_nifti_wf( bandpass_filter = config.workflow.bandpass_filter dummy_scans = config.workflow.dummy_scans despike = config.workflow.despike - atlases = config.execution.atlases TR = run_data["bold_metadata"]["RepetitionTime"] @@ -179,11 +178,11 @@ def init_postprocess_nifti_wf( inputnode.inputs.motion_json = run_data["motion_json"] inputnode.inputs.confounds_files = run_data["confounds"] inputnode.inputs.dummy_scans = dummy_scans - inputnode.inputs.atlases = atlases # Load confounds according to the config - workflow.__desc__ = f"""\ + workflow.__desc__ = f""" +#### Functional data For each of the {num2words(n_runs)} BOLD runs found per subject (across all tasks and sessions), the following post-processing was performed. @@ -344,6 +343,7 @@ def init_postprocess_nifti_wf( (inputnode, postproc_derivatives_wf, [ ("motion_file", "inputnode.preproc_confounds_file"), ("atlas_files", "inputnode.atlas_files"), + ("atlases", "inputnode.atlas_names"), ]), (prepare_confounds_wf, postproc_derivatives_wf, [ ("outputnode.confounds_tsv", "inputnode.confounds_tsv"), @@ -376,7 +376,7 @@ def init_postprocess_nifti_wf( ]), ]) # fmt:skip - if atlases: + if config.execution.atlases: connectivity_wf = init_functional_connectivity_nifti_wf(mem_gb=mem_gbx) workflow.connect([ diff --git a/xcp_d/workflows/bold/outputs.py b/xcp_d/workflows/bold/outputs.py index 4be169810..27505e734 100644 --- a/xcp_d/workflows/bold/outputs.py +++ b/xcp_d/workflows/bold/outputs.py @@ -90,7 +90,6 @@ def init_postproc_derivatives_wf( bpf_order = config.workflow.bpf_order fd_thresh = config.workflow.fd_thresh smoothing = config.workflow.smoothing - atlases = config.execution.atlases file_format = config.workflow.file_format output_dir = config.execution.output_dir @@ -125,6 +124,8 @@ def init_postproc_derivatives_wf( "timeseries_ciftis", "correlation_ciftis", "correlation_ciftis_exact", + # info for filenames + "atlas_names", ], ), name="inputnode", @@ -343,7 +344,7 @@ def init_postproc_derivatives_wf( ]) # fmt:skip # Connectivity workflow outputs - if atlases: + if config.execution.atlases: make_atlas_dict = pe.MapNode( niu.Function( function=_make_dictionary, @@ -395,9 +396,11 @@ def init_postproc_derivatives_wf( mem_gb=1, iterfield=["segmentation", "in_file", "meta_dict"], ) - ds_coverage.inputs.segmentation = atlases workflow.connect([ - (inputnode, ds_coverage, [("coverage", "in_file")]), + (inputnode, ds_coverage, [ + ("atlas_names", "segmentation"), + ("coverage", "in_file"), + ]), (make_atlas_dict, ds_coverage, [("metadata", "meta_dict")]), ]) # fmt:skip @@ -435,9 +438,11 @@ def init_postproc_derivatives_wf( mem_gb=1, iterfield=["segmentation", "in_file", "meta_dict"], ) - ds_timeseries.inputs.segmentation = atlases workflow.connect([ - (inputnode, ds_timeseries, [("timeseries", "in_file")]), + (inputnode, ds_timeseries, [ + ("atlas_names", "segmentation"), + ("timeseries", "in_file"), + ]), (add_coverage_to_src, ds_timeseries, [("metadata", "meta_dict")]), (ds_timeseries, outputnode, [("out_file", "timeseries")]), ]) # fmt:skip @@ -483,9 +488,11 @@ def init_postproc_derivatives_wf( mem_gb=1, iterfield=["segmentation", "in_file", "meta_dict"], ) - ds_correlations.inputs.segmentation = atlases workflow.connect([ - (inputnode, ds_correlations, [("correlations", "in_file")]), + (inputnode, ds_correlations, [ + ("atlas_names", "segmentation"), + ("correlations", "in_file"), + ]), (make_corrs_meta_dict, ds_correlations, [("metadata", "meta_dict")]), ]) # fmt:skip @@ -505,9 +512,11 @@ def init_postproc_derivatives_wf( mem_gb=1, iterfield=["segmentation", "in_file", "meta_dict"], ) - ds_coverage_ciftis.inputs.segmentation = atlases workflow.connect([ - (inputnode, ds_coverage_ciftis, [("coverage_ciftis", "in_file")]), + (inputnode, ds_coverage_ciftis, [ + ("atlas_names", "segmentation"), + ("coverage_ciftis", "in_file"), + ]), (add_denoised_to_src, ds_coverage_ciftis, [("metadata", "meta_dict")]), ]) # fmt:skip @@ -545,9 +554,11 @@ def init_postproc_derivatives_wf( mem_gb=1, iterfield=["segmentation", "in_file", "meta_dict"], ) - ds_timeseries_ciftis.inputs.segmentation = atlases workflow.connect([ - (inputnode, ds_timeseries_ciftis, [("timeseries_ciftis", "in_file")]), + (inputnode, ds_timeseries_ciftis, [ + ("atlas_names", "segmentation"), + ("timeseries_ciftis", "in_file"), + ]), (add_ccoverage_to_src, ds_timeseries_ciftis, [("metadata", "meta_dict")]), (ds_timeseries_ciftis, outputnode, [("out_file", "timeseries_ciftis")]), ]) # fmt:skip @@ -595,9 +606,9 @@ def init_postproc_derivatives_wf( mem_gb=1, iterfield=["segmentation", "in_file", "meta_dict"], ) - ds_correlation_ciftis.inputs.segmentation = atlases workflow.connect([ (inputnode, ds_correlation_ciftis, [ + ("atlas_names", "segmentation"), ("correlation_ciftis", "in_file"), ]), (make_ccorrs_meta_dict, ds_correlation_ciftis, [("metadata", "meta_dict")]), @@ -628,8 +639,8 @@ def init_postproc_derivatives_wf( mem_gb=1, iterfield=["segmentation", "in_file"], ) - ds_correlations_exact.inputs.segmentation = atlases workflow.connect([ + (inputnode, ds_correlations_exact, [("atlas_names", "segmentation")]), (select_exact_scan_files, ds_correlations_exact, [("out", "in_file")]), ]) # fmt:skip @@ -657,7 +668,7 @@ def init_postproc_derivatives_wf( (ds_denoised_bold, ds_reho, [(("out_file", _make_xcpd_uri, output_dir), "Sources")]), ]) # fmt:skip - if atlases: + if config.execution.atlases: add_reho_to_src = pe.MapNode( niu.Function( function=_make_dictionary, @@ -691,9 +702,11 @@ def init_postproc_derivatives_wf( mem_gb=1, iterfield=["segmentation", "in_file", "meta_dict"], ) - ds_parcellated_reho.inputs.segmentation = atlases workflow.connect([ - (inputnode, ds_parcellated_reho, [("parcellated_reho", "in_file")]), + (inputnode, ds_parcellated_reho, [ + ("atlas_names", "segmentation"), + ("parcellated_reho", "in_file"), + ]), (add_reho_to_src, ds_parcellated_reho, [("metadata", "meta_dict")]), ]) # fmt:skip @@ -747,7 +760,7 @@ def init_postproc_derivatives_wf( ]), ]) # fmt:skip - if atlases: + if config.execution.atlases: add_alff_to_src = pe.MapNode( niu.Function( function=_make_dictionary, @@ -780,9 +793,11 @@ def init_postproc_derivatives_wf( mem_gb=1, iterfield=["segmentation", "in_file", "meta_dict"], ) - ds_parcellated_alff.inputs.segmentation = atlases workflow.connect([ - (inputnode, ds_parcellated_alff, [("parcellated_alff", "in_file")]), + (inputnode, ds_parcellated_alff, [ + ("atlas_names", "segmentation"), + ("parcellated_alff", "in_file"), + ]), (add_alff_to_src, ds_parcellated_alff, [("metadata", "meta_dict")]), ]) # fmt:skip diff --git a/xcp_d/workflows/bold/plotting.py b/xcp_d/workflows/bold/plotting.py index c45d7ebff..6464a1ceb 100644 --- a/xcp_d/workflows/bold/plotting.py +++ b/xcp_d/workflows/bold/plotting.py @@ -213,16 +213,17 @@ def init_qc_report_wf( ]) # fmt:skip # NIFTI files require a tissue-type segmentation in the same space as the BOLD data. - # Get the set of transforms from MNI152NLin6Asym (the dseg) to the BOLD space. - # Given that XCP-D doesn't process native-space data, this transform will never be used. + # Get the set of transforms from MNI152NLin2009cAsym (the dseg) to the BOLD space. get_mni_to_bold_xfms = pe.Node( Function( - input_names=["bold_file"], - output_names=["transform_list"], + input_names=["bold_file", "source_file", "source_space"], + output_names=["transforms"], function=get_std2bold_xfms, ), name="get_std2native_transform", ) + get_mni_to_bold_xfms.inputs.source_file = None + get_mni_to_bold_xfms.inputs.source_space = "MNI152NLin2009cAsym" workflow.connect([(inputnode, get_mni_to_bold_xfms, [("name_source", "bold_file")])]) # Use MNI152NLin2009cAsym tissue-type segmentation file for carpet plots. @@ -236,29 +237,6 @@ def init_qc_report_wf( ) ) - # Get MNI152NLin2009cAsym --> MNI152NLin6Asym xform. - MNI152NLin2009cAsym_to_MNI152NLin6Asym = str( - get_template( - template="MNI152NLin6Asym", - mode="image", - suffix="xfm", - extension=".h5", - **{"from": "MNI152NLin2009cAsym"}, - ), - ) - - # Add the MNI152NLin2009cAsym --> MNI152NLin6Asym xform to the end of the - # BOLD --> MNI152NLin6Asym xform list, because xforms are applied in reverse order. - add_xfm_to_nlin6asym = pe.Node( - niu.Merge(2), - name="add_xfm_to_nlin6asym", - ) - add_xfm_to_nlin6asym.inputs.in2 = MNI152NLin2009cAsym_to_MNI152NLin6Asym - - workflow.connect([ - (get_mni_to_bold_xfms, add_xfm_to_nlin6asym, [("transform_list", "in1")]), - ]) # fmt:skip - # Transform MNI152NLin2009cAsym dseg file to the same space as the BOLD data. warp_dseg_to_bold = pe.Node( ApplyTransforms( @@ -273,7 +251,7 @@ def init_qc_report_wf( ) workflow.connect([ (inputnode, warp_dseg_to_bold, [("boldref", "reference_image")]), - (add_xfm_to_nlin6asym, warp_dseg_to_bold, [("out", "transforms")]), + (get_mni_to_bold_xfms, warp_dseg_to_bold, [("transforms", "transforms")]), ]) # fmt:skip if config.workflow.linc_qc: diff --git a/xcp_d/workflows/parcellation.py b/xcp_d/workflows/parcellation.py index 794e95183..3e6604358 100644 --- a/xcp_d/workflows/parcellation.py +++ b/xcp_d/workflows/parcellation.py @@ -10,7 +10,6 @@ from xcp_d import config from xcp_d.interfaces.ants import ApplyTransforms from xcp_d.interfaces.nilearn import IndexImage -from xcp_d.utils.atlas import get_atlas_cifti, get_atlas_nifti from xcp_d.utils.doc import fill_doc from xcp_d.utils.utils import get_std2bold_xfms @@ -49,57 +48,96 @@ def init_load_atlases_wf(name="load_atlases_wf"): atlas_labels_files """ from xcp_d.interfaces.bids import CopyAtlas + from xcp_d.utils.atlas import collect_atlases + from xcp_d.utils.boilerplate import describe_atlases workflow = Workflow(name=name) - atlases = config.execution.atlases output_dir = config.execution.output_dir - file_format = config.workflow.file_format + + atlases = collect_atlases( + datasets=config.execution.datasets, + atlases=config.execution.atlases, + file_format=config.workflow.file_format, + bids_filters=config.execution.bids_filters, + ) + + # Reorganize the atlas file information + atlas_names, atlas_files, atlas_labels_files, atlas_metadata = [], [], [], [] + atlas_datasets = [] + for atlas, atlas_dict in atlases.items(): + config.loggers.workflow.info(f"Loading atlas: {atlas}") + atlas_names.append(atlas) + atlas_datasets.append(atlas_dict["dataset"]) + atlas_files.append(atlas_dict["image"]) + atlas_labels_files.append(atlas_dict["labels"]) + atlas_metadata.append(atlas_dict["metadata"]) + + # Write a description + atlas_str = describe_atlases(atlas_names) + workflow.__desc__ = f""" +#### Segmentations + +The following atlases were used in the workflow: {atlas_str}. +""" inputnode = pe.Node( niu.IdentityInterface( fields=[ "name_source", "bold_file", + "atlas_names", + "atlas_datasets", + "atlas_files", + "atlas_labels_files", + "atlas_metadata", ], ), name="inputnode", ) + inputnode.inputs.atlas_names = atlas_names + inputnode.inputs.atlas_datasets = atlas_datasets + inputnode.inputs.atlas_files = atlas_files + inputnode.inputs.atlas_labels_files = atlas_labels_files + inputnode.inputs.atlas_metadata = atlas_metadata + outputnode = pe.Node( niu.IdentityInterface( fields=[ + "atlas_names", "atlas_files", "atlas_labels_files", ], ), name="outputnode", ) + workflow.connect([(inputnode, outputnode, [("atlas_names", "atlas_names")])]) - # get atlases via load_data - atlas_file_grabber = pe.MapNode( - Function( - input_names=["atlas"], - output_names=["atlas_file", "atlas_labels_file", "atlas_metadata_file"], - function=get_atlas_cifti if file_format == "cifti" else get_atlas_nifti, + atlas_buffer = pe.Node( + niu.IdentityInterface( + fields=["atlas_file"], ), - name="atlas_file_grabber", - iterfield=["atlas"], + name="atlas_buffer", ) - atlas_file_grabber.inputs.atlas = atlases - atlas_buffer = pe.Node(niu.IdentityInterface(fields=["atlas_file"]), name="atlas_buffer") - - if file_format == "nifti": - get_transforms_to_bold_space = pe.Node( + if config.workflow.file_format == "nifti": + workflow.__desc__ += ( + " Each atlas was warped to the same space and resolution as the BOLD file." + ) + get_xfms_to_bold_space = pe.MapNode( Function( - input_names=["bold_file"], - output_names=["transformfile"], + input_names=["bold_file", "source_file", "source_space"], + output_names=["transforms"], function=get_std2bold_xfms, ), - name="get_transforms_to_bold_space", + name="get_xfms_to_bold_space", + iterfield=["source_file"], ) workflow.connect([ - (inputnode, get_transforms_to_bold_space, [("name_source", "bold_file")]), + (inputnode, get_xfms_to_bold_space, [ + ("bold_file", "bold_file"), + ("atlas_files", "source_file"), + ]), ]) # fmt:skip # ApplyTransforms needs a 3D image for the reference image. @@ -107,7 +145,6 @@ def init_load_atlases_wf(name="load_atlases_wf"): IndexImage(index=0), name="grab_first_volume", ) - workflow.connect([(inputnode, grab_first_volume, [("bold_file", "in_file")])]) # Using the generated transforms, apply them to get everything in the correct MNI form @@ -119,33 +156,33 @@ def init_load_atlases_wf(name="load_atlases_wf"): num_threads=config.nipype.omp_nthreads, ), name="warp_atlases_to_bold_space", - iterfield=["input_image"], + iterfield=["input_image", "transforms"], mem_gb=2, n_procs=config.nipype.omp_nthreads, ) workflow.connect([ + (inputnode, warp_atlases_to_bold_space, [("atlas_files", "input_image")]), (grab_first_volume, warp_atlases_to_bold_space, [("out_file", "reference_image")]), - (atlas_file_grabber, warp_atlases_to_bold_space, [("atlas_file", "input_image")]), - (get_transforms_to_bold_space, warp_atlases_to_bold_space, [ - ("transformfile", "transforms"), - ]), + (get_xfms_to_bold_space, warp_atlases_to_bold_space, [("transforms", "transforms")]), (warp_atlases_to_bold_space, atlas_buffer, [("output_image", "atlas_file")]), ]) # fmt:skip else: - workflow.connect([(atlas_file_grabber, atlas_buffer, [("atlas_file", "atlas_file")])]) + workflow.connect([(inputnode, atlas_buffer, [("atlas_files", "atlas_file")])]) copy_atlas = pe.MapNode( CopyAtlas(output_dir=output_dir), name="copy_atlas", - iterfield=["in_file", "atlas"], + iterfield=["in_file", "atlas", "meta_dict"], run_without_submitting=True, ) - copy_atlas.inputs.atlas = atlases - workflow.connect([ - (inputnode, copy_atlas, [("name_source", "name_source")]), + (inputnode, copy_atlas, [ + ("name_source", "name_source"), + ("atlas_names", "atlas"), + ("atlas_metadata", "meta_dict"), + ]), (atlas_buffer, copy_atlas, [("atlas_file", "in_file")]), (copy_atlas, outputnode, [("out_file", "atlas_files")]), ]) # fmt:skip @@ -156,27 +193,15 @@ def init_load_atlases_wf(name="load_atlases_wf"): iterfield=["in_file", "atlas"], run_without_submitting=True, ) - copy_atlas_labels_file.inputs.atlas = atlases - workflow.connect([ - (inputnode, copy_atlas_labels_file, [("name_source", "name_source")]), - (atlas_file_grabber, copy_atlas_labels_file, [("atlas_labels_file", "in_file")]), + (inputnode, copy_atlas_labels_file, [ + ("name_source", "name_source"), + ("atlas_names", "atlas"), + ("atlas_labels_files", "in_file"), + ]), (copy_atlas_labels_file, outputnode, [("out_file", "atlas_labels_files")]), ]) # fmt:skip - copy_atlas_metadata = pe.MapNode( - CopyAtlas(output_dir=output_dir), - name="copy_atlas_metadata", - iterfield=["in_file", "atlas"], - run_without_submitting=True, - ) - copy_atlas_metadata.inputs.atlas = atlases - - workflow.connect([ - (inputnode, copy_atlas_metadata, [("name_source", "name_source")]), - (atlas_file_grabber, copy_atlas_metadata, [("atlas_metadata_file", "in_file")]), - ]) # fmt:skip - return workflow