Bio::Tree
TreeFunctionsI
Toolbar
Summary
Bio::Tree::TreeFunctionsI - Decorated Interface implementing basic Tree exploration methods
Package variables
No package variables defined.
Included modules
Inherit
Synopsis
use Bio::TreeIO;
my $in = new Bio::TreeIO(-format => 'newick', -file => 'tree.tre');
my $tree = $in->next_tree;
my @nodes = $tree->find_node('id1');
if( $tree->is_monophyletic(-clade => @nodes, -outgroup => $outnode) ){
}
Description
Describe the interface here
Methods
Methods description
Title : delete_edge Usage : $node->reverse_edge(child); Function: makes child be a parent of node Requires: child must be a direct descendent of node Returns : nothing Args : Bio::Tree::NodeI that is in the tree |
Title : distance Usage : distance(-nodes => \@nodes ) Function: returns the distance between two given nodes Returns : numerical distance Args : -nodes => arrayref of nodes to test |
Title : find_node Usage : my @nodes = $self->find_node(-id => 'node1'); Function: returns all nodes that match a specific field, by default this is id, but different branch_length, Returns : List of nodes which matched search Args : text string to search for OR -fieldname => $textstring |
Title : get_lca Usage : get_lca(-nodes => \@nodes ) Function: given two nodes, returns the lowest common ancestor Returns : node object Args : -nodes => arrayref of nodes to test |
Title : is_monophyletic Usage : if( $tree->is_monophyletic(-nodes => \@nodes, -outgroup => $outgroup) Function: Will do a test of monophyly for the nodes specified in comparison to a chosen outgroup Returns : boolean Args : -nodes => arrayref of nodes to test -outgroup => outgroup to serve as a reference |
Title : is_paraphyletic Usage : if( $tree->is_paraphyletic(-nodes =>\@nodes, -outgroup => $node) ){ } Function: Tests whether or not a given set of nodes are paraphyletic (representing the full clade) given an outgroup Returns : [-1,0,1] , -1 if the group is not monophyletic 0 if the group is not paraphyletic 1 if the group is paraphyletic Args : -nodes => Array of Bio::Tree::NodeI objects which are in the tree -outgroup => a Bio::Tree::NodeI to compare the nodes to |
Title : remove_Node Usage : $tree->remove_Node($node) Function: Removes a node from the tree Returns : boolean represent status of success Args : either Bio::Tree::NodeI or string of the node id |
Title : reroot_tree Usage : $tree->reroot($node); Function: Reroots a tree either making a new node the root Returns : 1 on success, 0 on failure Args : Bio::Tree::NodeI that is in the tree, but is not the current root |
Title : reverse_edge Usage : $node->reverse_edge(child); Function: makes child be a parent of node Requires: child must be a direct descendent of node Returns : nothing Args : Bio::Tree::NodeI that is in the tree |
Methods code
_check_two_nodes | description | prev | next | Top |
sub _check_two_nodes
{ my ($self, $nodes) = @_;
if( ref($nodes) !~ /ARRAY/i ||
!ref($nodes->[0]) ||
!ref($nodes->[1])
) {
$self->warn("Must provide a valid array reference for -nodes");
return undef;
} elsif( scalar(@$nodes) > 2 ){
$self->warn("More than two nodes given, using first two");
} elsif( scalar(@$nodes) < 2 ){
$self->warn("-nodes parameter does not contain reference to two nodes");
return undef;
}
unless( $nodes->[0]->isa('Bio::Tree::NodeI') &&
$nodes->[1]->isa('Bio::Tree::NodeI') ) {
$self->warn("Did not provide valid Bio::Tree::NodeI objects as nodes\n");
return undef;
}
return @$nodes; } |
sub delete_edge
{ my ($self,$node) = @_;
unless (defined $self && $self->isa("Bio::Tree::NodeI")) {
$self->warn("Must provide a valid Bio::Tree::NodeI when rerooting");
return 1;
}
unless (defined $node && $node->isa("Bio::Tree::NodeI")) {
$self->warn("Must provide a valid Bio::Tree::NodeI when rerooting");
return 1;
}
if( $self->{'_desc'}->{$node->internal_id} ) {
$node->ancestor(undef);
$self->{'_desc'}->{$node->internal_id}->ancestor(undef);
delete $self->{'_desc'}->{$node->internal_id};
} else {
$self->warn("First argument must be direct parent of node");
return 1;
}
1; } |
sub distance
{ my ($self,@args) = @_;
my ($nodes) = $self->_rearrange([qw(NODES)],@args);
if( ! defined $nodes ) {
$self->warn("Must supply -nodes parameter to distance() method");
return undef;
}
my ($node1,$node2) = $self->_check_two_nodes($nodes);
my %node1_ancestors; my %node1_cumul_dist; my $place = $node1; my $cumul_dist = 0;
while ( $place ){
$node1_ancestors{$place->internal_id} = $place;
$node1_cumul_dist{$place->internal_id} = $cumul_dist;
if ($place->branch_length) {
$cumul_dist += $place->branch_length; }
$place = $place->ancestor;
}
$place = $node2; $cumul_dist = 0;
while ( $place ){
foreach my $key ( keys %node1_ancestors ){ if ( $place->internal_id == $key){ return $node1_cumul_dist{$key} + $cumul_dist;
}
}
$cumul_dist += $place->branch_length;
$place = $place->ancestor;
}
$self->warn("Could not find distance!"); return undef;
}
} |
sub find_node
{ my ($self,$type,$field) = @_;
if( ! defined $type ) {
$self->warn("Must request a either a string or field and string when searching");
}
if( ! defined $field ) {
$field= $type;
$type = 'id';
} else {
$type =~ s/^-//;
}
unless( $type eq 'id' || $type eq 'name' ||
$type eq 'bootstrap' || $type eq 'description' ||
$type eq 'internal_id') {
$self->warn("unknown search type $type - will try anyways");
}
my @nodes = grep { $_->can($type) && defined $_->$type() &&
$_->$type() eq $field } $self->get_nodes();
if ( wantarray) {
return @nodes;
} else {
if( @nodes > 1 ) {
$self->warn("More than 1 node found but caller requested scalar, only returning first node");
}
return shift @nodes;
} } |
sub findnode_by_id
{ my $tree = shift;
my $id = shift;
my $rootnode = $tree->get_root_node;
if ( ($rootnode->id) and ($rootnode->id eq $id) ) {
return $rootnode;
}
foreach my $node ( $rootnode->get_Descendents ) {
if ( ($node->id) and ($node->id eq $id ) ) {
return $node;
}
}
}
1; } |
sub get_lca
{ my ($self,@args) = @_;
my ($nodes) = $self->_rearrange([qw(NODES)],@args);
if( ! defined $nodes ) {
$self->warn("Must supply -nodes parameter to get_lca() method");
return undef;
}
my ($node1,$node2) = $self->_check_two_nodes($nodes);
return undef unless $node1 && $node2;
my %node1_ancestors; my $place = $node1;
while ( $place ){
$node1_ancestors{$place->internal_id} = $place;
$place = $place->ancestor;
}
$place = $node2; while ( $place ){
foreach my $key ( keys %node1_ancestors ){ if ( $place->internal_id == $key){
return $node1_ancestors{$key};
}
}
$place = $place->ancestor;
}
$self->warn("Could not find lca!"); return undef;
}
} |
sub is_monophyletic
{ my ($self,@args) = @_;
my ($nodes,$outgroup) = $self->_rearrange([qw(NODES OUTGROUP)],@args);
if( ! defined $nodes || ! defined $outgroup ) {
$self->warn("Must supply -nodes and -outgroup parameters to the method
is_monophyletic");
return undef;
}
if( ref($nodes) !~ /ARRAY/i ) {
$self->warn("Must provide a valid array reference for -nodes");
}
my $clade_root;
while( @$nodes > 2 ) {
my ($a,$b) = ( shift @$nodes, shift @$nodes);
$clade_root = $self->get_lca(-nodes => [$a,$b] );
unshift @$nodes, $clade_root;
}
$clade_root = $self->get_lca(-nodes => $nodes );
my $og_ancestor = $outgroup->ancestor;
while( defined ($og_ancestor ) ) {
if( $og_ancestor->internal_id == $clade_root->internal_id ) {
return 0;
}
$og_ancestor = $og_ancestor->ancestor;
}
return 1; } |
sub is_paraphyletic
{ my ($self,@args) = @_;
my ($nodes,$outgroup) = $self->_rearrange([qw(NODES OUTGROUP)],@args);
if( ! defined $nodes || ! defined $outgroup ) {
$self->warn("Must suply -nodes and -outgroup parameters to the method is_paraphyletic");
return undef;
}
if( ref($nodes) !~ /ARRAY/i ) {
$self->warn("Must provide a valid array reference for -nodes");
return undef;
}
my %nodehash;
foreach my $n ( @$nodes ) {
$nodehash{$n->internal_id} = $n;
}
while( @$nodes > 2 ) {
unshift @$nodes, $self->get_lca(-nodes => [( shift @$nodes,
shift @$nodes)] );
}
my $clade_root = $self->get_lca(-nodes => $nodes );
unless( defined $clade_root ) {
$self->warn("could not find clade root via lca");
return undef;
}
my $og_ancestor = $outgroup->ancestor;
while( defined ($og_ancestor ) ) {
if( $og_ancestor->internal_id == $clade_root->internal_id ) {
return -1;
}
$og_ancestor = $og_ancestor->ancestor;
}
my $tree = new Bio::Tree::Tree(-root => $clade_root,
-nodelete => 1);
foreach my $n ( $tree->get_nodes() ) {
next unless $n->is_Leaf();
return 1 unless ( $nodehash{$n->internal_id} );
}
return 0; } |
sub remove_Node
{ my ($self,$input) = @_;
my $node = undef;
unless( ref($input) ) {
$node = $self->find_node($input);
} elsif( ! $input->isa('Bio::Tree::NodeI') ) {
$self->warn("Did not provide either a valid Bio::Tree::NodeI object to remove_node or the node name");
return 0;
} else {
$node = $input;
}
if( ! $node->ancestor && $self->get_root_node->internal_id != $node->internal_id) {
$self->warn("Node (".$node->to_string . ") has no ancestor, can't remove!");
} else {
$node->ancestor->remove_Descendent($node);
}
}
} |
sub reroot
{ my ($self,$new_root) = @_;
unless (defined $new_root && $new_root->isa("Bio::Tree::NodeI")) {
$self->warn("Must provide a valid Bio::Tree::NodeI when rerooting");
return 0;
}
if( $new_root->is_Leaf() ) {
$self->warn("Asking to root with a leaf, will use the leaf's ancestor");
$new_root = $new_root->ancestor;
}
my $old_root = $self->get_root_node;
if( $new_root == $old_root ) {
$self->warn("Node requested for reroot is already the root node!");
return 0;
}
my @path = (); my $node = $new_root;
while ($node) {
push @path, $node;
$node = $node->ancestor;
}
my @path_from_oldroot = reverse @path;
for (my $i = 0; $i < @path_from_oldroot - 1; $i++) {
my $current = $path_from_oldroot[$i];
my $next = $path_from_oldroot[$i + 1];
$current->remove_Descendent($next);
$current->branch_length($next->branch_length);
$next->add_Descendent($current);
}
$new_root->branch_length(undef);
$self->set_root_node($new_root);
return 1; } |
sub reverse_edge
{ my ($self,$node) = @_;
delete_edge($self, $node);
$node->add_Descendent($self);
1; } |
General documentation
User feedback is an integral part of the evolution of this and other
Bioperl modules. Send your comments and suggestions preferably to
the Bioperl mailing list. Your participation is much appreciated.
bioperl-l@bioperl.org - General discussion
http://bioperl.org/MailList.shtml - About the mailing lists
Report bugs to the Bioperl bug tracking system to help us keep track
of the bugs and their resolution. Bug reports can be submitted via
email or the web:
bioperl-bugs@bioperl.org
http://bugzilla.bioperl.org/
AUTHOR - Jason Stajich, Aaron Mackey, Justin Reese | Top |
Email jason-at-bioperl-dot-org
Email amackey-at-virginia.edu
Email jtr4v-at-virginia.edu
Additional contributors names and emails here
Rerooting code was worked on by
Daniel Barker d.barker-at-reading.ac.uk
Ramiro Barrantes Ramiro.Barrantes-at-uvm.edu
The rest of the documentation details each of the object methods.
Internal methods are usually preceded with a _