4

I'm quite new to R and stuck on a question. Would it be possible to print a heatmap on a vertex in iGraph? I know I can do a colored square or circle. But would a small heatmap be possible? This is the code that draws my current graph:

    # create graph
graph <- graph.data.frame(network[,1:2])
vertex_names <- get.vertex.attribute(graph,"name")


# define node attributes
V(graph)$label.font <- 1
V(graph)$label.font[which(element_types[vertex_names,"type"]=="PRIMARIES")] <- 2
V(graph)$label.font[which(element_types[vertex_names,"type"]=="REACTION")] <- 2

V(graph)$label <- element_types[vertex_names,"label"]
V(graph)$color <- element_types[vertex_names,"color"]
V(graph)$size <- as.integer(element_types[vertex_names,"size"]*20)
V(graph)$label.cex <- element_types[vertex_names,"weight"]

V(graph)$frame.color <- "gray"
V(graph)$frame.color[which(element_types[vertex_names,"type"]=="PRIMARIES")] <- "white"
V(graph)$frame.color[which(element_types[vertex_names,"type"]=="PATHWAY")] <- "white"
V(graph)$frame.color[which(element_types[vertex_names,"type"]=="PRODUCTS")] <- "white"
V(graph)$frame.width <- 10

V(graph)$shape <- "square"
V(graph)$shape[which(element_types[vertex_names,"type"]=="REACTION")] <- "circle"

V(graph)$label.color <- "black"
V(graph)$label.color[which(element_types[vertex_names,"type"]=="PRIMARIES")] <- "darkred"
V(graph)$label.color[which(element_types[vertex_names,"type"]=="PATHWAY")] <- "darkgreen"
V(graph)$label.color[which(element_types[vertex_names,"type"]=="REACTION")] <- "darkorange3"

E(graph)$color <- "red"
E(graph)$color[which(network[,3]=="out")] <- "blue"
E(graph)$color[which(network[,3]=="external")] <- "darkgreen"
E(graph)$arrow.size <- 0.5

layout <- layout.auto(graph)
plot.igraph(graph,layout=layout,main=pathways[pathway_id,"COMMON-NAME"])

Furthermore, I have matrices in a list that can be drawn into a heatmap. These matrices look like this:

[[1]]
     TotalSNP HighSNP ModerateSNP PromotorSNP
[1,]        1       0           0           1
[2,]        3       0           2           1
[3,]        5       0           2           3
[4,]        1       0           0           1
[5,]        7       0           4           3
[6,]        3       0           3           0
[7,]        4       0           1           3
[8,]        3       0           2           1

[[2]]
     TotalSNP HighSNP ModerateSNP PromotorSNP
[1,]        3       0           1           2
[2,]        0       0           0           0

[[3]]
     TotalSNP HighSNP ModerateSNP PromotorSNP
[1,]        0       0           0           0
[2,]        0       0           0           0

Does anyone know if it's possible to draw these matrices as heatmaps on the vertex?

Sample data:

    FinalList <- list(structure(c(1, 3, 5, 1, 7, 3, 4, 3, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 2, 2, 0, 4, 3, 1, 2, 1, 1, 3, 1, 3, 0, 3, 1), .Dim = c(8L, 
4L), .Dimnames = list(NULL, c("TotalSNP", "HighSNP", "ModerateSNP", 
"PromotorSNP"))), structure(c(3, 0, 0, 0, 1, 0, 2, 0), .Dim = c(2L, 
4L), .Dimnames = list(NULL, c("TotalSNP", "HighSNP", "ModerateSNP", 
"PromotorSNP"))), structure(c(0, 0, 0, 0, 0, 0, 0, 0), .Dim = c(2L, 
4L), .Dimnames = list(NULL, c("TotalSNP", "HighSNP", "ModerateSNP", 
"PromotorSNP"))))

The size of the matrices can vary, It's always 4 columns but the number of rows can vary from 0 rows till 10.

Amanda
  • 12,099
  • 17
  • 63
  • 91
Henkes
  • 288
  • 4
  • 16
  • 1
    This is actually relatively easy with the new vertex shape API in version 0.6.4 (officially to be released, but the R packages are already on CRAN). It would be even easier for me to help here if you could make your example reproducible and I would not need to come up with some example data myself. – Gabor Csardi Feb 06 '13 at 14:59
  • There is a lot of Data processing before this last step, making this reproducible is quite difficult, But not really necessary. This just just another `graph <- graph.data.frame(network[,1:2])` Does the vertex shape in version 0.6.4 (i have installed) this function? I have not found it yet. – Henkes Feb 06 '13 at 15:09
  • 1
    I don't care much about the data processing, you can include toy data as well, using `dput()` or `textConnection()`, see http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example This might seem a minor point for you, but in many cases it takes 5-10 minutes to come up with some meaningful toy data, and 1 minute to answer the question. You increase your chance of getting an answer by _a lot_ if you have a reproducible example, complete with data. – Gabor Csardi Feb 06 '13 at 15:57

1 Answers1

4

So, as I said in the comment above, this is relatively easy with the new vertex shape API, although there are some tricks that you need to know. There are some example shapes in igraph, those help I guess.

So you need to define a function that will plot your vertices. It must have three parameters, the coordinates in a matrix, the vertices to plot (NULL means all of them) and a function object that you can use to query igraph graphics parameters. Please see the details in the code if you are interested. If you want to change the look of the heatmaps, just change image() to whatever you like.

myheat <- function(coords, v=NULL, params) {
  colbar <- heat.colors(50)
  colbreaks <- seq(0, 1, length=length(colbar)+1)
  vertex.size <- 1/200 * params("vertex", "size")
  if (length(vertex.size) != 1 && !is.null(v)) {
    vertex.size <- vertex.size[v]
  }
  heat <- params("vertex", "heat")
  if (is.list(heat) && !is.null(v)) {
    heat <- heat[v]
  } else if (!is.null(v)) {
    heat <- list(heat)
  }
  mapply(coords[,1], coords[,2], vertex.size*2, heat,
         FUN=function(x, y, size, int) {
           stopifnot(is.matrix(int))
           nc <- ncol(int); nr <- nrow(int)
           xc <- seq(x, x+size/nc*(nc-1), length=nc)-size/nc*(nc-1)/2
           yc <- seq(y, y+size/nr*(nr-1), length=nr)-size/nr*(nr-1)/2
           image(xc, yc, int, add=TRUE, col=colbar, breaks=colbreaks)
         })
}

# OK, we add the new shape now, it will be called "heat", 
# and will have an extra vertex parameter, also called "heat". 
# This parameter gives the heatmap intensities. The shape will 
# clip as a square, ie. the edges will be cut at the boundary 
# of the heatmap.

add.vertex.shape("heat", clip=vertex.shapes("square")$clip, plot=myheat,
                 parameters=list(vertex.heat=matrix(0,3,3)))

# Some example data and random heatmaps

g <- graph.formula(A:B -+ C:D +- E)
randheat <- function() matrix(runif(9), 3)
heats <- lapply(1:vcount(g), function(x) randheat())

# Plot them

plot(g, vertex.shape="heat", vertex.heat=heats, vertex.size=50)

# You can mix various vertex shapes

par(mar=c(0,0,0,0)+.1)
plot(g, vertex.shape=c("heat", "heat", "sphere", "heat", "heat"),
     vertex.heat=heats, vertex.size=50)

plot

Gabor Csardi
  • 10,705
  • 1
  • 36
  • 53
  • Ha, This might be easy for the developer of iGraph yes! :P Thank you very much for your detailed solution! I'll be trying to integrate this is my code! – Henkes Feb 06 '13 at 16:11
  • Hi, sorry to bother you again, the function works perfectly fine with your randheat function. My own data however has not standard matrix size. there is always 4 collumns but the number of rows can differ. Also there can be 0 rows. I've tried a lot to modify your function but did not succeed in getting it running. – Henkes Feb 11 '13 at 09:23
  • This is the Error i got `Error in image.default(xc, yc, int, add = TRUE, col = colbar, breaks = colbreaks) : dimensions of z are not length(x)(-1) times length(y)(-1) In addition: Warning message: In vattrs[[name]][index] <- value : number of items to replace is not a multiple of replacement length` I also edited my question with some toy data. If you could help me out, that would be great!! cheers, – Henkes Feb 11 '13 at 09:24
  • 1
    I ended up forcing my Matrices to be a x : x dimension by adding a column or row of 0's to my data. When it was in an square x:x dimension it worked perfectly (4:4, 5:5, etc.) This does add some useless data which is never good. but it's a solution. If someone finds a way to force the img() to stretch, or allow a vertex to be rectangle shaped, please let me know. For now, I'll mark this as solved. Thanks again Gabor Csardi! – Henkes Feb 15 '13 at 11:05