-## plot.phylo.R (2009-09-23)
+## plot.phylo.R (2010-03-19)
## Plot Phylogenies
-## Copyright 2002-2009 Emmanuel Paradis
+## Copyright 2002-2010 Emmanuel Paradis
## This file is part of the R-package `ape'.
## See the file ../COPYING for licensing issues.
phyloORclado <- type %in% c("phylogram", "cladogram")
horizontal <- direction %in% c("rightwards", "leftwards")
+ xe <- x$edge # to save
if (phyloORclado) {
## we first compute the y-coordinates of the tips.
phyOrder <- attr(x, "order")
## make sure the tree is in cladewise order:
if (is.null(phyOrder) || phyOrder != "cladewise") {
- xe <- x$edge
x <- reorder(x) # fix from Klaus Schliep (2007-06-16)
if (!identical(x$edge, xe)) {
## modified from Li-San Wang's fix (2007-01-23):
} else {
xx <- .nodeDepthEdgelength(Ntip, Nnode, z$edge, Nedge, z$edge.length)
}
- }
- if (type == "fan") {
+ } else switch(type, "fan" = {
## if the tips are not in the same order in tip.label
## and in edge[, 2], we must reorder the angles: we
## use `xx' to store temporarily the angles
}
xx <- r*cos(theta)
yy <- r*sin(theta)
-
- }
- if (type == "unrooted") {
+ }, "unrooted" = {
nb.sp <- .nodeDepth(Ntip, Nnode, z$edge, Nedge)
XY <- if (use.edge.length)
unrooted.xy(Ntip, Nnode, z$edge, z$edge.length, nb.sp)
## rescale so that we have only positive values
xx <- XY$M[, 1] - min(XY$M[, 1])
yy <- XY$M[, 2] - min(XY$M[, 2])
- }
- if (type == "radial") {
+ }, "radial" = {
X <- .nodeDepth(Ntip, Nnode, z$edge, Nedge)
X[X == 1] <- 0
## radius:
Y <- .nodeHeight(Ntip, Nnode, z$edge, Nedge, yy)
xx <- X * cos(Y)
yy <- X * sin(Y)
- }
+ })
if (phyloORclado) {
if (!horizontal) {
tmp <- yy
tmp <- if (show.tip.label) max(xx.tips + strWi/alp) else max(xx.tips)
}
x.lim[2] <- tmp
- if (direction == "leftwards") xx <- x.lim[2] - xx #max(xx[ROOT] + tmp)
-# else max(xx[1:Ntip] + tmp)
} else x.lim <- c(1, Ntip)
- }
- if (type == "fan") {
+ } else switch(type, "fan" = {
if (show.tip.label) {
offset <- max(nchar(x$tip.label) * 0.018 * max(yy) * cex)
x.lim <- c(min(xx) - offset, max(xx) + offset)
} else x.lim <- c(min(xx), max(xx))
- }
- if (type == "unrooted") {
+ }, "unrooted" = {
if (show.tip.label) {
offset <- max(nchar(x$tip.label) * 0.018 * max(yy) * cex)
x.lim <- c(0 - offset, max(xx) + offset)
} else x.lim <- c(0, max(xx))
- }
- if (type == "radial") {
+ }, "radial" = {
if (show.tip.label) {
offset <- max(nchar(x$tip.label) * 0.03 * cex)
x.lim <- c(-1 - offset, 1 + offset)
} else x.lim <- c(-1, 1)
- }
+ })
} else if (length(x.lim) == 1) {
x.lim <- c(0, x.lim)
if (phyloORclado && !horizontal) x.lim[1] <- 1
if (show.tip.label) -1 - max(nchar(x$tip.label) * 0.03 * cex)
else -1
}
+ ## mirror the xx:
+ if (phyloORclado && direction == "leftwards") xx <- x.lim[2] - xx
if (is.null(y.lim)) {
if (phyloORclado) {
if (horizontal) y.lim <- c(1, Ntip) else {
tmp <- if (show.tip.label) max(yy.tips + strWi/alp) else max(yy.tips)
}
y.lim[2] <- tmp
- if (direction == "downwards") yy <- y.lim[2] - yy
}
- }
- if (type == "fan") {
+ } else switch(type, "fan" = {
if (show.tip.label) {
offset <- max(nchar(x$tip.label) * 0.018 * max(yy) * cex)
y.lim <- c(min(yy) - offset, max(yy) + offset)
} else y.lim <- c(min(yy), max(yy))
- }
- if (type == "unrooted") {
+ }, "unrooted" = {
if (show.tip.label) {
offset <- max(nchar(x$tip.label) * 0.018 * max(yy) * cex)
y.lim <- c(0 - offset, max(yy) + offset)
} else y.lim <- c(0, max(yy))
- }
- if (type == "radial") {
+ }, "radial" = {
if (show.tip.label) {
offset <- max(nchar(x$tip.label) * 0.03 * cex)
y.lim <- c(-1 - offset, 1 + offset)
} else y.lim <- c(-1, 1)
- }
+ })
} else if (length(y.lim) == 1) {
y.lim <- c(0, y.lim)
if (phyloORclado && horizontal) y.lim[1] <- 1
if (type == "radial")
y.lim[1] <- if (show.tip.label) -1 - max(nchar(x$tip.label) * 0.018 * max(yy) * cex) else -1
}
+ ## mirror the yy:
+ if (phyloORclado && direction == "downwards") yy <- y.lim[2] - yy
if (phyloORclado && root.edge) {
if (direction == "leftwards") x.lim[2] <- x.lim[2] + x$root.edge
if (direction == "downwards") y.lim[2] <- y.lim[2] + x$root.edge
}
- ## fix by Klaus Schliep (2008-03-28):
- asp <- if (type %in% c("fan", "radial")) 1 else NA
+ asp <- if (type %in% c("fan", "radial")) 1 else NA # fix by Klaus Schliep (2008-03-28)
plot(0, type = "n", xlim = x.lim, ylim = y.lim, ann = FALSE, axes = FALSE, asp = asp, ...)
if (is.null(adj))
adj <- if (phyloORclado && direction == "leftwards") 1 else 0
"upwards" = segments(xx[ROOT], 0, xx[ROOT], x$root.edge),
"downwards" = segments(xx[ROOT], yy[ROOT], xx[ROOT], yy[ROOT] + x$root.edge))
if (show.tip.label) {
+ if (is.expression(x$tip.label)) underscore <- TRUE
if (!underscore) x$tip.label <- gsub("_", " ", x$tip.label)
if (phyloORclado)
}
}
if (type %in% c("fan", "radial")) {
- xx.scaled <- xx[1:Ntip]
- if (type == "fan") { # no need if type == "radial"
- maxx <- max(abs(xx.scaled))
- if (maxx > 1) xx.scaled <- xx.scaled/maxx
- }
- angle <- acos(xx.scaled)*180/pi
- s1 <- angle > 90 & yy[1:Ntip] > 0
- s2 <- angle < 90 & yy[1:Ntip] < 0
- s3 <- angle > 90 & yy[1:Ntip] < 0
- angle[s1] <- angle[s1] + 180
- angle[s2] <- -angle[s2]
- angle[s3] <- 180 - angle[s3]
+ xx.tips <- xx[1:Ntip]
+ ## using atan2 considerably facilitates things compared to acos...
+ angle <- atan2(yy[1:Ntip], xx.tips)*180/pi
+ s <- xx.tips < 0
+ angle[s] <- angle[s] + 180
adj <- numeric(Ntip)
- adj[xx[1:Ntip] < 0] <- 1
+ adj[xx.tips < 0] <- 1
## `srt' takes only a single value, so can't vectorize this:
for (i in 1:Ntip)
- text(xx[i], yy[i], x$tip.label[i], font = font, cex = cex,
- srt = angle[i], adj = adj[i], col = tip.color[i])
+ text(xx[i], yy[i], x$tip.label[i], font = font, cex = cex,
+ srt = angle[i], adj = adj[i], col = tip.color[i])
}
}
if (show.node.label)
label.offset = label.offset, x.lim = x.lim, y.lim = y.lim,
direction = direction, tip.color = tip.color,
Ntip = Ntip, Nnode = Nnode)
- assign("last_plot.phylo", c(L, list(edge = x$edge, xx = xx, yy = yy)),
+ assign("last_plot.phylo", c(L, list(edge = xe, xx = xx, yy = yy)),
envir = .PlotPhyloEnv)
invisible(L)
}
}
## ... et un trait horizontal partant de chaque tip et chaque noeud
## vers la racine
-### sq <- c(1:Ntip, nodes[-1])
-### y0h <- yy[sq]
-### x1h <- xx[sq]
-### ## match() is very useful here becoz each element in edge[, 2] is
-### ## unique (not sure this is so useful in edge[, 1]; needs to be checked)
-### ## `pos' gives for each element in `sq' its index in edge[, 2]
-### pos <- match(sq, edge[, 2])
-### x0h <- xx[edge[pos, 1]]
x0h <- xx[edge[, 1]]
x1h <- xx[edge[, 2]]
y0h <- yy[edge[, 2]]
-### donc plus besoin de 'pos' ni 'sq'
nc <- length(edge.color)
nw <- length(edge.width)
edge.color <- rep(edge.color, length.out = Nedge)
edge.width <- rep(edge.width, length.out = Nedge)
edge.lty <- rep(edge.lty, length.out = Nedge)
- DF <- data.frame(edge.color, edge.width, edge.lty)
+ DF <- data.frame(edge.color, edge.width, edge.lty, stringsAsFactors = FALSE)
color.v <- rep("black", Nnode)
width.v <- rep(1, Nnode)
lty.v <- rep(1, Nnode)
}
}
-### ## function dispatching the features to the vertical edges
-### foo <- function(edge.feat, default) {
-### e <- unique(edge.feat)
-### if (length(e) == 1) return(rep(e, Nnode))
-### else {
-### feat.v <- rep(default, Nnode)
-### for (i in 1:Nnode) {
-### br <- NodeInEdge1[[i]]
-### if (length(br) > 2) {
-### x <- unique(edge.feat[br])
-### if (length(x) == 1) feat.v[i] <- x
-### } else {
-### if (edge.feat[br[1]] == edge.feat[br[2]])
-### feat.v[i] <- edge.feat[br[1]]
-### else {
-### feat.v[i] <- edge.feat[br[2]]
-### ## add a new line:
-### y0v <<- c(y0v, y0v[i])
-### y1v <<- c(y1v, yy[i + Ntip])
-### x0v <<- c(x0v, x0v[i])
-### feat.v <- c(feat.v, edge.feat[br[1]])
-### ## shorten the line:
-### y0v[i] <<- yy[i + Ntip]
-### }
-### }
-### }
-### }
-### feat.v
-### }
-### color.v <- foo(edge.color, "black")
-### width.v <- foo(edge.width, 1)
-### lty.v <- foo(edge.lty, 1)
-
-### ## we need to reorder:
-### edge.width <- edge.width[pos]
-### edge.color <- edge.color[pos]
-### edge.lty <- edge.lty[pos]
-
if (horizontal) {
segments(x0h, y0h, x1h, y0h, col = edge.color, lwd = edge.width, lty = edge.lty) # draws horizontal lines
segments(x0v, y0v, x0v, y1v, col = color.v, lwd = width.v, lty = lty.v) # draws vertical lines
par(ask = TRUE)
on.exit(par(ask = FALSE))
}
- for (i in x) plot(i, ...)
+ for (i in 1:length(x)) plot(x[[i]], ...)
}