From edcfba4a373d2c893a7322f3770cea062253dea5 Mon Sep 17 00:00:00 2001
From: "Gabriel A. Devenyi"
Date: Mon, 3 Aug 2026 13:13:47 -0400
Subject: [PATCH 1/9] Restructure documentation according to Diataxis
Reorganise docs/ into tutorials/, how_to/, reference/ and explanation/, so
each page serves one user need instead of mixing lesson, recipe, fact and
discussion on the same page.
Structural changes:
- Add a tutorial (docs/tutorials/first_run.md). There was none: the docs
offered no guided path from a fresh install to a first result.
- Split running_the_software.md, which was tutorial, reference and how-to at
once, into reference/bids_inputs.md, reference/cli.md and
how_to/run_with_containers.md.
- Split analysis_QC.md into explanation/data_quality.md (what the reports are
and why) and how_to/assess_data_quality.md (generating them, setting
thresholds, reporting in a publication).
- Move the source docstrings inlined in the preprocessing and confound
correction pages into reference/workflows.md.
- Add how_to/select_scans.md, covering --bids_filter, --inclusion_ids and
--exclusion_ids, which were previously only described in --help.
- Promote the single-entry FAQ to a titled how-to guide.
All MyST cross-reference anchors are preserved, so incoming links still
resolve.
Documentation errors fixed against the code:
- --conf_prior_idx/--bold_prior_idx do not exist; the options are
--prior_confound_idx/--prior_bold_idx.
- --scan_QC_thresholds takes a dictionary expression; document its actual
syntax and keys.
- QC report folders are commonspace_reg_wf.Anat2Unbiased/,
commonspace_reg_wf.Unbiased2Atlas/ and commonspace_reg_wf.Anat2Atlas/ (with
fast_commonspace=true), not Native2Unbiased/ and Unbiased2Atlas/. The
fast_commonspace layout was undocumented.
- Analysis outputs land in commonspace_analysis_datasink/ or
nativespace_analysis_datasink/, not analysis_datasink/.
- --conf_list is deprecated and raises; --detrending is --detrending_order.
- The Docker example pulled gabdesgreg/rabies while the installation page
pointed at ghcr.io/cobralab/rabies.
Sphinx configuration:
- html_theme was set to 'groundwork', which is not installed and was silently
overridden by sphinx_rtd_dark_mode. Set it to sphinx_rtd_theme explicitly.
- html_theme_options was defined twice; the second definition clobbered the
first, reducing navigation_depth from 3 to 2.
- Pin docutils==0.17.1. sphinx 5.0, myst-parser and sphinxcontrib-bibtex have
no other version in common, so the resolver could pick a broken combination.
- Add sphinx-design (pinned <0.6 for the sphinx==5.0 pin) and
sphinx-copybutton, plus colon_fence/deflist MyST extensions, heading
anchors, and numfig.
Formatting: blocks become {dropdown}; a raw tree
dump becomes a captioned code block; Apptainer and Docker instructions become
a {tab-set}; images become {figure} with alt text; parameter lists become
definition lists.
Co-Authored-By: Claude Opus 5 (1M context)
Claude-Session: https://claude.ai/code/session_01Kdq57U3c4xpcRTXWhtpWrt
---
.gitignore | 4 +-
docs/_static/custom.css | 28 ++
docs/analysis.md | 28 --
docs/analysis_QC.md | 56 ----
docs/bibliography.md | 5 -
docs/conf.py | 67 ++---
docs/confound_correction.md | 52 ----
docs/contributing.md | 154 ----------
docs/explanation/analysis.md | 133 +++++++++
docs/explanation/confound_correction.md | 181 ++++++++++++
docs/explanation/data_quality.md | 125 ++++++++
docs/explanation/distribution_plot.md | 68 +++++
docs/explanation/group_statistics.md | 78 +++++
docs/explanation/index.md | 39 +++
docs/explanation/preprocessing.md | 180 ++++++++++++
docs/explanation/scan_diagnosis.md | 187 ++++++++++++
docs/faq.md | 55 ----
docs/how_to/assess_data_quality.md | 172 +++++++++++
docs/how_to/check_orientation.md | 57 ++++
docs/how_to/contribute.md | 224 ++++++++++++++
docs/how_to/index.md | 46 +++
docs/how_to/install.md | 110 +++++++
docs/how_to/minimal_preprocessing.md | 104 +++++++
docs/how_to/optimise_confound_correction.md | 60 ++++
docs/how_to/run_with_containers.md | 116 ++++++++
docs/how_to/select_scans.md | 110 +++++++
docs/how_to/troubleshoot_registration.md | 89 ++++++
docs/index.md | 92 +++++-
docs/installation.md | 25 --
docs/metrics.md | 71 -----
docs/nested_docs/distribution_plot.md | 16 -
docs/nested_docs/group_stats.md | 15 -
docs/nested_docs/optim_CR.md | 15 -
docs/nested_docs/registration_troubleshoot.md | 17 --
docs/nested_docs/scan_diagnosis.md | 55 ----
docs/outputs.md | 99 -------
docs/preproc_QC.md | 26 --
docs/preprocessing.md | 99 -------
docs/reference/bibliography.md | 6 +
docs/reference/bids_inputs.md | 94 ++++++
docs/reference/cli.md | 162 +++++++++++
docs/reference/index.md | 36 +++
docs/reference/metrics.md | 237 +++++++++++++++
docs/reference/outputs.md | 180 ++++++++++++
docs/reference/qc_outputs.md | 154 ++++++++++
docs/reference/workflows.md | 119 ++++++++
docs/requirements.txt | 6 +
docs/running_the_software.md | 202 -------------
docs/troubleshooting.md | 41 ---
docs/tutorials/first_run.md | 275 ++++++++++++++++++
docs/tutorials/index.md | 23 ++
51 files changed, 3508 insertions(+), 1085 deletions(-)
create mode 100644 docs/_static/custom.css
delete mode 100644 docs/analysis.md
delete mode 100644 docs/analysis_QC.md
delete mode 100644 docs/bibliography.md
delete mode 100644 docs/confound_correction.md
delete mode 100644 docs/contributing.md
create mode 100644 docs/explanation/analysis.md
create mode 100644 docs/explanation/confound_correction.md
create mode 100644 docs/explanation/data_quality.md
create mode 100644 docs/explanation/distribution_plot.md
create mode 100644 docs/explanation/group_statistics.md
create mode 100644 docs/explanation/index.md
create mode 100644 docs/explanation/preprocessing.md
create mode 100644 docs/explanation/scan_diagnosis.md
delete mode 100644 docs/faq.md
create mode 100644 docs/how_to/assess_data_quality.md
create mode 100644 docs/how_to/check_orientation.md
create mode 100644 docs/how_to/contribute.md
create mode 100644 docs/how_to/index.md
create mode 100644 docs/how_to/install.md
create mode 100644 docs/how_to/minimal_preprocessing.md
create mode 100644 docs/how_to/optimise_confound_correction.md
create mode 100644 docs/how_to/run_with_containers.md
create mode 100644 docs/how_to/select_scans.md
create mode 100644 docs/how_to/troubleshoot_registration.md
delete mode 100644 docs/installation.md
delete mode 100644 docs/metrics.md
delete mode 100644 docs/nested_docs/distribution_plot.md
delete mode 100644 docs/nested_docs/group_stats.md
delete mode 100644 docs/nested_docs/optim_CR.md
delete mode 100644 docs/nested_docs/registration_troubleshoot.md
delete mode 100644 docs/nested_docs/scan_diagnosis.md
delete mode 100644 docs/outputs.md
delete mode 100644 docs/preproc_QC.md
delete mode 100644 docs/preprocessing.md
create mode 100644 docs/reference/bibliography.md
create mode 100644 docs/reference/bids_inputs.md
create mode 100644 docs/reference/cli.md
create mode 100644 docs/reference/index.md
create mode 100644 docs/reference/metrics.md
create mode 100644 docs/reference/outputs.md
create mode 100644 docs/reference/qc_outputs.md
create mode 100644 docs/reference/workflows.md
delete mode 100644 docs/running_the_software.md
delete mode 100644 docs/troubleshooting.md
create mode 100644 docs/tutorials/first_run.md
create mode 100644 docs/tutorials/index.md
diff --git a/.gitignore b/.gitignore
index 775aa256..3fb3e22a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,6 @@
*sif
build/
dist/
-rabies.egg-info/
\ No newline at end of file
+rabies.egg-info/
+docs/_build/
+__pycache__/
diff --git a/docs/_static/custom.css b/docs/_static/custom.css
new file mode 100644
index 00000000..ce308f54
--- /dev/null
+++ b/docs/_static/custom.css
@@ -0,0 +1,28 @@
+/* The RTD theme caps content width at 800px, which is cramped for the
+ parcellation tables, --help output and the wider figures. */
+.wy-nav-content {
+ max-width: 1000px;
+}
+
+/* Keep wide content (help output, tables, diagrams) inside its own scroll
+ region rather than forcing the page to scroll horizontally. */
+.rst-content div[class^='highlight'] pre,
+.rst-content table.docutils {
+ overflow-x: auto;
+}
+
+/* sphinx-design cards inherit an RTD margin that double-spaces the grids. */
+.rst-content .sd-card {
+ margin-bottom: 0;
+}
+
+.rst-content .sd-card .sd-card-title {
+ font-weight: 600;
+}
+
+/* Definition lists are used heavily for parameter descriptions; give the term
+ enough weight to scan against the body text. */
+.rst-content dl:not(.docutils) > dt,
+.rst-content dl.simple > dt {
+ font-weight: 600;
+}
diff --git a/docs/analysis.md b/docs/analysis.md
deleted file mode 100644
index 70b71cff..00000000
--- a/docs/analysis.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# Connectivity Analysis
-
-Following the completion of the confound correction workflow, RABIES allows the estimation of resting-state connectivity using standard analyses: seed-based connectivity, whole-brain connectivity, group independent component analysis (ICA) and dual regression (DR). For each analysis (except for group-ICA), RABIES will compute individualized connectivity maps for each scan separately, which can then be exported for relevant statistical analyses (e.g. group comparison) conducted outside of RABIES.
-
-## Correlation-based connectivity
-Correlation-based analyses rely on computing a temporal correlation between different brain regions' BOLD fluctuations to estimate their functional coupling. The assessment of connectivity using correlation requires careful a priori cleaning of confounds (see [confound correction](confound_correction) and [data quality assessment](analysis_QC_target)), as various fMRI confounds introduce spurious correlations that won't be distinguished from neural activity.
-(SBC_target)=
-- **Seed-based connectivity** (`--seed_list`): Seed-based connectivity is the first technique developped for the mapping of connectivity during resting state {cite}`Biswal1995-vh`. The mean timecourse is first extracted from an anatomical seed of interest, and the correlation (Pearson’s r in RABIES) between this timecourse and every other voxel is computed to obtain a correlation map, representing the ‘connectivity strength’ between the seed and every other brain regions.
-- **Whole-brain connectivity** (`--FC_matrix`/`--ROI_type`): This technique is an extension of the seed-based connectivity technique to encompass every brain region. That is, using the anatomical parcellation provided along with the atlas during preprocessing, the seed timecourse for every parcel is first extracted, and then the cross-correlation (Pearson’s r) is measured between every region pair. The correlation values are then re-organized into a whole-brain matrix representing the connectivity between every corresponding region pair.
-
-## ICA-based connectivity
-The second analysis approach available within RABIES rely on the spatial decomposition of BOLD timeseries using ICA, which models the data as a linear combination of independent sources. In contrast with correlation-based connectivity, which models a single linear relationship between regions, the ICA framework accounts for multiple potentially overlapping sources of BOLD fluctuations, which may further separate confound contributions from connectivity estimates. To obtain individualized connectivity estimates, this analysis framework consists of first deriving ICA components at the group level to define sources, and then recovering individual-specific versions of the sources with dual regression {cite}`Nickerson2017-gq`.
-(ICA_target)=
-- **Group ICA** (`--group_ica`): RABIES uses FSL’s MELODIC ICA algorithm {cite}`Beckmann2004-yw` to derive ICA components. For group-ICA, timeseries for all scans aligned in commonspace are concatenated to group all data, before computing the ICA decomposition, yielding
-$$
-Y_{concat} = A\hat{S}
-$$
-where $Y_{concat}$ are the concatenated timeseries, $\hat{S}$ are the set of spatial maps defining the independent sources, and $A$ is the mixing matrix storing timecourses associated to each component.
-(DR_target)=
-- **Dual regression (DR)** (`--prior_maps`/`--DR_ICA`) : DR builds on the group ICA decomposition to model scan-specific versions of the group-level components, thus allowing to estimate individualized connectivity for a given brain network first identified through group-ICA {cite}`Beckmann2009-cf,Nickerson2017-gq`. DR consists of two consecutive linear regression steps, where scan-specific timecourses are first derived for each ICA component, and then a scan-specific spatial map is obtained for each component timecourse. Using multivariate linear regression (with Ordinary least square (OLS)), component timecourses are obtained with
-$${\beta}_{TC} = OLS(\hat{S},Y)$$
-describing $Y = \hat{S}{\beta}_{TC} + \epsilon$ where $Y$ are the scan timeseries, $\hat{S}$ are the ICA components and ${\beta}_{TC}$ corresponds to the estimated timecourses for each component. To accurately measure connectivity amplitude in the spatial maps derived from DR, the timecourses from the first regression step must be standardized prior to the second regression{cite}`Nickerson2017-gq`. In RABIES, timecourses are thus variance-normalized using root-mean square (RMS)
-$$
-{\beta}^*_{TC} = \frac{{\beta}_{TC}}{RMS({\beta}_{TC})}
-$$
-where $RMS(x) = \sqrt{\frac{1}{n}\sum_{i=1}^{n}x_i^2}$. The normalized timecourses ${\beta}^*_{TC}$ are then inputed into a second regression step to derive the spatial maps ${\beta}_{SM}$ with
-$${\beta}_{SM} = OLS({\beta}^*_{TC},Y^T)$$
-where $Y = {\beta}^*_{TC}{\beta}_{SM} + \epsilon$, thus completing the linear model of the timeseries. The resulting scan-specific spatial maps ${\beta}_{SM}$ will comprise information about network amplitude and shape, which may be compared across subjects or groups with further statistical tests{cite}`Nickerson2017-gq`.
diff --git a/docs/analysis_QC.md b/docs/analysis_QC.md
deleted file mode 100644
index 53311c7b..00000000
--- a/docs/analysis_QC.md
+++ /dev/null
@@ -1,56 +0,0 @@
-# Data quality assessment
-
-(analysis_QC_target)=
-
-```{toctree}
----
-maxdepth: 3
----
-nested_docs/scan_diagnosis.md
-nested_docs/distribution_plot.md
-nested_docs/group_stats.md
-nested_docs/optim_CR.md
-```
-
-Data quality can have serious impacts on analysis outcomes, leading to false findings. Rodent imaging can suffer from spurious effects on connectivity measures if potential confounds are not well accounted for, or acquisition factors, such as anesthesia levels, can influence network activity {cite}`Desrosiers-Gregoire2024-ou,Grandjean2020-fa`. To support interpretability, troubleshooting and reproducible research, RABIES includes a set of reports for conducting data quality assessment in individual scans and conducting quality control prior to network analysis at the group level. The reports are designed most specifically to evaluate the detectability of canonical brain networks and the impact of potential confounds (motion, physiological instabilities, and more).
-
-This page describes how to generate the reports, our guidelines for conducting quality network of network analysis, and how to include those reports in a publication.
-
-## Generating the reports
-
-At the analysis stage of the pipeline, the `--data_diagnosis` option can be selected to generate the data quality reports. To generate the report, ICA components must also be provided with `--prior_maps` and a set of components corresponding to confounds must be selected using `--conf_prior_idx` (see further details below). Connectivity can be evaluated for both dual regression and seed-based connectivity:
-* **For [dual regression](DR_target)**: dual regression is always conducted using the set components from `--prior_maps`, since certain features are derived from confound components defined in `--conf_prior_idx`. On the other hand, connectivity will be evaluated in the reports for each network included in `--bold_prior_idx`.
-* **For [seed-based connectivity](SBC_target)**: reports will be generated for each seed provided to `--seed_list`. However, each seed needs to be supplemented with a reference network map (a 3D Nifti file for each seed, provided with `--seed_prior_list`) which should represent the expected connectivity for the canonical network corresponding to that seed.
-
-The set of reports are generated in the `data_diagnosis_datasink/` (details [here](diagnosis_datasink_target)). The interpretation of each report is described within its dedicated documentation page, and include:
-
-* [Spatiotemporal diagnosis](diagnosis_target): this qualitative report generated for each scan regroups a set of temporal and spatial features allowing to characterize the specific origin of data quality issues.
-* [Distribution plots](dist_plot_target): quantitative report displaying the distribution of scans along measures of: specificity of network connectivity, network amplitude (for dual regression), and confound measures. Visualizing the dataset distribution can help identify outliers.
-* [Group statistics](group_stats_target): for a given network, this group-level report regroups brain maps for visualizing cross-scan variability in connectivity and the group-wise correlation between connectivity and confounds.
-
-### Classification of group ICA components
-
-Ideally, the ICA components should be derived directly from the dataset analyzed by using [group ICA](ICA_target), although a [pre-computed set](https://zenodo.org/record/5118030/files/melodic_IC.nii.gz) is available by default. Newly-generated components must be visually inspected to identify the set of components corresponding to confound sources (which is inputted with `--conf_prior_idx`). This can be done by visualizing the group_melodic.ica/melodic_IC.nii.gz file, or using the automatically-generated FSL report in group_melodic.ica/report. Similarly, components corresponding to networks of interest can be identified and inputted with `--bold_prior_idx`.
-
-Classifying components requires careful considerations, and we recommend a conservative inclusion (i.e. not every components need to be classified, only include components which have clear feature delineating a network or a confound). Consult {cite}`Zerbi2015-nl` or {cite}`Desrosiers-Gregoire2024-ou` for more information on classifying ICA components in rodents, or the [pre-computed set](https://zenodo.org/record/5118030/files/melodic_IC.nii.gz) can be consulted as reference (the defaults for `--bold_prior_idx` and `--conf_prior_idx` correspond to the classification of these components).
-
-## Guidelines for analysis quality control
-
-
-
-Below are our recommendations for how the set of quality reports can be used identify and control for the impact of data quality issues on downstream group analysis. Although the reports may be used for a breadth of applications, these guidelines are formulated most specifically for a standard resting-state fMRI design aiming to compare network connectivity between subjects or groups. In particular, the following guidelines aim to identify features of spurious or absent connectivity, remove scans where these features are prominent to avoid false results (e.g. connectivity difference is driven by motion), and determine whether these issues may confound group statistics.
-
-1. Inspect the [spatiotemporal diagnosis](diagnosis_target) for each scan. Particular attention should be given to the 4 main quality markers defining [categories of scan quality](quality_marker_target), and whether features of spurious or absent connectivity are prominent.
-2. If spurious or absent connectivity is prominent in a subset of scans, these scans should be detected and removed to mitigate false results. This is done by setting thresholds using `--scan_QC_thresholds` for scan-level measures of network specificity and confound correlation. These measures are documented in the [distribution plots](dist_plot_target), and the specific measures for each scan ID can be consulted in the CSV file accompanying the plot. Using this CSV file, sensible threshold values can be selected for delineating scans with spurious or absent connectivity. Additionally, for dual regression analysis, `--scan_QC_thresholds` can be used to automatically detect and remove scans which present outlier values in network amplitude, which can be an indicator of spurious connectivity {cite}`Nickerson2017-gq`. By applying `--scan_QC_thresholds`, these scans won't be included for generating the group statistical report (thus the reports must re-generated after defining `--scan_QC_thresholds`).
-3. Finally, the [group statistical report](group_stats_target) can be consulted to identify the main driven of variability in connectivity across scans, and whether it relates primarily to network activity or to confounds.
-
-If significant issues are found from this evaluation, the design of the confound correction stage may be revisited to improve quality outcomes (see [dedicated documentation](optim_CR)).
-
-**Disclaimer**: Although these guidelines are meant to support identifying analysis pitfalls and improve research transparency, they are not meant to be prescriptive. The judgement of the experimenter is paramount in the adopting adequate practices (e.g. network detectability may not always be expected, if studying the impact of anesthesia or inspecting a visual network in blind subjects), and the conversation surrounding what should constitute proper standards for resting-state fMRI is evolving.
-
-### Reporting in a publication
-
-All figures from the report are generated in PNG (or SVG) format, and can be shared along a publication for data transparency. Ideally, a version of the spatiotemporal diagnosis can be shared for each scan used in deriving connectivity results, together with a group statistical report and its affiliated distribution plot for each groups/datasets if the analysis involves comparing connectivity differences across subjects and/or group.
-
-The set of ICA components classified as networks and confounds should be reported appropriately (e.g. melodic_IC.nii.gz file can be shared with its associated component classification). If certain scan inclusion/exclusion criteria were selected based on the quality control guidelines described above, it is particularly important to describe the observations motivating these criteria and make the associated reports readily accessible for consultation (e.g. the set of spatiotemporal diagnosis files for scans displaying spurious/absent connectivity and motivated setting a particular QC threshold with `--scan_QC_thresholds`). If the design of confound correction was defined using these tools, this should also be appropriately reported.
-
diff --git a/docs/bibliography.md b/docs/bibliography.md
deleted file mode 100644
index 7ace31d4..00000000
--- a/docs/bibliography.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bibliography
-
-```{bibliography} _static/refs.bib
-
-```
diff --git a/docs/conf.py b/docs/conf.py
index 02f664ab..d3a57243 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,37 +1,23 @@
# Configuration file for the Sphinx documentation builder.
#
-# This file only contains a selection of the most common options. For a full
-# list see the documentation:
+# For the full list of options see:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
-# -- Path setup --------------------------------------------------------------
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#
-# import os
-# import sys
-# sys.path.insert(0, os.path.abspath('.'))
-
-
# -- Project information -----------------------------------------------------
-project = 'RABIES Documentation'
+project = 'RABIES'
copyright = '2019, CoBrALab and Gabriel Desrosiers-Gregoire and Gabriel A. Devenyi and Mallar Chakravarty'
author = 'CoBrALab'
# The full version, including alpha/beta/rc tags
release = '0.6.1'
-
# -- General configuration ---------------------------------------------------
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
extensions = [
"myst_parser",
+ "sphinx_design",
+ "sphinx_copybutton",
"sphinx.ext.githubpages",
"sphinx_rtd_dark_mode",
"sphinx.ext.autosectionlabel",
@@ -43,7 +29,7 @@
# to get bibliography
bibtex_bibfiles = ['_static/refs.bib']
-# Choose to generate TOOD notices or not. Defaults to False
+# Choose to generate TODO notices or not. Defaults to False
todo_include_todos = False
# Set MyST specific extensions
@@ -51,14 +37,23 @@
"tasklist",
"amsmath",
"dollarmath",
+ "colon_fence", # ::: fences, so admonitions can nest and stay readable
+ "deflist",
+ "attrs_inline",
]
# enable equation rendering inline
myst_dmath_double_inline = True
+# Generate anchors for h1-h3 so other pages can deep-link to a section
+myst_heading_anchors = 3
+
# Make sure the target is unique
autosectionlabel_prefix_document = True
+# Number and cross-reference figures, tables and code blocks
+numfig = True
+
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -67,37 +62,35 @@
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
-
# -- Options for HTML output -------------------------------------------------
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-#
-html_theme = 'groundwork'
+# sphinx_rtd_dark_mode forces this theme, it is set here so the value is not
+# silently disagreeing with what actually gets built.
+html_theme = 'sphinx_rtd_theme'
+
+html_title = f'RABIES {release}'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
+html_css_files = ['custom.css']
-# -- Options for sphinx_rtd_dark_mode -------
+# -- Options for sphinx_rtd_dark_mode ----------------------------------------
default_dark_mode = False
-# Set some RTD theme config. This includes the entire navigation structure
-# into the sidebar of all pages. However, expanding the sections isn't
-# provided yet on the RTD theme (see
-# https://github.com/readthedocs/sphinx_rtd_theme/issues/455).
+# -- Options for the RTD theme -----------------------------------------------
+# The whole navigation structure is included in the sidebar of every page.
html_theme_options = {
'collapse_navigation': False,
'navigation_depth': 3,
+ 'sticky_navigation': True,
+ 'titles_only': False,
}
-# Set some RTD theme config. This includes the entire navigation structure
-# into the sidebar of all pages. However, expanding the sections isn't
-# provided yet on the RTD theme (see
-# https://github.com/readthedocs/sphinx_rtd_theme/issues/455).
-html_theme_options = {
- 'collapse_navigation': False,
- 'navigation_depth': 2,
-}
+# -- Options for sphinx_copybutton -------------------------------------------
+# Strip shell prompts and continuation markers when copying a command
+copybutton_prompt_text = r'>>> |\.\.\. |\$ '
+copybutton_prompt_is_regexp = True
+copybutton_line_continuation_character = '\\'
diff --git a/docs/confound_correction.md b/docs/confound_correction.md
deleted file mode 100644
index 45b758c2..00000000
--- a/docs/confound_correction.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# Confound Correction stage
-
-(confound_pipeline_target)=
-
-
-
-
-The workflow for confound correction regroups a broad set of standard tools from the human litterature. The implementation of each step is structured to follow best practices and prevent re-introduction of confounds, as recommended in {cite}`Power2014-yf` and {cite}`Lindquist2019-lq`. Importantly, each operation is optional (except detrending), and a set of operations can be selected to design a customized workflow. Optimal correction strategy can be dataset-specific, and ideally, should be tuned to address relevant quality issues identified within the dataset (see section on [data quality assessment](analysis_QC_target)).
-
-1. **Frame censoring** (`--frame_censoring`): Frame censoring temporal masks are derived from FD and/or DVARS thresholds, and applied first on both BOLD timeseries before any other correction step to exclude signal spikes which may bias downstream corrections, in particular, detrending, frequency filtering and confound regression{cite}`Power2014-yf`.
- * Censoring with framewise displacement (see [definition](FD_target)): Apply frame censoring based on a framewise displacement threshold. The frames that exceed the given threshold, together with 1 back and 2 forward frames will be masked out{cite}`Power2012-ji`.
- * Censoring with DVARS (see [definition](DVARS_target)): The DVARS values are z-scored ($DVARS_Z = \frac{DVARS-\mu}{\sigma}$, where $\mu$ is the mean DVARS across time, and $\sigma$ the standard deviation), and frames with $|DVARS_Z|>2.5$ (i.e. above 2.5 standard deviations from the mean) are removed. Z-scoring and outlier detection is repeated within the remaining frames, iteratively, until no more outlier is detected, to obtained a final set of frames post-censoring.
- * `--match_number_timepoints` : This option can be selected to constrain each scan to retain the same final number of frames, to account for downstream impacts from unequal temporal degrees of freedom (tDOF) on analysis. To do so, a pre-set final number of frames is defined with `minimum_timepoint`, and a number of extra frames remaining post-censoring (taking into account edge removal in 5) ) is randomly selected and removed from the set.
-
-2. **Detrending** (`--detrending_order`): Linear (or quadratic) trends are removed from timeseries. Detrended timeseries $\hat{Y}$ are obtained by performing ordinary-least square (OLS) linear regression,
-$$
-\beta = OLS(X,Y)
-$$
-$$
-\hat{Y} = Y - X\beta
-$$
-where Y is the timeseries and the predictors are $X = [intercept, time, time^2]$ ($time^2$ is included if removing quadratic trends).
-
-3. **ICA-AROMA** (`--ica_aroma`): Cleaning of motion-related sources using the ICA-AROMA{cite}`Pruim2015-nm` classifier. The hard-coded human priors for anatomical masking and the linear coefficients for classification were adapted from the [original code](https://github.com/maartenmennes/ICA-AROMA) to function with rodent images. ICA-AROMA is applied prior to frequency filtering to remove further effects of motion than can result in ringing after filtering{cite}`Carp2013-uf,Pruim2015-nm`.
-
-4. **Frequency filtering** (`--TR`/`--highpass`/`--lowpass`/`--edge_cutoff`):
- 1. Simulating censored timepoints: frequency filtering requires particular considerations when applied after frame censoring, since conventional filters cannot handle missing data (censoring results in missing timepoints). To address this issue, we implemented a method described in {cite}`Power2014-yf` allowing the simulation of data points while preserving the frequency composition of the data. This method relies on an adaptation of the Lomb-Scargle periodogram, which allows estimating the frequency composition of the timeseries despite missing data points, and from that estimation, missing timepoints can be simulated while preserving the frequency profile {cite}`Mathias2004-rt`.
- 2. Butterworth filter: Following the simulation, frequency filtering (highpass and/or lowpass) is applied using a 3rd-order Butterworth filter ([scipy.signal.butter](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.butter.html)). If applying highpass, it is recommended to remove 30 seconds at each end of the timeseries using `--edge_cutoff` to account for edge artefacts following filtering{cite}`Power2014-yf`. After frequency filtering, the temporal mask from censoring is re-applied to remove simulated timepoints.
-
-(CR_target)=
-5. **Confound regression** (`--nuisance_regressors`): For each voxel timeseries, a selected set of nuisance regressors (see [regressor options](regressor_target)) are modelled using OLS linear regression and their modelled contribution to the signal is removed. Regressed timeseries $\hat{Y}$ are obtained with
-$$\beta = OLS(X,Y)$$
-$$ Y_{CR} = X\beta $$
-$$ \hat{Y} = Y - Y_{CR} $$
-where $Y$ is the timeseries, $X$ is the set of nuisance timecourses and $Y_{CR}$ is the confound timeseries predicted from the model at each voxel ($Y_{CR}$ is a time by voxel 2D matrix).
-
-6. **Intensity scaling** (`--image_scaling`): Voxel intensity values should be scaled to improve comparability between scans/datasets. The following options are provided:
- * Grand mean (**recommended**): Timeseries are divided by the mean intensity across the brain, and then multiplied by 100 to obtain percent BOLD deviations from the mean. The mean intensity of each voxel is derived from the $\beta$ coefficient from the intercept computed during **Detrending**.
- * Voxelwise mean: Same as grand mean, but each voxel is independently scaled by its own mean signal.
- * Global standard deviation: Timeseries are divided by the total standard deviation across all voxel timeseries.
- * Voxelwise standardization: Each voxel is divided by its standard deviation.
- * Homogenize variance voxelwise: if no scaling was already applied voxelwise (voxelwise mean or standardization), by selecting the option `--scale_variance_voxelwise`, timeseries are first scaled voxelwise by their standard deviation (yielding homogeneous variance distribution across voxels), and then re-scaled to preserve the original total standard deviation of the entire 4D timeseries (i.e. the global standard deviation does not change). Inhomogeneous variability distribution can be a [confound signature](quality_marker_target), thus this option may downscale their impact. `--scale_variance_voxelwise` can be applied in combination with grand mean scaling.
-
-7. **Smoothing** (`--smoothing_filter`): Timeseries are spatially smoothed using a Gaussian smoothing filter ([nilearn.image.smooth_img](https://nilearn.github.io/dev/modules/generated/nilearn.image.smooth_img.html)).
-
-
-## rabies.confound_correction_pkg.confound_correction.init_confound_correction_wf [[source code](https://github.com/CoBrALab/RABIES/blob/master/rabies/confound_correction_pkg/confound_correction.py)]
-
-```{literalinclude} ../rabies/confound_correction_pkg/confound_correction.py
-:start-after: confound_wf_head_start
-:end-before: confound_wf_head_end
-```
\ No newline at end of file
diff --git a/docs/contributing.md b/docs/contributing.md
deleted file mode 100644
index 93765cdf..00000000
--- a/docs/contributing.md
+++ /dev/null
@@ -1,154 +0,0 @@
-# Contributing to RABIES
-
-RABIES aims to provide an accessible tool responding to growing needs across the preclinical fMRI community. This effort should be community-driven, and community involvement will be paramount in achieving this goal in several respects:
-- Adapting and maintaining **accessibility** for users across the broader community
-- **Reproducibility and transparency**, as well as scientific scrutiny and rigor
-- Defining and incorporating **best practices** across the different aspects of image processing and analysis, as well as quality control
-- Leveraging appropriate expertise for the **integration of new tools**
-
-Suggestions for improvements can be shared using the Github [issues system](https://github.com/CoBrALab/RABIES/issues) and [discussion board](https://github.com/CoBrALab/RABIES/discussions). Contributions from developers are welcomed and encouraged. This page provides preliminary guidelines for getting started as a RABIES developer, and covers: setting a developer environment, submitting a pull request, testing and debugging, and basic instructions for adding a new module to the pipeline. We recommend discussing your proposed updates on the Github discussion board or issues prior to creating a pull request. Thank you for your support!
-
-## Dev environment
-
-For development, it is recommend to install RABIES locally, as this will make the testing and debugging process smoother. This requires installing the dependencies listed in dependencies.txt, and then installing RABIES in an appropriate python environment (e.g. using anaconda) from the Github repository. This can be done by cloning the repository, and then running ```python setup.py install```.
-
-### ...using a container
-
-It is possible to run operations using a container to avoid installing dependencies manually (however, it won't be possible to use an interface for debugging (e.g. Spyder)). This can be with `docker exec`. First, an instance of the container must be opened, which can be done by including `-d --entrypoint sh --name mycontainer` when calling `docker run`. The paths to access from the container must be set with `-v`. Here's an example:
-```sh
-docker run -it -v $PWD:/work_dir -v /path_to_local_RABIES_package:/RABIES:ro \
---rm --entrypoint sh -d --name mycontainer rabies:local_testing
-```
-You can then execute commands from inside the container as follows (`mycontainer` corresponds to the name set above):
-```sh
-docker exec mycontainer micromamba run $COMMAND
-```
-To test for error, `$COMMAND` can correspond to `error_check_rabies.py --complete`.
-
-**Upgrading the RABIES package**: to test your updates, you must re-install RABIES inside the container. Below is a method to do so:
-```sh
-mkdir -p /tmp/RABIES
-# copy all files from your upgraded package inside the container (/RABIES must be related to your local package with -v)
-rsync -avz /RABIES/* /tmp/RABIES/.
-# re-install package
-cd /tmp/RABIES
-python setup.py install
-```
-These can be compiled into a .sh script to execute in place of `$COMMAND` above.
-
-## Instructions to create a pull request
-
-1. On github, fork the RABIES repository to have your own copy.
-2. Clone your repository to carry out local modifications and testing. Use the `--recursive` option to download the submodules together with the main RABIES package.
-3. Create and checkout into a new branch with `git checkout -b my_new_branch` (provide a sensible name for the branch). You are ready to make modifications to the code.
-4. Testing and debugging: install your updated version of the package with ```python setup.py install```, using a proper dev environment (see above). Your can test the workflow with specific parameters by editing the ```debug_workflow.py``` script, and executing in debug mode with Spyder (see below). Before commiting changes, make sure that running ```error_check_rabies.py --complete``` completes with no error.
-5. Commit and push your modifications to Github, and create a pull request from your forked repo to the original.
-
-## Interactive debugging with Spyder and debug_workflow.py
-
-Here are some recommendations for debugging using Spyder:
-1. open the debug_workflow.py file in Spyder
-2. find the scrips with your local installation to add breakpoints for debugging. Using `import rabies; os.path.abspath(rabies.__file__)` will provide the path to the __init__.py file of your installed package, and from there you can find file of interest and add a breakpoint where desired.
-3. execute debug_workflow.py in debug mode, and run until it finds the breakpoint, and debug from there.
-
-## Creation of a new module and integration within a Nipype workflow
-
-RABIES' workflow is structured using Nipype (for more info on Nipype, see online [documentation](https://nipype.readthedocs.io/en/latest/) and [tutorial](https://miykael.github.io/nipype_tutorial/)). Preferably, a new function should be created as a Nipype interface, which has the following syntax:
-
-```python
-from nipype.interfaces.base import (
- traits, TraitedSpec, BaseInterfaceInputSpec,
- File, BaseInterface
-)
-class NewInterfaceInputSpec(BaseInterfaceInputSpec):
- # you must select an appropriate input type with traits.type (can be Dict, File, Int, ...)
- input_str = traits.Str(exists=True, mandatory=True,
- desc="An input string.")
-
-class NewInterfaceOutputSpec(TraitedSpec):
- out_file = File(
- exists=True, desc="An output file.")
-
-
-class NewInterface(BaseInterface):
- """
- Describe your module.
- """
-
- input_spec = NewInterfaceInputSpec
- output_spec = NewInterfaceOutputSpec
-
- def _run_interface(self, runtime):
- input_str = self.inputs.input_str
-
- '''
- YOUR CODE
- '''
-
- setattr(self, 'out_file', out_file)
-
- return runtime
-
- def _list_outputs(self):
- return {'out_file': getattr(self, 'out_file')}
-
-
-```
-
-You can then create a Nipype node for your interface:
-```python
-from .other_script import NewInterface # import your interface if from a different script
-from nipype.pipeline import engine as pe
-
-new_interface_node = pe.Node(NewInterface(),
- name='new_interface')
-```
-
-Instead of an interface, it is also possible to create a Nipype node from any python function:
-```python
-from nipype.pipeline import engine as pe
-from nipype.interfaces.utility import Function
-
-new_function_node = pe.Node(Function(input_names=['input_1', 'input_2', ...],
- output_names=['output_1', 'output_2', ...],
- function=NewFunction),
- name='new_function')
-```
-
-After creating a node which can carry the desired operation, it must be integrated within a workflow by linking up the inputs and outputs with other nodes. Below is an example of a simple workflow which conducts slice-timing correction:
-
-```python
-from nipype.pipeline import engine as pe
-from nipype.interfaces.utility import Function
-from nipype.interfaces import utility as niu
-
-# this function creates and return a Nipype workflow which conducts slice timing correction
-def init_bold_stc_wf(name='bold_stc_wf'):
-
- workflow = pe.Workflow(name=name) # creating a new Nipype workflow
- # creating an intermediate node for storing inputs to the workflow
- inputnode = pe.Node(niu.IdentityInterface(
- fields=['bold_file']), name='inputnode')
- # creating an intermediate node for storing outputs to the workflow
- outputnode = pe.Node(niu.IdentityInterface(
- fields=['stc_file']), name='outputnode')
-
- # preparing the node conducting STC
- slice_timing_correction_node = pe.Node(Function(input_names=['in_file', 'tr', 'tpattern', 'stc_axis',
- 'interp_method', 'rabies_data_type'],
- output_names=[
- 'out_file'],
- function=slice_timing_correction),
- name='slice_timing_correction', mem_gb=1.5*opts.scale_min_memory)
-
- # linking up the inputnode to provide inputs to the STC node, and outputs from STC to the outputnode of the workflow
- workflow.connect([
- (inputnode, slice_timing_correction_node, [('bold_file', 'in_file')]),
- (slice_timing_correction_node,
- outputnode, [('out_file', 'stc_file')]),
- ])
- return workflow
-
-```
-
-This example demonstrates the basic syntax of a Nipype workflow. Most likely, a new interface will be integrated as part of a pre-existing workflow (instead of creating a new one), in which case the right nodes must be linked up with the new interface.
diff --git a/docs/explanation/analysis.md b/docs/explanation/analysis.md
new file mode 100644
index 00000000..ed141e4c
--- /dev/null
+++ b/docs/explanation/analysis.md
@@ -0,0 +1,133 @@
+# Connectivity analysis
+
+Once confound correction is complete, RABIES estimates resting-state
+connectivity using standard analyses: seed-based connectivity, whole-brain
+connectivity, group independent component analysis (ICA) and dual regression
+(DR).
+
+For every analysis except group ICA, RABIES computes individualised
+connectivity maps for each scan separately. These can be exported for
+statistical analysis — group comparison and so on — conducted outside RABIES.
+
+```{important}
+Every analysis on this page assumes confounds have already been dealt with.
+Various fMRI confounds introduce spurious correlations that are
+indistinguishable from neural activity in the result, so the quality of a
+connectivity estimate is bounded by the quality of the
+[confound correction](confound_correction.md) that preceded it. See
+[Data quality assessment](data_quality.md).
+```
+
+## Correlation-based connectivity
+
+Correlation-based analyses compute a temporal correlation between different
+brain regions' BOLD fluctuations to estimate their functional coupling.
+
+(SBC_target)=
+
+### Seed-based connectivity
+
+`--seed_list`
+
+Seed-based connectivity was the first technique developed for mapping
+connectivity during rest {cite}`Biswal1995-vh`. The mean timecourse is
+extracted from an anatomical seed of interest, and the correlation — Pearson's
+r in RABIES — between that timecourse and every other voxel is computed,
+producing a correlation map representing the connectivity strength between the
+seed and every other brain region.
+
+### Whole-brain connectivity
+
+`--FC_matrix` / `--ROI_type`
+
+An extension of seed-based connectivity to every brain region. Using the
+anatomical parcellation provided with the atlas during preprocessing, the seed
+timecourse for every parcel is extracted, then the cross-correlation (Pearson's
+r) is measured between every region pair. The correlation values are
+reorganised into a whole-brain matrix representing the connectivity between
+every corresponding region pair.
+
+## ICA-based connectivity
+
+The second approach relies on the spatial decomposition of BOLD timeseries
+using ICA, which models the data as a linear combination of independent
+sources.
+
+Where correlation-based connectivity models a single linear relationship
+between regions, the ICA framework accounts for multiple, potentially
+overlapping, sources of BOLD fluctuation. This can further separate confound
+contributions from connectivity estimates.
+
+To obtain individualised connectivity estimates, this framework first derives
+ICA components at the group level to define the sources, then recovers
+individual-specific versions of those sources with dual regression
+{cite}`Nickerson2017-gq`.
+
+(ICA_target)=
+
+### Group ICA
+
+`--group_ica`
+
+RABIES uses FSL's MELODIC ICA algorithm {cite}`Beckmann2004-yw` to derive ICA
+components. For group ICA, timeseries for all scans aligned in commonspace are
+concatenated to group all data before computing the decomposition, yielding
+
+$$
+Y_{concat} = A\hat{S}
+$$
+
+where $Y_{concat}$ are the concatenated timeseries, $\hat{S}$ are the set of
+spatial maps defining the independent sources, and $A$ is the mixing matrix
+storing the timecourses associated with each component.
+
+(DR_target)=
+
+### Dual regression
+
+`--prior_maps` / `--DR_ICA`
+
+Dual regression builds on the group ICA decomposition to model scan-specific
+versions of the group-level components, allowing individualised connectivity to
+be estimated for a brain network first identified through group ICA
+{cite}`Beckmann2009-cf,Nickerson2017-gq`.
+
+It consists of two consecutive linear regression steps. First, scan-specific
+timecourses are derived for each ICA component; second, a scan-specific spatial
+map is obtained for each component timecourse.
+
+Using multivariate OLS linear regression, component timecourses are obtained
+with
+
+$${\beta}_{TC} = OLS(\hat{S},Y)$$
+
+describing $Y = \hat{S}{\beta}_{TC} + \epsilon$, where $Y$ are the scan
+timeseries, $\hat{S}$ are the ICA components and ${\beta}_{TC}$ are the
+estimated timecourses for each component.
+
+To measure connectivity amplitude accurately in the spatial maps derived from
+dual regression, the timecourses from the first regression step must be
+standardised before the second regression {cite}`Nickerson2017-gq`. RABIES
+variance-normalises them using root-mean square (RMS):
+
+$$
+{\beta}^*_{TC} = \frac{{\beta}_{TC}}{RMS({\beta}_{TC})}
+$$
+
+where $RMS(x) = \sqrt{\frac{1}{n}\sum_{i=1}^{n}x_i^2}$. The normalised
+timecourses ${\beta}^*_{TC}$ are then fed into a second regression step to
+derive the spatial maps ${\beta}_{SM}$:
+
+$${\beta}_{SM} = OLS({\beta}^*_{TC},Y^T)$$
+
+where $Y = {\beta}^*_{TC}{\beta}_{SM} + \epsilon$, completing the linear model
+of the timeseries. The resulting scan-specific spatial maps ${\beta}_{SM}$
+carry information about both network amplitude and network shape, which can be
+compared across subjects or groups with further statistical tests
+{cite}`Nickerson2017-gq`.
+
+```{seealso}
+- [Analysis outputs](../reference/outputs.md#analysis-outputs) — where each result is written
+- [Metric definitions](../reference/metrics.md) — precise definitions of the derived quantities
+- [How to assess data quality](../how_to/assess_data_quality.md) — checking these estimates are trustworthy
+```
diff --git a/docs/explanation/confound_correction.md b/docs/explanation/confound_correction.md
new file mode 100644
index 00000000..6dd7a2f3
--- /dev/null
+++ b/docs/explanation/confound_correction.md
@@ -0,0 +1,181 @@
+# The confound correction workflow
+
+(confound_pipeline_target)=
+
+```{figure} ../pics/confound_correction.png
+:alt: Diagram of the RABIES confound correction workflow
+
+The confound correction workflow. Steps are applied in the order shown.
+```
+
+The confound correction workflow brings together a broad set of standard tools
+from the human literature. Each step's implementation follows best practices
+and is structured to prevent the re-introduction of confounds, as recommended
+in {cite}`Power2014-yf` and {cite}`Lindquist2019-lq`.
+
+Every operation is optional except detrending, and a set of operations can be
+selected to design a customised workflow.
+
+```{important}
+There is no universally optimal correction strategy. The right one is
+dataset-specific and should be tuned to address quality issues you have
+actually identified in your data — see
+[Data quality assessment](data_quality.md) and
+[How to optimise your confound correction strategy](../how_to/optimise_confound_correction.md).
+```
+
+## 1. Frame censoring
+
+`--frame_censoring`
+
+Frame censoring temporal masks are derived from FD and/or DVARS thresholds and
+applied to the BOLD timeseries **first**, before any other correction step, to
+exclude signal spikes which would otherwise bias detrending, frequency
+filtering and confound regression {cite}`Power2014-yf`.
+
+Censoring with framewise displacement
+: Applies frame censoring based on a [framewise displacement](FD_target)
+ threshold. Frames exceeding the threshold, together with 1 frame back and 2
+ frames forward, are masked out {cite}`Power2012-ji`.
+
+Censoring with DVARS
+: The [DVARS](DVARS_target) values are z-scored
+ ($DVARS_Z = \frac{DVARS-\mu}{\sigma}$, where $\mu$ is the mean DVARS across
+ time and $\sigma$ the standard deviation), and frames with $|DVARS_Z|>2.5$
+ are removed. Z-scoring and outlier detection are repeated within the
+ remaining frames, iteratively, until no further outlier is detected.
+
+`--match_number_timepoints`
+: Constrains every scan to retain the same final number of frames, to avoid
+ downstream effects of unequal temporal degrees of freedom (tDOF) on analysis.
+ A pre-set final number of frames is defined with `minimum_timepoint`, and the
+ surplus frames remaining after censoring — accounting for the edge removal in
+ step 4 — are selected at random and removed.
+
+## 2. Detrending
+
+`--detrending_order`
+
+Linear, or optionally quadratic, trends are removed from the timeseries.
+Detrended timeseries $\hat{Y}$ are obtained by ordinary least squares (OLS)
+linear regression:
+
+$$
+\beta = OLS(X,Y)
+$$
+
+$$
+\hat{Y} = Y - X\beta
+$$
+
+where $Y$ is the timeseries and the predictors are
+$X = [intercept, time, time^2]$, with $time^2$ included only when removing
+quadratic trends.
+
+## 3. ICA-AROMA
+
+`--ica_aroma`
+
+Cleaning of motion-related sources using the ICA-AROMA {cite}`Pruim2015-nm`
+classifier. The hard-coded human priors for anatomical masking and the linear
+coefficients for classification were adapted from the
+[original code](https://github.com/maartenmennes/ICA-AROMA) to function with
+rodent images.
+
+ICA-AROMA is applied *before* frequency filtering, to remove effects of motion
+that would otherwise produce ringing after filtering
+{cite}`Carp2013-uf,Pruim2015-nm`.
+
+## 4. Frequency filtering
+
+`--TR` / `--highpass` / `--lowpass` / `--edge_cutoff`
+
+Simulating censored timepoints
+: Frequency filtering needs special handling after frame censoring, because
+ conventional filters cannot handle missing data. RABIES implements the method
+ of {cite}`Power2014-yf`, which simulates data points while preserving the
+ frequency composition of the data. It relies on an adaptation of the
+ Lomb-Scargle periodogram, which estimates the frequency composition of the
+ timeseries despite missing data points; from that estimate, missing
+ timepoints are simulated with the frequency profile preserved
+ {cite}`Mathias2004-rt`.
+
+Butterworth filter
+: Following the simulation, highpass and/or lowpass filtering is applied using
+ a 3rd-order Butterworth filter
+ ([`scipy.signal.butter`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.butter.html)).
+ After filtering, the temporal mask from censoring is re-applied to remove the
+ simulated timepoints.
+
+ ```{tip}
+ When applying a highpass filter, remove 30 seconds at each end of the
+ timeseries with `--edge_cutoff` to account for edge artefacts
+ {cite}`Power2014-yf`.
+ ```
+
+(CR_target)=
+
+## 5. Confound regression
+
+`--nuisance_regressors`
+
+For each voxel timeseries, a selected set of
+[nuisance regressors](regressor_target) is modelled using OLS linear regression
+and their modelled contribution to the signal is removed. Regressed timeseries
+$\hat{Y}$ are obtained with
+
+$$\beta = OLS(X,Y)$$
+
+$$ Y_{CR} = X\beta $$
+
+$$ \hat{Y} = Y - Y_{CR} $$
+
+where $Y$ is the timeseries, $X$ is the set of nuisance timecourses, and
+$Y_{CR}$ is the confound timeseries predicted from the model at each voxel — a
+time-by-voxel 2D matrix.
+
+## 6. Intensity scaling
+
+`--image_scaling`
+
+Voxel intensity values should be scaled to improve comparability between scans
+and datasets. The available options:
+
+Grand mean
+: **Recommended.** Timeseries are divided by the mean intensity across the
+ brain, then multiplied by 100 to obtain percent BOLD deviations from the
+ mean. The mean intensity of each voxel is derived from the $\beta$
+ coefficient of the intercept computed during **Detrending**.
+
+Voxelwise mean
+: As grand mean, but each voxel is independently scaled by its own mean signal.
+
+Global standard deviation
+: Timeseries are divided by the total standard deviation across all voxel
+ timeseries.
+
+Voxelwise standardization
+: Each voxel is divided by its own standard deviation.
+
+Homogenize variance voxelwise
+: With `--scale_variance_voxelwise`, and only if no voxelwise scaling was
+ already applied, timeseries are first scaled voxelwise by their standard
+ deviation — yielding a homogeneous variance distribution across voxels — and
+ then re-scaled to preserve the original total standard deviation of the
+ entire 4D timeseries, so the global standard deviation does not change.
+ Inhomogeneous variability distribution can be a
+ [confound signature](quality_marker_target), so this option may downscale its
+ impact. It can be combined with grand mean scaling.
+
+## 7. Smoothing
+
+`--smoothing_filter`
+
+Timeseries are spatially smoothed using a Gaussian smoothing filter
+([`nilearn.image.smooth_img`](https://nilearn.github.io/dev/modules/generated/nilearn.image.smooth_img.html)).
+
+```{seealso}
+- [Nuisance regressor definitions](regressor_target) — what each regressor contains
+- [`init_confound_correction_wf`](wf_confound_correction) — the source docstring
+- [Confound correction outputs](../reference/outputs.md#confound-correction-outputs)
+```
diff --git a/docs/explanation/data_quality.md b/docs/explanation/data_quality.md
new file mode 100644
index 00000000..0ed17e9a
--- /dev/null
+++ b/docs/explanation/data_quality.md
@@ -0,0 +1,125 @@
+# Data quality assessment
+
+(analysis_QC_target)=
+
+Data quality can have serious impacts on analysis outcomes, leading to false
+findings. Rodent imaging can suffer from spurious effects on connectivity
+measures if potential confounds are not well accounted for, and acquisition
+factors such as anaesthesia level can themselves influence network activity
+{cite}`Desrosiers-Gregoire2024-ou,Grandjean2020-fa`.
+
+To support interpretability, troubleshooting and reproducible research, RABIES
+includes a set of reports for assessing data quality in individual scans and
+for conducting quality control before network analysis at the group level. The
+reports are designed specifically to evaluate two things: whether canonical
+brain networks are detectable, and how far potential confounds — motion,
+physiological instabilities, and others — have influenced the result.
+
+```{admonition} Where the practical instructions live
+:class: seealso
+
+This page explains what the reports are and how they relate to one another.
+For how to generate them, set inclusion thresholds and report your quality
+control in a publication, see
+[How to assess data quality](../how_to/assess_data_quality.md).
+```
+
+## The three reports
+
+The reports are generated by `--data_diagnosis` at the analysis stage, into
+[`data_diagnosis_datasink/`](diagnosis_datasink_target). Each addresses a
+different level of the problem.
+
+::::{grid} 1 1 3 3
+:gutter: 2
+
+:::{grid-item-card} Spatiotemporal diagnosis
+:link: diagnosis_target
+:link-type: ref
+
+Qualitative, per scan. Regroups temporal and spatial features that characterise
+the specific origin of a quality issue.
+:::
+
+:::{grid-item-card} Distribution plots
+:link: dist_plot_target
+:link-type: ref
+
+Quantitative, across the dataset. Shows where each scan falls on measures of
+network specificity, network amplitude and confounds — which is how outliers
+become visible.
+:::
+
+:::{grid-item-card} Group statistics
+:link: group_stats_target
+:link-type: ref
+
+Group level, per network. Brain maps of cross-scan variability in connectivity,
+and the group-wise correlation between connectivity and confounds.
+:::
+
+::::
+
+## Why three levels
+
+```{figure} ../pics/QC_framework.png
+:alt: The RABIES quality control framework
+
+The quality control framework. Each level conditions the validity of the next.
+```
+
+The three reports are not alternatives; they answer different questions, and
+they depend on each other in one direction.
+
+The **spatiotemporal diagnosis** tells you what is wrong with an individual
+scan — whether the signal variability carries an anatomical confound signature,
+whether the network is present at all, whether network and confound timecourses
+move together. It identifies the *type* of problem, which is what makes a
+targeted correction possible.
+
+The **distribution plots** turn those qualitative judgements into numbers you
+can threshold. Inspecting fifty scans by eye and deciding which are unusable is
+not reproducible; setting a Dice overlap and confound correlation threshold,
+and reporting them, is.
+
+The **group statistical report** asks the question that actually matters for a
+group analysis: is the *variability* in connectivity across scans driven by
+network activity, or by confounds? Scan-level features being acceptable does
+not by itself guarantee this.
+
+That last report depends on the first two. Either an absence of network
+activity or spurious effects in a subset of scans can drive apparent network
+variability, because there will be differences in the presence versus absence
+of the network across scans — differences actually driven by data quality
+divergences rather than by biology. This is why scan-level assumptions have to
+be met before the group-level report means anything.
+
+## What the reports need
+
+The reports are built on a set of ICA components that must be classified into
+networks of interest and confound sources. Ideally the components are derived
+from the dataset being analysed, using [group ICA](ICA_target); a pre-computed
+set for mice is available by default.
+
+Connectivity can be evaluated for [dual regression](DR_target), for
+[seed-based connectivity](SBC_target), or for both. Dual regression is always
+run internally regardless, because several report features are derived from the
+confound components.
+
+```{seealso}
+For guidance on classifying ICA components in rodents, consult
+{cite}`Zerbi2015-nl` and {cite}`Desrosiers-Gregoire2024-ou`.
+```
+
+## A note on judgement
+
+These reports and the guidelines built around them aim to identify analysis
+pitfalls and improve research transparency. They are not meant to be
+prescriptive.
+
+The judgement of the experimenter is paramount in adopting adequate practices.
+Network detectability is not always expected — not when studying the impact of
+anaesthesia, nor when inspecting a visual network in blind subjects. The
+conversation about what should constitute proper standards for resting-state
+fMRI is still evolving, and these tools are a contribution to it rather than a
+settlement of it.
diff --git a/docs/explanation/distribution_plot.md b/docs/explanation/distribution_plot.md
new file mode 100644
index 00000000..27ef18cf
--- /dev/null
+++ b/docs/explanation/distribution_plot.md
@@ -0,0 +1,68 @@
+# The distribution plot
+
+(dist_plot_target)=
+
+```{figure} ../pics/distribution_plot.png
+:alt: Scatter plots of network connectivity measures against confound measures across scans
+
+Each point is a scan. Measures of network connectivity — specificity and
+amplitude — are contrasted with measures of confounds across the sample.
+```
+
+The distribution plot visualises the distribution of data quality measures
+across the dataset, turning the per-scan judgements from the
+[spatiotemporal diagnosis](diagnosis_target) into something you can threshold
+and report.
+
+Reading the plot:
+
+- Points labelled in **grey** were removed using `--scan_QC_thresholds`. The
+ grey dotted lines are the QC thresholds selected for network specificity
+ (Dice overlap) and DR confound correlation.
+- Among the remaining samples, and for each metric separately, scans presenting
+ outlier values are labelled in **orange**. Outliers are detected with a
+ modified Z-score threshold, set by `--outlier_threshold` and 3.5 by default.
+
+The derivation of each quality metric is described in the
+[metric definitions](dist_plot_metrics).
+
+## What the report is for
+
+The plot serves two distinct purposes.
+
+**Setting scan inclusion criteria.** Inspect that network specificity is
+sufficient and that the temporal correlation with confounds (DR confound corr.)
+is minimal, then set thresholds for scan inclusion with `--scan_QC_thresholds`.
+This is the top right subplot, discussed below.
+
+**Complementing the group statistical report.** Visualise the association
+between connectivity and the three confound measures included in the report —
+$CR_{SD}$, mean FD and tDOF. This lets you determine, for instance, whether a
+group-wise correlation in the [statistical report](group_stats_target) is
+driven by a small number of outliers rather than by a dataset-wide effect.
+
+## Scan-level thresholds
+
+```{figure} ../pics/scan_QC_thresholds.png
+:alt: Scan quality categories separated along network specificity and confound correlation axes
+
+Reproduced from {cite}`Desrosiers-Gregoire2024-ou`: how the
+[categories of scan quality outcome](quality_marker_target) separate along
+these two measures.
+```
+
+The measures of network specificity (Dice overlap) and temporal correlation
+with confounds — where confound timecourses are extracted using the confound
+components specified with `--prior_confound_idx` and measured through dual
+regression — were defined in {cite}`Desrosiers-Gregoire2024-ou` for conducting
+scan-level QC.
+
+They were selected as the measures best suited to quantifying network
+detectability and spurious connectivity, and to applying inclusion thresholds
+that select scans respecting the assumptions of network detectability and
+minimal confound effects.
+
+```{seealso}
+[How to assess data quality](../how_to/assess_data_quality.md) gives the
+`--scan_QC_thresholds` syntax and the procedure for choosing values.
+```
diff --git a/docs/explanation/group_statistics.md b/docs/explanation/group_statistics.md
new file mode 100644
index 00000000..24e68dd8
--- /dev/null
+++ b/docs/explanation/group_statistics.md
@@ -0,0 +1,78 @@
+# The group statistical report
+
+(group_stats_target)=
+
+```{figure} ../pics/group_stats_QC.svg
+:alt: Group-level maps of connectivity variability and its correlation with confound measures
+:width: 100%
+
+Group-level features of connectivity variability, for the mouse somatomotor
+network.
+```
+
+Inspecting scan-level features is not sufficient to conclude that inter-scan
+*variability* in connectivity is itself unaffected — and that variability is
+what a group analysis is primarily interested in. This report examines
+connectivity variability at the group level, along two axes.
+
+## Specificity of network variability
+
+The standard deviation in connectivity across scans is computed voxelwise,
+which visualises the spatial contrast of network variability.
+
+If that variability is primarily driven by network connectivity, the contrast
+should reflect the anatomical extent of the network of interest, as in the
+example above for the mouse somatomotor network. Otherwise it may display
+spurious or absent features. For more on the development of this metric,
+consult {cite}`Desrosiers-Gregoire2024-ou`.
+
+```{note}
+**The contrast depends on sample size.** {cite}`Desrosiers-Gregoire2024-ou`
+demonstrate this directly. If network connectivity is observed in individual
+scans but not in this statistical report, increasing the sample size may
+improve the contrast.
+```
+
+## Correlation with confounds
+
+Connectivity is correlated across subjects, at each voxel, with each of three
+confound measures:
+
+- the variance explained by confound correction at that voxel ($CR_{SD}$, from
+ the [predicted confound timeseries $Y_{CR}$](CR_target))
+- mean framewise displacement (FD)
+- temporal degrees of freedom (tDOF)
+
+This establishes how strongly connectivity is associated with potential
+confounds. What constitutes a *concerning* correlation depends on the study and
+on the effect size of interest: the question to ask is whether the effect size
+you are looking for is much larger than the effect size of the confounds, or
+comparable to it.
+
+## The quantitative CSV report
+
+A CSV file is generated alongside the figure, recording a quantitative
+assessment of both aspects. The overlap between the network variability map and
+the reference network map is measured using Dice overlap; for the confound
+measures, the mean correlation is measured within the area of the network. See
+the [group QC metric definitions](group_QC_metrics).
+
+These measures can be consulted for a quantitative summary, though visualisation
+is preferred — the Dice overlap for network variability may not perfectly
+distinguish network features from spurious ones.
+
+```{important}
+The validity of this report depends on whether the
+[scan-level assumptions](dist_plot_target) of network detectability and
+minimal confound effects are met.
+
+Either a lack of network activity or spurious effects in a subset of scans can
+drive *apparent* network variability, because there will be differences in the
+presence versus absence of the network across scans — but those differences
+would be driven by data quality divergences rather than by biology.
+```
+
+```{seealso}
+[How to assess data quality](../how_to/assess_data_quality.md) — the full
+quality control workflow this report sits at the end of.
+```
diff --git a/docs/explanation/index.md b/docs/explanation/index.md
new file mode 100644
index 00000000..fd62833b
--- /dev/null
+++ b/docs/explanation/index.md
@@ -0,0 +1,39 @@
+# Explanation
+
+Background and discussion of how RABIES works and why it was built this way.
+These pages are for understanding, not for following along — read them away
+from the keyboard.
+
+## The processing stages
+
+RABIES is structured into three stages that run in sequence, each consuming the
+previous one's output.
+
+```{toctree}
+---
+maxdepth: 1
+---
+preprocessing
+confound_correction
+analysis
+```
+
+## Assessing data quality
+
+Confound correction cannot be designed blind. RABIES generates a set of reports
+for characterising data quality and its impact on connectivity estimates.
+
+```{toctree}
+---
+maxdepth: 1
+---
+data_quality
+scan_diagnosis
+distribution_plot
+group_statistics
+```
+
+```{seealso}
+The full methodological account is in the RABIES publication,
+{cite}`Desrosiers-Gregoire2024-ou`.
+```
diff --git a/docs/explanation/preprocessing.md b/docs/explanation/preprocessing.md
new file mode 100644
index 00000000..b73ea612
--- /dev/null
+++ b/docs/explanation/preprocessing.md
@@ -0,0 +1,180 @@
+# The preprocessing workflow
+
+```{figure} ../pics/preprocessing.png
+:alt: Diagram of the RABIES preprocessing workflow
+
+The RABIES preprocessing workflow. Bold labels correspond to the module names
+used throughout this page.
+```
+
+Preprocessing fMRI scans prior to analysis requires, at minimum, anatomical
+alignment of scans to a common space, head realignment to correct for motion,
+and correction of the susceptibility distortions arising from the echo-planar
+imaging (EPI) acquisition of functional scans. The core preprocessing pipeline
+in RABIES carries out each of these with state-of-the-art processing tools and
+techniques.
+
+## Getting the scans into a common space
+
+Structural images, acquired alongside the EPI scans, are initially corrected
+for inhomogeneities (**Structural inhomogeneity correction**) and then
+registered together so that different MRI acquisitions can be aligned.
+
+That registration works by generating an unbiased, data-driven template
+(**Unbiased template generation**) through the iterative non-linear
+registration of each image to the dataset consensus average, where the average
+is updated at each iteration to provide an increasingly representative dataset
+template ([optimized_antsMultivariateTemplateConstruction](https://github.com/CoBrALab/optimized_antsMultivariateTemplateConstruction);
+{cite}`Avants2011-av`).
+
+The finalised template, after the last iteration, provides a representative
+alignment of each MRI session to a template sharing the acquisition properties
+of the dataset — brain shape, field of view, anatomical contrast — which makes
+it a stable registration target for cross-subject alignment. This
+newly-generated unbiased template is then itself registered to an external
+reference atlas (**Atlas registration**), which supplies both an anatomical
+segmentation and a common space comparable across studies.
+
+```{note}
+This is why RABIES builds a study-specific template rather than registering
+every scan directly to the atlas: the intermediate target resembles your data,
+so each individual registration has less work to do and is less likely to
+fail. The cost is computation time, which is why `fast_commonspace=true`
+exists to skip it.
+```
+
+## Getting the EPI corrected
+
+A volumetric EPI image is first derived using a trimmed mean across the EPI
+frames, after an initial motion realignment step (**3D EPI generation**). Using
+this volumetric EPI as a target, the head motion parameters are estimated by
+realigning each EPI frame to the target with a rigid registration
+(**Head motion estimation**).
+
+To correct EPI susceptibility distortions, the volumetric EPI is first
+subjected to an inhomogeneity correction step
+(**Functional inhomogeneity correction**), then registered non-linearly to the
+anatomical scan from the same MRI session, which yields the geometrical
+transforms required to recover brain anatomy {cite}`Wang2017-ci`
+(**Susceptibility distortion estimation**).
+
+Finally, the transforms correcting head motion and susceptibility distortions
+are concatenated into a single resampling operation — avoiding multiple
+resampling — applied at each EPI frame, generating the preprocessed EPI
+timeseries in native space {cite}`Esteban2019-rs` (**Frame-wise resampling**).
+Preprocessed timeseries in common space are generated by further concatenating
+the transforms that resample to the reference atlas.
+
+```{important}
+Concatenating the transforms matters. Resampling an image is lossy, so
+applying motion correction and then distortion correction as two separate
+resampling steps blurs the data twice. RABIES composes the transforms first
+and resamples once.
+```
+
+## Each module in turn
+
+### Structural inhomogeneity correction
+
+```{figure} ../pics/sub-MFC067_ses-1_acq-FLASH_T1w_inho_cor.png
+:alt: Four-column figure showing the stages of structural inhomogeneity correction
+
+The steps of inhomogeneity correction for the structural image.
+```
+
+Implemented by
+[`init_inho_correction_wf`](wf_inho_correction).
+
+### Common space alignment
+
+Unbiased template generation followed by atlas registration.
+
+```{figure} ../pics/sub-MFC067_ses-1_acq-FLASH_T1w_inho_cor_registration.png
+:alt: Overlap between a structural scan and the dataset-generated unbiased template
+
+Overlap between a structural scan (top) and the dataset-generated unbiased
+template (bottom).
+```
+
+```{figure} ../pics/atlas_registration.png
+:alt: Overlap between the unbiased template and the reference atlas template
+
+Overlap between the unbiased template (top) and the reference atlas template
+(bottom).
+```
+
+Implemented by
+[`init_commonspace_reg_wf`](wf_commonspace_reg).
+
+(3D_EPI_target)=
+
+### 3D EPI generation
+
+Implemented by
+[`init_bold_reference_wf`](wf_bold_ref).
+
+### Head motion estimation
+
+```{figure} ../pics/example_motion_parameters.png
+:alt: Timecourses of the six rigid-body head motion parameters
+
+Example of the 6 motion parameters.
+```
+
+Implemented by
+[`init_bold_hmc_wf`](wf_hmc)
+and
+[`EstimateMotionParams`](wf_motion_params).
+
+### Functional inhomogeneity correction
+
+```{figure} ../pics/sub-MFC068_ses-1_task-rest_acq-EPI_run-1_bold_inho_cor.png
+:alt: Four-column figure showing the stages of EPI inhomogeneity correction
+
+The steps of inhomogeneity correction for the volumetric EPI.
+```
+
+The workflow is the same as for **structural inhomogeneity correction**.
+
+### Susceptibility distortion estimation
+
+```{figure} ../pics/sub-MFC068_ses-1_task-rest_acq-EPI_run-1_bold_registration.png
+:alt: Overlap between the volumetric EPI and the structural image
+
+Overlap between the volumetric EPI (top) and the structural image (bottom).
+```
+
+Implemented by
+[`init_cross_modal_reg_wf`](wf_cross_modal_reg).
+
+### Frame-wise resampling
+
+Implemented by
+[`init_bold_preproc_trans_wf`](wf_bold_resampling),
+with masks and labels handled by
+[`init_mask_preproc_trans_wf`](wf_mask_resampling).
+
+## Working without structural scans
+
+Structural scans are recommended but not required. An alternative workflow,
+selected with `--bold_only`, preprocesses an input dataset containing only EPI
+functional images.
+
+In this workflow the volumetric EPI corrected during
+**Functional inhomogeneity correction** replaces the structural image for the
+purpose of common space alignment, and is used to generate the unbiased
+template, which is in turn registered to the reference atlas. This final
+registration to the atlas accounts for the estimation of susceptibility
+distortions, in place of the registration to a same-session structural image.
+
+```{note}
+When using the RABIES default mouse atlas, `--bold_only` also switches the
+default template to an EPI reference template, which is a more robust target
+for EPI registration than a structural reference.
+```
+
+```{seealso}
+- [Preprocessing QC outputs](../reference/qc_outputs.md) — how to verify each step succeeded
+- [How to troubleshoot registration](../how_to/troubleshoot_registration.md) — what to do when one did not
+- [Workflow reference](../reference/workflows.md) — the source docstrings for every module above
+```
diff --git a/docs/explanation/scan_diagnosis.md b/docs/explanation/scan_diagnosis.md
new file mode 100644
index 00000000..a3ae2223
--- /dev/null
+++ b/docs/explanation/scan_diagnosis.md
@@ -0,0 +1,187 @@
+# The spatiotemporal diagnosis
+
+(diagnosis_target)=
+
+The spatiotemporal diagnosis is a visual report generated for each scan
+independently, after dual regression or seed-based connectivity analysis. It
+displays a large set of temporal and spatial features for that scan, supporting
+assessment of potential data quality issues and of whether network connectivity
+has been affected.
+
+It is generated by `--data_diagnosis` at the analysis stage, into
+`data_diagnosis_datasink/figure_temporal_diagnosis/` and
+`data_diagnosis_datasink/figure_spatial_diagnosis/`.
+
+```{note}
+Unless stated otherwise, all metrics are computed from fMRI timeseries **after**
+the confound correction stage.
+```
+
+## An example report
+
+```{figure} ../pics/spatiotemporal_diagnosis.png
+:alt: The spatiotemporal diagnosis report for a scan with clear network connectivity
+
+A scan with little confound signature and clear network connectivity. Each
+spatial map is shown along 6 cortical slices, overlapped onto the anatomical
+template in common space.
+```
+
+In this example both dual regression and seed-based connectivity were
+conducted: DR network 0 and SBC network 1 correspond to analysis of the
+somatomotor network, while DR network 1 and SBC network 0 correspond to the
+default mode network. Network maps from dual regression (DR) or seed-based
+connectivity (SBC) are thresholded to include the top X% of voxels with the
+highest values, X% being defined by `--brainmap_percent_threshold`.
+
+The features are detailed below. For the exact computation behind each one, see
+[Metric definitions](metrics_target).
+
+### Temporal features, top to bottom
+
+**Power spectrum**
+: The frequency power spectrum, showing the dominant frequency profile. Always
+ shown averaged across the whole brain; spectra for individual seeds can be
+ added with `--plot_seed_frequencies`.
+
+**Carpet plot**
+: The entire fMRI timeseries as a time-by-voxel 2D matrix. This makes global
+ fluctuations in signal intensity visible, which is a proxy for various global
+ artefacts {cite}`Power2017-wn`. Censored frames are labelled in red.
+
+**Translation and rotation head motion parameters**
+: The 6 rigid body parameters estimated during preprocessing, tracking head
+ position across the scan duration.
+
+**Framewise distance from the mean image**
+: The mean square error between each frame and the average EPI, computed as the
+ tri-mean across time voxelwise, and computed **prior to** confound correction
+ to map changes in brain contrast over time. This complements framewise
+ displacement, since it captures changes in raw image contrast across time
+ that remain after head motion realignment and might not be well captured by
+ framewise displacement. The metric is also output by `--hmc_qc_report` at the
+ `preprocess` stage, and can be used for censoring via `--frame_censoring` at
+ the `confound_correction` stage.
+
+**Framewise displacement and DVARS** {cite}`Power2012-ji`
+: Framewise displacement quantifies movement between consecutive frames,
+ revealing the timing and amplitude of spontaneous motion. DVARS — the
+ root-mean-square of the timeseries' temporal derivative — reveals shifts in
+ global fMRI signal intensity, which can also indicate suspicious spikes in
+ signal.
+
+**Variance captured and removed by confound regression**
+: The linear model fitted during nuisance regression provides an estimate of
+ the nuisance timeseries, from which the variance removed at each frame can be
+ quantified. The report displays the absolute variance, as the RMS of the
+ nuisance timeseries across voxels for each frame, and the relative variance
+ removed, as the $R^2$ at each frame. Together these visualise confound
+ effects and show whether confound regression appropriately modelled the
+ confounds detected in the other temporal features.
+
+**Mean signals within anatomical masks**
+: The mean timecourse within the whole-brain, edge, white matter and CSF masks.
+ The edge, WM and CSF regions are susceptible to motion and physiological
+ confounds {cite}`Pruim2015-nm`, and contrasting them with the whole-brain
+ global signal helps assess artefactual effects across the brain.
+
+**Mean amplitude of network vs confound timecourses**
+: The averaged timecourses for network analyses and for confound sources are
+ compared, to assess whether network amplitude is spurious — that is,
+ correlated with the confound timecourse. Confound timecourses are modelled by
+ running dual regression with a complete set of ICA components representing a
+ mixture of networks and confounds of various origins, and compiling the
+ timecourses from the confound components. RABIES uses
+ [this set](https://zenodo.org/records/19069284/files/melodic_IC.nii.gz) of
+ ICA components for mice by default.
+
+### Spatial features, top to bottom
+
+**Spatial distribution in signal variability (BOLDSD)**
+: The signal variability, i.e. standard deviation, at each voxel. This map
+ indexes whether significant confounds are contributing to the signal. Without
+ influence from confounds, as in the example above, signal variability is
+ largely homogeneous.
+
+**Confound regression variance explained (CRSD)**
+: The variance explained by confound regression at each voxel, taken as the
+ standard deviation of the modelled confound timecourse. This contrasts the
+ amplitude of confound effects spatially, and can specifically delineate the
+ presence of confounds and identify their type. In the example, minor motion
+ signatures are identified.
+
+**Confound regression variance explained proportion**
+: As CRSD, but showing the proportion of variance explained ($R^2$).
+
+**Global signal covariance**
+: The covariance of each voxel with the global signal. The contrast in this map
+ reveals the predominant source of global signal fluctuation, which takes
+ various forms depending on the contributions from neural networks and from
+ confounds. In the ideal case there is predominant contrast in grey matter,
+ with a shape reminiscent of a brain network, as in the example above.
+
+**Network spatial maps**
+: The spatial network maps fitted using dual regression, or seed-based
+ analysis, for the selected networks of interest — in the example, the
+ somatomotor and default mode networks. These fits give insight into the
+ quality of the network analysis and how it may affect downstream statistics.
+
+```{note}
+$CR_{SD}$ and $CR_{R^2}$ are computed from the regressors specified with
+`--nuisance_regressors` during confound correction. If no regressors are
+specified, they are still estimated using regression on the 6 motion
+parameters — but that regression is not applied to remove signal from the
+timeseries.
+```
+
+(quality_marker_target)=
+
+## The four key quality markers
+
+```{figure} ../pics/diagnosis_key_markers.png
+:alt: Four key diagnostic features shown across four categories of scan quality
+
+Four features across four categories of scan quality.
+```
+
+A subset of the features above are the most decisive in determining scan
+quality in relation to connectivity analysis. They are shown here across the 4
+main categories of scan quality.
+
+**BOLD variability**
+: Presents a homogeneous contrast in uncorrupted scans, and otherwise reveals
+ the anatomical signature of a confound — which is what allows the type of
+ confound to be identified.
+
+**Global signal covariance**
+: Sensitive to both non-neural confounds (the *spurious* category) and network
+ signatures (the *specific* category). It therefore reflects whether network
+ or confound sources dominate coordinated fluctuations, and delineates the
+ most likely contributors to downstream connectivity measures.
+
+**Network map**
+: Shows whether the expected anatomical features of the network are effectively
+ captured, i.e. network specificity. This is what establishes that the network
+ is not absent (the *absent* category), and that its shape is not distorted by
+ spurious features (the *spurious* category).
+
+**Network and confound timecourses**
+: The respective timecourses reveal direct relationships between network
+ amplitude and confounds in the temporal domain. This does not describe the
+ *type* of confound, but it is the most direct indicator of spurious
+ connectivity, and an important complement to inspecting network shape —
+ spurious effects can affect amplitude while leaving shape largely intact.
+
+These 4 features are sufficient to capture the essential characteristics of
+network detectability and spurious connectivity at the single scan level. The
+remaining features provide additional detail about timeseries properties,
+motion parameters and confound regression, and further support characterising
+the specific origin of a confound — for example, establishing that a
+correlation between network and confound timecourses originates from framewise
+displacement, i.e. from motion.
+
+```{seealso}
+- [How to assess data quality](../how_to/assess_data_quality.md) — acting on what you see here
+- [Distribution plot](distribution_plot.md) — turning these judgements into thresholds
+- [Metric definitions](metrics_target) — the computation behind each feature
+```
diff --git a/docs/faq.md b/docs/faq.md
deleted file mode 100644
index 9e4c2800..00000000
--- a/docs/faq.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# FAQ
-
-## How do I run minimal preprocessing?
-
-Some users arrive with functional data that was already preprocessed with their own pipeline, and only want to use RABIES for confound correction and analysis.
-
-Running `rabies confound_correction` directly on such data fails with missing `.pkl` file errors. Those `.pkl` files are serialized states of the internal preprocessing workflow and cannot be written by hand. Even with the `.pkl` in place, the confound correction stage expects the full range of output files produced by the preprocessing stage, so missing file errors would follow.
-
-The practical solution is to run a *SHAM* preprocessing, in which the correction and registration steps are turned off. RABIES still computes the intermediary outputs that the confound correction and analysis stages require, while leaving the image data largely unchanged. It is not a strict pass-through, however, and the operations which remain applied are described under *What still happens* below:
-
-```sh
-rabies preprocess bids_inputs/ preprocess_outputs/ \
- --anat_inho_cor method=disable \
- --bold_inho_cor method=disable \
- --commonspace_reg template_registration=no_reg,fast_commonspace=true \
- --bold2anat_coreg registration=no_reg \
- --no_HMC
-```
-
-| Parameter | What it turns off |
-|---|---|
-| `--anat_inho_cor method=disable` | inhomogeneity correction of the structural images |
-| `--bold_inho_cor method=disable` | inhomogeneity correction of the EPI images |
-| `--commonspace_reg template_registration=no_reg,fast_commonspace=true` | unbiased template generation, and the registration to the reference atlas (an identity transform is used instead) |
-| `--bold2anat_coreg registration=no_reg` | EPI-to-structural coregistration, i.e. the susceptibility distortion correction |
-| `--no_HMC` | the *application* of head motion correction to the resampled timeseries. Head motion parameters are still estimated and remain available to `--conf_list`, `--frame_censoring` and `--data_diagnosis` |
-
-If your dataset has no structural scans, add `--bold_only`, in which case `--anat_inho_cor` and `--bold2anat_coreg` no longer apply.
-
-### Caveat: your data must already be in commonspace
-
-Setting `template_registration=no_reg` does not skip the resampling to commonspace, it replaces the estimated transform with an identity transform. The commonspace outputs are therefore only meaningful if your input images already overlap with the template provided through `--anat_template`, which is the file that defines the commonspace. If they do not overlap, the commonspace timeseries and the atlas masks (`--brain_mask`, `--WM_mask`, `--CSF_mask`, `--vascular_mask`) applied downstream will not correspond to your data.
-
-Image orientation is worth confirming before you start, see [Troubleshooting](troubleshooting.md).
-
-### What still happens
-
-Operations which alter the data but are off by default stay off, and should not be added: `--apply_STC`, `--apply_despiking`, `--detect_dummy`, `--log_transform`, `--anat_autobox`, `--bold_autobox` and `--oblique2card`.
-
-The timeseries are still resampled onto the output grid, using the identity transforms described above. Use `--commonspace_resampling` and `--anatomical_resampling` to control the output voxel dimensions, and `--interpolation` to select the interpolator.
-
-Two further operations are applied unconditionally and cannot be turned off:
-
-* **Negative values are clipped to zero** when the preprocessed timeseries are written out. If your data legitimately contains negative values, for instance because it was already demeaned or detrended by your own pipeline, those voxels will be set to zero. Bring in data on a positive scale, and leave centering to `--detrending` at the confound correction stage.
-* **The output is cast** to the type given by `--data_type`, which is `float32` by default.
-
-A SHAM preprocessing is therefore a minimal pass, not a strictly non-modifying one.
-
-### Alternative: `--read_datasink`
-
-`rabies confound_correction --read_datasink` reads the preprocessing outputs from the datasink folders rather than from the saved workflow graph, which removes the need for the `.pkl` file. This requires reproducing the RABIES preprocessing output structure and file naming exactly, and is generally more work than running a SHAM preprocessing.
-
-### Still not covered?
-
-If your use case needs settings that are not exposed, open a [discussion](https://github.com/CoBrALab/RABIES/discussions) describing explicitly what you need. Providing example data lets us work out an implementation supporting your use case.
diff --git a/docs/how_to/assess_data_quality.md b/docs/how_to/assess_data_quality.md
new file mode 100644
index 00000000..4c983af3
--- /dev/null
+++ b/docs/how_to/assess_data_quality.md
@@ -0,0 +1,172 @@
+# How to assess data quality
+
+This guide covers generating the RABIES data quality reports, using them to
+decide which scans to keep, and reporting what you did in a publication. For
+what the reports mean and why they exist, see
+[Data quality assessment](../explanation/data_quality.md).
+
+The guidance below is written for a standard resting-state fMRI design in which
+you compare network connectivity between subjects or groups. The aim is to
+identify features of spurious or absent connectivity, remove the scans where
+those features dominate, and establish whether the remaining issues confound
+your group statistics.
+
+## Generate the reports
+
+Pass `--data_diagnosis` at the analysis stage. It needs a set of ICA components
+via `--prior_maps`, with the components corresponding to confounds identified
+through `--prior_confound_idx`:
+
+```sh
+rabies -p MultiProc analysis confound_correction_outputs/ analysis_outputs/ \
+ --data_diagnosis \
+ --prior_maps melodic_IC.nii.gz \
+ --prior_bold_idx 5 12 19 \
+ --prior_confound_idx 0 1 2 6 7 8 \
+ --DR_ICA
+```
+
+The reports appear in
+[`data_diagnosis_datasink/`](../reference/outputs.md#analysis-outputs).
+
+Connectivity can be evaluated for either analysis, or both:
+
+For [dual regression](DR_target)
+: Dual regression is always run using the full set of components from
+ `--prior_maps`, because several report features are derived from the confound
+ components named in `--prior_confound_idx`. Connectivity itself is evaluated for
+ each network listed in `--prior_bold_idx`.
+
+For [seed-based connectivity](SBC_target)
+: A report is generated for each seed given to `--seed_list`. Each seed must be
+ accompanied by a reference network map — a 3D NIfTI file per seed, passed
+ through `--seed_prior_list` — representing the connectivity expected for the
+ canonical network that seed belongs to.
+
+### Classify your group ICA components
+
+Ideally the components come from the dataset you are analysing, derived with
+[group ICA](ICA_target). A
+[pre-computed set](https://zenodo.org/records/19069284/files/melodic_IC.nii.gz)
+for mice is used by default.
+
+Newly generated components must be inspected visually to identify which
+correspond to confound sources. Visualise `group_melodic.ica/melodic_IC.nii.gz`,
+or use the FSL report generated automatically in `group_melodic.ica/report`.
+Pass the confound components to `--prior_confound_idx` and the networks of interest
+to `--prior_bold_idx`.
+
+```{tip}
+Classify conservatively. Not every component needs a label — include only
+those with a clear feature delineating a network or a confound. The defaults
+for `--prior_bold_idx` and `--prior_confound_idx` correspond to the classification
+of the pre-computed set, which you can consult as a reference.
+
+For guidance on classifying ICA components in rodents, see
+{cite}`Zerbi2015-nl` and {cite}`Desrosiers-Gregoire2024-ou`.
+```
+
+## Work through the reports
+
+```{figure} ../pics/QC_framework.png
+:alt: The RABIES quality control framework, from scan-level diagnosis to group statistics
+
+The quality control framework: scan-level diagnosis feeds scan inclusion
+decisions, which in turn condition the validity of the group-level report.
+```
+
+### 1. Inspect each scan
+
+Read the [spatiotemporal diagnosis](diagnosis_target) for every scan. Pay
+particular attention to the four main quality markers that define the
+[categories of scan quality](quality_marker_target), and judge whether features
+of spurious or absent connectivity are prominent.
+
+### 2. Remove scans with spurious or absent connectivity
+
+If those features are prominent in a subset of scans, remove those scans to
+mitigate false results. Set thresholds with `--scan_QC_thresholds` on the
+scan-level measures of network specificity and confound correlation:
+
+```sh
+rabies -p MultiProc analysis confound_correction_outputs/ analysis_outputs/ \
+ --data_diagnosis \
+ --prior_maps melodic_IC.nii.gz \
+ --prior_bold_idx 5 12 19 --prior_confound_idx 0 1 2 6 7 8 --DR_ICA \
+ --scan_QC_thresholds '{DR:{Dice:[0.3,0.3,0.3],Conf:[0.25,0.25,0.25],Amp:false}}'
+```
+
+The value is a dictionary expression, quoted so the shell leaves it alone. Per
+analysis (`DR`, `SBC` or `NPR`) you can set:
+
+`Dice`
+: Minimum network detectability, as Dice overlap with the prior. A list of
+ values between 0 and 1, matched in order to `--prior_bold_idx` for DR and
+ NPR, or to `--seed_list` for SBC. Either give an empty list, or give exactly
+ as many thresholds as there are networks.
+
+`Conf`
+: Maximum temporal correlation with the dual regression confound timecourses.
+ Same list rules as `Dice`.
+
+`Amp`
+: `true` to automatically remove scans with outlier network amplitude, which
+ can indicate spurious connectivity {cite}`Nickerson2017-gq`.
+
+To pick sensible threshold values, consult the
+[distribution plots](dist_plot_target) and the accompanying CSV file, which
+gives the measures per scan ID.
+
+```{important}
+Scans excluded by `--scan_QC_thresholds` are excluded from the group
+statistical report, so the reports must be regenerated after you set the
+thresholds.
+```
+
+### 3. Check the group level
+
+Consult the [group statistical report](group_stats_target) to identify the main
+driver of connectivity variability across scans, and whether it relates
+primarily to network activity or to confounds.
+
+### 4. Revisit confound correction if needed
+
+If significant issues remain, redesign the confound correction stage —
+see [How to optimise your confound correction strategy](optimise_confound_correction.md).
+
+```{admonition} These guidelines are not prescriptive
+:class: caution
+
+They are meant to support identifying analysis pitfalls and improving research
+transparency. The judgement of the experimenter is paramount: network
+detectability is not always expected, for instance when studying the impact of
+anaesthesia or inspecting a visual network in blind subjects. The conversation
+about what should constitute proper standards for resting-state fMRI is still
+evolving.
+```
+
+## Report your quality control in a publication
+
+Every figure in the report is generated as PNG or SVG and can be shared
+alongside a publication.
+
+Share, at minimum:
+
+- A spatiotemporal diagnosis for each scan used to derive connectivity results.
+- A group statistical report and its affiliated distribution plot, for each
+ group or dataset, if the analysis compares connectivity across subjects
+ and/or groups.
+- The set of ICA components classified as networks and confounds — for example
+ the `melodic_IC.nii.gz` file, with its component classification.
+
+If you excluded scans based on the guidelines above, describe the observations
+that motivated your criteria and make the associated reports accessible: the
+spatiotemporal diagnoses for the scans that displayed spurious or absent
+connectivity and motivated a particular `--scan_QC_thresholds` value. If you
+designed your confound correction using these tools, report that too.
+
+```{seealso}
+- [Data quality assessment](../explanation/data_quality.md) — what these reports are for
+- [Metric definitions](../reference/metrics.md) — how every quantity is computed
+- [Analysis outputs](../reference/outputs.md#analysis-outputs) — where each file lands
+```
diff --git a/docs/how_to/check_orientation.md b/docs/how_to/check_orientation.md
new file mode 100644
index 00000000..9c82b72b
--- /dev/null
+++ b/docs/how_to/check_orientation.md
@@ -0,0 +1,57 @@
+# How to check image orientation
+
+RABIES assumes input data is oriented according to the NIfTI standard (RAS+,
+i.e. Right–Anterior–Superior). Incorrectly oriented images are one of the most
+common causes of registration failure and of results that look wrong for no
+apparent reason, because the ANTs/ITK tools RABIES calls will happily register
+a mis-oriented brain to the template and produce nonsense.
+
+```{important}
+Check orientation before you report a bug, and before you start
+troubleshooting anything else. It costs five minutes and rules out the most
+likely explanation.
+```
+
+## Check with ITK-SNAP
+
+[ITK-SNAP](https://www.itksnap.org/pmwiki/pmwiki.php) is a free, open-source
+medical image viewer that reads NIfTI orientation information correctly. Other
+viewers do not always, which is why it is the recommended tool here.
+
+1. **Open your image.** *File → Open Main Image…*, and load your NIfTI
+ anatomical scan.
+
+2. **Check the anatomy is where you expect it.** ITK-SNAP shows axial, coronal
+ and sagittal views. The nose should be anterior, the top of the head
+ superior.
+
+3. **Compare against your reference template.** Open the atlas you intend to
+ pass to `--anat_template` (SIGMA, DSURQE, Fischer rat, whichever applies) in
+ a second ITK-SNAP window. Structures should appear in similar positions, and
+ the orientation labels should match.
+
+4. **Check the orientation labels.** Each view is labelled **R/L**, **A/P** and
+ **S/I**. Confirm each corresponds to the real anatomical direction in your
+ scan, then move the cursor: the crosshair should track consistently across
+ all three views, so that dragging towards the label **R** moves towards
+ anatomical right.
+
+If any of these disagree, the orientation stored in your NIfTI header does not
+describe your data, and you need to fix it before running RABIES. This is
+usually introduced during conversion from the scanner format.
+
+```{seealso}
+For Bruker data, [BrkRaw](https://brkraw.github.io/) handles the raw-to-NIfTI
+conversion; the CoBrALab maintains
+[notes on the conversion](https://github.com/CoBrALab/documentation/wiki/bruker2nifti-conversion).
+```
+
+## If orientation is correct and registration still fails
+
+Move on to [How to troubleshoot registration](troubleshoot_registration.md),
+which covers tuning inhomogeneity correction, masking and registration stages.
+Read the [preprocessing QC report](../reference/qc_outputs.md) first, to
+establish which registration step is the one that failed.
+
+When you do report a problem, follow the
+[issue template](https://github.com/CoBrALab/RABIES/blob/master/.github/ISSUE_TEMPLATE/standard-bug-report.md).
diff --git a/docs/how_to/contribute.md b/docs/how_to/contribute.md
new file mode 100644
index 00000000..47290f12
--- /dev/null
+++ b/docs/how_to/contribute.md
@@ -0,0 +1,224 @@
+# How to contribute to RABIES
+
+RABIES aims to provide an accessible tool responding to growing needs across
+the preclinical fMRI community. This effort should be community-driven, and
+community involvement is paramount in several respects:
+
+- adapting and maintaining **accessibility** for users across the broader community
+- **reproducibility and transparency**, as well as scientific scrutiny and rigour
+- defining and incorporating **best practices** across image processing, analysis and quality control
+- leveraging appropriate expertise for the **integration of new tools**
+
+Suggestions for improvements can be shared through the GitHub
+[issues system](https://github.com/CoBrALab/RABIES/issues) and
+[discussion board](https://github.com/CoBrALab/RABIES/discussions).
+
+```{tip}
+Discuss your proposed changes on the discussion board or in an issue before you
+open a pull request. It is much cheaper to redirect an approach before the code
+is written.
+```
+
+## Set up a development environment
+
+Install RABIES locally rather than working through a container — testing and
+debugging are much smoother that way. Install the dependencies listed in
+[`dependencies.txt`](https://github.com/CoBrALab/RABIES/blob/master/dependencies.txt),
+then install RABIES from a clone of the repository into a Python environment of
+your choice:
+
+```sh
+git clone --recursive https://github.com/CoBrALab/RABIES.git
+cd RABIES
+python setup.py install
+```
+
+```{note}
+Use `--recursive`. RABIES pulls in submodules, and a clone without them will
+not run.
+```
+
+### Working inside a container instead
+
+You can run operations in a container to avoid installing dependencies by hand,
+at the cost of losing interactive debugging (Spyder and similar will not be
+available).
+
+Open a persistent container instance with `-d --entrypoint sh --name mycontainer`,
+binding the paths you need with `-v`:
+
+```sh
+docker run -it -v $PWD:/work_dir -v /path_to_local_RABIES_package:/RABIES:ro \
+ --rm --entrypoint sh -d --name mycontainer rabies:local_testing
+```
+
+Then execute commands inside it:
+
+```sh
+docker exec mycontainer micromamba run $COMMAND
+```
+
+To check for errors, `$COMMAND` can be `error_check_rabies.py --complete`.
+
+To test your changes you must reinstall RABIES inside the container:
+
+```{code-block} sh
+:caption: Reinstalling the package inside a running container
+
+mkdir -p /tmp/RABIES
+# copy the upgraded package into the container
+# (/RABIES must be bound to your local package with -v)
+rsync -avz /RABIES/* /tmp/RABIES/.
+cd /tmp/RABIES
+python setup.py install
+```
+
+Compile these into a `.sh` script and run it in place of `$COMMAND` above.
+
+## Submit a pull request
+
+1. **Fork** the RABIES repository on GitHub.
+2. **Clone** your fork, with `--recursive` to pull the submodules.
+3. **Branch**: `git checkout -b my_new_branch`, with a name describing the
+ change. You are ready to modify the code.
+4. **Test and debug.** Install your updated package with
+ `python setup.py install` in a proper development environment. Test the
+ workflow with specific parameters by editing `debug_workflow.py` and running
+ it in debug mode (see below).
+
+ ```{important}
+ Before committing, confirm that `error_check_rabies.py --complete` finishes
+ with no errors.
+ ```
+5. **Commit, push and open a pull request** from your fork to the original
+ repository.
+
+## Debug interactively with Spyder
+
+1. Open `debug_workflow.py` in Spyder.
+2. Find the scripts in your local installation and add breakpoints. Running
+ `import rabies; os.path.abspath(rabies.__file__)` gives you the path to the
+ installed package's `__init__.py`, and from there you can locate the file of
+ interest.
+3. Run `debug_workflow.py` in debug mode until it reaches the breakpoint.
+
+## Add a new module to the pipeline
+
+RABIES workflows are structured with [Nipype](https://nipype.readthedocs.io/en/latest/)
+(see also the [Nipype tutorial](https://miykael.github.io/nipype_tutorial/)).
+
+### Write the function as a Nipype interface
+
+```python
+from nipype.interfaces.base import (
+ traits, TraitedSpec, BaseInterfaceInputSpec,
+ File, BaseInterface
+)
+
+
+class NewInterfaceInputSpec(BaseInterfaceInputSpec):
+ # select an appropriate input type with traits.type (Dict, File, Int, ...)
+ input_str = traits.Str(exists=True, mandatory=True,
+ desc="An input string.")
+
+
+class NewInterfaceOutputSpec(TraitedSpec):
+ out_file = File(
+ exists=True, desc="An output file.")
+
+
+class NewInterface(BaseInterface):
+ """
+ Describe your module.
+ """
+
+ input_spec = NewInterfaceInputSpec
+ output_spec = NewInterfaceOutputSpec
+
+ def _run_interface(self, runtime):
+ input_str = self.inputs.input_str
+
+ '''
+ YOUR CODE
+ '''
+
+ setattr(self, 'out_file', out_file)
+
+ return runtime
+
+ def _list_outputs(self):
+ return {'out_file': getattr(self, 'out_file')}
+```
+
+### Wrap it in a node
+
+```python
+from .other_script import NewInterface # if the interface is in a different script
+from nipype.pipeline import engine as pe
+
+new_interface_node = pe.Node(NewInterface(),
+ name='new_interface')
+```
+
+A node can also be built from any plain Python function, without writing an
+interface:
+
+```python
+from nipype.pipeline import engine as pe
+from nipype.interfaces.utility import Function
+
+new_function_node = pe.Node(Function(input_names=['input_1', 'input_2'],
+ output_names=['output_1', 'output_2'],
+ function=NewFunction),
+ name='new_function')
+```
+
+### Connect the node into a workflow
+
+Once the node carries out the operation you want, integrate it by linking its
+inputs and outputs to other nodes. Here is a complete minimal workflow, the one
+that performs slice timing correction:
+
+```{code-block} python
+:caption: A Nipype workflow conducting slice timing correction
+:linenos:
+
+from nipype.pipeline import engine as pe
+from nipype.interfaces.utility import Function
+from nipype.interfaces import utility as niu
+
+
+def init_bold_stc_wf(name='bold_stc_wf'):
+
+ workflow = pe.Workflow(name=name)
+ # intermediate node storing the workflow inputs
+ inputnode = pe.Node(niu.IdentityInterface(
+ fields=['bold_file']), name='inputnode')
+ # intermediate node storing the workflow outputs
+ outputnode = pe.Node(niu.IdentityInterface(
+ fields=['stc_file']), name='outputnode')
+
+ slice_timing_correction_node = pe.Node(
+ Function(input_names=['in_file', 'tr', 'tpattern', 'stc_axis',
+ 'interp_method', 'rabies_data_type'],
+ output_names=['out_file'],
+ function=slice_timing_correction),
+ name='slice_timing_correction', mem_gb=1.5 * opts.scale_min_memory)
+
+ # feed the inputnode into the STC node, and STC outputs into the outputnode
+ workflow.connect([
+ (inputnode, slice_timing_correction_node, [('bold_file', 'in_file')]),
+ (slice_timing_correction_node,
+ outputnode, [('out_file', 'stc_file')]),
+ ])
+ return workflow
+```
+
+Most contributions integrate a new interface into a pre-existing workflow
+rather than creating a new one, in which case the work is connecting the right
+nodes to your interface.
+
+```{seealso}
+[Workflow reference](../reference/workflows.md) documents the existing
+workflows and links to their source.
+```
diff --git a/docs/how_to/index.md b/docs/how_to/index.md
new file mode 100644
index 00000000..1289ac15
--- /dev/null
+++ b/docs/how_to/index.md
@@ -0,0 +1,46 @@
+# How-to guides
+
+These guides answer "how do I ...?" for a specific goal. They assume you
+already know what you want to achieve and are looking for the steps to get
+there. If you are new to RABIES, work through the
+[tutorial](../tutorials/index.md) first.
+
+## Getting RABIES running
+
+```{toctree}
+---
+maxdepth: 1
+---
+install
+run_with_containers
+select_scans
+```
+
+## Getting good results out of it
+
+```{toctree}
+---
+maxdepth: 1
+---
+check_orientation
+troubleshoot_registration
+assess_data_quality
+optimise_confound_correction
+minimal_preprocessing
+```
+
+## Contributing
+
+```{toctree}
+---
+maxdepth: 1
+---
+contribute
+```
+
+```{seealso}
+If your question is not covered here, ask on the
+[discussion board](https://github.com/CoBrALab/RABIES/discussions), or report a
+problem through the
+[issue tracker](https://github.com/CoBrALab/RABIES/issues).
+```
diff --git a/docs/how_to/install.md b/docs/how_to/install.md
new file mode 100644
index 00000000..3961acba
--- /dev/null
+++ b/docs/how_to/install.md
@@ -0,0 +1,110 @@
+# How to install RABIES
+
+Pick the installation route that matches where you will run RABIES.
+
+::::{grid} 1 1 3 3
+:gutter: 2
+
+:::{grid-item-card} Container
+**Recommended.** Apptainer on Linux and HPC clusters, Docker elsewhere. All
+dependencies included.
+:::
+
+:::{grid-item-card} PyPI
+Python package only. You install the non-Python dependencies yourself.
+:::
+
+:::{grid-item-card} Neurodesk
+Browser-based neuroimaging environment. Nothing to install locally.
+:::
+
+::::
+
+## Install as a container
+
+Containers package the entire computing environment, so you do not install
+dependencies by hand and the software behaves identically wherever you run it.
+[Apptainer](https://apptainer.org/) is generally preferred over
+[Docker](https://www.docker.com) because it does not require root permissions,
+which makes it usable on high performance computing clusters.
+
+Install Apptainer or Docker first (Apptainer publishes
+[quick start guidelines](https://apptainer.org/docs/user/main/quick_start.html)),
+then pull the [RABIES image](https://github.com/CoBrALab/RABIES/pkgs/container/rabies):
+
+::::{tab-set}
+
+:::{tab-item} Apptainer
+:sync: apptainer
+
+```sh
+apptainer build rabies-latest.sif docker://ghcr.io/cobralab/rabies:latest
+```
+
+This produces a single `.sif` file containing the whole environment.
+:::
+
+:::{tab-item} Docker
+:sync: docker
+
+```sh
+docker pull ghcr.io/cobralab/rabies:latest
+```
+:::
+
+::::
+
+To pin a version, replace `latest` with a tag from the
+[list of published images](https://github.com/CoBrALab/RABIES/pkgs/container/rabies).
+
+```{note}
+Versions prior to 0.5.0 are not on the GitHub container registry. They remain
+available on [Docker Hub](https://hub.docker.com/r/gabdesgreg/rabies).
+```
+
+For the execution syntax once the image is built, see
+[How to run RABIES in a container](run_with_containers.md).
+
+## Install from PyPI
+
+RABIES is published on [PyPI](https://pypi.org/project/rabies/):
+
+```sh
+pip install rabies
+```
+
+```{warning}
+`pip install` gives you the Python package only. RABIES also calls out to
+external neuroimaging tools, which are listed in
+[`dependencies.txt`](https://github.com/CoBrALab/RABIES/blob/master/dependencies.txt)
+and which you must install yourself. If you are not prepared to manage those,
+use a container.
+```
+
+## Use RABIES on Neurodesk
+
+RABIES is one of the [built-in tools](https://neurodesk.github.io/applications/)
+on the [Neurodesk platform](https://neurodesk.github.io/), a browser-based
+neuroimaging computing environment with community-maintained prebuilt tools.
+Nothing is installed on your own machine. See the
+[Neurodesk documentation](https://neurodesk.github.io/docs/) to get started.
+
+## The default atlas
+
+RABIES uses the DSURQE mouse atlas and a matching set of masks, labels, ICA
+priors and seeds by default. The container images have these preinstalled. A
+PyPI or development install downloads them into `$XDG_DATA_HOME/rabies`, or
+`~/.local/share/rabies` if `XDG_DATA_HOME` is unset, the first time you run a
+command that needs them.
+
+```{note}
+The first run after a fresh non-container install will therefore pause to
+download several hundred megabytes before any processing starts. This is
+expected, and happens once.
+```
+
+## Install for development
+
+If you intend to modify RABIES rather than just run it, see
+[How to contribute to RABIES](contribute.md), which covers setting up a
+development environment.
diff --git a/docs/how_to/minimal_preprocessing.md b/docs/how_to/minimal_preprocessing.md
new file mode 100644
index 00000000..583f30ba
--- /dev/null
+++ b/docs/how_to/minimal_preprocessing.md
@@ -0,0 +1,104 @@
+# How to use RABIES on already-preprocessed data
+
+If your functional data was preprocessed with your own pipeline and you only
+want RABIES for confound correction and analysis, you cannot skip the
+preprocessing stage — but you can run it with almost everything turned off.
+
+Running `rabies confound_correction` directly on external data fails with
+missing `.pkl` file errors. Those `.pkl` files are serialised states of the
+internal preprocessing workflow and cannot be written by hand. Even with the
+`.pkl` in place, the confound correction stage expects the full range of files
+produced by preprocessing, so missing file errors would follow.
+
+The practical solution is a *SHAM* preprocessing run, with the correction and
+registration steps disabled. RABIES still computes the intermediary outputs that
+the later stages require, while leaving the image data largely unchanged.
+
+## Run a SHAM preprocessing
+
+```sh
+rabies preprocess bids_inputs/ preprocess_outputs/ \
+ --anat_inho_cor method=disable \
+ --bold_inho_cor method=disable \
+ --commonspace_reg template_registration=no_reg,fast_commonspace=true \
+ --bold2anat_coreg registration=no_reg \
+ --no_HMC
+```
+
+```{list-table}
+:header-rows: 1
+:widths: 40 60
+
+* - Parameter
+ - What it turns off
+* - `--anat_inho_cor method=disable`
+ - inhomogeneity correction of the structural images
+* - `--bold_inho_cor method=disable`
+ - inhomogeneity correction of the EPI images
+* - `--commonspace_reg template_registration=no_reg,fast_commonspace=true`
+ - unbiased template generation, and the registration to the reference atlas (an identity transform is used instead)
+* - `--bold2anat_coreg registration=no_reg`
+ - EPI-to-structural coregistration, i.e. the susceptibility distortion correction
+* - `--no_HMC`
+ - the *application* of head motion correction to the resampled timeseries. Head motion parameters are still estimated and remain available to `--nuisance_regressors`, `--frame_censoring` and `--data_diagnosis`
+```
+
+If your dataset has no structural scans, add `--bold_only`, in which case
+`--anat_inho_cor` and `--bold2anat_coreg` no longer apply.
+
+## Your data must already be in commonspace
+
+```{warning}
+`template_registration=no_reg` does not skip the resampling to commonspace — it
+replaces the estimated transform with an identity transform. The commonspace
+outputs are therefore only meaningful if your input images **already overlap**
+with the template given to `--anat_template`, which is the file that defines
+the commonspace.
+
+If they do not overlap, the commonspace timeseries and the atlas masks
+(`--brain_mask`, `--WM_mask`, `--CSF_mask`, `--vascular_mask`) applied
+downstream will not correspond to your data.
+```
+
+Confirm your image orientation before you start — see
+[How to check image orientation](check_orientation.md).
+
+## What still happens
+
+A SHAM preprocessing is a minimal pass, not a strictly non-modifying one.
+
+Operations which alter the data but are off by default stay off, and should not
+be added: `--apply_STC`, `--apply_despiking`, `--detect_dummy`,
+`--log_transform`, `--anat_autobox`, `--bold_autobox` and `--oblique2card`.
+
+The timeseries are still resampled onto the output grid, using the identity
+transforms described above. Use `--commonspace_resampling` and
+`--anatomical_resampling` to control the output voxel dimensions, and
+`--interpolation` to select the interpolator.
+
+Two further operations are applied unconditionally and cannot be turned off:
+
+**Negative values are clipped to zero**
+: This happens when the preprocessed timeseries are written out. If your data
+ legitimately contains negative values — because it was already demeaned or
+ detrended by your own pipeline — those voxels will be set to zero. Bring in
+ data on a positive scale, and leave centring to `--detrending_order` at the
+ confound correction stage.
+
+**The output is cast** to the type given by `--data_type`
+: `float32` by default.
+
+## Alternative: `--read_datasink`
+
+`rabies confound_correction --read_datasink` reads the preprocessing outputs
+from the datasink folders rather than from the saved workflow graph, which
+removes the need for the `.pkl` file. This requires reproducing the RABIES
+[output structure and file naming](../reference/outputs.md) exactly, and is
+generally more work than running a SHAM preprocessing.
+
+## Still not covered?
+
+If your use case needs settings that are not exposed, open a
+[discussion](https://github.com/CoBrALab/RABIES/discussions) describing
+explicitly what you need. Providing example data lets us work out an
+implementation supporting your use case.
diff --git a/docs/how_to/optimise_confound_correction.md b/docs/how_to/optimise_confound_correction.md
new file mode 100644
index 00000000..0be1a9c0
--- /dev/null
+++ b/docs/how_to/optimise_confound_correction.md
@@ -0,0 +1,60 @@
+# How to optimise your confound correction strategy
+
+(optim_CR)=
+
+There is no single correct confound correction strategy. The right one is
+dataset-specific, and the way to find it is to start minimal and add one
+correction at a time, checking after each addition whether the data quality
+reports improved.
+
+This protocol comes from {cite}`Desrosiers-Gregoire2024-ou`. It assumes you can
+already generate and read the data quality reports — if not, start with
+[How to assess data quality](assess_data_quality.md).
+
+```{important}
+Start minimal and stay minimal for as long as the reports allow. Excessive
+correction removes network activity along with the confounds, and
+over-correction is harder to detect after the fact than under-correction.
+```
+
+## The protocol
+
+1. **Start with a minimal correction** and generate the data quality reports at
+ the analysis stage. A reasonable minimum is frame censoring on framewise
+ displacement, regression of the 6 motion parameters, and spatial smoothing:
+
+ ```sh
+ rabies -p MultiProc confound_correction preprocess_outputs/ confound_correction_outputs/ \
+ --frame_censoring FD_censoring=true,FD_threshold=0.05 \
+ --nuisance_regressors mot_6 \
+ --smoothing_filter 0.3
+ ```
+
+2. **Evaluate the reports**, following
+ [How to assess data quality](assess_data_quality.md).
+
+3. **Choose one additional correction**, using the table below to match what
+ you observed to the correction that addresses it.
+
+4. **Re-run confound correction with that one correction added**, regenerate
+ the reports, and compare. Keep the addition only if it improved the quality
+ outcomes. Adding one correction at a time is what makes its effect
+ attributable.
+
+5. **Repeat steps 3 and 4** until the quality outcomes are acceptable or you
+ have run out of options.
+
+## Matching observations to corrections
+
+```{figure} ../pics/CR_optimization_table.svg
+:alt: Table relating data quality observations to the corresponding confound correction options
+:width: 100%
+
+Guidance for prioritising additional corrections based on observations from the
+data quality reports.
+```
+
+```{seealso}
+[The confound correction workflow](confound_pipeline_target) describes every
+correction step available and the order in which RABIES applies them.
+```
diff --git a/docs/how_to/run_with_containers.md b/docs/how_to/run_with_containers.md
new file mode 100644
index 00000000..dede97fa
--- /dev/null
+++ b/docs/how_to/run_with_containers.md
@@ -0,0 +1,116 @@
+# How to run RABIES in a container
+
+A container has its own filesystem and cannot see your data unless you say so.
+Running RABIES in a container is therefore the same as running it natively,
+plus one rule: **every directory RABIES needs must be bound to a path inside
+the container, and the RABIES arguments must use the container-side paths.**
+
+Bind directories with `-B` for Apptainer and `-v` for Docker. Both take
+`host_path:container_path`, with an optional `:ro` to make the bind read-only.
+
+```{important}
+Bind the same directories at the same container-side paths for **all three
+stages**. Each stage reads the file paths recorded by the previous one, so a
+path used during preprocessing must still resolve during confound correction
+and analysis. Changing or dropping a bind between stages produces missing-file
+errors.
+```
+
+## Apptainer
+
+### Preprocessing
+
+```sh
+apptainer run -B $PWD/input_BIDS:/input_BIDS:ro \
+ -B $PWD/preprocess_outputs:/preprocess_outputs/ \
+ /path_to_apptainer_image/rabies.sif \
+ -p MultiProc preprocess /input_BIDS/ /preprocess_outputs/ \
+ --apply_STC --TR 1.2 \
+ --commonspace_reg masking=true,brain_extraction=false,template_registration=SyN,fast_commonspace=false
+```
+
+`apptainer run /path_to_apptainer_image/rabies.sif` executes the image; every
+argument after it is passed to RABIES and follows the ordinary
+[command line syntax](../reference/cli.md). The two binds are what make the
+data reachable:
+
+`-B $PWD/input_BIDS:/input_BIDS:ro`
+: Maps your BIDS folder to `/input_BIDS` inside the container, which is why the
+ RABIES argument reads `/input_BIDS/`. `:ro` grants read-only access, so the
+ container cannot modify your raw data.
+
+`-B $PWD/preprocess_outputs:/preprocess_outputs/`
+: Maps the desired output directory. There is no `:ro`, so the container can
+ write here.
+
+### Confound correction
+
+```sh
+apptainer run -B $PWD/input_BIDS:/input_BIDS:ro \
+ -B $PWD/preprocess_outputs:/preprocess_outputs/ \
+ -B $PWD/confound_correction_outputs:/confound_correction_outputs/ \
+ /path_to_apptainer_image/rabies.sif \
+ -p MultiProc confound_correction /preprocess_outputs/ /confound_correction_outputs/ \
+ --nuisance_regressors WM_signal CSF_signal vascular_signal mot_6 \
+ --smoothing_filter 0.3
+```
+
+`/input_BIDS` is still bound even though it does not appear in the RABIES
+arguments — this is the rule stated above.
+
+### Analysis
+
+```sh
+apptainer run -B $PWD/input_BIDS:/input_BIDS:ro \
+ -B $PWD/preprocess_outputs:/preprocess_outputs/ \
+ -B $PWD/confound_correction_outputs:/confound_correction_outputs/ \
+ -B $PWD/analysis_outputs:/analysis_outputs/ \
+ /path_to_apptainer_image/rabies.sif \
+ -p MultiProc analysis /confound_correction_outputs /analysis_outputs/ \
+ --group_ica apply=true,dim=30,random_seed=1
+```
+
+## Docker
+
+The syntax mirrors Apptainer, with `-v` in place of `-B` and a few extra flags:
+
+```sh
+docker run -it --rm --user $(id -u) \
+ -v $PWD/input_BIDS:/input_BIDS:ro \
+ -v $PWD/preprocess_outputs:/preprocess_outputs/ \
+ ghcr.io/cobralab/rabies:latest \
+ -p MultiProc preprocess /input_BIDS/ /preprocess_outputs/ \
+ --apply_STC --TR 1.2 \
+ --commonspace_reg masking=true,brain_extraction=false,template_registration=SyN,fast_commonspace=false
+```
+
+`--user $(id -u)`
+: Runs as your own user id, so output files are owned by you. Without it,
+ Docker writes files as root and you may be unable to delete them.
+
+`--rm`
+: Removes the container when the run finishes.
+
+Replace `latest` with a specific version tag for reproducible runs.
+
+## Using a custom atlas or seed files
+
+Template files, masks and seeds passed with `--anat_template`, `--brain_mask`,
+`--WM_mask`, `--CSF_mask`, `--vascular_mask`, `--prior_maps` or `--seed_list`
+live outside your input and output directories, so they need binds of their
+own:
+
+```sh
+apptainer run -B $PWD/input_BIDS:/input_BIDS:ro \
+ -B $PWD/preprocess_outputs:/preprocess_outputs/ \
+ -B $PWD/my_atlas:/atlas:ro \
+ /path_to_apptainer_image/rabies.sif \
+ -p MultiProc preprocess /input_BIDS/ /preprocess_outputs/ \
+ --anat_template /atlas/template.nii.gz \
+ --brain_mask /atlas/brain_mask.nii.gz
+```
+
+```{seealso}
+[CoBrALab recommendations](https://github.com/CoBrALab/documentation/wiki/Running-RABIES-on-niagara)
+for running RABIES on Compute Canada clusters.
+```
diff --git a/docs/how_to/select_scans.md b/docs/how_to/select_scans.md
new file mode 100644
index 00000000..ba378445
--- /dev/null
+++ b/docs/how_to/select_scans.md
@@ -0,0 +1,110 @@
+# How to select which scans get processed
+
+By default RABIES processes every functional scan it can find in the input BIDS
+directory. There are two independent ways to narrow that down: change which
+files count as functional or anatomical scans, or list the individual scans to
+keep or drop.
+
+## Change which files RABIES recognises
+
+RABIES identifies functional scans by the `bold` or `cbv` suffix and structural
+scans by the `T1w` or `T2w` suffix. Files matching neither are ignored.
+
+Override this with `--bids_filter`, which takes a JSON file with the functional
+filter under `func` and the structural filter under `anat`. This JSON reproduces
+the defaults:
+
+```{code-block} json
+:caption: bids_filter.json
+
+{
+ "func": {
+ "suffix": ["bold", "cbv"]
+ },
+ "anat": {
+ "suffix": ["T1w", "T2w"]
+ }
+}
+```
+
+Pass it at the preprocessing stage:
+
+```sh
+rabies preprocess input_BIDS/ preprocess_outputs/ --bids_filter bids_filter.json
+```
+
+Add any BIDS entity to either filter to be more specific. To use only the RARE
+anatomical acquisition and only the resting-state functional runs:
+
+```{code-block} json
+:caption: bids_filter.json
+
+{
+ "func": {
+ "suffix": ["bold"],
+ "task": ["rest"]
+ },
+ "anat": {
+ "suffix": ["T2w"],
+ "acquisition": ["RARE"]
+ }
+}
+```
+
+```{tip}
+Reach for `--bids_filter` when your dataset contains scans that are not meant
+for this pipeline at all — a second anatomical modality, a task run alongside
+the resting-state runs. Reach for `--inclusion_ids` below when you want a
+subset of otherwise-eligible scans.
+```
+
+## Include or exclude individual scans
+
+`--inclusion_ids` and `--exclusion_ids` take the full paths of BOLD files.
+They are execution options, so they go **before** the processing stage name,
+and they can be given at any stage.
+
+Process only two scans:
+
+```sh
+rabies --inclusion_ids input_BIDS/sub-001/ses-1/func/sub-001_ses-1_task-rest_bold.nii.gz \
+ input_BIDS/sub-002/ses-1/func/sub-002_ses-1_task-rest_bold.nii.gz \
+ -p MultiProc preprocess input_BIDS/ preprocess_outputs/
+```
+
+Process everything except one scan:
+
+```sh
+rabies --exclusion_ids input_BIDS/sub-003/ses-1/func/sub-003_ses-1_task-rest_bold.nii.gz \
+ -p MultiProc preprocess input_BIDS/ preprocess_outputs/
+```
+
+For longer lists, put one file path per row in a text file and pass the file:
+
+```sh
+rabies --inclusion_ids scans_to_process.txt -p MultiProc preprocess input_BIDS/ preprocess_outputs/
+```
+
+```{warning}
+Do not put `--inclusion_ids` or `--exclusion_ids` immediately before the
+processing stage name. The stage name gets swallowed into the list and
+argument parsing fails. Put another option, such as `-p` or `--verbose`,
+between them — as in every example above.
+
+`--inclusion_ids` and `--exclusion_ids` cannot be used together.
+```
+
+## Drop scans after quality control
+
+The two options above are also how you act on a quality control decision. To
+carry out an analysis without scans you have judged unusable, re-run the
+confound correction and analysis stages with `--exclusion_ids` listing them.
+See [How to assess data quality](assess_data_quality.md) for how to arrive at
+that decision, and for `--scan_QC_thresholds`, which excludes scans by
+threshold rather than by name.
+
+```{seealso}
+[Input data requirements](../reference/bids_inputs.md) for how RABIES pairs
+functional scans with anatomical scans, and the
+[`preprocess` options](../reference/cli.md) for the full parameter list.
+```
diff --git a/docs/how_to/troubleshoot_registration.md b/docs/how_to/troubleshoot_registration.md
new file mode 100644
index 00000000..9f156c0d
--- /dev/null
+++ b/docs/how_to/troubleshoot_registration.md
@@ -0,0 +1,89 @@
+# How to troubleshoot registration
+
+The RABIES defaults modify the images as little as possible and lean on the
+quality of the images at acquisition. They are the right starting point, but
+they do not produce a robust workflow for every dataset, and reaching good
+outcomes on your own data will often mean tuning parameters.
+
+This guide maps failures visible in the
+[preprocessing QC report](../reference/qc_outputs.md) onto the parameters that
+address them. Work through it in order: inhomogeneity correction feeds masking,
+and masking feeds every registration that follows, so a problem there will
+reappear downstream no matter what you change at the registration step.
+
+```{important}
+Before changing any parameter, confirm your images are correctly oriented —
+see [How to check image orientation](check_orientation.md). Mis-oriented
+images produce registration failures that no amount of parameter tuning will
+fix.
+```
+
+## Inhomogeneity correction
+
+Relevant parameters: `--anat_inho_cor`, `--bold_inho_cor`,
+`--anat_robust_inho_cor`, `--bold_robust_inho_cor`. Inspect the
+`anat_inho_cor/` and `bold_inho_cor/` folders of the QC report.
+
+Only a subset of scans have failed masking, or the mask is partially misregistered
+: Use `--anat_robust_inho_cor`/`--bold_robust_inho_cor`. These register all
+ corrected images together to generate a temporary template representing the
+ average of all scans, mask that template, and use it as the masking target in
+ a second pass of inhomogeneity correction, which is a more robust target. The
+ parameters for these options are the same as for `--commonspace_reg` below.
+
+Inhomogeneity biases are not completely corrected, with signal drops remaining
+: Apply `multiotsu=true`. This performs a staged correction, correcting low
+ intensities first and iteratively including higher ones, which better handles
+ images with strong inhomogeneity gradients and very low intensities.
+
+Tissue outside the brain is causing registration failures
+: If the initial correction enhanced the intensity of tissue outside the brain
+ and masking then fails, use `--anat_autobox`/`--bold_autobox` to crop out the
+ extra tissue automatically. You can also modify `otsu_thresh`, which sets the
+ threshold for the automatic masking during the initial correction, to select
+ a value more specific to brain tissue.
+
+A large proportion of masking failures remain — mismatched brain sizes, non-linear warps, or the mask falling outside the brain
+: Apply a less stringent registration `method`, stepping down through
+ `SyN` → `Affine` → `Rigid` → `no_reg`. If you reach `no_reg`, you may also
+ have to adjust `otsu_thresh` to obtain an automatically generated brain mask
+ covering only brain tissue.
+
+## Commonspace registration and susceptibility distortion correction
+
+Relevant parameters: `--commonspace_reg`, `--bold2anat_coreg`. Inspect the
+`commonspace_reg_wf.Anat2Unbiased/` and `commonspace_reg_wf.Unbiased2Atlas/`
+folders of the QC report (or `commonspace_reg_wf.Anat2Atlas/` if you used
+`fast_commonspace=true`), together with `EPI2Anat/`.
+
+Many scans are misregistered, or brain edges are not well matched
+: First inspect the quality of inhomogeneity correction for those scans, and
+ follow the guidance above if the correction or brain masking was poor. If
+ good quality masks were obtained during inhomogeneity correction, bring them
+ into the registration with `masking=true`. If registration errors persist,
+ particularly at the brain edges, `brain_extraction=true` further constrains
+ edge matching by removing tissue outside the brain.
+
+ ```{warning}
+ The quality of brain edge delineation depends on the masks derived during
+ inhomogeneity correction, so `brain_extraction=true` is only as good as that
+ earlier step. Fix masking first.
+ ```
+
+Scans have incomplete brain coverage, and surrounding tissue is stretched to fill the gap
+: Non-linear registration assumes corresponding anatomy between the moving
+ image and the target. When brain regions are missing — the cerebellum or
+ olfactory bulbs are the usual cases — the surrounding tissue may be
+ improperly stretched to fill the missing area. `brain_extraction=true` can
+ largely mitigate this.
+
+## When registration cannot be salvaged
+
+If a scan cannot be registered acceptably, exclude it rather than analysing it:
+see [How to select which scans get processed](select_scans.md).
+
+```{seealso}
+- [Preprocessing QC outputs](../reference/qc_outputs.md) — what each QC folder shows
+- [The preprocessing workflow](../explanation/preprocessing.md) — what each registration step is for
+- [`preprocess` options](../reference/cli.md) — the complete parameter list, with all accepted values
+```
diff --git a/docs/index.md b/docs/index.md
index 494d2cda..abfb2979 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,21 +1,81 @@
```{include} ../README.md
```
+## Finding your way around this documentation
+
+This documentation is organised around what you are trying to do right now.
+
+::::{grid} 1 1 2 2
+:gutter: 3
+
+:::{grid-item-card} {octicon}`rocket;1.5em;sd-mr-1` Tutorial
+:link: tutorials/index
+:link-type: doc
+
+**Start here if RABIES is new to you.** A guided run of the complete
+pipeline on a small example dataset, from raw BIDS input to a
+connectivity map.
+:::
+
+:::{grid-item-card} {octicon}`tools;1.5em;sd-mr-1` How-to guides
+:link: how_to/index
+:link-type: doc
+
+**Practical recipes for a specific goal.** Installing RABIES, running it
+in a container, tuning a failed registration, designing a confound
+correction strategy, contributing code.
+:::
+
+:::{grid-item-card} {octicon}`book;1.5em;sd-mr-1` Reference
+:link: reference/index
+:link-type: doc
+
+**Look something up.** Command line options, input requirements, every
+output file, and the precise definition of every metric.
+:::
+
+:::{grid-item-card} {octicon}`light-bulb;1.5em;sd-mr-1` Explanation
+:link: explanation/index
+:link-type: doc
+
+**Understand how RABIES works and why.** The preprocessing and confound
+correction workflows, the analyses, and the data quality framework.
+:::
+
+::::
+
```{toctree}
---
-maxdepth: 3
-caption: Content
----
-installation.md
-running_the_software.md
-preprocessing.md
-preproc_QC.md
-confound_correction.md
-analysis.md
-analysis_QC.md
-outputs.md
-metrics.md
-faq.md
-troubleshooting.md
-contributing.md
-bibliography.md
+maxdepth: 2
+hidden:
+caption: Getting started
+---
+tutorials/index
+```
+
+```{toctree}
+---
+maxdepth: 2
+hidden:
+caption: How-to guides
+---
+how_to/index
+```
+
+```{toctree}
+---
+maxdepth: 2
+hidden:
+caption: Reference
+---
+reference/index
+```
+
+```{toctree}
+---
+maxdepth: 2
+hidden:
+caption: Explanation
+---
+explanation/index
+```
diff --git a/docs/installation.md b/docs/installation.md
deleted file mode 100644
index 3eb3ea94..00000000
--- a/docs/installation.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# Installation
-
-## Container (Apptainer/Docker) \*\*RECOMMENDED\*\*
-For most uses, we recommend instead using a containerized installation with [Apptainer](https://apptainer.org/) when possible on a Linux system (here's their [quick start guidelines](https://apptainer.org/docs/user/main/quick_start.html)), or [Docker](https://www.docker.com) on other platforms. Containers allow to build entire computing environments, grouping all dependencies required to run the software. This in turn reduces the burden of installing dependencies manually and ensures reproducible behavior of the software. Apptainer is generally preferred over Docker since root permissions are not required, and is thus generally compatible across computing platforms (e.g. high performance computing clusters).
-
-A [containerized version](https://github.com/CoBrALab/RABIES/pkgs/container/rabies) of RABIES is available from Github. After installing Apptainer or Docker, the following command will pull and build the container:
-* Install Apptainer .sif file:
-```
-apptainer build rabies-latest.sif docker://ghcr.io/cobralab/rabies:latest
-```
-* Install Docker image:
-```
-docker pull ghcr.io/cobralab/rabies:latest
-```
-A specific tag version can be selected (instead of `latest`) from the [list online](https://github.com/CoBrALab/RABIES/pkgs/container/rabies). Versions prior to 0.5.0 are found on [Docker Hub](https://hub.docker.com/r/gabdesgreg/rabies).
-
-## PyPi
-The software is available on [PyPi](https://pypi.org/project/rabies/), which makes the rabies python package widely accessible with
-```
-pip install rabies
-```
-However, this does not account for non-python dependencies found in `dependencies.txt`.
-
-## Neurodesk
-RABIES is also made available on the [Neurodesk platform](https://neurodesk.github.io/), as part of the [built-in tools](https://neurodesk.github.io/applications/) for neuroimaging. The Neurodesk platform allows for an entirely browser-based neuroimaging computing environment, with pre-built neuroimaging tools from the community, and aims at reducing needs for manual development of computing environments and at improving reproducible neuroimaging. More details on Neurodesk here .
\ No newline at end of file
diff --git a/docs/metrics.md b/docs/metrics.md
deleted file mode 100644
index 4fe417a8..00000000
--- a/docs/metrics.md
+++ /dev/null
@@ -1,71 +0,0 @@
-# Metric definitions
-(metrics_target)=
-On this page, the root-mean square (RMS) corresponds to $||x||_2 = \sqrt{\frac{1}{n}\sum_{i=1}^{n}x_i^2}$
-
-(regressor_target)=
-## Nuisance regressors for confound regression
-* **mot_6**: Corresponds to the head motion translation and rotation parameters. Prior to the regression, the motion regressors are also subjected to the same frame censoring, detrending and frequency filtering which were applied to the BOLD timeseries to avoid the re-introduction of previously corrected confounds, as recommend in {cite}`Power2014-yf` and {cite}`Lindquist2019-lq`.
-* **mot_24**: Corresponds to the 6 motion parameters together with their temporal derivatives, and 12 additional parameters are obtained by taking the squared terms (i.e. Friston 24 parameters {cite}`Friston1996-sa`)
-$$
-mot24_t = [mot6_t,(mot6_t-mot6_{t-1}),(mot6_t)^2,(mot6_t-mot6_{t-1})^2]
-$$
-with $mot24_t$ representing the list of 24 regressors for timepoint $t$. As with mot_6, the 24 regressors are additionally subjected to censoring, detrending and frequency filtering if applied on BOLD.
-* **WM/CSF/vascular/global signal**: The mean signal is computed within the corresponding brain mask (WM,CSF,vascular or whole-brain mask) from the partially cleaned timeseries (i.e. after the confound correction steps 1-4 up to frequency filtering).
-* **aCompCor_percent**: Principal component timecourses are derived from timeseries within the combined WM and CSF masks (aCompCor technique {cite}`Muschelli2014-vi`). From the timeseries within the WM/CSF masks $Y_{WM/CSF}$, a principal component analysis (PCA) decomposition is conducted to derive
-$$
-Y_{WM/CSF} = W_{aCompCor}C^T
-$$
-with $C$ corresponding to a set of spatial principal components, and $W$ to their associated loadings across time. The set of first components explaining 50% of the variance are kept, and their loadings $W_{aCompCor}$ provide the set of aCompCor nuisance regressors. PCA is conducted on the partially cleaned timeseries (i.e. after the confound correction steps 1-4 up to frequency filtering).
-* **aCompCor_5**: Same as **aCompCor_percent**, but the first 5 components are kept instead of a set explaining 50% of the variance.
-
-
-## Temporal scan diagnosis
-
-(mot6_target)=
-* **Head motion translation and rotation parameters**: Corresponds to 3 rotations (Euler angles in radians) and 3 translations (in mm) measured for head motion realignment at each timeframe.
-(FD_target)=
-* **Framewise displacement**: For each timepoint, corresponds to the displacement (mean across the brain voxels) between the current and the next frame. For each brain voxel within the referential space for head realignment (i.e. the [3D EPI](3D_EPI_target) which was provided as reference for realignment) and for each timepoint, the inverse transform of the head motion parameters (from the corresponding timepoint) is applied to obtain the voxel position pre-motion correction. Framewise displacement can then be computed for each voxel by computing the Euclidean distance between the positions pre-motion correction for the current and next timepoints. Thus, the mean framewise displacement $FD_t$ at timepoint $t$ is computed as
-$$
-FD_t = \frac{1}{n}\sum_{i=1}^{n}\sqrt{(x_{i,t+1}-x_{i,t})^2+(y_{i,t+1}-y_{i,t})^2+(z_{i,t+1}-z_{i,t})^2}
-$$
-using the 3D $x$,$y$ and $z$ spatial coordinates in mm for timepoints $t$ and $t+1$ and for each voxel indices $i$. Framewise displacement for the last frame (which has no future timepoint) is set to 0.
-(DVARS_target)=
-* **DVARS**: represents the estimation of temporal shifts in global signal at each timepoint, measured as the root-mean-square of the timeseries’ temporal derivative
-$$
-DVARS_t = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(Y_{i,t}-Y_{i,t-1})^2}
-$$
-where $Y_{i,t}$ corresponds to the BOLD signal in brain voxel $i$ at timepoint $t$. The first timepoint is set to 0 (has no previous timepoint).
-* **Framewise distance from mean**: This corresponds to the mean square error (MSE) between each frame and the average EPI, with the average computed as the tri-mean across time voxelwise. The input to this function is the resampled timeseries outputed from the `preprocess` stage.
-* **Whole-brain/Edge/WM/CSF mask**: The mean signal across a certain brain mask, either whole-brain (i.e. the global signal), WM, CSF or brain edge.
-* **$CR_{var}$**: The variance estimated by confound regression is computed for each timepoint. This is done by taking $CR_{var} = RMS(Y_{CR})$ across voxels at each timepoints, where $Y_{CR}$ is the [predicted confound timeseries](CR_target).
-* **CR $R^2$**: Represents the proportion of variance explained (and removed) by confound regression. This is obtained with $CR_{R^2}= 1-\frac{Var(\hat{Y})}{Var(Y)}$ at each timepoint, where $Y$ and $\hat{Y}$ are the timeseries pre- and post-regression respectively, and $Var(x) = \frac{1}{n}\sum_{i=1}^{n}(x_i - \mu_x)^2$ calculates the variance, with $\mu$ as the mean.
-* **Mean amplitude**: A set of timecourse are averaged as $\frac{1}{n}\sum_{i=1}^{n}|X_i|$, where $X_i$ is the timecourse $i$. Timecourses can correspond to either of the following sets:
- * DR confounds: timecourses from the first stage of dual regression, using confound components provided to `--prior_confound_idx`.
- * DR networks: network timecourses from the first stage of dual regression as specified with `--prior_bold_idx`.
- * SBC networks: network timecourses derived from the set of seeds provided in `--seed_list`.
-
-## Spatial scan diagnosis
-
-* **BOLDSD**: The temporal standard deviation is computed for each voxel from the BOLD timeseries.
-* **CRSD**: The temporal standard deviation computed on each voxel from the predicted confound timeseries during confound regression (i.e. [$Y_{CR}$](CR_target)).
-* **CR R2**: The proportion of variance explained by confound regression at each voxel. This is obtained with $CR_{R^2}= 1-\frac{Var(\hat{Y})}{Var(Y)}$ at each voxel, where $Y$ and $\hat{Y}$ are the timeseries pre- and post-regression respectively, and $Var(x) = \frac{1}{n}\sum_{i=1}^{n}(x_i - \mu_x)^2$ is variance of $x$, with $\mu$ as the mean.
-* **Global signal covariance (GScov)**: The covariance between the global signal and the timeseries at each voxel is measured as $GS_{cov} = \frac{1}{n}\sum_{t=1}^{n}Y_t \times GS_t$, where $GS_t = \frac{1}{n}\sum_{i=1}^{n}Y_i$, i.e. the mean across all brain voxels for a given timepoint.
-* **DR network X**: The linear coefficients resulting from the [second regression with dual regression](DR_target), corresponding to a network amplitude map (for the Xth network specified for analysis with `--prior_bold_idx`).
-* **SBC network X**: The voxelwise correlation coefficients (pearson's r) estimated with seed-based connectivity (for the Xth seed provided for analysis with `--seed_list`).
-
-
-## Distribution plot
-(dist_plot_metrics)=
-
-* **Network amplitude**: The overall network amplitude is summarized by computing the L2-norm across a network connectivity map from a subject-level analysis (such a map can be derived from seed-based correlation, or correspond to the linear coefficients from the [second regression ${\beta}_{SM}$](DR_target) for dual regression)
-* **Network specificity**: The network map (seed-based or dual regression) and the corresponding canonical network map are thresholded to include the top X% of voxels with highest connectivity (X% is defined by `--brainmap_percent_threshold`), and the overlap of the thresholded area is computed using Dice overlap. For dual regression, the 'canonical network' map will consist of the original ICA component corresponding to that network provided with `--prior_maps`, and for seed-based connectivity, the reference network maps are provided using the `--seed_prior_list` parameter.
-* **Dual regression confound correlation**: The timecourse for a single network (from a seed or dual regression) is correlated with the timecourse from each confound component (provided using `--prior_confound_idx`) modelled through dual regression, then the absolute mean correlation is computed to obtain the average amplitude of confound correlations for this specific network analysis.
-* **FD-DVARS corr.**: For each scan, this QC metric corresponds to the correlation between the framewise displacement (FD) timecourse and the DVARS timecourse **computed post-confound correction** (i.e. this is not the DVARS plotted in the temporal diagnosis figure). Crucially, censored timeframes are excluded from both timecourses, and DVARS was recomputed after applying confound correction so that this metric represents *uncorrected/residual* associations between spontaneous motion and the cleaned global signal fluctuations.
-* **Total $CR_{SD}$**: The total standard deviation across the [predicted confound timeseries $Y_{CR}$](CR_target).
-* **Mean framewise displacement**: The mean framewise displacement computed across time (only including frames after censoring applied for confound correction).
-* **Temporal degrees of freedom**: The remaining degrees of freedom post-confound correction are calculated as `tDOF = Original number of timepoints - Number of censored timepoints - Number of AROMA components removed - Number of nuisance regressors`.
-
-## Group statistical QC report
-(group_QC_metrics)=
-* **Specificity of network variability**: similarly to network specificity in the distribution plot, the network variability map and the corresponding canonical network map are thresholded to include the top X% of voxels (X% is defined by `--brainmap_percent_threshold`), and then the overlap is estimated using Dice overlap.
-* **Mean confound correlation**: for each confound correlation map (either $CR_{SD}$, mean FD or tDOF), the mean is computed across voxels included within the thresholded area of the canonical network map, to obtain a mean correlation within the network's core region.
\ No newline at end of file
diff --git a/docs/nested_docs/distribution_plot.md b/docs/nested_docs/distribution_plot.md
deleted file mode 100644
index 137aba2c..00000000
--- a/docs/nested_docs/distribution_plot.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Distribution plot
-
-(dist_plot_target)=
-
-
-
-The distribution plot allows visualizing the distribution of data quality measures across the dataset, where measures of network connectivity (specificity and amplitude) are contrasted with measures of confounds across samples (each point in the plot is a scan). Data points labelled in gray were removed using `--scan_QC_thresholds`, where the gray dotted lines correspond to the QC thresholds selected for network specificity (Dice overlap) and DR confound correlation. Among the remaining samples and for each metric separately, scan presenting outlier values were detected based on a modified Z-score threshold (set with `--outlier_threshold`, 3.5 by default) and labelled in orange. The derivation of the quality metrics is described in details on the [metrics documentation](dist_plot_metrics).
-
-
-The report was designed to subserve two main functions: 1. Inspect that network specificity is sufficient and the temporal correlation with confounds (i.e. DR confound corr.) minimal, and set thresholds for scan inclusion using `--scan_QC_thresholds` (top right subplot, more details on this below), and 2. complement the group statistical report to visualize the association between connectivity and the three confound measures included in the report ($CR_{SD}$, mean FD and tDOF). In the later case, it can be possible for instance to determine whether a group-wise correlation in statistical report is driven by outliers.
-
-## Scan-level thresholds based on network specificity and confound temporal correlation
-
-
-
-The measures of network specificity (using Dice overlap) and temporal correlation with confounds (where confound timecourses are extracted using confound components specified with `--conf_prior_idx` and measured through dual regression) were defined in {cite}`Desrosiers-Gregoire2024-ou` for conducting scan-level QC (the figure above is reproduced from the study). They were selected as ideal measures for quantifying issues of network detectability and spurious connectivity (the figure above demonstrate how [categories of scan quality outcomes](quality_marker_target) can be distinguished with these metrics), and applying inclusion thresholds to select scans which respect assumptions for network detectability and minimal effects from confounds.
diff --git a/docs/nested_docs/group_stats.md b/docs/nested_docs/group_stats.md
deleted file mode 100644
index c6f69658..00000000
--- a/docs/nested_docs/group_stats.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Group stats
-
-(group_stats_target)=
-
-
-
-Inspecting scan-level features is insufficient to conclude that inter-scan variability in connectivity isn't itself impacted (which is of primary interest for group analysis). This final report is aimed at inspecting features of connectivity variability at the group level, and focuses on two aspects:
-
-1. **Specificity of network variability:** the standard deviation in connectivity across scan is computed voxelwise. This allows to visualize the spatial contrast of network variability. If primarily driven by network connectivity, the contrast should reflect the anatomical extent of the network of interest (as in the example above for the mouse somatomotor network), or otherwise may display spurious or absent features. For more details on the development of this metric, consult {cite}`Desrosiers-Gregoire2024-ou`.
- - **Relationship to sample size**: {cite}`Desrosiers-Gregoire2024-ou` demonstrate that the contrast of the network variability map depends on sample size. If network connectivity is observed in individual scans, but not in this statistical report, increasing sample size may improve this contrast.
-2. **Correlation with confounds:** Connectivity is correlated across subject, for each voxel, with either of the three measures of confound included: variance explained from confound correction at a given voxel ($CR_{SD}$, see [predicted confound timeseries $Y_{CR}$](CR_target)), mean framewise displacement (FD), or temporal degrees of freedom. This allows establishing the importance of the association with potential confounds. What constitute a 'concerning' correlation may depend on the study, and the effect size of interest (i.e. is the effect size of interest much higher or similar to the effect size of confounds?).
-
-**Quantitative CSV report**: A CSV file is also automatically generated along the figure, which records a quantitative assessment of these two aspects. More specifically, the overlap between the network variability map and the reference network map is measuring using Dice overlap, and for confound measures, the mean correlation is measured within the area of the network (consult the [metric details elsewhere](group_QC_metrics)). These measures can be referred to for a quantitative summary instead (although visualization is preferred, as the Dice overlap for network variability may not perfectly distinguish network and spurious features).
-
-**IMPORTANT**: the validity of this report is dependent on whether [scan-level assumptions](dist_plot_target) of network detectability and minimal confound effects are met. This is because either the lack of network activity or spurious effects in a subset of scan can drive 'apparent' network variability, since there will be differences in the presence VS absence of the network across scans, but these differences may be actually driven by data quality divergences.
\ No newline at end of file
diff --git a/docs/nested_docs/optim_CR.md b/docs/nested_docs/optim_CR.md
deleted file mode 100644
index fd8ed221..00000000
--- a/docs/nested_docs/optim_CR.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Optimization of confound correction strategy
-
-(optim_CR)=
-
-On this page is a procedure for improving confound correction design based on observations from the data quality assessment reports. These recommendations were originally developed in {cite}`Desrosiers-Gregoire2024-ou`, and consist of a stepwise protocol where confound correction is improved incrementally while referring to data quality reports and the table found on this page, relating data quality features to corresponding corrections. The protocol is as follows:
-
-1. Initiate a **minimal** confound correction, and generate data quality reports at the analysis stage. Correction should be minimal at first to mitigate potential issues of over-correction, where network activity itself can be removed by excessive correction. A minimal correction can consist of applying frame censoring using framewise displacement and the regression of 6 motion parameters together with spatial smoothing.
-2. Evaluation of the data quality reports (as described in the [guidelines on the main page](analysis_QC_target))
-3. The most sensible additional correction is selected based on the observations and using the table below.
-4. The confound correction pipeline stage is re-run with **one** additional correction at a time, and the data quality reports are re-evaluated. Only a single correction is tested at a time so its impact can be evaluated, and the correction is only kept if there were beneficial impacts.
-5. Repeat 3. and 4. until desirable quality outcomes are met, or no further options are left for confound correction.
-
-The table below offers guidance for prioritizing additional corrections based on observations from the data quality reports. The confound correction workflow and the various strategies available are described elsewhere in the [confound correction pipeline](confound_pipeline_target).
-
-
\ No newline at end of file
diff --git a/docs/nested_docs/registration_troubleshoot.md b/docs/nested_docs/registration_troubleshoot.md
deleted file mode 100644
index 49634f32..00000000
--- a/docs/nested_docs/registration_troubleshoot.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Recommendations for registration troubleshooting
-When first attemting preprocessing with RABIES, we recommend following the default parameters as they involve less stringent modifications of the images and mostly rely on the original quality of the MR images at acquisition. However, the default parameters do not offer a generalizable robust workflow for every datasets, and to reach ideal outcomes, the workflow parameters may require tuning. We provide below recommendations for common types of registration failures that may be found from the QC report.
-
-
-## Inhomogeneity correction (anat or BOLD) `--anat_inho_cor`, `--bold_inho_cor`, `--anat_robust_inho_cor`, `--bold_robust_inho_cor`
-
-* **Only a subset of the scans have failed masking, or the mask is partially misregistered:** Consider using the `--anat_robust_inho_cor/--bold_robust_inho_cor` option, which will register all corrected images to generate a temporary template representing the average of all scans, and this template is then itself masked, and becomes the new target for masking during a second iteration of inhomogeneity correction. This should provide a more robust registration target for masking. The parameters for handling this setp are the same as `--commonspace_reg` below.
-* **The inhomogeneity biases are not completely corrected:** if you observe that drops in signal are still present after the connection, you should consider applying `multiotsu=true`. This option will better correct low intensities in an image with important signal drops.
-* **Tissue outside the brain is provoking registration failures:** if the intensity of tissue outside the brain was enhanced during the initial inhomogeneity correction and leads to masking failures, you can consider using `--anat_autobox/--bold_autobox` which can automatically crop out extra tissue. You can also modify the `otsu_thresh` to set the threshold for the automatic masking during the initial correction, and attempt to select a threshold that is more specific to the brain tissue.
-* **There are still a large proportion of masking failures (mismatched brain sizes or non-linear wraps, or mask outside of the brain):** Consider applying a less stringent registration `method`, going down from `SyN` -> `Affine` -> `Rigid` -> `no_reg` . If `no_reg` is selected, you may have to also adjust the `otsu_thresh` to obtain an automatically-generated brain mask covering only the brain tissues.
-
-
-## Commonspace registration `--commonspace_reg` or susceptibility distortion correction `--bold2anat_coreg`
-
-* **Many scans are misregistered, or brain edges are not well-matched:** First, inspect the quality of inhomogeneity correction for those scans, and refer to instructions above if the correction or brain masking was poor. If good quality masks were obtained during inhomogeneity correction, they can be used to improve registration quality by using `masking=true`. If registration errors persist, in particular if brain edges are not well-matched, `brain_extraction=true` can be used to further constrain the matching of brain edges after removing tissue outside the brain. However, the quality of brain edge delineation depends on masks derived during inhomogeneity correction, so this option depends on high quality masking during this previous step.
-* **Scans have incomplete brain coverage (e.g. cerebellum/olfactory bulbs), and surrounding brain tissue is streched to fill in missing regions:** The non-linear registration assumes corresponding brain anatomy between the moving image and the target. If brain regions are missing, the surrounding tissue may be improperly stretched to fill missing areas. Using the `brain_extraction=true` can largely mitigate this issue.
-
diff --git a/docs/nested_docs/scan_diagnosis.md b/docs/nested_docs/scan_diagnosis.md
deleted file mode 100644
index 738bb11a..00000000
--- a/docs/nested_docs/scan_diagnosis.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# Scan diagnosis report
-(diagnosis_target)=
-
-By executing `--data_diagnosis` at the analysis stage of the pipeline, a set of visual reports are generated to support data quality assessment in relationship to connectivity analysis. Here, the *spatiotemporal diagnosis* report is described. The diagnosis is a visual report generated for each scan independently after conducting dual regression or seed-based connectivity analysis. It will display a large set of temporal and spatial features for the scan supporting the assessment of potential data quality issues, and whether network connectivity is impacted. Unless specified otherwise, all metrics are computed from fMRI timeseries after the confound correction stage. This page first covers an example of the report with the description for the set of features, and second provides guidance for interpreting the report.
-
-
-## Spatiotemporal diagnosis
-
-Above is an example of the report (files generated into the `data_diagnosis_datasink/figure_temporal_diagnosis/` and `data_diagnosis_datasink/figure_spatial_diagnosis/` folders) for a scan with little confound signatures and clear network connectivity. Each spatial map is represented along 6 cortical slices, overlapped onto the anatomical template in common space. The network maps from dual regression (DR) or seed-based connectivity (SBC) are thresholded to include the top X% of the voxels with the highest values (X% is defined by `--brainmap_percent_threshold`). In this example, both dual regression and seed-based connectivity was conducted, where DR network 0 and SBC network 1 correspond to analysis of the somatomotor network, whereas DR network 1 and SBC network 0 correspond to the default mode network. Below we detail the interpretation of each feature included in the diagnosis (whereas the detailed computations for each metric are further described in the [Metric definitions](metrics_target) page):
-
-### Temporal diagnosis from top to bottom:
-* **Power spectrum:** the frequency power spectrum is displayed to assess the dominant frequency profile. This always shown averaged across the whole brain, but it is also possible to display the spectrum for seeds using `--plot_seed_frequencies`.
-
-* **Carpet plot:** the entire fMRI timeseries are displayed in a time by voxel 2D matrix. This allows to visualize global fluctuations in signal intensity, which can be a proxy for various global artefacts {cite}`Power2017-wn`. Censored frames are labelled in red.
-
-* **The translation and rotation head motion parameters:** those are the 6 rigid body parameters estimated during preprocessing, and allow tracking of head position across scan duration.
-
-* **Framewise distance from the mean image**: This corresponds to the mean square error (MSE) between each frame and the average EPI (computed as the tri-mean across time voxelwise), computed prior to confound correction to map changes in brain constrast over time. This is a complementary measure of motion, since that metric represents changes in raw image contrast across time that remain post-head motion realignment, and thus might not be well captured by framewise displacement. This metric is also outputted using `--hmc_qc_report` during `preprocess` stage, and it is possible to censore using this metric with `--frame_censoring` at `confound_correction` stage.
-
-* **The framewise displacement and the temporal shifts in global signal from the root-mean-square of the timeseries’ temporal derivative (DVARS) {cite}`Power2012-ji`:** Framewise displacement quantifies movement between consecutive frames, which reveals the timing and amplitude of spontaneous motion, whereas DVARS reveals shifts in global fMRI signal intensities (which can also indicate suspicious spikes in signal).
-
-* **Variance captured and removed by confound regression:** The linear model fitted during nuisance regression provides an estimate of 'nuisance timeseries', from which it is possible to quantify the variance removed at each frame. The temporal diagnosis displays the absolute variance by computing the RMS of nuisance timeseries across voxels for each frame, as well as the relative variance removed by computing the R2 at each frame. These features allow both to visualize confound effects, and evaluate whether confound regression appropriately modelled confounds detected from other temporal features.
-
-* **Mean signals within anatomical masks:** The mean timecourse derived within a set of anatomical masks (whole-brain, edge, white matter and CSF masks) is displayed. The edge, WM and CSF regions are susceptible to motion and physiological confounds {cite}`Pruim2015-nm`, and can be contrasted with the whole-brain global signal to assess potential artefactual effects across the brain.
-
-* **Mean amplitude of network VS confound timecourses:** The averaged timecourse between network analyses and confound sources are compared to assess whether network amplitude is spurious (i.e. correlated with confound timecourse). To model confound timecourses, dual regression analysis is conducted with a complete set of components from Independent Component Analysis representing a mixture of networks and confounds from various origins, and the timecourses from confound components are compiled to summarize a broad set of potential confounds (by default, RABIES [this set](https://zenodo.org/record/5118030/files/melodic_IC.nii.gz) of ICA components for mice).
-
-### Spatial diagnosis from top to bottom:
-* **Spatial distribution in signal variability (BOLDSD):** The first spatial feature of the diagnosis is the signal variability (standard deviation) at each voxel. This map offers an index of whether significant confounds are contributing to the signal (see other examples in **Interpretation of the report and main features to inspect**). Without the influence from confounds, as in this example, signal variability is largely homogeneous.
-
-* **Confound regression variance explained (CRSD):** The variance explained from confound regression is quantified at each voxel by taking the standard deviation from the modelled confound timecourse. This allows to contrast spatially the amplitude of confound effects. This feature can specifically delineate the presence of confounds and identify the type of confound. In this example, minor motion signatures are identified.
-
-* **Confound regression variance explained proportion:** Similar to CRSD, but showing instead the proportion of variance explained (R2).
-
-* **Global signal covariance:** This map displays the covariance of each voxel with the global signal. The contrast from this map allows to evaluate the predominant source of global signal fluctuation, which can take various forms depending on the contributions from neural network and confounds (see examples below in **Interpretation of the report and main features to inspect**). In the ideal case, there is predominant contrast found in gray matter, with a shape reminescent of brain network, as in the example shown above.
-
-* **Network spatial maps:** Finally, the diagnosis shows the spatial network maps fitted using dual regression (or seed-based analysis) from the selected set of brain networks of interest (in this case the somatomotor and default mode networks). These fits provide insights into the quality of network analysis, and how they may affect downstream statistical analyses.
-
-* Note that $CR_{SD}$ and $CR_{R^2}$ are computed from the regressors specified with `--nuisance_regressors` during confound correction. If no regressors are specified, $CR_{SD}$ and $CR_{R^2}$ are still estimated using regression on the 6 motion parameters, but that regression is not applied to remove signal from the timeseries.
-
-## Interpretation of the report and main features to inspect
-(quality_marker_target)=
-
-
-A subset of the features in the spatiotemporal diagnosis are most crucial in determining scan quality in relationship to connectivity analysis, and are displayed above across 4 main categories of scan quality. Below we describe the key role of these four features in relationship to those 4 scan categories:
-
-* **BOLD variability:** The resulting BOLD variability map presents an homogeneous contrast in uncorrupted scans, and can otherwise reveal the anatomical signature of confounds, thus allowing to identify the type of confound.
-
-* **Global signal covariance:** The global signal covariance map is sensitive to both non-neural confounds (e.g. the spurious category) and network signatures (e.g. the specific category). The global signal covariance thus reflects whether network or confound sources dominate coordinated fluctuations, and can delineate the most likely contributors to downstream connectivity measures.
-
-* **Network map:** Allows inspecting whether the expected anatomical features of the network are effectively captured (i.e. network specificity). This is most crucial in ensuring that the network is not absent (see the absent category), or to ensure that the network shape is not distorded with spurious features (see spurious category).
-
-* **Network and confound timecourses:** Finally, the respective timecourses for networks and confounds can be compared to reveal direct relationships between network amplitude and confounds in the temporal domain. Although this metric does not describe the type of confound, it is the most direct indicator of spurious connectivity. It is an important complement to the inspection of network shape, since spurious effects may only affect amplitude with minimal impact on shape.
-
-These 4 features are sufficient to capture the essential characteristics of network detectability and spurious connectivity at the single scan level. The remaining features from the spatiotemporal diagnosis provide additional details regarding timeseries properties, the motion parameters, or confound regression, and can further support characterizing the specific origin of confounds (e.g. determining that a correlation between network and confound timecourse is originating from framewise displacement (i.e. motion)).
diff --git a/docs/outputs.md b/docs/outputs.md
deleted file mode 100644
index 21e4597b..00000000
--- a/docs/outputs.md
+++ /dev/null
@@ -1,99 +0,0 @@
-# Understanding the Outputs
-
-In this section, there is a description for all the output files provided at each processing stage. Important outputs from RABIES are stored into `datasink/` folders, which will be generated in the output folder specified at execution.
-
-## Preprocessing Outputs
-
-Multiple datasink folders are generated during preprocessing for different output types: `anat_datasink/`, `bold_datasink/`, `unbiased_template_datasink/`, `transforms_datasink/` and `confounds_datasink/`.
-
-- `anat_datasink/`: Includes the inhomogeneity-correction anatomical scans.
- - `anat_preproc/`: anatomical scans after inhomogeneity correction
-
-- `bold_datasink/`: Includes all outputs related to the functional scans, where files are either resampled onto the native or commonspace of the EPI. The native space outputs are resampled over the anatomical scan from each corresponding MRI session, whereas the commonspace outputs are resampled over the reference atlas (the original EPI voxel resolution is unchanged during resampling unless specified otherwise in the RABIES command).
- - `native_bold/`: preprocessed EPI timeseries resampled to nativespace
- - `native_brain_mask/`: brain mask in nativespace
- - `native_WM_mask/`: WM mask in nativespace
- - `native_CSF_mask/`: CSF mask in nativespace
- - `native_labels/`: atlas labels in nativespace
- - `native_bold_ref/`: a volumetric 3D EPI average generated from the 4D `native_bold/`
- - `commonspace_bold/`: preprocessed EPI timeseries resampled to commonspace
- - `commonspace_mask/`: brain mask in commonspace
- - `commonspace_WM_mask/`: WM mask in commonspace
- - `commonspace_CSF_mask/`: CSF mask in commonspace
- - `commonspace_vascular_mask/`: vascular mask in commonspace
- - `commonspace_labels/`: atlas labels in commonspace
- - `commonspace_resampled_template/`: the commonspace anatomical template, resampled to the EPI's dimensions
- - `input_bold/`: the raw EPI scans provided as inputs in the BIDS data folder
- - `initial_bold_ref/`: the initial volumetric 3D EPI average generated from the 4D `input_bold/`
- - `raw_brain_mask/`: brain mask resampled onto the 4D `input_bold/`
- - `inho_cor_bold/`: the volumetric 3D EPI (`initial_bold_ref/`) after inhomogeneity correction, which is later used for registration of the EPI
- - `inho_cor_bold_warped2anat/`: inho_cor_bold after co-registration to the associated anatomical image (`anat_preproc/`)
- - `std_map_preprocess/`: the temporal standard deviation at each voxel on the `commonspace_bold/`
- - `tSNR_map_preprocess/`: the temporal signal-to-noise ratio (tSNR) of the `commonspace_bold/`
-
-- `unbiased_template_datasink/`: Outputs related to the generation of the unbiased template using https://github.com/CoBrALab/optimized_antsMultivariateTemplateConstruction. The unbiased template corresponds to the average of all anatomical (or functional with `--bold_only`) scans after their alignment.
- - `unbiased_template/`: the unbiased template generated from the input dataset scans
- - `warped_unbiased_template/`: the unbiased template, registered to the reference atlas in commonspace
-
-- `transforms_datasink/`: datasink for all the relevant transform files resampling between the different spaces. The bold_to_anat registration transformed the raw EPI to overlap with the anatomical image, correcting for susceptibility distortions, which corresponds to the native space. The native_to_unbiased registration overlaps every scans to the generated unbiased template, and then the unbiased_to_atlas corresponds to the registration of the unbiased template with the reference atlas, which defines the commonspace.
- - `bold_to_anat_affine/`: affine transforms from the EPI co-registration to the anatomical image
- - `bold_to_anat_warp/`: non-linear transforms from the EPI co-registration to the anatomical image
- - `bold_to_anat_inverse_warp/`: inverse of the non-linear transforms from the EPI co-registration to the anatomical image
- - `native_to_unbiased_affine/`: affine transforms for the alignment between native space and the unbiased template
- - `native_to_unbiased_warp/`: non-linear transforms for the alignment between native space and the unbiased template
- - `native_to_unbiased_inverse_warp/`: inverse of the non-linear transforms for the alignment between native space and the unbiased template
- - `unbiased_to_atlas_affine/`: affine transforms for the alignment between unbiased template and the atlas in commonspace
- - `unbiased_to_atlas_warp/`: non-linear transforms for the alignment between unbiased template and the atlas in commonspace
- - `unbiased_to_atlas_inverse_warp/`: inverse of the non-linear transforms for the alignment between unbiased template and the atlas in commonspace
-
-- `motion_datasink/`: files derivated from motion estimation
- - `motion_params_csv/`: contains the 24 motion parameters which can be used as nuisance regressors at the confound correction pipeline stage.
- - `FD_csv/`: a CSV file with timescourses for either the mean or maximal framewise displacement (FD) estimations.
- - `FD_voxelwise/`: a Nifti image which contains framewise displacement evaluated at each voxel
- - `pos_voxelwise/`: a Nifti image which tracks the displacement (derived from the head motion realignment parameters) of each voxel across time
-
-
-## Confound Correction Outputs
-Important outputs from confound correction will be found in the `confound_correction_datasink/`:
-- `confound_correction_datasink/`:
- - `cleaned_timeseries/`: cleaned timeseries after the application of confound correction
- - `frame_censoring_mask/`: contains CSV files each recording as a boolean vector which timepoints were censored if frame censoring was applied.
- - `aroma_out/`: if `--ica_aroma` is applied, this folder contains outputs from running ICA-AROMA, which includes the MELODIC ICA outputs and the component classification results
- - `plot_CR_overfit/`: will contain figures illustrating the variance explained by random regressors during confound correction, and the variance explained by the real regressors after substrating the variance from random regressors.
-
-
-## Analysis Outputs
-
-Outputs from analyses will be found in the `analysis_datasink/`, whereas outputs relevant to the `--data_diagnosis` are found in `data_diagnosis_datasink/`:
-- `analysis_datasink/`:
- - `group_ICA_dir/`: complete output from MELODIC ICA, which the melodic_IC.nii.gz Nifti which gives all spatial components, and `report/` folder which includes a HTML visualization.
- - `matrix_data_file/`: .pkl file which contains a 2D numpy array representing the whole-brain correlation matrix. If `--ROI_type parcellated` is selected, the row/column indices of the array are matched in increasing order of the atlas ROI label number.
- - `matrix_fig/`: .png file which displays the correlation matrix
- - `seed_correlation_maps/`: nifti files for seed-based connectivity analysis, where each seed provided in `--seed_list` has an associated voxelwise correlation maps
- - `dual_regression_nii/`: the spatial maps from dual regression, which correspond to the linear coefficients from the second regression. The list of 3D spatial maps obtained are concatenated into a 4D Nifti file, where the order of component is consistent with the priors provided in `--prior_maps`.
- - `dual_regression_timecourse_csv/`: a CSV file which stores the outputs from the first linear regression during dual regression. This corresponds to a timecourse associated to each prior component from `--prior_maps`.
- - `NPR_prior_filename/`: spatial components fitted during NPR
- - `NPR_prior_timecourse_csv/`: timecourses associated to each components from NPR_prior_filename
- - `NPR_extra_filename/`: the extra spatial components fitted during NPR which were not part of priors
- - `NPR_extra_timecourse_csv/`: timecourses associated to each components from NPR_extra_filename
-(diagnosis_datasink_target)=
-- `data_diagnosis_datasink/`:
- - `figure_temporal_diagnosis/`: figure which displays scan-level temporal features from the [spatiotemporal diagnosis](diagnosis_target)
- - `figure_spatial_diagnosis/`: figure which displays scan-level spatial features from the [spatiotemporal diagnosis](diagnosis_target)
- - `analysis_QC/`: group-level features of data quality from `--data_diagnosis`
- - `sample_distributions/`: contains the [distribution plots](dist_plot_target)
- - `{analysis}_sample_distribution.png`: the distribution plot for a given network analysis
- - `{analysis}_outlier_detection.csv`: a CSV which associates the measures displayed in the distribution plot with corresponding scan IDs
- - `parametric_stats/`: [group statistical report](group_stats_target) for analysis quality control (using parametric measures)
- - `DR{component #}_QC_maps.png`: The _QC_maps.png files are displaying statistical maps relevant to analysis quality control. The DR refers to dual regression analysis, and the {component #} is relating the file to one of the BOLD components specified in `--prior_bold_idx`
- - `DR{component #}_QC_stats.csv`: a follow-up to _QC_maps.png which allows for the quantitative categorization of data quality outcomes as in {cite}`Desrosiers-Gregoire2024-ou`
- - `seed_FC{seed #}_QC_maps.png`: same statistical maps as with `DR{component #}_QC_maps.png`, but for seed-based connectivity analysis
- - `seed_FC{seed #}_QC_stats.csv`: same measures as with `DR{component #}_QC_maps.png`, but for seed-based connectivity analysis
- - `non_parametric_stats/`: same as `parametric_stats/`, but using non-parametric measures
- - `temporal_info_csv/`: CSV file containing the data plotted with `figure_temporal_diagnosis/`
- - `spatial_VE_nii/`: Nifti file with the confound regression percentage variance explained (R^2) at each voxel
- - `CR_prediction_std_nii/`: Nifti file with the confound regression variance explained at each voxel
- - `random_CR_std_nii/`: Nifti file with the variance explained from random regressors at each voxel
- - `corrected_CR_std_nii/`: Nifti file with the confound regression variance explained at each voxel after removing the variance explained by random regressors
- - `temporal_std_nii/`: the standard deviation at each voxel after confound correction
- - `GS_cov_nii/`: the covariance of each voxel with the global signal
diff --git a/docs/preproc_QC.md b/docs/preproc_QC.md
deleted file mode 100644
index 70429a55..00000000
--- a/docs/preproc_QC.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# Preprocessing quality control (QC)
-
-Several registration operations during preprocessing are prone to fail in accurately aligning images, and it is thus necessary to visually inspect the quality of registration to prevent errors arising from failed alignment, or biased analyses downstream. For this purpose, RABIES generates automatically a set PNG images allowing for efficient visual assessment of key registration steps. These are found in the `{output_folder}/preprocess_QC_report/` folder, which contains several subfolders belonging to different registration step in the pipeline or providing supportive information about the files:
-
-- `anat_inho_cor/`: intensity inhomogeneities are corrected for prior to important registration operations. This folder allows to assess the quality of the inhomogeneity correction, which is crucial for the performance of downstream registration. The figure is divided in 4 columns, showing 1-the raw image, 2-an initial correction of the image, 3-an overlay of the anatomical mask used to conduct a final correction (by default obtained through a preliminary registration to the commonspace template), and 4-final corrected output.
-
-- `Native2Unbiased/`: alignment between each anatomical image and the generated unbiased template. This registration step controls for the overlap between different scanning sessions.
-
-- `Unbiased2Atlas/`: alignment of the generated unbiased template to the external anatomical template in commonspace. This step ensures proper alignment with the commonspace and the associated brain parcellation.
-
-- `bold_inho_cor/`: same as `anat_inho_cor/`, but conducted on the 3D reference EPI image which is used for estimating the alignment of the EPI.
-
-- `EPI2Anat/`: shows the alignment of the EPI image to its associated anatomical image of the same scanning session. This step resamples the EPI into native space, and corrects for susceptibility distortions through non-linear registration. An example is shown below:
-
-- `template_files/`: displays the overlap of the provided external anatomical template with it's associated masks and labels. Allows to validate that proper template files were provided and share those along the RABIES report.
-
-- `temporal_features/`: includes the timecourse of the head motion realignment parameters together with framewise displacement, to observe subject motion. Also includes a spatial map of the signal variability at each voxel and then the temporal signal-to-noise ratio (tSNR).
-
-
-
-
-```{toctree}
----
-maxdepth: 3
----
-nested_docs/registration_troubleshoot.md
diff --git a/docs/preprocessing.md b/docs/preprocessing.md
deleted file mode 100644
index 36fe0873..00000000
--- a/docs/preprocessing.md
+++ /dev/null
@@ -1,99 +0,0 @@
-# Preprocessing stage
-
-
-The preprocessing of fMRI scans prior to analysis consists of, at minimum, the anatomical alignment of scans to a common space, head realignment to correct for motion, and the correction of susceptibility distortions arising from the echo-planar imaging (EPI) acquisition of functional scans. The core preprocessing pipeline in RABIES carries each of these steps with state-of-the-art processing tools and techniques.
-
-To conduct common space alignment, structural images, which were acquired along the EPI scans, are initially corrected for inhomogeneities (**Structural inhomogeneity correction**) and then registered together to allow the alignment of different MRI acquisitions. This registration is conducted by generating an unbiased data-driven template (**Unbiased template generation**) through the iterative non-linear registration of each image to the dataset consensus average, where the average gets updated at each iteration to provide an increasingly representative dataset template (; {cite}`Avants2011-av`). The finalized template after the last iteration provides a representative alignment of each MRI session to a template that shares the acquisition properties of the dataset (e.g. brain shape, FOV, anatomical contrast, ...), making it a stable registration target for cross-subject alignment. This newly-generated unbiased template is then itself registered to an external reference atlas to provide both an anatomical segmentation and a common space comparable across studies defined from the provided reference atlas (**Atlas registration**).
-
-The remaining preprocessing involves the EPI image. A volumetric EPI image is first derived using a trimmed mean across the EPI frames, after an initial motion realignment step (**3D EPI generation**). Using this volumetric EPI as a target, the head motion parameters are estimated by realigning each EPI frame to the target using a rigid registration (**Head motion estimation**). To correct for EPI susceptibility distortions, the volumetric EPI is first subjected to an inhomogeneity correction step (**Functional inhomogeneity correction**), and then registered non-linearly to the anatomical scan from the same MRI session, which allows to calculate the required geometrical transforms for recovering brain anatomy {cite}`Wang2017-ci` (**Susceptibility distortion estimation**). Finally, after calculating the transformations required to correct for head motion and susceptibility distortions, both transforms are concatenated into a single resampling operation (avoiding multiple resampling) which is applied at each EPI frame, generating the preprocessed EPI timeseries in native space {cite}`Esteban2019-rs` (**Frame-wise resampling**). Preprocessed timeseries in common space are also generated by further concatenating the transforms allowing resampling to the reference atlas.
-
-The workflow of the RABIES preprocessing pipeline is summarized in the diagram above, and each preprocessing module is further described below.
-
-## Structural inhomogeneity correction
-
-**Figure:** displays steps of inhomogeneity correction for the structural image.
-
-### rabies.preprocess_pkg.inho_correction.init_inho_correction_wf [[source code](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/inho_correction.py)]
-
-```{literalinclude} ../rabies/preprocess_pkg/inho_correction.py
-:start-after: inho_correction_head_start
-:end-before: inho_correction_head_end
-```
-
-## Common space alignment (i.e. Unbiased template generation + Atlas registration)
-
-**Figure:** displays the overlap between a structural scan (top) and the dataset-generated unbiased template (bottom).
-
-**Figure:** displays the overlap between the unbiased template (top) and the reference atlas template (bottom).
-
-### rabies.preprocess_pkg.commonspace_reg.init_commonspace_reg_wf [[source code](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/commonspace_reg.py)]
-```{literalinclude} ../rabies/preprocess_pkg/commonspace_reg.py
-:start-after: commonspace_wf_head_start
-:end-before: commonspace_wf_head_end
-```
-
-(3D_EPI_target)=
-## 3D EPI generation
-### rabies.preprocess_pkg.bold_ref.init_bold_reference_wf [[source code](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/bold_ref.py)]
-
-```{literalinclude} ../rabies/preprocess_pkg/bold_ref.py
-:start-after: gen_bold_ref_head_start
-:end-before: gen_bold_ref_head_end
-```
-
-## Head motion estimation
-
-**Figure:** example of the 6 motion parameters.
-
-### rabies.preprocess_pkg.hmc.init_bold_hmc_wf [[source code](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/hmc.py)]
-
-```{literalinclude} ../rabies/preprocess_pkg/hmc.py
-:start-after: hmc_wf_head_start
-:end-before: hmc_wf_head_end
-```
-
-### rabies.preprocess_pkg.hmc.EstimateMotionParams [[source code](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/hmc.py)]
-
-```{literalinclude} ../rabies/preprocess_pkg/hmc.py
-:start-after: motion_param_head_start
-:end-before: motion_param_head_end
-```
-
-## Functional inhomogeneity correction
-
-**Figure:** displays steps of inhomogeneity correction for the volumetric EPI.
-
-The workflow is the same as the **structural inhomogeneity correction**.
-
-## Susceptibility distortion estimation
-
-**Figure:** displays the overlap between the volumetric EPI (top) and structural image (bottom).
-
-### rabies.preprocess_pkg.registration.init_cross_modal_reg_wf [[source code](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/registration.py)]
-
-```{literalinclude} ../rabies/preprocess_pkg/registration.py
-:start-after: cross_modal_reg_head_start
-:end-before: cross_modal_reg_head_end
-```
-
-## Frame-wise resampling
-
-### rabies.preprocess_pkg.resampling.init_bold_preproc_trans_wf [[source code](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/resampling.py)]
-
-```{literalinclude} ../rabies/preprocess_pkg/resampling.py
-:start-after: bold_resampling_head_start
-:end-before: bold_resampling_head_end
-```
-
-## Resampling of masks and labels
-
-### rabies.preprocess_pkg.resampling.init_mask_preproc_trans_wf [[source code](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/resampling.py)]
-
-```{literalinclude} ../rabies/preprocess_pkg/resampling.py
-:start-after: mask_resampling_head_start
-:end-before: mask_resampling_head_end
-```
-
-## Adapted workflow without structural scans (i.e. --bold_only)
-Structural scans are recommended, but not required to complete preprocessing with RABIES. An alternative workflow is also implemented to preprocess a input dataset which contains only EPI functional images, and can be selected with the `--bold_only` option. In this alternative workflow, the volumetric EPI corrected for inhomogeneity during **Functional inhomogeneity correction** replaces the structural image for the purpose of common space alignment, and is thus used for generating the unbiased template, in turn, this template is registered to the reference atlas. This final registration to the atlas accounts for estimation of susceptibility distortions instead of the registration to a structural image from the same MRI session.
-If using the RABIES default mouse atlas, the default template is changed to a EPI reference template, which offers a more robust target for EPI registration than a structural image as reference template.
diff --git a/docs/reference/bibliography.md b/docs/reference/bibliography.md
new file mode 100644
index 00000000..7fb4808b
--- /dev/null
+++ b/docs/reference/bibliography.md
@@ -0,0 +1,6 @@
+# Bibliography
+
+Every work cited in this documentation.
+
+```{bibliography} ../_static/refs.bib
+```
diff --git a/docs/reference/bids_inputs.md b/docs/reference/bids_inputs.md
new file mode 100644
index 00000000..94f7f384
--- /dev/null
+++ b/docs/reference/bids_inputs.md
@@ -0,0 +1,94 @@
+# Input data requirements
+
+The input dataset must be organised according to the
+[BIDS data structure](https://bids.neuroimaging.io/) {cite}`Gorgolewski2016-zm`.
+
+## How RABIES traverses a dataset
+
+RABIES iterates through every subject found to contain a functional file, and
+within each subject through the sessions and runs present.
+
+When anatomical scans are used — that is, when `--bold_only` is not set — each
+functional scan is matched to one anatomical scan **from the same subject and
+session**.
+
+## Scan identification
+
+```{list-table}
+:header-rows: 1
+:widths: 30 30 40
+
+* - Image type
+ - Default BIDS suffixes
+ - Parameter
+* - Functional
+ - `bold`, `cbv`
+ - `--bids_filter`, key `func`
+* - Structural
+ - `T1w`, `T2w`
+ - `--bids_filter`, key `anat`
+```
+
+Files matching neither filter are ignored. The default filter is equivalent to:
+
+```{code-block} json
+:caption: Default value of --bids_filter
+
+{
+ "func": {
+ "suffix": ["bold", "cbv"]
+ },
+ "anat": {
+ "suffix": ["T1w", "T2w"]
+ }
+}
+```
+
+```{seealso}
+[How to select which scans get processed](../how_to/select_scans.md) for
+customising the filter and for selecting individual scans.
+```
+
+## Image orientation
+
+RABIES expects images in the NIfTI standard RAS+ orientation
+(Right–Anterior–Superior). Incorrectly oriented images are a common source of
+registration failures — see
+[How to check image orientation](../how_to/check_orientation.md).
+
+## Example dataset
+
+The [RABIES example dataset](http://doi.org/10.5281/zenodo.8349029)
+(`test_dataset.zip`) has the following structure:
+
+```{code-block} text
+:caption: Two subjects, one session each, with paired anatomical and functional scans
+
+test_dataset/
+├── sub-PHG001
+│ └── ses-3
+│ ├── anat
+│ │ ├── sub-PHG001_ses-3_acq-RARE_T2w.json
+│ │ └── sub-PHG001_ses-3_acq-RARE_T2w.nii.gz
+│ └── func
+│ ├── sub-PHG001_ses-3_task-rest_acq-EPI_run-1_bold.json
+│ └── sub-PHG001_ses-3_task-rest_acq-EPI_run-1_bold.nii.gz
+└── sub-PHG002
+ └── ses-3
+ ├── anat
+ │ ├── sub-PHG002_ses-3_acq-RARE_T2w.json
+ │ └── sub-PHG002_ses-3_acq-RARE_T2w.nii.gz
+ └── func
+ ├── sub-PHG002_ses-3_task-rest_acq-EPI_run-1_bold.json
+ └── sub-PHG002_ses-3_task-rest_acq-EPI_run-1_bold.nii.gz
+
+8 directories, 8 files
+```
+
+This is the dataset used in [the tutorial](../tutorials/first_run.md).
+
+## Format conversion
+
+Conversion from Bruker raw format to NIfTI can be handled with
+[BrkRaw](https://brkraw.github.io/). The CoBrALab maintains
+[notes on the conversion](https://github.com/CoBrALab/documentation/wiki/bruker2nifti-conversion).
diff --git a/docs/reference/cli.md b/docs/reference/cli.md
new file mode 100644
index 00000000..c7398b3c
--- /dev/null
+++ b/docs/reference/cli.md
@@ -0,0 +1,162 @@
+# Command line interface
+
+RABIES runs from a terminal. The software is divided into three processing
+stages, and one of them must be selected on every invocation:
+
+```text
+rabies [execution options] {preprocess,confound_correction,analysis} [stage options] input output
+```
+
+```{list-table}
+:header-rows: 1
+:widths: 25 25 50
+
+* - Stage
+ - Takes as input
+ - Produces
+* - `preprocess`
+ - A BIDS directory
+ - Motion-corrected, distortion-corrected timeseries aligned to commonspace
+* - `confound_correction`
+ - A `preprocess` output directory
+ - Cleaned timeseries
+* - `analysis`
+ - A `confound_correction` output directory
+ - Connectivity estimates and data quality reports
+```
+
+Execution options — parallel processing, memory management, scan selection —
+are given **before** the stage name. Stage options are given after it.
+
+```{note}
+The `--help` output below is generated at documentation build time from the
+RABIES version these docs were built for. Run `rabies --help` locally to see
+the options for the version you have installed.
+```
+
+## Argument syntax
+
+RABIES uses three argument shapes:
+
+Flags
+: `--apply_STC`. Present or absent, no value.
+
+Single values
+: `--TR 1.2`. The value follows the parameter name after a space.
+
+Lists
+: `--nuisance_regressors WM_signal CSF_signal mot_6`. Values follow the
+ parameter name, separated by spaces.
+
+Key-value groups
+: `--commonspace_reg masking=true,template_registration=SyN`. One parameter
+ takes several settings as comma-separated `key=value` pairs, with no spaces.
+
+## `rabies --help`
+
+Execution options that apply to every stage: parallel processing plugin, thread
+and memory limits, scan inclusion and exclusion, output data type and
+interpolation.
+
+:::{dropdown} rabies --help
+:icon: terminal
+
+```{program-output} rabies --help
+```
+:::
+
+## `rabies preprocess --help`
+
+Input selection, image corrections, registration options, resampling, slice
+timing correction, and the reference atlas files.
+
+:::{dropdown} rabies preprocess --help
+:icon: terminal
+
+```{program-output} rabies preprocess --help
+```
+:::
+
+## `rabies confound_correction --help`
+
+Frame censoring, detrending, ICA-AROMA, frequency filtering, confound
+regression, intensity scaling and smoothing.
+
+:::{dropdown} rabies confound_correction --help
+:icon: terminal
+
+```{program-output} rabies confound_correction --help
+```
+:::
+
+## `rabies analysis --help`
+
+Seed-based connectivity, whole-brain connectivity matrices, group ICA, dual
+regression, and the `--data_diagnosis` quality reports.
+
+:::{dropdown} rabies analysis --help
+:icon: terminal
+
+```{program-output} rabies analysis --help
+```
+:::
+
+## Worked examples
+
+### Preprocessing
+
+```sh
+rabies -p MultiProc preprocess input_BIDS/ preprocess_outputs/ \
+ --apply_STC --TR 1.2 \
+ --commonspace_reg masking=true,brain_extraction=false,template_registration=SyN,fast_commonspace=false
+```
+
+`-p MultiProc`
+: Executes the pipeline in parallel across local threads. This is an execution
+ option, so it comes before the stage name.
+
+`--apply_STC`
+: Applies slice timing correction, which is off by default.
+
+`--TR 1.2`
+: The repetition time in seconds, needed for slice timing correction. Defaults
+ to `auto`, which reads the TR from the NIfTI header.
+
+`--commonspace_reg ...`
+: Options for the commonspace registration step. `masking=true` uses the brain
+ masks from inhomogeneity correction to drive registration;
+ `template_registration=SyN` requests non-linear registration to the
+ commonspace template.
+
+### Confound correction
+
+```sh
+rabies -p MultiProc confound_correction preprocess_outputs/ confound_correction_outputs/ \
+ --nuisance_regressors WM_signal CSF_signal vascular_signal mot_6 \
+ --smoothing_filter 0.3
+```
+
+`--nuisance_regressors`
+: The nuisance timeseries to model and regress out — here the WM, CSF and
+ vascular mean signals plus the 6 rigid realignment parameters from head
+ motion. See [nuisance regressor definitions](regressor_target).
+
+`--smoothing_filter 0.3`
+: Gaussian spatial smoothing with a 0.3 mm filter.
+
+### Analysis
+
+```sh
+rabies -p MultiProc analysis confound_correction_outputs/ analysis_outputs/ \
+ --group_ica apply=true,dim=30,random_seed=1
+```
+
+`--group_ica apply=true,dim=30,random_seed=1`
+: Group independent component analysis with 30 components and a fixed random
+ seed.
+
+```{seealso}
+- [How to run RABIES in a container](../how_to/run_with_containers.md) — path binding syntax for Apptainer and Docker
+- [Input data requirements](bids_inputs.md) — what the input directory must look like
+- [Understanding the outputs](outputs.md) — what each stage writes
+```
diff --git a/docs/reference/index.md b/docs/reference/index.md
new file mode 100644
index 00000000..862337d8
--- /dev/null
+++ b/docs/reference/index.md
@@ -0,0 +1,36 @@
+# Reference
+
+Descriptive, factual material to consult while you work. Reference pages
+describe how RABIES behaves; they do not tell you what to do. For that, see the
+[how-to guides](../how_to/index.md).
+
+## Running RABIES
+
+```{toctree}
+---
+maxdepth: 1
+---
+bids_inputs
+cli
+```
+
+## What RABIES produces
+
+```{toctree}
+---
+maxdepth: 1
+---
+outputs
+qc_outputs
+metrics
+```
+
+## Internals
+
+```{toctree}
+---
+maxdepth: 1
+---
+workflows
+bibliography
+```
diff --git a/docs/reference/metrics.md b/docs/reference/metrics.md
new file mode 100644
index 00000000..48ffae7e
--- /dev/null
+++ b/docs/reference/metrics.md
@@ -0,0 +1,237 @@
+# Metric definitions
+
+(metrics_target)=
+
+Precise definitions of every quantity RABIES computes and reports. Throughout
+this page, the root-mean square (RMS) is
+$||x||_2 = \sqrt{\frac{1}{n}\sum_{i=1}^{n}x_i^2}$.
+
+```{seealso}
+For where these values appear, see [Output files](outputs.md). For how to
+interpret them, see [Data quality assessment](../explanation/data_quality.md).
+```
+
+(regressor_target)=
+
+## Nuisance regressors for confound regression
+
+Selected with `--nuisance_regressors` at the confound correction stage.
+
+**mot_6**
+: The head motion translation and rotation parameters. Prior to the regression,
+ the motion regressors are subjected to the same frame censoring, detrending
+ and frequency filtering applied to the BOLD timeseries, to avoid the
+ re-introduction of previously corrected confounds, as recommended in
+ {cite}`Power2014-yf` and {cite}`Lindquist2019-lq`.
+
+**mot_24**
+: The 6 motion parameters together with their temporal derivatives, plus 12
+ additional parameters obtained by taking the squared terms — the Friston 24
+ parameters {cite}`Friston1996-sa`:
+
+ $$
+ mot24_t = [mot6_t,(mot6_t-mot6_{t-1}),(mot6_t)^2,(mot6_t-mot6_{t-1})^2]
+ $$
+
+ with $mot24_t$ representing the list of 24 regressors for timepoint $t$. As
+ with mot_6, the 24 regressors are additionally subjected to censoring,
+ detrending and frequency filtering if applied on BOLD.
+
+**WM/CSF/vascular/global signal**
+: The mean signal computed within the corresponding brain mask (WM, CSF,
+ vascular or whole-brain) from the partially cleaned timeseries, i.e. after
+ confound correction steps 1–4 up to frequency filtering.
+
+**aCompCor_percent**
+: Principal component timecourses derived from timeseries within the combined
+ WM and CSF masks — the aCompCor technique {cite}`Muschelli2014-vi`. From the
+ timeseries within the WM/CSF masks $Y_{WM/CSF}$, a principal component
+ analysis (PCA) decomposition is conducted to derive
+
+ $$
+ Y_{WM/CSF} = W_{aCompCor}C^T
+ $$
+
+ with $C$ a set of spatial principal components and $W$ their associated
+ loadings across time. The first components explaining 50% of the variance are
+ kept, and their loadings $W_{aCompCor}$ provide the aCompCor nuisance
+ regressors. PCA is conducted on the partially cleaned timeseries, i.e. after
+ confound correction steps 1–4 up to frequency filtering.
+
+**aCompCor_5**
+: As **aCompCor_percent**, but the first 5 components are kept instead of a set
+ explaining 50% of the variance.
+
+## Temporal scan diagnosis
+
+(mot6_target)=
+
+**Head motion translation and rotation parameters**
+: 3 rotations (Euler angles in radians) and 3 translations (in mm) measured for
+ head motion realignment at each timeframe.
+
+(FD_target)=
+
+**Framewise displacement**
+: For each timepoint, the displacement — mean across the brain voxels — between
+ the current and the next frame. For each brain voxel within the referential
+ space for head realignment (the [3D EPI](3D_EPI_target) provided as reference
+ for realignment) and for each timepoint, the inverse transform of the head
+ motion parameters from the corresponding timepoint is applied to obtain the
+ voxel position pre-motion correction. Framewise displacement is then computed
+ for each voxel as the Euclidean distance between the pre-motion-correction
+ positions for the current and next timepoints. The mean framewise
+ displacement $FD_t$ at timepoint $t$ is therefore
+
+ $$
+ FD_t = \frac{1}{n}\sum_{i=1}^{n}\sqrt{(x_{i,t+1}-x_{i,t})^2+(y_{i,t+1}-y_{i,t})^2+(z_{i,t+1}-z_{i,t})^2}
+ $$
+
+ using the 3D $x$, $y$ and $z$ spatial coordinates in mm for timepoints $t$
+ and $t+1$ and voxel indices $i$. Framewise displacement for the last frame,
+ which has no future timepoint, is set to 0.
+
+(DVARS_target)=
+
+**DVARS**
+: The estimation of temporal shifts in global signal at each timepoint,
+ measured as the root-mean-square of the timeseries' temporal derivative
+
+ $$
+ DVARS_t = \sqrt{\frac{1}{n}\sum_{i=1}^{n}(Y_{i,t}-Y_{i,t-1})^2}
+ $$
+
+ where $Y_{i,t}$ is the BOLD signal in brain voxel $i$ at timepoint $t$. The
+ first timepoint is set to 0, having no previous timepoint.
+
+**Framewise distance from mean**
+: The mean square error (MSE) between each frame and the average EPI, with the
+ average computed as the tri-mean across time voxelwise. The input is the
+ resampled timeseries output from the `preprocess` stage.
+
+**Whole-brain/Edge/WM/CSF mask**
+: The mean signal across a given brain mask: whole-brain (the global signal),
+ WM, CSF or brain edge.
+
+**$CR_{var}$**
+: The variance estimated by confound regression at each timepoint, computed as
+ $CR_{var} = RMS(Y_{CR})$ across voxels, where $Y_{CR}$ is the
+ [predicted confound timeseries](CR_target).
+
+**CR $R^2$**
+: The proportion of variance explained, and removed, by confound regression.
+ Obtained with $CR_{R^2}= 1-\frac{Var(\hat{Y})}{Var(Y)}$ at each timepoint,
+ where $Y$ and $\hat{Y}$ are the timeseries pre- and post-regression, and
+ $Var(x) = \frac{1}{n}\sum_{i=1}^{n}(x_i - \mu_x)^2$ is the variance with
+ $\mu$ the mean.
+
+**Mean amplitude**
+: A set of timecourses averaged as $\frac{1}{n}\sum_{i=1}^{n}|X_i|$, where
+ $X_i$ is timecourse $i$. The timecourses correspond to one of:
+
+ - *DR confounds*: timecourses from the first stage of dual regression, using
+ the confound components provided to `--prior_confound_idx`
+ - *DR networks*: network timecourses from the first stage of dual regression
+ as specified with `--prior_bold_idx`
+ - *SBC networks*: network timecourses derived from the seeds provided in
+ `--seed_list`
+
+## Spatial scan diagnosis
+
+**BOLDSD**
+: The temporal standard deviation computed for each voxel from the BOLD
+ timeseries.
+
+**CRSD**
+: The temporal standard deviation computed for each voxel from the predicted
+ confound timeseries during confound regression, i.e. [$Y_{CR}$](CR_target).
+
+**CR R2**
+: The proportion of variance explained by confound regression at each voxel.
+ Obtained with $CR_{R^2}= 1-\frac{Var(\hat{Y})}{Var(Y)}$ at each voxel, where
+ $Y$ and $\hat{Y}$ are the timeseries pre- and post-regression, and
+ $Var(x) = \frac{1}{n}\sum_{i=1}^{n}(x_i - \mu_x)^2$ is the variance of $x$
+ with $\mu$ the mean.
+
+**Global signal covariance (GScov)**
+: The covariance between the global signal and the timeseries at each voxel,
+ measured as $GS_{cov} = \frac{1}{n}\sum_{t=1}^{n}Y_t \times GS_t$, where
+ $GS_t = \frac{1}{n}\sum_{i=1}^{n}Y_i$ is the mean across all brain voxels for
+ a given timepoint.
+
+**DR network X**
+: The linear coefficients resulting from the
+ [second regression with dual regression](DR_target), corresponding to a
+ network amplitude map, for the Xth network specified with `--prior_bold_idx`.
+
+**SBC network X**
+: The voxelwise correlation coefficients (Pearson's r) estimated with
+ seed-based connectivity, for the Xth seed provided in `--seed_list`.
+
+(dist_plot_metrics)=
+
+## Distribution plot
+
+**Network amplitude**
+: The overall network amplitude, summarised by computing the L2-norm across a
+ network connectivity map from a subject-level analysis. Such a map can be
+ derived from seed-based correlation, or correspond to the linear coefficients
+ from the [second regression ${\beta}_{SM}$](DR_target) for dual regression.
+
+**Network specificity**
+: The network map (seed-based or dual regression) and the corresponding
+ canonical network map are thresholded to include the top X% of voxels with
+ highest connectivity, X% being defined by `--brainmap_percent_threshold`, and
+ the overlap of the thresholded area is computed using Dice overlap. For dual
+ regression, the canonical network map is the original ICA component
+ corresponding to that network, provided with `--prior_maps`. For seed-based
+ connectivity, the reference network maps are provided using
+ `--seed_prior_list`.
+
+**Dual regression confound correlation**
+: The timecourse for a single network, from a seed or from dual regression, is
+ correlated with the timecourse from each confound component (provided using
+ `--prior_confound_idx`) modelled through dual regression. The absolute mean
+ correlation is then computed to obtain the average amplitude of confound
+ correlations for that network analysis.
+
+**FD-DVARS corr.**
+: For each scan, the correlation between the framewise displacement timecourse
+ and the DVARS timecourse **computed post-confound correction** — this is not
+ the DVARS plotted in the temporal diagnosis figure. Censored timeframes are
+ excluded from both timecourses, and DVARS is recomputed after applying
+ confound correction, so this metric represents *residual* associations
+ between spontaneous motion and the cleaned global signal fluctuations.
+
+**Total $CR_{SD}$**
+: The total standard deviation across the
+ [predicted confound timeseries $Y_{CR}$](CR_target).
+
+**Mean framewise displacement**
+: The mean framewise displacement computed across time, including only frames
+ remaining after the censoring applied for confound correction.
+
+**Temporal degrees of freedom**
+: The degrees of freedom remaining after confound correction:
+
+ ```text
+ tDOF = Original number of timepoints
+ - Number of censored timepoints
+ - Number of AROMA components removed
+ - Number of nuisance regressors
+ ```
+
+(group_QC_metrics)=
+
+## Group statistical QC report
+
+**Specificity of network variability**
+: As with network specificity in the distribution plot, the network variability
+ map and the corresponding canonical network map are thresholded to include
+ the top X% of voxels (X% defined by `--brainmap_percent_threshold`), and the
+ overlap is estimated using Dice overlap.
+
+**Mean confound correlation**
+: For each confound correlation map ($CR_{SD}$, mean FD or tDOF), the mean is
+ computed across voxels within the thresholded area of the canonical network
+ map, giving a mean correlation within the network's core region.
diff --git a/docs/reference/outputs.md b/docs/reference/outputs.md
new file mode 100644
index 00000000..5ed90d63
--- /dev/null
+++ b/docs/reference/outputs.md
@@ -0,0 +1,180 @@
+# Output files
+
+Every processing stage writes its important outputs into `datasink/` folders,
+created inside the output directory given at execution. This page describes
+every file produced.
+
+```{note}
+The output directory also contains the Nipype working directory and the
+serialised workflow state (`.pkl`). Those are internal, but they are what the
+next stage reads to locate the previous stage's files — do not move or delete
+them between stages.
+```
+
+## Preprocessing outputs
+
+Preprocessing writes five datasinks: `anat_datasink/`, `bold_datasink/`,
+`unbiased_template_datasink/`, `transforms_datasink/` and `motion_datasink/`.
+The quality control images are written separately to `preprocess_QC_report/`,
+described in [Preprocessing QC outputs](qc_outputs.md).
+
+### `anat_datasink/`
+
+Inhomogeneity-corrected anatomical scans.
+
+- `anat_preproc/`: anatomical scans after inhomogeneity correction
+
+### `bold_datasink/`
+
+All outputs related to the functional scans. Files are resampled either onto
+the native space or the commonspace of the EPI. Native space outputs are
+resampled over the anatomical scan from the corresponding MRI session;
+commonspace outputs are resampled over the reference atlas. The original EPI
+voxel resolution is unchanged during resampling unless specified otherwise in
+the RABIES command.
+
+**Native space**
+
+- `native_bold/`: preprocessed EPI timeseries resampled to native space
+- `native_brain_mask/`: brain mask in native space
+- `native_WM_mask/`: WM mask in native space
+- `native_CSF_mask/`: CSF mask in native space
+- `native_labels/`: atlas labels in native space
+- `native_bold_ref/`: a volumetric 3D EPI average generated from the 4D `native_bold/`
+
+**Commonspace**
+
+- `commonspace_bold/`: preprocessed EPI timeseries resampled to commonspace
+- `commonspace_mask/`: brain mask in commonspace
+- `commonspace_WM_mask/`: WM mask in commonspace
+- `commonspace_CSF_mask/`: CSF mask in commonspace
+- `commonspace_vascular_mask/`: vascular mask in commonspace
+- `commonspace_labels/`: atlas labels in commonspace
+- `commonspace_resampled_template/`: the commonspace anatomical template, resampled to the EPI's dimensions
+
+**Inputs and intermediates**
+
+- `input_bold/`: the raw EPI scans provided as inputs in the BIDS data folder
+- `initial_bold_ref/`: the initial volumetric 3D EPI average generated from the 4D `input_bold/`
+- `raw_brain_mask/`: brain mask resampled onto the 4D `input_bold/`
+- `inho_cor_bold/`: the volumetric 3D EPI (`initial_bold_ref/`) after inhomogeneity correction, later used for registration of the EPI
+- `inho_cor_bold_warped2anat/`: `inho_cor_bold` after co-registration to the associated anatomical image (`anat_preproc/`)
+- `std_map_preprocess/`: the temporal standard deviation at each voxel of `commonspace_bold/`
+- `tSNR_map_preprocess/`: the temporal signal-to-noise ratio (tSNR) of `commonspace_bold/`
+
+### `unbiased_template_datasink/`
+
+Outputs from the generation of the unbiased template using
+[optimized_antsMultivariateTemplateConstruction](https://github.com/CoBrALab/optimized_antsMultivariateTemplateConstruction).
+The unbiased template is the average of all anatomical scans (or functional
+scans with `--bold_only`) after their alignment.
+
+- `unbiased_template/`: the unbiased template generated from the input dataset scans
+- `warped_unbiased_template/`: the unbiased template, registered to the reference atlas in commonspace
+
+### `transforms_datasink/`
+
+All transform files for resampling between spaces.
+
+The `bold_to_anat` registration transforms the raw EPI to overlap with the
+anatomical image, correcting susceptibility distortions, which defines native
+space. The `native_to_unbiased` registration overlaps every scan onto the
+generated unbiased template. The `unbiased_to_atlas` registration aligns the
+unbiased template with the reference atlas, which defines commonspace.
+
+- `bold_to_anat_affine/`: affine transforms from the EPI co-registration to the anatomical image
+- `bold_to_anat_warp/`: non-linear transforms from the EPI co-registration to the anatomical image
+- `bold_to_anat_inverse_warp/`: inverse of `bold_to_anat_warp/`
+- `native_to_unbiased_affine/`: affine transforms for the alignment between native space and the unbiased template
+- `native_to_unbiased_warp/`: non-linear transforms for the same alignment
+- `native_to_unbiased_inverse_warp/`: inverse of `native_to_unbiased_warp/`
+- `unbiased_to_atlas_affine/`: affine transforms for the alignment between the unbiased template and the atlas in commonspace
+- `unbiased_to_atlas_warp/`: non-linear transforms for the same alignment
+- `unbiased_to_atlas_inverse_warp/`: inverse of `unbiased_to_atlas_warp/`
+
+### `motion_datasink/`
+
+Files derived from motion estimation.
+
+- `motion_params_csv/`: the 24 motion parameters, usable as nuisance regressors at the confound correction stage
+- `FD_csv/`: a CSV with timecourses for either the mean or maximal [framewise displacement](FD_target) estimations
+- `FD_voxelwise/`: a NIfTI image containing framewise displacement evaluated at each voxel
+- `pos_voxelwise/`: a NIfTI image tracking the displacement of each voxel across time, derived from the head motion realignment parameters
+
+## Confound correction outputs
+
+### `confound_correction_datasink/`
+
+- `cleaned_timeseries/`: cleaned timeseries after the application of confound correction
+- `frame_censoring_mask/`: CSV files recording, as a boolean vector, which timepoints were censored, if frame censoring was applied
+- `aroma_out/`: outputs from running ICA-AROMA if `--ica_aroma` is applied, including the MELODIC ICA outputs and the component classification results
+- `plot_CR_overfit/`: figures illustrating the variance explained by random regressors during confound correction, and the variance explained by the real regressors after subtracting the variance from random regressors
+
+## Analysis outputs
+
+### `commonspace_analysis_datasink/` and `nativespace_analysis_datasink/`
+
+Which of these appears depends on the space the cleaned timeseries were
+produced in:
+
+```{list-table}
+:header-rows: 1
+:widths: 45 55
+
+* - Datasink
+ - Present when
+* - `commonspace_analysis_datasink/`
+ - confound correction produced commonspace timeseries, or `--resample_to_commonspace` was passed, or `--group_ica apply=true` was used
+* - `nativespace_analysis_datasink/`
+ - confound correction produced nativespace timeseries
+```
+
+Both contain the same set of files, listed below. `group_ICA_dir/` is always
+written to `commonspace_analysis_datasink/`, since group ICA requires
+commonspace alignment.
+
+- `group_ICA_dir/`: complete output from MELODIC ICA, including the `melodic_IC.nii.gz` NIfTI giving all spatial components and a `report/` folder with an HTML visualisation
+- `matrix_data_file/`: a `.pkl` file containing a 2D NumPy array representing the whole-brain correlation matrix. With `--ROI_type parcellated`, the row and column indices are matched in increasing order of the atlas ROI label number
+- `matrix_fig/`: a `.png` displaying the correlation matrix
+- `seed_correlation_maps/`: NIfTI files for [seed-based connectivity](SBC_target), one voxelwise correlation map per seed provided in `--seed_list`
+- `dual_regression_nii/`: the spatial maps from [dual regression](DR_target), corresponding to the linear coefficients from the second regression. The 3D spatial maps are concatenated into a 4D NIfTI, with component order consistent with the priors provided in `--prior_maps`
+- `dual_regression_timecourse_csv/`: a CSV storing the outputs from the first linear regression during dual regression — one timecourse per prior component from `--prior_maps`
+- `NPR_prior_filename/`: spatial components fitted during NPR
+- `NPR_prior_timecourse_csv/`: timecourses associated with each component in `NPR_prior_filename/`
+- `NPR_extra_filename/`: the extra spatial components fitted during NPR which were not part of the priors
+- `NPR_extra_timecourse_csv/`: timecourses associated with each component in `NPR_extra_filename/`
+
+(diagnosis_datasink_target)=
+
+### `data_diagnosis_datasink/`
+
+Produced when `--data_diagnosis` is selected. See
+[How to assess data quality](../how_to/assess_data_quality.md) for how to use
+these.
+
+- `figure_temporal_diagnosis/`: scan-level temporal features from the [spatiotemporal diagnosis](diagnosis_target)
+- `figure_spatial_diagnosis/`: scan-level spatial features from the [spatiotemporal diagnosis](diagnosis_target)
+- `temporal_info_csv/`: CSV containing the data plotted in `figure_temporal_diagnosis/`
+- `spatial_VE_nii/`: NIfTI with the confound regression percentage variance explained ($R^2$) at each voxel
+- `CR_prediction_std_nii/`: NIfTI with the confound regression variance explained at each voxel
+- `random_CR_std_nii/`: NIfTI with the variance explained from random regressors at each voxel
+- `corrected_CR_std_nii/`: NIfTI with the confound regression variance explained at each voxel after removing the variance explained by random regressors
+- `temporal_std_nii/`: the standard deviation at each voxel after confound correction
+- `GS_cov_nii/`: the covariance of each voxel with the global signal
+
+`analysis_QC/` holds the group-level features of data quality:
+
+- `sample_distributions/`: the [distribution plots](dist_plot_target)
+ - `{analysis}_sample_distribution.png`: the distribution plot for a given network analysis
+ - `{analysis}_outlier_detection.csv`: a CSV associating the measures displayed in the distribution plot with the corresponding scan IDs
+- `parametric_stats/`: the [group statistical report](group_stats_target) for analysis quality control, using parametric measures
+ - `DR{component #}_QC_maps.png`: statistical maps relevant to analysis quality control. `DR` refers to dual regression analysis, and `{component #}` relates the file to one of the BOLD components specified in `--prior_bold_idx`
+ - `DR{component #}_QC_stats.csv`: a follow-up to `_QC_maps.png` allowing quantitative categorisation of data quality outcomes as in {cite}`Desrosiers-Gregoire2024-ou`
+ - `seed_FC{seed #}_QC_maps.png`: the same statistical maps, for seed-based connectivity analysis
+ - `seed_FC{seed #}_QC_stats.csv`: the same measures, for seed-based connectivity analysis
+- `non_parametric_stats/`: as `parametric_stats/`, but using non-parametric measures
+
+```{seealso}
+[Metric definitions](metrics.md) gives the precise computation behind every
+quantity named on this page.
+```
diff --git a/docs/reference/qc_outputs.md b/docs/reference/qc_outputs.md
new file mode 100644
index 00000000..723c6bce
--- /dev/null
+++ b/docs/reference/qc_outputs.md
@@ -0,0 +1,154 @@
+# Preprocessing QC outputs
+
+Several registration operations during preprocessing can fail to align images
+accurately. RABIES automatically generates a set of PNG images allowing
+efficient visual assessment of the key registration steps, so that failed
+alignment is caught before it biases downstream analyses.
+
+The images are written to `{output_folder}/preprocess_QC_report/`, one
+subfolder per registration step or per supporting file group.
+
+```{important}
+Inspect this report on every run. A failed registration does not raise an
+error — it produces plausible-looking output that is wrong.
+```
+
+## Which folders you get
+
+Some folder names carry the name of the workflow that produced them as a
+prefix, and which commonspace folders exist depends on `--commonspace_reg`.
+
+```{list-table}
+:header-rows: 1
+:widths: 45 55
+
+* - Folder
+ - Present when
+* - `anat_inho_cor/`
+ - structural scans are used, i.e. not `--bold_only`
+* - `bold_inho_cor/`
+ - always
+* - `commonspace_reg_wf.Anat2Unbiased/`
+ - `fast_commonspace=false` (the default)
+* - `commonspace_reg_wf.Unbiased2Atlas/`
+ - `fast_commonspace=false` (the default)
+* - `commonspace_reg_wf.unbiased_template_masking/`
+ - `fast_commonspace=false` and `masking=true`
+* - `commonspace_reg_wf.Anat2Atlas/`
+ - `fast_commonspace=true`
+* - `anat_robust_inho_cor_template.*/`
+ - `--anat_robust_inho_cor apply=true`
+* - `bold_robust_inho_cor_template.*/`
+ - `--bold_robust_inho_cor apply=true`
+* - `EPI2Anat/`
+ - structural scans are used, i.e. not `--bold_only`
+* - `template_files/`
+ - always
+* - `temporal_features/`
+ - always
+```
+
+The `*_robust_inho_cor_template.*` folders contain the same registration
+figures as the `commonspace_reg_wf.*` ones, for the template built during the
+robust inhomogeneity correction pass rather than for the main commonspace
+registration.
+
+## `anat_inho_cor/`
+
+Quality of the intensity inhomogeneity correction applied to the structural
+image, which is performed before the important registration operations and is
+crucial for their performance.
+
+Each figure has 4 columns: **1** the raw image, **2** an initial correction of
+the image, **3** an overlay of the anatomical mask used for the final
+correction (by default obtained through a preliminary registration to the
+commonspace template), and **4** the final corrected output.
+
+```{figure} ../pics/sub-MFC067_ses-1_acq-FLASH_T1w_inho_cor.png
+:alt: Four-column figure showing the stages of structural inhomogeneity correction
+
+Structural inhomogeneity correction.
+```
+
+## `bold_inho_cor/`
+
+The same as `anat_inho_cor/`, but for the 3D reference EPI image used to
+estimate the alignment of the EPI.
+
+```{figure} ../pics/sub-MFC068_ses-1_task-rest_acq-EPI_run-1_bold_inho_cor.png
+:alt: Four-column figure showing the stages of EPI inhomogeneity correction
+
+Functional inhomogeneity correction.
+```
+
+## `commonspace_reg_wf.Anat2Unbiased/`
+
+Alignment between each anatomical image and the generated unbiased template.
+This registration controls the overlap between different scanning sessions.
+
+```{figure} ../pics/sub-MFC067_ses-1_acq-FLASH_T1w_inho_cor_registration.png
+:alt: Overlap between a structural scan and the dataset-generated unbiased template
+
+Structural scan (top) against the unbiased template (bottom).
+```
+
+## `commonspace_reg_wf.Unbiased2Atlas/`
+
+Alignment of the generated unbiased template to the external anatomical
+template in commonspace. This ensures proper alignment with the commonspace and
+its associated brain parcellation.
+
+```{figure} ../pics/atlas_registration.png
+:alt: Overlap between the unbiased template and the reference atlas template
+
+Unbiased template (top) against the reference atlas template (bottom).
+```
+
+## `commonspace_reg_wf.Anat2Atlas/`
+
+Produced instead of the two folders above when `fast_commonspace=true`, which
+skips the unbiased template and registers each scan directly to the reference
+atlas. It shows that direct alignment, one figure per scan.
+
+## `EPI2Anat/`
+
+Alignment of the EPI image to the anatomical image from the same scanning
+session. This step resamples the EPI into native space and corrects
+susceptibility distortions through non-linear registration.
+
+```{figure} ../pics/sub-MFC068_ses-1_task-rest_acq-EPI_run-1_bold_registration.png
+:alt: Overlap between the volumetric EPI and the structural image
+
+Volumetric EPI (top) against the structural image (bottom).
+```
+
+## `template_files/`
+
+Overlap of the provided external anatomical template with its associated masks
+and labels. Use it to confirm the correct template files were provided, and
+share it alongside the RABIES report.
+
+```{figure} ../pics/template_files.png
+:alt: The anatomical template overlaid with its masks and labels
+
+Template, masks and labels.
+```
+
+## `temporal_features/`
+
+The timecourse of the head motion realignment parameters together with
+framewise displacement, showing subject motion. Also includes a spatial map of
+the signal variability at each voxel, and the temporal signal-to-noise ratio
+(tSNR).
+
+```{figure} ../pics/example_temporal_features.png
+:alt: Motion parameter timecourses, framewise displacement, variability and tSNR maps
+
+Temporal features.
+```
+
+```{seealso}
+- [How to troubleshoot registration](../how_to/troubleshoot_registration.md) — what to change when these figures show a failure
+- [Metric definitions](metrics.md) — how framewise displacement and the other quantities are computed
+- [Data quality assessment](../explanation/data_quality.md) — the separate, analysis-stage quality reports
+```
diff --git a/docs/reference/workflows.md b/docs/reference/workflows.md
new file mode 100644
index 00000000..218ce7ab
--- /dev/null
+++ b/docs/reference/workflows.md
@@ -0,0 +1,119 @@
+# Workflow reference
+
+RABIES pipelines are built as [Nipype](https://nipype.readthedocs.io/en/latest/)
+workflows: each node is a processing step, and the required inputs and outputs
+define the links between nodes.
+
+The docstrings below are included directly from the RABIES source, so they
+describe the version of the code these docs were built from. For what each
+workflow is for and why it exists, see
+[The preprocessing workflow](../explanation/preprocessing.md) and
+[The confound correction workflow](../explanation/confound_correction.md).
+
+## Preprocessing
+
+(wf_inho_correction)=
+
+### `rabies.preprocess_pkg.inho_correction.init_inho_correction_wf`
+
+[Source](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/inho_correction.py)
+
+```{literalinclude} ../../rabies/preprocess_pkg/inho_correction.py
+:start-after: inho_correction_head_start
+:end-before: inho_correction_head_end
+```
+
+(wf_commonspace_reg)=
+
+### `rabies.preprocess_pkg.commonspace_reg.init_commonspace_reg_wf`
+
+[Source](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/commonspace_reg.py)
+
+```{literalinclude} ../../rabies/preprocess_pkg/commonspace_reg.py
+:start-after: commonspace_wf_head_start
+:end-before: commonspace_wf_head_end
+```
+
+(wf_bold_ref)=
+
+### `rabies.preprocess_pkg.bold_ref.init_bold_reference_wf`
+
+[Source](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/bold_ref.py)
+
+```{literalinclude} ../../rabies/preprocess_pkg/bold_ref.py
+:start-after: gen_bold_ref_head_start
+:end-before: gen_bold_ref_head_end
+```
+
+(wf_hmc)=
+
+### `rabies.preprocess_pkg.hmc.init_bold_hmc_wf`
+
+[Source](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/hmc.py)
+
+```{literalinclude} ../../rabies/preprocess_pkg/hmc.py
+:start-after: hmc_wf_head_start
+:end-before: hmc_wf_head_end
+```
+
+(wf_motion_params)=
+
+### `rabies.preprocess_pkg.hmc.EstimateMotionParams`
+
+[Source](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/hmc.py)
+
+```{literalinclude} ../../rabies/preprocess_pkg/hmc.py
+:start-after: motion_param_head_start
+:end-before: motion_param_head_end
+```
+
+(wf_cross_modal_reg)=
+
+### `rabies.preprocess_pkg.registration.init_cross_modal_reg_wf`
+
+[Source](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/registration.py)
+
+```{literalinclude} ../../rabies/preprocess_pkg/registration.py
+:start-after: cross_modal_reg_head_start
+:end-before: cross_modal_reg_head_end
+```
+
+(wf_bold_resampling)=
+
+### `rabies.preprocess_pkg.resampling.init_bold_preproc_trans_wf`
+
+[Source](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/resampling.py)
+
+```{literalinclude} ../../rabies/preprocess_pkg/resampling.py
+:start-after: bold_resampling_head_start
+:end-before: bold_resampling_head_end
+```
+
+(wf_mask_resampling)=
+
+### `rabies.preprocess_pkg.resampling.init_mask_preproc_trans_wf`
+
+[Source](https://github.com/CoBrALab/RABIES/blob/master/rabies/preprocess_pkg/resampling.py)
+
+```{literalinclude} ../../rabies/preprocess_pkg/resampling.py
+:start-after: mask_resampling_head_start
+:end-before: mask_resampling_head_end
+```
+
+## Confound correction
+
+(wf_confound_correction)=
+
+### `rabies.confound_correction_pkg.confound_correction.init_confound_correction_wf`
+
+[Source](https://github.com/CoBrALab/RABIES/blob/master/rabies/confound_correction_pkg/confound_correction.py)
+
+```{literalinclude} ../../rabies/confound_correction_pkg/confound_correction.py
+:start-after: confound_wf_head_start
+:end-before: confound_wf_head_end
+```
+
+```{seealso}
+[How to contribute to RABIES](../how_to/contribute.md) covers writing a new
+Nipype interface and connecting it into one of these workflows.
+```
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 3e7f6c1e..15847770 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,7 +1,13 @@
sphinx==5.0
+# sphinx 5.0 needs docutils<0.19 and myst-parser needs <0.20, while
+# sphinxcontrib-bibtex rejects 0.18.* and 0.19.* — 0.17.1 is the only version
+# satisfying all three. Pinned so the resolver cannot pick a broken combination.
+docutils==0.17.1
myst-parser
sphinx-rtd-dark-mode
sphinx-rtd-theme
+sphinx-design<0.6 # 0.6+ requires sphinx>=6
+sphinx-copybutton
sphinxcontrib-bibtex
sphinxcontrib-programoutput
jinja2==3.1.6
diff --git a/docs/running_the_software.md b/docs/running_the_software.md
deleted file mode 100644
index ba3a63c2..00000000
--- a/docs/running_the_software.md
+++ /dev/null
@@ -1,202 +0,0 @@
-# Running The Software
-
-## Input data in BIDS standard
-
-The input dataset must be organized according to the [BIDS data structure](https://bids.neuroimaging.io/){cite}`Gorgolewski2016-zm`. RABIES will iterate through all subjects found to contain a functional file (see section on BIDS filters below), and will also iterate according to sessions and runs found within each subject if available. If anatomical scans are used for preprocessing (i.e. not using `--bold_only`), each functional scan will be matched to one corresponding anatomical scan of the same subject/session (using BIDS filters for the anatomical image, see below).
-
-### Directory structure for an example dataset
-* Our [example dataset](http://doi.org/10.5281/zenodo.8349029) has the following BIDS structure:
-
-
-
-
-
-
-
-
-
-
- https://zenodo.org/record/8349029/preview/test_dataset.zip
- ├── sub-PHG001
- │ └── ses-3
- │ ├── anat
- │ │ ├── sub-PHG001_ses-3_acq-RARE_T2w.json
- │ │ └── sub-PHG001_ses-3_acq-RARE_T2w.nii.gz
- │ └── func
- │ ├── sub-PHG001_ses-3_task-rest_acq-EPI_run-1_bold.json
- │ └── sub-PHG001_ses-3_task-rest_acq-EPI_run-1_bold.nii.gz
- └── sub-PHG002
- └── ses-3
- ├── anat
- │ ├── sub-PHG002_ses-3_acq-RARE_T2w.json
- │ └── sub-PHG002_ses-3_acq-RARE_T2w.nii.gz
- └── func
- ├── sub-PHG002_ses-3_task-rest_acq-EPI_run-1_bold.json
- └── sub-PHG002_ses-3_task-rest_acq-EPI_run-1_bold.nii.gz
-
-
-
-
-8 directories, 8 files
-
-
-
-
-
-
-### BIDS filters to identify functional and structural images
-By default, RABIES will use the 'bold' or 'cbv' suffix to identify functional scans and the 'T1w' or 'T2w' suffix for structural scans. Files which don't match the BIDS filters are ignored. However, the BIDS filters can also be customized with the `--bids_filter` parameter during the preprocessing stage. This can be useful for instance if the default is not enough to find the right set of scans. The custom BIDS filter must be formated into a JSON file with the functional filter under 'func' and structural filter under 'anat' (see example below for the default parameters):
-```json
-{
- "func": {
- "suffix":["bold","cbv"]
- },
- "anat": {
- "suffix":["T1w","T2w"]
- }
-}
-```
-
-## Command Line Interface
-
-RABIES is executed using a command line interface, within a terminal. The software is divided into three main processing stages: preprocessing, confound correction and analysis. Accordingly, the command line interface allows for three different mode of execution, corresponding to the processing stages. So first, when executing the software, one of the processing stage must be selected. Below you can find the general --help message printed with `rabies --help`, which provides a summary of each processing stage together with options for parallel processing and memory management. Then, the --help associated to each processing stage, i.e. `preprocess`, `confound_correction` and `analysis`, describes in more detail the various parameters available to adapt image processing according to the user needs. Click on the corresponding --help to expand:
-
-rabies --help
-
-
-```{program-output} rabies --help
-```
-
-
-
-
-rabies preprocess --help
-
-
-```{program-output} rabies preprocess --help
-```
-
-
-
-
-rabies confound_correction --help
-
-
-```{program-output} rabies confound_correction --help
-```
-
-
-
-
-
-rabies analysis --help
-
-
-```{program-output} rabies analysis --help
-```
-
-
-
-
-
-## Example execution syntax
-The following section provides examples describing the basic syntax for running the RABIES command line interface.
-
-
-**preprocess**
-```sh
-rabies -p MultiProc preprocess input_BIDS/ preprocess_outputs/ --apply_STC --TR 1.2 --commonspace_reg masking=true,brain_extraction=false,template_registration=SyN,fast_commonspace=false
-```
-First, we have to preprocess the dataset before it can be analyzed. In this example, we are running the RABIES preprocessing on the dataset found in the `input_BIDS/` folder, formatted according to the BIDS standard, and the outputs from RABIES are stored in the `preprocess_outputs/` folder. Additional execution parameters were specified:
-* `-p MultiProc` will execute the pipeline in parallel using the local threads available. Notice that this parameter is specified before the processing stage, because it is one of the `Execution Options` affiliated to the `rabies --help`.
-* `--apply_STC` is a boolean variable which, when selected, will apply slice timing correction during preprocessing, which is not applied by default in RABIES.
-* `--TR 1.2` specifies the repetition time (TR) of the fMRI images that are processed, which must be defined to apply slice timing correction appropriately. Notice that this parameter must be provided with an argument, here `1.2` for TR = 1.2sec, and this is done by writing down the argument with a space dividing the associated parameter.
-* `--commonspace_reg masking=true,brain_extraction=false,template_registration=SyN,fast_commonspace=false` this argument manages the options for the commonspace registration step. Some arguments, including `--commonspace_reg`, take multiple parameters as input, where each parameter-value pairs follow the syntax of `parameter=value`. In this case, we are using the masking optino with `masking=true`, which use available brain masks from inhomogeneity correction to drive the registration operations, and we specify a non-linear registration to the commonspace template with `template_registration=SyN`.
-
-**confound_correction**
-```sh
-rabies -p MultiProc confound_correction preprocess_outputs/ confound_correction_outputs/ --nuisance_regressors WM_signal CSF_signal vascular_signal mot_6 --smoothing_filter 0.3
-```
-Next, after completing preprocessing, in most cases the data should be corrected for potential confounds prior to analysis. This is done in the confound correction stage, where confounds are modelled and regressed from the data. In this example we correct the preprocessed data found in the `preprocess_outputs/` folder and store the cleaned outputs in the `confound_correction_outputs/` folder. Among the range of options available for confound correction, we define in this example three parameters:
-* `--nuisance_regressors` is the option to regress nuisance timeseries from the data, i.e., confound regression. This parameter takes a list as input, where each argument in the list is seperated by a space as follow `WM_signal CSF_signal mot_6`. This list defines which nuisance timeseries are going to model confounds during confound regression, in this case, the WM and CSF mean signals together with the 6 rigid realignment parameters from head motion realignment.
-* `--smoothing_filter` will additionally apply Gaussian spatial smoothing, where in this case, a filter size of `0.3` mm is specified.
-
-**analysis**
-```sh
-rabies -p MultiProc analysis confound_correction_outputs analysis_outputs/ --group_ica apply=true,dim=30,random_seed=1
-```
-Finally, after conducting preprocessing and confound correction, certain analyses can be run within RABIES. In this case, the cleaned outputs found in `confound_correction_outputs/` are going to be analyzed, with analysis outputs found in `analysis_outputs/`. We perform a group independent component analysis (ICA) with 30 components by providing `--group_ica apply=true,dim=30,random_seed=1` to the command.
-
-## Execution syntax with containerized installation (Apptainer and Docker)
-
-Containers are independent computing environments which have their own dependencies installed to ensure consistent and reliable
-execution of the software across computing platforms. The main difference in execution syntax when running a container, as opposed to the examples above, is that the paths between the local environment where the data is stored must be 'linked' to the container's internal paths. All relevant directories containing data that will be used by RABIES must be related to a container internal path, and this is done using `-B` for Apptainer and `-v` for Docker. See below for examples:
-
-### Apptainer execution
-
-**preprocess**
-```sh
-apptainer run -B $PWD/input_BIDS:/input_BIDS:ro \
--B $PWD/preprocess_outputs:/preprocess_outputs/ \
-/path_to_apptainer_image/rabies.sif -p MultiProc preprocess /input_BIDS/ /preprocess_outputs/ --apply_STC --TR 1.2 --commonspace_reg masking=true,brain_extraction=false,template_registration=SyN,fast_commonspace=false
-```
-Apptainer containers are stored in image files, for instance `rabies.sif`. `apptainer run /path_to_apptainer_image/rabies.sif` will execute the image, in this case the RABIES pipeline, and the same rules for the command line interface then apply as previously demonstrated. However, the container must gain access to the relevant folders for running RABIES, in this case an input folder and an output folder, and this is done with `-B`:
-* `-B $PWD/input_BIDS:/input_BIDS:ro`: this argument relates the BIDS input folder found in `$PWD/input_BIDS` to an internal path to the container, which we call `/input_BIDS`. The inputs are thus accessed according to this path in the RABIES arguments with `/input_BIDS/`. the `:ro` means that the container is only provided reading permissions at this location.
-* `-B $PWD/preprocess_outputs:/preprocess_outputs/`: same as with the `/input_BIDS/`, but now we are relating a desired output directory `$PWD/preprocess_outputs` to `/preprocess_outputs`, and the container has writing permissions at this path since `:ro` is not present.
-
-
-**confound_correction**
-```sh
-apptainer run -B $PWD/input_BIDS:/input_BIDS:ro \
--B $PWD/preprocess_outputs:/preprocess_outputs/ \
--B $PWD/confound_correction_outputs:/confound_correction_outputs/ \
-/path_to_apptainer_image/rabies.sif -p MultiProc confound_correction /preprocess_outputs/ /confound_correction_outputs/ --nuisance_regressors WM_signal CSF_signal vascular_signal mot_6 --smoothing_filter 0.3
-```
-The required paths are similarly provided for the confound correction stage. Note here that the path to `$PWD/input_BIDS` is still linked to the container, even though it is not explicitely part of the arguments during the confound correction call. This is necessary since the paths used in the preprocessing steps still need to be accessed at later stages, and there will be an error if the paths are not kept consistent across processing steps.
-
-**analysis**
-```sh
-apptainer run -B $PWD/input_BIDS:/input_BIDS:ro \
--B $PWD/preprocess_outputs:/preprocess_outputs/ \
--B $PWD/confound_correction_outputs:/confound_correction_outputs/ \
--B $PWD/analysis_outputs:/analysis_outputs/ \
-/path_to_apptainer_image/rabies.sif -p MultiProc analysis /confound_correction_outputs /analysis_outputs/ --group_ica apply=true,dim=30,random_seed=1
-```
-The same logic applies at the analysis stage.
-
-
-### Docker execution
-```sh
-docker run -it --rm --user $(id -u) \
--v $PWD/input_BIDS:/input_BIDS:ro \
--v $PWD/preprocess_outputs:/preprocess_outputs/ \
-gabdesgreg/rabies:tagname -p MultiProc preprocess /input_BIDS/ /preprocess_outputs/ --apply_STC --TR 1.2 --commonspace_reg masking=true,brain_extraction=false,template_registration=SyN,fast_commonspace=false
-```
-The syntax in Docker is very similar to Apptainer, except that `-B` is replaced by `-v`, and further parameters may be needed (e.g. `-it`, `--rm`). `--user $(id -u)` can be added to mitigate writing permission issues when using Docker. Note that 'tagname' should be replaced by the proper RABIES version you are using (e.g. 0.4.8).
-
-
-## Additional Resources
-
-* **Workshop and tutorial for RABIES:**
- * [Hands-on tutorial](https://github.com/CoBrALab/RABIES_tutorial) on RABIES (originally developed for and presented at the INCF Neuroinformatics Assembly 2023).
- * A workshop providing a complete software overview was [recorded and posted online](https://www.youtube.com/watch?v=LZohKlUgycc&t=2766s&ab_channel=DouglasResearchCentre) on February 2023.
-* Conversion from Bruker raw to Nifti formats can be handled with [BrkRaw](https://brkraw.github.io/) (consult [associated documentation](https://github.com/CoBrALab/documentation/wiki/bruker2nifti-conversion) from the CoBrALab)
-* [CoBrALab recommendations](https://github.com/CoBrALab/documentation/wiki/Running-RABIES-on-niagara) for using compute canada.
-
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
deleted file mode 100644
index 14140181..00000000
--- a/docs/troubleshooting.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# Troubleshooting
-
-This page provides guidance on common issues encountered when using RABIES.
-
-## Checking Image Orientation with ITK-SNAP
-
-RABIES assumes that input data are properly oriented according to the NIfTI standard (RAS+ orientation).
-Incorrectly oriented images are a common source of processing failures and unexpected results.
-Before reporting bugs or troubleshooting other issues, it is critical to verify that your images have the correct orientation.
-
-### Installing ITK-SNAP
-
-[ITK-SNAP](https://www.itksnap.org/pmwiki/pmwiki.php) is a free, open-source medical image viewer that properly displays NIfTI orientation information.
-RABIES uses ANTs/ITK tools under the hood.
-Incorrect image orientation is one of the most common causes of registration failures in RABIES.
-Since RABIES expects RAS orientation (Right–Anterior–Superior), you should always verify your anatomical scans in ITK-SNAP before running the pipeline.
-
-### How to Check Orientation in ITK-SNAP
-
-1. **Open your image in ITK-SNAP**
- - Go to **File → Open Main Image…**
- - Load your NIfTI anatomical scan.
-
-2. **Verify anatomical orientation**
- - ITK-SNAP shows three orthogonal views (Axial, Coronal, Sagittal).
- - Ensure anatomical structures appear where you expect them (e.g., nose = anterior, top of head = superior).
-
-3. **Compare your scan to a correctly oriented atlas/template**
- - Open your reference atlas (e.g., SIGMA, Fischer rat, etc.) in another ITK-SNAP window.
- - Verify that structures appear in similar positions and that the orientation labels match.
-
-4. **Check the orientation labels**
- - Inspect axes labels around each view (**R/L**, **A/P**, **S/I**).
- - Confirm they correspond to the real anatomical directions in your scan.
- - Move the cursor: the crosshair should move consistently across all views (e.g., dragging right corresponds to anatomical right).
-
-## See Also
-
-- For registration-specific troubleshooting, see [Registration Troubleshooting](nested_docs/registration_troubleshoot.md)
-- For QC-related guidance, see [Preprocessing QC](preproc_QC.md)
-- When reporting bugs, refer to the [issue template](https://github.com/CoBrALab/RABIES/blob/master/.github/ISSUE_TEMPLATE/standard-bug-report.md)
diff --git a/docs/tutorials/first_run.md b/docs/tutorials/first_run.md
new file mode 100644
index 00000000..a65da30e
--- /dev/null
+++ b/docs/tutorials/first_run.md
@@ -0,0 +1,275 @@
+# Your first RABIES run
+
+In this tutorial you will take two raw mouse fMRI scans and carry them all the
+way through RABIES: preprocessing, confound correction, and a whole-brain
+connectivity analysis. Along the way you will look at the quality control
+images RABIES produces, so that by the end you will have seen every part of the
+software in action.
+
+You do not need to understand every option you type. The point is to build a
+feel for the shape of a RABIES run. Everything you use here is explained
+elsewhere, and this page links to the relevant pages as it goes.
+
+## What you will end up with
+
+Three output folders that mirror the three stages of the software, and a
+connectivity matrix computed from the two scans:
+
+```text
+rabies_tutorial/
+├── bids_inputs/ the data you download in step 2
+├── preprocess_outputs/ step 3
+├── confound_correction_outputs/ step 5
+└── analysis_outputs/ step 6
+```
+
+```{admonition} How long this takes
+:class: important
+
+Steps 1 and 2 take a few minutes. Step 3 is real image processing on real
+brains, and is the long one — expect it to run for an hour or more, depending
+on how many cores your machine has. Steps 5 and 6 take a couple of minutes
+each. Start step 3 and come back to it.
+```
+
+## Step 1: Install the container
+
+RABIES has a lot of non-Python dependencies, so you will use the prebuilt
+container. Install [Apptainer](https://apptainer.org/docs/user/main/quick_start.html),
+then build the RABIES image:
+
+```sh
+apptainer build rabies.sif docker://ghcr.io/cobralab/rabies:latest
+```
+
+This downloads roughly a gigabyte and takes a few minutes. When it finishes you
+will have a single file, `rabies.sif`, which contains the entire software
+environment.
+
+Check that it runs:
+
+```sh
+apptainer run rabies.sif --help
+```
+
+You should see the RABIES usage message, listing the three processing stages:
+`preprocess`, `confound_correction` and `analysis`. That is the structure of
+the whole tutorial.
+
+```{tip}
+If you are on macOS or Windows, or Apptainer is not available to you, use
+Docker instead — see [How to install RABIES](../how_to/install.md). Every
+`apptainer run ... -B src:dst` below becomes `docker run ... -v src:dst`.
+```
+
+## Step 2: Get the example data
+
+Make a working directory and download the two-subject example dataset:
+
+```sh
+mkdir -p rabies_tutorial && cd rabies_tutorial
+curl -L -o test_dataset.zip https://zenodo.org/records/8349029/files/test_dataset.zip
+unzip test_dataset.zip -d bids_inputs
+```
+
+Look at what you got:
+
+```sh
+find bids_inputs -name '*.nii.gz'
+```
+
+Two subjects, each with one anatomical scan and one resting-state functional
+scan:
+
+```text
+bids_inputs/
+├── sub-PHG001/ses-3/
+│ ├── anat/sub-PHG001_ses-3_acq-RARE_T2w.nii.gz
+│ └── func/sub-PHG001_ses-3_task-rest_acq-EPI_run-1_bold.nii.gz
+└── sub-PHG002/ses-3/
+ ├── anat/sub-PHG002_ses-3_acq-RARE_T2w.nii.gz
+ └── func/sub-PHG002_ses-3_task-rest_acq-EPI_run-1_bold.nii.gz
+```
+
+Notice the file names. The `sub-`, `ses-`, `task-` and `T2w`/`bold` parts are
+not decoration — this is the [BIDS](https://bids.neuroimaging.io/) naming
+standard, and it is how RABIES finds the scans and pairs each functional image
+with the anatomical image from the same session. Your own data will need to
+look like this too. See [Input data requirements](../reference/bids_inputs.md).
+
+## Step 3: Preprocess
+
+Create the output folder, then run the preprocessing stage:
+
+```sh
+mkdir -p preprocess_outputs
+
+apptainer run \
+ -B $PWD/bids_inputs:/inputs:ro \
+ -B $PWD/preprocess_outputs:/outputs \
+ rabies.sif -p MultiProc \
+ preprocess /inputs /outputs \
+ --commonspace_reg masking=true,fast_commonspace=true
+```
+
+Three things are happening in that command:
+
+- `-B $PWD/bids_inputs:/inputs:ro` makes your input folder visible inside the
+ container under the name `/inputs`, read-only. The container cannot see any
+ path you do not bind, which is why the RABIES arguments say `/inputs` and
+ `/outputs` rather than the paths on your machine.
+- `-p MultiProc` runs the pipeline in parallel across the cores of your
+ machine. Leave it out and everything runs one step at a time.
+- `--commonspace_reg masking=true,fast_commonspace=true` registers each scan
+ straight to the reference atlas. RABIES would otherwise first build a
+ study-specific template out of your scans, which is the better choice for a
+ real study but is not worth it for two subjects.
+
+You did not specify an atlas. The container comes with the DSURQE mouse atlas
+already installed, and RABIES uses it by default — which is what makes this
+command so short.
+
+Let it run. You will see a stream of Nipype log lines as each node in the
+workflow completes.
+
+## Step 4: Look at the quality control report
+
+This is the step people skip, and it is the one that catches problems. Open the
+report folder:
+
+```sh
+ls preprocess_outputs/preprocess_QC_report/
+```
+
+Each subfolder holds PNG images for one registration step. Open
+`preprocess_QC_report/commonspace_reg_wf.Anat2Atlas/` first — this is where the
+alignment to the reference atlas landed, because you passed
+`fast_commonspace=true`:
+
+```{figure} ../pics/atlas_registration.png
+:alt: Overlap of the study template on the reference atlas
+
+The alignment of your data (top) with the reference atlas (bottom). The
+outlines should follow the same anatomy.
+```
+
+Then open `preprocess_QC_report/EPI2Anat/`, which shows each functional scan
+aligned onto its own anatomical scan:
+
+```{figure} ../pics/sub-MFC068_ses-1_task-rest_acq-EPI_run-1_bold_registration.png
+:alt: Overlap of a functional scan on its anatomical scan
+
+The functional image (top) matched to the anatomical image (bottom) from the
+same session. This registration is also what corrects susceptibility
+distortion.
+```
+
+In both figures the brain edges should line up. On this example dataset they
+will. When they do not on your own data, that is a registration failure, and
+[How to troubleshoot registration](../how_to/troubleshoot_registration.md)
+tells you which parameters to change.
+
+Every folder in the report is described in
+[Preprocessing QC outputs](../reference/qc_outputs.md).
+
+## Step 5: Correct confounds
+
+Preprocessed data is not yet ready to analyse: head motion and physiological
+noise produce correlations that look exactly like connectivity. The confound
+correction stage removes them.
+
+```sh
+mkdir -p confound_correction_outputs
+
+apptainer run \
+ -B $PWD/bids_inputs:/inputs:ro \
+ -B $PWD/preprocess_outputs:/outputs \
+ -B $PWD/confound_correction_outputs:/cc_outputs \
+ rabies.sif -p MultiProc \
+ confound_correction /outputs /cc_outputs \
+ --nuisance_regressors mot_6 WM_signal CSF_signal \
+ --smoothing_filter 0.3
+```
+
+Note that you bind `bids_inputs` again even though it is not in the RABIES
+arguments. Each stage reads the file paths recorded by the previous one, so
+every path used in step 3 has to stay reachable, at the same location, for the
+rest of the pipeline.
+
+The two options you passed:
+
+- `--nuisance_regressors mot_6 WM_signal CSF_signal` models the signal using
+ the six head motion parameters plus the mean white-matter and CSF signals,
+ and subtracts what it modelled.
+- `--smoothing_filter 0.3` applies 0.3 mm Gaussian spatial smoothing.
+
+That is a deliberately modest correction. Choosing a correction strategy for a
+real dataset is its own task, covered in
+[How to optimise your confound correction strategy](../how_to/optimise_confound_correction.md).
+
+The cleaned timeseries land in
+`confound_correction_outputs/confound_correction_datasink/cleaned_timeseries/`.
+
+## Step 6: Analyse
+
+Now compute a whole-brain connectivity matrix. RABIES will extract a timecourse
+from every region of the atlas parcellation and correlate every pair:
+
+```sh
+mkdir -p analysis_outputs
+
+apptainer run \
+ -B $PWD/bids_inputs:/inputs:ro \
+ -B $PWD/preprocess_outputs:/outputs \
+ -B $PWD/confound_correction_outputs:/cc_outputs \
+ -B $PWD/analysis_outputs:/analysis_outputs \
+ rabies.sif -p MultiProc \
+ analysis /cc_outputs /analysis_outputs \
+ --FC_matrix --ROI_type parcellated
+```
+
+Open the result:
+
+```sh
+ls analysis_outputs/commonspace_analysis_datasink/matrix_fig/
+```
+
+There is one PNG per scan, showing the correlation between every pair of atlas
+regions. The bright block structure along the diagonal is what functional
+organisation looks like in this representation: regions near each other, and
+regions belonging to the same network, fluctuate together.
+
+The same values are in `commonspace_analysis_datasink/matrix_data_file/` as a `.pkl` file
+holding a 2D NumPy array, with rows and columns ordered by atlas label number,
+ready to take into your own statistics.
+
+## What you have done
+
+You have run all three RABIES stages and produced a connectivity estimate from
+raw scans. Specifically, you:
+
+- built the container and confirmed it runs
+- preprocessed two subjects, registering them into a common atlas space
+- inspected the registration quality control images
+- removed motion and physiological confounds from the timeseries
+- computed a whole-brain connectivity matrix
+
+Run through it a second time on the same data. The commands will make more
+sense the second time, and the whole sequence will take you a few minutes of
+typing.
+
+## Where to go next
+
+For your own data, the decisions the tutorial made for you become yours to
+make:
+
+- Your data has to be in BIDS format — see
+ [Input data requirements](../reference/bids_inputs.md).
+- Your registrations will not always succeed on the first try — see
+ [How to troubleshoot registration](../how_to/troubleshoot_registration.md).
+- Confound correction should be tuned to your data, not copied from a tutorial
+ — see [How to optimise your confound correction strategy](../how_to/optimise_confound_correction.md)
+ and [How to assess data quality](../how_to/assess_data_quality.md).
+- To understand what the preprocessing actually did, read
+ [The preprocessing workflow](../explanation/preprocessing.md).
+```
diff --git a/docs/tutorials/index.md b/docs/tutorials/index.md
new file mode 100644
index 00000000..a1f9501f
--- /dev/null
+++ b/docs/tutorials/index.md
@@ -0,0 +1,23 @@
+# Tutorial
+
+A tutorial is a lesson. It takes you through a complete piece of work from
+beginning to end so that you learn what RABIES does by doing it, on data that
+is known to work. You are not expected to make any decisions along the way, and
+you do not need to understand every step as it happens.
+
+```{toctree}
+---
+maxdepth: 1
+---
+first_run
+```
+
+Once you have finished, the [how-to guides](../how_to/index.md) will help you
+apply RABIES to your own data.
+
+```{seealso}
+The CoBrALab also maintains a longer
+[hands-on workshop](https://github.com/CoBrALab/RABIES_tutorial), originally
+developed for the INCF Neuroinformatics Assembly 2023, and a
+[recorded software overview](https://www.youtube.com/watch?v=LZohKlUgycc&t=2766s&ab_channel=DouglasResearchCentre).
+```
From 409767f94e1f9a14c0099862de399cfed076c2d3 Mon Sep 17 00:00:00 2001
From: "Gabriel A. Devenyi"
Date: Mon, 3 Aug 2026 13:39:40 -0400
Subject: [PATCH 2/9] Expand the sidebar navigation fully
`collapse_navigation: False` already made Sphinx emit the complete toctree
into every page, but the RTD theme still hid most of it in CSS, so the nav
only opened along the branch you were currently on
(readthedocs/sphinx_rtd_theme#455).
Override the three theme rules that do the hiding, and drop the disclosure
arrows, which now have nothing to toggle.
This exposes a latent theme bug: nested entries are painted #404040, which
only works because the theme never shows them off the current branch. Once
every branch is open, off-branch entries sit on the dark sidebar and that
colour is illegible. Give them the same light-on-dark treatment as the
top-level entries, and put the dark text back on the current branch, where
the background really is light.
Verified in headless Chrome against computed styles: all 45 nav entries
visible, no collapsed lists, no visible arrows, and legible contrast in both
light and dark mode.
Co-Authored-By: Claude Opus 5 (1M context)
Claude-Session: https://claude.ai/code/session_01Kdq57U3c4xpcRTXWhtpWrt
---
docs/_static/custom.css | 64 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/docs/_static/custom.css b/docs/_static/custom.css
index ce308f54..8f40b2f7 100644
--- a/docs/_static/custom.css
+++ b/docs/_static/custom.css
@@ -1,3 +1,67 @@
+/* ---------------------------------------------------------------------------
+ Fully expanded sidebar navigation
+
+ `collapse_navigation: False` makes Sphinx emit the complete toctree into
+ every page, but the RTD theme still hides most of it in CSS, so the nav
+ only opens along the branch you are currently on. See
+ https://github.com/readthedocs/sphinx_rtd_theme/issues/455
+
+ Three theme rules do the hiding:
+ .wy-menu-vertical li ul { display: none }
+ .wy-menu-vertical .toctree-lN.current .toctree-lM>ul { display: none }
+ .wy-menu-vertical li.current ul { display: block }
+
+ The second is 4 classes deep, so !important is the honest way to beat it
+ without duplicating that whole selector chain.
+ --------------------------------------------------------------------------- */
+.wy-menu-vertical li ul {
+ display: block !important;
+}
+
+/* With nothing left to expand, the disclosure arrows are misleading: clicking
+ one would appear to do nothing. */
+.wy-menu-vertical li button.toctree-expand {
+ display: none !important;
+}
+
+/* The theme paints nested entries #404040 (near-black). That only works
+ because it shows them exclusively on the current branch, where the
+ background is light. Now that every branch is open, off-branch entries sit
+ on the dark sidebar and that colour is illegible — so give them the same
+ light-on-dark treatment the top-level entries get.
+
+ `.wy-menu-vertical li.current a` ties with this selector on specificity
+ (both 2 classes + 2 elements), and custom.css loads later, so this would
+ otherwise also repaint the current branch — where the background *is*
+ light. The rule below puts the dark text back there. */
+.wy-menu-vertical li.toctree-l2 a,
+.wy-menu-vertical li.toctree-l3 a,
+.wy-menu-vertical li.toctree-l4 a {
+ color: #d9d9d9;
+}
+
+.wy-menu-vertical li.current li.toctree-l2 a,
+.wy-menu-vertical li.current li.toctree-l3 a,
+.wy-menu-vertical li.current li.toctree-l4 a {
+ color: #404040;
+}
+
+/* Indent each level and taper the size, so the hierarchy still reads at a
+ glance without the disclosure arrows to mark it. */
+.wy-menu-vertical li.toctree-l2 a {
+ padding-left: 2.427em;
+}
+
+.wy-menu-vertical li.toctree-l3 a {
+ padding-left: 3.5em;
+ font-size: 0.85em;
+}
+
+.wy-menu-vertical li.toctree-l4 a {
+ padding-left: 4.5em;
+ font-size: 0.8em;
+}
+
/* The RTD theme caps content width at 800px, which is cramped for the
parcellation tables, --help output and the wider figures. */
.wy-nav-content {
From 7c64c17c14bde13ba0667be091e1993aacaf1be0 Mon Sep 17 00:00:00 2001
From: "Gabriel A. Devenyi"
Date: Mon, 3 Aug 2026 13:48:16 -0400
Subject: [PATCH 3/9] Upgrade the docs toolchain to the latest compatible
versions
Move the whole docs stack forward and drop the pins that were only holding it
back:
sphinx 5.0 -> 9.1.0
myst-parser 1.0.0 -> 5.1.0
sphinx-rtd-theme 2.0.0 -> 3.1.0
sphinxcontrib-bibtex 2.6.5 -> 2.7.0
sphinx-design 0.5.0 -> 0.7.0
docutils 0.17.1 -> 0.22.4
The docutils==0.17.1 and sphinx-design<0.6 pins existed only to satisfy
sphinx==5.0, so both are gone. Upper bounds are now specified only where a
real incompatibility exists, so routine upgrades no longer need a change here.
Bump Read the Docs to ubuntu-24.04 and Python 3.12. 3.12 is the ceiling, not
a preference: docs/requirements.txt installs rabies so that
sphinxcontrib-programoutput can run `rabies --help` at build time, and rabies
declares python_requires <3.13.
The upgrade surfaced a latent cross-reference bug. Seven page anchors sat
immediately after their H1, so they targeted the following paragraph or
figure rather than the section, and had no title for `:ref:` to use as link
text. Sphinx 5 rendered that silently; newer myst-parser reports it. Moving
each anchor above its heading makes it a section target, which is what every
incoming link already meant.
Verified with the upgraded stack: HTML and LaTeX both build clean under -n,
zero broken links or unresolved cross-references, sphinx-design cards, tabs
and dropdowns all render, and the expanded-sidebar CSS still applies
correctly under RTD theme 3.1 (45 entries, none collapsed, contrast intact).
Co-Authored-By: Claude Opus 5 (1M context)
Claude-Session: https://claude.ai/code/session_01Kdq57U3c4xpcRTXWhtpWrt
---
.readthedocs.yml | 14 ++++++--------
docs/explanation/confound_correction.md | 4 ++--
docs/explanation/data_quality.md | 4 ++--
docs/explanation/distribution_plot.md | 4 ++--
docs/explanation/group_statistics.md | 4 ++--
docs/explanation/scan_diagnosis.md | 4 ++--
docs/how_to/optimise_confound_correction.md | 4 ++--
docs/reference/metrics.md | 4 ++--
docs/requirements.txt | 21 +++++++++++----------
9 files changed, 31 insertions(+), 32 deletions(-)
diff --git a/.readthedocs.yml b/.readthedocs.yml
index 619212a4..c2138b49 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -5,15 +5,13 @@
# Required
version: 2
-# Set the version of Python and other tools you might need
build:
- os: ubuntu-22.04
+ os: ubuntu-24.04
tools:
- python: "3.10"
- # You can also specify other tool versions:
- # nodejs: "16"
- # rust: "1.55"
- # golang: "1.17"
+ # Capped at 3.12: docs/requirements.txt installs rabies so that
+ # sphinxcontrib-programoutput can run `rabies --help` at build time, and
+ # rabies requires Python <3.13.
+ python: "3.12"
# Build documentation in the docs/ directory with Sphinx
sphinx:
@@ -26,4 +24,4 @@ formats:
# Optionally declare the Python requirements required to build your docs
python:
install:
- - requirements: docs/requirements.txt
\ No newline at end of file
+ - requirements: docs/requirements.txt
diff --git a/docs/explanation/confound_correction.md b/docs/explanation/confound_correction.md
index 6dd7a2f3..42f4d490 100644
--- a/docs/explanation/confound_correction.md
+++ b/docs/explanation/confound_correction.md
@@ -1,7 +1,7 @@
-# The confound correction workflow
-
(confound_pipeline_target)=
+# The confound correction workflow
+
```{figure} ../pics/confound_correction.png
:alt: Diagram of the RABIES confound correction workflow
diff --git a/docs/explanation/data_quality.md b/docs/explanation/data_quality.md
index 0ed17e9a..9f006d4f 100644
--- a/docs/explanation/data_quality.md
+++ b/docs/explanation/data_quality.md
@@ -1,7 +1,7 @@
-# Data quality assessment
-
(analysis_QC_target)=
+# Data quality assessment
+
Data quality can have serious impacts on analysis outcomes, leading to false
findings. Rodent imaging can suffer from spurious effects on connectivity
measures if potential confounds are not well accounted for, and acquisition
diff --git a/docs/explanation/distribution_plot.md b/docs/explanation/distribution_plot.md
index 27ef18cf..0d149a13 100644
--- a/docs/explanation/distribution_plot.md
+++ b/docs/explanation/distribution_plot.md
@@ -1,7 +1,7 @@
-# The distribution plot
-
(dist_plot_target)=
+# The distribution plot
+
```{figure} ../pics/distribution_plot.png
:alt: Scatter plots of network connectivity measures against confound measures across scans
diff --git a/docs/explanation/group_statistics.md b/docs/explanation/group_statistics.md
index 24e68dd8..269e3bfa 100644
--- a/docs/explanation/group_statistics.md
+++ b/docs/explanation/group_statistics.md
@@ -1,7 +1,7 @@
-# The group statistical report
-
(group_stats_target)=
+# The group statistical report
+
```{figure} ../pics/group_stats_QC.svg
:alt: Group-level maps of connectivity variability and its correlation with confound measures
:width: 100%
diff --git a/docs/explanation/scan_diagnosis.md b/docs/explanation/scan_diagnosis.md
index a3ae2223..a346d1cc 100644
--- a/docs/explanation/scan_diagnosis.md
+++ b/docs/explanation/scan_diagnosis.md
@@ -1,7 +1,7 @@
-# The spatiotemporal diagnosis
-
(diagnosis_target)=
+# The spatiotemporal diagnosis
+
The spatiotemporal diagnosis is a visual report generated for each scan
independently, after dual regression or seed-based connectivity analysis. It
displays a large set of temporal and spatial features for that scan, supporting
diff --git a/docs/how_to/optimise_confound_correction.md b/docs/how_to/optimise_confound_correction.md
index 0be1a9c0..5547bddb 100644
--- a/docs/how_to/optimise_confound_correction.md
+++ b/docs/how_to/optimise_confound_correction.md
@@ -1,7 +1,7 @@
-# How to optimise your confound correction strategy
-
(optim_CR)=
+# How to optimise your confound correction strategy
+
There is no single correct confound correction strategy. The right one is
dataset-specific, and the way to find it is to start minimal and add one
correction at a time, checking after each addition whether the data quality
diff --git a/docs/reference/metrics.md b/docs/reference/metrics.md
index 48ffae7e..356fd2db 100644
--- a/docs/reference/metrics.md
+++ b/docs/reference/metrics.md
@@ -1,7 +1,7 @@
-# Metric definitions
-
(metrics_target)=
+# Metric definitions
+
Precise definitions of every quantity RABIES computes and reports. Throughout
this page, the root-mean square (RMS) is
$||x||_2 = \sqrt{\frac{1}{n}\sum_{i=1}^{n}x_i^2}$.
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 15847770..4d546ec2 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,16 +1,17 @@
-sphinx==5.0
-# sphinx 5.0 needs docutils<0.19 and myst-parser needs <0.20, while
-# sphinxcontrib-bibtex rejects 0.18.* and 0.19.* — 0.17.1 is the only version
-# satisfying all three. Pinned so the resolver cannot pick a broken combination.
-docutils==0.17.1
+# Docs toolchain. Upper bounds only where a real incompatibility exists, so
+# routine upgrades do not need a change here.
+#
+# The Python version is capped at 3.12 in .readthedocs.yml because this file
+# installs rabies (for sphinxcontrib-programoutput, which runs `rabies --help`
+# at build time) and rabies requires Python <3.13.
+sphinx
myst-parser
-sphinx-rtd-dark-mode
sphinx-rtd-theme
-sphinx-design<0.6 # 0.6+ requires sphinx>=6
+sphinx-rtd-dark-mode
+sphinx-design
sphinx-copybutton
sphinxcontrib-bibtex
sphinxcontrib-programoutput
-jinja2==3.1.6
-pillow==12.3.0
+jinja2
+pillow
rabies==0.6.1
-traits<7.0
From 2d54be1cbe8016ea6f4c728f4a0c4aaf3b173202 Mon Sep 17 00:00:00 2001
From: Gab-D-G
Date: Wed, 2 Sep 2026 16:00:50 +0200
Subject: [PATCH 4/9] Complete proof-reading of AI revisions on new
documentation layout. Several outdated aspects of the documentation were also
corrected. The tutorial section still need revising.
---
README.md | 17 +---
docs/explanation/analysis.md | 13 +--
docs/explanation/confound_correction.md | 56 ++++++-----
docs/explanation/data_quality.md | 41 +++-----
docs/explanation/distribution_plot.md | 32 +++---
docs/explanation/group_statistics.md | 24 ++---
docs/explanation/index.md | 2 +-
docs/explanation/preprocessing.md | 103 +++-----------------
docs/explanation/scan_diagnosis.md | 26 ++---
docs/how_to/assess_data_quality.md | 33 ++++---
docs/how_to/contribute.md | 6 --
docs/how_to/install.md | 20 ----
docs/how_to/minimal_preprocessing.md | 18 +---
docs/how_to/optimise_confound_correction.md | 28 +++---
docs/how_to/run_with_containers.md | 2 +-
docs/how_to/select_scans.md | 15 ---
docs/how_to/troubleshoot_registration.md | 4 +-
docs/reference/cli.md | 62 +-----------
docs/reference/metrics.md | 101 +++++++++----------
docs/reference/qc_outputs.md | 14 ++-
20 files changed, 207 insertions(+), 410 deletions(-)
diff --git a/README.md b/README.md
index 504f11a3..efcbce48 100644
--- a/README.md
+++ b/README.md
@@ -13,28 +13,25 @@ The preprocessing workflow regroups essential fMRI preprocessing steps prior to
- head motion correction
- susceptibility distortion correction
- resampling to native or common space
-- brain parcellation
- slice timing correction (optional)
- despiking (optional)
- visual assessment of registration for quality control
### Confound correction
-Following preprocessing, a range of strategies to correct fMRI confounds (e.g. motion) can then be conducted within RABIES:
-- linear detrending
+Following preprocessing, RABIES provides a highly-customizable confound correction pipeline regrouping several common strategies:
+- frame censoring (or scrubbing)
- confound regression (with several options for nuisance regressors)
- frequency filtering (highpass, lowpass, bandpass)
-- frame censoring (or scrubbing)
- ICA-AROMA
- spatial smoothing
### Analysis
-Simple resting-state connectivity analyses are made available after preprocessing and confound correction. RABIES also provides a 'data diagnosis' workflow, which generates several indices of data quality and potential confounds, and conversaly, aims to improve the correction of confounds and transparency with regards to data quality:
+Simple resting-state connectivity analyses are made available after preprocessing and confound correction:
- seed-based functional connectivity
- whole-brain connectivity matrix
- group-ICA
- dual regression
-- data diagnosis
-
+Importantly, the analysis stage is also complemented by a data quality assessment report (executed with `--data_diagnosis`), which generates several indices of data quality and potential confounds, with the aim of improving preprocessing stategies, data interpretation and scientific transparency.
## Notes on software design
@@ -44,7 +41,7 @@ Simple resting-state connectivity analyses are made available after preprocessin
- open source code
- standardized input data format with [BIDS](https://bids.neuroimaging.io/)
- easily shared, automatically-generated visual outputs for quality control
-- containerized distribution of the software hosted on [Docker Hub](https://hub.docker.com/r/gabdesgreg/rabies) which can be downloaded via Docker and Apptainer platforms
+- containerized distribution of the software through Docker/Apptainer, and conveniently installed from our [Github](https://github.com/CoBrALab/RABIES/pkgs/container/rabies) or [Docker Hub](https://hub.docker.com/r/gabdesgreg/rabies) servers.
## Citation
@@ -61,7 +58,3 @@ This software was developped by the [CoBrALab](https://cobralab.ca/), located at
## Ask for help
If you need support in using the software or experience issues that are not documented, we'll provide support on the [Github discussion](https://github.com/CoBrALab/RABIES/discussions).
-
-## Contributing to RABIES
-
-**Read our dedicated [documentation](https://rabies.readthedocs.io/en/latest/contributing.html)**
diff --git a/docs/explanation/analysis.md b/docs/explanation/analysis.md
index ed141e4c..590eaa02 100644
--- a/docs/explanation/analysis.md
+++ b/docs/explanation/analysis.md
@@ -9,15 +9,6 @@ For every analysis except group ICA, RABIES computes individualised
connectivity maps for each scan separately. These can be exported for
statistical analysis — group comparison and so on — conducted outside RABIES.
-```{important}
-Every analysis on this page assumes confounds have already been dealt with.
-Various fMRI confounds introduce spurious correlations that are
-indistinguishable from neural activity in the result, so the quality of a
-connectivity estimate is bounded by the quality of the
-[confound correction](confound_correction.md) that preceded it. See
-[Data quality assessment](data_quality.md).
-```
-
## Correlation-based connectivity
Correlation-based analyses compute a temporal correlation between different
@@ -38,10 +29,10 @@ seed and every other brain region.
### Whole-brain connectivity
-`--FC_matrix` / `--ROI_type`
+`--FC_matrix` / `--ROI_type` / `--ROI_labels_file`
An extension of seed-based connectivity to every brain region. Using the
-anatomical parcellation provided with the atlas during preprocessing, the seed
+anatomical parcellation provided with `--ROI_labels_file`, the seed
timecourse for every parcel is extracted, then the cross-correlation (Pearson's
r) is measured between every region pair. The correlation values are
reorganised into a whole-brain matrix representing the connectivity between
diff --git a/docs/explanation/confound_correction.md b/docs/explanation/confound_correction.md
index 42f4d490..ba617e6d 100644
--- a/docs/explanation/confound_correction.md
+++ b/docs/explanation/confound_correction.md
@@ -5,7 +5,7 @@
```{figure} ../pics/confound_correction.png
:alt: Diagram of the RABIES confound correction workflow
-The confound correction workflow. Steps are applied in the order shown.
+The confound correction workflow.
```
The confound correction workflow brings together a broad set of standard tools
@@ -13,12 +13,12 @@ from the human literature. Each step's implementation follows best practices
and is structured to prevent the re-introduction of confounds, as recommended
in {cite}`Power2014-yf` and {cite}`Lindquist2019-lq`.
-Every operation is optional except detrending, and a set of operations can be
+Every operation is optional (at minimum the temporal mean is removed), and a set of operations can be
selected to design a customised workflow.
```{important}
-There is no universally optimal correction strategy. The right one is
-dataset-specific and should be tuned to address quality issues you have
+There is no universally optimal correction strategy. We provide guidlines for
+tuning the pipeline to address quality issues you can
actually identified in your data — see
[Data quality assessment](data_quality.md) and
[How to optimise your confound correction strategy](../how_to/optimise_confound_correction.md).
@@ -54,9 +54,10 @@ Censoring with DVARS
## 2. Detrending
-`--detrending_order`
+`--detrending`
-Linear, or optionally quadratic, trends are removed from the timeseries.
+Detrending is applied at the inputted polynomial order (e.g. 0 only removes the intercept,
+1 for linear, 2 for quadratic, etc).
Detrended timeseries $\hat{Y}$ are obtained by ordinary least squares (OLS)
linear regression:
@@ -68,9 +69,8 @@ $$
\hat{Y} = Y - X\beta
$$
-where $Y$ is the timeseries and the predictors are
-$X = [intercept, time, time^2]$, with $time^2$ included only when removing
-quadratic trends.
+where $Y$ is the timeseries and the regressors are the polynomials expansions
+of the time axis, e.g. $X = [intercept, time, time^2]$ for `--detrending order=2`.
## 3. ICA-AROMA
@@ -90,11 +90,11 @@ that would otherwise produce ringing after filtering
`--TR` / `--highpass` / `--lowpass` / `--edge_cutoff`
-Simulating censored timepoints
+Spectral interpolation of censored timepoints
: Frequency filtering needs special handling after frame censoring, because
conventional filters cannot handle missing data. RABIES implements the method
- of {cite}`Power2014-yf`, which simulates data points while preserving the
- frequency composition of the data. It relies on an adaptation of the
+ of {cite}`Power2014-yf`, which interpolates the data while preserving its
+ frequency composition. It relies on an adaptation of the
Lomb-Scargle periodogram, which estimates the frequency composition of the
timeseries despite missing data points; from that estimate, missing
timepoints are simulated with the frequency profile preserved
@@ -105,24 +105,29 @@ Butterworth filter
a 3rd-order Butterworth filter
([`scipy.signal.butter`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.butter.html)).
After filtering, the temporal mask from censoring is re-applied to remove the
- simulated timepoints.
+ interpolated timepoints.
```{tip}
- When applying a highpass filter, remove 30 seconds at each end of the
- timeseries with `--edge_cutoff` to account for edge artefacts
- {cite}`Power2014-yf`.
+ Edge artefacts are introduced by standard frequency filters:
+ for a highpass at 0.01Hz, we recommend removing 30 seconds at each end of the
+ timeseries with `--edge_cutoff` {cite}`Power2014-yf`.
```
(CR_target)=
-## 5. Confound regression
+## 5. Nuisance regression
`--nuisance_regressors`
For each voxel timeseries, a selected set of
[nuisance regressors](regressor_target) is modelled using OLS linear regression
-and their modelled contribution to the signal is removed. Regressed timeseries
-$\hat{Y}$ are obtained with
+and their modelled contribution to the signal is removed.
+Prior to carrying the linear regression, a critical implementation strategy in
+RABIES is to apply the same censoring, detrending and frequency filtering carried
+in steps 1,2,4 onto the regressors themselves to mitigate the re-introduction
+of previously corrected confounds, as recommended in {cite}`Power2014-yf` and
+{cite}`Lindquist2019-lq`.
+After doing so, the regressed timeseries $\hat{Y}$ are obtained with
$$\beta = OLS(X,Y)$$
@@ -130,9 +135,9 @@ $$ Y_{CR} = X\beta $$
$$ \hat{Y} = Y - Y_{CR} $$
-where $Y$ is the timeseries, $X$ is the set of nuisance timecourses, and
-$Y_{CR}$ is the confound timeseries predicted from the model at each voxel — a
-time-by-voxel 2D matrix.
+where $Y$ is the timeseries, $X$ is the set of nuisance timecourses (censored, detrended
+and filtered), and $Y_{CR}$ is the confound timeseries predicted from the model at each
+voxel — a time-by-voxel 2D matrix.
## 6. Intensity scaling
@@ -142,20 +147,21 @@ Voxel intensity values should be scaled to improve comparability between scans
and datasets. The available options:
Grand mean
-: **Recommended.** Timeseries are divided by the mean intensity across the
+: **Default.** Timeseries are divided by the mean intensity across the
brain, then multiplied by 100 to obtain percent BOLD deviations from the
mean. The mean intensity of each voxel is derived from the $\beta$
coefficient of the intercept computed during **Detrending**.
Voxelwise mean
-: As grand mean, but each voxel is independently scaled by its own mean signal.
+: As grand mean, but each voxel is independently scaled by its own intercept from detrending.
Global standard deviation
: Timeseries are divided by the total standard deviation across all voxel
timeseries.
Voxelwise standardization
-: Each voxel is divided by its own standard deviation.
+: Each voxel is divided by its own standard deviation to derive z-scored timeseries
+(i.e. 0-mean and unit standard deviation).
Homogenize variance voxelwise
: With `--scale_variance_voxelwise`, and only if no voxelwise scaling was
diff --git a/docs/explanation/data_quality.md b/docs/explanation/data_quality.md
index 9f006d4f..3ff7e916 100644
--- a/docs/explanation/data_quality.md
+++ b/docs/explanation/data_quality.md
@@ -1,6 +1,6 @@
(analysis_QC_target)=
-# Data quality assessment
+# Overview of data quality assessment
Data quality can have serious impacts on analysis outcomes, leading to false
findings. Rodent imaging can suffer from spurious effects on connectivity
@@ -11,7 +11,7 @@ factors such as anaesthesia level can themselves influence network activity
To support interpretability, troubleshooting and reproducible research, RABIES
includes a set of reports for assessing data quality in individual scans and
for conducting quality control before network analysis at the group level. The
-reports are designed specifically to evaluate two things: whether canonical
+reports are designed to evaluate two main aspects: whether canonical
brain networks are detectable, and how far potential confounds — motion,
physiological instabilities, and others — have influenced the result.
@@ -27,8 +27,8 @@ control in a publication, see
## The three reports
The reports are generated by `--data_diagnosis` at the analysis stage, into
-[`data_diagnosis_datasink/`](diagnosis_datasink_target). Each addresses a
-different level of the problem.
+[`data_diagnosis_datasink/`](diagnosis_datasink_target). Each provide a
+complementary review of the data.
::::{grid} 1 1 3 3
:gutter: 2
@@ -71,19 +71,19 @@ The quality control framework. Each level conditions the validity of the next.
The three reports are not alternatives; they answer different questions, and
they depend on each other in one direction.
-The **spatiotemporal diagnosis** tells you what is wrong with an individual
+The **spatiotemporal diagnosis** can help you flag most specifically what is wrong with an individual
scan — whether the signal variability carries an anatomical confound signature,
whether the network is present at all, whether network and confound timecourses
-move together. It identifies the *type* of problem, which is what makes a
+move together. It identifies the *type* of problem, which can make a
targeted correction possible.
-The **distribution plots** turn those qualitative judgements into numbers you
-can threshold. Inspecting fifty scans by eye and deciding which are unusable is
-not reproducible; setting a Dice overlap and confound correlation threshold,
-and reporting them, is.
+The **QC-FC distribution plots** turn those qualitative judgements into numbers you
+can survey across the whole dataset. Doing so enable outlier detection, setting
+exclusion thresholds, and detecting subtle but systematic relationships between
+confounds and network measures across samples (i.e. QC-FC relationships).
-The **group statistical report** asks the question that actually matters for a
-group analysis: is the *variability* in connectivity across scans driven by
+The **group statistical report** asks the question that actually matters for
+common group statistical designs: is the *variability* in connectivity across scans driven by
network activity, or by confounds? Scan-level features being acceptable does
not by itself guarantee this.
@@ -94,23 +94,6 @@ of the network across scans — differences actually driven by data quality
divergences rather than by biology. This is why scan-level assumptions have to
be met before the group-level report means anything.
-## What the reports need
-
-The reports are built on a set of ICA components that must be classified into
-networks of interest and confound sources. Ideally the components are derived
-from the dataset being analysed, using [group ICA](ICA_target); a pre-computed
-set for mice is available by default.
-
-Connectivity can be evaluated for [dual regression](DR_target), for
-[seed-based connectivity](SBC_target), or for both. Dual regression is always
-run internally regardless, because several report features are derived from the
-confound components.
-
-```{seealso}
-For guidance on classifying ICA components in rodents, consult
-{cite}`Zerbi2015-nl` and {cite}`Desrosiers-Gregoire2024-ou`.
-```
-
## A note on judgement
These reports and the guidelines built around them aim to identify analysis
diff --git a/docs/explanation/distribution_plot.md b/docs/explanation/distribution_plot.md
index 0d149a13..4707c9f2 100644
--- a/docs/explanation/distribution_plot.md
+++ b/docs/explanation/distribution_plot.md
@@ -1,6 +1,6 @@
(dist_plot_target)=
-# The distribution plot
+# QC-FC distribution
```{figure} ../pics/distribution_plot.png
:alt: Scatter plots of network connectivity measures against confound measures across scans
@@ -9,10 +9,10 @@ Each point is a scan. Measures of network connectivity — specificity and
amplitude — are contrasted with measures of confounds across the sample.
```
-The distribution plot visualises the distribution of data quality measures
-across the dataset, turning the per-scan judgements from the
-[spatiotemporal diagnosis](diagnosis_target) into something you can threshold
-and report.
+The QC-FC distribution plot visualises the joint distributions of network and
+confound data quality measures across the dataset, expending the per-scan qualitative
+judgements from the [spatiotemporal diagnosis](diagnosis_target) into a quantitative
+comparison between subjects.
Reading the plot:
@@ -28,20 +28,24 @@ The derivation of each quality metric is described in the
## What the report is for
-The plot serves two distinct purposes.
+**Identify systematic QC-FC associations at the dataset-level.** Visualise the association
+between network (specificity and amplitude) and a set of scan-level summary confound measures (the columns
+in the plot). This complements the [group statistical report](group_stats_target) by
+indicating whether a group-wise correlation in the report is
+driven by a small number of outliers rather than by a dataset-wide effect.
**Setting scan inclusion criteria.** Inspect that network specificity is
sufficient and that the temporal correlation with confounds (DR confound corr.)
is minimal, then set thresholds for scan inclusion with `--scan_QC_thresholds`.
This is the top right subplot, discussed below.
-**Complementing the group statistical report.** Visualise the association
-between connectivity and the three confound measures included in the report —
-$CR_{SD}$, mean FD and tDOF. This lets you determine, for instance, whether a
-group-wise correlation in the [statistical report](group_stats_target) is
-driven by a small number of outliers rather than by a dataset-wide effect.
+```{seealso}
+[How to assess data quality](../how_to/assess_data_quality.md) gives the
+`--scan_QC_thresholds` syntax and the procedure for choosing values.
+```
-## Scan-level thresholds
+
+## Inclusion criteria examplified
```{figure} ../pics/scan_QC_thresholds.png
:alt: Scan quality categories separated along network specificity and confound correlation axes
@@ -62,7 +66,3 @@ detectability and spurious connectivity, and to applying inclusion thresholds
that select scans respecting the assumptions of network detectability and
minimal confound effects.
-```{seealso}
-[How to assess data quality](../how_to/assess_data_quality.md) gives the
-`--scan_QC_thresholds` syntax and the procedure for choosing values.
-```
diff --git a/docs/explanation/group_statistics.md b/docs/explanation/group_statistics.md
index 269e3bfa..1ec8852a 100644
--- a/docs/explanation/group_statistics.md
+++ b/docs/explanation/group_statistics.md
@@ -11,9 +11,13 @@ network.
```
Inspecting scan-level features is not sufficient to conclude that inter-scan
-*variability* in connectivity is itself unaffected — and that variability is
-what a group analysis is primarily interested in. This report examines
-connectivity variability at the group level, along two axes.
+*variability* in connectivity is itself unaffected — there can be subtle
+but systematic artefactual effects that impact that variability without
+being easily detected from the dataset average or individual maps.
+This variability is the primary driver of results in a conventional
+group statistical designs (e.g. comparing two different experimental groups),
+in which case it is important to also assess these additional aspects of
+data quality.
## Specificity of network variability
@@ -35,14 +39,8 @@ improve the contrast.
## Correlation with confounds
-Connectivity is correlated across subjects, at each voxel, with each of three
-confound measures:
-
-- the variance explained by confound correction at that voxel ($CR_{SD}$, from
- the [predicted confound timeseries $Y_{CR}$](CR_target))
-- mean framewise displacement (FD)
-- temporal degrees of freedom (tDOF)
-
+Connectivity is correlated across subjects, at each voxel, with each of
+confound measure listed in the [metric definitions](group_QC_metrics).
This establishes how strongly connectivity is associated with potential
confounds. What constitutes a *concerning* correlation depends on the study and
on the effect size of interest: the question to ask is whether the effect size
@@ -57,10 +55,6 @@ the reference network map is measured using Dice overlap; for the confound
measures, the mean correlation is measured within the area of the network. See
the [group QC metric definitions](group_QC_metrics).
-These measures can be consulted for a quantitative summary, though visualisation
-is preferred — the Dice overlap for network variability may not perfectly
-distinguish network features from spurious ones.
-
```{important}
The validity of this report depends on whether the
[scan-level assumptions](dist_plot_target) of network detectability and
diff --git a/docs/explanation/index.md b/docs/explanation/index.md
index fd62833b..8121345d 100644
--- a/docs/explanation/index.md
+++ b/docs/explanation/index.md
@@ -20,7 +20,7 @@ analysis
## Assessing data quality
-Confound correction cannot be designed blind. RABIES generates a set of reports
+RABIES generates a set of reports
for characterising data quality and its impact on connectivity estimates.
```{toctree}
diff --git a/docs/explanation/preprocessing.md b/docs/explanation/preprocessing.md
index b73ea612..39042a2b 100644
--- a/docs/explanation/preprocessing.md
+++ b/docs/explanation/preprocessing.md
@@ -3,8 +3,7 @@
```{figure} ../pics/preprocessing.png
:alt: Diagram of the RABIES preprocessing workflow
-The RABIES preprocessing workflow. Bold labels correspond to the module names
-used throughout this page.
+The RABIES preprocessing workflow.
```
Preprocessing fMRI scans prior to analysis requires, at minimum, anatomical
@@ -14,7 +13,7 @@ imaging (EPI) acquisition of functional scans. The core preprocessing pipeline
in RABIES carries out each of these with state-of-the-art processing tools and
techniques.
-## Getting the scans into a common space
+## Alignment to the common space
Structural images, acquired alongside the EPI scans, are initially corrected
for inhomogeneities (**Structural inhomogeneity correction**) and then
@@ -43,7 +42,7 @@ fail. The cost is computation time, which is why `fast_commonspace=true`
exists to skip it.
```
-## Getting the EPI corrected
+## EPI motion and distortion corrections
A volumetric EPI image is first derived using a trimmed mean across the EPI
frames, after an initial motion realignment step (**3D EPI generation**). Using
@@ -58,12 +57,14 @@ anatomical scan from the same MRI session, which yields the geometrical
transforms required to recover brain anatomy {cite}`Wang2017-ci`
(**Susceptibility distortion estimation**).
-Finally, the transforms correcting head motion and susceptibility distortions
-are concatenated into a single resampling operation — avoiding multiple
-resampling — applied at each EPI frame, generating the preprocessed EPI
-timeseries in native space {cite}`Esteban2019-rs` (**Frame-wise resampling**).
-Preprocessed timeseries in common space are generated by further concatenating
-the transforms that resample to the reference atlas.
+## Derivation of preprocessed EPI timeseries
+
+The transforms providing head motion correction, susceptibility distortions
+and alignment to the common space are concatenated into a single resampling operation
+— avoiding multiple resampling — applied at each EPI frame {cite}`Esteban2019-rs` (**Frame-wise resampling**).
+This generates the preprocessed EPI timeseries in common space, while alternatively
+the transforms to common space can be dropped to generate instead native space timeseries
+using the `--resampling_space` parameter.
```{important}
Concatenating the transforms matters. Resampling an image is lossy, so
@@ -72,88 +73,6 @@ resampling steps blurs the data twice. RABIES composes the transforms first
and resamples once.
```
-## Each module in turn
-
-### Structural inhomogeneity correction
-
-```{figure} ../pics/sub-MFC067_ses-1_acq-FLASH_T1w_inho_cor.png
-:alt: Four-column figure showing the stages of structural inhomogeneity correction
-
-The steps of inhomogeneity correction for the structural image.
-```
-
-Implemented by
-[`init_inho_correction_wf`](wf_inho_correction).
-
-### Common space alignment
-
-Unbiased template generation followed by atlas registration.
-
-```{figure} ../pics/sub-MFC067_ses-1_acq-FLASH_T1w_inho_cor_registration.png
-:alt: Overlap between a structural scan and the dataset-generated unbiased template
-
-Overlap between a structural scan (top) and the dataset-generated unbiased
-template (bottom).
-```
-
-```{figure} ../pics/atlas_registration.png
-:alt: Overlap between the unbiased template and the reference atlas template
-
-Overlap between the unbiased template (top) and the reference atlas template
-(bottom).
-```
-
-Implemented by
-[`init_commonspace_reg_wf`](wf_commonspace_reg).
-
-(3D_EPI_target)=
-
-### 3D EPI generation
-
-Implemented by
-[`init_bold_reference_wf`](wf_bold_ref).
-
-### Head motion estimation
-
-```{figure} ../pics/example_motion_parameters.png
-:alt: Timecourses of the six rigid-body head motion parameters
-
-Example of the 6 motion parameters.
-```
-
-Implemented by
-[`init_bold_hmc_wf`](wf_hmc)
-and
-[`EstimateMotionParams`](wf_motion_params).
-
-### Functional inhomogeneity correction
-
-```{figure} ../pics/sub-MFC068_ses-1_task-rest_acq-EPI_run-1_bold_inho_cor.png
-:alt: Four-column figure showing the stages of EPI inhomogeneity correction
-
-The steps of inhomogeneity correction for the volumetric EPI.
-```
-
-The workflow is the same as for **structural inhomogeneity correction**.
-
-### Susceptibility distortion estimation
-
-```{figure} ../pics/sub-MFC068_ses-1_task-rest_acq-EPI_run-1_bold_registration.png
-:alt: Overlap between the volumetric EPI and the structural image
-
-Overlap between the volumetric EPI (top) and the structural image (bottom).
-```
-
-Implemented by
-[`init_cross_modal_reg_wf`](wf_cross_modal_reg).
-
-### Frame-wise resampling
-
-Implemented by
-[`init_bold_preproc_trans_wf`](wf_bold_resampling),
-with masks and labels handled by
-[`init_mask_preproc_trans_wf`](wf_mask_resampling).
-
## Working without structural scans
Structural scans are recommended but not required. An alternative workflow,
diff --git a/docs/explanation/scan_diagnosis.md b/docs/explanation/scan_diagnosis.md
index a346d1cc..da226c4c 100644
--- a/docs/explanation/scan_diagnosis.md
+++ b/docs/explanation/scan_diagnosis.md
@@ -136,22 +136,22 @@ timeseries.
(quality_marker_target)=
-## The four key quality markers
+## Four categories of quality outcome
```{figure} ../pics/diagnosis_key_markers.png
-:alt: Four key diagnostic features shown across four categories of scan quality
+:alt: Five key diagnostic features enable identifying four categories of scan quality
-Four features across four categories of scan quality.
+Five key diagnostic features enable identifying four categories of scan quality.
```
A subset of the features above are the most decisive in determining scan
-quality in relation to connectivity analysis. They are shown here across the 4
-main categories of scan quality.
+quality in relation to connectivity analysis. We examplify here how these
+can distinguish between 4 main categories of scan quality.
**BOLD variability**
: Presents a homogeneous contrast in uncorrupted scans, and otherwise reveals
- the anatomical signature of a confound — which is what allows the type of
- confound to be identified.
+ the anatomical signature of a confound — this can allow recognizing the type of
+ confound present.
**Global signal covariance**
: Sensitive to both non-neural confounds (the *spurious* category) and network
@@ -160,16 +160,18 @@ main categories of scan quality.
most likely contributors to downstream connectivity measures.
**Network map**
-: Shows whether the expected anatomical features of the network are effectively
- captured, i.e. network specificity. This is what establishes that the network
+: By visualizing the network maps, we can directly intuit whether they
+ reproduce expected anatomical features of the network of interest.
+ This is what establishes that the network
is not absent (the *absent* category), and that its shape is not distorted by
spurious features (the *spurious* category).
**Network and confound timecourses**
-: The respective timecourses reveal direct relationships between network
+: The respective timecourses reveal relationships between network
amplitude and confounds in the temporal domain. This does not describe the
- *type* of confound, but it is the most direct indicator of spurious
- connectivity, and an important complement to inspecting network shape —
+ *type* of confound, but a strong correlation in the temporal domain
+ is the most conclusive indicator of spurious connectivity,
+ and an important complement to inspecting network shape —
spurious effects can affect amplitude while leaving shape largely intact.
These 4 features are sufficient to capture the essential characteristics of
diff --git a/docs/how_to/assess_data_quality.md b/docs/how_to/assess_data_quality.md
index 4c983af3..649f659e 100644
--- a/docs/how_to/assess_data_quality.md
+++ b/docs/how_to/assess_data_quality.md
@@ -113,26 +113,31 @@ analysis (`DR`, `SBC` or `NPR`) you can set:
: `true` to automatically remove scans with outlier network amplitude, which
can indicate spurious connectivity {cite}`Nickerson2017-gq`.
-To pick sensible threshold values, consult the
-[distribution plots](dist_plot_target) and the accompanying CSV file, which
-gives the measures per scan ID.
+**Sensible thresholds values** should be selected by relating scans flagged in
+step 1. (i.e. that present spurious/absent features in the [spatiotemporal diagnosis](diagnosis_target))
+to their associated `Dice`/`Conf` values listed in the [distribution plots](dist_plot_target)
+and the accompanying CSV file, which gives the measures per scan ID.
+We do not recommend blindly applying a threshold value listed in a previous
+publication, as legitimate `Dice`/`Conf` values will differ depending
+on the image signal-to-noise ratio and/or preprocessing decision
+(e.g. applying a lowpass filter will systematically increase `conf` values).
```{important}
Scans excluded by `--scan_QC_thresholds` are excluded from the group
-statistical report, so the reports must be regenerated after you set the
-thresholds.
+statistical report, so it is best to regenerate these reports after
+you set the thresholds.
```
### 3. Check the group level
Consult the [group statistical report](group_stats_target) to identify the main
-driver of connectivity variability across scans, and whether it relates
-primarily to network activity or to confounds.
+driver of connectivity variability across scans, and whether it relates there
+are systematic group-level associations with confound metrics.
### 4. Revisit confound correction if needed
-If significant issues remain, redesign the confound correction stage —
-see [How to optimise your confound correction strategy](optimise_confound_correction.md).
+If significant issues remain, consider redesigning the confound correction
+stage — see [How to optimise your confound correction strategy](optimise_confound_correction.md).
```{admonition} These guidelines are not prescriptive
:class: caution
@@ -147,12 +152,14 @@ evolving.
## Report your quality control in a publication
-Every figure in the report is generated as PNG or SVG and can be shared
-alongside a publication.
+A central motivation for implementing these automatically-generated
+quality reports is to encourage and improve scientific transparency and
+study comparison. Every figure in the report is generated as PNG or SVG
+and can be shared alongside a publication.
-Share, at minimum:
+We specifically recommend sharing:
-- A spatiotemporal diagnosis for each scan used to derive connectivity results.
+- The spatiotemporal diagnosis report from each scan used to derive connectivity results.
- A group statistical report and its affiliated distribution plot, for each
group or dataset, if the analysis compares connectivity across subjects
and/or groups.
diff --git a/docs/how_to/contribute.md b/docs/how_to/contribute.md
index 47290f12..d746442d 100644
--- a/docs/how_to/contribute.md
+++ b/docs/how_to/contribute.md
@@ -13,12 +13,6 @@ Suggestions for improvements can be shared through the GitHub
[issues system](https://github.com/CoBrALab/RABIES/issues) and
[discussion board](https://github.com/CoBrALab/RABIES/discussions).
-```{tip}
-Discuss your proposed changes on the discussion board or in an issue before you
-open a pull request. It is much cheaper to redirect an approach before the code
-is written.
-```
-
## Set up a development environment
Install RABIES locally rather than working through a container — testing and
diff --git a/docs/how_to/install.md b/docs/how_to/install.md
index 3961acba..9e160bd3 100644
--- a/docs/how_to/install.md
+++ b/docs/how_to/install.md
@@ -88,23 +88,3 @@ on the [Neurodesk platform](https://neurodesk.github.io/), a browser-based
neuroimaging computing environment with community-maintained prebuilt tools.
Nothing is installed on your own machine. See the
[Neurodesk documentation](https://neurodesk.github.io/docs/) to get started.
-
-## The default atlas
-
-RABIES uses the DSURQE mouse atlas and a matching set of masks, labels, ICA
-priors and seeds by default. The container images have these preinstalled. A
-PyPI or development install downloads them into `$XDG_DATA_HOME/rabies`, or
-`~/.local/share/rabies` if `XDG_DATA_HOME` is unset, the first time you run a
-command that needs them.
-
-```{note}
-The first run after a fresh non-container install will therefore pause to
-download several hundred megabytes before any processing starts. This is
-expected, and happens once.
-```
-
-## Install for development
-
-If you intend to modify RABIES rather than just run it, see
-[How to contribute to RABIES](contribute.md), which covers setting up a
-development environment.
diff --git a/docs/how_to/minimal_preprocessing.md b/docs/how_to/minimal_preprocessing.md
index 583f30ba..832286ea 100644
--- a/docs/how_to/minimal_preprocessing.md
+++ b/docs/how_to/minimal_preprocessing.md
@@ -4,15 +4,10 @@ If your functional data was preprocessed with your own pipeline and you only
want RABIES for confound correction and analysis, you cannot skip the
preprocessing stage — but you can run it with almost everything turned off.
-Running `rabies confound_correction` directly on external data fails with
-missing `.pkl` file errors. Those `.pkl` files are serialised states of the
-internal preprocessing workflow and cannot be written by hand. Even with the
-`.pkl` in place, the confound correction stage expects the full range of files
-produced by preprocessing, so missing file errors would follow.
-
-The practical solution is a *SHAM* preprocessing run, with the correction and
-registration steps disabled. RABIES still computes the intermediary outputs that
-the later stages require, while leaving the image data largely unchanged.
+Because running `rabies confound_correction --read_datasinks` expects the full range of files
+produced by the `preprocess` stage, it is most convenient to produce the required
+intermediary outputs by running a *SHAM* preprocessing run, that minimally modifies
+the input data.
## Run a SHAM preprocessing
@@ -46,8 +41,6 @@ rabies preprocess bids_inputs/ preprocess_outputs/ \
If your dataset has no structural scans, add `--bold_only`, in which case
`--anat_inho_cor` and `--bold2anat_coreg` no longer apply.
-## Your data must already be in commonspace
-
```{warning}
`template_registration=no_reg` does not skip the resampling to commonspace — it
replaces the estimated transform with an identity transform. The commonspace
@@ -60,9 +53,6 @@ If they do not overlap, the commonspace timeseries and the atlas masks
downstream will not correspond to your data.
```
-Confirm your image orientation before you start — see
-[How to check image orientation](check_orientation.md).
-
## What still happens
A SHAM preprocessing is a minimal pass, not a strictly non-modifying one.
diff --git a/docs/how_to/optimise_confound_correction.md b/docs/how_to/optimise_confound_correction.md
index 5547bddb..7df4fbea 100644
--- a/docs/how_to/optimise_confound_correction.md
+++ b/docs/how_to/optimise_confound_correction.md
@@ -2,25 +2,23 @@
# How to optimise your confound correction strategy
-There is no single correct confound correction strategy. The right one is
-dataset-specific, and the way to find it is to start minimal and add one
-correction at a time, checking after each addition whether the data quality
-reports improved.
+There is no agreed-upon single confound correction strategy for fMRI
+functional connectivity analysis. Designing a confound correction
+pipeline is navigating a central trade-off: too little signal removal
+risks leaving uncorrected artefacts that corrupt downstream analyses,
+excessive signal removal risks removing signal of interest relating to
+network activity. The ideal strategy will depend on the extent and
+nature of artefacts present in a given dataset.
-This protocol comes from {cite}`Desrosiers-Gregoire2024-ou`. It assumes you can
+Here is described a protocol introduced by {cite}`Desrosiers-Gregoire2024-ou`
+to navigate these decisions on a per-dataset basis. It assumes you can
already generate and read the data quality reports — if not, start with
[How to assess data quality](assess_data_quality.md).
-```{important}
-Start minimal and stay minimal for as long as the reports allow. Excessive
-correction removes network activity along with the confounds, and
-over-correction is harder to detect after the fact than under-correction.
-```
-
## The protocol
1. **Start with a minimal correction** and generate the data quality reports at
- the analysis stage. A reasonable minimum is frame censoring on framewise
+ the analysis stage. A reasonable minimum can be frame censoring on framewise
displacement, regression of the 6 motion parameters, and spatial smoothing:
```sh
@@ -30,6 +28,12 @@ over-correction is harder to detect after the fact than under-correction.
--smoothing_filter 0.3
```
+```{Advice}
+Starting minimal is ideal, as excessive
+correction removes network activity along with the confounds, and
+over-correction is harder to detect after the fact than under-correction.
+```
+
2. **Evaluate the reports**, following
[How to assess data quality](assess_data_quality.md).
diff --git a/docs/how_to/run_with_containers.md b/docs/how_to/run_with_containers.md
index dede97fa..32463a0f 100644
--- a/docs/how_to/run_with_containers.md
+++ b/docs/how_to/run_with_containers.md
@@ -1,4 +1,4 @@
-# How to run RABIES in a container
+# How to handle container syntax
A container has its own filesystem and cannot see your data unless you say so.
Running RABIES in a container is therefore the same as running it natively,
diff --git a/docs/how_to/select_scans.md b/docs/how_to/select_scans.md
index ba378445..97674448 100644
--- a/docs/how_to/select_scans.md
+++ b/docs/how_to/select_scans.md
@@ -93,18 +93,3 @@ between them — as in every example above.
`--inclusion_ids` and `--exclusion_ids` cannot be used together.
```
-
-## Drop scans after quality control
-
-The two options above are also how you act on a quality control decision. To
-carry out an analysis without scans you have judged unusable, re-run the
-confound correction and analysis stages with `--exclusion_ids` listing them.
-See [How to assess data quality](assess_data_quality.md) for how to arrive at
-that decision, and for `--scan_QC_thresholds`, which excludes scans by
-threshold rather than by name.
-
-```{seealso}
-[Input data requirements](../reference/bids_inputs.md) for how RABIES pairs
-functional scans with anatomical scans, and the
-[`preprocess` options](../reference/cli.md) for the full parameter list.
-```
diff --git a/docs/how_to/troubleshoot_registration.md b/docs/how_to/troubleshoot_registration.md
index 9f156c0d..01e60570 100644
--- a/docs/how_to/troubleshoot_registration.md
+++ b/docs/how_to/troubleshoot_registration.md
@@ -61,7 +61,7 @@ Many scans are misregistered, or brain edges are not well matched
follow the guidance above if the correction or brain masking was poor. If
good quality masks were obtained during inhomogeneity correction, bring them
into the registration with `masking=true`. If registration errors persist,
- particularly at the brain edges, `brain_extraction=true` further constrains
+ particularly at the brain edges, `brain_extraction=true` and `keep_mask_after_extract=true` further constrains
edge matching by removing tissue outside the brain.
```{warning}
@@ -74,7 +74,7 @@ Scans have incomplete brain coverage, and surrounding tissue is stretched to fil
: Non-linear registration assumes corresponding anatomy between the moving
image and the target. When brain regions are missing — the cerebellum or
olfactory bulbs are the usual cases — the surrounding tissue may be
- improperly stretched to fill the missing area. `brain_extraction=true` can
+ improperly stretched to fill the missing area. `brain_extraction=true,keep_mask_after_extract=true` can
largely mitigate this.
## When registration cannot be salvaged
diff --git a/docs/reference/cli.md b/docs/reference/cli.md
index c7398b3c..1146dacf 100644
--- a/docs/reference/cli.md
+++ b/docs/reference/cli.md
@@ -36,7 +36,7 @@ the options for the version you have installed.
## Argument syntax
-RABIES uses three argument shapes:
+RABIES uses diverse argument shapes:
Flags
: `--apply_STC`. Present or absent, no value.
@@ -100,63 +100,3 @@ regression, and the `--data_diagnosis` quality reports.
```{program-output} rabies analysis --help
```
:::
-
-## Worked examples
-
-### Preprocessing
-
-```sh
-rabies -p MultiProc preprocess input_BIDS/ preprocess_outputs/ \
- --apply_STC --TR 1.2 \
- --commonspace_reg masking=true,brain_extraction=false,template_registration=SyN,fast_commonspace=false
-```
-
-`-p MultiProc`
-: Executes the pipeline in parallel across local threads. This is an execution
- option, so it comes before the stage name.
-
-`--apply_STC`
-: Applies slice timing correction, which is off by default.
-
-`--TR 1.2`
-: The repetition time in seconds, needed for slice timing correction. Defaults
- to `auto`, which reads the TR from the NIfTI header.
-
-`--commonspace_reg ...`
-: Options for the commonspace registration step. `masking=true` uses the brain
- masks from inhomogeneity correction to drive registration;
- `template_registration=SyN` requests non-linear registration to the
- commonspace template.
-
-### Confound correction
-
-```sh
-rabies -p MultiProc confound_correction preprocess_outputs/ confound_correction_outputs/ \
- --nuisance_regressors WM_signal CSF_signal vascular_signal mot_6 \
- --smoothing_filter 0.3
-```
-
-`--nuisance_regressors`
-: The nuisance timeseries to model and regress out — here the WM, CSF and
- vascular mean signals plus the 6 rigid realignment parameters from head
- motion. See [nuisance regressor definitions](regressor_target).
-
-`--smoothing_filter 0.3`
-: Gaussian spatial smoothing with a 0.3 mm filter.
-
-### Analysis
-
-```sh
-rabies -p MultiProc analysis confound_correction_outputs/ analysis_outputs/ \
- --group_ica apply=true,dim=30,random_seed=1
-```
-
-`--group_ica apply=true,dim=30,random_seed=1`
-: Group independent component analysis with 30 components and a fixed random
- seed.
-
-```{seealso}
-- [How to run RABIES in a container](../how_to/run_with_containers.md) — path binding syntax for Apptainer and Docker
-- [Input data requirements](bids_inputs.md) — what the input directory must look like
-- [Understanding the outputs](outputs.md) — what each stage writes
-```
diff --git a/docs/reference/metrics.md b/docs/reference/metrics.md
index 356fd2db..7cc0fb60 100644
--- a/docs/reference/metrics.md
+++ b/docs/reference/metrics.md
@@ -2,9 +2,7 @@
# Metric definitions
-Precise definitions of every quantity RABIES computes and reports. Throughout
-this page, the root-mean square (RMS) is
-$||x||_2 = \sqrt{\frac{1}{n}\sum_{i=1}^{n}x_i^2}$.
+Precise definitions of every quantity RABIES computes and reports.
```{seealso}
For where these values appear, see [Output files](outputs.md). For how to
@@ -13,16 +11,13 @@ interpret them, see [Data quality assessment](../explanation/data_quality.md).
(regressor_target)=
-## Nuisance regressors for confound regression
+## Nuisance regressors
Selected with `--nuisance_regressors` at the confound correction stage.
**mot_6**
-: The head motion translation and rotation parameters. Prior to the regression,
- the motion regressors are subjected to the same frame censoring, detrending
- and frequency filtering applied to the BOLD timeseries, to avoid the
- re-introduction of previously corrected confounds, as recommended in
- {cite}`Power2014-yf` and {cite}`Lindquist2019-lq`.
+: 3 rotations (Euler angles in radians) and 3 translations (in mm) measured from
+ the rigid-body head realignment algorithm.
**mot_24**
: The 6 motion parameters together with their temporal derivatives, plus 12
@@ -33,14 +28,11 @@ Selected with `--nuisance_regressors` at the confound correction stage.
mot24_t = [mot6_t,(mot6_t-mot6_{t-1}),(mot6_t)^2,(mot6_t-mot6_{t-1})^2]
$$
- with $mot24_t$ representing the list of 24 regressors for timepoint $t$. As
- with mot_6, the 24 regressors are additionally subjected to censoring,
- detrending and frequency filtering if applied on BOLD.
+ with $mot24_t$ representing the list of 24 regressors for timepoint $t$.
**WM/CSF/vascular/global signal**
: The mean signal computed within the corresponding brain mask (WM, CSF,
- vascular or whole-brain) from the partially cleaned timeseries, i.e. after
- confound correction steps 1–4 up to frequency filtering.
+ vascular or whole-brain).
**aCompCor_percent**
: Principal component timecourses derived from timeseries within the combined
@@ -55,8 +47,8 @@ Selected with `--nuisance_regressors` at the confound correction stage.
with $C$ a set of spatial principal components and $W$ their associated
loadings across time. The first components explaining 50% of the variance are
kept, and their loadings $W_{aCompCor}$ provide the aCompCor nuisance
- regressors. PCA is conducted on the partially cleaned timeseries, i.e. after
- confound correction steps 1–4 up to frequency filtering.
+ regressors. The PCA is conducted on partially cleaned timeseries after
+ step 4 of the confound correction pipeline (see [Confound Correction Workflow](../explanation/confound_correction.md)).
**aCompCor_5**
: As **aCompCor_percent**, but the first 5 components are kept instead of a set
@@ -67,29 +59,30 @@ Selected with `--nuisance_regressors` at the confound correction stage.
(mot6_target)=
**Head motion translation and rotation parameters**
-: 3 rotations (Euler angles in radians) and 3 translations (in mm) measured for
- head motion realignment at each timeframe.
+: 3 rotations (Euler angles in radians) and 3 translations (in mm) measured from
+ the rigid-body head realignment algorithm.
(FD_target)=
**Framewise displacement**
-: For each timepoint, the displacement — mean across the brain voxels — between
- the current and the next frame. For each brain voxel within the referential
- space for head realignment (the [3D EPI](3D_EPI_target) provided as reference
+: For each timepoint, this is the displacement between
+ the current and the previous frame, averaged over all brain voxels.
+ For each brain voxel within the referential
+ space for head realignment (i.e. the [3D EPI](3D_EPI_target) provided as reference
for realignment) and for each timepoint, the inverse transform of the head
motion parameters from the corresponding timepoint is applied to obtain the
voxel position pre-motion correction. Framewise displacement is then computed
for each voxel as the Euclidean distance between the pre-motion-correction
- positions for the current and next timepoints. The mean framewise
+ positions for the current and previous timepoints. The mean framewise
displacement $FD_t$ at timepoint $t$ is therefore
$$
- FD_t = \frac{1}{n}\sum_{i=1}^{n}\sqrt{(x_{i,t+1}-x_{i,t})^2+(y_{i,t+1}-y_{i,t})^2+(z_{i,t+1}-z_{i,t})^2}
+ FD_t = \frac{1}{n}\sum_{i=1}^{n}\sqrt{(x_{i,t}-x_{i,t-1})^2+(y_{i,t}-y_{i,t-1})^2+(z_{i,t}-z_{i,t-1})^2}
$$
using the 3D $x$, $y$ and $z$ spatial coordinates in mm for timepoints $t$
- and $t+1$ and voxel indices $i$. Framewise displacement for the last frame,
- which has no future timepoint, is set to 0.
+ and $t+1$ and voxel indices $i$. Framewise displacement for the first frame,
+ which has no past timepoint, is set to 0.
(DVARS_target)=
@@ -113,19 +106,19 @@ Selected with `--nuisance_regressors` at the confound correction stage.
: The mean signal across a given brain mask: whole-brain (the global signal),
WM, CSF or brain edge.
-**$CR_{var}$**
-: The variance estimated by confound regression at each timepoint, computed as
- $CR_{var} = RMS(Y_{CR})$ across voxels, where $Y_{CR}$ is the
+**CRvar**
+: The variance estimated and removed by nuisance regression at each timepoint, computed as
+ the root-mean square (RMS) of $Y_{CR}$ across voxels, where $Y_{CR}$ is the
[predicted confound timeseries](CR_target).
-**CR $R^2$**
-: The proportion of variance explained, and removed, by confound regression.
- Obtained with $CR_{R^2}= 1-\frac{Var(\hat{Y})}{Var(Y)}$ at each timepoint,
- where $Y$ and $\hat{Y}$ are the timeseries pre- and post-regression, and
+**CR R2**
+: The proportion of variance explained, and removed, by nuisance regression.
+ Obtained with $CR_{R^2}= 1-\frac{Var(\hat{Y_t})}{Var(Y_t)}$ for a given frame at timepoint $t$,
+ where $Y_t$ and $\hat{Y_t}$ are the BOLD frame at timepoint $t$ pre- and post-regression, and
$Var(x) = \frac{1}{n}\sum_{i=1}^{n}(x_i - \mu_x)^2$ is the variance with
$\mu$ the mean.
-**Mean amplitude**
+**Mean amplitude of network VS confound sources**
: A set of timecourses averaged as $\frac{1}{n}\sum_{i=1}^{n}|X_i|$, where
$X_i$ is timecourse $i$. The timecourses correspond to one of:
@@ -139,7 +132,7 @@ Selected with `--nuisance_regressors` at the confound correction stage.
## Spatial scan diagnosis
**BOLDSD**
-: The temporal standard deviation computed for each voxel from the BOLD
+: The temporal standard deviation computed for each voxel from the cleaned BOLD
timeseries.
**CRSD**
@@ -148,16 +141,14 @@ Selected with `--nuisance_regressors` at the confound correction stage.
**CR R2**
: The proportion of variance explained by confound regression at each voxel.
- Obtained with $CR_{R^2}= 1-\frac{Var(\hat{Y})}{Var(Y)}$ at each voxel, where
- $Y$ and $\hat{Y}$ are the timeseries pre- and post-regression, and
+ Obtained with $CR_{R^2}= 1-\frac{Var(\hat{Y_v})}{Var(Y_v)}$ for a given voxel $v$, where
+ $Y_v$ and $\hat{Y_v}$ are the timeseries pre- and post-regression for that voxel, and
$Var(x) = \frac{1}{n}\sum_{i=1}^{n}(x_i - \mu_x)^2$ is the variance of $x$
with $\mu$ the mean.
**Global signal covariance (GScov)**
-: The covariance between the global signal and the timeseries at each voxel,
- measured as $GS_{cov} = \frac{1}{n}\sum_{t=1}^{n}Y_t \times GS_t$, where
- $GS_t = \frac{1}{n}\sum_{i=1}^{n}Y_i$ is the mean across all brain voxels for
- a given timepoint.
+: The covariance between the mean whole-brain signal (i.e. global signal) timecourse
+ and the timeseries at each voxel.
**DR network X**
: The linear coefficients resulting from the
@@ -179,14 +170,24 @@ Selected with `--nuisance_regressors` at the confound correction stage.
from the [second regression ${\beta}_{SM}$](DR_target) for dual regression.
**Network specificity**
-: The network map (seed-based or dual regression) and the corresponding
- canonical network map are thresholded to include the top X% of voxels with
+: The network map for a given analysis (seed-based or dual regression) and a given
+ fMRI scan is compared relative to a reference network map to assess specificity.
+ The reference map is either the original ICA component for dual regression, a
+ manually provided input map with `--seed_prior_list` for seed-based analysis,
+ or the dataset average itself if selecting `--group_avg_prior`.
+ To compute specificity, both the reference and individual scan network maps
+ are thresholded to retain the top X% of voxels with
highest connectivity, X% being defined by `--brainmap_percent_threshold`, and
- the overlap of the thresholded area is computed using Dice overlap. For dual
- regression, the canonical network map is the original ICA component
- corresponding to that network, provided with `--prior_maps`. For seed-based
- connectivity, the reference network maps are provided using
- `--seed_prior_list`.
+ the overlap of the thresholded area is computed using Dice overlap.
+
+```{important}
+If the reference network map was generate from the dataset average, it is
+important to validate that the average can indeed provide a adequate
+representation of the expected network connectivity. If the reference does
+not represent a network, then the network specificity metric is meaningless.
+The average network used for those computations can be visualized in the
+[group statistical report](group_stats_target).
+```
**Dual regression confound correlation**
: The timecourse for a single network, from a seed or from dual regression, is
@@ -225,13 +226,15 @@ Selected with `--nuisance_regressors` at the confound correction stage.
## Group statistical QC report
+These quantities are stored inside the `analysis_QC/*_stats/*_QC_stats.csv` output files.
+
**Specificity of network variability**
: As with network specificity in the distribution plot, the network variability
- map and the corresponding canonical network map are thresholded to include
+ map and the corresponding reference network map are thresholded to include
the top X% of voxels (X% defined by `--brainmap_percent_threshold`), and the
overlap is estimated using Dice overlap.
**Mean confound correlation**
: For each confound correlation map ($CR_{SD}$, mean FD or tDOF), the mean is
- computed across voxels within the thresholded area of the canonical network
+ computed across voxels within the thresholded area of the reference network
map, giving a mean correlation within the network's core region.
diff --git a/docs/reference/qc_outputs.md b/docs/reference/qc_outputs.md
index 723c6bce..4d4b7fb2 100644
--- a/docs/reference/qc_outputs.md
+++ b/docs/reference/qc_outputs.md
@@ -16,7 +16,8 @@ error — it produces plausible-looking output that is wrong.
## Which folders you get
Some folder names carry the name of the workflow that produced them as a
-prefix, and which commonspace folders exist depends on `--commonspace_reg`.
+prefix, and which commonspace folders exist depends on `--bold_only`,
+`--commonspace_reg`, `--anat_robust_inho_cor` and `--bold_robust_inho_cor`.
```{list-table}
:header-rows: 1
@@ -89,7 +90,10 @@ This registration controls the overlap between different scanning sessions.
```{figure} ../pics/sub-MFC067_ses-1_acq-FLASH_T1w_inho_cor_registration.png
:alt: Overlap between a structural scan and the dataset-generated unbiased template
-Structural scan (top) against the unbiased template (bottom).
+Structural scan (top) against the unbiased template (bottom). The red lining is
+an automated edge-detection computed from the **opposite** image - the lining on
+the top image is computed from the bottom one and vice-versa. This enables
+conveniently comparing edge-alignment.
```
## `commonspace_reg_wf.Unbiased2Atlas/`
@@ -101,7 +105,8 @@ its associated brain parcellation.
```{figure} ../pics/atlas_registration.png
:alt: Overlap between the unbiased template and the reference atlas template
-Unbiased template (top) against the reference atlas template (bottom).
+Unbiased template (top) against the reference atlas template (bottom). The red
+lining on each image is the automated edge-detection computed from the other image.
```
## `commonspace_reg_wf.Anat2Atlas/`
@@ -119,7 +124,8 @@ susceptibility distortions through non-linear registration.
```{figure} ../pics/sub-MFC068_ses-1_task-rest_acq-EPI_run-1_bold_registration.png
:alt: Overlap between the volumetric EPI and the structural image
-Volumetric EPI (top) against the structural image (bottom).
+Volumetric EPI (top) against the structural image (bottom). The red lining on each
+image is the automated edge-detection computed from the other image.
```
## `template_files/`
From 6502f80a98cafcb1a1fd90979c7d221adafceffc Mon Sep 17 00:00:00 2001
From: Gab-D-G
Date: Wed, 2 Sep 2026 18:18:28 +0200
Subject: [PATCH 5/9] Documentation of the default template, and how to change
the template parameters.
---
docs/_static/refs.bib | 31 +++++++++++++++++++++++++++++++
docs/how_to/change_template.md | 27 +++++++++++++++++++++++++++
docs/reference/index.md | 1 +
docs/reference/metrics.md | 2 +-
docs/reference/template_files.md | 19 +++++++++++++++++++
rabies/parser.py | 2 +-
6 files changed, 80 insertions(+), 2 deletions(-)
create mode 100644 docs/how_to/change_template.md
create mode 100644 docs/reference/template_files.md
diff --git a/docs/_static/refs.bib b/docs/_static/refs.bib
index 075bedd5..faff0569 100644
--- a/docs/_static/refs.bib
+++ b/docs/_static/refs.bib
@@ -969,3 +969,34 @@ @ARTICLE{Biswal1995-vh
keywords = "Functional connectivity;FC and Brain Networks;RABIES
documentation"
}
+
+@ARTICLE{Dorr2008-cc,
+ title = "High resolution three-dimensional brain atlas using an average
+ magnetic resonance image of 40 adult {C57Bl}/{6J} mice",
+ author = "Dorr, A E and Lerch, J P and Spring, S and Kabani, N and
+ Henkelman, R M",
+ journal = "Neuroimage",
+ volume = 42,
+ number = 1,
+ pages = "60--69",
+ abstract = "Detailed anatomical atlases can provide considerable interpretive
+ power in studies of both human and rodent neuroanatomy. Here we
+ describe a three-dimensional atlas of the mouse brain, manually
+ segmented into 62 structures, based on an average of 32 mum
+ isotropic resolution T(2)-weighted, within skull images of forty
+ 12 week old C57Bl/6J mice, scanned on a 7 T scanner. Individual
+ scans were normalized, registered, and averaged into one volume.
+ Structures within the cerebrum, cerebellum, and brainstem were
+ painted on each slice of the average MR image while using
+ simultaneous viewing of the coronal, sagittal and horizontal
+ orientations. The final product, which will be freely available to
+ the research community, provides the most detailed MR-based,
+ three-dimensional neuroanatomical atlas of the whole brain yet
+ created. The atlas is furthermore accompanied by ancillary
+ detailed descriptions of boundaries for each structure and
+ provides high quality neuroanatomical details pertinent to MR
+ studies using mouse models in research.",
+ month = aug,
+ year = 2008,
+ language = "en"
+}
diff --git a/docs/how_to/change_template.md b/docs/how_to/change_template.md
new file mode 100644
index 00000000..6c585687
--- /dev/null
+++ b/docs/how_to/change_template.md
@@ -0,0 +1,27 @@
+# How to override the default common space template
+
+The files that will define the common space template and associated masks are
+controlled by the following parameters at the `preprocess` stage:
+- `--anat_template`: the structural image that provides the target for common space
+ alignment.
+- `--brain_mask`: the brain mask file.
+- `--WM_mask`: a mask for the white matter.
+- `--CSF_mask`: a mask for the cerebrospinal fluid canals.
+- `--vascular_mask`: a mask labeling major blood vessels.
+
+RABIES will automatically input a file for each parameter by default (see [built-in commonspace template and atlas](../reference/template_files.md)),
+but you may want to choose a seperate template for your study (for instance if you are not inputting adult mouse data). To do so, you will need
+to provide the full path to an adequate set of NIfTI-formatted files. At minimum, both `--anat_template` and `--brain_mask` must be provided,
+as they are key components of the registration pipeline. The other brain parcellations are optional, but certain downstream options for
+confound correction or generating QC reports will be disabled.
+
+```{important}
+The template file `--anat_template` defines the common space coordinates for the entire pipeline. All other
+mask files are expected to overlap with this template file, as assess from the metadata coordinates of the
+Nifti header. An error will be thrown if a mismatch is detected.
+```
+
+```{important}
+At minimum, the image orientation of the template and input data must match. It is recommend to follow the
+RAS+ orientation convention that RABIES inspect, see [How to check image orientation](./check_orientation.md).
+```
diff --git a/docs/reference/index.md b/docs/reference/index.md
index 862337d8..f0b2b700 100644
--- a/docs/reference/index.md
+++ b/docs/reference/index.md
@@ -11,6 +11,7 @@ describe how RABIES behaves; they do not tell you what to do. For that, see the
maxdepth: 1
---
bids_inputs
+template_files
cli
```
diff --git a/docs/reference/metrics.md b/docs/reference/metrics.md
index 7cc0fb60..4a25832f 100644
--- a/docs/reference/metrics.md
+++ b/docs/reference/metrics.md
@@ -81,7 +81,7 @@ Selected with `--nuisance_regressors` at the confound correction stage.
$$
using the 3D $x$, $y$ and $z$ spatial coordinates in mm for timepoints $t$
- and $t+1$ and voxel indices $i$. Framewise displacement for the first frame,
+ and $t-1$ and voxel indices $i$. Framewise displacement for the first frame,
which has no past timepoint, is set to 0.
(DVARS_target)=
diff --git a/docs/reference/template_files.md b/docs/reference/template_files.md
new file mode 100644
index 00000000..2fbf0a96
--- /dev/null
+++ b/docs/reference/template_files.md
@@ -0,0 +1,19 @@
+# Built-in commonspace template and atlas
+
+## The DSURQE mouse atlas
+
+By default, RABIES uses the DSURQE mouse atlas {cite}`Dorr2008-cc` - a high-resolution *ex vivo* structural MRI average of the mouse brain
+accompanied with anatomical annotations provided by [the mouse imaging center (MICe)](https://www.mouseimaging.ca/) in Toronto, CA.
+The DSURQE template, mask and label files are all automatically pulled from the [original repository](https://www.mouseimaging.ca/repo/DSURQE_40micron/Dorr_2008_Steadman_2013_Ullmann_2013_Richards_2011_Qiu_2016_Egan_2015_40micron/) upon installing RABIES.
+
+## The EPICOMMON mouse template
+
+When using the `--bold_only` parameter to execute RABIES without structural scans, the common space
+template file is changed for an alternative EPI reference template. This so-called EPICOMMON template
+([available on zenodo](https://doi.org/10.5281/zenodo.19069284)) was generated by executing the initial
+stages of the `--bold_only` RABIES preprocessing - 3D EPI generation, EPI inhomogeneity correction and unbiased
+template generation from the EPI - using 5 independent fMRI datasets from different sites{cite}`Desrosiers-Gregoire2024-ou`.
+The EPI template then inherited all mask and label files from the DSURQE atlas through non-linear registration.
+
+Providing an EPI template as target greatly improves the robustness of EPI registration, since image contrast and
+shape is much more similar.
\ No newline at end of file
diff --git a/rabies/parser.py b/rabies/parser.py
index fe6526b8..c15b1d8a 100644
--- a/rabies/parser.py
+++ b/rabies/parser.py
@@ -580,7 +580,7 @@ def get_parser():
description=
"Specify commonspace template and associated mask files. By default, RABIES\n"
"provides the mouse DSURQE atlas\n"
- "https://wiki.mouseimaging.ca/display/MICePub/Mouse+Brain+Atlases.\n"
+ "https://www.mouseimaging.ca/repo/DSURQE_40micron/Dorr_2008_Steadman_2013_Ullmann_2013_Richards_2011_Qiu_2016_Egan_2015_40micron/.\n"
)
g_commonspace.add_argument(
'--anat_template', action='store', type=Path,
From cefa135564ad7c765a083322669617648b28f7a8 Mon Sep 17 00:00:00 2001
From: Gab-D-G
Date: Wed, 2 Sep 2026 18:24:29 +0200
Subject: [PATCH 6/9] change_template.md needs referencing in the index
---
docs/how_to/index.md | 1 +
docs/reference/template_files.md | 8 +++++++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/docs/how_to/index.md b/docs/how_to/index.md
index 1289ac15..6f4fd789 100644
--- a/docs/how_to/index.md
+++ b/docs/how_to/index.md
@@ -14,6 +14,7 @@ maxdepth: 1
install
run_with_containers
select_scans
+change_template
```
## Getting good results out of it
diff --git a/docs/reference/template_files.md b/docs/reference/template_files.md
index 2fbf0a96..b43dafbf 100644
--- a/docs/reference/template_files.md
+++ b/docs/reference/template_files.md
@@ -16,4 +16,10 @@ template generation from the EPI - using 5 independent fMRI datasets from differ
The EPI template then inherited all mask and label files from the DSURQE atlas through non-linear registration.
Providing an EPI template as target greatly improves the robustness of EPI registration, since image contrast and
-shape is much more similar.
\ No newline at end of file
+shape is much more similar.
+
+
+```{seealso}
+[How to override the default common space template](../how_to/change_template.md) for
+customising the input template and associated files.
+```
From a39c4a8a2f167e5f699603dccc97ef87136c5c7d Mon Sep 17 00:00:00 2001
From: Gab-D-G
Date: Wed, 2 Sep 2026 20:27:29 +0200
Subject: [PATCH 7/9] Reworking of the tutorial for compatibility with original
tutorial and the test dataset, addition of actual QC reports generated
through the tutorial, and brief coverage of the --data_diagnosis outputs.
---
...acq-RARE_T2w_RAS_inho_cor_registration.png | Bin 0 -> 594562 bytes
...sub-PHG001_ses-3_acq-RARE_T2w_inho_cor.png | Bin 0 -> 1003260 bytes
..._task-rest_acq-EPI_run-1_bold_inho_cor.png | Bin 0 -> 531752 bytes
...k-rest_acq-EPI_run-1_bold_registration.png | Bin 0 -> 525919 bytes
...t_acq-EPI_run-1_bold_spatial_diagnosis.png | Bin 0 -> 935684 bytes
docs/pics/test_dataset_atlas_registration.png | Bin 0 -> 662903 bytes
docs/tutorials/first_run.md | 199 ++++++++++++------
7 files changed, 136 insertions(+), 63 deletions(-)
create mode 100644 docs/pics/sub-PHG001_ses-3_acq-RARE_T2w_RAS_inho_cor_registration.png
create mode 100644 docs/pics/sub-PHG001_ses-3_acq-RARE_T2w_inho_cor.png
create mode 100644 docs/pics/sub-PHG001_ses-3_task-rest_acq-EPI_run-1_bold_inho_cor.png
create mode 100644 docs/pics/sub-PHG001_ses-3_task-rest_acq-EPI_run-1_bold_registration.png
create mode 100644 docs/pics/sub-PHG001_ses-3_task-rest_acq-EPI_run-1_bold_spatial_diagnosis.png
create mode 100644 docs/pics/test_dataset_atlas_registration.png
diff --git a/docs/pics/sub-PHG001_ses-3_acq-RARE_T2w_RAS_inho_cor_registration.png b/docs/pics/sub-PHG001_ses-3_acq-RARE_T2w_RAS_inho_cor_registration.png
new file mode 100644
index 0000000000000000000000000000000000000000..6f33bd3a2351a964fafa91bdaa2fdb34dd612d01
GIT binary patch
literal 594562
zcmeFZbySpH*f**I5=xge45gIPT{46q-Hm{NbW08*HGq_eATfYQ$AENq3JjgnARr*!
zb+*rYzIC4G{r~*;?S;6OOJ?T2@4c_N#fI{Lzp$MZ^xf{T#D^X>%Hd28#BP{sJSm0CN>}6hJX}mQ)lC+QA(-I#
z|NZuV@4^3{``{|m8L^4;zwU9Y#D|!_OEh{#Xt2b%-g9T>_~j)0fB!GZ=VFHohltaL
zmd|?ux5t$iNU@c9xdl(SgvI#({>&1WyUn*Zm%9s&)rQ47Ohn;wS+0iz7dwaPw^s@5
zx_!r!Pu1HtHa33#{7Ki8W2v5G`|&?-=WQjG@lgC2JvgXN;_a|($yQwnRXBA1_-z0y
zB+
zl(^@D|EWWz0b+eqqSL%gi|yL+*r?iZuFhj?b;2-lYW-WhN-_c=SG@Y!@blCmr<3;&
za3cjAW-7c7e=QVCsD=@%ig6Q#i|w_b;Y*w??lwCA-uTaX?+M@!fa_J~n*K6p-uCVl
z7<^N9eJk2=E?xz_jd*Soc=#F@Qiu_J?b#
z<+6tD1>SB?mAS1CQaRPVfSNe3#v#_{JWl5z-+jgl9A>M;$4|O%x*HD?x@q42B$THv
zgI)WeFJ(#)U=)tqRvH+Wp(K39Vgin`+VLf+D`j!_pEg~OBViuk^8NQd@Sc>isCHY~
zo2Kq12Au!>y1hi+8dQs=@m$KCaW6;x_aU-SJbLtqn%YlfSYb6L&4^1-NXVud3W-x-
zf;8=s5!6A^(-~|$L}(O@6eNVj#6DQaGR5~+%sTiXQd3{D#D90mg42tYjN9_3D1Tbm
zbazL^{j@iV~Olgu+X~#3u^@x4pf+&TEySo+}+4!S`q1Skg*(Ap|8PU{kNc
zUZLJLZW*VkSpWFUX;@{S|MxOEDWl{dadKJe$jQ-7ceaF&oQBXVV*qbH2!dzSRr4a;7YiPGHH5Wzavr{JJ
z;8e2|8Xg|LzrVk0a`-yYV%2L6-*tMYKT
zV2{(^<63D)zFKI>^F@KFr0EwWp?7Clw?N7O-St^F#C7#B-85h8>#z+UWhX*tg(d#3
ztL^%r9tT-C)Y)XiS_kWcToysU^SqZBLV;HS(Wt=MVorK#wgQ>enGHr0hD>
zJ{y^54GXZ#>5&W9<#5!|D?VSxoV`K(SA3Fi3Ia)
z#f^d$SEDgs9wb)rHP5oy`2Rpzl?Md{DdjsxGeTk<=C43iYWQ=E#P{<)f1M~xUti1h
ze%`z+3CAe_?0d*TkfBq^o%^p#MmMEup0~+8HXMq&A{JpY%HR7XglE1P8XC&CxrTPS
zASopD=Q+sQO2;0DFd
zM-`cfgb3PZkN(V+mzQtB&VQJfowWvB$xnK$?0a#L$*erY$H<EjFxnY`#7bokgCec*GIXM*S)H+_bsiM&F2HM_5JG=rwzGk
zkKtG$g8%LW=cDLPR&JnN(AS%tRt6E60Cthv@2ArOcvE{lV(Ulw$iQ^b%C
zc}dE%-+5WlKDU<(0fz&E3t(eTeJ}lIv36SVe0j;jI64YBNL?3`ce{|Dm2xIJNli);
z+AeJeuf~3H_GVwTB^$+7-*bw~M!Riq>zh
z6_eI01MDNVgr?(utMV{fpT`rYBbBZ6w;3#yGt3Y;SKT_o_fPFQ?UyuC!pC|~Vf&G$
zSIgv#3Cq6*QUo1lf|FZ*oz@86u-6<8iVE6K-Ql-$b|&~vaW6L(YhQ|x@O%kBKuA=S
zN`l%a370>9{uw{vo9fv!Hrg0Qg$JUR<cI)Q3<&H`(_vsXd?9>_!ddz{N
z=_e7hBVd3R8XOtXX`Vd7OBr?XagErw;3N5+(G`FM$`Qv!okfEEufk{qczMxg*%K6F
z`%mu|C;zLZ9H0lT>K`p!zg;}7ubYiuHJwGfA=sDlZKL~PU>;eVQ56;!+1l>VCDu(C
z=M=DINN(hOmoGtF^+CACpz!6kVB@B8tX`~%)7He_z0_%-zvD?&r%*q4b0OH2*==(6
z1qG@Ve!6!KykRrSsbMoGg&ubGD^C7ob?mN$%b!|ZV-IcmbCV2&Z`%Z?p%}`re7C9Y
z^>|-Gwgxstxk-&6&Ud$Vz3KALWh*|+d8@ek`C|U$R+QXI{>1qvGUD_T4!-lno7}a-
z^SqcYr>K~ir>0F}X)3v+Z&Jz$%}Fb?;aLSO(mugQB&%P(%sDSNI
zIG*BED+|RFUya?|+yq@>Y3Y?h?%M^o82C@Gc3ezq=R2#~-}HiwGt;zni6uR8$7O80
z0|Nt%xG*WS?Mm8Gj4zA-X{YGbuRQ9=Z)0v5ZrB`0M@Q@5?#|aaq`-f|W*xez-5z%J
z2sYgui|#gz{(?biB=&n%BYJ}H#hk&$v_Q?(d;UFlgM;AwMSb|Y#4e{%at&q#;J%w)
zU9E#Q*FM$iC4Js&$&;YS@Dk4xz&cf
zkf&ncc&>hpgs$$j{mM4LLdS<*p&y{%OYw3(KUf36!Q_AX<=R`Kc|6hWQX9Uy
z(o!|H1a}W^@k%4FCECwH8137ivtlGJ;^b+)AyvDfRM2nJ_MReXWo2bDc*5vB*amML
z9l6p`)drkViQmm|%dbynod6Qt_Y#X!=+SMaoLVm`AB=!Pn$J3){;At4(a5iW{#*j^
zApl?q-M=_XMD*{v{M*QW))1PHAdEJR-_B_lj^D?`3=0i4mjJJoGBB}q47!s7lRZ|}
znM(vEDgu9KXODBWS|yh_97+@pWlLzQB`~oHLXB+l1s8(yl_UlV0%2g)x2_d$lfvWjpM-s|6qRHv4YX0s-Ok(qtilXXt@3QVQfNjTH
zlQLeusQg^;hBZ}$JLribmiN^P#|y@78%>bowy}`Km$$>+k~iNxF0V@zPLGtlMC?9_
zkMCEqI(#2P%rCPZi4p2^9(=BDkiA$tC5}6kIPV1CZ^`5B
zRjgC2V>}rpmnFcOd4%HxIZ(Am2y=52#&m-!S6(`_AcN^G({Kg`F+Mv+Eoc-$w7u@?SFF$P#JgL1Q)O
zzt#X`ZUS@UN>gFgd_pLEv5`g7UAukoLw5CZij%}LoH5#;`#Lpk<`{9EZsGfx+1Oxxq%Ao$C3|x#@zWVi
zOKRws3o6#oM585@$(1v*iRkGh+fxe`l!pe3k2Fu?GTa3k3CYXIBm!l4~Z5ginU
z#hh8kx
z#Rzi4(hmrv$>q$X4qJk2?NvvgHn}MWWY~tJ(7STh!MInoQc!_%$N&*rX+%D2QKnZu
z%|U_#sDwe4{g)LXH#avSavwDh@-#j(0W})FuUzzn96Gm-)rGlalArqScQN>XJ;Q$J
zz(fo+_XAyK#<2%;%C>UMM_yiDwxcVM;lsl>ROx#4fA+g&eRSwG348RH@148@H{<>yX)28-
zlL}8$>!$60``Ayt{}t6~{^jL;L!A;M0F2b5m5tuS8`>_ssRy7Ct73|CsMwsNV^Bay
z?dq9w@p?xG6acRD^uHCdj5!@;ho+*U5*-y)X;5rlmKPV`BMUB;mzS3q0s(E1o>Vki
zvslO4$_l{2s&k=SBj1domf1&VO@kv=m=-C2@c6$Y9^r4|CcN^U;6-tEOt3!_}QwAzxp$mF!gBFR9OI=zw5@CqwM|I
zF(vz952MoS6Va`r&fsd$S+7qQZewNeuydr#
zDAby(UiM}R(l-sB3UC+LF>@(`PIy>O{>wbObxMEg?1l?#4pnLo2W6Xa6W-|8A>(^j
z!DjtjY$$8lxoTNG%bEDY_i=;1(ySY7UAq|_C(~>VcM}Yq
zYgq7u|Gbv<-{)r{oUVJVR6hOT5&cq)Rmd}{FW#}T>>5ZV}PGQxR?5<1ICrwi2bFh`k6z~1ZD&V&&%
zY2?pea<47Lq=-$`CcvQ%6nw74G7N{C1SCuwdb8Qj3o65eZjfTI69cD(yG0=1?92=g
z?bs|4bS@9
z6XdOknAjD}f+`FUI|j%?rI>dIwIlz_%MQKJTdS!ba5XC=pp6P*scRK{V5P)7P
zW{>b{PO`25hOJ*e$CaQ61Sumf8EspE6!?@>hDJ*`e%XMBaqt({i%{jZT+uGI4Lm-9^v2(RVva*3J}
zuvy=NPH3*v_z@Xk42>3AhJ%h$IIi`rHH0xcvr&p^3fi%Rm?T#BKR8EWRy7|aAUP5g
zotsquS-aj}bWQz_FOIk5<>ch#<+TIV=mVuhaOon?Wb;^hEnUsb?l4x5Zt|rlgBlLy
zBMQ$*%&fKbl6dJUuQ)6)J|3AxXQ>8jiJE&H9n~qR@LuDq(?dZlc&B+QG-kH^}2z?ja1B8is?kFH&;ZR7*fUR}q><)P1
zKoK&3V9u@GuDRb|Rghp%X(<}DQ5~JGNg_Wza<3{AiLpVT*W`D;y2|vs$Qt~pmu?F`
zz3P)TsrKvl#7idkBMWp2@2VGTu`&3veYndxRGml_)%EiywMPCQAmZ5CvZbTQaWESF
z{)?j;gB!Qe(9qa*OBxQ>CCTHmOwOKjn;0i(!>;1fk2rTEo6ckl>szEZh44D4iVWiw
zvo-R^)@7uHt^Kc7B+q+Qfe?B0DY!b9GO=ns&QmGzJebwXN)Ey2V3p6L%2FkMT~o)b
zc-FQqiT`$IbJrgUzuJx#1y3vSsi}mRnEhMdxRr*y(-zgV09dw$y36w{>%SEM6#tRO
zT$}D9@x5l8k9XYbCE`owLOwbip-!7FjVC>BH;<9zan)(Aid>1l6Xl3Xpa|d2)h}>D
z2ILrNV=OYC;3k&YY>XiGf)_n6Ha%CauCChtS=D$V3eb7ikrzN*+B1F&eu7T;d^NFQ
zmHDaUi5}s(TM4L+Ey(p`k8bJ|Y9lAx+o&$IJXi=@B_Ln1Pl>{Vb7p|BGj2Ln0EO6>
zfBCVdHT|4TiO{=yc7gV=c5yVFERL$A83s^X{^n*#2!>G{4(GlX_42Z&&Yam2q8eyX
z7e^J8Vi3h_U9WOR$R34lnH;k%`YJit4TR_20cV)#w*c7XIkGh@kzg5(c7;`DPz+z@
zrh6LH&;98i)F~Vv9#$uvSDOi#_e}ZeIXeKfHlRZ=0hljVLivqFcTB{vap#@21Ce5o6lhe)C|>^FQ?FZG&MEBz6^eze`!GrZUCj=G%}Ie@)z{E3iVA0
zD!_y|_E$tFI6Cc!Q!&CPtB2vx#73-lTO8ku*OENnYOaHY93nYz#d6tE&b%YmNVO
z>8H#7yS{WpebdaJ_DCUK^fA2v&_gh3++*dKj%=JFv79J9=^OWP?%rc~V3zKGB7D%p
zI9Y56^xL;U9JJ_;exCVEQu5Z<=`LZQAT<&FRe{3SM=IGi6x7tzK-mXi6|nWlp4yI?KB9
zCa>e|m5~Z5QU?15l6M?sNja`SOU}`Fvbxo-4hSz571a+*o;unoVnT)8fM(iC^G+Nr
zCpdIWui9NCO)gI(pAAPWthjK
zZ$yCwD>%>#DP=?n$+ka7G#`<-B|+k_w4|9xIuWIHK8?{ss!&0e_!mdy(IL;yJ5rxO
zAOQ3A61mk@axgSR!lADzfqp$v)Z>FI%Q&vQa*jqn&=*VS2On4cIK
z1QeIEL{$hu|s$G3W*B6LrIGA;9~1$YCWeysUPq@&jHi3tfGkLCrPl@tGmd7MDF
zuC}eoFMt0?H2R2IU$Pfp-!9J@-e?8qg*E{7CU;Z9^tw;iX!82EZqu?itzVHdqRN1?
zW^TNg!ZXD1&+RyJ>?yYJE7>e=5s`}v!3Jqm<-$y*5|+~|_1CDZ1#s@T5@i%+gd!OZ
zfJVd|T%DPj3HtBp3Ehnv^iShD;w4MglOBSHcj@@h3v%$Aw7XrTnBHA^&(+T}Ly*2Z
zcBg7y?ENSurypW=b9KzYf+=JBvQJ@UaIL@P{-z-s&zo5v6~eW6kprh
z+oOVJGjeQP8#>`#=J60JI`0k~rx_h^D=DLHK<|Kd%r;Wp`zZEh?bpz)--9f$pyHM2}?o_sx#!ZRNE6y#Ks6#C1;^bD+OptnN*`{R~rJ
zHjX&He6dNTEvU*U??E>_;Gu0Z#sI0D={$A!m(i{h1apVj)dSzy6_gDzs#F|+Ptd1?koS~nfal1Gh?FcveY;&7_C`X`T=
znBVFH6Z%F)RuxO;mlZ@g1G6`Wl0X%1&?_3Z^%U+h1?@0vSg#ofpldSLsoebh+H+;?
z`??UV-uO1Ee|cd6)Mgm;`*TJ9lMoHonxkKWZZCDXwkfbohluuaF9tl6^yr0w4T~pn
zW(Lh{-NBN7cG5lb20r#BJ^d*O4k+i4gZJbO8G0O$X>#;Tpe3}nN+)=mmp#(qF)X(l
z_&r|e_E%h=t#~tN8E`fJ8m>Ui&(@%z`MVP6t`(jVMB5vW
zVK#Ze9oWp^F4VJfSm>7Uo|%t_}OAm^UX05
z%~ZPKA>Zzwxq477?Fl~4NCAl~o<1up>%oHuh~~l1B_^K-tcH8AuBH7Rvf<0Sagen)
z6Od}%>qs!)fx0-Y%E6G9amS3vdZNooE)gX>7Wmn>5Xk^)RLI9MJwly5`@`*i8Z8m_~j~W^wgblHNAt3P`bk~Ygi$7
z6z)S3=hIlS#wem#DYAnhYRN~$-cY4OzpT7Yhhidizv2rTVaJ)tf1#S2f2Ag<_ojTh
zgX;dqJ<(xiBJ3y$&_&-TjoDTLIg%y5^$EeUmEoh~VLij1_P)MY3g8Da5n;o#2&zkI
zXxLaj^A+g|!y;5RmD{l6yTrmdlZ-PZGph)q+!4BV6?cc0x4h>Z$z2&|aDsqcwt9H3
z#m3LW19|&1kgPni&f|J*naTY}sUSJGlT*!&t=q=iN_2;kclYz(Qe01l{&`gm6j~sN
z?+498zv*$9FVbH>nUOZ6y5!*Cuz6JCUkt6z3l3*MbD(9!%NCzJI*6tbO&<8=Q;yME
znj<@FZ)^)3mW-&2zi(qEbY`!niMwuK&Cpsho=V2dmkPiuEUmzAqT@T
ze&~O06qvsMEoy~2G^Yi+;XMn@r;R`tfT7B|OZ3ZsVf;0Vt8fcFrCsYUlI@NTBo8-L
zb2ajD0im8MUHY4Kn3V+C2tbYr*+e~o>u-TceNjCJtN#fTJ*mAAU3kGnBw2Gj0d`9(
zja}Uig{`^XQJ{!xRp@%c;tojFP2tTj5fQsRGjZvAGyY
z2WOBIkuee4w{R!38-Fg*3@ifA^89@+#5zW>APL6XTDC}>B0*i@ck8_H@_U5
zfcQCS;t~Qka^3GFsQ$X^m-}ezeeC_R9VK$pBIba@fp*$mG_h9Hw|_p;7sGd{3)ajr}|Cqi^O$ln0RKCgU}AD!GTfhl9j%yC%LnKne`K
zx&|7ErLMy3l4g>+i{;d8V#bguN(7ecv2;3%Cf$6=1;
zc47gupy#%YK+1Zm|H<|?$GuU0#tQyW)(@Kh_J4eFfBVX2+&79%P?VL$uwhbomvdgf
zxHWdhS(qKJU(G_Gy%@5r!gu`Hr=>VFS5|-FwHU4LY2H>HU_~mgQ0TmG*h+mGn}Czc
zZ#VH$`S1E4i_Pf6UT8&_j?wVM(CdiMu&{tautSh@19g|<*S7KDn>=PSEO+tiFE033
z+vKn~1Br2dyS{wSZ!ZkWzGxcW1f~H<`heU5D+C;~cXu`~dN0QAgTpBxESz6^{LPg5
zWfBkuAY*dmtfMNyUEsQhf^5h<++;4xSY4?xBduOpu*46ORu#2V_Qg+#Ek^1tb-Pe^
z$hVc4wImmo?p8{%y@R~xEYq_$Gn4Y%CWtfQB9D>-?0Q_@W1^&ag68WrFqe70a3q3G
zHr*FkY2e`K=m>+sUcI{e%6SSgV08-h2wFD|;xC`x28jQN(}CHc%v}VR5M$-J1L<<0
zXZ*5|O4jg@&}2(ZG!)WnNyLd9*C~}F?+d#YWf{WZyu<$dYbOx0M8~!~D!Dp@3KZxF
zbcfm~#jNcdb6GZ{(n55;Au%%0)10-u+q_@}rfBNCGdG5d3frJJB8+n;B^>%yi*4=DyMF}o^$qORj={K8*0j>b
z*^lztMwei~oYnOOJW6-o_8W+VXZjP|M({tVeElrA5($71wd6hr+cdv)BjUwEL5`g&
z?t?&zx7YLv?5nenUv;DKH_u^HKIr39H7*tcDaHWi0!V|b
zJLs#e6^5p#o}UIhg`6Th4M26&cDh8}iY>lFn=i8+7lo?$qI>}xGjCgbcHNiQ+yK-S
z^2ko0XMK9nmfr@RMTnqLhHaEHrYMU$8f)c8riMDiy8p_Sscv(#@yhS;PoX}A@-SDm2m`77>x3@NbB
z!Oa`Ib{8pTqrVzs`_<}QtmGiv$iOk9209}sDMVNtWDXAqnZ>99oB&klx(q|z=qz=>
z>eYIW4S0UklIpgTs?0vExssfa+nZVxb9^tb1M;<=iEv$PTLZP~k9Hx@NA)yQ)7yWdn0RR)tNa+0;?S6SOtCP(N|Mit1v
zIW$mmHWo}!eDjd&o4fYMqP#v%w18Fj4hMRb#sqN*dGmJ14*R
z$RtIc(Kq1Y;o;%p0->CAzI0||un;MiY`&^C{(8Qmc3lbT_&t9@LWl)@h=#$IhmXwTn7zUCMdK|zVx(|hJhpW*R*ZS}R
z2Eg+L8Vh)y>`VoaK5Z*w1Bo*bZ1f(=pOO;TXyUJ5c48+m6$@D#w(|>5)XkO1rMveZ
z=thHgKZ%@UxZ|GTCDsIT09=WcX_Xi_A@_m>Cq2M+0)!i+Of%J_IF!IAvMSHlvITne
zdt9BJ_iKv<4B?xe#wstNW)>4~x0Br+5bGeHXUvMdZ+%u2XUpc17c(yqcg8KF=0l)4
za?DG7q8-9Hl-;3A;%qWd1mB}U9sXl-hr#kiDx$FnTOlUEvPl_uega}*3QKSU;piZ3
z?8Ll>j}sI_fb;lROce_K17fu{d=VW5Rl&BEGxh=?EdcV50petgg?8^bwC}azIhgW|
z&xb*i6|;{Dw9AcNdIVjK?s)Q7v$;!GjFh9T9(3x)_U{;F
z9w5%{IuOk8e(48>Y@3YnBnUHt5P_p3p1w$>xChzsOTU!hP)|L5az^tv?V&LvGDoWQ
zG2@|VJWLvybuh1Nevf`%TZ;)8D2w#2lulF|?zwJ>XNTVPa}#@}xRJpuVbi3iLev__
z$scPxMC
zGtJ9@(VFp|B(l@9zPQbB@|zpf{DmKEle^pIuh?wKgN?b-e6`ga(UYKSq|QNBR`PLt
zzK8`~weUClGOMM`7aiYr{sKelkSRUBdSk}IjzmZiKKVf8z06PG<5D@*yaEfzU10h7
zQ8TdoDKsrU=(@TRGfyCRdyw!nK$tAD(PPIzi$oS5{!rou`14bkg*9(3=~uu&L+k4W
z+sf#G0XyjG$H=F0P4Y>YwuP@A>);TT!zV}D45fsJBs-Z7NhFi73B^EThR9b7_F6A2
zWf0|XDvq=CsLMAWWkXy~^sQSPhHGs`ppgCANG?iR+GqhvJtW?Y1JL&hyvSj{cw-?z
zQ>}m7T<=8l38=k1A|muW^xx%H->do;s69?SteXt)iGiK91H?ve%-{*Kz5`aoTds5d
zlg69wGrni9I$UgD#;kN3dHRfg{pwbR@s*sZi*6p~3jh%-5yAXLf#aQlNHqcYGQm87
zkj)xJLN?5PAt@
z`dTH<4=EVk{5JXq)lu?lwQI$tuyrHEj7(NUvD-yW3s63?NVd7w0)WRv(mbg#)71w-
zkeJVvd~MdQT9?vMJFVuPC?6$mC9c*@svC+lPBqoH1P;Bre7}x7#9ZP`82|;e?Gb&0
z|5BtWNnEqY5;}Xs<`p=Mbu4r_I~eQ|Hw0i>7JPyAZ$a
z6}m~H`QyR2wjG=%j4cZI?*CiIT$CDfX16cWV$0U(ZL*`|pW-~*KH(}wFTOYU+Bi~S
zoIHkDZ*=mNiyd8|59z%46ivu(-y{8=S;_{q}i5fZ5NAHb%8xQ67J
zrSm^hkIMB1bhx{#E2Hs^Y2F~HorE3X6XlfUlT-#^gB+fVq1ziH9}H{3ErJF?oVXZ$
z+#ZYsk*OJQB`PryfxwsASksSELeNk&%(nzcSd8-I}g3+$4S4e$TRnQk2Q(ax`ElO}d)^{xtm+Y>*p^)*`h<;NF>ZQI*L
z0_yo%26}o}-_SbCP~Y}KQ`kw&Xo5xd^U0zX-{zjmJ}kt~;zOR!;cRM~?|h)E(nU2y
zzsjO-$8|W?BT#e9KCO&?ca1UlXiE7(ncL^NZZ3%8%@n{z)AnR1R+_ka>^pYYcUQ1)
zr%&~|80Ow_74Hz`KkA{Q@e1QMZ~0_LS5uZt
znb4Ss`O9$baiak8&~0(HDNE|*9?aCYiWTQ)P=^?!V)JEm@rw+C;-I5wJYTX)YN?yN
z;kU5;+?lGQrU~*tTTLkZ359!Al%-eB>b8d`+`5GoQ~uqK)hj*wba7}FZe^m+Yb5;T
zW8r2hdIie8wC~0jclyw2$|oXOCY-O|F70zlY^gG07mJi8(X@p+yiq}R_k9gBT#r7J
zjNf}8VE%aqZ=2Cdv0A{&j`Ylb<2Z+_j8P@Pz%Wr~@dbAG@>{RP$&8h!Esl02AvKNR
z=0)t%I}4ls3}dug7rTWbH?x%@fdB(DI{}GH!l$PMLy@
z-He|+eChbR4=P-T6MbETG~VL<_-j`qerO-WlBb;e%b_(AzwfDaYcBdYM84SFX|JkE
zqG;K=-pTOwRIZRWI})~%*i5R-Y0HwUpPlGSPA9J0nqFtlO)L%Z>gvtr%u?sLYd1-0
z%TS{KK+)K%YS_KY`NIR+=H>P*Gwgeu59=CtcjG0!322C%Ev3DvXlOdyoQAx#tcLVu
z8Rwlp(KI{L%|hKKW^>w7=7~L0>tGZ7`|U9Vql*_WreI!|JI6lag8U)c-=C%A?|F8G
zNiacnZ|a*1wb&A2J9ZG)(L$31;Kh1TQBahvto=%Hq@|8M}QFC%w(gA
zANe`v%@Q4Sb#~!m;_S?;L9gSh{M{wo#c86tp
zad@sg$%Xfnqb6s{r=21QoV3g
zXZF8%pA*^jq0@ZGK0~qL{98P9_4az(dKu+~bwg}g4h$>CtSpE|u@*2!roO+1d|#{E
zdKL}2sSCXb4x*UCaRO5>&P#a-4t{BFYSw8K_hQihUN=C)xpRNqMTTL8^_y97QA0kn
zPjcPs=T1{Sli@~J*-sf5)>~RydY$~YK-?f6_|#R3RUb=UFjLkHZ&aI)NpokGdH$*>
zCQOp7v>cO{S8Fsm6~jLT;}D)8ATEAdi}F9s&y7&vAk$nLs0ybdnjb@(=5I616$~sG
zbe(fNZMR0`cQ+kvWc~HI%^kUDW19Cnh=H%)R^_nfN^w7hN5
zw?z5QaA-}~%kqNix7Jlh6Yp!SSB2TE-j!f{hUFsZED9!vtjZ~3_s7@^Jc5|$As~5D
zr}0Ty1*-^Vl&@uFZ7rHM2w;0d9$Z(7s7)m|h`(h_-?Ug~JTCdi+8DdIkWi8WlWQ%t
z-w**F^N~tugm|)=`dq!aI}KGuan8H{S)%=T^cgbgB!z1h;8uSodwI5Z-sk*r?CU
zc82Q3M)rG
zft&+lQ_DO460I(of)UU9v;iyr!1=|+jG5x%@Y(vG$)05W4@V!!-Q_};pC-Sz4aa&&
zz>QoKx}KN53j__d$2Nt(Pk>WEiWBlT+pMfCJ#pM0Db4l~BnmkCLhiyXKoAB1v7$oY
zh5cCj$0lo4VEX#?6MW2;|B72s5Cq4bt>;CcU3LfOv>7&Lnrhj}U6S!Mm{-eA|u4!*oi=tzikQVJ=U(M&l
zk#hr0)W1&ThVyA-I76P_B}!aJD(V&Mtgo++69G57Ta~&%My9Y}iX3CR!v;BaXhDbe
zmF7LogOK-sK4_IJ5i+2P_9pBF0Gj0aLQO%@DtfO5<9E~mzwoEyHA3vhPq_E8h95Md
zmCQEI>t203^-$_YAB?2f2_()RJ`%qqLbtry>)Ipp^_{?=*iZXE`Ks3fObM?Vqn^JUzsW{2KIgk%)
zQnzuK=YGnqe^|czL7|7fUGqAAaKwLLe$!u5R4sX>`D-5CXD;jTP2&sPFME6YSAyv6
z?ZIw0bWiV!Rv=4-S$bsBuZ)PxUZooX6=>F++49^oN$AFPe*`6AeCUG=zMpkepK=tX
zVAB7s{gT7e4yys3wc=_4dp5z`gkC#9GegG1TD)|Yik#?Km18sf@l=(y4(iWk51~+^
z#rudhouw}dpO_IM9gkATBj6uR;_<{%q5V9&C(&lJLroaF$6a@(dFxn`#y@W+CDOIa
z%+5>fwcgN=OyE7loorB`wc(qiMaYoV-`z|p{!Mb|)5zwJBD(Rgb;|KEMtCQW$9rC%
zJ)7*n0Gcj2MjeM3{#28*^23sAj%%yuv)h6554AkXPO2F@PqJujE360
zB0^}aSr(fm&}5y2`tS3gG2#4dD9zmpbJQEhEpdjb0Hqbn3F~WHH34j~>-frAi$>A;
z%v=;b2853kn0Q1*fx!d%YQLC(7h~WOZ
z-lbVl+c&%yHJdb&pD?Fl>2ps_kgvazLs(!2SG5XgY2auqoyr>#23NmiIaIy9Ld__q
z*Dc;7to?JjKu1a0_E|0~vyhuXi>A$RDwrr7z2R18dSqR2Z0G2-Nf#>N--UX85U}nXRk0=llax(TXUZLWw+9{wOesv}<`5Z^S@vH9bd3t2e
zc7H!8i9Q>D+l&qrTGIF{8APi1|5+f94OX+q76@+5i{3-A0{0TkHV0w)UyhZ7q>{Zr
z;Vau2iHnW*(%-Vd(Crkh93MJw5#+u)W?!~vha0}gMlB@${3zGj+BzLfbpjo_ZFbr^
zO`9#@D=+U1{|xzKu>{3eMp8enmUgP?z>J(sqG?GZQpqGlskB-*!Ls9_)Fl3OaNQ`s
zKCW7gK_q`tlWMJxLbgVk>w^>GI5e7dsW>MSkMXN3zedp6M%YC*jR+VCttY<~xP~M-Enh
z%NY*xo|$>#JcagEw}8L2bpPQ8&gqjhe%H&E{6h^X(g)kq{1o~RLO}ZQ-aLl1q`^}0
zR&EAKfUq@_roPzr|Crug6@DUX&;)qD!WL{Img?I
z(+?#ts9!nJs_a@+KXThm4rZv5s=VW?amjEsMMJ9-BGS)zBx2E>(W6Pn}y=5CM}hfPB~*GH70dqT~Rob&jg^MJ#)q%@vlfN
z)s*XhjOT|nwtyI(Kkf+l=3C&Pf^aFqRobO4bds-wLF!9hSg$90uymY})ib2k>_)ZM
z`FK>9=qJsn3`>b)(QkWBq5|X0cR7|^W=;|2KPpVHFZ(bu)^72FeWxX+?;m|^asQ_1
zEcK>zRCiLf-0Jn6E1d7UK}yJ4pG-jt4rlf+CYy%0WgDz9hh?tGf;8l57>X=t(&%RwM-@*&r`d&O)P2R>y99zga
zQ!FB~y-Qw6=X>I8{Q?QK<>Y+!`PevEl6_#ZBXYH)yi`7v9mszC~Z3H1fW)Hi4^u8J$n6AZQRM*m(*=f3(VsIvgv<
zq;rA9fe{ES**>fCFE4YD!7LDgY0B+PBQC~K<3+Np#fIc9A`eYMa+t22y$IuGKlQQh
zZ=yJ>a$yikm4o*0k{^+4&}H#mDrA6BW!$%J)U01#;yrw5R{313chDevvzyW07@!0{Gxkr&a=>%v-6?tGF7XU}>Hp5yYKpE;xX12HOvo%_O
z9QiC%%Yt7Ku?Z#(g*Bj1*V@!59WBja$z!xX{DFo722^!eU$23&CXp_G76Avpq@x{~
z*BI`klufja!x?&a`B6UYIUC4YYE`?|Hk6h=>IR1A`S`xQE|>}CCW`4Eeo)HJ
zSEPMZ-&m$xLRj1Rc*11&f!@XCB)7iv_*BuI^3u|bEflD_APzhm17;+-$Ra^4iEjQx
z+BaO(ki<>-OZ-l@5!Wu@ROx?z*M?lyQXN;a4X{F9FzQCav3?2WWjX|!R-F7x`yGUb&y`g0tznCf{d~zr#y8J08Yw!Q=su_tH^}wpDYE
zcB>03F_H+yY`#97^np8ExDJoIRM(D6bi>3muXWi-jg4NWXJ?=4tBcY&z$XcxNt(@v
zeh}y9$4F4RI>sWb%F`j-k6+IUK*QeajM07YK^hgnEX$7cgln3io@c(B?-0jx1HJ3ut-60^|-Cfe%9fF8-
zgLF%G_u0PRIQK6H10SBc_g;IhIj^M?k*2?9_b9juJ9hmY`>@AH}Ql0lLR_k1AQiqkO~r+Gi>b9nPhQSOu$$EiKe
z=M4#yDpKu-$keCDjqtcmnBw`tcPyNI@1;g%fldD0i=S~Xn8dw;)mdzx?n-goAf|DP
zsU{|{g3H=VD|-5H5B1cTSs%yaXS`2x_2cwW4%WCE?V(A;@yBYKML~;*`;G72j@KnU
z34=y#EP~FX88LH|KcyWu;Ji4L=R2~FuZLWknr@7an=LbKPpwX;_*AYip!gt~Z(&Dz
zf|imI_%q#26{>q?MF^*GYuIEdk`e#nIuBzs6%!N7Le*HBYHYw5vy?m3>xf(iH6Nqcj$O>JrWbk(qwJD>*
z=Fjl{jo0Pkp-aO)T%%qT6Y?oq&4#em;l!R-%a)hGj3HKy-eJZ0!-~WATNDiY+$H?Q
zCKYGvH#Z3Eju6_IUTX8GRJAKu@75tR-s*fDs0hUEl3Wu1D4jDM1({HvkU>n)RYFz4
zVBO>W{4N?D^=QK=A0ox}(*+H1;+*qWFIa1xgLu`K`p@R3(OWQjt_}*hN#0?QFXCAV
z0^<=6!}UL2T)uD&xLp*fl)^_&U&gxD=~XXLMtO>zKWSo;`>cxUs*YarXO*%y>N4W+
zU9X%1g9gQY$6fi*e{H0@VXxDufvwR2VuqCA(4P+}zAt7iMze!@)$^EPFmsy^gE7AR
zyu9fjWX5OIEw^g0|k8d8@uYORzF|KQgjY#or!3Fx)rH!?_$}%C#Smk
z*$BK;3k#po??-}geg2sOHjcf0UvK~A85K`kpnZRBov-mf*|)E(7SD=$kzW|sBFM&s
z-&r+ncnC{~NUN@O9MGf7aQ%a71UO!yM4KhaF?D?srzVI38O(kCr~IX3$&)q)(hkE;
z)`prcsnBUMXUVmEF=OC!2YnSdn;ToZG1POK@v6^Ga^m<=!Osda`_5I5FSj6yu3J5C
z`1+eAO}6k1k|Q$1WgW==IzmJ{qNRxddZU#3lq?_0?|eO*!3hjny+~WXSNJU$m|F4O}{tMbe+8+_?60gpQ!4bBil+C
zGtlo4PtK*|`+PmGf4Y4cy#+dVz&<{%>#W?WW1B4NF6l3mI~rI0A!YanF=&UA)
zKak!y?|H3(j-Q321b^;o2F9cSkl0;y}E}S$sa5nxcLQ?t@sZcC{!TDp8+s&ETBV&kU
zXqtPYo%iDs`9-tuCD&qPO)N72f`Giv)NxzYV+_d?DPxlwJ+j#crAhGqc6}YBN|L2I
zY#UBt9w2-Sp6@2E)(6A^O#li4If5PEYfbWh0FNl=0dyfK`F3bdgZV(o{)VK2zb$ny
zeh=hb*>{PBWqb|Ge?YL9BR#H#^g@Zr>JqxKuEbf|l|e$VLw)^(j2as{=t=k|iZ$1Z
z&5z{$oU>taYRl2EgORCw^}L6P4Jpe`I39{2bp4XR)`ElR$-DQ<_!%qu4Ah-zMZ!H{
zn8ag#;X&FXf_@tTf`of74;_!+jbr&$ODtebY36;Q)f8au%zNq9<_%YF7pM)Uyxove
z+urrf(d6_{D6}*PBh0-V>(a4sKCXW6okc=5(}o*xQ?MknNiYg!l+2}oLRl6jaT)dU
z)fMU*@;tMt{b<)>pDWDjZE5C}^}ce!oDvTaVVTaF$MaTmAP1v`snO;!v%*XEciAHf
zUVA{J$+@qBvjU^;&v7|)`=XXkR{J~U5RyQ9&L44DpX~LRMP}hU%FAzwqR{HhBJau{
z&3QOsqYejV4hn<%d#OC97bVv`25%(heGxRj(xfjb;?_DD0T#eV-0@a5|
zt8*97m5Xj8Z{Aq1MK=}5i%uqQSiOzhtU`!XMM9?-TslNHXrI*!dX_j%eGKL3=;_z8
z+V|2Mzw79IzaO+6BCH6j)o!Ktv6;&Jpi=m7Lwls}$>nklbKV8e6@)*7m}I4foIs6b
zk8Z(Sxs8-(!RD1FG|n^VZMG2^*8}bT(B;nFxHc7;OvL^z2IpdX@NRLb8X4j)$lSK-
zRB2U~{n$FPKi^mlsR4J{j>jrE+EFHaVhlDh;x5yxc6;7gsDb@Kb@%pJc*GK`rN_4W
z)~kWY8Rt0tt8F$3M}Bx*7DA&sIyPi;wO-;!sKwqURdQ-1+LOPYZjuw&Oo*E7EG)T$
zJgiUW3%>$4>W4DhJktcFKRJKccWvL}n@0@@5H6>abonB9
zh5;UC-&t#kGi7*#K^L861nAlk{p7tDHB|qC95T9MAGfHln=_)PjcNhk!}aS&>ID3l
z!uao!X1rY{Rk!%!`}?){d9cV88s(+$-uz=Xd0tyu11Oeu`-OTG0cp$8Y(FrkewN2N6WNn8N<^M9zw8(5&e|SW0(W$3JE+{YHV3IQ*s4
zG7)^O0Nw+=FB}oL1(s!h#`I11J__;yP{mQ&ZEwfB)9V8Ul~nWx(jkeqeTgUrO5*%7fYZK-fG(l1HbI^h5S<
z+ez;SL8lO;bI~pqz5^(;+HR`v^TS7YuPLef@~FEMkE?xPTLCZ?TE<1X6uq*g7=at$
zRta|_Kbt5B;IT#xpFey>ys85QVnfUp1_lBpW%qmU)h?Pk$#=xC8&gmmZzGBJi30rI
z`x*C}q~Tt6$PKTREAattUQ7~LLN&_Cyv2X&_x0@WMkeUVgh%*(q)
z20A1Vnc~TsvGW&o=d^XtSbOINx8L!cRDj^Ds=3WEw4^(f+t(OWSEpy(eW(y=^G_a<
zxHE`>IeJIf3mJ(%HROTUy(QBM;-s}eI(Ka+a^KhU+=`k(pz8FDd>1uvVqv^Rm~fy(
z@Z+Ymvoxq(B@)Zfi=G8x&o82sx@oIdz+7RB7$emQO0)8q#2l@%(p915u|dC=+VId+
zfnk#w5u-*@pxP|E2f#jVp{Jr#2bG%PG3a8vMd4FwKJu*#DG?6sQZe(3+
zFKKK*J^IwN!=8NeTY;)~YtgRUfjPjd$+X|t7~-Q=C?CT1uGSj=vp?EV7Qn=BdacuB
zbTrpk81Cg!z+7ni%gIM
z;)@Pg^VWYE(iGn=Ah`!%Igd*jny}yMntFI);%NF88>rqTOUHBc*mtGCCfPWz!^X+U
znJWE9bB?k>!+c&`X#rK)SC@C++ZR^0xJwQF#Er0=OMko~yZo~LCS^C`5M78LojgB0
z5t!<-K2ms)j(q?NCc2%{&iQ8vj`49LILPsHRjExXV(pC{oxI+RhrJB}DZyVU#7^?-
zo_1~LlImgW8NGI{q3oea9sp4D_wpW>1Nd8s(5=yZXN8y0s}LmB@TOQDLtT?4S=wI?
z^-DMtwY*m-@uPs_=cNx$Fjls3OmGJaz4eM2*S|N=nY`GZ|5V*HVSV0e?+G
zgy%qLcJsKFa_akPrT=`e5kivfzV26Z_QuO~RGa7l@AJ#*YuBv+z%pe^Q|B>>>AC3Q
z#s%ecp7pM@yZLS=Q+H&}&kH`~o<+M7@BG=ckaL(>MkmHNm%9uc{#O^0b#&u44J
zs1%OoUw#sHSA7IVRnT%@&I5I4oOI@S9%|Tc*qjG7z^q93wG+5EVeQTMCDP_|l$Di1*KoM6jDzF_PG=HLa262Yo=aEB~iu=4w^f)!_(cC$%n8C
z3qPa=HW@}7uSdRBGIC8_kHQ=Lz~;EP*PKqSnEHyclm2<0+yBL6)7!&sb1lq8(zY>;
z^;m==p<%WXi#G#VsdIlpM&Wy#!w_zT;!D9?5@JlIrogaRUSLFpr{+vjQh!AEvn@I)
zvLd#fB|6AA
zHr{r40+7_#0pF*AD$@jd*9j8ZRjo=K^=zdM$fvzod>$u1B<7ZHeeHZOJ5T)TdA_gr
z;~5JH*>~awc$b3tdmpoIztaF)&ov6s;_|Y%qpUycp}Rbm&)Q>nvsG2+Tvg{yea`(`
z7RvB^C)|Hm&h67~#zKJ42JXA`1bMMU)Pf_9z4N`GYJOK5q(roeieX&GOub=cbg{LV
zBHA7cg*k-kxC#>N{ncK`GnTDOifmyazMVkKkKDVNPQ;gg2GSRDye|^cB6xgm{$={1
zGIL`^-80K%Z^yXYO
zS~S96N?H^f#ickg>u)!Iqk~?t(M)NM_-0;Vz}w=#lfI`jXSs3LE_FdYg6hC)z+JZAWikIpl
zr#as+ASe5>@w@&jleV2mgZo5&xuM5TYo0fg889D!8$k9noN;{d%g1x*Nj!DZ
zv|$EQ|I{ZmAvF{0vFR_0K6)?#Gp)Hlx*?;W1;dz?NtiK96lc5;j8vZhK?pR_Hpu})
zR!zgFXM{E^dMh<;Y42+?Z=d&D)C;2);Yo_XI2yWzVs;*w$`Oz2{xL4OKH_{1wP-3d
zs>Tm#Fm2+>ino7S!H-H1MPq^W+F5e@3*Jf0JA`Eoz`3k3Lh~?I11j%*kD608R<3<<
zQE@S_U4XCUuU~I&aNmo$#_)o;CU7&`+sD?*s~be!knL$oXvv6r8hv4*pgQ80l(A44
zt0*lk1xs;xZ{5G<=9wsOpKTusPy-Ax!BnQoj=FjndTj>
zb^8LsmVzohU~u7!C|iN}YICgp4^^eUHezo3Zw&lGLfthrXcEeeT2#qo6*-b$l$b=r
zh-)B}%HT!gF?MWpLX#FNrlMpEdjr2RFfhQO5Gv^lV3Behs*YCJmCw?>9k5{xmAc+ihr%4fk^_TB6A
z_LHql30s_BDxXnV9Unc9-ve3;un}a8{#{&Le0cE0lCZA~X6F8lj-2#uKUeo`^b4_I
z)%M~dekKK3xLP58`J_nlHj`_WV~-A&F4a@ZEw&vkU|%GBz=1hTP!#k4&+4DQ+7J@H
z=%~65m(jYOCd|8YVm*w;r_5HT4QSFz*0jLW`R)p|@f4xE^$K
zYI1`VJH`6WF;nak%Z9P2#Ew9b0_On@1cx{R5$eBxN|6wfV0#sg)n4gi#l5ci
znH?G9zZ?M`oGr{jH4n_tOU~YBQib~@QMC7jNpNz+)0bk}XG$_TA%w>_j(#;=7~#hZ
zfv^=2LPAiNx3Z8;W5!-L`&3$Xn2k-MEfrAL*df`K@TVV
z=Ce|`E_~n8v=fn`A<|bl!GVnVn-|E}Af&AZ6GxF=hLZv}aZl^-dg1wkdSMSb9%?bk
z2mK%7DIuxd-rGG{=tU&(_)-Wi2SbNZekEMm?V&~bEk66B$eH6xz1xHCq$EEGs%Qk^
z$UTm=)y*D~&Th)J*D30j)Mg;VCw+b`@nWIgnWNWx#*(+Xw=Y_(?%R=lx0**EtG1rU
znHZk5-I^EzEFv&OPo+Do9xE=*d$TL6d)5&7$n`WqQ0A}eSwIp7CyY`~l!wjM%rj~g
zxl6l^UgRDgyR_J@hA8WiSa|3lxzQ&qS=}u`^Ym}_Dxl75GzY{MouT3KOa)nuRbv?{
zkh*4Ee@lH#|9>xlOur{-LIZA)+(xBYI#+e=Q*_|gh7vYZBT6IuDru{@8h=I)1Wlo(
z#R~zftT~eTM`{&(PV9Wk4SX%)3x!yT!w{BSs^vy=?Kx4QtDF95TCdK)HLcw5S7RD>
z?rm<%acHglW%(1Zll)d6G)LXKFSB-bcJf9QvT=!@Qn%idrG$7=I1P9YenB7m`5;n?
zsK+Xmg18LOZgi!Q`Fjo1io5jQI}eA`>=Mq*c66KEFWWSN4gkKa|1_kTzOY4d+v3`;
zd+3Uu{Sn(vCjRMVSTC7U#@NvB1zAZ{*r1Hx2}>eL7S_o8?K_NFHU4qhIw`s&+25b9
zt6wjGAO~Bg3Bv?k5Pj!Igo==Xc6`cZ2MI71;>F&)Bq_c9aHT(~SABaJ~dVhM9D8K`z*dd;eLi|3G)%%B=kvX^w@#DiA36H)a
zc`Um`^8tsimkL~k7M`mzG-(TbOx<6-y`SSXyFJa#_h!dEqSJJ}MmYfBW!!zHVB~0e
zUKe+OHJQlz&%Z+k50A$jo|(Nm?%!Rx!l|<}migD{CA+m|yS3%pZpFK&b!^R}h5BOZ
zyT|UAP3DoKeMK*P#*%d;_(|X7FMH=dy6++Y58!oe2oY*pxiR1e{}XzQdrMkc=iq%Z
zq%35z{?k;-k(|Egsn;qrY4OY3A+7Cp&++!PmBVX2kMn*tINOt@W{~~+Pj0yPyY2RM
zc5c9th#StoEd(eJz3PIjV*WEf(;K_BCsSZKJ79*e+!^B&>nBj>29ga}KEVqE&p;eb
z@w`ZwK!!|`BDRz#0iXCVaCWAUC{MO8lYz{cb2$Zg#DKz`(zQ(m5I)sD%UdHy|JId_87AqWj^#t<@OYWdu{EV~n*@&A
zf5*X*qw1FnW`MFO2!I3Rb^X`2dC>S++1dg~+M*FWtxMYQb%9`hkF<8Tx5&t3()$ri
zZU2rQ1Fr3Vs$~mB+wddkFx+75WPI3CJZ(S%+{sC`QK!@i?&`$(Yev!j)MkEKzt9~d
zLcfsj7J;_5Hm=|{nNAf~$IEqjdAZw)i)MP!9=rgQel7vEpbBj0=Y(u~wKFfTMb#Wx
zf#!j8HU4Q##5Xk|x>xzQX$!L?uYi~8W!}C5(sUQM
zBjCJAF?d*YE-nh5=>Yjj{7ZOsGMyyN#yOV;o7UMZrpo$C~pe
ze6>`kGRe7nSMw0CSp9?x)cX^(aXfTTmc}6|Da+L1p4_~tNGS&+D>Nr+$5DaS8+i@q
z_@$hdj9#3oUu5TJ$6N!SUFOpqp9rGVPTtoRz`AO#{o7^ND`cyIg|aF7n?dz2c}NM1
zGFZAXcuvuFq!m!SJ53MM%I*ET*@cR^RR)fJ8;_DU2j~h
zm+`=PB)YM1kuFN87baII=I4K7WdvQG+RNi9iyIx1skd1t>#nUh7OTZel+nz$YImA>
zeWMux2ff;y*mJ1dlHQbE1P^GQ&d#y@H{R1Zs}3Ojb`S~)PrfhK<KJ%Wl~~l6
z=D6vMqOGqV
zLJmhy0zbWP3#H7RZJ>IVR|Kn|`y{z43v|g&J+t%@5X|)s^mKIo@3OE!co6culn0lB
z0svZ*XJ`$68IuEHjzF=iP=h4mn|gpw!2JjQmeJd#
zVtT4XP@6#uDgv3~9UI$Hx9@A7SO~lA25{rn5qRdh_ae|txM0Yb0QCycMh*_>uLy-#
z`$ABwtEwE&xi~pdi21oKVf*_cq}k)BQrbU0-*9qq&Ck#0slqVM9$o{;(f+>0%+DcI
zAS$7vg08J(fuE&0WN_ZGtJjw=uteaH|DK6SvUeOH6h}EVfyt3}iZRB4(909v<;}G@
z<1*Do0v2BuyBpqh-uJM~ZpH+&&aA*h-UYdNe*suHduaI;I&L@o?$*{`<-cv?{#^3#EGbI^M;g?fB
z=*+b%w&SCtAkw}S&1dWC>S|0oXM6Mwg5ioplKR-?%hyF@GgR?9H7R*-oNHD
zuN#6&LOuLF+AXd=0YY6|hO#lFDUCPJa}#Pc`KLA(qBTBRY=s9>KI6}o9)nvw0DrF^
z=h-D}zcUi_Se(v&L*7_dH+AfaO3WX+#{g6;0C4xQJ3KtJva;$ixj-g999#(Y*TR{j
zGr9XPiMjVY@e?xn_)|8;NI3VAPrulfXc61d$3rvkclwFkB=+N8JFwrn#uo$DB6bp0
zKb~jvpE$&1RWB!Y5PfAxmKnB1tT-_CC^Zr
zS$1n(9aMTu>PqL=uFYN*>4SnE0^q0mZe@*QGi1RL&?2FnoZf8E^W%RGBogI;)lCp
z2hOLEr-1niI3D7NO~cQjF+s+(6%{s~3CB|9E|fZ4n0NDA>w-JC)qDimVIAyRlT28v
zBo)$>$BiRzkg7;_9FxDu)2PDJ9QFDmM`d|yo*caQT;KXKEONfB&pA1z}!*)
zpd43<`RW-ul0nZmYu6dHSE^{<(VzE6v=`C
zTZ8cAZa~O$x=kBi^8BH`v9YngUjh@&pHj*&UW>eJLR2hG-hW5Mse15NU577mbY=Hz
zdpF?ZdR~`;KFgA5AidMX#TW!lF5Rx`anF&)~a`py?j!AVD3*is^XP8~>H&|bSp-r4!`6&S>F
z%OJITSMblH+uy!KEJD1nyf<>#7x(8f3x17=L3-!BksJ
z+Nnexl!_BD=-~4K>?kNrIrWZ7h7vHiWCcXj@r;~}jkkQC?{ma@^*}b$ZB?cc8_Nz%
zBLKA;5U9Z#9sJeOFb94KcGx6_mA*T#ujUkBrVXZj){o@KoSUynhP*?
z1@K!;OiZk;-yYU&m?CMYQQPM8X)DSBq!^gU!{zkmmM5Q~ZhgDI_t<`Y8~~G~fZmhpb-%RM
zRa*-w+t}3PdUs|>yP8|w`GA=-aSbSe!OBpQP~Vwa&-zQ=$cl0#<)6*XCDX4STtBR@
z8;~{s@}&qNAV&oly!j$yjI@l5zJoua`lW}^TYaMySSZaL7;apt>QUYt}npH=Ve+95D<3l
z|CsmffE|Q#KBU}=*3?M*Lybivt(Q|`ziCQ+IAO21h+nJoc}bMJo2GCrWP^1e#8TDN
zvAH$G%JKWt9+hMKEjTfPS_`DJz^n?~EC!BClrjZsnt!8j0Nw8yKd{8%r#^D@YQK2+isVN-pZy%&1V^=TB
zWF$gwdBIq14X-(SxOf3k{pa|YFQ-7t^EMqml6F9CC1bwyBoSr24;|H1G;tC`#z#s*
zj49o}1lCz`L!vK>;N?$B(&0M5FATw#0!oCKV&9WZ8~Sf02$ByC2tg!&kzo5aKxIqJ|L*Mq3W?xbDokey
zc4Stw1&AiUP#Iq-b6YeBHV4S_b*iFO>9z~RkW%yBGia?o>8DKa>;H7<;mRHmz6+^*
zKw!(r$QZ7BtH&r$B&E+)c%KR@05#eV{Y?+KlFSdG&u_{l(LX*wkQ`(RYs49Zmo03Jy`sSiw!*9g^NBPn-$9Ohqmo
zx2HD7dkpn84X3*#-YlFNh&)&hBL(vNC14K8rxlfz;7?0U
zJyTm`cTm!$n3u()InktcL);9??o0|SKd?^_mqZYMh7iRD1PuvZ}0eSRPr)il2D7cLfmcEx`%wiO9*x)gbTYiOTmR+hcF`RLpMiDgPD^wrh1w)Vi^P6hd71
z*=vgQs%1}755ZgTB!EbTUFvLD|3DcStb$hbhKgqs;TDtj)0?wM0?(
zjly#MjE$_awX+63{FNHmiDw@YVmcvNp4(-oEpAR_&PE1L9>Vggqaw?F9oMG
z<7l2YDTKm;0W&o5DIAy!`qCp5wWO`-}4c>f2dnj~}O#9aVrGDY91O_clrajbqG%}_2;NSr+S!#b4!5=ZP
z)w9)z3?Wp3J!ox+JUM5rutv*1&p57&sHb;f%^DA6d|*OA1M-MCqxPS_<96pTcn+(~
z;j{d!xv_XC<@-z~etSHl+W4lM{Yfp1MAqV;6P0H33f^z4BZ}~T%@0uKu~wt(y?K~w
zCe%LYHE=JE@i}q$!e2R+ZxCPB&}Sjt#e_k|jZ6nM
z`1WRFGW*Tr$BWi&5LZ1h&n*v_%)6EK+H52c`GcB8?{0g9?-6aJB6tR&@>Z;-FJ=^3
z{coL)CGuD?U1tIkXh~f4;0ojt5j-8kI$R8xD~?KOKTOI8)?~rTV%eEBiVy{B)I(@=
zzTt6PN$IuYVIEWKw@Hi%JS!k5el3gU)UkQG`5vW}ptwnHW!`H@-SGP&MZ8IpO!=tp
z9lcs$%h5CZ8ctUogweT@3umB!#2{KMBA?1PWCeQiU*dXIMkAyv*zkfTy13spAp{Q-_t4SYdEE(Gq
zd5*9|4N)TVH-NyJmq!*ze7^;pEGxG9SBb^;mUceV89k%aGAdenMY(T_E?WjHIE$LQ
zk8L{j?AmmI^+kzEo<)&BES}iS|BWK>2)z-^N(^KEIN1&j1ff=+QCck0#6rAS$r1f%{Ro9HwNA6SV2kD!arS5xz?*XF00CZ7V
zPyC?7mXVg`XIrph3&faJ&%?@E@$&F|b0?>Iy=v8S9G++W?T+c}mxkgjFbt#GYhn1m
zW&vC}>UE6gn8;}Cm(Sp&bW*8TEu|c&Yi#tM@o#mO7n9o=!@PbDHFMZ%$&%H!x4He#nY;-~Fy1|D{Kf4d%jtx=&9WS;2G3=I5=Z-dEO4
zSwlRfQnk7$Z8lzjy&ruA(+Fg&Vyo?&zpn7q{qKg!F4Ciy%0j=lVd
zo71(m_N{28a~vBl+?#BB60i8(`0CZ??Az1@{g;0If0p#_8@X;1)7OV0fRHO>5V`~W
zRqm~S17Jsw(!mD{4Ts|VcUOcVR~y8Yq9lz?Otzslbqq~?FI&fd&^X%L+yCPE1IdLc
zvnqKZT6aqHqauM4VI9vEq0He7MZ_kV5QS52zp2$q0^nkFKC$4kT+S9}8ks7352wBIBP$0zMNlaQ4X9K)W_r2ZgFT-`jH@JF{ySk@e&5EZzcFOg>
zj7?Fww(?W73hp89{aOL07j3&v>=2_$4FX)f16-KDFIS2$CKeX^0h&6j+}xqo?pz(4
z*k8RyCZ+lizYWXEL1H=fEknFWA`PAIK}nF0if0VHp(CTU{sFZ*Y5aG@MxJrbb+M5v
z*k?4~{T8h{@UCalGZ2C`JY2yozh7{a2)H;Q{#sVuSYp;Hf20I3)i8WIN3{&gGlEWC$(F7ox>!w07lgNAT;7^_*F4fhhEK~
zHB<8Lvp0Vo*jBObS`qZtkI{d>vL=HAA0HnQ+Vjz_;K1(DOdn^uHa{lidFX^JEqT;hKqa*|%_bvR%M5{AOozI4_18=%;agI5_G
zJ}*MseU_%xQZd=E%T`bpWB`D*^%MIaKce1v!TB&dHOty?i5fl%JK^<
zBPlXvWo?FrNIi4*iwOteL<}@UE*f&$@pnf&j4Fo!jsTT2%ej%m~
z7-?Hn{C4p`fqK{}=`GbLSGFpo!McK+Ffr%D#KZ&w)3s+-2NR)Nuns7|l^9E$ZD`+9y*2a%w^@z0J;9$CqT#UE)L3NJnfAY{)#Ah)%XlL}yz$eH
z$|N5+XVljE85#^hIHE+#(iQTgiF-!seCz^Z+rMFXYJ0x|Bc-WQ=3|XjOM>n25=zwR
zu}|Prd8zP~2GM-4-*aNgMvMd>P>8%mAgB)BfTCusYc8JZz5O~
zYo38t)B-~#QwIvrKLHMeAU0&50%}z4QZ=Bn=i08BGK%}`y@pJN52rSnl$>D9L~dvGQ4!ZpUN*Vp(+dsYM^(@!VBa*55w_!CrXk`1qIgq4v6hUlL4apz#t{-NV%bRYgbpaRqC%gvl-JG!8UIhG?ShHmHu=a13qgq
zdJHt$z*~wVvh+_ms-!R%y}tG2=dy-GsNPo$!aigP4b#6hVc0)j%=~oVkWXbr(+l
z0vaBIU+?S>jPNU}s(v|u%pao0I}Tt8+D6vwp}u$%-zJ*({i4eO4JL-l1i2DbSPMOi
zk#b!FW>8trpjm-AP(J1vxzz1<%z5=dqV_kwC;ChuMxXJA!EuglJEsa<;^);EpS9pe
z;xPFIE59H@j_w@>yWuM%oc2iDpr28s8zS%-;oJD9la`!?^Dp-4hQsvy*E13pt4UbGoNZ*#(t1j{P*FM3}fL+g~BG856nmGx>`@
zemM=MVNSHrvO@K!TEnR!Q4?B(zfPX?T70h)N$I;Lh?Nc!EW6UXUj;0@O-e2sHh9{5
z&5WO4+=N&GJa4nxx{FM)MpIHBAq)h`W=G87N
zBbW?-O>st3LeN0^J4Up6PEl;CDniq_M$5E~P3KCi85XF>zAKbM2__Z#VKY-9#9^*w
zEC523Q}&|{8<6hw{97!Qv666cIX2{gD7$i~Z)d6r2F+VT5_xa;k&M+<2(p0dtf5$F
zWu)u;x_bW5rNev5qBw1V#CK0j0QVPO9!egDSKZy8&R6eK&=Gj(d0Yd7-zCe`-P1s+
z7m1giahY@ecJ8&0t1FJ!5uCSmW*LWvb}poZZdlp826j?nqN9^_K55Y#|2DnUw}Y!)
zPi=uJYc>9T5#Ia>BTI!SXl-84NdYiaxUVhKi>h0X>Oj=9WZHrqA6M{k;Zto~TwER_
z8{5w*P_nmhu;hHEeCUw=R4SiX%8N85Q-?Nd_LS3m6#z$pD|aby>f`p`7rX1Q
zsy(<}x6B00n@ud0^~t--b0$76hk_30l5Pe+`@XyS=Ps#CO#bHs77=)sOw7#2PyhZt
zZFt+|B|UOz76-z$$M(P(my1U~JI&|xB0%jN{t$@K&qCUsYyCOP2iTu7#=WZ+tUod`
zr7w7`KI*Y~ZDM9aoK3TQr`&&veg1Itoj9@Llx}sC+m;<481}&a1}+1wy>Y32)J)Q~
zs}SFJJjDChioR`Wo#)7Qpf|a&OgIQ-!l)F~^?WfrdPLH776f#FPL$D7i#cQ!E!M6&c9ZkYc!tQaa+_1xu4puFGG?C2dKb~$MUZl42-a8~(`AA$cf
z`>{kSZNVw~+4`YX#c0mMrMmjes!Q>j|^*HsT7rdKQ-JM+%#
zxn-qgfvE)P;#k6<&!Q8^9qoJTG0s-+)_Iv#5gWc5n6PunPND|AVfD!VC;2k1$6ewK)QX9me9=O2fr>m>JQq($)^1j@F
zD#=KKTn>j{c|G)kU;npiFfxv4(kfTS5Ha(+rY+?{T4uKzey7q`M*|rBFJS6Nvj3+B
zsk$G}d$8eL!uuOw0N&2f0+U*8TG~-R1@yWHxHoP+JHc)O9C%3ez0N%SOJK
z6}J@H|3)cK%TJ-&UO6sQb}8~glR7^@Mg2>B@8${@Kg-xfJn0RAhLR{@Q>oZ&H<_&E
zBlk?>0)@xA&(%duh`^E1YZy6Od8$G>5x5OhO4)gM24Q_a)$pBqoqAa{E>27+0Yyjw
zGxGh*jqj@++hZa4u5DTQW^d&Kzc*Y*d&)nc|WLY}nXrBUMk_8Sz@(_QP
z;frjrN{&ts<_7rcH|prSQ3p+RkK!|@x~*hF1r-b4U_iHR-?3RMM)>Wod9>(h;!L_wcdR0{QwHzD
zoH6NpMFI+RXV7HLhxLHxXJJ!z@TfcwLny9<=%LXIXdBjAgNeLuh01`-jKdO5{Fp3c
zlv2)^U>~PvMU_HF8BYGk3ks9WHuNVs3nn%`qR@B!i01Fqnd;Qye6El;Jd1z!8N~?C
zYv^Dw`c-4D5mV+b%s#stNGyf#Qw$VoDe+6!@DJHdtEp}GmmF?Ex)Qo$WC)k4D38Ul
z#D?#SrMp$^(qIJy%Z>h^l{E2?&6duL6n*zmqO=sPTsj@LxtlVFH*xeJ73q8?fR!kQ
z^W@ka$NpNYp&IR}!NEv`TS`~m?hyN%%UfR4VKM7&NkqAp_*Hrbjt-)28s4|4F(W}7
zY;4$6hX)=C9+%ggtm0;gb>@GtMIgU#gly6)kF*W%sTE_{`wuM%
zmz0n)X?3yow=~eV@$CFa=H9$i7?}0zyix-Ry^Y_OJ5=x-2HTkqnE&D_f9xZ~G=o~X
z%vC8`@WGs3?pQri7~zW%|o~ptTx^DPgk*DG-n5^Q*lwz1Q;*O+^XbN%0`)APr<6(hzn+1
zPJ^+bz%Kvq0!O1eKapHCe_sb3&cp-3rkclU?!8SQjgNGDU-8KFhW}g>&2Qi~2
z>YT41(<^?GD88&*;=#gfEe@RTk;luePJn1qCFJg(o2Vv*?#QTU*9ziZfOl#3`Ayy}
zaPF9Szdo+{f^&v#To3aIRJ|#mv+Owx*6{G~NDTaMa6W1YnPLO&Lono1qF3L;L@3@U
zI(&+VW&3MrSY|~r#8$NUy&PnY{hC;n<9wCwSqQ9
zP)V>{xW^9QkWi>%@#WtI3-7-xP4BnH&c`5wGbkTv&*j3CGRfb^X#CnR<(_%X?C~b83$G
zF?kp6!^S6Rzx(eRF$ySL6Gk5kb0N*_dWZEKRghL
z>)Ly*b&fe^VX@deDk#fP0K}w@>lMY9~WDk_5h#uZ4rctKk)OT
zbaA(8aX{lC6U6k6wR}iB-c!unWjUT{_nd^mqH2MruMH9B=a0Z$e-Mu~B~8{+urT)c
z#!RzDHgf>syr@ezF~m7ljr@^Mwb$|Aw}C7ulc0b3G)Qa*1jzt302inT4_O1$@5|=j
zzr2oqtSl^myrQBfUj=mppg6;`15J$WlSs2jdD3~>9Q7J?D4Cf#xcd~Xj&@?>%(f>t
zwFF5nn_lF6j@`IAQKIr8xWQEL95xHA`hE7wGT&;KA}vk{{ts||1|*ZSMVU(nrMaEW
z%?RxfsVGNmJQo&JYd|cPIJ}(KpbtrxEz6Hr+`;&yx;}mh#b>v@s>km>84{1fdab#~Bzke2
z4n<&ta4gnNNaNElVq)2{AjF|A0h|yU$8j=a?jBgd?XUFFGjOw1a%h4P;?0Qb(`*WV
zBVs7A4MMO~V}2$wn{F0M`7#%6^Ja@f5qmPNS7|iY-oYIAwb+kZ`C*H_Olj=&`4Z@s
z68*AL_0
zsi;QCNeq|=3H2&{)mZiR&arFM8o%KT25~m7&qo9oBgU(H{c6(2K+pc+Q_PPCVI6)+
zwtj$jRKbWjTabv<^Hm@;H%#qz{XOR1FP<9Rm;vudYg{{4-dTGQ=c@J-0Q0XuPv^gN6KG=nR<_Vcd0}e8-#+yT**~wH|NV6a
z=#%$6WsGmoA(}6*Z~gzWVR=X+1kmcaF_3>}cC8Le6HLL6H3}{
zZ<6@?9rS8`)rInzn~xuJ_&xtJha)GVB@vZ6PI|Nqj3rZN+E#Ntw6c_CZPv>u0hN&8
zz;|Yhm81R)l*R*cn+((%;$?Ox?s5P&3YK3JH`SA#C9hDmR=t0l8HdM%!q)c7wP#1Y
zq}1fQwoPbqw)z}XZgB;YnnT9m&NR-La2fKcVTNApz2h|5PK{5f&Xmps#k?N&_Ol`nAIrPYdqwV3y(D38ON3aRHD;z-wBp+xD&31`DPz<h2vw4S-yGsCG+VTJt`2
zD$Vu%+wj?f7-NQuhD7(pzU84L6RdE**eE>b%F|ci?YJf#A5|_UxAcXLv0^XVk+|Tv
zJ%F4+MpA&B>>`}Pl(DH|HuU5cy&ccMY9W2=;V2X6GOBK0hx%{#A&d=kjr{YCuNpSw
zTlV5^9l_apQCh8JZYV{Oi%<6U7%$d-5BPrUA3i)Rh6$~VuR1*JfFrl9e*n=5X{wMscVfLniC&|FvyINC%KkWB{RE$R$nWT*bZt|6yL|XSQp?+}yG{JerKCP&jrJax
zBHgOa<2%1xF(?M#X$gE%es?xOZvqebL5r!lYCB2_088-q*`i0e!%x!Dj@Drv;`10<4eL%j}}76Tm1l|nnCwf
zW=sYn3_vO<@oWTxWfd~sRVuWs%fXve6ciNxGdDjsaAxp*)_4(KPv0NG6kEnT03n@i
zs`B$^^92Gz_6T^<_m&P;BjdD#Lx_nw1_8zi#-Q`BP*7A`clVN?Y85j9cLoRY23OXd
z%AMv9v^lmxDaOQ2jpmk)%+sL^(FS;GKFoljo#D%6<_kcvcyb7dGqba^v$C>40kzBP
zi(?DQn+v%~p1$#FP&)-kzvG+Amv!{fP{
zVKiJmY@T*P79^uu_zqSGT~QWg8NE|M&9(FSB4T8KyEO(jHa;WG=yLMs*pyV#qmQ2=
zcVgkj`kW|Bv~x}lxXpahU}f`i`Ow6t<`Rg1$cO!;cQO~uZA4vE
zjWqTL!|w`{e-+_3altr7oz<-
z9{xYHV_szLUYHAatPOe|F}cu
zb+coPmLW&ulP>D%!#vtQm)#VXDoFz4nlxMWTGd*UktjDTJ1*RR9%k4pjSPFVo!JyL
zongc?wIp4lF`x#IzA+$EHx}{VvZv(}#~r8wAa}5pumrk?PsP(v)9P%n;}S*lGPE
zgSM@gRd_zWgh7<67Zp&(qQsDAgk_s)0@5SjSi_~B^RlMe_2k`vq>DnL9|05I%)}&!
z%KY0nXaL#XE;1Jt4d7wIPB`spX>!KlRYQ}MrdBkbwhYKuCXMnzA%;1pz}Bvu?-iV}
zE1W%GbJqvL^QTvE-y$Ph(21)(`fYudLs*v69?9db$Yry=T`=_%_zq_!T>&n5q~yk3
zV7mE)Uyd+W{qq5rK@9iuHht>>viSON3t^geM`ei2ibu|lSa}~WVXug#&F!2h)AX3IC}+0
ztEym#7T@aRydt{EZs?JdIgPV}b)3B%1!_P+@gG|Y#n&P$<)nl}tOBdf}r2TU|FQc3ZNdX%6X77
z7Tf%Z3jymN7>$-%MB};so+z4AA^t|KjY1Wpv9Mb!GFVGVb$oMGr9Ip8u)H+Kv*LLv
zH+^YvFqBc$7~6W{4aj#SvPbn@hD-5puJ;6G9E7=oG4Q_{XiG~3%g`Xg{$jc}4%H=J
zl_Co{UD64_jt;Y>tY*K1+{s+RO?~X@g0@Lnv@6W<4L+T6z$&$H>(Fn<4M$u-I^mVX
zN!*KJTWc(4mXUaVd!JE&paPV&VxG}m8HS>OEIj7Pv>trRU`!2uR@s3nuE0Xs(9qD*
zLMVZm01fo;0Ig-(uAEn*3Q+GCvn*CV(1t$&*!jN&E?=p7%kvi7?Ordh;alONkH9Glh
z$Wae65HVjR7(=wN;jw1MVL6rErL!FsmHx^TF#GhfyW?BMh!YYCVBWX5iF!D%Zbe@w
z`x5La_&6CorF)t8wzZWr@0xoxBRH
z@|ZIiD(q`~>X0U9EID_wslvE_pgE+@xeD*f;S&myU{EEJhSO=z9QG5w++opTwnns5
zYbd9;FV-lC-|48Kl2I2M&aVxnRB-1QLa#+F_AX&!31)xyBrB1O7RE`!)l*!ys8UMk
zh@)cgPEkhc5T&5Qr>;F%<-mg|yuyX4qn=jJ^v@1w&EYB>L^B_=@#kd{>=Y@~GqDh=
zTiggt8l*1|Tviws@gJtyBH`KkHD8FM)VZCqXlz3``-?J``dQv)ks=!542Rc00ctU}
zx7eHyhvyUKea#J|mEzFykp0rq7b1kQ_Iyv}Djcp+WE>txY_8B=3))Q;^a=rKwET>Z
zC2|Uo1*bn)%UO|gj!q;W-q_)7yuWax-OFn-%o&l^rbF5f>cz51!YeO#j&Kfa#Vm54
zOETU3L=edI5uqu${`^#dOsKr?O4Ee63?VgSOX_FBScY2jTe3KJCadR>R4CPEH
z*Kq~p=0AkRA;%+pivWp3V2Z&{xR!@;l>!%>k{azZ$3g8sQMh=3#T(@dST0w!DLXzl
z^Vq$uHOzo!c5;+sOuvTVhUC|9$KaQpfJd82=7|v)AlAg~Vle(S5U?3-B>briCzMA0
zfH;5ycmAz0;uZyaVZj~hk4rcr?5~k!
zZ75NMUz>SAnF8wenzq~DfVbbv_Ula7f4+zXYt=Q+qvBMc8Sy?gS<&Q5eY$n)>@$CT
zQp@E9RTz`*>(D=sb31Q;WZHE;5O%#Bnct>^KLMt<8})jQ4tOhfA8-j^r5i8`O6p$I
zh{nk?Qs%j5W@P-$MrLKJC+@ri&qdy8OYxW%joxCWZyoNH_)*>{ad4y@{GSBSl<)L=
z{GY8!u`_D=g(3@JR}O
zgwa)Z{vKa__-c{1gq-vG1V+TZ1!Q*4oDG5dt=B%@aCt@w&Kn;Ku*Q)^ER}593<{JV^7?dyKjJAT0wcbHn?mJ)nm8@cx~uBRj!0&bste2;=ItxZHrIDt91T
z_Z9nuMd7bCBo>ub=!#l;2Tjp1iorH;tjAn`*LCIthKi>*o^b`r&xp~nL^kWozdCMz
zfCI01GxObuwVz+1>|@xF?oBtfXmw}y4b+@OHnRZi-2_}{X#|=F9Bs1ct
zJBW-w13mM@m0dpdcRSxZJAKdB|ABU
z7(bBX5O@C7sHsUO<+BWequs6LYa0LJX)W6ai*cr`wnVW?!fa<;WNoDBF`x85769pN
z(|esupq{09F>JgbY?sVRljJqNX>+gB2ywz|CJ_t|+Asg|s$C|)5)u%A-)LfDB1nXQ
zt?lv&2=OvWHitS!wba#J6s==jzG@mcPlLp0wsDFKnd9#mfvx+kM4F|4xu72!Sj5Kf
zR^qQr`egDQ&M9~Myf1JSsWN=JyQA?l$w4Q)l*@Isz9;Eu7DXB!<7mmbGKJ3|UGNi+
za*l-K4b@}8m$)!|aTrl9o%vyhLGfF+Uos%3Y?A(S6IZVI~k6m2nki*ih2N1|*vRY=U!@A;|&)?oSEnJg8Ov2V=-0`L4i7~z)
z2+_b5dt}RQc;7IMK?~!A4?px*;z_7Dne-WYGAMZ+s&$|c=9y?4ufFQ2;yYp|;5ZUl
zLQ3uB`W&i-_{@ifej7$s*5X52>}8It|47C)tdwA~{Sirqy41aJDmrekW6Rd_v3KL3
zDz1axF78$<*+Kemjay9vzswwaaBb05#&S=ufRaL^XBuZmg8@?Gd=0q
z>$R?%s$Kz7a^gbI=RzY30uz21z
z%(Me#-2xnq#~bMYsmg~`zVJ!8hlYjKFeJFA;7WCARP7$@Y7fJUk0BeJ%BhFzIzK-)
zsK)({^tTA)YxVgZa|aA1?itc~wVdRhiXW%usXM(s6SuiTSQ#9gDzK$wbtWZT*vcgo
z91U)4s29jmL{g#3q{>{<`AUehNqw+tSA0W4Cu(cs?oPl81#<>WH_|Bf{X?4%I6KiP
zmh^BN#2O0aJkH
z0bG30(DT0om+3T|ElEj9;duIK#Y^_Hn{dt@fj{0YlpL8(7c!b
z-uRpJm;!K16506|h
z)!>)WYxum0P@a~Ko57d9wA$fS$ggEhH6!q_ov21PE_+!mx;>Y?dZSm1jQ$o&OSR6H
zcGWBfSFs1JMvlF-4Cc$0msljvaF&B3vy>_8LS_dV_7E=o)7N$
z{^Z3VvEFkWvr%8pk_StkLxUwL=9UZIS{6vr^pVKBR6dpNZ(>Za9j<`xDOrLR;etfv
zDYD-=sOrLBdEG+Ibf^!TW>m`Y?KVv_7ul9-0?ys7QzrJ&kTzp7(g>F(oIgx4v-I;H
z{)qIJ?Lo%&sY|A=OD6l%FF$l^e+MN|DyZ=Y00gBuE^wNhkZ_}O?N9&9v$^Yx3>_v!
z_sC)Zw7Dyol?f@R6?eNyy~8a2eKACSHot_5tX2*-$3tlde^mE&zO`dR1d$MJ1mpe0
zxuECw!uW_q+@U`Ap*`^MuzWnJCMjA|vy@!Q)T5Dc+m*RyyUh*RLxpM7Ac$co0AF`y
zC{LDd|E8CY@mXCil^(;3!H#Wx^v}rNna03!j)0dxNXQfW%{!@k=;EUHltDFHO<+Ji
zMbJ%LQDB6uxE$h0!!+{LbcA2#P?5D2e1u-fw-L;BzuMV*9{z#G=Y9Hfm{@*$j`3U<
z;?B#htQs7G+qfEASw)ontdGqin`fgPb&pZL0phijU%#wMvr|eKcE;%c*mC2>H|*$$
zV3&53#ZCsF;^(-h4Vaa-Wm0{EUBpMcD&HilQ8?AYDVqW(JB+P#crVK9=*!budf2D<
zBx?2-T9u@Z3U&AOt0!uX>;CCrDv3?4B*9U!hL-|ReBZA&V)%r+K6j^3ybiFq#b0RO
z8TwR0@t|{e?5Og7tBv0ksPEtskH~Tsd|FtJw~rEN-jRu1BZ);y?!CA&&d_3X7v8~y
zw99O-#5jOX#v_6lC9Z!_{%(XNLxpK5Y)7!VCaQ-}H+jh;osyP|5mKeJaT~upw5~Be
zpt#lEn>;DU3Qx22L4&ToM5>!ZrMO#()e(uHA(vNaGe>+~Yyam8Lt{(J(wFxwu%pSz
zdf~KWo7>@e?u7|oL%Aq_LO%E`_L19~|3e!vv7*lps^Ad$?k!eWFK$<)1V+bKZx@=V
z)`@%a*lG!Iz@wS1FqXR)W1WM+U5<6?$VsLqnna
zDmzjh`@HvT5L|G$cIouD;Rxwh)w5f9G>}-yjFO5y{>9P>FpPxTynmn8UZ0bgs3!>h
zIp2%VXsah68F?eWmNK73=2ebnkd=AySeo0L9=r0I!@U}8D;j#idg4zEwTe}arm
z$7r{@UsmS_Ps|2KoY_(jH2e(bK&Q~ooZ3$?GkF*WhC1=*a1G?_GSz8$PWkxrbV?5L
zh+mf~QltYd9J@s~TI~+s$!NTgEj@^!G?6Cr-P`_dk%Lg3oGy!fRsVHW6^ks2k$52&sc?Lw!sU!xAk&-a&i|DAR`q#bqU|M#xc2k{u
ztRD1EfGhcfW@yTK9n5uMb9zD3aIpu?Xn^#^@dZM_jxjsTg}iC`-zg{x+J`7{iexxr
z1O6hUfsbX4F1eG4@B_rI7*hX4oq&Xyn@dU$xZa|GxjhA60VwmU{qOSLiUx$ze^cSv
zSl@Azac@0sefV#dmeVWzap;HcSNWgs5(iBj(aaUtN9`eTdVj>m>jib(
zR@~k9=Z{}6Q|!O=y2HjpIvFCu#52(QN1cLAKcJ3J-LLdBv9_zw6G~kyK94`RdL64>
zb8I0FNrXck(CM@-?jQx8vLK%Zh+iomTY4;DUIz?{4Q~q9A)`2dQW@6w`s1?d|4-%w
zq`7M^abZ9V?!I`%ysO11UnCqL*k2UQA=-)0zZs?;L$dJ$f(0)ZQWe{PY^U26}
zw?5bGxo%oT7kPS72rW?AA-+Xn`%2*+zN)a4z|Jj4UD{2@p~pn1L7~_Gv<)5_Z-u#_
zT~~U;aHxLu%VlL)j>`gg87A3xJ@~`Ng_g-boR&?GjSY`%L`;{rUQHNIWYp(%N70?x
z2_5Nt#Vu?)Rh#7;`;P9nO}*L~8y!RI;q_J@@++jUM0_OdZ=x4XU)5YSqwV~Uw3~Dj
zF*d4UKdZi8hR~PuSJ*~t@vm4+2Na74GGb$BXmf?uA`|$BWqHu{?=b4_+>7v@-!``ZtZdE}ZDdF%!yo9ljY*0ZU6C^8S62OQD$c|hJPe?=!tZ3SG
zuCg+rIB7(<6$^9A(}fY#3WgFAJdDNEYnr{#%~?3b>A2+z#NC%8A4ZG)mb`jzLPv
zQfIEFNpkF;a4FwJnm`~bb(D-~Hf0zXCb59UWGv%k8u~PNViSCq>2#5kMo{3Qp*}#%dFHvpe0#hchaU7N!5t3l;`ybmNwgj7?!QQObg}J%8?QNRQ41m#a
z5&_tMMfTEUC4}>gT{C4|n*`d|pQS%R_55?7GTGACtc0NJ(cnSJ2UXTo%H!T;px_sg
z3?>az3{=VZ&fHfa8M9%U!(p?A-Lz@w|EA@gV;UKrlnU@!U}9ihRBrM}PDzY0Nl~^G
zgn