% NOTE -- ONLY EDIT biocGraph.Rnw!!! % biocGraph.tex file will get overwritten. % %\VignetteIndexEntry{Examples of plotting graphs Using Rgraphviz} %\VignetteDepends{Rgraphviz, graph} %\VignetteKeywords{tools, graphs} %\VignettePackage{biocGraph} \documentclass{article} \usepackage{hyperref} \newcommand{\Rfunction}[1]{{\texttt{#1}}} \newcommand{\Rpackage}[1]{{\textit{#1}}} \newcommand{\Robject}[1]{{\textit{#1}}} \newcommand{\Rclass}[1]{{\textit{#1}}} \newcommand{\inclfig}[3]{% \begin{figure}[htbp] \begin{center} \includegraphics[width=#2]{#1} \caption{\label{#1}#3} \end{center} \end{figure} } \author{biocGraph authors and maintainer} \begin{document} \title{How To Plot A Graph Using Rgraphviz} \maketitle \tableofcontents \section{Overview} This vignette demonstrate how to easily render a graph from R into various formats using the \Rpackage{Rgraphviz} package. To do this, let us generate a graph using the \Rpackage{graph} package: % <>= library("biocGraph") set.seed(123) V <- letters[1:10] M <- 1:4 @ <>= g1 <- randomGraph(V, M, 0.2) @ \section{Different layout methods} It is quite simple to generate a R plot window to display your graph. Once you have your graph object, simply use the \Rfunction{plot} method. % <>= plot(g1) @ % \inclfig{plotDot}{0.4\textwidth}{\Robject{g1} laid out with \textit{dot}.} The result is shown in Figure~\ref{plotDot}. The \Rpackage{Rgraphviz} package allows you to specify varying layout engines, such as \textit{dot} (the default), \textit{neato} and \textit{twopi}. % <>= plot(g1, "neato") @ <>= plot(g1, "twopi") @ \begin{figure}[htbp] \begin{center} \includegraphics[width=0.4\textwidth]{plotNeato} \hspace*{19mm} \includegraphics[width=0.4\textwidth]{plotTwopi} \caption{\label{plotNeatoTwopi}\Robject{g1} laid out with \textit{neato} (left) and \textit{twopi} (right).} \end{center} \end{figure} The result is shown in Figure~\ref{plotNeatoTwopi}. A word of warning: some versions of graphviz (notably 2.4, 2.6 and 2.8) have a problem using the \textit{neato} layout on graphs with singletons (single nodes, unconnected to any other node). If you are trying to run these examples on such a system, just add an edge to these singleton nodes (that however, will change the output). % wh 16.6.06): % I have commented the following remarks about fully connectedness % and the definition of g2 out. Note that g2 is not connected, either! % % The "twopi" layout method requires a graph to be fully connected. % To determine if your graph is fully connected: % % <>= % isConnected(g1) % @ % % A working "twopi" layout can be seen with this graph: % <>= % set.seed(123) % V <- letters[14:22] % g2 <- randomEGraph(V, .2) % isConnected(g2) % z <- plot(g2,"twopi") % @ % %And finally, to demonstrate how the differing layout methods work on %this second graph: % <>= % z <- plot(g2,"dot") % @ % <>= % z <- plot(g2,"neato") % @ \subsection{Reciprocated edges} There is an option \Robject{recipEdges} that details how to deal with reciprocated edges in a graph. The two options are \Robject{combined} (the default) and \Robject{distinct}. This is mostly useful in directed graphs that have reciprocating edges - the \Robject{combined} option will display them as a single edge with an arrow on both ends while \Robject{distinct} shows them as two separate edges. % <>= rEG <- new("graphNEL", nodes=c("A", "B"), edgemode="directed") rEG <- addEdge("A", "B", rEG, 1) rEG <- addEdge("B", "A", rEG, 1) @ % \begin{figure}[htbp] \begin{center} \includegraphics[width=0.4\textwidth]{recipEdgesComb} \includegraphics[width=0.4\textwidth]{recipEdgesDistinct} \caption{\label{recipEdges}\Robject{rEG} laid out with \Robject{recipEdges} set to \Robject{combined} (left) and \Robject{distinct} (right).} \end{center} \end{figure} % <>= plot(rEG) @ <>= plot(rEG, recipEdges="distinct") @ The result is shown in Figure~\ref{recipEdges}. The function \Rfunction{removedEdges} can be used to return a numerical vector detailing which edges (if any) would be removed by the combining of edges. % <>= removedEdges(g1) @ \section{Subgraphs} \Rpackage{Rgraphviz} supports the ability to define specific clustering of nodes. This will instruct the layout algorithm to attempt to keep the clustered nodes close together. To do this, one must first generate the desired set (one or more) of subgraphs with the \Robject{graph} object. <>= sg1 <- subGraph(c("a","d","j","i"), g1) sg1 sg2 <- subGraph(c("b","e","h"), g1) sg3 <- subGraph(c("c","f","g"), g1) @ To plot using the subgraphs, one must use the \Rfunction{subGList} argument which is a list of lists, with each sublist having three elements: \begin{itemize} \item \Robject{graph} : The actual \Robject{graph} object for this subgraph. \item \Robject{cluster} : A logical value noting if this is a \texttt{cluster} or a \texttt{subgraph}. A value of \Robject{TRUE} (the default, if this element is not used) indicates a \texttt{cluster}. In Graphviz, \texttt{subgraphs} are used as an organizational mechanism but are not necessarily laid out in such a way that they are visually together. Clusters are laid out as a separate graph, and thus Graphviz will tend to keep nodes of a cluster together. Typically for \Rpackage{Rgraphviz} users, a \texttt{cluster} is what one wants to use. \item \Robject{attrs} : A named vector of attributes, where the names are the attribute and the elements are the value. For more information about attributes, see Section~\ref{sec:attributes} below. \end{itemize} Please note that only the \Robject{graph} element is required. If the \Robject{cluster} element is not specified, the subgraph is assumed to be a \texttt{cluster} and if there are no attributes to specify for this subgraph then \Robject{attrs} is unnecessary. % <>= subGList <- vector(mode="list", length=3) subGList[[1]] <- list(graph=sg1) subGList[[2]] <- list(graph=sg2, cluster=FALSE) subGList[[3]] <- list(graph=sg3) plot(g1, subGList=subGList) @ \begin{figure}[htbp] \begin{center} \includegraphics[width=0.4\textwidth]{subGplot} \hspace*{19mm} \includegraphics[width=0.4\textwidth]{subGPlot2} \caption{\label{subGplot}\Robject{g1} laid out with two different settings for the parameter \Robject{subGList}.} \end{center} \end{figure} % The result is shown in the left panel of Figure~\ref{subGplot}, and for comparison, another example: % <>= sg1 <- subGraph(c("a","c","d","e","j"), g1) sg2 <- subGraph(c("f","h","i"), g1) plot(g1, subGList=list(list(graph=sg1), list(graph=sg2))) @ \subsection{A note about edge names} While internal node naming is quite straight forward (it is simply taken from the \Robject{graph} object), \Rpackage{Rgraphviz} needs to be able to uniquely identify edges by name. End users as well will need to be able to do this to correctly assign attributes. The name of an edge between tail node \verb+x+ and head node \verb+y+ is \verb+x~y+. The method \Rfunction{edgeNames} can be used to obtain a vector of all edge names, and it takes the argument \Robject{recipEdges} so that the output correctly matches which edges will be used by \Rpackage{Rgraphviz}. <>= edgeNames(g1) edgeNames(g1, recipEdges="distinct") @ %-------------------------------------------------- \section{Attributes} \label{sec:attributes} %-------------------------------------------------- \subsection{Global attributes} There are many visualization options in Graphviz that can be set beyond those which are given explicit options using Rgraphviz - such as colors of nodes and edges, which node to center on for twopi plots, node labels, edge labels, edge weights, arrow heads and tails, etc. A list of all available attributes is accessible online at: \url{http://www.graphviz.org/pub/scm/graphviz2/doc/info/attrs.html}. Note that there are some differences between default values and also some attributes will not have an effect in Rgraphviz. Please see the man page for \Rfunction{graphvizAttributes} for more details. Attributes can be set both globally (for the entire graph, for all edges, all nodes, etc) as well as on a per-node and per-edge basis. Global attributes are set via a list and passed in as the \Robject{attrs} argument to \Rfunction{plot}. A default set of global attributes are used for global values which are not specified (by using the \Rfunction{getDefaultAttrs} function). The \Rfunction{getDefaultAttrs} function will take a partial global attribute list (see below for a description) and/or the layout type to be used (dot, neato, or twopi) and will generate an attribute list to be used with defaults for values that the user did not specify. % % FIXME (wh 16.6.2006) % Both of the following are somewhat minor, but would be nice to have... % % 1.) 'getDefaultAttrs' is an odd name for a function that sets user-defined % attributes. If the package maintainer or someone had the energy, they % could % 1. deprecate this function and call it 'setAttributes' % 2. give it a somewhat nicer user interface % e.g. the current syntax for making node boundaries red is: % getDefaultAttrs(list(node=list(color="red"))) % nicer would be (imho) % setAttributes(node=c(color="red")) % % 2.) Why is the value of 'getDefaultAttrs' a list of lists, and not a list of % character vectors: anyway all elements of those inner lists seem to be % characters. I find it confusing to allow sth to be a list if semantically % it is a vector. % I don't know what the data types are that graphviz uses, do they have % the notion of numeric or other data types? % The list has four elements: 'graph', 'cluster', 'edge' and 'node'. Within each element is another list, where the names correspond to attributes and the values correspond to the value to use globally on that attribute. An example of this structure can be seen with the default list provided by \Rfunction{getDefaultAttrs}: <>= defAttrs <- getDefaultAttrs() @ To manually set some attributes, but not others, pass in a list with the specific attributes that you desire. In the following example (see Figure~\ref{defAttrs2}, we set two attributes (\Robject{label} and \Robject{fillcolor} for nodes, one for edges (\Robject{color}) and one for the graph itself (\Robject{rankdir}). We could also have called \Rfunction{getDefaultAttrs} with the same list that we are passing as the \Robject{attrs} argument, but there is no need here. % <>= plot(g1, attrs=list(node=list(label="foo", fillcolor="lightgreen"), edge=list(color="cyan"), graph=list(rankdir="LR"))) @ % \inclfig{defAttrs2}{0.4\textwidth}{\Robject{g1} laid out with user-defined \Robject{attrs}.} \subsection{Per node attributes} Users can also set attributes per-node and per-edge. In this case, if an attribute is defined for a particular node then that node uses the specified attribute and the rest of the nodes use the global default. Note that any attribute that is set on a per-node or per-edge basis \texttt{must} have a default set globally, due to the way that Graphviz sets attributes. Both the per-node and per-edge attributes are set in the same basic manner - the attributes are set using a list where the names of the elements are the attributes, and each element contains a named vector. The names of this vector correspond to either node names or edge names, and the values of the vector are the values to set the attribute to for that node or edge. The following sections will demonstrate how to set per-node and per-edge attributes for commonly desired tasks. For these we will use two lists \Robject{nAttrs} and \Robject{eAttrs}. <>= nAttrs <- list() eAttrs <- list() @ \subsection{Node labels} By default, nodes use the node name as their label and edges do not have a label. However, both can have custom labels supplied via attributes. <>= z <- strsplit(packageDescription("Rgraphviz")$Description, " ")[[1]] z <- z[1:numNodes(g1)] names(z) = nodes(g1) nAttrs$label <- z @ <>= eAttrs$label <- c("a~h"="Label 1", "c~h"="Label 2") @ <>= attrs <- list(node=list(shape="ellipse", fixedsize=FALSE)) @ <>= plot(g1, nodeAttrs=nAttrs, edgeAttrs=eAttrs, attrs=attrs) @ \inclfig{figLabels}{0.6\textwidth}{\Robject{g1} laid out with user-defined node and edge labels.} The result is shown in Figure~\ref{figLabels}. \subsection{Using edge weights for labels} A common desire for edge weights is to use the edge weights for the edge labels. This can be done with just a couple of extra steps. First we will get the edge weights, and unlist them, to provide them in vector format. Then, first we will determine which of those to remove (this step is only necessary if \Robject{recipEdges} is set to \Robject{TRUE}, which is default behavior for both undirected and directed graphs) and remove those positions from our vector. Finally, we will get the set of edge names which will be used for plotting and bundle that into the appropriate structure for plotting. Please note to take care with edge names. If \Robject{recipEdges} is set to \Robject{combined}, then only one of any pair of reciprocal edges will actually be used. Users should utilize the \Rfunction{edgeNames} method to be sure that they are setting attributes for the right edge names. <>= ew <- as.character(unlist(edgeWeights(g1))) ew <- ew[setdiff(seq(along=ew), removedEdges(g1))] names(ew) <- edgeNames(g1) eAttrs$label <- ew ## FIXME (wh 17.6.06): This does not work - see bug report: ## attrs$edge$labelfontsize="27" @ <>= plot(g1, nodeAttrs=nAttrs, edgeAttrs=eAttrs, attrs=attrs) @ \inclfig{edgeWeightLabels}{0.6\textwidth}{\Robject{g1} laid out with edge weights as edge labels.} The result is shown in Figure~\ref{edgeWeightLabels}. %-------------------------------------------------- \subsection{Adding color} %-------------------------------------------------- There are many areas where color can be specified to the plotted graph. Edges can be drawn in a non-default color, as can nodes. Nodes can also have a specific \Robject{fillcolor} defined, detailing what color the interior of the node should be. The color used for the labels can also be specified with the \Robject{fontcolor} attribute. <>= ## Specify node drawing color nAttrs$color <- c(a="red", b="red", g="green", d="blue") ## Specify edge drawing color eAttrs$color <- c("a~d"="blue", "c~h"="purple") ## Specify node fill color nAttrs$fillcolor <- c(j="yellow") ## label color nAttrs$fontcolor <- c(e="green", f="red") eAttrs$fontcolor <- c("a~h"="green", "c~h"="brown") nAttrs eAttrs @ <>= plot(g1, nodeAttrs=nAttrs, attrs=attrs) @ \inclfig{figColors}{0.6\textwidth}{\Robject{g1} laid out with colors.} The result is shown in Figure~\ref{figColors}. %-------------------------------------------------- \subsection{Node shapes} %-------------------------------------------------- The \Rpackage{Rgraphviz} package allows you to specify different shapes for your nodes. Currently, the supported shapes are \Robject{circle} (the default), \Robject{ellipse}, \Robject{plaintext} and \Robject{box}. \Robject{plaintext} is simply a \Robject{box} that is not displayed for purposes of layout. As with previous attributes, the shape can be set globally or for specific nodes. Figure~\ref{figNodeShapes} shows the graph of the previous example, with the default shape as \Robject{ellipse} and with two nodes specified as being \Robject{box}, one as a \Robject{circle} and one as a \Robject{plaintext} node: % <>= attrs$node$shape <- "ellipse" nAttrs$shape <- c(g="box", f="circle", j="box", a="plaintext") @ <>= plot(g1, attrs=attrs, nodeAttrs=nAttrs) @ \inclfig{figNodeShapes}{0.6\textwidth}{\Robject{g1} laid out with user defined node shapes.} %-------------------------------------------------- %-------------------------------------------------- \section{Layout, rendering and the function \Rfunction{agopen}} %-------------------------------------------------- The calls to the \Rfunction{plot} that we have made above amount to two different processing steps, \textit{layout} and \textit{rendering}. In the layout step, Graphviz lays out the nodes and edges on a (virtual) 2D plotting surface. In the \textit{rendering} step, a plot consisting of lines, shapes, and letters with particular line styles, colors, fonts, font size etc.\ is created. By dissecting these steps and manually interfering, we can achieve finer control over the appearance of the rendered graph. The functions \Rfunction{buildNodeList} and \Rfunction{buildEdgeList} generate a list of \Robject{pNode} and \Robject{pEdge} objects respectively. These are used to provide the information for the Graphviz layout, and by default they are generated automatically during the call to the \Robject{plot} function. By generating these manually before the layout, one can edit these objects and perform the layout with these edited lists. For example: % <>= nodes <- buildNodeList(g1) edges <- buildEdgeList(g1) @ You can now see the contents of the first \Robject{pNode} and first \Robject{pEdge} objects in their respective lists. <>= nodes[[1]] edges[[1]] @ % The functions \Rfunction{buildNodeList} and \Rfunction{buildEdgeList} can also use the attribute lists constructed above. % <>= nodes <- buildNodeList(g1, nodeAttrs=nAttrs, defAttrs=defAttrs$node) edges <- buildEdgeList(g1, edgeAttrs=eAttrs, defAttrs=defAttrs$edge) nodes[[1]] edges[[1]] @ Note the difference between the objects in the second example as compared with the first. We can add arrowheads to the a~e and a~h edges <>= for(j in c("a~e", "a~h")) edges[[j]]@attrs$arrowhead <- "open" @ % While visually indicating direction, these will have no bearing on the layout itself as Graphviz views these edges as undirected. Now we can plot this graph (see Figure~\ref{plotbuild}): % <>= vv <- agopen(name="foo", nodes=nodes, edges=edges, attrs=attrs, edgeMode="undirected") plot(vv) @ \inclfig{plotbuild}{0.6\textwidth}{\Robject{g1} laid out via nodes and edge lists.} Next we use a different graph, one of the graphs in the \Robject{graphExamples} dataset in the \Rpackage{graph} package and provide another demonstration of working with attributes to customize your plot. <>= data(graphExamples) z <- graphExamples[[8]] nNodes <- length(nodes(z)) nA <- list() nA$fixedSize<-rep(FALSE, nNodes) nA$height <- nA$width <- rep("1", nNodes) nA$label <- rep("z", nNodes) nA$color <- rep("green", nNodes) nA$fillcolor <- rep("orange", nNodes) nA$shape <- rep("circle", nNodes) nA$fontcolor <- rep("blue", nNodes) nA$fontsize <- rep(14, nNodes) nA <- lapply(nA, function(x) { names(x) <- nodes(z); x}) @ <>= plot(z, nodeAttrs=nA) @ \inclfig{graph17}{0.6\textwidth}{Customized layout of graph \Robject{z}.} %-------------------------------------------------- \section{Customized node plots} %-------------------------------------------------- The \Rpackage{Rgraphviz} package provides for customized drawing of nodes. Customized nodes must have one of the standard node shapes, but are able to provide for richer information inside. To do this, lay out the graph using the shape desired, then, when plotting the laid out graph, use the \Robject{drawNode} argument to \Rfunction{plot} to define how the nodes are drawn. This argument can be either of length one (in which case all nodes are drawn with that same function) or a list of length equal to the number of nodes in the graph (in which case the first element of the list is used to draw the first node, etc). To work correctly, the function will take four arguments: \begin{description} \item[\Robject{node}] is an object of class \Robject{AgNode} describing the node's location and other information \item[\Robject{ur}] is of class \Robject{XYPoint} and describes the upper right hand point of the bounding box (the lower left is 0,0) \item[\Robject{attrs}] is a node attribute list as discussed in Section~\ref{sec:attributes}. It can be used for post-layout attribute changes to override values that were used for the layout. \item[\Robject{radConv}] is used by \Rpackage{Rgraphviz} to convert Graphviz units to R plotting units. This argument will probably not need to be used a custom drawing function, but does need to exist. \end{description} A custom drawing function is free to ignore these arguments, but the argument must exist in the function signature. The default function for node drawing on all nodes is \Rfunction{drawAgNode}, and users who want to supply their own node drawing function are encouraged to inspect this function as a template. If one wants to use a custom function for some nodes but the standard function for others, the list passed in to \Robject{drawNode} can have the custom functions in the elements corresponding to those nodes desired to have special display and \Rfunction{drawAgNode} in the elements corresponding to the nodes where standard display is desired. One function included with the \Rpackage{Rgraphviz} package that can be used for such alternate node drawing is \Rfunction{pieGlyph}. This allows users to put arbitrary pie charts in as circular nodes. <>= set.seed(123) counts = matrix(rexp(numNodes(g1)*4), ncol=4) g1layout <- agopen(g1, name="foo") makeNodeDrawFunction <- function(x) { force(x) function(node, ur, attrs, radConv) { nc <- getNodeCenter(node) pieGlyph(x, xpos=getX(nc), ypos=getY(nc), radius=getNodeRW(node), col=rainbow(4)) text(getX(nc), getY(nc), paste(signif(sum(x), 2)), cex=0.5, col="white", font=2) } } drawFuns <- apply(counts, 1, makeNodeDrawFunction) @ <>= plot(g1layout, drawNode=drawFuns, main="Example Pie Chart Plot") @ \inclfig{pieChartGraph}{0.6\textwidth}{\Robject{g1} with pie charts as nodes.} The result is shown in Figure~\ref{pieChartGraph}. %------------------------------------------------------------ \section{Special types of graphs} %------------------------------------------------------------ Up to this point, we have only been working with objects of class \Robject{graphNEL}, but the other subclasses of the virtual class \Rclass{graph} (such as \Rclass{distGraph} and \Rclass{clusterGraph}) will work as well, provided that they support the \Rfunction{nodes} and \Rfunction{edgeL} methods. In this section, we demonstrate a few examples. Users should not notice a difference in the interface, but this will provide some visual examples as to how these types of graphs will appear. \subsection{Cluster graphs} For our first set of examples, we create an object of class \Rclass{clusterGraph} and then plot it using all three layout methods: <>= cG <- new("clusterGraph", clusters=list(a=c(1:10), b=c(11:13), c=c(14:20), d=c(21, 22))) @ In Figure~\ref{fig:cGdot} we show \Robject{cG} laid out using three different algorithms. \begin{figure}[tp] \begin{center} <>= plot(cG, main="dot") @ <>= par(bg="#e0e0e0") plot(cG, "twopi", main="twopi") @ <>= plot(cG, "neato", main="neato") @ \includegraphics[width=0.32\textwidth]{biocGraph-cGdot} \includegraphics[width=0.32\textwidth]{biocGraph-cGtwopi} \includegraphics[width=0.32\textwidth]{biocGraph-cGneato} \end{center} \caption{\label{fig:cGdot}% A cluster graph laid out using the three layout algorithms.} \end{figure} % %The same demonstration is now given with a \Robject{distGraph} object: % %<>= % x <- rnorm(26) % names(x) <- letters % d1 <- dist(x) % dG <- new("distGraph", Dist=d1) % dG % % plot(dG) %@ % %Again using "twopi": % %<>= % plot(dG, "twopi") %%@ % %And finally using "neato": % %<>= % plot(dG, "neato") %@ %% %-------------------------------------------------- \subsection{Bipartite graphs} %-------------------------------------------------- We provide a simple example of laying out a bipartite graph. There are two types of nodes, and edges go only from one type to the other. We first construct the bipartite graph. % <>= set.seed(123) nodes1 <- paste(0:7) nodes2 <- letters[1:10] ft <- cbind(sample(nodes1, 24, replace=TRUE), sample(nodes2, 24, replace=TRUE)) ft <- ft[!duplicated(apply(ft, 1, paste, collapse="")),] g <- ftM2graphNEL(ft, edgemode='directed') g @ % Next we set up the node attributes and create subgraphs so that we can better control the layout. We want to have color for the nodes, and we want to lay the graph out from left to right, rather than vertically. % <>= twocolors <- c("#D9EF8B", "#E0F3F8") nodeType <- 1 + (nodes(g) %in% nodes1) nA = makeNodeAttrs(g, fillcolor=twocolors[nodeType]) sg1 = subGraph(nodes1, g) sgL = list(list(graph=sg1, cluster = FALSE, attrs = c(rank="sink"))) att = list(graph = list(rankdir = "LR", rank = "")) @ % Finally, in Figure~\ref{figbipartite} we plot the bipartite graph. % <>= plot(g, attrs = att, nodeAttrs=nA, subGList = sgL) @ % \inclfig{figbipartite}{0.4\textwidth}{A bipartite graph.} %-------------------------------------------------- \section{NEW Another workflow to plot a graph } Another workflow in doing layout, rendering is as following: (1) convert a graph in \Robject{graph} class to \Robject{Ragraph} class, (2) set its default attributes for graph, cluster(s), nodes and edges, (3) set attributes for individual cluster, node(s) and/or edge(s), (4) layout it with desired algorithm, (5) render it to desired media. Repeat steps (3), (4) and/or (5) as needed. \subsection{Convert a graph to \Robject{Ragraph} class} We prepare a graph with two subgraphs: graphExample-01.gxl.gz and graphExample-11.gxl.gz from package \Rpackage{graph}. We specify the 1st one is NOT a cluster, while the 2nd one is. Just as in graphviz, \Rpackage{Rgraphviz} treats a cluster as a special subgraph, its nodes are layed out and drawn together and within a bounding rectangel. <>= library("graph") g1_gz <- gzfile(system.file("GXL/graphExample-01.gxl.gz",package="graph"), open="rb") g11_gz <- gzfile(system.file("GXL/graphExample-11.gxl.gz",package="graph"), open="rb") g1 <- fromGXL(g1_gz) g11 <- fromGXL(g11_gz) g1_11 <- join(g1, g11) sgl <- vector(mode="list", length=2) sgl[[1]] <- list(graph=g1, cluster=FALSE) sgl[[2]] <- list(graph=g11, cluster=TRUE) ng <- agopenSimple(g1_11, "tmpsg", subGList=sgl) @ Note: this instance of \Robject{Ragraph} class from \Rfunction{agopenSimple} contains less content than that you obtain from calling \Robject{agopen}: it maintains a pointer for access to graphviz; after setting various attributes and doing layout, other entries are filled in for drawing only. The following workflow works well for an instance of \Robject{Ragraph} class obtained from \Rfunction{agopen} as well. \subsection{Get default attributes} There are default attributes associated with a graph, a cluster (a subgraph), nodes and edges. You can find out what they are as follows: After you explicitly set one or more default attributes, you'll see the default attributes. If you like the notation from package \Robject{graph} better, the following codes accomplish the same: <>= graphDataDefaults(ng) nodeDataDefaults(ng) edgeDataDefaults(ng) @ \subsection{Set default attributes} If you want to set default attributes yourself, you could call functions like following: <>= graphDataDefaults(ng, c("size", "bgcolor")) <- c("1", "yellow") nodeDataDefaults(ng, c("fontcolor", "width")) <- c("blue", 0.5) edgeDataDefaults(ng, c("color", "style")) <- c("green", "dotted") @ As shown in the examples, you can specify multiple attributes and their corresponding values in one call. R's circular rule applies. Currently, only the 1st call to set default attributes has effects. Subsequent calls yield no effect. \subsection{Get attributes} You could set attributes for individual elements: graph, cluster(s), node(s) and edge(s). As R's circular rule applies, you could get multiple attributes to multiple elements in one call. The package \Robject{graph} like notations are: <>= graphData(ng, "bgcolor") nodeData(ng, "a", c("fontcolor", "width")) edgeData(ng, "f", "h", c("color", "arrowhead")) @ The return value, "default {graph, node, cluster, node} attr val 1", indicates that the attribute is NOT defined. The return value, "default {graph, node, cluster, node} attr val 2", indicates that the attribute is NOT set for this object, the software will use default instead. \subsection{Set attributes} Likewise, you can set attributes for each element: graph, cluster(s), node(s) and edge(s). R's circular rule applies to element(s), attribute name(s) and attribute value(s). A note on default value(s): default value could be set once and only once at this time. Only the first call has effect. <>= graphData(ng, "bgcolor") <- "orange" clusterData(ng, 2, "bgcolor") <- "red" nodeData(ng, "a", c("fontcolor", "width")) <- c("red", "0.8") edgeData(ng, "f", "h", c("color", "style")) <- c("blue", "solid") @ You can set as many attributes as you like. Not every rendering software honors all the attributes, even for those provided by graphviz. Different attributes could have different impact in layout: some affect layout and drawing, such as node shapes, font size; others affect only drawing, such as fill color, font color. Some attribute seem only take effect for certain layout, for instance, \Robject{bgcolor} for cluster shows the effect when layout is "dot", but not for "circo". \subsection{Layout and render the graph in various formats} To do the layout and render the results, there are two main output channels: (1) interactive output, and (2) file output which you could use various viewers to view the results. To plot a graph interactively, simply do: <>= plot(ng, "neato") plot(ng, "circo") @ Currently, interactive output only honors a small number of attributes, mainly those from \Robject{buildNodelist} and \Robject{buildEdgeList}. To do layout and then output to a file, you can do: <>= toFile(ng, layoutType="dot", filename="test_dot.svg", fileType="svg") toFile(ng, layoutType="circo", filename="test_circo.ps", fileType="ps") toFile(ng, layoutType="twopi", filename="test_twopi.dot", fileType="dot") @ These examples use various renderer provided by graphviz, which honor a lot more attributes. You can look into graphviz doc to find out more, for instance, node shapes, color schemes, line types/sizes, etc. You need corresponding viewers installed to be able to view the output files. %------------------------------------------------------------ %------------------------------------------------------------ \section{Tooltips and hyperlinks on graphs} %------------------------------------------------------------ This section is for advanced users. It gives an example for how the \Rfunction{imageMap} function of the \Rpackage{Rgraphviz} package can be used to create clickable graph renderings with drill-down capability. First, we load an example graph <>= data("integrinMediatedCellAdhesion") @ In the next code chunk, we create a set of plots, one for each node. Here they are just meaningless ``dummy'' plots, but of course in your application these could be showing real data, corresponding to the nodes. <>= outdir=tempdir() nd = nodes(IMCAGraph) plotFiles = paste(seq(along=nd), 'png', sep='.') for(i in seq(along=nd)) { png(file.path(outdir, plotFiles[i]), width=400, height=600) plot(cumsum(rnorm(100)), type='l', col='blue', lwd=2, main=nd[i]) dev.off() } @ Now we create a HTML page that consists of two parts, so-called frames, one to hold the graph plot, one for the per-node data plots that we generated above. <>= fhtml = file.path(outdir, "index.html") con = file(fhtml, open="wt") cat("", "Integrin Mediated Cell Adhesion graph with tooltips and hyperlinks, please click on the nodes.", "", "", " ", " ", "", sep="\n", file=con) close(con) @ Finally, we create the graph plot, and the associated HTML image map. <>= width = 600 height = 512 imgname = "graph.png" png(file.path(outdir, imgname), width=width, height=height) par(mai=rep(0,4)) lg = agopen(IMCAGraph, name="foo", attrs = list(graph=list(rankdir="LR", rank=""), node=list(fixedsize=FALSE)), nodeAttrs = makeNodeAttrs(IMCAGraph), subGList = IMCAAttrs$subGList) plot(lg) con = file(file.path(outdir, "graph.html"), open="wt") writeLines("\n", con) imageMap(lg, con=con, tags=list(HREF=plotFiles, TITLE = nd, TARGET = rep("nodedata", length(nd))), imgname=imgname, width=width, height=height) writeLines("", con) close(con) dev.off() @ We can have a look at the result by pointing a web browser to it. <>= fhtml if(interactive()) browseURL(fhtml) @ \section{Sessioninfo} This document was produced using <>= sessionInfo() @ together with version \Sexpr{graphvizVersion()} of graphviz. \end{document}