File Coverage

blib/lib/Bio/Phylo/Forest.pm
Criterion Covered Total %
statement 186 292 63.7
branch 41 102 40.2
condition 3 10 30.0
subroutine 15 20 75.0
pod 9 9 100.0
total 254 433 58.6


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