## Copyright 2010 Laurent Jacob, Pierre Neuvial and Sandrine Dudoit. ## This file is part of DEGraph. ## DEGraph is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## DEGraph is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with DEGraph. If not, see <http://www.gnu.org/licenses/>. #########################################################################/** ## @RdocFunction plotValuedGraph ## ## @title "Plots a graph with nodes colored according to a quantitative variable" ## ## \description{ ## @get "title". ## } ## ## @synopsis ## ## \arguments{ ## \item{graph}{A \code{\link[=graph-class]{graph}} object.} ## \item{values}{A named @vector of @numeric values according to which the ## graph nodes should be colored.} ## \item{nodeLabels}{A @character @vector of the same length and in the ## same order as 'nodes(graph)': node labels to be displayed. Defaults ## to 'nodes(graph)'.} ## \item{qMax}{A @numeric value, fraction of the data to be truncated in order ## to avoid outliers.} ## \item{colorPalette}{A @character vector, the set of colors to be used.} ## \item{adjustColorRange}{A @logical value. If @TRUE, the color range is ## adjusted to the range of values of nodes actually present in the graph. ## Defaults to @FALSE, i.e. the color range spans range(values) regardless ## of which nodes are present in the graph.} ## \item{symmetrizeArrows}{A @logical value. If @TRUE, arrow tails are ## drawn as the corresponding arrow heads. Defaults to @FALSE.} ## \item{height}{A @numeric value, the (common) size of nodes.} ## \item{lwd}{A @numeric value, the (common) width of edges.} ## \item{cex}{A @numeric value, the relative size of the text for gene names.} ## \item{...}{Further arguments to be passed to 'edgeRenderInfo' and ## 'nodeRenderInfo'.} ## \item{verbose}{If @TRUE, extra information is output.} ## } ## ## \value{ ## A @list containing the following components: ## \describe{ ## \item{graph}{The 'graph' object as plotted.} ## \item{breaks}{The break points in the supplied values (can be used for ## plotting a legend).} ## } ## } ## ## @author ## ## \seealso{ ## @see "plotKEGGgraph" ## @see "plot" ## } ## ## @examples "../incl/testOneGraph.Rex" ## ##*/######################################################################## plotValuedGraph <- function(graph, values=NULL, nodeLabels=nodes(graph), qMax=0.95, colorPalette=heat.colors(10), adjustColorRange=FALSE, symmetrizeArrows=FALSE, height=1, lwd=1, cex=1, ..., verbose=FALSE){ ##par(oma=c( 0,0,0,4)) ## Validate arguments ## Argument 'graph' if (!inherits(graph, "graph")) { throw("Argument 'graph' should derive from class 'graph'") } gnodes <- nodes(graph) nnodes <- length(gnodes) ## Argument 'values' values <- Arguments$getNumerics(values) vnodes <- names(values) if (length(values) && is.null(vnodes)) { throw("Names of argument 'values' should be non NULL") } ## Argument 'nodeLabels' nodeLabels <- Arguments$getCharacters(nodeLabels) if (length(nodeLabels) != nnodes) { throw("Length of argument 'nodeLabels' should match the number of nodes in the graph") } nLabels <- nodeLabels names(nLabels) <- gnodes ## Argument 'qMax' qMax <- Arguments$getNumeric(qMax) ## Argument 'colorPalette' colorPalette <- Arguments$getCharacters(colorPalette) ## Argument 'adjustColorRange' adjustColorRange <- Arguments$getLogical(adjustColorRange) ## Argument 'symmetrizeArrows' symmetrizeArrows <- Arguments$getLogical(symmetrizeArrows) ## Argument 'verbose': verbose <- Arguments$getVerbose(verbose) if (verbose) { cat <- R.utils::cat pushState(verbose) on.exit(popState(verbose)) } verbose && cat(verbose, "Nodes and their labels") verbose && str(verbose, nLabels) ## Associate values to the corresponding nodes on the graph graphValues <- rep(NA, nnodes) names(graphValues) <- gnodes cnodes <- intersect(vnodes, gnodes) graphValues[match(cnodes, gnodes)] <- values[cnodes] if (length(values)) { if (adjustColorRange) { cs <- graphValues } else { ## color range from all the values cs <- values } cs <- abs(cs) ## enforce color scale symmetry MM <- quantile(cs, qMax, na.rm=TRUE) ## try to avoid outliers ## truncate outliers graphValues[graphValues< -MM] <- -MM graphValues[graphValues> MM] <- MM breaks <- seq(from=-MM, to=MM, length=length(colorPalette)) verbose && cat(verbose, "Color scale breaks") verbose && str(verbose, breaks) nodeCols <- level.colors(graphValues, at=breaks, col.regions=colorPalette) names(nodeCols) <- names(graphValues) verbose && cat(verbose, "Node colors") verbose && str(verbose, nodeCols) } else { breaks=NULL } ##par(mfrow=c(1,2)) ##par(mar = c(5, 0, 0, 5)) ##image(cbind(1L:length(pal)), col = pal, axes = FALSE) ##par(mar = c(0, 0, 0, 0)) ed <- edgeData(graph) ke <- ed[[1]]$KEGGEdge if (!is.null(ke)) { ## only way to know if graph is KEGGgraph-compliant ## BEGIN code borrowed from plotKEGGgraph subdisplay <- subtypeDisplay(graph) eLabel <- subdisplay["label", ] eCol <- subdisplay["color", ] eTextCol <- subdisplay["fontcolor", ] eLty <- subdisplay["style", ] eArrowhead <- subdisplay["arrowhead", ] eArrowhead[eArrowhead=="normal"] <- "normArrow" if (ncol(subdisplay) == 1) { tmp <- colnames(subdisplay)[1] names(eLabel) <- names(eCol) <- names(eTextCol) <- tmp names(eLty) <- names(eArrowhead) <- tmp } edgeRenderInfo(graph) <- list(lty=eLty, col=eCol, textCol=eTextCol, label=eLabel, arrowhead=eArrowhead, label=eLabel) if (symmetrizeArrows) { edgeRenderInfo(graph) <- list(arrowtail=eArrowhead) } } else if(is.NCIgraph(graph)) ## NCIgraph { eTypeDictionnary <- c('normal','tee') eColDictionnary <- c('red','blue') names(eTypeDictionnary) <- names(eColDictionnary) <- c('activation','inhibition') eTypes <- unlist(lapply(graph@edgeData@data,FUN=function(e) tolower(e$edgeType))) ERIarrowhead =eTypeDictionnary[eTypes] ERIcol =eColDictionnary[eTypes] eNames <- sapply(names(graph@edgeData@data),FUN=function(e) gsub(e,pattern='\\|',replacement='~')) names(ERIarrowhead) <- names(ERIcol) <- eNames edgeRenderInfo(graph) <- list(arrowhead=ERIarrowhead,col=ERIcol) } else { ## graphAM if (inherits(graph, "graphAM")) { ahd <- rep("normal", length(ed)) names(ahd) <- names(ed) adjMat <- graph@adjMat ## not useful: adjacency matrix is not signed... } } graph <- layoutGraph(graph) nodeRenderInfo(graph) <- list(label=nLabels, height=height, cex=cex, ...) if (length(values)) { nodeRenderInfo(graph) <- list(fill=nodeCols,textCol="black") } edgeRenderInfo(graph) <- list(lwd=lwd, ...) renderGraph(graph) ## END code borrowed from plotKEGGgraph ##par(oma=c( 0,0,15,1))# reset margin to be much smaller. ##image.plot(legend.only=TRUE, zlim=range(breaks), col=colorPalette, legend.shrink=0.3, legend.width=0.8, legend.lab="t-scores", legend.mar=5) ##set.panel() # reset plotting device invisible(list(graph=graph, breaks=breaks)) } ############################################################################ ## HISTORY ## 2010-10-08 ## o Now validating argument 'verbose'. ## 2010-09-17 ## o Fixed node labels. ## 2010-09-16 ## o Removed dependency on KEGGgraph. ## o Added option 'symmetrizeArrows'. ## 2010-09-07 ## o Added option 'translateGeneIDs'. ## o Added Rdoc. ## o removed brewer.pal to avoid depending on RColorBrewer. ## o renamed 'shift' into 'values' for more general applicability. ## 2010-08-05 ## o Color scale is now symmetric / 0. ## o Legend is not drawn within plotDERes anymore. ## 2010-08-04 ## o BUG FIX: colors were wrong (due to a factor/character problem). ############################################################################