=pod

=head1 NAME

  Bio::EnsEMBL::Analysis::RunnableDB::RecoverFalseIntrons; 



=head1 SYNOPSIS

  my $fs = Bio::EnsEMBL::Analysis::RunnableDB::RecoverFalseIntrons->new(
			      -analysis   => $analysis_obj,
			     );

  $fs->fetch_input();
  $fs->run();
  $fs->output();
  fs->write_output(); 


=head1 DESCRIPTION

 This object wraps Bio::EnsEMBL::Analysis::Runnable::OrthologueEvaluator and is 
 used to fetch the input from different databases as well as writing results 
 the results to the database.a

 The input_id_format for this analysis requires that you ran the module FindFalseIntrons beforehand. 
 This is because false introns ( coding introns in a different species ) are stored as simple 
 features in the core /reference database and their db id is used in this analysis, to check if the 
 false intron has been fully recovered or not.  

  The input_ids are quite long for this analysis so you have to patch  the input_id_analysis table : 
  
  alter table input_id_analysis change input_id input_id varchar(950) ;

  The input_ids will look like this : 

  chromosome:BROADD2:31:26912747:27017854:1:ENSCAFT00000013647:ENSMUST00000039449,ENST00000361371,ENST00000389194:0_0_0:2190659 

  chromosome:BROADD2:31:26912747:27017854:1  ENSCAFT00000013647     ENSMUST00000039449,ENST00000361371,ENST00000389194    : 0,1_0_0 :        2190659,21906560 
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^           ^^^^^^^^^              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^          ^^^^^^^^^        ^^^^^^^^^^^^^^
       slice to re-run analysis on           Trans. - StableId        Id's of homologues which hace the correct struct.    indexes of       simple_feature dbID's   
                                             of 'faulty' transcript   the protein supporting features of these trans       simple_features 
                                                                      will be used to recompute the prediction             ( see below)     ( see below ) 



    the indexes of simple features provide a 'link' between the homolog transcripts which are used for the 
    re-computation and the false introns ( simple features ) which they should 'repair'. 

    i.e. ENSMUST00000039449,ENST00000361371,ENST00000389194 : 0,1_0_0 : 2190659,2190656  

    exactly means : 

       ENSMUST00000039449 has two exons which has a non-coding counterpart in the  
       questionable transcript ENSCAFT00000013647. These have index 0 and 1  in the simple-feature 
       array string. Simple-features  2190659 and 2190656 ( intron coords ) should be overlapped by the 
       new computed gene structure. 

       ENST00000361371 _0_ 2190659   - only simple feature 2190659 should be overlapped 


=head1 CONTACT

 Post general queries to B<ensembl-dev@ebi.ac.uk>

=head1 APPENDIX

 The rest of the documentation details each of the object methods.
 Internal methods are usually preceded with a '_'

=cut



package Bio::EnsEMBL::Analysis::RunnableDB::RecoverFalseIntrons;  
#package Bio::EnsEMBL::Analysis::RunnableDB::ExonerateVSGenewise;  
use strict; 
use List::Util qw(max); 
use Bio::EnsEMBL::Utils::Exception qw(throw warning info stack_trace_dump);
use Bio::EnsEMBL::Analysis::RunnableDB::Exonerate2Genes; 
#use Bio::EnsEMBL::Pipeline::RunnableDB::TargettedExonerate; 
use Bio::EnsEMBL::Analysis::Runnable::ExonerateTranscript; 
use Bio::EnsEMBL::Analysis::RunnableDB::BaseGeneBuild;
use Bio::EnsEMBL::Analysis::Config::GeneBuild::ExamineGeneSets; 
use Bio::EnsEMBL::Analysis::Config::GeneBuild::OrthologueEvaluator; 
use Bio::EnsEMBL::Analysis::Config::GeneBuild::Databases; 
use Bio::EnsEMBL::Analysis::RunnableDB::ExamineGeneSets; 
use Bio::EnsEMBL::Pipeline::SeqFetcher::Pfetch; 
use Bio::EnsEMBL::Registry;  
use IO::String;
use Bio::SeqIO; 
use Bio::EnsEMBL::Pipeline::SeqFetcher::OBDAIndexSeqFetcher;
use Bio::EnsEMBL::Analysis::Runnable::BestTargetted; 
use Bio::EnsEMBL::Analysis::Config::GeneBuild::ExamineGeneSets; 
use Bio::EnsEMBL::Analysis::Tools::GeneBuildUtils::GeneUtils; 
use Bio::EnsEMBL::Analysis ; 

use Bio::EnsEMBL::Analysis::Tools::ExonerateTranscriptFilter;

# to get the registry file to load the databases : 
use Bio::EnsEMBL::Analysis::Config::GeneBuild::OrthologueEvaluator;
use Bio::EnsEMBL::Analysis::RunnableDB::UTR_Builder;
use Bio::EnsEMBL::Analysis::RunnableDB::ExonerateForGenewise;
use Bio::EnsEMBL::Analysis::Tools::GeneBuildUtils::GeneUtils 
         qw(
            get_transcript_with_longest_CDS
            get_one2one_orth_for_gene_in_other_species
           );
use Bio::EnsEMBL::Pipeline::RunnableDB::FPC_BlastMiniGenewise;
use Bio::EnsEMBL::Analysis::Tools::GeneBuildUtils::HomologyUtils 
         qw( 
            get_gene_obj_out_of_compara_homology_object
           );
use Bio::EnsEMBL::Analysis::Tools::GeneBuildUtils::TranscriptUtils 
         qw(
            list_evidence 
            convert_translateable_exons_to_exon_extended_objects
           ); 
use Bio::EnsEMBL::Analysis::Tools::Utilities qw(create_file_name write_seqfile);
use Bio::EnsEMBL::Analysis::Tools::GeneBuildUtils::EvidenceUtils
  qw(create_feature_from_gapped_pieces create_feature);

use vars qw(@ISA);  

@ISA = qw ( Bio::EnsEMBL::Analysis::RunnableDB::BaseGeneBuild ) ; 




sub new {
  my ($class,@args) = @_;  
  my $self = $class->SUPER::new(@args);   


   


  # old input_id_format : 
  #
  # chromosome:BROADD2:3:30384105:30579389:1:ENSCAFT00000014395:ENST00000282259:2187827
  # chromosome:BROADD2:3:30384105:30579389:1:ENSCAFT00000014395:ENST00000396135:2187827
  # chromosome:BROADD2:3:30384105:30579389:1:ENSCAFT00000014395:ENST00000396137:2187809
  # chromosome:BROADD2:3:30384105:30579389:1:ENSCAFT00000014395:ENST00000396137:2187826
  # chromosome:BROADD2:3:30384105:30579389:1:ENSCAFT00000014395:ENST00000396137:2187827
  #
  # can be changed to :
  #
  # chromosome:BROADD2:3:30384105:30579389:1:ENSCAFT00000014395:ENST00000282259[1],ENST00000396135[1],ENST00000396137[1,2,3]:2187827,2187809,2187826
  #
  # would help - so this means  :
  #
  #    ENSCAFT00000014395 contains a lot of introns to recover.
  #
  #    homolog ENST00000282259 has coding intron of simple feature [1] which is 2187827
  #    homolog ENST00000396135 has coding intron of simple feature [1] which is 2187827
  #    homolog ENST00000396137 has coding intron of simple features [1,2,3]= 2187827,2187809,2187826
  #
  # the good thing about this : all possible genes are computed in one run so we don't need another run to compare the genes, or to cluster them. 
  # 
  
  my @input = split/\:/,$self->input_id ;    
  my ($csys,$asm,$name,$start,$end,$strand,$transcript_sid,$homolog_transcript_sid, $simple_feature_index, $simple_feature_string) = split/\:/,$self->input_id ;     

#  print "csys $csys\n" ; 
#  print "asm $asm \nname $name\nstart $start\nend $end\nstrand $strand\nquery$transcript_sid\nhom_string$homolog_transcript_sid\nsimple_feature_index $simple_feature_index \nsimple_feature_string $simple_feature_string\n" ; 


  if ( scalar(@input) != 10) { 
 #   throw ("wrongly-formatted input_id ; should be : ". 
 #          "CcoordSystemName:Assembly:SeqRegionName:START:END:STRAND:PROTEIN_DB:PROTEIN_id:transcript_sid:SupportingFeatureDBId".
 #          "\nexample:   chromosome:Btau_3.1:10:16466933:16595540:1:ENSBTAT00000018735:ENST00000379915:347368" ) ; 
  } 
 
  # process input_id .....
 
  # simple features are a string of format 2344,23425,3245 
  my @simple_feature_ids = split /\,/, $simple_feature_string ; 
  $self->simple_feature_db_id(\@simple_feature_ids) ;

  # simple features are a string of format ENST00000282259,ENST00000396135,ENST00000396137 
  # this string can include different species !!!!!!
  my @stable_ids_of_homolog_transcripts = split /\,/, $homolog_transcript_sid ; 
  $self->homolog_transcript_sid(\@stable_ids_of_homolog_transcripts) ; 


  # simple feature index  stored in a string like : 0_0,1,2_0 
  # gives information which of the homolog transcripts has recovered which false intron ( which is stored in simple feature table  )
   
  $self->simple_feature_index($simple_feature_index) ;   

  $self->transcript_sid ( $transcript_sid ) ;    

  my $simgw_input_id = "$csys:$asm:$name:$start:$end:$strand" ; 
  $self->simgw_input_id ( $simgw_input_id) ; 

  print "simple_feature_ids: " . join (" ", @simple_feature_ids) . "\n" ;  
  print "homolog_trans_sid : " . join (" ", @stable_ids_of_homolog_transcripts) . "\n" ; 
  print "transcript_sid    : $transcript_sid\n" ;  
  print "simgw-id          : $simgw_input_id\n" ;  

  $self->{_ex_genes} = [] ;  
  $self->{_gw_genes} = [] ;  
  $self->{_src_genes} = [] ;  
  $self->{hom_trans_cache} = {} ; 
  $self->{sf_to_hom_trans_cache} = {} ; 
  $self->{_test_exon} = {} ; 
  $self->{_homolog_exon_alignments}= {} ; 
  $self->{_exon_pairing} = {} ; 
  $self->{_register_testex_vs_homex_coverage}= {} ; 
  $self->{_register_nr_aligned_exons_vs_all_exons_in_trans} = {} ; 
  $self->{_register_f_matrix_score} = {};

  $self->{_hit_matrix}=[];

  $self->limit_input_ids(0); 
  $self->limit_genewise_options(1); 
  $self->use_artifical_input_ids(0);   
  $self->only_run_exonerate(0);  
  $self->lightweight_analysis(0);  

  if ( $self->lightweight_analysis) { 
    $self->limit_genewise_options(1); 
    print "\n\n\t\t********* WARNINNG - Running lightweight analysis and only 1 protein per species per recovery-case - this is quicker  *******\n\n" ;  
  } 

  if ( $self->limit_genewise_options) {  
    print "\n\n\t\t********* WARNING - ONLY GENEWISE OPTIONS LIMITED ! ******** \n\n\n\n" ; 
  } 

  if ( $self->only_run_exonerate ) { 
    print "\n\n\t\t******** WARNING - ONLY RUNNING EXONERATE  !!!!****** \n\n\n" ;  
    sleep(1);
  } 

  $self->debug(0);
  $self->use_dna_align_features_from_homologs_to_add_utr(0); 
  if ( $self->use_dna_align_features_from_homologs_to_add_utr ) { 
    print "\n\n\t\t******** WARNING - USING SPECIES cDNA / EST to predict UTR !!!!****** \n\n\n" ;  
    sleep(1);
  } 

  return $self;
}



sub make_seqfetcher {
  my ( $self, $index, $seqfetcher_class ) = @_;
  my $seqfetcher;

  (my $class = $seqfetcher_class) =~ s/::/\//g;
  require "$class.pm";

  if(defined $index && $index ne ''){
    my @db = ( $index );

    # make sure that your class is compatible with the index type
    $seqfetcher = "$seqfetcher_class"->new('-db' => \@db, );

  }
  else{
    &throw("Can't make seqfetcher\n");
  }

  return $seqfetcher;

}

sub fetch_input {   
  my ( $self) = @_ ;   
 
  # 
  # fetch questionable transcript with possible false introns from QUERY_SPECIES database 
  # query_species is the species which has the gene model which we want to check // which 
  # might contain repeetive introns which should be exons  
  # 

  my $new_gene = $self->make_new_gene_from_source_transcript($self->transcript_sid);  
  $self->src_genes($new_gene) ; 

  
  my $enst_to_simple_features  = $self->build_hash_of_recoverd_introns_per_transcript() ;  
  $self->recovered_introns_of_transcript($enst_to_simple_features) ;  

  #
  # get protein supporting features for Exons of all homologes genes which have coding exon where there is  
  # an intron in the query species 
  # 
  #  
  
  my %protein_align_feature_acc ;    
  my %dna_align_feature_acc ;    

  for my $stable_id_of_homolog_transcript ( @{$self->homolog_transcript_sid} ) {   

     my ($sp,$type) = Bio::EnsEMBL::Registry->get_species_and_object_type( $stable_id_of_homolog_transcript ) ; 
     my $ta = Bio::EnsEMBL::Registry->get_adaptor($sp,"core","transcript");       
     Bio::EnsEMBL::Registry->set_disconnect_when_inactive(); 

     print " fetching homologues transcript by stable_id : $stable_id_of_homolog_transcript\n" ; 
  
     my $one2one_orth_trans = $ta->fetch_by_stable_id( $stable_id_of_homolog_transcript ) ; 
  
     unless ( $one2one_orth_trans ) {  
          throw("no transcript with stable_id $stable_id_of_homolog_transcript found\n") ; 
     }   

     $self->set_homolog_transcript($one2one_orth_trans) ; 

     # also recompute with the translation of the one2one homologue 
     my $one2one_translation = $one2one_orth_trans->translation ;  
     $protein_align_feature_acc{$one2one_translation->stable_id} = 1 ;  

     # get all supporting features for all Exons - filter out dna_align features    

     my @e_sf = map { $_->get_all_supporting_features } @{$one2one_orth_trans->get_all_Exons}  ;   

     for my $sf_array ( @e_sf) {      
        my @reduced_sf_array ; 
        if ( $self->lightweight_analysis){ 
          @reduced_sf_array = splice @$sf_array,0,3;  
        }else {  
          @reduced_sf_array = @$sf_array;
        }
        for ( @reduced_sf_array) {   
           #print "using " . $_->hseqname . "\n" ; 
          if (ref($_)=~m/Bio::EnsEMBL::DnaPepAlignFeature/){   
            $protein_align_feature_acc{$_->hseqname} = 1 ;   
            $self->sf_to_gene($_->hseqname, $one2one_orth_trans) ;    
            if ( $_->hseqname =~m/\.+/ ) {  
              (my $tmp=$_->hseqname)=~s/\..+//g;
              $self->sf_to_gene($tmp, $one2one_orth_trans) ;   
            }
          }elsif (ref($_)=~m/Bio::EnsEMBL::DnaDnaAlignFeature/){   
            $dna_align_feature_acc{$_->hseqname} = 1 ;   
          }
        } 
     }  
     # also register the ENSMUSP whatever protein as sf to compute f_matrix later  
     if ( $one2one_orth_trans->translation ) { 
        $self->sf_to_gene($one2one_orth_trans->translation->stable_id, $one2one_orth_trans) ;    
     }
   } # next homolog transcript id  
   $self->dna_align_features_of_homologs([keys %dna_align_feature_acc]) ;  

   print "\n\n" ; 
   my %sf = %{$self->{sf_to_hom_trans_cache} } ; 
   for ( keys %sf ) {  
     print "sf : " . $_ . "\n" ; 
   } 

    
   # re-run trial with old supporting features as well ... 
   # not sure if this was a good idea - if you re-run with old supporting features you can't really
   # compare/ align against the old exons of the buggy gene .....
   
#   
#   my $q_trans = $self->db->get_TranscriptAdaptor->fetch_by_stable_id($self->transcript_sid) ; 
#   my @q_sf = map { $_->get_all_supporting_features } @{$q_trans->get_all_Exons} ;  
#     
#   for my $sf_array ( @q_sf ) {  
#     for ( @$sf_array) {  
#       if (ref($_)=~m/Bio::EnsEMBL::DnaPepAlignFeature/){  
#          $protein_align_feature_acc{$_->hseqname} = 1 ;  
#          $self->sf_to_gene($_->hseqname, $q_trans) ; 
#       }
#     } 
#   }     
#
   my @target_input_ids ;   

   my @my_input_ids = qw ( Q9GM99.1 P42859.2 P42858.1 P42859-2) ;  
   if ( $self->use_artifical_input_ids ) {  
     print "\n"x30 ; 
     print "\nWarning - using artificial input_ids"x30 ; 
     print "\n"x30 ; 
     my %tmp ; 
     @tmp{@my_input_ids}=1; 
     %protein_align_feature_acc= %tmp ; 
   } 

  for ( keys %protein_align_feature_acc ) {   
    push @target_input_ids, $self->simgw_input_id.",".$_ ;  
  }   

  if ( $self->limit_input_ids ) {  
    print "\n"x30 ; 
    print "\nWarning - input-id range limited "x30 ; 
    print "\n"x30 ; 
    print "I will run on these input_ids / proteins :\n" ;  
    print "\n\n\n\n\nWARNING - INPU_IDS LIMITED ----\n\n\n\n\n" ; 
    @target_input_ids = splice(@target_input_ids,0,5) ;  
  }

  for ( @target_input_ids ){  
    print "input_id : " . $_."\n" ; 
  } 
  #
  # get protein seq from homologues transcript stable id .... 
  # 
 
   

  print "\nRunning ExonerateTranscript-runs\n====================================\n\n" ;    

  my @protein_files ; 
  my @eg ;  
  my %genomic_seq_written;    

   #
   # we will run the exonerate comptues first and we don't delete the protein files. 
   # than we will run the genewise on the protein files, than we delete protein files. 
   # that saves us time to write the files twicce .... 
   #


  PROTEIN_ID: for my $targ_xrate_input ( @target_input_ids ) {
    print "\n\ninput_id : $targ_xrate_input\n\n" ;  

     # prepare input for ExonerateTranscript run 

     my ($slice_name, $protein_id) = split /\,/, $targ_xrate_input;  

     unless ( $genomic_seq_written{$slice_name}) { 
       $self->write_genomic_sequence_to_file($slice_name) ; 
       $genomic_seq_written{$slice_name} = 1 ; 
     }  


################

    my $seqfetcher = Bio::EnsEMBL::Pipeline::SeqFetcher::OBDAIndexSeqFetcher->new(
                                                                                  -db     => [("/lustre/blastdb/Ensembl/uniprot_index/")], 
                                                                                  -format  => 'fasta', 
                                                                                 );

    my $seqx ;
    eval {
      $seqx = $seqfetcher->get_Seq_by_acc($protein_id);
    };

    if($@) {
      warning("Problem fetching sequence for id [$protein_id] with $seqfetcher $@\n");
    }

    if(!defined($seqx)){
      warning("Could not find sequence for [$protein_id] with $seqfetcher "); 
    }
    my $protein_seq ;  

    unless ( defined $seqx )  {  

       print "Could not find sequence for [$protein_id] with $seqfetcher - now trying with pfetch.... \n" ;  
       my $seq_fetcher = Bio::EnsEMBL::Pipeline::SeqFetcher::Pfetch->new() ; 
        $protein_seq = $seq_fetcher->get_Seq_by_acc($protein_id ) ;   
  
       unless ( $protein_seq ) { 
          $seq_fetcher = Bio::EnsEMBL::Pipeline::SeqFetcher::Pfetch->new( -options => '-a' ) ;  
          $protein_seq = $seq_fetcher->get_Seq_by_acc($protein_id ) ;   
       }  

       unless ( $protein_seq ) {  
          (my $p=$protein_id)=~s/\..+//g; 

          $seq_fetcher = Bio::EnsEMBL::Pipeline::SeqFetcher::Pfetch->new(); 
          $protein_seq = $seq_fetcher->get_Seq_by_acc($p) ;    
          unless ( $protein_seq ) { 
            $seq_fetcher = Bio::EnsEMBL::Pipeline::SeqFetcher::Pfetch->new( -options => '-a' ) ;  
            $protein_seq = $seq_fetcher->get_Seq_by_acc($p) ;   
          }  
       } 

       unless ( $protein_seq ) {   
          print "Failed to fetch sequence $protein_id via pfetch -a / OBDA\n"; 
          next PROTEIN_ID ; 
       }  
    } else {   
        $protein_seq = $seqx ; 
    } 
     my $pepfile      = create_file_name("protein_" ,"fa" , "/tmp" );  
     write_seqfile($protein_seq, $pepfile, 'fasta') ; 
     push @protein_files, $pepfile ; 

     print STDERR "running ExonerateTranscript on Protein :  ".$protein_id.
     " and ".$self->slice->name." length ".$self->slice->length."\n";
     print "\nUsing hardcoded program vwerion exonerate 1.4.0 !\n" ;
 
      my $r = Bio::EnsEMBL::Analysis::Runnable::ExonerateTranscript->new(
                                                                         -analysis => $self->analysis,
                                                                         -query => $self->slice, 
                                                                         -target_file => $self->genomic_file, 
                                                                         -query_type => 'protein',
                                                                         -query_file => $pepfile,
                                                                         -program   => "/software/ensembl/bin/exonerate-1.4.0" ,
                                                                         -options => "--model protein2genome --bestn 1 ".
                                                                                     "--maxintron 700000 " , 
                                                                        );
    
     $r->run() ;    
     my @output = @{$r->output()} ;   
     # these are actually all transcripts not genes .... 
   
     for ( @output ) {      
       map { $_->slice($self->slice()) } @{$_->get_all_Exons} ; 
       my $g= Bio::EnsEMBL::Gene->new();  
       $g->biotype("exonerate_recomp") ;  
       $_->biotype("exonerate_recomp") ;  
       $g->add_Transcript($_);  
       $self->ex_genes($g); 
       push @eg, $g ; 
     }    
  } 
  print scalar(@eg) . " exonerate genes made\n" ;

  for ( @eg ) {  
    print_whole_gene($_) if $self->debug ;
  } 


  print "\n\nRecoverFalseIntrons: Now running BlastMiniGenewise:\n" ;  
  print "================================================\n\n" ; 

  # either the analysis is stored or we need to create a new one :   
  # needs to be re-written    
  #

 my @gw_options ; 

 if ( $self->limit_genewise_options ) {    
   print "WARNING !!!!!!!!! Genewise options limited !!! \n"x10 ; 
   push @gw_options, { '-options' => '-init endbias -splice_gtag -quiet ' } ; 
   push @gw_options, { '-options' => '-splice_gtag -quiet ' }   ;  
 } else {   

   push @gw_options, { '-options' => '-quiet' } ; 
   push @gw_options, { '-options' => '-quiet -splice_gtag ' }   ; 
   push @gw_options, { '-options' => '-quiet -splice_gtag -init endbias ' } ; 
   push @gw_options, { '-options' => '-quiet -nosplice_gtag ' } ; 

 } 

  my @gw_genes ;  

  if ( $self->only_run_exonerate ) {   
     print "WARNING - only running exonerate, not genwises .\n" ; 
     for my $g ( @eg) {  
        $self->gw_genes($g);
     } 
  } else { 
  
    my $gs = Bio::SeqIO->new(-file   => "<".$self->genomic_file , -format => "FASTA" );     
    my $genomic_seq = $gs->next_seq(); 
  
  
    # hmm i need to know which strand we're on .... need have the correct strand information in the input_id .... 
    # or does this disturb iexonerate ?  
  
  
    my $sf_strand = ${$self->get_aligned_intron_coord()}[0]->strand(); 
   
  
      for my $gw_run_options ( @gw_options ) {    
          for my $protein_file ( @protein_files )    { 
             my $ps = Bio::SeqIO->new(-file   => "<$protein_file", -format => "FASTA" );     
             my $prot_seq = $ps->next_seq() ;     
    
             my ($sr,$asm,,$chr,$start,$end,$strand,$fintron_trans,$hom_trans,$simple_feat_id) = split/:/, $self->input_id ; 
    
             my $rangefeat = new Bio::EnsEMBL::FeaturePair
             (
             -start => 1, 
             -end   => ( ($self->slice->end+1) - $self->slice->start ) , 
             -strand=> $sf_strand, 
             -slice => $self->slice
             );
             $rangefeat->strand(-1) if($strand == -1); 
    
             my $features = [$rangefeat];
    
             my $gw = Bio::EnsEMBL::Analysis::Runnable::MiniGenewise->new(  
                                                                      -query=> $self->slice, 
                                                                      -protein => $prot_seq, 
                                                                      -analysis=> $self->analysis,
                                                                      -features => $features, 
                                                                      -genewise_options => $gw_run_options,  
                                                                     );  
              if ( $sf_strand == 1 )  {  
                 $gw->reversed_sequence(0); 
              } else { 
                 $gw->reversed_sequence(1); 
              } 
              $gw->run() ; 
              my @transcripts = @{ $gw->output } ;  
    
              # Due to miniseq/fullseq possibility in Genewise, the transcripts produced 
              # only hold FeaturePairs rather than DnaPep align features - we need to 
              # convert them .... this is normally done by BlastMiniGenewise.
              # genewise only makes transcripts !  
     
              for my $t ( @transcripts ) {      
                   my $g = Bio::EnsEMBL::Gene->new(
                                 -start => $t->start , 
                                 -end   => $t->end , 
                                 -strand => $t->strand , 
                                 -slice => $self->slice, 
                                 ) ; 
    
                    $g->add_Transcript($t) ;     
                    $t->analysis($self->analysis) ; 
                    $self->gw_genes($g);
          }
        } 
      }   
    
  }   

  #
  # remove protein - and genomic files ......
  # 
  for my $pf ( @protein_files ) {  
     my $cmd = "rm $pf" ; 
     system("$cmd"); 
  } 
  
 # my $cmd = "rm " . $self->genomic_file();  
 # system("$cmd");  
}





sub print_pos {  
  my ($obj,$string , $tsf)  = @_ ;    
  #print stack_trace_dump(). "\n"; 
  print "$string " . $obj->seq_region_start . "\t" ; 
  print "" . $obj->seq_region_end   . "\t" ; 
  print "" . ( $obj->seq_region_end  - $obj->seq_region_start + 1 )   . "\t" ; 
  print "" . $obj->seq_region_strand ;   
  if ( ref($obj)=~m/Gene/) {  
    print "  ".$obj->biotype." " ; 
  } 
  if ( ref($obj)=~m/Transcript/) {  
    print "  ".$obj->biotype." " ; 
  } 
  if ( $tsf ) {
    print "  " . map { $_->display_id } @$tsf ; 
  } 
  print "\n" ;  
}


sub run { 
  my ($self) = @_ ;  

  my @gw_genes = @{$self->gw_genes} ; 
  my @ex_genes = @{$self->ex_genes} ; 
  my @src_genes = @{$self->src_genes} ;  

  # setting standard biotypes for both sets  
  if ( $self->debug) { 
     print "exonerate-genes:\n=================\n";
     for my $g ( @ex_genes ) {   
         print_whole_gene($g);
         print_pos($g, "EX_GENE") ; 
     }  
     print "genewise-genes:\n=================\n";
     for my $g ( @gw_genes ) {   
       print_whole_gene($g);
       print_pos($g, "GW_GENE") ; 
     } 
     print "src-genes:\n=================\n";
     for my $g ( @src_genes ) {  
         print_whole_gene($g);
         print_pos($g, "SRC_GENE") ; 
     } 
  } 

  my %exons ; 
  for my $gw ( @gw_genes ) { 
    for my $tw ( @{$gw->get_all_Transcripts} ) {  
      my $tw_exon = scalar(@{$tw->get_all_Exons}); 
      $exons{$tw}= scalar(@{$tw->get_all_Exons}); 
    } 
  } 
  
  for my $gw ( @ex_genes ) { 
    for my $tw ( @{$gw->get_all_Transcripts} ) {  
      my $tw_exon = scalar(@{$tw->get_all_Exons}); 
      $exons{$tw}= scalar(@{$tw->get_all_Exons}); 
    } 
  } 

  my @all_genes= (@gw_genes, @ex_genes,@src_genes ) ;   

  # use BestTargetted to check which gene strucutre is best  

  my %unique_biotypes = map {$_->biotype => 1} @all_genes;  

  # genes will be clustered by biotypes so we have to handover all biotypes we got  
  
  my $seq_fetcher = Bio::EnsEMBL::Pipeline::SeqFetcher::Pfetch->new() ;     

  my $runnable = Bio::EnsEMBL::Analysis::Runnable::BestTargetted->new
     (
      -biotypes => [keys %unique_biotypes],
      -seqfetcher => $seq_fetcher ,
      -verbose => 1  , 
      -genes => \@all_genes, 
      -analysis => $self->analysis, 
     ); 

  $runnable->run;
  my @best_targetted_genes = @{$runnable->output};  

  my @filter_out_buggy_gene ; 
  for ( @best_targetted_genes ) {  
    if ($_->biotype=~m/buggy_gene/){   
      print "BestTargetted returned our buggy_gene which we used as input. we're skipping it. skipping buggy gene\n"; 
      next ; 
    }else {  
      push @filter_out_buggy_gene, $_ ; 
    }  
  }  
  @best_targetted_genes = @filter_out_buggy_gene;  

  if ( $self->debug ) {  
     print_best_targetted_genes(\@best_targetted_genes) ;  
  }


  # 
  # i should do a kind of  get aligned intron coords by stable id of homolog thingy ......
  # 
 
  my $ma = Bio::EnsEMBL::Registry->get_adaptor("compara","compara","member");
  Bio::EnsEMBL::Registry->set_disconnect_when_inactive();

  # dynamicly choose gene-adaptor for core db 
  # ATTENTION ! Name of the species is fetched out of the compara db than the gene-adaptor is 
  # constructed out of the config file !!!   
 

  # this checks if an intron has been removed and checks how many have been removed, too - comparing 
  # to how many coding introns there are in the homolg trnscript 
 
  my @checked_genes ;  

  my %hom_trans_to_gene ; 
  my %hom_trans_is_ccds ; 
 
  for my $homolog_transcript_id ( @{$self->homolog_transcript_sid} ) {  
     
    my ($species, $object )  =  Bio::EnsEMBL::Registry->get_species_and_object_type($homolog_transcript_id ); 
    my $ta = Bio::EnsEMBL::Registry->get_adaptor($species,"core","transcript");      
    my $ga = Bio::EnsEMBL::Registry->get_adaptor($species,"core","gene");      
    Bio::EnsEMBL::Registry->set_disconnect_when_inactive();
  
    my $homolog_trans = $ta->fetch_by_stable_id($homolog_transcript_id) ;  
    my $homolog_gene = $ga->fetch_by_transcript_stable_id($homolog_transcript_id) ;  

    $hom_trans_to_gene{$homolog_transcript_id} = $homolog_gene;

    # find out if the gene / transcript is a member of the CCDS set ... 
    # this needs to be changed once we start defining CCDS membership for transcripts 

    my @dbe = @{ $homolog_gene->get_all_DBEntries } ;   

    $hom_trans_is_ccds{$homolog_trans->stable_id}="NO" ;  

    for my $dbe ( @dbe ) {  
       if ( $dbe->dbname =~m/CCDS/ )  {
         $hom_trans_is_ccds{$homolog_trans->stable_id}="YES" ; 
       } else {  
         $hom_trans_is_ccds{$homolog_trans->stable_id}="no" ; 
       } 
    } 

    # compare gene-structure with structure of homologue   

    for my $new_gene (@best_targetted_genes) {  
       $self->attach_slice($new_gene) ;  
       
       # this sub changes the biotype if an intron was removed  
       my $ch_gene = $self->check_if_false_intron_has_been_removed_in_new_trans($homolog_trans, $new_gene ) ;  

       if ( $ch_gene->biotype =~m/intron_removed/) {   
         print "match " .  $ch_gene->biotype . " matches biotype intron_removed\n" if $self->debug; 
         push @checked_genes, $ch_gene ;  
       } 
    }  
  }  

  print "\n" . scalar(@checked_genes ) . " transcripts found which have the intron removed\n\n" ;  

  my @intron_removed_genes = @checked_genes ; 
   
  # now remove redudant transcripts of all genes which have the intron removed 

  my @non_redundant_genes = @{$self->remove_redundant_genes ( \@checked_genes )} ;  


   
  # 2 methods of scoring are currently implemente ..... :   
  
  #  SCORING METHOD 1 : 
  #  - calcualting the overlap between old and new gene-exons 
  #  - building ratio 
  #  - sselecting gene with highest ratio and longest translation .....
  # 
#  
#  my $very_best_gene = $self->check_exon_overlap_between_new_gene_and_src_gene(\@non_redundant_genes) ;  
#
   my @very_final_genes ;    
#
#  if ( $self->other_genes ) {  
#     push @very_final_genes, @{$self->other_genes} ; 
#  }  
# 
#
  # SCORING METHOD 2 : 
  # - calculate exon-alignment score for aligning trans against homologe exons and use the one with highest score, 
  # than compare against score of buggy transcript and select one with highest score 
  #
  # calculate f-score for old (buggy) transcript and store them
  # 
  
  my %old_f_matrix_scores;   
  my $src_gene ;  

  for my $stable_id_of_homolog_transcript ( @{$self->homolog_transcript_sid} ) {    
    $src_gene = ${$self->src_genes}[0];
    my $src_trans = ${$src_gene->get_all_Transcripts}[0]; 
    my $homolog_trans = $self->get_homolog_transcript_by_stable_id($stable_id_of_homolog_transcript) ;    

    print " \n\nCalculating_values for old gene vs $stable_id_of_homolog_transcript\n\n" if $self->debug ; 
    my $f_matrix_score_old_gene  = $self->check_test_transcript_against_homolog($src_gene, $src_trans, $homolog_trans )  ;   
    $old_f_matrix_scores{$stable_id_of_homolog_transcript} = $f_matrix_score_old_gene ;  
    print " Transcript : " .  $homolog_trans->stable_id . " scores ......  $f_matrix_score_old_gene\n" ;  
  } 

  print "\nCalculating_scores of all genes against the homologs and set biotype of best gene to 'MAX' ....\n" ;  
  my @most_similar_to_homolog_genes = @{ $self->find_gene_which_has_exon_length_distr_most_similar_to_homolog(\@non_redundant_genes) } ; 

  my @lower_genes ; 
  my @max_genes ;  
  for my $g ( @most_similar_to_homolog_genes ) {  
    if ( $g->biotype=~m/MAX/) {   
      push @max_genes, $g; 
    } else {   
       # this is where all other genes get filtered out.
       print "skipping $g\n" ;  
       push @lower_genes, $g ; 
    } 
  } 
  my @most_sim_non_redundant ;  
  if ( scalar(@max_genes) > 1 )  {  
    print "have " . scalar(@max_genes) .  " genes with the same max score.. let's see if they're redundant.\n" ; 
    @most_sim_non_redundant = @{check_if_genes_are_redundant(\@max_genes)};    

    my $gene ; 
    if ( @most_sim_non_redundant > 1 ) {  
      print "WARNING : genes have the same score but are different - i will use the gene with less exons\n" ; 
      my $less_exon = 100000000;
      for my $g ( @most_sim_non_redundant) {       
         print_whole_gene($g);
         if ( $less_exon > scalar(@{$g->get_all_Exons})  ) {  
            $less_exon = @{$g->get_all_Exons } ; 
            $gene = $g; 
         } 
      }
      @most_sim_non_redundant=();
      push @most_sim_non_redundant, $gene ;
    }  
  } else {  
    print "setting most_sim_non_redundant to max_genes\n" ;
    print "max_genes : " . scalar(@max_genes) . "\n" ;  
    print join("\n", @max_genes ) . "\n" ; 
    @most_sim_non_redundant = @max_genes ; 
  } 
 
  print "\n\n\n" ; 
  print "Comparison of all test_genes against the homologs :\n---------------------------------------------------------\n" ; 
  my @all_scores ;  

  for my $g ( @most_sim_non_redundant ) { 
    print_whole_gene($g) ;    
    print " coverage against homolog transcript for gene $g :\n\n" ;   

    my %tmp1 = %{ $self->register_testex_vs_homex_coverage($g)};  
    my %aligned_coverage = %{ $self->register_nr_aligned_exons_vs_all_exons_in_gene($g)};    
    my %f_matrix = %{ $self->register_f_matrix_score($g)};  
    my $score ;  

    for my $k  ( keys %tmp1 ) {   
      my $score_src_trans_vs_homolog = 0 ; 
      if (  $old_f_matrix_scores{$tmp1{$k}{htrans}->stable_id} ) { 
        $score_src_trans_vs_homolog = $old_f_matrix_scores{$tmp1{$k}{htrans}->stable_id}; 
      }       

      print " homolog transcript                  : " . $tmp1{$k}{htrans}->stable_id  . "\n" ;  
      print " coverage against homolog            : " . $tmp1{$k}{val} . " (nr_aligned_dog_exons / nr_of_exons_in_homolog)\n" ;  
      print " exons aligned vs all exons in gene  : " . $aligned_coverage{$k}{val} . " (nr_aligned_dog_exons / nr_of_all_dog_exons)\n" ;  
      print " f_matrix_score of new transcript    : " . $f_matrix{$k}{val} . " (f-matrix-value)\n" ;  
      print " f_matrix_score of old trans vs hom  : " .  $score_src_trans_vs_homolog . "\n\n" ;    # fix  
      $score = $f_matrix{$k}{val} ;
      if (  $score_src_trans_vs_homolog > $f_matrix{$k}{val} ) {   
        print " the f_matrix_score of the old transcript is higher than the one of the newly built one...\n";   
        print "NO_FIX_old_score_higher_".$score_src_trans_vs_homolog. "_" . $f_matrix{$k}{val} . "\n";  
        $g->biotype("NO_FIX") ;  
      }
    } 
    if ($score ){
      $g->biotype($score) ;  
      push @all_scores, $score ; 
    } 
    push @very_final_genes, $g;
  }  


  @all_scores = sort {$b <=> $a} @all_scores ;   
  my $cnt = 1 ; 
  for my $s ( @all_scores ) {   
    for my $g ( @very_final_genes ) {   
      if ($g->biotype=~m/$s/) {  
         print "score : $s --- " . $g->biotype . "\n" ; 
         $g->biotype($cnt); 
      } 
    } 
    $cnt++; 
  }  
 
  my @genes_with_utr ; 
  print "try to add utr to " . scalar(@very_final_genes) . " genes\n" ;   

  # first try to add utr from org. species....  
  
  my @dna_align_features_of_src_gene = @{$self->src_gene_dna_align_features};   
  my @dna_align_features_of_homologs = @{$self->dna_align_features_of_homologs};    

  if ( scalar(@dna_align_features_of_src_gene)){  
    print "adding utr from org species\n"; 
    for my $vg ( @very_final_genes ) {  
      push @genes_with_utr, @{$self->add_utr($vg,\@dna_align_features_of_src_gene)} ;  
    }
  } elsif(  scalar(@dna_align_features_of_homologs) && $self->use_dna_align_features_from_homologs_to_add_utr ) { 
      print "try to use cDNA's from homologs to add utr to genes\n" ; 
      print "have " .scalar( @dna_align_features_of_homologs ) . " cdnas from homologs which i could use for utr_addition \n" ; 
      if ( $self->use_dna_align_features_from_homologs_to_add_utr ) { 
        print "try to use cDNA's from homologs to add utr to genes\n" ; 
        for my $vg ( @very_final_genes ) {  
          push @genes_with_utr, @{$self->add_utr($vg,\@dna_align_features_of_homologs)} ;  
        } 
      }
  } else {  
    @genes_with_utr = @very_final_genes ; 
  }
  print "now have " . scalar(@genes_with_utr) . " genes\n" ;   

  #
  # now we can identify the most similar transcript ( transcript with high similarity-treshold vs homolog ... 
  # if there is more than one wtih the same score we might pick the one which has the highest coverage against homolog 
  #

  my $cmd = "rm " . $self->genomic_file();   
  system("$cmd");   

  my @complete_genes ;  

  for my $g ( @genes_with_utr ) {  
    my @new_transcripts = @{$g->get_all_Transcripts}; 
    if ( scalar(@new_transcripts)  > 1 ) { 
      throw("gene has more than one transcript after processing - this should not the case. check where the other transcript is added\n"); 
    }  

    $self->attach_slice($g);   
    $g = $self->attach_stuff_to_new_gene($g); 

    # attach existing, non-fixed transcripts back 
     my $orgi_gene = $self->very_original_query_gene(); 
     my @orgi_trans_diff_slice  = @{$orgi_gene->get_all_Transcripts};
     my @orgi_trans ;   

     for ( @orgi_trans_diff_slice  ) { 
         my $t = $_->transfer($self->reference_slice) ; 
         push @orgi_trans, $t ; 
     }
 
#     if ( scalar(@orgi_trans) > 1 )  {
#       print "boof ! have more than one transcript ...... need to add other transcripts .... \n" ;  
#       for my $otr ( @orgi_trans ) {   
#         print "processing transcript : " . $otr->stable_id . "\n"; 
#         if ( $otr->stable_id eq $self->src_transcript->stable_id ) { 
#            print " it's the SAME trans : ".$otr->stable_id." and " . $self->src_transcript->stable_id . " - no need to add this - skipping\n" ; 
#         }  else {  
#
# 
#            if ( $self->check_if_transcripts_are_different([@{$g->get_all_Transcripts}, $otr])) { 
#               # transcripts are all different  
#               print "Adding old transcript: " .  $otr->stable_id . " to gene \n" ;   
#               $g = $g->transfer($otr->slice);  
#               $otr->dbID(undef);
#               $otr->adaptor(undef);  
#               $g->add_Transcript($otr) ;  
#             } else {
#               print "transcripts are redundant - not addin transcript\n" ;  
#            }
#            
#         } 
#       } 
#     }  
     push @complete_genes, $g;
  } 
  for my $c ( @complete_genes ) {  
    print "GENE :  " . $c->biotype . "\t" . $c->stable_id . "\n" ;  

    for ( @{ $c->get_all_Transcripts } ) {  
       print "\tTranscript : " .  "\t" . $_."\t" ;  

       if ( $_->stable_id ) { 
         print "\t" . $_->stable_id . "\t" ;  
       }else{ 
         print " transcript_no_stable_id\t" ; 
       }  

       if (  $_->translation ) { 
         print  $_->translation. "\t".$_->translation->stable_id   ; 
       } else {  
         print " transcript_hs_no_translation" ; 
       }  
       print "\n" ; 
    } 
  }    
  #print "adding crappy stuff for verbosity\n" ; 
  #push @complete_genes, @lower_genes ; 
  $self->output(\@complete_genes) ; 
}


sub check_if_transcripts_are_different{ 
  my ($self, $aref) = @_ ;    

  # to check by hash-key you have to make sure all transcripts are on the same slice :  
  my @transcripts_diff_slice = @$aref ;  
  my @normallised_tr; 
  for ( @$aref ) {  
     my $tmp_t = $_->transfer($self->reference_slice);  
     push @normallised_tr, $tmp_t ; 
  } 


  my %tmp ; 
  for my $t (@normallised_tr  ) { 
    my @ex= @{ $t->get_all_Exons } ;
     my $string ;
     for my $e (@ex) {
       my $exon_hk = $e->hashkey ;
       $string.=$exon_hk ;
     }  
     print $string . "\n" ; 
     $tmp{$string} = 1 ;
   }
   if ( scalar(@$aref) == scalar(keys %tmp)) {   
       print "Transcripts are different\n"; 
       return 1 ; 
   }
       print "Transcripts are duplicated.\n" ; 
  return 0;  
} 

sub check_if_genes_are_redundant { 
    my ($aref) = @_ ;  

    my @max_genes=@$aref; 
    my @non_red_genes ;
    my %tmp ;
    # little check 
    for my $g ( @max_genes) { 
      if ( scalar(@{$g->get_all_Transcripts}) > 1 ){  
        throw("gene has more than one transcript - this is wrong .... : " . $g->biotype); 
      } 
    }  
    for my $g ( @max_genes ) { 
       for my $t (@{ $g->get_all_Transcripts } ) {  
         my @ex= @{ $t->get_all_Exons } ;
         my $string ;
         for my $e (@ex) {
           my $exon_hk = $e->hashkey ;
           $string.=$exon_hk ;
         } 
         $tmp{$string} = $g ;
       }
    }  

    if ( scalar(keys %tmp)==1) {  
        print "genes are redudant \n" ; 
    }else {  
        print "genes_have_same_max_score_but_are_different\n" ;   
        for ( values %tmp ) {  
          print_whole_gene($_); 
        }
    }  
    return [values %tmp] ; 
 }



sub add_utr {  
  my ( $self, $very_best_gene , $cdna_acc_ref ) = @_ ;        

  my @hseq_names = @$cdna_acc_ref ;  

#   print "now trying to add utr\n" ; 
#   my $ta = Bio::EnsEMBL::Registry->get_adaptor($$MAIN_CONFIG{QUERY_SPECIES},"core","gene");    
#   Bio::EnsEMBL::Registry->set_disconnect_when_inactive();
#   
#   my $transcript_sid = $transcript_sid->stable_id; 
#   my $source_gene = $ta->fetch_by_transcript_stable_id($transcript_sid) ;    
#   my @source_transcripts = @{ $source_gene->get_all_Transcripts } ;   
#
#
#   for my $st ( @source_transcripts ) { 
#
#      if ($st->three_prime_utr) {  
#         print "transcript_has_3_prim_utr\t" . $source_gene->stable_id . "\n" ; 
#      } 
#      if ($st->five_prime_utr) {  
#         print "transcript_has_5_prim_utr\t" . $source_gene->stable_id . "\n" ; 
#      } 
#   } 
#   my %cdna_acc ; 
#   for my $e ( @{$source_gene->get_all_Exons} ) {  
#      my @sf = @{ $e->get_all_supporting_features}; 
#      for my $s ( @sf ) {  
#        if ( ref($s)=~m/Bio::EnsEMBL::DnaDnaAlignFeature/) {  
#          $cdna_acc{$s->hseqname}=1; 
#        } 
#      } 
#   }    
#   print scalar(keys %cdna_acc) . " cdna's found which could be added as UTR\n" ;    
#
#  if (scalar ( keys %cdna_acc ) == 0 ) { 
#      print " no cDNAs found which could be added - now trying to fetch / use cDNA from compare-species\n" ;  
#  } 

  # get cdna seq from pfetch   
  my @cdna_seqs ; 
  my $seq_fetcher = Bio::EnsEMBL::Pipeline::SeqFetcher::Pfetch->new() ; 
  for my $acc ( @hseq_names ) {  
    my $seq = $seq_fetcher->get_Seq_by_acc($acc) ;    
    unless ( $seq ) { 
      $seq_fetcher = Bio::EnsEMBL::Pipeline::SeqFetcher::Pfetch->new( -options => '-a' ) ;  
      $seq = $seq_fetcher->get_Seq_by_acc($acc) ;    
    } 
    unless ( $seq ) {  
      print "sequence $acc could not be fetched\n" ; 
    }else { 
      push @cdna_seqs, $seq ; 
    }  
  }  

  # now we need to align the cDNA to the genome to get a proper gene structure........    
  #  align seqs with Exonerate2Genes 

  my @cdna_genes ;  
  my @cdna_file_names ; 
  for my $cdna  ( @cdna_seqs ) { 
     print " running ExonerateTranscript on cdna \n" ;  
     my $cdna_file      = create_file_name("cdna_" ,"fa" , "/tmp" );  
     write_seqfile($cdna, $cdna_file, 'fasta') ; 
      push @cdna_file_names, $cdna_file ; 
     print STDERR "running ExonerateTranscript on cDNA and slice ".$self->slice->name." length ".$self->slice->length."\n";
     print "\nUsing hardcoded program vwerion exonerate 1.4.0 !\n" ;
                                                # CDNA !!!!  
     my $options = "--model est2genome --forwardcoordinates FALSE --softmasktarget TRUE --exhaustive FALSE  --score 500 ".
                   "--saturatethreshold 100 --dnahspthreshold 60 --dnawordlen 14";  

     my $r = Bio::EnsEMBL::Analysis::Runnable::ExonerateTranscript->new(
                                                                         -analysis => $self->analysis,
                                                                         -query => $self->slice, 
                                                                         -target_file => $self->genomic_file, 
                                                                         -query_type => 'dna',
                                                                         -query_file => $cdna_file,
                                                                         -program   => "/usr/local/ensembl/bin/exonerate-0.8.3", 
                                                                         #-program   => "/software/ensembl/bin/exonerate-1.4.0" ,
                                                                         -options => $options , 
                                                                        ); 
    
     $r->run() ;   

     my @output = @{$r->output()} ;     

     my $percent_ident_filter = 97 ; 
     my @o2 = @output ;  
     print "have " .scalar(@output) . " featrues before filtering $percent_ident_filter\n" ;  
     # filter results 
     my $et_filter= new Bio::EnsEMBL::Analysis::Tools::ExonerateTranscriptFilter->new(
        -percent_id => $percent_ident_filter,
        -best_in_genome => 1, 
        -coverage => 90, 
       );
     my @filtered_cdnas = @{$et_filter->filter_results(\@output)};  
     print "have " .scalar(@filtered_cdnas) . " features after filtering by percentage_ident >= $percent_ident_filter\n" ; 
     @output = @filtered_cdnas ; 

     # these are actually all transcripts not genes .... 
      
     for ( @output ) {     
       map { $_->slice($self->slice()) } @{$_->get_all_Exons} ; 
       my $g= Bio::EnsEMBL::Gene->new();  
       $g->biotype("cdna_recomp") ;  
       $_->biotype("cdna_recomp") ;  
       $g->add_Transcript($_);  
       push @cdna_genes, $g; 
     }     
  }  # next cnda 
  my $rm_string = "rm ".join (" ", @cdna_file_names ) ;  
  if ( scalar(@cdna_file_names) > 0 ) { 
    system($rm_string);  
  }
  print scalar(@cdna_genes) . " cdna_genes from cdna made in total.\n" ; 
  my @result ;     

   #
   ########## utr builder 
   #  
   
   if ( @cdna_genes ) { 
      my $utr_builder = Bio::EnsEMBL::Analysis::RunnableDB::UTR_Builder->new(
        -db        => $self->db,
        -input_id  => 'fake', 
        -analysis  => $self->analysis, 
        -dont_use_config => 1, 
       );     
      $utr_builder->gw_genes([$very_best_gene]) ;  
      $utr_builder->INPUT_GENETYPES([$very_best_gene->biotype]); 
      $utr_builder->cDNA_GENETYPE([$cdna_genes[0]->biotype]); 
      $utr_builder->MAX_EXON_LENGTH(20000); 
      $utr_builder->MAX_INTRON_LENGTH(200000);  
      $utr_builder->query($self->slice); 
      $utr_builder->VERBOSE(1);  
      $utr_builder->UTR_GENETYPE($very_best_gene->biotype); 
      $utr_builder->BLESSED_UTR_GENETYPE("blessed") ; 
      #$utr_builder->UTR_GENETYPE('utr_added');
      # set cDNA's 
      $utr_builder->cdna_genes(\@cdna_genes); 
      $utr_builder->{evidence_sets} = {
                                'est'   => [] , #\@est_biotypes,
                                'simgw' => $utr_builder->INPUT_GENETYPES, 
                                'cdna'  => $utr_builder->cDNA_GENETYPE, 
                               };
      # fetch_input does nearly all the stuff we've just done by hand .... 
      #$utr_builder->fetch_input() ;   
      $utr_builder->run() ;    
    
      @result= @{ $utr_builder->output()} ;   
      #for ( @result) {  
      #  print "UTR gene ? $_\n" ;  
      #  print_whole_gene($_); 
      #}  
  }else {  
    # no cDNA-gene made ....  
    push @result, $very_best_gene; 
  } 
  return \@result; 
}


sub attach_stuff_to_new_gene { 
  my ( $self, $very_best_gene ) = @_ ;    

   my $transcript_sid = $self->transcript_sid() ; 
   my $ta = Bio::EnsEMBL::Registry->get_adaptor($$MAIN_CONFIG{QUERY_SPECIES},"core","gene");    
   my $tla  = Bio::EnsEMBL::Registry->get_adaptor($$MAIN_CONFIG{QUERY_SPECIES},"core","translation");    
   Bio::EnsEMBL::Registry->set_disconnect_when_inactive();

   unless ( $ta ) {  
    throw(
          "could not get gene-adaptor for $$MAIN_CONFIG{QUERY_SPECIES} - check your " . 
          "registry file / your OrthologueEvaluator-config\n"
          ); 
   }
   my $source_gene = $ta->fetch_by_transcript_stable_id($transcript_sid) ;    

   my @src_dbentries =  @{$source_gene->get_all_DBEntries}  ;  

   unless($source_gene){  
    throw("could not get transcript with stable_id $transcript_sid out of database :"  .$ta->db->dbname . "\@" . $ta->db->host. "\n")  ;  
   } 

  my @source_transcripts = @{ $source_gene->get_all_Transcripts } ; 

  my $very_best_transcript = ${$very_best_gene->get_all_Transcripts}[0]; 

  my $new_gene = Bio::EnsEMBL::Gene->new(); 
  $new_gene->stable_id($source_gene->stable_id);   
  $new_gene->biotype($very_best_gene->biotype) ; 
  my $src_status = $source_gene->status ; 
  $new_gene->status($src_status) ;  
  $new_gene->confidence($src_status) ;  

  $new_gene->description($source_gene->description);  
  $new_gene->display_xref($source_gene->display_xref);  
  $new_gene->external_db($source_gene->external_db);  
  $new_gene->created_date($source_gene->created_date);  
  $new_gene->modified_date($source_gene->modified_date);  

   for my $dbe ( @src_dbentries ) {   
     $new_gene->add_DBEntry($dbe) ; 
   } 
  my @new_exons = @{ $very_best_transcript->get_all_Exons } ;   

  my @nsf ;   

  my $original_slice = $very_best_transcript->slice ;  
  $self->reference_slice($original_slice) ;  
  #my $reference_slice ; 
  for my $st ( @source_transcripts ) {  
     print " try to attach : " . $st->stable_id . "\n" ; 

    if ( $st->stable_id=~m/$transcript_sid/ ) {  

      my @old_exons = @{ $st->get_all_Exons } ;  

      for my $oe ( @old_exons ) {   
         for my $ne ( @new_exons ) {   

           if ( $oe->seq_region_end >= $ne->seq_region_start and $oe->seq_region_start <= $ne->seq_region_end )  {  
             $ne->stable_id($oe->stable_id) ; 
             my $v =  $oe->version;
             $v++; 
             $ne->version($v) ; 
             $ne->created_date($oe->created_date) ; 
             $ne->modified_date(time) ; 
           } 
         } 
      } 

      my @tdb = @{$st->get_all_DBEntries}    ;
      # now we need to edit the transcript and remove one exon ....

       # now wee need to attach all stuff to the transcript   
       # how do we deal with UTR  ?
       # how do we deal with the exon-stable-ids etc ? 
       my $new_version = $st->version ; 
       $new_version++ ; 
       my $new_transcript = new Bio::EnsEMBL::Transcript(  
                     -exons => \@new_exons , 
                     -stable_id => $st->stable_id , 
                     -version => $new_version ,  
                     -external_name =>$st->external_name ,  
                     -external_db => $st->external_db ,
                     -external_status => $st->external_status , 
                     -display_xref => $st->display_xref , 
                     -created_date => $st->{'created_date'} , 
                     -modified_date=> time, 
                     -description => $st->description , 
                     -biotype=> $st->biotype, 
                     -status =>$st->status, 
                     -analysis =>$st->analysis, 
                     ) ;     

         for my $db ( @tdb ) {  
             $new_transcript->add_DBEntry($db) ; 
         }  

         $new_transcript->translation($very_best_transcript->translation) ; 
         $new_transcript->translation->stable_id($st->translation->stable_id) ;  
         my $tl_version = $st->translation->version ; 
         $tl_version++ ; 
         $new_transcript->translation->version($tl_version) ; 
         $new_transcript->translation->created_date($st->translation->created_date) ; 
         $new_transcript->translation->modified_date(time);  


         my @tl_db = @{$st->translation->get_all_DBEntries} ; 
         for ( @tl_db ) {   
            $new_transcript->translation->add_DBEntry($_) ; 
         }
         my @all_supporting_features ;    

         for my $f ( @{ $very_best_transcript->get_all_supporting_features} ) { 
           my $nf = $f->transfer($original_slice); 
           push @all_supporting_features, $nf ; 
         } 
                 
         $new_transcript->add_supporting_features(@all_supporting_features);    

         my $nt = $new_transcript->transfer($original_slice); 
         $new_transcript = $nt ;  
      
      # if ( $reference_slice) { 
       #  my $nt = $new_transcript->transfer($reference_slice); 
       #  $new_transcript  = $nt ;  
      # }
       $new_gene->add_Transcript($new_transcript) ; 
    } else {   
         my $nt = $st->transfer($original_slice); 
         $st = $nt ;   
         print $new_gene . "\n" ;
         if ( $new_gene->get_all_Transcripts ) {       
            if ( $self->check_if_transcripts_are_different([@{$new_gene->get_all_Transcripts}, $st])) {  
            # otherwise there's confusion where to get the start / end exon from ... not sure why ...  
              print "adding : " . $st->stable_id . " to transcript \n\n" ; 
              $st->translation->adaptor($tla); 
              $new_gene->add_Transcript($st) ; 
             }
         }else { 
              print "adding : " . $st->stable_id . " to transcript \n\n" ; 
              $st->translation->adaptor($tla); 
              $new_gene->add_Transcript($st) ; 
         } 
       # transfer old ( unchagned ) source-transcript to the same slice 
       #if ( $reference_slice) { 
       #  my $nt = $st->transfer($reference_slice); 
       #  $st = $nt ;  
       #}  
       
    }   
    # first trans was added so now get reference slice  
    #my @tmp  = @{ $new_gene->get_all_Transcripts} ;    
    #$reference_slice = $tmp[0]->slice();   
  }
  return $new_gene ; 
}  




#
# compare the exon length of the new genes against the exon length of the homolog transcripts ..... 
#


sub find_gene_which_has_exon_length_distr_most_similar_to_homolog { 
  my ( $self, $genes_to_test ) = @_ ;   

  my @most_sim_to_hom_genes ; 
  my %scores ; 
  my @test_genes = @$genes_to_test ;  

  for my $g ( @test_genes ) {  
    my $test_trans = ${$g->get_all_Transcripts}[0];  

    print "\n\t\t---------------\n\nNow computing all those funny values for $g\n"  if $self->debug;

    #
    # Only compare the test_trainscript against homolog gene structures which share the same supporting features 
    #
    # i.e. : homolog ENSG1 was build from seq1, seq2, seq3
    # i.e. : homolog ENSG2 was build from seq1, seq2
    # test_transcript was build from seq3. compare test_transcript against ENSG1 
    # 
    
    my $mm_score = 0;  

    for my $sf ( @{ $test_trans->get_all_supporting_features } ) {    

       print "have supporting feature : " . $sf->hseqname . "\n" if $self->debug;  

       my @homologues_transcripts_which_are_supported_by_sf = @{$self->sf_to_gene($sf->hseqname)} ;    

       if ( scalar (@homologues_transcripts_which_are_supported_by_sf) == 0 ) {   
          (my $sfn = $sf->hseqname)=~s/\..+//; 
           @homologues_transcripts_which_are_supported_by_sf = @{$self->sf_to_gene($sfn)} ;    
           if ( scalar (@homologues_transcripts_which_are_supported_by_sf) == 0 ) {   
             throw("No homologues transcript found for supporting_feature : " . $sf->hseqname  );
           }
       }  
       print "Supporting_feature : ".$sf->hseqname . " supports these transcripts : " ; 
       for ( @homologues_transcripts_which_are_supported_by_sf ) {  
           print "  " . $_->stable_id ; 
       }
       print "\n" ; 


       for my $homolog_trans ( @homologues_transcripts_which_are_supported_by_sf) {   
         print "\nCalculating homolog_score for " . $g . " [ " . $sf->hseqname . " ]  against_homolog: " . $homolog_trans->stable_id . "\n" ; 
         my $max_score_f_matrix  = $self->check_test_transcript_against_homolog($g, $test_trans, $homolog_trans )  ;    

         if ( $max_score_f_matrix > $mm_score ) {  
           $mm_score = $max_score_f_matrix ; 
         } 
         $scores{$g}{score} = $mm_score; 
         $scores{$g}{gene}  = $g ; 
       }
    }  
    $g->biotype("lower_homolog_score");
  }   

  
  # thsi whole part needs to be re-written as it's oold ........... 
  my $max_score = 0 ; 
  for my $k ( keys %scores ) {   
    my $sg = $scores{$k}{gene} ;  

    print "transcript " . $sg->seq_region_start . "\t" . $sg->seq_region_end . " scores : " . $scores{$k}{score} ."\n" ;  

    if ( $max_score < $scores{$k}{score}) {  
       $max_score = $scores{$k}{score}; 
    }   
  }   

  for my $g ( @test_genes ) {   
    if ( exists $scores{$g}{score}){ 
      if ($scores{$g}{score} == $max_score) { 
         my $sg = $scores{$g}{gene} ;  
         print "\nmax_scoring transcript : " . $sg->seq_region_start . "\t" . $sg->seq_region_end . " score : " . $scores{$g}{score} ."\n" ;  
         $g->biotype("MAX");
      }
    }
  } 
  return \@test_genes ; 
} 














# this routine is used to get the test_exon object from a reference string while parsing exonerate results 

sub test_exon {  
   my ($self,$test_exon) = @_ ; 
 
   unless ( exists ${$self->{_test_exon}}{$test_exon} ) { 
      ${$self->{_test_exon}}{$test_exon}=$test_exon;
   } 
   return ${$self->{_test_exon}}{$test_exon}; 
} 

#
# this routine stores the homolog exon - test exon pairings which align to each other 
#

sub exon_pairs {   
   my ($self,$homolog_exon,$test_exon) = @_ ; 

   if ( $homolog_exon && $test_exon ) {  
     if ( exists (  ${$self->{_exon_pairing}}{$homolog_exon} )) {  
       my %uniq;
       @uniq{ @{${$self->{_exon_pairing}}{$homolog_exon}} }=1;
 
       unless ( $uniq{$test_exon} ) { 
         push  @{${$self->{_exon_pairing}}{$homolog_exon}}, $test_exon;
       }
     } else {  
       push  @{${$self->{_exon_pairing}}{$homolog_exon}}, $test_exon;
     } 
   } 
   return ${$self->{_exon_pairing}}{$homolog_exon} ; 
} 


sub homolog_exon_alignments{  
   my ($self,$homolog_exon, $val) = @_ ; 

   if ( $val ) {  
     ${$self->{_homolog_exon_alignments}}{$homolog_exon}++; 
   }
   return  ${$self->{_homolog_exon_alignments}}{$homolog_exon}; 
} 




sub check_test_transcript_against_homolog { 
   my ($self,$test_gene, $test_transcript, $homolog_trans ) = @_ ;  

   if ( $self->debug ) { 
     print "\n\n################ test_gene vs HOM TRANSCRIPT " . $homolog_trans->stable_id . " ######################\n";  
     print "\n\t\tTEST_TRANSCRIPT :\n" ; 
     print_whole_trans($test_transcript) ; 
     print "\n\t\tHOMOLOG_TRANS :\n" ; 
     print_whole_trans($homolog_trans) ; 
   } 
    my $max_score_f_matrix ; 

   # prepare matrix 

   my @test_exons    = @{ $test_transcript->get_all_translateable_Exons() };   
   for (my $i=0 ; $i < scalar(@test_exons) ; $i++ ) {    
     $test_exons[$i]->{_jhv_rank}=$i ; 
     $self->test_exon($test_exons[$i]);
   } 

   my @homolog_exons = @{ $homolog_trans->get_all_translateable_Exons() };   
   for (my $i=0 ; $i < scalar(@homolog_exons) ; $i++ ) {    
     $homolog_exons[$i]->{_jhv_rank}=$i ; 
   } 
   my $max_t_rank = scalar(@test_exons) ; 
   my $max_h_rank = scalar(@homolog_exons) ; 

   for ( my $i=0; $i<$max_h_rank; $i++)  {   
     for ( my $j=0; $j<$max_t_rank; $j++ ) {    
          $self->hit_matrix($i,$j,0); 
     }
   }  

   my %exon_counterparts ; 
   my $var ;  

   # write all test exons into one big file to speed exonerate up ...

    my $test_exons_filename = "/tmp/jhv_". $$  . ".test.exon_seqs";   
    open (FH,">$test_exons_filename") || die "Cant write file $test_exons_filename\n" ; 
    for my $te ( @test_exons ) {  
      (my $seq=$te->seq->seq )=~ s/(.{1,60})/$1\n/g;
      print FH ">". "test_exon_rank " . $te->{_jhv_rank} . "\t" . $te ."\t".$te->hashkey . " " .  $te->length . "\n$seq";
    } 
    close(FH) ;  


   for my $he ( @homolog_exons) {   
      $self->exonerate_he_exon_against_test_exons($he, $test_exons_filename ) ;    
   }
   system("rm $test_exons_filename");
 
   my @hit_exons = @{$self->hit_matrix}; 

   #my $length_A = $#hit_exons ;
   #my $length_B = $#{$hit_exons[0]} ;  

   my $length_A = scalar(@homolog_exons) ; 
   my $length_B = scalar(@test_exons) ; 

   #print "length_A : $length_A " . scalar(@homolog_exons) . "\n" ; 

  if ( $self->debug ) {  
    print "\n\n" ; 
    for ( my $i=0;$i < $length_A; $i++) { 
       printf "HIT_MATRIX :\t"; 
       for (my $j = 0; $j < $length_B; $j++ ) {  
          printf "%6s", $hit_exons[$i][$j] ; 
       } 
         print "\t" . $homolog_exons[$i]->stable_id . "  $i\n" ; 
     }
     print "\n\n\n";  
  }
  # compute F-Matrix 
  
  my @f_matrix ;   

  for ( my $i=0;$i < $length_A; $i++) { 
     $f_matrix[$i][0] =  $hit_exons[$i][0]; 
  }  

  for (my $j = 0; $j < $length_B; $j++ ) {  
     $f_matrix[0][$j] =  $hit_exons[0][$j]; 
  }    


  for ( my $i=1; $i < $length_A; $i++) { 
       #print "i = $i\t" ; 
    for ( my $j= 1; $j <$length_B; $j++ ) {    
       #print "j : $j\n" ;
       my $choice_1 = $f_matrix[$i-1][$j-1] + $hit_exons[$i][$j];
       my $choice_2 = $f_matrix[$i-1][$j]   + $hit_exons[$i][$j];
       my $choice_3 = $f_matrix[$i][$j-1]   + $hit_exons[$i][$j];  
       my $max = max($choice_1,$choice_2,$choice_3);  
       #print "i = $i  j=$j  $choice_1,$choice_2,$choice_3 -- > max $max\n" ; 

       $f_matrix[$i][$j]=max($choice_1,$choice_2,$choice_3) ;   
    }
  }   

  if ( $self->debug ) { 
    for ( my $i=0; $i < $length_A; $i++) { 
      for ( my $j=0; $j < $length_B; $j++ ) {   
         printf "%5s", $f_matrix[$i][$j] ; 
      } 
        print  "\t" .$homolog_exons[$i]->stable_id . "\n" ;  
    }  
  }
  # now trace-back and see which test_gene has the most exons which align with the highest score ..... 
  
  $max_score_f_matrix = $f_matrix[$length_A-1][$length_B-1] ; 
  if ( $self->debug ) { 
    print "\n\nmax_score for aligning test_transcript to homolog is : ".$homolog_trans->stable_id." : $f_matrix[$length_A-1][$length_B-1]\n\n\n";  
    print "\n\n----- " . $homolog_trans->stable_id . "  VS  $test_transcript      ---------\n\n" ; 
  }  

  # little routine to check the pairing of the exons   OLD 


   my $exon_hits = 0 ;   
   my %exon_pairs = %{$self->{_exon_pairing}};

   HOMO_EXON: for my $he ( @homolog_exons ) {      
      unless ( $exon_pairs{$he} ) {  
         print $he->stable_id . "  DOES NOT HAVE A MATCH \n" if $self->debug ; 
         next HOMO_EXON; 
      } 

      print "\n" if ( scalar(  @{$exon_pairs{$he}}) > 1 ) ;  

      #print "\nnr_of_te_exons aligning M1: " . scalar(@{$exon_pairs{$he}}) . "\n" ; 
      #print "nr_of_te_exons aligning M2: " . $self->homolog_exon_alignments($he) . "\n\n" ; 

      if ( scalar(  @{$exon_pairs{$he}}) ==  1 ) { 
         $exon_hits++ ;  
      }elsif ( scalar(  @{$exon_pairs{$he}}) >  1 ) { 
        print "EXON HAS MORE THAN ONE HIT : " . $self->homolog_exon_alignments($he) . "\n" if $self->debug ; 
      } 

      for my $dog_exon ( @{$exon_pairs{$he}}) {  
         print $he->stable_id . "  ALIGNS  : " if ( $self->debug );
         my $diff = $he->length - $dog_exon->length ;  
         if ( $self->debug ) { 
           print " " . $dog_exon->seq_region_start . " " . $dog_exon->seq_region_end . " " .$dog_exon->length . " ". $he->length . " diff: " ;  
           print $diff . "\n" ;  
         } 
      }
      print "\n" if ( scalar(  @{$exon_pairs{$he}}) > 1 ) ; 
   }    

   print "\n\nComparison : " .  $homolog_trans->stable_id . "\t$test_gene\n" if $self->debug ; 
   #print "dog-transcripts has " . $exon_hits . " exons out of " . scalar(@test_exons) . " exons aligned : " . ( $exon_hits / scalar(@test_exons)) . "\n"  ; 
   #print "nr hom exons  : " . scalar(@homolog_exons) . "\n" ; 
   #print "nr dog exons  : " . scalar(@test_exons) . "\n" ; 
   #print "aligned exons : " . $exon_hits . "\n" ; 
   #print "hits vs homologs-coverage ratio : " . ( $exon_hits / scalar(@homolog_exons)) . "  (nr_aligned_dog_exons / nr_of_exons_in_homolog) \n";  
   #print "hits vs all-exons-in-dog-ratio  : " . ( $exon_hits / scalar(@test_exons)) . "  (nr_aligned_dog_exons / nr_of_all_dog_exons )  \n";  
   #print "exon_hits : $exon_hits    \n\n\n" ; 
   print "f_matrix max_score for aligning test_transcript to homolog is : ".$homolog_trans->stable_id." : $f_matrix[$length_A-1][$length_B-1]\n"
    if $self->debug ; 

   $self->register_testex_vs_homex_coverage($test_gene, ( $exon_hits / scalar(@homolog_exons)),$homolog_trans) ;  

   # nr of aligned dog exons vs all exons in dog - somehow a measurement how similar the structures are .... 
   $self->register_nr_aligned_exons_vs_all_exons_in_gene($test_gene, ( $exon_hits / scalar(@test_exons)),$homolog_trans) ;   

   $self->register_f_matrix_score($test_gene, $max_score_f_matrix, $homolog_trans) ; 
   
   $self->{_exon_pairing} = {};
  return $max_score_f_matrix ; 
}





 #
 # nr_aligned_dog_exons / nr_of_exons_in_homolog -measurement how much of the homolog is covered 
 #
sub register_testex_vs_homex_coverage{
  my ( $self, $test_gene, $val, $homolog_trans ) = @_ ;  
  
  if ( defined $val ) {   
   print "adding values for : $test_gene\n" if $self->debug ; 
   ${$self->{_register_testex_vs_homex_coverage}}{$test_gene}{$homolog_trans}{val} = $val ;  
   ${$self->{_register_testex_vs_homex_coverage}}{$test_gene}{$homolog_trans}{htrans} = $homolog_trans ; 
  } 
  return  ${$self->{_register_testex_vs_homex_coverage}}{$test_gene} ; 
} 



 #
 # nr of aligned dog exons vs all exons in dog - somehow a measurement how similar the structures are .... 
 #
sub register_nr_aligned_exons_vs_all_exons_in_gene{ 
  my ( $self, $test_gene, $val ,$homolog_trans) = @_ ;  
  
  if ( defined $val ) {  
    ${$self->{_register_nr_aligned_exons_vs_all_exons_in_trans}}{$test_gene}{$homolog_trans}{val} = $val ;  
    ${$self->{_register_nr_aligned_exons_vs_all_exons_in_trans}}{$test_gene}{$homolog_trans}{htrans} = $homolog_trans ; 
  } 
  return  ${$self->{_register_nr_aligned_exons_vs_all_exons_in_trans}}{$test_gene} ; 
} 


 
sub register_f_matrix_score { 
  my ($self, $test_gene, $max_score_f_matrix , $homolog_trans) = @_; 
  
  if ( defined $max_score_f_matrix) {  
    ${$self->{_register_f_matrix_score}}{$test_gene}{$homolog_trans}{val} = $max_score_f_matrix;  
    ${$self->{_register_f_matrix_score}}{$test_gene}{$homolog_trans}{htrans} = $homolog_trans ; 
  } 
  return  ${$self->{_register_f_matrix_score}}{$test_gene} ; 
} 




sub write_exon_to_file {  
   my ($exon) = @_ ;   

   my $f1= "/tmp/query_".$exon->stable_id . "_" .$$."_exon.query" ;  
   open (FH,">$f1") || die "Cant write file $f1\n" ;
   my $seq = $exon->seq->seq;
   $seq=~ s/(.{1,60})/$1\n/g;
   print FH ">homolog_exon_rank\t". $exon->{_jhv_rank} . "\t" . $exon->stable_id . "\n" . $seq;
   close(FH) ;
   return $f1 ; 
} 



sub exonerate_he_exon_against_test_exons { 
  my ($self,$he, $test_exon_filename ) = @_ ;   

  my @all_hits_for_he;  
   
  # write sequence of homolog exon to file seq to file 
  my $homolog_exon_seq_file = write_exon_to_file($he) ; 

  #print "Trying to align all test_exons against " . $he->stable_id . "\t" . $he->seq_region_start . "\t" . $he->seq_region_end . "\n" ; 

  my $result_file = "/tmp/jhv_". $he->stable_id . "_" . $$ . ".exonerate.alignment"; 

  # use option to find all exons ..... ie. match ENSMUSE00000185591  vs 
  
  my $cmd = "/software/ensembl/bin/exonerate-1.4.0 -q $homolog_exon_seq_file -t $test_exon_filename -m affine:local --bestn 1 > $result_file"; 
  system("$cmd") ; 

  # routine to parse the results out of the exonerate alignment file and write it to hit-matrix
  my $at_least_one_hit = $self->parse_exonerate_results($result_file,$he) ;   
  system("rm $result_file");

  if ( $at_least_one_hit ) { 
    #print STDERR "run produced hit : " . $he->stable_id . "\n" ; 
  } else { 
    #print STDERR "NO hit found for " . $he->stable_id . "  running with --exhaustive \n" ; 
  
  } 


  unless ( defined $at_least_one_hit ) {  
    my $cmd = "/software/ensembl/bin/exonerate-1.4.0 -q $homolog_exon_seq_file -t $test_exon_filename -m affine:local --bestn 1 --exhaustive  > $result_file"; 
    system("$cmd") ;  

    my $exhaustive_hit = $self->parse_exonerate_results($result_file,$he) ;  
    system("rm $result_file"); 

    unless ( $exhaustive_hit ) {   
      print STDERR " NO HIT even with  EXHAUSTIVE option for : " . $he->stable_id . "\n" if $self->debug;
    }
  } 
  system("rm $homolog_exon_seq_file");

}






sub parse_exonerate_results { 
  my ($self,$results_file,$he) = @_ ; 

  my $hit = 0 ;
  my $query_length =0  ;
  my $raw_score ;
  my @alignment ;  
  my $vulgar= ""; 
  my %results_hash; 

  my @result_matrix; 

  # we exonerate the sequence of the homolog exon against all coding exons of the test gene.
  # we can have multiple hits, i.e. a homolog exon can align to ONE single test-exons in different 
  # ways with different score. we only count one hit ( the best hit ) per test exon ... 

  my ($he_exon_rank, $he_stable_id, $test_exon_rank, $score,$test_exon_ref); 

  my $main_hit ; 

  open (F,"$results_file") || die " can't read $results_file\n" ;
     foreach my $l (<F>){ 
        if ($l=~/C4 Alignment:/) { 
          $hit = 1; 
          $main_hit = 1 ;
          $he_exon_rank = undef ; 
          $he_stable_id = undef ; 
          $test_exon_rank = undef ;  
          $test_exon_ref = undef ; 
          $score =undef ; 
        }
        push @alignment , $l  if $hit ;

        my @col = split/\s+/,$l;

        if ( $l=~m/Query:/ && ! defined($he_exon_rank)){
           $he_exon_rank = $col[3];  
           $he_stable_id = $col[4];  
           #print "\n\nline :$l\n"; 
           #print "QUERY : $he_exon_rank    $he_stable_id \n" ; 
        }elsif ( $l=~m/Target:/ && !defined ($test_exon_rank)){ 
           $test_exon_rank = $col[3];  
           $test_exon_ref  = $col[4];
           #print "\n\nline :$l\n"; 
           #print "TARGET : $test_exon_rank\n" ; 
        }elsif ( $l=~m/Raw score:/){ 
           $score = $col[3]; 
           #print "\n\nline :$l\n"; 
           #print "RAW SCORE : $score\n" ; 
        }   
        if ( defined $he_exon_rank && defined $test_exon_rank &&  defined $score ) {   
          #print "\ngot_a_hit : $he_exon_rank $test_exon_rank $score for:  $he_stable_id \n" ; 
          $self->hit_matrix($he_exon_rank,$test_exon_rank,$score);

          # now store the pair which aligns ( he : $te ) 
          my $test_exon_object = $self->test_exon($test_exon_ref);      
          $self->exon_pairs($he, $test_exon_object ) ;  
          $self->homolog_exon_alignments($he,1);  

          $he_exon_rank = undef ; 
          $he_stable_id = undef ; 
          $test_exon_rank = undef ; 
          $score = undef ; 
        }  
     } 
   close(F); 
    #print @alignment ; 
   unless ( $hit ) {  
        print "homolog exon : " . $he->{_jhv_rank} . " " .$he->stable_id  . " did not align at all against any test exon\n" if $self->debug; 
   }  
   return $main_hit ; 
}



sub hit_matrix { 
  my ($self, $he_exon_rank,$test_exon_rank,$score) = @_ ;  

  if ( defined $he_exon_rank && defined $test_exon_rank ) { 
     $self->{_hit_matrix}[ $he_exon_rank ][ $test_exon_rank ]= $score; 
  } 
  return $self->{_hit_matrix};
} 




sub attach_slice { 
   my ($self, $new_gene, $slice )  = @_ ;  

   my @nt = @{$new_gene->get_all_Transcripts} ;  
   throw("more than one transcript in gene structure!\n") if scalar(@nt)>1 ;     

    unless ( $slice ) { 
      $slice = $self->slice  ; 
    } 

   for my $t ( @nt ) {
     $t->slice($slice) unless $t->slice() ;  
     $t->analysis($self->analysis) ;  
     if ( $t->translation() ) { 
       $t->translation->stable_id(undef) ;  
      } 
     for my $tsf ( @{ $t->get_all_supporting_features } ) {   
        $tsf->slice($slice) unless $tsf->slice;      
        $tsf->analysis($self->analysis) unless $tsf->analysis ; 
      } 
     for my $e ( @{ $t->get_all_Exons } ) {   
       $e->slice($slice) unless $e->slice;
       for my $sf ( @{$e->get_all_supporting_features} ) { 
          $sf->analysis($self->analysis) unless $sf->analysis ; 
         $sf->slice($slice) unless $sf->slice() ; 
       } 
     } 
     if ( $t->translation() ) { 
        $t->translation->stable_id(undef) ; 
     } 
  }
  return $new_gene ; 
} 


sub print_best_targetted_genes {
  my ($aref ) = @_ ; 
  my @best_targetted_genes = @{$aref} ;  

  print "HERE's the output of BestTargetted :\n" ;  
  print "====================================\n\n"; 
   
  for my $g ( @best_targetted_genes ) {
   print_pos($g,"gene " ) ;  
       for my $t ( @{$g->get_all_Transcripts} ){ 
         my @tsf = @{$t->get_all_supporting_features} ; 
         print_pos($t,"  trans ", \@tsf ) ;    
   
         for my $e ( @{$t->get_all_Exons } ) {  
           print_pos($e,"     exon " ) ;  
         } 
         for  ( my $nr=0; $nr< scalar(@{$t->get_all_Exons }); $nr++  ) {   
           my @exons = @{ $t->get_all_Exons} ; 
           print_pos($exons[$nr],"     exon " ) ;  
           if ( $nr+1 < scalar(@exons) ) {  
             print_pos(new Bio::EnsEMBL::Intron ( $exons[$nr], $exons[$nr+1])," INTRON ") ;  
           }
         } 
         for my $i ( @{$t->get_all_Introns} ) {   
           print_pos($i, "         INTRON ");  
           print"\n";
         }
       }
      print"\n";
  }    
}



#
# make an array of non-redundant genes with the exon-hash-keys. 
# also check that all genes which will be removed from the set 
# have sf which support the same homolog transcripts 
#

sub remove_redundant_genes {   
  my ($self, $genes) = @_ ; 

  print "removing non-redundant genes\n" if $self->debug;  

  my @non_red_genes ;
  my %tmp ;

  for my $g ( @$genes) { 
    if ( scalar(@{$g->get_all_Transcripts}) > 1 ){  
      throw("gene has more than one transcript - this is wrong .... : " . $g->biotype); 
    } 
  }  

  # make an array of non-redundant genes with the exon-hash-keys
 
  for my $g ( @$genes ) {      
     #print_whole_gene($g); 
     for my $t (@{ $g->get_all_Transcripts } ) {  
       my @ex= @{ $t->get_all_Exons } ;
       my $string ;
       for my $e (@ex) {
         my $exon_hk = $e->hashkey ;
         $string.=$exon_hk ;
       } 
       # same exon_hash-keys = same gene 
       push @{$tmp{$string}}, $g ;
     }
  }  


  for my $k (keys %tmp){  

    my @g = @{$tmp{$k}} ;  

    # now check if the supporting-feature of the gene supports the same homolog transcripts 

    my %protein_align_feature_acc;  
    my %stable_ids_of_supported_transcripts;  
    my %gene_to_supported_transcripts ; 
    for my $g ( @g ) {   
      # get a list of uniq supporting features for the transcript 
      #
      #  A GENE IS ONLY REDUNDANT IF IT HAS THE SAME sf WHICH SUPPORT THE SAME TRANSCRIPTS  
      #
      #  do we really want this ?   NO !!!
      #
       my $t = ${$g->get_all_Transcripts}[0]; 
       my @e_sf = map { $_->get_all_supporting_features } @{$t->get_all_Exons}  ;  

       for my $sf_array ( @e_sf) {  
         for ( @$sf_array) {  
           if (ref($_)=~m/Bio::EnsEMBL::DnaPepAlignFeature/){   
             $protein_align_feature_acc{$_->hseqname} = 1 ;   
           }
         } 
       }   
       for my $hseqname ( keys %protein_align_feature_acc ) { 
         my @supported_transcripts = sort @{$self->sf_to_gene($hseqname)} ;
         for my $trans ( @supported_transcripts ) { 
           $stable_ids_of_supported_transcripts{$trans->stable_id} = 1 ; 
         }
       }
       my @supported_hom_stable_ids = sort keys %stable_ids_of_supported_transcripts ; 
       $gene_to_supported_transcripts{join("_",@supported_hom_stable_ids)} = $g;
    }
    for my $sid ( keys %gene_to_supported_transcripts ) {
      print "sid : $sid  ----> $gene_to_supported_transcripts{$sid} \n" if $self->debug ; 
      push @non_red_genes, $gene_to_supported_transcripts{$sid}; 
    }
      #push @non_red_genes, $g[0];
  }  
  #print "\nNON-redundant genes : " . scalar(@non_red_genes) . " left after removal of redundant strucutres ....(ALL: ".scalar(@$genes) ." )\n\n" ; 
  #for ( @non_red_genes){
  #   print_whole_gene($_);
  #}
  print "\nNON-redundant genes : " . scalar(@non_red_genes) . " left after removal of redundant strucutres ....(ALL: ".scalar(@$genes) ." )\n\n"  
   if $self->debug ; 
  return \@non_red_genes ; 
}













sub check_exon_overlap_between_new_gene_and_src_gene { 
  my ($self, $non_red_genes) = @_ ;

  my %scoring ; 
  print "check_exon_overlap_between_new_gene_and_src_gene " . scalar(@$non_red_genes) . "\n"  ;  

  # now compare the different, non-redundant  structures against the original gene .   
  
  my @src_genes = @{$self->src_genes} ;  
  my $src_gene = $src_genes[0]; 
  
  my @src_trans = @{$src_gene->get_all_Transcripts} ; 
  my @src_exons = @{ $src_trans[0]->get_all_translateable_Exons };  

  for my $ng ( @$non_red_genes ) {    

    my @tr = @{$ng->get_all_Transcripts}; 
    my @test_exons = @{ $tr[0]->get_all_translateable_Exons } ;  

    $scoring{$ng}{gene_object} = $ng ; 
    $scoring{$ng}{trans_object} = $tr[0] ; 
    $scoring{$ng}{src_exons_which_are_not_overlapped} = 0 ; 
    $scoring{$ng}{new_exons_without_overlap} = []; 
    $scoring{$ng}{overlapped_exon} = []; 
    $scoring{$ng}{nr_non_overlapping_exons} = 0 ; 



    for my $te ( @test_exons ) { 
       # looping over all new exons first ....  
       for my $se ( @src_exons ) {      
         if ( $te->seq_region_end >= $se->seq_region_start and $te->seq_region_start <= $se->seq_region_end )  {  
              #print "overlapping exons :-)\n" ; 
              #print "\nSRC_EXON  : " . $se->seq_region_start . " - " . $se->seq_region_end . "\n";
              #print "TEST_EXON : " . $te->seq_region_start . " _ " . $te->seq_region_end . "\n" ;  

              # overlap - NOW there could be some szenarios 
              # - it could be that the new exon is overlapping some shorter exons of the old prediction 
              # - it could be that one of the exons of the old gene is skipped 
              # - it could be that 
               
              push @{$scoring{$ng}{overlapped_exon}}, $se ;   
         } 
           #print "\n\n" ; 
       } 
    }   
   
    # this bit calculates how many original exons are not overlapped by the new exons.  
    my %se_exons ;  
    for my $se ( @src_exons, @test_exons  ) {        
        if (exists $se_exons{$se} ) {  
          die("this is weird - the exon keys are the same, this suggest something has gone wrong\n") ; 
        }  
        $se_exons{$se}=$se;
    } 

    my %overlapped_original_exon ;   

    print_whole_gene($ng) if $self->debug; 

    for my $se ( @src_exons ) {      
        $overlapped_original_exon{$se}{overlapping_new_exons}=[];
        for my $te ( @test_exons ) {   
         if ( $se->seq_region_end >= $te->seq_region_start and $se->seq_region_start <= $te->seq_region_end )  {   
            #print "\nmarking src_exon as OVERLAPPED       :: " .  $se_exons{$se}->seq_region_start . "\t" . $se_exons{$se}->seq_region_end."\n";
            #print "        new_exon                     :: " .  $se_exons{$te}->seq_region_start . "\t" . $se_exons{$te}->seq_region_end."\n\n";
            $overlapped_original_exon{$se}{is_overlapped}=1; 
            push @{$overlapped_original_exon{$se}{overlapping_new_exons}}, $te ; 
         }else{
            # if the exon has already been overlapped we don't change it's value  
            unless ( exists $overlapped_original_exon{$se}{is_overlapped} ) {  
              #print "marking org_exon as non-overlapped : " .  $se_exons{$se}->seq_region_start . "\t" . $se_exons{$se}->seq_region_end."\n";
              $overlapped_original_exon{$se}{is_overlapped}=0;
            } 
            if ($overlapped_original_exon{$se}{is_overlapped} == 1 ) {  
              # do nothing 
            }else{ 
              $overlapped_original_exon{$se}{is_overlapped}=0; 
            }
         } 
       }
    }   

    my $non_overlapped_exons = 0 ; 
    for my $se ( @src_exons ) {
       if ( $overlapped_original_exon{$se}{is_overlapped} == 0 ) {    
         # exon is not overlapped 
         $non_overlapped_exons++; 
       }   

      if ( scalar ( @{$overlapped_original_exon{$se}{overlapping_new_exons}}) > 1 ) {  
        print "WARN! Oh,, we might have a look at this - one old exon is overlapped by more than one new exon\n" ; 
        print "orig. exon : " . $se_exons{$se}->seq_region_start . "\t" . $se_exons{$se}->seq_region_end . "\n" ;  
        for my $te ( @{$overlapped_original_exon{$se}{overlapping_new_exons}} ) { 
           print " new. exon : " . $se_exons{$te}->seq_region_start . "\t" . $se_exons{$te}->seq_region_end . "\n" ;  
        } 
      } 
    } 


    # we should calculate as well how many original exons are overlapped by more than one new exon as this is bad, too
    # as suggests frameshifts ..... 
    #   <----------old_exon------------>
    #      <new>  <new_ex> <new_ex>         <new_ex> 

    my $new_exons_without_overlap = 0 ; 
    my %ymp ; 
    @ymp{@{$scoring{$ng}{overlapped_exon}}}=1 ; 
    for ( keys %ymp ) { 
     $new_exons_without_overlap++; 
    } 
    $scoring{$ng}{new_exons_without_overlap} = $new_exons_without_overlap ; 
    $scoring{$ng}{src_exons_which_are_not_overlapped} = $non_overlapped_exons ; 
   } 



  # now find best-scored gene(s) 

  for my $ng ( keys %scoring ) {
    
    #print "Gene : \n====================\n" ;
    #print_whole_gene($scoring{$ng}{gene_object}) ; 
    #print "nr_overlapped_exons                : " . scalar(@{$scoring{$ng}{overlapped_exon}}) . "\n" ;  
    #print "overlap_ratio                      : " . scalar(@{$scoring{$ng}{overlapped_exon}}) / scalar(@{$src_trans[0]->get_all_translateable_Exons} ) . "\n"  ;    
    $scoring{$ng}{overlap_ratio} = scalar(@{$scoring{$ng}{overlapped_exon}}) / scalar(@{$src_trans[0]->get_all_translateable_Exons} );
    #print "overlap_ratio  numbers             : " . scalar(@{$scoring{$ng}{overlapped_exon}}) . " / " . scalar(@{$src_trans[0]->get_all_translateable_Exons} ) . "\n"  ;   
    #print "translation_ratio                  : " . length($scoring{$ng}{trans_object}->translateable_seq) / length($src_trans[0]->translateable_seq ) . "\n" ; 
    #print "new_exons_without_overlap          : " . $scoring{$ng}{new_exons_without_overlap} . "\n" ; 
    # best gene seems to be the one with : 
    #  - highest nr of overlapped exons  
    #  - highest overlapped_ratio
    #  ??? nr of fixed exons ?  
  }    

  my $most_number_of_exons_fixed = -1000000; 
  my $highest_overlapping_ratio = -100000; 

  # find the gene with the maximum number of exons fixed 
  for my $ng ( keys %scoring ) {   
      if ( $scoring{$ng}{new_exons_without_overlap} >= $most_number_of_exons_fixed ) {    
        $most_number_of_exons_fixed = $scoring{$ng}{new_exons_without_overlap} ; 
      } 
      if ( $scoring{$ng}{overlap_ratio}  >= $highest_overlapping_ratio ) {     
        $highest_overlapping_ratio = $scoring{$ng}{overlap_ratio} ;
      } 
  }    


  my %best_genes ; 

  my $gene_misses_src_exon ; 
  my $nr_exons_not_overlapped = 100000 ; 

  for my $ng ( keys %scoring ) {
    if ( $scoring{$ng}{src_exons_which_are_not_overlapped} == 0  ) { 
      if ( $scoring{$ng}{overlap_ratio} == 1 ) { 
         $best_genes{$ng} = $scoring{$ng}{gene_object} ;    
         print_whole_gene($scoring{$ng}{gene_object}) ; 
         my $biotype =  "b_ratio_" . $scoring{$ng}{overlap_ratio} ; 
         $best_genes{$ng}->biotype("$biotype"); 
      } else {  
         print "skipping gene as it's overlap_ratio is not == 1. It's : $scoring{$ng}{overlap_ratio} \n" ;  
      }      
    } else {   
      if ( $nr_exons_not_overlapped  >  $scoring{$ng}{src_exons_which_are_not_overlapped} ) {  
           $nr_exons_not_overlapped =  $scoring{$ng}{src_exons_which_are_not_overlapped} ; 
           $gene_misses_src_exon = $scoring{$ng}{gene_object} ; 
      }  
      print "skipping gene - not all source exons are overlapped\n" ; 
    }  
  }    

  my @best_genes = values %best_genes ;   
  
  my $very_best_gene ;  

  if ( scalar(@best_genes) > 0 ) { 
  
    #
    # find gene with longest translation ......   
    # up to here it all worked fine but the longest translation is not always the best ..........
    # 
    
    print "\nNow selecting gene with longest translation out of " . scalar(@best_genes) . " ...\n" ;  
  
    my $max_translation_length = 0 ;  
  
    for my $bg ( @best_genes ) {   
      my $bt = ${$bg->get_all_Transcripts}[0];
         print "comparing translation length ... " .  length($bt->translateable_seq) . " vs max. length : " . $max_translation_length . "\n" ; 
      if ( length($bt->translateable_seq) > $max_translation_length ) {   
         print "translation is longer - new very best gene is : \n" ; 
         $very_best_gene = $bg ; 
         $max_translation_length = length($bt->translateable_seq); 
         print_whole_gene($very_best_gene) ;   
      }     
    }  
    if ( $very_best_gene ) { 
      print "the FINAL VERY best gene is : \n" ;  
      print_whole_gene($very_best_gene) ;   
    } else {  
      print "no very best final gene found\n" ; 
    } 
     #this is just to not loose any genes and store them for debugging 
    my @other_genes ; 
    for my $g ( @best_genes) {  
      unless ($g eq $very_best_gene ) {   
         $g->biotype("not_selected") ; 
         push @other_genes , $g ; 
      } 
    } 
    $self->other_genes(\@other_genes) ; 
    $very_best_gene->biotype("very_best_gene_old_method"); 
  }
  unless ( $very_best_gene ) {  
    print " no very best gene could be selected with method 1 as not all src_exons are overlapped\n" ; 
  }
  return $very_best_gene ; 
}








sub check_if_false_intron_has_been_removed_in_new_trans {  
   my ($self, $homolog_trans, $new_gene) = @_ ;   

   my $src_gene = $self->src_gene ;  

   my @checked_genes; 

   my @transcripts_to_check = @{$new_gene->get_all_Transcripts } ;  
   throw(" Gene has more than one transcript - this is wrong\n") if scalar(@transcripts_to_check) > 1 ;  

   my $trans_to_check = $transcripts_to_check[0]; 

   my %tmp = %{$self->recovered_introns_of_transcript};  

   my @simple_features_to_be_overlapped_by_transcript = @{ $tmp{$homolog_trans->stable_id }} ; 

   my $overlapped_simple_features_in_new_gene = 0 ; 
   my $fully_removed_simple_features_in_new_gene = 0 ; 

   my $gaps_removed = 0 ;  
   my $full_gaps_removed = 0 ;  

     SIMPLE_FEATURE: for my $sf ( @simple_features_to_be_overlapped_by_transcript ) {  
     
       if ( $self->debug) { 
         print "\n\nChecking introns of transcript ...\n" ;    
       }
       my $intron_removed;   
  
       for my $e ( @{$trans_to_check->get_all_Exons} ) {  
               if ( $self->debug) { 
                 print "checking .......\n" ;  
                 print "EXON   : " . $e->seq_region_start . "\t" .  $e->seq_region_end . "\t" . $e->seq_region_name."\t". ( $e->seq_region_end - $e->seq_region_start)."\n" ; 
                 print "GAP    : " . $sf->seq_region_start . "\t" . $sf->seq_region_end . "\t". $sf->seq_region_name."\t".( $sf->seq_region_end - $sf->seq_region_start)."\n" ;  
                 print $e->seq_region_end." >= " .$sf->seq_region_start ." && ".$e->seq_region_start . " <= ".$sf->seq_region_end . " ???\n" ; 
               }  
                 if ( $e->seq_region_end  >=   $sf->seq_region_start  &&  $e->seq_region_start  <= $sf->seq_region_end) {   
                    # we found an exon which overlaps the buyggy intron
                                                                              
                    #                        +++++++++++++++++++++++++++++++++++++++++++++++++++++
                    #                   sf_start 10                                           sf_end 20 
                    #       e_start================================  e_end  



                    


                    $overlapped_simple_features_in_new_gene++; 
                    if ( $self->debug) { 
                      print "Intron is overlapped by exon ...\n" ;    
                      print "exon: " . $e->seq_region_start . "\t" .  $e->seq_region_end . "\t" . $e->seq_region_name."\t". ( $e->seq_region_end - $e->seq_region_start)."\n" ; 
                      print "GAP : " . $sf->seq_region_start . "\t" . $sf->seq_region_end . "\t". $sf->seq_region_name."\t".( $sf->seq_region_end - $sf->seq_region_start)."\n" ;   
                    }    

                    $gaps_removed++ ; 
                    $intron_removed = 1 ; 
                    #
                    #  full overlap if : 
                    # 
                    # another check if the intron ( simple_feature ) is fully overlapped by the exon or not 
                    #
                    #                      start--EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE--end  
                    #                                  start-IIIIIIIIIIIIIIIIIIIIII-end

                    if ( $e->seq_region_start <= $sf->seq_region_start && $e->seq_region_end >=$sf->seq_region_end ) {   
                      $fully_removed_simple_features_in_new_gene ++ ; 
                      $full_gaps_removed++ ; 
                      $trans_to_check->biotype("intron_removed_".$gaps_removed."_full_".$full_gaps_removed);
                      $new_gene->biotype("intron_removed_".$gaps_removed."_full_".$full_gaps_removed); 
                    
                      if ( $self->debug )  { 
                        print "intron is fully overlapped by exon !!! \n" ; 
                        print "Exon  : " . $e->seq_region_start . 
                        "--eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee--" .
                        $e->seq_region_end . " (end)\n" ; 
                        print "  GAP :                       " .$sf->seq_region_start . "--IIIIIIIIIII--" . $sf->seq_region_end 
                       . " (end)\n" ;  
                      }
                    }  else { 
                      if ( $self->debug )  { 
                        print "intron is partially overlapped by exon !!! \n" ; 
                        print "Exon  : " . $e->seq_region_start . "--eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee--" .  
                        $e->seq_region_end . " (end)\n" ; 
                        print "  GAP :                       " .$sf->seq_region_start . "--IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII--" . 
                        $sf->seq_region_end . " (end)\n" ;  
                      }
                    }
                 } else{
                    print "Intron was NOT removed in gene ! \n" if $self->debug ; 
                    $trans_to_check->biotype("intron_removed_$gaps_removed");
                    $new_gene->biotype("intron_removed_$gaps_removed");
                 } 
       }  

      if ( $intron_removed ) {   
          if ( $self->debug ) { 
            print "intron removed in transcript :\n" ;  
            print_whole_trans($trans_to_check);  
          }
          $trans_to_check->biotype("intron_removed_".$gaps_removed."_full_".$full_gaps_removed);
          $new_gene->biotype("intron_removed_".$gaps_removed."_full_".$full_gaps_removed);
          next SIMPLE_FEATURE ; 
       }   

     }  
 
     # check if all introns are overlapped by new transcript  

     if ( scalar(@simple_features_to_be_overlapped_by_transcript) == $overlapped_simple_features_in_new_gene ) { 
       print "All introns are overlapped by gene\n" if ( $self->debug) ; 
       $trans_to_check->biotype("intron_removed_all") ; 
       $new_gene->biotype("intron_removed_all") ; 
     } 
     if ( scalar(@simple_features_to_be_overlapped_by_transcript) == $fully_removed_simple_features_in_new_gene ) { 
       print "All introns are overlapped by gene : $fully_removed_simple_features_in_new_gene\n" if ( $self->debug ) ; 
       $trans_to_check->biotype("intron_removed_all_full") ; 
       $new_gene->biotype("intron_removed_all_full") ; 
     } 
  if ( $self->debug ) {  
    print "full    gaps removed in this gene : $full_gaps_removed\n" ; 
    print "overlap gaps removed in this gene : $gaps_removed\n" ;  
  } 
  if ( $full_gaps_removed ==  0  && $gaps_removed == 0 )  {   
     print "intron has not been removed\n" if $self->debug ; 
     $new_gene->biotype("intron_NOT_removed"); 
  } 

  return $new_gene ; 
} 









sub get_aligned_intron_coord {  
  my ( $self) = @_ ;  

  my $sfa = $self->db->get_SimpleFeatureAdaptor() ;    

  my @simple_features; 
  for my $db_id ( @{ $self->simple_feature_db_id } ) { 
   
    my $sf = $sfa->fetch_by_dbID($db_id) ; 
    if ( $self->debug ) { 
      print "aligned -intron coordinates are : " . $sf->seq_region_start . "\t" . $sf->seq_region_end . "\n"  ; 
      print "aligned -intron coordinates - chromosome are : " . $sf->slice->seq_region_name . "\n";  
      print "aligned -intron -id : " .  $sf->display_id . "\n" ; 
    }  
    push @simple_features, $sf ; 
  }
  return \@simple_features ; 
}

sub print_whole_gene { 
  my ($g) = @_ ;   
  print $g . "\n" ; 
  print_pos($g,"gene :" ) ;  
  for my $t ( @{$g->get_all_Transcripts} ){ 
    print_pos($t,"  trans :" ) ;   
    my @tsf = @{$t->get_all_supporting_features} ; 
    for ( @tsf ) {  
      print "   DISPLAY : " . $_->display_id . "\n" ; 
    } 
    for my $e ( @{$t->get_all_Exons } ) { 
      print_pos($e,"     exon : " ) ;  
    } 
  } 
  print "\n\n";
}

 
sub print_whole_trans { 
  my ($t) = @_ ;    
   print_pos($t,"  trans :" ) ;    
  
    my @tsf = @{$t->get_all_supporting_features} ; 
    for ( @tsf ) {  
      print "DISPLAY : " . $_->display_id . "\n" ; 
    } 
    for my $e ( @{$t->get_all_Exons } ) { 
      print_pos($e,"     exon : " ) ;  
    } 
  print "\n\n";
}


sub ex_genes { 
   my ( $self,$aref ) = @_ ;  
   if ( $aref ) {   
     push @{$self->{_ex_genes}}, $aref ; 
   } 
   return $self->{_ex_genes} ;  
} 

sub gw_genes { 
   my ( $self,$aref ) = @_ ; 
   if ( $aref ) {   
     push @{$self->{_gw_genes}}, $aref ; 
   } 
   return $self->{_gw_genes} ;  
} 

sub src_genes { 
   my ( $self,$aref ) = @_ ; 
   if ( $aref ) {   
     push @{$self->{_src_genes}}, $aref ; 
   } 
   return $self->{_src_genes} ;  
}  

sub simple_feature_db_id { 
   my ( $self,$aref ) = @_ ; 
   $self->{_sf_dbid} = $aref if $aref ; 
   return $self->{_sf_dbid} ;  
}


sub make_new_gene_from_source_transcript{ 
  my ( $self,$transcript_sid ) = @_ ;   

   print "Reading compara-config file : $$MAIN_CONFIG{LOCATION_OF_COMPARA_REGISTRY_FILE}\n";
   print "defined in : ./Config/GeneBuild/Orthologue_Evaluator.pm\n" ; 
   
   Bio::EnsEMBL::Registry->load_all($$MAIN_CONFIG{LOCATION_OF_COMPARA_REGISTRY_FILE},1,1); 

   # get gene-adaptor for other species as well 

   my $ta = Bio::EnsEMBL::Registry->get_adaptor($$MAIN_CONFIG{QUERY_SPECIES},"core","transcript");    
   Bio::EnsEMBL::Registry->set_disconnect_when_inactive();

   my $ga = Bio::EnsEMBL::Registry->get_adaptor($$MAIN_CONFIG{QUERY_SPECIES},"core","gene");    
   Bio::EnsEMBL::Registry->set_disconnect_when_inactive();
   

   unless ( $ta && $ga ) {  
    throw(
          "could not get gene-adaptor for $$MAIN_CONFIG{QUERY_SPECIES} - check your " . 
          "registry file / your OrthologueEvaluator-config\n"
          ); 

   } 

   # collect dna-align features for source_gene for utr-addition later  
   my $source_gene = $ga->fetch_by_transcript_stable_id($transcript_sid) ;     
   $self->very_original_query_gene($source_gene) ; 
   my %cdna_acc ; 
   for my $e ( @{$source_gene->get_all_Exons} ) {  
      my @sf = @{ $e->get_all_supporting_features}; 
      for my $s ( @sf ) {  
        if ( ref($s)=~m/Bio::EnsEMBL::DnaDnaAlignFeature/) {  
          $cdna_acc{$s->hseqname}=1; 
        } 
      } 
   }    
   print scalar(keys %cdna_acc) . " dna_align_features found for src_gene which could be added as UTR\n" ;    
   $self->src_gene_dna_align_features([keys %cdna_acc]) ; 

   my $source_transcript= $ta->fetch_by_stable_id($transcript_sid) ;     

  

   unless($source_transcript){  
    throw("could not get transcript with stable_id $transcript_sid out of database :"  .$ta->db->dbname . "\@" . $ta->db->host. "\n")  ;  
   } else { 
     $self->src_transcript($source_transcript); 
   }

  my $new_gene = Bio::EnsEMBL::Gene->new(); 
  $new_gene->add_Transcript($source_transcript) ; 
  $new_gene->biotype("buggy_gene") ;  
  return $new_gene ; 
}  




sub get_adaptor {  
  my ($self)=@_;  
  print "USING HARDCODED VALUE TEST_DB as output db\n" ; 
  return $self->get_dbadaptor('TEST_DB')->get_adaptor("Gene"); 
} 


sub write_genomic_sequence_to_file { 
   my ( $self, $slice_name  ) = @_ ; 

     my @array = split(/:/,$slice_name);

     if(@array != 6) {
       throw("Malformed slice name [$slice_name].  Format is " .
          "coord_system:version:seq_region:start:end:strand");
     } 
   
     my ($cs_name, $cs_version, $seq_region, $start, $end, $strand) = @array;
     # we want to give exonerate a bit more genomic seq 
     if($start > $end){
       my $tmp_start = $end;
       $end = $start;
       $start = $tmp_start;
     }
     print STDERR "Have coordiantes :  ".$start." ".$end." \n";
     
     # sequence_padding
     my $new_start  = $start - 5000 ; 
     my $new_end    = $end   + 5000 ;
   
     if($new_start < 1){
       $new_start = 1;
     } 

     my $sliceadp = $self->db->get_SliceAdaptor(); 

     my $slice = $sliceadp->fetch_by_region($cs_name,$seq_region, $new_start,$new_end, $strand, $cs_version); 

     $self->slice($slice) ; 
 
     if($slice->end() > $slice->seq_region_length) {
       #refetch slice, since we went past end, second call is fast
       $new_end = $slice->seq_region_length();
       $slice = $sliceadp->fetch_by_region($cs_name, $seq_region,
                                           $new_start, $new_end,
                                           $strand, $cs_version);
     }
   
      print STDERR "Have ".$slice->name." sequence to run\n";
      $self->genomic($slice);  

      # my $seq = $slice->get_repeatmasked_seq(undef,1) ;  
      # make target(genomic) and query(protein) tmp sequencefiles
      my $genfile      = create_file_name("genomic" ,"fa" , "/tmp" );    
      #write_seqfile($seq, $genfile, 'fasta') ;

      my $seq = $slice->seq(); 
      (my $str= $seq) =~ s/(.{1,60})/$1\n/g;
      $str = ">genomic_seq_header\n$str" ;  
      open(FH, ">$genfile") ;
       print FH $str;
      close(FH) ;
  
      #write_seqfile($seqio, $genfile, 'fasta') ;

      $self->genomic_file ( $genfile ) ; 
}


# building  

sub build_hash_of_recoverd_introns_per_transcript {  
  my ($self ) = @_ ;  

  my @simple_feature_index ; 
  if ($self->simple_feature_index=~m/\_/ ) { 
    @simple_feature_index = split /\_/, $self->simple_feature_index ;   
  } else { 
   push  @simple_feature_index , $self->simple_feature_index ;  
  }


  # to save some compute time we only want 2 transcripts used which revoer the same intron  
  my %recov_simple_feat_to_transcript ; 

  my @simple_feature_ids = @{$self->simple_feature_db_id};
  my @stable_ids_of_homolog_transcripts = @{$self->homolog_transcript_sid()} ;  

  my %enst_to_simple_features;

  my $sfa = $self->db->get_SimpleFeatureAdaptor() ;     

  for ( my $i =0 ; $i <@simple_feature_index ; $i++ ) {   
    # print "\n\nSTABLE_ID : " . $stable_ids_of_homolog_transcripts[$i] . ":" ;  
     my $str = $simple_feature_index[$i] ; 
     my @indexes = split /\,/, $str ; 
     for my $s_index ( @indexes ) {    
       #print "s_index : $s_index " ;  
       #print " $s_index " ;  
       #print "simple_feature_id : " . $simple_feature_ids[$s_index] . "\n"   
       #
       push @{$recov_simple_feat_to_transcript{$str}},  $stable_ids_of_homolog_transcripts[$i]; 
     
       my $sf = $sfa->fetch_by_dbID($simple_feature_ids[$s_index]) ; 
  
       push @{$enst_to_simple_features{ $stable_ids_of_homolog_transcripts[$i]}} , $sf ; 
       unless (  $simple_feature_ids[$s_index] ) {  
         throw("something is wrong with your simple_feature-indexes - the simple feature with index $s_index does not exist\n") ; 
       }  
       unless (  $sf ) { 
         throw("Simple feature with dbID :  $simple_feature_ids[$s_index] not found in simple_feature table of database : " .  
         $sfa->db->dbname . "\@" . $sfa->db->host . "\n" ) ; 
       }

     }  
  }    


  for ( keys %recov_simple_feat_to_transcript ) {   
      my %species_processed ; 
      my %tmp ; 
      my @selected_id_for_species ; 
      @tmp{@{$recov_simple_feat_to_transcript{$_}}} = 1 ;  
      
      for my $stable_id ( keys %tmp ) {   
        my $species = substr($stable_id,0,4); 
        unless (exists $species_processed{$species} ) {   
          push @selected_id_for_species, $stable_id ;  
        }
        $species_processed{$species} =1 ; 
      } 
      #$recov_simple_feat_to_transcript{$_}=[keys %tmp] ; 
      $recov_simple_feat_to_transcript{$_}=\@selected_id_for_species ;  
      print "pushing $_ " . join ( "\t", @selected_id_for_species ) . "\n"; 
  }  

  my @stable_ids_to_process ; 
  for my $id ( keys %recov_simple_feat_to_transcript ) {      
    my @tmp = @{$recov_simple_feat_to_transcript{$id}};  
    for ( @tmp ) { 
       push @stable_ids_to_process, $_ ;  
    }
  } 
  if ( $self->lightweight_analysis ) {  
    print "\n\nWarning : Using lightweight analysis and only 1 protein per species per recovery-case\n\n" ; 
    $self->homolog_transcript_sid(\@stable_ids_to_process);
  }   

 
  if ( $self->debug ) {  
    print "\n\nProcessing these ids :\n\n" ;  
    for ( keys %recov_simple_feat_to_transcript ) {   
       print "$_  " ; 
       for ( @{$recov_simple_feat_to_transcript{$_}}  ) { 
         print "$_  " ; 
       } 
       print "\n" ; 
    }
  }
  return \%enst_to_simple_features ;
}  

sub set_homolog_transcript {  
   my ( $self,  $trans ) = @_ ; 
   if ( $trans) {  
      ${$self->{hom_trans_cache}}{$trans->stable_id}= $trans ; 
   }
   return $self->{hom_trans_cache};    
} 

sub get_homolog_transcript_by_stable_id {  
   my ( $self,  $trans_stable_id ) = @_ ;  
   return ${$self->{hom_trans_cache}}{$trans_stable_id}; 
} 



sub sf_to_gene {  
   my ( $self,  $hseq_name, $orth_trans ) = @_ ;  

   
   if ( $hseq_name && $orth_trans ) {     
       # avoid to store transcripts twice 
       if ( exists ${$self->{sf_to_hom_trans_cache}}{$hseq_name} ) {    
          
          # hash-slice check if we've already stored the hseq-to-transcript relation 
          #      $xx{$hseq} = [ tr1 tr2 tr3 ]   
          my %tmp  ; 
          my @transcripts_stored =  @{${$self->{sf_to_hom_trans_cache}{$hseq_name}}} ; 
          @tmp{@transcripts_stored} = 1;    
          # now we got all transcript refs as keys 
          
          if ( exists $tmp{$orth_trans} ) {  
            # transcript already stored for this supporting feature 
          } else { 
            
           push @{ ${ $self->{sf_to_hom_trans_cache}{$hseq_name}}}, $orth_trans ; 
          } 
       } else {   
          # we got no entry for this hseq_name so let's create one 
           push @{ ${ $self->{sf_to_hom_trans_cache}{$hseq_name}}}, $orth_trans ; 
       } 
   } elsif ( $hseq_name ) { 
     # only $hseq_name is given so we return the transcripts associated to this supporting feature   
     return \@{${$self->{sf_to_hom_trans_cache}{$hseq_name}}} ; 
   } 
} 


use vars '$AUTOLOAD';
sub AUTOLOAD {
 my ($self,$val) = @_;
 (my $routine_name=$AUTOLOAD)=~s/.*:://; #trim package name 
 $self->{$routine_name}=$val if defined $val ; 
 return $self->{$routine_name} ;
}
sub DESTROY {} # required due to AUTOLOAD
1; 

