Translation.pm 35.3 KB
Newer Older
1 2
=head1 LICENSE

Magali Ruffier's avatar
Magali Ruffier committed
3
Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
Tiago Grego's avatar
Tiago Grego committed
4
Copyright [2016-2019] EMBL-European Bioinformatics Institute
5

6 7 8 9 10 11 12 13 14 15 16 17 18
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

=cut
19 20 21 22 23


=head1 CONTACT

  Please email comments or questions to the public Ensembl
Magali Ruffier's avatar
Magali Ruffier committed
24
  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.
25 26

  Questions may also be sent to the Ensembl help desk at
Magali Ruffier's avatar
Magali Ruffier committed
27
  <http://www.ensembl.org/Help/Contact>.
28 29

=cut
Ewan Birney's avatar
Ewan Birney committed
30 31 32

=head1 NAME

33 34
Bio::EnsEMBL::Translation - A class representing the translation of a
transcript
Ewan Birney's avatar
Ewan Birney committed
35 36 37

=head1 SYNOPSIS

Patrick Meidl's avatar
Patrick Meidl committed
38 39 40 41 42 43 44 45 46 47 48 49
  my $translation = Bio::EnsEMBL::Translation->new(
    -START_EXON => $exon1,
    -END_EXON   => $exon2,
    -SEQ_START  => 98,
    -SEQ_END    => 39
  );

  # stable ID setter
  $translation->stable_id('ENSP00053458');

  # get start and end position in start/end exons
  my $start = $translation->start;
50
  my $end   = $translation->end;
51

Ewan Birney's avatar
Ewan Birney committed
52 53
=head1 DESCRIPTION

54
A Translation object defines the CDS and UTR regions of a Transcript
55
through the use of start_Exon/end_Exon, and start/end attributes.
Ewan Birney's avatar
Ewan Birney committed
56 57 58 59

=cut


60 61
package Bio::EnsEMBL::Translation;

Ewan Birney's avatar
Ewan Birney committed
62 63 64
use vars qw($AUTOLOAD @ISA);
use strict;

Magali Ruffier's avatar
Magali Ruffier committed
65
use Bio::EnsEMBL::Utils::Exception qw(throw warning );
66
use Bio::EnsEMBL::Utils::Argument qw( rearrange );
67
use Bio::EnsEMBL::Utils::Scalar qw( assert_ref wrap_array );
68
use Scalar::Util qw(weaken);
Ewan Birney's avatar
Ewan Birney committed
69

70
use Bio::EnsEMBL::Storable;
Ewan Birney's avatar
Ewan Birney committed
71

72
@ISA = qw(Bio::EnsEMBL::Storable);
Ewan Birney's avatar
Ewan Birney committed
73 74


75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
=head2 new

  Arg [-START_EXON] : The Exon object in which the translation (CDS) starts
  Arg [-END_EXON]   : The Exon object in which the translation (CDS) ends
  Arg [-SEQ_START]  : The offset in the start_Exon indicating the start
                      position of the CDS.
  Arg [-SEQ_END]    : The offset in the end_Exon indicating the end
                      position of the CDS.
  Arg [-STABLE_ID]  : The stable identifier for this Translation
  Arg [-VERSION]    : The version of the stable identifier
  Arg [-DBID]       : The internal identifier of this Translation
  Arg [-ADAPTOR]    : The TranslationAdaptor for this Translation
  Arg [-SEQ]        : Manually sets the peptide sequence of this translation.
                      May be useful if this translation is not stored in
                      a database.
90 91
  Arg [-CREATED_DATE]: the date the translation was created
  Arg [-MODIFIED_DATE]: the date the translation was modified
92 93 94 95 96 97 98 99 100
  Example    : my $tl = Bio::EnsEMBL::Translation->new
                   (-START_EXON => $ex1,
                    -END_EXON   => $ex2,
                    -SEQ_START  => 98,
                    -SEQ_END    => 39);
  Description: Constructor.  Creates a new Translation object
  Returntype : Bio::EnsEMBL::Translation
  Exceptions : none
  Caller     : general
101
  Status     : Stable
102 103 104

=cut

105
sub new {
Graham McVicker's avatar
Graham McVicker committed
106
  my $caller = shift;
107

Graham McVicker's avatar
Graham McVicker committed
108
  my $class = ref($caller) || $caller;
Ewan Birney's avatar
Ewan Birney committed
109

110
  my ( $start_exon, $end_exon, $seq_start, $seq_end,
111
       $stable_id, $version, $dbID, $adaptor, $seq,
112 113 114 115
       $created_date, $modified_date ) =
	   rearrange( [ "START_EXON", "END_EXON", "SEQ_START", "SEQ_END",
			"STABLE_ID", "VERSION", "DBID", "ADAPTOR",
			"SEQ", "CREATED_DATE", "MODIFIED_DATE" ], @_ );
116 117 118
      
  # Default version
  if ( !defined($version) ) { $version = 1 }
119 120 121

  my $self = bless {
		    'start_exon' => $start_exon,
122 123 124 125 126 127
		    'end_exon'   => $end_exon,
		    'dbID'       => $dbID,
		    'start'      => $seq_start,
		    'end'        => $seq_end,
		    'stable_id'  => $stable_id,
		    'version'    => $version,
128 129
		    'created_date' => $created_date,
		    'modified_date' => $modified_date,
Monika Komorowska's avatar
Monika Komorowska committed
130
                    'seq'        => $seq
131 132
		   }, $class;

Monika Komorowska's avatar
Monika Komorowska committed
133 134
  $self->adaptor($adaptor);

135
  return $self;
Ewan Birney's avatar
Ewan Birney committed
136 137
}

138 139


140 141 142 143 144 145 146
=head2 transcript

  Arg [1]       : Transcript object (optional)
  Description   : Sets or retrieves the transcript object associated
                  with this translation object.
  Exceptions    : Throws if there is no adaptor or no dbID defined for
                  the translation object.
147
  Returntype    : Bio::EnsEMBL::Transcript
148 149
=cut

150 151 152 153
sub transcript {
  my ( $self, $transcript ) = @_;

  if ( defined($transcript) ) {
154
    assert_ref( $transcript, 'Bio::EnsEMBL::Transcript' );
155 156 157

    $self->{'transcript'} = $transcript;

158
    weaken( $self->{'transcript'} );    # Avoid circular references.
159

160 161 162
  } elsif ( @_ > 1 ) {
    # Break connection to transcript.
    delete( $self->{'transcript'} );
163
  } elsif ( !defined( $self->{'transcript'} ) ) {
Monika Komorowska's avatar
Monika Komorowska committed
164
    my $adaptor = $self->adaptor;
165
    if ( !defined($adaptor) ) {
166
      throw(   "Adaptor is not set for translation, "
167
             . "can not fetch its transcript." );
168 169 170 171
    }

    my $dbID = $self->{'dbID'};
    if ( !defined($dbID) ) {
172 173
      throw(   "dbID is not set for translation, "
             . " can not fetch its transcript." );
174 175 176 177 178
    }

    $self->{'transcript'} =
      $adaptor->db()->get_TranscriptAdaptor()
      ->fetch_by_translation_id($dbID);
179

180 181 182 183
  # Do not weaken the reference if we had to get the transcript from the
  # database.  The user is probably working on translations directly,
  # not going through transcripts.
  #weaken( $self->{'transcript'} );    # Avoid circular references.
184 185 186
  }

  return $self->{'transcript'};
187
} ## end sub transcript
188

Ewan Birney's avatar
Ewan Birney committed
189 190 191

=head2 start

Patrick Meidl's avatar
Patrick Meidl committed
192 193 194 195 196
  Arg [1]    : (optional) int $start - start position to set
  Example    : $translation->start(17);
  Description: Getter/setter for the value of start, which is a position within
               the exon given by start_Exon.

197 198
               If you need genomic coordinates, use the genomic_start()
               method.
Patrick Meidl's avatar
Patrick Meidl committed
199 200 201 202
  Returntype : int
  Exceptions : none
  Caller     : general
  Status     : Stable
Ewan Birney's avatar
Ewan Birney committed
203 204 205 206 207 208 209

=cut

sub start{
   my $obj = shift;
   if( @_ ) {
      my $value = shift;
Laura Clarke's avatar
 
Laura Clarke committed
210
      
Ewan Birney's avatar
Ewan Birney committed
211 212 213 214 215 216 217
      $obj->{'start'} = $value;
    }
    return $obj->{'start'};

}


218 219
=head2 end

Patrick Meidl's avatar
Patrick Meidl committed
220 221 222 223
  Arg [1]    : (optional) int $end - end position to set
  Example    : $translation->end(8);
  Description: Getter/setter for the value of end, which is a position within
               the exon given by end_Exon.
224

225 226
               If you need genomic coordinates, use the genomic_end()
               method.
Patrick Meidl's avatar
Patrick Meidl committed
227 228 229 230
  Returntype : int
  Exceptions : none
  Caller     : general
  Status     : Stable
231 232 233 234 235 236 237

=cut

sub end {
   my $self = shift;
   if( @_ ) {
      my $value = shift;
Laura Clarke's avatar
 
Laura Clarke committed
238
      
239 240 241 242 243 244 245
      $self->{'end'} = $value;
    }
    return $self->{'end'};

}


Graham McVicker's avatar
Graham McVicker committed
246
=head2 start_Exon
247

Patrick Meidl's avatar
Patrick Meidl committed
248 249 250 251 252 253 254 255 256
  Arg [1]    : (optional) Bio::EnsEMBL::Exon - start exon to assign
  Example    : $translation->start_Exon($exon1);
  Description: Getter/setter for the value of start_Exon, which denotes the
               exon at which translation starts (and within this exon, at the
               position indicated by start, see above).
  Returntype : Bio::EnsEMBL::Exon
  Exceptions : thrown on wrong argument type
  Caller     : general
  Status     : Stable
Ewan Birney's avatar
Ewan Birney committed
257 258 259

=cut

Graham McVicker's avatar
Graham McVicker committed
260
sub start_Exon {
261
   my $self = shift;
262

Ewan Birney's avatar
Ewan Birney committed
263 264
   if( @_ ) {
      my $value = shift;
265
      if( !ref $value || !$value->isa('Bio::EnsEMBL::Exon') ) {
266
         throw("Got to have an Exon object, not a $value");
267 268
      }
      $self->{'start_exon'} = $value;
Ewan Birney's avatar
Ewan Birney committed
269
    }
270
   return $self->{'start_exon'};
Ewan Birney's avatar
Ewan Birney committed
271 272 273
}


Graham McVicker's avatar
Graham McVicker committed
274
=head2 end_Exon
275

Patrick Meidl's avatar
Patrick Meidl committed
276 277 278 279 280 281 282 283 284
  Arg [1]    : (optional) Bio::EnsEMBL::Exon - start exon to assign
  Example    : $translation->start_Exon($exon1);
  Description: Getter/setter for the value of end_Exon, which denotes the
               exon at which translation ends (and within this exon, at the
               position indicated by end, see above).
  Returntype : Bio::EnsEMBL::Exon
  Exceptions : thrown on wrong argument type
  Caller     : general
  Status     : Stable
Ewan Birney's avatar
Ewan Birney committed
285 286 287

=cut

Graham McVicker's avatar
Graham McVicker committed
288
sub end_Exon {
289
   my $self = shift;
Ewan Birney's avatar
Ewan Birney committed
290 291
   if( @_ ) {
      my $value = shift;
292
      if( !ref $value || !$value->isa('Bio::EnsEMBL::Exon') ) {
293
         throw("Got to have an Exon object, not a $value");
294 295
      }
      $self->{'end_exon'} = $value;
296
    } 
Ewan Birney's avatar
Ewan Birney committed
297

298
    return $self->{'end_exon'};
Ewan Birney's avatar
Ewan Birney committed
299 300
}

301 302
=head2 cdna_start

Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
303 304
    Arg  [1]    : (optional) Bio::EnsEMBL::Transcript $transcript
                  The transcript which this is a translation of.
305 306 307
    Example     : $translation_cdna_start = $translation->cdna_start();
    Description : Returns the start position of the translation in cDNA
                  coordinates.
Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
308 309 310
                  If no transcript is given, the method will use
                  TranscriptAdaptor->fetch_by_translation_id() to locate
                  the correct transcript.
311 312 313 314 315 316 317 318 319
    Return type : Integer
    Exceptions  : Throws if the given (optional) argument is not a
                  transcript.
    Caller      : General
    Status      : At Risk (Under Development)

=cut

sub cdna_start {
320
  my ( $self, $transcript ) = @_;
321

322 323 324 325 326 327
  if ( defined($transcript)
       && (    !ref($transcript)
            || !$transcript->isa('Bio::EnsEMBL::Transcript') ) )
  {
    throw("Argument is not a transcript");
  }
328

329 330 331 332 333
  if ( !exists( $self->{'cdna_start'} ) ) {
    if ( !defined($transcript) ) {
      # We were not given a transcript, get the transcript out of
      # the database.
      $transcript = $self->transcript();
334 335
    }

336 337 338 339 340 341
    $self->{'cdna_start'} =
      $self->start_Exon()->cdna_coding_start($transcript);
  }

  return $self->{'cdna_start'};
}
342 343 344

=head2 cdna_end

Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
345 346
    Arg  [1]    : (optional) Bio::EnsEMBL::Transcript $transcript
                  The transcript which this is a translation of.
347 348 349
    Example     : $translation_cdna_end = $translation->cdna_end();
    Description : Returns the end position of the translation in cDNA
                  coordinates.
Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
350 351 352
                  If no transcript is given, the method will use
                  TranscriptAdaptor->fetch_by_translation_id() to locate
                  the correct transcript.
353 354 355 356 357 358 359 360 361
    Return type : Integer
    Exceptions  : Throws if the given (optional) argument is not a
                  transcript.
    Caller      : General
    Status      : At Risk (Under Development)

=cut

sub cdna_end {
362
  my ( $self, $transcript ) = @_;
363

364 365 366 367 368 369
  if ( defined($transcript)
       && (    !ref($transcript)
            || !$transcript->isa('Bio::EnsEMBL::Transcript') ) )
  {
    throw("Argument is not a transcript");
  }
370

371 372 373 374 375
  if ( !exists( $self->{'cdna_end'} ) ) {
    if ( !defined($transcript) ) {
      # We were not given a transcript, get the transcript out of
      # the database.
      $transcript = $self->transcript();
376 377
    }

378 379 380 381 382 383
    $self->{'cdna_end'} =
      $self->end_Exon()->cdna_coding_end($transcript);
  }

  return $self->{'cdna_end'};
}
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442

=head2 genomic_start

    Args        : None
    Example     : $translation_genomic_start =
                      $translation->genomic_start();
    Description : Returns the start position of the translation in
                  genomic coordinates on the forward strand.
    Return type : Integer
    Exceptions  : None
    Caller      : General
    Status      : At Risk (Under Development)

=cut

sub genomic_start {
    my $self = shift;

    if ( !exists $self->{'genomic_start'} ) {
        if ( $self->start_Exon()->strand() >= 0 ) {
            $self->{'genomic_start'} =
              $self->start_Exon()->start() + ( $self->start() - 1 );
        } else {
            $self->{'genomic_start'} =
              $self->end_Exon()->end() - ( $self->end() - 1 );
        }
    }

    return $self->{'genomic_start'};
}

=head2 genomic_end

    Args        : None
    Example     : $translation_genomic_end = $translation->genomic_end();
    Description : Returns the end position of the translation in genomic
                  coordinates on the forward strand.
    Return type : Integer
    Exceptions  : None
    Caller      : General
    Status      : At Risk (Under Development)

=cut

sub genomic_end {
    my $self = shift;

    if ( !exists $self->{'genomic_end'} ) {
        if ( $self->end_Exon()->strand() >= 0 ) {
            $self->{'genomic_end'} =
              $self->end_Exon()->start() + ( $self->end() - 1 );
        } else {
            $self->{'genomic_end'} =
              $self->start_Exon()->end() - ( $self->start() - 1 );
        }
    }

    return $self->{'genomic_end'};
}
Ewan Birney's avatar
Ewan Birney committed
443

444
=head2 version
445

Patrick Meidl's avatar
Patrick Meidl committed
446 447 448
  Arg [1]    : (optional) string $version - version to set
  Example    : $translation->version(2);
  Description: Getter/setter for attribute version
449 450 451
  Returntype : string
  Exceptions : none
  Caller     : general
452
  Status     : Stable
Ewan Birney's avatar
Ewan Birney committed
453 454 455

=cut

456
sub version {
457
   my $self = shift;
458 459
  $self->{'version'} = shift if( @_ );
  return $self->{'version'};
Ewan Birney's avatar
Ewan Birney committed
460
}
461 462


463
=head2 stable_id
Graham McVicker's avatar
Graham McVicker committed
464

Patrick Meidl's avatar
Patrick Meidl committed
465 466 467
  Arg [1]    : (optional) string $stable_id - stable ID to set
  Example    : $translation->stable_id('ENSP0059890');
  Description: Getter/setter for attribute stable_id
468 469 470
  Returntype : string
  Exceptions : none
  Caller     : general
471
  Status     : Stable
472 473 474

=cut

475
sub stable_id {
476
   my $self = shift;
477 478
  $self->{'stable_id'} = shift if( @_ );
  return $self->{'stable_id'};
479 480
}

Matthew Laird's avatar
Matthew Laird committed
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
=head2 stable_id_version

  Arg [1]    : (optional) String - the stable ID with version to set
  Example    : $translation->stable_id("ENSP0059890.3");
  Description: Getter/setter for stable id with version for this translation.
  Returntype : String
  Exceptions : none
  Caller     : general
  Status     : Stable

=cut

sub stable_id_version {
    my $self = shift;
    if(my $stable_id = shift) {
	# See if there's an embedded period, assume that's a
	# version, might not work for some species but you
	# should use ->stable_id() and version() if you're worried
	# about ambiguity
	my $vindex = rindex($stable_id, '.');
	# Set the stable_id and version pair depending on if
	# we found a version delimiter in the stable_id
	($self->{stable_id}, $self->{version}) = ($vindex > 0 ?
						  (substr($stable_id,0,$vindex), substr($stable_id,$vindex+1)) :
						  $stable_id, undef);
    }
    return $self->{stable_id} . ($self->{version} ? ".$self->{version}" : '');
}

510 511
=head2 created_date

Patrick Meidl's avatar
Patrick Meidl committed
512 513 514
  Arg [1]    : (optional) string $created_date - created date to set
  Example    : $translation->created_date('2007-01-10 20:52:00');
  Description: Getter/setter for attribute created date
515 516 517 518 519 520 521
  Returntype : string
  Exceptions : none
  Caller     : general
  Status     : Stable

=cut 

522 523 524 525 526 527 528
sub created_date {
  my $self = shift;
  $self->{'created_date'} = shift if ( @_ );
  return $self->{'created_date'};
}


529 530
=head2 modified_date

Patrick Meidl's avatar
Patrick Meidl committed
531 532 533
  Arg [1]    : (optional) string $modified_date - modification date to set
  Example    : $translation->modified_date('2007-01-10 20:52:00');
  Description: Getter/setter for attribute modified date
534 535 536 537 538 539 540
  Returntype : string
  Exceptions : none
  Caller     : general
  Status     : Stable

=cut 

541 542 543 544 545 546
sub modified_date {
  my $self = shift;
  $self->{'modified_date'} = shift if ( @_ );
  return $self->{'modified_date'};
}

547

Graham McVicker's avatar
Graham McVicker committed
548

549 550
=head2 transform

Patrick Meidl's avatar
Patrick Meidl committed
551 552 553 554
  Arg [1]    : hashref $old_new_exon_map
               a hash that maps old to new exons for a whole gene
  Description: maps start end end exon according to mapping table.
              If an exon is not mapped, just keep the old one.
555
  Returntype : none
Patrick Meidl's avatar
Patrick Meidl committed
556 557
  Exceptions : none
  Caller     : Transcript->transform() 
558
  Status     : Stable
559 560 561 562 563 564 565

=cut

sub transform {
  my $self = shift;
  my $href_exons = shift;

Graham McVicker's avatar
Graham McVicker committed
566 567
  my $start_exon = $self->start_Exon();
  my $end_exon = $self->end_Exon();
568

Arne Stabenau's avatar
Arne Stabenau committed
569 570
  if ( exists $href_exons->{$start_exon} ) {
    $self->start_Exon($href_exons->{$start_exon});
571 572
  } else {
    # do nothing, the start exon wasnt mapped
573 574
  }

Arne Stabenau's avatar
Arne Stabenau committed
575 576
  if ( exists $href_exons->{$end_exon} ) {
    $self->end_Exon($href_exons->{$end_exon});
577 578
  } else { 
    # do nothing, the end exon wasnt mapped
579 580 581
  }
}

582 583 584

=head2 get_all_DBEntries

585 586 587
  Arg [1]    : (optional) String, external database name,
               SQL wildcard characters (_ and %) can be used to
               specify patterns.
588

589 590 591 592
  Arg [2]    : (optional) String, external_db type,
               ('ARRAY','ALT_TRANS','ALT_GENE','MISC','LIT','PRIMARY_DB_SYNONYM','ENSEMBL'),
               SQL wildcard characters (_ and %) can be used to
               specify patterns.
593

594 595 596
  Example    : my @dbentries = @{ $translation->get_all_DBEntries() };
               @dbentries = @{ $translation->get_all_DBEntries('Uniprot%') };
               @dbentries = @{ $translation->get_all_DBEntries('%', 'ENSEMBL') };
597 598 599 600 601 602 603 604 605

  Description: Retrieves DBEntries (xrefs) for this translation.

               This method will attempt to lazy-load DBEntries
               from a database if an adaptor is available and no
               DBEntries are present on the translation (i.e. they
               have not already been added or loaded).

  Returntype : Listref to Bio::EnsEMBL::DBEntry objects
606
  Exceptions : none
607
  Caller     : TranslationAdaptor::store
608
  Status     : Stable
609 610 611 612

=cut

sub get_all_DBEntries {
613
  my ( $self, $ex_db_exp, $ex_db_type ) = @_;
614

615
  my $cache_name = 'dbentries';
616

617
  if ( defined($ex_db_exp) ) {
618 619
    $cache_name .= $ex_db_exp;
  }
620 621

  if ( defined($ex_db_type) ) {
Ian Longden's avatar
Ian Longden committed
622
    $cache_name .= $ex_db_type;
623
  }
624

625 626 627
  # if not cached, retrieve all of the xrefs for this translation
  if ( !defined( $self->{$cache_name} ) && defined( $self->adaptor() ) )
  {
628
    $self->{$cache_name} =
629 630
      $self->adaptor()->db()->get_DBEntryAdaptor()
      ->fetch_all_by_Translation( $self, $ex_db_exp, $ex_db_type );
631 632
  }

633
  $self->{$cache_name} ||= [];
634

635
  return $self->{$cache_name};
636
} ## end sub get_all_DBEntries
637

638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
=head2 get_all_object_xrefs

  Arg [1]    : (optional) String, external database name

  Arg [2]    : (optional) String, external_db type

  Example    : @oxrefs = @{ $translation->get_all_object_xrefs() };

  Description: Retrieves xrefs for this translation.

               This method will attempt to lazy-load xrefs from a
               database if an adaptor is available and no xrefs
               are present on the translation (i.e. they have not
               already been added or loaded).

653 654
                NB: This method is an alias for the
                    get_all_DBentries() method.
655 656 657 658 659 660 661

  Return type: Listref of Bio::EnsEMBL::DBEntry objects

  Status     : Stable

=cut

662 663 664 665
sub get_all_object_xrefs {
      my $self = shift;
            return $self->get_all_DBEntries(@_);
}
666 667 668 669 670

=head2 add_DBEntry

  Arg [1]    : Bio::EnsEMBL::DBEntry $dbe
               The dbEntry to be added
Patrick Meidl's avatar
Patrick Meidl committed
671 672 673 674
  Example    : $translation->add_DBEntry($xref);
  Description: Associates a DBEntry with this translation. Note that adding
               DBEntries will prevent future lazy-loading of DBEntries for this
               translation (see get_all_DBEntries).
675 676 677
  Returntype : none
  Exceptions : thrown on incorrect argument type
  Caller     : general
678
  Status     : Stable
679 680 681 682 683 684 685 686

=cut

sub add_DBEntry {
  my $self = shift;
  my $dbe = shift;

  unless($dbe && ref($dbe) && $dbe->isa('Bio::EnsEMBL::DBEntry')) {
687
    throw('Expected DBEntry argument');
688 689 690 691 692 693 694
  }

  $self->{'dbentries'} ||= [];
  push @{$self->{'dbentries'}}, $dbe;
}


Stephen Keenan's avatar
Stephen Keenan committed
695 696
=head2 get_all_DBLinks

697 698 699 700
  Arg [1]    : String database name (optional)
               SQL wildcard characters (_ and %) can be used to
               specify patterns.

701 702 703 704 705
  Arg [2]    : (optional) String, external database type, can be one of
               ('ARRAY','ALT_TRANS','ALT_GENE','MISC','LIT','PRIMARY_DB_SYNONYM','ENSEMBL'),
               SQL wildcard characters (_ and %) can be used to
               specify patterns.

706
  Example    :  my @dblinks = @{ $translation->get_all_DBLinks() };
707 708
                @dblinks = @{ $translation->get_all_DBLinks('Uniprot%') };
                @dblinks = @{ $translation->get_all_DBLinks('%', 'ENSEMBL') };
709 710 711 712 713 714

  Description: This is here for consistancy with the Transcript
               and Gene classes.  It is a synonym for the
               get_all_DBEntries() method.

  Return type: Listref to Bio::EnsEMBL::DBEntry objects
715 716
  Exceptions : none
  Caller     : general
717
  Status     : Stable
Stephen Keenan's avatar
Stephen Keenan committed
718 719 720 721 722

=cut

sub get_all_DBLinks {
  my $self = shift;
723
  return $self->get_all_DBEntries(@_);
Stephen Keenan's avatar
Stephen Keenan committed
724 725
}

726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
=head2 get_all_xrefs

  Arg [1]    : String database name (optional)
               SQL wildcard characters (_ and %) can be used to
               specify patterns.

  Example    : @xrefs = @{ $translation->get_all_xrefs() };
               @xrefs = @{ $translation->get_all_xrefs('Uniprot%') };

  Description: This method is here for consistancy with the Gene
               and Transcript classes.  It is an alias for the
               get_all_DBLinks() method, which in turn directly
               calls get_all_DBEntries().

  Return type: Listref of Bio::EnsEMBL::DBEntry objects

  Status     : Stable

=cut

746 747 748 749
sub get_all_xrefs {
  my $self = shift;
  return $self->get_all_DBLinks(@_);
}
750

751 752 753 754 755
=head2 get_all_ProteinFeatures

  Arg [1]    : (optional) string $logic_name
               The analysis logic_name of the features to retrieve.  If not
               specified, all features are retrieved instead.
756
               If no logic_name is found, looking for analysis db name instead.
757 758 759 760 761
  Example    : $features = $self->get_all_ProteinFeatures('PFam');
  Description: Retrieves all ProteinFeatures associated with this 
               Translation. If a logic_name is specified, only features with 
               that logic_name are returned.  If no logic_name is provided all
               associated protein_features are returned.
762 763 764

               ProteinFeatures are lazy-loaded from the database unless they
               added manually to the Translation or had already been loaded.
Kieron Taylor's avatar
Kieron Taylor committed
765
  Returntype : Listref of Bio::EnsEMBL::ProteinFeature
766 767
  Exceptions : none
  Caller     : general
768
  Status     : Stable
769 770 771 772 773 774 775

=cut

sub get_all_ProteinFeatures {
  my $self = shift;
  my $logic_name = shift;

776 777 778
  my (%hash, %db_hash);
  my $no_pf = 0;

779
  if(!$self->{'protein_features'}) {
780
    $no_pf = 1;
781 782
    my $adaptor = $self->adaptor();
    my $dbID    = $self->dbID();
783 784

    return [] if (!$adaptor || !$dbID);
785 786 787 788

    $self->{'protein_features'} = \%hash;

    my $pfa = $adaptor->db()->get_ProteinFeatureAdaptor();
789
    my ($name, $ana_db);
790 791 792
    foreach my $f (@{$pfa->fetch_all_by_translation_id($dbID)}) {
      my $analysis = $f->analysis();
      if($analysis) {
793
        $name = lc($f->analysis->logic_name());
794 795
        $ana_db = lc($f->analysis->db());
        $db_hash{$ana_db} = $name;
796
      } else {
797 798
        warning("ProteinFeature has no attached analysis\n");
        $name = '';
799 800 801 802 803 804
      }
      $hash{$name} ||= [];
      push @{$hash{$name}}, $f;
    }
  }

Patrick Meidl's avatar
Patrick Meidl committed
805
  # a specific type of protein feature was requested
806 807
  if(defined($logic_name)) {
    $logic_name = lc($logic_name);
808 809 810
    if (!$hash{$logic_name} && $no_pf) {
      $logic_name = $db_hash{$logic_name};
    }
811 812 813
    return $self->{'protein_features'}->{$logic_name} || [];
  }

814
  my @features = ();
815

Patrick Meidl's avatar
Patrick Meidl committed
816
  # all protein features were requested
817 818 819 820 821 822 823 824 825 826 827 828 829 830
  foreach my $type (keys %{$self->{'protein_features'}}) {
    push @features, @{$self->{'protein_features'}->{$type}};
  }

  return \@features;    
}


=head2 get_all_DomainFeatures

  Example    : @domain_feats = @{$translation->get_all_DomainFeatures};
  Description: A convenience method which retrieves all protein features
               that are considered to be 'Domain' features.  Features which
               are 'domain' features are those with analysis logic names:
Patrick Meidl's avatar
Patrick Meidl committed
831 832
               'pfscan', 'scanprosite', 'superfamily', 'pfam', 'prints',
               'smart', 'pirsf', 'tigrfam'.
Kieron Taylor's avatar
Kieron Taylor committed
833
  Returntype : listref of Bio::EnsEMBL::ProteinFeature
834 835
  Exceptions : none
  Caller     : webcode (protview)
836
  Status     : Stable
837 838 839 840 841 842 843 844

=cut

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

 my @features;

845 846 847
 my @types = ('pfscan',      #profile (prosite or pfam motifs)
              'scanprosite', #prosite
              'superfamily',
848
              'pfam',
849 850 851
              'smart',
              'tigrfam',
              'pirsf',
852 853 854 855 856 857 858 859 860
              'prints');

 foreach my $type (@types) {
   push @features, @{$self->get_all_ProteinFeatures($type)};
 }

 return \@features;
}

861

862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892
=head2 add_ProteinFeature

  Arg [1]    : Bio::EnsEMBL::ProteinFeature $pf
               The ProteinFeature to be added
  Example    : $translation->add_ProteinFeature($pf);
  Description: Associates a ProteinFeature with this translation. Note that
               adding ProteinFeatures will prevent future lazy-loading of
               ProteinFeatures for this translation (see
               get_all_ProteinFeatures).
  Returntype : none
  Exceptions : thrown on incorrect argument type
  Caller     : general
  Status     : Stable

=cut

sub add_ProteinFeature {
  my $self = shift;
  my $pf = shift;

  unless ($pf && ref($pf) && $pf->isa('Bio::EnsEMBL::ProteinFeature')) {
    throw('Expected ProteinFeature argument');
  }

  my $analysis = $pf->analysis;
  throw("ProteinFeature has no attached Analysis.") unless $analysis;

  push @{ $self->{'protein_features'}->{$analysis->logic_name} }, $pf;
}


893 894 895 896
=head2 display_id

  Example    : print $translation->display_id();
  Description: This method returns a string that is considered to be
897 898 899
               the 'display' identifier. For translations this is (depending on
               availability and in this order) the stable Id, the dbID or an
               empty string.
900 901 902
  Returntype : string
  Exceptions : none
  Caller     : web drawing code
903
  Status     : Stable
904 905 906 907 908

=cut

sub display_id {
  my $self = shift;
909
  return $self->{'stable_id'} || $self->dbID || '';
910 911 912
}


913 914 915 916 917 918 919 920
=head2 length

  Example    : print "Peptide length =", $translation->length();
  Description: Retrieves the length of the peptide sequence (i.e. number of
               amino acids) represented by this Translation object.
  Returntype : int
  Exceptions : none
  Caller     : webcode (protview etc.)
921
  Status     : Stable
922 923 924

=cut

Web Admin's avatar
Web Admin committed
925
sub length {
926 927
  my $self = shift;
  my $seq = $self->seq();
Web Admin's avatar
testing  
Web Admin committed
928

929
  return ($seq) ? CORE::length($seq) : 0;
930 931 932 933 934 935 936 937 938
}


=head2 seq

  Example    : print $translation->seq();
  Description: Retrieves a string representation of the peptide sequence
               of this Translation.  This retrieves the transcript from the
               database and gets its sequence, or retrieves the sequence which
Patrick Meidl's avatar
Patrick Meidl committed
939
               was set via the constructor.
940 941 942 943
  Returntype : string
  Exceptions : warning if the sequence is not set and cannot be retrieved from
               the database.
  Caller     : webcode (protview etc.)
944
  Status     : Stable
945 946 947 948

=cut

sub seq {
Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
949
  my ( $self, $sequence ) = @_;
950

Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
951
  if ( defined($sequence) ) {
952

Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
953
    $self->{'seq'} = $sequence;
954

Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
955
  } elsif ( !defined( $self->{'seq'} ) ) {
956

957
    my $transcript = $self->transcript();
Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
958

959
    my $canonical_translation = $transcript->translation();
960
    my $is_alternative;
961 962 963
    if(!$canonical_translation) {
	throw "Transcript does not have a canonical translation";
    }
964 965 966
    if (    defined( $canonical_translation->stable_id() )
         && defined( $self->stable_id() ) )
    {
967
      # Try stable ID.
968 969
      $is_alternative =
        ( $canonical_translation->stable_id() ne $self->stable_id() );
970 971 972 973
    } elsif (    defined( $canonical_translation->dbID() )
              && defined( $self->dbID() ) )
    {
      # Try dbID.
974 975
      $is_alternative =
        ( $canonical_translation->dbID() != $self->dbID() );
976 977 978 979 980 981
    } else {
      # Resort to using geomic start/end coordinates.
      $is_alternative = ( ($canonical_translation->genomic_start() !=
                             $self->genomic_start() )
                           || ( $canonical_translation->genomic_end() !=
                                $self->genomic_end() ) );
982
    }
Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
983

984 985 986 987
    if ($is_alternative) {
      # To deal with non-canonical (alternative) translations, subsitute
      # the canonical translation in the transcript with $self for a
      # while.
Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
988

989 990 991 992
      $transcript->translation($self);
    }

    my $seq = $transcript->translate();
Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
993 994 995
    if ( defined($seq) ) {
      $self->{'seq'} = $seq->seq();
    }
996

997 998 999 1000 1001 1002 1003
    if ($is_alternative) {
      # Reinstate the real canonical translation.

      $transcript->translation($canonical_translation);
    }

  } ## end elsif ( !defined( $self->...))
Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
1004 1005 1006

  if ( !defined( $self->{'seq'} ) ) {
    return '';    # Empty string
1007
  }
Andreas Kusalananda Kähäri's avatar
Andreas Kusalananda Kähäri committed
1008 1009 1010 1011

  return $self->{'seq'};

} ## end sub seq
1012

Patrick Meidl's avatar
Patrick Meidl committed
1013

1014 1015 1016 1017
=head2 get_all_Attributes

  Arg [1]    : optional string $attrib_code
               The code of the attribute type to retrieve values for.
1018
  Example    : ($sc_attr) = @{$tl->get_all_Attributes('_selenocysteine')};
1019
               @tl_attributes = @{$translation->get_all_Attributes()};
1020 1021
  Description: Gets a list of Attributes of this translation.
               Optionally just get Attrubutes for given code.
1022
               Recognized attribute "_selenocysteine"
1023 1024 1025 1026
  Returntype : listref Bio::EnsEMBL::Attribute
  Exceptions : warning if translation does not have attached adaptor and 
               attempts lazy load.
  Caller     : general, modify_translation
1027
  Status     : Stable
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040

=cut

sub get_all_Attributes {
  my $self = shift;
  my $attrib_code = shift;

  if( ! exists $self->{'attributes' } ) {
    if(!$self->adaptor() ) {
#      warning('Cannot get attributes without an adaptor.');
      return [];
    }

1041 1042
    my $aa = $self->adaptor->db->get_AttributeAdaptor();
    $self->{'attributes'} = $aa->fetch_all_by_Translation( $self );
1043 1044 1045
  }

  if( defined $attrib_code ) {
1046