fontsize in Rgraphviz
2
0
Entering edit mode
Mark W Kimpel ▴ 830
@mark-w-kimpel-2027
Last seen 9.6 years ago
Florian, Here is a potential way to get some more plotting symbols into Rgraphviz, most of these based on those available in Graphviz. I have a vested interest in getting more symbols as I am already using fill- color to denote fold change direction and p value and size to indicate fold change magnitude. I'd like to denote up to 5 or 6 different KEGG pathways in one graph. Anyways, here goes: The relevant section of your code is found in renderGraph.R: ## deal with different shapes possible.shapes <- c("circle", "ellipse", "box", "rectangle", "plaintext") shape <- possible.shapes[pmatch(shape, possible.shapes, duplicates.ok = TRUE)] ## shape == circle i <- shape == "circle" if (any(i, na.rm=TRUE)) { symbols(nodeX[i], nodeY[i], circles = rad[i], fg = col[i], bg = fill[i], inches = FALSE, add = TRUE) } ############################################################## I have come up with the following self-contained code-snippet which follows to demonstrate a way to draw other shapes with user-specified radii. If you and others think this is an okay way to go, then I will work on a patch for renderGraph.R. I also believe that the workhorse function polygon.vertex.calc.func could be modified to calculate ellipses so that box, rectangle, circle, and ellipse could all use this as a generic and users could specify height and width instead of radii to customize the other shapes below. Let me know what you think. Mark #calculates vertices of a regular polygon centered on origin using radius and number of vertices. First vertex is on y axis # unless 'shift' is specified in degrees, positive (up) or negative (down) polygon.vertex.calc.func <- function(no.vert, radius, shift.deg){ x <- y <- rep(0, no.vert) shift.rad <- (shift.deg * 2 * pi)/360 for (i in 1:no.vert){ x[i] <- radius * (cos((((2 * pi)/no.vert) * (i - 1)) + (shift.rad))) y[i] <- radius * (sin((((2 * pi)/no.vert) * (i - 1)) + (shift.rad))) } vertex.list <- list(x = x,y = y) } ###################################################################### ###### triangle.func <- function(radius = 1){ vertex.list <- polygon.vertex.calc.func(no.vert = 3, radius, shift.deg = 90) vertex.list } ###################################################################### ###### inverted.triangle.func <- function(radius = 1){ vertex.list <- polygon.vertex.calc.func(no.vert = 3, radius, shift.deg = 270) vertex.list } ###################################################################### ###### pentagon.func <- function(radius = 1){ vertex.list <- polygon.vertex.calc.func(no.vert = 5, radius, shift.deg = 18) vertex.list } ###################################################################### ###### octagon.func <- function(radius = 1){ vertex.list <- polygon.vertex.calc.func(no.vert = 8, radius, shift.deg = 0) vertex.list } ###################################################################### ###### house.func <- function(radius = 1){ vertex.list <- pentagon.func(radius) vertex.list$x[4] <- vertex.list$x[3] vertex.list$x[5] <- vertex.list$x[1] vertex.list } ###################################################################### ###### inverted.house.func <- function(radius = 1){ vertex.list <- pentagon.func(radius) vertex.list$x[4] <- vertex.list$x[3] vertex.list$x[5] <- vertex.list$x[1] vertex.list$x <- -1 * vertex.list$x vertex.list$y <- -1 * vertex.list$y vertex.list } ######################################## op <- par() par(mfrow=c(2,4)) ########################################### plot(c(-2,2), c(-2,2), type="n") vertex.list <- triangle.func(radius = 1) polygon(x = vertex.list$x, y = vertex.list$y) ########################################### plot(c(-2,2), c(-2,2), type="n") vertex.list <- inverted.triangle.func(radius = 1) polygon(x = vertex.list$x, y = vertex.list$y) ########################################### plot(c(-2,2), c(-2,2), type="n") vertex.list <- inverted.triangle.func(radius = 1) polygon(x = vertex.list$x, y = vertex.list$y) vertex.list <- triangle.func(radius = 1) polygon(x = vertex.list$x, y = vertex.list$y) ########################################### plot(c(-2,2), c(-2,2), type="n") vertex.list <- pentagon.func(radius = 1) polygon(x = vertex.list$x, y = vertex.list$y) ########################################### plot(c(-2,2), c(-2,2), type="n") vertex.list <- octagon.func(radius = 1) polygon(x = vertex.list$x, y = vertex.list$y) ########################################### plot(c(-2,2), c(-2,2), type="n") vertex.list <- octagon.func(radius = 1) polygon(x = vertex.list$x, y = vertex.list$y) vertex.list <- octagon.func(radius = 0.75) polygon(x = vertex.list$x, y = vertex.list$y) ########################################### plot(c(-2,2), c(-2,2), type="n") vertex.list <- house.func(radius = 1) polygon(x = vertex.list$x, y = vertex.list$y) ########################################### plot(c(-2,2), c(-2,2), type="n") vertex.list <- inv.house.func(radius = 1) polygon(x = vertex.list$x, y = vertex.list$y) ########################################### ########################################### ########################################### ########################################### ########################################### par(op) Mark W. Kimpel MD ** Neuroinformatics ** Dept. of Psychiatry Indiana University School of Medicine 15032 Hunter Court, Westfield, IN 46074 (317) 490-5129 Work, & Mobile & VoiceMail (317) 204-4202 Home (no voice mail please) mwkimpel<at>gmail<dot>com ****************************************************************** Florian Hahne wrote: > Hi Mark, > to get you all the way, take a look at this: > > require(Rgraphviz) > # Generate random graph > set.seed(123) > nodeNames <- letters[1:10] > M <- 1:4 > g1 <- randomGraph(nodeNames, M, .2) > > nAttrs <- list() > > #node width > nAttrs$width <- rep(3, length(nodeNames)) > names(nAttrs$width)<-nodeNames > > #node height > nAttrs$height <- rep(3, length(nodeNames)) > names(nAttrs$height)<-nodeNames > > #font size > fontsize <- rep(c(1, 2), (length(nodeNames)/2)) > names(fontsize)<-nodeNames > > #layout and render > x <- layoutGraph(g1, nodeAttr=nAttrs) > nodeRenderInfo(x) <- list(cex=fontsize) > renderGraph(x, graph.pars=list(nodes=list(fill="black", > textCol="white"))) > > I didn't set the node shape at all, because the default for dot is to > use "ellipse", and since you fix your node widths and node heights to > the same size, this boils down to a circle. I also set the fill and text > color as attributes in the graph.pars argument to renderGraph, but > Deepayan's suggestion works, too. The only difference is, that the > latter permanently assigns the colors to the graph object x, while the > former takes effect only for the current rendering operation. > > nodeRenderInfo(x) <- list(cex=fontsize, fill="black", textCol="white") > renderGraph(x) > > fillcolor is ignored in your example because in the new rendering API > this parameter is called fill (we tried to stay closer to R's base > graphic parameter names, and thinking of that now, maybe we should > rename textCol to font.col or something similar). I just uploaded a much > more detailed vignette and some bug fixes, and these changes should be > available soon in Rgraphviz version 1.17.12. If you know how to access > the svn repository you can get this update immediately. In the Vignette > there are also tables of the available parameters for nodes, edges and > the whole graph and I will update the documentation accordingly ASAP. > > Everything that affects the graph layout can still be passed on to > Graphviz as nodeAttrs, edgeAttrs or attrs arguments. For instance, the > following would change the node shapes: > > nAttrs$shape <- c("circle", "rect", rep(c("ellipse", "box"), 4)) > names(nAttrs$shape )<- nodeNames > x <- layoutGraph(g1, nodeAttr=nAttrs) > renderGraph(x) > Again, since widths and heights of the nodes are constant, there's no > difference between ellipse and circle (box and rect are synonyms, > anyways). You can see the difference here: > > nAttrs$width <- rep(6, length(nodeNames)) > names(nAttrs$width)<-nodeNames > x <- layoutGraph(g1, nodeAttr=nAttrs) > renderGraph(x) > > Another Graphviz parameter that I find quite useful is fixedsize. If > this is set to TRUE (the default) all nodes will be forced to have the > same size unless manually changed. For FALSE, the node sizes will be > computed from the labels, so longer labels will create larger nodes. As > far as I remeber, this has to be given to the attrs argument, something > like this: > > attrs <- list(node=list(fixedsize=FALSE)) > x <- layoutGraph(g1, nodeAttr=nAttrs, attrs=attrs) > > I'm affaid I can't really point you to the C code for the Graphviz > interaction (we tried to stay clear of that, it's so easy to break > things there...), but agopen is the workhorse in Rgraphviz to talk to > the Graphviz library. Starting there and working your way though the > code should quickly get you to the interesting C calls. Once you've > figured out a way to access the different shapes in Graphviz and how to > get the coordinates back into R, it is straightforward to render them. > Everything that is stored in the Ragraph object (the return value of > agopen) can be accessed by our rendering API. > > Cheers, > Florian > > > > > > Mark W Kimpel schrieb: >> Deepayan, >> >> We are making progress. I just updated Rgraphviz-devel. Simply >> adjusting the way adjusting my parameters to "layoutGraph" as you >> suggested fixed the font size problem! I did not have to add it at the >> nodeRenderInfo stage. Attached is a postscript file documenting the >> results, which would look prettier if I had bothered to adjust the >> size of the output. >> >> Unfortunately, now nAttrs$fillcolor is being ignored, even if it is >> added as an argument to noRenderInfo. >> >> Also, I would very much like to use many of the other shapes available >> via graphviz. If I was willing to do some of the coding (I know some >> C), would you point me in the right direction so that I might provide >> a patch with more shapes? >> >> Thanks, >> Mark >> >> >> Mark W. Kimpel MD ** Neuroinformatics ** Dept. of Psychiatry >> Indiana University School of Medicine >> >> 15032 Hunter Court, Westfield, IN 46074 >> >> (317) 490-5129 Work, & Mobile & VoiceMail >> (317) 204-4202 Home (no voice mail please) >> >> mwkimpel<at>gmail<dot>com >> >> ****************************************************************** >> >> >> Deepayan Sarkar wrote: >>> On 1/30/08, Mark W Kimpel <mwkimpel at="" gmail.com=""> wrote: >>>> Sorry for the complex prior example, I shouldn't write emails late at >>>> night. Below is a self-contained, reproducible example. >>>> >>>> I've made some progress and can get the following script to flow >>>> without >>>> error messages. The fontsize, however, is not varying as I believe it >>>> should and when I substitute "ellipse" for circle the width and height >>>> parameters do not appropriately effect the shape. >>> >>> There are certain attributes which need to be supplied at the layout >>> step, especially shape, width, and height, as without these the edges >>> (which need to start from node boundaries) will not be placed >>> properly. So, you need to supply nAttrs to layoutGraph as >>> >>> x <- layoutGraph(g1, nodeAttrs = nAttrs) >>> >>> Of course, it's not clear from the documentation that you can do this! >>> >>>> I also do not understand where I can specify "neato" vs. "dot" for the >>>> rendering layout. >>> >>> Same goes for this; you can do >>> >>> x <- layoutGraph(g1, nodeAttrs = nAttrs, layoutType = "neato") >>> >>> The trick is to notice that the default layout function in >>> 'layoutGraph' is 'layoutGraphviz', which is unexported, but you can >>> get it's argument list by >>> >>>> args(Rgraphviz:::layoutGraphviz) >>> function (x, layoutType = "dot", name = "graph", recipEdges = >>> "combined", >>> nodeAttrs = list(), edgeAttrs = list(), ...) >>> >>> >>> Unfortunately, the fontsize doesn't seem to be retained in the result >>> of layoutGraph, and I'm not sure yet if that's a bug in our wrapper or >>> a limitation of the graphviz interface. We will look into it. >>> >>>> Also, where to specify a title. >>> >>> Generally speaking, our new model is that once the layout is done, you >>> should be able to modify other attributes before rendering. These >>> attributes are divided into three types: those for nodes, those for >>> edges, and those for the whole graph, and these can be accessed and >>> modified using nodeRenderInfo(), edgeRenderInfo(), and >>> graphRenderInfo(), respectively. >>> >>> So, to come back to your problem, once you have the layout done, you >>> can modify the fontsize and title as follows: >>> >>> nodeRenderInfo(x) <- list(fontsize = nAttrs$fontsize * 5) >>> graphRenderInfo(x) <- list(main = "Main title") >>> >>> and then finally render it with >>> >>> renderGraph(x) >>> >>> Obviously there are many warts still to be worked out. >>> >>> -Deepayan >>> >>>> Thanks, mark >>>> >>>> >>>> #################### >>>> require(Rgraphviz) >>>> # Generate random graph >>>> set.seed(123) >>>> nodeNames <- letters[1:10] >>>> M <- 1:4 >>>> g1 <- randomGraph(nodeNames, M, .2) >>>> >>>> nAttrs <- list() >>>> >>>> #node shapes >>>> nAttrs$shape <- rep("circle", length(nodeNames)) >>>> names(nAttrs$shape )<- nodeNames >>>> >>>> #node width >>>> nAttrs$width <- rep(3, length(nodeNames)) >>>> names(nAttrs$width)<-nodeNames >>>> >>>> #node height >>>> nAttrs$height <- rep(3, length(nodeNames)) >>>> names(nAttrs$height)<-nodeNames >>>> >>>> #node colors >>>> nAttrs$fillcolor <-rep("black", length(nodeNames)) >>>> names(nAttrs$fillcolor) <- nodeNames >>>> >>>> #font color >>>> nAttrs$fontcolor <- rep("white", length(nodeNames)) >>>> names(nAttrs$fontcolor)<-nodeNames >>>> >>>> #font size >>>> nAttrs$fontsize <- rep(c(1, 2), (length(nodeNames)/2)) >>>> names(nAttrs$fontsize)<-nodeNames >>>> >>>> postscript(file="my.test.graph.ps", paper="special",width=4, height=5) >>>> #set up graphics device >>>> x <- layoutGraph(g1) >>>> nodeRenderInfo(x) = nAttrs >>>> renderGraph(x) >>>> dev.off()## close the graphics device >>>> >>>> >>>> >>>> Mark W. Kimpel MD ** Neuroinformatics ** Dept. of Psychiatry >>>> Indiana University School of Medicine >>>> >>>> 15032 Hunter Court, Westfield, IN 46074 >>>> >>>> (317) 490-5129 Work, & Mobile & VoiceMail >>>> (317) 204-4202 Home (no voice mail please) >>>> >>>> mwkimpel<at>gmail<dot>com >>> >> ------------------------------------------------------------------- ----- >> >> _______________________________________________ >> 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 > >
GO graph Rgraphviz GO graph Rgraphviz • 1.1k views
ADD COMMENT
0
Entering edit mode
Mark W Kimpel ▴ 830
@mark-w-kimpel-2027
Last seen 9.6 years ago
Already found a bug. Please change inv.house.func to inverted.house.func in the demo code. Sorry! Mark W. Kimpel MD ** Neuroinformatics ** Dept. of Psychiatry Indiana University School of Medicine 15032 Hunter Court, Westfield, IN 46074 (317) 490-5129 Work, & Mobile & VoiceMail (317) 204-4202 Home (no voice mail please) mwkimpel<at>gmail<dot>com ****************************************************************** Florian Hahne wrote: > Hi Mark, > to get you all the way, take a look at this: > > require(Rgraphviz) > # Generate random graph > set.seed(123) > nodeNames <- letters[1:10] > M <- 1:4 > g1 <- randomGraph(nodeNames, M, .2) > > nAttrs <- list() > > #node width > nAttrs$width <- rep(3, length(nodeNames)) > names(nAttrs$width)<-nodeNames > > #node height > nAttrs$height <- rep(3, length(nodeNames)) > names(nAttrs$height)<-nodeNames > > #font size > fontsize <- rep(c(1, 2), (length(nodeNames)/2)) > names(fontsize)<-nodeNames > > #layout and render > x <- layoutGraph(g1, nodeAttr=nAttrs) > nodeRenderInfo(x) <- list(cex=fontsize) > renderGraph(x, graph.pars=list(nodes=list(fill="black", > textCol="white"))) > > I didn't set the node shape at all, because the default for dot is to > use "ellipse", and since you fix your node widths and node heights to > the same size, this boils down to a circle. I also set the fill and text > color as attributes in the graph.pars argument to renderGraph, but > Deepayan's suggestion works, too. The only difference is, that the > latter permanently assigns the colors to the graph object x, while the > former takes effect only for the current rendering operation. > > nodeRenderInfo(x) <- list(cex=fontsize, fill="black", textCol="white") > renderGraph(x) > > fillcolor is ignored in your example because in the new rendering API > this parameter is called fill (we tried to stay closer to R's base > graphic parameter names, and thinking of that now, maybe we should > rename textCol to font.col or something similar). I just uploaded a much > more detailed vignette and some bug fixes, and these changes should be > available soon in Rgraphviz version 1.17.12. If you know how to access > the svn repository you can get this update immediately. In the Vignette > there are also tables of the available parameters for nodes, edges and > the whole graph and I will update the documentation accordingly ASAP. > > Everything that affects the graph layout can still be passed on to > Graphviz as nodeAttrs, edgeAttrs or attrs arguments. For instance, the > following would change the node shapes: > > nAttrs$shape <- c("circle", "rect", rep(c("ellipse", "box"), 4)) > names(nAttrs$shape )<- nodeNames > x <- layoutGraph(g1, nodeAttr=nAttrs) > renderGraph(x) > Again, since widths and heights of the nodes are constant, there's no > difference between ellipse and circle (box and rect are synonyms, > anyways). You can see the difference here: > > nAttrs$width <- rep(6, length(nodeNames)) > names(nAttrs$width)<-nodeNames > x <- layoutGraph(g1, nodeAttr=nAttrs) > renderGraph(x) > > Another Graphviz parameter that I find quite useful is fixedsize. If > this is set to TRUE (the default) all nodes will be forced to have the > same size unless manually changed. For FALSE, the node sizes will be > computed from the labels, so longer labels will create larger nodes. As > far as I remeber, this has to be given to the attrs argument, something > like this: > > attrs <- list(node=list(fixedsize=FALSE)) > x <- layoutGraph(g1, nodeAttr=nAttrs, attrs=attrs) > > I'm affaid I can't really point you to the C code for the Graphviz > interaction (we tried to stay clear of that, it's so easy to break > things there...), but agopen is the workhorse in Rgraphviz to talk to > the Graphviz library. Starting there and working your way though the > code should quickly get you to the interesting C calls. Once you've > figured out a way to access the different shapes in Graphviz and how to > get the coordinates back into R, it is straightforward to render them. > Everything that is stored in the Ragraph object (the return value of > agopen) can be accessed by our rendering API. > > Cheers, > Florian > > > > > > Mark W Kimpel schrieb: >> Deepayan, >> >> We are making progress. I just updated Rgraphviz-devel. Simply >> adjusting the way adjusting my parameters to "layoutGraph" as you >> suggested fixed the font size problem! I did not have to add it at the >> nodeRenderInfo stage. Attached is a postscript file documenting the >> results, which would look prettier if I had bothered to adjust the >> size of the output. >> >> Unfortunately, now nAttrs$fillcolor is being ignored, even if it is >> added as an argument to noRenderInfo. >> >> Also, I would very much like to use many of the other shapes available >> via graphviz. If I was willing to do some of the coding (I know some >> C), would you point me in the right direction so that I might provide >> a patch with more shapes? >> >> Thanks, >> Mark >> >> >> Mark W. Kimpel MD ** Neuroinformatics ** Dept. of Psychiatry >> Indiana University School of Medicine >> >> 15032 Hunter Court, Westfield, IN 46074 >> >> (317) 490-5129 Work, & Mobile & VoiceMail >> (317) 204-4202 Home (no voice mail please) >> >> mwkimpel<at>gmail<dot>com >> >> ****************************************************************** >> >> >> Deepayan Sarkar wrote: >>> On 1/30/08, Mark W Kimpel <mwkimpel at="" gmail.com=""> wrote: >>>> Sorry for the complex prior example, I shouldn't write emails late at >>>> night. Below is a self-contained, reproducible example. >>>> >>>> I've made some progress and can get the following script to flow >>>> without >>>> error messages. The fontsize, however, is not varying as I believe it >>>> should and when I substitute "ellipse" for circle the width and height >>>> parameters do not appropriately effect the shape. >>> >>> There are certain attributes which need to be supplied at the layout >>> step, especially shape, width, and height, as without these the edges >>> (which need to start from node boundaries) will not be placed >>> properly. So, you need to supply nAttrs to layoutGraph as >>> >>> x <- layoutGraph(g1, nodeAttrs = nAttrs) >>> >>> Of course, it's not clear from the documentation that you can do this! >>> >>>> I also do not understand where I can specify "neato" vs. "dot" for the >>>> rendering layout. >>> >>> Same goes for this; you can do >>> >>> x <- layoutGraph(g1, nodeAttrs = nAttrs, layoutType = "neato") >>> >>> The trick is to notice that the default layout function in >>> 'layoutGraph' is 'layoutGraphviz', which is unexported, but you can >>> get it's argument list by >>> >>>> args(Rgraphviz:::layoutGraphviz) >>> function (x, layoutType = "dot", name = "graph", recipEdges = >>> "combined", >>> nodeAttrs = list(), edgeAttrs = list(), ...) >>> >>> >>> Unfortunately, the fontsize doesn't seem to be retained in the result >>> of layoutGraph, and I'm not sure yet if that's a bug in our wrapper or >>> a limitation of the graphviz interface. We will look into it. >>> >>>> Also, where to specify a title. >>> >>> Generally speaking, our new model is that once the layout is done, you >>> should be able to modify other attributes before rendering. These >>> attributes are divided into three types: those for nodes, those for >>> edges, and those for the whole graph, and these can be accessed and >>> modified using nodeRenderInfo(), edgeRenderInfo(), and >>> graphRenderInfo(), respectively. >>> >>> So, to come back to your problem, once you have the layout done, you >>> can modify the fontsize and title as follows: >>> >>> nodeRenderInfo(x) <- list(fontsize = nAttrs$fontsize * 5) >>> graphRenderInfo(x) <- list(main = "Main title") >>> >>> and then finally render it with >>> >>> renderGraph(x) >>> >>> Obviously there are many warts still to be worked out. >>> >>> -Deepayan >>> >>>> Thanks, mark >>>> >>>> >>>> #################### >>>> require(Rgraphviz) >>>> # Generate random graph >>>> set.seed(123) >>>> nodeNames <- letters[1:10] >>>> M <- 1:4 >>>> g1 <- randomGraph(nodeNames, M, .2) >>>> >>>> nAttrs <- list() >>>> >>>> #node shapes >>>> nAttrs$shape <- rep("circle", length(nodeNames)) >>>> names(nAttrs$shape )<- nodeNames >>>> >>>> #node width >>>> nAttrs$width <- rep(3, length(nodeNames)) >>>> names(nAttrs$width)<-nodeNames >>>> >>>> #node height >>>> nAttrs$height <- rep(3, length(nodeNames)) >>>> names(nAttrs$height)<-nodeNames >>>> >>>> #node colors >>>> nAttrs$fillcolor <-rep("black", length(nodeNames)) >>>> names(nAttrs$fillcolor) <- nodeNames >>>> >>>> #font color >>>> nAttrs$fontcolor <- rep("white", length(nodeNames)) >>>> names(nAttrs$fontcolor)<-nodeNames >>>> >>>> #font size >>>> nAttrs$fontsize <- rep(c(1, 2), (length(nodeNames)/2)) >>>> names(nAttrs$fontsize)<-nodeNames >>>> >>>> postscript(file="my.test.graph.ps", paper="special",width=4, height=5) >>>> #set up graphics device >>>> x <- layoutGraph(g1) >>>> nodeRenderInfo(x) = nAttrs >>>> renderGraph(x) >>>> dev.off()## close the graphics device >>>> >>>> >>>> >>>> Mark W. Kimpel MD ** Neuroinformatics ** Dept. of Psychiatry >>>> Indiana University School of Medicine >>>> >>>> 15032 Hunter Court, Westfield, IN 46074 >>>> >>>> (317) 490-5129 Work, & Mobile & VoiceMail >>>> (317) 204-4202 Home (no voice mail please) >>>> >>>> mwkimpel<at>gmail<dot>com >>> >> ------------------------------------------------------------------- ----- >> >> _______________________________________________ >> 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 > >
ADD COMMENT
0
Entering edit mode
Florian Hahne ▴ 540
@florian-hahne-2471
Last seen 9.6 years ago
Hi Mark, this is great, the only issue that I see here is that we completely bypass Graphviz and this might cause some problems: 1.) The start end endpoints of the edges might look a bit weird. Graphviz tries to keep them at a reasonable distance from the nodes. These is a concept of bounding boxes, so you could ask Graphviz to compute node and edge locations for rectangular nodes (in which case the node fills the whole bounding box), but this might look strange. 2.) I'm not sure that you can pass your shapes down to Graphviz as nodeAttrs arguments. In the best case those will only be ignored, but I'm almost positive that the Rgraphviz interface will not return those shapes in the Ragraph object, hence we don't get them back into the laid out graph object without messing around a lot in layoutGraph. The alternative to set them through nodeRenderInfo doesn't appeal to me that much, because this sort of breaks the concept of keeping the layout and the rendering part separate. Maybe Deeapayan or Robert have something to add here, but ideally you might want to figure out how Rgraphviz passes stuff to the Graphviz library and implement your additional shapes at that level. bw, Florian Mark W Kimpel schrieb: > Florian, > > Here is a potential way to get some more plotting symbols into > Rgraphviz, most of these based on those available in Graphviz. I have > a vested interest in getting more symbols as I am already using > fill-color to denote fold change direction and p value and size to > indicate fold change magnitude. I'd like to denote up to 5 or 6 > different KEGG pathways in one graph. Anyways, here goes: > > The relevant section of your code is found in renderGraph.R: > > ## deal with different shapes > possible.shapes <- > c("circle", "ellipse", "box", "rectangle", "plaintext") > shape <- > possible.shapes[pmatch(shape, > possible.shapes, > duplicates.ok = TRUE)] > ## shape == circle > i <- shape == "circle" > if (any(i, na.rm=TRUE)) > { > symbols(nodeX[i], nodeY[i], circles = rad[i], > fg = col[i], bg = fill[i], > inches = FALSE, add = TRUE) > } > > ############################################################## > > I have come up with the following self-contained code-snippet which > follows to demonstrate a way to draw other shapes with user- specified > radii. If you and others think this is an okay way to go, then I will > work on a patch for renderGraph.R. I also believe that the workhorse > function polygon.vertex.calc.func could be modified to calculate > ellipses so that box, rectangle, circle, and ellipse could all use > this as a generic and users could specify height and width instead of > radii to customize the other shapes below. > > Let me know what you think. Mark > > #calculates vertices of a regular polygon centered on origin using > radius and number of vertices. First vertex is on y axis > # unless 'shift' is specified in degrees, positive (up) or negative > (down) > polygon.vertex.calc.func <- function(no.vert, radius, shift.deg){ > x <- y <- rep(0, no.vert) > shift.rad <- (shift.deg * 2 * pi)/360 > for (i in 1:no.vert){ > x[i] <- radius * (cos((((2 * pi)/no.vert) * (i - 1)) + (shift.rad))) > y[i] <- radius * (sin((((2 * pi)/no.vert) * (i - 1)) + (shift.rad))) > } > vertex.list <- list(x = x,y = y) > } > #################################################################### ######## > > triangle.func <- function(radius = 1){ > vertex.list <- polygon.vertex.calc.func(no.vert = 3, radius, > shift.deg = 90) > vertex.list > } > #################################################################### ######## > > inverted.triangle.func <- function(radius = 1){ > vertex.list <- polygon.vertex.calc.func(no.vert = 3, radius, > shift.deg = 270) > vertex.list > } > #################################################################### ######## > > pentagon.func <- function(radius = 1){ > vertex.list <- polygon.vertex.calc.func(no.vert = 5, radius, > shift.deg = 18) > vertex.list > } > #################################################################### ######## > > octagon.func <- function(radius = 1){ > vertex.list <- polygon.vertex.calc.func(no.vert = 8, radius, > shift.deg = 0) > vertex.list > } > #################################################################### ######## > > house.func <- function(radius = 1){ > vertex.list <- pentagon.func(radius) > vertex.list$x[4] <- vertex.list$x[3] > vertex.list$x[5] <- vertex.list$x[1] > vertex.list > } > #################################################################### ######## > > inverted.house.func <- function(radius = 1){ > vertex.list <- pentagon.func(radius) > vertex.list$x[4] <- vertex.list$x[3] > vertex.list$x[5] <- vertex.list$x[1] > vertex.list$x <- -1 * vertex.list$x > vertex.list$y <- -1 * vertex.list$y > vertex.list > } > ######################################## > > op <- par() > par(mfrow=c(2,4)) > ########################################### > plot(c(-2,2), c(-2,2), type="n") > vertex.list <- triangle.func(radius = 1) > polygon(x = vertex.list$x, y = vertex.list$y) > ########################################### > plot(c(-2,2), c(-2,2), type="n") > vertex.list <- inverted.triangle.func(radius = 1) > polygon(x = vertex.list$x, y = vertex.list$y) > ########################################### > plot(c(-2,2), c(-2,2), type="n") > vertex.list <- inverted.triangle.func(radius = 1) > polygon(x = vertex.list$x, y = vertex.list$y) > vertex.list <- triangle.func(radius = 1) > polygon(x = vertex.list$x, y = vertex.list$y) > ########################################### > plot(c(-2,2), c(-2,2), type="n") > vertex.list <- pentagon.func(radius = 1) > polygon(x = vertex.list$x, y = vertex.list$y) > ########################################### > plot(c(-2,2), c(-2,2), type="n") > vertex.list <- octagon.func(radius = 1) > polygon(x = vertex.list$x, y = vertex.list$y) > ########################################### > plot(c(-2,2), c(-2,2), type="n") > vertex.list <- octagon.func(radius = 1) > polygon(x = vertex.list$x, y = vertex.list$y) > vertex.list <- octagon.func(radius = 0.75) > polygon(x = vertex.list$x, y = vertex.list$y) > ########################################### > plot(c(-2,2), c(-2,2), type="n") > vertex.list <- house.func(radius = 1) > polygon(x = vertex.list$x, y = vertex.list$y) > ########################################### > plot(c(-2,2), c(-2,2), type="n") > vertex.list <- inv.house.func(radius = 1) > polygon(x = vertex.list$x, y = vertex.list$y) > ########################################### > ########################################### > ########################################### > ########################################### > ########################################### > par(op) > > Mark W. Kimpel MD ** Neuroinformatics ** Dept. of Psychiatry > Indiana University School of Medicine > > 15032 Hunter Court, Westfield, IN 46074 > > (317) 490-5129 Work, & Mobile & VoiceMail > (317) 204-4202 Home (no voice mail please) > > mwkimpel<at>gmail<dot>com > > ****************************************************************** > > > Florian Hahne wrote: >> Hi Mark, >> to get you all the way, take a look at this: >> >> require(Rgraphviz) >> # Generate random graph >> set.seed(123) >> nodeNames <- letters[1:10] >> M <- 1:4 >> g1 <- randomGraph(nodeNames, M, .2) >> >> nAttrs <- list() >> >> #node width >> nAttrs$width <- rep(3, length(nodeNames)) >> names(nAttrs$width)<-nodeNames >> >> #node height >> nAttrs$height <- rep(3, length(nodeNames)) >> names(nAttrs$height)<-nodeNames >> >> #font size >> fontsize <- rep(c(1, 2), (length(nodeNames)/2)) >> names(fontsize)<-nodeNames >> >> #layout and render >> x <- layoutGraph(g1, nodeAttr=nAttrs) >> nodeRenderInfo(x) <- list(cex=fontsize) >> renderGraph(x, graph.pars=list(nodes=list(fill="black", >> textCol="white"))) >> >> I didn't set the node shape at all, because the default for dot is to >> use "ellipse", and since you fix your node widths and node heights to >> the same size, this boils down to a circle. I also set the fill and >> text color as attributes in the graph.pars argument to renderGraph, >> but Deepayan's suggestion works, too. The only difference is, that >> the latter permanently assigns the colors to the graph object x, >> while the former takes effect only for the current rendering operation. >> >> nodeRenderInfo(x) <- list(cex=fontsize, fill="black", textCol="white") >> renderGraph(x) >> >> fillcolor is ignored in your example because in the new rendering API >> this parameter is called fill (we tried to stay closer to R's base >> graphic parameter names, and thinking of that now, maybe we should >> rename textCol to font.col or something similar). I just uploaded a >> much more detailed vignette and some bug fixes, and these changes >> should be available soon in Rgraphviz version 1.17.12. If you know >> how to access the svn repository you can get this update immediately. >> In the Vignette there are also tables of the available parameters for >> nodes, edges and the whole graph and I will update the documentation >> accordingly ASAP. >> >> Everything that affects the graph layout can still be passed on to >> Graphviz as nodeAttrs, edgeAttrs or attrs arguments. For instance, >> the following would change the node shapes: >> >> nAttrs$shape <- c("circle", "rect", rep(c("ellipse", "box"), 4)) >> names(nAttrs$shape )<- nodeNames >> x <- layoutGraph(g1, nodeAttr=nAttrs) >> renderGraph(x) >> Again, since widths and heights of the nodes are constant, there's no >> difference between ellipse and circle (box and rect are synonyms, >> anyways). You can see the difference here: >> >> nAttrs$width <- rep(6, length(nodeNames)) >> names(nAttrs$width)<-nodeNames >> x <- layoutGraph(g1, nodeAttr=nAttrs) >> renderGraph(x) >> >> Another Graphviz parameter that I find quite useful is fixedsize. If >> this is set to TRUE (the default) all nodes will be forced to have >> the same size unless manually changed. For FALSE, the node sizes will >> be computed from the labels, so longer labels will create larger >> nodes. As far as I remeber, this has to be given to the attrs >> argument, something like this: >> >> attrs <- list(node=list(fixedsize=FALSE)) >> x <- layoutGraph(g1, nodeAttr=nAttrs, attrs=attrs) >> >> I'm affaid I can't really point you to the C code for the Graphviz >> interaction (we tried to stay clear of that, it's so easy to break >> things there...), but agopen is the workhorse in Rgraphviz to talk to >> the Graphviz library. Starting there and working your way though the >> code should quickly get you to the interesting C calls. Once you've >> figured out a way to access the different shapes in Graphviz and how >> to get the coordinates back into R, it is straightforward to render >> them. Everything that is stored in the Ragraph object (the return >> value of agopen) can be accessed by our rendering API. >> >> Cheers, >> Florian >> >> >> >> >> >> Mark W Kimpel schrieb: >>> Deepayan, >>> >>> We are making progress. I just updated Rgraphviz-devel. Simply >>> adjusting the way adjusting my parameters to "layoutGraph" as you >>> suggested fixed the font size problem! I did not have to add it at >>> the nodeRenderInfo stage. Attached is a postscript file documenting >>> the results, which would look prettier if I had bothered to adjust >>> the size of the output. >>> >>> Unfortunately, now nAttrs$fillcolor is being ignored, even if it is >>> added as an argument to noRenderInfo. >>> >>> Also, I would very much like to use many of the other shapes >>> available via graphviz. If I was willing to do some of the coding (I >>> know some C), would you point me in the right direction so that I >>> might provide a patch with more shapes? >>> >>> Thanks, >>> Mark >>> >>> >>> Mark W. Kimpel MD ** Neuroinformatics ** Dept. of Psychiatry >>> Indiana University School of Medicine >>> >>> 15032 Hunter Court, Westfield, IN 46074 >>> >>> (317) 490-5129 Work, & Mobile & VoiceMail >>> (317) 204-4202 Home (no voice mail please) >>> >>> mwkimpel<at>gmail<dot>com >>> >>> ****************************************************************** >>> >>> >>> Deepayan Sarkar wrote: >>>> On 1/30/08, Mark W Kimpel <mwkimpel at="" gmail.com=""> wrote: >>>>> Sorry for the complex prior example, I shouldn't write emails late at >>>>> night. Below is a self-contained, reproducible example. >>>>> >>>>> I've made some progress and can get the following script to flow >>>>> without >>>>> error messages. The fontsize, however, is not varying as I believe it >>>>> should and when I substitute "ellipse" for circle the width and >>>>> height >>>>> parameters do not appropriately effect the shape. >>>> >>>> There are certain attributes which need to be supplied at the layout >>>> step, especially shape, width, and height, as without these the edges >>>> (which need to start from node boundaries) will not be placed >>>> properly. So, you need to supply nAttrs to layoutGraph as >>>> >>>> x <- layoutGraph(g1, nodeAttrs = nAttrs) >>>> >>>> Of course, it's not clear from the documentation that you can do this! >>>> >>>>> I also do not understand where I can specify "neato" vs. "dot" for >>>>> the >>>>> rendering layout. >>>> >>>> Same goes for this; you can do >>>> >>>> x <- layoutGraph(g1, nodeAttrs = nAttrs, layoutType = "neato") >>>> >>>> The trick is to notice that the default layout function in >>>> 'layoutGraph' is 'layoutGraphviz', which is unexported, but you can >>>> get it's argument list by >>>> >>>>> args(Rgraphviz:::layoutGraphviz) >>>> function (x, layoutType = "dot", name = "graph", recipEdges = >>>> "combined", >>>> nodeAttrs = list(), edgeAttrs = list(), ...) >>>> >>>> >>>> Unfortunately, the fontsize doesn't seem to be retained in the result >>>> of layoutGraph, and I'm not sure yet if that's a bug in our wrapper or >>>> a limitation of the graphviz interface. We will look into it. >>>> >>>>> Also, where to specify a title. >>>> >>>> Generally speaking, our new model is that once the layout is done, you >>>> should be able to modify other attributes before rendering. These >>>> attributes are divided into three types: those for nodes, those for >>>> edges, and those for the whole graph, and these can be accessed and >>>> modified using nodeRenderInfo(), edgeRenderInfo(), and >>>> graphRenderInfo(), respectively. >>>> >>>> So, to come back to your problem, once you have the layout done, you >>>> can modify the fontsize and title as follows: >>>> >>>> nodeRenderInfo(x) <- list(fontsize = nAttrs$fontsize * 5) >>>> graphRenderInfo(x) <- list(main = "Main title") >>>> >>>> and then finally render it with >>>> >>>> renderGraph(x) >>>> >>>> Obviously there are many warts still to be worked out. >>>> >>>> -Deepayan >>>> >>>>> Thanks, mark >>>>> >>>>> >>>>> #################### >>>>> require(Rgraphviz) >>>>> # Generate random graph >>>>> set.seed(123) >>>>> nodeNames <- letters[1:10] >>>>> M <- 1:4 >>>>> g1 <- randomGraph(nodeNames, M, .2) >>>>> >>>>> nAttrs <- list() >>>>> >>>>> #node shapes >>>>> nAttrs$shape <- rep("circle", length(nodeNames)) >>>>> names(nAttrs$shape )<- nodeNames >>>>> >>>>> #node width >>>>> nAttrs$width <- rep(3, length(nodeNames)) >>>>> names(nAttrs$width)<-nodeNames >>>>> >>>>> #node height >>>>> nAttrs$height <- rep(3, length(nodeNames)) >>>>> names(nAttrs$height)<-nodeNames >>>>> >>>>> #node colors >>>>> nAttrs$fillcolor <-rep("black", length(nodeNames)) >>>>> names(nAttrs$fillcolor) <- nodeNames >>>>> >>>>> #font color >>>>> nAttrs$fontcolor <- rep("white", length(nodeNames)) >>>>> names(nAttrs$fontcolor)<-nodeNames >>>>> >>>>> #font size >>>>> nAttrs$fontsize <- rep(c(1, 2), (length(nodeNames)/2)) >>>>> names(nAttrs$fontsize)<-nodeNames >>>>> >>>>> postscript(file="my.test.graph.ps", paper="special",width=4, >>>>> height=5) >>>>> #set up graphics device >>>>> x <- layoutGraph(g1) >>>>> nodeRenderInfo(x) = nAttrs >>>>> renderGraph(x) >>>>> dev.off()## close the graphics device >>>>> >>>>> >>>>> >>>>> Mark W. Kimpel MD ** Neuroinformatics ** Dept. of Psychiatry >>>>> Indiana University School of Medicine >>>>> >>>>> 15032 Hunter Court, Westfield, IN 46074 >>>>> >>>>> (317) 490-5129 Work, & Mobile & VoiceMail >>>>> (317) 204-4202 Home (no voice mail please) >>>>> >>>>> mwkimpel<at>gmail<dot>com >>>> >>> ------------------------------------------------------------------ ------ >>> >>> >>> _______________________________________________ >>> 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 >> >> -- Florian Hahne, PhD Computational Biology Program Division of Public Health Sciences Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N, M2-B876 PO Box 19024 Seattle, Washington 98109-1024 206-667-3148 fhahne at fhcrc.org
ADD COMMENT

Login before adding your answer.

Traffic: 655 users visited in the last hour
Help About
FAQ
Access RSS
API
Stats

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.

Powered by the version 2.3.6