File Coverage

Bio/Variation/RNAChange.pm
Criterion Covered Total %
statement 139 162 85.8
branch 116 162 71.6
condition 40 81 49.3
subroutine 13 15 86.6
pod 11 11 100.0
total 319 431 74.0


line stmt bran cond sub pod time code
1             #
2             # BioPerl module for Bio::Variation::RNAChange
3             #
4             # Please direct questions and support issues to
5             #
6             # Cared for by Heikki Lehvaslaiho
7             #
8             # Copyright Heikki Lehvaslaiho
9             #
10             # You may distribute this module under the same terms as perl itself
11              
12             # POD documentation - main docs before the code
13              
14             =head1 NAME
15              
16             Bio::Variation::RNAChange - Sequence change class for RNA level
17              
18             =head1 SYNOPSIS
19              
20             $rnachange = Bio::Variation::RNAChange->new
21             ('-start' => $start,
22             '-end' => $end,
23             '-length' => $len,
24             '-codon_pos' => $cp,
25             '-upStreamSeq' => $upflank,
26             '-dnStreamSeq' => $dnflank,
27             '-proof' => $proof,
28             '-isMutation' => 1,
29             '-mut_number' => $mut_number
30             );
31             $a1 = Bio::Variation::Allele->new;
32             $a1->seq('a');
33             $rnachange->allele_ori($a1);
34             my $a2 = Bio::Variation::Allele->new;
35             $a2->seq('t');
36             $rnachange->add_Allele($a2);
37             $rnachange->allele_mut($a2);
38              
39             print "The codon change is ", $rnachange->codon_ori,
40             ">", $rnachange->codon_mut, "\n";
41              
42             # add it to a SeqDiff container object
43             $seqdiff->add_Variant($rnachange);
44              
45             # and create links to and from DNA level mutation objects
46             $rnachange->DNAMutation($dnamut);
47             $dnamut->RNAChange($rnachange);
48              
49             =head1 DESCRIPTION
50              
51             The instantiable class Bio::Variation::DNAMutation describes basic
52             sequence changes at RNA molecule level. It uses methods defined in
53             superclass Bio::Variation::VariantI. See L
54             for details.
55              
56             You are normally expected to create a corresponding
57             Bio::Variation::DNAMutation object even if mutation is defined at
58             RNA level. The numbering follows then cDNA numbering. Link the
59             DNAMutation object to the RNAChange object using the method
60             DNAMutation(). If the variation described by a RNAChange object is
61             translated, link the corresponding Bio::Variation::AAChange object
62             to it using method AAChange(). See L and
63             L for more information.
64              
65              
66             =head1 FEEDBACK
67              
68             =head2 Mailing Lists
69              
70             User feedback is an integral part of the evolution of this and other
71             Bioperl modules. Send your comments and suggestions preferably to the
72             Bioperl mailing lists Your participation is much appreciated.
73              
74             bioperl-l@bioperl.org - General discussion
75             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
76              
77              
78             =head2 Support
79              
80             Please direct usage questions or support issues to the mailing list:
81              
82             I
83              
84             rather than to the module maintainer directly. Many experienced and
85             reponsive experts will be able look at the problem and quickly
86             address it. Please include a thorough description of the problem
87             with code and data examples if at all possible.
88              
89             =head2 Reporting Bugs
90              
91             Report bugs to the Bioperl bug tracking system to help us keep track
92             the bugs and their resolution. Bug reports can be submitted via the
93             web:
94              
95             https://github.com/bioperl/bioperl-live/issues
96              
97             =head1 AUTHOR - Heikki Lehvaslaiho
98              
99             Email: heikki-at-bioperl-dot-org
100              
101             =head1 APPENDIX
102              
103             The rest of the documentation details each of the object
104             methods. Internal methods are usually preceded with a _
105              
106             =cut
107              
108              
109             # Let the code begin...
110              
111              
112             package Bio::Variation::RNAChange;
113 5     5   1601 use strict;
  5         6  
  5         118  
114              
115             # Object preamble - inheritance
116              
117 5     5   15 use Bio::Tools::CodonTable;
  5         6  
  5         82  
118              
119 5     5   14 use base qw(Bio::Variation::VariantI);
  5         5  
  5         4621  
120              
121             sub new {
122 26     26 1 183 my($class,@args) = @_;
123 26         86 my $self = $class->SUPER::new(@args);
124              
125 26         170 my ($start, $end, $length, $strand, $primary, $source,
126             $frame, $score, $gff_string,
127             $allele_ori, $allele_mut, $upstreamseq, $dnstreamseq,
128             $label, $status, $proof, $region, $region_value, $region_dist, $numbering,
129             $mut_number, $isMutation,
130             $codon_ori, $codon_mut, $codon_pos, $codon_table, $cds_end) =
131             $self->_rearrange([qw(START
132             END
133             LENGTH
134             STRAND
135             PRIMARY
136             SOURCE
137             FRAME
138             SCORE
139             GFF_STRING
140             ALLELE_ORI
141             ALLELE_MUT
142             UPSTREAMSEQ
143             DNSTREAMSEQ
144             LABEL
145             STATUS
146             PROOF
147             REGION
148             REGION_VALUE
149             REGION_DIST
150             NUMBERING
151             MUT_NUMBER
152             ISMUTATION
153             CODON_ORI
154             CODON_MUT
155             CODON_POS
156             TRANSLATION_TABLE
157             CDS_END
158             )],@args);
159            
160 26         144 $self->primary_tag("Variation");
161            
162 26         33 $self->{ 'alleles' } = [];
163            
164 26 100       82 $start && $self->start($start);
165 26 100       84 $end && $self->end($end);
166 26 100       64 $length && $self->length($length);
167 26 50       669 $strand && $self->strand($strand);
168 26 50       43 $primary && $self->primary_tag($primary);
169 26 50       45 $source && $self->source_tag($source);
170 26 50       36 $frame && $self->frame($frame);
171 26 50       35 $score && $self->score($score);
172 26 50       40 $gff_string && $self->_from_gff_string($gff_string);
173            
174 26 50       41 $allele_ori && $self->allele_ori($allele_ori);
175 26 50       36 $allele_mut && $self->allele_mut($allele_mut);
176 26 100       53 $upstreamseq && $self->upStreamSeq($upstreamseq);
177 26 100       57 $dnstreamseq && $self->dnStreamSeq($dnstreamseq);
178            
179 26 50       40 $label && $self->label($label);
180 26 50       48 $status && $self->status($status);
181 26 100       71 $proof && $self->proof($proof);
182 26 50       39 $region && $self->region($region);
183 26 50       42 $region_value && $self->region_value($region_value);
184 26 50       35 $region_dist && $self->region_dist($region_dist);
185 26 50       35 $numbering && $self->numbering($numbering);
186 26 100       66 $mut_number && $self->mut_number($mut_number);
187 26 100       44 $isMutation && $self->isMutation($isMutation);
188            
189 26 100       49 $codon_ori && $self->codon_ori($codon_ori);
190 26 100       61 $codon_mut && $self->codon_mut($codon_mut);
191 26 100       43 $codon_pos && $self->codon_pos($codon_pos);
192 26 50       40 $codon_table && $self->codon_table($codon_table);
193 26 100       37 $cds_end && $self->cds_end($cds_end);
194 26         70 return $self; # success - we hope!
195             }
196              
197              
198             =head2 codon_ori
199              
200             Title : codon_ori
201             Usage : $obj->codon_ori();
202             Function:
203              
204             Sets and returns codon_ori triplet. If value is not set,
205             creates the codon triplet from the codon position and
206             flanking sequences. The string has to be three characters
207             long. The character content is not checked.
208              
209             Example :
210             Returns : string
211             Args : string
212              
213             =cut
214              
215             sub codon_ori {
216 123     123 1 101 my ($self,$value) = @_;
217 123 100       237 if (defined $value) {
    100          
218 3 50       5 if (length $value != 3) {
219 0         0 $self->warn("Codon string \"$value\" is not three characters long");
220             }
221 3         6 $self->{'codon_ori'} = $value;
222             }
223             elsif (! $self->{'codon_ori'}) {
224 19         27 my $codon_ori = '';
225              
226 19 50 33     44 if ($self->region eq 'coding' && $self->start && $self->start >= 1) {
      33        
227            
228 19 50       47 $self->warn('Codon position is not defined')
229             if not defined $self->codon_pos;
230 19 50       48 $self->warn('Upstream flanking sequence is not defined')
231             if not defined $self->upStreamSeq;
232 19 50       43 $self->warn('Downstream flanking sequence is not defined')
233             if not defined $self->dnStreamSeq;
234              
235 19         32 my $cpos = $self->codon_pos;
236 19         36 $codon_ori = substr($self->upStreamSeq, -$cpos +1 , $cpos-1);
237 19 100 100     42 $codon_ori .= substr($self->allele_ori->seq, 0, 4-$cpos)
238             if $self->allele_ori and $self->allele_ori->seq;
239 19         40 $codon_ori .= substr($self->dnStreamSeq, 0, 3-length($codon_ori));
240             }
241 19         47 $self->{'codon_ori'} = lc $codon_ori;
242             }
243 123         346 return $self->{'codon_ori'};
244             }
245              
246              
247             =head2 codon_mut
248              
249             Title : codon_mut
250             Usage : $obj->codon_mut();
251             Function:
252              
253             Sets and returns codon_mut triplet. If value is not
254             set, creates the codon triplet from the codon position and
255             flanking sequences. Return undef for other than point mutations.
256              
257             Example :
258             Returns : string
259             Args : string
260              
261             =cut
262              
263              
264             sub codon_mut {
265 62     62 1 57 my ($self,$value) = @_;
266 62 100       87 if (defined $value) {
267 3 50       5 if (length $value != 3 ) {
268 0         0 $self->warn("Codon string \"$value\" is not three characters long");
269             }
270 3         4 $self->{'codon_mut'} = $value;
271             }
272             else {
273 59         52 my $codon_mut = '';
274 59 50 33     104 if ($self->allele_ori->seq and $self->allele_mut->seq and
      33        
      33        
      33        
      33        
275             CORE::length($self->allele_ori->seq) == 1 and
276             CORE::length($self->allele_mut->seq) == 1 and
277             $self->region eq 'coding' and $self->start >= 1) {
278              
279 59 50       84 $self->warn('Codon position is not defined')
280             if not defined $self->codon_pos;
281 59 50       95 $self->warn('Upstream flanking sequnce is not defined')
282             if not defined $self->upStreamSeq;
283 59 50       82 $self->warn('Downstream flanking sequnce is not defined')
284             if not defined $self->dnStreamSeq;
285 59 50       85 $self->throw('Mutated allele is not defined')
286             if not defined $self->allele_mut;
287            
288 59         77 my $cpos = $self->codon_pos;
289 59         89 $codon_mut = substr($self->upStreamSeq, -$cpos +1 , $cpos-1);
290 59 50 33     82 $codon_mut .= substr($self->allele_mut->seq, 0, 4-$cpos)
291             if $self->allele_mut and $self->allele_mut->seq;
292 59         99 $codon_mut .= substr($self->dnStreamSeq, 0, 3-length($codon_mut));
293            
294 59         92 $self->{'codon_mut'} = lc $codon_mut;
295             }
296             }
297 62         180 return $self->{'codon_mut'};
298             }
299              
300              
301             =head2 codon_pos
302              
303             Title : codon_pos
304             Usage : $obj->codon_pos();
305             Function:
306              
307             Sets and returns the position of the mutation start in the
308             codon. If value is not set, returns false.
309              
310             Example :
311             Returns : 1,2,3
312             Args : none if get, the new value if set
313              
314             =cut
315              
316              
317             sub codon_pos {
318 196     196 1 170 my ($self,$value) = @_;
319 196 100       260 if( defined $value) {
320 23 50       91 if ( $value !~ /[123]/ ) {
321 0         0 $self->throw("'$value' is not a valid codon position");
322             }
323 23         47 $self->{'codon_pos'} = $value;
324             }
325 196         311 return $self->{'codon_pos'};
326             }
327              
328              
329             =head2 codon_table
330              
331             Title : codon_table
332             Usage : $obj->codon_table();
333             Function:
334              
335             Sets and returns the codon table id of the RNA
336             If value is not set, returns 1, 'universal' code, as the default.
337              
338             Example :
339             Returns : integer
340             Args : none if get, the new value if set
341              
342             =cut
343              
344              
345             sub codon_table {
346 84     84 1 78 my ($self,$value) = @_;
347 84 100       128 if( defined $value) {
348 13 50       27 if ( not $value =~ /^\d$/ ) {
349 0         0 $self->throw("'$value' is not a valid codon table ID\n".
350             "Has to be a positive integer. Defaulting to 1\n");
351             } else {
352 13         16 $self->{'codon_table'} = $value;
353             }
354             }
355 84 100       127 if( ! exists $self->{'codon_table'} ) {
356 17         75 return 1;
357             } else {
358 67         160 return $self->{'codon_table'};
359             }
360             }
361              
362              
363             =head2 DNAMutation
364              
365             Title : DNAMutation
366             Usage : $mutobj = $obj->DNAMutation;
367             : $mutobj = $obj->DNAMutation($objref);
368             Function: Returns or sets the link-reference to a mutation/change object.
369             If there is no link, it will return undef
370             Returns : an obj_ref or undef
371              
372             =cut
373              
374              
375             sub DNAMutation {
376 120     120 1 98 my ($self,$value) = @_;
377 120 100       152 if (defined $value) {
378 21 50       52 if( ! $value->isa('Bio::Variation::DNAMutation') ) {
379 0         0 $self->throw("Is not a Bio::Variation::DNAMutation object but a [$self]");
380 0         0 return;
381             }
382             else {
383 21         35 $self->{'DNAMutation'} = $value;
384             }
385             }
386 120 100       163 unless (exists $self->{'DNAMutation'}) {
387 1         7 return;
388             } else {
389 119         249 return $self->{'DNAMutation'};
390             }
391             }
392              
393              
394             =head2 AAChange
395              
396             Title : AAChange
397             Usage : $mutobj = $obj->AAChange;
398             : $mutobj = $obj->AAChange($objref);
399             Function: Returns or sets the link-reference to a mutation/change object.
400             If there is no link, it will return undef
401             Returns : an obj_ref or undef
402              
403             =cut
404              
405             sub AAChange {
406 84     84 1 74 my ($self,$value) = @_;
407 84 100       131 if (defined $value) {
408 18 50       45 if( ! $value->isa('Bio::Variation::AAChange') ) {
409 0         0 $self->throw("Is not a Bio::Variation::AAChange object but a [$self]");
410 0         0 return;
411             }
412             else {
413 18         25 $self->{'AAChange'} = $value;
414             }
415             }
416 84 100       113 unless (exists $self->{'AAChange'}) {
417 4         8 return;
418             } else {
419 80         142 return $self->{'AAChange'};
420             }
421             }
422              
423              
424             =head2 exons_modified
425              
426             Title : exons_modified
427             Usage : $modified = $obj->exons_modified;
428             : $modified = $obj->exons_modified(1);
429             Function: Returns or sets information (example: a simple boolean flag) about
430             the modification of exons as a result of a mutation.
431              
432             =cut
433              
434             sub exons_modified {
435 0     0 1 0 my ($self,$value)=@_;
436 0 0       0 if (defined($value)) {
437 0         0 $self->{'exons_modified'}=$value;
438             }
439 0         0 return ($self->{'exons_modified'});
440             }
441              
442             =head2 region
443              
444             Title : region
445             Usage : $obj->region();
446             Function:
447              
448             Sets and returns the name of the sequence region type or
449             protein domain at this location. If value is not set,
450             returns false.
451              
452             Example :
453             Returns : string
454             Args : string
455              
456             =cut
457              
458              
459              
460             sub region {
461 162     162 1 136 my ($self,$value) = @_;
462 162 100       311 if( defined $value) {
    100          
463 24         37 $self->{'region'} = $value;
464             }
465             elsif (not defined $self->{'region'}) {
466              
467 7 50 33     23 $self->warn('Mutation start position is not defined')
468             if not defined $self->start and $self->verbose;
469 7 50 33     26 $self->warn('Mutation end position is not defined')
470             if not defined $self->end and $self->verbose;
471 7 50 33     25 $self->warn('Length of the CDS is not defined, the mutation can be beyond coding region!')
472             if not defined $self->cds_end and $self->verbose;
473            
474 7         26 $self->region('coding');
475 7 50 33     17 if ($self->end && $self->end < 0 ){
    50 33        
      33        
476 0         0 $self->region('5\'UTR');
477             }
478             elsif ($self->start && $self->cds_end && $self->start > $self->cds_end ) {
479 0         0 $self->region('3\'UTR');
480             }
481             }
482 162         450 return $self->{'region'};
483             }
484              
485             =head2 cds_end
486              
487             Title : cds_end
488             Usage : $cds_end = $obj->get_cds_end();
489             Function:
490              
491             Sets or returns the cds_end from the beginning of the DNA sequence
492             to the coordinate start used to describe variants.
493             Should be the location of the last nucleotide of the
494             terminator codon of the gene.
495              
496             Example :
497             Returns : value of cds_end, a scalar
498             Args :
499              
500             =cut
501              
502              
503              
504             sub cds_end {
505 24     24 1 25 my ($self, $value) = @_;
506 24 100       34 if (defined $value) {
507 2 50       12 $self->warn("[$value] is not a good value for sequence position")
508             if not $value =~ /^\d+$/ ;
509 2         6 $self->{'cds_end'} = $value;
510             } else {
511 22 100       52 $self->{'cds_end'} = $self->SeqDiff->cds_end if $self->SeqDiff;
512             }
513 24         93 return $self->{'cds_end'};
514             }
515              
516              
517             =head2 label
518              
519             Title : label
520             Usage : $obj->label();
521             Function:
522              
523             Sets and returns mutation event label(s). If value is not
524             set, or no argument is given returns false. Each
525             instantiable subclass of L needs
526             to implement this method. Valid values are listed in
527             'Mutation event controlled vocabulary' in
528             http://www.ebi.ac.uk/mutations/recommendations/mutevent.html.
529              
530             Example :
531             Returns : string
532             Args : string
533              
534             =cut
535              
536             sub label {
537 55     55 1 58 my ($self) = @_;
538 55         41 my ($o, $m, $type);
539 55 100 100     96 $o = $self->allele_ori->seq if $self->allele_ori and $self->allele_ori->seq;
540 55 100 100     129 $m = $self->allele_mut->seq if $self->allele_mut and $self->allele_mut->seq;
541              
542 55         134 my $ct = Bio::Tools::CodonTable -> new ( -id => $self->codon_table );
543 55 100 100     305 if ($o and $m and CORE::length($o) == 1 and CORE::length($m) == 1) {
      100        
      66        
544 28 100       64 if (defined $self->AAChange) {
545 24 50 33     60 if ($self->start > 0 and $self->start < 4 ) {
    50 33        
    100 66        
    100 33        
      66        
      33        
546 0         0 $type = 'initiation codon';
547             }
548             elsif ($self->codon_ori && $ct->is_ter_codon($self->codon_ori) ) {
549             #AAChange->allele_ori and $self->AAChange->allele_ori->seq eq '*' ) {
550 0         0 $type = 'termination codon';
551             }
552             elsif ($self->codon_mut && $ct->is_ter_codon($self->codon_mut) ) {
553             #elsif ($self->AAChange->allele_mut and $self->AAChange->allele_mut->seq eq "*") {
554 5         6 $type = 'nonsense';
555             }
556             elsif ($o and $m and ($o eq $m or
557             $self->AAChange->allele_ori->seq eq
558             $self->AAChange->allele_mut->seq)) {
559 2         6 $type = 'silent';
560             } else {
561 17         28 $type = 'missense';
562             }
563             } else {
564 4         4 $type = 'unknown';
565             }
566             } else {
567 27         25 my $len = 0;
568 27 100       34 $len = CORE::length($o) if $o;
569 27 100       37 $len -= CORE::length($m) if $m;
570 27 100       41 if ($len%3 == 0 ) {
571 12         303 $type = 'inframe';
572             } else {
573 15         9 $type = 'frameshift';
574             }
575 27 100       44 if (not $m ) {
    100          
576 11         17 $type .= ', '. 'deletion';
577             }
578             elsif (not $o ) {
579 10         16 $type .= ', '. 'insertion';
580             }
581             else {
582 6         8 $type .= ', '. 'complex';
583             }
584 27 50 33     42 if ($self->codon_ori && $ct->is_ter_codon($self->codon_ori) ) {
585 0         0 $type .= ', '. 'termination codon';
586             }
587             }
588              
589 55         104 $self->{'label'} = $type;
590 55         161 return $self->{'label'};
591             }
592              
593              
594             =head2 _change_codon_pos
595              
596             Title : _change_codon_pos
597             Usage : $newCodonPos = _change_codon_pos($myCodonPos, 5)
598             Function:
599              
600             Keeps track of the codon position in a changeing sequence
601              
602             Returns : codon_pos = integer 1, 2 or 3
603             Args : valid codon position
604             signed integer offset to a new location in sequence
605              
606             =cut
607              
608              
609             sub _change_codon_pos ($$) {
610 0     0     my ($cpos, $i) = @_;
611              
612 0           $cpos = ($cpos + $i%3)%3;
613 0 0         if ($cpos > 3 ) {
    0          
614 0           $cpos = $cpos - 3;
615             }
616             elsif ($cpos < 1 ) {
617 0           $cpos = $cpos + 3;
618             }
619 0           return $cpos;
620             }
621              
622             1;