[Bioperl-l] getting a subtree
Devin Scannell
scannedr at tcd.ie
Sat Mar 6 15:55:21 EST 2004
Hi Jason and Deng,
I suspect Jasons solution was the required one but I have been getting
a lot of use out of the method below which does something similar -
return a branch as a new tree object but also remove it from the
original tree. I have been using it to split trees into well supported
clades according to certain criteria.
if its useful and the caveats (1. only works for bifurcating nodes and
2. does not correct branch lengths (it was written for use with phylip
trees)) are not too problematic, I would be happy to have it added to
the Tree::FunctionsI module. Failing this, if I get an interested
reply, I'll correct these problems when less busy and resubmit.
best,
Devin
=head2 remove_branch
Title : remove_branch
Usage : $tree->remove_branch($first_node_on_branch_to_be_removed)
Function: At a bifurcating node removes one descendant branch
and replaces the ancestral branch with the other descendant
branch.
As a bonus the removed node is used to root and return a new
tree.
This function therefore effectively makes two trees from the
original.
This method DOES NOT work at trifurcating nodes
and DOES NOT correct branch lengths.
Returns : New tree object corresponding to removed branch.
Args : Bio::Tree::NodeI object or node id
Added : Devin Scannell Wed Feb 11 22:09:28 GMT 2004
=cut
sub remove_branch {
# if b is a bifurcating node
# where a->b is the ancestral branch
# and b->c, b->d are descendent branches
# then
# 1) destroy central_node (b)
# 2) make retain_node (c) a descendent of attach_node (a)
# 3) return remove_node (d) as a new tree object
my $self = shift;
my $remove_node = shift;
$remove_node = $self->find_node($remove_node) unless
ref($remove_node);
# some light checking
unless ($remove_node) {
$self->warn("Requires Bio::Tree::NodeI object or node id as an
argument");
return undef;
}
unless (scalar($remove_node->ancestor->each_Descendent) == 2 ) {
$self->warn("Tree not bifurcating");
return undef;
}
# get attach_node && central_node
my $central_node = $remove_node->ancestor;
my $attach_node = $central_node->ancestor;
# get retain_node
my $retain_node = '';
foreach ($remove_node->ancestor->each_Descendent) {
$retain_node = $_;
last if $retain_node ne $remove_node;
}
# destroy central_node
$self->remove_Node($central_node);
# if no attach_node, tree is bisected
# ie remove_node and retain_node are immediate descendants of the
root node
# therefore just reroot current tree at retain_node
if ($attach_node) {
$attach_node->add_Descendent($retain_node, 1);
} else {
$retain_node->ancestor(undef);
$self->set_root_node($retain_node);
}
# make new tree from removed branch and return
$remove_node->ancestor(undef);
return(Bio::Tree::Tree->new(-root => $remove_node));
}
On Thursday, Mar 4, 2004, at 21:15 Europe/Dublin, Jason Stajich wrote:
> Deng - here is some code to answer your question.
>
> use Bio::Tree::Tree;
> use Bio::TreeIO;
>
> # get a tree somehow
> # choose the subnodes for finding the lca somehow
>
> # get the least common ancestor
> my $node = $tree->get_lca( -nodes => \@nodes );
>
> # build a new tree with its root at $node
> my $subtree = Bio::Tree::Tree->new(-root => $node, -nodelete => 1);
>
> my $out = Bio::TreeIO->new(-format=>'newick');
> $out->write_tree($subtree);
>
> -jason
>
> --
> Jason Stajich
> Duke University
> jason at cgt.mc.duke.edu
> _______________________________________________
> Bioperl-l mailing list
> Bioperl-l at portal.open-bio.org
> http://portal.open-bio.org/mailman/listinfo/bioperl-l
>
-----------------
Devin Scannell,
Wolfe Lab,
TCD,
Ireland
00353-1-6081288
-----------------
More information about the Bioperl-l
mailing list