fastCNV provides comprehensive visualization tools for CNV analysis results. This vignette covers:
CNV heatmap showing chromosomal alterations. Rows represent cells, columns represent genomic windows. Blue = deletion, Red = amplification.
The plotCNVResults() function generates
publication-ready heatmaps:
The heatmap uses a diverging color scale: - Blue: Deletions (negative CNV scores) - White: Neutral (no alteration) - Red: Amplifications (positive CNV scores)
A typical CNV heatmap includes:
┌─────────────────────────────────────────────────────────────┐
│ Chromosome Labels (1-22, X) │
├─────────────────────────────────────────────────────────────┤
│ Row │ │
│ Anno- │ CNV Score Matrix │
│ tations │ (cells × genomic windows) │
│ │ │
│ - Cell │ Blue = Deletion │
│ type │ White = Neutral │
│ - Clone │ Red = Amplification │
│ │ │
├─────────────────────────────────────────────────────────────┤
│ Color Legend │
└─────────────────────────────────────────────────────────────┘
Hierarchical clustering dendrogram based on CNV profiles, showing the relationship between different clones.
CNV profiles can be used to reconstruct clonal phylogenies:
Add CNV event annotations to tree branches:
┌─── Clone A (chr7+, chr10-)
┌───────┤
│ └─── Clone B (chr7+, chr10-, chr19+)
────────┤
│ ┌─── Clone C (chr1q+)
└───────┤
└─── Clone D (chr1q+, chr8-)
Legend:
+ = Amplification
- = Deletion
Bar plot showing mean CNV scores per chromosome arm for different clones.
library(ggplot2)
# Extract arm-level data
arm_data <- result$cnv_per_arm
# Create bar plot
ggplot(arm_data, aes(x = arm, y = cnv_fraction, fill = cnv_type)) +
geom_bar(stat = "identity") +
facet_wrap(~cluster, ncol = 1) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(
title = "CNV Fraction per Chromosome Arm",
x = "Chromosome Arm",
y = "Fraction of Cells with CNV"
)# Create a multi-panel figure
library(patchwork)
# Panel 1: Cell type annotation
p1 <- SpatialDimPlot(result, group.by = "cell_type")
# Panel 2: CNV clusters
p2 <- SpatialDimPlot(result, group.by = "cnv_clusters")
# Panel 3: CNV score for specific chromosome
p3 <- SpatialFeaturePlot(result, features = "chr7_cnv_score")
# Combine
p1 | p2 | p3library(ggplot2)
library(tidyr)
# Example: Plot CNV profile for a single cell
cell_profile <- cnv_scores[, "cell_1"]
window_positions <- 1:length(cell_profile)
ggplot(data.frame(pos = window_positions, cnv = cell_profile)) +
geom_line(aes(x = pos, y = cnv), color = "steelblue") +
geom_hline(yintercept = 0, linetype = "dashed", color = "gray50") +
theme_minimal() +
labs(
title = "CNV Profile: Cell 1",
x = "Genomic Position (window)",
y = "CNV Score"
)# Compare average CNV profiles between clusters
library(dplyr)
# Calculate mean CNV per cluster
cluster_means <- result@meta.data %>%
group_by(cnv_clusters) %>%
summarise(
mean_cnv_fraction = mean(cnv_fraction),
n_cells = n()
)
# Plot
ggplot(cluster_means, aes(x = cnv_clusters, y = mean_cnv_fraction, fill = cnv_clusters)) +
geom_bar(stat = "identity") +
theme_minimal() +
labs(
title = "Mean CNV Fraction by Cluster",
x = "CNV Cluster",
y = "Mean CNV Fraction"
)# Save heatmap as PDF
pdf("cnv_heatmap.pdf", width = 12, height = 8)
plotCNVResults(
seuratObj = result,
referenceVar = "cell_type",
tumorLabel = "Tumor"
)
dev.off()
# Save tree as PDF
pdf("cnv_tree.pdf", width = 8, height = 6)
plotCNVTree(
tree = tree,
seuratObj = result,
referenceVar = "cell_type",
tumorLabel = "Tumor"
)
dev.off()library(patchwork)
library(ggplot2)
# Create individual panels
p_umap <- DimPlot(result, group.by = "cnv_clusters")
p_spatial <- SpatialDimPlot(result, group.by = "cnv_clusters")
# Assemble figure
figure <- (p_umap | p_spatial) /
plot_spacer() +
plot_layout(heights = c(2, 1))
# Save
ggsave("figure_panel.pdf", figure, width = 14, height = 10)fastCNV uses carefully selected color palettes:
sessionInfo()
#> R version 4.6.0 (2026-04-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.4 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.26.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.0 sys_3.4.3 tools_4.6.0
#> [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