root/lib/PhatHit_utils.pm

Revision 277, 27.1 kB (checked in by cholt, 3 weeks ago)

attempt to fix exonerate holdover errors

Line 
1 #------------------------------------------------------------------------
2 #----                          PhatHit_utils                         ----
3 #------------------------------------------------------------------------
4 package PhatHit_utils;
5 use strict;
6 use vars qw(@ISA @EXPORT $VERSION);
7 use Exporter;
8 use PostData;
9 use FileHandle;
10 use PostData;
11 use Exporter;
12 use Fasta;
13 @ISA = qw(
14        );
15 #------------------------------------------------------------------------
16 #--------------------------- CLASS FUNCTIONS ----------------------------
17 #------------------------------------------------------------------------
18 sub sort_hits {
19         my $hit  = shift;
20         my $what = shift;
21
22         my $sorted;
23         if    ($hit->strand($what) == 1 || $hit->strand($what) == 0) {
24                 $sorted = $hit->sortFeatures($what);
25         }
26         elsif ($hit->strand($what) == -1 ){
27                 $sorted = $hit->revSortFeatures($what);
28         }     
29         else {
30                 $hit->show();
31                 PostData($hit);
32                 print "caller:".caller()."STRAND:".$hit->strand('query')."\n";
33
34                 print "not yet supported in PhatHit_utils::sort_hits\n";
35                 die;
36         }
37
38         return $sorted;
39 }
40 #------------------------------------------------------------------------
41 sub seperate_by_strand {
42         my $what = shift;
43         my $hits = shift;
44         my $exonerate_flag = shift || 0;
45        
46         #The exonerate flag specifies whether to take into account
47         #exonerate realignment alignment flip.  In other words should
48         #a blastn hit be considered to belong to the opposite strand
49         #if its exonerate counterpart was flipped
50
51         my @p;
52         my @m;
53         my @x;
54         my @z;
55         foreach my $hit (@{$hits}){
56             my $strand = $hit->strand($what);
57            
58             unless($strand =~ /^\-?\d$/){
59                 die "FATAL: Could not get stand correctly. Perhaps".
60                     "your using the wrong version of BioPerl.\n\n";
61             }       
62
63             $strand *= -1 if($exonerate_flag && $hit->{_exonerate_flipped});
64            
65             if ($strand == 1) {
66                 push(@p, $hit);
67             }       
68             elsif ($strand == -1 ){
69                 push(@m, $hit);
70             }     
71             elsif ($strand == 0 ){
72                 push(@z, $hit);
73             }
74
75         }
76         return (\@p, \@m, \@x, \@z);
77 }
78 #------------------------------------------------------------------------
79 sub sort_hsps_by_score {
80         my $hit = shift;
81        
82         my @hsps;
83         foreach my $hsp ($hit->hsps){
84                 push(@hsps, $hsp);
85         }
86         my @sorted = sort {$b->score() <=> $a->score()} @hsps;
87         return \@sorted;
88
89 }
90 #------------------------------------------------------------------------
91 sub to_begin_and_end_coors {
92         my $hits = shift;
93         my $what = shift;
94         my @coors;
95         foreach my $hit (@{$hits}){
96                 push(@coors, [get_span_of_hit($hit, $what)]);
97         }
98         return \@coors;
99 }
100 #------------------------------------------------------------------------
101 sub get_hsp_coors_from_hit {
102         my $hit = shift;
103         my $what = shift;
104         my @coors;
105         foreach my $hsp ($hit->hsps){
106                 push(@coors, [$hsp->nB($what), $hsp->nE($what)]);
107         }
108         return \@coors;
109 }
110 #------------------------------------------------------------------------
111 sub get_total_score_of_hit {
112         my $hit = shift;
113         my $total_score = 0;
114         foreach my $hsp ($hit->hsps){
115                 $total_score += $hsp->score();
116         }
117         return $total_score;
118 }
119 #------------------------------------------------------------------------
120 sub get_hsp_coors {
121         my $hits = shift;
122         my $what = shift;
123         my @coors;
124         foreach my $hit (@{$hits}){
125                 foreach my $hsp ($hit->hsps){
126                         push(@coors, [$hsp->nB($what), $hsp->nE($what)]);
127                 }
128         }
129         return \@coors;
130 }
131 #------------------------------------------------------------------------
132 sub get_hit_coors {
133         my $hits = shift;
134         my $what = shift;
135         my @coors;
136         foreach my $hit (@{$hits}){
137             push(@coors, [$hit->nB($what), $hit->nE($what)]);
138         }
139         return \@coors;
140 }
141 #------------------------------------------------------------------------
142 sub split_hit_on_intron {
143    my $hits        = shift;
144    my $max_intron = shift;
145    
146    push (@{$hits}, $hits) if (ref($hits) ne 'ARRAY');
147    
148    my @new_hits;
149    
150    foreach my $hit (@{$hits}){
151       my $ref = ref($hit);
152      
153       my $sorted = $hit->sortFeatures('query');
154      
155       unless (defined($sorted->[1])){
156          push(@new_hits, $hit);
157          next;
158       }
159      
160       my %splits;
161       my $k = 0;
162       my $distance;
163       for (my $i = 0; $i < @{$sorted} - 1; $i++){
164          my $hsp_i = $sorted->[$i];
165          my $hsp_j = $sorted->[$i + 1];
166
167          my $end_i = $hsp_i->end('query'); #end is normalized to be larger than start
168          my $beg_j = $hsp_j->start('query'); #start is normalized to be smaller than end
169         
170          $distance = $beg_j - $end_i;
171          
172          
173          push(@{$splits{$k}}, $hsp_i);
174          
175          $k++ if $distance > $max_intron;
176       }
177      
178       push(@{$splits{$k}}, $sorted->[-1]);
179      
180       my $num = (keys %splits);
181      
182       foreach my $key (sort keys %splits){
183          
184          my $new_hit =
185          new $ref('-name'         => $hit->name,
186                   '-description'  => $hit->description,
187                   '-algorithm'    => $hit->algorithm,
188                   '-length'       => $hit->length,
189                  );
190          
191          $new_hit->queryLength($hit->queryLength);
192          $new_hit->database_name($hit->database_name);
193          $new_hit->{is_split} = 1 if $num > 1;
194          
195          foreach my  $hsp (@{$splits{$key}}){
196             $new_hit->add_hsp($hsp);
197          }
198          
199          push(@new_hits, $new_hit);
200          
201          $num++;
202       }
203    }
204    
205    return \@new_hits;
206 }
207 #------------------------------------------------------------------------
208 sub split_hit_by_strand {
209    my $hits = shift;
210
211    push (@{$hits}, $hits) if (ref($hits) ne 'ARRAY');
212
213    my @new_hits;
214
215    foreach my $hit (@{$hits}){
216       my $ref = ref($hit);
217      
218       my @hsps = $hit->hsps;
219      
220       my %pm_splits;
221      
222       foreach my $hsp (@hsps){
223          my $strand = $hsp->strand('query');
224          
225          if($strand == 1 || $strand == 0){
226             push(@{$pm_splits{plus}}, $hsp); #plus strand
227          }
228          elsif($strand == -1){
229             push(@{$pm_splits{minus}}, $hsp); #minus strand
230          }
231          else{
232             die "ERROR: There is no strand for this HSP\n";
233          }
234       } 
235      
236       my @keys = keys %pm_splits;
237      
238       if(@keys == 1){
239          push(@new_hits, $hit);
240          next;
241       }
242      
243       foreach my $k (@keys){
244          my $new_hit = new $ref('-name'         => $hit->name,
245                                 '-description'  => $hit->description,
246                                 '-algorithm'    => $hit->algorithm,
247                                 '-length'       => $hit->length,
248                                );
249          
250          $new_hit->queryLength($hit->queryLength);
251          $new_hit->database_name($hit->database_name);
252          $new_hit->{is_split} = 1;
253          
254          foreach my  $hsp (@{$pm_splits{$k}}){
255             $new_hit->add_hsp($hsp);
256          }
257          
258          push(@new_hits, $new_hit);
259       }
260    }
261
262    return \@new_hits;
263 }
264 #------------------------------------------------------------------------
265 sub shatter_hit {
266         my $hit = shift;
267
268         my $ref = ref($hit);
269
270         my @new_hits;
271         foreach my $hsp ($hit->hsps){
272                
273             my $new_hit = new $ref('-name'         => $hit->name,
274                                    '-description'  => $hit->description,
275                                    '-algorithm'    => $hit->algorithm,
276                                    '-length'       => $hit->length,
277                                    '-score'        => $hsp->score,
278                                    '-bits'         => $hsp->bits,
279                                    '-significance' => $hsp->significance
280                                    );
281
282                 $new_hit->queryLength($hit->queryLength);
283                 $new_hit->database_name($hit->database_name);
284                 $new_hit->{is_shattered} = 1;
285
286                 $new_hit->add_hsp($hsp);
287
288                 push(@new_hits, $new_hit);
289         }
290
291         return \@new_hits;
292 }
293 #------------------------------------------------------------------------
294 sub shatter_all_hits {
295         my $hits = shift;
296
297         my $ref = ref($hits->[0]);
298
299         my @new_hits;
300         foreach my $hit (@$hits){
301             foreach my $hsp ($hit->hsps){
302                
303                 my $new_hit = new $ref('-name'         => $hit->name,
304                                        '-description'  => $hit->description,
305                                        '-algorithm'    => $hit->algorithm,
306                                        '-length'       => $hit->length,
307                                        '-score'        => $hsp->score,
308                                        '-bits'         => $hsp->bits,
309                                        '-significance' => $hsp->significance
310                                        );
311                
312                 $new_hit->queryLength($hit->queryLength);
313                 $new_hit->database_name($hit->database_name);
314                 $new_hit->{is_shattered} = 1;
315                
316                 $new_hit->add_hsp($hsp);
317                
318                 push(@new_hits, $new_hit);
319             }
320         }
321
322         return \@new_hits;
323 }
324 #------------------------------------------------------------------------
325 #this method assumes that the features are all on the same strand
326 #they must also be shattered hits
327 sub make_flat_hits {
328         my $hits = shift;
329         my $seq = shift;
330
331         return [] if(! @$hits);
332
333         my $ref = ref($hits->[0]);
334         my $hsp_ref = ref($hits->[0]->{_hsps}->[0]);
335         my $strand = $hits->[0]->strand;
336
337         my $coors  = get_hit_coors($hits, 'query');
338         my $pieces = Shadower::getPieces($seq, $coors, 0);
339
340         my @new_hits;
341
342         foreach my $p (@$pieces){
343             my $nB = $p->{b};
344             my $nE = $p->{e};
345             my $length = abs($nE -$nB) + 1;
346            
347             #natural end and beginning are non-normalized values
348             ($nB, $nE) = ($nE, $nB) if($nB < $nE && $strand == -1);
349
350             my $pSeq = $p->{piece};
351             $pSeq = Fasta::revComp(\$pSeq) if($strand == -1);
352
353             my $new_hit = new $ref('-name'         => "flat_hit_$nB\_$nE",
354                                    '-description'  => '',
355                                    '-algorithm'    => $hits->[0]->algorithm,
356                                    '-length'       => $length,
357                                    '-score'        => $length,
358                                    '-bits'         => $length*2,
359                                    '-significance' => 0
360                                    );
361                
362             $new_hit->queryLength($length);
363            
364             my @args;
365            
366             push(@args, '-query_start');
367             push(@args, $nB);
368
369             push(@args, '-query_seq');
370             push(@args, $pSeq);
371            
372             push(@args, '-score');
373             push(@args, $length);
374             push(@args, '-homology_seq');
375             push(@args, $pSeq);
376            
377             push(@args, '-hit_start');
378             push(@args, 1);
379            
380             push(@args, '-hit_seq');
381             push(@args, $pSeq);
382            
383             push(@args, '-hsp_length');
384             push(@args, $length);
385            
386             push(@args, '-identical');
387             push(@args, $length);
388            
389             push(@args, '-hit_length');
390             push(@args, $length);
391                  
392             push(@args, '-query_name');
393             push(@args, $hits->[0]->{_hsps}->[0]->query_name);
394
395             push(@args, '-algorithm');
396             push(@args, $hits->[0]->algorithm);
397            
398             push(@args, '-bits');
399             push(@args, $length*2);
400            
401             push(@args, '-evalue');
402             push(@args, 0);
403
404             push(@args, '-pvalue');
405             push(@args, 0);
406            
407             push(@args, '-query_length');
408             push(@args, $length);
409            
410             push(@args, '-query_end');
411             push(@args, $nE);
412            
413             push(@args, '-conserved');
414             push(@args, $length);
415            
416             push(@args, '-hit_name');
417             push(@args, "flat_hit_$nB\_$nE");
418
419             push(@args, '-hit_end');
420             push(@args, $length);
421
422             push(@args, '-query_gaps');
423             push(@args, 0);
424            
425             push(@args, '-hit_gaps');
426             push(@args, 0);
427            
428             my $hsp = new $hsp_ref(@args);
429             $hsp->queryName($hits->[0]->{_hsps}->[0]->query_name);
430             #-------------------------------------------------
431             # setting strand because bioperl is all messed up!
432             #------------------------------------------------
433             if ($strand == 1 ){
434                 $hsp->{_strand_hack}->{query} = 1;
435                 $hsp->{_strand_hack}->{hit}   = 1;
436             }
437             else {
438                 $hsp->{_strand_hack}->{query} = -1;
439                 $hsp->{_strand_hack}->{hit}   =  1;
440             }
441             $new_hit->add_hsp($hsp);
442            
443             push(@new_hits, $new_hit);
444         }
445
446         return \@new_hits;
447 }
448 #------------------------------------------------------------------------
449 #this will also walk out 3 base pairs looking for the stop codon
450 sub trim_to_CDS{
451     my $hit = shift;
452     my $seq = shift;
453
454     my $ref = ref($hit);
455     my $hsp_ref = ref($hit->{_hsps}->[0]);
456
457     my $transcript_seq  = maker::auto_annotator::get_transcript_seq($hit, $seq);
458     my ($translation_seq, $offset, $end, $has_stop)
459         = maker::auto_annotator::get_translation_seq($transcript_seq);
460
461     my $new_hit = new $ref('-name'         => $hit->name,
462                            '-description'  => $hit->description,
463                            '-algorithm'    => $hit->algorithm,
464                            '-length'       => $hit->length,
465                            '-score'        => $hit->score,
466                            '-bits'         => $hit->bits,
467                            '-significance' => $hit->significance
468                            );
469
470
471
472     my $tB;
473     my $tE;
474
475     my $strand = $hit->strand('query');
476     if($strand == 1){
477         $tB = $hit->start('query') + $offset;
478         #translation end is always one base pair after stop -- why??
479         $tE = $hit->start('query') + ($end - 1) - 1;
480     }
481     else{
482         $tE = $hit->end('query') - $offset;
483         $tB = $hit->end('query') - ($end - 1) + 1;
484     }
485
486     #walk out a little and look for the stop codon
487     my $new_stop;
488     if(!$has_stop){
489         my $codon;
490         if($strand == 1){
491             $codon = substr($$seq, $tE, 3);
492             if($codon =~ /TAA|TAG|TGA/){
493                 $new_stop = 1;
494                 $has_stop = 1;
495                 $tE = $tE + 3;
496             }
497         }
498         elsif($tB - 4 >= 0){
499             $codon = Fasta::revComp(substr($$seq, $tB - 4, 3));
500             if($codon =~ /TAA|TAG|TGA/){
501                 $new_stop = 1;
502                 $has_stop = 1;
503                 $tB = $tB - 3;
504             }
505         }
506     }
507
508     my $hit_start = 1;
509     foreach my $hsp ($hit->hsps){
510         #this is not the natural end and beginning!!
511         my $B = $hsp->start('query');
512         my $E = $hsp->end('query');
513
514         #see if hsp even overlaps the current CDS
515         my $class = compare::compare($B, $E, $tB, $tE);
516
517         next if($class eq '0');
518
519         #extend hsp for new stop found
520         if($new_stop){
521             if($strand == 1){
522                 $E = $tE if($tE - $E == 3);
523             }
524             elsif($strand == -1){
525                 $B = $tB if(abs$B - $tB == 3);
526             }
527         }
528
529         #figure out change to trim off seq sring
530         my $change = 0;
531         if($B < $tB){
532             $change = abs($tB - $B) if($strand == 1);
533             $B = $tB;
534         }
535        
536         if($E > $tE){
537             $E = $tE;
538             $change = abs($tE - $E) if($strand == -1);
539         }
540
541         my $length = abs($E-$B)+1;
542
543         #set natural begining (important for correct strandedness)
544         my ($nB, $nE) = ($strand == 1) ? ($B, $E) : ($E, $B) ;
545
546         my $qrSeq = substr($hsp->query_string(),
547                           $change,
548                           $length);
549
550         my $htSeq = substr($hsp->hit_string(),
551                           $change,
552                           $length);
553
554         my $hoSeq = substr($hsp->homology_string(),
555                           $change,
556                           $length);
557
558         my @args;
559        
560         push(@args, '-query_start');
561         push(@args, $nB);
562        
563         push(@args, '-query_seq');
564         push(@args, $qrSeq);
565        
566         push(@args, '-score');
567         push(@args, $hsp->score);
568         push(@args, '-homology_seq');
569         push(@args, $hoSeq);
570        
571         push(@args, '-hit_start');
572         push(@args, $hit_start);
573        
574         push(@args, '-hit_seq');
575         push(@args, $htSeq);
576        
577         push(@args, '-hsp_length');
578         push(@args, $length);
579        
580         push(@args, '-identical');
581         push(@args, $hsp->identical);
582            
583         push(@args, '-hit_length');
584         push(@args, $length);
585        
586         push(@args, '-query_name');
587         push(@args, $hsp->query_name);
588        
589         push(@args, '-algorithm');
590         push(@args, $hsp->algorithm);
591        
592         push(@args, '-bits');
593         push(@args, $hsp->bits);
594        
595         push(@args, '-evalue');
596         push(@args, $hsp->evalue);
597        
598         push(@args, '-pvalue');
599         push(@args, $hsp->pvalue);
600        
601         push(@args, '-query_length');
602         push(@args, $length);
603        
604         push(@args, '-query_end');
605         push(@args, $nE);
606        
607         push(@args, '-conserved');
608         push(@args, $length);
609        
610         push(@args, '-hit_name');
611         push(@args, $hsp->name);
612        
613         push(@args, '-hit_end');
614         push(@args, $hit_start + $length - 1);
615        
616         push(@args, '-query_gaps');
617         push(@args, 0);
618        
619         push(@args, '-hit_gaps');
620         push(@args, 0);
621        
622         my $hsp = new $hsp_ref(@args);
623         $hsp->queryName($hsp->query_name);
624         #-------------------------------------------------
625         # setting strand because bioperl is all messed up!
626         #------------------------------------------------
627         if ($strand == 1 ){
628             $hsp->{_strand_hack}->{query} = 1;
629             $hsp->{_strand_hack}->{hit}   = 1;
630         }
631         else {
632             $hsp->{_strand_hack}->{query} = -1;
633             $hsp->{_strand_hack}->{hit}   =  1;
634         }
635
636         $new_hit->add_hsp($hsp);
637        
638         $hit_start = $hit_start + $length;
639     }   
640
641     return $new_hit;
642 }
643 #------------------------------------------------------------------------
644 sub add_splice_data {
645         my $new_hsp = shift;
646         my $old_hsp = shift;
647         my $what    = shift;
648
649         my $d = $old_hsp->donor();
650         my $a = $old_hsp->acceptor();
651         if ($what eq 'revq' || $what eq 'both'){
652                 $new_hsp->acceptor(Fasta::revComp($d))
653                 if defined($d);
654
655                 $new_hsp->donor(Fasta::revComp($a))
656                 if defined($a);
657
658         }
659         else {
660                 $new_hsp->donor($d);
661                 $new_hsp->acceptor($a);
662         }
663
664 }
665 #------------------------------------------------------------------------
666 sub load_args {
667         my $hsp    = shift;
668         my $action = shift;
669
670         my @args;
671
672         push(@args, '-query_start');
673         push(@args, $hsp->start('query'));
674
675         my $q_s = $hsp->query_string();
676         push(@args, '-query_seq');
677
678         if ($action eq 'copy'){
679                 push(@args, $q_s);
680         }
681         elsif ($action eq 'revq' || $action eq 'both'){
682            if (ref($hsp) =~ /blastp|tblastn|blastx/ && ref($hsp) !~ /tblastx/){
683               push(@args, $q_s);
684            }
685            else{
686               push(@args, Fasta::revComp($q_s));
687            }
688         }
689
690         push(@args, '-score');
691         push(@args, $hsp->{SCORE});
692
693         push(@args, '-homology_seq');
694         push(@args, $hsp->homology_string);
695
696
697         push(@args, '-hit_start');
698         push(@args, $hsp->start('hit'));
699
700         my $h_s = $hsp->hit_string();
701
702         push(@args, '-hit_seq');
703
704         if ($action eq 'copy'){
705                 push(@args, $h_s);
706         }
707         elsif ($action eq 'revh' || $action eq 'both'){
708            if(ref($hsp) =~ /blastp|tblastn|blastx/ && ref($hsp) !~ /tblastx/){
709                push(@args, $h_s);
710            }
711            else{
712               push(@args, Fasta::revComp($h_s))
713            }
714         }
715
716         push(@args, '-hsp_length');
717         push(@args, $hsp->query->length);
718        
719         #my $spaces = $hsp->homology_string =~ tr/ / /;
720         #my $midd = length($hsp->homology_string) - $spaces;
721
722         push(@args, '-identical');
723         push(@args, $hsp->num_identical);
724
725         push(@args, '-hit_length');
726         push(@args, $hsp->hit->length);
727
728         push(@args, '-query_name');
729         push(@args, $hsp->name());
730
731         push(@args, '-algorithm');
732         push(@args, $hsp->algorithm);
733
734         push(@args, '-bits');
735         push(@args, $hsp->bits);
736
737         push(@args, '-evalue');
738         push(@args, $hsp->evalue);
739
740         push(@args, '-pvalue');
741         push(@args, $hsp->signifcance);
742
743         push(@args, '-query_length');
744         push(@args, $hsp->query->length);
745
746         push(@args, '-query_end');
747         push(@args, $hsp->end('query'));
748
749         push(@args, '-conserved');
750         push(@args, $hsp->num_conserved);
751
752         push(@args, '-hit_name');
753         push(@args, $hsp->name());
754
755         push(@args, '-hit_end');
756         push(@args, $hsp->end('hit'));
757
758         push(@args, '-query_gaps');
759         push(@args, $hsp->gaps('query'));
760
761         push(@args, '-hit_gaps');
762         push(@args, $hsp->gaps('hit'));
763
764         return \@args;
765
766 }
767 #------------------------------------------------------------------------
768 sub copy {
769
770         my $hit   = shift;
771         my $what  = shift;
772
773         die "PhatHit_utils::copy have what arg revq, revh, both, copy!\n"
774         unless defined($what);
775
776         my $ref = ref($hit);
777
778         my $new_hit = new $ref('-name'         => $hit->name,
779                                '-description'  => $hit->description,
780                                '-algorithm'    => $hit->algorithm,
781                                '-length'       => $hit->length,
782                               );
783
784         $new_hit->queryLength($hit->queryLength);
785         $new_hit->database_name($hit->database_name);
786
787         my @new_hsps;
788         foreach my $hsp ($hit->hsps){
789                 my $args  = load_args($hsp, $what);
790
791                 my $ref = ref($hsp);
792                 my $new_hsp = new $ref(@{$args});
793                
794
795                 add_splice_data($new_hsp, $hsp, $what) if ref($hsp) =~ /est2genome$/;
796
797                 $new_hsp->queryName($hsp->queryName)
798                 if defined($hsp->queryName);
799
800                 my $n_q_s = $hsp->strand('query');
801                 my $n_h_s = $hsp->strand('hit');
802
803                 if    ($what eq 'both') {
804                    $n_q_s = -1*$n_q_s;
805                    $n_h_s = -1*$n_h_s;
806                 }
807                 elsif ($what eq 'revq'){
808                    $n_q_s = -1*$n_q_s;
809                 }
810                 elsif ($what eq 'revh'){
811                    $n_h_s = -1*$n_h_s;
812                 }
813
814                $new_hsp->{_strand_hack}->{query} = $n_q_s;
815                $new_hsp->{_strand_hack}->{hit}   = $n_h_s;
816                $new_hsp->{_indentical_hack}      = $hsp->frac_identical();
817
818                 push(@new_hsps, $new_hsp);
819         }
820
821         my @sorted;
822         if ($what eq 'both' || $what eq 'rev'){
823                 @sorted = sort {$b->nB('query') <=> $a->nB('query') } @new_hsps;
824                 $new_hit->{_was_flipped} = 1;
825         }
826         elsif ($what eq 'revh'){
827                 @sorted = sort {$b->nB('hit') <=> $a->nB('hit') } @new_hsps;
828         }
829
830         foreach my $hsp (@sorted){
831                 $new_hit->add_hsp($hsp);
832         }
833
834         return $new_hit;
835 }
836 #------------------------------------------------------------------------
837 sub normalize {
838         my $hit  = shift;
839         my $what = shift;
840
841         my $sorted = sort_hits($hit, $what);
842
843         my %seen;
844         my @keepers;
845         for (my $i = 0; $i < @{$sorted} -1;$i++){
846                 my $hsp_i = $sorted->[$i];
847                 my $nbeg_i = $hsp_i->nB($what);
848                 my $nend_i = $hsp_i->nE($what);
849
850                 for (my $j = 1; $j < @{$sorted};$j++){
851                         my $hsp_j = $sorted->[$j];
852                         my $nbeg_j = $hsp_j->nB($what);
853                         my $nend_j = $hsp_j->nE($what);
854
855                         if ($nbeg_i >= $nbeg_j && $nbeg_i <= $nend_j){
856                                 if ($hsp_i->score > $hsp_j->score){
857                                         push(@keepers, $hsp_i)
858                                         unless $seen{$nbeg_i}{$nend_i};
859                                 }
860                                 else {
861                                         push(@keepers, $hsp_j)
862                                         unless $seen{$nbeg_j}{$nend_j};
863                                 }
864                                 $seen{$nbeg_i}{$nend_i}++;
865                                 $seen{$nbeg_j}{$nend_j}++;
866
867                         }
868                         elsif ($nbeg_j >= $nbeg_i && $nbeg_j <= $nend_i){
869                                if ($hsp_i->score > $hsp_j->score){
870                                         push(@keepers, $hsp_i)
871                                         unless $seen{$nbeg_i}{$nend_i};
872                                 }
873                                 else {
874                                         push(@keepers, $hsp_j)
875                                         unless $seen{$nbeg_j}{$nend_j};
876                                 }
877
878                                 $seen{$nbeg_i}{$nend_i}++;
879                                 $seen{$nbeg_j}{$nend_j}++;
880                         }
881                         else {
882                         }
883                        
884                 }
885         }
886
887         my $ref = ref($hit);
888
889         my $new_hit = new $ref('-name'         => $hit->name,
890                                '-description'  => $hit->description,
891                                '-algorithm'    => $hit->algorithm,
892                                '-length'       => $hit->length,
893                               );
894
895         $new_hit->queryLength($hit->queryLength);
896         $new_hit->database_name($hit->database_name);
897         $new_hit->{is_normalized} = 1;
898        
899         my %crap;
900         foreach my $hsp (@keepers){
901             $crap{$hsp->nB('hit')}{$hsp->nE('hit')}++;
902             $new_hit->add_hsp($hsp);
903         }
904
905         my $s_size = @{$sorted};
906         my $k_size = @keepers;
907
908         #print "s_size:$s_size k_size:$k_size\n";
909         #sleep 2;
910
911         return $new_hit;
912 }
913 #------------------------------------------------------------------------
914 sub is_contigous {
915         my $hit = shift;
916        
917         my $q_sorted = sort_hits($hit, 'query');
918         my $h_sorted = sort_hits($hit, 'hit');
919
920         #print $hit->name."\n";
921         for (my $i = 0; $i < @{$q_sorted};$i++){
922                 my $q_hsp = $q_sorted->[$i];
923                 my $h_hsp = $h_sorted->[$i];
924
925                 my $q_nB = $q_hsp->nB('query');
926                 my $q_nE = $q_hsp->nE('query');
927
928                 my $h_nB = $h_hsp->nB('query');
929                 my $h_nE = $h_hsp->nE('query');
930
931                 #print "q_nB:$q_nB h_nB:$h_nB q_nE:$q_nE h_nE:$h_nE\n";
932
933                 return 0 if $q_nB != $h_nB;
934                 return 0 if $q_nE != $h_nE;
935         }
936         return 1;
937 }
938 #------------------------------------------------------------------------
939 sub get_span_of_hit {
940         my $hit  = shift;
941         my $what = shift || 'query';
942        
943         if ($hit->strand($what) eq '-1/1'){
944                 print STDERR " mixed strand feature in PhatHit_utils\n";       
945         }
946         elsif ($hit->strand($what) eq '1/-1'){
947                 print STDERR " mixed strand feature in PhatHit_utils\n";
948         }
949
950         return ($hit->nB($what), $hit->nE($what));
951 }
952 #------------------------------------------------------------------------
953 sub add_offset {
954         my $lil_fish = shift;
955         my $offset   = shift;
956
957         foreach my $f (@{$lil_fish}){
958                 foreach my $hsp ($f->hsps){
959                         my $new_start = $offset + $hsp->start('query');
960                         my $new_end   = $offset + $hsp->end('query');
961
962                         $hsp->query->location->start($new_start);
963                         $hsp->query->location->end($new_end);
964                         $hsp->{'_sequenceschanged'} = 1;
965                 }
966                 $f->{nB}{query} += $offset if (defined($f->{nB}) && defined($f->{nB}{query}));
967                 $f->{nE}{query} += $offset if (defined($f->{nE}) && defined($f->{nE}{query}));
968                 $f->{'_sequenceschanged'} = 1;
969         }
970
971 }
972 #------------------------------------------------------------------------
973 sub reset_query_lengths {
974         my $features       = shift;
975         my $query_length   = shift;
976
977         foreach my $f (@{$features}){
978                 $f->queryLength($query_length);
979                 $f->{'_sequenceschanged'} = 1;
980         }
981
982 }
983 #------------------------------------------------------------------------
984 sub merge_hits {
985         my $big_fish = shift;
986         my $lil_fish = shift;
987         my $max_sep  = shift;
988        
989         return unless @{$lil_fish};
990
991         unless (@{$big_fish}){
992                 @{$big_fish} = @{$lil_fish};
993                 return;
994         }
995
996         print STDERR "merging blast reports...\n" unless($main::quiet);
997
998         #-- working
999         my %big_names;
1000         my %little_names;
1001         my @merged;
1002         foreach my $b_hit (@{$big_fish}){
1003                 $big_names{$b_hit->hsp(0)->hit->seq_id} = $b_hit;
1004         }
1005         foreach my $l_hit (@{$lil_fish}){
1006                 $little_names{$l_hit->hsp(0)->hit->seq_id}++;
1007         }
1008
1009         my %was_merged;
1010         foreach my $l_hit (@{$lil_fish}){
1011
1012                 next unless defined($big_names{$l_hit->hsp(0)->hit->seq_id});
1013
1014                 my $b_hit = $big_names{$l_hit->hsp(0)->hit->seq_id};
1015
1016                 my $b_start = $b_hit->nB('query');
1017                 my $b_end   = $b_hit->nE('query');
1018
1019                 ($b_start, $b_end) = ($b_end, $b_start)
1020                 if $b_start > $b_end;
1021        
1022                 my @new_l_hsps;
1023
1024                 my $l_start = $l_hit->nB('query');
1025                 my $l_end   = $l_hit->nE('query');
1026
1027                ($l_start, $l_end) = ($l_end, $l_start)
1028                 if $l_start > $l_end;
1029
1030                 #print STDERR "b_start:$b_start l_start:$l_start\n";
1031                 #print STDERR "b_end:$b_end l_end:$l_end\n";
1032
1033                 my $distance =
1034                 $b_start <= $l_start ? $l_start - $b_end : $b_start - $l_end;
1035
1036                 #print STDERR "distance:$distance\n";
1037
1038                 next unless $distance < $max_sep;
1039
1040                 next unless $b_hit->strand('query') eq $l_hit->strand('query');
1041
1042                 next unless $b_hit->strand('hit') eq $l_hit->strand('hit');
1043
1044                 #print STDERR "adding new hsp to ".$b_hit->name." ".$b_hit->description."\n";
1045
1046                 $was_merged{$l_hit->hsp(0)->hit->seq_id}++;
1047
1048                 my @new_b_hsps;
1049                 foreach my $b_hsp ($b_hit->hsps) {
1050                         push(@new_b_hsps, $b_hsp);
1051                 }
1052
1053
1054                foreach my $l_hsp ($l_hit->hsps){
1055                         push(@new_b_hsps, $l_hsp);
1056                }
1057
1058                 $b_hit->hsps(\@new_b_hsps);
1059                 $b_hit->{'_sequenceschanged'} = 1;
1060                 $b_hit->{'_sequences_was_merged'} = 1;
1061                 push(@merged, $b_hit)   
1062         }
1063
1064         foreach my $b_hit (@{$big_fish}){
1065                 next if $was_merged{$b_hit->hsp(0)->hit->seq_id};
1066                 push(@merged, $b_hit);
1067         }
1068         foreach my $l_hit (@{$lil_fish}){
1069                 next if $was_merged{$l_hit->hsp(0)->hit->seq_id};
1070                 push(@merged, $l_hit);
1071         }
1072
1073         print STDERR "...finished\n" unless($main::quiet);
1074         @{$big_fish} = @merged;
1075 }
1076 #------------------------------------------------------------------------
1077 #--------------------------- FUNCTIONS ----------------------------------
1078 #------------------------------------------------------------------------
1079 sub AUTOLOAD {
1080         my ($self, $arg) = @_;
1081
1082         my $caller = caller();
1083         use vars qw($AUTOLOAD);
1084         my ($call) = $AUTOLOAD =~/.*\:\:(\w+)$/;
1085         $call =~/DESTROY/ && return;
1086
1087         #print STDERR "PhatHit::AutoLoader called for: ",
1088         #      "\$self->$call","()\n";
1089         #print STDERR "call to AutoLoader issued from: ", $caller, "\n";
1090
1091         if ($arg){
1092                 $self->{$call} = $arg;
1093         }
1094         else {
1095                 return $self->{$call};
1096         }
1097 }
1098 #------------------------------------------------------------------------
1099 1;
1100
1101
Note: See TracBrowser for help on using the browser.