This vignette covers advanced usage patterns for recall, including:
recall supports multiple methods for generating synthetic null variables:
| Method | Distribution | Correlations | Speed | Best For |
|---|---|---|---|---|
ZIP |
Zero-Inflated Poisson | No | Fast | Most scRNA-seq data |
NB |
Negative Binomial | No | Fast | Overdispersed data |
ZIP-copula |
ZIP + Gaussian copula | Yes | Slow | Correlated genes |
NB-copula |
NB + Gaussian copula | Yes | Slow | Complex datasets |
Poisson-copula |
Poisson + copula | Yes | Medium | Low-variance data |
Gaussian-copula |
Gaussian + copula | Yes | Medium | Normalized data |
library(recall)
library(Seurat)
# For standard scRNA-seq data with excess zeros
pbmc_zip <- FindClustersRecall(
pbmc,
null_method = "ZIP", # Default, fastest
resolution_start = 0.8
)
# For highly overdispersed data
pbmc_nb <- FindClustersRecall(
pbmc,
null_method = "NB",
resolution_start = 0.8
)
# For data with strong gene-gene correlations
pbmc_copula <- FindClustersRecall(
pbmc,
null_method = "NB-copula",
cores = 4, # Parallel processing recommended
resolution_start = 0.8
)# Check for overdispersion
counts <- GetAssayData(pbmc, layer = "counts")
means <- rowMeans(counts)
vars <- apply(counts, 1, var)
# Overdispersion ratio
overdispersion_ratio <- vars / means
summary(overdispersion_ratio)
# If median ratio >> 1, use NB instead of ZIP
if (median(overdispersion_ratio, na.rm = TRUE) > 2) {
message("Data appears overdispersed. Consider using null_method = 'NB'")
}recall automatically handles parallelization across platforms:
multicore
(fork-based)multisession
(socket-based)recall also implements the count splitting approach as an alternative to knockoff filtering:
# Count splitting method (Neufeld et al., 2022)
pbmc_countsplit <- FindClustersCountsplit(
pbmc,
resolution_start = 0.8,
algorithm = "leiden"
)library(patchwork)
# Run both methods
pbmc_recall <- FindClustersRecall(pbmc, resolution_start = 0.8)
pbmc_countsplit <- FindClustersCountsplit(pbmc, resolution_start = 0.8)
# Compare results
p1 <- DimPlot(pbmc_recall, label = TRUE) +
ggtitle(paste0("recall (", length(unique(Idents(pbmc_recall))), " clusters)"))
p2 <- DimPlot(pbmc_countsplit, group.by = "countsplit_clusters", label = TRUE) +
ggtitle(paste0("Count Split (", length(unique(pbmc_countsplit$countsplit_clusters)), " clusters)"))
p1 + p2The reduction_percentage parameter controls how quickly
resolution decreases:
# Conservative: Slower reduction, may result in more clusters
pbmc_conservative <- FindClustersRecall(
pbmc,
resolution_start = 1.2,
reduction_percentage = 0.1 # 10% reduction per iteration
)
# Aggressive: Faster reduction, may result in fewer clusters
pbmc_aggressive <- FindClustersRecall(
pbmc,
resolution_start = 1.2,
reduction_percentage = 0.3 # 30% reduction per iteration
)# Sweep different starting resolutions
resolutions <- c(0.4, 0.6, 0.8, 1.0, 1.2, 1.5)
results <- list()
for (res in resolutions) {
pbmc_temp <- FindClustersRecall(pbmc, resolution_start = res)
results[[as.character(res)]] <- list(
n_clusters = length(unique(Idents(pbmc_temp))),
clusters = Idents(pbmc_temp)
)
}
# Summary
sapply(results, function(x) x$n_clusters)library(Seurat)
library(recall)
# 1. Load and preprocess
seurat_obj <- CreateSeuratObject(counts = raw_counts)
seurat_obj <- NormalizeData(seurat_obj)
seurat_obj <- FindVariableFeatures(seurat_obj, nfeatures = 2000)
seurat_obj <- ScaleData(seurat_obj)
seurat_obj <- RunPCA(seurat_obj)
seurat_obj <- FindNeighbors(seurat_obj, dims = 1:20)
seurat_obj <- RunUMAP(seurat_obj, dims = 1:20)
# 2. Calibrated clustering with recall
seurat_obj <- FindClustersRecall(
seurat_obj,
resolution_start = 0.8,
null_method = "ZIP",
algorithm = "leiden",
cores = 4
)
# 3. Downstream analysis
markers <- FindAllMarkers(seurat_obj, only.pos = TRUE)
# 4. Visualization
DimPlot(seurat_obj, group.by = "recall_clusters", label = TRUE)# Process multiple samples
sample_list <- list(sample1 = seurat1, sample2 = seurat2, sample3 = seurat3)
results <- lapply(sample_list, function(obj) {
# Preprocess
obj <- NormalizeData(obj)
obj <- FindVariableFeatures(obj)
obj <- ScaleData(obj)
obj <- RunPCA(obj)
obj <- FindNeighbors(obj, dims = 1:10)
# Calibrated clustering
obj <- FindClustersRecall(obj, resolution_start = 0.8, cores = 2)
return(obj)
})