File Coverage

Bio/LiveSeq/Mutator.pm
Criterion Covered Total %
statement 325 518 62.7
branch 99 228 43.4
condition 47 150 31.3
subroutine 26 29 89.6
pod 15 15 100.0
total 512 940 54.4


line stmt bran cond sub pod time code
1             #
2             # bioperl module for Bio::LiveSeq::Mutator
3             #
4             # Please direct questions and support issues to
5             #
6             # Cared for by Heikki Lehvaslaiho
7             #
8             # Copyright Joseph Insana
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::LiveSeq::Mutator - Package mutating LiveSequences
17              
18             =head1 SYNOPSIS
19              
20             # $gene is a Bio::LiveSeq::Gene object
21             my $mutate = Bio::LiveSeq::Mutator->new('-gene' => $gene,
22             '-numbering' => "coding"
23             );
24             # $mut is a Bio::LiveSeq::Mutation object
25             $mutate->add_Mutation($mut);
26             # $results is a Bio::Variation::SeqDiff object
27             my $results=$mutate->change_gene();
28             if ($results) {
29             my $out = Bio::Variation::IO->new( '-format' => 'flat');
30             $out->write($results);
31             }
32              
33             =head1 DESCRIPTION
34              
35             This class mutates Bio::LiveSeq::Gene objects and returns a
36             Bio::Variation::SeqDiff object. Mutations are described as
37             Bio::LiveSeq::Mutation objects. See L,
38             L, and L for details.
39              
40             =head1 FEEDBACK
41              
42              
43             User feedback is an integral part of the evolution of this and other
44             Bioperl modules. Send your comments and suggestions preferably to the
45             Bioperl mailing lists Your participation is much appreciated.
46              
47             bioperl-l@bioperl.org - General discussion
48             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
49              
50             =head2 Support
51              
52             Please direct usage questions or support issues to the mailing list:
53              
54             I
55              
56             rather than to the module maintainer directly. Many experienced and
57             reponsive experts will be able look at the problem and quickly
58             address it. Please include a thorough description of the problem
59             with code and data examples if at all possible.
60              
61             =head2 Reporting Bugs
62              
63             report bugs to the Bioperl bug tracking system to help us keep track
64             the bugs and their resolution. Bug reports can be submitted via the
65             web:
66              
67             https://github.com/bioperl/bioperl-live/issues
68              
69             =head1 AUTHOR - Heikki Lehvaslaiho & Joseph A.L. Insana
70              
71             Email: heikki-at-bioperl-dot-org
72             insana@ebi.ac.uk, jinsana@gmx.net
73              
74             =head1 APPENDIX
75              
76             The rest of the documentation details each of the object
77             methods. Internal methods are usually preceded with a _
78              
79             =cut
80              
81             # Let the code begin...
82              
83             package Bio::LiveSeq::Mutator;
84 1     1   623 use strict;
  1         2  
  1         23  
85              
86 1     1   305 use Bio::Variation::SeqDiff;
  1         1  
  1         25  
87 1     1   283 use Bio::Variation::DNAMutation;
  1         3  
  1         31  
88 1     1   352 use Bio::Variation::RNAChange;
  1         2  
  1         28  
89 1     1   306 use Bio::Variation::AAChange;
  1         4  
  1         45  
90 1     1   262 use Bio::Variation::Allele;
  1         2  
  1         29  
91 1     1   295 use Bio::LiveSeq::Mutation;
  1         2  
  1         24  
92              
93             #use integer;
94             # Object preamble - inheritance
95              
96              
97 1     1   3 use base qw(Bio::Root::Root);
  1         2  
  1         3920  
98              
99             sub new {
100 5     5 1 163 my($class,@args) = @_;
101 5         10 my $self;
102 5         10 $self = {};
103 5         10 bless $self, $class;
104              
105 5         27 my ($gene, $numbering) =
106             $self->_rearrange([qw(GENE
107             NUMBERING
108             )],
109             @args);
110              
111 5         22 $self->{ 'mutations' } = [];
112              
113 5 100       24 $gene && $self->gene($gene);
114 5 100       21 $numbering && $self->numbering($numbering);
115              
116             #class constant;
117 5         9 $self->{'flanklen'} = 25;
118 5         14 return $self; # success - we hope!
119             }
120              
121             =head2 gene
122              
123             Title : gene
124             Usage : $mutobj = $obj->gene;
125             : $mutobj = $obj->gene($objref);
126             Function:
127              
128             Returns or sets the link-reference to a
129             Bio::LiveSeq::Gene object. If no value has ben set, it
130             will return undef
131              
132             Returns : an object reference or undef
133             Args : a Bio::LiveSeq::Gene
134              
135             See L for more information.
136              
137             =cut
138              
139             sub gene {
140 25     25 1 352 my ($self,$value) = @_;
141 25 100       42 if (defined $value) {
142 5 50       35 if( ! $value->isa('Bio::LiveSeq::Gene') ) {
143 0         0 $self->throw("Is not a Bio::LiveSeq::Gene object but a [$value]");
144 0         0 return;
145             }
146             else {
147 5         10 $self->{'gene'} = $value;
148             }
149             }
150 25 50       31 unless (exists $self->{'gene'}) {
151 0         0 return;
152             } else {
153 25         66 return $self->{'gene'};
154             }
155             }
156              
157              
158             =head2 numbering
159              
160             Title : numbering
161             Usage : $obj->numbering();
162             Function:
163              
164             Sets and returns coordinate system used in positioning the
165             mutations. See L for details.
166              
167             Example :
168             Returns : string
169             Args : string (coding [transcript number] | gene | entry)
170              
171             =cut
172              
173              
174             sub numbering {
175 29     29 1 402 my ($self,$value) = @_;
176 29 100       62 if( defined $value) {
177 6 50 66     51 if ($value =~ /(coding)( )?(\d+)?/ or $value eq 'entry' or $value eq 'gene') {
      33        
178 6         15 $self->{'numbering'} = $value;
179             } else { # defaulting to 'coding'
180 0         0 $self->{'numbering'} = 'coding';
181             }
182             }
183 29 100       74 unless (exists $self->{'numbering'}) {
184 1         5 return 'coding';
185             } else {
186 28         84 return $self->{'numbering'};
187             }
188             }
189              
190             =head2 add_Mutation
191              
192             Title : add_Mutation
193             Usage : $self->add_Mutation($ref)
194             Function: adds a Bio::LiveSeq::Mutation object
195             Example :
196             Returns :
197             Args : a Bio::LiveSeq::Mutation
198              
199             See L for more information.
200              
201             =cut
202              
203             sub add_Mutation{
204 5     5 1 23 my ($self,$value) = @_;
205 5 50       49 if( $value->isa('Bio::Liveseq::Mutation') ) {
206 0         0 my $com = ref $value;
207 0         0 $self->throw("Is not a Mutation object but a [$com]" );
208 0         0 return;
209             }
210 5 50       14 if (! $value->pos) {
211 0         0 $self->warn("No value for mutation position in the sequence!");
212 0         0 return;
213             }
214 5 0 33     12 if (! $value->seq && ! $value->len) {
215 0         0 $self->warn("Either mutated sequence or length of the deletion must be given!");
216 0         0 return;
217             }
218 5         9 push(@{$self->{'mutations'}},$value);
  5         17  
219             }
220              
221             =head2 each_Mutation
222              
223             Title : each_Mutation
224             Usage : foreach $ref ( $a->each_Mutation )
225             Function: gets an array of Bio::LiveSeq::Mutation objects
226             Example :
227             Returns : array of Mutations
228             Args :
229              
230             See L for more information.
231              
232             =cut
233              
234             sub each_Mutation{
235 6     6 1 13 my ($self) = @_;
236 6         10 return @{$self->{'mutations'}};
  6         22  
237             }
238              
239              
240             =head2 mutation
241              
242             Title : mutation
243             Usage : $mutobj = $obj->mutation;
244             : $mutobj = $obj->mutation($objref);
245             Function:
246              
247             Returns or sets the link-reference to the current mutation
248             object. If the value is not set, it will return undef.
249             Internal method.
250              
251             Returns : an object reference or undef
252              
253             =cut
254              
255              
256             sub mutation {
257 255     255 1 188 my ($self,$value) = @_;
258 255 100       379 if (defined $value) {
259 5 50       39 if( ! $value->isa('Bio::LiveSeq::Mutation') ) {
260 0         0 $self->throw("Is not a Bio::LiveSeq::Mutation object but a [$value]");
261 0         0 return;
262             }
263             else {
264 5         21 $self->{'mutation'} = $value;
265             }
266             }
267 255 50       317 unless (exists $self->{'mutation'}) {
268 0         0 return;
269             } else {
270 255         582 return $self->{'mutation'};
271             }
272             }
273              
274             =head2 DNA
275              
276             Title : DNA
277             Usage : $mutobj = $obj->DNA;
278             : $mutobj = $obj->DNA($objref);
279             Function:
280              
281             Returns or sets the reference to the LiveSeq object holding
282             the reference sequence. If there is no link, it will return
283             undef.
284             Internal method.
285              
286             Returns : an object reference or undef
287              
288             =cut
289              
290             sub DNA {
291 65     65 1 67 my ($self,$value) = @_;
292 65 100       116 if (defined $value) {
293 5 50 33     21 if( ! $value->isa('Bio::LiveSeq::DNA') and ! $value->isa('Bio::LiveSeq::Transcript') ) {
294 0         0 $self->throw("Is not a Bio::LiveSeq::DNA/Transcript object but a [$value]");
295 0         0 return;
296             }
297             else {
298 5         10 $self->{'DNA'} = $value;
299             }
300             }
301 65 50       111 unless (exists $self->{'DNA'}) {
302 0         0 return;
303             } else {
304 65         216 return $self->{'DNA'};
305             }
306             }
307              
308              
309             =head2 RNA
310              
311             Title : RNA
312             Usage : $mutobj = $obj->RNA;
313             : $mutobj = $obj->RNA($objref);
314             Function:
315              
316             Returns or sets the reference to the LiveSeq object holding
317             the reference sequence. If the value is not set, it will return
318             undef.
319             Internal method.
320              
321             Returns : an object reference or undef
322              
323             =cut
324              
325              
326             sub RNA {
327 116     116 1 191 my ($self,$value) = @_;
328 116 100       277 if (defined $value) {
329 5 50       19 if( ! $value->isa('Bio::LiveSeq::Transcript') ) {
330 0         0 $self->throw("Is not a Bio::LiveSeq::RNA/Transcript object but a [$value]");
331 0         0 return;
332             }
333             else {
334 5         6 $self->{'RNA'} = $value;
335             }
336             }
337 116 50       228 unless (exists $self->{'RNA'}) {
338 0         0 return;
339             } else {
340 116         472 return $self->{'RNA'};
341             }
342             }
343              
344              
345             =head2 dnamut
346              
347             Title : dnamut
348             Usage : $mutobj = $obj->dnamut;
349             : $mutobj = $obj->dnamut($objref);
350             Function:
351              
352             Returns or sets the reference to the current DNAMutation object.
353             If the value is not set, it will return undef.
354             Internal method.
355              
356             Returns : a Bio::Variation::DNAMutation object or undef
357              
358             See L for more information.
359              
360             =cut
361              
362              
363             sub dnamut {
364 22     22 1 25 my ($self,$value) = @_;
365 22 100       48 if (defined $value) {
366 5 50       16 if( ! $value->isa('Bio::Variation::DNAMutation') ) {
367 0         0 $self->throw("Is not a Bio::Variation::DNAMutation object but a [$value]");
368 0         0 return;
369             }
370             else {
371 5         13 $self->{'dnamut'} = $value;
372             }
373             }
374 22 50       41 unless (exists $self->{'dnamut'}) {
375 0         0 return;
376             } else {
377 22         67 return $self->{'dnamut'};
378             }
379             }
380              
381              
382             =head2 rnachange
383              
384             Title : rnachange
385             Usage : $mutobj = $obj->rnachange;
386             : $mutobj = $obj->rnachange($objref);
387             Function:
388              
389             Returns or sets the reference to the current RNAChange object.
390             If the value is not set, it will return undef.
391             Internal method.
392              
393             Returns : a Bio::Variation::RNAChange object or undef
394              
395             See L for more information.
396              
397             =cut
398              
399              
400             sub rnachange {
401 20     20 1 26 my ($self,$value) = @_;
402 20 100       52 if (defined $value) {
403 5 50       17 if( ! $value->isa('Bio::Variation::RNAChange') ) {
404 0         0 $self->throw("Is not a Bio::Variation::RNAChange object but a [$value]");
405 0         0 return;
406             }
407             else {
408 5         11 $self->{'rnachange'} = $value;
409             }
410             }
411 20 50       49 unless (exists $self->{'rnachange'}) {
412 0         0 return;
413             } else {
414 20         69 return $self->{'rnachange'};
415             }
416             }
417              
418              
419             =head2 aachange
420              
421             Title : aachange
422             Usage : $mutobj = $obj->aachange;
423             : $mutobj = $obj->aachange($objref);
424             Function:
425              
426             Returns or sets the reference to the current AAChange object.
427             If the value is not set, it will return undef.
428             Internal method.
429              
430             Returns : a Bio::Variation::AAChange object or undef
431              
432             See L for more information.
433              
434             =cut
435              
436              
437             sub aachange {
438 15     15 1 26 my ($self,$value) = @_;
439 15 100       40 if (defined $value) {
440 5 50       21 if( ! $value->isa('Bio::Variation::AAChange') ) {
441 0         0 $self->throw("Is not a Bio::Variation::AAChange object but a [$value]");
442 0         0 return;
443             }
444             else {
445 5         14 $self->{'aachange'} = $value;
446             }
447             }
448 15 50       42 unless (exists $self->{'aachange'}) {
449 0         0 return;
450             } else {
451 15         25 return $self->{'aachange'};
452             }
453             }
454              
455              
456             =head2 exons
457              
458             Title : exons
459             Usage : $mutobj = $obj->exons;
460             : $mutobj = $obj->exons($objref);
461             Function:
462              
463             Returns or sets the reference to a current array of Exons.
464             If the value is not set, it will return undef.
465             Internal method.
466              
467             Returns : an array of Bio::LiveSeq::Exon objects or undef
468              
469             See L for more information.
470              
471             =cut
472              
473              
474             sub exons {
475 15     15 1 22 my ($self,$value) = @_;
476 15 100       38 if (defined $value) {
477 5         11 $self->{'exons'} = $value;
478             }
479 15 50       32 unless (exists $self->{'exons'}) {
480 0         0 return;
481             } else {
482 15         46 return $self->{'exons'};
483             }
484             }
485              
486             =head2 change_gene_with_alignment
487              
488             Title : change_gene_with_alignment
489             Usage : $results=$mutate->change_gene_with_alignment($aln);
490              
491             Function:
492              
493             Returns a Bio::Variation::SeqDiff object containing the
494             results of the changes in the alignment. The alignment has
495             to be pairwise and have one sequence named 'QUERY', the
496             other one is assumed to be a part of the sequence from
497             $gene.
498              
499             This method offers a shortcut to change_gene and
500             automates the creation of Bio::LiveSeq::Mutation objects.
501             Use it with almost identical sequnces, e.g. to locate a SNP.
502              
503             Args : Bio::SimpleAlign object representing a short local alignment
504             Returns : Bio::Variation::SeqDiff object or 0 on error
505              
506             See L, L, and
507             L for more information.
508              
509             =cut
510              
511             sub change_gene_with_alignment {
512 0     0 1 0 my ($self, $aln) = @_;
513              
514             #
515             # Sanity checks
516             #
517              
518 0 0       0 $self->throw("Argument is not a Bio::SimpleAlign object but a [$aln]")
519             unless $aln->isa('Bio::SimpleAlign');
520 0 0       0 $self->throw("'Pairwise alignments only, please")
521             if $aln->no_sequences != 2;
522              
523             # find out the order the two sequences are given
524 0         0 my $queryseq_pos = 1; #default
525 0         0 my $refseq_pos = 2;
526 0 0       0 unless ($aln->get_seq_by_pos(1)->id eq 'QUERY') {
527 0 0       0 carp('Query sequence has to be named QUERY')
528             if $aln->get_seq_by_pos(2)->id ne 'QUERY';
529 0         0 $queryseq_pos = 2; # alternative
530 0         0 $refseq_pos = 1;
531             }
532              
533             # trim the alignment
534 0         0 my $start = $aln->column_from_residue_number('QUERY', 1);
535 0         0 my $end = $aln->column_from_residue_number('QUERY',
536             $aln->get_seq_by_pos($queryseq_pos)->end );
537            
538 0         0 my $aln2 = $aln->slice($start, $end);
539              
540             #
541             # extracting mutations
542             #
543              
544 0         0 my $cs = $aln2->consensus_string(51);
545 0         0 my $queryseq = $aln2->get_seq_by_pos($queryseq_pos);
546 0         0 my $refseq = $aln2->get_seq_by_pos($refseq_pos);
547              
548 0         0 while ( $cs =~ /(\?+)/g) {
549             # pos in local coordinates
550 0         0 my $pos = pos($cs) - length($1) + 1;
551 0         0 my $mutation = create_mutation($self,
552             $refseq,
553             $queryseq,
554             $pos,
555             CORE::length($1)
556             );
557             # reset pos to refseq coordinates
558 0         0 $pos += $refseq->start - 1;
559 0         0 $mutation->pos($pos);
560              
561 0         0 $self->add_Mutation($mutation);
562             }
563 0         0 return $self->change_gene();
564             }
565              
566             =head2 create_mutation
567              
568             Title : create_mutation
569             Usage :
570             Function:
571              
572             Formats sequence differences from two sequences into
573             Bio::LiveSeq::Mutation objects which can be applied to a
574             gene.
575              
576             To keep it generic, sequence arguments need not to be
577             Bio::LocatableSeq. Coordinate change to parent sequence
578             numbering needs to be done by the calling code.
579              
580             Called from change_gene_with_alignment
581              
582             Args : Bio::PrimarySeqI inheriting object for the reference sequence
583             Bio::PrimarySeqI inheriting object for the query sequence
584             integer for the start position of the local sequence difference
585             integer for the length of the sequence difference
586             Returns : Bio::LiveSeq::Mutation object
587              
588             =cut
589              
590             sub create_mutation {
591 0     0 1 0 my ($self, $refseq, $queryseq, $pos, $len) = @_;
592            
593 0 0       0 $self->throw("Is not a Bio::PrimarySeqI object but a [$refseq]")
594             unless $refseq->isa('Bio::PrimarySeqI');
595 0 0       0 $self->throw("Is not a Bio::PrimarySeqI object but a [$queryseq]")
596             unless $queryseq->isa('Bio::PrimarySeqI');
597 0 0       0 $self->throw("Position is not a positive integer but [$pos]")
598             unless $pos =~ /^\+?\d+$/;
599 0 0       0 $self->throw("Length is not a positive integer but [$len]")
600             unless $len =~ /^\+?\d+$/;
601              
602 0         0 my $mutation;
603 0         0 my $refstring = $refseq->subseq($pos, $pos + $len - 1);
604 0         0 my $varstring = $queryseq->subseq($pos, $pos + $len - 1);
605            
606 0 0 0     0 if ($len == 1 and $refstring =~ /[^\.\-\*\?]/ and
    0 0        
    0 0        
      0        
607             $varstring =~ /[^\.\-\*\?]/ ) { #point
608 0         0 $mutation = Bio::LiveSeq::Mutation->new(-seq => $varstring,
609             -pos => $pos,
610             );
611             }
612             elsif ( $refstring =~ /^[^\.\-\*\?]+$/ and
613             $varstring !~ /^[^\.\-\*\?]+$/ ) { # deletion
614 0         0 $mutation = Bio::LiveSeq::Mutation->new(-pos => $pos,
615             -len => $len
616             );
617             }
618             elsif ( $refstring !~ /^[^\.\-\*\?]+$/ and
619             $varstring =~ /^[^\.\-\*\?]+$/ ) { # insertion
620 0         0 $mutation = Bio::LiveSeq::Mutation->new(-seq => $varstring,
621             -pos => $pos,
622             -len => 0
623             );
624             } else { # complex
625 0         0 $mutation = Bio::LiveSeq::Mutation->new(-seq => $varstring,
626             -pos => $pos,
627             -len => $len
628             );
629             }
630            
631 0         0 return $mutation;
632             }
633              
634             =head2 change_gene
635              
636             Title : change_gene
637             Usage : my $mutate = Bio::LiveSeq::Mutator->new(-gene => $gene,
638             numbering => "coding"
639             );
640             # $mut is Bio::LiveSeq::Mutation object
641             $mutate->add_Mutation($mut);
642             my $results=$mutate->change_gene();
643              
644             Function:
645              
646             Returns a Bio::Variation::SeqDiff object containing the
647             results of the changes performed according to the
648             instructions present in Mutation(s). The -numbering
649             argument decides what molecule is being changed and what
650             numbering scheme being used:
651              
652             -numbering => "entry"
653              
654             determines the DNA level, using the numbering from the
655             beginning of the sequence
656              
657             -numbering => "coding"
658              
659             determines the RNA level, using the numbering from the
660             beginning of the 1st transcript
661              
662             Alternative transcripts can be used by specifying
663             "coding 2" or "coding 3" ...
664              
665             -numbering => "gene"
666              
667             determines the DNA level, using the numbering from the
668             beginning of the 1st transcript and inluding introns.
669             The meaning equals 'coding' if the reference molecule
670             is cDNA.
671              
672             Args : Bio::LiveSeq::Gene object
673             Bio::LiveSeq::Mutation object(s)
674             string specifying a numbering scheme (defaults to 'coding')
675             Returns : Bio::Variation::SeqDiff object or 0 on error
676              
677             =cut
678              
679             sub change_gene {
680 5     5 1 19 my ($self) = @_;
681              
682             #
683             # Sanity check
684             #
685 5 50       11 unless ($self->gene) {
686 0         0 $self->warn("Input object Bio::LiveSeq::Gene is not given");
687 0         0 return 0;
688             }
689             #
690             # Setting the reference sequence based on -numbering
691             #
692 5         6 my @transcripts=@{$self->gene->get_Transcripts};
  5         12  
693 5         8 my $refseq; # will hold Bio::LiveSeq:Transcript object or Bio::LiveSeq::DNA
694              
695             # 'gene' eq 'coding' if reference sequence is cDNA
696 5 50 66     11 $self->numbering ('coding') if $self->gene->get_DNA->alphabet eq 'rna' and $self->numbering eq 'gene';
697              
698 5 100       14 if ($self->numbering =~ /(coding)( )?(\d+)?/ ) {
699 1         3 $self->numbering($1);
700 1         3 my $transnumber = $3;
701 1 50       4 $transnumber-- if $3; # 1 -> 0, 2 -> 1
702 1 50 33     5 if ($transnumber && $transnumber >= 0 && $transnumber <= $#transcripts) {
      33        
703 0         0 $refseq=$transcripts[$transnumber];
704             } else {
705 1 50       3 $transnumber && $self->warn("The alternative transcript number ". $transnumber+1 .
706             "- does not exist. Reverting to the 1st transcript\n");
707 1         1 $refseq=$transcripts[0];
708             }
709             } else {
710 4         12 $refseq=$transcripts[0]->{'seq'};
711             }
712             #
713             # Recording the state: SeqDiff object creation ?? transcript no.??
714             #
715 5         32 my $seqDiff = Bio::Variation::SeqDiff->new(-verbose => $self->verbose);
716 5         15 $seqDiff->alphabet($self->gene->get_DNA->alphabet);
717 5         12 $seqDiff->numbering($self->numbering);
718 5         9 my ($DNAobj, $RNAobj);
719 5 100       34 if ($refseq->isa("Bio::LiveSeq::Transcript")) {
720 1         3 $self->RNA($refseq);
721 1         4 $self->DNA($refseq->{'seq'});
722 1         9 $seqDiff->rna_ori($refseq->seq );
723 1         5 $seqDiff->aa_ori($refseq->get_Translation->seq);
724             } else {
725 4         15 $self->DNA($refseq);
726 4         14 $self->RNA($transcripts[0]);
727 4         11 $seqDiff->rna_ori($self->RNA->seq);
728 4         17 $seqDiff->aa_ori($self->RNA->get_Translation->seq);
729             }
730 5         28 $seqDiff->dna_ori($self->DNA->seq);
731             # put the accession number into the SeqDiff object ID
732 5         27 $seqDiff->id($self->DNA->accession_number);
733              
734             # the atg_offset takes in account that DNA object could be a subset of the
735             # whole entry (via the light_weight loader)
736 5         17 my $atg_label=$self->RNA->start;
737 5         15 my $atg_offset=$self->DNA->position($atg_label)+($self->DNA->start)-1;
738 5         24 $seqDiff->offset($atg_offset - 1);
739 5         11 $self->DNA->coordinate_start($atg_label);
740              
741 5         10 my @exons = $self->RNA->all_Exons;
742 5         22 $seqDiff->cds_end($exons[$#exons]->end);
743              
744             #
745             # Converting mutation positions to labels
746             #
747 5 50       17 $self->warn("no mutations"), return 0
748             unless $self->_mutationpos2label($refseq, $seqDiff);
749              
750             # need to add more than one rna & aa
751             #foreach $transcript (@transcripts) {
752             # $seqDiff{"ori_transcript_${i}_seq"}=$transcript->seq;
753             # $seqDiff{"ori_translation_${i}_seq"}=$transcript->get_Translation->seq;
754             #}
755              
756             # do changes
757 5         10 my $k;
758 5         17 foreach my $mutation ($self->each_Mutation) {
759 5 50       13 next unless $mutation->label > 0;
760 5         15 $self->mutation($mutation);
761              
762 5         25 $mutation->issue(++$k);
763             #
764             # current position on the transcript
765             #
766 5 100       16 if ($self->numbering =~ /coding/) {
767 1         4 $mutation->transpos($mutation->pos); # transpos given by user
768             } else {
769             #transpos of label / It will be 0 if mutating an intron, negative if upstream of ATG
770 4         13 $mutation->transpos($self->RNA->position($mutation->label,$atg_label));
771             }
772             #
773             # Calculate adjacent labels based on the position on the current sequence
774             #
775 5         26 $mutation->prelabel($self->DNA->label(-1, $mutation->label)); # 1 before label
776 5 50       19 if ($mutation->len == 0) {
    50          
777 0         0 $mutation->postlabel($mutation->label);
778 0         0 $mutation->lastlabel($mutation->label);
779             } elsif ($mutation->len == 1) {
780 5         13 $mutation->lastlabel($mutation->label); # last nucleotide affected
781 5         12 $mutation->postlabel($self->DNA->label(2,$mutation->lastlabel)); # $len after label
782             } else {
783 0         0 $mutation->lastlabel($self->DNA->label($mutation->len,$mutation->label));
784 0         0 $mutation->postlabel($self->DNA->label(2,$mutation->lastlabel));
785             }
786 5         21 my $dnamut = $self->_set_DNAMutation($seqDiff);
787             #
788             #
789             #
790 5 50 0     19 if ($self->_rnaAffected) {
    0          
791 5         24 $self->_set_effects($seqDiff, $dnamut);
792             }
793             elsif ($seqDiff->offset != 0 and $dnamut->region ne 'intron') {
794 0         0 $self->_untranslated ($seqDiff, $dnamut);
795             } else {
796             #$self->warn("Mutation starts outside coding region, RNAChange object not created");
797             }
798              
799             #########################################################################
800             # Mutations are done here! #
801 5         30 $refseq->labelchange($mutation->seq, $mutation->label, $mutation->len); #
802             #########################################################################
803              
804 5         23 $self->_post_mutation ($seqDiff);
805              
806 5         20 $self->dnamut(undef);
807 5         13 $self->rnachange(undef);
808 5         17 $self->aachange(undef);
809 5         14 $self->exons(undef);
810             }
811             # record the final state of all three sequences
812 5         18 $seqDiff->dna_mut($self->DNA->seq);
813 5         24 $seqDiff->rna_mut($self->RNA->seq);
814 5 100       52 if ($refseq->isa("Bio::LiveSeq::Transcript")) {
815 1         7 $seqDiff->aa_mut($refseq->get_Translation->seq);
816             } else {
817 4         16 $seqDiff->aa_mut($self->RNA->get_Translation->seq);
818             }
819              
820             #$seqDiff{mut_dna_seq}=$gene->get_DNA->seq;
821             #my $i=1;
822             #foreach $transcript (@transcripts) {
823             # $seqDiff{"mut_transcript_${i}_seq"}=$transcript->seq;
824             # $seqDiff{"mut_translation_${i}_seq"}=$transcript->get_Translation->seq;
825             #}
826 5         32 return $seqDiff;
827             }
828              
829             =head2 _mutationpos2label
830              
831             Title : _mutationpos2label
832             Usage :
833             Function: converts mutation positions into labels
834             Example :
835             Returns : number of valid mutations
836             Args : LiveSeq sequence object
837              
838             =cut
839              
840             sub _mutationpos2label {
841 5     5   10 my ($self, $refseq, $SeqDiff) = @_;
842 5         5 my $count;
843 5         10 my @bb = @{$self->{'mutations'}};
  5         16  
844 5         10 my $cc = scalar @bb;
845 5         7 foreach my $mut (@{$self->{'mutations'}}) {
  5         15  
846             # if ($self->numbering eq 'gene' and $mut->pos < 1) {
847             # my $tmp = $mut->pos;
848             # print STDERR "pos: ", "$tmp\n";
849             # $tmp++ if $tmp < 1;
850             # $tmp += $SeqDiff->offset;
851             # print STDERR "pos2: ", "$tmp\n";
852             # $mut->pos($tmp);
853             # }
854             # elsif ($self->numbering eq 'entry') {
855 5 100       20 if ($self->numbering eq 'entry') {
856 4         25 my $tmp = $mut->pos;
857 4         13 $tmp -= $SeqDiff->offset;
858 4 50       13 $tmp-- if $tmp < 1;
859 4         14 $mut->pos($tmp);
860             }
861              
862 5         21 my $label = $refseq->label($mut->pos); # get the label for the position
863 5 50       40 $mut->label($label), $count++ if $label > 0 ;
864             #print STDERR "x", $mut->pos,'|' ,$mut->label, "\n";
865             }
866 5         17 return $count;
867             }
868              
869             #
870             # Calculate labels around mutated nucleotide
871             #
872              
873             =head2 _set_DNAMutation
874              
875             Title : _set_DNAMutation
876             Usage :
877             Function:
878              
879             Stores DNA level mutation attributes before mutation into
880             Bio::Variation::DNAMutation object. Links it to SeqDiff
881             object.
882              
883             Example :
884             Returns : Bio::Variation::DNAMutation object
885             Args : Bio::Variation::SeqDiff object
886              
887             See L and L.
888              
889             =cut
890              
891             sub _set_DNAMutation {
892 5     5   9 my ($self, $seqDiff) = @_;
893              
894 5         18 my $dnamut_start = $self->mutation->label - $seqDiff->offset;
895             # if negative DNA positions (before ATG)
896 5 50       11 $dnamut_start-- if $dnamut_start <= 0;
897 5         6 my $dnamut_end;
898 5 50 33     14 ($self->mutation->len == 0 or $self->mutation->len == 1) ?
899             ($dnamut_end = $dnamut_start) :
900             ($dnamut_end = $dnamut_start+$self->mutation->len);
901             #print "start:$dnamut_start, end:$dnamut_end\n";
902 5         184 my $dnamut = Bio::Variation::DNAMutation->new(-start => $dnamut_start,
903             -end => $dnamut_end,
904             );
905 5         12 $dnamut->mut_number($self->mutation->issue);
906 5         21 $dnamut->isMutation(1);
907 5         30 my $da_m = Bio::Variation::Allele->new;
908 5 50       13 $da_m->seq($self->mutation->seq) if $self->mutation->seq;
909 5         27 $dnamut->allele_mut($da_m);
910 5         19 $dnamut->add_Allele($da_m);
911             # allele_ori
912 5         13 my $allele_ori = $self->DNA->labelsubseq($self->mutation->prelabel,
913             undef,
914             $self->mutation->postlabel); # get seq
915 5         14 chop $allele_ori; # chop the postlabel nucleotide
916 5         13 $allele_ori=substr($allele_ori,1); # away the prelabel nucleotide
917 5         15 my $da_o = Bio::Variation::Allele->new;
918 5 50       19 $da_o->seq($allele_ori) if $allele_ori;
919 5         24 $dnamut->allele_ori($da_o);
920 5 50       13 ($self->mutation->len == 0) ?
921             ($dnamut->length($self->mutation->len)) : ($dnamut->length(CORE::length $allele_ori));
922             #print " --------------- $dnamut_start -$len- $dnamut_end -\n";
923 5         21 $seqDiff->add_Variant($dnamut);
924 5         17 $self->dnamut($dnamut);
925 5         12 $dnamut->mut_number($self->mutation->issue);
926             # setting proof
927 5 100 66     19 if ($seqDiff->numbering eq "entry" or $seqDiff->numbering eq "gene") {
928 4         17 $dnamut->proof('experimental');
929             } else {
930 1         5 $dnamut->proof('computed');
931             }
932             # how many nucleotides to store upstream and downstream of the change
933 5         10 my $flanklen = $self->{'flanklen'};
934             #print `date`, " flanking sequences start\n";
935 5         12 my $uplabel = $self->DNA->label(1-$flanklen,$self->mutation->prelabel); # this could be unavailable!
936              
937 5         11 my $upstreamseq;
938 5 50       12 if ($uplabel > 0) {
939 5         13 $upstreamseq =
940             $self->DNA->labelsubseq($uplabel, undef, $self->mutation->prelabel);
941             } else { # from start (less than $flanklen nucleotides)
942 0         0 $upstreamseq =
943             $self->DNA->labelsubseq($self->DNA->start, undef, $self->mutation->prelabel);
944             }
945 5         25 $dnamut->upStreamSeq($upstreamseq);
946 5         13 my $dnstreamseq = $self->DNA->labelsubseq($self->mutation->postlabel, $flanklen);
947 5         20 $dnamut->dnStreamSeq($dnstreamseq); # $flanklen or less nucleotides
948 5         13 return $dnamut;
949             }
950              
951              
952             #
953             ### Check if mutation propagates to RNA (and AA) level
954             #
955             # side effect: sets intron/exon information
956             # returns a boolean value
957             #
958              
959             sub _rnaAffected {
960 5     5   8 my ($self) = @_;
961 5         15 my @exons=$self->RNA->all_Exons;
962 5         14 my $RNAstart=$self->RNA->start;
963 5         14 my $RNAend=$self->RNA->end;
964 5         10 my ($firstexon,$before,$after,$i);
965 5         9 my ($rnaAffected) = 0;
966              
967             # check for inserted labels (that require follows instead of <,>)
968 5         12 my $DNAend=$self->RNA->{'seq'}->end;
969 5 50 33     14 if ($self->mutation->prelabel > $DNAend or $self->mutation->postlabel > $DNAend) {
970             #this means one of the two labels is an inserted one
971             #(coming from a previous mutation. This would falsify all <,>
972             #checks, so the follow() has to be used
973 0         0 $self->warn("Attention, workaround not fully tested yet! Expect unpredictable results.\n");
974 0 0 0     0 if (($self->mutation->postlabel==$RNAstart) or (follows($self->mutation->postlabel,$RNAstart))) {
    0 0        
    0          
975 0         0 $self->warn("RNA not affected because change occurs before RNAstart");
976             }
977             elsif (($RNAend==$self->mutation->prelabel) or (follows($RNAend,$self->mutation->prelabel))) {
978 0         0 $self->warn("RNA not affected because change occurs after RNAend");
979             }
980             elsif (scalar @exons == 1) {
981             #no introns, just one exon
982 0         0 $rnaAffected = 1; # then RNA is affected!
983             } else {
984             # otherwise check for change occurring inside an intron
985 0         0 $firstexon=shift(@exons);
986 0         0 $before=$firstexon->end;
987            
988 0         0 foreach $i (0..$#exons) {
989 0         0 $after=$exons[$i]->start;
990 0 0 0     0 if (follows($self->mutation->prelabel,$before) or
      0        
      0        
991             ($after==$self->mutation->prelabel) or
992             follows($after,$self->mutation->prelabel) or
993             follows($after,$self->mutation->postlabel)) {
994              
995 0         0 $rnaAffected = 1;
996             # $i is number of exon and can be used for proximity check
997             }
998 0         0 $before=$exons[$i]->end;
999             }
1000            
1001             }
1002             } else {
1003 5         17 my $strand = $exons[0]->strand;
1004 5 50 33     28 if (($strand == 1 and $self->mutation->postlabel <= $RNAstart) or
    50 33        
    100 33        
      33        
      33        
      33        
1005             ($strand != 1 and $self->mutation->postlabel >= $RNAstart)) {
1006             #$self->warn("RNA not affected because change occurs before RNAstart");
1007 0         0 $rnaAffected = 0;
1008             }
1009             elsif (($strand == 1 and $self->mutation->prelabel >= $RNAend) or
1010             ($strand != 1 and $self->mutation->prelabel <= $RNAend)) {
1011             #$self->warn("RNA not affected because change occurs after RNAend");
1012 0         0 $rnaAffected = 0;
1013 0         0 my $dist;
1014 0 0       0 if ($strand == 1){
1015 0         0 $dist = $self->mutation->prelabel - $RNAend;
1016             } else {
1017 0         0 $dist = $RNAend - $self->mutation->prelabel;
1018             }
1019 0         0 $self->dnamut->region_dist($dist);
1020             }
1021             elsif (scalar @exons == 1) {
1022             #if just one exon -> no introns,
1023 1         3 $rnaAffected = 1; # then RNA is affected!
1024             } else {
1025             # otherwise check for mutation occurring inside an intron
1026 4         6 $firstexon=shift(@exons);
1027 4         14 $before=$firstexon->end;
1028 4 50 33     18 if ( ($strand == 1 and $self->mutation->prelabel < $before) or
      33        
      33        
1029             ($strand == -1 and $self->mutation->prelabel > $before)
1030             ) {
1031 0         0 $rnaAffected = 1 ;
1032              
1033             #print "Exon 1 : ", $firstexon->start, " - ", $firstexon->end, "
\n";
1034 0         0 my $afterdist = $self->mutation->prelabel - $firstexon->start;
1035 0         0 my $beforedist = $firstexon->end - $self->mutation->postlabel;
1036 0         0 my $exonvalue = $i + 1;
1037 0         0 $self->dnamut->region('exon');
1038 0         0 $self->dnamut->region_value($exonvalue);
1039 0 0       0 if ($afterdist < $beforedist) {
1040 0         0 $afterdist++;
1041 0         0 $afterdist++;
1042 0         0 $self->dnamut->region_dist($afterdist);
1043             #print "splice site $afterdist nt upstream!
";
1044             } else {
1045 0         0 $self->dnamut->region_dist($beforedist);
1046             #print "splice site $beforedist nt downstream!
";
1047             }
1048             } else {
1049             #print "first exon : ", $firstexon->start, " - ", $firstexon->end, "
\n";
1050 4         16 foreach $i (0..$#exons) {
1051 14         30 $after=$exons[$i]->start;
1052             #proximity test for intronic mutations
1053 14 50 33     36 if ( ($strand == 1 and
    100 33        
      33        
      33        
      33        
      66        
      100        
      33        
      66        
      66        
      33        
      33        
      66        
      33        
      33        
      33        
1054             $self->mutation->prelabel >= $before and
1055             $self->mutation->postlabel <= $after)
1056             or
1057             ($strand == -1 and
1058             $self->mutation->prelabel <= $before and
1059             $self->mutation->postlabel >= $after) ) {
1060 0         0 $self->dnamut->region('intron');
1061             #$self->dnamut->region_value($i);
1062 0         0 my $afterdist = $self->mutation->prelabel - $before;
1063 0         0 my $beforedist = $after - $self->mutation->postlabel;
1064 0         0 my $intronvalue = $i + 1;
1065 0 0       0 if ($afterdist < $beforedist) {
1066 0         0 $afterdist++;
1067 0         0 $self->dnamut->region_value($intronvalue);
1068 0         0 $self->dnamut->region_dist($afterdist);
1069             #print "splice site $afterdist nt upstream!
";
1070             } else {
1071 0         0 $self->dnamut->region_value($intronvalue);
1072 0         0 $self->dnamut->region_dist($beforedist * -1);
1073             #print "splice site $beforedist nt downstream!
";
1074             }
1075 0         0 $self->rnachange(undef);
1076 0         0 last;
1077             }
1078             #proximity test for exon mutations
1079             #proximity test for exon mutations
1080             elsif ( ( $strand == 1 and
1081             $exons[$i]->start < $self->mutation->prelabel and
1082             $exons[$i]->end > $self->mutation->prelabel) or
1083             ( $strand == 1 and
1084             $exons[$i]->start < $self->mutation->postlabel and
1085             $exons[$i]->end > $self->mutation->postlabel) or
1086             ( $strand == -1 and
1087             $exons[$i]->start > $self->mutation->prelabel and
1088             $exons[$i]->end < $self->mutation->prelabel) or
1089             ( $strand == -1 and
1090             $exons[$i]->start > $self->mutation->postlabel and
1091             $exons[$i]->end < $self->mutation->postlabel) ) {
1092 4         6 $rnaAffected = 1;
1093              
1094 4         10 my $afterdist = $self->mutation->prelabel - $exons[$i]->start;
1095 4         13 my $beforedist = $exons[$i]->end - $self->mutation->postlabel;
1096 4         6 my $exonvalue = $i + 1;
1097 4         9 $self->dnamut->region('exon');
1098 4 100       10 if ($afterdist < $beforedist) {
1099 2         4 $afterdist++;
1100 2         5 $self->dnamut->region_value($exonvalue+1);
1101 2         5 $self->dnamut->region_dist($afterdist);
1102             #print "splice site $afterdist nt upstream!
";
1103             } else {
1104             #$beforedist;
1105 2         6 $self->dnamut->region_value($exonvalue+1);
1106 2         5 $self->dnamut->region_dist($beforedist * -1);
1107             #print "splice site $beforedist nt downstream!
";
1108             }
1109 4         12 last;
1110             }
1111 10         24 $before=$exons[$i]->end;
1112             }
1113             }
1114             }
1115             }
1116             #$self->warn("RNA not affected because change occurs inside an intron");
1117             #return(0); # if still not returned, then not affected, return 0
1118 5         19 return $rnaAffected;
1119             }
1120              
1121             #
1122             # ### Creation of RNA and AA variation objects
1123             #
1124              
1125             =head2 _set_effects
1126              
1127             Title : _set_effects
1128             Usage :
1129             Function:
1130              
1131             Stores RNA and AA level mutation attributes before mutation
1132             into Bio::Variation::RNAChange and
1133             Bio::Variation::AAChange objects. Links them to
1134             SeqDiff object.
1135              
1136             Example :
1137             Returns :
1138             Args : Bio::Variation::SeqDiff object
1139             Bio::Variation::DNAMutation object
1140              
1141             See L, L,
1142             L, and L.
1143              
1144             =cut
1145              
1146             sub _set_effects {
1147 5     5   8 my ($self, $seqDiff, $dnamut) = @_;
1148 5         7 my ($rnapos_end, $upstreamseq, $dnstreamseq);
1149 5         9 my $flanklen = $self->{'flanklen'};
1150              
1151 5 50       9 ($self->mutation->len == 0) ?
1152             ($rnapos_end = $self->mutation->transpos) :
1153             ($rnapos_end = $self->mutation->transpos + $self->mutation->len -1);
1154 5         19 my $rnachange = Bio::Variation::RNAChange->new(-start => $self->mutation->transpos,
1155             -end => $rnapos_end
1156             );
1157 5         21 $rnachange->isMutation(1);
1158              
1159             # setting proof
1160 5 100       13 if ($seqDiff->numbering eq "coding") {
1161 1         5 $rnachange->proof('experimental');
1162             } else {
1163 4         12 $rnachange->proof('computed');
1164             }
1165              
1166 5         15 $seqDiff->add_Variant($rnachange);
1167 5         12 $self->rnachange($rnachange);
1168 5         16 $rnachange->DNAMutation($dnamut);
1169 5         16 $dnamut->RNAChange($rnachange);
1170 5         14 $rnachange->mut_number($self->mutation->issue);
1171              
1172             # setting the codon_position of the "start" nucleotide of the change
1173 5         14 $rnachange->codon_pos(($self->RNA->frame($self->mutation->label))+1); # codon_pos=frame+1
1174              
1175 5         21 my @exons=$self->RNA->all_Exons;
1176 5         20 $self->exons(\@exons);
1177             #print `date`, " before flank, after exons. RNAObj query\n";
1178             # if cannot retrieve from Transcript, Transcript::upstream_seq will be used
1179             # before "fac7 g 65" bug discovered
1180             # $uplabel=$self->RNA->label(1-$flanklen,$prelabel);
1181 5         12 my $RNAprelabel=$self->RNA->label(-1,$self->mutation->label); # to fix fac7g65 bug
1182             # for the fix, all prelabel used in the next block have been changed to RNAprelabel
1183 5         26 my $uplabel=$self->RNA->label(1-$flanklen,$RNAprelabel);
1184 5 50       31 if ($self->RNA->valid($uplabel)) {
1185 5         24 $upstreamseq = $self->RNA->labelsubseq($uplabel, undef, $RNAprelabel);
1186             } else {
1187 0 0       0 $upstreamseq = $self->RNA->labelsubseq($self->RNA->start, undef, $RNAprelabel)
1188             if $self->RNA->valid($RNAprelabel);
1189 0         0 my $lacking=$flanklen-length($upstreamseq); # how many missing
1190 0         0 my $upstream_atg=$exons[0]->subseq(-$lacking,-1);
1191 0         0 $upstreamseq=$upstream_atg . $upstreamseq;
1192             }
1193              
1194 5         43 $rnachange->upStreamSeq($upstreamseq);
1195              
1196             # won't work OK if postlabel NOT in Transcript
1197             # now added RNApostlabel but this has to be /fully tested/
1198             # for the fix, all postlabel used in the next block have been changed to RNApostlabel
1199 5         8 my $RNApostlabel; # to fix fac7g64 bug
1200 5 50       23 if ($self->mutation->len == 0) {
1201 0         0 $RNApostlabel=$self->mutation->label;
1202             } else {
1203 5         12 my $mutlen = 1 + $self->mutation->len;
1204 5         16 $RNApostlabel=$self->RNA->label($mutlen,$self->mutation->label);
1205             }
1206 5         32 $dnstreamseq=$self->RNA->labelsubseq($RNApostlabel, $flanklen);
1207 5 50       16 if ($dnstreamseq eq '-1') { # if out of transcript was requested
1208 0         0 my $lastexon=$exons[-1];
1209 0         0 my $lastexonlength=$lastexon->length;
1210 0         0 $dnstreamseq=$self->RNA->labelsubseq($RNApostlabel); # retrieves till RNAend
1211 0         0 my $lacking=$flanklen-length($dnstreamseq); # how many missing
1212 0         0 my $downstream_stop=$lastexon->subseq($lastexonlength+1,undef,$lacking);
1213 0         0 $dnstreamseq .= $downstream_stop;
1214             } else {
1215 5         65 $rnachange->dnStreamSeq($dnstreamseq);
1216             }
1217             # AAChange creation
1218 5         28 my $AAobj=$self->RNA->get_Translation;
1219             # storage of prelabel here, to be used in create_mut_objs_after
1220 5         55 my $aachange = Bio::Variation::AAChange->new(-start => $RNAprelabel
1221             );
1222 5         27 $aachange->isMutation(1);
1223 5         21 $aachange->proof('computed');
1224              
1225 5         30 $seqDiff->add_Variant($aachange);
1226 5         17 $self->aachange($aachange);
1227 5         26 $rnachange->AAChange($aachange);
1228 5         20 $aachange->RNAChange($rnachange);
1229              
1230 5         18 $aachange->mut_number($self->mutation->issue);
1231             # $before_mutation{aachange}=$aachange;
1232              
1233 5         31 my $ra_o = Bio::Variation::Allele->new;
1234 5 50       21 $ra_o->seq($dnamut->allele_ori->seq) if $dnamut->allele_ori->seq;
1235 5         17 $rnachange->allele_ori($ra_o);
1236              
1237 5         17 $rnachange->length(CORE::length $rnachange->allele_ori->seq);
1238              
1239 5         16 my $ra_m = Bio::Variation::Allele->new;
1240 5 50       16 $ra_m->seq($self->mutation->seq) if $self->mutation->seq;
1241 5         21 $rnachange->allele_mut($ra_m);
1242 5         21 $rnachange->add_Allele($ra_m);
1243              
1244             #$rnachange->allele_mut($seq);
1245 5 50       16 $rnachange->end($rnachange->start) if $rnachange->length == 0;
1246              
1247             # this holds the aminoacid sequence that will be affected by the mutation
1248 5         16 my $aa_allele_ori=$AAobj->labelsubseq($self->mutation->label,undef,
1249             $self->mutation->lastlabel);
1250              
1251 5         38 my $aa_o = Bio::Variation::Allele->new;
1252 5 50       25 $aa_o->seq($aa_allele_ori) if $aa_allele_ori;
1253 5         40 $aachange->allele_ori($aa_o);
1254             #$aachange->allele_ori($aa_allele_ori);
1255              
1256 5         9 my $aa_length_ori = length($aa_allele_ori);
1257 5         20 $aachange->length($aa_length_ori); #print "==========$aa_length_ori\n";
1258 5         26 $aachange->end($aachange->start + $aa_length_ori - 1 );
1259             }
1260              
1261             =head2 _untranslated
1262              
1263             Title : _untranslated
1264             Usage :
1265             Function:
1266              
1267             Stores RNA change attributes before mutation
1268             into Bio::Variation::RNAChange object. Links it to
1269             SeqDiff object.
1270              
1271             Example :
1272             Returns :
1273             Args : Bio::Variation::SeqDiff object
1274             Bio::Variation::DNAMutation object
1275              
1276             See L, L and
1277             L for details.
1278              
1279             =cut
1280              
1281             sub _untranslated {
1282 0     0   0 my ($self, $seqDiff, $dnamut) = @_;
1283 0         0 my $rnapos_end;
1284 0 0       0 ($self->mutation->len == 0) ?
1285             ($rnapos_end = $self->mutation->transpos) :
1286             ($rnapos_end = $self->mutation->transpos + $self->mutation->len -1);
1287 0         0 my $rnachange = Bio::Variation::RNAChange->new(-start => $self->mutation->transpos,
1288             -end => $rnapos_end
1289             );
1290             #my $rnachange = Bio::Variation::RNAChange->new;
1291              
1292 0         0 $rnachange->isMutation(1);
1293 0         0 my $ra_o = Bio::Variation::Allele->new;
1294 0 0       0 $ra_o->seq($dnamut->allele_ori->seq) if $dnamut->allele_ori->seq;
1295 0         0 $rnachange->allele_ori($ra_o);
1296 0         0 my $ra_m = Bio::Variation::Allele->new;
1297 0 0       0 $ra_m->seq($dnamut->allele_mut->seq) if $dnamut->allele_mut->seq;
1298 0         0 $rnachange->allele_mut($ra_m);
1299 0         0 $rnachange->add_Allele($ra_m);
1300 0         0 $rnachange->upStreamSeq($dnamut->upStreamSeq);
1301 0         0 $rnachange->dnStreamSeq($dnamut->dnStreamSeq);
1302 0         0 $rnachange->length($dnamut->length);
1303 0         0 $rnachange->mut_number($dnamut->mut_number);
1304             # setting proof
1305 0 0       0 if ($seqDiff->numbering eq "coding") {
1306 0         0 $rnachange->proof('experimental');
1307             } else {
1308 0         0 $rnachange->proof('computed');
1309             }
1310              
1311 0         0 my $dist;
1312 0 0       0 if ($rnachange->end < 0) {
1313 0         0 $rnachange->region('5\'UTR');
1314 0         0 $dnamut->region('5\'UTR');
1315 0         0 my $dist = $dnamut->end ;
1316 0         0 $dnamut->region_dist($dist);
1317 0         0 $dist = $seqDiff->offset - $self->gene->maxtranscript->start + 1 + $dist;
1318 0         0 $rnachange->region_dist($dist);
1319 0 0       0 return if $dist < 1; # if mutation is not in mRNA
1320             } else {
1321 0         0 $rnachange->region('3\'UTR');
1322 0         0 $dnamut->region('3\'UTR');
1323 0         0 my $dist = $dnamut->start - $seqDiff->cds_end + $seqDiff->offset;
1324 0         0 $dnamut->region_dist($dist);
1325 0         0 $dist = $seqDiff->cds_end - $self->gene->maxtranscript->end -1 + $dist;
1326 0         0 $rnachange->region_dist($dist);
1327 0 0       0 return if $dist > 0; # if mutation is not in mRNA
1328             }
1329 0         0 $seqDiff->add_Variant($rnachange);
1330 0         0 $self->rnachange($rnachange);
1331 0         0 $rnachange->DNAMutation($dnamut);
1332 0         0 $dnamut->RNAChange($rnachange);
1333             }
1334              
1335             # args: reference to label changearray, reference to position changearray
1336             # Function: take care of the creation of mutation objects, with
1337             # information AFTER the change takes place
1338             sub _post_mutation {
1339 5     5   9 my ($self, $seqDiff) = @_;
1340              
1341 5 50 33     15 if ($self->rnachange and $self->rnachange->region eq 'coding') {
1342              
1343             #$seqDiff->add_Variant($self->rnachange);
1344              
1345 5         16 my $aachange=$self->aachange;
1346 5         8 my ($AAobj,$aa_start_prelabel,$aa_start,$mut_translation);
1347 5         16 $AAobj=$self->RNA->get_Translation;
1348 5         16 $aa_start_prelabel=$aachange->start;
1349 5         18 $aa_start=$AAobj->position($self->RNA->label(2,$aa_start_prelabel));
1350 5         39 $aachange->start($aa_start);
1351 5         20 $mut_translation=$AAobj->seq;
1352              
1353             # this now takes in account possible preinsertions
1354 5         35 my $aa_m = Bio::Variation::Allele->new;
1355 5 50       39 $aa_m->seq(substr($mut_translation,$aa_start-1)) if substr($mut_translation,$aa_start-1);
1356 5         42 $aachange->allele_mut($aa_m);
1357 5         22 $aachange->add_Allele($aa_m);
1358             #$aachange->allele_mut(substr($mut_translation,$aa_start-1));
1359             #$aachange->allele_mut($mut_translation);
1360 5         9 my ($rlenori, $rlenmut);
1361 5         28 $rlenori = CORE::length($aachange->RNAChange->allele_ori->seq);
1362 5         16 $rlenmut = CORE::length($aachange->RNAChange->allele_mut->seq);
1363             #point mutation
1364              
1365 5 50 33     60 if ($rlenori == 1 and $rlenmut == 1 and $aachange->allele_ori->seq ne '*') {
    0 33        
    0 0        
1366 5         10 my $alleleseq;
1367 5 50       12 if ($aachange->allele_mut->seq) {
1368 5         15 $alleleseq = substr($aachange->allele_mut->seq, 0, 1);
1369 5         14 $aachange->allele_mut->seq($alleleseq);
1370             }
1371 5         26 $aachange->end($aachange->start);
1372 5         22 $aachange->length(1);
1373             }
1374             elsif ( $rlenori == $rlenmut and
1375             $aachange->allele_ori->seq ne '*' ) { #complex inframe mutation
1376 0         0 $aachange->allele_mut->seq(substr $aachange->allele_mut->seq,
1377             0,
1378             length($aachange->allele_ori->seq));
1379             }
1380             #inframe mutation
1381             elsif ((int($rlenori-$rlenmut))%3 == 0) {
1382 0 0 0     0 if ($aachange->RNAChange->allele_mut->seq and
    0          
1383             $aachange->RNAChange->allele_ori->seq ) {
1384             # complex
1385 0         0 my $rna_len = length ($aachange->RNAChange->allele_mut->seq);
1386 0         0 my $len = $rna_len/3;
1387 0 0       0 $len++ unless $rna_len%3 == 0;
1388 0         0 $aachange->allele_mut->seq(substr $aachange->allele_mut->seq, 0, $len );
1389             }
1390             elsif ($aachange->RNAChange->codon_pos == 1){
1391             # deletion
1392 0 0       0 if ($aachange->RNAChange->allele_mut->seq eq '') {
    0          
1393 0         0 $aachange->allele_mut->seq('');
1394 0         0 $aachange->end($aachange->start + $aachange->length - 1 );
1395             }
1396             # insertion
1397             elsif ($aachange->RNAChange->allele_ori->seq eq '' ) {
1398 0         0 $aachange->allele_mut->seq(substr $aachange->allele_mut->seq, 0,
1399             length ($aachange->RNAChange->allele_mut->seq) / 3);
1400 0         0 $aachange->allele_ori->seq('');
1401 0         0 $aachange->end($aachange->start + $aachange->length - 1 );
1402 0         0 $aachange->length(0);
1403             }
1404             } else {
1405             #elsif ($aachange->RNAChange->codon_pos == 2){
1406             # deletion
1407 0 0       0 if (not $aachange->RNAChange->allele_mut->seq ) {
    0          
1408 0         0 $aachange->allele_mut->seq(substr $aachange->allele_mut->seq, 0, 1);
1409             }
1410             # insertion
1411             elsif (not $aachange->RNAChange->allele_ori->seq) {
1412 0         0 $aachange->allele_mut->seq(substr $aachange->allele_mut->seq, 0,
1413             length ($aachange->RNAChange->allele_mut->seq) / 3 +1);
1414             }
1415             }
1416             } else {
1417             #frameshift
1418             #my $pos = index $aachange->allele_mut
1419             #$aachange->allele_mut(substr($aachange->allele_mut, 0, 1));
1420 0         0 $aachange->length(CORE::length($aachange->allele_ori->seq));
1421 0         0 my $aaend = $aachange->start + $aachange->length -1;
1422 0         0 $aachange->end($aachange->start);
1423             }
1424              
1425             # splicing site deletion check
1426 5         7 my @beforeexons=@{$self->exons};
  5         22  
1427 5         19 my @afterexons=$self->RNA->all_Exons;
1428 5         10 my $i;
1429 5 50       17 if (scalar(@beforeexons) ne scalar(@afterexons)) {
1430 0         0 my $mut_number = $self->mutation->issue;
1431 0         0 $self->warn("Exons have been modified at mutation n.$mut_number!");
1432 0         0 $self->rnachange->exons_modified(1);
1433             } else {
1434             EXONCHECK:
1435 5         18 foreach $i (0..$#beforeexons) {
1436 25 50       54 if ($beforeexons[$i] ne $afterexons[$i]) {
1437 0         0 my $mut_number = $self->mutation->issue;
1438 0         0 $self->warn("Exons have been modified at mutation n.$mut_number!");
1439 0         0 $self->rnachange->exons_modified(1);
1440 0         0 last EXONCHECK;
1441             }
1442             }
1443             }
1444             } else {
1445             #$seqDiff->rnachange(undef);
1446             #print "getting here?";
1447             }
1448 5         13 return 1;
1449             }
1450              
1451             1;