Gotree

GoTree is a set of command line tools to manipulate phylogenetic trees. It is implemented in Go language.
The goal is to handle phylogenetic trees in Newick format, through several basic commands. Each command may print result (a tree for example) in the standard output, and thus can be piped to the standard input of the next gotree command.
See also Goalign for handling multiple alignments.
Example:
$ gotree generate uniformtree -l 100 -n 10 | gotree stats
This will generate 10 random unrooted uniform binary trees, each having 100 tips, and print statistics about them, for example:
| tree |
nodes |
tips |
edges |
meanbrlen |
sumbrlen |
meansupport |
mediansupport |
rooted |
| 0 |
198 |
100 |
197 |
0.08143890 |
16.04346409 |
NaN |
NaN |
unrooted |
| 1 |
198 |
100 |
197 |
0.08896295 |
17.52570158 |
NaN |
NaN |
unrooted |
| 2 |
198 |
100 |
197 |
0.07622673 |
15.01666610 |
NaN |
NaN |
unrooted |
| 3 |
198 |
100 |
197 |
0.07433737 |
14.64446097 |
NaN |
NaN |
unrooted |
| 4 |
198 |
100 |
197 |
0.09340993 |
18.40175678 |
NaN |
NaN |
unrooted |
| 5 |
198 |
100 |
197 |
0.08389979 |
16.52825835 |
NaN |
NaN |
unrooted |
| 6 |
198 |
100 |
197 |
0.08146519 |
16.04864327 |
NaN |
NaN |
unrooted |
| 7 |
198 |
100 |
197 |
0.07461762 |
14.69967048 |
NaN |
NaN |
unrooted |
| 8 |
198 |
100 |
197 |
0.08672365 |
17.08455809 |
NaN |
NaN |
unrooted |
| 9 |
198 |
100 |
197 |
0.09403232 |
18.52436632 |
NaN |
NaN |
unrooted |
Installation
Binaries
You can download already compiled binaries for the latest release in the release section.
Binaries are available for MacOS, Linux, and Windows (32 and 64 bits).
Once downloaded, you can just run the executable without any other downloads.
From sources
In order to compile gotree, you must first download and install Go on your system.
Then you just have to type :
go get github.com/fredericlemoine/gotree/
This will download GoTree sources from github, and all its dependencies.
You can then build it with:
cd $GOPATH/src/github.com/fredericlemoine/gotree/
make
The gotree executable should be located in the $GOPATH/bin folder.
Usage
gotree implements several tree manipulation commands.
You may go to the doc for a more detailed documentation of the commands.
List of commands
- annotate: Annotate internal nodes of a tree with given data
- clear: Clear lengths or supports from input trees
- collapse: Collapse branches of input trees
- compare: Compare full trees, edges, or tips
- edges: Individually compare edges of the reference tree to a compared tree
- tips: Compare the set of tips of the reference tree to a compared tree
- trees: Compare 2 trees in terms of common and specific branches
- compute: Computations such as consensus and supports
- bipartitiontree: Builds one tree with only one given bipartition
- consensus: Compute the consensus from a set of input trees
- edgetrees: Write one output tree per branch of the input tree, with only one branch
- support: Compute bootstrap supports
- divide: Divide an input tree file into several tree files
- dlimage: Download a tree image from a server
- itol: download a tree image from iTOL, with given image options
- draw: Draw tree(s) with different layouts
- text: Display tree(s) in ASCII text format
- png : Draw tree(s) in png format, with normal, radial/unrooted or circular layout
- svg : Draw tree(s) in svg format, with normal, radial/unrooted or circular layout
- generate: Generate random trees, branch lengths are simply drawn from an expontential(1) law
- balancedtree
- caterpillartree
- uniformtree
- yuletree
- matrix: Print distance matrix associated to the input tree
- minbrlen: Set a minimum branch length to all branches with length < cutoff
- prune: Remove tips of the input tree that are not in the compared tree, or that are given on the command line
- randbrlen: Assign a random length to edges of input trees
- randsupport: Assign a random support to edges of input trees
- rename: Rename tips of the input tree, given a map file
- reroot: Reroot trees using an outgroup or at midpoint
- resolve: Resolve multifurcations by adding 0 length branches
- shuffletips: Shuffle tip names of an input tree
- subtree: extract a subtree
- stats: Print statistics about the tree, its edges, its nodes, if it is rooted, and its tips
- edges
- nodes
- rooted
- tips
- splits
- unroot: Unroot input tree
- upload: Upload a tree to a given server
- itol : Upload a tree to itol, with given annotations
- version: Display version of gotree
Gotree commandline examples
- Generate 10 random unrooted uniform binary trees
$ gotree generate uniformtree -l 100 -n 10 | gotree stats
- Generate 1 Yule-Harding tree with 50 tips, and display it on the terminal (width 100)
$ gotree generate yuletree -l 50 | gotree draw text -w 100
- Generate 1 tree with 50 tips, and draw it on a SVG image
$ gotree generate yuletree -l 50 | gotree draw svg -w 1000 -H 1000 -o tree.svg
$ gotree generate yuletree -l 50 | gotree draw svg -w 1000 -H 1000 -r -o tree_radial.svg
$ gotree unroot -i tree.tre -o unrooted.tre
- Collapsing short branches
$ gotree collapse length -i tree.tre -l 0.001 -o collapsed.tre
- Collapsing lowly supported branches
$ gotree collapse support -i tree.tre -s 0.8 -o collapsed.tre
- Removing length information
$ gotree clear lengths -i tree.nw -o nolength.nw
- Removing support information
$ gotree clear supports -i tree.nw -o nosupport.nw
Note that you can pipe the two previous commands:
$ gotree clear supports -i tree.nw | gotree clear lengths -o nosupport.nw
$ gotree stats -i tree.tre
$ gotree stats edges -i tree.tre
Example of result:
| tree |
brid |
length |
support |
terminal |
depth |
topodepth |
rightname |
| 0 |
0 |
0.107614 |
N/A |
false |
1 |
6 |
|
| 0 |
1 |
0.149560 |
N/A |
true |
0 |
1 |
Tip51 |
| 0 |
2 |
0.051126 |
N/A |
false |
1 |
5 |
|
| 0 |
3 |
0.003992 |
N/A |
false |
1 |
4 |
|
| 0 |
4 |
0.030974 |
N/A |
false |
1 |
3 |
|
| 0 |
5 |
0.270017 |
N/A |
true |
0 |
1 |
Tip84 |
| 0 |
6 |
0.029931 |
N/A |
false |
1 |
2 |
|
| 0 |
7 |
0.001136 |
N/A |
true |
0 |
1 |
Tip70 |
| 0 |
8 |
0.011658 |
N/A |
true |
0 |
1 |
Tip45 |
| 0 |
9 |
0.104188 |
N/A |
true |
0 |
1 |
Tip34 |
| 0 |
10 |
0.003361 |
N/A |
true |
0 |
1 |
Tip16 |
| 0 |
11 |
0.021988 |
N/A |
true |
0 |
1 |
Node0 |
$ gotree stats tips -i tree.tre
Example of result:
| tree |
id |
nneigh |
name |
| 0 |
1 |
1 |
Tip8 |
| 0 |
2 |
1 |
Node0 |
| 0 |
5 |
1 |
Tip4 |
| 0 |
8 |
1 |
Tip9 |
| 0 |
9 |
1 |
Tip7 |
| 0 |
11 |
1 |
Tip6 |
| 0 |
13 |
1 |
Tip5 |
| 0 |
14 |
1 |
Tip3 |
| 0 |
16 |
1 |
Tip2 |
| 0 |
17 |
1 |
Tip1 |
- Comparing tips of two trees
$ gotree compare tips -i tree.tre -c tree2.tre
This will compare the two sets of tips.
Example:
$ gotree compare tips -i <(gotree generate uniformtree -l 10 -n 1) \
-c <(gotree generate uniformtree -l 11 -n 1)
> Tip10
= 10
10 tips are equal, and "Tip10" is present only in the second tree.
- Removing tips that are absent from another tree
$ gotree prune -i tree.tre -c other.tre -o pruned.tre
You can test with
$ gotree prune -i <(gotree generate uniformtree -l 1000 -n 1) \
-c <(gotree generate uniformtree -l 100 -n 1) \
| gotree stats
It should print 100 tips.
- Comparing bipartitions
Count the number of common/specific bipartitions between two trees.
$ gotree compare trees -i tree.tre -c other.tre
You can test with random trees (there should be very few common bipartitions)
$ gotree compare trees -i <(gotree generate uniformtree -l 100 -n 1) \
-c <(gotree generate uniformtree -l 100 -n 1)
| Tree |
reference |
common |
compared |
| 0 |
97 |
0 |
97 |
- Renaming tips of the tree
If you have a file containing the mapping between current names and new names of the tips, you can rename the tips:
$ gotree rename -i tree.tre -m mapfile.txt -o newtree.tre
You can try by doing:
$ gotree generate uniformtree -l 100 -n 1 -o tree.tre
$ gotree stats tips -i tree.tre | awk '{if(NR>1){print $4 "\tNEWNAME" $4}}' > mapfile.txt
$ gotree rename -i tree.tre -m mapfile.txt | gotree stats tips
Gotree api usage examples
package main
import (
"fmt"
"strings"
"github.com/fredericlemoine/gotree/io/newick"
"github.com/fredericlemoine/gotree/tree"
)
func main() {
var treeString string
var t *tree.Tree
var err error
treeString = "(Tip2,Tip0,(Tip3,(Tip4,Tip1)));"
t, err = newick.NewParser(strings.NewReader(treeString)).Parse()
if err != nil {
panic(err)
}
fmt.Println(t.Newick())
}
package main
import (
"fmt"
"os"
"github.com/fredericlemoine/gotree/io/newick"
"github.com/fredericlemoine/gotree/tree"
)
func main() {
var t *tree.Tree
var err error
var f *os.File
if f, err = os.Open("t.nw"); err != nil {
panic(err)
}
t, err = newick.NewParser(f).Parse()
if err != nil {
panic(err)
}
fmt.Println(t.Newick())
}
- Helper functions to parse multi tree newick file
package main
import (
"bufio"
"fmt"
"os"
"github.com/fredericlemoine/gotree/io/utils"
"github.com/fredericlemoine/gotree/tree"
)
func main() {
var t tree.Trees
var err error
var ntrees int = 0
var trees <-chan tree.Trees
var treefile *os.File
var treereader *bufio.Reader
/* File reader (plain text or gzip) */
if treefile, treereader, err = utils.GetReader("trees.nw"); err != nil {
panic(err)
}
defer treefile.Close()
trees = utils.ReadMultiTrees(treereader)
for t = range trees {
if t.Err != nil {
panic(t.Err)
}
ntrees++
fmt.Println(t.Tree.Newick())
}
fmt.Printf("Number of trees: %d\n", ntrees)
}
// Getting edges
var edges []*tree.Edge = t.Edges()
// Internal edges only
var iedges []*tree.Edge = t.InternalEdges()
// Tip edges only
var tedges []*tree.Edge = t.TipEdges()
// Getting Nodes
var nodes []*tree.Node = t.Nodes()
// Tips only
var tips []*tree.Node = t.Tips()
// Getting tips
var tips []*tree.Node = t.Tips()
// Getting tip names
var tipnames []string = t.AllTipNames()
// Root/Pseudoroot node
var root *tree.Node = t.Root()
// If the tree is rooted or not
var rooted bool = t.Rooted()
// Branch length
var l float64 = e.Length()
// Branch support
var s float64 = e.Support()
// Node on the "right"
var n1 *tree.Node = e.Right()
// Node on the "left"
var n2 *tree.Node = e.Left()
// Number of leaves under this edge
var nt uint = e.NumTips()
// Node name
var n string = n.Name()
// Number of neighbors
var nn int = n.Nneigh()
// List of neighbors (including "parent")
var neighb []*tree.Node = n.Neigh()
// If a node is a tip or not
var tip bool = n.Tip()
// List of branches going from this node (including "parent")
var edges []*tree.Edge = n.Edges()
if err = t.RemoveTips(false, "Tip0"); err != nil {
panic(err)
}
fmt.Println(t.Newick())
- Knowning if a tip exists in the tree
var exists bool
var err error
exists,err = t.ExistsTip("Tip0")
- Shuffling tip names of the tree
t.ShuffleTips()
// Short branches
t.CollapseShortBranches(0.01)
// Lowly supported branches
t.CollapseLowSupport(0.7)
// Branches with "depth" <=10 && >= 1
t.CollapseTopoDepth(1,10)
- Randomly resolving multifurcations
t.Resolve()
- Removing branch informations
// Branch lengths
t.ClearLengths()
// Branch supports
t.ClearSupports()
t.Unroot()
t.Clone()
t.RerootMidPoint()
var ntips int = 100
var rooted bool = true
// Uniform tree
t,err = tree.RandomUniformBinaryTree(ntips, rooted)
// Balanced tree
t,err = tree.RandomBalancedBinaryTree(ntips, rooted)
// Yule-Harding tree
t,err = tree.RandomYuleBinaryTree(ntips, rooted)
- Computing bootstrap supports from tree files
import "github.com/fredericlemoine/gotree/support"
...
var cpus int = 1
boottree,err := support.ClassicalFile("referencetreefile", "bootstraptreesfile", cpus)
import "github.com/fredericlemoine/gotree/draw"
...
f, err := os.Create("image.svg")
d = draw.NewSvgTreeDrawer(f, 800, 800, 30, 30, 30, 30)
l = draw.NewRadialLayout(d, false, false, false, false)
// or l = draw.NewCircularLayout(d, false, false, false, false)
// or l = draw.NewNormalLayout(d, false, false, false, false)
l.DrawTree(t)
f.Close()
import "github.com/fredericlemoine/gotree/draw"
...
f, err := os.Create("image.svg")
d = draw.NewPngTreeDrawer(f, 800, 800, 30, 30, 30, 30)
l = draw.NewRadialLayout(d, false, false, false, false)
// or l = draw.NewCircularLayout(d, false, false, false, false)
// or l = draw.NewNormalLayout(d, false, false, false, false)
l.DrawTree(t)
f.Close()