Group-Level Statistical Analysis¶
SPIMquant supports group-level statistical analysis to compare pathology metrics across experimental groups using a formula-based OLS model (via statsmodels and patsy).
Overview¶
Group analysis performs statistical comparisons of:
- Field fraction: Proportion of pathology signal per atlas region
- Density: Cell/particle count per unit volume
- Count / Volume / Voxel counts: Other quantification metrics
- Colocalization metrics: Overlap ratio, distance, density, count
Results are provided as:
- Merged per-subject ROI tables for export to external stats tools
- Statistical tables per pairwise contrast (t-statistics, p-values, Cohen's d, group means)
- Heatmap visualizations
- 3D volumetric stat maps
Prerequisites¶
Before running group analysis:
- Complete participant-level processing for all subjects
- Create participants.tsv with group assignments
Creating participants.tsv¶
Create a tab-separated file in your BIDS root directory with participant metadata:
participant_id treatment genotype sex age
sub-01 vehicle WT M 12
sub-02 vehicle WT F 13
sub-03 drug WT M 11
sub-04 drug WT F 12
sub-05 vehicle KO M 12
sub-06 vehicle KO F 14
sub-07 drug KO M 11
sub-08 drug KO F 12
Required columns:
participant_id: Subject identifiers matching BIDS subject IDs (e.g.sub-01)- At least one grouping column (e.g.,
treatment,genotype)
Running Group Analysis¶
Minimal Example¶
Fit a simple two-group model and compute all pairwise contrasts for treatment:
pixi run spimquant /bids /output group \
--group-stats-model "metric ~ C(treatment)" \
--group-stats-pairwise treatment \
--cores all
Including Covariates¶
Add continuous or categorical covariates to the model:
pixi run spimquant /bids /output group \
--group-stats-model "metric ~ C(treatment) + age + C(sex)" \
--group-stats-pairwise treatment \
--cores all
Interaction Effects¶
Fit a full factorial model with interaction terms:
pixi run spimquant /bids /output group \
--group-stats-model "metric ~ C(treatment) * C(genotype) * C(sex) + age" \
--group-stats-pairwise treatment \
--group-stats-pairwise genotype \
--cores all
Multiple --group-stats-pairwise flags enumerate pairwise contrasts for each factor independently.
Stratified Contrasts¶
Use --group-stats-within to compute treatment contrasts within each combination of stratifying factors (e.g., separately for each genotype × sex combination):
pixi run spimquant /bids /output group \
--group-stats-model "metric ~ C(treatment) * C(genotype) * C(sex) + age" \
--group-stats-pairwise treatment \
--group-stats-within genotype sex \
--cores all
This produces one set of output files per stratum combination (e.g., WT/M, WT/F, KO/M, KO/F).
Filtering Subjects¶
Use --group-stats-where to restrict which subjects are included in model fitting and contrasts.
The expression is a pandas query string:
# Exclude subjects not meeting QC criteria
pixi run spimquant /bids /output group \
--group-stats-model "metric ~ C(treatment) + age" \
--group-stats-pairwise treatment \
--group-stats-where "treatment in ['vehicle', 'drug'] and qc_pass == 1" \
--cores all
Subjects that do not match the expression are excluded from both model fitting and contrast enumeration.
Labelling Analysis Runs¶
Use --group-stats-label to assign a name to each analysis run. Outputs are placed under <output_dir>/group/<label>/, so different analyses (different models, different filters, etc.) never overwrite each other:
# First analysis
pixi run spimquant /bids /output group \
--group-stats-label treatment_only \
--group-stats-model "metric ~ C(treatment)" \
--group-stats-pairwise treatment \
--cores all
# Second analysis with covariates
pixi run spimquant /bids /output group \
--group-stats-label treatment_with_covariates \
--group-stats-model "metric ~ C(treatment) + age + C(sex)" \
--group-stats-pairwise treatment \
--cores all
Default label is 1 if not specified.
Group Analysis Options Summary¶
| Option | Description |
|---|---|
--group-stats-model |
Patsy/statsmodels formula with metric as response placeholder, e.g. "metric ~ C(treatment) + age" |
--group-stats-pairwise |
Factor(s) for which all pairwise comparisons are computed. Can be repeated for multiple factors. |
--group-stats-within |
Stratifying factor(s) — contrasts are computed separately within each level combination. |
--group-stats-where |
Pandas query expression to filter subjects before model fitting. |
--group-stats-label |
Label for this run; outputs go under group/<label>/ (default: 1). |
Output Files¶
All group outputs are placed under <output_dir>/group/<label>/.
Merged Subject Table (always produced)¶
*_allsubjects.tsv: All subject-level ROI statistics concatenated into a single file, joined with participant metadata from participants.tsv. Produced whenever analysis_level=group, regardless of whether any contrasts are specified.
index name Abeta+fieldfrac Abeta+density ... participant_id treatment sex age
0 Isocortex 0.023 1452 ... sub-01 vehicle M 12
0 Isocortex 0.031 1893 ... sub-03 drug M 11
...
Useful for exporting to R, Python (pandas/seaborn), or GraphPad Prism for custom analysis.
An accompanying *_allsubjects.json sidecar describes each column.
Statistical Results (per pairwise contrast)¶
*_contrast-<label>_groupstats.tsv: Per-region statistics for one pairwise contrast.
The contrast label encodes the factor, levels, and any strata — for example:
- contrast-treatment+vehiclevsdrug — vehicle vs. drug, no strata
- contrast-treatment+vehiclevsdrug+genotype-WT+sex-M — same contrast within WT males
index name n_vehicle n_drug Abeta+fieldfrac_mean_vehicle Abeta+fieldfrac_mean_drug Abeta+fieldfrac_tstat Abeta+fieldfrac_pval Abeta+fieldfrac_cohensd ...
0 Isocortex 10 10 0.023 0.031 -2.14 0.042 -0.95 ...
1 Hippocampus 10 10 0.015 0.024 -1.88 0.071 -0.84 ...
Columns per metric:
- <metric>_mean_<levelA> / <metric>_mean_<levelB>: Group means
- <metric>_tstat: OLS-derived t-statistic for the marginal mean contrast
- <metric>_pval: Corresponding p-value (uncorrected)
- <metric>_cohensd: Cohen's d effect size
An accompanying *_groupstats.json sidecar describes each column.
Visualizations¶
*_contrast-<label>_groupstats.png: Heatmap of t-statistics across all brain regions and metrics for one contrast.
3D Maps¶
*_contrast-<label>_groupstats.nii: Volumetric map of t-statistics registered to the template space.
View in FSLeyes, ITK-SNAP, or 3D Slicer.
Statistical Methods¶
SPIMquant fits a single OLS (Ordinary Least Squares) model per brain region and metric using the formula you supply:
- The user formula (e.g.
metric ~ C(treatment) + age) is evaluated for each region × metric combination using patsy for design matrix construction. - The model is fit on all rows passing the
--group-stats-wherefilter. - Marginal means for the two contrast levels are predicted at reference covariate values (continuous covariates at their mean, categorical at their mode; strata factors fixed at the requested level).
- The contrast vector (levelA − levelB) is evaluated against the model's covariance matrix to produce the t-statistic and p-value.
- Cohen's d is computed from pooled standard deviation.
Multiple comparison correction
P-values in the output are uncorrected. Apply FDR or Bonferroni correction in your downstream analysis (e.g. using statsmodels.stats.multitest.multipletests in Python or p.adjust() in R).
Example Workflows¶
Drug Treatment Study¶
# 1. Process all subjects (participant level)
pixi run spimquant /bids /output participant --cores all
# 2. Run group analysis comparing drug vs. vehicle
pixi run spimquant /bids /output group \
--group-stats-label drug_study \
--group-stats-model "metric ~ C(treatment) + age + C(sex)" \
--group-stats-pairwise treatment \
--cores all
Genotype Comparison with Sex Stratification¶
pixi run spimquant /bids /output group \
--group-stats-label genotype_by_sex \
--group-stats-model "metric ~ C(genotype) * C(sex) + age" \
--group-stats-pairwise genotype \
--group-stats-within sex \
--cores all
This produces separate statistical maps for male and female cohorts.
Multi-Factor Study with Subject Exclusion¶
pixi run spimquant /bids /output group \
--group-stats-label lecanemab_qc \
--group-stats-model "metric ~ C(treatment) * C(sex) + age" \
--group-stats-pairwise treatment \
--group-stats-where "treatment in ['PBS', 'Lecanemab'] and qc_pass == 1" \
--cores all
Merged Table Only (No Statistics)¶
To obtain only the merged subject table without running any statistical contrasts, simply omit --group-stats-pairwise:
This always runs when analysis_level=group and produces *_allsubjects.tsv for all subjects.
Interpreting Results¶
Statistical Significance¶
- Interpret p-values in the context of the number of regions and metrics tested
- Apply appropriate multiple comparison correction for your use case
- Consider effect sizes (Cohen's d) alongside p-values
Effect Sizes (Cohen's d)¶
| d | Interpretation |
|---|---|
| < 0.2 | Small |
| 0.2 – 0.8 | Medium |
| ≥ 0.8 | Large |
Heatmap Color Scale¶
- Positive t-statistic (warm colors): levelA > levelB
- Negative t-statistic (cool colors): levelA < levelB
- Intensity reflects the magnitude of the difference
Troubleshooting¶
Missing participants.tsv¶
Error: participants.tsv not found
- Create
participants.tsvin the BIDS root directory - Ensure tab-separated format
NaN in tstat / pval columns¶
Check the log file at logs/group_stats/<entities>_groupstats.log. Common causes:
- Fewer than 2 subjects per group in a region (logged as a skip message)
- A column referenced in the formula is missing from the data
- A contrast level is absent after --group-stats-where filtering
Contrast Level Not Found¶
Error: Contrast level 'X' ... is not present in the filtered data
- Verify the spelling of level names in
participants.tsv - Check that
--group-stats-wheredoes not exclude subjects with that level
Group Size Warnings¶
Minimum 2 subjects per group are required to fit the model. Larger groups increase statistical power.
Next Steps¶
- CLI Reference: Full group analysis option reference
- Visualization: Advanced visualization techniques
- FAQ: Common questions about group analysis