From 3f91879755fdbbe39cfd936495b2985fa4621615 Mon Sep 17 00:00:00 2001 From: paradis Date: Wed, 23 Mar 2011 12:28:30 +0000 Subject: [PATCH] new trex() + kronoviz() and bug fixing in identify.phylo() git-svn-id: https://svn.mpl.ird.fr/ape/dev/ape@153 6e262413-ae40-0410-9e79-b911bd7a66b7 --- ChangeLog | 22 ++++++++++++- DESCRIPTION | 2 +- R/identify.phylo.R | 22 ++++++++++--- R/plot.phylo.R | 77 ++++++++++++++++++++++++++++++++++++++++++- man/identify.phylo.Rd | 4 ++- man/kronoviz.Rd | 33 +++++++++++++++++++ man/trex.Rd | 69 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 220 insertions(+), 9 deletions(-) create mode 100644 man/kronoviz.Rd create mode 100644 man/trex.Rd diff --git a/ChangeLog b/ChangeLog index cfc7f07..5f6172d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,32 @@ CHANGES IN APE VERSION 2.7-1 +NEW FEATURES + + o The new function trex does tree exploration with multiple + graphical devices. + + o The new function kronoviz plots several rooted (dated) trees on + the scale scale. + + o identify.phylo() has a new option 'quiet' (FALSE by default). + + BUG FIXES o A bug was introduced in read.nexus() in ape 2.7. o image.DNAbin() did not colour correctly the bases if there were - '-' and no 'N' in the alignment. + some '-' and no 'N'. + + o identify.phylo() returned a wrong answer when the x- and y-scales + are very different. + + +OTHER CHANGES + + o identify.phylo() now returns NULL if the user right-(instead of + left-)clicks (an error was returned previously). diff --git a/DESCRIPTION b/DESCRIPTION index 3c49985..32054d4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: ape Version: 2.7-1 -Date: 2011-03-18 +Date: 2011-03-22 Title: Analyses of Phylogenetics and Evolution Author: Emmanuel Paradis, Ben Bolker, Julien Claude, Hoa Sien Cuong, Richard Desper, Benoit Durand, Julien Dutheil, Olivier Gascuel, Christoph Heibl, Daniel Lawson, Vincent Lefort, Pierre Legendre, Jim Lemon, Yvonnick Noel, Johan Nylander, Rainer Opgen-Rhein, Klaus Schliep, Korbinian Strimmer, Damien de Vienne Maintainer: Emmanuel Paradis diff --git a/R/identify.phylo.R b/R/identify.phylo.R index 130a878..64ecc38 100644 --- a/R/identify.phylo.R +++ b/R/identify.phylo.R @@ -1,19 +1,31 @@ -## identify.phylo.R (2008-02-28) +## identify.phylo.R (2011-03-23) ## Graphical Identification of Nodes and Tips -## Copyright 2008 Emmanuel Paradis +## Copyright 2008-2011 Emmanuel Paradis ## This file is part of the R-package `ape'. ## See the file ../COPYING for licensing issues. identify.phylo <- function(x, nodes = TRUE, tips = FALSE, - labels = FALSE, ...) + labels = FALSE, quiet = FALSE, ...) { - cat("Click close to a node of the tree...\n") + if (!quiet) + cat("Click close to a node of the tree...\n") xy <- locator(1) + if (is.null(xy)) return(NULL) lastPP <- get("last_plot.phylo", envir = .PlotPhyloEnv) - d <- sqrt((xy$x - lastPP$xx)^2 + (xy$y - lastPP$yy)^2) + ## rescale the coordinates (especially if the x- and + ## y-scales are very different): + pin <- par("pin") + rescaleX <- pin[1]/max(lastPP$xx) + xx <- rescaleX * lastPP$xx + rescaleY <- pin[2]/max(lastPP$yy) + yy <- rescaleY * lastPP$yy + xy$x <- rescaleX * xy$x + xy$y <- rescaleY * xy$y + ## end of rescaling + d <- (xy$x - xx)^2 + (xy$y - yy)^2 # no need to sqrt() NODE <- which.min(d) res <- list() if (NODE <= lastPP$Ntip) { diff --git a/R/plot.phylo.R b/R/plot.phylo.R index b2273ca..18bba88 100644 --- a/R/plot.phylo.R +++ b/R/plot.phylo.R @@ -1,4 +1,4 @@ -## plot.phylo.R (2011-02-17) +## plot.phylo.R (2011-03-23) ## Plot Phylogenies @@ -609,3 +609,78 @@ plot.multiPhylo <- function(x, layout = 1, ...) } for (i in 1:length(x)) plot(x[[i]], ...) } + +trex <- function(phy, title = TRUE, subbg = "lightyellow3", + return.tree = FALSE, ...) +{ + lastPP <- get("last_plot.phylo", envir = .PlotPhyloEnv) + devmain <- dev.cur() # where the main tree is plotted + + restore <- function() { + dev.set(devmain) + assign("last_plot.phylo", lastPP, envir = .PlotPhyloEnv) + } + + on.exit(restore()) + NEW <- TRUE + cat("Click close to a node. Right-click to exit.\n") + repeat { + x <- identify.phylo(phy, quiet = TRUE) + if (is.null(x)) return(invisible(NULL)) else { + x <- x$nodes + if (is.null(x)) cat("Try again!\n") else { + if (NEW) { + dev.new() + par(bg = subbg) + devsub <- dev.cur() + NEW <- FALSE + } else dev.set(devsub) + + tr <- extract.clade(phy, x) + plot(tr, ...) + if (is.character(title)) title(title) + else if (title) { + tl <- + if (is.null(phy$node.label)) + paste("From node #", x, sep = "") + else paste("From", phy$node.label[x - Ntip(phy)]) + title(tl) + } + if (return.tree) return(tr) + restore() + } + } + } +} + +kronoviz <- function(x, layout = length(x), horiz = TRUE, ...) +{ + par(mar = rep(0.5, 4), oma = rep(2, 4)) + rts <- sapply(x, function(x) branching.times(x)[1]) + maxrts <- max(rts) + lim <- cbind(rts - maxrts, rts) + Ntree <- length(x) + Ntips <- sapply(x, Ntip) + if (horiz) { + nrow <- layout + w <- 1 + h <- Ntips + } else { + nrow <- 1 + w <- Ntips + h <- 1 + } + layout(matrix(1:layout, nrow), widths = w, heights = h) + if (layout > Ntree && !par("ask")) { + par(ask = TRUE) + on.exit(par(ask = FALSE)) + } + if (horiz) { + for (i in 1:Ntree) + plot(x[[i]], x.lim = lim[i, ], ...) + } else { + for (i in 1:Ntree) + plot(x[[i]], y.lim = lim[i, ], direction = "u", ...) + } + axisPhylo(if (horiz) 1 else 4) # better if the deepest tree is last ;) +} diff --git a/man/identify.phylo.Rd b/man/identify.phylo.Rd index 166653a..c7fd7af 100644 --- a/man/identify.phylo.Rd +++ b/man/identify.phylo.Rd @@ -3,7 +3,7 @@ \title{Graphical Identification of Nodes and Tips} \usage{ \method{identify}{phylo}(x, nodes = TRUE, tips = FALSE, - labels = FALSE, ...) + labels = FALSE, quiet = FALSE, ...) } \arguments{ \item{x}{an object of class \code{"phylo"}.} @@ -12,6 +12,8 @@ information.} \item{labels}{a logical specifying whether to return the labels; by default only the numbers are returned.} + \item{quiet}{a logical controlling whether to print a message inviting + the user to click on the tree.} \item{\dots}{further arguments to be passed to or from other methods.} } \description{ diff --git a/man/kronoviz.Rd b/man/kronoviz.Rd new file mode 100644 index 0000000..596fc54 --- /dev/null +++ b/man/kronoviz.Rd @@ -0,0 +1,33 @@ +\name{kronoviz} +\alias{kronoviz} +\title{Plot Multiple Chronograms on the Same Scale} +\description{ + The main argument is a list of (rooted) trees which are plotted on the + same scale. +} +\usage{ +kronoviz(x, layout = length(x), horiz = TRUE, ...) +} +\arguments{ + \item{x}{a list of (rooted) trees of class \code{"phylo"}.} + \item{layout}{an integer giving the number of trees plotted + simultaneously; by default all.} + \item{horiz}{a logical specifying whether the trees should be plotted + rightwards (the default) or upwards.} + \item{\dots}{further arguments passed to \code{plot.phylo}.} +} +\details{ + The size of the individual plots is proportional to the size of the + trees. +} +\value{NULL} +\author{Emmanuel Paradis} +\seealso{ + \code{\link{plot.phylo}} +} +\examples{ +TR <- replicate(10, rcoal(sample(11:20, size = 1)), simplify = FALSE) +kronoviz(TR) +kronoviz(TR, horiz = FALSE, type = "c", show.tip.label = FALSE) +} +\keyword{hplot} diff --git a/man/trex.Rd b/man/trex.Rd new file mode 100644 index 0000000..e05ed42 --- /dev/null +++ b/man/trex.Rd @@ -0,0 +1,69 @@ +\name{trex} +\alias{trex} +\title{Tree Explorer With Multiple Devices} +\description{ + This functions requires a plotted tree: the user is invited to click + close to a node and the corresponding subtree (or clade) is plotted on + a new window. +} +\usage{ +trex(phy, title = TRUE, subbg = "lightyellow3", + return.tree = FALSE, ...) +} +\arguments{ + \item{phy}{an object of class \code{"phylo"}.} + \item{title}{a logical or a character string (see details).} + \item{subbg}{a character string giving the background colour for the + subtree.} + \item{return.tree}{a logical: if \code{TRUE}, the subtree is returned + after being plotted and the operation is stopped.} + \item{\dots}{further arguments to pass to \code{plot.phylo}.} +} +\details{ + This function works with a tree (freshly) plotted on an interactive + graphical device (i.e., not a file). After calling \code{trex}, the + user clicks close to a node of the tree, then the clade from this node + is plotted on a \emph{new} window. The user can click as many times on + the main tree: the clades are plotted successively on the \emph{same} + new window. The process is stopped by a right-click. If the user clicks + too close to the tips, a message ``Try again!'' is printed. + + Each time \code{trex} is called, the subtree is plotted on a new + window without closing or deleting those possibly already + plotted. They may be distinguished with the options \code{title} + and/or \code{subbg}. + + In all cases, the device where \code{phy} is plotted is the active + window after the operation. It should \emph{not} be closed during the + whole process. + + If \code{title = TRUE}, a default title is printed on the new window + using the node label, or the node number if there are no node labels + in the tree. If \code{title = FALSE}, no title is printed. If + \code{title} is a character string, this is used for the title. +} +\value{ + an object of class \code{"phylo"} if \code{return.tree = TRUE} +} +\author{Emmanuel Paradis} +\seealso{ + \code{\link{plot.phylo}}, \code{\link{identify.phylo}} +} +\examples{ +\dontrun{ +tr <- rcoal(1000) +plot(tr, show.tip.label = FALSE) +trex(tr) # left-click as many times as you want, then right-click +tr <- makeNodeLabel(tr) +trex(tr, subbg = "lightgreen") # id. + +## generate a random colour with control on the darkness: +rRGB <- function(a, b) + rgb(runif(1, a, b), runif(1, a, b), runif(1, a, b)) + +### with a random pale background: +trex(tr, subbg = rRGB(0.8, 1)) +## the above can be called many times... +graphics.off() # close all graphical devices +}} +\keyword{hplot} -- 2.39.2