Making A List of Heatmaps ======================================== **Author**: Zuguang Gu ( z.gu@dkfz.de ) **Date**: `r Sys.Date()` ------------------------------------------------------------- ```{r global_settings, echo = FALSE, message = FALSE} 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) ``` 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**](s9.examples.html) vignette as well as [in the supplementaries](http://jokergoo.github.io/supplementary/ComplexHeatmap-supplementary1-4/index.html) of [the ComplexHeatmap paper](http://bioinformatics.oxfordjournals.org/content/early/2016/05/20/bioinformatics.btw313.abstract). ## Heatmap concatenation 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. ```{r heatmap_list_default, fig.width = 10} 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) class(ht2) 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. ```{r} ht_list = ht1 + ht2 class(ht_list) ``` You can append any number of heatmaps to the heatmap list. Also you can append a heatmap list to a heatmap list. ```{r, eval = FALSE} 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. ```{r, eval = FALSE} ht_list = NULL for(s in sth) { ht_list = ht_list + Heatmap(...) } ``` ## Titles A heatmap list also has titles which are independent to the heatmap titles. ```{r heatmap_list_title, fig.width = 10} 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") ``` ## Gaps between heatmaps The gaps between heatmaps can be set by `gap` argument with a `unit` object. ```{r heatmap_list_gap, fig.width = 10, fig.keep = "all"} draw(ht_list, gap = unit(1, "cm")) draw(ht_list + ht_list, gap = unit(c(3, 6, 9, 0), "mm")) ``` ## Size of heatmaps The width for some (not all) heatmaps can be set to a fixed width. ```{r heatmap_list_size, fig.width = 10, fig.keep = "all"} 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). ```{r heatmap_list_relative_size, fig.width = 10, fig.keep = "all"} ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1", width = 2) ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2", width = 1) ht1 + ht2 ``` ## Auto adjustment 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: - row clusters are removed. - row titles are removed. - if the main heatmap is split by rows, all remaining heatmaps will also be split by same levels as the main one. 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). ```{r heatmap_list_auto_adjust, fig.width = 10, fig.keep = "all"} 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. ```{r heatmap_list_auto_adjust_no_row_cluster, fig.width = 10} ht1 = Heatmap(mat1, name = "ht1", column_title = "Heatmap 1", cluster_rows = FALSE) ht2 = Heatmap(mat2, name = "ht2", column_title = "Heatmap 2") ht1 + ht2 ``` ## Change graphic parameters simultaneously `ht_global_opt()` can set graphic parameters for dimension names and titles as global settings. ```{r, fig.width = 10} 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. ```{r} names(ht_global_opt()) ``` ## Retrieve orders and dendrograms `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: ```{r} ht_list = ht1 + ht2 row_order(ht_list) column_order(ht_list) row_dend(ht_list) column_dend(ht_list) ``` 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. ```{r, eval = FALSE} ht_list = draw(ht1 + ht2) row_order(ht_list) column_order(ht_list) row_dend(ht_list) column_dend(ht_list) ``` ## Heatmap list with row annotations Row annotations can be added to the heatmap list, please see [**Heatmap Annotation**](s4.heatmap_annotation.html) for more explanations. ## Modify row orders/clustering in main heatmap 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. ```{r, fig.width = 8} 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) ``` ## Session info ```{r} sessionInfo() ```