| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Bio::Phylo::Matrices::Datatype; |
|
2
|
16
|
|
|
16
|
|
93
|
use strict; |
|
|
16
|
|
|
|
|
31
|
|
|
|
16
|
|
|
|
|
463
|
|
|
3
|
16
|
|
|
16
|
|
72
|
use base 'Bio::Phylo::NeXML::Writable'; |
|
|
16
|
|
|
|
|
29
|
|
|
|
16
|
|
|
|
|
1884
|
|
|
4
|
16
|
|
|
16
|
|
94
|
use Bio::Phylo::Factory; |
|
|
16
|
|
|
|
|
27
|
|
|
|
16
|
|
|
|
|
89
|
|
|
5
|
16
|
|
|
16
|
|
74
|
use Bio::Phylo::Util::Exceptions 'throw'; |
|
|
16
|
|
|
|
|
26
|
|
|
|
16
|
|
|
|
|
613
|
|
|
6
|
16
|
|
|
16
|
|
83
|
use Bio::Phylo::Util::CONSTANT qw'_DOMCREATOR_ _DATATYPE_ /looks_like/'; |
|
|
16
|
|
|
|
|
29
|
|
|
|
16
|
|
|
|
|
3962
|
|
|
7
|
|
|
|
|
|
|
{ |
|
8
|
|
|
|
|
|
|
my $logger = __PACKAGE__->get_logger; |
|
9
|
|
|
|
|
|
|
my $fac = Bio::Phylo::Factory->new(); |
|
10
|
|
|
|
|
|
|
my @fields = \( my ( %lookup, %missing, %gap, %meta ) ); |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 NAME |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Bio::Phylo::Matrices::Datatype - Validator of character state data |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# No direct usage |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
This is a superclass for objects that validate character data. Objects that |
|
23
|
|
|
|
|
|
|
inherit from this class (typically those in the |
|
24
|
|
|
|
|
|
|
Bio::Phylo::Matrices::Datatype::* namespace) can check strings and arrays of |
|
25
|
|
|
|
|
|
|
character data for invalid symbols, and split and join strings and arrays |
|
26
|
|
|
|
|
|
|
in a way appropriate for the type (on whitespace for continuous data, |
|
27
|
|
|
|
|
|
|
on single characters for categorical data). |
|
28
|
|
|
|
|
|
|
L<Bio::Phylo::Matrices::Matrix> objects and L<Bio::Phylo::Matrices::Datum> |
|
29
|
|
|
|
|
|
|
internally delegate validation of their contents to these datatype objects; |
|
30
|
|
|
|
|
|
|
there is no normal usage in which you'd have to deal with datatype objects |
|
31
|
|
|
|
|
|
|
directly. |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=head1 METHODS |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head2 CONSTRUCTOR |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=over |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=item new() |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
Datatype constructor. |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
Type : Constructor |
|
44
|
|
|
|
|
|
|
Title : new |
|
45
|
|
|
|
|
|
|
Usage : No direct usage, is called by TypeSafeData classes; |
|
46
|
|
|
|
|
|
|
Function: Instantiates a Datatype object |
|
47
|
|
|
|
|
|
|
Returns : a Bio::Phylo::Matrices::Datatype child class |
|
48
|
|
|
|
|
|
|
Args : $type (optional, one of continuous, custom, dna, |
|
49
|
|
|
|
|
|
|
mixed, protein, restriction, rna, standard) |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=cut |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub new : Constructor { |
|
54
|
837
|
|
|
837
|
1
|
1883
|
my $class = shift; |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# constructor called with type string |
|
57
|
837
|
100
|
|
|
|
2255
|
if ( $class eq __PACKAGE__ ) { |
|
58
|
787
|
|
|
|
|
2538
|
my $type = ucfirst( lc(shift) ); |
|
59
|
787
|
50
|
|
|
|
1994
|
if ( not $type ) { |
|
60
|
0
|
|
|
|
|
0
|
throw 'BadArgs' => "No subtype specified!"; |
|
61
|
|
|
|
|
|
|
} |
|
62
|
787
|
100
|
|
|
|
2257
|
if ( $type eq 'Nucleotide' ) { |
|
63
|
1
|
|
|
|
|
4
|
$logger->warn("'nucleotide' datatype requested, using 'dna'"); |
|
64
|
1
|
|
|
|
|
2
|
$type = 'Dna'; |
|
65
|
|
|
|
|
|
|
} |
|
66
|
787
|
|
|
|
|
3170
|
return looks_like_class( __PACKAGE__ . '::' . $type ) |
|
67
|
|
|
|
|
|
|
->SUPER::new(@_); |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# constructor called from type subclass |
|
71
|
|
|
|
|
|
|
else { |
|
72
|
50
|
|
|
|
|
144
|
my %args = looks_like_hash @_; |
|
73
|
|
|
|
|
|
|
{ |
|
74
|
16
|
|
|
16
|
|
97
|
no strict 'refs'; |
|
|
16
|
|
|
|
|
32
|
|
|
|
16
|
|
|
|
|
1443
|
|
|
|
0
|
|
|
|
|
0
|
|
|
75
|
50
|
|
|
|
|
143
|
$args{'-lookup'} = ${"${class}::LOOKUP"} |
|
76
|
50
|
50
|
|
|
|
78
|
if ${"${class}::LOOKUP"}; |
|
|
50
|
|
|
|
|
208
|
|
|
77
|
50
|
|
|
|
|
127
|
$args{'-missing'} = ${"${class}::MISSING"} |
|
78
|
50
|
50
|
|
|
|
64
|
if ${"${class}::MISSING"}; |
|
|
50
|
|
|
|
|
160
|
|
|
79
|
50
|
100
|
|
|
|
71
|
$args{'-gap'} = ${"${class}::GAP"} if ${"${class}::GAP"}; |
|
|
10
|
|
|
|
|
36
|
|
|
|
50
|
|
|
|
|
154
|
|
|
80
|
16
|
|
|
16
|
|
86
|
use strict; |
|
|
16
|
|
|
|
|
34
|
|
|
|
16
|
|
|
|
|
848
|
|
|
81
|
|
|
|
|
|
|
} |
|
82
|
50
|
|
|
|
|
73
|
return $class->SUPER::new(%args); |
|
|
50
|
|
|
|
|
166
|
|
|
83
|
|
|
|
|
|
|
} |
|
84
|
16
|
|
|
16
|
|
80
|
} |
|
|
16
|
|
|
|
|
35
|
|
|
|
16
|
|
|
|
|
82
|
|
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=back |
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=head2 MUTATORS |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=over |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=item set_lookup() |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Sets state lookup table. |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
Type : Mutator |
|
97
|
|
|
|
|
|
|
Title : set_lookup |
|
98
|
|
|
|
|
|
|
Usage : $obj->set_lookup($hashref); |
|
99
|
|
|
|
|
|
|
Function: Sets the state lookup table. |
|
100
|
|
|
|
|
|
|
Returns : Modified object. |
|
101
|
|
|
|
|
|
|
Args : Argument must be a hash |
|
102
|
|
|
|
|
|
|
reference that maps allowed |
|
103
|
|
|
|
|
|
|
single character symbols |
|
104
|
|
|
|
|
|
|
(including ambiguity symbols) |
|
105
|
|
|
|
|
|
|
onto the equivalent set of |
|
106
|
|
|
|
|
|
|
non-ambiguous symbols |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=cut |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub set_lookup : Clonable { |
|
111
|
756
|
|
|
756
|
1
|
1982
|
my ( $self, $lookup ) = @_; |
|
112
|
756
|
|
|
|
|
1979
|
my $id = $self->get_id; |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# we have a value |
|
115
|
756
|
50
|
|
|
|
1927
|
if ( defined $lookup ) { |
|
116
|
756
|
50
|
|
|
|
2364
|
if ( looks_like_instance $lookup, 'HASH' ) { |
|
117
|
756
|
|
|
|
|
2191
|
$lookup{$id} = $lookup; |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
else { |
|
120
|
0
|
|
|
|
|
0
|
throw 'BadArgs' => "lookup must be a hash reference"; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# no value, so must be a reset |
|
125
|
|
|
|
|
|
|
else { |
|
126
|
0
|
|
|
|
|
0
|
$lookup{$id} = $self->get_lookup; |
|
127
|
|
|
|
|
|
|
} |
|
128
|
756
|
|
|
|
|
2099
|
return $self; |
|
129
|
16
|
|
|
16
|
|
4098
|
} |
|
|
16
|
|
|
|
|
31
|
|
|
|
16
|
|
|
|
|
52
|
|
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=item set_missing() |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
Sets missing data symbol. |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Type : Mutator |
|
136
|
|
|
|
|
|
|
Title : set_missing |
|
137
|
|
|
|
|
|
|
Usage : $obj->set_missing('?'); |
|
138
|
|
|
|
|
|
|
Function: Sets the symbol for missing data |
|
139
|
|
|
|
|
|
|
Returns : Modified object. |
|
140
|
|
|
|
|
|
|
Args : Argument must be a single |
|
141
|
|
|
|
|
|
|
character, default is '?' |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=cut |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub set_missing : Clonable { |
|
146
|
109
|
|
|
109
|
1
|
211
|
my ( $self, $missing ) = @_; |
|
147
|
109
|
|
|
|
|
251
|
my $id = $self->get_id; |
|
148
|
109
|
50
|
|
|
|
247
|
if ( $missing ne $self->get_gap ) { |
|
149
|
109
|
|
|
|
|
218
|
$missing{$id} = $missing; |
|
150
|
|
|
|
|
|
|
} |
|
151
|
|
|
|
|
|
|
else { |
|
152
|
0
|
|
|
|
|
0
|
throw 'BadArgs' => |
|
153
|
|
|
|
|
|
|
"Missing character '$missing' already in use as gap character"; |
|
154
|
|
|
|
|
|
|
} |
|
155
|
109
|
|
|
|
|
222
|
return $self; |
|
156
|
16
|
|
|
16
|
|
3691
|
} |
|
|
16
|
|
|
|
|
31
|
|
|
|
16
|
|
|
|
|
55
|
|
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=item set_gap() |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
Sets gap symbol. |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Type : Mutator |
|
163
|
|
|
|
|
|
|
Title : set_gap |
|
164
|
|
|
|
|
|
|
Usage : $obj->set_gap('-'); |
|
165
|
|
|
|
|
|
|
Function: Sets the symbol for gaps |
|
166
|
|
|
|
|
|
|
Returns : Modified object. |
|
167
|
|
|
|
|
|
|
Args : Argument must be a single |
|
168
|
|
|
|
|
|
|
character, default is '-' |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=cut |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub set_gap : Clonable { |
|
173
|
69
|
|
|
69
|
1
|
146
|
my ( $self, $gap ) = @_; |
|
174
|
69
|
50
|
|
|
|
192
|
if ( not $gap eq $self->get_missing ) { |
|
175
|
69
|
|
|
|
|
208
|
$gap{ $self->get_id } = $gap; |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
else { |
|
178
|
0
|
|
|
|
|
0
|
throw 'BadArgs' => |
|
179
|
|
|
|
|
|
|
"Gap character '$gap' already in use as missing character"; |
|
180
|
|
|
|
|
|
|
} |
|
181
|
69
|
|
|
|
|
171
|
return $self; |
|
182
|
16
|
|
|
16
|
|
3499
|
} |
|
|
16
|
|
|
|
|
34
|
|
|
|
16
|
|
|
|
|
62
|
|
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=item set_metas_for_states() |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
Assigns all metadata annotations for all state symbols |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
Type : Mutator |
|
189
|
|
|
|
|
|
|
Title : set_metas_for_states |
|
190
|
|
|
|
|
|
|
Usage : $obj->set_metas_for_states({ $state => [ $m1, $m2 ] }); |
|
191
|
|
|
|
|
|
|
Function: Assigns all metadata annotations for all state symbols |
|
192
|
|
|
|
|
|
|
Returns : Modified object. |
|
193
|
|
|
|
|
|
|
Args : A hash reference of state symbols with metadata arrays |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=cut |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
sub set_metas_for_states : Clonable { |
|
198
|
50
|
|
|
50
|
1
|
94
|
my ( $self, $metas ) = @_; |
|
199
|
50
|
|
|
|
|
121
|
$meta{$self->get_id} = $metas; |
|
200
|
50
|
|
|
|
|
126
|
return $self; |
|
201
|
16
|
|
|
16
|
|
2833
|
} |
|
|
16
|
|
|
|
|
32
|
|
|
|
16
|
|
|
|
|
63
|
|
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=item add_meta_for_state() |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
Adds a metadata annotation for a state symbol |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
Type : Mutator |
|
208
|
|
|
|
|
|
|
Title : add_meta_for_state |
|
209
|
|
|
|
|
|
|
Usage : $obj->add_meta_for_state($meta,$state); |
|
210
|
|
|
|
|
|
|
Function: Adds a metadata annotation for a state symbol |
|
211
|
|
|
|
|
|
|
Returns : Modified object. |
|
212
|
|
|
|
|
|
|
Args : A Bio::Phylo::NeXML::Meta object and a state symbol |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=cut |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub add_meta_for_state { |
|
217
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $meta, $state ) = @_; |
|
218
|
0
|
0
|
|
|
|
0
|
if ( my $lookup = $self->get_lookup ) { |
|
219
|
0
|
0
|
|
|
|
0
|
if ( exists $lookup->{$state} ) { |
|
220
|
0
|
|
|
|
|
0
|
my $id = $self->get_id; |
|
221
|
0
|
0
|
|
|
|
0
|
$meta{$id} = {} if not $meta{$id}; |
|
222
|
0
|
0
|
|
|
|
0
|
$meta{$id}->{$state} = [] if not $meta{$id}->{$state}; |
|
223
|
0
|
|
|
|
|
0
|
push @{ $meta{$id}->{$state} }, $meta; |
|
|
0
|
|
|
|
|
0
|
|
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
else { |
|
226
|
0
|
|
|
|
|
0
|
$logger->warn( |
|
227
|
|
|
|
|
|
|
"State '$state' is unknown, can't add annotation"); |
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
} |
|
230
|
|
|
|
|
|
|
else { |
|
231
|
0
|
|
|
|
|
0
|
$logger->warn( |
|
232
|
|
|
|
|
|
|
"This data type has no categorical states to annotate"); |
|
233
|
|
|
|
|
|
|
} |
|
234
|
0
|
|
|
|
|
0
|
return $self; |
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=item remove_meta_for_state() |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
Removes a metadata annotation for a state symbol |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Type : Mutator |
|
242
|
|
|
|
|
|
|
Title : remove_meta_for_state |
|
243
|
|
|
|
|
|
|
Usage : $obj->remove_meta_for_state($meta,$state); |
|
244
|
|
|
|
|
|
|
Function: Removes a metadata annotation for a state symbol |
|
245
|
|
|
|
|
|
|
Returns : Modified object. |
|
246
|
|
|
|
|
|
|
Args : A Bio::Phylo::NeXML::Meta object and a state symbol |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=cut |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
sub remove_meta_for_state { |
|
251
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $meta, $state ) = @_; |
|
252
|
0
|
|
|
|
|
0
|
my $id = $self->get_id; |
|
253
|
0
|
0
|
0
|
|
|
0
|
if ( $meta{$id} && $meta{$id}->{$state} ) { |
|
254
|
0
|
|
|
|
|
0
|
my $meta_array = $meta{$id}->{$state}; |
|
255
|
0
|
|
|
|
|
0
|
my $meta_id = $meta->get_id; |
|
256
|
0
|
|
|
|
|
0
|
DICT: for my $i ( 0 .. $#{$meta_array} ) { |
|
|
0
|
|
|
|
|
0
|
|
|
257
|
0
|
0
|
|
|
|
0
|
if ( $meta_array->[$i]->get_id == $meta_id ) { |
|
258
|
0
|
|
|
|
|
0
|
splice @{$meta_array}, $i, 1; |
|
|
0
|
|
|
|
|
0
|
|
|
259
|
0
|
|
|
|
|
0
|
last DICT; |
|
260
|
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
} |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
else { |
|
264
|
0
|
|
|
|
|
0
|
$logger->warn( |
|
265
|
|
|
|
|
|
|
"There are no annotations to remove for state '$state'"); |
|
266
|
|
|
|
|
|
|
} |
|
267
|
0
|
|
|
|
|
0
|
return $self; |
|
268
|
|
|
|
|
|
|
} |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=back |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=head2 ACCESSORS |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=over |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=item get_type() |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
Gets data type as string. |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
Type : Accessor |
|
281
|
|
|
|
|
|
|
Title : get_type |
|
282
|
|
|
|
|
|
|
Usage : my $type = $obj->get_type; |
|
283
|
|
|
|
|
|
|
Function: Returns the object's datatype |
|
284
|
|
|
|
|
|
|
Returns : A string |
|
285
|
|
|
|
|
|
|
Args : None |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=cut |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub get_type { |
|
290
|
824
|
|
|
824
|
1
|
1810
|
my $type = ref shift; |
|
291
|
824
|
|
|
|
|
4758
|
$type =~ s/.*:://; |
|
292
|
824
|
|
|
|
|
3240
|
return $type; |
|
293
|
|
|
|
|
|
|
} |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=item get_ids_for_special_symbols() |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Gets state-to-id mapping for missing and gap symbols |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
Type : Accessor |
|
300
|
|
|
|
|
|
|
Title : get_ids_for_special_symbols |
|
301
|
|
|
|
|
|
|
Usage : my %ids = %{ $obj->get_ids_for_special_symbols }; |
|
302
|
|
|
|
|
|
|
Function: Returns state-to-id mapping |
|
303
|
|
|
|
|
|
|
Returns : A hash reference, keyed on symbol, with UID values |
|
304
|
|
|
|
|
|
|
Args : Optional, a boolean: |
|
305
|
|
|
|
|
|
|
true => prefix state ids with 's' |
|
306
|
|
|
|
|
|
|
false => keep ids numerical |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=cut |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
sub get_ids_for_special_symbols { |
|
311
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
312
|
0
|
|
|
|
|
0
|
my $ids_for_states = $self->get_ids_for_states; |
|
313
|
0
|
|
|
|
|
0
|
my @indices = sort { $a <=> $b } values %{$ids_for_states}; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
314
|
0
|
|
|
|
|
0
|
my $max_id = $indices[-1]; |
|
315
|
0
|
|
|
|
|
0
|
my ( $missing, $gap ) = ( $self->get_missing, $self->get_gap ); |
|
316
|
0
|
|
|
|
|
0
|
my $ids_for_special_symbols = {}; |
|
317
|
0
|
0
|
|
|
|
0
|
if ( $_[0] ) { |
|
318
|
0
|
|
|
|
|
0
|
$ids_for_special_symbols->{$gap} = 's' . ++$max_id; |
|
319
|
0
|
|
|
|
|
0
|
$ids_for_special_symbols->{$missing} = 's' . ++$max_id; |
|
320
|
|
|
|
|
|
|
} |
|
321
|
|
|
|
|
|
|
else { |
|
322
|
0
|
|
|
|
|
0
|
$ids_for_special_symbols->{$gap} = ++$max_id; |
|
323
|
0
|
|
|
|
|
0
|
$ids_for_special_symbols->{$missing} = ++$max_id; |
|
324
|
|
|
|
|
|
|
} |
|
325
|
0
|
|
|
|
|
0
|
return $ids_for_special_symbols; |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=item get_ids_for_states() |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
Gets state-to-id mapping |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
Type : Accessor |
|
333
|
|
|
|
|
|
|
Title : get_ids_for_states |
|
334
|
|
|
|
|
|
|
Usage : my %ids = %{ $obj->get_ids_for_states }; |
|
335
|
|
|
|
|
|
|
Function: Returns state-to-id mapping |
|
336
|
|
|
|
|
|
|
Returns : A hash reference, keyed on symbol, with UID values |
|
337
|
|
|
|
|
|
|
Args : Optional, a boolean: |
|
338
|
|
|
|
|
|
|
true => prefix state ids with 's' |
|
339
|
|
|
|
|
|
|
false => keep ids numerical |
|
340
|
|
|
|
|
|
|
Note : This returns a mapping to alphanumeric states; special |
|
341
|
|
|
|
|
|
|
symbols (for missing data and gaps) are handled separately |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=cut |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
sub get_ids_for_states { |
|
346
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
347
|
0
|
|
|
|
|
0
|
$logger->debug("getting ids for state set $self"); |
|
348
|
0
|
0
|
|
|
|
0
|
if ( my $lookup = $self->get_lookup ) { |
|
349
|
0
|
|
|
|
|
0
|
my $ids_for_states = {}; |
|
350
|
0
|
|
|
|
|
0
|
my ( @symbols, %tmp_cats, $i ); |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
# build a list of state symbols: what properties will this |
|
353
|
|
|
|
|
|
|
# list have? Symbols will be present in order of the |
|
354
|
|
|
|
|
|
|
# size of the state set to which they belong; within |
|
355
|
|
|
|
|
|
|
# each of these ranks, the symbols will be in lexical |
|
356
|
|
|
|
|
|
|
# order. |
|
357
|
0
|
|
0
|
|
|
0
|
push( @{ $tmp_cats{ @{ $lookup->{$_} } } ||= [] }, $_ ) |
|
|
0
|
|
|
|
|
0
|
|
|
358
|
0
|
|
|
|
|
0
|
for grep /^\d+|[a-zA-Z]/, keys %{$lookup}; |
|
|
0
|
|
|
|
|
0
|
|
|
359
|
0
|
|
|
|
|
0
|
push( @symbols, sort { $a cmp $b } @{ $tmp_cats{$_} } ) |
|
|
0
|
|
|
|
|
0
|
|
|
360
|
0
|
|
|
|
|
0
|
for sort { $a <=> $b } keys %tmp_cats; |
|
|
0
|
|
|
|
|
0
|
|
|
361
|
|
|
|
|
|
|
$ids_for_states->{$_} = ( $_[0] ? 's' : '' ) . ( ++$i ) |
|
362
|
0
|
0
|
|
|
|
0
|
for (@symbols); |
|
363
|
0
|
|
|
|
|
0
|
return $ids_for_states; |
|
364
|
|
|
|
|
|
|
} |
|
365
|
0
|
|
|
|
|
0
|
return {}; |
|
366
|
|
|
|
|
|
|
} |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
=item get_states_for_symbol() |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
Gets set of fundamental states for an ambiguity symbol |
|
371
|
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
Type : Accessor |
|
373
|
|
|
|
|
|
|
Title : get_states_for_symbol |
|
374
|
|
|
|
|
|
|
Usage : my @states = @{ $obj->get_states_for_symbol('N') }; |
|
375
|
|
|
|
|
|
|
Function: Returns the set of states for an ambiguity symbol |
|
376
|
|
|
|
|
|
|
Returns : An array ref of symbols |
|
377
|
|
|
|
|
|
|
Args : An ambiguity symbol |
|
378
|
|
|
|
|
|
|
Comments: If supplied argument is a fundamental state, an array |
|
379
|
|
|
|
|
|
|
ref with just that state is returned, e.g. 'A' returns |
|
380
|
|
|
|
|
|
|
['A'] for DNA and RNA |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=cut |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
sub get_states_for_symbol { |
|
385
|
82250
|
|
|
82250
|
1
|
151914
|
my ( $self, $symbol ) = @_; |
|
386
|
82250
|
|
|
|
|
115358
|
my @states; |
|
387
|
82250
|
50
|
|
|
|
138676
|
if ( my $lookup = $self->get_lookup ) { |
|
388
|
82250
|
50
|
|
|
|
227901
|
if ( my $map = $lookup->{uc $symbol} ) { |
|
389
|
82250
|
|
|
|
|
123580
|
@states = @{ $map }; |
|
|
82250
|
|
|
|
|
165362
|
|
|
390
|
|
|
|
|
|
|
} |
|
391
|
|
|
|
|
|
|
} |
|
392
|
82250
|
|
|
|
|
235066
|
return \@states; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=item get_symbol_for_states() |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
Gets ambiguity symbol for a set of states |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
Type : Accessor |
|
400
|
|
|
|
|
|
|
Title : get_symbol_for_states |
|
401
|
|
|
|
|
|
|
Usage : my $state = $obj->get_symbol_for_states('A','C'); |
|
402
|
|
|
|
|
|
|
Function: Returns the ambiguity symbol for a set of states |
|
403
|
|
|
|
|
|
|
Returns : A symbol (SCALAR) |
|
404
|
|
|
|
|
|
|
Args : A set of symbols |
|
405
|
|
|
|
|
|
|
Comments: If no symbol exists in the lookup |
|
406
|
|
|
|
|
|
|
table for the given set of states, |
|
407
|
|
|
|
|
|
|
a new - numerical - one is created |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=cut |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
sub get_symbol_for_states { |
|
412
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
413
|
0
|
|
|
|
|
0
|
my @syms = @_; |
|
414
|
0
|
|
|
|
|
0
|
my $lookup = $self->get_lookup; |
|
415
|
0
|
0
|
|
|
|
0
|
if ($lookup) { |
|
416
|
0
|
|
|
|
|
0
|
my @lookup_syms = keys %{$lookup}; |
|
|
0
|
|
|
|
|
0
|
|
|
417
|
0
|
|
|
|
|
0
|
SYM: for my $sym (@lookup_syms) { |
|
418
|
0
|
|
|
|
|
0
|
my @states = @{ $lookup->{$sym} }; |
|
|
0
|
|
|
|
|
0
|
|
|
419
|
0
|
0
|
|
|
|
0
|
if ( scalar @syms == scalar @states ) { |
|
420
|
0
|
|
|
|
|
0
|
my $seen_all = 0; |
|
421
|
0
|
|
|
|
|
0
|
for my $i ( 0 .. $#syms ) { |
|
422
|
0
|
|
|
|
|
0
|
my $seen = 0; |
|
423
|
0
|
|
|
|
|
0
|
for my $j ( 0 .. $#states ) { |
|
424
|
0
|
0
|
|
|
|
0
|
if ( $syms[$i] eq $states[$j] ) { |
|
425
|
0
|
|
|
|
|
0
|
$seen++; |
|
426
|
0
|
|
|
|
|
0
|
$seen_all++; |
|
427
|
|
|
|
|
|
|
} |
|
428
|
|
|
|
|
|
|
} |
|
429
|
0
|
0
|
|
|
|
0
|
next SYM if not $seen; |
|
430
|
|
|
|
|
|
|
} |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
# found existing symbol |
|
433
|
0
|
0
|
|
|
|
0
|
return $sym if $seen_all == scalar @syms; |
|
434
|
|
|
|
|
|
|
} |
|
435
|
|
|
|
|
|
|
} |
|
436
|
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
# create new symbol |
|
438
|
0
|
|
|
|
|
0
|
my $sym; |
|
439
|
0
|
0
|
|
|
|
0
|
if ( $self->get_type !~ /standard/i ) { |
|
440
|
0
|
|
|
|
|
0
|
my $sym = 0; |
|
441
|
0
|
|
|
|
|
0
|
while ( exists $lookup->{$sym} ) { |
|
442
|
0
|
|
|
|
|
0
|
$sym++; |
|
443
|
|
|
|
|
|
|
} |
|
444
|
|
|
|
|
|
|
} |
|
445
|
|
|
|
|
|
|
else { |
|
446
|
0
|
|
|
|
|
0
|
LETTER: for my $char ( 'A' .. 'Z' ) { |
|
447
|
0
|
0
|
|
|
|
0
|
if ( not exists $lookup->{$char} ) { |
|
448
|
0
|
|
|
|
|
0
|
$sym = $char; |
|
449
|
0
|
|
|
|
|
0
|
last LETTER; |
|
450
|
|
|
|
|
|
|
} |
|
451
|
|
|
|
|
|
|
} |
|
452
|
|
|
|
|
|
|
} |
|
453
|
0
|
|
|
|
|
0
|
$lookup->{$sym} = \@syms; |
|
454
|
0
|
|
|
|
|
0
|
$self->set_lookup($lookup); |
|
455
|
0
|
|
|
|
|
0
|
return $sym; |
|
456
|
|
|
|
|
|
|
} |
|
457
|
|
|
|
|
|
|
else { |
|
458
|
0
|
|
|
|
|
0
|
$logger->info("No lookup table!"); |
|
459
|
0
|
|
|
|
|
0
|
return; |
|
460
|
|
|
|
|
|
|
} |
|
461
|
|
|
|
|
|
|
} |
|
462
|
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
=item get_lookup() |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
Gets state lookup table. |
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
Type : Accessor |
|
468
|
|
|
|
|
|
|
Title : get_lookup |
|
469
|
|
|
|
|
|
|
Usage : my $lookup = $obj->get_lookup; |
|
470
|
|
|
|
|
|
|
Function: Returns the object's lookup hash |
|
471
|
|
|
|
|
|
|
Returns : A hash reference |
|
472
|
|
|
|
|
|
|
Args : None |
|
473
|
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=cut |
|
475
|
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
sub get_lookup { |
|
477
|
83130
|
|
|
83130
|
1
|
129371
|
my $self = shift; |
|
478
|
83130
|
|
|
|
|
166390
|
my $id = $self->get_id; |
|
479
|
83130
|
100
|
|
|
|
176279
|
if ( exists $lookup{$id} ) { |
|
480
|
82476
|
|
|
|
|
199977
|
return $lookup{$id}; |
|
481
|
|
|
|
|
|
|
} |
|
482
|
|
|
|
|
|
|
else { |
|
483
|
654
|
|
|
|
|
1595
|
my $class = __PACKAGE__; |
|
484
|
654
|
|
|
|
|
2522
|
$class .= '::' . $self->get_type; |
|
485
|
654
|
|
|
|
|
3550
|
$logger->debug("datatype class is $class"); |
|
486
|
654
|
50
|
|
|
|
2455
|
if ( looks_like_class $class ) { |
|
487
|
654
|
|
|
|
|
1225
|
my $lookup; |
|
488
|
|
|
|
|
|
|
{ |
|
489
|
16
|
|
|
16
|
|
17132
|
no strict 'refs'; |
|
|
16
|
|
|
|
|
35
|
|
|
|
16
|
|
|
|
|
598
|
|
|
|
0
|
|
|
|
|
0
|
|
|
490
|
654
|
|
|
|
|
1075
|
$lookup = ${ $class . '::LOOKUP' }; |
|
|
654
|
|
|
|
|
3156
|
|
|
491
|
16
|
|
|
16
|
|
79
|
use strict; |
|
|
16
|
|
|
|
|
27
|
|
|
|
16
|
|
|
|
|
12390
|
|
|
492
|
|
|
|
|
|
|
} |
|
493
|
654
|
|
|
|
|
1097
|
$self->set_lookup($lookup); |
|
|
654
|
|
|
|
|
2563
|
|
|
494
|
654
|
|
|
|
|
1829
|
return $lookup; |
|
495
|
|
|
|
|
|
|
} |
|
496
|
|
|
|
|
|
|
} |
|
497
|
|
|
|
|
|
|
} |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=item get_missing() |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
Gets missing data symbol. |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
Type : Accessor |
|
504
|
|
|
|
|
|
|
Title : get_missing |
|
505
|
|
|
|
|
|
|
Usage : my $missing = $obj->get_missing; |
|
506
|
|
|
|
|
|
|
Function: Returns the object's missing data symbol |
|
507
|
|
|
|
|
|
|
Returns : A string |
|
508
|
|
|
|
|
|
|
Args : None |
|
509
|
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
=cut |
|
511
|
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
sub get_missing { |
|
513
|
1643
|
|
|
1643
|
1
|
2906
|
my $self = shift; |
|
514
|
1643
|
|
|
|
|
3994
|
my $missing = $missing{ $self->get_id }; |
|
515
|
1643
|
100
|
|
|
|
6208
|
return defined $missing ? $missing : '?'; |
|
516
|
|
|
|
|
|
|
} |
|
517
|
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
=item get_gap() |
|
519
|
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
Gets gap symbol. |
|
521
|
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
Type : Accessor |
|
523
|
|
|
|
|
|
|
Title : get_gap |
|
524
|
|
|
|
|
|
|
Usage : my $gap = $obj->get_gap; |
|
525
|
|
|
|
|
|
|
Function: Returns the object's gap symbol |
|
526
|
|
|
|
|
|
|
Returns : A string |
|
527
|
|
|
|
|
|
|
Args : None |
|
528
|
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
=cut |
|
530
|
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
sub get_gap { |
|
532
|
950
|
|
|
950
|
1
|
1566
|
my $self = shift; |
|
533
|
950
|
|
|
|
|
2143
|
my $gap = $gap{ $self->get_id }; |
|
534
|
950
|
100
|
|
|
|
2644
|
return defined $gap ? $gap : '-'; |
|
535
|
|
|
|
|
|
|
} |
|
536
|
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
=item get_meta_for_state() |
|
538
|
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
Gets metadata annotations (if any) for the provided state symbol |
|
540
|
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
Type : Accessor |
|
542
|
|
|
|
|
|
|
Title : get_meta_for_state |
|
543
|
|
|
|
|
|
|
Usage : my @meta = @{ $obj->get_meta_for_state }; |
|
544
|
|
|
|
|
|
|
Function: Gets metadata annotations for a state symbol |
|
545
|
|
|
|
|
|
|
Returns : An array reference of Bio::Phylo::NeXML::Meta objects |
|
546
|
|
|
|
|
|
|
Args : A state symbol |
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
=cut |
|
549
|
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
sub get_meta_for_state { |
|
551
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $state ) = @_; |
|
552
|
0
|
|
|
|
|
0
|
my $id = $self->get_id; |
|
553
|
0
|
0
|
0
|
|
|
0
|
if ( $meta{$id} && $meta{$id}->{$state} ) { |
|
554
|
0
|
|
|
|
|
0
|
return $meta{$id}->{$state}; |
|
555
|
|
|
|
|
|
|
} |
|
556
|
0
|
|
|
|
|
0
|
return []; |
|
557
|
|
|
|
|
|
|
} |
|
558
|
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=item get_metas_for_states() |
|
560
|
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
Gets metadata annotations (if any) for all state symbols |
|
562
|
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
Type : Accessor |
|
564
|
|
|
|
|
|
|
Title : get_metas_for_states |
|
565
|
|
|
|
|
|
|
Usage : my @meta = @{ $obj->get_metas_for_states }; |
|
566
|
|
|
|
|
|
|
Function: Gets metadata annotations for state symbols |
|
567
|
|
|
|
|
|
|
Returns : An array reference of Bio::Phylo::NeXML::Meta objects |
|
568
|
|
|
|
|
|
|
Args : None |
|
569
|
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
=cut |
|
571
|
|
|
|
|
|
|
|
|
572
|
50
|
|
|
50
|
1
|
111
|
sub get_metas_for_states { $meta{shift->get_id} } |
|
573
|
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
=back |
|
575
|
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
=head2 TESTS |
|
577
|
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
=over |
|
579
|
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
=item is_ambiguous() |
|
581
|
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
Tests whether the supplied state symbol represents an ambiguous (polymorphic |
|
583
|
|
|
|
|
|
|
or uncertain) state. For example, for the most commonly-used alphabet for |
|
584
|
|
|
|
|
|
|
DNA states, the symbol 'N' represents complete uncertainty, the actual state |
|
585
|
|
|
|
|
|
|
could be any of 'A', 'C', 'G' or 'T', and so this method would return a true |
|
586
|
|
|
|
|
|
|
value. |
|
587
|
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
Type : Test |
|
589
|
|
|
|
|
|
|
Title : is_ambiguous |
|
590
|
|
|
|
|
|
|
Usage : if ( $obj->is_ambiguous('N') ) { |
|
591
|
|
|
|
|
|
|
# do something |
|
592
|
|
|
|
|
|
|
} |
|
593
|
|
|
|
|
|
|
Function: Returns true if argument is an ambiguous state symbol |
|
594
|
|
|
|
|
|
|
Returns : BOOLEAN |
|
595
|
|
|
|
|
|
|
Args : A state symbol |
|
596
|
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
=cut |
|
598
|
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
sub is_ambiguous { |
|
600
|
65
|
|
|
65
|
1
|
95
|
my ( $self, $symbol ) = @_; |
|
601
|
65
|
100
|
|
|
|
88
|
if ( my $lookup = $self->get_lookup ) { |
|
602
|
50
|
|
|
|
|
70
|
my $mapping = $lookup->{uc $symbol}; |
|
603
|
50
|
100
|
66
|
|
|
121
|
if ( $mapping and ref $mapping eq 'ARRAY' ) { |
|
604
|
39
|
|
|
|
|
44
|
return scalar(@{$mapping}) > 1; |
|
|
39
|
|
|
|
|
86
|
|
|
605
|
|
|
|
|
|
|
} |
|
606
|
|
|
|
|
|
|
} |
|
607
|
26
|
|
|
|
|
50
|
return 0; |
|
608
|
|
|
|
|
|
|
} |
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
=item is_valid() |
|
611
|
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
Validates argument. |
|
613
|
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
Type : Test |
|
615
|
|
|
|
|
|
|
Title : is_valid |
|
616
|
|
|
|
|
|
|
Usage : if ( $obj->is_valid($datum) ) { |
|
617
|
|
|
|
|
|
|
# do something |
|
618
|
|
|
|
|
|
|
} |
|
619
|
|
|
|
|
|
|
Function: Returns true if $datum only contains valid characters |
|
620
|
|
|
|
|
|
|
Returns : BOOLEAN |
|
621
|
|
|
|
|
|
|
Args : A Bio::Phylo::Matrices::Datum object |
|
622
|
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
=cut |
|
624
|
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
sub is_valid { |
|
626
|
1451
|
|
|
1451
|
1
|
2634
|
my $self = shift; |
|
627
|
1451
|
|
|
|
|
2510
|
my @data; |
|
628
|
1451
|
|
|
|
|
4210
|
ARG: for my $arg (@_) { |
|
629
|
1451
|
50
|
|
|
|
8880
|
if ( ref $arg eq 'ARRAY' ) { |
|
|
|
100
|
|
|
|
|
|
|
630
|
0
|
|
|
|
|
0
|
push @data, @{$arg}; |
|
|
0
|
|
|
|
|
0
|
|
|
631
|
|
|
|
|
|
|
} |
|
632
|
|
|
|
|
|
|
elsif ( UNIVERSAL::can( $arg, 'get_char' ) ) { |
|
633
|
743
|
|
|
|
|
2572
|
push @data, $arg->get_char; |
|
634
|
|
|
|
|
|
|
} |
|
635
|
|
|
|
|
|
|
else { |
|
636
|
708
|
50
|
|
|
|
3205
|
if ( length($arg) > 1 ) { |
|
637
|
0
|
|
|
|
|
0
|
push @data, @{ $self->split($arg) }; |
|
|
0
|
|
|
|
|
0
|
|
|
638
|
|
|
|
|
|
|
} |
|
639
|
|
|
|
|
|
|
else { |
|
640
|
708
|
|
|
|
|
17230
|
@data = @_; |
|
641
|
708
|
|
|
|
|
1964
|
last ARG; |
|
642
|
|
|
|
|
|
|
} |
|
643
|
|
|
|
|
|
|
} |
|
644
|
|
|
|
|
|
|
} |
|
645
|
1451
|
100
|
|
|
|
5873
|
return 1 if not @data; |
|
646
|
712
|
|
|
|
|
2461
|
my $lookup = $self->get_lookup; |
|
647
|
712
|
|
|
|
|
2037
|
my @symbols = ( $self->get_missing, $self->get_gap, keys %{$lookup} ); |
|
|
712
|
|
|
|
|
4762
|
|
|
648
|
712
|
|
|
|
|
1916
|
my %symbols = map { $_ => 1 } grep { defined $_ } @symbols; |
|
|
12480
|
|
|
|
|
24278
|
|
|
|
12480
|
|
|
|
|
21641
|
|
|
649
|
712
|
|
|
|
|
2360
|
CHAR_CHECK: for my $char (@data) { |
|
650
|
82978
|
50
|
|
|
|
143250
|
next CHAR_CHECK if not defined $char; |
|
651
|
82978
|
100
|
|
|
|
181110
|
next CHAR_CHECK if $symbols{ uc $char }; |
|
652
|
8
|
|
|
|
|
43
|
return 0; |
|
653
|
|
|
|
|
|
|
} |
|
654
|
704
|
|
|
|
|
15401
|
return 1; |
|
655
|
|
|
|
|
|
|
} |
|
656
|
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
=item is_same() |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
Compares data type objects. |
|
660
|
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
Type : Test |
|
662
|
|
|
|
|
|
|
Title : is_same |
|
663
|
|
|
|
|
|
|
Usage : if ( $obj->is_same($obj1) ) { |
|
664
|
|
|
|
|
|
|
# do something |
|
665
|
|
|
|
|
|
|
} |
|
666
|
|
|
|
|
|
|
Function: Returns true if $obj1 contains the same validation rules |
|
667
|
|
|
|
|
|
|
Returns : BOOLEAN |
|
668
|
|
|
|
|
|
|
Args : A Bio::Phylo::Matrices::Datatype::* object |
|
669
|
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
=cut |
|
671
|
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
sub is_same { |
|
673
|
119
|
|
|
119
|
1
|
213
|
my ( $self, $model ) = @_; |
|
674
|
119
|
|
|
|
|
496
|
$logger->info("Comparing datatype '$self' to '$model'"); |
|
675
|
119
|
100
|
|
|
|
266
|
return 1 if $self->get_id == $model->get_id; |
|
676
|
34
|
50
|
|
|
|
76
|
return 0 if $self->get_type ne $model->get_type; |
|
677
|
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
# check strings |
|
679
|
34
|
|
|
|
|
77
|
for my $prop (qw(get_type get_missing get_gap)) { |
|
680
|
102
|
|
|
|
|
223
|
my ( $self_prop, $model_prop ) = ( $self->$prop, $model->$prop ); |
|
681
|
102
|
50
|
33
|
|
|
442
|
return 0 |
|
|
|
|
33
|
|
|
|
|
|
682
|
|
|
|
|
|
|
if defined $self_prop |
|
683
|
|
|
|
|
|
|
&& defined $model_prop |
|
684
|
|
|
|
|
|
|
&& $self_prop ne $model_prop; |
|
685
|
|
|
|
|
|
|
} |
|
686
|
34
|
|
|
|
|
72
|
my ( $s_lookup, $m_lookup ) = ( $self->get_lookup, $model->get_lookup ); |
|
687
|
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
# one has lookup, other hasn't |
|
689
|
34
|
50
|
33
|
|
|
133
|
if ( $s_lookup && !$m_lookup ) { |
|
690
|
0
|
|
|
|
|
0
|
return 0; |
|
691
|
|
|
|
|
|
|
} |
|
692
|
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
# both don't have lookup -> are continuous |
|
694
|
34
|
0
|
33
|
|
|
63
|
if ( !$s_lookup && !$m_lookup ) { |
|
695
|
0
|
|
|
|
|
0
|
return 1; |
|
696
|
|
|
|
|
|
|
} |
|
697
|
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
# get keys |
|
699
|
34
|
|
|
|
|
49
|
my @s_keys = keys %{$s_lookup}; |
|
|
34
|
|
|
|
|
114
|
|
|
700
|
34
|
|
|
|
|
58
|
my @m_keys = keys %{$m_lookup}; |
|
|
34
|
|
|
|
|
83
|
|
|
701
|
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
# different number of keys |
|
703
|
34
|
50
|
|
|
|
78
|
if ( scalar(@s_keys) != scalar(@m_keys) ) { |
|
704
|
0
|
|
|
|
|
0
|
return 0; |
|
705
|
|
|
|
|
|
|
} |
|
706
|
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
# compare keys |
|
708
|
34
|
|
|
|
|
56
|
for my $key (@s_keys) { |
|
709
|
448
|
50
|
|
|
|
709
|
if ( not exists $m_lookup->{$key} ) { |
|
710
|
0
|
|
|
|
|
0
|
return 0; |
|
711
|
|
|
|
|
|
|
} |
|
712
|
|
|
|
|
|
|
else { |
|
713
|
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
# compare values |
|
715
|
448
|
|
|
|
|
747
|
my ( %s_vals, %m_vals ); |
|
716
|
448
|
|
|
|
|
0
|
my ( @s_vals, @m_vals ); |
|
717
|
448
|
|
|
|
|
473
|
@s_vals = @{ $s_lookup->{$key} }; |
|
|
448
|
|
|
|
|
692
|
|
|
718
|
448
|
|
|
|
|
528
|
@m_vals = @{ $m_lookup->{$key} }; |
|
|
448
|
|
|
|
|
628
|
|
|
719
|
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
# different number of vals |
|
721
|
448
|
50
|
|
|
|
702
|
if ( scalar(@m_vals) != scalar(@s_vals) ) { |
|
722
|
0
|
|
|
|
|
0
|
return 0; |
|
723
|
|
|
|
|
|
|
} |
|
724
|
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
# make hashes to compare on vals |
|
726
|
448
|
|
|
|
|
621
|
%s_vals = map { $_ => 1 } @s_vals; |
|
|
808
|
|
|
|
|
1308
|
|
|
727
|
448
|
|
|
|
|
591
|
%m_vals = map { $_ => 1 } @m_vals; |
|
|
808
|
|
|
|
|
1200
|
|
|
728
|
448
|
|
|
|
|
771
|
for my $val ( keys %s_vals ) { |
|
729
|
808
|
50
|
|
|
|
1624
|
return 0 if not exists $m_vals{$val}; |
|
730
|
|
|
|
|
|
|
} |
|
731
|
|
|
|
|
|
|
} |
|
732
|
|
|
|
|
|
|
} |
|
733
|
34
|
|
|
|
|
136
|
return 1; |
|
734
|
|
|
|
|
|
|
} |
|
735
|
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
=back |
|
737
|
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
=head2 UTILITY METHODS |
|
739
|
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
=over |
|
741
|
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
=item split() |
|
743
|
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
Splits argument string of characters following appropriate rules. |
|
745
|
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
Type : Utility method |
|
747
|
|
|
|
|
|
|
Title : split |
|
748
|
|
|
|
|
|
|
Usage : $obj->split($string) |
|
749
|
|
|
|
|
|
|
Function: Splits $string into characters |
|
750
|
|
|
|
|
|
|
Returns : An array reference of characters |
|
751
|
|
|
|
|
|
|
Args : A string |
|
752
|
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
=cut |
|
754
|
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
sub split { |
|
756
|
1237
|
|
|
1237
|
1
|
3500
|
my ( $self, $string ) = @_; |
|
757
|
1237
|
|
|
|
|
97972
|
my @array = CORE::split( /\s*/, $string ); |
|
758
|
1237
|
|
|
|
|
29191
|
return \@array; |
|
759
|
|
|
|
|
|
|
} |
|
760
|
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
=item join() |
|
762
|
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
Joins argument array ref of characters following appropriate rules. |
|
764
|
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
Type : Utility method |
|
766
|
|
|
|
|
|
|
Title : join |
|
767
|
|
|
|
|
|
|
Usage : $obj->join($arrayref) |
|
768
|
|
|
|
|
|
|
Function: Joins $arrayref into a string |
|
769
|
|
|
|
|
|
|
Returns : A string |
|
770
|
|
|
|
|
|
|
Args : An array reference |
|
771
|
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
=cut |
|
773
|
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
sub join { |
|
775
|
40
|
|
|
40
|
1
|
70
|
my ( $self, $array ) = @_; |
|
776
|
40
|
|
|
|
|
48
|
return CORE::join( '', @{$array} ); |
|
|
40
|
|
|
|
|
180
|
|
|
777
|
|
|
|
|
|
|
} |
|
778
|
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
sub _cleanup : Destructor { |
|
780
|
1672
|
|
|
1672
|
|
2949
|
my $self = shift; |
|
781
|
1672
|
|
|
|
|
8500
|
$logger->debug("cleaning up '$self'"); |
|
782
|
1672
|
|
|
|
|
4724
|
my $id = $self->get_id; |
|
783
|
1672
|
|
|
|
|
3638
|
for my $field (@fields) { |
|
784
|
6688
|
|
|
|
|
13610
|
delete $field->{$id}; |
|
785
|
|
|
|
|
|
|
} |
|
786
|
16
|
|
|
16
|
|
112
|
} |
|
|
16
|
|
|
|
|
34
|
|
|
|
16
|
|
|
|
|
73
|
|
|
787
|
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
=back |
|
789
|
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
=head2 SERIALIZERS |
|
791
|
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
=over |
|
793
|
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
=item to_xml() |
|
795
|
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
Writes data type definitions to xml |
|
797
|
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
Type : Serializer |
|
799
|
|
|
|
|
|
|
Title : to_xml |
|
800
|
|
|
|
|
|
|
Usage : my $xml = $obj->to_xml |
|
801
|
|
|
|
|
|
|
Function: Writes data type definitions to xml |
|
802
|
|
|
|
|
|
|
Returns : An xml string representation of data type definition |
|
803
|
|
|
|
|
|
|
Args : None |
|
804
|
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
=cut |
|
806
|
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
sub to_xml { |
|
808
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
809
|
0
|
|
|
|
|
0
|
$logger->debug("writing $self to xml"); |
|
810
|
0
|
|
|
|
|
0
|
my $xml = ''; |
|
811
|
0
|
|
0
|
|
|
0
|
my $normalized = $_[0] || {}; |
|
812
|
0
|
|
|
|
|
0
|
my $polymorphism = $_[1]; |
|
813
|
0
|
0
|
|
|
|
0
|
if ( my $lookup = $self->get_lookup ) { |
|
814
|
0
|
|
|
|
|
0
|
$xml .= "\n" . $self->get_xml_tag; |
|
815
|
0
|
|
|
|
|
0
|
$logger->debug($xml); |
|
816
|
0
|
|
|
|
|
0
|
my $id_for_state = $self->get_ids_for_states(1); |
|
817
|
|
|
|
|
|
|
my @states = sort { |
|
818
|
0
|
|
|
|
|
0
|
my ( $m, $n ); |
|
819
|
0
|
|
|
|
|
0
|
($m) = $id_for_state->{$a} =~ /([0-9]+)/; |
|
820
|
0
|
|
|
|
|
0
|
($n) = $id_for_state->{$b} =~ /([0-9]+)/; |
|
821
|
0
|
|
|
|
|
0
|
$m <=> $n |
|
822
|
0
|
|
|
|
|
0
|
} keys %{$id_for_state}; |
|
|
0
|
|
|
|
|
0
|
|
|
823
|
0
|
|
|
|
|
0
|
for my $state (@states) { |
|
824
|
0
|
|
|
|
|
0
|
$xml .= |
|
825
|
|
|
|
|
|
|
$self->_state_to_xml( $state, $id_for_state, $lookup, |
|
826
|
|
|
|
|
|
|
$normalized, $polymorphism ); |
|
827
|
|
|
|
|
|
|
} |
|
828
|
0
|
|
|
|
|
0
|
my ( $missing, $gap ) = ( $self->get_missing, $self->get_gap ); |
|
829
|
0
|
|
|
|
|
0
|
my $special = $self->get_ids_for_special_symbols; |
|
830
|
0
|
0
|
|
|
|
0
|
if ( %{$special} ) { |
|
|
0
|
|
|
|
|
0
|
|
|
831
|
0
|
|
|
|
|
0
|
my $uss = |
|
832
|
|
|
|
|
|
|
$fac->create_xmlwritable( '-tag' => 'uncertain_state_set' ); |
|
833
|
0
|
|
|
|
|
0
|
my $mbr = $fac->create_xmlwritable( |
|
834
|
|
|
|
|
|
|
'-tag' => 'member', |
|
835
|
|
|
|
|
|
|
'-identifiable' => 0 |
|
836
|
|
|
|
|
|
|
); |
|
837
|
|
|
|
|
|
|
$uss->set_attributes( |
|
838
|
0
|
|
|
|
|
0
|
'id' => "s" . $special->{$gap}, |
|
839
|
|
|
|
|
|
|
'symbol' => '-' |
|
840
|
|
|
|
|
|
|
); |
|
841
|
0
|
|
|
|
|
0
|
$xml .= "\n" . $uss->get_xml_tag(1); |
|
842
|
|
|
|
|
|
|
$uss->set_attributes( |
|
843
|
0
|
|
|
|
|
0
|
'id' => "s" . $special->{$missing}, |
|
844
|
|
|
|
|
|
|
'symbol' => '?' |
|
845
|
|
|
|
|
|
|
); |
|
846
|
0
|
|
|
|
|
0
|
$xml .= "\n" . $uss->get_xml_tag(); |
|
847
|
0
|
|
|
|
|
0
|
for (@states) { |
|
848
|
0
|
|
|
|
|
0
|
$mbr->set_attributes( 'state' => $id_for_state->{$_} ); |
|
849
|
0
|
|
|
|
|
0
|
$xml .= "\n" . $mbr->get_xml_tag(1); |
|
850
|
|
|
|
|
|
|
} |
|
851
|
0
|
|
|
|
|
0
|
$mbr->set_attributes( 'state' => "s" . $special->{$gap} ); |
|
852
|
0
|
|
|
|
|
0
|
$xml .= "\n" . $mbr->get_xml_tag(1); |
|
853
|
0
|
|
|
|
|
0
|
$xml .= "\n</" . $uss->get_tag . ">"; |
|
854
|
|
|
|
|
|
|
} |
|
855
|
0
|
|
|
|
|
0
|
$xml .= "\n</" . $self->get_tag . ">"; |
|
856
|
|
|
|
|
|
|
} |
|
857
|
0
|
|
|
|
|
0
|
return $xml; |
|
858
|
|
|
|
|
|
|
} |
|
859
|
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
sub _state_to_xml { |
|
861
|
0
|
|
|
0
|
|
0
|
my ( $self, $state, $id_for_state, $lookup, $normalized, $polymorphism ) |
|
862
|
|
|
|
|
|
|
= @_; |
|
863
|
0
|
|
|
|
|
0
|
my $state_id = $id_for_state->{$state}; |
|
864
|
0
|
|
|
|
|
0
|
my @mapping = @{ $lookup->{$state} }; |
|
|
0
|
|
|
|
|
0
|
|
|
865
|
|
|
|
|
|
|
my $symbol = |
|
866
|
0
|
0
|
|
|
|
0
|
exists $normalized->{$state} ? $normalized->{$state} : $state; |
|
867
|
0
|
|
|
|
|
0
|
my $xml = ''; |
|
868
|
0
|
|
|
|
|
0
|
my $unambiguous = scalar @mapping <= 1; |
|
869
|
0
|
0
|
|
|
|
0
|
my $tag = |
|
|
|
0
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
$unambiguous ? 'state' |
|
871
|
|
|
|
|
|
|
: $polymorphism ? 'polymorphic_state_set' |
|
872
|
|
|
|
|
|
|
: 'uncertain_state_set'; |
|
873
|
0
|
|
|
|
|
0
|
my $elt = $fac->create_xmlwritable( |
|
874
|
|
|
|
|
|
|
'-tag' => $tag, |
|
875
|
|
|
|
|
|
|
'-xml_id' => $state_id, |
|
876
|
|
|
|
|
|
|
'-attributes' => { 'symbol' => $symbol } |
|
877
|
|
|
|
|
|
|
); |
|
878
|
0
|
|
|
|
|
0
|
$elt->add_meta($_) for @{ $self->get_meta_for_state($state) }; |
|
|
0
|
|
|
|
|
0
|
|
|
879
|
|
|
|
|
|
|
|
|
880
|
0
|
0
|
|
|
|
0
|
if ($unambiguous) { |
|
881
|
0
|
|
|
|
|
0
|
$xml .= "\n" . $elt->get_xml_tag(1); |
|
882
|
|
|
|
|
|
|
} |
|
883
|
|
|
|
|
|
|
else { |
|
884
|
0
|
|
|
|
|
0
|
$xml .= "\n" . $elt->get_xml_tag(); |
|
885
|
0
|
|
|
|
|
0
|
for (@mapping) { |
|
886
|
|
|
|
|
|
|
$xml .= $fac->create_xmlwritable( |
|
887
|
|
|
|
|
|
|
'-tag' => 'member', |
|
888
|
|
|
|
|
|
|
'-identifiable' => 0, |
|
889
|
0
|
|
|
|
|
0
|
'-attributes' => { 'state' => $id_for_state->{$_} } |
|
890
|
|
|
|
|
|
|
)->get_xml_tag(1); |
|
891
|
|
|
|
|
|
|
} |
|
892
|
0
|
|
|
|
|
0
|
$xml .= "\n</" . $elt->get_tag . ">"; |
|
893
|
|
|
|
|
|
|
} |
|
894
|
0
|
|
|
|
|
0
|
return $xml; |
|
895
|
|
|
|
|
|
|
} |
|
896
|
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
=item to_dom() |
|
898
|
|
|
|
|
|
|
|
|
899
|
|
|
|
|
|
|
Analog to to_xml. |
|
900
|
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
Type : Serializer |
|
902
|
|
|
|
|
|
|
Title : to_dom |
|
903
|
|
|
|
|
|
|
Usage : $type->to_dom |
|
904
|
|
|
|
|
|
|
Function: Generates a DOM subtree from the invocant |
|
905
|
|
|
|
|
|
|
and its contained objects |
|
906
|
|
|
|
|
|
|
Returns : an <XML Package>::Element object |
|
907
|
|
|
|
|
|
|
Args : none |
|
908
|
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
=cut |
|
910
|
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
sub to_dom { |
|
912
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
913
|
0
|
|
|
|
|
0
|
my $dom = $_[0]; |
|
914
|
0
|
|
|
|
|
0
|
my @args = @_; |
|
915
|
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
# handle dom factory object... |
|
917
|
0
|
0
|
0
|
|
|
0
|
if ( looks_like_instance( $dom, 'SCALAR' ) |
|
918
|
|
|
|
|
|
|
&& $dom->_type == _DOMCREATOR_ ) |
|
919
|
|
|
|
|
|
|
{ |
|
920
|
0
|
|
|
|
|
0
|
splice( @args, 0, 1 ); |
|
921
|
|
|
|
|
|
|
} |
|
922
|
|
|
|
|
|
|
else { |
|
923
|
0
|
|
|
|
|
0
|
$dom = $Bio::Phylo::NeXML::DOM::DOM; |
|
924
|
0
|
0
|
|
|
|
0
|
unless ($dom) { |
|
925
|
0
|
|
|
|
|
0
|
throw 'BadArgs' => 'DOM factory object not provided'; |
|
926
|
|
|
|
|
|
|
} |
|
927
|
|
|
|
|
|
|
} |
|
928
|
0
|
|
|
|
|
0
|
my $elt; |
|
929
|
0
|
|
0
|
|
|
0
|
my $normalized = $args[0] || {}; |
|
930
|
0
|
|
|
|
|
0
|
my $polymorphism = $args[1]; |
|
931
|
0
|
0
|
|
|
|
0
|
if ( my $lookup = $self->get_lookup ) { |
|
932
|
0
|
|
|
|
|
0
|
$elt = $self->get_dom_elt($dom); |
|
933
|
0
|
|
|
|
|
0
|
my $id_for_state = $self->get_ids_for_states; |
|
934
|
|
|
|
|
|
|
my @states = sort { |
|
935
|
0
|
|
|
|
|
0
|
my ( $m, $n ); |
|
936
|
0
|
|
|
|
|
0
|
($m) = $id_for_state->{$a} =~ /([0-9]+)/; |
|
937
|
0
|
|
|
|
|
0
|
($n) = $id_for_state->{$b} =~ /([0-9]+)/; |
|
938
|
0
|
|
|
|
|
0
|
$m <=> $n |
|
939
|
0
|
|
|
|
|
0
|
} keys %{$id_for_state}; |
|
|
0
|
|
|
|
|
0
|
|
|
940
|
0
|
|
|
|
|
0
|
keys %{$id_for_state}; |
|
|
0
|
|
|
|
|
0
|
|
|
941
|
0
|
|
|
|
|
0
|
my $max_id = 0; |
|
942
|
0
|
|
|
|
|
0
|
for my $state (@states) { |
|
943
|
0
|
|
|
|
|
0
|
my $state_id = $id_for_state->{$state}; |
|
944
|
0
|
|
|
|
|
0
|
$id_for_state->{$state} = 's' . $state_id; |
|
945
|
0
|
|
|
|
|
0
|
$max_id = $state_id; |
|
946
|
|
|
|
|
|
|
} |
|
947
|
0
|
|
|
|
|
0
|
for my $state (@states) { |
|
948
|
0
|
|
|
|
|
0
|
$elt->set_child( |
|
949
|
|
|
|
|
|
|
$self->_state_to_dom( |
|
950
|
|
|
|
|
|
|
$dom, $state, $id_for_state, |
|
951
|
|
|
|
|
|
|
$lookup, $normalized, $polymorphism |
|
952
|
|
|
|
|
|
|
) |
|
953
|
|
|
|
|
|
|
); |
|
954
|
|
|
|
|
|
|
} |
|
955
|
0
|
|
|
|
|
0
|
my ( $missing, $gap ) = ( $self->get_missing, $self->get_gap ); |
|
956
|
0
|
|
|
|
|
0
|
my $special = $self->get_ids_for_special_symbols; |
|
957
|
0
|
0
|
|
|
|
0
|
if ( %{$special} ) { |
|
|
0
|
|
|
|
|
0
|
|
|
958
|
0
|
|
|
|
|
0
|
my $uss; |
|
959
|
0
|
|
|
|
|
0
|
$uss = $dom->create_element( '-tag' => 'uncertain_state_set' ); |
|
960
|
0
|
|
|
|
|
0
|
$uss->set_attributes( 'id' => 's' . $special->{$gap} ); |
|
961
|
0
|
|
|
|
|
0
|
$uss->set_attributes( 'symbol' => '-' ); |
|
962
|
0
|
|
|
|
|
0
|
$elt->set_child($uss); |
|
963
|
0
|
|
|
|
|
0
|
$uss = $dom->create_element( '-tag' => 'uncertain_state_set' ); |
|
964
|
0
|
|
|
|
|
0
|
$uss->set_attributes( 'id' => 's' . $special->{$missing} ); |
|
965
|
0
|
|
|
|
|
0
|
$uss->set_attributes( 'symbol' => '?' ); |
|
966
|
0
|
|
|
|
|
0
|
my $mbr; |
|
967
|
|
|
|
|
|
|
|
|
968
|
0
|
|
|
|
|
0
|
for (@states) { |
|
969
|
0
|
|
|
|
|
0
|
$mbr = $dom->create_element( '-tag' => 'member' ); |
|
970
|
0
|
|
|
|
|
0
|
$mbr->set_attributes( 'state' => $id_for_state->{$_} ); |
|
971
|
0
|
|
|
|
|
0
|
$uss->set_child($mbr); |
|
972
|
|
|
|
|
|
|
} |
|
973
|
0
|
|
|
|
|
0
|
$mbr = $dom->create_element( '-tag' => 'member' ); |
|
974
|
0
|
|
|
|
|
0
|
$mbr->set_attributes( 'state' => 's' . $special->{$gap} ); |
|
975
|
0
|
|
|
|
|
0
|
$uss->set_child($mbr); |
|
976
|
0
|
|
|
|
|
0
|
$elt->set_child($uss); |
|
977
|
|
|
|
|
|
|
} |
|
978
|
|
|
|
|
|
|
} |
|
979
|
0
|
|
|
|
|
0
|
return $elt; |
|
980
|
|
|
|
|
|
|
} |
|
981
|
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
sub _state_to_dom { |
|
983
|
0
|
|
|
0
|
|
0
|
my ( $self, $dom, $state, $id_for_state, $lookup, $normalized, |
|
984
|
|
|
|
|
|
|
$polymorphism ) |
|
985
|
|
|
|
|
|
|
= @_; |
|
986
|
0
|
|
|
|
|
0
|
my $state_id = $id_for_state->{$state}; |
|
987
|
0
|
|
|
|
|
0
|
my @mapping = @{ $lookup->{$state} }; |
|
|
0
|
|
|
|
|
0
|
|
|
988
|
|
|
|
|
|
|
my $symbol = |
|
989
|
0
|
0
|
|
|
|
0
|
exists $normalized->{$state} ? $normalized->{$state} : $state; |
|
990
|
0
|
|
|
|
|
0
|
my $elt; |
|
991
|
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
# has ambiguity mappings |
|
993
|
0
|
0
|
|
|
|
0
|
if ( scalar @mapping > 1 ) { |
|
994
|
0
|
0
|
|
|
|
0
|
my $tag = |
|
995
|
|
|
|
|
|
|
$polymorphism ? 'polymorphic_state_set' : 'uncertain_state_set'; |
|
996
|
0
|
|
|
|
|
0
|
$elt = $dom->create_element( '-tag' => $tag ); |
|
997
|
0
|
|
|
|
|
0
|
$elt->set_attributes( 'id' => $state_id ); |
|
998
|
0
|
|
|
|
|
0
|
$elt->set_attributes( 'symbol' => $symbol ); |
|
999
|
0
|
|
|
|
|
0
|
for my $map (@mapping) { |
|
1000
|
0
|
|
|
|
|
0
|
my $mbr = $dom->create_element( '-tag' => 'member' ); |
|
1001
|
0
|
|
|
|
|
0
|
$mbr->set_attributes( 'state' => $id_for_state->{$map} ); |
|
1002
|
0
|
|
|
|
|
0
|
$elt->set_child($mbr); |
|
1003
|
|
|
|
|
|
|
} |
|
1004
|
|
|
|
|
|
|
} |
|
1005
|
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
# no ambiguity |
|
1007
|
|
|
|
|
|
|
else { |
|
1008
|
0
|
|
|
|
|
0
|
$elt = $dom->create_element( '-tag' => 'state' ); |
|
1009
|
0
|
|
|
|
|
0
|
$elt->set_attributes( 'id' => $state_id ); |
|
1010
|
0
|
|
|
|
|
0
|
$elt->set_attributes( 'symbol' => $symbol ); |
|
1011
|
|
|
|
|
|
|
} |
|
1012
|
0
|
|
|
|
|
0
|
return $elt; |
|
1013
|
|
|
|
|
|
|
} |
|
1014
|
50
|
|
|
50
|
|
136
|
sub _tag { 'states' } |
|
1015
|
50
|
|
|
50
|
|
126
|
sub _type { _DATATYPE_ } |
|
1016
|
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
=back |
|
1018
|
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
=cut |
|
1020
|
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
# podinherit_insert_token |
|
1022
|
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
1024
|
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
There is a mailing list at L<https://groups.google.com/forum/#!forum/bio-phylo> |
|
1026
|
|
|
|
|
|
|
for any user or developer questions and discussions. |
|
1027
|
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
=over |
|
1029
|
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
=item L<Bio::Phylo> |
|
1031
|
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
This object inherits from L<Bio::Phylo>, so the methods defined |
|
1033
|
|
|
|
|
|
|
therein are also applicable to L<Bio::Phylo::Matrices::Datatype> objects. |
|
1034
|
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
=item L<Bio::Phylo::Manual> |
|
1036
|
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
Also see the manual: L<Bio::Phylo::Manual> and L<http://rutgervos.blogspot.com>. |
|
1038
|
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
=back |
|
1040
|
|
|
|
|
|
|
|
|
1041
|
|
|
|
|
|
|
=head1 CITATION |
|
1042
|
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
If you use Bio::Phylo in published research, please cite it: |
|
1044
|
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
B<Rutger A Vos>, B<Jason Caravas>, B<Klaas Hartmann>, B<Mark A Jensen> |
|
1046
|
|
|
|
|
|
|
and B<Chase Miller>, 2011. Bio::Phylo - phyloinformatic analysis using Perl. |
|
1047
|
|
|
|
|
|
|
I<BMC Bioinformatics> B<12>:63. |
|
1048
|
|
|
|
|
|
|
L<http://dx.doi.org/10.1186/1471-2105-12-63> |
|
1049
|
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
=cut |
|
1051
|
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
} |
|
1053
|
|
|
|
|
|
|
1; |