rare-quickprot 1.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- quickprot/Fasta_reader.pm +169 -0
- quickprot/GFF3_utils2.pm +249 -0
- quickprot/Gene_obj.pm +5604 -0
- quickprot/Longest_orf.pm +371 -0
- quickprot/Nuc_translator.pm +647 -0
- quickprot/__init__.py +1 -0
- quickprot/add_type_gff3.py +66 -0
- quickprot/cdna_alignment_orf_to_genome_orf.pl +411 -0
- quickprot/extract_sequence_from_gff3.py +207 -0
- quickprot/filter_repeatPeps_from_gff3.py +187 -0
- quickprot/get_intron_from_gff3.py +105 -0
- quickprot/get_longest_transcript_gff3.py +114 -0
- quickprot/gtf_genome_to_cdna_fasta.py +82 -0
- quickprot/gtf_to_alignment_gff3.pl +100 -0
- quickprot/quickprot.py +667 -0
- quickprot/rename_gff3.py +94 -0
- quickprot/sm2rmForFasta.py +39 -0
- quickprot/sort_gff3.py +95 -0
- quickprot/split_and_filter_gene_model.py +174 -0
- quickprot/stat_gff3.py +181 -0
- quickprot/update_gff3_from_minibusco.py +230 -0
- quickprot/version.py +1 -0
- rare_quickprot-1.10.0.data/scripts/Fasta_reader.pm +169 -0
- rare_quickprot-1.10.0.data/scripts/GFF3_utils2.pm +249 -0
- rare_quickprot-1.10.0.data/scripts/Gene_obj.pm +5604 -0
- rare_quickprot-1.10.0.data/scripts/Longest_orf.pm +371 -0
- rare_quickprot-1.10.0.data/scripts/Nuc_translator.pm +647 -0
- rare_quickprot-1.10.0.data/scripts/add_type_gff3.py +66 -0
- rare_quickprot-1.10.0.data/scripts/cdna_alignment_orf_to_genome_orf.pl +411 -0
- rare_quickprot-1.10.0.data/scripts/extract_sequence_from_gff3.py +207 -0
- rare_quickprot-1.10.0.data/scripts/filter_repeatPeps_from_gff3.py +187 -0
- rare_quickprot-1.10.0.data/scripts/get_intron_from_gff3.py +105 -0
- rare_quickprot-1.10.0.data/scripts/get_longest_transcript_gff3.py +114 -0
- rare_quickprot-1.10.0.data/scripts/gtf_genome_to_cdna_fasta.py +82 -0
- rare_quickprot-1.10.0.data/scripts/gtf_to_alignment_gff3.pl +100 -0
- rare_quickprot-1.10.0.data/scripts/quickprot.py +667 -0
- rare_quickprot-1.10.0.data/scripts/rename_gff3.py +94 -0
- rare_quickprot-1.10.0.data/scripts/sm2rmForFasta.py +39 -0
- rare_quickprot-1.10.0.data/scripts/sort_gff3.py +95 -0
- rare_quickprot-1.10.0.data/scripts/split_and_filter_gene_model.py +174 -0
- rare_quickprot-1.10.0.data/scripts/stat_gff3.py +181 -0
- rare_quickprot-1.10.0.data/scripts/update_gff3_from_minibusco.py +230 -0
- rare_quickprot-1.10.0.dist-info/METADATA +151 -0
- rare_quickprot-1.10.0.dist-info/RECORD +48 -0
- rare_quickprot-1.10.0.dist-info/WHEEL +5 -0
- rare_quickprot-1.10.0.dist-info/entry_points.txt +2 -0
- rare_quickprot-1.10.0.dist-info/licenses/LICENSE.txt +23 -0
- rare_quickprot-1.10.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/local/bin/perl -w
|
|
2
|
+
|
|
3
|
+
# lightweight fasta reader capabilities:
|
|
4
|
+
package Fasta_reader;
|
|
5
|
+
|
|
6
|
+
use strict;
|
|
7
|
+
|
|
8
|
+
sub new {
|
|
9
|
+
my ($packagename, $fastaFile) = @_;
|
|
10
|
+
|
|
11
|
+
## note: fastaFile can be a filename or an IO::Handle
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
my $self = { fastaFile => undef,,
|
|
15
|
+
fileHandle => undef };
|
|
16
|
+
|
|
17
|
+
bless ($self, $packagename);
|
|
18
|
+
|
|
19
|
+
## create filehandle
|
|
20
|
+
my $filehandle = undef;
|
|
21
|
+
|
|
22
|
+
if (ref $fastaFile eq 'IO::Handle') {
|
|
23
|
+
$filehandle = $fastaFile;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
|
|
27
|
+
open ($filehandle, $fastaFile) or die "Error: Couldn't open $fastaFile\n";
|
|
28
|
+
$self->{fastaFile} = $fastaFile;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
$self->{fileHandle} = $filehandle;
|
|
32
|
+
|
|
33
|
+
return ($self);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
#### next() fetches next Sequence object.
|
|
39
|
+
sub next {
|
|
40
|
+
my $self = shift;
|
|
41
|
+
my $orig_record_sep = $/;
|
|
42
|
+
$/="\n>";
|
|
43
|
+
my $filehandle = $self->{fileHandle};
|
|
44
|
+
my $next_text_input = <$filehandle>;
|
|
45
|
+
|
|
46
|
+
if (defined($next_text_input) && $next_text_input !~ /\w/) {
|
|
47
|
+
## must have been some whitespace at start of fasta file, before first entry.
|
|
48
|
+
## try again:
|
|
49
|
+
$next_text_input = <$filehandle>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
my $seqobj = undef;
|
|
53
|
+
|
|
54
|
+
if ($next_text_input) {
|
|
55
|
+
$next_text_input =~ s/^>|>$//g; #remove trailing > char.
|
|
56
|
+
$next_text_input =~ tr/\t\n\000-\037\177-\377/\t\n/d; #remove cntrl chars
|
|
57
|
+
my ($header, @seqlines) = split (/\n/, $next_text_input);
|
|
58
|
+
my $sequence = join ("", @seqlines);
|
|
59
|
+
$sequence =~ s/\s//g;
|
|
60
|
+
|
|
61
|
+
$seqobj = Sequence->new($header, $sequence);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
$/ = $orig_record_sep; #reset the record separator to original setting.
|
|
65
|
+
|
|
66
|
+
return ($seqobj); #returns null if not instantiated.
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
#### finish() closes the open filehandle to the query database.
|
|
71
|
+
sub finish {
|
|
72
|
+
my $self = shift;
|
|
73
|
+
my $filehandle = $self->{fileHandle};
|
|
74
|
+
close $filehandle;
|
|
75
|
+
$self->{fileHandle} = undef;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
####
|
|
79
|
+
sub retrieve_all_seqs_hash {
|
|
80
|
+
my $self = shift;
|
|
81
|
+
|
|
82
|
+
my %acc_to_seq;
|
|
83
|
+
|
|
84
|
+
while (my $seq_obj = $self->next()) {
|
|
85
|
+
my $acc = $seq_obj->get_accession();
|
|
86
|
+
my $sequence = $seq_obj->get_sequence();
|
|
87
|
+
|
|
88
|
+
$acc_to_seq{$acc} = $sequence;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return(%acc_to_seq);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
##############################################
|
|
97
|
+
package Sequence;
|
|
98
|
+
use strict;
|
|
99
|
+
|
|
100
|
+
sub new {
|
|
101
|
+
my ($packagename, $header, $sequence) = @_;
|
|
102
|
+
|
|
103
|
+
## extract an accession from the header:
|
|
104
|
+
my ($acc, $rest) = split (/\s+/, $header, 2);
|
|
105
|
+
|
|
106
|
+
my $self = { accession => $acc,
|
|
107
|
+
header => $header,
|
|
108
|
+
sequence => $sequence,
|
|
109
|
+
filename => undef };
|
|
110
|
+
bless ($self, $packagename);
|
|
111
|
+
return ($self);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
####
|
|
115
|
+
sub get_accession {
|
|
116
|
+
my $self = shift;
|
|
117
|
+
return ($self->{accession});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
####
|
|
121
|
+
sub get_header {
|
|
122
|
+
my $self = shift;
|
|
123
|
+
return ($self->{header});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
####
|
|
127
|
+
sub get_sequence {
|
|
128
|
+
my $self = shift;
|
|
129
|
+
return ($self->{sequence});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
####
|
|
133
|
+
sub get_FASTA_format {
|
|
134
|
+
my $self = shift;
|
|
135
|
+
my $header = $self->get_header();
|
|
136
|
+
my $sequence = $self->get_sequence();
|
|
137
|
+
$sequence =~ s/(\S{60})/$1\n/g;
|
|
138
|
+
my $fasta_entry = ">$header\n$sequence\n";
|
|
139
|
+
return ($fasta_entry);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
####
|
|
144
|
+
sub write_fasta_file {
|
|
145
|
+
my $self = shift;
|
|
146
|
+
my $filename = shift;
|
|
147
|
+
|
|
148
|
+
my ($accession, $header, $sequence) = ($self->{accession}, $self->{header}, $self->{sequence});
|
|
149
|
+
|
|
150
|
+
my $fasta_entry = $self->get_FASTA_format();
|
|
151
|
+
|
|
152
|
+
my $tempfile;
|
|
153
|
+
if ($filename) {
|
|
154
|
+
$tempfile = $filename;
|
|
155
|
+
} else {
|
|
156
|
+
my $acc = $accession;
|
|
157
|
+
$acc =~ s/\W/_/g;
|
|
158
|
+
$tempfile = "$acc.fasta";
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
open (TMP, ">$tempfile") or die "ERROR! Couldn't write a temporary file in current directory.\n";
|
|
162
|
+
print TMP $fasta_entry;
|
|
163
|
+
close TMP;
|
|
164
|
+
return ($tempfile);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
1; #EOM
|
|
168
|
+
|
|
169
|
+
|
quickprot/GFF3_utils2.pm
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/usr/local/bin/perl
|
|
2
|
+
|
|
3
|
+
package main;
|
|
4
|
+
our $SEE;
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
package GFF3_utils2; # removes DB_File requirement, no use of Gene_obj_indexer module.
|
|
8
|
+
|
|
9
|
+
use strict;
|
|
10
|
+
use warnings;
|
|
11
|
+
use Gene_obj;
|
|
12
|
+
use Carp;
|
|
13
|
+
use URI::Escape;
|
|
14
|
+
use Data::Dumper;
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
####
|
|
18
|
+
sub index_GFF3_gene_objs {
|
|
19
|
+
|
|
20
|
+
my ($gff_filename, $gene_obj_indexer, $contig_id) = @_;
|
|
21
|
+
# contig_id is optional.
|
|
22
|
+
|
|
23
|
+
unless (ref $gene_obj_indexer eq 'HASH') {
|
|
24
|
+
confess "Error, \$gene_obj_indexer must be a hashref";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
## note can use either a gene_obj_indexer or a hash reference.
|
|
28
|
+
|
|
29
|
+
my %gene_coords;
|
|
30
|
+
my %asmbl_id_to_gene_id_list;
|
|
31
|
+
my %transcript_to_gene;
|
|
32
|
+
my %cds_phases;
|
|
33
|
+
|
|
34
|
+
my %gene_names;
|
|
35
|
+
my %loci;
|
|
36
|
+
|
|
37
|
+
open (my $fh, $gff_filename) or die $!;
|
|
38
|
+
|
|
39
|
+
my %gene_id_to_source_type;
|
|
40
|
+
|
|
41
|
+
my %source_tracker;
|
|
42
|
+
|
|
43
|
+
my $counter = 0;
|
|
44
|
+
# print STDERR "\n-parsing file $gff_filename\n";
|
|
45
|
+
while (<$fh>) {
|
|
46
|
+
|
|
47
|
+
chomp;
|
|
48
|
+
|
|
49
|
+
unless (/\w/) { next;} # empty line
|
|
50
|
+
|
|
51
|
+
if (/^\#/) { next; } # comment entry in gff3
|
|
52
|
+
|
|
53
|
+
my @x = split (/\t/);
|
|
54
|
+
|
|
55
|
+
unless (scalar @x >= 9) {
|
|
56
|
+
print STDERR "-ignoring line $_\n";
|
|
57
|
+
next;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
my ($asmbl_id, $source, $feat_type, $lend, $rend, $orient, $cds_phase, $gene_info) = ($x[0], $x[1], $x[2], $x[3], $x[4], $x[6], $x[7], $x[8]);
|
|
61
|
+
|
|
62
|
+
if ($contig_id && $asmbl_id ne $contig_id) { next; }
|
|
63
|
+
|
|
64
|
+
unless ($feat_type) { die "Error, $_, no feat_type: line\[$_\]"; }
|
|
65
|
+
|
|
66
|
+
unless ($feat_type =~ /^(gene|mRNA|CDS|exon)$/) { next;} ## these are the only fields I care about right now.
|
|
67
|
+
|
|
68
|
+
$gene_info = uri_unescape($gene_info);
|
|
69
|
+
|
|
70
|
+
$gene_info =~ /ID=([^;\s]+);?/;
|
|
71
|
+
my $id = $1 or die "Error, couldn't get the id field $_";
|
|
72
|
+
|
|
73
|
+
if (exists $source_tracker{$id} && $source_tracker{$id} ne $source) {
|
|
74
|
+
confess "Error, gene ID $id is given source $source when previously encountered with source $source_tracker{$id} ";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if ($feat_type eq 'gene') {
|
|
78
|
+
my $gene_name = "";
|
|
79
|
+
if ($gene_info =~ /Name=\"?([^\;\"]+)\"?/) {
|
|
80
|
+
$gene_name = $1;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
$gene_name = "";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if ($gene_info =~ /Note=\"?([^\;\"]+)\"?/) {
|
|
87
|
+
$gene_name .= " $1";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
$gene_names{$id} = $gene_name;
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if ($gene_info =~ /Alias=([^;]+)/) {
|
|
95
|
+
my $locus = $1;
|
|
96
|
+
$loci{$id} = $locus;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if ($feat_type eq 'gene') { next;} ## beyond this pt, gene is not needed.
|
|
101
|
+
|
|
102
|
+
$gene_info =~ /Parent=([^;\s]+);?/;
|
|
103
|
+
my $parent = $1 or die "Error, couldn't get the parent info $_";
|
|
104
|
+
|
|
105
|
+
# print "id: $id, parent: $parent\n";
|
|
106
|
+
|
|
107
|
+
if ($feat_type eq 'mRNA') {
|
|
108
|
+
## just get the identifier info
|
|
109
|
+
$transcript_to_gene{$id} = $parent;
|
|
110
|
+
next;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
my $transcript_id = $parent;
|
|
114
|
+
my $gene_id = $transcript_to_gene{$transcript_id};
|
|
115
|
+
unless (defined $gene_id) {
|
|
116
|
+
print STDERR "Error, no gene feature found for $transcript_id.... ignoring feature.\n";
|
|
117
|
+
next;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
$gene_id_to_source_type{$gene_id} = $source;
|
|
122
|
+
|
|
123
|
+
my ($end5, $end3) = ($orient eq '+') ? ($lend, $rend) : ($rend, $lend);
|
|
124
|
+
|
|
125
|
+
$gene_coords{$asmbl_id}->{$gene_id}->{$transcript_id}->{$feat_type}->{$end5} = $end3;
|
|
126
|
+
# print "$asmbl_id, $gene_id, $transcript_id, $feat_type, $end5, $end3\n";
|
|
127
|
+
|
|
128
|
+
if ($cds_phase =~ /^\d+$/) {
|
|
129
|
+
$cds_phases{$gene_id}->{$transcript_id}->{$end5} = $cds_phase;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
}
|
|
133
|
+
close $fh;
|
|
134
|
+
|
|
135
|
+
##
|
|
136
|
+
# print STDERR "\n-caching genes.\n";
|
|
137
|
+
foreach my $asmbl_id (sort keys %gene_coords) {
|
|
138
|
+
my $genes_href = $gene_coords{$asmbl_id};
|
|
139
|
+
|
|
140
|
+
foreach my $gene_id (keys %$genes_href) {
|
|
141
|
+
#print STDERR "\r-indexing [$gene_id] ";
|
|
142
|
+
my $transcripts_href = $genes_href->{$gene_id};
|
|
143
|
+
|
|
144
|
+
my @gene_objs;
|
|
145
|
+
|
|
146
|
+
foreach my $transcript_id (keys %$transcripts_href) {
|
|
147
|
+
|
|
148
|
+
my $cds_coords_href = $transcripts_href->{$transcript_id}->{CDS} || {}; # could be a noncoding transcript w/ no CDS
|
|
149
|
+
my $exon_coords_href = $transcripts_href->{$transcript_id}->{exon};
|
|
150
|
+
|
|
151
|
+
unless (ref $exon_coords_href) {
|
|
152
|
+
print STDERR Dumper ($transcripts_href);
|
|
153
|
+
die "Error, missing exon coords for $transcript_id, $gene_id\n";
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
my $gene_obj = new Gene_obj();
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
if (scalar (keys %$cds_coords_href) == 1) {
|
|
160
|
+
|
|
161
|
+
## could be that only the cds span was provided.
|
|
162
|
+
## break it up across the exon segments
|
|
163
|
+
|
|
164
|
+
my ($cds_lend, $cds_rend) = sort {$a<=>$b} %$cds_coords_href;
|
|
165
|
+
my @exon_coords;
|
|
166
|
+
my $orient;
|
|
167
|
+
foreach my $exon_end5 (keys %$exon_coords_href) {
|
|
168
|
+
my $exon_end3 = $exon_coords_href->{$exon_end5};
|
|
169
|
+
push (@exon_coords, [$exon_end5, $exon_end3]);
|
|
170
|
+
if ($exon_end5 < $exon_end3) {
|
|
171
|
+
$orient = '+';
|
|
172
|
+
}
|
|
173
|
+
elsif ($exon_end5 > $exon_end3) {
|
|
174
|
+
$orient = '-';
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
$gene_obj->build_gene_obj_exons_n_cds_range(\@exon_coords, $cds_lend, $cds_rend, $orient);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
|
|
182
|
+
## cds and exons specified separately
|
|
183
|
+
|
|
184
|
+
$gene_obj->populate_gene_obj($cds_coords_href, $exon_coords_href);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
$gene_obj->{Model_feat_name} = $transcript_id;
|
|
188
|
+
$gene_obj->{TU_feat_name} = $gene_id;
|
|
189
|
+
$gene_obj->{asmbl_id} = $asmbl_id;
|
|
190
|
+
|
|
191
|
+
if (my $gene_locus = $loci{$gene_id}) {
|
|
192
|
+
$gene_obj->{pub_locus} = $gene_locus;
|
|
193
|
+
}
|
|
194
|
+
if (my $transcript_locus = $loci{$transcript_id}) {
|
|
195
|
+
$gene_obj->{model_pub_locus} = $transcript_locus;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
$gene_obj->{com_name} = $gene_names{$gene_id} || $transcript_id;
|
|
200
|
+
|
|
201
|
+
$gene_obj->{source} = $gene_id_to_source_type{$gene_id};
|
|
202
|
+
|
|
203
|
+
## set CDS phase info if available from the gff
|
|
204
|
+
my $cds_phases_href = $cds_phases{$gene_id}->{$transcript_id};
|
|
205
|
+
if (ref $cds_phases_href) {
|
|
206
|
+
## set the cds phases
|
|
207
|
+
my @exons = $gene_obj->get_exons();
|
|
208
|
+
foreach my $exon (@exons) {
|
|
209
|
+
if (my $cds = $exon->get_CDS_obj()) {
|
|
210
|
+
my ($end5, $end3) = $cds->get_coords();
|
|
211
|
+
my $phase = $cds_phases_href->{$end5};
|
|
212
|
+
unless ($phase =~ /\d+/) {
|
|
213
|
+
confess "Error, should have phase set for cds $gene_id $transcript_id $end5, but I do not. ";
|
|
214
|
+
}
|
|
215
|
+
$cds->set_phase($phase);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
push (@gene_objs, $gene_obj);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
## want single gene that includes all alt splice variants here
|
|
224
|
+
my $template_gene_obj = shift @gene_objs;
|
|
225
|
+
foreach my $other_gene_obj (@gene_objs) {
|
|
226
|
+
$template_gene_obj->add_isoform($other_gene_obj);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
$template_gene_obj->refine_gene_object();
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
$gene_obj_indexer->{$gene_id} = $template_gene_obj;
|
|
233
|
+
|
|
234
|
+
print "GFF3_utils: stored $gene_id\n" if $SEE;
|
|
235
|
+
|
|
236
|
+
# add to gene list for asmbl_id
|
|
237
|
+
my $gene_list_aref = $asmbl_id_to_gene_id_list{$asmbl_id};
|
|
238
|
+
unless (ref $gene_list_aref) {
|
|
239
|
+
$gene_list_aref = $asmbl_id_to_gene_id_list{$asmbl_id} = [];
|
|
240
|
+
}
|
|
241
|
+
push (@$gene_list_aref, $gene_id);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
print STDERR "\n";
|
|
245
|
+
return (\%asmbl_id_to_gene_id_list);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
1; #EOM
|