[BioC] Rgraphviz: interactive graphs

Rainer Machne raim at tbi.univie.ac.at
Fri Sep 4 06:44:40 CEST 2009


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
> >>
> >
>



More information about the Bioconductor mailing list