Align legends to each heatmap in a ComplexHeatmap with 2 heatmaps
1
1
Entering edit mode
Ram ▴ 220
@ram
Last seen 7 weeks ago
United States

I have created a ComplexHeatmap containing 2 Heatmaps, each with their own legend. The legend on the first Heatmap is continuous, whereas that of the second is discrete.

When I concatenate these Heatmaps vertically, and draw the HeatmapList, their legends are auto-aligned to the center of the plot. Is there any way I can have these legends positioned centered to the respective heatmaps and not to the center of the plot?

This is what I have:

Here's what I'd like to have:

How can I go about solving this problem? I'd really like to avoid creating customized Legends if I can, but if that's what it takes, that works too.

Thank you in advance for any help/pointers!

Note: I initially created this post on Bioinformatics SE, but since this is a Bioconductor package, I feel this question belongs here.

sessionInfo:

> sessionInfo()
R version 3.5.1 (2018-07-02)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: macOS  10.14.4

Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Users/ram/miniconda3/lib/R/lib/libRblas.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] viridis_0.5.1        viridisLite_0.3.0    ComplexHeatmap_2.1.0 forcats_0.4.0       
 [5] stringr_1.4.0        dplyr_0.8.0.1        purrr_0.2.5          readr_1.3.1         
 [9] tidyr_0.8.3          tibble_2.1.1         ggplot2_3.1.1        tidyverse_1.2.1     

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.0          RColorBrewer_1.1-2  compiler_3.5.1      pillar_1.3.1        cellranger_1.1.0   
 [6] plyr_1.8.4          tools_3.5.1         clue_0.3-57         jsonlite_1.6        lubridate_1.7.4    
[11] gtable_0.3.0        nlme_3.1-137        lattice_0.20-38     png_0.1-7           pkgconfig_2.0.2    
[16] rlang_0.3.1         cli_1.1.0           rstudioapi_0.10     parallel_3.5.1      haven_2.1.0        
[21] gridExtra_2.3       cluster_2.0.7-1     withr_2.1.2         xml2_1.2.0          httr_1.4.0         
[26] GlobalOptions_0.1.0 generics_0.0.2      hms_0.4.2           tidyselect_0.2.5    glue_1.3.0         
[31] R6_2.3.0            GetoptLong_0.1.7    readxl_1.3.1        modelr_0.1.4        magrittr_1.5       
[36] backports_1.1.4     scales_1.0.0        assertthat_0.2.1    rvest_0.3.3         shape_1.4.4        
[41] circlize_0.4.6      colorspace_1.4-1    stringi_1.4.3       lazyeval_0.2.2      munsell_0.5.0      
[46] broom_0.5.2         rjson_0.2.20        crayon_1.3.4

Dummy data and code:

devtools::install_github('jokergoo/ComplexHeatmap');
library(ComplexHeatmap);
library(viridis);

dummy_top_mat <- structure(c(0.4563, 0.2211, 1.2235, 0.067, 1.6859, 1.0936, 0.4533, 
1.6844, 1.0039, 0.5402, 0.6841, 1.498, 1.042, 0.1711, 0.3565, 
2.2814, 3.0516, 1.5012, 0.5367, 3.0846, 1.1909, 0.235, 1.4266, 
0.4858, 2.9054, 0.3733, 0.6902, 0.8555, 0.4234, 2.6778, 0.1568, 
0.5556, 2.0172, 0.8034, 2.2897, 0.1166, 3.8033, 0.1431, 2.0606, 
1.2725, 1.5365, 0.4123, 1.2087, 1.1264, 0.8334, 1.1943, 1.58, 
1.5849, 0.3004, 0.3722, 0.0362, 0.0532, 1.4867, 0.4053, 0.3615, 
0.0897, 1.3217, 1.1447, 1.3058, 0.1903, 0.1067, 0.9482, 1.3382, 
3.2955, 0.391, 1.0418, 0.2041, 1.208, 1.5857, 3.5313, 0.472, 
1.389, 0.2143, 0.0226, 0.029, 0.444, 2.0521, 0.3955, 0.3495, 
0.5062, 1.3236, 1.3234, 0.7111, 0.1176, 2.2223, 1.2073, 0.3964, 
2.1175, 0.3382, 0.2816, 0.71, 3.1417, 0.2402, 0.5793, 0.7662, 
1.6782, 0.0986, 0.087, 0.5447, 2.6672, 1.2498, 1.0676, 1.8608, 
1.8146, 0.1422, 0.4221, 0.0303, 0.9541, 0.7358, 1.7664, 1.5144, 
0.2034, 0.9366, 0.7837, 0.3284, 0.1477, 1.8306, 1.3564, 0.1126, 
0.0171, 2.9858, 0.0233, 0.2796, 0.6995, 1.6081, 0.215, 1.7093, 
0.5178, 1.7061, 2.473, 1.8912, 0.7661, 4.4102, 1.2963, 0.6542, 
0.4281, 0.4491, 0.6, 0.4076, 1.6869, 0.4747, 3.9823, 1.1226, 
2.7355, 2.7036, 0.2241, 0.983, 1.0992, 1.4736, 0.1584, 0.2995, 
0.2272, 0.5744, 0.9314, 0.6924, 0.0812, 1.361, 0.727, 0.1525, 
1.3367, 0.566, 2.7801, 0.2349, 3.2655, 1.0675, 0.449, 0.5411, 
0.8291, 0.52, 0.0507, 0.6538, 0.4636, 1.2063, 0.9784, 0.1925, 
0.0756, 0.136, 1.2529, 0.317, 0.0281, 0.8668, 3.4138, 5.3898, 
0.521, 0.087, 3.4819, 0.1114, 0.0061, 0.9804, 1.139, 1.4159, 
1.0297, 0.6503, 1.0828, 2.3527, 0.057, 0.5602, 0.4017, 0.9985, 
0.8673), .Dim = c(10L, 20L), .Dimnames = list(c("gene01", "gene02", 
"gene03", "gene04", "gene05", "gene06", "gene07", "gene08", "gene09", 
"gene10"), c("sample01", "sample02", "sample03", "sample04", 
"sample05", "sample06", "sample07", "sample08", "sample09", "sample10", 
"sample11", "sample12", "sample13", "sample14", "sample15", "sample16", 
"sample17", "sample18", "sample19", "sample20")));

dummy_bottom_mat <- structure(c("Positive", "Positive", "Positive", "Positive", "Negative", 
"Positive", "Positive", "Positive", "Positive", "Negative", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Negative", "Positive", 
"Negative", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Negative", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Negative", "Positive", "Positive", "Positive", "Negative", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Negative", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Negative", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive", "Positive", "Positive", "Positive", "Positive", "Positive", 
"Positive"), .Dim = c(6L, 20L), .Dimnames = list(c("marker1", 
"marker2", "marker3", "marker4", "marker5", "marker6"), c("sample01", 
"sample02", "sample03", "sample04", "sample05", "sample06", "sample07", 
"sample08", "sample09", "sample10", "sample11", "sample12", "sample13", 
"sample14", "sample15", "sample16", "sample17", "sample18", "sample19", 
"sample20")));

hmap1 <- Heatmap(dummy_top_mat, col = colorRampPalette(viridis(15))(100), name = 'log2 (TPM)', na_col = 'grey60', cluster_rows = FALSE, cluster_columns = FALSE, row_names_side = 'left', column_title_side = 'top', rect_gp = gpar(col='white', lwd=0.5), height=unit(10*0.75,'cm'), width = unit(20*0.75, 'cm'), column_title = 'Gene Expression');

hmap2 <- Heatmap(dummy_bottom_mat, col = c('Negative'='red', 'Positive'='blue'), na_col = 'grey60', row_split = factor( c('gp1','gp1','gp1','gp1','gp2','gp2'), c('gp1','gp2'), ordered = TRUE), name = 'Marker\nStatus', rect_gp = gpar(col='white',lwd=1), row_title = NULL, height = unit(6*0.75,'cm'), width = unit(20*0.75, 'cm'), row_names_side = 'left', column_title = 'Biomarkers');

draw(hmap1 %v% hmap2, ht_gap = unit(1, 'cm'), auto_adjust = FALSE);
complexheatmap r • 3.5k views
ADD COMMENT
2
Entering edit mode
Zuguang Gu ▴ 290
@zuguang-gu-7797
Last seen 28 days ago
Germany / Heidelberg / DKFZ

No, since you put the two heatmaps as one plot, the legends are grouped.

You can either edit in Inkscape or make two heatmaps in two plots. You can get the column of the first heatmap by:

hmap1 = draw(hmap1)
column_order = column_order(hmap1)

and assign to the second heatmap:

Heatmap(..., column_order = column_order)

To make the size of single rows identical for the two heatmaps if you save into two PDF files, you can adjust the height of the PDF files according to following link:

https://jokergoo.github.io/ComplexHeatmap-reference/book/other-tricks.html#set-the-same-cell-size-for-different-heatmaps-with-different-dimensions

ADD COMMENT
0
Entering edit mode

I do use the column_order to unify column order as I'm using auto_adjust = FALSE in the draw(). I also already predicate the height/width of the png output using the number of rows and columns respectively in hmap1.

I need to automate this logic so it can work for any number of rows What you're telling me is to do this:

png(...)
hmp1 <- draw(hmp1, ...)
hmp2 <- Heatmap(..., column_order = column_order(hmp1))
draw(hmp2, x = unit(0, 'npc'), y = <calculated height of hmp1 + ht_gap>)
dev.off()

instead of using hmp1 %v% hmp2?

EDIT: Tried this, it won't work as draw for Heatmap class does not accept x= and y= parameters. How can I automate this?

ADD REPLY
1
Entering edit mode

OK, I see. You want to put the two heatmaps together so that you can compare directly between the two heatmaps. The thing is if you add two heatmaps, the legends are always plotted together. One way I can think to improve this is to move the legends to the bottom of the heatmap:


hmap1 <- Heatmap(dummy_top_mat, col = colorRampPalette(viridis(15))(100), name = 'log2 (TPM)', na_col = 'grey60', cluster_rows = FALSE, cluster_columns = FALSE, row_names_side = 'left', column_title_side = 'top', rect_gp = gpar(col='white', lwd=0.5), height=unit(10*0.5,'cm'), width = unit(20*0.5, 'cm'), column_title = 'Gene Expression',
    show_column_names = FALSE, heatmap_legend_param = list(direction = "horizontal"));

hmap2 <- Heatmap(dummy_bottom_mat, col = c('Negative'='red', 'Positive'='blue'), na_col = 'grey60', row_split = factor( c('gp1','gp1','gp1','gp1','gp2','gp2'), c('gp1','gp2'), ordered = TRUE), name = 'Marker\nStatus', rect_gp = gpar(col='white',lwd=1), row_title = NULL, height = unit(6*0.5,'cm'), width = unit(20*0.5, 'cm'), row_names_side = 'left', column_title = 'Biomarkers',
    heatmap_legend_param = list(direction = "horizontal", nrow = 1, title = "Marker Status"));

draw(hmap1 %v% hmap2, auto_adjust = FALSE,
    heatmap_legend_side = "bottom");

enter image description here

ADD REPLY

Login before adding your answer.

Traffic: 821 users visited in the last hour
Help About
FAQ
Access RSS
API
Stats

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.

Powered by the version 2.3.6