Package: phylotree
PhyloTreeThis crate aims to be a general purpose package to deal with phylogenetic trees and simulate them. Is also comes with a simple CLI tool to manipulate and simulate phylogenetic trees directly from the command line.Crate usageCLI usagePython packageInstallingphylotreeCrateTo use this crate just runcargo add phylotreein your cargo project or addphylotree = "0.1.0"to yourCargo.tomlfile.CliTo install the CLI you can usecargo install phylotreeOr you can build the project from source:gitclonehttps://github.com/lucblassel/phylotree.gitcdphylotree
cargobuild--release
mvtarget/release/phylotree<somewhere/in/your/PATH>Using this crateBelow is some sample usage of thephylotreecrate, please seedocs.rs/phylotreefor the full documentation.usephylotree::tree::Tree;//////////////////////////////////// Building a tree from scratch ////////////////////////////////////letmuttree=Tree::new();// Add the root nodeletroot=tree.add(Node::new());// Add a child to the rootletchild1=tree.add_child(Node::new_named("Child_1"),root,None).unwrap();// Add a child to the root with a branch lengthletchild2=tree.add_child(Node::new_named("Child_2"),root,Some(0.5)).unwrap();// Add more childrenletchild3=tree.add_child(Node::new_named("Child_3"),child1,None).unwrap();// Get depth of childassert_eq!(tree.get(&child3).unwrap().get_depth(),2)///////////////////////////////// Reading and writing trees /////////////////////////////////letnewick_str="((A:0.1,B:0.2)F:0.6,(C:0.3,D:0.4)E:0.5)G;";lettree=Tree::from_newick(newick_str).unwrap();assert_eq!(tree.to_newick().unwrap(),newick_string)//////////////////////// Traversing trees ////////////////////////letnewick_str="((A,B)C,(D,E)F)G;";letmuttree=Tree::from_newick(newick_str).unwrap();letroot=tree.get_root().unwrap();letpreorder:Vec<_>=tree.preorder(&root).unwrap().iter().map(|node_id|tree.get(node_id).unwrap().name.clone().unwrap()).collect();assert_eq!(preorder,vec!["G","C","A","B","F","D","E"]);/////////////////////// Comparing trees ///////////////////////// The second tree is just a random rotation of the first,// they represent the same phylogeneyletnewick_orig="((A:0.1,B:0.2)F:0.6,(C:0.3,D:0.4)E:0.5)G;";letnewick_rota="((D:0.3,C:0.4)E:0.5,(B:0.2,A:0.1)F:0.6)G;";lettree_orig=Tree::from_newick(newick_orig).unwrap();lettree_rota=Tree::from_newick(newick_rota).unwrap();letrf=tree_orig.robinson_foulds(&tree_rota).unwrap();assert_eq!(rf,0)/////////////////////////////////// Computing a distance matrix ///////////////////////////////////letnewick="((T3:0.2,T1:0.2):0.3,(T2:0.4,T0:0.5):0.6);";lettree=Tree::from_newick(newick).unwrap();// Compute the whole distance matrixletmatrix=tree.distance_matrix_recursive().unwrap();letphylip="\4T0    0  1.6  0.9  1.6T1    1.6  0  1.5  0.4T2    0.9  1.5  0  1.5T3    1.6  0.4  1.5  0";assert_eq!(matrix.to_phylip(true).unwrap(),phylip)Using the CLIThere is a simple CLI that comes with this package:A simple command line tool to manipulate phylogenetic trees

Usage: phylotree <COMMAND>

Commands:
  generate     Generate random tree(s)
  stats        Get statistics about a tree
  compare      Compare two phylogenetic trees
  matrix       Output the phylogenetic distance matrix of the tree
  distance     Outputs a subset of phylogenetic distances
  collapse     Collapse branches that are under a certain branch length threshold
  remove       Remove tips from the trees
  deduplicate  Remove or collapse branches corresponding to identical sequences in a reference alignment
  help         Print this message or the help of the given subcommand(s)

Options:
  -h, --help  Print helpPython packageA python package has also been implemented, using PyO3 to create the python bindings. It is available onPyPi, you can see the API of the packagehere.Example usage:fromphylotreeimportTree# Read a newick filetree=Tree.from_newick("path/to/tree.nwk")# Read a newick stringtree=Tree.from_string("((A,(C,E)D)B,((H)I)G)F;")# Print newick formatted string of the treetree.to_newick()# Get information about the treetree.n_nodes()tree.n_tips()tree.height()tree.diameter()tree.n_cherries()tree.colless()tree.sackin()tree.is_binarytree.is_rooted# Get information about nodesnames=tree.get_leaf_names()info=tree.get_node_attributes(name=names[0])print(f"Parent edge has length:{info['parent_edge']}")dist_branches,dist_topo=tree.get_distance(names=(names[0],names[1]))distance_matrix=tree.to_matrix()dist_mat=distance_matrix[(names[0],names[1])]assertdist_branches==dist_mat# Modify the treetree.compress()# Remove nodes with 1 parent and 1 childtree.rescale()# Change branch lengthstree.prune(name="D")# Remove sbutree rooted a specific node# Traverse the tree in a given orderfornode_idintree.traversal(order="levelorder"):node=tree.get_node_attributes(id=node_id)print(node.name)