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; |