Phylo
Phylo is a fast, extensible, general-purpose, and WebAssembly-capable library for phylogenetic analysis and inference written in Rust. Phylo-rs leverages a combination of memory safety, speed, and native WebAssembly support offered by Rust to provide a robust set of memory-efficient data structures with basic algorithms ranging from tree manipulation with SPR to computing tree statistics such as phylogenetic diversity.
A note on implementation
Implementation of tree-like structures in Rust can be complex and time-intensive. Additionally implementing tree traversals and operations on tree structures (recursive or otherwise) can be a substantial task. This crate aims to implement most such methods as easily derivable traits, so you don't have to implement them from scratch where they are not needed.
We also provide a struct, so you don't have to implement one...
Using phylo
Most of the functionality is implemented in [crate::tree::simple_rtree]. The
[crate::tree::ops] module deals with phylogenetic analysis that requires tree mutations such as SPR, NNI, etc.
[crate::tree::simulation] module is used to simulate random trees
[crate::tree::io] module is used to read trees from various encodings
[crate::tree::distances] module is used to compute various types of distance between nodes in a tree and between trees
[crate::iter] is a helper module to provide tree traversals and iterations.
Building trees
The simplest way to build a tree is to create an empty tree, add a root node, and then add children to the various added nodes:
use *;
let mut tree = new;
let new_node = new;
tree.add_child;
let new_node = new;
tree.add_child;
let new_node: PhyloNode = new;
tree.add_child;
let new_node: PhyloNode = new;
tree.add_child;
Reading and writing trees
This library can build trees strings (or files) encoded in the newick format:
use *;
let input_str = Stringfrom;
let tree = from_newick.unwrap;
Traversing trees
Several traversals are implemented to visit nodes in a particular order: pre- and post-order. A traversal returns an [Iterator] of nodes or NodeIDs in the order in which they are to be visited.
use *;
let input_str = Stringfrom;
let tree = from_newick.unwrap;
let dfs_traversal = tree.dfs.into_iter;
let bfs_traversal = tree.bfs_ids;
let postfix_traversal = tree.postord_ids;
Comparing trees
Several metrics taking into account topology and branch lengths are implemented to compare trees with each other:
use *;
let newick_1 = "((A:0.1,B:0.2):0.6,(C:0.3,D:0.4):0.5);";
let newick_2 = "((D:0.3,C:0.4):0.5,(B:0.2,A:0.1):0.6);";
let mut tree_1 = from_newick.unwrap;
let mut tree_2 = from_newick.unwrap;
tree_1.precompute_constant_time_lca;
tree_2.precompute_constant_time_lca;
tree_1.set_zeta;
tree_2.set_zeta;
let ca = tree_1.ca;
let cophen = tree_1.cophen_dist;
Examples
The following snippets are code examples of some phylogenetic analyses. You can find these in the examples directory of the repository. To visualize the outputs of the examples, please first install the requirements using the following command:
Quantifying Phylogenetic Diversity
Quantifying the Phylogenetic Diversity of a set of trees using the Faith Index:
use FxHashMap as HashMap;
use HashMap;
use Itertools;
use ;
use *;
use Write;
The variations in Phylogenetic Diversity can be visualized using the python script examples/visualization/pd.py.
Visualizing Phylogenetic Tree Space
Here, we compare all pairwise RF distances of a set of trees:
use FxHashMap as HashMap;
use HashMap;
use Itertools;
use ;
use *;
use Write;
use ;
The tree space can be visualized using the python script examples/visualization/tree-space.py.
To run the code examples, run the following: