ComplexHeatmap icon indicating copy to clipboard operation
ComplexHeatmap copied to clipboard

color code for HeatmapAnnotation/top_annotation changes and is inconsistent. Is the a option to mimic pheatmap here?

Open ChristianRohde opened this issue 1 year ago • 4 comments

Hi,

is it possible to control the HeatmapAnnotation colors for the top_annotation in a similar way that I get colors with pheatmap? I created a shiny were one can select cols/items from the sample follow up. With pheatmap I will always get a consistent color scheme with the same colors just defined by the order of the items as selected. However with Complexheatmap with each new rendering all colors will change. Please have a look at the examples below.

Unfortunately, when working with ComplexHeatmap this means that once I remove a sample, gene or add an item to the top_annotation the color code changes of the top_annotation changes completely. The only workaround is to manually provide settings for each item. This requires a lot of effort and even worse means that I have to adapt the script to each data set and cannot write a shiny which works with all data set we have. At the moment this is the reason why I prefer pheatmap. However, here I have the problem that somehow only one plot in my shiny app works consistently while the others are subject to the re-sizing issue described here: https://github.com/raivokolde/pheatmap/issues/85. OK, that's not the point here, but maybe someone knows a real workaround for pheatmap. I would be happy with pheatmap otherwise...

Example ComplexHeatmap with 3 and 4 selected items as top_annotation: Complexheatmap3 ComplexHeatmap4

Example pheatmap with 3 and 4 selected items as annotation_col: pheatmap3 pheatmap4

ChristianRohde avatar Sep 14 '22 10:09 ChristianRohde

It is because you are use random colors and when you remove genes or samples, you actually make a new heatmap where a new set of random colors will be used.

I think manually set colors for all annotations is not that complex:

library(circlize)
FAB_color = structure(rand_color(length(unique(FAB)), names = unique(FAB))
sex_color = structure(rand_color(length(unique(sex)), names = unique(sex))
...
# for numeric annotations
age_col = colorRamp2(c(0, 80), c("white", "green"))
...

If you use pheatmap and if samples from a group are all removed (e.g. M1 in FAB), you will also get inconsistent colors.

jokergoo avatar Sep 28 '22 18:09 jokergoo

thank you for the answer. My point is that I do not want to set colors individually by colnames, since a) this is very tedious for larger follow-up data sets and b) sometimes in a ShinyApp I do not know beforehand the exact sample follow up which will be provided. I observed that while ComplexHeatmap indeed uses random color (if you do not specify by colnames beforehand) the behavior of pheatmap is different: it always uses the same colors for the first, second, third etc. item. I found this very helpful in terms of easy programming for my ShinyApps.

ChristianRohde avatar Sep 28 '22 18:09 ChristianRohde

I totally understand the pain of setting nice and distinct colors for a larger number of annotations. If the samples are fixed, actually you can simply set a same random seed before calling Heatmap(), then in every run of the heatmap, the same set of random colors will always be used. But if the number of samples changes (or the number of unique annotation levels changes), the colors will also change.

The default color schema in pheatmap depends on the number of unique levels in every annotation. In your shiny app, assume users remove all samples in a group, I believe the color schema will change. In your example, AL samples are in pink, and if all samples in AL are removed, I believe AML samples will become pink.

Last, to develop a shiny app for other people to use, I think it is necessary to make all the color schemas "precise", which means you need to explicitly set colors for all annotations. Even for new annotations which are provided by users, you should also generate a color set for them and keep them unchanged in the shiny session.

jokergoo avatar Sep 28 '22 18:09 jokergoo

you are correct, the color swaps and AML got the color from AL. Sure, in a productive Shiny for publication colors need to be set because of this reason. In a more informal Shiny this still would be OK for me. This is the part where I would have expected a color change. Next using set.seed() I can fix the colors for ComplexHeatmap as well. Now it gives me the same color if I select the same conditions. That was a great hint, thanks. The unexpected part is that by removing the only AL or M5 sample in both pheatmap & ComplexHeatmap the color code for sex change although the factor levels stay the same. In case of ComplexHeatmap even age changes the color while it keeps consistent in pheatmap. But right, it is hard to talk about consistency here and manual annotation finally will be the key.

ChristianRohde avatar Sep 28 '22 20:09 ChristianRohde