SCEVAN seamlessly integrates with Seurat, the most widely used R toolkit for single-cell analysis. This guide demonstrates how to:
SCEVAN supports both Seurat v4 and v5 data structures.
SCEVAN provides a helper function that works with both Seurat v4 and v5:
You can use Seurat’s clustering to identify potential normal cells:
# Get cluster assignments
clusters <- Idents(seurat_obj)
# Identify clusters with normal cell markers
# (e.g., immune clusters, fibroblast clusters)
normal_clusters <- c("T_cells", "Macrophages", "Fibroblasts")
potential_normals <- names(clusters)[clusters %in% normal_clusters]
# Run SCEVAN with known normals
results <- pipelineCNA(
count_mtx,
sample = "MySample_guided",
norm_cell = potential_normals,
SUBCLONES = TRUE
)# Load CNA matrix
load("./output/MySample_CNAmtx.RData")
load("./output/MySample_count_mtx_annot.RData")
# Calculate global CNA score per cell
global_cna <- colMeans(abs(CNA_mtx_relat))
seurat_obj$CNA_score <- global_cna[colnames(seurat_obj)]
# Calculate chromosome-specific scores
chr7_cna <- colMeans(CNA_mtx_relat[count_mtx_annot$seqnames == 7, ])
seurat_obj$chr7_cna <- chr7_cna[colnames(seurat_obj)]
chr10_cna <- colMeans(CNA_mtx_relat[count_mtx_annot$seqnames == 10, ])
seurat_obj$chr10_cna <- chr10_cna[colnames(seurat_obj)]# Define genomic regions of interest
regions <- list(
EGFR = c(chr = 7, start = 55019017, end = 55211628),
CDKN2A = c(chr = 9, start = 21967751, end = 21995301),
PTEN = c(chr = 10, start = 87863113, end = 87971930)
)
# Calculate CNA for each region
for(gene in names(regions)) {
r <- regions[[gene]]
region_cna <- colMeans(CNA_mtx_relat[
count_mtx_annot$seqnames == r["chr"] &
count_mtx_annot$start >= r["start"] &
count_mtx_annot$end <= r["end"], , drop = FALSE
])
seurat_obj[[paste0(gene, "_cna")]] <- region_cna[colnames(seurat_obj)]
}
# Visualize
FeaturePlot(seurat_obj, features = c("EGFR_cna", "PTEN_cna"))# Create combined plot with classification and clustering
p1 <- DimPlot(seurat_obj, group.by = "class") +
ggtitle("SCEVAN Classification") + NoLegend()
p2 <- DimPlot(seurat_obj, group.by = "seurat_clusters") +
ggtitle("Seurat Clusters") + NoLegend()
p3 <- FeaturePlot(seurat_obj, features = "CNA_score") +
ggtitle("CNA Score")
p4 <- DimPlot(seurat_obj, group.by = "subclone", na.value = "lightgray") +
ggtitle("Subclones")
# Combine
(p1 | p2) / (p3 | p4)# Set identity to subclone
Idents(seurat_obj) <- "subclone"
# Find markers for each subclone
subclone_markers <- FindAllMarkers(
seurat_obj,
only.pos = TRUE,
min.pct = 0.25,
logfc.threshold = 0.25
)
# Top markers per subclone
top_markers <- subclone_markers %>%
group_by(cluster) %>%
top_n(10, avg_log2FC)
print(top_markers)# Use marker genes for pathway analysis
# Example with enrichR or clusterProfiler
# Get genes from subclone 1
s1_genes <- subclone_markers %>%
filter(cluster == 1, p_val_adj < 0.05) %>%
pull(gene)
# Run enrichment (requires clusterProfiler)
# enrichGO(s1_genes, OrgDb = org.Hs.eg.db, keyType = "SYMBOL")# Create new Seurat object with SCEVAN metadata
seurat_new <- CreateSeuratObject(
counts = count_mtx,
meta.data = results,
project = "SCEVAN_analysis"
)
# Standard Seurat workflow
seurat_new <- NormalizeData(seurat_new)
seurat_new <- FindVariableFeatures(seurat_new)
seurat_new <- ScaleData(seurat_new)
seurat_new <- RunPCA(seurat_new)
seurat_new <- RunUMAP(seurat_new, dims = 1:30)
# Visualize with SCEVAN results
DimPlot(seurat_new, group.by = "class")| Issue | Solution |
|---|---|
| Cell name mismatch | Check for - vs . in barcodes |
| Missing cells | Verify cells passed SCEVAN filtering |
| Empty CNA values | Check if cell is classified as “filtered” |
sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.32.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] rmarkdown_2.31
#>
#> loaded via a namespace (and not attached):
#> [1] digest_0.6.39 R6_2.6.1 fastmap_1.2.0 xfun_0.59
#> [5] maketools_1.3.2 cachem_1.1.0 knitr_1.51 htmltools_0.5.9
#> [9] buildtools_1.0.0 lifecycle_1.0.5 cli_3.6.6 sass_0.4.10
#> [13] jquerylib_0.1.4 compiler_4.6.1 sys_3.4.3 tools_4.6.1
#> [17] evaluate_1.0.5 bslib_0.11.0 yaml_2.3.12 otel_0.2.0
#> [21] jsonlite_2.0.0 rlang_1.2.0