jokergoo / ComplexHeatmap

Make Complex Heatmaps
https://jokergoo.github.io/ComplexHeatmap-reference/book/
Other
1.31k stars 230 forks source link

Dotplot heat map using grid.circle changes with row/column_split #982

Closed BenJCQuah closed 2 years ago

BenJCQuah commented 2 years ago

Hi,

Thanks for your awesome heatmap package,

I am trying to make a dotplot heat map using grid.circle in cell_fun. When I plot without row_split and column_split the plot looks as it should, but as soon as I enable split, the circles no longer scale correctly.

The code I am using as follows. Is there any way of using split and grid.circle together?

Thanks!

Ben

png("test2.png",width=18,height=18,units="cm",res=300)
Heatmap(rdata,
        name = "MedFI diff",
        rect_gp = gpar(type = "none"), 
        col = col_fun, 
        column_title = "%s", 
        column_title_gp = gpar(fontsize = 8, fontface = "plain"),
        column_title_rot = 0,
        column_names_side = "bottom",
        column_names_gp = gpar(fontsize = 5, fontface = "plain"),
        cluster_columns = col_dend, 
        show_column_dend = TRUE,
        column_dend_side = "top",
        column_dend_height = unit(1, "cm"),
        row_title = "%s", #FOR CLSUTER TITLE
        row_title_gp = gpar(fontsize = 8, fontface = "plain"),
        row_title_rot = 0,
        row_names_side = "right",
        row_names_gp = gpar(fontsize = 5, fontface = "plain"),
        cluster_rows = row_dend, 
        show_row_dend = TRUE,
        row_dend_side = "left", 
        row_dend_width = unit(1, "cm"),
        row_split = 12, column_split = 15, # THIS CAUSES THE PROBLEM WHEN ENABLED
        border = TRUE,
        cell_fun = function(j, i, x, y, width, height, fill) {
          grid.circle(x = x, y = y, r = abs(rdata[i, j])/100,
                      gp = gpar(fill = col_fun(rdata[i, j]), col = NA))
        }
  ) 
dev.off()
jokergoo commented 2 years ago

I would suggest to set r directly on width and height. Check the following example:

m = matrix(rnorm(100), 10)

max_value = max(abs(m))
cell_fun = function(j, i, x, y, width, height, fill) {
  width = convertWidth(width, "mm")
  height = convertHeight(height, "mm")
  r = abs(m[i, j])/max_value * min(unit.c(width, height))*0.5
  grid.circle(x = x, y = y, r = r,
              gp = gpar(fill = NA, col = "black"))
}

Heatmap(m, cell_fun = cell_fun, row_km = 4)

Here it is important to convert width and height to physical units.

BenJCQuah commented 2 years ago

Thank you for your quick response! This worked perfectly! Thank you.

tvegawaichman commented 1 year ago

Hello! I want to know how I could add grid.circle to the legend and have the same relationship between the circles in the heatmap and the ones in the legend. Thank you!