
scSidekick - Upstream Regulator Analysis
19_ura.RmdOverview
Differential expression tells you which genes change;
upstream regulator analysis (URA) asks which transcription
factors drive those changes. RunURA() infers
per-sample TF activity from gene expression using decoupleR and the CollecTRI TF-target
network, then (optionally) tests for differential TF
activity between conditions.
The workflow:
- Collapse cells to pseudobulk profiles (per group, donor, and any stratifier) - statistically sound replicates for downstream testing.
- Score TF activity per sample with decoupleR’s univariate linear
model (
ulm, the default;viperandmlmare also available) against CollecTRI. - If a contrast is given, test for differential activity (limma when there are at least 3 donors per side, t-test otherwise).
- Save a TF-activity heatmap and a differential bubble plot, each with
a
.legendsidecar.
RunURA() complements the pathway tools (Vignettes
08-10): GSEA finds enriched gene sets, URA finds the regulators upstream
of them.
decoupleR is an optional dependency. Install it once (Section 1). The CollecTRI network is fetched from OmniPath on first use and cached locally.
1. Installation
if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager")
BiocManager::install("decoupleR")
# Optional but recommended for the differential heatmap and limma-based testing:
BiocManager::install(c("limma", "ComplexHeatmap"))The first RunURA() call downloads CollecTRI from
OmniPath and caches it to
~/.scSidekick/collectri_<organism>.rds, so subsequent
runs are offline and instant. See the note on network access at the end
if OmniPath is blocked on your network.
2. Basic TF activity (no contrast)
With just group.by, RunURA() infers mean TF
activity per group and saves a z-scored activity heatmap of the most
variable TFs.
ura <- RunURA(obj,
group.by = "CellType",
organism = "human",
output_dir = "./Figures/URA")The return value is a list:
| Element | Description |
|---|---|
activity |
TF x group mean-activity matrix |
scores |
Long-format decoupleR output (all pseudobulk samples) |
de |
Differential table (NULL when no contrast) |
network |
The TF-target network actually used |
ura$activity[1:5, 1:4] # TFs x cell types3. Differential TF activity between conditions
Supply contrast.by (the condition column) and
contrast (a c("test", "reference") pair), plus
donor.by to enable replicate-based testing. This produces a
differential heatmap (activity difference, with dots marking
p.adj < 0.05) and a bubble plot.
ura <- RunURA(obj,
group.by = "CellType",
donor.by = "Donor.ID", # biological replicates -> limma
contrast.by = "Diagnosis",
contrast = c("AD", "Control"), # test vs reference
organism = "human",
output_dir = "./Figures/URA")
head(ura$de) # TF, cell_type, activity_diff, p.value, p.adj, contrast ...Stratify with split.by
split.by (e.g. "Sex") adds a second
dimension: the contrast is computed within each level, columns of the
heatmap are grouped by it, and the bubble plot is faceted.
ura <- RunURA(obj,
group.by = "CellType",
donor.by = "Donor.ID",
split.by = "Sex",
contrast.by = "Diagnosis",
contrast = c("AD", "Control"),
output_dir = "./Figures/URA")4. Useful options
RunURA(obj,
group.by = "CellType",
contrast.by = "Diagnosis",
contrast = c("AD", "Control"),
method = "ulm", # "ulm" (default), "viper", or "mlm"
n_top = 30, # TFs shown in plots
min_cells = 10, # minimum cells per pseudobulk group
group.levels = c("Microglia", "Astrocyte"), # restrict to some groups
use_pseudobulk = TRUE, # FALSE = score per cell, then average
organism = "human", # or "mouse"
output_dir = "./Figures/URA")-
use_pseudobulk = TRUE(default) is the rigorous route: TF activity is inferred from per-sample pseudobulk averages. Withuse_pseudobulk = FALSE, decoupleR scores every cell directly and activities are averaged per group (simpler, nodonor.byneeded, but cells are pseudoreplicates so interpret DE p-values with caution; usemax_cellsto subsample large objects). -
force = TRUErecomputes pseudobulk even if a cached result is stored inobj@misc$pseudobulk. - A custom
network(a data frame withsource,target,mor) can be passed instead of CollecTRI.
5. Outputs
When output_dir is set, RunURA() writes
(file names encode group.by, split.by, and the
contrast):
-
<object>_URA_by_<group>..._heatmap.pdf- one per contrast; rows are top TFs, columns are cell types (grouped bysplit.by), color is activity difference, black dots markp.adj < 0.05. -
<object>_URA_by_<group>..._bubble.pdf- matrix bubble plot (cell type x TF, color = activity difference, size = -log10 p.adj), faceted by contrast andsplit.by. - A
.legendsidecar next to each PDF, socreate_analysis_pptx()picks the description up automatically.
6. Note on network access (OmniPath)
CollecTRI is fetched from the OmniPath web service on first use.
RunURA() tries several fallbacks (bundled copy, alternate
OmniPathR options, disk cache, direct REST download) and caches a
working network to
~/.scSidekick/collectri_<organism>.rds. If your
institution blocks OmniPath, fetch the network once from an unrestricted
machine and drop it in the cache:
net <- decoupleR::get_collectri(organism = "human")
saveRDS(net, "~/.scSidekick/collectri_human.rds")Then every RunURA() call uses the cached network
offline. You can also pass it directly via the network
argument.
See also
- Vignette 08-10:
RunGSEA()and the pathway family - the enriched gene sets that URA finds the regulators for - Vignette 14:
ComputePseudobulk()- the donor-level aggregation URA builds on - Vignette 12:
create_analysis_pptx()- assembles the URA figures (with their.legendtext) into a deck
Session info
## R version 4.3.1 (2023-06-16)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS 15.6
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: America/Chicago
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## loaded via a namespace (and not attached):
## [1] digest_0.6.37 desc_1.4.3 R6_2.6.1 fastmap_1.2.0
## [5] xfun_0.52 cachem_1.1.0 knitr_1.45 htmltools_0.5.8.1
## [9] rmarkdown_2.29 lifecycle_1.0.4 cli_3.6.5 sass_0.4.10
## [13] pkgdown_2.1.3 textshaping_0.3.7 jquerylib_0.1.4 systemfonts_1.3.2
## [17] compiler_4.3.1 rstudioapi_0.16.0 tools_4.3.1 ragg_1.4.0
## [21] bslib_0.9.0 evaluate_0.23 yaml_2.3.10 jsonlite_2.0.0
## [25] rlang_1.1.6 fs_1.6.6 htmlwidgets_1.6.4