| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
=head1 NAME |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
Bio::Polloc::LocusIO::gff3 - A LocusIO for Gff3 |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
A repeatitive locus. |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 IMPLEMENTS OR EXTENDS |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=over |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=item * |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
L<Bio::Polloc::LocusIO> |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=back |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 AUTHOR - Luis M. Rodriguez-R |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
Email lmrodriguezr at gmail dot com |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=cut |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
package Bio::Polloc::LocusIO::gff3; |
|
26
|
2
|
|
|
2
|
|
10
|
use base qw(Bio::Polloc::LocusIO); |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
199
|
|
|
27
|
2
|
|
|
2
|
|
14
|
use strict; |
|
|
2
|
|
|
|
|
70
|
|
|
|
2
|
|
|
|
|
80
|
|
|
28
|
2
|
|
|
2
|
|
1702
|
use Bio::Polloc::LociGroup; |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
72
|
|
|
29
|
2
|
|
|
2
|
|
750
|
use Bio::Polloc::LocusI; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
4197
|
|
|
30
|
|
|
|
|
|
|
our $VERSION = 1.0503; # [a-version] from Bio::Polloc::Polloc::Version |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=head1 APPENDIX |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
Methods provided by the package |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head2 new |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
Creates a B<Bio::Polloc::LocusIO::gff3> object. |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head3 Returns |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
A L<Bio::Polloc::LocusIO::gff3> object. |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=cut |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub new { |
|
48
|
0
|
|
|
0
|
1
|
0
|
my($caller,@args) = @_; |
|
49
|
0
|
|
|
|
|
0
|
my $self = $caller->SUPER::new(@args); |
|
50
|
0
|
|
|
|
|
0
|
$self->_initialize(@args); |
|
51
|
0
|
|
|
|
|
0
|
return $self; |
|
52
|
|
|
|
|
|
|
} |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head2 gff3_line |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
Formats the locus as a GFF3 line and returns it. |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head3 Arguments |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=over |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=item -force |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Boolean (1 or 0) |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=back |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=head3 Returns |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
The GFF3-formatted line (str) |
|
71
|
|
|
|
|
|
|
=head3 Note |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
This function stores the line in cache. If it is called twice, the second |
|
74
|
|
|
|
|
|
|
time will return the cached line unless the C<-force=>1> flag is passed. |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=cut |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub gff3_line { |
|
79
|
3
|
|
|
3
|
1
|
6
|
my($self,@args) = @_; |
|
80
|
3
|
|
|
|
|
14
|
my($locus, $force) = $self->_rearrange([qw(LOCUS FORCE)], @args); |
|
81
|
3
|
50
|
33
|
|
|
37
|
defined $locus and UNIVERSAL::can($locus, 'isa') and $locus->isa('Bio::Polloc::LocusI') |
|
|
|
|
33
|
|
|
|
|
|
82
|
|
|
|
|
|
|
or $self->throw("Undefined locus or bad type", $locus); |
|
83
|
3
|
50
|
33
|
|
|
15
|
return $locus->{'_gff3_line'} if defined $locus->{'_gff3_line'} and not $force; |
|
84
|
3
|
|
|
|
|
4
|
my @out; |
|
85
|
3
|
50
|
|
|
|
11
|
push @out, defined $locus->seq_name ? $locus->seq_name : "."; |
|
86
|
3
|
|
|
|
|
8
|
$out[0] =~ s/^>/{{%}}3E/; |
|
87
|
3
|
|
|
|
|
13
|
push @out, $locus->source; #defined $locus->rule ? $locus->rule->source : 'bme'; |
|
88
|
3
|
|
|
|
|
10
|
push @out, $locus->family; |
|
89
|
3
|
|
|
|
|
22
|
push @out, $locus->from , $locus->to; |
|
90
|
3
|
50
|
|
|
|
11
|
push @out, defined $locus->score ? $locus->score : "."; |
|
91
|
3
|
|
|
|
|
9
|
push @out, $locus->strand, "0"; |
|
92
|
3
|
|
|
|
|
6
|
my %atts; |
|
93
|
3
|
50
|
|
|
|
8
|
$atts{'ID'} = $locus->id if defined $locus->id; |
|
94
|
3
|
50
|
|
|
|
11
|
$atts{'Name'} = $locus->name if defined $locus->name; |
|
95
|
3
|
50
|
|
|
|
17
|
$atts{'Alias'} = $locus->aliases if defined $locus->aliases; |
|
96
|
3
|
50
|
|
|
|
14
|
$atts{'Parent'} = $locus->parents if defined $locus->parents; |
|
97
|
3
|
50
|
33
|
|
|
10
|
$atts{'organism_name'} = $locus->genome->name |
|
98
|
|
|
|
|
|
|
if defined $locus->genome and defined $locus->genome->name; |
|
99
|
3
|
50
|
|
|
|
12
|
if(defined $locus->target){ |
|
100
|
0
|
|
|
|
|
0
|
my $tid = $locus->target->{'id'}; |
|
101
|
0
|
|
|
|
|
0
|
$tid =~ s/\s/{{%}}20/g; |
|
102
|
0
|
|
|
|
|
0
|
$atts{'Target'} = $tid . " " . $locus->target->{'from'} . " " . $locus->target->{'to'}; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
# TODO Gap |
|
105
|
3
|
50
|
|
|
|
10
|
$atts{'Note'} = [split /[\n\r]+/, $locus->comments] if defined $locus->comments; |
|
106
|
3
|
50
|
|
|
|
15
|
$atts{'Dbxref'} = $locus->xrefs if defined $locus->xrefs; |
|
107
|
3
|
50
|
|
|
|
12
|
$atts{'Ontology_term'} = $locus->ontology_terms_str if defined $locus->ontology_terms_str; |
|
108
|
3
|
|
|
|
|
17
|
my $o = ""; |
|
109
|
3
|
|
|
|
|
6
|
for my $v (@out){ |
|
110
|
24
|
|
|
|
|
44
|
$o.= $self->_gff3_value($v)."\t"; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
3
|
|
|
|
|
5
|
$a = ""; |
|
113
|
3
|
|
|
|
|
8
|
for my $k (keys %atts){ |
|
114
|
9
|
|
|
|
|
25
|
$a .= "$k=" . $self->_gff3_attribute($atts{$k}).";"; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
3
|
50
|
|
|
|
12
|
$a = substr($a,0,-1) if $a; |
|
117
|
3
|
|
|
|
|
13
|
$locus->{'_gff3_line'} = $o . $a . "\n"; |
|
118
|
3
|
|
|
|
|
18
|
return $locus->{'_gff3_line'}; |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=head1 INTERNAL METHODS |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
Methods intended to be used only within the scope of Bio::Polloc::* |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=head2 _next_locus_impl |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=cut |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub _next_locus_impl { |
|
131
|
90
|
|
|
90
|
|
121
|
my ($self, @args) = @_; |
|
132
|
90
|
|
|
|
|
304
|
my($genomes) = $self->_rearrange([qw(GENOMES)], @args); |
|
133
|
90
|
|
|
|
|
150
|
my $ln; |
|
134
|
90
|
|
|
|
|
306
|
while($ln = $self->_readline){ |
|
135
|
94
|
100
|
100
|
|
|
577
|
last unless $ln =~ /^\s*#/ or $ln =~ /^\s*$/; |
|
136
|
|
|
|
|
|
|
} |
|
137
|
90
|
100
|
|
|
|
166
|
return unless $ln; |
|
138
|
87
|
|
|
|
|
325
|
$self->debug("Parsing: $ln"); |
|
139
|
87
|
|
|
|
|
443
|
my @row = split /\t/, $ln; |
|
140
|
87
|
|
|
|
|
217
|
my $seqid = $self->_gff3_decode($row[0]); |
|
141
|
87
|
|
|
|
|
172
|
my $source = $self->_gff3_decode($row[1]); |
|
142
|
87
|
|
|
|
|
178
|
my $family = $self->_gff3_decode($row[2]); |
|
143
|
87
|
|
|
|
|
176
|
my $from = $self->_gff3_decode($row[3]); |
|
144
|
87
|
|
|
|
|
175
|
my $to = $self->_gff3_decode($row[4]); |
|
145
|
87
|
|
|
|
|
168
|
my $score= $self->_gff3_decode($row[5]); |
|
146
|
87
|
|
|
|
|
180
|
my $strand = $self->_gff3_decode($row[6]); |
|
147
|
87
|
|
|
|
|
155
|
my $frame = $self->_gff3_decode($row[7]); |
|
148
|
87
|
|
|
|
|
257
|
my @compl = split /;/, $row[8]; |
|
149
|
87
|
|
|
|
|
127
|
my %atts = (); |
|
150
|
87
|
|
|
|
|
124
|
for my $c (@compl){ |
|
151
|
229
|
50
|
|
|
|
947
|
$c =~ /(.+?)=(.*)/ or next; |
|
152
|
229
|
|
|
|
|
488
|
my ($k,$v) = ($1, $2); |
|
153
|
229
|
|
|
|
|
406
|
$atts{lc $k} = $self->_gff3_decode($v); |
|
154
|
|
|
|
|
|
|
} |
|
155
|
87
|
|
|
|
|
140
|
my $id = $atts{'id'}; |
|
156
|
87
|
|
|
|
|
112
|
my $name = $atts{'name'}; |
|
157
|
87
|
|
|
|
|
116
|
my $genome_name = $atts{'organism_name'}; |
|
158
|
87
|
|
|
|
|
115
|
my @comments = (); |
|
159
|
87
|
50
|
|
|
|
361
|
@comments = split /,/, $atts{'note'} if defined $atts{'note'}; |
|
160
|
87
|
|
|
|
|
317
|
my $f = Bio::Polloc::LocusI->_qualify_type($family); |
|
161
|
87
|
50
|
33
|
|
|
1138
|
my $type = ($f eq 'amplicon' or $f eq 'amplification') ? 'amplicon' : |
|
|
|
50
|
33
|
|
|
|
|
|
|
|
50
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
($f eq 'composition') ? 'composition' : |
|
163
|
|
|
|
|
|
|
($f eq 'crispr') ? 'crispr' : |
|
164
|
|
|
|
|
|
|
($f eq 'pattern' or $f eq 'domain') ? 'pattern' : |
|
165
|
|
|
|
|
|
|
($f eq 'repeat' or $f eq 'vntr' or $f =~ /tandem.?repeat/ |
|
166
|
|
|
|
|
|
|
or lc $source eq 'trf' or lc $source eq 'mreps') ? 'repeat' : |
|
167
|
|
|
|
|
|
|
'generic'; |
|
168
|
87
|
100
|
|
|
|
139
|
$type = "extend" if grep{ /Extended feature/ } @comments; |
|
|
298
|
|
|
|
|
615
|
|
|
169
|
87
|
|
|
|
|
583
|
my $locus = Bio::Polloc::LocusI->new( |
|
170
|
|
|
|
|
|
|
-id=>$id, -name=>$name, |
|
171
|
|
|
|
|
|
|
-type=>$type, |
|
172
|
|
|
|
|
|
|
-from=>$from, -to=>$to, -strand=>$strand, |
|
173
|
|
|
|
|
|
|
-source=>$source, -family=>$family, |
|
174
|
|
|
|
|
|
|
-score=>$score, |
|
175
|
|
|
|
|
|
|
-seqname=>$seqid); |
|
176
|
|
|
|
|
|
|
# Parse comments |
|
177
|
87
|
|
|
|
|
201
|
for my $comm (@comments){ |
|
178
|
298
|
100
|
66
|
|
|
1289
|
if($comm =~ m/^(.+?)=(.+)$/){ |
|
|
|
100
|
|
|
|
|
|
|
179
|
215
|
|
|
|
|
450
|
my ($k, $v) = (lc $1, $2); |
|
180
|
215
|
100
|
66
|
|
|
1367
|
if($k and $v and $locus->can($k)){ |
|
|
|
|
66
|
|
|
|
|
|
181
|
207
|
|
|
|
|
710
|
$self->debug("Setting $k to $v"); |
|
182
|
207
|
|
|
|
|
559
|
$locus->$k($v); |
|
183
|
207
|
|
|
|
|
353
|
next; |
|
184
|
|
|
|
|
|
|
} |
|
185
|
8
|
50
|
33
|
|
|
82
|
$genome_name = $v if not defined $genome_name and |
|
|
|
|
33
|
|
|
|
|
|
186
|
|
|
|
|
|
|
($k =~ /^organism(?:_name)?$/ or $k =~ /^genome(?:_name)?$/); |
|
187
|
|
|
|
|
|
|
}elsif($type eq 'extend' and $comm =~ m/Based on group [^:]+: (.*)/){ |
|
188
|
34
|
|
|
|
|
120
|
for my $b (split /\s/, $1){ |
|
189
|
34
|
50
|
|
|
|
103
|
$locus->basefeature($self->_locus_by_id($b)) if defined $self->_locus_by_id($b); |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
} |
|
192
|
|
|
|
|
|
|
} |
|
193
|
87
|
100
|
|
|
|
176
|
if(defined $genomes){ |
|
194
|
2
|
|
|
|
|
3
|
my $genome; |
|
195
|
|
|
|
|
|
|
# Search the genome by name: |
|
196
|
2
|
50
|
|
|
|
6
|
if(defined $genome_name){ |
|
197
|
2
|
|
|
|
|
4
|
for my $g (@$genomes){ |
|
198
|
2
|
50
|
|
|
|
8
|
$genome = $g if $g->name eq $genome_name; |
|
199
|
2
|
50
|
|
|
|
6
|
last if defined $genome; |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
# Search the genome by sequence name (prone to errors, but it's a guess): |
|
203
|
2
|
50
|
|
|
|
11
|
unless(defined $genome){ |
|
204
|
0
|
|
|
|
|
0
|
for my $g (@$genomes){ |
|
205
|
0
|
0
|
|
|
|
0
|
$genome = $g if defined $g->search_sequence($seqid); |
|
206
|
0
|
0
|
|
|
|
0
|
last if defined $genome; |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
} |
|
209
|
2
|
|
|
|
|
7
|
$locus->genome($genome); |
|
210
|
|
|
|
|
|
|
} |
|
211
|
87
|
|
|
|
|
239
|
$locus->comments(@comments); |
|
212
|
87
|
|
|
|
|
271
|
return $self->_save_locus($locus); |
|
213
|
|
|
|
|
|
|
} |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=head2 _write_locus_impl |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=cut |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
sub _write_locus_impl { |
|
220
|
3
|
|
|
3
|
|
5
|
my $self = shift; |
|
221
|
3
|
|
|
|
|
10
|
my $line = $self->gff3_line(@_); |
|
222
|
3
|
100
|
|
|
|
9
|
unless($self->{'_header'}){ |
|
223
|
1
|
|
|
|
|
30
|
$self->_print("##gff-version 3\n\n"); |
|
224
|
1
|
|
|
|
|
3
|
$self->{'_header'} = 1; |
|
225
|
|
|
|
|
|
|
} |
|
226
|
3
|
|
|
|
|
11
|
$self->_print($line); |
|
227
|
|
|
|
|
|
|
} |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
=head2 _gff3_attribute |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
Properly escapes an attribute for GFF3 (an attribute the value of one of |
|
232
|
|
|
|
|
|
|
the colon-separated entries in the ninth column) |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=head3 Purpose |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
To simplify the code of L<Bio::Polloc::LocusI::gff3_line> |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=head3 Arguments |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
The value to escape |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=head3 Returns |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
The escaped value |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=cut |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub _gff3_attribute { |
|
249
|
9
|
|
|
9
|
|
13
|
my($self,$value) = @_; |
|
250
|
9
|
50
|
|
|
|
19
|
return unless defined $value; |
|
251
|
9
|
100
|
66
|
|
|
39
|
if(ref($value) && ref($value) =~ m/array/i){ |
|
252
|
3
|
|
|
|
|
5
|
my $out = ""; |
|
253
|
3
|
|
|
|
|
4
|
for my $att (@{$value}){ |
|
|
3
|
|
|
|
|
7
|
|
|
254
|
15
|
|
|
|
|
29
|
$out.= "," . $self->_gff3_value($att); |
|
255
|
|
|
|
|
|
|
} |
|
256
|
3
|
50
|
|
|
|
12
|
$out = substr($out, 1) if $out; |
|
257
|
3
|
|
|
|
|
14
|
return $out; |
|
258
|
|
|
|
|
|
|
} |
|
259
|
6
|
|
|
|
|
13
|
return $self->_gff3_value($value); |
|
260
|
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=head2 _gff3_value |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
Properly escapes a value on the GFF3 line. I.e., the content of one column. |
|
265
|
|
|
|
|
|
|
Not to be used with the ninth column, because scapes the colon. the comma and |
|
266
|
|
|
|
|
|
|
the equals signs. Use instead the L<_gff3_attribute> function attribute by |
|
267
|
|
|
|
|
|
|
attribute |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=head3 Purpose |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
To simplify the code of L<gff3_line> |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=head3 Arguments |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
The value to escape |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=head3 Returns |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
The escaped value |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=cut |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub _gff3_value { |
|
284
|
45
|
|
|
45
|
|
55
|
my ($self,$value) = @_; |
|
285
|
45
|
50
|
|
|
|
77
|
return unless defined $value; |
|
286
|
45
|
|
|
|
|
61
|
$value =~ s/%/%25/g; |
|
287
|
45
|
|
|
|
|
45
|
$value =~ s/\{\{%25\}\}/%/g; |
|
288
|
45
|
|
|
|
|
43
|
$value =~ s/\t/%9/g; |
|
289
|
45
|
|
|
|
|
48
|
$value =~ s/\n/\%D/g; |
|
290
|
45
|
|
|
|
|
43
|
$value =~ s/\r/\%A/g; |
|
291
|
45
|
|
|
|
|
46
|
$value =~ s/;/%3B/g; |
|
292
|
45
|
|
|
|
|
106
|
$value =~ s/=/%3D/g; |
|
293
|
45
|
|
|
|
|
47
|
$value =~ s/&/%26/g; |
|
294
|
45
|
|
|
|
|
51
|
$value =~ s/,/%2C/g; |
|
295
|
45
|
|
|
|
|
49
|
$value =~ s/ /%20/g; |
|
296
|
45
|
|
|
|
|
135
|
return $value; |
|
297
|
|
|
|
|
|
|
} |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head2 _gff_decode |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
Decodes the URI-fashioned values on GFF3 |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=head3 Arguments |
|
304
|
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
The value to decode (str) |
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=head3 Returns |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
The decoded value (str) |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=cut |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
sub _gff3_decode { |
|
314
|
925
|
|
|
925
|
|
1088
|
my($self,$value) = @_; |
|
315
|
925
|
50
|
|
|
|
1426
|
return unless defined $value; |
|
316
|
925
|
|
|
|
|
1014
|
$value =~ s/%25/%/g; |
|
317
|
925
|
|
|
|
|
917
|
$value =~ s/%9/\t/g; |
|
318
|
925
|
|
|
|
|
875
|
$value =~ s/\%D/\n/g; |
|
319
|
925
|
|
|
|
|
931
|
$value =~ s/\%A/\r/g; |
|
320
|
925
|
|
|
|
|
885
|
$value =~ s/%3B/;/g; |
|
321
|
925
|
|
|
|
|
1062
|
$value =~ s/%3D/=/g; |
|
322
|
925
|
|
|
|
|
892
|
$value =~ s/%26/&/g; |
|
323
|
925
|
|
|
|
|
862
|
$value =~ s/%2C/,/g; |
|
324
|
925
|
|
|
|
|
1019
|
$value =~ s/%20/ /g; |
|
325
|
925
|
|
|
|
|
1970
|
return $value; |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
1; |