tree2phyDat <- function(trees) {
# some minor error checking
if (!inherits(trees, "multiPhylo"))
stop("trees must be of class multiPhylo")
labels <- lapply(trees, function(x) sort(x$tip.label))
ulabels <- unique(labels)
lul <- length(ulabels)
# compute matrix representation phylogenies
X <- vector("list", lul) # list of bipartitions
characters <- 0 # number of characters
weights <- NULL
species <- trees[[1]]$tip.label
characters <- 0 # number of characters
weights <- NULL
for (i in 1:lul) {
pos <- match(labels, ulabels[i])
ind <- which(!is.na(pos))
temp <- prop.part(trees[ind]) # find all bipartitions
# create matrix representation of trees[[i]] in X[[i]]
TMP <- matrix(1L, nrow = length(temp) - 1,
ncol = length(trees[[ind[1]]]$tip.label))
for (j in seq_len(nrow(TMP))) TMP[j, c(temp[[j + 1]])] <- 2L
colnames(TMP) <- attr(temp, "labels") # label rows
X[[i]] <- TMP
species <- union(species, trees[[ind[1]]]$tip.label) # accumulate labels
characters <- characters + nrow(TMP) # count characters
weights <- c(weights, attr(temp, "number")[-1])
}
data <- matrix(data = 3L, nrow = characters, ncol = length(species),
dimnames = list(NULL, species))
j <- 1
for (i in seq_along(X)) {
# copy each of X into supermatrix data
data[c(j:((j - 1) + nrow(X[[i]]))), colnames(X[[i]])] <- X[[i]]
# [1:nrow(X[[i]]),1:ncol(X[[i]])]
j <- j + nrow(X[[i]])
}
data <- as.data.frame(data)
# compute contrast matrix
contrast <- matrix(data = c(1, 0, 0, 1, 1, 1), 3, 2,
dimnames = list(NULL, c("0", "1")), byrow = TRUE)
attr(data, "row.names") <- NULL
class(data) <- "phyDat"
attr(data, "weight") <- weights
attr(data, "nr") <- length(weights)
attr(data, "nc") <- 2L
attr(data, "levels") <- c("0", "1")
attr(data, "allLevels") <- c("0", "1", "?")
attr(data, "type") <- "USER"
attr(data, "contrast") <- contrast
class(data) <- "phyDat"
data
}
my.supertree <- function(trees, trace = 0, ...) {
has_edge_length <- vapply(trees, function(x) !is.null(x$edge.length), FALSE)
if (all(has_edge_length)){
trees <- .uncompressTipLabel(trees)
trees <- di2multi(trees)
}
XX <- tree2phyDat(trees)
supertree <- pratchet(XX, trace = trace, ...)
# maybe add edge length supertree <- acctran(supertree, XX)
return(supertree)
}
# Robinson-Foulds supertree
fun.rf <- function(x, tree) sum(RF.dist(x, tree))
fun.spr <- function(x, tree) sum(SPR.dist(x, tree))
dist.superTree <- function(tree, trace = 0, fun, start = NULL,
multicore = FALSE, mc.cores = NULL) {
if(.Platform$OS.type=="windows") multicore <- FALSE
if (multicore && is.null(mc.cores)) mc.cores <- detectCores()
if (is.null(start)) start <- superTree(tree, rooted = FALSE)
if (inherits(start, "multiPhylo")) start <- start[[1]]
best_tree <- unroot(start)
best <- fun(best_tree, tree)
if (trace > 0) cat("best score so far:", best, "\n")
eps <- TRUE
while (eps) {
nni_trees <- nni(best_tree)
if (multicore) {
tmp <- mclapply(nni_trees, fun, tree, mc.cores = mc.cores)
tmp <- unlist(tmp)
}
else tmp <- sapply(nni_trees, fun, tree)
if (min(tmp) < best) {
ind <- which.min(tmp)
best_tree <- nni_trees[[ind]]
best <- tmp[ind]
if (trace > 0) cat("best score so far:", best, "\n")
}
else eps <- FALSE
}
attr(best_tree, "score") <- best
best_tree
}
#' Super Tree methods
#'
#' These function \code{superTree} allows the estimation of a supertree from a
#' set of trees using either Matrix representation parsimony, Robinson-Foulds
#' or SPR as criterion.
#'
#' The function \code{superTree} extends the function mrp.supertree from Liam
#' Revells, with artificial adding an outgroup on the root of the trees. This
#' allows to root the supertree afterwards. The functions is internally used in
#' DensiTree. The implementation for the RF- and SPR-supertree are very basic
#' so far and assume that all trees share the same set of taxa.
#'
#' @param tree an object of class \code{multiPhylo}
#' @param method An argument defining which algorithm is used to optimize the
#' tree. Possible are "MRP", "RF", and "SPR".
#' @param rooted should the resulting supertrees be rooted.
#' @param trace defines how much information is printed during optimization.
#' @param start a starting tree can be supplied.
#' @param multicore logical, whether models should estimated in parallel.
#' @param mc.cores The number of cores to use, i.e. at most how many child
#' processes will be run simultaneously.
#' @param \dots further arguments passed to or from other methods.
#' @return The function returns an object of class \code{phylo}.
#' @author Klaus Schliep \email{klaus.schliep@@gmail.com} Liam Revell
#' @seealso \code{mrp.supertree}, \code{\link{densiTree}},
#' \code{\link{RF.dist}}, \code{\link{SPR.dist}}
#' @references Baum, B. R., (1992) Combining trees as a way of combining data
#' sets for phylogenetic inference, and the desirability of combining gene
#' trees. \emph{Taxon}, \bold{41}, 3-10.
#'
#' Ragan, M. A. (1992) Phylogenetic inference based on matrix representation of
#' trees. \emph{Molecular Phylogenetics and Evolution}, \bold{1}, 53-58.
#' @keywords cluster
#' @examples
#'
#' data(Laurasiatherian)
#' set.seed(1)
#' bs <- bootstrap.phyDat(Laurasiatherian,
#' FUN = function(x) upgma(dist.hamming(x)), bs=50)
#'
#' mrp_st <- superTree(bs, minit = 25, maxit=50)
#' plot(mrp_st)
#' \donttest{
#' rf_st <- superTree(bs, method = "RF")
#' spr_st <- superTree(bs, method = "SPR")
#' }
#'
#' @export superTree
superTree <- function(tree, method = "MRP", rooted = FALSE, trace = 0,
start = NULL, multicore = FALSE, mc.cores = NULL, ...) {
fun <- function(x) {
x <- reorder(x, "postorder")
nTips <- length(x$tip.label)
x$edge[x$edge > nTips] <- x$edge[x$edge > nTips] + 2L
l <- nrow(x$edge)
oldroot <- x$edge[l, 1L]
x$edge <- rbind(x$edge, matrix(c(rep(nTips + 2, 2), oldroot, nTips + 1),
2L, 2L))
x$edge.length <- c(x$edge.length, 100, 100)
x$tip.label <- c(x$tip.label, "ZZZ")
x$Nnode <- x$Nnode + 1L
x
}
# labels_start <- unique(unlist(lapply(tree, function(x)x$tip.label)))
# TODO check for missing labels
tmp <- Nnode(tree)
if(any(tmp < (3 + !rooted))){
tree_tmp <- tree[ tmp > (2 + !rooted) ]
if (length(tree_tmp) == 0) return(consensus(tree))
tree <- tree_tmp
}
# start <- allCompat(tree) ??
if (method != "MRP") rooted <- FALSE
if (!rooted) tree <- unroot(tree)
if (method == "MRP" | is.null(start)) {
if (rooted) {
if (!is.null(attr(tree, "TipLabel"))) tree <- .uncompressTipLabel(tree)
tree <- unclass(tree)
if (rooted) tree <- lapply(tree, fun)
class(tree) <- "multiPhylo"
}
res <- my.supertree(tree, trace = trace, ...)
if (rooted) {
# if (inherits(res, "multiPhylo")) {
# res <- lapply(res, root, "ZZZ")
# res <- lapply(res, drop.tip, "ZZZ")
# class(res) <- "multiPhylo"
# }
# else {
res <- root(res, "ZZZ")
res <- drop.tip(res, "ZZZ")
# }
}
if (inherits(res, "multiPhylo")) {
fun <- function(x) {
x$edge.length <- rep(.1, nrow(x$edge))
x
}
res <- lapply(res, fun)
res <- lapply(res, reorder, "postorder")
class(res) <- "multiPhylo"
}
else {
res$edge.length <- rep(.1, nrow(res$edge))
res <- reorder(res, "postorder")
}
}
if (method == "MRP") return(res)
if (is.null(start)) start <- res
tree <- unroot(tree)
tree <- reorder(tree, "postorder")
if (method == "RF") res <- dist.superTree(tree, trace = trace, fun.rf,
start = start, multicore = multicore, mc.cores = mc.cores)
if (method == "SPR") res <- dist.superTree(tree, trace = trace, fun.spr,
start = start, multicore = multicore, mc.cores = mc.cores)
res
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.