jokergoo / ComplexHeatmap

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

anno_block from data.table #1223

Closed rbutleriii closed 1 day ago

rbutleriii commented 1 day ago

I have a data.table with the annotations for my columns, and am interested in coloring sections of an anno_block and labeling them inside to match a column in that data.frame. It seems like align_to would be the best approach, but I wanted to check before I try to figure out how to convert a column to a named list of indices. Is there a way to use the data.table more directly?

  # upper annot
  ad_anno = ad[, Consensus_Cluster]
  col = list(
      "Astroglial" = "#FAFF34", 
      "Microglial" = "#62B0B0", 
      "Neuronal" = "#7E2221", 
      "Oligodendroglial" = "#6CC835", 
      "Proteostasis" = "#280808"
  )
  ha = HeatmapAnnotation(
    "Consensus Cluster" = anno_block(
      align_to = ???, # convert ad_anno$`Consensus_Cluster` into named list of indices
      gp = gpar(fill = col),
      labels = names(col), 
      labels_gp = gpar(col = "white"), 
      show_name = TRUE
    ), 
    show_legend = FALSE #,
  )

Where the top block annotation has white text inside, and the ad_anno data.table has a column for Consensus_cluster giving the label for each column. The final figure looks like this: 366604617-39e3ea8a-7e80-4092-92ef-5a9dec6bb195

rbutleriii commented 1 day ago

Now looks like:

  # upper annot
  col = list(
      "Astroglial" = "#FAFF34", 
      "Microglial" = "#62B0B0", 
      "Neuronal" = "#7E2221", 
      "Oligodendroglial" = "#6CC835", 
      "Proteostasis" = "#280808"
  )
  ad_ind <- lapply(names(col), function(i) which(ad[, Consensus_Cluster] %in% i))
  names(ad_ind) <- names(col)
  ha = HeatmapAnnotation(
    "Consensus Cluster" = anno_block(
      align_to = ad_ind, # convert ad_anno$`Consensus_Cluster` into named list of indices
      gp = gpar(fill = col),
      labels = names(col), 
      labels_gp = gpar(col = "white"), 
      show_name = TRUE
    ), 
    show_legend = FALSE
  )

But throws an error:

Error in validGP(list(...)) :
  'fill' gpar list components must all be patterns
Calls: lapply ... anno_block -> AnnotationFunction -> gpar -> validGP
Execution halted
rbutleriii commented 1 day ago

Here is a version using iris as the dataset:

# upper annot
ad <- data.table(iris)
mat <- t(ad[, 1:4])
col = list(
    "setosa" = "#FAFF34", 
    "versicolor" = "#62B0B0", 
    "virginica" = "#7E2221"
)
ad_ind <- lapply(names(col), function(i) which(ad[, Species] %in% i))
names(ad_ind) <- names(col)
ha = HeatmapAnnotation(
  "Consensus Cluster" = anno_block(
    align_to = ad_ind, # convert ad_anno$`Consensus_Cluster` into named list of indices
    # gp = gpar(fill = col),
    labels = names(col), 
    labels_gp = gpar(col = "white"), 
    show_name = TRUE
  ), 
  show_legend = FALSE
)
# heatmap plot 
a = Heatmap(mat, 
  cluster_rows = FALSE, 
  cluster_columns = FALSE, 
  na_col = "#FFFFFF", 
  row_names_side = "left",
  top_annotation = ha 
)

Gives an error specifying Error in panel_fun(index[ind], names(align_to)[ai]) : could not find function "panel_fun" Is the panel_fun required?

rbutleriii commented 1 day ago

Looks like I have it working on the test set:

# upper annot
ad <- data.table(iris)
mat <- t(ad[, 1:4])
col = list(
    "setosa" = "#FAFF34", 
    "versicolor" = "#62B0B0", 
    "virginica" = "#7E2221"
)
ad_anno = unique(ad, by=c("Species"))[, Species]
ad_ind <- lapply(names(col), function(i) which(ad[, Species] %in% i))
names(ad_ind) <- names(col)
panel_fun = function(index, nm) {
    grid.rect(gp = gpar(fill = col[[nm]], col = col[[nm]]))
    grid.text(
      label = nm, 
      x = 0.5, 
      y = 0.5, 
      gp = gpar(col = "white", fontface = "bold")
    )
}
ha = HeatmapAnnotation(
  "Consensus Cluster" = anno_block(
    align_to = ad_ind, # convert ad_anno$`Consensus_Cluster` into named list of indices
    panel_fun = panel_fun,
    # show_name = TRUE
  )
)
# heatmap plot 
a = Heatmap(mat, 
  cluster_rows = FALSE, 
  cluster_columns = FALSE, 
  na_col = "#FFFFFF", 
  column_split = ad[, Species], 
  column_gap = unit(5, "mm"), 
  column_title = "Test title",
  column_title_gp = gpar(fontsize = 20, fontface = "bold"),
  row_names_side = "left",
  top_annotation = ha 
)

image