]> git.donarmstrong.com Git - ape.git/blob - R/read.dna.R
some modifs for ape 3.0-8
[ape.git] / R / read.dna.R
1 ## read.dna.R (2013-01-31)
2
3 ##   Read DNA Sequences in a File
4
5 ## Copyright 2003-2013 Emmanuel Paradis
6
7 ## This file is part of the R-package `ape'.
8 ## See the file ../COPYING for licensing issues.
9
10 read.FASTA <- function(file)
11 {
12     sz <- file.info(file)$size
13     x <- readBin(file, "raw", sz)
14     icr <- which(x == as.raw(0x0d)) # CR
15     x <- x[-icr]
16     res <- .Call("rawStreamToDNAbin", x, PACKAGE = "ape")
17     names(res) <- sub("^ +", "", names(res)) # to permit phylosim
18     class(res) <- "DNAbin"
19     res
20 }
21
22 read.dna <- function(file, format = "interleaved", skip = 0,
23                      nlines = 0, comment.char = "#",
24                      as.character = FALSE, as.matrix = NULL)
25 {
26     findFirstNucleotide <- function(x) {
27         ## actually find the 1st non-blank character
28         ## just in case: pat.base <- "[-AaCcGgTtUuMmRrWwSsYyKkVvHhDdBbNn?]{10}"
29         tmp <- regexpr("[[:blank:]]+", x[1]) # consider only a single string
30         tmp[1] + attr(tmp, "match.length")
31     }
32     getTaxaNames <- function(x) {
33         x <- sub("^['\" ]+", "", x) # remove the leading quotes and spaces
34         x <- sub("['\" ]+$", "", x) #   "     "  trailing  "     "    "
35         x
36     }
37     getNucleotide <- function(x) {
38         x <- gsub(" ", "", x)
39         x <- strsplit(x, NULL)
40         tolower(unlist(x))
41     }
42     formats <- c("interleaved", "sequential", "fasta", "clustal")
43     format <- match.arg(format, formats)
44     if (format == "fasta") {
45         obj <- read.FASTA(file)
46     } else {
47         X <- scan(file = file, what = "", sep = "\n", quiet = TRUE,
48                   skip = skip, nlines = nlines, comment.char = comment.char)
49         if (format %in% formats[1:2]) {
50             ## need to remove the possible leading spaces and/or tabs in the first line
51             fl <- gsub("^[[:blank:]]+", "", X[1])
52             fl <- as.numeric(unlist(strsplit(fl, "[[:blank:]]+")))
53             if (length(fl) != 2 || any(is.na(fl)))
54                 stop("the first line of the file must contain the dimensions of the data")
55             n <- fl[1]
56             s <- fl[2]
57             obj <- matrix("", n, s)
58             X <- X[-1]
59         }
60         switch(format,
61                "interleaved" = {
62                    start.seq <- findFirstNucleotide(X[1])
63                    one2n <- 1:n
64                    taxa <- getTaxaNames(substr(X[one2n], 1, start.seq - 1))
65                    X[one2n] <- substr(X[one2n], start.seq, nchar(X[one2n]))
66                    nl <- length(X)
67                    for (i in one2n)
68                        obj[i, ] <- getNucleotide(X[seq(i, nl, n)])
69                },
70                "sequential" = {
71                    taxa <- character(n)
72                    j <- 1L # line number
73                    for (i in 1:n) {
74                        start.seq <- findFirstNucleotide(X[j])
75                        taxa[i] <- getTaxaNames(substr(X[j], 1, start.seq - 1))
76                        sequ <- getNucleotide(substr(X[j], start.seq, nchar(X[j])))
77                        j <- j + 1L
78                        while (length(sequ) < s) {
79                            sequ <- c(sequ, getNucleotide(X[j]))
80                            j <- j + 1L
81                        }
82                        obj[i, ] <- sequ
83                    }
84                    taxa <- getTaxaNames(taxa)
85                },
86                "clustal" = {
87                    X <- X[-1] # drop the line with "Clustal bla bla..."
88                    ## find where the 1st sequence starts
89                    start.seq <- findFirstNucleotide(X[1])
90                    ## find the lines with *********....
91                    nspaces <- paste("^ {", start.seq - 1, "}", sep = "", collapse = "")
92                    stars <- grep(nspaces, X)
93                    ## we now know how many sequences in the file:
94                    n <- stars[1] - 1
95                    taxa <- getTaxaNames(substr(X[1:n], 1, start.seq - 1))
96                    ## need to remove the sequence names before getting the sequences:
97                    X <- substr(X, start.seq, nchar(X))
98                    nl <- length(X)
99                    ## find the length of the 1st sequence:
100                    tmp <- getNucleotide(X[seq(1, nl, n + 1)])
101                    s <- length(tmp)
102                    obj <- matrix("", n, s)
103                    obj[1, ] <- tmp
104                    for (i in 2:n)
105                        obj[i, ] <- getNucleotide(X[seq(i, nl, n + 1)])
106                })
107     }
108     if (format != "fasta") {
109         rownames(obj) <- taxa
110         if (!as.character) obj <- as.DNAbin(obj)
111     } else {
112         LENGTHS <- unique(unlist(lapply(obj, length)))
113         allSameLength <- length(LENGTHS) == 1
114         if (is.logical(as.matrix)) {
115             if (as.matrix && !allSameLength)
116                 stop("sequences in FASTA file not of the same length")
117         } else {
118             as.matrix <- allSameLength
119         }
120         if (as.matrix) {
121             taxa <- names(obj)
122             n <- length(obj)
123             y <- matrix(as.raw(0), n, LENGTHS)
124             for (i in seq_len(n)) y[i, ] <- obj[[i]]
125             obj <- y
126             rownames(obj) <- taxa
127             class(obj) <- "DNAbin"
128         }
129         if (as.character) obj <- as.character(obj)
130     }
131     obj
132 }