Name | phylotree JSON |
Version |
0.1.1
JSON |
| download |
home_page | |
Summary | A Rust backed package to deal with phylogenetic trees |
upload_time | 2023-06-21 17:45:34 |
maintainer | |
docs_url | None |
author | Luc Blassel |
requires_python | >=3.7 |
license | GPL3 |
keywords |
phylogenetic
tree
distance
matrix
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# PhyloTree
[![license_badge](https://img.shields.io/crates/l/phylotree)](https://choosealicense.com/licenses/gpl-3.0/) [![crate version](https://img.shields.io/crates/v/phylotree)](https://crates.io/crates/phylotree) [![rust doc](https://img.shields.io/docsrs/phylotree)](https://docs.rs/phylotree)
This 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 usage](#using-this-crate)
- [CLI usage](#using-the-cli)
- [Python package](#python-package)
## Installing `phylotree`
### Crate
To use this crate just run `cargo add phylotree` in your cargo project or add `phylotree = "0.1.0"` to your `Cargo.toml` file.
### Cli
To install the CLI you can use
`cargo install phylotree`
Or you can build the project from source:
```shell
git clone https://github.com/lucblassel/phylotree.git
cd phylotree
cargo build --release
mv target/release/phylotree <somewhere/in/your/PATH>
```
## Using this crate
Below is some sample usage of the `phylotree` crate, please see [docs.rs/phylotree](https://docs.rs/phylotree) for the full documentation.
```rust
use phylotree::tree::Tree;
//////////////////////////////////
// Building a tree from scratch //
//////////////////////////////////
let mut tree = Tree::new();
// Add the root node
let root = tree.add(Node::new());
// Add a child to the root
let child1 = tree.add_child(Node::new_named("Child_1"), root, None).unwrap();
// Add a child to the root with a branch length
let child2 = tree.add_child(Node::new_named("Child_2"), root, Some(0.5)).unwrap();
// Add more children
let child3 = tree.add_child(Node::new_named("Child_3"), child1, None).unwrap();
// Get depth of child
assert_eq!(tree.get(&child3).unwrap().get_depth(), 2)
///////////////////////////////
// Reading and writing trees //
///////////////////////////////
let newick_str = "((A:0.1,B:0.2)F:0.6,(C:0.3,D:0.4)E:0.5)G;";
let tree = Tree::from_newick(newick_str).unwrap();
assert_eq!(tree.to_newick().unwrap(), newick_string)
//////////////////////
// Traversing trees //
//////////////////////
let newick_str = "((A,B)C,(D,E)F)G;";
let mut tree = Tree::from_newick(newick_str).unwrap();
let root = tree.get_root().unwrap();
let preorder: 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 phylogeney
let newick_orig = "((A:0.1,B:0.2)F:0.6,(C:0.3,D:0.4)E:0.5)G;";
let newick_rota = "((D:0.3,C:0.4)E:0.5,(B:0.2,A:0.1)F:0.6)G;";
let tree_orig = Tree::from_newick(newick_orig).unwrap();
let tree_rota = Tree::from_newick(newick_rota).unwrap();
let rf = tree_orig.robinson_foulds(&tree_rota).unwrap();
assert_eq!(rf, 0)
/////////////////////////////////
// Computing a distance matrix //
/////////////////////////////////
let newick = "((T3:0.2,T1:0.2):0.3,(T2:0.4,T0:0.5):0.6);";
let tree = Tree::from_newick(newick).unwrap();
// Compute the whole distance matrix
let matrix = tree.distance_matrix_recursive().unwrap();
let phylip="\
4
T0 0 1.6 0.9 1.6
T1 1.6 0 1.5 0.4
T2 0.9 1.5 0 1.5
T3 1.6 0.4 1.5 0
";
assert_eq!(matrix.to_phylip(true).unwrap(), phylip)
```
## Using the CLI
There 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 help
```
## Python package
A python package has also been implemented, using PyO3 to create the python bindings. It is available on [PyPi](https://pypi.org/project/phylotree/0.1.1/), you can see the API of the package [here](./phylotree/__init__.py).
Example usage:
```python
from phylotree import Tree
# Read a newick file
tree = Tree.from_newick("path/to/tree.nwk")
# Read a newick string
tree = Tree.from_string("((A,(C,E)D)B,((H)I)G)F;")
# Print newick formatted string of the tree
tree.to_newick()
# Get information about the tree
tree.n_nodes()
tree.n_tips()
tree.height()
tree.diameter()
tree.n_cherries()
tree.colless()
tree.sackin()
tree.is_binary
tree.is_rooted
# Get information about nodes
names = 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])]
assert dist_branches == dist_mat
# Modify the tree
tree.compress() # Remove nodes with 1 parent and 1 child
tree.rescale() # Change branch lengths
tree.prune(name="D") # Remove sbutree rooted a specific node
# Traverse the tree in a given order
for node_id in tree.traversal(order="levelorder"):
node = tree.get_node_attributes(id=node_id)
print(node.name)
```
Raw data
{
"_id": null,
"home_page": "",
"name": "phylotree",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "phylogenetic tree distance matrix",
"author": "Luc Blassel",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/f4/9a/807394a52e8c072d021eee3772ee1ec0025927d767ec3372f2edacc4bdfe/phylotree-0.1.1.tar.gz",
"platform": null,
"description": "# PhyloTree\n\n[![license_badge](https://img.shields.io/crates/l/phylotree)](https://choosealicense.com/licenses/gpl-3.0/) [![crate version](https://img.shields.io/crates/v/phylotree)](https://crates.io/crates/phylotree) [![rust doc](https://img.shields.io/docsrs/phylotree)](https://docs.rs/phylotree)\n\nThis 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.\n\n- [Crate usage](#using-this-crate)\n- [CLI usage](#using-the-cli)\n- [Python package](#python-package)\n\n## Installing `phylotree`\n\n### Crate\n\nTo use this crate just run `cargo add phylotree` in your cargo project or add `phylotree = \"0.1.0\"` to your `Cargo.toml` file.\n\n### Cli\n\nTo install the CLI you can use\n`cargo install phylotree`\n\nOr you can build the project from source:\n\n```shell\ngit clone https://github.com/lucblassel/phylotree.git\ncd phylotree\ncargo build --release\nmv target/release/phylotree <somewhere/in/your/PATH>\n```\n\n## Using this crate\n\nBelow is some sample usage of the `phylotree` crate, please see [docs.rs/phylotree](https://docs.rs/phylotree) for the full documentation.\n\n```rust\nuse phylotree::tree::Tree;\n\n//////////////////////////////////\n// Building a tree from scratch //\n//////////////////////////////////\nlet mut tree = Tree::new();\n\n// Add the root node\nlet root = tree.add(Node::new());\n\n// Add a child to the root\nlet child1 = tree.add_child(Node::new_named(\"Child_1\"), root, None).unwrap();\n// Add a child to the root with a branch length\nlet child2 = tree.add_child(Node::new_named(\"Child_2\"), root, Some(0.5)).unwrap();\n\n// Add more children\nlet child3 = tree.add_child(Node::new_named(\"Child_3\"), child1, None).unwrap();\n\n// Get depth of child\nassert_eq!(tree.get(&child3).unwrap().get_depth(), 2)\n\n///////////////////////////////\n// Reading and writing trees //\n///////////////////////////////\nlet newick_str = \"((A:0.1,B:0.2)F:0.6,(C:0.3,D:0.4)E:0.5)G;\";\nlet tree = Tree::from_newick(newick_str).unwrap();\n\nassert_eq!(tree.to_newick().unwrap(), newick_string)\n\n//////////////////////\n// Traversing trees //\n//////////////////////\nlet newick_str = \"((A,B)C,(D,E)F)G;\";\nlet mut tree = Tree::from_newick(newick_str).unwrap();\nlet root = tree.get_root().unwrap();\n\nlet preorder: Vec<_> = tree.preorder(&root).unwrap()\n .iter()\n .map(|node_id| tree.get(node_id).unwrap().name.clone().unwrap())\n .collect();\n\nassert_eq!(preorder, vec![\"G\", \"C\", \"A\", \"B\", \"F\", \"D\", \"E\"]);\n\n\n/////////////////////\n// Comparing trees //\n/////////////////////\n\n// The second tree is just a random rotation of the first,\n// they represent the same phylogeney\nlet newick_orig = \"((A:0.1,B:0.2)F:0.6,(C:0.3,D:0.4)E:0.5)G;\";\nlet newick_rota = \"((D:0.3,C:0.4)E:0.5,(B:0.2,A:0.1)F:0.6)G;\";\n\nlet tree_orig = Tree::from_newick(newick_orig).unwrap();\nlet tree_rota = Tree::from_newick(newick_rota).unwrap();\n\nlet rf = tree_orig.robinson_foulds(&tree_rota).unwrap();\n\nassert_eq!(rf, 0)\n\n\n/////////////////////////////////\n// Computing a distance matrix //\n/////////////////////////////////\nlet newick = \"((T3:0.2,T1:0.2):0.3,(T2:0.4,T0:0.5):0.6);\";\nlet tree = Tree::from_newick(newick).unwrap();\n// Compute the whole distance matrix\nlet matrix = tree.distance_matrix_recursive().unwrap();\nlet phylip=\"\\\n4\nT0 0 1.6 0.9 1.6\nT1 1.6 0 1.5 0.4\nT2 0.9 1.5 0 1.5\nT3 1.6 0.4 1.5 0\n\";\n\nassert_eq!(matrix.to_phylip(true).unwrap(), phylip)\n```\n\n## Using the CLI\n\nThere is a simple CLI that comes with this package:\n\n```\nA simple command line tool to manipulate phylogenetic trees\n\nUsage: phylotree <COMMAND>\n\nCommands:\n generate Generate random tree(s)\n stats Get statistics about a tree\n compare Compare two phylogenetic trees\n matrix Output the phylogenetic distance matrix of the tree\n distance Outputs a subset of phylogenetic distances\n collapse Collapse branches that are under a certain branch length threshold\n remove Remove tips from the trees\n deduplicate Remove or collapse branches corresponding to identical sequences in a reference alignment\n help Print this message or the help of the given subcommand(s)\n\nOptions:\n -h, --help Print help\n```\n\n## Python package\n\nA python package has also been implemented, using PyO3 to create the python bindings. It is available on [PyPi](https://pypi.org/project/phylotree/0.1.1/), you can see the API of the package [here](./phylotree/__init__.py).\n\nExample usage:\n\n```python\nfrom phylotree import Tree\n\n# Read a newick file\ntree = Tree.from_newick(\"path/to/tree.nwk\")\n\n# Read a newick string\ntree = Tree.from_string(\"((A,(C,E)D)B,((H)I)G)F;\")\n\n# Print newick formatted string of the tree\ntree.to_newick()\n\n# Get information about the tree\ntree.n_nodes()\ntree.n_tips()\ntree.height()\ntree.diameter()\ntree.n_cherries()\ntree.colless()\ntree.sackin()\ntree.is_binary\ntree.is_rooted\n\n# Get information about nodes\nnames = tree.get_leaf_names()\ninfo = tree.get_node_attributes(name=names[0])\nprint(f\"Parent edge has length: {info['parent_edge']}\")\ndist_branches, dist_topo = tree.get_distance(names=(names[0], names[1]))\n\ndistance_matrix = tree.to_matrix()\ndist_mat = distance_matrix[(names[0], names[1])]\nassert dist_branches == dist_mat\n\n# Modify the tree\ntree.compress() # Remove nodes with 1 parent and 1 child\ntree.rescale() # Change branch lengths\ntree.prune(name=\"D\") # Remove sbutree rooted a specific node\n\n# Traverse the tree in a given order\nfor node_id in tree.traversal(order=\"levelorder\"):\n node = tree.get_node_attributes(id=node_id)\n print(node.name)\n```\n",
"bugtrack_url": null,
"license": "GPL3",
"summary": "A Rust backed package to deal with phylogenetic trees",
"version": "0.1.1",
"project_urls": {
"Bug Tracker": "https://github.com/lucblassel/phylotree-rs/issues",
"Documentation": "https://github.com/lucblassel/phylotree-rs",
"Source Code": "https://github.com/lucblassel/phylotree-rs"
},
"split_keywords": [
"phylogenetic",
"tree",
"distance",
"matrix"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f49a807394a52e8c072d021eee3772ee1ec0025927d767ec3372f2edacc4bdfe",
"md5": "06222057400f3c0cd8135f05c43e486b",
"sha256": "50a3d61800857573b643027ca69145598a7f867c7f42688a825411c2adb6237f"
},
"downloads": -1,
"filename": "phylotree-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "06222057400f3c0cd8135f05c43e486b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 49605,
"upload_time": "2023-06-21T17:45:34",
"upload_time_iso_8601": "2023-06-21T17:45:34.989245Z",
"url": "https://files.pythonhosted.org/packages/f4/9a/807394a52e8c072d021eee3772ee1ec0025927d767ec3372f2edacc4bdfe/phylotree-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-06-21 17:45:34",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "lucblassel",
"github_project": "phylotree-rs",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "phylotree"
}