]> git.donarmstrong.com Git - ape.git/commitdiff
change nlm to nlminb in ace() + new makeNodeLabel + fixed drop.tip
authorparadis <paradis@6e262413-ae40-0410-9e79-b911bd7a66b7>
Mon, 23 Mar 2009 07:49:41 +0000 (07:49 +0000)
committerparadis <paradis@6e262413-ae40-0410-9e79-b911bd7a66b7>
Mon, 23 Mar 2009 07:49:41 +0000 (07:49 +0000)
git-svn-id: https://svn.mpl.ird.fr/ape/dev/ape@66 6e262413-ae40-0410-9e79-b911bd7a66b7

ChangeLog
DESCRIPTION
R/ace.R
R/drop.tip.R
R/makeNodeLabel.R [new file with mode: 0644]
Thanks
man/ace.Rd
man/makeNodeLabel.Rd [new file with mode: 0644]

index b6bffe8687b5bf9a7dc248c22ae7d5b7ed99725f..d659113a7cd989de0357b1303000d0a47674b66b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,13 +10,22 @@ NEW FEATURES
     o The new function yule.time fits a user-defined time-dependent
       Yule model by maximum likelihood.
 
     o The new function yule.time fits a user-defined time-dependent
       Yule model by maximum likelihood.
 
+    o The new function makeNodeLabel creates and/or modifies node
+      labels in a flexible way.
+
 
 BUG FIXES
 
     o drop.tip() shuffled tip labels in some cases.
 
 
 BUG FIXES
 
     o drop.tip() shuffled tip labels in some cases.
 
+    o drop.tip() did not handle node.label correctly.
+
     o is.ultrametric() now checks the ordering of the edge matrix.
 
     o is.ultrametric() now checks the ordering of the edge matrix.
 
+    o ace() sometimes returned negative values of likelihoods of
+      ancestral states (thanks to Dan Rabosky for solving this long
+      lasting bug).
+
 
 OTHER CHANGES
 
 
 OTHER CHANGES
 
index 1cc4f4a5db33950648020404c37519a60709e038..51c4cfc7521bf5690602170f13938196171210d9 100644 (file)
@@ -1,6 +1,6 @@
 Package: ape
 Version: 2.3
 Package: ape
 Version: 2.3
-Date: 2009-03-10
+Date: 2009-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,
 Title: Analyses of Phylogenetics and Evolution
 Author: Emmanuel Paradis, Ben Bolker, Julien Claude, Hoa Sien Cuong,
   Richard Desper, Benoit Durand, Julien Dutheil, Olivier Gascuel,
diff --git a/R/ace.R b/R/ace.R
index c38faeb6bdb2ef2b8b489139a841b3b5a440adaf..0439600832a0f1018af4b75974ea11703f2a6e02 100644 (file)
--- a/R/ace.R
+++ b/R/ace.R
@@ -1,4 +1,4 @@
-## ace.R (2009-01-19)
+## ace.R (2009-03-22)
 
 ##     Ancestral Character Estimation
 
 
 ##     Ancestral Character Estimation
 
@@ -170,13 +170,18 @@ as the number of categories in `x'")
             if (output.liks) return(liks[-(1:nb.tip), ])
             - 2 * log(sum(liks[nb.tip + 1, ]))
         }
             if (output.liks) return(liks[-(1:nb.tip), ])
             - 2 * log(sum(liks[nb.tip + 1, ]))
         }
-        out <- nlm(function(p) dev(p), p = rep(ip, length.out = np),
-                   hessian = TRUE)
-        obj$loglik <- -out$minimum / 2
-        obj$rates <- out$estimate
-        if (any(out$gradient == 0))
+        out <- nlminb(rep(ip, length.out = np), function(p) dev(p),
+                      lower = rep(0, np), upper = rep(Inf, np))
+        obj$loglik <- -out$objective/2
+        obj$rates <- out$par
+        oldwarn <- options("warn")
+        options(warn = -1)
+        h <- nlm(function(p) dev(p), p = obj$rates, iterlim = 1,
+                 stepmax = 0, hessian = TRUE)$hessian
+        options(oldwarn)
+        if (any(h == 0))
           warning("The likelihood gradient seems flat in at least one dimension (gradient null):\ncannot compute the standard-errors of the transition rates.\n")
           warning("The likelihood gradient seems flat in at least one dimension (gradient null):\ncannot compute the standard-errors of the transition rates.\n")
-        else obj$se <- sqrt(diag(solve(out$hessian)))
+        else obj$se <- sqrt(diag(solve(h)))
         obj$index.matrix <- index.matrix
         if (CI) {
             lik.anc <- dev(obj$rates, TRUE)
         obj$index.matrix <- index.matrix
         if (CI) {
             lik.anc <- dev(obj$rates, TRUE)
index 69c957629e6533598488d0f7b3c4ede773faede7..c0bda8bc15042186f101ac7f548e7fc1fb20dd34 100644 (file)
@@ -1,4 +1,4 @@
-## drop.tip.R (2009-03-04)
+## drop.tip.R (2009-03-22)
 
 ##   Remove Tips in a Phylogenetic Tree
 
 
 ##   Remove Tips in a Phylogenetic Tree
 
@@ -76,6 +76,7 @@ drop.tip <-
 {
     if (class(phy) != "phylo")
         stop('object "phy" is not of class "phylo"')
 {
     if (class(phy) != "phylo")
         stop('object "phy" is not of class "phylo"')
+    phy <- reorder(phy)
     Ntip <- length(phy$tip.label)
     NEWROOT <- ROOT <- Ntip + 1
     Nnode <- phy$Nnode
     Ntip <- length(phy$tip.label)
     NEWROOT <- ROOT <- Ntip + 1
     Nnode <- phy$Nnode
@@ -145,7 +146,10 @@ drop.tip <-
     TIPS <- phy$edge[, 2] <= Ntip
     ## keep the ordering so no need to reorder tip.label:
     phy$edge[TIPS, 2] <- rank(phy$edge[TIPS, 2])
     TIPS <- phy$edge[, 2] <= Ntip
     ## keep the ordering so no need to reorder tip.label:
     phy$edge[TIPS, 2] <- rank(phy$edge[TIPS, 2])
-    Ntip <- length(phy$tip.label) # update Ntip
+    ## 3) update node.label if needed
+    if (!is.null(phy$node.label))
+        phy$node.label <- phy$node.label[sort(unique(phy$edge[, 1])) - Ntip]
+    Ntip <- length(phy$tip.label) # 4) update Ntip
 
     ## make new tip labels if necessary
     if (subtree || !trim.internal) {
 
     ## make new tip labels if necessary
     if (subtree || !trim.internal) {
diff --git a/R/makeNodeLabel.R b/R/makeNodeLabel.R
new file mode 100644 (file)
index 0000000..d679f5e
--- /dev/null
@@ -0,0 +1,61 @@
+## makeNodeLabel.R (2009-03-22)
+
+##   Makes Node Labels
+
+## Copyright 2009 Emmanuel Paradis
+
+## This file is part of the R-package `ape'.
+## See the file ../COPYING for licensing issues.
+
+makeNodeLabel <- function(phy, method = "number", prefix = "Node",
+                          nodeList = list(), ...)
+{
+    method <- sapply(method, match.arg, c("number", "md5sum", "user"),
+                     USE.NAMES = FALSE)
+
+    if ("number" %in% method)
+        phy$node.label <- paste(prefix, 1:phy$Nnode, sep = "")
+
+    if ("md5sum" %in% method) {
+        nl <- character(phy$Nnode)
+        pp <- prop.part(phy, check.labels = FALSE)
+        labs <- attr(pp, "labels")
+        fl <- tempfile()
+        for (i in seq_len(phy$Nnode)) {
+            cat(sort(labs[pp[[i]]]), sep = "\n", file = fl)
+            nl[i] <- tools::md5sum(fl)
+        }
+        unlink(fl)
+        phy$node.label <- nl
+    }
+
+    if ("user" %in% method) {
+        if (is.null(phy$node.label))
+            phy$node.label <- character(phy$Nnode)
+        nl <- names(nodeList)
+        if (is.null(nl)) stop("argument 'nodeList' has no names")
+        Ntip <- length(phy$tip.label)
+        seq.nod <- .Call("seq_root2tip", phy$edge, Ntip, phy$Nnode,
+                         PACKAGE = "ape")
+        ## a local version to avoid the above call many times:
+        .getMRCA <- function(seq.nod, tip) {
+            sn <- seq.nod[tip]
+            MRCA <- Ntip + 1
+            i <- 2
+            repeat {
+                x <- unique(unlist(lapply(sn, "[", i)))
+                if (length(x) != 1) break
+                MRCA <- x
+                i <- i + 1
+            }
+            MRCA
+        }
+        for (i in seq_along(nodeList)) {
+            tips <- sapply(nodeList[[i]], grep, phy$tip.label, ...,
+                           USE.NAMES = FALSE)
+            j <- .getMRCA(seq.nod, unique(unlist(tips)))
+            phy$node.label[j - Ntip] <- nl[i]
+        }
+    }
+    phy
+}
diff --git a/Thanks b/Thanks
index 8f93403e4748d0fc9b8329e11b75a3381835ba65..57e3cb259be8cb042aa554fa3149471ed787837d 100644 (file)
--- a/Thanks
+++ b/Thanks
@@ -6,8 +6,8 @@ comments, or bug reports: thanks to all of you!
 
 Significant bug fixes were provided by Cécile Ané, James Bullard,
 Éric Durand, Olivier François, Bret Larget, Nick Matzke,
 
 Significant bug fixes were provided by Cécile Ané, James Bullard,
 Éric Durand, Olivier François, Bret Larget, Nick Matzke,
-Elizabeth Purdom, Klaus Schliep, Li-San Wang, Yan Wong, and Peter
-Wragg. Contact me if I forgot someone.
+Elizabeth Purdom, Dan Rabosky, Klaus Schliep, Li-San Wang, Yan Wong,
+and Peter Wragg. Contact me if I forgot someone.
 
 Kurt Hornik, of the R Core Team, helped in several occasions to
 fix some problems and bugs.
 
 Kurt Hornik, of the R Core Team, helped in several occasions to
 fix some problems and bugs.
index 85cfb210bbbea57af3f7f0786d6b4f4028ea8e89..73934dfb303498aacbdcaf7a2fe78bc536f7b532 100644 (file)
@@ -41,7 +41,7 @@ ace(x, phy, type = "continuous", method = "ML", CI = TRUE,
   \item{k}{a numeric value giving the penalty per estimated parameter;
     the default is \code{k = 2} which is the classical Akaike
     information criterion.}
   \item{k}{a numeric value giving the penalty per estimated parameter;
     the default is \code{k = 2} which is the classical Akaike
     information criterion.}
-  \item{...}{further arguments passed to or from other methods.}
+  \item{\dots}{further arguments passed to or from other methods.}
 }
 \description{
   This function estimates ancestral character states, and the associated
 }
 \description{
   This function estimates ancestral character states, and the associated
diff --git a/man/makeNodeLabel.Rd b/man/makeNodeLabel.Rd
new file mode 100644 (file)
index 0000000..501f405
--- /dev/null
@@ -0,0 +1,69 @@
+\name{makeNodeLabel}
+\alias{makeNodeLabel}
+\title{Makes Node Labels}
+\description{
+  This function makes node labels in a tree in a flexible way.
+}
+
+\usage{
+makeNodeLabel(phy, method = "number", prefix = "Node", nodeList = list(), ...)
+}
+\arguments{
+  \item{phy}{an object of class \code{"phylo"}.}
+  \item{method}{a character string giving the method used to create the
+    labels. Three choices are possible: \code{"number"} (the default),
+    \code{"md5sum"}, and \code{"user"}, or any unambiguous abbreviation
+    of these.}
+  \item{prefix}{the prefix used if \code{method = "number"}.}
+  \item{nodeList}{a named list specifying how nodes are names if
+    \code{method = "user"} (see details and examples).}
+   \item{\dots}{further arguments passed to \code{grep}.}
+}
+\details{
+  The three methods are described below:
+
+  \itemize{
+    \item{``number''}{The labels are created with 1, 2, \dots suffixed
+      with the argument \code{prefix}; thus the default is to have
+      Node1, Node2, \dots Set \code{prefix = ""} to have only numbers.}
+    \item{``md5sum''}{For each node, the labels of the tips descendant
+      from this node are extracted, sorted alphabetically, and written
+      into a temporary file, then the md5sum of this file is extracted
+      and used as label. This results in a 32-character string which is
+      unique (even accross trees) for a given set of tip labels.}
+    \item{``user''}{the argument \code{nodeList} must be a list with
+      names, the latter will be used as node labels. For each element of
+      \code{nodeList}, the tip labels of the tree are searched for
+      patterns present in this element: this is done using
+      \code{\link[base]{grep}}. Then the most recent common ancestor of
+      the matching tips is given the corresponding names as labels. This
+      is repeated for each element of \code{nodeList}.}
+  }
+
+  The method \code{"user"} can be used in combination with either of the
+  two others (see examples). Note that this method only modifies the
+  specified node labels (so that if the other nodes have already labels
+  they are not modified) while the two others change all labels.
+}
+
+\author{Emmanuel Paradis \email{Emmanuel.Paradis@mpl.ird.fr}}
+\seealso{
+  \code{\link{makeLabel}}, \code{\link[base]{grep}}
+}
+\examples{
+tr <-
+"((Pan_paniscus,Pan_troglodytes),((Homo_sapiens,Hom_erectus),Homo_abilis));"
+tr <- read.tree(text = tr)
+tr <- makeNodeLabel(tr, "u", nodeList = list(Pan = "Pan", Homo = "Homo"))
+plot(tr, show.node.label = TRUE)
+### does not erase the previous node labels:
+tr <- makeNodeLabel(tr, "u", nodeList = list(Hominid = c("Pan","Homo")))
+plot(tr, show.node.label = TRUE)
+### the two previous commands could be combined:
+L <- list(Pan = "Pan", Homo = "Homo", Hominid = c("Pan","Homo"))
+tr <- makeNodeLabel(tr, "u", nodeList = L)
+### combining different methods:
+tr <- makeNodeLabel(tr, c("n", "u"), prefix = "#", nodeList = list(Hominid = c("Pan","Homo")))
+plot(tr, show.node.label = TRUE)
+}
+\keyword{manip}