File Coverage

blib/lib/Bio/Phylo/Forest.pm
Criterion Covered Total %
statement 183 289 63.3
branch 41 102 40.2
condition 3 10 30.0
subroutine 14 19 73.6
pod 9 9 100.0
total 250 429 58.2


line stmt bran cond sub pod time code
1             package Bio::Phylo::Forest;
2 29     29   1034 use strict;
  29         55  
  29         894  
3 29     29   139 use base qw'Bio::Phylo::Listable Bio::Phylo::Taxa::TaxaLinker';
  29         52  
  29         9237  
4 29     29   195 use Bio::Phylo::Util::CONSTANT qw':objecttypes /looks_like/';
  29         55  
  29         6645  
5 29     29   183 use Bio::Phylo::Util::Exceptions 'throw';
  29         61  
  29         1018  
6 29     29   153 use Bio::Phylo::Factory;
  29         46  
  29         176  
7              
8             =begin comment
9              
10             This class has no internal state, no cleanup is necessary.
11              
12             =end comment
13              
14             =cut
15              
16             {
17             my $logger = __PACKAGE__->get_logger;
18             my $factory = Bio::Phylo::Factory->new;
19             my $CONSTANT_TYPE = _FOREST_;
20             my $CONTAINER_CONSTANT = _PROJECT_;
21              
22             =head1 NAME
23              
24             Bio::Phylo::Forest - Container for tree objects
25              
26             =head1 SYNOPSIS
27              
28             use Bio::Phylo::Factory;
29             my $fac = Bio::Phylo::Factory->new;
30             my $forest = $fac->create_forest;
31             my $tree = $fac->create_tree;
32             $forest->insert($tree);
33             print $forest->to_nexus;
34              
35             =head1 DESCRIPTION
36              
37             The Bio::Phylo::Forest object models a set of trees. The object subclasses the
38             L<Bio::Phylo::Listable> object, so look there for more methods available to
39             forest objects.
40              
41             =head1 CALCULATIONS
42              
43             =over
44              
45             =item calc_split_frequency()
46              
47             Calculates frequency of provided split
48              
49             Type : Calculation
50             Title : calc_split_frequency
51             Usage : my $freq = $trees->calc_split_frequency([$node1,$node2]);
52             Function: Calculates split frequency
53             Returns : Scalar, a number
54             Args : An array of taxon objects, or a taxa object
55             Comment :
56              
57             =cut
58              
59             sub calc_split_frequency {
60 1     1 1 8 my ( $self, $arg ) = @_;
61 1         2 my @trees = @{ $self->get_entities };
  1         4  
62 1         3 my $ntrees = scalar @trees;
63 1 50       4 if ($ntrees) {
64 1         2 my $count = 0;
65 1         3 for my $tree (@trees) {
66 3 100       15 $count++ if $tree->is_clade($arg);
67             }
68 1         12 return $count / $ntrees;
69             }
70 0         0 return 0;
71             }
72              
73             =back
74              
75             =head1 METHODS
76              
77             =over
78              
79             =item insert()
80              
81             Inserts trees in forest.
82              
83             Type : Method
84             Title : insert
85             Usage : $trees->insert( $tree1, $tree2, ... );
86             Function: Inserts trees in forest.
87             Returns : A Bio::Phylo::Forest object.
88             Args : Trees
89             Comment : The last seen tree that is set as default
90             becomes the default for the entire forest
91              
92             =cut
93              
94             sub insert {
95 151     151 1 257 my $self = shift;
96 151 100       635 if ( $self->can_contain(@_) ) {
97 150         260 my $seen_default = 0;
98 150         289 for my $tree ( reverse @_ ) {
99 150 50       551 if ( $tree->is_default ) {
100 0 0       0 if ( not $seen_default ) {
101 0         0 $seen_default++;
102             }
103             else {
104 0         0 $tree->set_not_default;
105             }
106             }
107             }
108 150 50       391 if ($seen_default) {
109 0 0       0 if ( my $tree = $self->get_default_tree ) {
110 0         0 $tree->set_not_default;
111             }
112             }
113 150         490 $self->SUPER::insert(@_);
114             }
115             else {
116 1         11 throw 'ObjectMismatch' => "Failed insertion: @_ [in $self]";
117             }
118             }
119              
120             =item get_default_tree()
121              
122             Gets the default tree in the forest.
123              
124             Type : Method
125             Title : get_default_tree
126             Usage : my $tree = $trees->get_default_tree;
127             Function: Gets the default tree in the forest.
128             Returns : A Bio::Phylo::Forest::Tree object.
129             Args : None
130             Comment : If no default tree has been set,
131             returns first tree.
132              
133             =cut
134              
135             sub get_default_tree {
136 0     0 1 0 my $self = shift;
137 0         0 my $first = $self->first;
138 0         0 for my $tree ( @{ $self->get_entities } ) {
  0         0  
139 0 0       0 return $tree if $tree->is_default;
140             }
141 0         0 return $first;
142             }
143              
144             =item check_taxa()
145              
146             Validates taxon links of nodes in invocant's trees.
147              
148             Type : Method
149             Title : check_taxa
150             Usage : $trees->check_taxa;
151             Function: Validates the taxon links of the
152             nodes of the trees in $trees
153             Returns : A validated Bio::Phylo::Forest object.
154             Args : None
155              
156             =cut
157              
158             sub check_taxa {
159 8     8 1 15 my $self = shift;
160              
161             # is linked
162 8 50       46 if ( my $taxa = $self->get_taxa ) {
163 8         19 my %tips;
164            
165             # build a hash of all the unlinked tips by their names
166 8         13 TIP: for my $tip ( map { @{ $_->get_terminals } } @{ $self->get_entities } ) {
  18         39  
  18         238  
  8         29  
167 120 50 33     253 next TIP if $tip->get_taxon && $taxa->contains($tip->get_taxon);
168 120         408 my $name = $tip->get_internal_name;
169 120 100       229 if ( not $tips{$name} ) {
170 78         166 $tips{$name} = [];
171             }
172 120         140 push @{ $tips{$name} }, $tip;
  120         221  
173             }
174            
175             # build a hash of the available taxa
176 8         22 my %taxa = map { $_->get_internal_name => $_ } @{ $taxa->get_entities };
  79         212  
  8         27  
177            
178             # iterate over unlinked tip
179 8         44 for my $name ( keys %tips ) {
180 78         246 $logger->debug("linking tip $name");
181            
182             # tip not seen yet, creating new
183 78 50       150 if ( not exists $taxa{$name} ) {
184 0         0 $logger->debug("no taxon object for $name yet, instantiating");
185 0         0 $taxa->insert( $taxa{$name} = $factory->create_taxon( '-name' => $name ) );
186             }
187            
188             # link tips to newly created taxon
189 78         104 for my $tip ( @{ $tips{$name} } ) {
  78         142  
190 120         264 $tip->set_taxon( $taxa{$name} );
191             }
192             }
193             }
194              
195             # not linked
196             else {
197 0         0 for my $tree ( @{ $self->get_entities } ) {
  0         0  
198 0         0 for my $node ( @{ $tree->get_entities } ) {
  0         0  
199 0         0 $node->set_taxon();
200             }
201             }
202             }
203 8         27 return $self;
204             }
205              
206             =item make_consensus()
207              
208             Creates a consensus tree.
209              
210             Type : Method
211             Title : make_consensus
212             Usage : my $tree = $obj->make_consensus
213             Function: Creates a consensus tree
214             Returns : $tree
215             Args : Optional:
216             -fraction => a fraction that specifies the cutoff frequency for including
217             bipartitions in the consensus. Default is 0.5 (MajRule)
218             -branches => 'frequency' or 'average', sets branch lengths to bipartition
219             frequency or average branch length in input trees
220             -summarize => 'fraction' or 'probability', sets node label as either the
221             fraction of this bipartition on the whole (e.g. "85/100") or
222             as a probability (e.g. "0.85")
223              
224             =cut
225              
226             sub make_consensus {
227 1     1 1 3 my $self = shift;
228 1         4 my %args = looks_like_hash @_;
229 1   50     5 my $perc = $args{'-fraction'} || 0.5;
230 1   50     7 my $branches = $args{'-branches'} || 'freq';
231 1         2 my %seen_partitions;
232             my %clade_lengths;
233 1         2 my $tree_count = 0;
234             my $average = sub {
235 5     5   11 my @list = @_;
236 5         6 my $sum = 0;
237 5         11 for my $val (@list) {
238 14 50       21 $sum += $val if defined $val;
239             }
240 5         11 my $avg = $sum / scalar @list;
241 5         27 return $avg;
242 1         7 };
243              
244             # here we populate a hash whose keys are strings identifying all bipartitions in all trees
245             # in the forest. Because we construct these strings by concatenating (with an unlikely
246             # separator) all tips in that clade after sorting them alphabetically, we will get
247             # the same string in topologically identical clades across trees. We use these keys
248             # to keep a running tally of all seen bipartitions.
249 1         2 for my $tree ( @{ $self->get_entities } ) {
  1         13  
250 3         5 for my $node ( @{ $tree->get_internals } ) {
  3         25  
251              
252             # whoever puts this string in their input tree gets what he deserves!
253             my $clade =
254             join '!\@\$%^&****unlikely_clade_separator***!\@\$%^&****',
255 12         34 sort { $a cmp $b }
256 6         8 map { $_->get_internal_name } @{ $node->get_terminals };
  15         36  
  6         22  
257 6         17 $seen_partitions{$clade}++;
258 6 100       13 if ( not exists $clade_lengths{$clade} ) {
259 3         6 $clade_lengths{$clade} = [];
260             }
261 6         10 push @{ $clade_lengths{$clade} }, $node->get_branch_length;
  6         17  
262             }
263 3         7 for my $tip ( @{ $tree->get_terminals } ) {
  3         16  
264 9         43 my $clade = $tip->get_internal_name;
265 9 100       24 if ( not exists $clade_lengths{$clade} ) {
266 3         7 $clade_lengths{$clade} = [];
267             }
268 9         13 push @{ $clade_lengths{$clade} }, $tip->get_branch_length;
  9         26  
269             }
270 3         7 $tree_count++;
271             }
272              
273             # here we remove the seen bipartitions that occur in fewer trees than in the specified
274             # fraction
275             my @by_size =
276 1         21 sort { $seen_partitions{$b} <=> $seen_partitions{$a} }
  3         9  
277             keys %seen_partitions;
278 1         3 my $largest = shift @by_size;
279 1         3 my @partitions = keys %seen_partitions;
280 1         2 for my $partition (@partitions) {
281 3 100       13 if ( ( $seen_partitions{$partition} / $tree_count ) <= $perc ) {
282 1         4 delete $seen_partitions{$partition};
283             }
284             }
285              
286             # we now sort the clade strings by size, which automatically means once we start
287             # traversing them that we will visit the bipartitions in the right nesting order
288 1         4 my @sorted = sort { length($b) <=> length($a) } keys %seen_partitions;
  1         5  
289 1         2 my %seen_nodes;
290 1         13 my $tree = $factory->create_tree;
291 1 50       7 if ( @sorted == 0 ) {
292 0         0 push @sorted, $largest;
293 0         0 $seen_partitions{$largest} = $tree_count;
294             }
295 1         3 for my $partition (@sorted) {
296              
297             # now create the individual tip names again from the key string
298 2         12 my @tips =
299             split /\Q!\@\$%^&****unlikely_clade_separator***!\@\$%^&****\E/,
300             $partition;
301              
302             # create the tip object if we haven't done so already
303 2         4 for my $tip (@tips) {
304 5 100       12 if ( not exists $seen_nodes{$tip} ) {
305 3         16 my $node = $factory->create_node( '-name' => $tip );
306 3 50       13 if ( $branches =~ /^f/i ) {
307 3         12 $node->set_branch_length(1.0);
308             $node->set_generic( 'average_branch_length' =>
309 3         4 $average->( @{ $clade_lengths{$tip} } ) );
  3         9  
310             }
311             else {
312             $node->set_branch_length(
313 0         0 $average->( @{ $clade_lengths{$tip} } ) );
  0         0  
314 0         0 $node->set_generic( 'bipartition_frequency' => 1.0 );
315             }
316 3         6 $seen_nodes{$tip} = $node;
317 3         10 $tree->insert($node);
318             }
319             }
320              
321             # create the new parent node
322 2         19 my $new_parent = $factory->create_node();
323 2 50       10 if ( $branches =~ /^f/i ) {
324             $new_parent->set_branch_length(
325 2         10 $seen_partitions{$partition} / $tree_count );
326             $new_parent->set_name(
327 2         4 $average->( @{ $clade_lengths{$partition} } ) );
  2         13  
328             }
329             else {
330 0         0 $new_parent->set_branch_length( $average->( @{ $clade_lengths{$partition} } ) );
  0         0  
331 0 0       0 if ( $args{'-summarize'} =~ /^f/i ) {
332 0         0 $new_parent->set_name( $seen_partitions{$partition} .'/'. $tree_count );
333             }
334             else {
335 0         0 $new_parent->set_name( $seen_partitions{$partition} / $tree_count );
336             }
337             }
338 2         9 $tree->insert($new_parent);
339              
340             # check to see if there is an old parent node: we want to squeeze the new parent
341             # node between the old parent and its children
342 2         7 my $old_parent = $seen_nodes{ $tips[0] }->get_parent;
343 2 100       6 if ($old_parent) {
344 1         4 $new_parent->set_parent($old_parent);
345             }
346              
347             # now assign the new parent to the tips in the current bipartition
348 2         5 for my $tip (@tips) {
349 5         10 my $node = $seen_nodes{$tip};
350 5         12 $node->set_parent($new_parent);
351             }
352             }
353              
354             # theoretically, the root length should be 1.0 because this "partition is present
355             # in all trees. But it's too much trouble to stick :-)
356 1         5 $tree->get_root->set_branch_length();
357 1         19 return $tree;
358             }
359              
360             =item make_matrix()
361              
362             Creates an MRP matrix object.
363              
364             Type : Method
365             Title : make_matrix
366             Usage : my $matrix = $obj->make_matrix
367             Function: Creates an MRP matrix object
368             Returns : $matrix
369             Args : NONE
370              
371             =cut
372              
373             sub make_matrix {
374 0     0 1 0 my $self = shift;
375 0         0 my $taxa = $self->make_taxa;
376 0         0 my $matrix = $factory->create_matrix;
377 0         0 $matrix->set_taxa($taxa);
378 0         0 my ( %data, @charlabels, @statelabels );
379 0         0 for my $taxon ( @{ $taxa->get_entities } ) {
  0         0  
380 0         0 my $datum = $factory->create_datum;
381 0         0 $datum->set_taxon($taxon);
382 0         0 $datum->set_name( $taxon->get_name );
383 0         0 $matrix->insert($datum);
384 0         0 $data{ $taxon->get_name } = [];
385             }
386             my $recursion = sub {
387 0     0   0 my ( $node, $tree, $taxa, $method ) = @_;
388 0         0 push @charlabels, $tree->get_internal_name;
389 0         0 push @statelabels, [ 'outgroup', $node->get_nexus_name ];
390             my %tip_values =
391 0         0 map { $_->get_name => 1 } @{ $node->get_terminals };
  0         0  
  0         0  
392 0         0 for my $tipname ( map { $_->get_name } @{ $tree->get_terminals } ) {
  0         0  
  0         0  
393 0 0       0 $tip_values{$tipname} = 0 if not exists $tip_values{$tipname};
394             }
395 0         0 for my $datumname ( keys %data ) {
396 0 0       0 if ( exists $tip_values{$datumname} ) {
397 0         0 push @{ $data{$datumname} }, $tip_values{$datumname};
  0         0  
398             }
399             else {
400 0         0 push @{ $data{$datumname} }, '?';
  0         0  
401             }
402             }
403             $method->( $_, $tree, $taxa, $method )
404 0         0 for grep { $_->is_internal } @{ $node->get_children };
  0         0  
  0         0  
405 0         0 };
406 0         0 for my $tree ( @{ $self->get_entities } ) {
  0         0  
407 0 0       0 if ( my $root = $tree->get_root ) {
408 0         0 $recursion->( $root, $tree, $taxa, $recursion );
409             }
410             }
411 0         0 for my $datum ( @{ $matrix->get_entities } ) {
  0         0  
412 0 0       0 if ( my $data = $data{ $datum->get_name } ) {
413 0 0       0 $datum->set_char( $data ) if @{ $data };
  0         0  
414             }
415             }
416 0         0 $matrix->set_charlabels( \@charlabels );
417 0         0 $matrix->set_statelabels( \@statelabels );
418 0         0 return $matrix;
419             }
420              
421             =item make_taxa()
422              
423             Creates a taxa block from the objects contents if none exists yet.
424              
425             Type : Method
426             Title : make_taxa
427             Usage : my $taxa = $obj->make_taxa
428             Function: Creates a taxa block from the objects contents if none exists yet.
429             Returns : $taxa
430             Args : NONE
431              
432             =cut
433              
434             sub make_taxa {
435 4     4 1 10 my $self = shift;
436 4 50       44 if ( my $taxa = $self->get_taxa ) {
437 0         0 return $taxa;
438             }
439             else {
440 4         7 my %taxa;
441 4         40 my $taxa = $factory->create_taxa;
442 4         9 for my $tree ( @{ $self->get_entities } ) {
  4         18  
443 8         16 for my $tip ( @{ $tree->get_terminals } ) {
  8         28  
444 81         231 my $name = $tip->get_internal_name;
445 81 100       160 if ( not $taxa{$name} ) {
446 65         271 $taxa{$name} =
447             $factory->create_taxon( '-name' => $name );
448             }
449             }
450             }
451 4 50       22 if (%taxa) {
452 65         110 $taxa->insert( map { $taxa{$_} }
453 4         44 sort { $a cmp $b } keys %taxa );
  219         238  
454             }
455 4         45 $self->set_taxa($taxa);
456 4         32 return $taxa;
457             }
458             }
459              
460             =item to_newick()
461              
462             Serializes invocant to newick string.
463              
464             Type : Stringifier
465             Title : to_newick
466             Usage : my $string = $forest->to_newick;
467             Function: Turns the invocant forest object
468             into a newick string, one line per tree
469             Returns : SCALAR
470             Args : The same arguments as
471             Bio::Phylo::Forest::Tree::to_newick
472              
473             =cut
474              
475             sub to_newick {
476 0     0 1 0 my $self = shift;
477 0         0 my $newick;
478 0         0 for my $tree ( @{ $self->get_entities } ) {
  0         0  
479 0         0 $newick .= $tree->to_newick(@_) . "\n";
480             }
481 0         0 return $newick;
482             }
483              
484             =item to_nexus()
485              
486             Serializer to nexus format.
487              
488             Type : Format convertor
489             Title : to_nexus
490             Usage : my $data_block = $matrix->to_nexus;
491             Function: Converts matrix object into a nexus data block.
492             Returns : Nexus data block (SCALAR).
493             Args : Trees can be formatted using the same arguments as those
494             passed to Bio::Phylo::Unparsers::Newick. In addition, you
495             can provide:
496            
497             # as per mesquite's inter-block linking system (default is false):
498             -links => 1 (to create a TITLE token, and a LINK token, if applicable)
499            
500             # rooting is determined based on basal trichotomy. "token" means 'TREE' or 'UTREE'
501             # is used, "comment" means [&R] or [&U] is used, "nhx" means [%unrooted=on] or
502             # [%unrooted=off] if used, default is "comment"
503             -rooting => one of (token|comment|nhx)
504            
505             # to map taxon names to indices (default is true)
506             -make_translate => 1 (autogenerate translation table, overrides -translate => {})
507            
508             # when making a translation table, which index to start (default is
509             # 1, BayesTraits needs 0)
510             -translate_start => 1
511             Comments:
512              
513             =cut
514              
515             sub to_nexus {
516 1     1 1 2 my $self = shift;
517 1         6 my %args = (
518             '-rooting' => 'comment',
519             '-make_translate' => 1,
520             '-translate_start' => 1,
521             @_
522             );
523 1         2 my %translate;
524             my $nexus;
525              
526             # make translation table
527 1 50       5 if ( $args{'-make_translate'} ) {
528 1         2 my $i = 0;
529 1         2 for my $tree ( @{ $self->get_entities } ) {
  1         4  
530 1         3 for my $node ( @{ $tree->get_terminals } ) {
  1         4  
531 18         21 my $name;
532 18 50 0     28 if ( not $args{'-tipnames'} ) {
    0          
    0          
533 18         50 $name = $node->get_nexus_name;
534             }
535             elsif ( $args{'-tipnames'} =~ /^internal$/i ) {
536 0         0 $name = $node->get_nexus_name;
537             }
538             elsif ( $args{'-tipnames'} =~ /^taxon/i
539             and $node->get_taxon )
540             {
541 0 0       0 if ( $args{'-tipnames'} =~ /^taxon_internal$/i ) {
    0          
542 0         0 $name = $node->get_taxon->get_nexus_name;
543             }
544             elsif ( $args{'-tipnames'} =~ /^taxon$/i ) {
545 0         0 $name = $node->get_taxon->get_nexus_name;
546             }
547             }
548             else {
549 0         0 $name = $node->get_generic( $args{'-tipnames'} );
550             }
551             $translate{$name} = ( $args{'-translate_start'} + $i++ )
552 18 50       62 if not exists $translate{$name};
553             }
554             }
555 1         10 $args{'-translate'} = \%translate;
556             }
557              
558             # create header
559 1         3 $nexus = "BEGIN TREES;\n";
560 1         14 $nexus .=
561             "[! Trees block written by "
562             . ref($self) . " "
563             . $self->VERSION . " on "
564             . localtime() . " ]\n";
565 1 50       6 if ( $args{'-figtree'} ) {
566 1         3 delete $args{'-figtree'};
567 1         6 $nexus .= "[! Tree(s) include FigTree node annotations ]\n";
568             }
569 1 50       3 if ( $args{'-links'} ) {
570 0         0 delete $args{'-links'};
571 0         0 $nexus .= "\tTITLE " . $self->get_nexus_name . ";\n";
572 0 0       0 if ( my $taxa = $self->get_taxa ) {
573 0         0 $nexus .= "\tLINK TAXA=" . $taxa->get_nexus_name . ";\n";
574             }
575             }
576              
577             # stringify translate table
578 1 50       3 if ( $args{'-make_translate'} ) {
579 1         2 delete $args{'-make_translate'};
580 1         3 $nexus .= "\tTRANSLATE\n";
581 1         2 my @translate;
582 1         6 for ( keys %translate ) { $translate[ $translate{$_} - 1 ] = $_ }
  18         32  
583 1         5 for my $i ( 0 .. $#translate ) {
584 18         40 $nexus .= "\t\t" . ( $i + 1 ) . " " . $translate[$i];
585 18 100       24 if ( $i == $#translate ) {
586 1         4 $nexus .= ";\n";
587             }
588             else {
589 17         20 $nexus .= ",\n";
590             }
591             }
592             }
593              
594             # stringify trees
595 1         3 for my $tree ( @{ $self->get_entities } ) {
  1         4  
596 1 50       8 if ( $tree->is_rooted ) {
597 1 50       9 if ( $args{'-rooting'} =~ /^token$/i ) {
    50          
    0          
598 0         0 $nexus .=
599             "\tTREE "
600             . $tree->get_nexus_name . ' = '
601             . $tree->to_newick(%args) . "\n";
602             }
603             elsif ( $args{'-rooting'} =~ /^comment$/i ) {
604 1         17 $nexus .=
605             "\tTREE "
606             . $tree->get_nexus_name
607             . ' = [&R] '
608             . $tree->to_newick(%args) . "\n";
609             }
610             elsif ( $args{'-rooting'} =~ /^nhx/i ) {
611 0         0 $tree->get_root->set_generic( 'unrooted' => 'off' );
612 0 0       0 if ( $args{'-nhxkeys'} ) {
613 0         0 push @{ $args{'-nhxkeys'} }, 'unrooted';
  0         0  
614             }
615             else {
616 0         0 $args{'-nhxkeys'} = ['unrooted'];
617             }
618 0         0 $nexus .=
619             "\tTREE "
620             . $tree->get_nexus_name . ' = '
621             . $tree->to_newick(%args) . "\n";
622             }
623             }
624             else {
625 0 0       0 if ( $args{'-rooting'} =~ /^token$/i ) {
    0          
    0          
626 0         0 $nexus .=
627             "\tUTREE "
628             . $tree->get_nexus_name . ' = '
629             . $tree->to_newick(%args) . "\n";
630             }
631             elsif ( $args{'-rooting'} =~ /^comment$/i ) {
632 0         0 $nexus .=
633             "\tTREE "
634             . $tree->get_nexus_name
635             . ' = [&U] '
636             . $tree->to_newick(%args) . "\n";
637             }
638             elsif ( $args{'-rooting'} =~ /^nhx/i ) {
639 0         0 $tree->get_root->set_generic( 'unrooted' => 'on' );
640 0 0       0 if ( $args{'-nhxkeys'} ) {
641 0         0 push @{ $args{'-nhxkeys'} }, 'unrooted';
  0         0  
642             }
643             else {
644 0         0 $args{'-nhxkeys'} = ['unrooted'];
645             }
646 0         0 $nexus .=
647             "\tTREE "
648             . $tree->get_nexus_name . ' = '
649             . $tree->to_newick(%args) . "\n";
650             }
651             }
652             }
653              
654             # done!
655 1         4 $nexus .= "END;\n";
656 1         18 return $nexus;
657             }
658              
659             =begin comment
660              
661             Type : Internal method
662             Title : _container
663             Usage : $trees->_container;
664             Function:
665             Returns : CONSTANT
666             Args :
667              
668             =end comment
669              
670             =cut
671              
672 31     31   54 sub _container { $CONTAINER_CONSTANT }
673              
674             =begin comment
675              
676             Type : Internal method
677             Title : _type
678             Usage : $trees->_type;
679             Function:
680             Returns : CONSTANT
681             Args :
682              
683             =end comment
684              
685             =cut
686              
687 608     608   1131 sub _type { $CONSTANT_TYPE }
688 0     0     sub _tag { 'trees' }
689              
690             =back
691              
692             =cut
693              
694             # podinherit_insert_token
695              
696             =head1 SEE ALSO
697              
698             There is a mailing list at L<https://groups.google.com/forum/#!forum/bio-phylo>
699             for any user or developer questions and discussions.
700              
701             =over
702              
703             =item L<Bio::Phylo::Listable>
704              
705             The forest object inherits from the L<Bio::Phylo::Listable>
706             object. The methods defined therein are applicable to forest objects.
707              
708             =item L<Bio::Phylo::Taxa::TaxaLinker>
709              
710             The forest object inherits from the L<Bio::Phylo::Taxa::TaxaLinker>
711             object. The methods defined therein are applicable to forest objects.
712              
713             =item L<Bio::Phylo::Manual>
714              
715             Also see the manual: L<Bio::Phylo::Manual> and L<http://rutgervos.blogspot.com>.
716              
717             =back
718              
719             =head1 CITATION
720              
721             If you use Bio::Phylo in published research, please cite it:
722              
723             B<Rutger A Vos>, B<Jason Caravas>, B<Klaas Hartmann>, B<Mark A Jensen>
724             and B<Chase Miller>, 2011. Bio::Phylo - phyloinformatic analysis using Perl.
725             I<BMC Bioinformatics> B<12>:63.
726             L<http://dx.doi.org/10.1186/1471-2105-12-63>
727              
728             =cut
729              
730             }
731             1;