File Coverage

blib/lib/Bio/CUA.pm
Criterion Covered Total %
statement 63 97 64.9
branch 13 30 43.3
condition 2 13 15.3
subroutine 13 17 76.4
pod 3 6 50.0
total 94 163 57.6


line stmt bran cond sub pod time code
1             package Bio::CUA;
2              
3 6     6   19354 use 5.006;
  6         19  
  6         303  
4 6     6   25 use strict;
  6         9  
  6         151  
5 6     6   21 use warnings;
  6         13  
  6         138  
6 6     6   21 use Carp;
  6         9  
  6         7442  
7              
8             # some global variables
9             our $VERSION = '1.03';
10             my $sep = "\t";
11             #my @openFHs; # all file handles opened by this class
12              
13             =pod
14              
15             =head1 NAME
16              
17             Bio::CUA - Codon Usage Analyzer.
18              
19             =head1 VERSION
20              
21             Version 1.03
22              
23             =head1 SYNOPSIS
24              
25             This is the root class for the whole distribution of
26             L,
27             providing some routine methods used by all classs in the
28             distribution L. Users should not use this class
29             directly. Please start with its child classes such as
30             L, L.
31              
32             =head1 DESCRIPTION
33              
34             The aim of this distribution is to provide comprehensive and flexible
35             tools to analyze codon usage bias (CUB) and relevant problems, so that
36             users can speed up the genetic research by taking advantage of this
37             convenience.
38              
39             One amino acid can be encoded by more than one synonymous codon, and
40             synonymous codons are unevenly used. For example, some codons are used
41             more often than other synonymous ones in highly expressed genes (I
42             and Li 1987>). To measure the unevenness of codon usage, multiple
43             metrics of codon usage bias have been developed, such as Fop
44             (Frequency of optimal codons), CAI (Codon Adaptation Index), tAI (tRNA
45             Adaptation Index), and ENC (Effective Number of Codons). The causes of
46             CUB phenomena are complicated, including, mutational bias, selection on
47             translational efficiency or accurancy. CUB is one fundamental concept
48             in genetics.
49              
50             So far, no software exists to compute all the above CUB metrics, and
51             more importantly parameters of CUB calculations are often fixed in
52             software, so one can only analyze genes in a limited list of species
53             and one can not incorporate its own parameters such as sequences of
54             highly expressed genes in a tissue.
55              
56             This package mainly solves these two problems. We also extend some
57             methods, such as GC-content corrected ENC, background-data normalized
58             CAI, etc. See the relevant methods in CUB classes for more details.
59              
60             =head1 METHODS
61              
62             =cut
63              
64             sub new
65             {
66 119     119 0 453 my ($caller, @args) = @_;
67 119         233 my $self = {};
68 119 50       345 my $class = ref($caller)? ref($caller) : $caller;
69              
70 119         502 bless $self, $class;
71 119         453 my $hashRef = $self->_array_to_hash(\@args);
72              
73             # only process its own argument
74 119 50       361 $self->debug(1) if($hashRef->{'debug'});
75              
76 119         620 return $self;
77             }
78              
79             # store and retrieve tag values
80             sub get_tag
81             {
82 312     312 0 651 my ($self, $tag) = @_;
83 312         2188 return $self->{'_tags'}->{$tag};
84             }
85              
86             sub set_tag
87             {
88 323     323 0 639 my ($self, $tag, $val) = @_;
89 323         1186 $self->{'_tags'}->{$tag} = $val;
90             }
91              
92             =head2 debug
93              
94             Title : debug
95             Usage : $true_of_false=$self->debug([$bool]);
96             Function: get/set the boolean value.
97             Returns : 0 as false, 1 as true
98             Args : optional. 0 or 1 for false and true, respectively.
99              
100             =cut
101              
102             sub debug
103             {
104 74     74 1 150 my ($self, $val) = @_;
105 74 50       221 $self->set_tag('debug', $val) if($val);
106 74         173 return $self->get_tag('debug');
107             }
108              
109              
110             =head2 throw
111              
112             Title : throw
113             Usage : $self->throw("Some fatal errors");
114             Function: stop and report when fatal errors in formatted message
115             Returns : None
116             Args : error message
117              
118             =cut
119              
120             # simplified version
121             sub throw
122             {
123 0     0 1 0 my ($self, @args) = @_;
124 0   0     0 my $class = ref($self) || $self;
125 0 0       0 $class = ' '.$class if $class;
126 0         0 my $title = "------------- EXCEPTION$class -------------";
127 0         0 my $footer = ('-' x length($title))."\n";
128             #my $text = join("\n", @args);
129 0         0 my $text = _format_text(join(' ',@args));
130 0         0 croak "\n$title\n", "MSG: $text\n", $footer, "\n";
131             }
132              
133             =head2 warn
134              
135             Title : warn
136             Usage : $self->warn("Please pay attention here")
137             Function: report warning message when something looks not good
138             Returns : None
139             Args : warning messages.
140              
141             =cut
142              
143             sub warn
144             {
145 0     0 1 0 my ($self, @args) = @_;
146              
147 0   0     0 my $class = ref($self) || $self;
148 0 0       0 $class = ' '.$class if $class;
149 0         0 my $title = "------------- WARNING$class -------------";
150 0         0 my $footer = ('-' x length($title))."\n";
151 0         0 my $text = _format_text(join(' ',@args));
152             #my $text = join("\n", @args);
153 0         0 carp "\n$title\n", "MSG: $text\n", $footer, "\n";
154             }
155              
156             # format the text into blocks with same line length
157             sub _format_text
158             {
159 0     0   0 my ($text, $lineLen) = @_;
160              
161 0   0     0 $lineLen ||= 60;
162 0         0 chomp($text);
163 0         0 my $result = '';
164              
165 0         0 my @blocks = split /\n/, $text;
166              
167 0         0 foreach my $b (@blocks)
168             {
169 0         0 my $newB = _break_into_lines($b, $lineLen);
170 0         0 $result .= $newB;
171             }
172 0         0 return $result;
173             }
174              
175             sub _break_into_lines
176             {
177 0     0   0 my ($text, $size) = @_;
178              
179 0         0 my $lines = '';
180 0         0 my $textLen = length($text);
181              
182 0         0 my $accuLen = 0;
183 0         0 while($accuLen < $textLen)
184             {
185 0 0       0 my $lineLen = $accuLen + $size > $textLen? $textLen - $accuLen
186             : $size;
187 0         0 my $l = substr($text,$accuLen,$lineLen);
188 0         0 $accuLen += $lineLen;
189 0         0 $lines .= $l."\n";
190             }
191              
192 0         0 return $lines;
193             }
194              
195             # return hash ref by reading into an array ref
196             sub _array_to_hash
197             {
198 240     240   356 my ($self,$arrayRef,$nc) = @_;
199              
200 240 50       854 $self->throw("parameter '$arrayRef' to _array_to_hash is not an array reference")
201             unless(ref($arrayRef) eq 'ARRAY');
202              
203 240         329 my %hash;
204              
205 240 50       770 $self->throw("Odd number of elements are in the array fed to",
206             "_array_to_hash, check the array $arrayRef")
207             unless($#$arrayRef % 2);
208              
209 240         790 for(my $i = 0; $i < $#$arrayRef; $i += 2)
210             {
211 674         856 my $k = $arrayRef->[$i];
212 674         2094 $k =~ s/^\-*//; # removing leading '-'
213 674 50       1607 $k = lc($k) unless($nc);
214 674         2569 $hash{$k} = $arrayRef->[$i+1];
215             }
216              
217 240         739 return \%hash;
218             }
219              
220              
221             # write out hash to an outfile
222             sub _write_out_hash
223             {
224 2     2   5 my ($self, $outFile, $hashRef) = @_;
225              
226 2         4 my $fh;
227 2 50       276 open($fh, "> $outFile") or die "Can not open $outFile:$!";
228             # let's sort the hash so that every time the same order is
229             # produced
230 2         73 my @sortedKeys = sort keys(%$hashRef);
231 2         11 foreach my $k (@sortedKeys)
232             {
233 119         464 print $fh join($sep, $k, $hashRef->{$k}),"\n";
234             }
235 2         99 close $fh;
236              
237 2         20 return 1;
238             }
239              
240             # open a file and return its file handle
241             sub _open_file
242             {
243 15     15   41 my ($self, $file, $mode) = @_;
244              
245 15   50     88 $mode ||= ' ';
246              
247 15         26 my $fh;
248 15 50       1162 open($fh, "$mode $file") or $self->throw("can not open $file:$!");
249             #push @openFHs, $fh;
250 15         108 return $fh;
251             }
252              
253             # parse the first $num fields of input file, and use the vaule at the
254             # first column as key
255             sub _parse_file
256             {
257 2     2   5 my ($self, $file, $num) = @_;
258              
259 2         4 my %hash;
260 2         12 my $fh = $self->_open_file($file);
261 2         54 while(<$fh>)
262             {
263 119 50 33     1010 next if /^#/ or /^\s*$/;
264 119         190 chomp;
265 119         254 s/^\s+//; # remove leading blanks
266 119         674 my @fields = split /\s+/;
267 119 50       412 if($num > 1)
268             {
269 119 50       901 $hash{uc($fields[0])} = $num > 2?
270             [@fields[1..($num-1)]] : $fields[1];
271             }else
272             {
273 0         0 $hash{uc($fields[0])}++;
274             }
275             }
276 2         38 close $fh;
277 2         29 return \%hash;
278             }
279              
280             # this method is called when object of this or child classes is being
281             # destroyed
282             # close the file handle if the object has one
283             sub DESTROY
284             {
285 119     119   12076 my $self = shift;
286             #print $self;
287 119 100       1993 close $self->{'_fh'} if(exists $self->{'_fh'});
288             # $self->SUPER::DESTROY(@_);
289             }
290              
291             =head1 AUTHOR
292              
293             Zhenguo Zhang, C<< >>
294              
295             =head1 BUGS
296              
297             Please report any bugs or feature requests to C
298             rt.cpan.org> or through the web interface at
299             L. I will be
300             notified, and then you'll automatically be notified of progress on
301             your bug as I make changes.
302              
303             =cut
304              
305             =head1 SUPPORT
306              
307             You can find documentation for this class with the perldoc command.
308              
309             perldoc Bio::CUA
310              
311             You can also look for information at:
312              
313             =over 4
314              
315             =item * RT: CPAN's request tracker (report bugs here)
316              
317             L
318              
319             =item * AnnoCPAN: Annotated CPAN documentation
320              
321             L
322              
323             =item * CPAN Ratings
324              
325             L
326              
327             =item * Search CPAN
328              
329             L
330              
331             =back
332              
333              
334             =head1 ACKNOWLEDGEMENTS
335              
336              
337             =head1 LICENSE AND COPYRIGHT
338              
339             Copyright 2015 Zhenguo Zhang.
340              
341             This program is free software: you can redistribute it and/or modify
342             it under the terms of the GNU General Public License as published by
343             the Free Software Foundation, either version 3 of the License, or
344             (at your option) any later version.
345              
346             This program is distributed in the hope that it will be useful,
347             but WITHOUT ANY WARRANTY; without even the implied warranty of
348             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
349             GNU General Public License for more details.
350              
351             You should have received a copy of the GNU General Public License
352             along with this program. If not, see L.
353              
354              
355             =cut
356              
357             1; # End of Bio::CUA
358