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