File Coverage

blib/lib/Bio/Translator.pm
Criterion Covered Total %
statement 58 78 74.3
branch 15 26 57.6
condition 0 3 0.0
subroutine 14 16 87.5
pod 5 5 100.0
total 92 128 71.8


line stmt bran cond sub pod time code
1             package Bio::Translator;
2              
3 9     9   73702 use strict;
  9         19  
  9         441  
4 9     9   47 use warnings;
  9         15  
  9         235  
5              
6 9     9   6418 use version; our $VERSION = qv('0.6.1');
  9         17277  
  9         62  
7              
8             =head1 NAME
9              
10             Bio::Translator - Translate DNA sequences
11              
12             =head1 SYNOPSIS
13              
14             use Bio::Translator;
15              
16             my $translator = new Bio::Translator();
17             my $translator = new Bio::Translator(11);
18             my $translator = new Bio::Translator( 12, 'id' );
19             my $translator = new Bio::Translator( 'Yeast Mitochondrial', 'name' );
20             my $translator = new Bio::Translator( 'mito', 'name' );
21              
22             my $translator = custom Bio::Translator( \$custom_table );
23             my $translator = custom Bio::Translator( \$custom_table, 1 );
24              
25             $translator->translate( \$seq );
26             $translator->translate( \$seq, { strand => 1 } );
27             $translator->translate( \$seq, { strand => -1 } );
28              
29             =head1 DESCRIPTION
30              
31             C tries to be a robust translator object featuring
32             translation tables based off the the ones provided by
33             L.
34             Key features include the ability to handle degenerate nucleotides and to
35             translate to ambiguous amino acids.
36              
37             First, create a new translator object using one of the included tables or a
38             custom one (see C for table formats), and then
39             passing your DNA sequences to your translator object.
40              
41             The translator uses interbase coordinates. See below for the difference between
42             interbase coordinates and traditional numbering methods:
43              
44             Traditional 1 2 3 4
45             A C G T ...
46             Interbase 0 1 2 3 4
47              
48             Conversion methods between the two methods can depend upon what you are trying
49             to do, but the simple way to do this is:
50              
51             strand = 3' end <=> 5' end # that's the spaceship operator!
52             lower = min( 5' end, 3' end ) - 1
53             upper = max( 5' end, 3' end )
54              
55             Parameter validation uses L which introduces overhead but can
56             be disabled. See the C documentation for more information.
57              
58             =cut
59              
60 9     9   900 use base 'Class::Accessor::Fast';
  9         19  
  9         8445  
61             __PACKAGE__->mk_accessors('table');
62              
63 9     9   34485 use Carp;
  9         23  
  9         1020  
64 9     9   19517 use Params::Validate;
  9         108974  
  9         621  
65              
66 9     9   6567 use Bio::Translator::Table;
  9         33  
  9         85  
67 9     9   6909 use Bio::Translator::Validations ':validations';
  9         23  
  9         1929  
68              
69 9     9   90 use Bio::Util::DNA qw/ $all_nucleotide_match /;
  9         19  
  9         10050  
70              
71             =head1 CONSTRUCTORS
72              
73             =cut
74              
75 8     8   138 sub _new { shift->SUPER::new( { table => shift } ) }
76              
77             =head2 new
78              
79             my $translator = new Bio::Translator();
80             my $translator = new Bio::Translator( $id );
81             my $translator = new Bio::Translator( $id, \%params );
82              
83             Create a translator with a translation table provided by $id. Please see
84             Bio::Translator::Table for the full list of options.
85              
86             =cut
87              
88             sub new {
89 7     7 1 127 my $class = shift;
90 7 50       84 my $table = Bio::Translator::Table->new(@_) or return;
91 7         70 $class->_new($table);
92             }
93              
94             =head2 custom()
95              
96             my $translator = $translator->custom( $table_ref );
97             my $translator = $translator->custom( $table_ref, \%params );
98              
99             Create a translator with a custom translation table. Please see
100             Bio::Translator::Table for the full list of options.
101              
102             =cut
103              
104             sub custom {
105 1     1 1 13 my $class = shift;
106 1 50       10 my $table = Bio::Translator::Table->custom(@_) or return;
107 1         8 $class->_new($table);
108             }
109              
110             =head1 METHODS
111              
112             =cut
113              
114             =head2 translate
115              
116             $pep_ref = $translator->translate( $seq_ref, \%params );
117              
118             The basic function of this module. Translate the specified region of the
119             sequence (passed as $seq_ref) and return a reference to the translated string.
120             The parameters are:
121              
122             strand: [+-]?1; default = 1
123             lower: integer between 0 and seq_length; default = 0
124             upper: integer between 0 and seq_length; default = seq_length
125             start: boolean
126             offset: [012]
127              
128             Translator uses interbase coordinates. "lower" and "upper" are optional
129             parameters such that:
130              
131             0 <= lower <= upper <= seq_length
132              
133             Translator will croak if those conditions are not satisfied.
134              
135             "start" sets whether or not to try translating the first codon as a start
136             codon. By default, translator will try to do this. "offset" allows you to
137             specify an offset in addition to the lower and upper abounds and have
138             Translator figure out the correct bound to offset from.
139              
140             To translate the following:
141              
142             0 1 2 3 4 5 6 7 8 9
143             C G C G C A G G A
144             ---------->
145              
146             $pep_ref = $translator->translate(
147             \$sequence,
148             {
149             strand => 1,
150             lower => 1,
151             upper => 7
152             }
153             );
154              
155             0 1 2 3 4 5 6 7 8 9
156             C G C G C A G G A
157             <----------
158              
159             $pep_ref = $translator->translate(
160             \$sequence,
161             {
162             strand => -1,
163             lower => 2,
164             upper => 8
165             }
166             );
167              
168             Examples:
169              
170             my $pep_ref = $translator->translate( \'acttgacgt' );
171              
172             my $pep_ref = $translator->translate( \'acttgacgt', { strand => -1 } );
173              
174             my $pep_ref = $translator->translate(
175             \'acttgacgt',
176             {
177             strand => -1,
178             lower => 2,
179             upper => 5
180             }
181             );
182              
183             my $pep_ref = $translator->translate(
184             \'acttgacgt',
185             {
186             strand => 1,
187             lower => 0,
188             upper => 8,
189             start => 0
190             }
191             );
192              
193             =cut
194              
195             sub translate {
196 9     9 1 98 my $self = shift;
197              
198 9         105 my ( $seq_ref, @p ) = validate_seq_params(@_);
199              
200 9         154 my %p = validate(
201             @p,
202             {
203             lower => $VAL_NON_NEG_INT,
204             upper => $VAL_NON_NEG_INT,
205             strand => $VAL_STRAND,
206             start => $VAL_START,
207             offset => $VAL_OFFSET,
208             }
209             );
210              
211 9         215 my ( $lower, $upper ) =
212             validate_lower_upper( delete( @p{qw/ lower upper /} ), $seq_ref );
213              
214             # adjust lower bound
215 9 100       27 $lower +=
216             $p{strand} == -1 ? ( $upper - $lower - $p{offset} ) % 3 : $p{offset};
217              
218 9         76 return $self->_translate( $seq_ref, $lower, $upper,
219             @p{qw/ strand start /} );
220             }
221              
222             =head2 translate_lus
223              
224             $pep_ref = $translator->translate_lus( $seq_ref, $range, \%params );
225             =cut
226              
227             sub translate_lus {
228 0     0 1 0 my $self = shift;
229              
230             # first validation pass
231 0         0 my ( $seq_ref, $r, @p ) = validate_pos(
232             @_,
233             { type => Params::Validate::SCALARREF | Params::Validate::SCALAR },
234             { type => Params::Validate::ARRAYREF },
235             { default => {}, type => Params::Validate::HASHREF }
236             );
237              
238 0 0       0 $seq_ref = \$seq_ref unless ( ref $seq_ref );
239              
240             # validate range
241 0         0 my ( $lower, $upper, $strand ) =
242             validate_pos( @$r, $VAL_NON_NEG_INT, $VAL_NON_NEG_INT, $VAL_STRAND );
243 0         0 ( $lower, $upper ) = validate_lower_upper( $lower, $upper, $seq_ref );
244              
245             # validate options
246 0         0 my %p = validate(
247             @p,
248             {
249             start => $VAL_START,
250             offset => $VAL_OFFSET,
251             }
252             );
253              
254             # adjust lower bound
255 0 0       0 $lower +=
256             $strand == -1
257             ? ( $upper - $p{offset} - $lower ) % 3
258             : $p{offset};
259              
260 0         0 return $self->_translate( $seq_ref, $lower, $upper, $strand, $p{start} );
261             }
262              
263             sub _translate {
264 9     9   19 my $self = shift;
265 9         17 my ( $seq_ref, $lower, $upper, $strand, $start ) = @_;
266 9 100       19 my $rc = $strand == -1 ? 1 : 0;
267              
268             # get a list of codon start locations
269 156         286 my @codon_starts =
270 9         30 map { $lower + 3 * $_ } ( 0 .. ( int( ( $upper - $lower ) / 3 ) - 1 ) );
271 9 100       30 @codon_starts = reverse @codon_starts if ($rc);
272              
273 9 50       15 return \'' unless (@codon_starts);
274              
275             # try to translate the start codon
276 9         12 my @start_peptide;
277 9 100       39 if ($start) {
278 7         20 my $start_aa =
279             $self->table->codon2start->[$rc]
280             { substr( $$seq_ref, $codon_starts[0], 3 ) };
281 7 100       78 if ($start_aa) {
282 2         5 push @start_peptide, $start_aa;
283 2         4 shift @codon_starts;
284             }
285             }
286              
287             # translate the rest of the peptide
288 9         23 my $codon2aa = $self->table->codon2aa->[$rc];
289 154 100       339 my $peptide = join '', @start_peptide,
290 154         262 map { $_ || 'X' }
291 9         62 @$codon2aa{ map { substr $$seq_ref, $_, 3 } @codon_starts };
292              
293 9         96 return \$peptide;
294             }
295              
296             =head2 translate_codon
297              
298             my $residue = $translator->translate_codon( $codon );
299             my $residue = $translator->translate_codon( $codon, \%params );
300              
301             Translate a codon. Return 'X' or '-' if it isn't in the
302             codon table. Handles degenerate nucleotides, so if all
303             possible codons for an ambiguity map to the same residue,
304             return that residue.
305              
306             Example:
307              
308             $residue = $translator->translate_codon('atg');
309             $residue = $translator->translate_codon( 'tty', { strand => -1 } );
310             $residue = $translator->translate_codon( 'cat', { start => 1 } );
311              
312             =cut
313              
314             sub translate_codon {
315 0     0 1   my $self = shift;
316              
317 0           my ( $codon, @p ) = validate_pos(
318             @_,
319             { regex => qr/^${all_nucleotide_match}{3}$/ },
320             { type => Params::Validate::HASHREF, default => {} }
321              
322             );
323              
324 0           my %p = validate(
325             @p,
326             {
327             strand => $VAL_STRAND,
328             start => { %$VAL_START, default => 0 }
329             }
330             );
331              
332 0           $codon = uc $codon;
333              
334             # Set up the translation table given the strand and whether this is
335             # searching for stop codons. Set up the not_found string by whether this
336             # is a start or not.
337 0 0         my $rc = $p{strand} == 1 ? 0 : 1;
338 0           my ( $table, $not_found );
339 0 0         unless ( $p{start} ) {
340 0           $table = $self->table->codon2aa->[$rc];
341 0           $not_found = 'X';
342             }
343             else {
344 0           $table = $self->table->codon2start->[$rc];
345 0           $not_found = '-';
346             }
347              
348 0   0       return $self->table->_unroll( $codon, $table, { start => $p{start} } )
349             || $not_found;
350             }
351              
352             1;
353              
354             =head1 AUTHOR
355              
356             Kevin Galinsky, C
357              
358             =head1 BUGS
359              
360             Please report any bugs or feature requests to
361             C, or through the web interface at
362             L.
363             I will be notified, and then you'll automatically be notified of progress on
364             your bug as I make changes.
365              
366             =head1 SUPPORT
367              
368             You can find documentation for this module with the perldoc command.
369              
370             perldoc Bio::Translator
371              
372             You can also look for information at:
373              
374             =over 4
375              
376             =item * AnnoCPAN: Annotated CPAN documentation
377              
378             L
379              
380             =item * CPAN Ratings
381              
382             L
383              
384             =item * RT: CPAN's request tracker
385              
386             L
387              
388             =item * Search CPAN
389              
390             L
391              
392             =back
393              
394             =head1 ACKNOWLEDGEMENTS
395              
396             JCVI/Paolo Amedeo
397              
398             =head1 COPYRIGHT & LICENSE
399              
400             Copyright 2008-2009 J. Craig Venter Institute, 2011 Kevin Galinsky.
401              
402             This program is free software; you can redistribute it and/or modify it
403             under the same terms as Perl itself.
404              
405             =cut