Participant-level differential analysis for longitudinal single-cell experiments: DiD, paired comparisons, module scoring, pseudobulk, and power analysis.
Project description
Participant-Level Differential Analysis for Longitudinal Single-Cell Experiments
Overview
sctrial is a Python package for participant-level differential analysis of longitudinal single-cell RNA-seq data from clinical trials and translational studies. Built on AnnData and the scverse ecosystem, it provides:
- Difference-in-Differences (DiD) analysis with participant fixed effects
- Paired within-arm pre→post contrasts
- Between-arm comparisons at fixed timepoints
- Cell-type abundance change testing
- Gene set enrichment analysis (GSEA) on DiD rankings
- Power analysis and sample size calculations
- Effect size estimation with confidence intervals
Key Features
| Feature | Description |
|---|---|
| Trial-Aware Design | Define participant, visit, arm, and cell type columns once |
| Robust Statistics | Wild cluster bootstrap, participant-level aggregation |
| Multiple Comparisons | Built-in FDR correction across features and cell types |
| Power Analysis | Two-arm DiD and single-arm paired power/sample size calculations |
| Single-Arm Support | arm_col=None for studies without a control arm |
| Publication-Ready Plots | Forest plots, interaction plots, GSEA heatmaps |
| Scalable | Efficient processing of large single-cell datasets |
Installation
pip install sctrial
For development:
git clone https://github.com/TheOmarLab/sctrial.git
cd sctrial
pip install -e ".[dev]"
Quick Start
pip install "sctrial[plots]" # includes dataset loaders and visualization
import sctrial as st
# 1. Load a real immunotherapy trial dataset (auto-downloads on first use)
adata = st.load_sade_feldman()
adata = st.harmonize_response(adata) # majority-vote response labels
# 2. Define trial design
design = st.TrialDesign(
participant_col="participant_id",
visit_col="visit",
arm_col="response_harmonized",
arm_treated="Responder",
arm_control="Non-responder",
celltype_col="cell_type",
)
# 3. Score gene sets (dataset ships pre-normalized with log1p_tpm layer)
gene_sets = {
"Cytotoxicity": ["GZMA", "GZMB", "PRF1", "GNLY", "NKG7"],
"Exhaustion": ["PDCD1", "CTLA4", "HAVCR2", "LAG3", "TIGIT"],
}
adata = st.score_gene_sets(adata, gene_sets, layer="log1p_tpm", method="zmean", prefix="ms_")
# 4. Run Difference-in-Differences on CD8 T cells
features = [c for c in adata.obs.columns if c.startswith("ms_")]
results = st.did_table(adata, features, design, visits=("Pre", "Post"), celltype="CD8 T cell")
print(results[["feature", "beta_DiD", "se_DiD", "p_DiD", "FDR_DiD"]])
Or use the one-liner convenience wrapper for a quick multi-cell-type scan:
results = st.quick_did(
adata,
module_scores=gene_sets,
visits=("Pre", "Post"),
arm_col="response_harmonized",
arm_treated="Responder",
arm_control="Non-responder",
celltype_col="cell_type",
)
Supported Study Designs & Datasets
sctrial ships with five real clinical trial datasets, accessible via built-in loaders (st.load_*()). Each demonstrates a different study design:
| Design | Description | Dataset | Source | Tutorial |
|---|---|---|---|---|
| Two-arm paired DiD | Pre/post × treatment/control interaction | Sade-Feldman et al., Cell 2018 — melanoma immunotherapy | GSE120575 | Immunotherapy |
| Single-arm pre/post | Paired within-arm contrasts over time | ImmPort GSE171964 — PBMC vaccine response | GSE171964 | Vaccine |
| Single-arm pre/post | Paired within-arm, multi-timepoint | van Galen et al., Cell 2019 — AML chemotherapy | GSE116256 | — |
| Single-arm multi-timepoint | Longitudinal tracking across 4 visits | GSE290722 — CAR-T cell therapy (ZUMA-1) | GSE290722 | — |
| Cross-sectional between-arm | Between-group comparison at one timepoint | Stephenson et al., Nature Medicine 2021 — COVID-19 severity | E-MTAB-10026 | COVID-19 |
Additional tutorial: Scalability Benchmark — performance testing on the Sade-Feldman dataset.
Documentation
Full documentation: https://www.omar-lab.com/sctrial/
Citation
If you use sctrial in your research, please cite:
Vasanthakumari P, Valencia I, Aghmiouni MR, Magana B, Omar MN. sctrial: Participant-Level Differential Analysis for Longitudinal Single-Cell Experiments. bioRxiv (2026).
@article{vasanthakumari2026sctrial,
title = {sctrial: Participant-Level Differential Analysis for Longitudinal Single-Cell Experiments},
author = {Vasanthakumari, Priyanka and Valencia, Itzel and Aghmiouni, Maryam R. and Magana, Bryan and Omar, Mohamed N.},
journal = {bioRxiv},
year = {2026},
url = {https://github.com/TheOmarLab/sctrial}
}
License
MIT License - see LICENSE for details.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sctrial-0.3.3.tar.gz.
File metadata
- Download URL: sctrial-0.3.3.tar.gz
- Upload date:
- Size: 185.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ecbb92d4d537b1c0f5c04e1f30b180f7bd08ecbd6a6c9e7a47d41b1ba198575c
|
|
| MD5 |
b6ad7c905bb35303c90cb84eddd0b134
|
|
| BLAKE2b-256 |
2d1f436d5b624f725c6062e2e8a16bf035e9abe416e67abfa0eeacf0ecc46c26
|
File details
Details for the file sctrial-0.3.3-py3-none-any.whl.
File metadata
- Download URL: sctrial-0.3.3-py3-none-any.whl
- Upload date:
- Size: 170.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
575b1a9a8537d057e03283d0c2eb1b192816931f1956bf9e71156ecdfccabeaa
|
|
| MD5 |
7af2315da20ef1331f3691746ed0c101
|
|
| BLAKE2b-256 |
30dbd5867e35cdab7d801b07f790085d3dbae8a7665bf65cc71a0e944b22c579
|