sync w/ main trunk
[bioperl-live.git] / Bio / Tree / NodeI.pm
blobf0362cbbcdc2171a092c458bca08a196bf825ef0
1 # $Id$
3 # BioPerl module for Bio::Tree::NodeI
5 # Please direct questions and support issues to <bioperl-l@bioperl.org>
7 # Cared for by Jason Stajich <jason@bioperl.org>
9 # Copyright Jason Stajich
11 # You may distribute this module under the same terms as perl itself
13 # POD documentation - main docs before the code
15 =head1 NAME
17 Bio::Tree::NodeI - Interface describing a Tree Node
19 =head1 SYNOPSIS
21 # get a Tree::NodeI somehow
22 # like from a TreeIO
23 use Bio::TreeIO;
24 # read in a clustalw NJ in phylip/newick format
25 my $treeio = Bio::TreeIO->new(-format => 'newick', -file => 'file.dnd');
27 my $tree = $treeio->next_tree; # we'll assume it worked for demo purposes
28 # you might want to test that it was defined
30 my $rootnode = $tree->get_root_node;
32 # process just the next generation
33 foreach my $node ( $rootnode->each_Descendent() ) {
34 print "branch len is ", $node->branch_length, "\n";
37 # process all the children
38 my $example_leaf_node;
39 foreach my $node ( $rootnode->get_all_Descendents() ) {
40 if( $node->is_Leaf ) {
41 print "node is a leaf ... ";
42 # for example use below
43 $example_leaf_node = $node unless defined $example_leaf_node;
45 print "branch len is ", $node->branch_length, "\n";
48 # The ancestor() method points to the parent of a node
49 # A node can only have one parent
51 my $parent = $example_leaf_node->ancestor;
53 # parent won't likely have an description because it is an internal node
54 # but child will because it is a leaf
56 print "Parent id: ", $parent->id," child id: ",
57 $example_leaf_node->id, "\n";
60 =head1 DESCRIPTION
62 A NodeI is capable of the basic structure of building a tree and
63 storing the branch length between nodes. The branch length is the
64 length of the branch between the node and its ancestor, thus a root
65 node in a Tree will not typically have a valid branch length.
67 Various implementations of NodeI may extend the basic functions and
68 allow storing of other information (like attatching a species object
69 or full sequences used to build a tree or alternative sequences). If
70 you don't know how to extend a Bioperl object please ask, happy to
71 help, we would also greatly appreciate contributions with improvements
72 or extensions of the objects back to the Bioperl code base so that
73 others don't have to reinvent your ideas.
76 =head1 FEEDBACK
78 =head2 Mailing Lists
80 User feedback is an integral part of the evolution of this and other
81 Bioperl modules. Send your comments and suggestions preferably to
82 the Bioperl mailing list. Your participation is much appreciated.
84 bioperl-l@bioperl.org - General discussion
85 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
87 =head2 Support
89 Please direct usage questions or support issues to the mailing list:
91 L<bioperl-l@bioperl.org>
93 rather than to the module maintainer directly. Many experienced and
94 reponsive experts will be able look at the problem and quickly
95 address it. Please include a thorough description of the problem
96 with code and data examples if at all possible.
98 =head2 Reporting Bugs
100 Report bugs to the Bioperl bug tracking system to help us keep track
101 of the bugs and their resolution. Bug reports can be submitted via
102 the web:
104 http://bugzilla.open-bio.org/
106 =head1 AUTHOR - Jason Stajich
108 Email jason@bioperl.org
110 =head1 CONTRIBUTORS
112 Aaron Mackey amackey@virginia.edu
114 =head1 APPENDIX
116 The rest of the documentation details each of the object methods.
117 Internal methods are usually preceded with a _
119 =cut
121 # Let the code begin...
123 package Bio::Tree::NodeI;
124 use strict;
125 no warnings 'recursion';
127 use base qw(Bio::Root::RootI);
129 =head2 add_Descendent
131 Title : add_Descendent
132 Usage : $node->add_Descendent($node);
133 Function: Adds a descendent to a node
134 Returns : number of current descendents for this node
135 Args : Bio::Node::NodeI
138 =cut
140 sub add_Descendent{
141 my ($self,@args) = @_;
143 $self->throw_not_implemented();
147 =head2 each_Descendent
149 Title : each_Descendent
150 Usage : my @nodes = $node->each_Descendent;
151 Function: all the descendents for this Node (but not their descendents
152 i.e. not a recursive fetchall)
153 Returns : Array of Bio::Tree::NodeI objects
154 Args : none
156 =cut
158 sub each_Descendent{
159 my ($self) = @_;
160 $self->throw_not_implemented();
163 =head2 Decorated Interface methods
165 =cut
167 =head2 get_all_Descendents
169 Title : get_all_Descendents($sortby)
170 Usage : my @nodes = $node->get_all_Descendents;
171 Function: Recursively fetch all the nodes and their descendents
172 *NOTE* This is different from each_Descendent
173 Returns : Array or Bio::Tree::NodeI objects
174 Args : $sortby [optional] "height", "creation", "alpha", "revalpha",
175 or a coderef to be used to sort the order of children nodes.
177 =cut
179 sub get_all_Descendents{
180 my ($self, $sortby) = @_;
181 $sortby ||= 'none';
182 my @nodes;
183 foreach my $node ( $self->each_Descendent($sortby) ) {
184 push @nodes, ($node,$node->get_all_Descendents($sortby));
186 return @nodes;
189 *get_Descendents = \&get_all_Descendents;
191 =head2 is_Leaf
193 Title : is_Leaf
194 Usage : if( $node->is_Leaf )
195 Function: Get Leaf status
196 Returns : boolean
197 Args : none
199 =cut
201 sub is_Leaf{
202 my ($self) = @_;
203 $self->throw_not_implemented();
206 =head2 descendent_count
208 Title : descendent_count
209 Usage : my $count = $node->descendent_count;
210 Function: Counts the number of descendents a node has
211 (and all of their subnodes)
212 Returns : integer
213 Args : none
215 =cut
217 sub descendent_count{
218 my ($self) = @_;
219 my $count = 0;
221 foreach my $node ( $self->each_Descendent ) {
222 $count += 1;
223 $node->can('descendent_count') ? $count += $node->descendent_count : next;
225 return $count;
228 =head2 to_string
230 Title : to_string
231 Usage : my $str = $node->to_string()
232 Function: For debugging, provide a node as a string
233 Returns : string
234 Args : none
237 =cut
239 sub to_string{
240 my ($self) = @_;
241 return join('',defined $self->id_output ? $self->id_output : '',
242 defined $self->branch_length ? ':' . $self->branch_length
243 : ' ')
246 =head2 height
248 Title : height
249 Usage : my $len = $node->height
250 Function: Returns the height of the tree starting at this
251 node. Height is the maximum branchlength to get to the tip.
252 Returns : The longest length (weighting branches with branch_length) to a leaf
253 Args : none
255 =cut
257 sub height{
258 my ($self) = @_;
260 return 0 if( $self->is_Leaf );
262 my $max = 0;
263 foreach my $subnode ( $self->each_Descendent ) {
264 my $s = $subnode->height + $subnode->branch_length;;
265 if( $s > $max ) { $max = $s; }
267 return $max;
270 =head2 depth
272 Title : depth
273 Usage : my $len = $node->depth
274 Function: Returns the depth of the tree starting at this
275 node. Depth is the distance from this node to the root.
276 Returns : The branch length to the root.
277 Args : none
279 =cut
281 sub depth{
282 my ($self) = @_;
284 my $depth = 0;
285 my $node = $self;
286 while( defined $node->ancestor ) {
287 $depth += $node->branch_length;
288 $node = $node->ancestor;
290 return $depth;
293 =head2 Get/Set methods
295 =cut
297 =head2 branch_length
299 Title : branch_length
300 Usage : $obj->branch_length()
301 Function: Get/Set the branch length
302 Returns : value of branch_length
303 Args : newvalue (optional)
306 =cut
308 sub branch_length{
309 my ($self)= @_;
310 $self->throw_not_implemented();
313 =head2 id
315 Title : id
316 Usage : $obj->id($newval)
317 Function: The human readable identifier for the node
318 Returns : value of human readable id
319 Args : newvalue (optional)
322 =cut
324 sub id{
325 my ($self)= @_;
326 $self->throw_not_implemented();
329 =head2 internal_id
331 Title : internal_id
332 Usage : my $internalid = $node->internal_id
333 Function: Returns the internal unique id for this Node
334 Returns : unique id
335 Args : none
337 =cut
339 sub internal_id{
340 my ($self) = @_;
341 $self->throw_not_implemented();
344 =head2 description
346 Title : description
347 Usage : $obj->description($newval)
348 Function: Get/Set the description string
349 Returns : value of description
350 Args : newvalue (optional)
353 =cut
355 sub description{
356 my ($self) = @_;
357 $self->throw_not_implemented();
360 =head2 bootstrap
362 Title : bootstrap
363 Usage : $obj->bootstrap($newval)
364 Function: Get/Set the bootstrap value
365 Returns : value of bootstrap
366 Args : newvalue (optional)
369 =cut
371 sub bootstrap{
372 my ($self) = @_;
373 $self->throw_not_implemented();
376 =head2 ancestor
378 Title : ancestor
379 Usage : my $node = $node->ancestor;
380 Function: Get/Set the ancestor node pointer for a Node
381 Returns : Null if this is top level node
382 Args : none
384 =cut
387 sub ancestor{
388 my ($self,@args) = @_;
389 $self->throw_not_implemented();
392 =head2 invalidate_height
394 Title : invalidate_height
395 Usage : private helper method
396 Function: Invalidate our cached value of the node height in the tree
397 Returns : nothing
398 Args : none
400 =cut
402 sub invalidate_height {
403 shift->throw_not_implemented();
406 =head2 Methods for associating Tag/Values with a Node
408 These methods associate tag/value pairs with a Node
410 =head2 set_tag_value
412 Title : set_tag_value
413 Usage : $node->set_tag_value($tag,$value)
414 $node->set_tag_value($tag,@values)
415 Function: Sets a tag value(s) to a node. Replaces old values.
416 Returns : number of values stored for this tag
417 Args : $tag - tag name
418 $value - value to store for the tag
420 =cut
422 sub set_tag_value{
423 shift->throw_not_implemented();
426 =head2 add_tag_value
428 Title : add_tag_value
429 Usage : $node->add_tag_value($tag,$value)
430 Function: Adds a tag value to a node
431 Returns : number of values stored for this tag
432 Args : $tag - tag name
433 $value - value to store for the tag
436 =cut
438 sub add_tag_value{
439 shift->throw_not_implemented();
442 =head2 remove_tag
444 Title : remove_tag
445 Usage : $node->remove_tag($tag)
446 Function: Remove the tag and all values for this tag
447 Returns : boolean representing success (0 if tag does not exist)
448 Args : $tag - tagname to remove
451 =cut
453 sub remove_tag {
454 shift->throw_not_implemented();
457 =head2 remove_all_tags
459 Title : remove_all_tags
460 Usage : $node->remove_all_tags()
461 Function: Removes all tags
462 Returns : None
463 Args : None
466 =cut
468 sub remove_all_tags{
469 shift->throw_not_implemented();
472 =head2 get_all_tags
474 Title : get_all_tags
475 Usage : my @tags = $node->get_all_tags()
476 Function: Gets all the tag names for this Node
477 Returns : Array of tagnames
478 Args : None
481 =cut
483 sub get_all_tags {
484 shift->throw_not_implemented();
487 =head2 get_tag_values
489 Title : get_tag_values
490 Usage : my @values = $node->get_tag_values($tag)
491 Function: Gets the values for given tag ($tag)
492 Returns : Array of values or empty list if tag does not exist
493 Args : $tag - tag name
496 =cut
498 sub get_tag_values{
499 shift->throw_not_implemented();
502 =head2 has_tag
504 Title : has_tag
505 Usage : $node->has_tag($tag)
506 Function: Boolean test if tag exists in the Node
507 Returns : Boolean
508 Args : $tag - tagname
511 =cut
513 sub has_tag{
514 shift->throw_not_implemented();
518 =head2 Helper Functions
520 =cut
522 =head2 id_output
524 Title : id_output
525 Usage : my $id = $node->id_output;
526 Function: Return an id suitable for output in format like newick
527 so that if it contains spaces or ():; characters it is properly
528 quoted
529 Returns : $id string if $node->id has a value
530 Args : none
533 =cut
535 sub id_output{
536 my $node = shift;
537 my $id = $node->id;
538 return unless( defined $id && length($id ) );
539 # single quotes must become double quotes
540 # $id =~ s/'/''/g;
541 if( $id =~ /[\(\);:,\s]/ ) {
542 $id = '"'.$id.'"';
544 return $id;