Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2 create rooted phylo tree struct and impl generic rooted tree traits #6

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
65ab5ae
swtiched the outputs of get methods to refs
sriram98v Oct 14, 2023
e153a1b
renamed rooted tree struct, implemented get_root, get_nodes, get_chil…
sriram98v Oct 14, 2023
17fb6f3
added comments to traits, renamed distance matrix method
sriram98v Oct 15, 2023
0dcfb6a
implemented node iterators, removed data field in tree struct, implem…
sriram98v Oct 15, 2023
315f61c
added get_cluster trait, implemented get_cluster and get_bipartition
sriram98v Oct 15, 2023
60ebcf8
fixed bipartition implementation
sriram98v Oct 15, 2023
d16aa15
added method to get tree from newick string
sriram98v Oct 16, 2023
66ca88a
added unrooted tree struct
sriram98v Oct 16, 2023
9ab0ee3
moved leaves from HashSet to HashMap
sriram98v Oct 16, 2023
b473d2b
added preorder ancestor iterator
sriram98v Oct 17, 2023
fbce887
simple mrca implemented
sriram98v Oct 17, 2023
20dc054
switched to Vec instead of Hashset for children, added method to inse…
sriram98v Oct 17, 2023
6ddc242
added reroot at edge
sriram98v Oct 17, 2023
3610dba
removed empty line
sriram98v Oct 17, 2023
788b636
Updated the tree structure to have HashSet(Node) and distance matrix
swagle8987 Oct 17, 2023
c7175c8
Added newick reader
swagle8987 Oct 17, 2023
cf0ce30
Merge remote-tracking branch 'refs/remotes/origin/2-create-rooted-phy…
swagle8987 Oct 17, 2023
d5a9b7c
switched from Hashset to Vec for children
sriram98v Oct 18, 2023
f38db88
switched to dbg! macro, modified add_node and from_newick
sriram98v Oct 18, 2023
7b6a3d4
added new methods with default implementations to tree trait (get_nod…
sriram98v Oct 19, 2023
d5e9686
updated output type of edge iterator
sriram98v Oct 19, 2023
5c6d4c3
adding weighted tree parsing
sriram98v Oct 20, 2023
a3bd6a6
changing newick string iterator
sriram98v Oct 20, 2023
b13faee
Revert "updated output type of edge iterator"
sriram98v Oct 21, 2023
a79b073
Revert "added new methods with default implementations to tree trait …
sriram98v Oct 21, 2023
0f7435b
updated trait methods for tree, added from newick weighted tree support
sriram98v Oct 21, 2023
0ba768b
implemented to_newick
sriram98v Oct 21, 2023
02c762f
added method to split edge, distance from root
sriram98v Oct 23, 2023
b57e585
removed unused import
sriram98v Oct 23, 2023
01a5e3b
implemented methods distance_from ancestor, distance from rootm dista…
sriram98v Oct 23, 2023
8926595
implemented post order edges
sriram98v Oct 23, 2023
6b28751
added methods to get each field of tree
sriram98v Oct 23, 2023
97478aa
added method to increment node_ids, renamed extract_subtree to prune
sriram98v Oct 23, 2023
53245eb
switched node from type to enum, updated all dependent methods and st…
sriram98v Oct 23, 2023
61a7a92
cargo warnings
sriram98v Oct 23, 2023
2be296e
cargo clippy
sriram98v Oct 23, 2023
5356840
switched to using preOrderNodeiterator for preOrderEdgeIterator
sriram98v Oct 23, 2023
ec4cf09
implemented graft_subtree method
sriram98v Oct 23, 2023
8615f6d
implemented partial reroot_at_node (dfs)
sriram98v Oct 23, 2023
86e8fe3
renamed graft_subtree to graft
sriram98v Oct 24, 2023
2ccd142
implemented iter_edges_pre and reroot at node
sriram98v Oct 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 66 additions & 16 deletions src/iter/edge_iter.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,99 @@
use crate::node::*;
use crate::tree::simple_rtree::*;
use std::collections::{HashMap, HashSet};
use itertools::Itertools;

use std::collections::HashMap;
use crate::iter::node_iter::{PostOrdNodes, PreOrdNodes};
use crate::tree::RootedPhyloTree;

pub struct PreOrdEdges
{
stack: Vec<(NodeID, NodeID)>,
nodes: HashMap<NodeID, HashSet<NodeID>>
node_iter: PreOrdNodes,
parents: HashMap<NodeID, (Option<NodeID>, Option<EdgeWeight>)>,
}

impl PreOrdEdges
{
pub fn new(_tree: &HashMap<NodeID, (EdgeWeight, NodeID)>)->Self{
Self { stack:vec![], nodes: HashMap::new()}
pub fn new(tree: &RootedPhyloTree, start_node: &NodeID)->Self{
Self {
node_iter: PreOrdNodes::new(
start_node,
tree.get_children(),
),
parents: tree.get_parents().into_iter()
.filter(|(_child_id, parent_id)| parent_id!=&&None)
.map(|(child_id, parent_id)| (child_id.clone(), (parent_id.clone(), tree.get_edge_weight(parent_id.as_ref().unwrap(), child_id).cloned()))).collect(),
}
}
}

impl Iterator for PreOrdEdges
{
type Item = (NodeID, NodeID);
type Item = (NodeID, NodeID, Option<EdgeWeight>);

fn next(&mut self)->Option<Self::Item>{
todo!();
while let Some(next_node) = self.node_iter.next() {
match next_node {
0 => {
continue;
}
_ => {
let parents = self.parents.get(&next_node).unwrap();
return Some((parents.0.unwrap(), next_node, parents.1));
}
}
}
None
}
}

pub struct PostOrdEdges
{
stack: Vec<(NodeID, NodeID)>,
nodes: HashMap<NodeID, HashSet<NodeID>>
stack: Vec<(NodeID, NodeID, Option<EdgeWeight>)>,
node_iter: PostOrdNodes,
children: HashMap<NodeID, Vec<(NodeID, Option<EdgeWeight>)>>,
parents: HashMap<NodeID, Option<NodeID>>,
}

impl PostOrdEdges
{
pub fn new(_tree: &HashMap<NodeID, (EdgeWeight, NodeID)>)->Self{
Self { stack:vec![], nodes: HashMap::new()}
pub fn new(tree: &RootedPhyloTree, start_node: &NodeID)->Self{
Self {
stack:vec![],
node_iter: PostOrdNodes::new(
start_node,
tree.get_children(),
),
children: tree.get_children().clone(),
parents: tree.get_parents().clone(),
}
}
}

impl Iterator for PostOrdEdges
{
type Item = (NodeID, NodeID);
type Item = (NodeID, NodeID, Option<EdgeWeight>);

fn next(&mut self)->Option<Self::Item>{
todo!();
}
match self.stack.pop(){
Some((n1, n2, w)) => Some((n1, n2, w)),
None => {
match self.node_iter.next(){
Some(node_id) => {
let node_id_parent = self.parents.get(&node_id).unwrap();
match node_id_parent {
Some(parent_id) => {
let mut w: Option<EdgeWeight> = None;
for (child_node_id, weight) in self.children.get(parent_id).unwrap(){
if child_node_id==&node_id{
w = *weight;
}
}
Some((*parent_id, node_id, w))
},
None => None,
}
},
None => None
}
}
} }
}
42 changes: 34 additions & 8 deletions src/iter/node_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::tree::simple_rtree::*;
use std::collections::{HashMap, HashSet};
use itertools::Itertools;


pub struct PreOrdNodes
{
stack: Vec<NodeID>,
Expand All @@ -12,8 +11,11 @@ pub struct PreOrdNodes

impl PreOrdNodes
{
pub fn new(start_node_id: &NodeID, _tree: &HashMap<NodeID, (EdgeWeight, NodeID)>)->Self{
Self { stack:vec![*start_node_id], nodes: HashMap::new()}
pub fn new(start_node_id: &NodeID, children: &HashMap<NodeID, Vec<(NodeID, Option<EdgeWeight>)>>)->Self{
Self { stack:vec![*start_node_id], nodes: children.iter()
.map(|(k, v)| (*k, v.iter()
.map(|ni| ni.0).collect::<HashSet<NodeID>>()))
.collect()}
}
}

Expand All @@ -22,7 +24,16 @@ impl Iterator for PreOrdNodes
type Item = NodeID;

fn next(&mut self)->Option<Self::Item>{
todo!()
match self.stack.pop() {
Some(node_id) => {
let children_ids:HashSet<NodeID> = self.nodes.get(&node_id).cloned().expect("Invalid Node ID!");
for child_node_id in children_ids.into_iter().sorted(){
self.stack.push(child_node_id)
}
Some(node_id)
}
None => None,
}
}
}

Expand All @@ -34,8 +45,11 @@ pub struct PostOrdNodes

impl PostOrdNodes
{
pub fn new(start_node_id: &NodeID, _tree: &HashMap<NodeID, (EdgeWeight, NodeID)>)->Self{
Self { stack:vec![*start_node_id], nodes: HashMap::new()}
pub fn new(start_node_id: &NodeID, children: &HashMap<NodeID, Vec<(NodeID, Option<EdgeWeight>)>>)->Self{
Self { stack:vec![*start_node_id], nodes: children.iter()
.map(|(k, v)| (*k, v.iter()
.map(|ni| ni.0).collect::<HashSet<NodeID>>()))
.collect()}
}
}

Expand All @@ -44,6 +58,18 @@ impl Iterator for PostOrdNodes
type Item = NodeID;

fn next(&mut self)->Option<Self::Item>{
todo!()
while let Some(node_id) = self.stack.pop() {
if self.nodes.contains_key(&node_id){
self.stack.push(node_id);
let children = self.nodes.remove(&node_id).unwrap();
for child_id in children.into_iter().sorted(){
self.stack.push(child_id)
}
}
else{
return Some(node_id)
}
}
None
}
}
}
57 changes: 56 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,59 @@
pub mod node;
pub mod tree;
pub mod taxa;
pub mod iter;
pub mod iter;


#[cfg(test)]
mod tests {
use crate::tree::{RootedPhyloTree, simple_rtree::SimpleRTree};
#[test]
fn read_small_tree() {
let input_str = String::from("((A,B),(C,D));");
let tree = RootedPhyloTree::from_newick(input_str);
dbg!(tree.to_newick());
}
#[test]
fn read_big_tree() {
let input_str = String::from("(0,(1,(2,(3,(4,(5,(6,(7,(8,(9,(10,(11,(12,(13,(14,(15,(16,(17,(18,(19,(20,(21,(22,(23,(24,(25,(26,(27,(28,(29,(30,(31,(32,(33,(34,(35,(36,(37,(38,(39,(40,(41,(42,(43,(44,(45,(46,(47,(48,(49,(50,(51,(52,(53,(54,(55,(56,(57,(58,(59,(60,(61,(62,(63,(64,(65,(66,(67,(68,(69,(70,(71,(72,(73,(74,(75,(76,(77,(78,(79,(80,(81,(82,(83,(84,(85,(86,(87,(88,(89,(90,(91,(92,(93,(94,(95,(96, (97,98))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))");
let tree = RootedPhyloTree::from_newick(input_str);
dbg!(tree.to_newick());
}
#[test]
fn read_smalllw_tree() {
let input_str = String::from("((A:0.12,B:12),(C:10,D:0.001));");
let tree = RootedPhyloTree::from_newick(input_str);
dbg!(tree.to_newick());
}
#[test]
fn read_smallfw_tree() {
let input_str = String::from("((A:0.12,B:12):10,(C:15,D:0.001):20);");
let tree = RootedPhyloTree::from_newick(input_str);
dbg!(tree.to_newick());
}
#[test]
fn read_smallfwfl_tree() {
let input_str = String::from("((A:0.12,B:12)E:10,(C:15,D:0.001)F:20)G;");
let mut tree = RootedPhyloTree::from_newick(input_str);
dbg!(tree.to_newick());
tree.reroot_at_node(&1);
dbg!(tree.to_newick());
}
#[test]
fn reroot_node_smallfwfl_tree() {
let input_str = String::from("((A:0.12,B:12)E:10,(C:15,D:0.001)F:20)G;");
let mut tree = RootedPhyloTree::from_newick(input_str);
dbg!(tree.to_newick());
tree.reroot_at_node(&1);
dbg!(tree.to_newick());
}
#[test]
fn reroot_edge_smallfwfl_tree() {
let input_str = String::from("((A:0.12,B:12)E:10,(C:15,D:0.001)F:20)G;");
let mut tree = RootedPhyloTree::from_newick(input_str);
dbg!(tree.to_newick());
tree.reroot_at_edge((&1, &0), (None, None));
dbg!(tree.to_newick());
}

}
59 changes: 53 additions & 6 deletions src/node.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,59 @@
use std::fmt::{Debug, Display};

pub type NodeID = usize;
pub type NodeType = bool; // True for leaves, false for internal nodes
// pub type NodeType = bool; // True for leaves, false for internal nodes

#[derive(Clone, PartialEq, Eq)]
pub enum NodeType{
Internal(Option<String>),
Leaf(Option<String>),
}

impl NodeType{
pub fn new(is_leaf: bool, taxa: Option<String>)->Self{
match is_leaf {
true => Self::Leaf(taxa),
false => Self::Internal(taxa),
}
}

pub fn is_leaf(&self)->bool{
match self {
NodeType::Internal(_taxa) => false,
NodeType::Leaf(_taxa) => true,
}
}

pub trait Node {
fn is_leaf(&self)->bool;
pub fn flip(&mut self){
match self {
NodeType::Internal(taxa) => {*self = NodeType::Leaf(taxa.clone())},
NodeType::Leaf(taxa) => {*self = NodeType::Internal(taxa.clone())},
}
}

pub fn taxa(&self)->String{
match self {
NodeType::Internal(taxa) => taxa.clone().unwrap_or("".to_string()),
NodeType::Leaf(taxa) => taxa.clone().unwrap_or("".to_string()),
}
}

pub fn node_type(&self)->String{
match self.is_leaf() {
false => "Internal".to_string(),
true => "Leaf".to_string(),
}
}
}

impl Debug for NodeType{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.node_type(), self.taxa())
}
}

impl Node for NodeType{
fn is_leaf(&self)->bool {
*self
impl Display for NodeType{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.node_type(), self.taxa())
}
}
Loading