[Bioperl-guts-l] bioperl-live/Bio/Tree TreeFunctionsI.pm, 1.31, 1.32
Senduran Balasubramaniam
sendu at dev.open-bio.org
Thu Dec 21 11:47:31 EST 2006
Update of /home/repository/bioperl/bioperl-live/Bio/Tree
In directory dev.open-bio.org:/tmp/cvs-serv3409/Bio/Tree
Modified Files:
TreeFunctionsI.pm
Log Message:
added force_binary() method
Index: TreeFunctionsI.pm
===================================================================
RCS file: /home/repository/bioperl/bioperl-live/Bio/Tree/TreeFunctionsI.pm,v
retrieving revision 1.31
retrieving revision 1.32
diff -C2 -d -r1.31 -r1.32
*** TreeFunctionsI.pm 18 Dec 2006 19:13:10 -0000 1.31
--- TreeFunctionsI.pm 21 Dec 2006 16:47:29 -0000 1.32
***************
*** 506,509 ****
--- 506,622 ----
}
+ =head2 force_binary
+
+ Title : force_binary
+ Usage : force_binary()
+ Function: Forces the tree into a binary tree, splitting branches arbitrarily
+ and creating extra nodes as necessary, such that all nodes have
+ exactly two or zero descendants.
+ Returns : n/a
+ Args : none
+
+ For example, if we are the tree $tree:
+
+ +---G
+ |
+ +---F
+ |
+ +---E
+ |
+ A
+ |
+ +---D
+ |
+ +---C
+ |
+ +---B
+
+ (A has 6 descendants B-G)
+
+ After calling $tree->force_binary(), $tree looks like:
+
+ +---X
+ |
+ +---X
+ | |
+ | +---X
+ |
+ +---X
+ | |
+ | | +---G
+ | | |
+ | +---X
+ | |
+ | +---F
+ A
+ | +---E
+ | |
+ | +---X
+ | | |
+ | | +---D
+ | |
+ +---X
+ |
+ | +---C
+ | |
+ +---X
+ |
+ +---B
+
+ (Where X are artificially created nodes with ids 'artificial_n', where n is
+ an integer making the id unique within the tree)
+
+ =cut
+
+ sub force_binary {
+ my $self = shift;
+ my $node = shift || $self->get_root_node;
+
+ my @descs = $node->each_Descendent;
+ if (@descs > 2) {
+ $self->warn("Node ".($node->can('node_name') ? ($node->node_name || $node->id) : $node->id).
+ " has more than two descendants\n(".
+ join(", ", map { $node->can('node_name') ? ($node->node_name || $node->id) : $node->id } @descs).
+ ")\nWill do an arbitrary balanced split");
+
+ my @working = @descs;
+
+ # create an even set of artifical nodes on which to later hang the descs
+ my $half = @working / 2;
+ $half++ if $half > int($half);
+ $half = int($half);
+ my @artificials;
+ while ($half > 1) {
+ my @this_level;
+ foreach my $top_node (@artificials || $node) {
+ for (1..2) {
+ my $art = $top_node->new(-id => "artificial_".++$self->{_art_num});
+ $top_node->add_Descendent($art);
+ push(@this_level, $art);
+ }
+ }
+ @artificials = @this_level;
+ $half--;
+ }
+
+ # attach two descs to each artifical leaf
+ foreach my $art (@artificials) {
+ for (1..2) {
+ my $desc = shift(@working) || $node->new(-id => "artificial_".++$self->{_art_num});
+ $desc->ancestor($art);
+ }
+ }
+ }
+ elsif (@descs == 1) {
+ # ensure that all nodes have 2 descs
+ $node->add_Descendent($node->new(-id => "artificial_".++$self->{_art_num}));
+ }
+
+ # recurse
+ foreach my $desc (@descs) {
+ $self->force_binary($desc);
+ }
+ }
+
=head2 distance
More information about the Bioperl-guts-l
mailing list