]> git.donarmstrong.com Git - ape.git/blobdiff - R/read.nexus.R
few corrections and fixes
[ape.git] / R / read.nexus.R
index 0b0cacc1281ebd6f43350ba8db5457f9fe4434e0..969d42c0e403c23c28bb459ecdc41dc1d2a3305c 100644 (file)
@@ -1,20 +1,28 @@
-## read.nexus.R (2008-02-28)
+## read.nexus.R (2009-11-21)
 
 ##   Read Tree File in Nexus Format
 
-## Copyright 2003-2008 Emmanuel Paradis
+## Copyright 2003-2009 Emmanuel Paradis
 
 ## This file is part of the R-package `ape'.
 ## See the file ../COPYING for licensing issues.
 
 .treeBuildWithTokens <- function(x)
 {
+    ## remove potential node labels; see ?read.nexus for justification
+    node.label <- gsub("[:;].*$", "", strsplit(x, ")")[[1]][-1])
+    has.node.labels <- FALSE
+    if (any(node.label != "")) {
+        x <- gsub(")[^:]*:", "):", x)
+        x <- gsub(")[^:]*;", ");", x) # if there's no root edge
+        has.node.labels <- TRUE
+    }
     phy <- .Call("treeBuildWithTokens", x, PACKAGE = "ape")
     dim(phy[[1]]) <- c(length(phy[[1]])/2, 2)
-    nms <- c("edge", "edge.length", "Nnode", "node.label")
-    if (length(phy) == 5) nms <- c(nms, "root.edge")
+    nms <- c("edge", "edge.length", "Nnode", "root.edge")
+    if (length(phy) == 3) nms <- nms[-4]
     names(phy) <- nms
-    if (!sum(phy[[4]])) phy[[4]] <- NULL
+    if (has.node.labels) phy$node.label <- node.label
     class(phy) <- "phylo"
     phy
 }
@@ -109,7 +117,17 @@ read.nexus <- function(file, tree.names = NULL)
         w <- LEFT == RIGHT
         if (any(w)) { # in case all comments use at least 2 lines
             s <- LEFT[w]
-            X[s] <- gsub("\\[.*\\]", "", X[s])
+            X[s] <- gsub("\\[[^]]*\\]", "", X[s])
+            ## The above regexp was quite tough to find: it makes
+            ## possible to delete series of comments on the same line:
+            ##       ...[...]xxx[...]...
+            ## without deleting the "xxx". This regexp is in three parts:
+            ##       \\[      [^]]*       \\]
+            ## where [^]]* means "any character, except "]", repeated zero
+            ## or more times" (note that the ']' is not escaped here).
+            ## The previous version was:
+            ##       X[s] <- gsub("\\[.*\\]", "", X[s])
+            ## which deleted the "xxx". (EP  2008-06-24)
         }
         w <- !w
         if (any(w)) {
@@ -143,16 +161,25 @@ read.nexus <- function(file, tree.names = NULL)
     tree <- X[start:end]
     rm(X)
     tree <- gsub("^.*= *", "", tree)
+    ## check whether there are empty lines from the above manips:
+    tree <- tree[tree != ""]
     semico <- grep(";", tree)
     Ntree <- length(semico)
     ## are some trees on several lines?
-    if (any(diff(semico) != 1)) {
-        STRING <- character(Ntree)
-        s <- c(1, semico[-Ntree] + 1)
-        j <- mapply(":", s, semico)
-        for (i in 1:Ntree)
-            STRING[i] <- paste(tree[j[, i]], collapse = "")
-    } else STRING <- tree
+    if (Ntree == 1 && length(tree) > 1) STRING <- paste(tree, collapse = "") else {
+        if (any(diff(semico) != 1)) {
+            STRING <- character(Ntree)
+            s <- c(1, semico[-Ntree] + 1)
+            j <- mapply(":", s, semico)
+            if (is.list(j)) {
+                for (i in 1:Ntree)
+                    STRING[i] <- paste(tree[j[[i]]], collapse = "")
+            } else {
+                for (i in 1:Ntree)
+                    STRING[i] <- paste(tree[j[, i]], collapse = "")
+            }
+        } else STRING <- tree
+    }
     rm(tree)
     STRING <- gsub(" ", "", STRING)
     colon <- grep(":", STRING)
@@ -196,13 +223,30 @@ read.nexus <- function(file, tree.names = NULL)
             stop(paste("There is apparently two root edges in your file: cannot read tree file.\n  Reading NEXUS file aborted at tree no.", i, sep = ""))
         }
     }
-    if (Ntree == 1) trees <- trees[[1]] else {
+    if (Ntree == 1) {
+        trees <- trees[[1]]
+        if (translation) {
+            trees$tip.label <-
+                if (length(colon)) TRANS[, 2] else
+                TRANS[, 2][as.numeric(trees$tip.label)]
+        }
+    } else {
         if (!is.null(tree.names)) names(trees) <- tree.names
-        if (translation) attr(trees, "TipLabel") <- TRANS[, 2]
+        if (translation) {
+            if (length(colon) == Ntree) # .treeBuildWithTokens() was used
+                attr(trees, "TipLabel") <- TRANS[, 2]
+            else { # reassign the tip labels then compress
+                for (i in 1:Ntree)
+                    trees[[i]]$tip.label <-
+                        TRANS[, 2][as.numeric(trees[[i]]$tip.label)]
+                trees <- .compressTipLabel(trees)
+            }
+        }
         class(trees) <- "multiPhylo"
     }
     if (length(grep("[\\/]", file)) == 1)
-        file <- paste(getwd(), file, sep = "/")
+        if (!file.exists(file)) # suggestion by Francois Michonneau
+            file <- paste(getwd(), file, sep = "/")
     attr(trees, "origin") <- file
     trees
 }