File Coverage

Bio/Tree/Node.pm
Criterion Covered Total %
statement 174 240 72.5
branch 75 122 61.4
condition 42 79 53.1
subroutine 28 29 96.5
pod 22 23 95.6
total 341 493 69.1


line stmt bran cond sub pod time code
1             #
2             # BioPerl module for Bio::Tree::Node
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             =head1 NAME
15              
16             Bio::Tree::Node - A Simple Tree Node
17              
18             =head1 SYNOPSIS
19              
20             use Bio::Tree::Node;
21             my $nodeA = Bio::Tree::Node->new();
22             my $nodeL = Bio::Tree::Node->new();
23             my $nodeR = Bio::Tree::Node->new();
24              
25             my $node = Bio::Tree::Node->new();
26             $node->add_Descendent($nodeL);
27             $node->add_Descendent($nodeR);
28              
29             print "node is not a leaf \n" if( $node->is_leaf);
30              
31             =head1 DESCRIPTION
32              
33             Makes a Tree Node suitable for building a Tree.
34              
35             =head1 FEEDBACK
36              
37             =head2 Mailing Lists
38              
39             User feedback is an integral part of the evolution of this and other
40             Bioperl modules. Send your comments and suggestions preferably to
41             the Bioperl mailing list. Your participation is much appreciated.
42              
43             bioperl-l@bioperl.org - General discussion
44             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
45              
46             =head2 Support
47              
48             Please direct usage questions or support issues to the mailing list:
49              
50             I
51              
52             rather than to the module maintainer directly. Many experienced and
53             reponsive experts will be able look at the problem and quickly
54             address it. Please include a thorough description of the problem
55             with code and data examples if at all possible.
56              
57             =head2 Reporting Bugs
58              
59             Report bugs to the Bioperl bug tracking system to help us keep track
60             of the bugs and their resolution. Bug reports can be submitted via
61             the web:
62              
63             https://github.com/bioperl/bioperl-live/issues
64              
65             =head1 AUTHOR - Jason Stajich
66              
67             Email jason-at-bioperl-dot-org
68              
69             =head1 CONTRIBUTORS
70              
71             Aaron Mackey, amackey-at-virginia-dot-edu
72             Sendu Bala, bix@sendu.me.uk
73              
74             =head1 APPENDIX
75              
76             The rest of the documentation details each of the object methods.
77             Internal methods are usually preceded with a _
78              
79             =cut
80              
81              
82             # Let the code begin...
83              
84             package Bio::Tree::Node;
85 67     67   690 use vars qw($CREATIONORDER);
  67         76  
  67         2495  
86 67     67   223 use strict;
  67         77  
  67         1224  
87              
88 67     67   191 use base qw(Bio::Root::Root Bio::Tree::NodeI);
  67         413  
  67         22765  
89              
90             BEGIN {
91 67     67   126687 $CREATIONORDER = 1;
92             }
93              
94             =head2 new
95              
96             Title : new
97             Usage : my $obj = Bio::Tree::Node->new();
98             Function: Builds a new Bio::Tree::Node object
99             Returns : Bio::Tree::Node
100             Args : -descendents => arrayref of descendents (they will be
101             updated s.t. their ancestor point is this
102             node)
103             -branch_length => branch length [integer] (optional)
104             -bootstrap => value bootstrap value (string)
105             -description => description of node
106             -id => human readable id for node
107              
108             =cut
109              
110             sub new {
111 17402     17402 1 28794 my($class,@args) = @_;
112              
113 17402         32662 my $self = $class->SUPER::new(@args);
114 17402         52733 my ($children, $branchlen,$id,
115             $bootstrap, $desc,$d) = $self->_rearrange([qw(
116             DESCENDENTS
117             BRANCH_LENGTH
118             ID
119             BOOTSTRAP
120             DESC
121             DESCRIPTION
122             )],
123             @args);
124 17402         50090 $self->_register_for_cleanup(\&node_cleanup);
125 17402         22072 $self->{'_desc'} = {}; # for descendents
126 17402 50 33     62757 if( defined $d && defined $desc ) {
    50 33        
127 0         0 $self->warn("can only accept -desc or -description, not both, accepting -description");
128 0         0 $desc = $d;
129             } elsif( defined $d && ! defined $desc ) {
130 0         0 $desc = $d;
131             }
132 17402 100       23439 defined $desc && $self->description($desc);
133 17402 100       22628 defined $bootstrap && $self->bootstrap($bootstrap);
134 17402 100       30971 defined $id && $self->id($id);
135 17402 100       29884 defined $branchlen && $self->branch_length($branchlen);
136 17402 100       21908 if( defined $children ) {
137 2072 50       8318 if( ref($children) !~ /ARRAY/i ) {
138 0         0 $self->throw("Must specify a valid ARRAY reference to initialize a Node's Descendents");
139             }
140 2072         3066 foreach my $c ( @$children ) {
141 4145         6615 $self->add_Descendent($c);
142             }
143             }
144 17402         29345 $self->_creation_id($CREATIONORDER++);
145 17402         38023 return $self;
146             }
147              
148             =head2 create_node_on_branch
149              
150             Title : create_node_on_branch
151             Usage : $node->create_node_on_branch($at_length)
152             Function: Create a node on the ancestral branch of the calling
153             object.
154             Example :
155             Returns : the created node
156             Args : -POSITION=>$absolute_branch_length_from_caller (default)
157             -FRACTION=>$fraction_of_branch_length_from_caller
158             -ANNOT=>{ -id => "the id", -desc => "the description" }
159             -FORCE, set to allow nodes with zero branch lengths
160              
161             =cut
162              
163             sub create_node_on_branch{
164 19     19 1 51 my ($self,@args) = @_;
165 19         71 my ($pos, $frac, $annot, $force) = $self->_rearrange([qw(POSITION FRACTION ANNOT FORCE)], @args);
166 19         31 my ($newpos);
167 19         35 my $blen = $self->branch_length;
168             # arg checks
169 19   100     45 $force||=0;
170 19   100     61 $annot||={};
171              
172 19 50       31 unless ($self->ancestor) {
173 0         0 $self->throw("Refusing to create nodes above the root--exiting");
174             }
175 19 50       38 unless ($blen) {
176 0 0       0 $self->throw("Calling node's branch length is zero") unless $force;
177             }
178 19 50 66     101 unless ((defined $pos && !defined $frac)||(defined $frac && !defined $pos)) {
      33        
      66        
179 0         0 $self->throw("Either position or fraction must be specified, but not both");
180             }
181 19 100       51 if (defined $frac) {
    50          
182 2 50 33     17 $self->throw("FRACTION arg must be in the range [0,1]") unless ( (0 <= $frac) && ($frac <= 1) );
183 2         5 $newpos = $frac*$blen;
184             }
185             elsif (defined $pos) {
186 17 50 33     106 $self->throw("POSITION arg must be in the range [0,$blen]") unless ( (0 <= $pos) && ($pos <= $blen) );
187 17         22 $newpos = $pos;
188             }
189             else {
190 0         0 $self->throw("How did I get here?");
191             }
192 19 50 66     79 $self->throw("Calling node's branch length will be zero (set -FORCE to force)--exiting") unless ($newpos > 0) || $force;
193 19 50 33     47 $self->throw("Created nodes branch length would be zero (set -FORCE to force)--exiting") unless ($newpos < $blen) || $force;
194              
195             #guts
196 19         37 $annot->{'-branch_length'} = $blen-$newpos;
197 19         72 my $node = Bio::Tree::Node->new(%$annot);
198 19         33 my $anc = $self->ancestor;
199             # null anc check is above
200 19         35 $node->add_Descendent($self);
201 19         32 $anc->add_Descendent($node);
202 19         29 $anc->remove_Descendent($self);
203 19         30 $self->branch_length($newpos);
204 19         51 return $node;
205             }
206              
207             =head2 add_Descendent
208              
209             Title : add_Descendent
210             Usage : $node->add_Descendent($node);
211             Function: Adds a descendent to a node
212             Returns : number of current descendents for this node
213             Args : Bio::Node::NodeI
214             boolean flag, true if you want to ignore the fact that you are
215             adding a second node with the same unique id (typically memory
216             location reference in this implementation). default is false and
217             will throw an error if you try and overwrite an existing node.
218              
219             =cut
220              
221             sub add_Descendent{
222 11318     11318 1 10265 my ($self,$node,$ignoreoverwrite) = @_;
223 11318 50       15477 return -1 if( ! defined $node );
224            
225 11318 50 33     68934 if( ! ref($node) ||
      33        
226             ref($node) =~ /HASH/ ||
227             ! $node->isa('Bio::Tree::NodeI') ) {
228 0         0 $self->throw("Trying to add a Descendent who is not a Bio::Tree::NodeI");
229 0         0 return -1;
230             }
231            
232 11318         12006 $self->{_adding_descendent} = 1;
233             # avoid infinite recurse
234 11318 100       22053 $node->ancestor($self) unless $node->{_setting_ancestor};
235 11318         9466 $self->{_adding_descendent} = 0;
236            
237 11318 50 33     16398 if( $self->{'_desc'}->{$node->internal_id} && ! $ignoreoverwrite ) {
238 0         0 $self->throw("Going to overwrite a node which is $node that is already stored here, set the ignore overwrite flag (parameter 2) to true to ignore this in the future");
239             }
240 11318         16836 $self->{'_desc'}->{$node->internal_id} = $node; # is this safely unique - we've tested before at any rate??
241            
242 11318         15563 $self->invalidate_height();
243            
244 11318         8997 return scalar keys %{$self->{'_desc'}};
  11318         24235  
245             }
246              
247             =head2 each_Descendent
248              
249             Title : each_Descendent($sortby)
250             Usage : my @nodes = $node->each_Descendent;
251             Function: all the descendents for this Node (but not their descendents
252             i.e. not a recursive fetchall)
253             Returns : Array of Bio::Tree::NodeI objects
254             Args : $sortby [optional] "height", "creation", "alpha", "revalpha",
255             or coderef to be used to sort the order of children nodes.
256              
257             =cut
258              
259             sub each_Descendent{
260 35113     35113 1 26390 my ($self, $sortby) = @_;
261              
262             # order can be based on branch length (and sub branchlength)
263 35113   100     47119 $sortby ||= 'none';
264 35113 50       73924 if (ref $sortby eq 'CODE') {
    50          
    50          
    50          
265 0         0 my @values = sort { $sortby->($a,$b) } values %{$self->{'_desc'}};
  0         0  
  0         0  
266 0         0 return @values;
267             } elsif ($sortby eq 'height') {
268 0         0 return map { $_->[0] }
269 0 0       0 sort { $a->[1] <=> $b->[1] ||
270             $a->[2] <=> $b->[2] }
271 0         0 map { [$_, $_->height, $_->internal_id ] }
272 0         0 values %{$self->{'_desc'}};
  0         0  
273             } elsif( $sortby eq 'alpha' ) {
274 0         0 my @set;
275 0         0 for my $v ( values %{$self->{'_desc'}} ) {
  0         0  
276 0 0       0 unless( $v->is_Leaf ) {
277 0         0 my @lst = ( sort { $a cmp $b } map { $_->id }
  0         0  
278 0         0 grep { $_->is_Leaf }
  0         0  
279             $v->get_all_Descendents($sortby));
280 0         0 push @set, [$v, $lst[0], $v->internal_id];
281             } else {
282 0         0 push @set, [$v, $v->id, $v->internal_id];
283             }
284             }
285 0         0 return map { $_->[0] }
286 0 0       0 sort {$a->[1] cmp $b->[1] || $a->[2] <=> $b->[2] } @set;
  0         0  
287             } elsif( $sortby eq 'revalpha' ) {
288 0         0 my @set;
289 0         0 for my $v ( values %{$self->{'_desc'}} ) {
  0         0  
290 0 0 0     0 if( ! defined $v->id &&
291             ! $v->is_Leaf ) {
292 0         0 my ($l) = ( sort { $b cmp $a } map { $_->id }
  0         0  
293 0         0 grep { $_->is_Leaf }
  0         0  
294             $v->get_all_Descendents($sortby));
295 0         0 push @set, [$v, $l, $v->internal_id];
296             } else {
297 0         0 push @set, [$v, $v->id, $v->internal_id];
298             }
299             }
300 0         0 return map { $_->[0] }
301 0 0       0 sort {$b->[1] cmp $a->[1] || $b->[2] <=> $a->[2] } @set;
  0         0  
302             } else { # creation
303 31596         40651 return map { $_->[0] }
304 15372         19371 sort { $a->[1] <=> $b->[1] }
305 31596         35902 map { [$_, $_->internal_id ] }
306 31596         33030 grep {defined $_}
307 35113         22558 values %{$self->{'_desc'}};
  35113         64532  
308             }
309             }
310              
311             =head2 remove_Descendent
312              
313             Title : remove_Descendent
314             Usage : $node->remove_Descendent($node_foo);
315             Function: Removes a specific node from being a Descendent of this node
316             Returns : nothing
317             Args : An array of Bio::Node::NodeI objects which have been previously
318             passed to the add_Descendent call of this object.
319              
320             =cut
321              
322             sub remove_Descendent{
323 224     224 1 234 my ($self,@nodes) = @_;
324 224         159 my $c= 0;
325 224         227 foreach my $n ( @nodes ) {
326 224 100       258 if( $self->{'_desc'}->{$n->internal_id} ) {
327 188         212 $self->{_removing_descendent} = 1;
328 188         226 $n->ancestor(undef);
329 188         140 $self->{_removing_descendent} = 0;
330             # should be redundant
331 188         254 $self->{'_desc'}->{$n->internal_id}->ancestor(undef);
332 188         237 delete $self->{'_desc'}->{$n->internal_id};
333 188         236 $c++;
334             } else {
335 36 50       63 if( $self->verbose ) {
336 0         0 $self->debug(sprintf("no node %s (%s) listed as a descendent in this node %s (%s)\n",$n->id, $n,$self->id,$self));
337 0         0 $self->debug("Descendents are " . join(',', keys %{$self->{'_desc'}})."\n");
  0         0  
338             }
339             }
340             }
341 224         218 $c;
342             }
343              
344             =head2 remove_all_Descendents
345              
346             Title : remove_all_Descendents
347             Usage : $node->remove_All_Descendents()
348             Function: Cleanup the node's reference to descendents and reset
349             their ancestor pointers to undef, if you don't have a reference
350             to these objects after this call they will be cleaned up - so
351             a get_nodes from the Tree object would be a safe thing to do first
352             Returns : nothing
353             Args : none
354              
355             =cut
356              
357             sub remove_all_Descendents{
358 23513     23513 1 16378 my ($self) = @_;
359             # This won't cleanup the nodes themselves if you also have
360             # a copy/pointer of them (I think)...
361            
362             # That's true. But that's not a bug; if we retain a reference to them it's
363             # very possible we want to keep them. The only way to truly destroy them is
364             # to call DESTROY on the instance.
365            
366 23513         15167 while( my ($node,$val) = each %{ $self->{'_desc'} } ) {
  35007         63236  
367 11494         12798 delete $self->{'_desc'}->{$node}
368             }
369 23513         20333 $self->{'_desc'} = {};
370 23513         22369 1;
371             }
372              
373             =head2 get_all_Descendents
374              
375             Title : get_all_Descendents
376             Usage : my @nodes = $node->get_all_Descendents;
377             Function: Recursively fetch all the nodes and their descendents
378             *NOTE* This is different from each_Descendent
379             Returns : Array or Bio::Tree::NodeI objects
380             Args : none
381              
382             =cut
383              
384             # get_all_Descendents implemented in the interface
385              
386             =head2 ancestor
387              
388             Title : ancestor
389             Usage : $obj->ancestor($newval)
390             Function: Set the Ancestor
391             Returns : ancestral node
392             Args : newvalue (optional)
393              
394             =cut
395              
396             sub ancestor {
397 59355     59355 1 39992 my $self = shift;
398 59355 100       72494 if (@_) {
399 11754         8903 my $new_ancestor = shift;
400            
401             # we can set ancestor to undef
402 11754 100       16055 if ($new_ancestor) {
403 11329 50       23137 $self->throw("This is [$new_ancestor], not a Bio::Tree::NodeI")
404             unless $new_ancestor->isa('Bio::Tree::NodeI');
405             }
406            
407 11754   100     27970 my $old_ancestor = $self->{'_ancestor'} || '';
408 11754 100 100     23237 if (!$old_ancestor ||
      33        
      66        
409             ($old_ancestor && ( !$new_ancestor ||
410             $new_ancestor ne $old_ancestor)) ) {
411 11743 100 100     18992 if( $old_ancestor && ! $old_ancestor->{_removing_descendent}) {
412 144         195 $old_ancestor->remove_Descendent($self);
413             }
414 11743 100 100     34437 if ($new_ancestor &&
415             ! $new_ancestor->{_adding_descendent} ) { # avoid infinite recurse
416 2155         2489 $self->{_setting_ancestor} = 1;
417 2155         3520 $new_ancestor->add_Descendent($self, 1);
418 2155         2773 $self->{_setting_ancestor} = 0;
419             }
420             }
421 11754         21208 $self->{'_ancestor'} = $new_ancestor;
422             }
423            
424 59355         72291 return $self->{'_ancestor'};
425             }
426              
427             =head2 branch_length
428              
429             Title : branch_length
430             Usage : $obj->branch_length()
431             Function: Get/Set the branch length
432             Returns : value of branch_length
433             Args : newvalue (optional)
434              
435             =cut
436              
437             sub branch_length{
438 59570     59570 1 40194 my $self = shift;
439 59570 100       69756 if( @_ ) {
440 8795         6720 my $bl = shift;
441 8795 50 66     50873 if( defined $bl &&
442             $bl =~ s/\[(\d+)\]// ) {
443 0         0 $self->bootstrap($1);
444             }
445 8795         10308 $self->{'_branch_length'} = $bl;
446 8795         13429 $self->invalidate_height();
447             }
448 59570         112337 return $self->{'_branch_length'};
449             }
450              
451             =head2 bootstrap
452              
453             Title : bootstrap
454             Usage : $obj->bootstrap($newval)
455             Function: Get/Set the bootstrap value
456             Returns : value of bootstrap
457             Args : newvalue (optional)
458              
459             =cut
460              
461             sub bootstrap {
462 2721     2721   2171 my $self = shift;
463 2721 100       4137 if( @_ ) {
464 228 100       290 if( $self->has_tag('B') ) {
465 135         188 $self->remove_tag('B');
466             }
467 228         311 $self->add_tag_value('B',shift);
468             }
469 2721         5112 return ($self->get_tag_values('B'))[0];
470             }
471              
472             =head2 description
473              
474             Title : description
475             Usage : $obj->description($newval)
476             Function: Get/Set the description string
477             Returns : value of description
478             Args : newvalue (optional)
479              
480             =cut
481              
482             sub description {
483 2     2 1 2 my $self = shift;
484 2 100       7 $self->{'_description'} = shift @_ if @_;
485 2         3 return $self->{'_description'};
486             }
487              
488             =head2 id
489              
490             Title : id
491             Usage : $obj->id($newval)
492             Function: The human readable identifier for the node
493             Returns : value of human readable id
494             Args : newvalue (optional)
495              
496             "A name can be any string of printable characters except blanks,
497             colons, semicolons, parentheses, and square brackets. Because you may
498             want to include a blank in a name, it is assumed that an underscore
499             character ("_") stands for a blank; any of these in a name will be
500             converted to a blank when it is read in."
501              
502             from L
503              
504             Also note that these objects now support spaces, ();: because we can
505             automatically quote the strings if they contain these characters. The
506             L method does this for you so use the id() method to get
507             the raw string while L to get the pre-escaped string.
508              
509             =cut
510              
511             sub id {
512 96618     96618 1 78968 my ($self, $value) = @_;
513 96618 100       115897 if (defined $value) {
514             #$self->warn("Illegal characters ();: and space in the id [$value], converting to _ ")
515             # if $value =~ /\(\);:/ and $self->verbose >= 0;
516             #$value =~ s/[\(\);:\s]/_/g;
517 16941         20601 $self->{'_id'} = $value;
518             }
519 96618         163719 return $self->{'_id'};
520             }
521              
522             =head2 Helper Functions
523              
524             =cut
525              
526             =head2 id_output
527              
528             Title : id_output
529             Usage : my $id = $node->id_output;
530             Function: Return an id suitable for output in format like newick
531             so that if it contains spaces or ():; characters it is properly
532             quoted
533             Returns : $id string if $node->id has a value
534             Args : none
535              
536             =cut
537              
538             # implemented in NodeI interface
539              
540             =head2 internal_id
541              
542             Title : internal_id
543             Usage : my $internalid = $node->internal_id
544             Function: Returns the internal unique id for this Node
545             (a monotonically increasing number for this in-memory implementation
546             but could be a database determined unique id in other
547             implementations)
548             Returns : unique id
549             Args : none
550              
551             =cut
552              
553             sub internal_id {
554 60000     60000 1 60938 return $_[0]->_creation_id;
555             }
556              
557             =head2 _creation_id
558              
559             Title : _creation_id
560             Usage : $obj->_creation_id($newval)
561             Function: a private method signifying the internal creation order
562             Returns : value of _creation_id
563             Args : newvalue (optional)
564              
565             =cut
566              
567             sub _creation_id {
568 82925     82925   61268 my $self = shift @_;
569 82925 100       109720 $self->{'_creation_id'} = shift @_ if( @_);
570 82925   50     193498 return $self->{'_creation_id'} || 0;
571             }
572              
573             =head2 Bio::Node::NodeI decorated interface implemented
574              
575             The following methods are implemented by L decorated
576             interface.
577              
578             =head2 is_Leaf
579              
580             Title : is_Leaf
581             Usage : if( $node->is_Leaf )
582             Function: Get Leaf status
583             Returns : boolean
584             Args : none
585              
586             =cut
587              
588             sub is_Leaf {
589 10295     10295 1 7276 my ($self) = @_;
590             my $isleaf = ! (defined $self->{'_desc'} &&
591 10295   66     13950 (keys %{$self->{'_desc'}} > 0) );
592 10295         30387 return $isleaf;
593             }
594              
595             =head2 height
596              
597             Title : height
598             Usage : my $len = $node->height
599             Function: Returns the height of the tree starting at this
600             node. Height is the maximum branchlength to get to the tip.
601             Returns : The longest length (weighting branches with branch_length) to a leaf
602             Args : none
603              
604             =cut
605              
606             sub height {
607 1     1 1 6 my ($self) = @_;
608 1 50       4 return $self->{'_height'} if( defined $self->{'_height'} );
609            
610 1 50       2 return 0 if( $self->is_Leaf );
611 0         0 my $max = 0;
612 0         0 foreach my $subnode ( $self->each_Descendent ) {
613 0         0 my $bl = $subnode->branch_length;
614 0 0 0     0 $bl = 1 unless (defined $bl && $bl =~ /^\-?\d+(\.\d+)?$/);
615 0         0 my $s = $subnode->height + $bl;
616 0 0       0 if( $s > $max ) { $max = $s; }
  0         0  
617             }
618 0         0 return ($self->{'_height'} = $max);
619             }
620              
621             =head2 invalidate_height
622              
623             Title : invalidate_height
624             Usage : private helper method
625             Function: Invalidate our cached value of the node height in the tree
626             Returns : nothing
627             Args : none
628              
629             =cut
630              
631             sub invalidate_height {
632 30817     30817 1 23924 my ($self) = @_;
633            
634 30817         26912 $self->{'_height'} = undef;
635 30817 100       34497 if( defined $self->ancestor ) {
636 10704         11819 $self->ancestor->invalidate_height;
637             }
638             }
639              
640             =head2 set_tag_value
641              
642             Title : set_tag_value
643             Usage : $node->set_tag_value($tag,$value)
644             $node->set_tag_value($tag,@values)
645             Function: Sets a tag value(s) to a node. Replaces old values.
646             Returns : number of values stored for this tag
647             Args : $tag - tag name
648             $value - value to store for the tag
649              
650             =cut
651              
652             sub set_tag_value{
653 111     111 1 110 my ($self,$tag,@values) = @_;
654 111 50 33     225 if( ! defined $tag || ! scalar @values ) {
655 0         0 $self->warn("cannot call set_tag_value with an undefined value");
656             }
657 111         114 $self->remove_tag ($tag);
658 111         86 map { push @{$self->{'_tags'}->{$tag}}, $_ } @values;
  118         58  
  118         208  
659 111         72 return scalar @{$self->{'_tags'}->{$tag}};
  111         161  
660             }
661              
662              
663             =head2 add_tag_value
664              
665             Title : add_tag_value
666             Usage : $node->add_tag_value($tag,$value)
667             Function: Adds a tag value to a node
668             Returns : number of values stored for this tag
669             Args : $tag - tag name
670             $value - value to store for the tag
671              
672             =cut
673              
674             sub add_tag_value{
675 1841     1841 1 1551 my ($self,$tag,$value) = @_;
676 1841 50 33     3545 if( ! defined $tag || ! defined $value ) {
677 0 0       0 $self->warn("cannot call add_tag_value with an undefined value".($tag ? " ($tag)" : ''));
678 0         0 $self->warn($self->stack_trace_dump,"\n");
679             }
680 1841         1142 push @{$self->{'_tags'}->{$tag}}, $value;
  1841         3429  
681 1841         1198 return scalar @{$self->{'_tags'}->{$tag}};
  1841         4435  
682             }
683              
684             =head2 remove_tag
685              
686             Title : remove_tag
687             Usage : $node->remove_tag($tag)
688             Function: Remove the tag and all values for this tag
689             Returns : boolean representing success (0 if tag does not exist)
690             Args : $tag - tagname to remove
691              
692              
693             =cut
694              
695             sub remove_tag {
696 291     291 1 246 my ($self,$tag) = @_;
697 291 100       428 if( exists $self->{'_tags'}->{$tag} ) {
698 189         167 $self->{'_tags'}->{$tag} = undef;
699 189         237 delete $self->{'_tags'}->{$tag};
700 189         217 return 1;
701             }
702 102         97 return 0;
703             }
704              
705             =head2 remove_all_tags
706              
707             Title : remove_all_tags
708             Usage : $node->remove_all_tags()
709             Function: Removes all tags
710             Returns : None
711             Args : None
712              
713             =cut
714              
715             sub remove_all_tags{
716 1     1 1 2 my ($self) = @_;
717 1         2 $self->{'_tags'} = {};
718 1         3 return;
719             }
720              
721             =head2 get_all_tags
722              
723             Title : get_all_tags
724             Usage : my @tags = $node->get_all_tags()
725             Function: Gets all the tag names for this Node
726             Returns : Array of tagnames
727             Args : None
728              
729             =cut
730              
731             sub get_all_tags{
732 2988     2988 1 1968 my ($self) = @_;
733 2988 100       1773 my @tags = sort keys %{$self->{'_tags'} || {}};
  2988         8181  
734 2988         4268 return @tags;
735             }
736              
737             =head2 get_tag_values
738              
739             Title : get_tag_values
740             Usage : my @values = $node->get_tag_values($tag)
741             Function: Gets the values for given tag ($tag)
742             Returns : In array context returns an array of values
743             or an empty list if tag does not exist.
744             In scalar context returns the first value or undef.
745             Args : $tag - tag name
746              
747             =cut
748              
749             sub get_tag_values{
750 7561     7561 1 6476 my ($self,$tag) = @_;
751 6973 100       32329 return wantarray ? @{$self->{'_tags'}->{$tag} || []} :
752 7561 50       7633 (@{$self->{'_tags'}->{$tag} || []})[0];
  588 100       1450  
753             }
754              
755             =head2 has_tag
756              
757             Title : has_tag
758             Usage : $node->has_tag($tag)
759             Function: Boolean test if tag exists in the Node
760             Returns : Boolean
761             Args : $tag - tagname
762              
763             =cut
764              
765             sub has_tag {
766 677     677 1 560 my ($self,$tag) = @_;
767 677         1202 return exists $self->{'_tags'}->{$tag};
768             }
769              
770             sub node_cleanup {
771 23513     23513 0 15723 my $self = shift;
772 23513 50       27003 return unless defined $self;
773            
774             #*** below is wrong, cleanup doesn't actually occur. Will replace with:
775             # $self->remove_all_Descendents; once further fixes in place..
776             #if( defined $self->{'_desc'} &&
777             # ref($self->{'_desc'}) =~ /HASH/i ) {
778             # while( my ($nodeid,$node) = each %{ $self->{'_desc'} } ) {
779             # $node->ancestor(undef); # insure no circular references
780             # $node = undef;
781             # }
782             #}
783 23513         22569 $self->remove_all_Descendents;
784            
785             #$self->{'_desc'} = {};
786 23513         52658 1;
787             }
788              
789             =head2 reverse_edge
790              
791             Title : reverse_edge
792             Usage : $node->reverse_edge(child);
793             Function: makes child be a parent of node
794             Requires: child must be a direct descendent of node
795             Returns : 1 on success, 0 on failure
796             Args : Bio::Tree::NodeI that is in the tree
797              
798             =cut
799              
800             sub reverse_edge {
801 0     0 1   my ($self,$node) = @_;
802 0 0         if( $self->delete_edge($node) ) {
803 0           $node->add_Descendent($self);
804 0           return 1;
805             }
806 0           return 0;
807             }
808              
809             1;