Question: How to extract cell positions from pheatmap
1
gravatar for sunnysean
12 months ago by
sunnysean20
sunnysean20 wrote:

Hi, I am trying to add points and lines to some certain cells in pheatmap image. But it is very hard to get their positions by extracting them from pheatmap object. Manually obtaining the positions with locator() or something like this is not a good way, as it cannot handle a bulk of points. Anyone can help me?

R • 513 views
ADD COMMENTlink modified 12 months ago by Kevin Blighe60k • written 12 months ago by sunnysean20
2
gravatar for Kevin Blighe
12 months ago by
Kevin Blighe60k
Kevin Blighe60k wrote:

I don't think that there is any quick way to do what you want. One way is to use grid functions:

1, create random data

data <- replicate(20, rnorm(50))
rownames(data) <- paste("Gene", c(1:nrow(data)))
colnames(data) <- paste("Sample", c(1:ncol(data)))

2, create col and row metadata

metadata <- data.frame(
      c(rep("case", ncol(data)/2), rep("control", ncol(data)/2)),
      c(rep("cond1", ncol(data)/4), rep("cond2", ncol(data)/4), rep("cond3", ncol(data)/4), rep("cond4", ncol(data)/4)),
      row.names=colnames(data))
colnames(metadata) <- c("casecontrol","condition")

metadata_gene <- data.frame(
      c(rep("Tcell", nrow(data)/2), rep("Bcell", nrow(data)/2)),
      row.names=rownames(data))
colnames(metadata_gene) <- c("Cell")

3, create the heatmap

require(pheatmap)
out <- pheatmap(data, 
      show_rownames=F, cluster_cols=T, cluster_rows=T, scale="row",
      cex=1, clustering_distance_rows="euclidean", cex=1,
      clustering_distance_cols="euclidean", clustering_method="complete", border_color=FALSE,
      annotation_col=metadata,
      annotation_row=metadata_gene)

4, add annotation

Add a vertical line at 8th column

grid.lines(
  x = unit(c(8/ncol(data), 8/ncol(data)), "npc"),
  y = c(0.1, 0.9),
  gp = gpar(lty = 2, lwd = 3, col = "black"))

The x and y relate to c(x1, x2) and c(y1, y2), respectively. A useful way to quickly identify regions is to do as I have done for x, i.e.,

  • c(8/ncol(data), 8/ncol(data)), x1 x2 will relate roughly to 8th column
  • c(15/ncol(data), 15/ncol(data)), x1 x2 will relate roughly to 15th column
  • et cetera

Horizontal line at middle, from 1st to 18th column:

grid.lines(
  x = unit(c(1/ncol(data), 18/ncol(data)), "npc"),
  y = c(0.5, 0.5),
  gp = gpar(lty = 2, lwd = 3, col = "royalblue"))

add an arrow

grid.lines(
  x = unit(c(10/ncol(data), 13/ncol(data)), "npc"),
  y = unit(c(0.6, 0.6), "npc"),
  gp = gpar(fill="black"),
  arrow = arrow(length = unit(0.25, "inches"), ends="last", type="closed"))

add text

grid.text(
  bquote(Key~cell),
  x = unit(c(10/ncol(data)), "npc"),
  y = 0.6,
  just = "top",
  rot = 0,
  gp=gpar(col="black", fontsize=18, face="bold"))

f

You can look up other grid functions so that you can draw points, et cetera.

Other ways of editing pheatmap objects: A: pheatmap annotation - legend only for columns

Kevin

ADD COMMENTlink written 12 months ago by Kevin Blighe60k

Thanks for your answer. I am using RStudio, where your codes seems not work very well for unknown reason. Take these codes for example: grid.lines( x = unit(c(8/ncol(data), 8/ncol(data)), "npc"), y = c(0.1, 0.9), gp = gpar(lty = 2, lwd = 3, col = "black")).

The position of added line always change when I resize the plot window in Rstudio. I want to output a pdf picture, but the position of added line is totally wrong for the same reason.

Then, I followed your second suggestion, using grob.

grid.ls(grid.force()) a=grid.get('GRID.rect.91') # return all the cells of pheatmap matrix rects a$x; a$y # this gives the coordinates of every cell. grid.point(a$x[1], a$y[1]) # this doesn't draw a point on the up-left cell of pheatmap matrix rects

The coordinates system seems conflicting. Could you give any more suggestion?

ADD REPLYlink written 12 months ago by sunnysean20
Please log in to add an answer.

Help
Access

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.
Powered by Biostar version 2.3.0
Traffic: 1246 users visited in the last hour