o The new function parafit by Pierre Legendre tests for the
coevolution between hosts and parasites. It has a companion
- function, pcoa, that does principal coordinate decomposition. The
- latter has a biplot method.
+ function, pcoa, that does principal coordinate decomposition.
+ The latter has a biplot method.
o The new function lmorigin by Pierre Legendre performs multiple
regression through the origin with testing by permutation.
o The new function delta.plot does a delta plot following Holland et
al. (2002, Mol. Biol. Evol. 12:2051).
+ o The new function edges draws additional branches between any nodes
+ and/or tips on a plotted tree.
+
+ o The new function fancyarrows enhances arrows from graphics with
+ triangle and harpoon heads; it can be called from edges().
+
o add.scale.bar() has a new option 'ask' to draw interactively.
o The branch length score replaces the geodesic distance in dist.topo.
-## nodelabels.R (2009-09-30)
+## nodelabels.R (2010-01-30)
## Labelling Trees
-## Copyright 2004-2009 Emmanuel Paradis, 2006 Ben Bolker, and 2006 Jim Lemon
+## Copyright 2004-2010 Emmanuel Paradis, 2006 Ben Bolker, and 2006 Jim Lemon
## This file is part of the R-package `ape'.
## See the file ../COPYING for licensing issues.
BOTHlabels(text, sel, XX, YY, adj, frame, pch, thermo,
pie, piecol, col, bg, ...)
}
+
+edges <- function(nodes0, nodes1, arrows = 0, type = "classical", ...)
+{
+ type <- match.arg(type, c("classical", "triangle", "harpoon"))
+ lastPP <- get("last_plot.phylo", envir = .PlotPhyloEnv)
+ ## we do the recycling if necessary:
+ if (length(nodes0) != length(nodes1)) {
+ tmp <- cbind(nodes0, nodes1)
+ nodes0 <- tmp[, 1]
+ nodes1 <- tmp[, 2]
+ }
+ x0 <- lastPP$xx[nodes0]
+ y0 <- lastPP$yy[nodes0]
+ x1 <- lastPP$xx[nodes1]
+ y1 <- lastPP$yy[nodes1]
+ if (arrows)
+ if (type == "classical")
+ graphics::arrows(x0, y0, x1, y1, code = arrows, ...)
+ else
+ fancyarrows(x0, y0, x1, y1, code = arrows, type = type, ...)
+ else
+ graphics::segments(x0, y0, x1, y1, ...)
+}
+
+fancyarrows <-
+ function(x0, y0, x1, y1, length = 0.25, angle = 30, code = 2,
+ col = par("fg"), lty = par("lty"), lwd = par("lwd"),
+ type = "triangle", ...)
+{
+ foo <- function(x0, y0, x1, y1) {
+ ## important to correct with these parameters cause
+ ## the coordinate system will likely not be Cartesian
+ pin <- par("pin")
+ usr <- par("usr")
+ A1 <- pin[1]/diff(usr[1:2])
+ A2 <- pin[2]/diff(usr[3:4])
+ x0 <- x0 * A1
+ y0 <- y0 * A2
+ x1 <- x1 * A1
+ y1 <- y1 * A2
+ atan2(y1 - y0, x1 - x0)
+ }
+ arrow.triangle <- function(x, y) {
+ beta <- alpha - angle/2
+ xa <- xinch(length * cos(beta)) + x
+ ya <- yinch(length * sin(beta)) + y
+ beta <- beta + angle
+ xb <- xinch(length * cos(beta)) + x
+ yb <- yinch(length * sin(beta)) + y
+ n <- length(x)
+ col <- rep(col, length.out = n)
+ for (i in 1:n)
+ polygon(c(x[i], xa[i], xb[i]), c(y[i], ya[i], yb[i]),
+ col = col[i], border = col[i])
+ list((xa + xb)/2, (ya + yb)/2)
+ }
+ arrow.harpoon <- function(x, y) {
+ beta <- alpha - angle/2
+ xa <- xinch(length * cos(beta)) + x
+ ya <- yinch(length * sin(beta)) + y
+ beta <- alpha + angle/2
+ xb <- xinch(length * cos(beta)) + x
+ yb <- yinch(length * sin(beta)) + y
+ xc <- x/2 + (xa + xb)/4
+ yc <- y/2 + (ya + yb)/4
+ n <- length(x)
+ col <- rep(col, length.out = n)
+ for (i in 1:n)
+ polygon(c(x[i], xa[i], xc[i], xb[i]),
+ c(y[i], ya[i], yc[i], yb[i]),
+ col = col[i], border = col[i])
+ list(xc, yc)
+ }
+
+ type <- match.arg(type, c("triangle", "harpoon"))
+ angle <- pi*angle/180 # degree -> radian
+ alpha <- foo(x0, y0, x1, y1) # angle of segment with x-axis
+ ## alpha is in [-pi, pi]
+
+ FUN <- if (type == "triangle") arrow.triangle else arrow.harpoon
+ XY0 <- if (code == 1 || code == 3) FUN(x0, y0) else list(x0, y0)
+ if (code >= 2) {
+ alpha <- (alpha + pi) %% (2 * pi)
+ XY1 <- FUN(x1, y1)
+ } else XY1 <- list(x1, y1)
+ segments(XY0[[1]], XY0[[2]], XY1[[1]], XY1[[2]], col = col, lty = lty, lwd = lwd, ...)
+}
--- /dev/null
+\name{edges}
+\alias{edges}
+\alias{fancyarrows}
+\title{Draw Additional Edges on a Plotted Tree}
+\description{
+ \code{edges} draws edges on a plotted tree. \code{fancyarrows}
+ enhances \code{\link[graphics]{arrows}} with triangle and harpoon
+ heads; it can be called from \code{edges}.
+}
+\usage{
+edges(nodes0, nodes1, arrows = 0, type = "classical", ...)
+fancyarrows(x0, y0, x1, y1, length = 0.25, angle = 30, code = 2,
+ col = par("fg"), lty = par("lty"), lwd = par("lwd"),
+ type = "triangle", ...)
+}
+\arguments{
+ \item{nodes0, nodes1}{vectors of integers giving the tip and/or node
+ numbers where to start and to end the edges (eventually recycled).}
+ \item{arrows}{an integer between 0 and 3; 0: lines (the default); 1:
+ an arrow head is drawn at \code{nodes0}; 2: at \code{nodes1}; 3:
+ both.}
+ \item{type}{if the previous argument is not 0, the type of arrow head:
+ \code{"classical"} (just lines, the default), \code{"triangle"},
+ \code{"harpoon"}, or any unambiguous abbreviations of these. For
+ \code{fancyarrows} only the last two are available.}
+ \item{x0, y0, x1, y1}{the coordinates of the start and end points for
+ \code{fancyarrows} (these are not recycled and so should be vectors
+ of the same length).}
+ \item{length, angle, code, col, lty, lwd}{default options similar to
+ those of \code{\link[graphics]{arrows}}.}
+ \item{\dots}{further arguments passed to \code{\link[graphics]{segments}}.}
+}
+\details{
+ The first function is helpful when drawing reticulations on a phylogeny,
+ especially if computed from the edge matrix.
+}
+\author{Emmanuel Paradis}
+\seealso{
+ \code{\link{plot.phylo}}, \code{\link{nodelabels}}
+}
+\examples{
+set.seed(2)
+tr <- rcoal(6)
+plot(tr, "c")
+edges(10, 9, col = "red", lty = 2)
+edges(10:11, 8, col = c("blue", "green")) # recycling of 'nodes1'
+edges(1, 2, lwd = 2, type = "h", arrows = 3, col = "green")
+nodelabels()
+}
+\keyword{aplot}