Build Status

NewickTree.jl

Read a newick tree to a tree data structure. The resulting data structure supports the AbstractTrees.jl interface.

Reading trees

using NewickTree
t = readnw("((A:1.2,B:1.4)86:0.2,C:0.6);")
print_tree(t)
((A:1.2,B:1.4)86.0:1.4,C:0.6);
├─ (A:1.2,B:1.4);
│  ├─ A:1.2
│  └─ B:1.4
└─ C:0.6

Use readnw(readline("your_file.nw")) to read a newick tree from a file. Use readnw.(readlines("your_file.nw")) to read a vector of trees from a file with a newick tree on each line.

Note that trees should adhere to the Newick standard, they should end with a semicolon and can only contain (1) leaf names, (2) support values or internal names and (3) branch lengths as node information. Failure to provide a valid Newick string will trigger an error:

try
    t = readnw("((A:1.2,B:1.4)86:0.2,C:0.6)")
catch ex
    @show ex
end
"Malformed Newick string '((A:1.2,B:1.4)86:0.2,C:0.6)' (no trailing semicolon?)"

The tree data structure is pretty straightforward, with nodes storing the following fields:

fieldnames(typeof(t))
(:id, :data, :parent, :children)

Some simple recursive tree traversals are implemented

postwalk(t)
prewalk(t)
5-element Array{Node{UInt16,NewickData{Float64,String}},1}:
 ((A:1.2,B:1.4)86.0:0.2,C:0.6);
 (A:1.2,B:1.4)86.0:0.2;
 A:1.2;
 B:1.4;
 C:0.6;

There are also the following self-explanatory functions:

getleaves(t)
getroot(t)
getlca(t, "A", "B")  # get last common ancestor
(A:1.2,B:1.4)86.0:0.2;

Functions from AbstractTrees can also be used, for instance

using AbstractTrees
collect(Leaves(t))
collect(PostOrderDFS(t))
5-element Array{Node{UInt16,NewickData{Float64,String}},1}:
 A:1.2;
 B:1.4;
 (A:1.2,B:1.4)86.0:0.2;
 C:0.6;
 ((A:1.2,B:1.4)86.0:0.2,C:0.6);

Writing trees

nwstr converts a tree data structure that implements the required functions (see below) to a Newick string:

nwstr(t)
"((A:1.2,B:1.4)86.0:0.2,C:0.6);"

writenw uses this to write to a stream or file.

io = IOBuffer()
writenw(io, t)
String(take!(io))
"((A:1.2,B:1.4)86.0:0.2,C:0.6);"

Support for writing other tree structured data to Newick strings

Any data structure that implements the AbstractTrees interface (i.e. defines AbstractTrees.children) can be written to a Newick structure provided several functions are defined. For example:

t = (((1,2),3),(4,5))
NewickTree.isleaf(::Int) = true
NewickTree.isleaf(::Tuple) = false
print_tree(t)
(((1, 2), 3), (4, 5))
├─ ((1, 2), 3)
│  ├─ (1, 2)
│  │  ├─ 1
│  │  └─ 2
│  └─ 3
└─ (4, 5)
   ├─ 4
   └─ 5

This enables us to use the nwstr and writenw functions

s = nwstr(t)
"(((1,2),3),(4,5));"

now we can read the Newick string

n = readnw(s)
print_tree(n)
(((1,2),3),(4,5));
├─ ((1,2),3);
│  ├─ (1,2);
│  │  ├─ 1
│  │  └─ 2
│  └─ 3
└─ (4,5);
   ├─ 4
   └─ 5
using Literate
Literate.markdown(
    joinpath(@__DIR__, "README.jl"),
    joinpath(@__DIR__, "../"),
    documenter=false, execute=true)

This page was generated using Literate.jl.