Translation.pm 27.8 KB
Newer Older
Patrick Meidl's avatar
Patrick Meidl committed
1
package Bio::EnsEMBL::Translation;
Ewan Birney's avatar
Ewan Birney committed
2
3
4

=head1 NAME

5
6
Bio::EnsEMBL::Translation - A class representing the translation of a
transcript
Ewan Birney's avatar
Ewan Birney committed
7
8
9

=head1 SYNOPSIS

Patrick Meidl's avatar
Patrick Meidl committed
10
11
12
13
14
15
16
17
18
19
20
21
22
  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;
  my $end = $translation->end;
23

Ewan Birney's avatar
Ewan Birney committed
24
25
=head1 DESCRIPTION

26
A Translation object defines the CDS and UTR regions of a Transcript
27
through the use of start_Exon/end_Exon, and start/end attributes.
Ewan Birney's avatar
Ewan Birney committed
28

Patrick Meidl's avatar
Patrick Meidl committed
29
30
31
32
=head1 LICENCE

This code is distributed under an Apache style licence. Please see
http://www.ensembl.org/info/about/code_licence.html for details.
Ewan Birney's avatar
Ewan Birney committed
33

Patrick Meidl's avatar
Patrick Meidl committed
34
=head1 AUTHOR
Ewan Birney's avatar
Ewan Birney committed
35

Patrick Meidl's avatar
Patrick Meidl committed
36
37
38
39
40
41
Ensembl core API team

=head1 CONTACT

Please post comments/questions to the Ensembl development list
<ensembl-dev@ebi.ac.uk>
Ewan Birney's avatar
Ewan Birney committed
42
43
44
45
46
47
48

=cut


use vars qw($AUTOLOAD @ISA);
use strict;

49
50
use Bio::EnsEMBL::Utils::Exception qw( deprecate throw warning );
use Bio::EnsEMBL::Utils::Argument qw( rearrange );
Ewan Birney's avatar
Ewan Birney committed
51

52
use Bio::EnsEMBL::Storable;
Ewan Birney's avatar
Ewan Birney committed
53

54
@ISA = qw(Bio::EnsEMBL::Storable);
Ewan Birney's avatar
Ewan Birney committed
55
56


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
=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.
72
73
  Arg [-CREATED_DATE]: the date the translation was created
  Arg [-MODIFIED_DATE]: the date the translation was modified
74
75
76
77
78
79
80
81
82
  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
83
  Status     : Stable
84
85
86

=cut

87
sub new {
Graham McVicker's avatar
Graham McVicker committed
88
  my $caller = shift;
89

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

92
  my ( $start_exon, $end_exon, $seq_start, $seq_end,
93
94
       $stable_id, $version, $dbID, $adaptor, $seq,
       $created_date, $modified_date ) = 
95
    rearrange( [ "START_EXON", "END_EXON", "SEQ_START", "SEQ_END",
96
                 "STABLE_ID", "VERSION", "DBID", "ADAPTOR",
97
                 "SEQ", "CREATED_DATE", "MODIFIED_DATE" ], @_ );
98
99
100

  my $self = bless {
		    'start_exon' => $start_exon,
101
102
103
104
105
106
107
		    'end_exon'   => $end_exon,
		    'adaptor'    => $adaptor,
		    'dbID'       => $dbID,
		    'start'      => $seq_start,
		    'end'        => $seq_end,
		    'stable_id'  => $stable_id,
		    'version'    => $version,
108
109
		    'created_date' => $created_date,
		    'modified_date' => $modified_date,
110
        'seq'        => $seq
111
112
113
		   }, $class;

  return $self;
Ewan Birney's avatar
Ewan Birney committed
114
115
116
117
118
}


=head2 start

Patrick Meidl's avatar
Patrick Meidl committed
119
120
121
122
123
  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.

124
125
               If you need genomic coordinates, use the genomic_start()
               method.
Patrick Meidl's avatar
Patrick Meidl committed
126
127
128
129
  Returntype : int
  Exceptions : none
  Caller     : general
  Status     : Stable
Ewan Birney's avatar
Ewan Birney committed
130
131
132
133
134
135
136

=cut

sub start{
   my $obj = shift;
   if( @_ ) {
      my $value = shift;
Laura Clarke's avatar
 
Laura Clarke committed
137
      
Ewan Birney's avatar
Ewan Birney committed
138
139
140
141
142
143
144
      $obj->{'start'} = $value;
    }
    return $obj->{'start'};

}


145
146
=head2 end

Patrick Meidl's avatar
Patrick Meidl committed
147
148
149
150
  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.
151

152
153
               If you need genomic coordinates, use the genomic_end()
               method.
Patrick Meidl's avatar
Patrick Meidl committed
154
155
156
157
  Returntype : int
  Exceptions : none
  Caller     : general
  Status     : Stable
158
159
160
161
162
163
164

=cut

sub end {
   my $self = shift;
   if( @_ ) {
      my $value = shift;
Laura Clarke's avatar
 
Laura Clarke committed
165
      
166
167
168
169
170
171
172
      $self->{'end'} = $value;
    }
    return $self->{'end'};

}


Graham McVicker's avatar
Graham McVicker committed
173
=head2 start_Exon
174

Patrick Meidl's avatar
Patrick Meidl committed
175
176
177
178
179
180
181
182
183
  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
184
185
186

=cut

Graham McVicker's avatar
Graham McVicker committed
187
sub start_Exon {
188
   my $self = shift;
189

Ewan Birney's avatar
Ewan Birney committed
190
191
   if( @_ ) {
      my $value = shift;
192
      if( !ref $value || !$value->isa('Bio::EnsEMBL::Exon') ) {
193
         throw("Got to have an Exon object, not a $value");
194
195
      }
      $self->{'start_exon'} = $value;
Ewan Birney's avatar
Ewan Birney committed
196
    }
197
   return $self->{'start_exon'};
Ewan Birney's avatar
Ewan Birney committed
198
199
200
}


Graham McVicker's avatar
Graham McVicker committed
201
=head2 end_Exon
202

Patrick Meidl's avatar
Patrick Meidl committed
203
204
205
206
207
208
209
210
211
  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
212
213
214

=cut

Graham McVicker's avatar
Graham McVicker committed
215
sub end_Exon {
216
   my $self = shift;
Ewan Birney's avatar
Ewan Birney committed
217
218
   if( @_ ) {
      my $value = shift;
219
      if( !ref $value || !$value->isa('Bio::EnsEMBL::Exon') ) {
220
         throw("Got to have an Exon object, not a $value");
221
222
      }
      $self->{'end_exon'} = $value;
223
    } 
Ewan Birney's avatar
Ewan Birney committed
224

225
    return $self->{'end_exon'};
Ewan Birney's avatar
Ewan Birney committed
226
227
}

228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
=head2 cdna_start

    Arg  [1]    : Bio::EnsEMBL::Transcript (optional).  The
                  transcript which this is a translation of.  If
                  no transcript is given, the method will use
                  TranscriptAdaptor->fetch_by_translation_id() to locate
                  the correct transcript.
    Example     : $translation_cdna_start = $translation->cdna_start();
    Description : Returns the start position of the translation in cDNA
                  coordinates.
    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 {
    my $self = shift;
    my ($transcript) = @_;

    if ( defined $transcript
         && (    !ref $transcript
              || !$transcript->isa('Bio::EnsEMBL::Transcript') )
      ) {
        throw("Argument is not a transcript");
    }

    if ( !exists $self->{'cdna_start'} ) {
        if ( !defined $transcript ) {
            # We were not given a transcript, get the transcript out of
            # the database.

            my $transcript_adaptor =
              $self->adaptor()->db()->get_TranscriptAdaptor();

            $transcript =
              $transcript_adaptor->fetch_by_translation_id(
                                                        $self->dbID() );
        }

        $self->{'cdna_start'} =
          $self->start_Exon()->cdna_coding_start($transcript);
    }

    return $self->{'cdna_start'};
} ## end sub cdna_start

=head2 cdna_end

    Arg  [1]    : Bio::EnsEMBL::Transcript (optional).  The
                  transcript which this is a translation of.  If
                  no transcript is given, the method will use
                  TranscriptAdaptor->fetch_by_translation_id() to locate
                  the correct transcript.
    Example     : $translation_cdna_end = $translation->cdna_end();
    Description : Returns the end position of the translation in cDNA
                  coordinates.
    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 {
    my $self = shift;
    my ($transcript) = @_;

    if ( defined $transcript
         && (    !ref $transcript
              || !$transcript->isa('Bio::EnsEMBL::Transcript') )
      ) {
        throw("Argument is not a transcript");
    }

    if ( !exists $self->{'cdna_end'} ) {
        if ( !defined $transcript ) {
            # We were not given a transcript, get the transcript out of
            # the database.

            my $transcript_adaptor =
              $self->adaptor()->db()->get_TranscriptAdaptor();

            $transcript =
              $transcript_adaptor->fetch_by_translation_id(
                                                        $self->dbID() );
        }

        $self->{'cdna_end'} =
          $self->end_Exon()->cdna_coding_end($transcript);
    }

    return $self->{'cdna_end'};
} ## end sub cdna_end

=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
384

385
=head2 version
386

Patrick Meidl's avatar
Patrick Meidl committed
387
388
389
  Arg [1]    : (optional) string $version - version to set
  Example    : $translation->version(2);
  Description: Getter/setter for attribute version
390
391
392
  Returntype : string
  Exceptions : none
  Caller     : general
393
  Status     : Stable
Ewan Birney's avatar
Ewan Birney committed
394
395
396

=cut

397
sub version {
398
   my $self = shift;
399
400
  $self->{'version'} = shift if( @_ );
  return $self->{'version'};
Ewan Birney's avatar
Ewan Birney committed
401
}
402
403


404
=head2 stable_id
Graham McVicker's avatar
Graham McVicker committed
405

Patrick Meidl's avatar
Patrick Meidl committed
406
407
408
  Arg [1]    : (optional) string $stable_id - stable ID to set
  Example    : $translation->stable_id('ENSP0059890');
  Description: Getter/setter for attribute stable_id
409
410
411
  Returntype : string
  Exceptions : none
  Caller     : general
412
  Status     : Stable
413
414
415

=cut

416
sub stable_id {
417
   my $self = shift;
418
419
  $self->{'stable_id'} = shift if( @_ );
  return $self->{'stable_id'};
420
421
}

422
423
=head2 created_date

Patrick Meidl's avatar
Patrick Meidl committed
424
425
426
  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
427
428
429
430
431
432
433
  Returntype : string
  Exceptions : none
  Caller     : general
  Status     : Stable

=cut 

434
435
436
437
438
439
440
sub created_date {
  my $self = shift;
  $self->{'created_date'} = shift if ( @_ );
  return $self->{'created_date'};
}


441
442
=head2 modified_date

Patrick Meidl's avatar
Patrick Meidl committed
443
444
445
  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
446
447
448
449
450
451
452
  Returntype : string
  Exceptions : none
  Caller     : general
  Status     : Stable

=cut 

453
454
455
456
457
458
sub modified_date {
  my $self = shift;
  $self->{'modified_date'} = shift if ( @_ );
  return $self->{'modified_date'};
}

459

Graham McVicker's avatar
Graham McVicker committed
460

461
462
=head2 transform

Patrick Meidl's avatar
Patrick Meidl committed
463
464
465
466
  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.
467
  Returntype: none
Patrick Meidl's avatar
Patrick Meidl committed
468
469
  Exceptions : none
  Caller     : Transcript->transform() 
470
  Status     : Stable
471
472
473
474
475
476
477

=cut

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

Graham McVicker's avatar
Graham McVicker committed
478
479
  my $start_exon = $self->start_Exon();
  my $end_exon = $self->end_Exon();
480

Arne Stabenau's avatar
Arne Stabenau committed
481
482
  if ( exists $href_exons->{$start_exon} ) {
    $self->start_Exon($href_exons->{$start_exon});
483
484
  } else {
    # do nothing, the start exon wasnt mapped
485
486
  }

Arne Stabenau's avatar
Arne Stabenau committed
487
488
  if ( exists $href_exons->{$end_exon} ) {
    $self->end_Exon($href_exons->{$end_exon});
489
490
  } else { 
    # do nothing, the end exon wasnt mapped
491
492
493
  }
}

494
495
496

=head2 get_all_DBEntries

Patrick Meidl's avatar
Patrick Meidl committed
497
498
  Arg [1]    : (optional) $ex_db_exp - external db name
  Example    : @dbentries = @{$translation->get_all_DBEntries()};
499
500
501
502
503
504
505
506
507
  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 : list reference to Bio::EnsEMBL::DBEntry objects
  Exceptions : none
  Caller     : get_all_DBLinks, TranslationAdaptor::store
508
  Status     : Stable
509
510
511
512
513

=cut

sub get_all_DBEntries {
  my $self = shift;
514
515
516
517
518
519
520
  my $ex_db_exp = shift;

  my $cache_name = "dbentries";

  if(defined($ex_db_exp)){
    $cache_name .= $ex_db_exp;
  }
521

Patrick Meidl's avatar
Patrick Meidl committed
522
  # if not cached, retrieve all of the xrefs for this gene
523
  if(!defined $self->{$cache_name}) {
524
525
    my $adaptor = $self->adaptor();
    my $dbID    = $self->dbID();
Graham McVicker's avatar
Graham McVicker committed
526
527
528

    return [] if(!$adaptor || !$dbID);

529
530
    $self->{$cache_name} =
      $self->adaptor->db->get_DBEntryAdaptor->fetch_all_by_Translation($self, $ex_db_exp);
531
532
  }

533
  $self->{$cache_name} ||= [];
534

535
  return $self->{$cache_name};
536
537
538
539
540
541
542
}


=head2 add_DBEntry

  Arg [1]    : Bio::EnsEMBL::DBEntry $dbe
               The dbEntry to be added
Patrick Meidl's avatar
Patrick Meidl committed
543
544
545
546
  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).
547
548
549
  Returntype : none
  Exceptions : thrown on incorrect argument type
  Caller     : general
550
  Status     : Stable
551
552
553
554
555
556
557
558

=cut

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

  unless($dbe && ref($dbe) && $dbe->isa('Bio::EnsEMBL::DBEntry')) {
559
    throw('Expected DBEntry argument');
560
561
562
563
564
565
566
  }

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


Stephen Keenan's avatar
Stephen Keenan committed
567
568
=head2 get_all_DBLinks

569
570
571
  Arg [1]    : see get_all_DBEntries
  Example    : see get_all_DBEntries
  Description: This is here for consistancy with the Transcript and Gene 
Patrick Meidl's avatar
Patrick Meidl committed
572
               classes. It is a synonym for the get_all_DBEntries method.
573
574
575
  Returntype : see get_all_DBEntries
  Exceptions : none
  Caller     : general
576
  Status     : Stable
Stephen Keenan's avatar
Stephen Keenan committed
577
578
579
580
581

=cut

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

585

586
587
588
589
590
591
592
593
594
595
=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.
  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.
596
597
598

               ProteinFeatures are lazy-loaded from the database unless they
               added manually to the Translation or had already been loaded.
599
600
601
  Returntype : Bio::EnsEMBL::ProteinFeature
  Exceptions : none
  Caller     : general
602
  Status     : Stable
603
604
605
606
607
608
609
610
611
612

=cut

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

  if(!$self->{'protein_features'}) {
    my $adaptor = $self->adaptor();
    my $dbID    = $self->dbID();
613
614

    return [] if (!$adaptor || !$dbID);
615
616
617
618
619
620
621
622
623

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

    my $pfa = $adaptor->db()->get_ProteinFeatureAdaptor();
    my $name;
    foreach my $f (@{$pfa->fetch_all_by_translation_id($dbID)}) {
      my $analysis = $f->analysis();
      if($analysis) {
624
        $name = lc($f->analysis->logic_name());
625
      } else {
626
627
        warning("ProteinFeature has no attached analysis\n");
        $name = '';
628
629
630
631
632
633
      }
      $hash{$name} ||= [];
      push @{$hash{$name}}, $f;
    }
  }

Patrick Meidl's avatar
Patrick Meidl committed
634
  # a specific type of protein feature was requested
635
636
637
638
639
  if(defined($logic_name)) {
    $logic_name = lc($logic_name);
    return $self->{'protein_features'}->{$logic_name} || [];
  }

640
  my @features = ();
641

Patrick Meidl's avatar
Patrick Meidl committed
642
  # all protein features were requested
643
644
645
646
647
648
649
650
651
652
653
654
655
656
  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
657
658
               'pfscan', 'scanprosite', 'superfamily', 'pfam', 'prints',
               'smart', 'pirsf', 'tigrfam'.
659
660
661
  Returntype : listref of Bio::EnsEMBL::ProteinFeatures
  Exceptions : none
  Caller     : webcode (protview)
662
  Status     : Stable
663
664
665
666
667
668
669
670

=cut

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

 my @features;

671
672
673
 my @types = ('pfscan',      #profile (prosite or pfam motifs)
              'scanprosite', #prosite
              'superfamily',
674
              'pfam',
675
676
677
              'smart',
              'tigrfam',
              'pirsf',
678
679
680
681
682
683
684
685
686
              'prints');

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

 return \@features;
}

687

688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
=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;
}


719
720
721
722
=head2 display_id

  Example    : print $translation->display_id();
  Description: This method returns a string that is considered to be
723
724
725
               the 'display' identifier. For translations this is (depending on
               availability and in this order) the stable Id, the dbID or an
               empty string.
726
727
728
  Returntype : string
  Exceptions : none
  Caller     : web drawing code
729
  Status     : Stable
730
731
732
733
734

=cut

sub display_id {
  my $self = shift;
735
  return $self->{'stable_id'} || $self->dbID || '';
736
737
738
}


739
740
741
742
743
744
745
746
=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.)
747
  Status     : Stable
748
749
750

=cut

Web Admin's avatar
Web Admin committed
751
sub length {
752
753
  my $self = shift;
  my $seq = $self->seq();
Web Admin's avatar
testing  
Web Admin committed
754

755
  return ($seq) ? CORE::length($seq) : 0;
756
757
758
759
760
761
762
763
764
}


=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
765
               was set via the constructor.
766
767
768
769
  Returntype : string
  Exceptions : warning if the sequence is not set and cannot be retrieved from
               the database.
  Caller     : webcode (protview etc.)
770
  Status     : Stable
771
772
773
774
775
776

=cut

sub seq {
  my $self = shift;

777
778
779
780
781
  if(@_) {
    $self->{'seq'} = shift;
    return $self->{'seq'};
  }

782
783
784
785
786
787
788
789
790
  return $self->{'seq'} if($self->{'seq'});

  my $adaptor = $self->{'adaptor'};
  if(!$adaptor) {
    warning("Cannot retrieve sequence from Translation - adaptor is not set.");
  }

  my $dbID = $self->{'dbID'};
  if(!$dbID) {
791
    warning("Cannot retrieve sequence from Translation - dbID is not set.");
792
793
794
795
796
  }
  
  my $tr_adaptor = $self->{'adaptor'}->db()->get_TranscriptAdaptor;

  my $seq = $tr_adaptor->fetch_by_translation_id($dbID)->translate();
797
798
799
800
801
802
803
  if($seq){
    $self->{'seq'} = $seq->seq();
    return $self->{'seq'};
  }
  else{
    return ''; #empty string
  }
804
805
}

Patrick Meidl's avatar
Patrick Meidl committed
806

807
808
809
810
=head2 get_all_Attributes

  Arg [1]    : optional string $attrib_code
               The code of the attribute type to retrieve values for.
811
  Example    : ($sc_attr) = @{$tl->get_all_Attributes('_selenocysteine')};
812
               @tl_attributes = @{$translation->get_all_Attributes()};
813
814
  Description: Gets a list of Attributes of this translation.
               Optionally just get Attrubutes for given code.
815
               Recognized attribute "_selenocysteine"
816
817
818
819
  Returntype : listref Bio::EnsEMBL::Attribute
  Exceptions : warning if translation does not have attached adaptor and 
               attempts lazy load.
  Caller     : general, modify_translation
820
  Status     : Stable
821
822
823
824
825
826
827
828
829
830
831
832
833

=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 [];
    }

834
835
    my $aa = $self->adaptor->db->get_AttributeAdaptor();
    $self->{'attributes'} = $aa->fetch_all_by_Translation( $self );
836
837
838
  }

  if( defined $attrib_code ) {
839
    my @results = grep { uc($_->code()) eq uc($attrib_code) }
840
841
842
843
844
845
846
847
848
849
    @{$self->{'attributes'}};
    return \@results;
  } else {
    return $self->{'attributes'};
  }
}


=head2 add_Attributes

Patrick Meidl's avatar
Patrick Meidl committed
850
851
  Arg [1..N] : Bio::EnsEMBL::Attribute $attribute
               Attributes to add.
852
  Example    : $translation->add_Attributes($selenocysteine_attribute);
853
  Description: Adds an Attribute to the Translation. Usefull to 
854
               do _selenocysteine.
855
856
               If you add an attribute before you retrieve any from database, 
               lazy load will be disabled.
857
  Returntype : none
858
  Exceptions : throw on incorrect arguments
859
  Caller     : general
860
  Status     : Stable
861
862
863
864
865
866
867
868
869
870
871
872
873

=cut

sub add_Attributes {
  my $self = shift;
  my @attribs = @_;

  if( ! exists $self->{'attributes'} ) {
    $self->{'attributes'} = [];
  }

  for my $attrib ( @attribs ) {
    if( ! $attrib->isa( "Bio::EnsEMBL::Attribute" )) {
874
      throw( "Argument to add_Attribute must be a Bio::EnsEMBL::Attribute" );
875
876
877
878
879
    }
    push( @{$self->{'attributes'}}, $attrib );
  }
}

Patrick Meidl's avatar
Patrick Meidl committed
880

881
=head2 get_all_SeqEdits
882

883
884
885
886
887
888
  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()
889
  Status     : Stable
890
891
892

=cut

893
sub get_all_SeqEdits {
894
895
  my $self = shift;

896
  my @seqeds;
897

898
899
900
901
902
903
904
  my $attribs;
  
  my @edits = ('initial_met', '_selenocysteine');
  

  foreach my $edit(@edits){
    $attribs = $self->get_all_Attributes($edit);
905

906
907
908
909
    # convert attributes to SeqEdit objects
    foreach my $a (@$attribs) {
      push @seqeds, Bio::EnsEMBL::SeqEdit->new(-ATTRIB => $a);
    }
910
  }
911

912
913
  return \@seqeds;
}
Patrick Meidl's avatar
Patrick Meidl committed
914
  
915
916
917

=head2 modify_translation

Patrick Meidl's avatar
Patrick Meidl committed
918
  Arg [1]    : Bio::Seq $peptide 
919
920
  Example    : my $seq = Bio::Seq->new(-SEQ => $dna)->translate();
               $translation->modify_translation($seq);
921
  Description: Applies sequence edits such as selenocysteines to the Bio::Seq 
922
               peptide thats passed in
923
  Returntype : Bio::Seq
Patrick Meidl's avatar
Patrick Meidl committed
924
  Exceptions : none
925
  Caller     : Bio::EnsEMBL::Transcript->translate
926
  Status     : Stable
927
928
929
930
931
932

=cut

sub modify_translation {
  my ($self, $seq) = @_;

933
  my @seqeds = @{$self->get_all_SeqEdits()};
934

935
936
  # sort in reverse order to avoid complication of adjusting downstream edits
  @seqeds = sort {$b <=> $a} @seqeds;
937

938
939
940
941
  # apply all edits
  my $peptide = $seq->seq();
  foreach my $se (@seqeds) {
    $se->apply_edit(\$peptide);
942
  }
943
  $seq->seq($peptide);
944
945
946
947
948

  return $seq;
}


949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
=head2 temporary_id

  Description: DEPRECATED This method should not be needed. Use dbID,
               stable_id or something else.

=cut

sub temporary_id {
   my $self = shift;
   deprecate( "I cant see what a temporary_id is good for, please use " .
               "dbID or stableID or\n try without an id." );
  $self->{'temporary_id'} = shift if( @_ );
  return $self->{'temporary_id'};
}


965
966
967
=head2 get_all_DASFactories

  Function  : Retrieves a listref of registered DAS objects
Patrick Meidl's avatar
Patrick Meidl committed
968
969
  Returntype: DAS objects
  Exceptions: none
970
  Caller    : webcode
Patrick Meidl's avatar
Patrick Meidl committed
971
972
  Example   : $dasref = $prot->get_all_DASFactories;
  Status    : Stable
973
974
975
976
977
978
979
980
981

=cut

sub get_all_DASFactories {
   my $self = shift;
   return [ $self->adaptor()->db()->_each_DASFeatureFactory ];
}


982
983
984
985
986
987
988
989
990
=head2 get_all_DAS_Features

  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
Patrick Meidl's avatar
Patrick Meidl committed
991
  Exceptions : none
992
  Caller     : webcode
993
  Status     : Stable
994
995
996
997

=cut

sub get_all_DAS_Features{
Patrick Meidl's avatar
Patrick Meidl committed
998
  my $self = shift;
999
1000
1001
1002
1003
  $self->{_das_features} ||= {}; # Cache
  my %das_features;

  my $db = $self->adaptor->db;
  my $GeneAdaptor = $db->get_GeneAdaptor;
1004
  my $Gene = $GeneAdaptor->fetch_by_translation_stable_id($self->stable_id) || return;
1005
  my $slice = $Gene->feature_Slice;
1006
1007
 
  return $self->SUPER::get_all_DAS_Features($slice);
1008
1009
1010

  foreach my $dasfact( @{$self->get_all_DASFactories} ){
    my $dsn = $dasfact->adaptor->dsn;
1011
    my $name = $dasfact->adaptor->name;
1012
    my $type = $dasfact->adaptor->type;
1013
    my $url = $dasfact->adaptor->url;
1014

1015
1016
# Construct a cache key : SOURCE_URL/TYPE
# Need the type to handle sources that serve multiple types of features
1017

1018
1019
    my $key = $url || $dasfact->adaptor->protocol .'://'.$dasfact->adaptor->domain;
    $key .= "/$dsn/$type";
1020

1021
1022
1023
    if( $self->{_das_features}->{$key} ){ # Use cached
	$das_features{$name} = $self->{_das_features}->{$key};
	next;
1024
    } else{ # Get fresh data
1025
1026
#	my $featref = ($type eq 'ensembl_location') ?  ($dasfact->fetch_all_by_Slice( $slice ))[0] : $dasfact->fetch_all_by_ID( $self );
	my $featref = ($type =~ /^ensembl_location/) ?  ($dasfact->fetch_all_Features( $slice, $type ))[0] : $dasfact->fetch_all_by_ID( $self );
1027
1028
1029
	$self->{_das_features}->{$key} = $featref;
	$das_features{$name} = $featref;
    }
1030
1031
1032
1033
  }
  return \%das_features;
}

1034
=head2 get_all_regulatory_features
1035

Glenn Proctor's avatar
Glenn Proctor committed
1036
  Example    : @features = $translation->get_all_regulatory_features();
Patrick Meidl's avatar
Patrick Meidl committed
1037
1038
  Description: Gets all the regulatory features associated with this
               translation.
1039
1040
1041
               Each feature only appears once.
  Returntype : Listref of Bio::EnsEMBL::RegulatoryFeature
  Exceptions : If arg is not of correct type.
Patrick Meidl's avatar
Patrick Meidl committed
1042
  Caller     : general
1043
1044
1045
  Status     : At Risk
             : Regulatory features are currently under development and are 
             : likely to change.
1046
1047
1048

=cut

1049
sub get_all_regulatory_features {
1050
1051
1052
1053
1054
1055
1056
   my ($self) = @_;

   my $rfa = $self->adaptor->db->get_RegulatoryFeatureAdaptor();

   return $rfa->fetch_all_by_translation($self);
}

1057
1;