Table of Contents

Making A List of Heatmaps

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

Date: 2018-06-19


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.

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.

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

plot of chunk heatmap_list_default

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(...)
}

Titles

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")

plot of chunk heatmap_list_title

Gaps between heatmaps

The gaps between heatmaps can be set by gap argument with a unit object.

draw(ht_list, gap = unit(1, "cm"))

plot of chunk heatmap_list_gap

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

plot of chunk heatmap_list_gap

Size of heatmaps

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

plot of chunk heatmap_list_size

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

plot of chunk heatmap_list_relative_size

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:

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

plot of chunk heatmap_list_auto_adjust

# note we changed the order of `ht1` and `ht2`
draw(ht2 + ht1)

plot of chunk heatmap_list_auto_adjust

# 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")

plot of chunk heatmap_list_auto_adjust

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

plot of chunk heatmap_list_auto_adjust_no_row_cluster

Change graphic parameters simultaneously

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

plot of chunk unnamed-chunk-4

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"

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:

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)

Heatmap list with row annotations

Row annotations can be added to the heatmap list, please see Heatmap Annotation 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.

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)

plot of chunk unnamed-chunk-8

draw(ht_list, main_heatmap = "mat2", km = 2, cluster_rows = TRUE)

plot of chunk unnamed-chunk-8

draw(ht_list, cluster_rows = TRUE, main_heatmap = "mat1", show_row_dend =TRUE)

plot of chunk unnamed-chunk-8

draw(ht_list, cluster_rows = TRUE, main_heatmap = "mat2", show_row_dend =TRUE)

plot of chunk unnamed-chunk-8

Session info

sessionInfo()
## R version 3.5.0 (2018-04-23)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 16.04.4 LTS
## 
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.7-bioc/R/lib/libRblas.so
## LAPACK: /home/biocbuild/bbs-3.7-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.8.0      dendsort_0.3.3        cluster_2.0.7-1       HilbertCurve_1.10.1  
##  [5] GenomicRanges_1.32.3  GenomeInfoDb_1.16.0   IRanges_2.14.10       S4Vectors_0.18.3     
##  [9] BiocGenerics_0.26.0   circlize_0.4.4        ComplexHeatmap_1.18.1 knitr_1.20           
## [13] markdown_0.8         
## 
## loaded via a namespace (and not attached):
##  [1] fastcluster_1.1.25     shape_1.4.4            modeltools_0.2-21      GetoptLong_0.1.7      
##  [5] kernlab_0.9-26         lattice_0.20-35        colorspace_1.3-2       viridisLite_0.3.0     
##  [9] rlang_0.2.1            pillar_1.2.3           prabclus_2.2-6         RColorBrewer_1.1-2    
## [13] fpc_2.1-11             GenomeInfoDbData_1.1.0 plyr_1.8.4             robustbase_0.93-0     
## [17] stringr_1.3.1          zlibbioc_1.26.0        munsell_0.5.0          gtable_0.2.0          
## [21] GlobalOptions_0.1.0    mvtnorm_1.0-8          evaluate_0.10.1        flexmix_2.3-14        
## [25] class_7.3-14           highr_0.7              DEoptimR_1.0-8         trimcluster_0.1-2     
## [29] Rcpp_0.12.17           scales_0.5.0           diptest_0.75-7         XVector_0.20.0        
## [33] mime_0.5               gridExtra_2.3          rjson_0.2.20           ggplot2_2.2.1         
## [37] png_0.1-7              stringi_1.2.3          tools_3.5.0            HilbertVis_1.38.0     
## [41] bitops_1.0-6           magrittr_1.5           RCurl_1.95-4.10        lazyeval_0.2.1        
## [45] tibble_1.4.2           whisker_0.3-2          MASS_7.3-50            viridis_0.5.1         
## [49] mclust_5.4             nnet_7.3-12            compiler_3.5.0