选自ComplexHeatmap 完全指南
https://jokergoo.github.io/ComplexHeatmap-reference/book/
作者是鼎鼎大名的Zuguang Gu,最后修订于 2019-07-03
用Github安装最新版的ComplexHeatmap
library(devtools)
install_github("jokergoo/ComplexHeatmap")
电子书中包含的内容如下
This chapter describes the configurations of a single heatmap.
This chapter describes the concept of the heatmap annotation and demonstrates how to make simple annotations as well as complex annotations. Also, the chapter explains the difference between column annotations and row annotations.
This chapter describes how to concatenate a list of heatmaps and annotations and how adjustment is applied to keep the correspondence of the heatmaps.
This chapter describes how to configurate the heatmap legends and annotation legends, also how to create self-defined legends.
This chapter describes methods to add more self-defined graphics to the heatmaps after the heatmaps are generated.
This chapter describes how to make oncoPrints and how to integrate other functionalities from ComplexHeatmap to oncoPrints.
This chapter describes how to make enhanced UpSet plots.
This chapter describes functions implemented in ComplexHeatmap for specific use, e.g. visualizing distributions.
More simulated and real-world examples are demonstrated in this chapter.
下面节选一些好看的图片和源代码用于展示其奇妙之处
Chapter 7 OncoPrint
image.png好多文章都有这样突变基因的热图,代码如下
1. 获取TCGA的数据集
mat = read.table(system.file("extdata", package = "ComplexHeatmap",
"tcga_lung_adenocarcinoma_provisional_ras_raf_mek_jnk_signalling.txt"),
header = TRUE, stringsAsFactors = FALSE, sep = "\t")
mat[is.na(mat)] = ""
rownames(mat) = mat[, 1]
mat = mat[, -1]
mat= mat[, -ncol(mat)]
mat = t(as.matrix(mat))
mat[1:3, 1:3]
## TCGA-05-4384-01 TCGA-05-4390-01 TCGA-05-4425-01
## KRAS " " "MUT;" " "
## HRAS " " " " " "
## BRAF " " " " " "
2. 为不同的突变形式定义图形的添加方式
col = c("HOMDEL" = "blue", "AMP" = "red", "MUT" = "#008000")
alter_fun = list(
background = function(x, y, w, h) {
grid.rect(x, y, w-unit(0.5, "mm"), h-unit(0.5, "mm"),
gp = gpar(fill = "#CCCCCC", col = NA))
},
# big blue
HOMDEL = function(x, y, w, h) {
grid.rect(x, y, w-unit(0.5, "mm"), h-unit(0.5, "mm"),
gp = gpar(fill = col["HOMDEL"], col = NA))
},
# bug red
AMP = function(x, y, w, h) {
grid.rect(x, y, w-unit(0.5, "mm"), h-unit(0.5, "mm"),
gp = gpar(fill = col["AMP"], col = NA))
},
# small green
MUT = function(x, y, w, h) {
grid.rect(x, y, w-unit(0.5, "mm"), h*0.33,
gp = gpar(fill = col["MUT"], col = NA))
}
)
column_title = "OncoPrint for TCGA Lung Adenocarcinoma, genes in Ras Raf MEK JNK signalling"
heatmap_legend_param = list(title = "Alternations", at = c("HOMDEL", "AMP", "MUT"),
labels = c("Deep deletion", "Amplification", "Mutation"))
3. 绘图,简单吧!
ht_list = oncoPrint(mat,
alter_fun = alter_fun, col = col,
column_title = column_title, heatmap_legend_param = heatmap_legend_param) +
Heatmap(matrix(rnorm(nrow(mat)*10), ncol = 10), name = "expr", width = unit(4, "cm"))
draw(ht_list, row_split = sample(c("a", "b"), nrow(mat), replace = TRUE))
Chapter 8 UpSet plot
用于多个数据集的比较,可以完美替代Venn图
image.png
这是一个六个电影数据集的比较,如果用Venn图简直不能直视,但是用Upset就可以完美解决这个问题
1.导入数据集
movies = read.csv(system.file("extdata", "movies.csv", package = "UpSetR"),
header = TRUE, sep = ";")
head(movies)
## Name ReleaseDate Action Adventure Children
## 1 Toy Story (1995) 1995 0 0 1
## 2 Jumanji (1995) 1995 0 1 1
## 3 Grumpier Old Men (1995) 1995 0 0 0
## 4 Waiting to Exhale (1995) 1995 0 0 0
## 5 Father of the Bride Part II (1995) 1995 0 0 0
## 6 Heat (1995) 1995 1 0 0
## Comedy Crime Documentary Drama Fantasy Noir Horror Musical Mystery
## 1 1 0 0 0 0 0 0 0 0
## 2 0 0 0 0 1 0 0 0 0
## 3 1 0 0 0 0 0 0 0 0
## 4 1 0 0 1 0 0 0 0 0
## 5 1 0 0 0 0 0 0 0 0
## 6 0 1 0 0 0 0 0 0 0
## Romance SciFi Thriller War Western AvgRating Watches
## 1 0 0 0 0 0 4.15 2077
## 2 0 0 0 0 0 3.20 701
## 3 1 0 0 0 0 3.02 478
## 4 0 0 0 0 0 2.73 170
## 5 0 0 0 0 0 3.01 296
## 6 0 0 1 0 0 3.88 940
2.绘图,很简单就完成!
m = make_comb_mat(movies, top_n_sets = 6, remove_complement_set = TRUE)
UpSet(m)
image.png
绘制基因表达矩阵
library(ComplexHeatmap)
library(circlize)
expr = readRDS(system.file(package = "ComplexHeatmap", "extdata", "gene_expression.rds"))
mat = as.matrix(expr[, grep("cell", colnames(expr))])
base_mean = rowMeans(mat)
mat_scaled = t(apply(mat, 1, scale))
type = gsub("s\\d+_", "", colnames(mat))
ha = HeatmapAnnotation(type = type, annotation_name_side = "left")
ht_list = Heatmap(mat_scaled, name = "expression", row_km = 5,
col = colorRamp2(c(-2, 0, 2), c("green", "white", "red")),
top_annotation = ha,
show_column_names = FALSE, row_title = NULL, show_row_dend = FALSE) +
Heatmap(base_mean, name = "base mean",
top_annotation = HeatmapAnnotation(summary = anno_summary(gp = gpar(fill = 2:6),
height = unit(2, "cm"))),
width = unit(15, "mm")) +
rowAnnotation(length = anno_points(expr$length, pch = 16, size = unit(1, "mm"),
axis_param = list(at = c(0, 2e5, 4e5, 6e5),
labels = c("0kb", "200kb", "400kb", "600kb")),
width = unit(2, "cm"))) +
Heatmap(expr$type, name = "gene type",
top_annotation = HeatmapAnnotation(summary = anno_summary(height = unit(2, "cm"))),
width = unit(15, "mm"))
ht_list = rowAnnotation(block = anno_block(gp = gpar(fill = 2:6, col = NA)),
width = unit(2, "mm")) + ht_list
draw(ht_list, ht_gap = unit(5, "mm"))
image.png
绘制麻疹疫苗热图
mat = readRDS(system.file("extdata", "measles.rds", package = "ComplexHeatmap"))
ha1 = HeatmapAnnotation(
dist1 = anno_barplot(
colSums(mat),
bar_width = 1,
gp = gpar(col = "white", fill = "#FFE200"),
border = FALSE,
axis_param = list(at = c(0, 2e5, 4e5, 6e5, 8e5),
labels = c("0", "200k", "400k", "600k", "800k")),
height = unit(2, "cm")
), show_annotation_name = FALSE)
ha2 = rowAnnotation(
dist2 = anno_barplot(
rowSums(mat),
bar_width = 1,
gp = gpar(col = "white", fill = "#FFE200"),
border = FALSE,
axis_param = list(at = c(0, 5e5, 1e6, 1.5e6),
labels = c("0", "500k", "1m", "1.5m")),
width = unit(2, "cm")
), show_annotation_name = FALSE)
year_text = as.numeric(colnames(mat))
year_text[year_text %% 10 != 0] = ""
ha_column = HeatmapAnnotation(
year = anno_text(year_text, rot = 0, location = unit(1, "npc"), just = "top")
)
col_fun = colorRamp2(c(0, 800, 1000, 127000), c("white", "cornflowerblue", "yellow", "red"))
ht_list = Heatmap(mat, name = "cases", col = col_fun,
cluster_columns = FALSE, show_row_dend = FALSE, rect_gp = gpar(col= "white"),
show_column_names = FALSE,
row_names_side = "left", row_names_gp = gpar(fontsize = 8),
column_title = 'Measles cases in US states 1930-2001\nVaccine introduced 1961',
top_annotation = ha1, bottom_annotation = ha_column,
heatmap_legend_param = list(at = c(0, 5e4, 1e5, 1.5e5),
labels = c("0", "50k", "100k", "150k"))) + ha2
draw(ht_list, ht_gap = unit(3, "mm"))
decorate_heatmap_body("cases", {
i = which(colnames(mat) == "1961")
x = i/ncol(mat)
grid.lines(c(x, x), c(0, 1), gp = gpar(lwd = 2, lty = 2))
grid.text("Vaccine introduced", x, unit(1, "npc") + unit(5, "mm"))
})
image.png
绘制甲基化图谱,这个比较复杂😝
In this example, Figure 1 in Strum et al., 2012 is re-implemented with some adjustments.
Some packages need to be loaded firstly.
library(matrixStats)
library(GenomicRanges)
Methylation profiles can be download from GEO database. The [GEOquery package]
(http://bioconductor.org/packages/release/bioc/html/GEOquery.html) is used to retrieve data from GEO.
library(GEOquery)
gset = getGEO("GSE36278")
The methylation profiles have been measured by Illumina HumanMethylation450 BeadChip arrays. We load probe data via the IlluminaHumanMethylation450kanno.ilmn12.hg19 package.
Adjust row names in the matrix to be the same as the probes.
library("IlluminaHumanMethylation450kanno.ilmn12.hg19")
data(Locations)
mat = exprs(gset[[1]])
colnames(mat) = phenoData(gset[[1]])@data$title
mat = mat[rownames(Locations), ]
probe
contains locations of probes and also information whether the CpG sites overlap with SNPs. Here we remove probes that are on sex chromosomes and probes that overlap with SNPs.
data(SNPs.137CommonSingle)
data(Islands.UCSC)
l = Locations$chr %in% paste0("chr", 1:22) & is.na(SNPs.137CommonSingle$Probe_rs)
mat = mat[l, ]
Get subsets for locations of probes and the annotation to CpG Islands accordingly.
cgi = Islands.UCSC$Relation_to_Island[l]
loc = Locations[l, ]
Separate the matrix into a matrix for tumor samples and a matrix for normal samples. Also modify column names for the tumor samples to be consistent with the phenotype data which we will read later.
mat1 = as.matrix(mat[, grep("GBM", colnames(mat))]) # tumor samples
mat2 = as.matrix(mat[, grep("CTRL", colnames(mat))]) # normal samples
colnames(mat1) = gsub("GBM", "dkfz", colnames(mat1))
Phenotype data is from Sturm et al., 2012, supplementary table S1 and can be found here.
The rows of phenotype data are adjusted to be the same as the columns of the methylation matrix.
phenotype = read.table("data/450K_annotation.txt", header = TRUE, sep = "\t",
row.names = 1, check.names = FALSE, comment.char = "", stringsAsFactors = FALSE)
phenotype = phenotype[colnames(mat1), ]
Please note that we only use the 136 samples which are from DKFZ, while in Sturm et al., 2012, additional 74 TCGA samples have been used.
Extract the top 8000 probes with most variable methylation in the tumor samples, and also subset other information correspondingly.
ind = order(rowVars(mat1, na.rm = TRUE), decreasing = TRUE)[1:8000]
m1 = mat1[ind, ]
m2 = mat2[ind, ]
cgi2 = cgi[ind]
cgi2 = ifelse(grepl("Shore", cgi2), "Shore", cgi2)
cgi2 = ifelse(grepl("Shelf", cgi2), "Shelf", cgi2)
loc = loc[ind, ]
For each probe, find the distance to the closest TSS. pc_tx_tss.bed
contains positions of TSS from protein coding genes.
gr = GRanges(loc[, 1], ranges = IRanges(loc[, 2], loc[, 2]+1))
tss = read.table("data/pc_tx_tss.bed", stringsAsFactors = FALSE)
tss = GRanges(tss[[1]], ranges = IRanges(tss[, 2], tss[, 3]))
tss_dist = distanceToNearest(gr, tss)
tss_dist = tss_dist@elementMetadata$distance
Because there are a few NA
in the matrix (sum(is.na(m1))/length(m1)
= 0.0011967) which will break the cor()
function, we replace NA
to the intermediate methylation (0.5). Note that although ComplexHeatmap allows NA
in the matrix, removal of NA
will speed up the clustering.
m1[is.na(m1)] = 0.5
m2[is.na(m2)] = 0.5
The following annotations will be added to the columns of the methylation matrix:
- age
- subtype classification by DKFZ
- subtype classification by TCGA
- subtype classification by TCGA, based on expression profile
- IDH1 mutation
- H3F3A mutation
- TP53 mutation
- chr7 gain
- chr10 loss
- CDKN2A deletion
- EGFR amplification
- PDGFRA amplification
In following code we define the column annotation in the ha
variable. Also we customize colors, legends and height of the annotations.
mutation_col = structure(names = c("MUT", "WT", "G34R", "G34V", "K27M"),
c("black", "white", "#4DAF4A", "#4DAF4A", "#377EB8"))
cnv_col = c("gain" = "#E41A1C", "loss" = "#377EB8", "amp" = "#E41A1C",
"del" = "#377EB8", "normal" = "white")
ha = HeatmapAnnotation(
age = anno_points(phenotype[[13]],
gp = gpar(col = ifelse(phenotype[[13]] > 20, "black", "red")),
height = unit(3, "cm")),
dkfz_cluster = phenotype[[1]],
tcga_cluster = phenotype[[2]],
tcga_expr = phenotype[[3]],
IDH1 = phenotype[[5]],
H3F3A = phenotype[[4]],
TP53 = phenotype[[6]],
chr7_gain = ifelse(phenotype[[7]] == 1, "gain", "normal"),
chr10_loss = ifelse(phenotype[[8]] == 1, "loss", "normal"),
CDKN2A_del = ifelse(phenotype[[9]] == 1, "del", "normal"),
EGFR_amp = ifelse(phenotype[[10]] == 1, "amp", "normal"),
PDGFRA_amp = ifelse(phenotype[[11]] == 1, "amp", "normal"),
col = list(dkfz_cluster = structure(names = c("IDH", "K27", "G34", "RTK I PDGFRA",
"Mesenchymal", "RTK II Classic"), brewer.pal(6, "Set1")),
tcga_cluster = structure(names = c("G-CIMP+", "Cluster #2", "Cluster #3"),
brewer.pal(3, "Set1")),
tcga_expr = structure(names = c("Proneural", "Classical", "Mesenchymal"),
c("#377EB8", "#FFFF33", "#FF7F00")),
IDH1 = mutation_col,
H3F3A = mutation_col,
TP53 = mutation_col,
chr7_gain = cnv_col,
chr10_loss = cnv_col,
CDKN2A_del = cnv_col,
EGFR_amp = cnv_col,
PDGFRA_amp = cnv_col),
na_col = "grey", border = TRUE,
show_legend = c(TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE),
show_annotation_name = FALSE,
annotation_legend_param = list(
dkfz_cluster = list(title = "DKFZ Methylation"),
tcga_cluster = list(title = "TCGA Methylation"),
tcga_expr = list(title = "TCGA Expression"),
H3F3A = list(title = "Mutations"),
chr7_gain = list(title = "CNV"))
)
In the final plot, there are four heatmaps added. From left to right, there are
- heatmap for methylation in tumor samples
- methylation in normal samples
- distance to nearest TSS
- CpG Island (CGI) annotation.
The heatmaps are split by rows according to CGI annotations.
After the heatmaps are plotted, additional graphics such as labels for annotations are added by decorate_*()
functions.
col_fun = colorRamp2(c(0, 0.5, 1), c("#377EB8", "white", "#E41A1C"))
ht_list = Heatmap(m1, col = col_fun, name = "Methylation",
clustering_distance_columns = "spearman",
show_row_dend = FALSE, show_column_dend = FALSE,
show_column_names = FALSE,
bottom_annotation = ha, column_title = qq("GBM samples (n = @{ncol(m1)})"),
row_split = factor(cgi2, levels = c("Island", "Shore", "Shelf", "OpenSea")),
row_title_gp = gpar(col = "#FFFFFF00")) +
Heatmap(m2, col = col_fun, show_column_names = FALSE,
show_column_dend = FALSE, column_title = "Controls",
show_heatmap_legend = FALSE, width = unit(1, "cm")) +
Heatmap(tss_dist, name = "tss_dist", col = colorRamp2(c(0, 2e5), c("white", "black")),
width = unit(5, "mm"),
heatmap_legend_param = list(at = c(0, 1e5, 2e5), labels = c("0kb", "100kb", "200kb"))) +
Heatmap(cgi2, name = "CGI", show_row_names = FALSE, width = unit(5, "mm"),
col = structure(names = c("Island", "Shore", "Shelf", "OpenSea"), c("red", "blue", "green", "#CCCCCC")))
draw(ht_list, row_title = paste0("DNA methylation probes (n = ", nrow(m1), ")"),
annotation_legend_side = "left", heatmap_legend_side = "left")
annotation_titles = c(dkfz_cluster = "DKFZ Methylation",
tcga_cluster = "TCGA Methylation",
tcga_expr = "TCGA Expression",
IDH1 = "IDH1",
H3F3A = "H3F3A",
TP53 = "TP53",
chr7_gain = "Chr7 gain",
chr10_loss = "Chr10 loss",
CDKN2A_del = "Chr10 loss",
EGFR_amp = "EGFR amp",
PDGFRA_amp = "PDGFRA amp")
for(an in names(annotation_titles)) {
decorate_annotation(an, {
grid.text(annotation_titles[an], unit(-2, "mm"), just = "right")
grid.rect(gp = gpar(fill = NA, col = "black"))
})
}
decorate_annotation("age", {
grid.text("Age", unit(8, "mm"), just = "right")
grid.rect(gp = gpar(fill = NA, col = "black"))
grid.lines(unit(c(0, 1), "npc"), unit(c(20, 20), "native"), gp = gpar(lty = 2))
})
decorate_annotation("IDH1", {
grid.lines(unit(c(-40, 0), "mm"), unit(c(1, 1), "npc"))
})
decorate_annotation("chr7_gain", {
grid.lines(unit(c(-40, 0), "mm"), unit(c(1, 1), "npc"))
})
网友评论