]> git.donarmstrong.com Git - ape.git/blobdiff - R/rtree.R
new operators for "multiPhylo" + fixed small bug in bind.tree()
[ape.git] / R / rtree.R
index 6829b02d294be46753894cea6f074f5e09bfbd3d..46f9abd3c3cc435de4adc92fb0a32d1b73bbb1e7 100644 (file)
--- a/R/rtree.R
+++ b/R/rtree.R
@@ -1,8 +1,8 @@
-## rtree.R (2000-05-13)
+## rtree.R (2010-03-09)
 
-##   Generates Random Trees
+##   Generates Trees
 
-## Copyright 2004-2009 Emmanuel Paradis
+## Copyright 2004-2010 Emmanuel Paradis
 
 ## This file is part of the R-package `ape'.
 ## See the file ../COPYING for licensing issues.
@@ -94,7 +94,10 @@ rtree <- function(n, rooted = TRUE, tip.label = NULL, br = runif, ...)
     phy$tip.label <-
       if (is.null(tip.label)) paste("t", sample(n), sep = "")
       else sample(tip.label)
-    if (is.function(br)) phy$edge.length <- br(nbr, ...)
+    if (!is.null(br)) {
+        phy$edge.length <-
+            if (is.function(br)) br(nbr, ...) else rep(br, length.out = nbr)
+    }
     phy$Nnode <- n - 2L + rooted
     class(phy) <- "phylo"
     phy
@@ -107,7 +110,7 @@ rcoal <- function(n, tip.label = NULL, br = "coalescent", ...)
     edge <- matrix(NA, nbr, 2)
     ## coalescence times by default:
     x <- if (is.character(br)) 2*rexp(n - 1)/(as.double(n:2) * as.double((n - 1):1))
-    else br(n - 1, ...)
+    else if (is.numeric(br)) rep(br, length.out = n - 1) else br(n - 1, ...)
     if (n == 2) {
         edge[] <- c(3L, 3L, 1:2)
         edge.length <- rep(x, 2)
@@ -150,3 +153,60 @@ rmtree <- function(N, n, rooted = TRUE, tip.label = NULL, br = runif, ...)
     class(a) <- "multiPhylo"
     a
 }
+
+stree <- function(n, type = "star", tip.label = NULL)
+{
+    type <- match.arg(type, c("star", "balanced", "left", "right"))
+    n <- as.integer(n)
+    if (type == "star") {
+        N <- n
+        m <- 1L
+    } else {
+        m <- n - 1L
+        N <- n + m - 1L
+    }
+    edge <- matrix(0L, N, 2)
+
+    switch(type, "star" = {
+        edge[, 1] <- n + 1L
+        edge[, 2] <- 1:n
+    }, "balanced" = {
+        if (log2(n) %% 1)
+            stop("'n' is not a power of 2: cannot make a balanced tree")
+        foo <- function(node, size) {
+            if (size == 2) {
+                edge[c(i, i + 1L), 1L] <<- node
+                edge[c(i, i + 1L), 2L] <<- c(nexttip, nexttip + 1L)
+                nexttip <<- nexttip + 2L
+                i <<- i + 2L
+            } else {
+                for (k in 1:2) { # do the 2 subclades
+                    edge[i, ] <<- c(node, nextnode)
+                    nextnode <<- nextnode + 1L
+                    i <<- i + 1L
+                    foo(nextnode - 1L, size/2)
+                }
+            }
+        }
+        i <- 1L
+        nexttip <- 1L
+        nextnode <- n + 2L
+        foo(n + 1L, n)
+    }, "left" = {
+        edge[c(seq.int(from = 1, to = N - 1, by = 2), N), 2L] <- 1:n
+        nodes <- (n + 1L):(n + m)
+        edge[seq.int(from = 2, to = N - 1, by = 2), 2L] <- nodes[-1]
+        edge[, 1L] <- rep(nodes, each = 2)
+    }, "right" = {
+        nodes <- (n + 1L):(n + m)
+        edge[, 1L] <- c(nodes, rev(nodes))
+        edge[, 2L] <- c(nodes[-1], 1:n)
+    })
+
+    if (is.null(tip.label))
+        tip.label <- paste("t", 1:n, sep = "")
+    phy <- list(edge = edge, tip.label = tip.label, Nnode = m)
+    class(phy) <- "phylo"
+    attr(phy, "order" <- "cladewise")
+    phy
+}