Question: Rgraphviz: interactive graphs, how to map coordinates to plotted graph?
0
10.3 years ago by
Rainer Machne60 wrote:
On Mon, 2009-08-31 at 14:54 +0200, Wolfgang Huber wrote: > Dear Rainer > > Have a look at the 'renderGraph' function: > showMethods("renderGraph", includeDefs=TRUE) > > and at > > r1 <- renderGraph(g1) > graphRenderInfo(r1) > Ok, thanks! Still hacking around I have changed my function to first plot an empty plot on the same window (par(new=T)) using graphRenderInfo()$bbox coordinates as xlim and ylim values, before calling identify() or plotting stuff using the node coordinates. bbox <- graphRenderInfo(graph)$bbox par(new=T, mai=c(0,0,0,0)) plot(xy,xlim=bbox[,1],ylim=bbox[,2], pch=19, col=showNodeXY*3) This already comes much closer, but is not quite there yet. I guess to do it correctly would require setting or using the user coordinates in "usr", but I don't really know how "usr" works yet. I will have a closer loock at this and the renderGraph methods once I have some spare time (unless someone jumps in heroically to help me out ;) Thanks, Rainer > Florian might be able to tell you more on how to map the output of that > to the user coordinates of the R graphics device. > > Best wishes > Wolfgang > > > Btw, a "poor man's" interactive plot (in static html) can be made like > this: http://www.ebi.ac.uk/~huber/tooltips/IMCA/imca.R > resulting in http://www.ebi.ac.uk/~huber/tooltips/IMCA/imca.html > > > > ------------------------------------------------------- > Wolfgang Huber > EMBL > http://www.embl.de/research/units/genome_biology/huber > ------------------------------------------------------- > > > > Machne ha scritto: > > Hi, > > > > I want to use interactive features of R ("identify()") on Rgraphviz > > plots, and also plot other things over the plotted graph (using node > > coordinates) after it has been rendered. However, the plotted > > coordinates are shifted with respect to the coordinates returned by > > nodeRenderInfo(graph)$nodeX/nodeY. > > > > Does anyone know an easy way to calculate this shift, avoid the shift, > > or reset the plot area to coordinates used for rendering the graph? > > Or: are there already packages providing interactivity for > > Rgraphviz-rendered graphs? > > > > Below you find a small example script, including a hack of the function > > identifyPch() provided by the help page "?identify" to work on > > renderGraph(graph) plots, here for a graph object from the ?randomGraph > > help page example. > > This should illustrate well what i want to do and what the problem is. > > > > The green "x" should be on the nodes but are shifted. The > > identifyNode(graph) function would allow to click on nodes (here the > > "x"), plot something over them, and e.g. return a list of selected > > nodes. I think this would open up the graph and Rgraphviz packages for a > > lot of nice applications. > > > > Rainer > > > > > > # graphCoordinates.R > > > > library('Rgraphviz') > > > > ## TODO : find out how we can set coordinates to allow > > ## usage of identify() function in Rgraphviz graphs > > identifyNode <- function(graph, pch=19, showNodeXY=TRUE, ...) > > { > > > > xy <- cbind(nodeRenderInfo(graph)$nodeX,nodeRenderInfo(graph)$nodeY) > > > > # show where x/y coordinates would put nodes > > if (showNodeXY) > > points(xy, pch=4, col=3) > > > > n <- nrow(xy) > > > > x <- xy[,1] > > y <- xy[,2] > > > > sel <- rep(FALSE, length(x)); res <- integer(0) > > while(sum(sel) < n) { > > ans <- identify(x[!sel], y[!sel], n=1, plot=FALSE, ...) > > if(!length(ans)) break > > ans <- which(!sel)[ans] > > points(x[ans], y[ans], pch = pch, col=2) > > > > cat(paste("SELECTED NODE", rownames(xy)[ans], "\n")) > > > > sel[ans] <- TRUE > > res <- c(res, ans) > > } > > res > > } > > > > ## 1) generate random graph, from ?randomGraph help page: > > set.seed(123) > > V <- letters[1:10] > > M <- 1:4 > > g1 <- randomGraph(V, M, 0.2) > > numEdges(g1) # 16, in this case > > edgeNames(g1)# "<from> ~ <to>" since undirected > > > > ## 2) layout and plot the graph > > g1 <- layoutGraph(g1) > > renderGraph(g1) > > > > > > ## 3) Identify nodes: > > ## After calling identifyNode(g1) please click on the graph > > ## to identify nodes. > > ## The green "x" are plotted at x/y coordinates in nodeRenderInfo > > ## Note that they are shifted wrt to the rendered nodes. > > > > identifyNode(g1) > > > > # End of file > > > > _______________________________________________ > > Bioconductor mailing list > > Bioconductor at stat.math.ethz.ch > > https://stat.ethz.ch/mailman/listinfo/bioconductor > > Search the archives: http://news.gmane.org/gmane.science.biology.informatics.conductor > graph rgraphviz • 811 views ADD COMMENTlink modified 10.3 years ago by Florian Hahne540 • written 10.3 years ago by Rainer Machne60 Answer: Rgraphviz: interactive graphs, how to map coordinates to plotted graph? 0 10.3 years ago by Florian Hahne540 Florian Hahne540 wrote: Hi Rainer, let me try to be the hero here :) When you call the renderGraph method, the graph object is returned with some useful information added to the graphRenderInfo slot: library(graph) set.seed(123) V <- letters[1:5] M <- 1:2 g1 <- randomGraph(V, M, 0.5) edgemode(g1) <- "directed" x <- layoutGraph(g1) y <- renderGraph(x) names(graphRenderInfo(y)) [1] "bbox" "laidout" "recipEdges" "nativeCoords" "figDim" [6] "usr" "mai" As you can see, there are two graphical parameters in there, 'mai' and 'usr'. The former sets the plot margins and the letter sets the user coordinate system. All you need to do is extract these values and set the graphical parameters accordingly using the 'par' function. Please note that 'mai' has to be set first since it affects the value of 'usr'. So the following little example would add the numbers 1 to 5 on top of the nodes: par(mai=graphRenderInfo(y)$mai, usr=graphRenderInfo(y)$usr) text(nodeRenderInfo(y)$nodeX, nodeRenderInfo(y)$nodeY, 1:5, col=2, cex=4) Of course you could make this a bit more elegant by creating a little function that calls an arbitrary plotting function with the parameters set accordingly, something along the lines of: addToGraph <- function(graph, fun) { opar <- par(mai=graphRenderInfo(graph)$mai, usr=graphRenderInfo(graph) $usr) on.exit(par=opar) fun(graph) } And the example from above would then be: addToGraph(y, function(g) text(nodeRenderInfo(g)$nodeX, nodeRenderInfo(g)$nodeY, seq_along(nodes(g)), col=3, cex=4)) Hope that's what you were looking for, Florian On 31.08.2009, at 23:43, Rainer Machne wrote: > On Mon, 2009-08-31 at 14:54 +0200, Wolfgang Huber wrote: >> Dear Rainer >> >> Have a look at the 'renderGraph' function: >> showMethods("renderGraph", includeDefs=TRUE) >> >> and at >> >> r1 <- renderGraph(g1) >> graphRenderInfo(r1) >> > > Ok, thanks! Still hacking around I have changed my function to first > plot an empty plot on the same window (par(new=T)) using > graphRenderInfo()$bbox coordinates as xlim and ylim values, before > calling identify() or plotting stuff using the node coordinates. > > bbox <- graphRenderInfo(graph)$bbox > par(new=T, mai=c(0,0,0,0)) > plot(xy,xlim=bbox[,1],ylim=bbox[,2], pch=19, col=showNodeXY*3) > > This already comes much closer, but is not quite there yet. > I guess to do it correctly would require setting or using the user > coordinates in "usr", > but I don't really know how "usr" works yet. I will have a closer > loock at this and the > renderGraph methods once I have some spare time (unless someone > jumps in heroically > to help me out ;) > > Thanks, > Rainer > > > >> Florian might be able to tell you more on how to map the output of >> that >> to the user coordinates of the R graphics device. >> >> Best wishes >> Wolfgang >> >> >> Btw, a "poor man's" interactive plot (in static html) can be made >> like >> this: http://www.ebi.ac.uk/~huber/tooltips/IMCA/imca.R >> resulting in http://www.ebi.ac.uk/~huber/tooltips/IMCA/imca.html >> >> >> >> ------------------------------------------------------- >> Wolfgang Huber >> EMBL >> http://www.embl.de/research/units/genome_biology/huber >> ------------------------------------------------------- >> >> >> >> Machne ha scritto: >>> Hi, >>> >>> I want to use interactive features of R ("identify()") on Rgraphviz >>> plots, and also plot other things over the plotted graph (using node >>> coordinates) after it has been rendered. However, the plotted >>> coordinates are shifted with respect to the coordinates returned by >>> nodeRenderInfo(graph)$nodeX/nodeY. >>> >>> Does anyone know an easy way to calculate this shift, avoid the >>> shift, >>> or reset the plot area to coordinates used for rendering the graph? >>> Or: are there already packages providing interactivity for >>> Rgraphviz-rendered graphs? >>> >>> Below you find a small example script, including a hack of the >>> function >>> identifyPch() provided by the help page "?identify" to work on >>> renderGraph(graph) plots, here for a graph object from the ? >>> randomGraph >>> help page example. >>> This should illustrate well what i want to do and what the problem >>> is. >>> >>> The green "x" should be on the nodes but are shifted. The >>> identifyNode(graph) function would allow to click on nodes (here the >>> "x"), plot something over them, and e.g. return a list of selected >>> nodes. I think this would open up the graph and Rgraphviz packages >>> for a >>> lot of nice applications. >>> >>> Rainer >>> >>> >>> # graphCoordinates.R >>> >>> library('Rgraphviz') >>> >>> ## TODO : find out how we can set coordinates to allow >>> ## usage of identify() function in Rgraphviz graphs >>> identifyNode <- function(graph, pch=19, showNodeXY=TRUE, ...) >>> { >>> >>> xy <- cbind(nodeRenderInfo(graph)$nodeX,nodeRenderInfo(graph) >>>$nodeY) >>> >>> # show where x/y coordinates would put nodes >>> if (showNodeXY) >>> points(xy, pch=4, col=3) >>> >>> n <- nrow(xy) >>> >>> x <- xy[,1] >>> y <- xy[,2] >>> >>> sel <- rep(FALSE, length(x)); res <- integer(0) >>> while(sum(sel) < n) { >>> ans <- identify(x[!sel], y[!sel], n=1, plot=FALSE, ...) >>> if(!length(ans)) break >>> ans <- which(!sel)[ans] >>> points(x[ans], y[ans], pch = pch, col=2) >>> >>> cat(paste("SELECTED NODE", rownames(xy)[ans], "\n")) >>> >>> sel[ans] <- TRUE >>> res <- c(res, ans) >>> } >>> res >>> } >>> >>> ## 1) generate random graph, from ?randomGraph help page: >>> set.seed(123) >>> V <- letters[1:10] >>> M <- 1:4 >>> g1 <- randomGraph(V, M, 0.2) >>> numEdges(g1) # 16, in this case >>> edgeNames(g1)# "<from> ~ <to>" since undirected >>> >>> ## 2) layout and plot the graph >>> g1 <- layoutGraph(g1) >>> renderGraph(g1) >>> >>> >>> ## 3) Identify nodes: >>> ## After calling identifyNode(g1) please click on the graph >>> ## to identify nodes. >>> ## The green "x" are plotted at x/y coordinates in nodeRenderInfo >>> ## Note that they are shifted wrt to the rendered nodes. >>> >>> identifyNode(g1) >>> >>> # End of file >>> >>> _______________________________________________ >>> Bioconductor mailing list >>> Bioconductor at stat.math.ethz.ch >>> https://stat.ethz.ch/mailman/listinfo/bioconductor >>> Search the archives: http://news.gmane.org/gmane.science.biology.informatics.conductor >> >
On Wed, 2009-09-02 at 15:35 -0700, Florian Hahne wrote > Hi Rainer, > let me try to be the hero here :) You are! Thanks :) I was only playing around with interactive graph thingy while waiting for some other calculations, but it appears rather simple to make an interactive graph thing in R. The simple function now allows to remove, collapse and expand selected nodes, or e.g. click on a node and call an any passed function that can do something with the node name or label (e.g. plot some other data on a new x11() device, or open a website). Such interactivity could e.g. be useful for exploring larger metabolic networks etc., for which usually one would have to go into Cytoscape or other interactive graph software, but it'd be nice to allow some simple stuff in R. I can share my quick hack approach to this if anyone is interested, but also I'd be very interested if other thigns in this direction already exist or are worked on. Thanks, Rainer > When you call the renderGraph method, the graph object is returned > with some useful information added to the graphRenderInfo slot: > > library(graph) > set.seed(123) > V <- letters[1:5] > M <- 1:2 > g1 <- randomGraph(V, M, 0.5) > edgemode(g1) <- "directed" > x <- layoutGraph(g1) > y <- renderGraph(x) > names(graphRenderInfo(y)) > [1] "bbox" "laidout" "recipEdges" "nativeCoords" "figDim" > [6] "usr" "mai" > > As you can see, there are two graphical parameters in there, 'mai' and > 'usr'. The former sets the plot margins and the letter sets the user > coordinate system. All you need to do is extract these values and set > the graphical parameters accordingly using the 'par' function. Please > note that 'mai' has to be set first since it affects the value of > 'usr'. So the following little example would add the numbers 1 to 5 on > top of the nodes: > par(mai=graphRenderInfo(y)$mai, usr=graphRenderInfo(y)$usr) > text(nodeRenderInfo(y)$nodeX, nodeRenderInfo(y)$nodeY, 1:5, col=2, > cex=4) > > Of course you could make this a bit more elegant by creating a little > function that calls an arbitrary plotting function with the parameters > set accordingly, something along the lines of: > > addToGraph <- function(graph, fun) > { > opar <- par(mai=graphRenderInfo(graph)$mai, usr=graphRenderInfo(graph) >$usr) > on.exit(par=opar) > fun(graph) > } > > And the example from above would then be: > addToGraph(y, function(g) text(nodeRenderInfo(g)$nodeX, > nodeRenderInfo(g)$nodeY, seq_along(nodes(g)), col=3, cex=4)) > > Hope that's what you were looking for, > Florian > > > On 31.08.2009, at 23:43, Rainer Machne wrote: > > > On Mon, 2009-08-31 at 14:54 +0200, Wolfgang Huber wrote: > >> Dear Rainer > >> > >> Have a look at the 'renderGraph' function: > >> showMethods("renderGraph", includeDefs=TRUE) > >> > >> and at > >> > >> r1 <- renderGraph(g1) > >> graphRenderInfo(r1) > >> > > > > Ok, thanks! Still hacking around I have changed my function to first > > plot an empty plot on the same window (par(new=T)) using > > graphRenderInfo()$bbox coordinates as xlim and ylim values, before > > calling identify() or plotting stuff using the node coordinates. > > > > bbox <- graphRenderInfo(graph)$bbox > > par(new=T, mai=c(0,0,0,0)) > > plot(xy,xlim=bbox[,1],ylim=bbox[,2], pch=19, col=showNodeXY*3) > > > > This already comes much closer, but is not quite there yet. > > I guess to do it correctly would require setting or using the user > > coordinates in "usr", > > but I don't really know how "usr" works yet. I will have a closer > > loock at this and the > > renderGraph methods once I have some spare time (unless someone > > jumps in heroically > > to help me out ;) > > > > Thanks, > > Rainer > > > > > > > >> Florian might be able to tell you more on how to map the output of > >> that > >> to the user coordinates of the R graphics device. > >> > >> Best wishes > >> Wolfgang > >> > >> > >> Btw, a "poor man's" interactive plot (in static html) can be made > >> like > >> this: http://www.ebi.ac.uk/~huber/tooltips/IMCA/imca.R > >> resulting in http://www.ebi.ac.uk/~huber/tooltips/IMCA/imca.html > >> > >> > >> > >> ------------------------------------------------------- > >> Wolfgang Huber > >> EMBL > >> http://www.embl.de/research/units/genome_biology/huber > >> ------------------------------------------------------- > >> > >> > >> > >> Machne ha scritto: > >>> Hi, > >>> > >>> I want to use interactive features of R ("identify()") on Rgraphviz > >>> plots, and also plot other things over the plotted graph (using node > >>> coordinates) after it has been rendered. However, the plotted > >>> coordinates are shifted with respect to the coordinates returned by > >>> nodeRenderInfo(graph)$nodeX/nodeY. > >>> > >>> Does anyone know an easy way to calculate this shift, avoid the > >>> shift, > >>> or reset the plot area to coordinates used for rendering the graph? > >>> Or: are there already packages providing interactivity for > >>> Rgraphviz-rendered graphs? > >>> > >>> Below you find a small example script, including a hack of the > >>> function > >>> identifyPch() provided by the help page "?identify" to work on > >>> renderGraph(graph) plots, here for a graph object from the ? > >>> randomGraph > >>> help page example. > >>> This should illustrate well what i want to do and what the problem > >>> is. > >>> > >>> The green "x" should be on the nodes but are shifted. The > >>> identifyNode(graph) function would allow to click on nodes (here the > >>> "x"), plot something over them, and e.g. return a list of selected > >>> nodes. I think this would open up the graph and Rgraphviz packages > >>> for a > >>> lot of nice applications. > >>> > >>> Rainer > >>> > >>> > >>> # graphCoordinates.R > >>> > >>> library('Rgraphviz') > >>> > >>> ## TODO : find out how we can set coordinates to allow > >>> ## usage of identify() function in Rgraphviz graphs > >>> identifyNode <- function(graph, pch=19, showNodeXY=TRUE, ...) > >>> { > >>> > >>> xy <- cbind(nodeRenderInfo(graph)$nodeX,nodeRenderInfo(graph) > >>> \$nodeY) > >>> > >>> # show where x/y coordinates would put nodes > >>> if (showNodeXY) > >>> points(xy, pch=4, col=3) > >>> > >>> n <- nrow(xy) > >>> > >>> x <- xy[,1] > >>> y <- xy[,2] > >>> > >>> sel <- rep(FALSE, length(x)); res <- integer(0) > >>> while(sum(sel) < n) { > >>> ans <- identify(x[!sel], y[!sel], n=1, plot=FALSE, ...) > >>> if(!length(ans)) break > >>> ans <- which(!sel)[ans] > >>> points(x[ans], y[ans], pch = pch, col=2) > >>> > >>> cat(paste("SELECTED NODE", rownames(xy)[ans], "\n")) > >>> > >>> sel[ans] <- TRUE > >>> res <- c(res, ans) > >>> } > >>> res > >>> } > >>> > >>> ## 1) generate random graph, from ?randomGraph help page: > >>> set.seed(123) > >>> V <- letters[1:10] > >>> M <- 1:4 > >>> g1 <- randomGraph(V, M, 0.2) > >>> numEdges(g1) # 16, in this case > >>> edgeNames(g1)# "<from> ~ <to>" since undirected > >>> > >>> ## 2) layout and plot the graph > >>> g1 <- layoutGraph(g1) > >>> renderGraph(g1) > >>> > >>> > >>> ## 3) Identify nodes: > >>> ## After calling identifyNode(g1) please click on the graph > >>> ## to identify nodes. > >>> ## The green "x" are plotted at x/y coordinates in nodeRenderInfo > >>> ## Note that they are shifted wrt to the rendered nodes. > >>> > >>> identifyNode(g1) > >>> > >>> # End of file > >>> > >>> _______________________________________________ > >>> Bioconductor mailing list > >>> Bioconductor at stat.math.ethz.ch > >>> https://stat.ethz.ch/mailman/listinfo/bioconductor > >>> Search the archives: http://news.gmane.org/gmane.science.biology.informatics.conductor > >> > > >