Combining ComplexHeatmap with other plot types
1
1
Entering edit mode
my4 ▴ 10
@my4-10129
Last seen 5.1 years ago

I have two plots that I want to place next to each other on a grid.  If they were both ggplot2 plots I'd just do something like this:

plot_grid(plot_a,plot_b,ncol=2)

using the cowplot package.

However, one of my plots I have created using the ComplexHeatmap package.  While the other is created with ggplot2.  That is:

> class(plot_a)
[1] "gg"     "ggplot"
> class(plot_b)
[1] "Heatmap"
attr(,"package")
[1] "ComplexHeatmap"

How can I combine these plots in a grid and more generally what is the recommended way of making a grid of plots of different types?

Thanks.

complexheatmap ggplot2 • 5.5k views
4
Entering edit mode
Zuguang Gu ▴ 220
@zuguang-gu-7797
Last seen 5 weeks ago
Germany / Heidelberg / DKFZ

You can use grid.grabExpr() to capture the output of ComplexHeatmap as a grob object and later you can arrange this grob object by other packages which do layout.

Note you need to explicitly use draw() on the heatmap object.

grob = grid.grabExpr(draw(Heatmap(...)))

0
Entering edit mode

This was exactly what I was looking for.  Thank you!

0
Entering edit mode

Thank you for this great package!

In line with this answer I am wondering if there is any way to extract the annotation(s) as a separate grob, for increased flexibility in combination with the plot_grid function in the cowplot package, similar the solution for extracting legend (se below)?

The legend can be extracted by:

hm_legend = draw(hm)
hm_legend = color_mapping_legend(hm_legend@ht_list[[1]]@matrix_color_mapping, legend_direction = "horizontal",plot = FALSE)


With regards,

0
Entering edit mode

The heatmap annotations are drawn by draw,HeatmapAnnotation-method. You can check the documentation at https://jokergoo.github.io/ComplexHeatmap/reference/draw-HeatmapAnnotation-method.html

To draw the animations, you need to first create a viewport to put them:

gb = grid.grabExpr({
pushViewport(viewport(...))
draw(ht@top_annotation, index = ...) # index contains the column order
popViewport()
})

0
Entering edit mode

I am still struggeling to get the annotation-bar identical to the one in the heatmap-object. Either I can use draw on the 'HeatmapAnnotation' object directly, but then the ordering and the position and the width are not the same as the heatmap main body, or I can try to extract the annotation from the annotation-slot in the heatmap-list as you have shown, but still I am facing difficulties getting the size, position, gap, column split, ordering of columns correct. Ideally I would like to extract all this as it is in the heatmap-list object, and draw the grob separately in the plot_grid function.

With regards,

0
Entering edit mode

Then I would suggest using HeatmapAnnotation(...) %v% NULL, but still you need to manually set the order. You can try the following code, but I am not sure they 100% work:

# first make the heatmap with the annotations
ha  # this is your annotation
ht = Heatmap(..., top_annotation_ha)
ht = draw(ht)
column_order = column_order(ht) # this gives you the column order after clustering

# next only draw the heatmap annotation
draw(ha[column_order] %v% NULL)

0
Entering edit mode

This is getting close, thanks again! I am still not able to make the topannotation have columnsplit as the heatmap body do, and am also struggling to make the top_annotation grob have the same x-position and width as the heatmap body.

To get the column_order I used

column_order<-unlist(column_order(ht))

0
Entering edit mode

Then can you try to put the top annotation with a zero-row matrix?

m = matrix(nrow = 0, ncol = ...)
ht = Heatmap(m, top_annotation = ha, column_split = ...)
draw(ht)

0
Entering edit mode

This is even closer, the gap and the splitting and order are right. Still I do not have the proper width and x-position for the annotation bar, to make it inheret the space above the heatmap main body, for alignment, as the heatmap also has dendrograms and row labels.

Here is my code, although not working without input variables split_cell etc.:

ha_t <- HeatmapAnnotation(df=ann,col=colours1,name="Cancer or control", show_annotation_name = FALSE, annotation_legend_param = list(title = "Cancer or control"), show_legend = FALSE)

ht = draw(hm)

column_order<-unlist(column_order(ht))

m = matrix(nrow = 0, ncol = 46)

ht_a = Heatmap(m, top_annotation = ha_t, column_split = split_cell,column_order = column_order,
column_gap=unit(c(5,2), "mm"))
ht_a = draw(ht_a)
gb<-grid.grabExpr(draw(ht_a))

0
Entering edit mode

It is not a ggplot2 plot, so it won't automatically align to other figures, you should manually adjust the plot size by the padding argument, e.g.draw(ht_a, padding = unit(c(1, 1, 1, 1), "mm")). The four values are the space on the bottom, left, top and right of the heatmap.

0
Entering edit mode

Thank you again for very good help!