Author: Zuguang Gu ( z.gu@dkfz.de )
Date: 2018-10-30
A list of heatmaps can improve visualization of the correspondence between multiple data sources. In this vignette, we will discuss configurations for making a list of heatmaps and you can see more real-world examples in the Examples vignette as well as in the supplementaries of the ComplexHeatmap paper.
You can arrange more than one heatmaps on the plot from left to right. Actually, one single heatmap is just a special case of the heatmap list of length one.
Heatmap()
is actually a class constructor function for a single heatmap. If more than one heatmaps
are to be combined, users can append one heatmap to the other by +
operator.
library(ComplexHeatmap)
mat1 = matrix(rnorm(80, 2), 8, 10)
mat1 = rbind(mat1, matrix(rnorm(40, -2), 4, 10))
rownames(mat1) = paste0("R", 1:12)
colnames(mat1) = paste0("C", 1:10)
mat2 = matrix(rnorm(60, 2), 6, 10)
mat2 = rbind(mat2, matrix(rnorm(60, -2), 6, 10))
rownames(mat2) = paste0("R", 1:12)
colnames(mat2) = paste0("C", 1:10)
ht1 = Heatmap(mat1, name = "ht1")
ht2 = Heatmap(mat2, name = "ht2")
class(ht1)
## [1] "Heatmap"
## attr(,"package")
## [1] "ComplexHeatmap"
class(ht2)
## [1] "Heatmap"
## attr(,"package")
## [1] "ComplexHeatmap"
ht1 + ht2
Under default mode, dendrograms from the second heatmap will be removed and row orders will be same as the first one.
The returned value of addition of two heatmaps is a HeatmapList
object. Directly calling ht_list
object
will call draw()
method with default settings. With explicitly calling draw()
method, you can have more controls
e.g. on the legend and titles.
ht_list = ht1 + ht2
class(ht_list)
## [1] "HeatmapList"
## attr(,"package")
## [1] "ComplexHeatmap"
You can append any number of heatmaps to the heatmap list. Also you can append a heatmap list to a heatmap list.
ht1 + ht1 + ht1
ht1 + ht_list
ht_list + ht1
ht_list + ht_list
NULL
can be added to the heatmap list. It would be convinient when users want to construct a heatmap list through a for
loop.
ht_list = NULL
for(s in sth) {
ht_list = ht_list + Heatmap(...)
}
A heatmap list also has titles which are independent to the heatmap titles.
ht1 = Heatmap(mat1, name = "ht1", row_title = "Heatmap 1", column_title = "Heatmap 1")
ht2 = Heatmap(mat2, name = "ht2", row_title = "Heatmap 2", column_title = "Heatmap 2")
ht_list = ht1 + ht2
draw(ht_list, row_title = "Two heatmaps, row title", row_title_gp = gpar(col = "red"),
column_title = "Two heatmaps, column title", column_title_side = "bottom")
The gaps between heatmaps can be set by gap
argument with a unit
object.
draw(ht_list, gap = unit(1, "cm"))
draw(ht_list + ht_list, gap = unit(c(3, 6, 9, 0), "mm"))
## Warning in .local(object, ...): Heatmap/row annotation names are duplicated: ht1, ht2
The width for some (not all) heatmaps can be set to a fixed width.
ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1")
ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2", width = unit(5, "cm"))
ht1 + ht2
or the width can be set as relative values. Please not in this case, width
for all heatmaps
should be set (relative width and fixed width can be mixed).
ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1", width = 2)
ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2", width = 1)
ht1 + ht2
There are some automatic adjustment if more than one heatmaps are plotted. There should be a main heatmap which by default is the first one. Some settings for the remaining heatmaps will be modified to the settings in the main heatmap. The adjustment are:
The main heatmap can be specified by main_heatmap
argument. The value can be a numeric index or the name of the heatmap
(of course, you need to set the heatmap name when you create the Heatmap
object).
ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1", km = 2)
ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2")
ht1 + ht2
# note we changed the order of `ht1` and `ht2`
draw(ht2 + ht1)
# here although `ht1` is the second heatmap, we specify `ht1` to be
# the main heatmap by explicitely setting `main_heatmap` argument
draw(ht2 + ht1, main_heatmap = "ht1")
If there is no row clustering in the main heatmap, all other heatmaps have no row clustering neither.
ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1", cluster_rows = FALSE)
ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2")
ht1 + ht2
ht_global_opt()
can set graphic parameters for dimension names and titles as global settings.
ht_global_opt(heatmap_row_names_gp = gpar(fontface = "italic"),
heatmap_column_names_gp = gpar(fontsize = 14))
ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1")
ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2")
ht1 + ht2
ht_global_opt(RESET = TRUE)
Following are global settings supported by ht_global_opt()
. By this function, you can also control settings
for the legends.
names(ht_global_opt())
## [1] "heatmap_row_names_gp" "heatmap_column_names_gp"
## [3] "heatmap_row_title_gp" "heatmap_column_title_gp"
## [5] "heatmap_legend_title_gp" "heatmap_legend_title_position"
## [7] "heatmap_legend_labels_gp" "heatmap_legend_grid_height"
## [9] "heatmap_legend_grid_width" "heatmap_legend_grid_border"
## [11] "annotation_legend_title_gp" "annotation_legend_title_position"
## [13] "annotation_legend_labels_gp" "annotation_legend_grid_height"
## [15] "annotation_legend_grid_width" "annotation_legend_grid_border"
## [17] "fast_hclust"
row_order
, column_order
, row_dend
and column_dend
can be used to retrieve corresponding information from
the heatmaps. The usage is straightforward by following example:
ht_list = ht1 + ht2
row_order(ht_list)
## [[1]]
## [1] 8 3 4 1 5 7 2 6 9 11 10 12
column_order(ht_list)
## $ht1
## [1] 5 1 3 2 7 9 6 10 8 4
##
## $ht2
## [1] 9 4 6 7 8 1 5 10 3 2
row_dend(ht_list)
## [[1]]
## 'dendrogram' with 2 branches and 12 members total, at height 16.14288
column_dend(ht_list)
## $ht1
## 'dendrogram' with 2 branches and 10 members total, at height 8.069474
##
## $ht2
## 'dendrogram' with 2 branches and 10 members total, at height 6.883646
If ht_list
has not been drawn yet, calling these four functions would be a little bit slow if the matrix are huge.
But if ht_list
is already drawn which means clustering is already applied to the matrix, it will be fast to retrieve
these information.
ht_list = draw(ht1 + ht2)
row_order(ht_list)
column_order(ht_list)
row_dend(ht_list)
column_dend(ht_list)
Row annotations can be added to the heatmap list, please see Heatmap Annotation for more explanations.
From version 1.11.1, settings for row order/clustering for the main heatmap can be directly set
in draw()
method. This makes it convinient to switch main heatmaps without modifying settings in individual
heatmaps. Actually settings specified in draw()
will overwrite corresponding settings in the main heatmap.
split = rep(c("a", "b"), each = 6)
ht_list = Heatmap(mat1, name = "mat1", cluster_rows = FALSE, column_title = "mat1") +
Heatmap(mat2, name = "mat2", cluster_rows = FALSE, column_title = "mat2")
draw(ht_list, main_heatmap = "mat1", split = split)
draw(ht_list, main_heatmap = "mat2", km = 2, cluster_rows = TRUE)
draw(ht_list, cluster_rows = TRUE, main_heatmap = "mat1", show_row_dend =TRUE)
draw(ht_list, cluster_rows = TRUE, main_heatmap = "mat2", show_row_dend =TRUE)
sessionInfo()
## R version 3.5.1 Patched (2018-07-12 r74967)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 16.04.5 LTS
##
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.8-bioc/R/lib/libRblas.so
## LAPACK: /home/biocbuild/bbs-3.8-bioc/R/lib/libRlapack.so
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8
## [4] LC_COLLATE=C LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C
## [10] LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats4 parallel grid stats graphics grDevices utils datasets methods
## [10] base
##
## other attached packages:
## [1] dendextend_1.9.0 dendsort_0.3.3 cluster_2.0.7-1 IRanges_2.16.0
## [5] S4Vectors_0.20.0 BiocGenerics_0.28.0 HilbertCurve_1.12.0 circlize_0.4.4
## [9] ComplexHeatmap_1.20.0 knitr_1.20 markdown_0.8
##
## loaded via a namespace (and not attached):
## [1] mclust_5.4.1 Rcpp_0.12.19 mvtnorm_1.0-8 lattice_0.20-35
## [5] png_0.1-7 class_7.3-14 assertthat_0.2.0 mime_0.6
## [9] R6_2.3.0 GenomeInfoDb_1.18.0 plyr_1.8.4 evaluate_0.12
## [13] ggplot2_3.1.0 highr_0.7 pillar_1.3.0 GlobalOptions_0.1.0
## [17] zlibbioc_1.28.0 rlang_0.3.0.1 lazyeval_0.2.1 diptest_0.75-7
## [21] kernlab_0.9-27 whisker_0.3-2 GetoptLong_0.1.7 stringr_1.3.1
## [25] RCurl_1.95-4.11 munsell_0.5.0 compiler_3.5.1 pkgconfig_2.0.2
## [29] shape_1.4.4 nnet_7.3-12 tidyselect_0.2.5 gridExtra_2.3
## [33] tibble_1.4.2 GenomeInfoDbData_1.2.0 viridisLite_0.3.0 crayon_1.3.4
## [37] dplyr_0.7.7 MASS_7.3-51 bitops_1.0-6 gtable_0.2.0
## [41] magrittr_1.5 scales_1.0.0 stringi_1.2.4 XVector_0.22.0
## [45] viridis_0.5.1 flexmix_2.3-14 bindrcpp_0.2.2 robustbase_0.93-3
## [49] fastcluster_1.1.25 HilbertVis_1.40.0 rjson_0.2.20 RColorBrewer_1.1-2
## [53] tools_3.5.1 fpc_2.1-11.1 glue_1.3.0 trimcluster_0.1-2.1
## [57] DEoptimR_1.0-8 purrr_0.2.5 colorspace_1.3-2 GenomicRanges_1.34.0
## [61] prabclus_2.2-6 bindr_0.1.1 modeltools_0.2-22