Heatmap and Annotation Legends

Author: Zuguang Gu ( z.gu@dkfz.de )

Date: r Sys.Date()


library(markdown)
options(markdown.HTML.options = c(options('markdown.HTML.options')[[1]], "toc"))

library(knitr)
knitr::opts_chunk$set(
    error = FALSE,
    tidy  = FALSE,
    message = FALSE,
    fig.align = "center",
    fig.width = 5,
    fig.height = 5)
options(markdown.HTML.stylesheet = "custom.css")

options(width = 100)

The legends for heatmaps are composed with a color bar, labels and titles. ComplexHeatmap automatically generates legends according to the input matrix and annotations, while also provide flexibility to customize and add new legends.

Basic settings

Legends for all heatmaps and row annotations are drawn together and legends for all column annotations are drawn together. The legends for heatmaps and legends for annotations are put in independent viewports.

library(ComplexHeatmap)
library(circlize)

set.seed(123)
mat = matrix(rnorm(80, 2), 8, 10)
mat = rbind(mat, matrix(rnorm(40, -2), 4, 10))
rownames(mat) = paste0("R", 1:12)
colnames(mat) = paste0("C", 1:10)

ha_column = HeatmapAnnotation(df = data.frame(type1 = c(rep("a", 5), rep("b", 5))), 
    col = list(type1 = c("a" =  "red", "b" = "blue")))
ha_row = rowAnnotation(df = data.frame(type2 = c(rep("A", 6), rep("B", 6))), 
    col = list(type2 = c("A" =  "green", "B" = "orange")), width = unit(1, "cm"))

ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1", top_annotation = ha_column)
ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2")
ht_list = ht1 + ht2 + ha_row

draw(ht_list)

Side of legends can be set by heatmap_legend_side and annotation_legend_side.

draw(ht_list, heatmap_legend_side = "left", annotation_legend_side = "bottom")

show_heatmap_legend and show_annotation_legend set visibility of legends.

draw(ht_list, show_heatmap_legend = FALSE, show_annotation_legend = FALSE)

You can choose to only show some of the heatmap legends by setting show_heatmap_legend to a logical value when constructing single heatmaps. Also HeatmapAnnotation() (or the shortcut function columnAnnotation() and rowAnnotation()) provides show_legend argument to control visibility of annotation legends.

ha_column = HeatmapAnnotation(df = data.frame(type1 = c(rep("a", 5), rep("b", 5))), 
    col = list(type1 = c("a" =  "red", "b" = "blue")), show_legend = FALSE)
ha_row = rowAnnotation(df = data.frame(type2 = c(rep("A", 6), rep("B", 6))), 
    col = list(type2 = c("A" =  "green", "B" = "orange")), show_legend = FALSE, width = unit(1, "cm"))

ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1", top_annotation = ha_column)
ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2", show_heatmap_legend = FALSE)
ht1 + ht2 + ha_row

Customization of legends

Legend itself can be flexibly customized. Parameters for making the legend can be set by heatmap_legend_param (for heatmap) or annotation_legend_param (for annotations). The parameters that can be set are as follows:

Following example changes the default graphic parameters for labels and titles:

df = data.frame(type = c(rep("a", 5), rep("b", 5)))
ha = HeatmapAnnotation(df = df, col = list(type = c("a" =  "red", "b" = "blue")),
    annotation_legend_param = list(type = list(title = "TYPE", title_gp = gpar(fontsize = 14), 
                                               labels_gp = gpar(fontsize = 8))))
ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1", top_annotation = ha)
ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2", 
    heatmap_legend_param = list(title = "Heatmap2", title_gp = gpar(fontsize = 8), 
        labels_gp = gpar(fontsize = 14)))
ht1 + ht2

You can specify break values and break labels (both for character values and numeric values) by at and labels in corresponding heatmap_legend_param and annotation_legend_param. Note at can also be character break values.

ha = HeatmapAnnotation(df = df, col = list(type = c("a" =  "red", "b" = "blue")),
    annotation_legend_param = list(type = list(title = "TYPE", title_gp = gpar(fontsize = 14), 
        labels_gp = gpar(fontsize = 8), at = c("a", "b"), labels = c("A", "B"))))
ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1", top_annotation = ha,
    heatmap_legend_param = list(at = c(-3, 0, 3), labels = c("-three", "zero", "+three")))
ht1 + ht2

If you have many levels in your annotation or matrix, you can put all levels into an array by specifying nrow or ncol:

ha_chr = rowAnnotation(chr = sample(paste0("chr", 1:20), nrow(mat), replace = TRUE),
    annotation_legend_param = list(chr = list(ncol = 2, title = "chromosome", title_position = "topcenter")),
    width = unit(5, "mm"))
ht1 = Heatmap(mat, name = "ht1")
ht1 + ha_chr

Or put at bottom of the heatmap:

ha_chr = rowAnnotation(chr = sample(paste0("chr", 1:20), nrow(mat), replace = TRUE),
    annotation_legend_param = list(chr = list(nrow = 2, title = "chr", title_position = "leftcenter")),
    width = unit(5, "mm"))
ht1 = Heatmap(mat, name = "ht1", show_heatmap_legend = FALSE)
draw(ht1 + ha_chr, heatmap_legend_side = "bottom")

Discrete color bar for can be used for continuous values, if you specify color_bar to discrete. For the simple annotation which contains continuous values, color_bar can also be set to discrete.

ha = HeatmapAnnotation(df = data.frame(value = runif(10)), 
    col = list(value = colorRamp2(c(0, 1), c("white", "blue"))), 
    annotation_legend_param = list(color_bar = "discrete", at = c(0, 0.5, 1)))
Heatmap(mat, name = "ht1", top_annotation = ha, heatmap_legend_param = list(color_bar = "discrete"))

Some users prefer to put the legend at the bottom of heatmaps.

ht = Heatmap(mat, name = "ht1", heatmap_legend_param = list(legend_direction = "horizontal",
    legend_width = unit(5, "cm"), title_position = "lefttop"))
draw(ht, heatmap_legend_side = "bottom")

Similarly, the height of the legend can be adjusted by legend_height if the legend is vertical.

Heatmap(mat, name = "ht1", heatmap_legend_param = list(legend_height = unit(5, "cm")))

If you want to change default settings for all heatmaps/annotations, you can set it globally by ht_global_opt().

ht_global_opt(heatmap_legend_title_gp = gpar(fontsize = 16), annotation_legend_labels_gp = gpar(fontface = "italic"))
ha = HeatmapAnnotation(df = data.frame(value = runif(10)), 
    col = list(value = colorRamp2(c(0, 1), c("white", "blue"))))
ht1 = Heatmap(mat, name = "ht1", column_title = "Heatmap 1", top_annotation = ha)
ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2", heatmap_legend_param = list(title_gp = gpar(fontsize = 8)))
ht1 + ht2
ht_global_opt(RESET = TRUE)

Add new legends

ComplexHeatmap only generates legends for heatmaps and simple annotations. Self-defined legends can be passed by heatmap_legend_list and annotation_legend_list as a list of grob objects.

grid package provides legendGrob() to construct a legend grob with certain style but styles are still limited. For advanced users, they can construct a legend grob totally from ground by frameGrob() and placeGrob().

ha = HeatmapAnnotation(points = anno_points(rnorm(10)))
ht2 = Heatmap(mat, name = "ht2", column_title = "Heatmap 2", top_annotation = ha, show_heatmap_legend = FALSE)
lgd = legendGrob(c("dots"), pch = 16)
draw(ht1 + ht2, annotation_legend_list = list(lgd))

From version 1.9.7, ComplexHeatmap package provides a Legend() function which can produce legends in grob formats (actually all legends in the package are implemented by Legend() function). In following example, we have several column annotations which contains points and we also want to show legends for these non-heatmap graphics.

ha = HeatmapAnnotation(points = anno_points(rnorm(10), gp = gpar(col = rep(2:3, each = 5))))
ht = Heatmap(mat, name = "ht2", column_title = "Heatmap 2", top_annotation = ha)
lgd = Legend(at = c("class1", "class2"), title = "points", type = "points", legend_gp = gpar(col = 2:3))
draw(ht, annotation_legend_list = list(lgd))

Also check this blog link for more demonstrations.

Session info

sessionInfo()


eilslabs/ComplexHeatmap documentation built on May 16, 2019, 1:21 a.m.