diff --git a/README.md b/README.md index 1dd2559e..190cd879 100644 --- a/README.md +++ b/README.md @@ -8,36 +8,27 @@ > [!WARNING] > This software is under active development and not yet intended for production use. APIs, outputs, and behavior may change without notice. Use at your own risk. -Reference implementation of the [Reproducible Brain Charts (RBC)](https://doi.org/10.1016/j.neuron.2024.08.026) preprocessing protocol for structural and functional MRI. Built on [NiWrap](https://github.com/styx-api/niwrap). +Reference implementation of the [Reproducible Brain Charts (RBC)](https://reprobrainchart.github.io/) preprocessing protocol for structural and functional MRI, built on [NiWrap](https://github.com/styx-api/niwrap). Handles brain extraction, tissue segmentation, registration, motion correction, nuisance regression, and resting-state metrics, with optional longitudinal (multi-session) support. See [Shafiei et al. (2025)](https://doi.org/10.1016/j.neuron.2024.08.026) for the full protocol description.

RBC pipeline flow

-## Installation - -```bash -pip install git+https://github.com/childmindresearch/rbc.git -``` - -Requires Python 3.12+. Neuroimaging tools (AFNI, FSL, ANTs) are needed at runtime. Pass `--runner docker` to pull and run them automatically via containers. See the [NiWrap docs](https://github.com/styx-api/niwrap) for runner configuration. - ## Quick start -```bash -# Usage: rbc {workflow} INPUT_DIR [INPUT_DIR ...] -o OUTPUT_DIR [options] +Input must be a [BIDS-organized](https://bids-specification.readthedocs.io/) dataset. Neuroimaging tools (AFNI, FSL, ANTs, FreeSurfer) run automatically via Docker by default. -# Run the full pipeline -rbc all /data -o /data/derivatives --runner docker +```bash +pip install git+https://github.com/childmindresearch/rbc.git -# Or run a single stage for specific subjects -rbc functional /data -o /data/derivatives --task rest --participant-label 01 02 --runner docker +# Run the full cross-sectional pipeline +rbc all /data -o /data/derivatives -# Multiple input directories (e.g., raw BIDS + prior derivatives) -rbc functional /data /data/derivatives -o /data/derivatives --runner docker +# Run a single stage for specific subjects +rbc functional /data -o /data/derivatives --task rest --participant-label 01 02 ``` -Run any command with `--help` for full options. +Run any command with `--help` for full options (e.g., `rbc functional --help`). Requires Python 3.12+. Pass `--runner docker` explicitly if auto-detection doesn't find your container runtime, or see the [NiWrap docs](https://github.com/styx-api/niwrap) for other runners (Podman, Singularity, local installs). ## Workflows @@ -48,75 +39,46 @@ Run any command with `--help` for full options. | `rbc metrics` | ALFF/fALFF, ReHo, smoothing, z-scoring, atlas-based timeseries and correlation matrices | | `rbc qc` | XCP-D format quality metrics, framewise displacement, DVARS, RBC pass/fail thresholds | | `rbc all` | Runs all four stages in sequence, passing results in memory between stages | -| `rbc longitudinal …` | Multi-session workflows: `template`, `anatomical`, `functional`, `metrics`, `qc`, `all` | -Workflows must be run in order: `anatomical` → `functional` → `metrics` / `qc`. The `all` command handles this automatically. +Stages must be run in order: `anatomical` -> `functional` -> `metrics` / `qc`. The `all` command handles this automatically. -Longitudinal workflows consume cross-sectional derivatives. Typical flow: +Multiple input directories are supported when raw data and derivatives live in separate trees: ```bash -rbc all /data -o /data/derivatives --runner docker -rbc longitudinal template /data/derivatives -o /data/derivatives --runner docker -rbc longitudinal anatomical /data/derivatives -o /data/derivatives --runner docker +rbc functional /data /pipelines/rbc -o /pipelines/rbc ``` -`rbc long` is an alias for `rbc longitudinal`. The `metrics`, `qc`, and `all` -longitudinal stages are registered but raise `NotImplementedError` until -Stage 6 of the longitudinal refactor lands (tracker: #301). - -## Outputs - -See the [data dictionary](docs/data_dictionary.md) for a complete description of every output file, including format details and the processing step that produces each one. +### Longitudinal -
-Example BIDS derivative tree +For multi-session datasets, longitudinal workflows build a within-subject template and reprocess derivatives in that common space. Run the cross-sectional pipeline first: -``` -derivatives/rbc/ - sub-01/ - ses-01/ - anat/ - sub-01_ses-01_desc-brain_T1w.nii.gz - sub-01_ses-01_desc-T1w_mask.nii.gz - sub-01_ses-01_desc-{csf,gm,wm}_mask.nii.gz - sub-01_ses-01_from-T1w_to-template_mode-image_xfm.nii.gz - sub-01_ses-01_from-template_to-T1w_mode-image_xfm.nii.gz - func/ - sub-01_ses-01_task-rest_desc-preproc_bold.nii.gz - sub-01_ses-01_task-rest_space-MNI152NLin6ASym_desc-preproc_bold.nii.gz - sub-01_ses-01_task-rest_space-MNI152NLin6ASym_reg-36parameter_desc-preproc_bold.nii.gz - sub-01_ses-01_task-rest_desc-motionParams_motion.1D - sub-01_ses-01_task-rest_space-MNI152NLin6ASym_reg-36parameter_desc-xcp_quality.tsv - sub-01_ses-01_task-rest_space-MNI152NLin6ASym_reg-36parameter_alff.nii.gz - sub-01_ses-01_task-rest_space-MNI152NLin6ASym_reg-36parameter_reho.nii.gz - sub-01_ses-01_task-rest_space-MNI152NLin6ASym_atlas-schaefer200_reg-36parameter_desc-mean_timeseries.tsv - sub-01_ses-01_task-rest_space-MNI152NLin6ASym_atlas-schaefer200_reg-36parameter_desc-pearson_correlations.tsv +```bash +rbc all /data -o /data/derivatives +rbc longitudinal all /data/derivatives -o /data/derivatives ``` -
+`rbc long` is an alias for `rbc longitudinal`. -## Testing +
+Individual longitudinal stages ```bash -# Unit tests (fast, no runner needed) -uv run pytest -m unit - -# Integration tests (requires Docker) -uv run pytest -m "integration and not slow" --runner docker - -# Full pipeline (~30+ min) -uv run pytest -m full_pipeline --runner docker +rbc longitudinal template /data/derivatives -o /data/derivatives +rbc longitudinal anatomical /data/derivatives -o /data/derivatives +rbc longitudinal functional /data/derivatives -o /data/derivatives --regressor 36-parameter +rbc longitudinal metrics /data/derivatives -o /data/derivatives --atlas schaefer_200 +rbc longitudinal qc /data/derivatives -o /data/derivatives ``` -See [tests/README.md](tests/README.md) for the full testing strategy. +
-## Contributing +## Outputs -```bash -uv sync && uv run pre-commit install -``` +See the [data dictionary](docs/data_dictionary.md) for a complete description of every output file. -See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. +

+ RBC output tree +

## Citation @@ -136,20 +98,22 @@ If you use this pipeline, please cite: } ``` -## About RBC +## Development -[Reproducible Brain Charts (RBC)](https://reprobrainchart.github.io/) is an open resource integrating data from 5 large studies of brain development in youth from three continents (N = 6,346). The resource provides: +```bash +uv sync && uv run pre-commit install +``` -- Harmonized psychiatric phenotypes using bifactor models -- Quality-assured neuroimaging data processed with consistent pipelines -- All data openly shared via the International Neuroimaging Data-sharing Initiative (INDI) +```bash +uv run pytest -m unit # fast, no runner needed +uv run pytest -m "integration and not slow" # integration tests +uv run pytest -m full_pipeline # full pipeline (~30+ min) +``` -RBC facilitates large-scale, reproducible, and generalizable research in developmental and psychiatric neuroscience. The RBC pipeline was developed originally in the [Configurable Pipeline for the Analysis of Connectomes](https://github.com/FCP-INDI/C-PAC/), and has been remade here using NiWrap to increase readability, portability, and runtime efficiency. +See [tests/README.md](tests/README.md) for the full testing strategy and [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. ## License -[MIT License](LICENSE) - -## Acknowledgments +[LGPL-3.0-or-later](LICENSE) -This implementation is based on the RBC protocol described in Shafiei et al. (2025) and originally implemented in [C-PAC](https://fcp-indi.github.io/). Development is supported by the [Child Mind Institute](https://childmind.org). +This implementation is based on the RBC protocol originally implemented in [C-PAC](https://fcp-indi.github.io/). Development is supported by the [Child Mind Institute](https://childmind.org). All data are openly shared via the [International Neuroimaging Data-sharing Initiative (INDI)](https://fcon_1000.projects.nitrc.org/). diff --git a/docs/data_dictionary.md b/docs/data_dictionary.md index 080764f1..dd4ba726 100644 --- a/docs/data_dictionary.md +++ b/docs/data_dictionary.md @@ -37,6 +37,7 @@ Produced by `rbc anatomical`. These are structural (T1-weighted) processing resu | `*_desc-wmBBR_mask.nii.gz` | `mask` | White matter boundary used for boundary-based registration (BBR) of functional data to anatomy | FSL WM boundary extraction | 3D NIfTI, binary mask | | `*_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.nii.gz` | `xfm` | Nonlinear warp field mapping subject anatomy to MNI152NLin6Asym template space | ANTs registration | 3D NIfTI, displacement field | | `*_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.nii.gz` | `xfm` | Inverse warp field mapping MNI152NLin6Asym template space back to subject anatomy | ANTs registration | 3D NIfTI, displacement field | +| `*_space-MNI152NLin6Asym_desc-brain_T1w.nii.gz` | `T1w` | Skull-stripped brain image warped to MNI152NLin6Asym template space | ANTs resampling | 3D NIfTI | --- @@ -52,10 +53,12 @@ Produced by `rbc functional`. These are functional MRI (BOLD) processing results | `*_desc-relsDisplacement_motion.rms` | `motion` | Frame-to-frame relative root-mean-square displacement over time | FSL MCFLIRT | Text, single-column RMS file | | `*_desc-maxDisplacement_motion.rms` | `motion` | Absolute root-mean-square displacement of each volume relative to the reference | FSL MCFLIRT | Text, single-column RMS file | | `*_desc-brain_mask.nii.gz` | `mask` | Binary brain mask in native BOLD space | FSL BET | 3D NIfTI, binary mask | -| `*_from-bold_to-T1w_mode-image_desc-linear_xfm.mat` | `xfm` | Affine transformation matrix aligning BOLD to the T1w anatomical image | ANTs boundary-based registration | 4x4 affine matrix | +| `*_from-bold_to-T1w_mode-image_desc-linear_xfm.mat` | `xfm` | Affine transformation matrix aligning BOLD to the T1w anatomical image (FSL format) | ANTs boundary-based registration | 4x4 affine matrix | +| `*_from-bold_to-T1w_mode-image_desc-linearITK_xfm.txt` | `xfm` | Same BOLD-to-T1w affine in ITK format, used by ANTs for composing longitudinal transforms | Converted from FSL via `rbc.core.fsl2itk` | ITK affine text | | `*_space-MNI152NLin6Asym_desc-preproc_bold.nii.gz` | `bold` | BOLD timeseries resampled to MNI152NLin6Asym template space in a single interpolation step (before denoising) | ANTs resampling | 4D NIfTI | | `*_space-MNI152NLin6Asym_desc-bold_mask.nii.gz` | `mask` | Brain mask warped to template space at the BOLD resolution | ANTs resampling | 3D NIfTI, binary mask | -| `*_space-MNI152NLin6Asym_reg-{regressor}_desc-preproc_bold.nii.gz` | `bold` | Denoised BOLD timeseries in template space after nuisance regression and bandpass filtering. `{regressor}` is `36parameter` or `aCompCor` | Nuisance regression | 4D NIfTI | +| `*_space-MNI152NLin6Asym_reg-{regressor}_desc-regressed_bold.nii.gz` | `bold` | Nuisance-regressed BOLD in template space (no bandpass filtering). `{regressor}` is `36parameter` or `aCompCor` | AFNI 3dTproject | 4D NIfTI | +| `*_space-MNI152NLin6Asym_reg-{regressor}_desc-preproc_bold.nii.gz` | `bold` | Denoised BOLD timeseries in template space after nuisance regression and bandpass filtering. `{regressor}` is `36parameter` or `aCompCor` | AFNI 3dTproject -bandpass | 4D NIfTI | | `*_desc-{regressor}_regressors.1D` | `regressors` | Raw (unfiltered) nuisance regressor matrix. `{regressor}` is `36parameter` or `aCompCor`. Carried forward for longitudinal regression reuse | Computed from motion parameters and tissue masks | Text, multi-column 1D file | | `*_desc-{regressor}Filtered_regressors.1D` | `regressors` | Bandpass-filtered nuisance regressor matrix matching what `3dTproject -bandpass` applied. For provenance only | FFT-based bandpass filter | Text, multi-column 1D file | @@ -126,17 +129,77 @@ Produced by `rbc qc`. A single summary file per functional run containing qualit ## Longitudinal outputs -Produced by the `rbc longitudinal` subcommand group (`template`, `anatomical`, `functional`, `metrics`, `qc`, `all`). Anatomical outputs aligned to a subject-specific longitudinal template built from multiple sessions. Note: longitudinal metrics, QC, and the combined `all` stage are not yet implemented (tracker: #301). - -| File | Suffix | Description | Created by | Format | -| -------------------------------------------------- | ------ | ------------------------------------------------------------------------- | ------------------------------------------ | ---------------------------- | -| `*_space-longitudinal_desc-brain_T1w.nii.gz` | `T1w` | Skull-stripped brain image aligned to the subject's longitudinal template | ANTs registration to longitudinal template | 3D NIfTI | -| `*_space-longitudinal_desc-T1w_mask.nii.gz` | `mask` | Brain mask in longitudinal template space | ANTs registration to longitudinal template | 3D NIfTI, binary mask | -| `*_from-T1w_to-longitudinal_mode-image_xfm.nii.gz` | `xfm` | Warp field mapping subject anatomy to the longitudinal template | ANTs registration | 3D NIfTI, displacement field | -| `*_from-longitudinal_to-T1w_mode-image_xfm.nii.gz` | `xfm` | Inverse warp field mapping longitudinal template back to subject anatomy | ANTs registration | 3D NIfTI, displacement field | -| `*_space-longitudinal_sbref.nii.gz` | `sbref` | Motion reference volume warped to longitudinal template space | ANTs warping (composed BOLD-to-longitudinal) | 3D NIfTI | -| `*_space-longitudinal_desc-preproc_bold.nii.gz` | `bold` | Preprocessed BOLD warped to longitudinal template space | ANTs warping (composed BOLD-to-longitudinal) | 4D NIfTI | -| `*_space-longitudinal_desc-brain_mask.nii.gz` | `mask` | BOLD brain mask in longitudinal template space | ANTs warping (nearest-neighbor) | 3D NIfTI, binary mask | -| `*_from-bold_to-longitudinal_...xfm.nii.gz` | `xfm` | Composite BOLD-to-longitudinal-template warp field | ANTs compose transforms | 3D NIfTI, displacement field | -| `*_space-longitudinal_desc-regressed_reg-_bold.nii.gz` | `bold` | Nuisance-regressed BOLD (no bandpass) in longitudinal space, per regressor strategy | AFNI 3dTproject | 4D NIfTI | -| `*_space-longitudinal_desc-preproc_reg-_bold.nii.gz` | `bold` | Nuisance-regressed + bandpass-filtered BOLD in longitudinal space, per regressor strategy | AFNI 3dTproject -bandpass | 4D NIfTI | +Produced by the `rbc longitudinal` subcommand group (`template`, `anatomical`, `functional`, `metrics`, `qc`, `all`). These workflows consume cross-sectional derivatives and align them to a subject-specific longitudinal template built from multiple sessions. `rbc long` is a shorthand alias. + +### Template + +Produced by `rbc longitudinal template`. One template per subject, one transform per session. + +| File | Suffix | Description | Created by | Format | +| --- | --- | --- | --- | --- | +| `*_ses-longitudinal_T1w.nii.gz` | `T1w` | Unbiased within-subject T1w template built from all sessions | FreeSurfer `mri_robust_template` | 3D NIfTI | +| `*_ses-longitudinal_from-{ses}_to-longitudinal_mode-image_xfm.txt` | `xfm` | Affine transform mapping a single session's T1w to the longitudinal template. One file per session, identified by the `from-` entity | FreeSurfer LTA, converted to ITK via `rbc.core.fsl2itk` | ITK affine text | + +### Anatomical + +Produced by `rbc longitudinal anatomical`. + +| File | Suffix | Description | Created by | Format | +| --- | --- | --- | --- | --- | +| `*_space-longitudinal_desc-brain_T1w.nii.gz` | `T1w` | Skull-stripped brain image aligned to the subject's longitudinal template | ANTs registration to longitudinal template | 3D NIfTI | +| `*_space-longitudinal_desc-T1w_mask.nii.gz` | `mask` | Brain mask in longitudinal template space | ANTs registration to longitudinal template | 3D NIfTI, binary mask | +| `*_from-longitudinal_to-MNI152NLin6Asym_mode-image_xfm.nii.gz` | `xfm` | Warp field mapping longitudinal template space to MNI152NLin6Asym | ANTs registration | 3D NIfTI, displacement field | +| `*_from-MNI152NLin6Asym_to-longitudinal_mode-image_xfm.nii.gz` | `xfm` | Inverse warp field mapping MNI152NLin6Asym back to longitudinal template space | ANTs registration | 3D NIfTI, displacement field | + +### Functional + +Produced by `rbc longitudinal functional`. + +| File | Suffix | Description | Created by | Format | +| --- | --- | --- | --- | --- | +| `*_space-longitudinal_sbref.nii.gz` | `sbref` | Motion reference volume warped to longitudinal template space | ANTs warping (composed BOLD-to-longitudinal) | 3D NIfTI | +| `*_space-longitudinal_desc-preproc_bold.nii.gz` | `bold` | Preprocessed BOLD warped to longitudinal template space | ANTs warping (composed BOLD-to-longitudinal) | 4D NIfTI | +| `*_space-longitudinal_desc-brain_mask.nii.gz` | `mask` | BOLD brain mask in longitudinal template space | ANTs warping (nearest-neighbor) | 3D NIfTI, binary mask | +| `*_from-bold_to-longitudinal_mode-image_xfm.nii.gz` | `xfm` | Composite BOLD-to-longitudinal-template warp field | ANTs compose transforms | 3D NIfTI, displacement field | +| `*_space-longitudinal_reg-{regressor}_desc-regressed_bold.nii.gz` | `bold` | Nuisance-regressed BOLD (no bandpass) in longitudinal space, per regressor strategy | AFNI 3dTproject | 4D NIfTI | +| `*_space-longitudinal_reg-{regressor}_desc-preproc_bold.nii.gz` | `bold` | Nuisance-regressed + bandpass-filtered BOLD in longitudinal space, per regressor strategy | AFNI 3dTproject -bandpass | 4D NIfTI | + +### Metrics + +Produced by `rbc longitudinal metrics`. Identical to the cross-sectional metrics structure, but computed in `space-longitudinal` from the longitudinal-space denoised BOLD. + +| File | Suffix | Description | Created by | Format | +| --- | --- | --- | --- | --- | +| `*_space-longitudinal_reg-{regressor}_alff.nii.gz` | `alff` | Amplitude of Low-Frequency Fluctuations (0.01-0.1 Hz) | Frequency-domain analysis | 3D NIfTI | +| `*_space-longitudinal_reg-{regressor}_desc-smooth_alff.nii.gz` | `alff` | Spatially smoothed ALFF map | Gaussian kernel smoothing | 3D NIfTI | +| `*_space-longitudinal_reg-{regressor}_desc-smoothZstd_alff.nii.gz` | `alff` | Z-scored smoothed ALFF, normalized within the brain mask | Z-score normalization | 3D NIfTI | +| `*_space-longitudinal_reg-{regressor}_falff.nii.gz` | `falff` | Fractional ALFF (ratio of low-frequency to total power) | Frequency-domain analysis | 3D NIfTI | +| `*_space-longitudinal_reg-{regressor}_desc-smooth_falff.nii.gz` | `falff` | Spatially smoothed fALFF map | Gaussian kernel smoothing | 3D NIfTI | +| `*_space-longitudinal_reg-{regressor}_desc-smoothZstd_falff.nii.gz` | `falff` | Z-scored smoothed fALFF | Z-score normalization | 3D NIfTI | +| `*_space-longitudinal_reg-{regressor}_reho.nii.gz` | `reho` | Regional Homogeneity (Kendall's W, 26-voxel neighborhood) | AFNI 3dReHo | 3D NIfTI | +| `*_space-longitudinal_reg-{regressor}_desc-smooth_reho.nii.gz` | `reho` | Spatially smoothed ReHo map | Gaussian kernel smoothing | 3D NIfTI | +| `*_space-longitudinal_reg-{regressor}_desc-smoothZstd_reho.nii.gz` | `reho` | Z-scored smoothed ReHo | Z-score normalization | 3D NIfTI | +| `*_space-longitudinal_atlas-{atlas}_reg-{regressor}_desc-mean_timeseries.tsv` | `timeseries` | Mean BOLD signal per atlas region | Region-wise averaging | TSV, regions x timepoints | +| `*_space-longitudinal_atlas-{atlas}_reg-{regressor}_desc-pearson_correlations.tsv` | `correlations` | Pairwise Pearson correlation matrix between atlas regions | Pearson correlation | TSV, regions x regions | + +### QC + +Produced by `rbc longitudinal qc`. Evaluates registration quality by measuring overlap between the anatomical brain mask and the BOLD brain mask in longitudinal template space. + +| File | Suffix | Description | Created by | Format | +| --- | --- | --- | --- | --- | +| `*_space-longitudinal_desc-registration_quality.tsv` | `quality` | Single-row TSV with mask overlap metrics (see columns below) | Registration QC | TSV, 1 row | + +#### Longitudinal QC columns + +| Column | Type | Description | +| --- | --- | --- | +| `sub` | string | Subject identifier | +| `ses` | string | Session label | +| `task` | string | Task label | +| `run` | integer | Run number | +| `dice` | float | Dice coefficient between anat and BOLD masks in longitudinal space | +| `jaccard` | float | Jaccard index between anat and BOLD masks in longitudinal space | +| `coverage` | float | Coverage of the smaller mask by the overlap region | +| `cross_corr` | float | Pearson correlation between flattened binary masks | +| `passed` | boolean | Whether the run passes the Dice threshold (>= 0.85) | diff --git a/docs/output_tree.svg b/docs/output_tree.svg new file mode 100644 index 00000000..e8ef8f82 --- /dev/null +++ b/docs/output_tree.svg @@ -0,0 +1,2 @@ + +Pipeline stage:anatomicalfunctionalmetricsqctemplatelongitudinalderivatives/sub-01/ses-01/anat/sub-01_ses-01_desc-T1w_mask.nii.gzsub-01_ses-01_desc-brain_T1w.nii.gzsub-01_ses-01_desc-csf_mask.nii.gzsub-01_ses-01_desc-gm_mask.nii.gzsub-01_ses-01_desc-wmBBR_mask.nii.gzsub-01_ses-01_desc-wm_mask.nii.gzsub-01_ses-01_from-MNI152NLin6Asym_to-T1w_mode-image_xfm.nii.gzsub-01_ses-01_from-T1w_to-MNI152NLin6Asym_mode-image_xfm.nii.gzsub-01_ses-01_space-MNI152NLin6Asym_desc-brain_T1w.nii.gzsub-01_ses-01_space-longitudinal_desc-T1w_mask.nii.gzsub-01_ses-01_space-longitudinal_desc-brain_T1w.nii.gzsub-01_ses-01_space-longitudinal_from-MNI152NLin6Asym_to-longitudinal_mode-image_xfm.nii.gzsub-01_ses-01_space-longitudinal_from-longitudinal_to-MNI152NLin6Asym_mode-image_xfm.nii.gzfunc/sub-01_ses-01_task-rest_run-1_desc-36parameterFiltered_regressors.1Dsub-01_ses-01_task-rest_run-1_desc-36parameter_regressors.1Dsub-01_ses-01_task-rest_run-1_desc-brain_mask.nii.gzsub-01_ses-01_task-rest_run-1_desc-maxDisplacement_motion.rmssub-01_ses-01_task-rest_run-1_desc-motionParams_motion.1Dsub-01_ses-01_task-rest_run-1_desc-preproc_bold.nii.gzsub-01_ses-01_task-rest_run-1_desc-relsDisplacement_motion.rmssub-01_ses-01_task-rest_run-1_from-bold_to-T1w_mode-image_desc-linearITK_xfm.txtsub-01_ses-01_task-rest_run-1_from-bold_to-T1w_mode-image_desc-linear_xfm.matsub-01_ses-01_task-rest_run-1_sbref.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_atlas-schaefer200_reg-36parameter_desc-mean_timeseries.tsvsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_atlas-schaefer200_reg-36parameter_desc-pearson_correlations.tsvsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_desc-bold_mask.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_desc-preproc_bold.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_alff.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_desc-preproc_bold.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_desc-regressed_bold.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_desc-smoothZstd_alff.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_desc-smoothZstd_falff.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_desc-smoothZstd_reho.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_desc-smooth_alff.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_desc-smooth_falff.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_desc-smooth_reho.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_desc-xcp_quality.tsvsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_falff.nii.gzsub-01_ses-01_task-rest_run-1_space-MNI152NLin6Asym_reg-36parameter_reho.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_atlas-schaefer200_reg-36parameter_desc-mean_timeseries.tsvsub-01_ses-01_task-rest_run-1_space-longitudinal_atlas-schaefer200_reg-36parameter_desc-pearson_correlations.tsvsub-01_ses-01_task-rest_run-1_space-longitudinal_desc-brain_mask.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_desc-preproc_bold.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_desc-registration_quality.tsvsub-01_ses-01_task-rest_run-1_space-longitudinal_from-bold_to-longitudinal_mode-image_desc-composite_xfm.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_alff.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_desc-preproc_bold.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_desc-regressed_bold.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_desc-smoothZstd_alff.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_desc-smoothZstd_falff.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_desc-smoothZstd_reho.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_desc-smooth_alff.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_desc-smooth_falff.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_desc-smooth_reho.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_falff.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_reg-36parameter_reho.nii.gzsub-01_ses-01_task-rest_run-1_space-longitudinal_sbref.nii.gzses-longitudinal/anat/sub-01_ses-longitudinal_T1w.nii.gzsub-01_ses-longitudinal_from-01_to-longitudinal_mode-image_xfm.txtanatomicalanatomicalanatomicalanatomicalanatomicalanatomicalanatomicalanatomicalanatomicallongitudinalanatomicallongitudinalanatomicallongitudinalanatomicallongitudinalanatomicalfunctionalfunctionalfunctionalfunctionalfunctionalfunctionalfunctionalfunctionalfunctionalfunctionalmetricsmetricsfunctionalfunctionalmetricsfunctionalfunctionalmetricsmetricsmetricsmetricsmetricsmetricsqcmetricsmetricslongitudinalmetricslongitudinalmetricslongitudinalfunctionallongitudinalfunctionallongitudinalqclongitudinalfunctionallongitudinalmetricslongitudinalfunctionallongitudinalfunctionallongitudinalmetricslongitudinalmetricslongitudinalmetricslongitudinalmetricslongitudinalmetricslongitudinalmetricslongitudinalmetricslongitudinalmetricslongitudinalfunctionallongitudinaltemplatelongitudinaltemplate \ No newline at end of file diff --git a/src/rbc/bids/query.py b/src/rbc/bids/query.py index 7fe74ba8..c5616db2 100644 --- a/src/rbc/bids/query.py +++ b/src/rbc/bids/query.py @@ -57,6 +57,11 @@ def load_table( for d in dirs: all_roots.extend(b2t.find_bids_datasets(d)) + # Deduplicate: when one input dir is a subdirectory of another (e.g. + # /data and /data/derivatives), find_bids_datasets discovers the nested + # dataset from both roots. Use dict.fromkeys to preserve discovery order. + all_roots = list(dict.fromkeys(r.resolve() for r in all_roots)) + tables = b2t.batch_index_dataset( all_roots, max_workers=max_workers,