File Coverage

Bio/Tree/Tree.pm
Criterion Covered Total %
statement 118 138 85.5
branch 34 52 65.3
condition 20 39 51.2
subroutine 19 21 90.4
pod 18 19 94.7
total 209 269 77.7


line stmt bran cond sub pod time code
1             #
2             # BioPerl module for Bio::Tree::Tree
3             #
4             # Please direct questions and support issues to
5             #
6             # Cared for by Jason Stajich
7             #
8             # Copyright Jason Stajich
9             #
10             # You may distribute this module under the same terms as perl itself
11              
12             # POD documentation - main docs before the code
13              
14              
15             =head1 NAME
16              
17             Bio::Tree::Tree - An implementation of the TreeI interface.
18              
19             =head1 SYNOPSIS
20              
21             use Bio::TreeIO;
22              
23             # like from a TreeIO
24             my $treeio = Bio::TreeIO->new(-format => 'newick', -file => 'treefile.dnd');
25             my $tree = $treeio->next_tree;
26             my @nodes = $tree->get_nodes;
27             my $root = $tree->get_root_node;
28              
29             =head1 DESCRIPTION
30              
31             This object holds handles to Nodes which make up a tree.
32              
33             =head1 IMPLEMENTATION NOTE
34              
35             This implementation of Bio::Tree::Tree contains Bio::Tree:::NodeI; mainly linked
36             via the root node. As NodeI can potentially contain circular references (as
37             nodes will need to refer to both parent and child nodes), Bio::Tree::Tree will
38             remove those circular references when the object is garbage-collected. This has
39             some side effects; primarily, one must keep the Tree in scope or have at least
40             one reference to it if working with nodes. The fix is to count the references to
41             the nodes and if it is greater than expected retain all of them, but it requires
42             an additional prereq and thus may not be worth the effort. This only shows up
43             in minor edge cases, though (see Bug #2869).
44              
45             Example of issue:
46              
47             # tree is not assigned to a variable, so passes from memory after
48             # root node is passed
49             my $root = Bio::TreeIO->new(-format => 'newick', -file => 'foo.txt')->next_tree
50             ->get_root_node;
51              
52             # gets nothing, as all Node links are broken when Tree is garbage-collected above
53             my @descendents = $root->get_all_Descendents;
54              
55             =head1 FEEDBACK
56              
57             =head2 Mailing Lists
58              
59             User feedback is an integral part of the evolution of this and other
60             Bioperl modules. Send your comments and suggestions preferably to
61             the Bioperl mailing list. Your participation is much appreciated.
62              
63             bioperl-l@bioperl.org - General discussion
64             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
65              
66             =head2 Support
67              
68             Please direct usage questions or support issues to the mailing list:
69              
70             I
71              
72             rather than to the module maintainer directly. Many experienced and
73             reponsive experts will be able look at the problem and quickly
74             address it. Please include a thorough description of the problem
75             with code and data examples if at all possible.
76              
77             =head2 Reporting Bugs
78              
79             Report bugs to the Bioperl bug tracking system to help us keep track
80             of the bugs and their resolution. Bug reports can be submitted via
81             the web:
82              
83             https://github.com/bioperl/bioperl-live/issues
84              
85             =head1 AUTHOR - Jason Stajich
86              
87             Email jason@bioperl.org
88              
89             =head1 CONTRIBUTORS
90              
91             Aaron Mackey amackey@virginia.edu
92             Sendu Bala bix@sendu.me.uk
93             Mark A. Jensen maj@fortinbras.us
94              
95             =head1 APPENDIX
96              
97             The rest of the documentation details each of the object methods.
98             Internal methods are usually preceded with a _
99              
100             =cut
101              
102              
103             # Let the code begin...
104              
105              
106             package Bio::Tree::Tree;
107 67     67   1014 use strict;
  67         75  
  67         1872  
108              
109             # Object preamble - inherits from Bio::Root::Root
110              
111              
112 67     67   207 use base qw(Bio::Root::Root Bio::Tree::TreeI Bio::Tree::TreeFunctionsI);
  67         141  
  67         20735  
113              
114             =head2 new
115              
116             Title : new
117             Usage : my $obj = Bio::Tree::Tree->new();
118             Function: Builds a new Bio::Tree::Tree object
119             Returns : Bio::Tree::Tree
120             Args : -root => L object which is the root
121             OR
122             -node => L object from which the root will be
123             determined
124            
125             -nodelete => boolean, whether or not to try and cleanup all
126             the nodes when this this tree goes out of scope.
127             -id => optional tree ID
128             -score => optional tree score value
129              
130             =cut
131              
132             sub new {
133 1150     1150 1 1865 my ($class, @args) = @_;
134            
135 1150         2687 my $self = $class->SUPER::new(@args);
136 1150         1794 $self->{'_rootnode'} = undef;
137 1150         1560 $self->{'_maxbranchlen'} = 0;
138 1150         2507 $self->_register_for_cleanup(\&cleanup_tree);
139 1150         4081 my ($root, $node, $nodel, $id, $score) =
140             $self->_rearrange([qw(ROOT NODE NODELETE ID SCORE)], @args);
141            
142 1150 100 66     3698 if ($node && ! $root) {
143 252 50 33     1538 $self->throw("Must supply a Bio::Tree::NodeI") unless ref($node) && $node->isa('Bio::Tree::NodeI');
144 252         1135 my @lineage = $self->get_lineage_nodes($node);
145 252   33     805 $root = shift(@lineage) || $node;
146            
147             # to stop us pulling in entire database of a Bio::Taxon when we later do
148             # get_nodes() or similar, specifically set ancestor() for each node
149 252 50       953 if ($node->isa('Bio::Taxon')) {
150 252 50       1035 push(@lineage, $node) unless $node eq $root;
151 252         331 my $ancestor = $root;
152 252         747 foreach my $lineage_node (@lineage) {
153 2111         3521 $lineage_node->ancestor($ancestor);
154 2111         3255 } continue { $ancestor = $lineage_node; }
155             }
156             }
157 1150 100       2061 if ($root) {
158 912         2263 $self->set_root_node($root);
159             }
160            
161 1150   100     4440 $self->nodelete($nodel || 0);
162 1150 50       1997 $self->id($id) if defined $id;
163 1150 50       1936 $self->score($score) if defined $score;
164 1150         3268 return $self;
165             }
166              
167              
168             =head2 nodelete
169              
170             Title : nodelete
171             Usage : $obj->nodelete($newval)
172             Function: Get/Set Boolean whether or not to delete the underlying
173             nodes when it goes out of scope. By default this is false
174             meaning trees are cleaned up.
175             Returns : boolean
176             Args : on set, new boolean value
177              
178             =cut
179              
180             sub nodelete {
181 2102     2102 1 2011 my $self = shift;
182 2102 100       4314 return $self->{'nodelete'} = shift if @_;
183 952         2192 return $self->{'nodelete'};
184             }
185              
186              
187             =head2 get_nodes
188              
189             Title : get_nodes
190             Usage : my @nodes = $tree->get_nodes()
191             Function: Return list of Bio::Tree::NodeI objects
192             Returns : array of Bio::Tree::NodeI objects
193             Args : (named values) hash with one value
194             order => 'b|breadth' first order or 'd|depth' first order
195             sortby => [optional] "height", "creation", "alpha", "revalpha",
196             or coderef to be used to sort the order of children nodes. See L for details
197              
198             =cut
199              
200             sub get_nodes {
201 1782     1782 1 6009 my ($self, @args) = @_;
202 1782         4970 my ($order, $sortby) = $self->_rearrange([qw(ORDER SORTBY)], @args);
203 1782   100     4732 $order ||= 'depth';
204 1782   100     3447 $sortby ||= 'none';
205              
206 1782         1294 my @children;
207 1782         2701 my $node = $self->get_root_node;
208 1782 100       3095 if ($node) {
209 1776 100       4711 if ($order =~ m/^b/oi) { # breadth-first
    50          
210 946         1323 @children = ($node);
211 946         1280 my @to_process = ($node);
212 946         1732 while( @to_process ) {
213 10311         7318 my $n = shift @to_process;
214 10311         12977 my @c = $n->each_Descendent($sortby);
215 10311         9672 push @children, @c;
216 10311         14837 push @to_process, @c;
217             }
218             } elsif ($order =~ m/^d/oi) { # depth-first
219 830         1812 @children = ($node, $node->get_all_Descendents($sortby));
220             } else {
221 0         0 $self->verbose(1);
222 0         0 $self->warn("specified an order '$order' which I don't understan\n");
223             }
224             }
225              
226 1782         4750 return @children;
227             }
228              
229              
230             =head2 get_root_node
231              
232             Title : get_root_node
233             Usage : my $node = $tree->get_root_node();
234             Function: Get the Top Node in the tree, in this implementation
235             Trees only have one top node.
236             Returns : Bio::Tree::NodeI object
237             Args : none
238              
239             =cut
240              
241             sub get_root_node {
242 4416     4416 1 4663 my ($self) = @_;
243 4416         7140 return $self->{'_rootnode'};
244             }
245              
246              
247             =head2 set_root_node
248              
249             Title : set_root_node
250             Usage : $tree->set_root_node($node)
251             Function: Set the Root Node for the Tree
252             Returns : Bio::Tree::NodeI
253             Args : Bio::Tree::NodeI
254              
255             =cut
256              
257             sub set_root_node {
258 929     929 1 1032 my $self = shift;
259 929 50       1735 if ( @_ ) {
260 929         860 my $value = shift;
261 929 50 33     4612 if ( defined $value && ! $value->isa('Bio::Tree::NodeI') ) {
262 0         0 $self->warn("Trying to set the root node to $value which is not a Bio::Tree::NodeI");
263 0         0 return $self->get_root_node;
264             }
265 929         1273 $self->{'_rootnode'} = $value;
266             }
267 929         1695 return $self->get_root_node;
268             }
269              
270              
271             =head2 total_branch_length
272              
273             Title : total_branch_length
274             Usage : my $size = $tree->total_branch_length
275             Function: Returns the sum of the length of all branches
276             Returns : real
277             Args : none
278              
279             =cut
280              
281 18     18 1 936 sub total_branch_length { shift->subtree_length }
282              
283              
284             =head2 subtree_length
285              
286             Title : subtree_length
287             Usage : my $subtree_size = $tree->subtree_length($internal_node)
288             Function: Returns the sum of the length of all branches in a subtree
289             under the node. Calculates the size of the whole tree
290             without an argument (but only if root node is defined)
291             Returns : real or undef
292             Args : Bio::Tree::NodeI object, defaults to the root node
293              
294             =cut
295              
296             sub subtree_length {
297 20     20 1 24 my $tree = shift;
298 20   66     61 my $node = shift || $tree->get_root_node;
299 20 50       36 return unless $node;
300 20         22 my $sum = 0;
301 20         43 for ( $node->get_all_Descendents ) {
302 581   100     628 $sum += $_->branch_length || 0;
303             }
304 20         123 return $sum;
305             }
306              
307              
308             =head2 id
309              
310             Title : id
311             Usage : my $id = $tree->id();
312             Function: An id value for the tree
313             Returns : scalar
314             Args : [optional] new value to set
315              
316             =cut
317              
318             sub id {
319 73     73 1 1774 my ($self, $val) = @_;
320 73 100       140 if ( defined $val ) {
321 68         133 $self->{'_treeid'} = $val;
322             }
323 73         115 return $self->{'_treeid'};
324             }
325              
326              
327             =head2 score
328              
329             Title : score
330             Usage : $obj->score($newval)
331             Function: Sets the associated score with this tree
332             This is a generic slot which is probably best used
333             for log likelihood or other overall tree score
334             Returns : value of score
335             Args : newvalue (optional)
336              
337             =cut
338              
339             sub score {
340 205     205 1 2209 my ($self, $val) = @_;
341 205 100       362 if ( defined $val ) {
342 33         44 $self->{'_score'} = $val;
343             }
344 205         312 return $self->{'_score'};
345             }
346              
347              
348             # decorated interface TreeI Implements this
349              
350             =head2 height
351              
352             Title : height
353             Usage : my $height = $tree->height
354             Function: Gets the height of tree - this LOG_2($number_nodes)
355             WARNING: this is only true for strict binary trees. The TreeIO
356             system is capable of building non-binary trees, for which this
357             method will currently return an incorrect value!!
358             Returns : integer
359             Args : none
360              
361             =head2 number_nodes
362              
363             Title : number_nodes
364             Usage : my $size = $tree->number_nodes
365             Function: Returns the number of nodes in the tree
366             Returns : integer
367             Args : none
368              
369             =head2 as_text
370              
371             Title : as_text
372             Usage : my $tree_as_string = $tree->as_text($format)
373             Function: Returns the tree as a string representation in the
374             desired format, e.g.: 'newick', 'nhx' or 'tabtree' (the default)
375             Returns : scalar string
376             Args : format type as specified by Bio::TreeIO
377             Note : This method loads the Bio::TreeIO::$format module
378             on the fly, and commandeers the _write_tree_Helper
379             routine therein to create the tree string.
380              
381             =cut
382              
383             sub as_text {
384 42     42 1 102 my $self = shift;
385 42   50     79 my $format = shift || 'tabtree';
386 42   100     111 my $params_input = shift || {};
387              
388 42         59 my $iomod = "Bio::TreeIO::$format";
389 42         77 $self->_load_module($iomod);
390              
391 42         41 my $string = '';
392 42 50       419 open my $fh, '>', \$string or $self->throw("Could not write '$string' as file: $!");
393 42         229 my $test = $iomod->new( -format => $format, -fh => $fh );
394              
395             # Get the default params for the given IO module.
396 42         94 $test->set_params($params_input);
397              
398 42         61 $test->write_tree($self);
399 42         68 close $fh;
400 42         113 return $string;
401             }
402              
403              
404             =head2 Methods for associating Tag/Values with a Tree
405              
406             These methods associate tag/value pairs with a Tree
407              
408             =head2 set_tag_value
409              
410             Title : set_tag_value
411             Usage : $tree->set_tag_value($tag,$value)
412             $tree->set_tag_value($tag,@values)
413             Function: Sets a tag value(s) to a tree. Replaces old values.
414             Returns : number of values stored for this tag
415             Args : $tag - tag name
416             $value - value to store for the tag
417              
418             =cut
419              
420             sub set_tag_value {
421 1     1 1 3 my ($self, $tag, @values) = @_;
422 1 50 33     5 if ( ! defined $tag || ! scalar @values ) {
423 0         0 $self->warn("cannot call set_tag_value with an undefined value");
424             }
425 1         2 $self->remove_tag ($tag);
426 1         2 map { push @{$self->{'_tags'}->{$tag}}, $_ } @values;
  3         2  
  3         7  
427 1         1 return scalar @{$self->{'_tags'}->{$tag}};
  1         3  
428             }
429              
430              
431             =head2 add_tag_value
432              
433             Title : add_tag_value
434             Usage : $tree->add_tag_value($tag,$value)
435             Function: Adds a tag value to a tree
436             Returns : number of values stored for this tag
437             Args : $tag - tag name
438             $value - value to store for the tag
439              
440             =cut
441              
442             sub add_tag_value {
443 2     2 1 5 my ($self, $tag, $value) = @_;
444 2 50 33     7 if ( ! defined $tag || ! defined $value ) {
445 0         0 $self->warn("cannot call add_tag_value with an undefined value");
446             }
447 2         2 push @{$self->{'_tags'}->{$tag}}, $value;
  2         5  
448 2         3 return scalar @{$self->{'_tags'}->{$tag}};
  2         7  
449             }
450              
451              
452             =head2 remove_tag
453              
454             Title : remove_tag
455             Usage : $tree->remove_tag($tag)
456             Function: Remove the tag and all values for this tag
457             Returns : boolean representing success (0 if tag does not exist)
458             Args : $tag - tagname to remove
459              
460             =cut
461              
462             sub remove_tag {
463 3     3 1 4 my ($self, $tag) = @_;
464 3 100       9 if ( exists $self->{'_tags'}->{$tag} ) {
465 1         1 $self->{'_tags'}->{$tag} = undef;
466 1         2 delete $self->{'_tags'}->{$tag};
467 1         3 return 1;
468             }
469 2         4 return 0;
470             }
471              
472              
473             =head2 remove_all_tags
474              
475             Title : remove_all_tags
476             Usage : $tree->remove_all_tags()
477             Function: Removes all tags
478             Returns : None
479             Args : None
480              
481             =cut
482              
483             sub remove_all_tags {
484 1     1 1 2 my ($self) = @_;
485 1         2 $self->{'_tags'} = {};
486 1         3 return;
487             }
488              
489              
490             =head2 get_all_tags
491              
492             Title : get_all_tags
493             Usage : my @tags = $tree->get_all_tags()
494             Function: Gets all the tag names for this Tree
495             Returns : Array of tagnames
496             Args : None
497              
498             =cut
499              
500             sub get_all_tags {
501 0     0 1 0 my ($self) = @_;
502 0 0       0 my @tags = sort keys %{$self->{'_tags'} || {}};
  0         0  
503 0         0 return @tags;
504             }
505              
506              
507             =head2 get_tag_values
508              
509             Title : get_tag_values
510             Usage : my @values = $tree->get_tag_values($tag)
511             Function: Gets the values for given tag ($tag)
512             Returns : Array of values or empty list if tag does not exist
513             Args : $tag - tag name
514              
515             =cut
516              
517             sub get_tag_values {
518 2     2 1 406 my ($self, $tag) = @_;
519 1 50       5 return wantarray ? @{$self->{'_tags'}->{$tag} || []} :
520 2 50       5 (@{$self->{'_tags'}->{$tag} || []})[0];
  1 100       7  
521             }
522              
523              
524             =head2 has_tag
525              
526             Title : has_tag
527             Usage : $tree->has_tag($tag)
528             Function: Boolean test if tag exists in the Tree
529             Returns : Boolean
530             Args : $tag - tagname
531              
532             =cut
533              
534             sub has_tag {
535 4     4 1 8 my ($self, $tag) = @_;
536 4         25 return exists $self->{'_tags'}->{$tag};
537             }
538              
539              
540             # safe tree clone that doesn't seg fault
541              
542             =head2 clone
543              
544             Title : clone
545             Alias : _clone
546             Usage : $tree_copy = $tree->clone();
547             $subtree_copy = $tree->clone($internal_node);
548             Function: Safe tree clone that doesn't segfault
549             Returns : Bio::Tree::Tree object
550             Args : [optional] $start_node, Bio::Tree::Node object
551              
552             =cut
553              
554             sub clone {
555 0     0 1 0 my ($self, $parent, $parent_clone) = @_;
556 0   0     0 $parent ||= $self->get_root_node;
557 0   0     0 $parent_clone ||= $self->_clone_node($parent);
558              
559 0         0 foreach my $node ($parent->each_Descendent()) {
560 0         0 my $child = $self->_clone_node($node);
561 0         0 $child->ancestor($parent_clone);
562 0         0 $self->_clone($node, $child);
563             }
564 0 0       0 $parent->ancestor && return;
565              
566 0         0 my $tree = $self->new(-root => $parent_clone);
567 0         0 return $tree;
568             }
569              
570              
571             # -- private internal methods --
572              
573             sub cleanup_tree {
574 952     952 0 946 my $self = shift;
575 952 100       2439 unless( $self->nodelete ) {
576 950         3065 for my $node ($self->get_nodes(-order => 'b', -sortby => 'none')) {
577 10299         12640 $node->node_cleanup;
578             }
579             }
580 952         2247 $self->{'_rootnode'} = undef;
581             }
582              
583             1;