diff variant_effect_predictor/Bio/EnsEMBL/Transcript.pm @ 0:2bc9b66ada89 draft default tip

Uploaded
author mahtabm
date Thu, 11 Apr 2013 06:29:17 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/variant_effect_predictor/Bio/EnsEMBL/Transcript.pm	Thu Apr 11 06:29:17 2013 -0400
@@ -0,0 +1,2993 @@
+=head1 LICENSE
+
+  Copyright (c) 1999-2012 The European Bioinformatics Institute and
+  Genome Research Limited.  All rights reserved.
+
+  This software is distributed under a modified Apache license.
+  For license details, please see
+
+    http://www.ensembl.org/info/about/code_licence.html
+
+=head1 CONTACT
+
+  Please email comments or questions to the public Ensembl
+  developers list at <dev@ensembl.org>.
+
+  Questions may also be sent to the Ensembl help desk at
+  <helpdesk@ensembl.org>.
+
+=cut
+
+=head1 NAME
+
+Bio::EnsEMBL::Transcript - object representing an Ensembl transcript
+
+=head1 SYNOPSIS
+
+Creation:
+
+  my $tran = new Bio::EnsEMBL::Transcript();
+  my $tran = new Bio::EnsEMBL::Transcript( -EXONS => \@exons );
+
+Manipulation:
+
+  # Returns an array of Exon objects
+  my @exons = @{ $tran->get_all_Exons() };
+
+  # Returns the peptide translation of the exons as a Bio::Seq
+  if ( $tran->translation() ) {
+    my $pep = $tran->translate();
+  } else {
+    print "Transcript ", $tran->stable_id(), " is non-coding\n";
+  }
+
+=head1 DESCRIPTION
+
+A representation of a transcript within the Ensembl system.  A transcript
+consists of a set of Exons and (possibly) a Translation which defines the
+coding and non-coding regions of the exons.
+
+=cut
+
+package Bio::EnsEMBL::Transcript;
+
+use strict;
+
+use Bio::EnsEMBL::Feature;
+use Bio::EnsEMBL::Intron;
+use Bio::EnsEMBL::TranscriptMapper;
+use Bio::EnsEMBL::Utils::TranscriptSNPs;
+use Bio::EnsEMBL::SeqEdit;
+
+use Bio::EnsEMBL::Utils::Argument qw( rearrange );
+use Bio::EnsEMBL::Utils::Exception qw( deprecate warning throw );
+use Bio::EnsEMBL::Utils::Scalar qw( assert_ref );
+
+use vars qw(@ISA);
+@ISA = qw(Bio::EnsEMBL::Feature);
+
+
+=head2 new
+
+  Arg [-EXONS] :
+        reference to list of Bio::EnsEMBL::Exon objects - exons which make up 
+        this transcript
+  Arg [-STABLE_ID] :
+        string - the stable identifier of this transcript
+  Arg [-VERSION] :
+        int - the version of the stable identifier of this transcript
+  Arg [-EXTERNAL_NAME] :
+        string - the external database name associated with this transcript
+  Arg [-EXTERNAL_DB] :
+        string - the name of the database the external name is from
+  Arg [-EXTERNAL_STATUS]:
+        string - the status of the external identifier
+  Arg [-DISPLAY_XREF]:
+        Bio::EnsEMBL::DBEntry - The external database entry that is used
+        to label this transcript when it is displayed.
+  Arg [-CREATED_DATE]:
+        string - the date the transcript was created
+  Arg [-MODIFIED_DATE]:
+        string - the date the transcript was last modified
+  Arg [-DESCRIPTION]:
+        string - the transcipts description
+  Arg [-BIOTYPE]: 
+        string - the biotype e.g. "protein_coding"
+  Arg [-STATUS]:
+        string - the transcripts status i.e. "KNOWN","NOVEL"
+  Arg [-IS_CURRENT]:
+        Boolean - specifies if this is the current version of the transcript
+  Example    : $tran = new Bio::EnsEMBL::Transcript(-EXONS => \@exons);
+  Description: Constructor. Instantiates a Transcript object.
+  Returntype : Bio::EnsEMBL::Transcript
+  Exceptions : throw on bad arguments
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub new {
+  my $proto = shift;
+
+  my $class = ref($proto) || $proto;
+
+  my $self = $class->SUPER::new(@_);
+
+  my (
+    $exons,            $stable_id,    $version,
+    $external_name,    $external_db,  $external_status,
+    $display_xref,     $created_date, $modified_date,
+    $description,      $biotype,      $confidence,
+    $external_db_name, $status,       $is_current
+  );
+
+  # Catch for old style constructor calling:
+  if ( ( @_ > 0 ) && ref( $_[0] ) ) {
+    $exons = [@_];
+    deprecate( "Transcript constructor should use named arguments.\n"
+        . "Use Bio::EnsEMBL::Transcript->new(-EXONS => \@exons);\n"
+        . "instead of Bio::EnsEMBL::Transcript->new(\@exons);" );
+  } else {
+    (
+      $exons,            $stable_id,    $version,
+      $external_name,    $external_db,  $external_status,
+      $display_xref,     $created_date, $modified_date,
+      $description,      $biotype,      $confidence,
+      $external_db_name, $status,       $is_current
+      )
+      = rearrange( [
+        'EXONS',            'STABLE_ID',
+        'VERSION',          'EXTERNAL_NAME',
+        'EXTERNAL_DB',      'EXTERNAL_STATUS',
+        'DISPLAY_XREF',     'CREATED_DATE',
+        'MODIFIED_DATE',    'DESCRIPTION',
+        'BIOTYPE',          'CONFIDENCE',
+        'EXTERNAL_DB_NAME', 'STATUS',
+        'IS_CURRENT'
+      ],
+      @_
+      );
+  }
+
+  if ($exons) {
+    $self->{'_trans_exon_array'} = $exons;
+    $self->recalculate_coordinates();
+  }
+
+  $self->stable_id($stable_id);
+  $self->version($version);
+  $self->{'created_date'}  = $created_date;
+  $self->{'modified_date'} = $modified_date;
+  $self->external_name($external_name) if ( defined $external_name );
+  $self->external_db($external_db)     if ( defined $external_db );
+  $self->external_status($external_status)
+    if ( defined $external_status );
+  $self->display_xref($display_xref) if ( defined $display_xref );
+  $self->edits_enabled(1);
+
+  $self->description($description);
+  $self->status($confidence);    # old style name
+  $self->status($status);        # new style name
+  $self->biotype($biotype);
+
+  # default is_current
+  $is_current = 1 unless ( defined($is_current) );
+  $self->{'is_current'} = $is_current;
+
+  return $self;
+} ## end sub new
+
+=head2 get_all_DBLinks
+
+  Arg [1]    : String database name (optional)
+               SQL wildcard characters (_ and %) can be used to
+               specify patterns.
+
+  Example    : my @dblinks = @{ $transcript->get_all_DBLinks() };
+               my @dblinks = @{ $transcript->get_all_DBLinks('Uniprot%') };
+
+  Description: Retrieves *all* related DBEntries for this
+               transcript.  This includes all DBEntries that are
+               associated with the corresponding translation.
+
+               If you only want to retrieve the DBEntries associated
+               with the transcript (and not the translation) then
+               you should use the get_all_DBEntries() call instead.
+
+               Note: Each entry may be listed more than once.  No
+               uniqueness checks are done.  Also if you put in an
+               incorrect external database name no checks are done
+               to see if this exists, you will just get an empty
+               list.
+
+  Return type: Listref of Bio::EnsEMBL::DBEntry objects
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub get_all_DBLinks {
+  my ( $self, $db_name_exp, $ex_db_type ) = @_;
+
+  my @links =
+    @{ $self->get_all_DBEntries( $db_name_exp, $ex_db_type ) };
+
+  # Add all of the transcript and translation xrefs to the return list.
+  my $translation = $self->translation();
+  if ( defined($translation) ) {
+    push( @links,
+          @{$translation->get_all_DBEntries( $db_name_exp, $ex_db_type ) }
+    );
+  }
+
+  @links = sort { _compare_xrefs() } @links;
+
+  return \@links;
+}
+
+=head2 get_all_xrefs
+
+  Arg [1]    : String database name (optional)
+               SQL wildcard characters (_ and %) can be used to
+               specify patterns.
+
+  Example    : @xrefs = @{ $transcript->get_all_xrefs() };
+               @xrefs = @{ $transcript->get_all_xrefs('Uniprot%') };
+
+  Description: Retrieves *all* related xrefs for this transcript.
+               This includes all xrefs that are associated with the
+               corresponding translation of this transcript.
+
+               If you want to retrieve the xrefs associated with
+               only the transcript (and not the translation) then
+               you should use the get_all_object_xrefs() method
+               instead.
+
+               Note: Each entry may be listed more than once.  No
+               uniqueness checks are done.  Also if you put in an
+               incorrect external database name no checks are done
+               to see if this exists, you will just get an empty
+               list.
+
+                NB: This method is an alias for the
+                    get_all_DBLinks() method.
+
+  Return type: Listref of Bio::EnsEMBL::DBEntry objects
+
+  Status     : Stable
+
+=cut
+
+sub get_all_xrefs {
+  my $self = shift;
+  return $self->get_all_DBLinks(@_);
+}
+
+=head2 get_all_DBEntries
+
+  Arg [1]    : (optional) String, external database name
+
+  Arg [2]    : (optional) String, external database type
+
+  Example    : my @dbentries = @{ $transcript->get_all_DBEntries() };
+
+  Description: Retrieves DBEntries (xrefs) for this transcript.
+               This does *not* include the corresponding
+               translations DBEntries (see get_all_DBLinks()).
+
+               This method will attempt to lazy-load DBEntries
+               from a database if an adaptor is available and no
+               DBEntries are present on the transcript (i.e. they
+               have not already been added or loaded).
+
+  Returntype : Listref of Bio::EnsEMBL::DBEntry objects
+  Exceptions : none
+  Caller     : get_all_DBLinks, TranscriptAdaptor::store
+  Status     : Stable
+
+=cut
+
+sub get_all_DBEntries {
+  my ( $self, $ex_db_exp, $ex_db_type ) = @_;
+
+  my $cache_name = 'dbentries';
+
+  if ( defined($ex_db_exp) ) {
+    $cache_name .= $ex_db_exp;
+  }
+
+  if ( defined($ex_db_type) ) {
+    $cache_name .= $ex_db_type;
+  }
+
+  # if not cached, retrieve all of the xrefs for this transcript
+  if ( !defined( $self->{$cache_name} ) && defined( $self->adaptor() ) )
+  {
+    $self->{$cache_name} =
+      $self->adaptor()->db()->get_DBEntryAdaptor()
+      ->fetch_all_by_Transcript( $self, $ex_db_exp, $ex_db_type );
+  }
+
+  $self->{$cache_name} ||= [];
+
+  return $self->{$cache_name};
+} ## end sub get_all_DBEntries
+
+=head2 get_all_object_xrefs
+
+  Arg [1]    : (optional) String, external database name
+
+  Arg [2]    : (optional) String, external_db type
+
+  Example    : @oxrefs = @{ $transcript->get_all_object_xrefs() };
+
+  Description: Retrieves xrefs for this transcript.  This does
+               *not* include xrefs that are associated with the
+               corresponding translations of this transcript (see
+               get_all_xrefs()).
+
+               This method will attempt to lazy-load xrefs from a
+               database if an adaptor is available and no xrefs are
+               present on the transcript (i.e. they have not already
+               been added or loaded).
+
+                NB: This method is an alias for the
+                    get_all_DBentries() method.
+
+  Return type: Listref of Bio::EnsEMBL::DBEntry objects
+
+  Status     : Stable
+
+=cut
+
+sub get_all_object_xrefs {
+  my $self = shift;
+  return $self->get_all_DBEntries(@_);
+}
+
+=head2 add_DBEntry
+
+  Arg [1]    : Bio::EnsEMBL::DBEntry $dbe
+               The dbEntry to be added
+  Example    : my $dbe = Bio::EnsEMBL::DBEntery->new(...);
+               $transcript->add_DBEntry($dbe);
+  Description: Associates a DBEntry with this transcript. Note that adding
+               DBEntries will prevent future lazy-loading of DBEntries for this
+               gene (see get_all_DBEntries).
+  Returntype : none
+  Exceptions : thrown on incorrect argument type
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub add_DBEntry {
+  my $self = shift;
+  my $dbe = shift;
+
+  unless($dbe && ref($dbe) && $dbe->isa('Bio::EnsEMBL::DBEntry')) {
+    throw('Expected DBEntry argument');
+  }
+
+  $self->{'dbentries'} ||= [];
+  push @{$self->{'dbentries'}}, $dbe;
+}
+
+
+=head2 get_all_supporting_features
+
+  Example    : my @evidence = @{ $transcript->get_all_supporting_features };
+  Description: Retreives any supporting features added manually by 
+               calls to add_supporting_features.
+  Returntype : Listref of Bio::EnsEMBL::FeaturePair objects
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub get_all_supporting_features {
+  my $self = shift;
+
+  if( !exists  $self->{_supporting_evidence} )  {
+    if($self->adaptor) {
+      my $tsfa = $self->adaptor->db->get_TranscriptSupportingFeatureAdaptor();
+      $self->{_supporting_evidence} = $tsfa->fetch_all_by_Transcript($self);
+    }
+  }
+  
+  return $self->{_supporting_evidence} || [];
+}
+
+
+=head2 add_supporting_features
+
+  Arg [1-N]  : Bio::EnsEMBL::FeaturePair $feature
+               The supporting features to add
+  Example    : $transcript->add_supporting_features(@features);
+  Description: Adds a list of supporting features to this Transcript.
+               The added features can be retieved by
+               get_all_supporting_features().
+  Returntype : none
+  Exceptions : throw if any of the features are not FeaturePairs
+               throw if any of the features are not in the same coordinate
+               system as the Transcript
+  Caller     : general
+  Status     : Stable
+ 
+=cut
+ 
+sub add_supporting_features {
+  my ($self, @features) = @_;
+
+  return unless @features;
+ 
+  $self->{_supporting_evidence} ||= [];
+  
+  # check whether this feature object has been added already
+  FEATURE: foreach my $feature (@features) {
+
+    if (!defined($feature) || ref($feature) eq "ARRAY") {
+      throw("Element in transcript supporting features array is undefined or is an ARRAY for " . $self->dbID);
+    }
+    if (!$feature || !$feature->isa("Bio::EnsEMBL::FeaturePair")) {
+      print "feature = " . $feature . "\n";
+      throw("Supporting feat [$feature] not a " .
+            "Bio::EnsEMBL::FeaturePair");
+    } 
+    
+    if ((defined $self->slice() && defined $feature->slice())&&
+      ( $self->slice()->name() ne $feature->slice()->name())){
+      throw("Supporting feat not in same coord system as exon\n" .
+            "exon is attached to [".$self->slice()->name()."]\n" .
+            "feat is attached to [".$feature->slice()->name()."]");
+    }
+
+    foreach my $added_feature ( @{ $self->{_supporting_evidence} } ){
+      # compare objects
+      if ( $feature == $added_feature ){
+  #this feature has already been added
+  next FEATURE;
+      }
+    }
+    
+    #no duplicate was found, add the feature
+    push(@{$self->{_supporting_evidence}}, $feature);
+  }
+}
+
+
+=head2 flush_supporting_features
+
+  Example     : $transcript->flush_supporting_features;
+  Description : Removes all supporting evidence from the transcript.
+  Return type : (Empty) listref
+  Exceptions  : none
+  Caller      : general
+  Status      : Stable
+
+=cut
+
+sub flush_supporting_features {
+  my $self = shift;
+  $self->{'_supporting_evidence'} = [];
+}
+
+
+=head2 external_db
+
+  Arg [1]    : (optional) String - name of external db to set
+  Example    : $transcript->external_db('HGNC');
+  Description: Getter/setter for attribute external_db. The db is the one that 
+               belongs to the external_name.  
+  Returntype : String
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub external_db {
+  my ( $self, $ext_dbname ) = @_;
+
+  if(defined $ext_dbname) { 
+    return ( $self->{'external_db'} = $ext_dbname );
+  }
+
+  if( exists $self->{'external_db'} ) {
+    return $self->{'external_db'};
+  }
+
+  my $display_xref = $self->display_xref();
+
+  if( defined $display_xref ) {
+    return $display_xref->dbname()
+  } else {
+    return undef;
+  }
+}
+
+
+=head2 external_status
+
+  Arg [1]    : (optional) String - status of the external db
+  Example    : $transcript->external_status('KNOWNXREF');
+  Description: Getter/setter for attribute external_status. The status of
+               the external db of the one that belongs to the external_name.
+  Returntype : String
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub external_status { 
+  my ( $self, $ext_status ) = @_;
+
+  if(defined $ext_status) {
+    return ( $self->{'external_status'} = $ext_status );
+  }
+
+  if( exists $self->{'external_status'} ) {
+    return $self->{'external_status'};
+  }
+
+  my $display_xref = $self->display_xref();
+
+  if( defined $display_xref ) {
+    return $display_xref->status()
+  } else {
+    return undef;
+  }
+}
+
+
+=head2 external_name
+
+  Arg [1]    : (optional) String - the external name to set
+  Example    : $transcript->external_name('BRCA2-001');
+  Description: Getter/setter for attribute external_name.
+  Returntype : String or undef
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub external_name {
+  my ($self, $ext_name) = @_;
+
+  if(defined $ext_name) { 
+    return ( $self->{'external_name'} = $ext_name );
+  }
+
+  if( exists $self->{'external_name'} ) {
+    return $self->{'external_name'};
+  }
+
+  my $display_xref = $self->display_xref();
+
+  if( defined $display_xref ) {
+    return $display_xref->display_id()
+  } else {
+    return undef;
+  }
+}
+
+
+=head2 is_known
+
+  Example    : print "Transcript ".$transcript->stable_id." is KNOWN\n" if
+                  $transcript->is_known;
+  Description: Returns TRUE if this gene has a status of 'KNOWN'
+  Returntype : TRUE if known, FALSE otherwise
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub is_known {
+  my $self = shift;
+  return ( $self->{'status'} eq "KNOWN" || $self->{'status'} eq "KNOWN_BY_PROJECTION" );
+}
+
+
+=head2 status
+
+  Arg [1]    : string $status
+  Example    : none
+  Description: get/set for attribute status
+  Returntype : string
+  Exceptions : none
+  Caller     : general
+  Status     : Medium Risk
+
+=cut
+
+sub status {
+   my $self = shift;
+  $self->{'status'} = shift if( @_ );
+  return $self->{'status'};
+}
+
+=head2 biotype
+
+  Arg [1]    : string $biotype
+  Example    : none
+  Description: get/set for attribute biotype
+  Returntype : string
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub biotype {
+   my $self = shift;
+  $self->{'biotype'} = shift if( @_ );
+  return ( $self->{'biotype'} || "protein_coding" );
+}
+
+
+=head2 display_xref
+
+  Arg [1]    : (optional) Bio::EnsEMBL::DBEntry - the display xref to set
+  Example    : $transcript->display_xref($db_entry);
+  Description: Getter/setter for display_xref for this transcript.
+  Returntype : Bio::EnsEMBL::DBEntry
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub display_xref {
+  my $self = shift;
+  $self->{'display_xref'} = shift if(@_);
+  return $self->{'display_xref'};
+}
+
+=head2 is_canonical
+
+  Args [1]      : (optional) Boolean is_canonical
+
+  Example       : if ($transcript->is_canonical()) { ... }
+
+  Description : Returns true (non-zero) if the transcript is the
+                canonical transcript of its gene, false (0) if not. If the code
+                returns an undefined it is because its state is not currently
+                known. Internally the code will consult the database for this
+                value if it is unknown and the transcript has a dbID and an
+                attached adaptor
+
+  Return type   : Boolean
+
+  Status        : Stable
+
+=cut
+
+sub is_canonical {
+  my ( $self, $value ) = @_;
+  
+  #Shortcut call
+  return $self->{is_canonical} if defined $self->{is_canonical};
+  
+  if ( defined($value) ) {
+    $self->{is_canonical} = ( $value ? 1 : 0 );
+  }
+  else {
+    if(! defined $self->{is_canonical} && $self->dbID() && $self->adaptor()) {
+      $self->{is_canonical} = $self->adaptor()->is_Transcript_canonical($self);
+    }
+  }
+
+  return $self->{is_canonical};
+}
+
+=head2 translation
+
+  Args       : None
+  Example    : if ( $transcript->translation() ) {
+                 print( $transcript->translation()->stable_id(), "\n" );
+               } else {
+                 print("Pseudogene\n");
+               }
+  Description: Getter/setter for the Translation object which
+               defines the CDS (and as a result the peptide encoded
+               by) this transcript.  This function will return
+               undef if this transcript is a pseudogene, i.e. a
+               non-translating transcript such as an ncRNA.  This
+               is the accepted method of determining whether a
+               transcript is a pseudogene or not.
+  Returntype : Bio::EnsEMBL::Translation
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub translation {
+  my ( $self, $translation ) = @_;
+
+  if ( defined($translation) ) {
+    assert_ref( $translation, 'Bio::EnsEMBL::Translation' );
+
+    $self->{'translation'} = $translation;
+    $translation->transcript($self);
+
+    $self->{'cdna_coding_start'} = undef;
+    $self->{'cdna_coding_end'}   = undef;
+
+    $self->{'coding_region_start'} = undef;
+    $self->{'coding_region_end'}   = undef;
+
+    $self->{'transcript_mapper'} = undef;
+
+  } elsif ( @_ > 1 ) {
+    if ( defined( $self->{'translation'} ) ) {
+      # Removing existing translation
+
+      $self->{'translation'}->transcript(undef);
+      delete( $self->{'translation'} );
+
+      $self->{'cdna_coding_start'} = undef;
+      $self->{'cdna_coding_end'}   = undef;
+
+      $self->{'coding_region_start'} = undef;
+      $self->{'coding_region_end'}   = undef;
+
+      $self->{'transcript_mapper'} = undef;
+    }
+  } elsif (   !exists( $self->{'translation'} )
+            && defined( $self->adaptor() ) )
+  {
+    $self->{'translation'} =
+      $self->adaptor()->db()->get_TranslationAdaptor()
+      ->fetch_by_Transcript($self);
+  }
+
+  return $self->{'translation'};
+} ## end sub translation
+
+=head2 get_all_alternative_translations
+
+  Args       : None
+  Example    :
+
+    my @alt_translations =
+      @{ $transcript->get_all_alternative_translations() };
+
+  Description:  Fetches all alternative translations defined for this
+                transcript.  The canonical translation is not returned.
+
+  Returntype : Arrayref to Bio::EnsEMBL::Translation
+  Exceptions : None
+  Caller     : General
+  Status     : Stable
+
+=cut
+
+sub get_all_alternative_translations {
+  my ($self) = @_;
+
+  if (   !exists( $self->{'alternative_translations'} )
+       && defined( $self->adaptor() ) )
+  {
+    my $pa = $self->adaptor()->db()->get_TranslationAdaptor();
+    my @translations =
+      @{ $pa->fetch_all_alternative_by_Transcript($self) };
+
+    $self->{'alternative_translations'} = \@translations;
+  }
+
+  return $self->{'alternative_translations'};
+}
+
+=head2 add_alternative_translation
+
+  Args       : Bio::EnsEMBL::Translation $translation
+  Example    :
+
+    $transcript->add_alternative_translation($translation);
+
+  Description: Adds an alternative translation to this transcript.
+  Returntype : None
+  Exceptions : None
+  Caller     : General
+  Status     : Stable
+
+=cut
+
+sub add_alternative_translation {
+  my ( $self, $translation ) = @_;
+
+  if ( !(    defined($translation)
+          && ref($translation)
+          && $translation->isa('Bio::EnsEMBL::Translation') ) )
+  {
+    throw("Bio::EnsEMBL::Translation argument expected.");
+  }
+
+  # Load the existsing alternative translations from the database if
+  # they haven't already been loaded.
+  $self->get_all_alternative_translations();
+
+  push( @{ $self->{'alternative_translations'} }, $translation );
+}
+
+=head2 spliced_seq
+
+  Args       : none
+  Example    : none
+  Description: Retrieves all Exon sequences and concats them together.
+               No phase padding magic is done, even if phases do not align.
+  Returntype : Text
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub spliced_seq {
+  my ( $self ) = @_;
+
+  my $seq_string = "";
+  for my $ex ( @{$self->get_all_Exons()} ) {
+    my $seq = $ex->seq();
+
+    if(!$seq) {
+      warning("Could not obtain seq for exon.  Transcript sequence may not " .
+              "be correct.");
+      $seq_string .= 'N' x $ex->length();
+    } else {
+      $seq_string .= $seq->seq();
+    }
+  }
+
+  # apply post transcriptional edits
+  if($self->edits_enabled()) {
+    my @seqeds = @{$self->get_all_SeqEdits()};
+
+    # sort edits in reverse order to remove complication of
+    # adjusting downstream edits
+    @seqeds = sort {$b->start() <=> $a->start()} @seqeds;
+
+    foreach my $se (@seqeds) {
+      $se->apply_edit(\$seq_string);
+    }
+  }
+
+  return $seq_string;
+}
+
+
+=head2 translateable_seq
+
+  Args       : none
+  Example    : print $transcript->translateable_seq(), "\n";
+  Description: Returns a sequence string which is the the translateable part
+               of the transcripts sequence.  This is formed by splicing all
+               Exon sequences together and apply all defined RNA edits.
+               Then the coding part of the sequence is extracted and returned.
+               The code will not support monkey exons any more. If you want to
+               have non phase matching exons, defined appropriate _rna_edit
+               attributes!
+
+               An empty string is returned if this transcript is a pseudogene
+               (i.e. is non-translateable).
+  Returntype : Text
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub translateable_seq {
+  my ( $self ) = @_;
+
+  if ( !$self->translation() ) {
+    return '';
+  }
+
+  my $mrna = $self->spliced_seq();
+
+  my $start = $self->cdna_coding_start();
+  my $end   = $self->cdna_coding_end();
+
+  $mrna = substr( $mrna, $start - 1, $end - $start + 1 );
+
+  my $start_phase = $self->translation->start_Exon->phase();
+  if( $start_phase > 0 ) {
+    $mrna = "N"x$start_phase . $mrna;
+  }
+  if( ! $start || ! $end ) {
+    return "";
+  }
+
+  return $mrna;
+}
+
+
+=head2 cdna_coding_start
+
+  Arg [1]    : (optional) $value
+  Example    : $relative_coding_start = $transcript->cdna_coding_start;
+  Description: Retrieves the position of the coding start of this transcript
+               in cdna coordinates (relative to the start of the 5prime end of
+               the transcript, excluding introns, including utrs).
+
+               This will return undef if this is a pseudogene (i.e. a
+               transcript with no translation).
+  Returntype : int
+  Exceptions : none
+  Caller     : five_prime_utr, get_all_snps, general
+  Status     : Stable
+
+=cut
+
+sub cdna_coding_start {
+  my $self = shift;
+
+  if( @_ ) {
+    $self->{'cdna_coding_start'} = shift;
+  }
+
+  if(!defined $self->{'cdna_coding_start'} && defined $self->translation){
+    # calc coding start relative from the start of translation (in cdna coords)
+    my $start = 0;
+
+    my @exons = @{$self->get_all_Exons};
+    my $exon;
+
+    while($exon = shift @exons) {
+      if($exon == $self->translation->start_Exon) {
+        #add the utr portion of the start exon
+        $start += $self->translation->start;
+        last;
+      } else {
+        #add the entire length of this non-coding exon
+        $start += $exon->length;
+      }
+    }
+
+    # adjust cdna coords if sequence edits are enabled
+    if($self->edits_enabled()) {
+      my @seqeds = @{$self->get_all_SeqEdits()};
+      # sort in reverse order to avoid adjustment of downstream edits
+      @seqeds = sort {$b->start() <=> $a->start()} @seqeds;
+
+      foreach my $se (@seqeds) {
+        # use less than start so that start of CDS can be extended
+        if($se->start() < $start) {
+          $start += $se->length_diff();
+        }
+      }
+    }
+
+    $self->{'cdna_coding_start'} = $start;
+  }
+
+  return $self->{'cdna_coding_start'};
+}
+
+
+=head2 cdna_coding_end
+
+  Arg [1]    : (optional) $value
+  Example    : $cdna_coding_end = $transcript->cdna_coding_end;
+  Description: Retrieves the end of the coding region of this transcript in
+               cdna coordinates (relative to the five prime end of the
+               transcript, excluding introns, including utrs).
+
+               This will return undef if this transcript is a pseudogene
+               (i.e. a transcript with no translation and therefor no CDS).
+  Returntype : int
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub cdna_coding_end {
+  my $self = shift;
+
+  if( @_ ) {
+    $self->{'cdna_coding_end'} = shift;
+  }
+
+  if(!defined $self->{'cdna_coding_end'} && defined $self->translation) {
+    my @exons = @{$self->get_all_Exons};
+
+    my $end = 0;
+    while(my $exon = shift @exons) {
+      if($exon == $self->translation->end_Exon) {
+        # add coding portion of the final coding exon
+        $end += $self->translation->end;
+        last;
+      } else {
+        # add entire exon
+        $end += $exon->length;
+      }
+    }
+
+    # adjust cdna coords if sequence edits are enabled
+    if($self->edits_enabled()) {
+      my @seqeds = @{$self->get_all_SeqEdits()};
+      # sort in reverse order to avoid adjustment of downstream edits
+      @seqeds = sort {$b->start() <=> $a->start()} @seqeds;
+
+      foreach my $se (@seqeds) {
+        # use less than or equal to end+1 so end of the CDS can be extended
+        if($se->start() <= $end + 1) {
+          $end += $se->length_diff();
+        }
+      }
+    }
+
+    $self->{'cdna_coding_end'} = $end;
+  }
+
+  return $self->{'cdna_coding_end'};
+}
+
+
+=head2 coding_region_start
+
+  Arg [1]    : (optional) $value
+  Example    : $coding_region_start = $transcript->coding_region_start
+  Description: Retrieves the start of the coding region of this transcript
+               in genomic coordinates (i.e. in either slice or contig coords).
+               By convention, the coding_region_start is always lower than
+               the value returned by the coding_end method.
+               The value returned by this function is NOT the biological
+               coding start since on the reverse strand the biological coding
+               start would be the higher genomic value.
+
+               This function will return undef if this is a pseudogene
+               (a non-translated transcript).
+  Returntype : int
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub coding_region_start {
+  my ($self, $value) = @_;
+
+  if( defined $value ) {
+    $self->{'coding_region_start'} = $value;
+  } elsif(!defined $self->{'coding_region_start'} &&
+    defined $self->translation) {
+    #calculate the coding start from the translation
+    my $start;
+    my $strand = $self->translation()->start_Exon->strand();
+    if( $strand == 1 ) {
+      $start = $self->translation()->start_Exon->start();
+      $start += ( $self->translation()->start() - 1 );
+    } else {
+      $start = $self->translation()->end_Exon->end();
+      $start -= ( $self->translation()->end() - 1 );
+    }
+    $self->{'coding_region_start'} = $start;
+  }
+
+  return $self->{'coding_region_start'};
+}
+
+
+=head2 coding_region_end
+
+  Arg [1]    : (optional) $value
+  Example    : $coding_region_end = $transcript->coding_region_end
+  Description: Retrieves the end of the coding region of this transcript
+               in genomic coordinates (i.e. in either slice or contig coords).
+               By convention, the coding_region_end is always higher than the
+               value returned by the coding_region_start method.
+               The value returned by this function is NOT the biological
+               coding end since on the reverse strand the biological coding
+               end would be the lower genomic value.
+
+               This function will return undef if this is a pseudogene
+               (a non-translated transcript).
+  Returntype : int
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub coding_region_end {
+  my ($self, $value ) = @_;
+
+  my $strand;
+  my $end;
+
+  if( defined $value ) {
+    $self->{'coding_region_end'} = $value;
+  } elsif( ! defined $self->{'coding_region_end'}
+     && defined $self->translation() ) {
+    $strand = $self->translation()->start_Exon->strand();
+    if( $strand == 1 ) {
+      $end = $self->translation()->end_Exon->start();
+      $end += ( $self->translation()->end() - 1 );
+    } else {
+      $end = $self->translation()->start_Exon->end();
+      $end -= ( $self->translation()->start() - 1 );
+    }
+    $self->{'coding_region_end'} = $end;
+  }
+
+  return $self->{'coding_region_end'};
+}
+
+
+=head2 edits_enabled
+
+  Arg [1]    : (optional) boolean $newval
+  Example    : $transcript->edits_enabled(1);
+  Description: Enables/Disables the application of SeqEdits to this transcript.
+               Edits are enabled by default, and affect the cdna/mrna
+               sequences coordinates and the resultant translation.
+  Returntype : boolean - the current value of the edits
+  Exceptions : none
+  Caller     : general, cdna_coding_start, cdna_coding_end, length
+  Status     : Stable
+
+=cut
+
+sub edits_enabled {
+  my ( $self, $boolean ) = @_;
+
+  if ( defined($boolean) ) {
+    $self->{'edits_enabled'} = $boolean;
+
+    # flush cached values that will be different with/without edits
+    $self->{'cdna_coding_start'} = undef;
+    $self->{'cdna_coding_end'}   = undef;
+    $self->{'transcript_mapper'} = undef;
+  }
+
+  return $self->{'edits_enabled'};
+}
+
+
+=head2 get_all_SeqEdits
+
+  Arg [1]    : none
+  Example    : my @seqeds = @{$transcript->get_all_SeqEdits()};
+  Description: Retrieves all post transcriptional sequence modifications for
+               this transcript.
+  Returntype : Bio::EnsEMBL::SeqEdit
+  Exceptions : none
+  Caller     : spliced_seq()
+  Status     : Stable
+
+=cut
+
+sub get_all_SeqEdits {
+  my $self = shift;
+
+  my @seqeds;
+
+  my $attribs = $self->get_all_Attributes('_rna_edit');
+
+  # convert attributes to SeqEdit objects
+  foreach my $a (@$attribs) {
+    push @seqeds, Bio::EnsEMBL::SeqEdit->new(-ATTRIB => $a);
+  }
+
+  return \@seqeds;
+}
+
+
+=head2 get_all_Attributes
+
+  Arg [1]    : optional string $attrib_code
+               The code of the attribute type to retrieve values for.
+  Example    : ($rna_edits) = @{$transcript->get_all_Attributes('_rna_edit')};
+               @transc_attributes    = @{$transcript->get_all_Attributes()};
+  Description: Gets a list of Attributes of this transcript.
+               Optionally just get Attrubutes for given code.
+  Returntype : listref Bio::EnsEMBL::Attribute
+  Exceptions : warning if transcript does not have attached adaptor and 
+               attempts lazy load.
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub get_all_Attributes {
+  my $self = shift;
+  my $attrib_code = shift;
+
+  if( ! exists $self->{'attributes' } ) {
+    if(!$self->adaptor() ) {
+      return [];
+    }
+
+    my $attribute_adaptor = $self->adaptor->db->get_AttributeAdaptor();
+    $self->{'attributes'} = $attribute_adaptor->fetch_all_by_Transcript($self);
+  }
+
+  if( defined $attrib_code) {
+    my @results = grep { uc($_->code()) eq uc($attrib_code) }
+      @{$self->{'attributes'}};
+    return \@results;
+  } else {
+    return $self->{'attributes'};
+  }
+}
+
+
+=head2 add_Attributes
+
+  Arg [1...] : Bio::EnsEMBL::Attribute $attribute
+               You can have more Attributes as arguments, all will be added.
+  Example    : $transcript->add_Attributes($rna_edit_attribute);
+  Description: Adds an Attribute to the Transcript. Usefull to do _rna_edits.
+               If you add an attribute before you retrieve any from database, 
+               lazy load will be disabled.
+  Returntype : none
+  Exceptions : throw on incorrect arguments
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub add_Attributes {
+  my ( $self, @attribs ) = @_;
+
+  if ( !exists( $self->{'attributes'} ) ) {
+    $self->{'attributes'} = [];
+  }
+
+  my $seq_change = 0;
+  foreach my $attrib (@attribs) {
+    assert_ref( $attrib, 'Bio::EnsEMBL::Attribute' );
+
+    push( @{ $self->{'attributes'} }, $attrib );
+
+    if ( $attrib->code() eq "_rna_edit" ) {
+      $seq_change = 1;
+    }
+  }
+
+  if ($seq_change) {
+    my $translation = $self->translation();
+    if ( defined($translation) ) {
+      delete( $translation->{'seq'} );
+    }
+  }
+
+  # flush cdna coord cache b/c we may have added a SeqEdit
+  delete( $self->{'cdna_coding_start'} );
+  delete( $self->{'cdna_coding_end'} );
+  delete( $self->{'transcript_mapper'} );
+} ## end sub add_Attributes
+
+
+=head2 add_Exon
+
+ Title   : add_Exon
+ Usage   : $trans->add_Exon($exon)
+ Returns : None
+ Args [1]: Bio::EnsEMBL::Exon object to add
+ Args [2]: rank
+ Exceptions: throws if not a valid Bio::EnsEMBL::Exon
+           : or exon clashes with another one
+ Status  : Stable
+
+=cut
+
+sub add_Exon {
+  my ( $self, $exon, $rank ) = @_;
+
+  assert_ref( $exon, 'Bio::EnsEMBL::Exon' );
+
+  $self->{'_trans_exon_array'} ||= [];
+
+  if ( defined($rank) ) {
+    $self->{'_trans_exon_array'}->[ $rank - 1 ] = $exon;
+    return;
+  }
+
+  my $was_added = 0;
+
+  my $ea = $self->{'_trans_exon_array'};
+
+  if ( @{$ea} ) {
+    if ( $exon->strand() == 1 ) {
+
+      my $exon_start = $exon->start();
+
+      if ( $exon_start > $ea->[-1]->end() ) {
+        push( @{$ea}, $exon );
+        $was_added = 1;
+      } else {
+        # Insert it at correct place
+
+        my $i = 0;
+        foreach my $e ( @{$ea} ) {
+          if ( $exon_start < $e->start() ) {
+            if ( $exon->end() >= $e->start() ) {
+              # Overlap
+              last;
+            }
+            if ( $i and $exon_start <= $ea->[$i-1]->end() ) {
+              # Overlap
+              last;
+            }
+            splice( @{$ea}, $i, 0, $exon );
+            $was_added = 1;
+            last;
+          }
+          ++$i;
+        }
+
+      }
+
+    } else {
+
+      my $exon_end = $exon->end();
+
+      if ( $exon_end < $ea->[-1]->start() ) {
+        push( @{$ea}, $exon );
+        $was_added = 1;
+      } else {
+        # Insert it at correct place
+
+        my $i = 0;
+        foreach my $e ( @{$ea} ) {
+          if ( $exon_end > $e->end() ) {
+            if ( $exon->start() <= $e->end() ) {
+              # Overlap
+              last;
+            }
+            if ( $i and $exon_end >= $ea->[$i-1]->start() ) {
+              # Overlap
+              last;
+            }
+            splice( @{$ea}, $i, 0, $exon );
+            $was_added = 1;
+            last;
+          }
+          ++$i;
+        }
+
+      }
+
+    } ## end else [ if ( $exon->strand() ==...)]
+  } else {
+    push( @{$ea}, $exon );
+    $was_added = 1;
+  }
+
+  # sanity check:
+  if ( !$was_added ) {
+    # The exon was not added because it was overloapping with an
+    # existing exon.
+    my $all_str = '';
+
+    foreach my $e ( @{$ea} ) {
+      $all_str .= '  '
+        . $e->start() . '-'
+        . $e->end() . ' ('
+        . $e->strand() . ') '
+        . ( $e->stable_id() || '' ) . "\n";
+    }
+
+    my $cur_str = '  '
+      . $exon->start() . '-'
+      . $exon->end() . ' ('
+      . $exon->strand() . ') '
+      . ( $exon->stable_id() || '' ) . "\n";
+
+    throw(   "Exon overlaps with other exon in same transcript.\n"
+           . "Transcript Exons:\n$all_str\n"
+           . "This Exon:\n$cur_str" );
+  }
+
+  # recalculate start, end, slice, strand
+  $self->recalculate_coordinates();
+} ## end sub add_Exon
+
+
+=head2 get_all_Exons
+
+  Arg [CONSTITUTIVE]    : Boolean
+                          Only return constitutive exons if true (non-zero)
+
+  Examples  :   my @exons = @{ $transcript->get_all_Exons() };
+
+                my @exons =
+                  @{ $transcript->get_all_Exons( -constitutive => 1 ) };
+
+  Description: Returns an listref of the exons in this transcript
+               in order, i.e. the first exon in the listref is the
+               5prime most exon in the transcript.  Only returns
+               constitutive exons if the CONSTITUTIVE argument is
+               true.
+
+  Returntype : listref to Bio::EnsEMBL::Exon objects
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub get_all_Exons {
+  my ( $self, @args ) = @_;
+
+  my $constitutive;
+  if (@args) {
+    $constitutive = rearrange( ['CONSTITUTIVE'], @args );
+  }
+
+  if (!defined( $self->{'_trans_exon_array'} )
+    && defined( $self->adaptor() ) )
+  {
+    $self->{'_trans_exon_array'} =
+      $self->adaptor()->db()->get_ExonAdaptor()
+      ->fetch_all_by_Transcript($self);
+  }
+
+  my @result;
+  if ( defined($constitutive) && $constitutive != 0 ) {
+    foreach my $exon ( @{ $self->{'_trans_exon_array'} } ) {
+      if ( $exon->is_constitutive() ) {
+        push( @result, $exon );
+      }
+    }
+  } else {
+    @result = @{ $self->{'_trans_exon_array'} };
+  }
+
+  return \@result;
+} ## end sub get_all_Exons
+
+=head2 get_all_constitutive_Exons
+
+  Arg        :  None
+
+  Examples   :  my @exons = @{ $transcript->get_all_constitutive_Exons() };
+
+  Description:  Returns an listref of the constitutive exons in this
+                transcript in order, i.e. the first exon in the
+                listref is the 5prime most exon in the transcript.
+
+  Returntype : listref to Bio::EnsEMBL::Exon objects
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub get_all_constitutive_Exons {
+  my ($self) = @_;
+  return $self->get_all_Exons( '-constitutive' => 1 );
+}
+
+=head2 get_all_IntronSupportingEvidence
+
+  Example     : $ise->get_all_IntronSupportingEvidence();
+  Description : Fetches all ISE instances linked to this Transript
+  Returntype  : ArrayRef[Bio::EnsEMBL::IntronSupportEvidence] retrieved from 
+                the DB or from those added via C<add_IntronSupportingEvidence>
+  Exceptions  : None
+
+=cut
+
+sub get_all_IntronSupportingEvidence {
+  my ($self) = @_;
+  if(! defined $self->{_ise_array} && defined $self->adaptor()) {
+    my $isea = $self->adaptor()->db()->get_IntronSupportingEvidenceAdaptor();
+    $self->{_ise_array} = $isea->fetch_all_by_Transcript($self);
+  }
+  return $self->{_ise_array};
+}
+
+
+=head2 add_IntronSupportingEvidence
+
+  Arg [1]     : Bio::EnsEMBL::IntronSupportEvidence Object to add
+  Example     : $ise->add_IntronSupportingEvidence($ise);
+  Description : Adds the IntronSupportEvidence instance to this Transcript. The
+                code checks to see if it is a unique ISE instance
+  Returntype  : Boolean; true means it was added. False means it was not 
+                as this ISE was already attached
+  Exceptions  : None
+
+=cut
+
+sub add_IntronSupportingEvidence {
+  my ($self, $ise) = @_;
+  assert_ref($ise, 'Bio::EnsEMBL::IntronSupportingEvidence', 'IntronSupportingEvidence');
+  my $unique = 1;
+  foreach my $other_ise (@{$self->{_ise_array}}) {
+    if($ise->equals($other_ise)) {
+      $unique = 0;
+      last;
+    }
+  }
+  if($unique) {
+    push(@{$self->{_ise_array}}, $ise);
+    return 1;
+  }
+  return 0;
+}
+
+=head2 get_all_Introns
+
+  Arg [1]    : none
+  Example    : my @introns = @{$transcript->get_all_Introns()};
+  Description: Returns an listref of the introns in this transcript in order.
+               i.e. the first intron in the listref is the 5prime most exon in 
+               the transcript.
+  Returntype : listref to Bio::EnsEMBL::Intron objects
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub get_all_Introns {
+   my ($self) = @_;
+   if( ! defined $self->{'_trans_exon_array'} && defined $self->adaptor() ) {
+     $self->{'_trans_exon_array'} = $self->adaptor()->db()->
+       get_ExonAdaptor()->fetch_all_by_Transcript( $self );
+   }
+
+   my @introns=();
+   my @exons = @{$self->{'_trans_exon_array'}};
+   for(my $i=0; $i < scalar(@exons)-1; $i++){
+     my $intron = new Bio::EnsEMBL::Intron($exons[$i],$exons[$i+1]);
+     push(@introns, $intron)
+   }
+   return \@introns;
+}
+
+
+=head2 length
+
+  Args       : none
+  Example    : my $t_length = $transcript->length
+  Description: Returns the sum of the length of all the exons in the transcript.
+  Returntype : int
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub length {
+  my( $self ) = @_;
+
+  my $length = 0;
+  foreach my $ex (@{$self->get_all_Exons}) {
+    $length += $ex->length;
+  }
+
+  # adjust the length if post transcriptional edits are enabled
+  if($self->edits_enabled()) {
+    foreach my $se (@{$self->get_all_SeqEdits()}) {
+      $length += $se->length_diff();
+    }
+  }
+
+  return $length;
+}
+
+
+=head2 flush_Exons
+
+  Arg [1]    : none
+  Example    : $transcript->flush_Exons();
+  Description: Removes all Exons from this transcript and flushes related
+               internal caches.
+  Returntype : none
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub flush_Exons {
+  my ($self) = @_;
+
+  $self->{'transcript_mapper'}   = undef;
+  $self->{'coding_region_start'} = undef;
+  $self->{'coding_region_end'}   = undef;
+  $self->{'cdna_coding_start'}   = undef;
+  $self->{'cdna_coding_end'}     = undef;
+  $self->{'start'}               = undef;
+  $self->{'end'}                 = undef;
+  $self->{'strand'}              = undef;
+
+  $self->{'_trans_exon_array'} = [];
+}
+
+=head2 flush_IntronSupportingEvidence
+
+  Example    : $transcript->flush_IntronSupportingEvidence();
+  Description: Removes all IntronSupportingEvidence from this transcript
+  Returntype : none
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub flush_IntronSupportingEvidence {
+  my ($self) = @_;
+  $self->{_ise_array} = [];
+  return;
+}
+
+=head2 five_prime_utr
+
+  Arg [1]    : none
+  Example    : my $five_prime  = $transcrpt->five_prime_utr
+                 or warn "No five prime UTR";
+  Description: Obtains a Bio::Seq object of the five prime UTR of this
+               transcript.  If this transcript is a pseudogene
+               (i.e. non-translating) or has no five prime UTR undef is
+               returned instead.
+  Returntype : Bio::Seq or undef
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub five_prime_utr {
+  my $self = shift;
+
+  my $cdna_coding_start  = $self->cdna_coding_start();
+
+  return undef if(!$cdna_coding_start);
+
+  my $seq = substr($self->spliced_seq, 0, $cdna_coding_start - 1);
+
+  return undef if(!$seq);
+
+  return
+    Bio::Seq->new( -id       => $self->display_id,
+                   -moltype  => 'dna',
+                   -alphabet => 'dna',
+                   -seq      => $seq );
+}
+
+
+=head2 three_prime_utr
+
+  Arg [1]    : none
+  Example    : my $three_prime  = $transcrpt->three_prime_utr
+                 or warn "No three prime UTR";
+  Description: Obtains a Bio::Seq object of the three prime UTR of this
+               transcript.  If this transcript is a pseudogene
+               (i.e. non-translating) or has no three prime UTR,
+               undef is returned instead.
+  Returntype : Bio::Seq or undef
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub three_prime_utr {
+  my $self = shift;
+
+  my $cdna_coding_end = $self->cdna_coding_end();
+
+  return undef if(!$cdna_coding_end);
+
+  my $seq = substr($self->spliced_seq, $cdna_coding_end);
+
+  return undef if(!$seq);
+
+  return
+    Bio::Seq->new( -id       => $self->display_id,
+                   -moltype  => 'dna',
+                   -alphabet => 'dna',
+                   -seq      => $seq );
+}
+
+=head2 five_prime_utr_Feature
+
+  Example    : my $five_prime  = $transcrpt->five_prime_utr_Feature
+                 or warn "No five prime UTR";
+  Description: Returns the genomic coordinates of the start and end of the
+               5' UTR of this transcript. Note that if you want the sequence
+               of the 5' UTR use C<five_prime_utr> as this will return the
+               sequence from the spliced transcript. 
+  Returntype : Bio::EnsEMBL::Feature or undef if there is no UTR
+  Exceptions : none
+
+=cut
+
+sub five_prime_utr_Feature {
+  my ($self) = @_;
+  my ($start, $end);
+  my $cdna_coding = $self->cdna_coding_start();
+  my ($genomic_pos) = $self->cdna2genomic($cdna_coding, $cdna_coding);
+  if($self->strand() == 1) {
+    $start = $self->seq_region_start();
+    if($start == $genomic_pos->start()) {
+      return; # just return as we have no UTR
+    }
+    $end = $genomic_pos->start() - 1;
+  }
+  else {
+    $end = $self->seq_region_end();
+    if($end == $genomic_pos->start()) {
+      return; # just return as we have no UTR
+    }
+    $start = $genomic_pos->start() + 1;
+  }
+    
+  my $feature = Bio::EnsEMBL::Feature->new(
+    -START => $start,
+    -END => $end,
+    -STRAND => $self->strand(),
+    -SLICE => $self->slice(),
+  );
+  return $feature;
+}
+
+=head2 three_prime_utr_Feature
+
+  Example    : my $five_prime  = $transcrpt->three_prime_utr_Feature
+                 or warn "No three prime UTR";
+  Description: Returns the genomic coordinates of the start and end of the
+               3' UTR of this transcript. Note that if you want the sequence
+               of the 3' UTR use C<three_prime_utr> as this will return the
+               sequence from the spliced transcript. 
+  Returntype : Bio::EnsEMBL::Feature or undef if there is no UTR
+  Exceptions : none
+
+=cut
+
+sub three_prime_utr_Feature {
+  my ($self) = @_;
+  my ($start, $end);
+  my $cdna_coding = $self->cdna_coding_end();
+  my ($genomic_pos) = $self->cdna2genomic($cdna_coding, $cdna_coding);
+  if($self->strand() == 1) {
+    $end = $self->seq_region_end();
+    if($end == $genomic_pos->start()) {
+      return; # just return as we have no UTR
+    }
+    $start = $genomic_pos->start() + 1;
+  }
+  else {
+    $start = $self->seq_region_start();
+    if($start == $genomic_pos->start()) {
+      return; # just return as we have no UTR
+    }
+    $end = $genomic_pos->start() - 1;
+  }
+  my $feature = Bio::EnsEMBL::Feature->new(
+    -START => $start,
+    -END => $end,
+    -STRAND => $self->strand(),
+    -SLICE => $self->slice(),
+  );
+  return $feature;
+}
+
+
+=head2 get_all_translateable_Exons
+
+  Args       : none
+  Example    : none
+  Description: Returns a list of exons that translate with the
+               start and end exons truncated to the CDS regions.
+               This function does not take into account any SeqEdits
+               (post transcriptional RNA modifictions) when constructing the
+               the 'translateable' exons, and it does not update the phase
+               information of the created 'translateable' exons.
+
+               If this transcript is a pseudogene (i.e. non-translateable)
+               a reference to an empty list is returned.
+
+  Returntype : listref Bio::EnsEMBL::Exon
+  Exceptions : throw if translation has invalid information
+  Caller     : Genebuild
+  Status     : Stable
+
+=cut
+
+
+sub get_all_translateable_Exons {
+  my ( $self ) = @_;
+
+  #return an empty list if there is no translation (i.e. pseudogene)
+  my $translation = $self->translation or return [];
+  my $start_exon      = $translation->start_Exon;
+  my $end_exon        = $translation->end_Exon;
+  my $t_start         = $translation->start;
+  my $t_end           = $translation->end;
+
+  my( @translateable );
+
+  foreach my $ex (@{$self->get_all_Exons}) {
+
+    if ($ex ne $start_exon and ! @translateable) {
+      next;   # Not yet in translated region
+    }
+
+    my $length  = $ex->length;
+
+    my $adjust_start = 0;
+    my $adjust_end = 0;
+    # Adjust to translation start if this is the start exon
+    if ($ex == $start_exon ) {
+      if ($t_start < 1 or $t_start > $length) {
+        warning("WARN: Translation start '$t_start' is outside exon $ex length=$length");
+  return [];
+      }
+      $adjust_start = $t_start - 1;
+    }
+
+    # Adjust to translation end if this is the end exon
+    if ($ex == $end_exon) {
+#      if ($t_end < 1 or $t_end > $length) {
+#        throw("Translation end '$t_end' is outside exon $ex length=$length");
+#      }
+      $adjust_end = $t_end - $length;
+    }
+
+    # Make a truncated exon if the translation start or
+    # end causes the coordinates to be altered.
+    if ($adjust_end || $adjust_start) {
+      my $newex = $ex->adjust_start_end( $adjust_start, $adjust_end );
+
+      push( @translateable, $newex );
+    } else {
+      push(@translateable, $ex);
+    }
+
+    # Exit the loop when we've found the last exon
+    last if $ex eq $end_exon;
+  }
+  return \@translateable;
+}
+
+
+=head2 translate
+
+  Args       : none
+  Example    : none
+  Description: Return the peptide (plus eventual stop codon) for
+               this transcript.  Does N-padding of non-phase
+               matching exons.  It uses translateable_seq
+               internally.  Returns undef if this Transcript does
+               not have a translation (i.e. pseudogene).
+  Returntype : Bio::Seq or undef
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub translate {
+  my ($self) = @_;
+
+  if ( !defined( $self->translation() ) ) { return undef }
+
+  my $mrna = $self->translateable_seq();
+
+  # Alternative codon tables (such as the mitochondrial codon table)
+  # can be specified for a sequence region via the seq_region_attrib
+  # table.  A list of codon tables and their codes is at:
+  # http://www.ncbi.nlm.nih.gov/htbin-post/Taxonomy/wprintgc?mode=c
+
+  my $codon_table_id;
+  my ( $complete5, $complete3 );
+  if ( defined( $self->slice() ) ) {
+    my $attrib;
+
+    ($attrib) = @{ $self->slice()->get_all_Attributes('codon_table') };
+    if ( defined($attrib) ) {
+      $codon_table_id = $attrib->value();
+    }
+
+    ($attrib) = @{ $self->slice()->get_all_Attributes('complete5') };
+    if ( defined($attrib) ) {
+      $complete5 = $attrib->value();
+    }
+
+    ($attrib) = @{ $self->slice()->get_all_Attributes('complete3') };
+    if ( defined($attrib) ) {
+      $complete3 = $attrib->value();
+    }
+  }
+  $codon_table_id ||= 1;    # default vertebrate codon table
+
+  # Remove final stop codon from the mrna if it is present.  Produced
+  # peptides will not have '*' at end.  If terminal stop codon is
+  # desired call translatable_seq directly and produce a translation
+  # from it.
+
+  if ( CORE::length($mrna) % 3 == 0 ) {
+    my $codon_table =
+      Bio::Tools::CodonTable->new( -id => $codon_table_id );
+
+    if ( $codon_table->is_ter_codon( substr( $mrna, -3, 3 ) ) ) {
+      substr( $mrna, -3, 3, '' );
+    }
+  }
+
+  if ( CORE::length($mrna) < 1 ) { return undef }
+
+  my $display_id = $self->translation->display_id()
+    || scalar( $self->translation() );
+
+  my $peptide = Bio::Seq->new( -seq      => $mrna,
+                               -moltype  => 'dna',
+                               -alphabet => 'dna',
+                               -id       => $display_id );
+
+  my $translation =
+    $peptide->translate( undef, undef, undef, $codon_table_id, undef,
+                         undef, $complete5, $complete3 );
+
+  if ( $self->edits_enabled() ) {
+    $self->translation()->modify_translation($translation);
+  }
+
+  return $translation;
+} ## end sub translate
+
+
+=head2 seq
+
+  Description: Returns a Bio::Seq object which consists of just
+             : the sequence of the exons concatenated together,
+             : without messing about with padding with N\'s from
+             : Exon phases like B<dna_seq> does.
+  Args       : none
+  Example    : none
+  Returntype : Bio::Seq
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub seq {
+  my ($self) = @_;
+
+  return
+    Bio::Seq->new( -id       => $self->display_id,
+                   -moltype  => 'dna',
+                   -alphabet => 'dna',
+                   -seq      => $self->spliced_seq );
+}
+
+
+=head2 pep2genomic
+
+  Description: See Bio::EnsEMBL::TranscriptMapper::pep2genomic
+
+=cut
+
+sub pep2genomic {
+  my $self = shift;
+  return $self->get_TranscriptMapper()->pep2genomic(@_);
+}
+
+
+=head2 genomic2pep
+
+  Description: See Bio::EnsEMBL::TranscriptMapper::genomic2pep
+
+=cut
+
+sub genomic2pep {
+  my $self = shift;
+  return $self->get_TranscriptMapper()->genomic2pep(@_);
+}
+
+
+=head2 cdna2genomic
+
+  Description: See Bio::EnsEMBL::TranscriptMapper::cdna2genomic
+
+=cut
+
+sub cdna2genomic {
+  my $self = shift;
+  return $self->get_TranscriptMapper()->cdna2genomic(@_);
+}
+
+
+=head2 genomic2cdna
+
+  Description: See Bio::EnsEMBL::TranscriptMapper::genomic2cdna
+
+=cut
+
+sub genomic2cdna {
+  my $self = shift;
+  return $self->get_TranscriptMapper->genomic2cdna(@_);
+}
+
+
+=head2 get_TranscriptMapper
+
+  Args       : none
+  Example    : my $trans_mapper = $transcript->get_TranscriptMapper();
+  Description: Gets a TranscriptMapper object which can be used to perform
+               a variety of coordinate conversions relating this transcript,
+               genomic sequence and peptide resulting from this transcripts
+               translation.
+  Returntype : Bio::EnsEMBL::TranscriptMapper
+  Exceptions : none
+  Caller     : cdna2genomic, pep2genomic, genomic2cdna, cdna2genomic
+  Status     : Stable
+
+=cut
+
+sub get_TranscriptMapper {
+  my ( $self ) = @_;
+  return $self->{'transcript_mapper'} ||=
+    Bio::EnsEMBL::TranscriptMapper->new($self);
+}
+
+
+=head2 start_Exon
+
+ Title       : start_Exon
+ Usage       : $start_exon = $transcript->start_Exon;
+ Returntype  : Bio::EnsEMBL::Exon
+ Description : The first exon in the transcript.
+ Args        : NONE
+ Status      : Stable
+
+=cut
+
+sub start_Exon {
+  my $self = shift;
+  return $self->get_all_Exons()->[0];
+}
+
+
+=head2 end_Exon
+
+ Title       : end_exon
+ Usage       : $end_exon = $transcript->end_Exon;
+ Description : The last exon in the transcript.
+ Returntype  : Bio::EnsEMBL::Exon
+ Args        : NONE
+ Status      : Stable
+
+=cut
+
+sub end_Exon {
+   my $self = shift;
+   return $self->get_all_Exons()->[-1];
+}
+
+
+=head2 description
+
+ Title   : description
+ Usage   : $obj->description($newval)
+ Function: 
+ Returns : String
+ Args    : newvalue (optional)
+ Status  : Stable
+
+=cut
+
+sub description {
+  my $self = shift;
+  $self->{'description'} = shift if( @_ );
+  return $self->{'description'};
+}
+
+
+=head2 version
+
+ Title   : version
+ Usage   : $obj->version()
+ Function: 
+ Returns : String
+ Args    : 
+ Status  : Stable
+
+=cut
+
+sub version {
+  my $self = shift;
+  $self->{'version'} = shift if( @_ );
+  return $self->{'version'};
+}
+
+
+=head2 stable_id
+
+ Title   : stable_id
+ Usage   : $obj->stable_id
+ Function: 
+ Returns : String
+ Args    : 
+ Status  : Stable
+
+=cut
+
+sub stable_id {
+  my $self = shift;
+  $self->{'stable_id'} = shift if( @_ );
+  return $self->{'stable_id'};
+}
+
+
+=head2 is_current
+
+  Arg [1]    : Boolean $is_current
+  Example    : $transcript->is_current(1)
+  Description: Getter/setter for is_current state of this transcript.
+  Returntype : Int
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub is_current {
+  my $self = shift;
+  $self->{'is_current'} = shift if (@_);
+  return $self->{'is_current'};
+}
+
+
+=head2 created_date
+
+  Arg [1]    : (optional) string to be used for the created date
+  Example    : none
+  Description: get/set for attribute created date
+  Returntype : string
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub created_date {
+  my $self = shift;
+  $self->{'created_date'} = shift if ( @_ );
+  return $self->{'created_date'};
+}
+
+
+=head2 modified_date
+
+  Arg [1]    : (optional) string to be used for the modified date
+  Example    : none
+  Description: get/set for attribute modified date
+  Returntype : string
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+sub modified_date {
+  my $self = shift;
+  $self->{'modified_date'} = shift if ( @_ );
+  return $self->{'modified_date'};
+}
+
+
+=head2 swap_exons
+
+  Arg [1]    : Bio::EnsEMBL::Exon $old_Exon
+               An exon that should be replaced
+  Arg [2]    : Bio::EnsEMBL::Exon $new_Exon
+               The replacement Exon
+  Example    : none
+  Description: exchange an exon in the current Exon list with a given one.
+               Usually done before storing of Gene, so the Exons can
+               be shared between Transcripts.
+  Returntype : none
+  Exceptions : none
+  Caller     : GeneAdaptor->store()
+  Status     : Stable
+
+=cut
+
+sub swap_exons {
+  my ( $self, $old_exon, $new_exon ) = @_;
+  
+  my $arref = $self->{'_trans_exon_array'};
+  for(my $i = 0; $i < @$arref; $i++) {
+    if($arref->[$i] == $old_exon) {
+      $arref->[$i] = $new_exon;
+      last;
+    }
+  }
+
+  if( defined $self->{'translation'} ) {
+     if( $self->translation()->start_Exon() == $old_exon ) {
+      $self->translation()->start_Exon( $new_exon );
+    }
+    if( $self->translation()->end_Exon() == $old_exon ) {
+      $self->translation()->end_Exon( $new_exon );
+    }
+  }
+}
+
+
+=head2 equals
+
+  Arg [1]       : Bio::EnsEMBL::Transcript transcript
+  Example       : if ($transcriptA->equals($transcriptB)) { ... }
+  Description   : Compares two transcripts for equality.
+                  The test for eqality goes through the following list
+                  and terminates at the first true match:
+
+                  1. If Bio::EnsEMBL::Feature::equals() returns false,
+                     then the transcripts are *not* equal.
+                  2. If the biotypes differ, then the transcripts are
+                     *not* equal.
+                  3. If both transcripts have stable IDs: if these are
+                     the same, the transcripts are equal, otherwise not.
+                  4. If both transcripts have the same number of exons
+                     and if these are (when compared pair-wise sorted by
+                     start-position and length) the same, then they are
+                     equal, otherwise not.
+
+  Return type   : Boolean (0, 1)
+
+  Exceptions    : Thrown if a non-transcript is passed as the argument.
+
+=cut
+
+sub equals {
+  my ( $self, $transcript ) = @_;
+
+  if ( !defined($transcript) ) { return 0 }
+  if ( $self eq $transcript ) { return 1 }
+
+  assert_ref( $transcript, 'Bio::EnsEMBL::Transcript' );
+
+  my $feature_equals = $self->SUPER::equals($transcript);
+  if ( defined($feature_equals) && $feature_equals == 0 ) {
+    return 0;
+  }
+
+  if ( $self->biotype() ne $transcript->biotype() ) {
+    return 0;
+  }
+
+  if ( defined( $self->stable_id() ) &&
+       defined( $transcript->stable_id() ) )
+  {
+    if ( $self->stable_id() eq $transcript->stable_id() ) {
+      return 1;
+    }
+    else {
+      return 0;
+    }
+  }
+
+  my @self_exons = sort {
+    $a->start() <=> $b->start() ||
+      $a->length() <=> $b->length()
+  } @{ $self->get_all_Exons() };
+  my @transcript_exons = sort {
+    $a->start() <=> $b->start() ||
+      $a->length() <=> $b->length()
+  } @{ $transcript->get_all_Exons() };
+
+  if ( scalar(@self_exons) != scalar(@transcript_exons) ) {
+    return 0;
+  }
+
+  while (@self_exons) {
+    my $self_exon       = shift(@self_exons);
+    my $transcript_exon = shift(@transcript_exons);
+
+    if ( !$self_exon->equals($transcript_exon) ) {
+      return 0;
+    }
+  }
+
+  return 1;
+} ## end sub equals
+
+=head2 transform
+
+  Arg  1     : String $coordinate_system_name
+  Arg [2]    : String $coordinate_system_version
+  Example    : $transcript = $transcript->transform('contig');
+               $transcript = $transcript->transform('chromosome', 'NCBI33');
+  Description: Moves this Transcript to the given coordinate system.
+               If this Transcript has Exons attached, they move as well.
+               A new Transcript is returned. If the transcript cannot be
+               transformed to the destination coordinate system undef is
+               returned instead.
+  Returntype : Bio::EnsEMBL::Transcript
+  Exceptions : wrong parameters
+  Caller     : general
+  Status     : Medium Risk
+             : deprecation needs to be removed at some time
+
+=cut
+
+
+sub transform {
+  my $self = shift;
+
+  # catch for old style transform calls
+  if( ref $_[0] eq 'HASH') {
+    deprecate("Calling transform with a hashref is deprecate.\n" .
+              'Use $trans->transfer($slice) or ' .
+              '$trans->transform("coordsysname") instead.');
+    my (undef, $new_ex) = each(%{$_[0]});
+    return $self->transfer($new_ex->slice);
+  }
+
+  my $new_transcript = $self->SUPER::transform(@_);
+  if ( !defined($new_transcript) ) {
+    my @segments = @{ $self->project(@_) };
+    # if it projects, maybe the exons transform well?
+    # lazy load them here
+    if ( !@segments ) {
+      return undef;
+    }
+    $self->get_all_Exons();
+  }
+
+
+  if( exists $self->{'_trans_exon_array'} ) {
+    my @new_exons;
+    my ( $low_start, $hi_end, $slice );
+    # we want to check whether the transform preserved 5prime 3prime
+    # ordering. This assumes 5->3 order. No complaints on transsplicing.
+
+    my ( $last_new_start, $last_old_strand, 
+   $last_new_strand, $start_exon, $end_exon,
+  $last_seq_region_name );
+    my $first = 1;
+    my $ignore_order = 0;
+    my $order_broken = 0;
+
+    for my $old_exon ( @{$self->{'_trans_exon_array'}} ) {      
+      my $new_exon = $old_exon->transform( @_ );
+      return undef if( !defined $new_exon );
+      if( ! defined $new_transcript ) {
+  if( !$first ) {
+    if( $old_exon->strand() != $last_old_strand ) {
+      # transsplicing, ignore ordering
+      $ignore_order = 1;  
+    }
+
+    if( $new_exon->slice()->seq_region_name() ne 
+        $last_seq_region_name ) {
+      return undef;
+    }
+
+    if( $last_new_strand == 1 and 
+        $new_exon->start() < $last_new_start ) {
+      $order_broken = 1;
+    }
+
+    if( $last_new_strand == -1 and
+        $new_exon->start() > $last_new_start ) {
+      $order_broken = 1;
+    }
+
+    #additional check that if exons were on same strand previously, they should be again
+    if(($last_old_strand == $old_exon->strand()) and !($last_new_strand == $new_exon->strand())){
+      return undef;
+    }
+
+    if( $new_exon->start() < $low_start ) {
+      $low_start = $new_exon->start();
+    }
+    if( $new_exon->end() > $hi_end ) {
+      $hi_end = $new_exon->end();
+    }
+  } else {
+    $first = 0;
+    $low_start = $new_exon->start();
+    $hi_end = $new_exon->end();
+  }
+
+  $last_seq_region_name = $new_exon->slice()->seq_region_name();
+  $last_old_strand = $old_exon->strand();
+  $last_new_start = $new_exon->start();
+  $last_new_strand = $new_exon->strand();
+      }
+
+      if( defined $self->{'translation'} ) {
+        if( $self->translation()->start_Exon() == $old_exon ) {
+          $start_exon = $new_exon;
+        }
+        if( $self->translation()->end_Exon() == $old_exon ) {
+          $end_exon = $new_exon;
+        }
+      }
+      push( @new_exons, $new_exon );
+    }
+
+    if( $order_broken && !$ignore_order ) {
+      warning( "Order of exons broken in transform of ".$self->dbID() ); 
+      return undef;
+    }
+
+    if( !defined $new_transcript ) {
+      %$new_transcript = %$self;
+      bless $new_transcript, ref( $self );
+      $new_transcript->start( $low_start );
+      $new_transcript->end( $hi_end );
+      $new_transcript->slice( $new_exons[0]->slice() );
+      $new_transcript->strand( $new_exons[0]->strand() );
+    }
+
+    $new_transcript->{'_trans_exon_array'} = \@new_exons;
+
+    # should be ok to do inside exon array loop
+    # translations only exist together with the exons ...
+
+    if( defined $self->{'translation'} ) {
+      my $new_translation;
+      %$new_translation = %{$self->{'translation'}};;
+      bless $new_translation, ref( $self->{'translation'} );
+      $new_transcript->{'translation'} = $new_translation;
+      $new_translation->start_Exon( $start_exon );
+      $new_translation->end_Exon( $end_exon );
+    }
+  }
+
+  if( exists $self->{'_supporting_evidence'} ) {
+    my @new_features;
+    for my $old_feature ( @{$self->{'_supporting_evidence'}} ) {
+      my $new_feature = $old_feature->transform( @_ );
+      if (defined $new_feature) { 
+        push @new_features, $new_feature;
+      }
+    }
+    $new_transcript->{'_supporting_evidence'} = \@new_features;
+  }
+  
+  if(exists $self->{_ise_array}) {
+    my @new_features;
+    foreach my $old_feature ( @{$self->{_ise_array}} ) {
+      my $new_feature = $old_feature->transform(@_);
+      push( @new_features, $new_feature );
+    }
+    $new_transcript->{_ise_array} = \@new_features;
+  }
+
+
+  # flush cached internal values that depend on the exon coords
+  $new_transcript->{'transcript_mapper'}   = undef;
+  $new_transcript->{'coding_region_start'} = undef;
+  $new_transcript->{'coding_region_end'}   = undef;
+  $new_transcript->{'cdna_coding_start'}   = undef;
+  $new_transcript->{'cdna_coding_end'}     = undef;
+
+  return $new_transcript;
+}
+
+
+=head2 transfer
+
+  Arg  1     : Bio::EnsEMBL::Slice $destination_slice
+  Example    : $transcript = $transcript->transfer($slice);
+  Description: Moves this transcript to the given slice.
+               If this Transcripts has Exons attached, they move as well.
+  Returntype : Bio::EnsEMBL::Transcript
+  Exceptions : none
+  Caller     : general
+  Status     : Stable
+
+=cut
+
+
+sub transfer {
+  my $self = shift;
+
+  my $new_transcript = $self->SUPER::transfer( @_ );
+  return undef unless $new_transcript;
+
+  if( defined $self->{'translation'} ) {
+    my $new_translation;
+    %$new_translation = %{$self->{'translation'}};;
+    bless $new_translation, ref( $self->{'translation'} );
+    $new_transcript->{'translation'} = $new_translation;
+  }
+
+  if( exists $self->{'_trans_exon_array'} ) {
+    my @new_exons;
+    for my $old_exon ( @{$self->{'_trans_exon_array'}} ) {
+      my $new_exon = $old_exon->transfer( @_ );
+      if( defined $new_transcript->{'translation'} ) {
+        if( $new_transcript->translation()->start_Exon() == $old_exon ) {
+          $new_transcript->translation()->start_Exon( $new_exon );
+        }
+        if( $new_transcript->translation()->end_Exon() == $old_exon ) {
+          $new_transcript->translation()->end_Exon( $new_exon );
+        }
+      }
+      push( @new_exons, $new_exon );
+    }
+
+    $new_transcript->{'_trans_exon_array'} = \@new_exons;
+  }
+
+  if( exists $self->{'_supporting_evidence'} ) {
+    my @new_features;
+    for my $old_feature ( @{$self->{'_supporting_evidence'}} ) {
+      my $new_feature = $old_feature->transfer( @_ );
+      push( @new_features, $new_feature );
+    }
+    $new_transcript->{'_supporting_evidence'} = \@new_features;
+  }
+  
+  if(exists $self->{_ise_array}) {
+    my @new_features;
+    foreach my $old_feature ( @{$self->{_ise_array}} ) {
+      my $new_feature = $old_feature->transfer(@_);
+      push( @new_features, $new_feature );
+    }
+    $new_transcript->{_ise_array} = \@new_features;
+  }
+
+
+  # flush cached internal values that depend on the exon coords
+  $new_transcript->{'transcript_mapper'}   = undef;
+  $new_transcript->{'coding_region_start'} = undef;
+  $new_transcript->{'coding_region_end'}   = undef;
+  $new_transcript->{'cdna_coding_start'}   = undef;
+  $new_transcript->{'cdna_coding_end'}     = undef;
+
+  return $new_transcript;
+}
+
+
+=head recalculate_coordinates
+
+  Args       : none
+  Example    : none
+  Description: called when exon coordinate change happened to recalculate the
+               coords of the transcript.  This method should be called if one
+               of the exons has been changed.
+  Returntype : none
+  Exceptions : none
+  Caller     : internal
+  Status     : Stable
+
+=cut
+
+sub recalculate_coordinates {
+  my ($self) = @_;
+
+  my $exons = $self->get_all_Exons();
+
+  if ( !$exons || !@{$exons} ) { return }
+
+  my ( $slice, $start, $end, $strand );
+
+  my $e_index;
+  for ( $e_index = 0; $e_index < @{$exons}; $e_index++ ) {
+    my $e = $exons->[$e_index];
+
+    # Skip missing or unmapped exons!
+    if ( defined($e) && defined( $e->start() ) ) {
+      $slice  = $e->slice();
+      $strand = $e->strand();
+      $start  = $e->start();
+      $end    = $e->end();
+
+      last;
+    }
+  }
+
+  my $transsplicing = 0;
+
+  # Start loop after first exon with coordinates
+  for ( ; $e_index < @{$exons}; $e_index++ ) {
+    my $e = $exons->[$e_index];
+
+    # Skip missing or unmapped exons!
+    if ( !defined($e) || !defined( $e->start() ) ) { next }
+
+    if ( $e->start() < $start ) {
+      $start = $e->start();
+    }
+
+    if ( $e->end() > $end ) {
+      $end = $e->end();
+    }
+
+    if (    defined($slice)
+         && $e->slice()
+         && $e->slice()->name() ne $slice->name() )
+    {
+      throw(   "Exons with different slices "
+             . "are not allowed on one Transcript" );
+    }
+
+    if ( $e->strand() != $strand ) {
+      $transsplicing = 1;
+    }
+  } ## end for ( ; $e_index < @{$exons...})
+  if ($transsplicing) {
+    warning("Transcript contained trans splicing event");
+  }
+
+  $self->start($start);
+  $self->end($end);
+  $self->strand($strand);
+  $self->slice($slice);
+
+  # flush cached internal values that depend on the exon coords
+  $self->{'transcript_mapper'}   = undef;
+  $self->{'coding_region_start'} = undef;
+  $self->{'coding_region_end'}   = undef;
+  $self->{'cdna_coding_start'}   = undef;
+  $self->{'cdna_coding_end'}     = undef;
+} ## end sub recalculate_coordinates
+
+
+=head2 display_id
+
+  Arg [1]    : none
+  Example    : print $transcript->display_id();
+  Description: This method returns a string that is considered to be
+               the 'display' identifier. For transcripts this is (depending on
+               availability and in this order) the stable Id, the dbID or an
+               empty string.
+  Returntype : string
+  Exceptions : none
+  Caller     : web drawing code
+  Status     : Stable
+
+=cut
+
+sub display_id {
+  my $self = shift;
+  return $self->{'stable_id'} || $self->dbID || '';
+}
+
+
+=head2 get_all_peptide_variations
+
+  Description: See Bio::EnsEMBL::Utils::TranscriptSNPs::get_all_peptide_variations
+  Status  : At Risk
+          : Will be replaced with modules from the ensembl-variation package
+
+
+=cut
+
+sub get_all_peptide_variations {
+  my ($self, $source, $snps) = @_;
+
+  if(!$snps) {
+    my $shash = Bio::EnsEMBL::Utils::TranscriptSNPs::get_all_cdna_SNPs($self, $source);
+    $snps = $shash->{'coding'};
+  }
+
+  return Bio::EnsEMBL::Utils::TranscriptSNPs::get_all_peptide_variations($self,
+                                                                        $snps);
+}
+
+
+=head2 get_all_SNPs
+
+  Description: See Bio::EnsEMBL::Utils::TranscriptSNPs::get_all_SNPs
+
+  Status  : At Risk
+          : Will be replaced with modules from the ensembl-variation package
+
+=cut
+
+sub get_all_SNPs {
+  return Bio::EnsEMBL::Utils::TranscriptSNPs::get_all_SNPs(@_);
+}
+
+
+=head2 get_all_cdna_SNPs
+
+  Description: See Bio::EnsEMBL::Utils::TranscriptSNPs::get_all_cdna_SNPs
+ 
+  Status  : At Risk
+          : Will be replaced with modules from the ensembl-variation package
+
+=cut
+
+sub get_all_cdna_SNPs {
+  return Bio::EnsEMBL::Utils::TranscriptSNPs::get_all_cdna_SNPs(@_);
+}
+
+
+=head2 get_all_DASFactories
+
+  Arg [1]   : none
+  Function  : Retrieves a listref of registered DAS objects
+  Returntype: [ DAS_objects ]
+  Exceptions:
+  Caller    :
+  Example   : $dasref = $prot->get_all_DASFactories
+  Status    : Stable
+
+=cut
+
+sub get_all_DASFactories {
+   my $self = shift;
+   return [ $self->adaptor()->db()->_each_DASFeatureFactory ];
+}
+
+
+=head2 get_all_DAS_Features
+
+  Arg [1]    : none
+  Example    : $features = $prot->get_all_DAS_Features;
+  Description: Retreives a hash reference to a hash of DAS feature
+               sets, keyed by the DNS, NOTE the values of this hash
+               are an anonymous array containing:
+                (1) a pointer to an array of features;
+                (2) a pointer to the DAS stylesheet
+  Returntype : hashref of Bio::SeqFeatures
+  Exceptions : ?
+  Caller     : webcode
+  Status    : Stable
+
+
+=cut
+
+sub get_all_DAS_Features {
+  my ($self,@args) = @_;
+
+  my $db = $self->adaptor->db;
+  my $GeneAdaptor = $db->get_GeneAdaptor;
+  my $Gene = $GeneAdaptor->fetch_by_transcript_stable_id($self->stable_id); 
+  my $slice = $Gene->feature_Slice;
+  return $self->SUPER::get_all_DAS_Features($slice);
+}
+
+
+
+=head2 _compare_xrefs
+
+  Description: compare xrefs based on priority (descending), then
+               name (ascending), then display_label (ascending)
+
+=cut
+
+sub _compare_xrefs {
+  # compare on priority first (descending)
+  if ( $a->priority() != $b->priority() ) {
+    return $b->priority() <=> $a->priority();
+  } else {
+    # equal priorities, compare on external_db name
+    if ( $a->dbname() ne $b->dbname() ) {
+      return $a->dbname() cmp $b->dbname();
+    } else {
+      # equal priorities and names, compare on display_label
+      return $a->display_id() cmp $b->display_id();
+    }
+  }
+}
+
+
+=head2 load
+
+  Arg [1]       : Boolean $load_xrefs
+                  Load (or don't load) xrefs.  Default is to load xrefs.
+  Example       : $transcript->load();
+  Description   : The Ensembl API makes extensive use of
+                  lazy-loading.  Under some circumstances (e.g.,
+                  when copying genes between databases), all data of
+                  an object needs to be fully loaded.  This method
+                  loads the parts of the object that are usually
+                  lazy-loaded.  It will also call the equivalent
+                  method on any translation and on all exons of the
+                  transcript.
+  Returntype    : None
+
+=cut
+
+sub load {
+  my ( $self, $load_xrefs ) = @_;
+
+  if ( !defined($load_xrefs) ) { $load_xrefs = 1 }
+
+  my $translation = $self->translation();
+  if ( defined($translation) ) {
+    $translation->load($load_xrefs);
+
+    my $alt_translations = $self->get_all_alternative_translations();
+
+    if ( defined($alt_translations) ) {
+      foreach my $alt_translation ( @{$alt_translations} ) {
+        $alt_translation->load($load_xrefs);
+      }
+    }
+  }
+
+  foreach my $exon ( @{ $self->get_all_Exons() } ) {
+    $exon->load();
+  }
+
+  $self->stable_id();
+  $self->analysis();
+  $self->get_all_Attributes();
+  $self->get_all_supporting_features();
+
+  if ($load_xrefs) {
+    $self->get_all_DBEntries();
+  }
+
+} ## end sub load
+
+=head2 summary_as_hash
+
+  Example       : $transcript_summary = $transcript->summary_as_hash();
+  Description   : Extends Feature::summary_as_hash
+                  Retrieves a summary of this Transcript.
+  Returns       : hashref of descriptive strings
+  Status        : Intended for internal use
+=cut
+
+sub summary_as_hash {
+  my $self = shift;
+  my $summary_ref = $self->SUPER::summary_as_hash;
+  $summary_ref->{'description'} = $self->description;
+  $summary_ref->{'biotype'} = $self->biotype;
+  my $parent_gene = $self->get_Gene();
+  $summary_ref->{'Parent'} = $parent_gene->display_id;
+  return $summary_ref;
+}
+
+=head2 get_Gene
+  
+  Example     : $gene = $transcript->get_Gene;
+  Description : Locates the parent Gene using a transcript dbID
+  Returns     : Bio::EnsEMBL::Gene
+
+=cut
+
+sub get_Gene {
+  my $self = shift;
+  my $gene_adaptor = $self->adaptor->db->get_GeneAdaptor();
+  my $parent_gene = $gene_adaptor->fetch_by_transcript_id($self->dbID);
+  return $parent_gene;
+}
+
+###########################
+# DEPRECATED METHODS FOLLOW
+###########################
+
+=head2 sort
+
+  Description: DEPRECATED.  This method is no longer needed.  Exons are sorted
+               automatically when added to the transcript.
+
+=cut
+
+sub sort {
+  my $self = shift;
+
+  deprecate( "Exons are kept sorted, you dont have to call sort any more" );
+  # Fetch all the features
+  my @exons = @{$self->get_all_Exons()};
+  
+  # Empty the feature table
+  $self->flush_Exons();
+
+  # Now sort the exons and put back in the feature table
+  my $strand = $exons[0]->strand;
+
+  if ($strand == 1) {
+    @exons = sort { $a->start <=> $b->start } @exons;
+  } elsif ($strand == -1) {
+    @exons = sort { $b->start <=> $a->start } @exons;
+  }
+
+  foreach my $e (@exons) {
+    $self->add_Exon($e);
+  }
+}
+
+
+# _translation_id
+# Usage   : DEPRECATED - not needed anymore
+
+sub _translation_id {
+   my $self = shift;
+   deprecate( "This method shouldnt be necessary any more" );
+   if( @_ ) {
+      my $value = shift;
+      $self->{'_translation_id'} = $value;
+    }
+    return $self->{'_translation_id'};
+
+}
+
+
+=head2 created
+
+ Description: DEPRECATED - this attribute is not part of transcript anymore
+
+=cut
+
+sub created{
+   my $obj = shift;
+   deprecate( "This attribute is no longer supported" );
+   if( @_ ) {
+      my $value = shift;
+      $obj->{'created'} = $value;
+    }
+    return $obj->{'created'};
+}
+
+
+=head2 modified
+
+  Description: DEPRECATED - this attribute is not part of transcript anymore
+
+=cut
+
+sub modified{
+   my $obj = shift;
+   deprecate( "This attribute is no longer supported" );
+   if( @_ ) {
+      my $value = shift;
+      $obj->{'modified'} = $value;
+    }
+    return $obj->{'modified'};
+}
+
+
+=head2 temporary_id
+
+ Function: DEPRECATED: Use dbID or stable_id or something else instead
+
+=cut
+
+sub temporary_id{
+   my ($obj,$value) = @_;
+   deprecate( "I cant see what a temporary_id is good for, please use dbID" .
+               "or stableID or\ntry without an id." );
+   if( defined $value) {
+      $obj->{'temporary_id'} = $value;
+    }
+    return $obj->{'temporary_id'};
+}
+
+
+=head2 type
+
+  Description: DEPRECATED. Use biotype() instead.
+
+=cut
+
+sub type {
+  deprecate("Use biotype() instead");
+  biotype(@_);
+}
+
+
+=head2 confidence
+
+  Description: DEPRECATED. Use status() instead.
+
+=cut
+
+sub confidence {
+  deprecate("Use status() instead");
+  status(@_);
+}
+
+
+1;
+