File Coverage

blib/lib/Bio/NEXUS/Node.pm
Criterion Covered Total %
statement 344 494 69.6
branch 131 210 62.3
condition 52 79 65.8
subroutine 53 70 75.7
pod 46 46 100.0
total 626 899 69.6


line stmt bran cond sub pod time code
1             ######################################################
2             # Node.pm
3             ######################################################
4             # Author: Weigang Qiu, Eugene Melamud, Chengzhi Liang, Peter Yang, Thomas Hladish, Vivek Gopalan
5             # $Id: Node.pm,v 1.70 2009/08/13 20:35:55 astoltzfus Exp $
6              
7             #################### START POD DOCUMENTATION ##################
8              
9             =head1 NAME
10              
11             Bio::NEXUS::Node - Provides functions for manipulating nodes in trees
12              
13             =head1 SYNOPSIS
14              
15             new Bio::NEXUS::Node;
16              
17             =head1 DESCRIPTION
18              
19             Provides a few useful functions for nodes.
20              
21             =head1 FEEDBACK
22              
23             All feedback (bugs, feature enhancements, etc.) are all greatly appreciated. There are no mailing lists at this time for the Bio::NEXUS::Node module, so send all relevant contributions to Dr. Weigang Qiu (weigang@genectr.hunter.cuny.edu).
24              
25             =head1 AUTHORS
26              
27             Weigang Qiu (weigang@genectr.hunter.cuny.edu)
28             Eugene Melamud (melamud@carb.nist.gov)
29             Chengzhi Liang (liangc@umbi.umd.edu)
30             Thomas Hladish (tjhladish at yahoo)
31              
32             =head1 CONTRIBUTORS
33              
34             Peter Yang (pyang@rice.edu)
35              
36             =head1 METHODS
37              
38             =cut
39              
40             package Bio::NEXUS::Node;
41              
42 34     34   187 use strict;
  34         71  
  34         1132  
43 34     34   180 use Bio::NEXUS::Functions;
  34         1524  
  34         7062  
44 34     34   20239 use Bio::NEXUS::NHXCmd;
  34         159  
  34         1095  
45 34     34   258 use Bio::NEXUS::Util::Exceptions;
  34         66  
  34         1419  
46 34     34   225 use Bio::NEXUS::Util::Logger;
  34         62  
  34         851  
47 34     34   174 use vars qw($VERSION $AUTOLOAD);
  34         103  
  34         1734  
48             #use Data::Dumper; # XXX this is not used, might as well not import it!
49             #use Carp; # XXX this is not used, might as well not import it!
50              
51 34     34   191 use Bio::NEXUS; $VERSION = $Bio::NEXUS::VERSION;
  34         57  
  34         3405  
52             my $logger = Bio::NEXUS::Util::Logger->new();
53              
54             sub BEGIN {
55             eval {
56 34         362 require warnings;
57 34         100321 1;
58             }
59 34 50   34   91 or do {
60 34     34   174 no strict 'refs';
  34         60  
  34         3585  
61 0         0 *warnings::import = *warnings::unimport = sub { };
  0         0  
62 0         0 $INC{'warnings.pm'} = '';
63             };
64             }
65              
66             =head2 new
67              
68             Title : new
69             Usage : $node = new Bio::NEXUS::Node();
70             Function: Creates a new Bio::NEXUS::Node object
71             Returns : Bio::NEXUS::Node object
72             Args : none
73              
74             =cut
75              
76             sub new {
77 1073     1073 1 1339 my ($class) = @_;
78 1073         2863 my $self = { _nhx_obj => undef };
79 1073         2943 bless $self, $class;
80 1073         2154 return $self;
81             }
82              
83             =head2 clone
84              
85             Title : clone
86             Usage : my $newblock = $block->clone();
87             Function: clone a block object (shallow)
88             Returns : Block object
89             Args : none
90              
91             =cut
92              
93             sub clone {
94 36     36 1 72 my ($self) = @_;
95 36         109 my $class = ref($self);
96 36         48 my $newnode = bless( { %{$self} }, $class );
  36         295  
97 36 100       140 if ( defined $self->{_nhx_obj} ) {
98 8         21 $newnode->{_nhx_obj} = $self->clone_nhx_command;
99             }
100 36         59 my @children = @{ $newnode->get_children() };
  36         77  
101 36         132 $newnode->set_children();
102 36         66 for my $child (@children) {
103 24         145 my $newchild = $child->clone();
104 24         54 $newnode->add_child($newchild);
105 24         58 $newchild->set_parent_node($newnode);
106             }
107 36         95 return $newnode;
108             }
109              
110             =head2 get_seq
111              
112             Title : get_seq
113             Usage : $sequence = $node->get_seq();
114             Function: Returns the node's sequence
115             Returns : sequence (string)
116             Args : none
117              
118             =cut
119              
120             sub get_seq {
121 0     0 1 0 my ($self) = @_;
122 0         0 return $self->{'seq'};
123             }
124              
125             =head2 set_seq
126              
127             Title : set_seq
128             Usage : $node->set_seq($sequence);
129             Function: Sets sequence of the node
130             Returns : none
131             Args : sequence (string)
132              
133             =cut
134              
135             sub set_seq {
136 0     0 1 0 my ( $self, $seq ) = @_;
137 0         0 $self->{'seq'} = $seq;
138             }
139              
140             =head2 set_parent_node
141              
142             Title : set_parent_node
143             Usage : $node->set_parent_node($parent);
144             Function: Sets the parent node of the node
145             Returns : none
146             Args : parent node (Bio::NEXUS::Node object)
147              
148             =cut
149              
150             sub set_parent_node {
151 1028     1028 1 1239 my ( $self, $parent ) = @_;
152 1028         2538 $self->{'parent'} = $parent;
153             }
154              
155             =head2 get_parent
156              
157             Title : get_parent
158             Usage : $parent=$node->get_parent();
159             Function: Returns the parent node of the node
160             Returns : parent node (Bio::NEXUS::Node object) or undef if nonexistent
161             Args : none
162              
163             =cut
164              
165             sub get_parent {
166 1020 100   1020 1 2872 if ( defined $_[0]->{'parent'} ) {
167 1017         2303 return $_[0]->{'parent'};
168             }
169             else {
170 3         21 return undef;
171             }
172             }
173              
174             =head2 set_length
175              
176             Title : set_length
177             Usage : $node->set_length($length);
178             Function: Sets the node's length (meaning the length of the branch leading to the node)
179             Returns : none
180             Args : length (number)
181              
182             =cut
183              
184             sub set_length {
185 701     701 1 1013 my ( $self, $length ) = @_;
186 701         1832 $self->{'length'} = $length;
187             }
188              
189             =head2 get_length
190              
191             Title : length
192             Usage : $length=$node->get_length();
193             Function: Returns the node's length
194             Returns : length (integer) or undef if nonexistent
195             Args : none
196              
197             =cut
198              
199             sub get_length {
200 2769 100   2769 1 7384 if ( defined $_[0]->{'length'} ) {
201 1703         5171 return $_[0]->{'length'};
202             }
203             else {
204 1066         3116 return undef;
205             }
206             }
207              
208             =head2 get_total_length
209              
210             Title : get_total_length
211             Usage : $total_length = $node->get_total_length();
212             Function: Gets the total branch length of the node and that of all the children (???)
213             Returns : total branch length
214             Args : none
215              
216             =cut
217              
218             sub get_total_length {
219 34     34 1 44 my $self = shift;
220 34   100     66 my $len = $self->get_length() || 0;
221 34         47 for my $child ( @{ $self->get_children() } ) {
  34         56  
222 30         82 $len += $child->get_total_length();
223             }
224 34         113 return $len;
225             }
226              
227             =head2 set_support_value
228              
229             Title : set_support_value
230             Usage : $node->set_support_value($bootstrap);
231             Function: Sets the branch support value associated with this node
232             Returns : none
233             Args : bootstrap value (integer)
234              
235             =cut
236              
237             sub set_support_value {
238 44     44 1 84 my ( $self, $bootstrap ) = @_;
239 44 50 66     190 if ( defined $bootstrap and not _is_number($bootstrap) ) {
    100          
240 0         0 $logger->info("Attempt to set bad branch support value: <$bootstrap> is not a valid number");
241             }
242             elsif ( not defined $bootstrap ) {
243 1         8 $logger->info("Attempt to set undefined branch support value");
244             }
245              
246 44         181 $self->set_nhx_tag( 'B', [$bootstrap] );
247             }
248              
249             =head2 get_support_value
250              
251             Title : get_support_value
252             Usage : $bootstrap = $node->get_support_value();
253             Function: Returns the branch support value associated with this node
254             Returns : bootstrap value (integer) or undef if nonexistent
255             Args : none
256              
257             =cut
258              
259             sub get_support_value {
260 1102     1102 1 1413 my ($self) = @_;
261 1102         2227 my ($support_val) = $self->get_nhx_values('B');
262 1102         2176 return $support_val;
263             }
264              
265             =begin comment
266              
267             Title : _set_xcoord
268             Usage : $node->_set_xcoord($xcoord);
269             Function: Sets the node's x coordinate (?)
270             Returns : none
271             Args : x coordinate (integer)
272              
273             =end comment
274              
275             =cut
276              
277             sub _set_xcoord {
278 0     0   0 my ( $self, $xcoord ) = @_;
279 0         0 $self->{'xcoord'} = $xcoord;
280             }
281              
282             =begin comment
283              
284             Title : _get_xcoord
285             Usage : $xcoord=$node->_get_xcoord();
286             Function: Returns the node's x coordinate
287             Returns : x coordinate (integer) or undef if nonexistent
288             Args : none
289              
290             =end comment
291              
292             =cut
293              
294             sub _get_xcoord {
295 0 0   0   0 if ( defined $_[0]->{'xcoord'} ) {
296 0         0 return $_[0]->{'xcoord'};
297             }
298             else {
299 0         0 return undef;
300             }
301             }
302              
303             =begin comment
304              
305             Title : _set_ycoord
306             Usage : $node->_set_ycoord($ycoord);
307             Function: Sets the node's y coordinate (?)
308             Returns : none
309             Args : y coordinate (integer)
310              
311             =end comment
312              
313             =cut
314              
315             sub _set_ycoord {
316 0     0   0 my ( $self, $ycoord ) = @_;
317 0         0 $self->{'ycoord'} = $ycoord;
318             }
319              
320             =begin comment
321              
322             Title : _get_ycoord
323             Usage : $ycoord=$node->_get_ycoord();
324             Function: Returns the node's y coordinate
325             Returns : y coordinate (integer) or undef if nonexistent
326             Args : none
327              
328             =end comment
329              
330             =cut
331              
332             sub _get_ycoord {
333 0     0   0 my $self = shift;
334 0         0 return $self->{'ycoord'};
335             }
336              
337             =head2 set_name
338              
339             Title : set_name
340             Usage : $node->set_name($name);
341             Function: Sets the node's name
342             Returns : none
343             Args : name (string/integer)
344              
345             =cut
346              
347             sub set_name {
348 1761     1761 1 2602 my ( $self, $name ) = @_;
349 1761         5877 $self->{'name'} = $name;
350             }
351              
352             =head2 get_name
353              
354             Title : get_name
355             Usage : $name = $node->get_name();
356             Function: Returns the node's name
357             Returns : name (integer/string) or undef if nonexistent
358             Args : none
359              
360             =cut
361              
362             sub get_name {
363 7034     7034 1 10240 my $self = shift;
364 7034         23833 return $self->{'name'};
365             }
366              
367             =head2 is_otu
368              
369             Title : is_otu
370             Usage : $node->is_otu();
371             Function: Returns 1 if the node is an OTU or 0 if it is not (internal node)
372             Returns : 1 or 0
373             Args : none
374              
375             =cut
376              
377             sub is_otu {
378 7678     7678 1 40742 my $self = shift;
379 7678 100       36547 defined $self->{'children'} ? return 0 : return 1;
380             }
381              
382             =head2 add_child
383              
384             Title : add_childTU
385             Usage : $node->add_child($node);
386             Function: Adds a child to an existing node
387             Returns : none
388             Args : child (Bio::NEXUS::Node object)
389              
390             =cut
391              
392             sub add_child {
393 1020     1020 1 1599 my ( $self, $child ) = @_;
394 1020         1407 push @{ $self->{'children'} }, $child;
  1020         3099  
395             }
396              
397             =head2 get_distance
398              
399             Title : get_distance
400             Usage : $distance = $node1->get_distance($node2);
401             Function: Calculates tree distance from one node to another (?)
402             Returns : distance (floating-point number)
403             Args : target node (Bio::NEXUS::Node objects)
404              
405             =cut
406              
407             sub get_distance {
408 6     6 1 15 my ( $node1, $node2 ) = @_;
409 6 50       19 if ( not defined $node2 ) {
410 0         0 Bio::NEXUS::Util::Exceptions::BadArgs->throw(
411             'error' => "Missing argument for 'get_distance' method.\n"
412             ."The target node is node has to be defined"
413             );
414             }
415 6         10 my $distance = 0;
416 6 50       27 if ( $node1 eq $node2 ) {
417 0         0 return 0;
418             }
419 6         11 my $tmp_node1 = $node1;
420 6         9 my $tmp_node2 = $node2;
421              
422 6         12 my %parent1;
423             my $common_parent;
424              
425 6         21 while ( defined $tmp_node1->{'parent'} ) {
426 3         11 $parent1{$tmp_node1} = 1;
427 3         13 $tmp_node1 = $tmp_node1->{'parent'};
428             }
429              
430             #add root node to hash
431 6         18 $parent1{$tmp_node1} = 1;
432              
433             #the following line handles cases where node2 is root
434 6         9 $common_parent = $tmp_node2;
435              
436 6         20 while ( not exists $parent1{$tmp_node2} ) {
437 16 50       46 if ( defined $tmp_node2->{'parent'} ) {
438 16         36 $distance += $tmp_node2->get_length();
439 16         33 $tmp_node2 = $tmp_node2->{'parent'};
440             }
441 16         274 $common_parent = $tmp_node2;
442 16         327 my $tmp = $common_parent->get_length();
443             }
444              
445 6         7 $tmp_node1 = $node1; #reset node1
446 6         26 while ( $tmp_node1 ne $common_parent ) {
447 3 50       11 if ( defined $tmp_node1->{'parent'} ) {
448 3         9 $distance += $tmp_node1->get_length();
449 3         16 $tmp_node1 = $tmp_node1->{'parent'};
450             }
451             }
452 6         40 return $distance;
453             }
454              
455             =head2 to_string
456              
457             Title : to_string
458             Usage : my $string; $root->tree_string(\$string, 0, $format)
459             Function: recursively builds Newick tree string from root to tips
460             Returns : none
461             Args : reference to string, boolean $remove_inode_names flag, string - $format (NHX or STD)
462              
463             =cut
464              
465             sub to_string {
466 1159     1159 1 1967 my ( $self, $outtree, $remove_inode_names, $out_format ) = @_;
467              
468 1159         2122 my $name = $self->get_name();
469 1159         3439 $name = _nexus_formatted($name);
470              
471             #my $bootstrap = $self->get_support_value();
472 1159 100       3689 my $comment =
473             ( $out_format =~ /NHX/i )
474             ? $self->nhx_command_to_string
475             : $self->get_support_value;
476 1159         2464 my $length = $self->get_length();
477 1159         1583 my @children = @{ $self->get_children() };
  1159         2453  
478              
479 1159 100       2429 if (@children) { # if $self is an internal node
480 491         665 $$outtree .= '(';
481              
482 491         771 for my $child (@children) {
483 1067         2913 $child->to_string( $outtree, $remove_inode_names, $out_format );
484             }
485              
486 491         817 $$outtree .= ')';
487              
488 491 100 66     2420 if ( defined $name && !$remove_inode_names ) { $$outtree .= $name }
  479         689  
489 491 100       979 if ( defined $length ) { $$outtree .= ":$length" }
  272         444  
490 491 100       1253 if ( defined $comment ) { $$outtree .= "[$comment]" }
  81         151  
491              
492 491         677 $$outtree .= ',';
493              
494             }
495             else { # if $self is a terminal node
496              
497 668 50       1302 if ( not defined $name ) {
498 0         0 Bio::NEXUS::Util::Exceptions::BadArgs->throw(
499             'error' => "OTU found without a name (terminal nodes must be named)"
500             );
501             }
502 668         1018 $$outtree .= $name;
503              
504 668 100       1546 if ( defined $length ) { $$outtree .= ":$length" }
  488         858  
505 668 100       1731 if ( defined $comment ) { $$outtree .= "[$comment]" }
  35         134  
506              
507 668         837 $$outtree .= ',';
508             }
509 1159         5273 $$outtree =~ s/,\)/)/g;
510             }
511              
512             =head2 set_children
513              
514             Title : set_children
515             Usage : $node->set_children($children);
516             Function: Sets children
517             Returns : $node
518             Args : arrayref of children
519              
520             =cut
521              
522             sub set_children {
523 36     36 1 69 my ( $self, $children ) = @_;
524 36         86 $self->{'children'} = $children;
525             }
526              
527             =head2 get_children
528              
529             Title : get_children
530             Usage : @children = @{ $node->get_children() };
531             Function: Retrieves list of children
532             Returns : array of children (Bio::NEXUS::Node objects)
533             Args : none
534              
535             =cut
536              
537             sub get_children {
538 5647     5647 1 7560 my $self = shift;
539 5647 100       19243 return $self->{'children'} if ( $self->{'children'} );
540 2820         6358 return [];
541             }
542              
543             =head2 walk
544              
545             Title : walk
546             Usage : @descendents = $node->walk();
547             Function: Walks through tree and compiles a "clade list"
548             (including $self and all inodes and otus descended from $self)
549             Returns : array of nodes
550             Args : generally, none, though walk() calls itself recurseively with
551             2 arguments: the node list so far, and a counting variable for inode-naming
552              
553             =cut
554              
555             sub walk {
556 3192     3192 1 4868 my ( $self, $nodes, $i ) = @_;
557              
558 3192         5703 my $name = $self->get_name();
559             # if the node doesn't have a name, name it inode
560 3192 100 66     8311 if ( !$name ) {
    50          
561 409         1455 $self->set_name( 'inode' . $$i++ );
562             }
563              
564             # if it's not an otu, and the name is a number ('X'), rename it inodeX
565             elsif ( !$self->is_otu() && $name =~ /^\d+$/ ) {
566 0         0 $self->set_name( 'inode' . $name );
567             }
568              
569 3192         5027 my @children = @{ $self->get_children() };
  3192         5998  
570              
571             # if $self is not an otu,
572 3192 100       7379 if (@children) {
573 1362         1839 for my $child (@children) {
574 2953 50       8692 $child->walk( $nodes, $i ) if $child;
575             }
576             }
577              
578             #print scalar @{$nodes}, "\n";;
579 3192         9155 push @$nodes, $self;
580             }
581              
582             =head2 get_otus
583              
584             Title : get_otus
585             Usage : @listOTU = @{$node->get_otu()}; (?)
586             Function: Retrieves list of OTUs
587             Returns : reference to array of OTUs (Bio::NEXUS::Node objects)
588             Args : none
589              
590             =cut
591              
592             sub get_otus {
593 0     0 1 0 my $self = shift;
594 0         0 my @otus;
595 0         0 $self->_walk_otus( \@otus );
596 0         0 return \@otus;
597             }
598              
599             =begin comment
600              
601             Title : _walk_otus
602             Usage : $self->_walk_otus(\@otus);
603             Function: Walks through tree and retrieves otus; recursive
604             Returns : none
605             Args : reference to list of otus
606              
607             =end comment
608              
609             =cut
610              
611             sub _walk_otus {
612 0     0   0 my $self = shift;
613 0         0 my $nodes = shift;
614              
615 0         0 my $children = $self->get_children();
616 0         0 for my $child (@$children) {
617 0 0       0 if ( $child->is_otu ) {
618 0         0 push @$nodes, $child;
619             }
620             else {
621 0 0       0 $child->_walk_otus($nodes) if @$children;
622             }
623             }
624             }
625              
626             =head2 printall
627              
628             Title : printall
629             Usage : $tree_as_string = $self->printall();
630             Function: Gets the node properties as a tabbed string for printing nicely
631             formatted trees (developed by Tom)
632             Returns : Formatted string
633             Args : Bio::NEXUS::Node object
634              
635             =cut
636              
637             sub printall {
638 0     0 1 0 my $self = shift;
639              
640 0         0 my $children = $self->get_children();
641 0         0 my $str = "Name: ";
642 0 0       0 $str .= $self->get_name() if ( $self->get_name() );
643 0         0 $str .= " OTU\?: ";
644 0         0 $str .= $self->is_otu();
645 0         0 $str .= " Length: ";
646 0 0       0 $str .= $self->get_length() if $self->get_length();
647              
648             #$str .= " bootstrap: ";
649             #$str .= $self->get_support_value() if $self->get_support_value();
650 0         0 $str .= " Comment: ";
651 0 0       0 $str .= $self->nhx_command_to_string() if $self->nhx_command_to_string();
652 0         0 $str .= "\n";
653              
654             #carp($str);
655 0         0 print $str;
656              
657 0         0 for my $child (@$children) {
658 0         0 $child->printall();
659             }
660             }
661              
662             =begin comment
663              
664             Title : _parse_newick
665             Usage : $self->_parse_newick($nexus_words, $pos);
666             Function: Parse a newick tree string and build up the NEXPL tree it implies
667             Returns : none
668             Args : Ref to array of NEXUS-style words that make up the tree string; ref to current position in array
669              
670             =end comment
671              
672             =cut
673              
674             sub _parse_newick {
675 34     34   300 no warnings qw( recursion );
  34         72  
  34         182835  
676 1525     1525   2354 my ( $self, $words, $pos ) = @_;
677 1525 0 33     3214 if ( not $words and not @$words ) {
678 0         0 Bio::NEXUS::Util::Exceptions::BadArgs->throw(
679             'error' => 'Bio::NEXUS::Node::_parse_newick() called without something to parse'
680             );
681             }
682 1525 100       2759 $pos = 0 unless $pos;
683              
684 1525         3257 for ( ; $pos < @$words; $pos++ ) {
685 2781         4054 my $word = $words->[$pos];
686              
687             # For parsing the comments within the NEXUS word.
688 2781         6296 $word = $self->_parse_comment($word);
689 2781 100       8383 if ( $word eq '(' ) {
    100          
    100          
    100          
690 461         564 my $parent_node = $self;
691              
692             # start a new clade
693 461         2569 my $new_node = new Bio::NEXUS::Node;
694 461         1076 $parent_node->adopt($new_node);
695 461         1721 $pos = $new_node->_parse_newick( $words, ++$pos );
696             }
697              
698             # We're starting a sibling of the current node's
699             elsif ( $word eq ',' ) {
700 521         1066 my $parent_node = $self->get_parent();
701 521         1383 my $new_node = new Bio::NEXUS::Node;
702 521         1250 $parent_node->adopt($new_node);
703 521         1991 $pos = $new_node->_parse_newick( $words, ++$pos );
704             }
705              
706             elsif ( $word eq ')' ) {
707 461         952 my $parent_node = $self->get_parent();
708 461         1714 $pos = $parent_node->_parse_newick( $words, ++$pos );
709              
710             # finish a clade
711 461         650 last;
712             }
713             elsif ( $word eq ':' ) {
714 676         1474 $pos = $self->_parse_length( $words, ++$pos );
715             }
716             else {
717 662         1634 $self->set_name($word);
718             }
719             }
720 1525         3529 return $pos;
721             }
722              
723             =begin comment
724              
725             Title : _parse_comment
726             Usage : $self->_parse_comment($words,$pos);
727             Function: parses and stores comments in the nodes
728             Returns : none
729             Args : $words, $pos string, which may contain bootstraps as well
730              
731             =end comment
732              
733             =cut
734              
735             sub _parse_comment {
736 3457     3457   4803 my ( $self, $word ) = @_;
737 3457         3443 my $nhx_obj;
738              
739 3457 100       7031 if ( $word =~ s/\[(.*)\]// ) {
740              
741             # parse non-empty comment string
742 88         208 my $comment_str = $1;
743 88         330 $nhx_obj = new Bio::NEXUS::NHXCmd($comment_str);
744              
745             # check if the comment was an NHX command (&&NHX)
746 88 100       264 if ( defined $nhx_obj->to_string ) {
747 46         87 $self->{'is_nhx'} = 1;
748             }
749             else {
750 42         88 $self->{'is_nhx'} = 0;
751 42         163 $nhx_obj->set_tag( 'B', [$comment_str] );
752 42 50       133 $self->_parse_support_value($comment_str) if defined $comment_str;
753              
754             #$nhx_obj = new Bio::NEXUS::NHXCmd();
755             #$nhx_obj->set_tag('B',$support_value);
756             }
757 88         184 $self->{_nhx_obj} = $nhx_obj;
758             }
759 3457         7077 return $word;
760             }
761              
762             =begin comment
763              
764             Title : _parse_length
765             Usage : $self->_parse_length($length);
766             Function: parses and stores branch lengths
767             Returns : none
768             Args : $distance string, which may contain bootstraps as well
769              
770             =end comment
771              
772             =cut
773              
774             sub _parse_length {
775 676     676   886 my ( $self, $words, $pos ) = @_;
776              
777 676         691 my $length;
778              
779             # number may have been split up if there were '-' (negative) signs
780 676   100     3970 until ( !defined $words->[$pos] || $words->[$pos] =~ /^[),]$/ ) {
781 685         4145 $length .= $words->[ $pos++ ];
782             }
783 676         709 --$pos;
784              
785 676         1339 $length = $self->_parse_comment($length);
786              
787             # empty branch length definition
788 676 50       1457 return $pos unless defined $length;
789              
790 676 50       1906 if ( not _is_number($length) ) {
791 0         0 Bio::NEXUS::Util::Exceptions::BadNumber->throw(
792             'error' => "Bad branch length found in tree string: <$length> is not a valid number"
793            
794             );
795             }
796              
797 676 100       1885 if ( $length =~ /e/i ) {
798 4         15 $length = _sci_to_dec($length);
799             }
800 676         1575 $self->set_length($length);
801 676         2162 return $pos;
802             }
803              
804             =begin comment
805              
806             Title : _parse_support_value
807             Usage : $self->_parse_support_value($boostrap_value);
808             Function: Unsure
809             Returns : none
810             Args : unsure
811              
812             =end comment
813              
814             =cut
815              
816             sub _parse_support_value {
817 42     42   63 my ( $self, $bootstrap ) = @_;
818              
819 42 50       109 if ( not _is_number($bootstrap) ) {
820 0         0 Bio::NEXUS::Util::Exceptions::BadNumber->throw(
821             'error' => "Bad branch support value found in tree string: <$bootstrap> is not a valid number"
822             );
823             }
824              
825 42 50       123 $self->set_support_value( _sci_to_dec($bootstrap) )
826             if defined _sci_to_dec($bootstrap);
827 42         93 return $bootstrap;
828             }
829              
830             =head2 find
831              
832             Title : find
833             Usage : $node = $node->find($name);
834             Function: Finds the first occurrence of a node called 'name' in the tree
835             Returns : Bio::NEXUS::Node object
836             Args : name (string)
837              
838             =cut
839              
840             sub find {
841 196     196 1 264 my ( $self, $name ) = @_;
842 196         338 my $nodename = $self->get_name();
843 196         376 my $children = $self->get_children();
844 196 100       381 return $self if ( $self->get_name() eq $name );
845 169         308 for my $child (@$children) {
846 165         354 my $result = $child->find($name);
847 165 100       457 return $result if $result;
848             }
849 98         184 return undef;
850             }
851              
852             =head2 prune
853              
854             Name : prune
855             Usage : $node->prune($OTUlist);
856             Function: Removes everything from the tree except for OTUs specified in $OTUlist
857             Returns : none
858             Args : list of OTUs (string)
859              
860             =cut
861              
862             sub prune {
863 5     5 1 8 my ( $self, $OTUlist ) = @_;
864 5         10 my $name = $self->get_name();
865             # the following line is in response to [rt.cpan.org #47707] Bug in Bio::NEXUS::Node.pm
866 5         11 $name = quotemeta $name;
867 5 100       10 if ( $self->is_otu() ) {
868 4 100       61 if ( $OTUlist =~ /\s+$name\s+/ ) {
869              
870             # if in the list, keep this OTU
871 3         9 return "keep";
872             }
873             else {
874             # otherwise, delete it
875 1         3 return "delete";
876             }
877             }
878 1         2 my @children = @{ $self->get_children() };
  1         4  
879 1         9 my @newchildren = ();
880 1         2 for my $child (@children) {
881 4         13 my $result = $child->prune($OTUlist);
882 4 100       12 if ( $result eq "keep" ) {
883 3         5 push @newchildren, $child;
884             }
885             }
886 1         3 $self->{'children'} = \@newchildren;
887 1 50       16 if ( $#newchildren == -1 ) {
888              
889             # delete the inode because it doesn't have any children
890 0         0 $self->{'children'} = undef;
891 0         0 return "delete";
892             }
893 1         3 @children = @{ $self->get_children() };
  1         3  
894 1 50       5 if ( $#children == 0 ) {
895 0         0 my $child = $children[0];
896 0         0 my $childname = $children[0]->get_name();
897              
898 0         0 $self->set_name( $child->get_name() );
899 0         0 $self->set_seq( $child->get_seq() );
900 0   0     0 my $self_length = $self->get_length() || 0;
901 0         0 $self->set_length( $self_length + $child->get_length() );
902 0         0 $self->set_support_value( $child->get_support_value() );
903 0 0       0 $self->set_nhx_obj( $child->get_nhx_obj()->clone )
904             if defined $child->{_nhx_obj};
905 0         0 $self->_set_xcoord( $child->_get_xcoord() );
906 0         0 $self->_set_ycoord( $child->_get_ycoord() );
907 0         0 $self->{'children'} = $child->{'children'};
908              
909 0 0       0 if ( $child->is_otu() ) {
910 0         0 $self->{'children'} = undef;
911 0         0 undef $self->{'children'};
912             }
913              
914             # assigning inode $name to child $childname
915 0         0 return "keep";
916             }
917              
918             # keeping this inode as is, since it has multiple children
919 1         6 return "keep";
920             }
921              
922             =head2 equals
923              
924             Name : equals
925             Usage : $node->equals($another_node);
926             Function: compare if two nodes (and their subtrees) are equivalent
927             Returns : 1 if equal or 0 if not
928             Args : another Node object
929              
930             =cut
931              
932             sub equals {
933 216     216 1 282 my ( $self, $other ) = @_;
934              
935             # 1 if only one is OTU
936 216 100 100     372 if ( ( $self->is_otu() && !$other->is_otu() )
      100        
      66        
937             || ( !$self->is_otu() && $other->is_otu() ) )
938             {
939              
940             # not the same
941 12         53 return 0;
942             }
943              
944             # 2. both are OTUs
945 204 100 66     460 if ( $self->is_otu() && $other->is_otu() ) {
946 115 100       213 if ( $self->_same_attributes($other) ) {
947              
948             # ...
949 81         207 return 1;
950             }
951             else {
952 34         154 return 0;
953             }
954             }
955              
956             # 3. neither is OTU
957 89         101 my @self_children = @{ $self->get_children() };
  89         167  
958 89         101 my @other_children = @{ $other->get_children() };
  89         174  
959              
960             # compare the attributes of the nodes - see if different
961 89 100       188 if ( !$self->_same_attributes($other) ) { return 0; }
  2         13  
962              
963 87         109 my $num_of_kids = scalar @self_children;
964              
965 87 100       150 if ( scalar @self_children != scalar @other_children ) {
966              
967             # children are different (their quantity differs)
968 2         14 return 0;
969             }
970             else {
971 85         195 for ( my $self_index = 0; $self_index < $num_of_kids; $self_index++ ) {
972 152         177 my $found = 'false';
973              
974 152         298 for (
975             my $other_index = $self_index;
976             $other_index < $num_of_kids;
977             $other_index++
978             )
979             {
980              
981             # the fun part starts here
982             # comparing the unsorted arrays of children
983              
984 191 100       427 if ( $self_children[$self_index]
985             ->equals( $other_children[$other_index] ) )
986             {
987 123         145 $found = 'true';
988              
989             # pull out the child that was found and add it to
990             # the front of the array
991 123         142 my $temp = $other_children[$other_index];
992 123         142 splice( @other_children, $other_index, 1 );
993 123         163 unshift( @other_children, $temp );
994              
995 123         157 last;
996             }
997             }
998              
999 152 100       490 if ( $found eq 'false' ) {
1000 29         142 return 0;
1001             }
1002             }
1003             }
1004              
1005 56         225 return 1;
1006              
1007             }
1008              
1009             # helper function that compares attributes of two node objects
1010             sub _same_attributes {
1011 204     204   255 my ( $self, $other ) = @_;
1012              
1013             # mighty one-liner (if the length of one of the nodes is defined, and the length of the other node is not, return false)
1014 204 100 66     357 return 0 if (!((defined $self->get_length() && defined $other->get_length())
      66        
      100        
1015             ||
1016             (! defined $self->get_length() && ! defined $other->get_length())));
1017            
1018 202 100 66     447 if (defined $self->get_length() && defined $other->get_length()) {
1019 132 100       264 if ( $self->get_length() != $other->get_length() ) { return 0; }
  2         6  
1020             }
1021              
1022             # if the nodes are internal, don't check their names...
1023             # they will most likely differ
1024 200 100 66     415 if ( $self->is_otu() && $other->is_otu() ) {
1025 113 100       202 if ( $self->get_name() ne $other->get_name() ) { return 0; }
  30         71  
1026             }
1027              
1028 170 100 100     349 if ( defined $self->get_nhx_obj() && defined $other->get_nhx_obj() ) {
1029 13 100       27 if ( !$self->get_nhx_obj()->equals( $other->get_nhx_obj ) ) {
1030 1         4 return 0;
1031             }
1032             }
1033 169 50 66     295 if ( !defined $self->get_nhx_obj() && defined $other->get_nhx_obj() ) {
1034 0         0 return 0;
1035             }
1036 169 100 100     283 if ( defined $self->get_nhx_obj() && !defined $other->get_nhx_obj() ) {
1037 1         3 return 0;
1038             }
1039              
1040 168         384 return 1;
1041             }
1042              
1043             =head2 get_siblings
1044              
1045             Name : get_siblings
1046             Usage : $node->get_siblings();
1047             Function: get sibling nodes of this node
1048             Returns : array ref of sibling nodes
1049             Args : none
1050              
1051             =cut
1052              
1053             sub get_siblings {
1054 2     2 1 5 my $self = shift;
1055 2 100       7 return [] unless defined $self->get_parent;
1056 1         4 my $generation = $self->get_parent()->get_children();
1057 1         4 my $siblings = [];
1058 1         2 for my $potential_sibling ( @{$generation} ) {
  1         5  
1059 2 100       11 if ( $potential_sibling ne $self ) {
1060 1         4 push( @$siblings, $potential_sibling );
1061             }
1062             }
1063 1         6 return $siblings;
1064             }
1065              
1066             =head2 is_sibling
1067              
1068             Name : is_sibling
1069             Usage : $node1->is_sibling($node2);
1070             Function: tests whether node1 and node2 are siblings
1071             Returns : 1 if true, 0 if false
1072             Args : second node
1073              
1074             =cut
1075              
1076             sub is_sibling {
1077 2     2 1 7 my ( $self, $node2 ) = @_;
1078 2 50       9 if ( not defined $node2 ) {
1079 0         0 Bio::NEXUS::Util::Exceptions::BadArgs->throw(
1080             'error' => "Missing argument for 'is_sibling' method.\n"
1081             . " The node object to test for sibiling has to be given as argument"
1082             );
1083             }
1084 2         472 my $parent1 = $self->get_parent();
1085 2         8 my $parent2 = $node2->get_parent();
1086 2 50 66     28 return "1"
      66        
1087             if ( ( defined $parent1 and defined $parent2 )
1088             and $parent1 eq $parent2 );
1089 2         14 return "0";
1090             }
1091              
1092             =begin comment
1093              
1094             Name : _rearrange
1095             Usage : $node->_rearrange($newparentnode);
1096             Function: re-arrange this node's parent and children (used in rerooting)
1097             Returns : this node after rearrangement
1098             Args : this node's new parent node, $newparentnode must be this node's old child
1099              
1100             =end comment
1101              
1102             =cut
1103              
1104             sub _rearrange {
1105 0     0   0 my ( $self, $newparent ) = @_;
1106              
1107             # Remove the newparent from this node's children
1108 0         0 $self->set_children( $newparent->get_siblings() );
1109              
1110             # Recursively work up the tree until you get to the node
1111 0         0 my $oldparent = $self->get_parent();
1112 0 0       0 if ($oldparent) { $oldparent->_rearrange($self); }
  0         0  
1113              
1114             # set new parent as parent, self as child
1115 0         0 $newparent->adopt( $self, 0 );
1116 0         0 $self->set_support_value( $newparent->get_support_value() );
1117 0 0       0 $self->set_nhx_obj( $newparent->get_nhx_obj()->clone )
1118             if defined $newparent->{_nhx_obj};
1119 0         0 $self->set_length( $newparent->get_length() );
1120              
1121 0         0 return $self;
1122             }
1123              
1124             =head2 adopt
1125              
1126             Title : adopt
1127             Usage : $parent->adopt($child, $overwrite_children);
1128             Function: make a parent-child relationship between two nodes
1129             Returns : none
1130             Args : the child node, boolean clobber flag
1131              
1132             =cut
1133              
1134             sub adopt {
1135 982     982 1 1438 my ( $parent, $child, $overwrite_children ) = @_;
1136 982         1962 $child->set_parent_node($parent);
1137 982 50       1985 if ($overwrite_children) {
1138 0         0 $parent->set_children( [$child] );
1139             }
1140             else {
1141 982         2159 $parent->add_child($child);
1142             }
1143             }
1144              
1145             =head2 combine
1146              
1147             Title : combine
1148             Usage : my $newblock = $node->combine($child);
1149             Function: removes a node from the tree, effectively by sliding its only child up the branch to its former position
1150             Returns : none
1151             Args : the child node
1152             Methods : Combines the child node and the current node by assigning the
1153             name, bootstrap value, children and other properties of the child. The branch length
1154             of the current node is added to the child node's branch length.
1155              
1156             =cut
1157              
1158             sub combine {
1159 0     0 1 0 my ( $self, $child ) = @_;
1160 0         0 $self->set_name( $child->get_name() );
1161 0         0 $self->set_support_value( $child->get_support_value() );
1162 0 0       0 $self->set_nhx_obj( $child->get_nhx_obj()->clone )
1163             if defined $child->{_nhx_obj};
1164 0   0     0 $self->set_length( ( $self->get_length() || 0 ) + $child->get_length() );
1165 0         0 $self->set_children();
1166 0         0 $self->set_children( $child->get_children() )
1167 0 0       0 if @{ $child->get_children } > 0;
1168             }
1169              
1170             =begin comment
1171              
1172             Title : _assign_otu_ycoord
1173             Usage : $root->_assign_otu_ycoord(\$ypos, \$spacing);
1174             Function: Assign y coords of OTUs
1175             Returns : none
1176             Args : references to initial y position and space between each OTU
1177              
1178             =end comment
1179              
1180             =cut
1181              
1182             # Traverses tree and determines y position of every OTU it finds. If it finds
1183             # an OTU, it adds the current y position to a hash of y coordinates (one key
1184             # for each OTU) and increments the y position.
1185             sub _assign_otu_ycoord {
1186 0     0   0 my ( $self, $yposref, $spacingref ) = @_;
1187 0 0       0 return if $self->is_otu();
1188 0         0 for my $child ( @{ $self->get_children() } ) {
  0         0  
1189 0 0       0 if ( $child->is_otu() ) {
1190 0         0 $child->_set_ycoord($$yposref);
1191 0         0 $$yposref += $$spacingref;
1192             }
1193             else {
1194 0         0 $child->_assign_otu_ycoord( $yposref, $spacingref );
1195             }
1196             }
1197             }
1198              
1199             =begin comment
1200              
1201             Title : _assign_inode_ycoord
1202             Usage : $root->_assign_inode_ycoord();
1203             Function: Get y coords of internal nodes based on OTU position (see _assign_otu_ycoord)
1204             Returns : none
1205             Args : none
1206              
1207             =end comment
1208              
1209             =cut
1210              
1211             # Determines position of an internal node (halfway between all its children). Recursive.
1212             sub _assign_inode_ycoord {
1213 0     0   0 my $self = shift;
1214              
1215 0         0 my @tmp;
1216 0         0 for my $child ( @{ $self->get_children() } ) {
  0         0  
1217 0 0       0 $child->_assign_inode_ycoord() unless ( defined $child->_get_ycoord() );
1218 0         0 push @tmp, $child->_get_ycoord();
1219             }
1220 0         0 my @sorted = sort { $a <=> $b } @tmp;
  0         0  
1221 0         0 my $high = pop @sorted;
1222 0   0     0 my $low = shift @sorted || $high;
1223 0         0 $self->_set_ycoord( $low + 1 / 2 * ( $high - $low ) );
1224             }
1225              
1226             =head2 set_depth
1227              
1228             Title : set_depth
1229             Usage : $root->set_depth();
1230             Function: Determines depth in tree of every node below this one
1231             Returns : none
1232             Args : This node's depth
1233              
1234             =cut
1235              
1236             sub set_depth {
1237 1064     1064 1 1556 my ( $self, $depth ) = @_;
1238 1064         2117 $self->{'depth'} = $depth;
1239 1064 100       3273 return if $self->is_otu();
1240 461         763 for my $child ( @{ $self->get_children() } ) {
  461         960  
1241 982         2512 $child->set_depth( $depth + 1 );
1242             }
1243             }
1244              
1245             =head2 get_depth
1246              
1247             Title : get_depth
1248             Usage : $depth = $node->get_depth();
1249             Function: Returns the node's depth (number of 'generations' removed from the root) in tree
1250             Returns : integer representing node's depth
1251             Args : none
1252              
1253             =cut
1254              
1255             sub get_depth {
1256 57     57 1 69 my $self = shift;
1257 57         135 return $self->{'depth'};
1258             }
1259              
1260             =head2 find_lengths
1261              
1262             Title : find_lengths
1263             Usage : $cladogram = 1 unless $root->find_lengths();
1264             Function: Tries to determine if branch lengths are present in the tree
1265             Returns : 1 if lengths are found, 0 if not
1266             Args : none
1267              
1268             =cut
1269              
1270             sub find_lengths {
1271 445     445 1 613 my $self = shift;
1272 445         989 my $length = $self->get_length();
1273 445 100 100     2604 return 1 if ( $length || ( $length = 0 ) );
1274 379         631 for my $child ( @{ $self->get_children() } ) {
  379         915  
1275 363 100       1040 return 1 if $child->find_lengths();
1276             }
1277 316         1638 return 0;
1278             }
1279              
1280             =head2 mrca
1281              
1282             Title : mrca
1283             Usage : $mrca = $otu1-> mrca($otu2, $treename);
1284             Function : Finds most recent common ancestor of otu1 and otu2
1285             Returns : Node object of most recent common ancestor
1286             Args : Nexus object, two otu objects, name of tree to look in
1287              
1288             =cut
1289              
1290             sub mrca {
1291 2     2 1 5 my ( $otu1, $otu2, $treename ) = @_;
1292 2 0 33     7 if ( not $otu1->is_otu and not $otu2->is_otu ) {
1293 0         0 Bio::NEXUS::Util::Exceptions::ObjectMismatch->throw(
1294             'error' => "the mrca method to calculate most recent\n"
1295             . "common ancestor can be performed only on\n"
1296             . "an OTU node and also requires another OTU\n"
1297             . "node (target) as input argument"
1298             );
1299             }
1300              
1301 2         6 my $currentnode = $otu1;
1302 2         3 my @ancestors;
1303             my $mrca;
1304 2         7 until ( $currentnode->get_name() eq 'root' ) {
1305 8         112 $currentnode = $currentnode->get_parent();
1306 8         23 push( @ancestors, $currentnode );
1307             }
1308 2         5 $currentnode = $otu2;
1309 2         6 until ( $currentnode->get_name() eq 'root' ) {
1310 8         17 $currentnode = $currentnode->get_parent();
1311 8         17 for my $inode (@ancestors) {
1312 14 100       354 if ( $inode eq $currentnode ) {
1313 2         12 return $inode;
1314             }
1315             }
1316             }
1317             }
1318              
1319             =head2 get_mrca_of_otus
1320              
1321             Title : get_mrca_of_otus
1322             Usage : $mrca = $root->get_mrca_of_otus(\@otus);
1323             Function : Finds most recent common ancestor of set of OTUs
1324             Returns : Node object of most recent common ancestor
1325             Args : Nexus object, two otu objects, name of tree to look in
1326              
1327             =cut
1328              
1329             sub get_mrca_of_otus {
1330              
1331             # Not yet implemented completely. Still in the testing mode -- Vivek Gopalan 10MAR2007.
1332             # Used in assigning meaning inode names to gene tree based on species tree and species names of the OTUs of the inodes.
1333             # Note: Internal nodes can also be given as input instead of the OTU to find the mrca;
1334              
1335 0     0 1 0 my ($self, $otus, $ancestors ) = @_;
1336 0   0     0 $ancestors ||= [];
1337 0         0 my @inp_otus = @{$otus};
  0         0  
1338 0         0 my $node_otus =[];
1339 0         0 $self->walk($node_otus);
1340 0         0 my $eq_count = 0 ;
1341 0         0 foreach my $inp_otu (@inp_otus) {
1342 0 0       0 if ( grep {$_->get_name eq $inp_otu} @{$node_otus}) {
  0         0  
  0         0  
1343 0         0 $eq_count++;
1344 0 0       0 last if $eq_count == scalar @inp_otus;
1345             }
1346             #print "$inp_otu $eq_count\n";
1347             }
1348 0 0       0 if ($eq_count == scalar @inp_otus) {
1349             #print Dumper $ancestors;
1350 0         0 push @{$ancestors}, $self;
  0         0  
1351 0         0 foreach my $child ( @{$self->get_children} ) {
  0         0  
1352 0 0       0 next if $child->is_otu;
1353 0         0 $child->get_mrca_of_otus($otus, $ancestors);
1354             }
1355             #print $self->get_name, "," , $eq_count, ", ", scalar @inp_otus, "\n";
1356 0 0       0 if (scalar @{$ancestors}) {
  0         0  
1357 0         0 return $ancestors->[$#{$ancestors}];
  0         0  
1358             }
1359             }
1360 0         0 return;
1361              
1362             }
1363              
1364             sub AUTOLOAD {
1365 0 0   0   0 return if $AUTOLOAD =~ /DESTROY$/;
1366 0         0 my $package_name = 'Bio::NEXUS::Node::';
1367              
1368             # The following methods are deprecated and are temporarily supported
1369             # via a warning and a redirection
1370 0         0 my %synonym_for = (
1371             "${package_name}depth" => "${package_name}get_depth",
1372             "${package_name}boot" => "${package_name}get_support_value",
1373             "${package_name}_parse_boot" => "${package_name}_parse_support_value",
1374             "${package_name}set_boot" => "${package_name}set_support_value",
1375             "${package_name}name" => "${package_name}get_name",
1376             "${package_name}children" => "${package_name}get_children",
1377             "${package_name}length" => "${package_name}get_length",
1378             "${package_name}seq" => "${package_name}get_seq",
1379             "${package_name}distance" => "${package_name}get_distance",
1380             "${package_name}xcoord" => "${package_name}_get_xcoord",
1381             "${package_name}ycoord" => "${package_name}_get_ycoord",
1382             "${package_name}set_xcoord" => "${package_name}_set_xcoord",
1383             "${package_name}set_ycoord" => "${package_name}_set_ycoord",
1384             "${package_name}parent_node" => "${package_name}get_parent",
1385             "${package_name}isOTU" => "${package_name}is_otu",
1386             "${package_name}walk_OTUs" => "${package_name}_walk_otus",
1387             "${package_name}rearrange" => "${package_name}_rearrange",
1388             "${package_name}parse" => "${package_name}_parse_newick",
1389             );
1390              
1391 0 0       0 if ( defined $synonym_for{$AUTOLOAD} ) {
1392 0         0 $logger->warn("$AUTOLOAD() is deprecated; use $synonym_for{$AUTOLOAD}() instead");
1393 0         0 goto &{ $synonym_for{$AUTOLOAD} };
  0         0  
1394             }
1395             else {
1396 0         0 Bio::NEXUS::Util::Exceptions::UnknownMethod->throw(
1397             'error' => "ERROR: Unknown method $AUTOLOAD called"
1398             );
1399             }
1400 0         0 return;
1401             }
1402              
1403             ################## NHXCmd adapter functions ###############
1404              
1405             =head2 contains_nhx_tag
1406              
1407             Title : contains_nhx_tag
1408             Usage : $node_obj->_contains_nhx_tag($tag_name)
1409             Function: Checks if a given tag exists
1410             Returns : 1 if the tax exists, 0 if it doesn't
1411             Args : $tag_name - a string representation of a tag
1412              
1413             =cut
1414              
1415             sub contains_nhx_tag {
1416 3     3 1 1015 my ( $self, $tag_name ) = @_;
1417 3 50       15 if ( defined $self->{_nhx_obj} ) {
1418 3         13 return $self->{_nhx_obj}->contains_tag($tag_name);
1419             }
1420              
1421             } # end of sub
1422              
1423             =head2 get_nhx_tags
1424              
1425             Title : get_nhx_tags
1426             Usage : $node_obj->get_nhx_tags();
1427             Function: Reads and returns an array of tags
1428             Returns : An array of tags
1429             Args : None
1430              
1431             =cut
1432              
1433             sub get_nhx_tags {
1434 1     1 1 2 my ($self) = @_;
1435 1 50       5 if ( defined $self->{_nhx_obj} ) {
1436 1         5 return $self->{_nhx_obj}->get_tags();
1437             }
1438             else {
1439 0         0 return ();
1440             }
1441             }
1442              
1443             =head2 get_nhx_values
1444              
1445             Title : get_nhx_values
1446             Usage : $node_obj->get_nhx_values($tag_name);
1447             Function: Returns the list of values associated with a given tag ($tag_name)
1448             Returns : Array of values
1449             Args : $tag_name - a string representation of the tag
1450              
1451             =cut
1452              
1453             sub get_nhx_values {
1454 1106     1106 1 2402 my ( $self, $tag_name ) = @_;
1455              
1456 1106 100 100     3609 if ( defined $self->{_nhx_obj}
1457             && $self->{_nhx_obj}->contains_tag($tag_name) )
1458             {
1459 71         241 return $self->{_nhx_obj}->get_values($tag_name);
1460             }
1461             else {
1462 1035         3308 return ();
1463             }
1464             }
1465              
1466             =head2 set_nhx_tag
1467              
1468             Title : set_nhx_tag
1469             Usage : node_obj->set_nhx_tag($tag_name, $tag_reference);
1470             Function: Updates the list of values associated with a given tag
1471             Returns : Nothing
1472             Args : $tag_name - a string, $tag_reference - an array-reference
1473              
1474             =cut
1475              
1476             sub set_nhx_tag {
1477 47     47 1 2123 my ( $self, $tag_name, $tag_values ) = @_;
1478 47 50 33     143 if ( not defined $tag_name || not defined $tag_values ) {
1479 0         0 Bio::NEXUS::Util::Exceptions::BadArgs->throw(
1480             'error' => "tag_name or tag_values is not defined"
1481             );
1482             }
1483 47 50       131 if ( ref $tag_values ne 'ARRAY' ) {
1484 0         0 Bio::NEXUS::Util::Exceptions::BadArgs->throw(
1485             'error' => 'tag_values is not an array reference'
1486             );
1487             }
1488 47 100       223 $self->{_nhx_obj} = new Bio::NEXUS::NHXCmd
1489             unless ( defined $self->{_nhx_obj} );
1490 47         165 $self->{_nhx_obj}->set_tag( $tag_name, $tag_values );
1491              
1492             }
1493              
1494             =head2 add_nhx_tag_value
1495              
1496             Title : add_nhx_tag_value
1497             Usage : $node_obj->add_nhx_tag_value($tag_name, $tag_value);
1498             Function: Adds a new tag/value set to the $nhx_obj;
1499             Returns : Nothing
1500             Args : $tag_name - a string, $tag_reference - an array-reference
1501              
1502             =cut
1503              
1504             sub add_nhx_tag_value {
1505 3     3 1 9 my ( $self, $tag_name, $tag_value ) = @_;
1506              
1507 3 50       13 $self->{_nhx_obj} = new Bio::NEXUS::NHXCmd
1508             unless ( defined $self->{_nhx_obj} );
1509 3         16 return $self->{_nhx_obj}->add_tag_value( $tag_name, $tag_value );
1510              
1511             }
1512              
1513             =head2 delete_nhx_tag
1514              
1515             Title : delete_nhx_tag
1516             Usage : $node_obj->delete_nhx_tag($tag_name);
1517             Function: Removes a given tag (and the associated valus) from the $nhx_obj
1518             Returns : Nothing
1519             Args : $tag_name - a string representation of the tag
1520              
1521             =cut
1522              
1523             sub delete_nhx_tag {
1524 0     0 1 0 my ( $self, $tag_name ) = @_;
1525 0 0       0 if ( defined( $self->{_nhx_obj} ) ) {
1526 0         0 $self->{_nhx_obj}->delete_tag($tag_name);
1527             }
1528              
1529             }
1530              
1531             =head2 delete_all_nhx_tags
1532              
1533             Title : delete_all_nhx_tags
1534             Usage : $node_obj->delete_all_nhx_tags();
1535             Function: Removes all tags from $nhx_obj
1536             Returns : Nothing
1537             Args : None
1538              
1539             =cut
1540              
1541             sub delete_all_nhx_tags {
1542 0     0 1 0 my ($self) = @_;
1543              
1544 0 0       0 $self->{_nhx_obj}->delete_all_tags() if defined $self->{_nhx_obj};
1545             }
1546              
1547             =head2 nhx_command_to_string
1548              
1549             Title : nhx_command_to_string
1550             Usage : $node_obj->nhx_command_to_string();
1551             Function: As NHX command string
1552             Returns : NHX command string
1553             Args : None
1554              
1555             =cut
1556              
1557             sub nhx_command_to_string {
1558 68     68 1 701 my ($self) = @_;
1559 68 100       155 if ( defined $self->{_nhx_obj} ) {
1560 55         175 return $self->{_nhx_obj}->to_string();
1561             }
1562             else {
1563 13         30 return undef;
1564             }
1565             }
1566              
1567             =head2 clone_nhx_command
1568              
1569             Title : clone_nhx_command
1570             Usage : $some_node_obj->clone_nhx_command($original_node);
1571             Function: Copies the data of the NHX command of the $original_node object into the NHX command of the $some_node_obj
1572             Returns : Nothing
1573             Args : $original_node - Bio::NEXUS::NHXCmd object whose NHX command data will be cloned
1574              
1575             =cut
1576              
1577             sub clone_nhx_command {
1578 8     8 1 12 my ($self) = @_;
1579 8 50       23 if ( defined $self->{_nhx_obj} ) {
1580 8         37 return $self->{_nhx_obj}->clone();
1581             }
1582             else {
1583 0         0 return undef;
1584             }
1585              
1586             }
1587              
1588             =head2 check_nhx_tag_value_present
1589              
1590             Title : check_nhx_tag_value
1591             Usage : $boolean = nhx_obj->check_nhx_tag_value($tag_name, $value);
1592             Function: check whether a particular value is present in a tag
1593             Returns : 0 or 1 [ true or false]
1594             Args : $tag_name - a string, $value - scalar (string or number)
1595              
1596             =cut
1597              
1598             sub check_nhx_tag_value_present {
1599 1     1 1 4 my ( $self, $tag_name, $tag_value ) = @_;
1600              
1601              
1602 1 50       8 return $self->{_nhx_obj}->check_tag_value_present( $tag_name, $tag_value )
1603             if defined $self->{_nhx_obj};
1604             }
1605              
1606             =head2 set_nhx_obj
1607              
1608             Title : set_nhx_obj
1609             Usage : $node->set_nhx_obj($nhx_obj);
1610             Function: Sets Bio::NEXUS::NHXCmd object associated with this node
1611             Returns : Nothing
1612             Args : Reference of the NHXCmd object
1613             othing
1614              
1615             =cut
1616              
1617             sub set_nhx_obj {
1618 2     2 1 10 my ( $self, $nhx_obj ) = @_;
1619 2         8 $self->{_nhx_obj} = $nhx_obj;
1620             }
1621              
1622             =head2 get_nhx_obj
1623              
1624             Title : get_nhx_obj
1625             Usage : $nhx_obj = get_nhx_obj();
1626             Function: Returns Bio::NEXUS::NHXCmd object associated with this node
1627             Returns : Reference of the NHXCmd object
1628             Args : Nothing
1629              
1630             =cut
1631              
1632             sub get_nhx_obj {
1633 717     717 1 748 my ($self) = @_;
1634 717         2275 return $self->{_nhx_obj};
1635             }
1636              
1637             1;