ensembl-hive  2.7.0
Exon.pm
Go to the documentation of this file.
1 =head1 LICENSE
2 
3 See the NOTICE file distributed with this work for additional information
4 regarding copyright ownership.
5 
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 
18 =cut
19 
20 
21 =head1 CONTACT
22 
23  Please email comments or questions to the public Ensembl
24  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.
25 
26  Questions may also be sent to the Ensembl help desk at
27  <http://www.ensembl.org/Help/Contact>.
28 
29 =cut
30 
31 =head1 NAME
32 
33 Bio::EnsEMBL::Exon - A class representing an Exon
34 
35 =head1 SYNOPSIS
36 
37  $exon = new Bio::EnsEMBL::Exon(
38  -START => 100,
39  -END => 200,
40  -STRAND => 1,
41  -SLICE => $slice,
42  -DBID => $dbID,
43  -ANALYSIS => $analysis,
44  -STABLE_ID => 'ENSE000000123',
45  -VERSION => 2
46  );
47 
48  # seq() returns a Bio::Seq
49  my $seq = $exon->seq->seq();
50 
51  # Peptide only makes sense within transcript context
52  my $pep = $exon->peptide($transcript)->seq();
53 
54  # Normal feature operations can be performed:
55  $exon = $exon->transform('clone');
56  $exon->move( $new_start, $new_end, $new_strand );
57  print $exon->slice->seq_region_name();
58 
59 =head1 DESCRIPTION
60 
61 This is a class which represents an exon which is part of a transcript.
63 
64 =head1 METHODS
65 
66 =cut
67 
68 package Bio::EnsEMBL::Exon;
69 
70 use strict;
71 
73 use Bio::Seq; # exons have to have sequences...
74 
75 use Bio::EnsEMBL::Utils::Exception qw( warning throw);
76 use Bio::EnsEMBL::Utils::Argument qw( rearrange );
77 use Bio::EnsEMBL::Utils::Scalar qw( assert_ref );
79 
80 use vars qw(@ISA);
81 @ISA = qw(Bio::EnsEMBL::Feature);
82 
83 use constant SEQUENCE_ONTOLOGY => {
84  acc => 'SO:0000147',
85  term => 'exon',
86 };
87 
88 =head2 new
89 
90  Arg [-SLICE]: Bio::EnsEMBL::SLice - Represents the sequence that this
91  feature is on. The coordinates of the created feature are
92  relative to the start of the slice.
93  Arg [-START]: The start coordinate of this feature relative to the start
94  of the slice it is sitting on. Coordinates start at 1 and
95  are inclusive.
96  Arg [-END] : The end coordinate of this feature relative to the start of
97  the slice it is sitting on. Coordinates start at 1 and are
98  inclusive.
99  Arg [-STRAND]: The orientation of this feature. Valid values are 1,-1,0.
100  Arg [-SEQNAME] : (optional) A seqname to be used instead of the default name
101  of the of the slice. Useful for features that do not have an
102  attached slice such as protein features.
103  Arg [-dbID] : (optional) internal database id
104  Arg [-ADAPTOR]: (optional) Bio::EnsEMBL::DBSQL::BaseAdaptor
105  Arg [-PHASE] : the phase.
106  Arg [-END_PHASE]: the end phase
107  Arg [-STABLE_ID]: (optional) the stable id of the exon
108  Arg [-VERSION] : (optional) the version
109  Arg [-CREATED_DATE] : (optional) the created date
110  Arg [-MODIFIED_DATE]: (optional) the last midifeid date
111 
112  Example : none
113  Description: create an Exon object
114  Returntype : Bio::EnsEMBL::Exon
115  Exceptions : if phase is not valid (i.e. 0,1, 2 -1)
116  Caller : general
117  Status : Stable
118 
119 =cut
120 
121 sub new {
122  my $class = shift;
123 
124  $class = ref $class || $class;
125 
126  my $self = $class->SUPER::new( @_ );
127 
128  my ( $phase, $end_phase, $stable_id, $version, $created_date,
129  $modified_date, $is_current, $is_constitutive )
130  = rearrange( [
131  "PHASE", "END_PHASE",
132  "STABLE_ID", "VERSION",
133  "CREATED_DATE", "MODIFIED_DATE",
134  "IS_CURRENT", "IS_CONSTITUTIVE"
135  ],
136  @_
137  );
138 
139  if ( defined($phase) ) { # make sure phase is valid.
140  $self->phase($phase);
141  }
142 
143  $self->{'end_phase'} = $end_phase;
144  $self->{'stable_id'} = $stable_id;
145  $self->{'created_date'} = $created_date;
146  $self->{'modified_date'} = $modified_date;
147 
148  # Default version
149  if ( !defined($version) ) { $version = 1 }
150  $self->{'version'} = $version;
151 
152  # Default is_current
153  if ( !defined($is_current) ) { $is_current = 1 }
154  $self->{'is_current'} = $is_current;
155 
156  # Default is_constitutive
157  if ( !defined($is_constitutive) ) { $is_constitutive = 0 }
158  $self->{'is_constitutive'} = $is_constitutive;
159 
160  return $self;
161 }
162 
163 
164 =head2 end_phase
165 
166  Arg [1] : (optional) int $end_phase
167  Example : $end_phase = $feat->end_phase;
168  Description: Gets/Sets the end phase of the exon.
169  end_phase = number of bases from the last incomplete codon of
170  this exon.
171  Usually, end_phase = (phase + exon_length)%3
172  but end_phase could be -1 if the exon is half-coding and its 3
173  prime end is UTR.
174  Returntype : int
175  Exceptions : warning if end_phase is called without an argument and the
176  value is not set.
177  Caller : general
178  Status : Stable
179 
180 =cut
181 
182 sub end_phase {
183  my $self = shift;
184  if (@_) {
185  $self->{'end_phase'} = shift;
186  }
187  else {
188  if ( !defined( $self->{'end_phase'} ) ) {
189  my $stable_id = '';
190  $stable_id = $self->stable_id if defined $self->stable_id;
191  warning("No end phase set in Exon ".$stable_id.". You must set it explicitly.");
192  }
193  }
194  return $self->{'end_phase'};
195 }
196 
197 
198 =head2 phase
199 
200  Arg [1] : (optional) int $phase
201  Example : my $phase = $exon->phase;
202  $exon->phase(2);
203  Description: Gets/Sets the phase of the exon.
204  Returntype : int
205  Exceptions : throws if phase is not (0, 1 2 or -1).
206  Caller : general
207  Status : Stable
208 
209 
210 Get or set the phase of the Exon, which tells the
211 translation machinery, which makes a peptide from
212 the DNA, where to start.
213 
214 The Ensembl phase convention can be thought of as
215 "the number of bases of the first codon which are
216 on the previous exon". It is therefore 0, 1 or 2
217 (or -1 if the exon is non-coding). In ascii art,
218 with alternate codons represented by B<###> and
219 B<+++>:
220 
221  Previous Exon Intron This Exon
222  ...------------- -------------...
223 
224  5' Phase 3'
225  ...#+++###+++### 0 +++###+++###+...
226  ...+++###+++###+ 1 ++###+++###++...
227  ...++###+++###++ 2 +###+++###+++...
228 
229 Here is another explanation from Ewan:
230 
231 Phase means the place where the intron lands
232 inside the codon - 0 between codons, 1 between
233 the 1st and second base, 2 between the second and
234 3rd base. Exons therefore have a start phase and
235 a end phase, but introns have just one phase.
236 
237 =cut
238 
239 sub phase {
240  my ($self,$value) = @_;
241 
242  if (defined($value)) {
243  # Value must be 0,1,2, or -1 for non-coding
244  if ($value =~ /^(-1|0|1|2)$/) {
245  #print STDERR "Setting phase to $value\n";
246  $self->{'phase'} = $value;
247  } else {
248  throw("Bad value ($value) for exon phase. Should only be" .
249  " -1,0,1,2\n");
250  }
251  }
252  return $self->{'phase'};
253 }
254 
255 
256 =head2 frame
257 
258  Arg [1] : none
259  Example : $frame = $exon->frame
260  Description: Gets the frame of this exon
261  Returntype : int
262  Exceptions : thrown if an arg is passed
263  thrown if frame cannot be calculated due to a bad phase value
264  Caller : general
265  Status : Stable
266 
267 =cut
268 
269 sub frame {
270  my ($self,$value) = @_;
271 
272  if( defined $value ) {
273  throw("Cannot set frame. Deduced from seq_start and phase");
274  }
275 
276  # frame is mod 3 of the translation point
277 
278  if( $self->phase == -1 ) {
279  return '.'; # gff convention for no frame info
280  }
281  if( $self->phase == 0 ) {
282  return $self->start%3;
283  }
284 
285  if( $self->phase == 1 ) {
286  return ($self->start+2)%3;
287  }
288 
289  if( $self->phase == 2 ) {
290  return ($self->start+1)%3;
291  }
292 
293  throw("bad phase in exon ".$self->phase);
294 
295 }
296 
297 
298 =head2 start
299 
300  Arg [1] : int $start (optional)
301  Example : $start = $exon->start();
302  Description: Getter/Setter for the start of this exon. The superclass
303  implmentation is overridden to flush the internal sequence
304  cache if this value is altered
305  Returntype : int
306  Exceptions : none
307  Caller : general
308  Status : Stable
309 
310 =cut
311 
312 sub start {
313  my $self = shift;
314  # if an arg was provided, flush the internal sequence cache
315  delete $self->{'_seq_cache'} if(@_);
316  return $self->SUPER::start(@_);
317 }
318 
319 
320 =head2 end
321 
322  Arg [1] : int $end (optional)
323  Example : $end = $exon->end();
324  Description: Getter/Setter for the end of this exon. The superclass
325  implmentation is overridden to flush the internal sequence
326  cache if this value is altered
327  Returntype : int
328  Exceptions : none
329  Caller : general
330  Status : Stable
331 
332 =cut
333 
334 sub end {
335  my $self = shift;
336  # if an arg was provided, flush the internal sequence cache
337  delete $self->{'_seq_cache'} if(@_);
338  return $self->SUPER::end(@_);
339 }
340 
341 
342 =head2 strand
343 
344  Arg [1] : int $strand (optional)
345  Example : $start = $exon->strand();
346  Description: Getter/Setter for the strand of this exon. The superclass
347  implmentation is overridden to flush the internal sequence
348  cache if this value is altered
349  Returntype : int
350  Exceptions : none
351  Caller : general
352  Status : Stable
353 
354 =cut
355 
356 sub strand {
357  my $self = shift;
358  # if an arg was provided, flush the internal sequence cache
359  delete $self->{'_seq_cache'} if(@_);
360  return $self->SUPER::strand(@_);
361 }
362 
363 =head2 cdna_start
364 
365  Arg [1] : Bio::EnsEMBL::Transcript $transcript
366  The transcript for which cDNA coordinates should be
367  relative to.
368  Example : $cdna_start = $exon->cdna_start($transcript);
369  Description : Returns the start position of the exon in cDNA
370  coordinates.
371  Since an exon may be part of one or more transcripts,
372  the relevant transcript must be given as argument to
373  this method.
374  Return type : Integer
375  Exceptions : Throws if the given argument is not a transcript.
376  Throws if the first part of the exon maps into a gap.
377  Throws if the exon can not be mapped at all.
378  Caller : General
379  Status : Stable
380 
381 =cut
382 
383 sub cdna_start {
384  my ($self, $transcript) = @_;
385  assert_ref($transcript, 'Bio::EnsEMBL::Transcript', 'transcript');
386 
387  my $id = $transcript->dbID();
388 
389  if(defined $id && exists $self->{cdna_start}->{$id}) {
390  return $self->{cdna_start}->{$id};
391  }
392 
393  my $cdna_start;
394  my @coords = $transcript->genomic2cdna($self->seq_region_start(), $self->seq_region_end(), $self->strand());
395  if(@coords && !$coords[0]->isa('Bio::EnsEMBL::Mapper::Gap')) {
396  $cdna_start = $coords[0]->start();
397  }
398  elsif(@coords) {
399  throw "First part of exon maps into gap";
400  }
401  else {
402  throw "Can not map exon";
403  }
404 
405  if(defined $id) {
406  $self->{cdna_start}->{$id} = $cdna_start;
407  }
408 
409  return $cdna_start;
410 } ## end sub cdna_start
411 
412 =head2 cdna_end
413 
414  Arg [1] : Bio::EnsEMBL::Transcript $transcript
415  The transcript for which cDNA coordinates should be
416  relative to.
417  Example : $cdna_end = $exon->cdna_end($transcript);
418  Description : Returns the end position of the exon in cDNA
419  coordinates.
420  Since an exon may be part of one or more transcripts,
421  the relevant transcript must be given as argument to
422  this method.
423  Return type : Integer
424  Exceptions : Throws if the given argument is not a transcript.
425  Throws if the last part of the exon maps into a gap.
426  Throws if the exon can not be mapped at all.
427  Caller : General
428  Status : Stable
429 
430 =cut
431 
432 sub cdna_end {
433  my ($self, $transcript) = @_;
434  assert_ref($transcript, 'Bio::EnsEMBL::Transcript', 'transcript');
435 
436  my $id = $transcript->dbID();
437 
438  if(defined $id && exists $self->{cdna_end}->{$id}) {
439  return $self->{cdna_end}->{$id};
440  }
441 
442  my $cdna_end;
443  my @coords = $transcript->genomic2cdna($self->seq_region_start(), $self->seq_region_end(), $self->strand());
444  if(@coords && !$coords[-1]->isa('Bio::EnsEMBL::Mapper::Gap')) {
445  $cdna_end = $coords[-1]->end();
446  }
447  elsif(@coords) {
448  throw "Last part of exon maps into gap";
449  }
450  else {
451  throw "Can not map exon";
452  }
453 
454  if(defined $id) {
455  $self->{cdna_end}->{$id} = $cdna_end;
456  }
457 
458  return $cdna_end;
459 } ## end sub cdna_end
460 
461 =head2 cdna_coding_start
462 
463  Arg [1] : Bio::EnsEMBL::Transcript $transcript
464  The transcript for which cDNA coordinates should be
465  relative to.
466  Example : $cdna_coding_start = $exon->cdna_coding_start($transcript);
467  Description : Returns the start position of the coding region of the
468  exon in cDNA coordinates. Returns undef if the whole
469  exon is non-coding.
470  Since an exon may be part of one or more transcripts,
471  the relevant transcript must be given as argument to
472  this method.
473  Return type : Integer or undef
474  Exceptions : Throws if the given argument is not a transcript.
475  Caller : General
476  Status : Stable
477 
478 =cut
479 
480 sub cdna_coding_start {
481  my ($self, $transcript) = @_;
482  assert_ref($transcript, 'Bio::EnsEMBL::Transcript', 'transcript');
483 
484  my $id = $transcript->dbID();
485 
486  if(defined $id && exists $self->{cdna_coding_start}->{$id}) {
487  return $self->{cdna_coding_start}->{$id};
488  }
489 
490  my $cdna_coding_start;
491  my $transcript_coding_start = $transcript->cdna_coding_start();
492  if(defined $transcript_coding_start) {
493  my $cdna_start = $self->cdna_start($transcript);
494 
495  if ( $transcript_coding_start < $cdna_start ) {
496  # Coding region starts upstream of this exon...
497 
498  if ( $transcript->cdna_coding_end() < $cdna_start ) {
499  # ... and also ends upstream of this exon.
500  $cdna_coding_start = undef;
501  }
502  else {
503  # ... and does not end upstream of this exon.
504  $cdna_coding_start = $cdna_start;
505  }
506  } else {
507  # Coding region starts either within or downstream of this
508  # exon.
509 
510  if ( $transcript_coding_start <= $self->cdna_end($transcript) ) {
511  # Coding region starts within this exon.
512  $cdna_coding_start = $transcript_coding_start;
513  }
514  else {
515  # Coding region starts downstream of this exon.
516  $cdna_coding_start = undef;
517  }
518  }
519  }
520  else {
521  $cdna_coding_start = undef;
522  }
523 
524  if(defined $id) {
525  $self->{cdna_coding_start}->{$id} = $cdna_coding_start;
526  $self->{cdna_coding_end}->{$id} = undef if ! defined $cdna_coding_start;
527  }
528 
529  return $cdna_coding_start;
530 } ## end sub cdna_coding_start
531 
532 =head2 cdna_coding_end
533 
534  Arg [1] : Bio::EnsEMBL::Transcript $transcript
535  The transcript for which cDNA coordinates should be
536  relative to.
537  Example : $cdna_coding_end = $exon->cdna_coding_end($transcript);
538  Description : Returns the end position of the coding region of the
539  exon in cDNA coordinates. Returns undef if the whole
540  exon is non-coding.
541  Since an exon may be part of one or more transcripts,
542  the relevant transcript must be given as argument to
543  this method.
544  Return type : Integer or undef
545  Exceptions : Throws if the given argument is not a transcript.
546  Caller : General
547  Status : Stable
548 
549 =cut
550 
551 sub cdna_coding_end {
552  my ($self, $transcript) = @_;
553  assert_ref($transcript, 'Bio::EnsEMBL::Transcript', 'transcript');
554 
555  my $id = $transcript->dbID();
556 
557  if(defined $id && exists $self->{cdna_coding_end}->{$id}) {
558  return $self->{cdna_coding_end}->{$id};
559  }
560 
561  my $cdna_coding_end;
562  my $transcript_coding_end = $transcript->cdna_coding_end();
563  if(defined $transcript_coding_end) {
564  my $cdna_end = $self->cdna_end($transcript);
565 
566  if ( $transcript_coding_end > $cdna_end ) {
567 
568  # Coding region ends downstream of this exon...
569  if ( $transcript->cdna_coding_start() > $cdna_end ) {
570  # ... and also starts downstream of this exon.
571  $cdna_coding_end = undef;
572  }
573  else {
574  # ... and does not start downstream of this exon.
575  $cdna_coding_end = $cdna_end;
576  }
577  }
578  else {
579  # Coding region ends either within or upstream of this
580  # exon.
581 
582  if ( $transcript_coding_end >= $self->cdna_start($transcript) ) {
583  # Coding region ends within this exon.
584  $cdna_coding_end = $transcript_coding_end;
585  }
586  else {
587  # Coding region ends upstream of this exon.
588  $cdna_coding_end = undef;
589  }
590  }
591  }
592  else {
593  $cdna_coding_end = undef;
594  }
595 
596  if(defined $id) {
597  $self->{cdna_coding_end}->{$id} = $cdna_coding_end;
598  $self->{cdna_coding_start}->{$id} = undef if ! defined $cdna_coding_end;
599  }
600 
601  return $cdna_coding_end;
602 } ## end sub cdna_coding_end
603 
604 =head2 coding_region_start
605 
606  Arg [1] : Bio::EnsEMBL::Transcript $transcript
607  Example : $coding_region_start =
608  $exon->coding_region_start($transcript);
609  Description : Returns the start position of the coding region
610  of the exon in slice-relative coordinates on the
611  forward strand. Returns undef if the whole exon is
612  non-coding.
613  Since an exon may be part of one or more transcripts,
614  the relevant transcript must be given as argument to
615  this method.
616  Return type : Integer or undef
617  Exceptions : Throws if the given argument is not a transcript.
618  Caller : General
619  Status : Stable
620 
621 =cut
622 
623 # The implementation of this method is analogous to the implementation
624 # of cdna_coding_start().
625 
626 sub coding_region_start {
627  my ($self, $transcript) = @_;
628  assert_ref($transcript, 'Bio::EnsEMBL::Transcript', 'transcript');
629 
630  my $id = $transcript->dbID();
631 
632  if(defined $id && exists $self->{coding_region_start}->{$id}) {
633  return $self->{coding_region_start}->{$id};
634  }
635 
636  my $coding_region_start;
637  my $transcript_coding_start = $transcript->coding_region_start();
638  if(defined $transcript_coding_start) {
639  my $start = $self->start();
640 
641  if ( $transcript_coding_start < $start ) {
642  # Coding region starts upstream of this exon...
643 
644  if ( $transcript->coding_region_end() < $start ) {
645  # ... and also ends upstream of this exon.
646  $coding_region_start = undef;
647  }
648  else {
649  # ... and does not end upstream of this exon.
650  $coding_region_start = $start;
651  }
652  }
653  else {
654  # Coding region starts either within or downstream of this
655  # exon.
656 
657  if ( $transcript_coding_start <= $self->end() ) {
658  # Coding region starts within this exon.
659  $coding_region_start = $transcript_coding_start;
660  }
661  else {
662  # Coding region starts downstream of this exon.
663  $coding_region_start = undef;
664  }
665  }
666  }
667  else {
668  $coding_region_start = undef;
669  }
670 
671  if(defined $id) {
672  $self->{coding_region_start}->{$id} = $coding_region_start;
673  $self->{coding_region_end}->{$id} = undef if ! defined $coding_region_start;
674  }
675 
676  return $coding_region_start;
677 } ## end sub coding_region_start
678 
679 =head2 coding_region_end
680 
681  Arg [1] : Bio::EnsEMBL::Transcript $transcript
682  Example : $coding_region_end =
683  $exon->coding_region_end($transcript);
684  Description : Returns the end position of the coding region of
685  the exon in slice-relative coordinates on the
686  forward strand. Returns undef if the whole exon is
687  non-coding.
688  Since an exon may be part of one or more transcripts,
689  the relevant transcript must be given as argument to
690  this method.
691  Return type : Integer or undef
692  Exceptions : Throws if the given argument is not a transcript.
693  Caller : General
694  Status : Stable
695 
696 =cut
697 
698 # The implementation of this method is analogous to the implementation
699 # of cdna_coding_end().
700 
701 sub coding_region_end {
702  my ($self, $transcript) = @_;
703  assert_ref($transcript, 'Bio::EnsEMBL::Transcript', 'transcript');
704 
705  my $id = $transcript->dbID();
706 
707  if(defined $id && exists $self->{coding_region_end}->{$id}) {
708  return $self->{coding_region_end}->{$id};
709  }
710 
711  my $coding_region_end;
712  my $transcript_coding_end = $transcript->coding_region_end();
713  if(defined $transcript_coding_end) {
714 
715  my $end = $self->end();
716  if($transcript_coding_end > $end) {
717  # Coding region ends downstream of this exon...
718 
719  if ( $transcript->coding_region_start() > $end ) {
720  # ... and also starts downstream of this exon.
721  $coding_region_end = undef;
722  }
723  else {
724  # ... and does not start downstream of this exon.
725  $coding_region_end = $end;
726  }
727  }
728  else {
729  # Coding region ends either within or upstream of this
730  # exon.
731  if ( $transcript_coding_end >= $self->start() ) {
732  $coding_region_end = $transcript_coding_end;
733  }
734  else {
735  $coding_region_end = undef;
736  }
737  }
738  }
739  else {
740  # This is a non-coding transcript.
741  $coding_region_end = undef;
742  }
743 
744  if(defined $id) {
745  $self->{coding_region_end}->{$id} = $coding_region_end;
746  $self->{coding_region_start}->{$id} = undef if ! defined $coding_region_end;
747  }
748 
749  return $coding_region_end;
750 } ## end sub coding_region_end
751 
752 
753 =head2 rank
754 
755  Arg [1] : Bio::EnsEMBL::Transcript $transcript
756  The transcript for which the exon rank
757  is requested.
758  Example : $rank = $exon->rank($transcript);
759  Description : Returns the rank of the exon relative to
760  the transcript.
761  Since an exon may be part of one or more transcripts,
762  the relevant transcript must be given as argument to
763  this method.
764  Return type : Integer
765  Exceptions : Throws if the given argument is not a transcript.
766  Throws if the exon does not belong to the transcript.
767  Caller : General
768  Status : Stable
769 
770 =cut
771 
772 sub rank {
773  my ($self, $transcript) = @_;
774  assert_ref($transcript, 'Bio::EnsEMBL::Transcript', 'transcript');
775 
776  my $rank = $transcript->exon_rank($self);
777 
778  return $rank;
779 } ## end sub rank
780 
781 =head2 slice
782 
783  Arg [1] : Bio::EnsEMBL::Slice
784  Example : $slice = $exon->slice();
785  Description: Getter/Setter for the slice this exon is on. The superclass
786  implmentation is overridden to flush the internal sequence
787  cache if this value is altered
788  Returntype : Bio::EnsEMBL::Slice
789  Exceptions : none
790  Caller : general
791  Status : Stable
792 
793 =cut
794 
795 sub slice {
796  my ( $self, $slice ) = @_;
797 
798  if ( defined($slice) ) {
799  # If a new slice was provided, flush the internal sequence cache and
800  # transfer all supporting evidence to the new slice.
801 
802  delete $self->{'_seq_cache'};
803 
804  if ( exists( $self->{'_supporting_evidence'} ) ) {
805  my @new_features;
806 
807  for my $old_feature ( @{ $self->{'_supporting_evidence'} } ) {
808 
809  my $new_feature;
810 
811  if ( defined( $old_feature->slice() ) ) {
812  $new_feature = $old_feature->transfer($slice);
813  } else {
814  # If the old feature does not have a slice, assume transfer is
815  # not necessary.
816  $new_feature = $old_feature;
817  }
818 
819  push( @new_features, $new_feature );
820  }
821 
822  $self->{'_supporting_evidence'} = \@new_features;
823  }
824 
825  return $self->SUPER::slice($slice);
826  } elsif ( @_ > 1 ) {
827  return $self->SUPER::slice(undef);
828  } else {
829  return $self->SUPER::slice();
830  }
831 } ## end sub slice
832 
833 =head2 equals
834 
835  Arg [1] : Bio::EnsEMBL::Exon exon
836  Example : if ($exonA->equals($exonB)) { ... }
837  Description : Compares two exons for equality.
838  The test for eqality goes through the following list
839  and terminates at the first true match:
840 
841  1. If Bio::EnsEMBL::Feature::equals() returns false,
842  then the exons are *not* equal.
843  2. If both exons have stable IDs: if these are the
844  same, the exons are equal, otherwise not.
845  3. If the exons have the same start, end, strand, and
846  phase, then they are equal, otherwise not.
847 
848  Return type : Boolean (0, 1)
849 
850  Exceptions : Thrown if a non-transcript is passed as the argument.
851 
852 =cut
853 
854 sub equals {
855  my ( $self, $exon ) = @_;
856 
857  if ( !defined($exon) ) { return 0 }
858  if ( $self eq $exon ) { return 1 }
859 
860  assert_ref( $exon, 'Bio::EnsEMBL::Exon' );
861 
862  my $feature_equals = $self->SUPER::equals($exon);
863  if ( defined($feature_equals) && $feature_equals == 0 ) {
864  return 0;
865  }
866 
867  if ( defined( $self->stable_id() ) && defined( $exon->stable_id() ) )
868  {
869  if ( $self->stable_id() eq $exon->stable_id() ) {
870  return 1;
871  }
872  else {
873  return 0;
874  }
875  }
876 
877  if ( $self->start() == $exon->start() &&
878  $self->end() == $exon->end() &&
879  $self->strand() == $exon->strand() &&
880  $self->phase() == $exon->phase() &&
881  $self->end_phase() == $exon->end_phase() )
882  {
883  return 1;
884  }
885 
886  return 0;
887 } ## end sub equals
888 
889 =head2 move
890 
891  Arg [1] : int start
892  Arg [2] : int end
893  Arg [3] : (optional) int strand
894  Example : None
895  Description: Sets the start, end and strand in one call rather than in
896  3 seperate calls to the start(), end() and strand() methods.
897  This is for convenience and for speed when this needs to be
898  done within a tight loop. This overrides the superclass
899  move() method so that the internal sequence cache can be
900  flushed if the exon if moved.
901  Returntype : none
902  Exceptions : Thrown is invalid arguments are provided
903  Caller : general
904  Status : Stable
905 
906 =cut
907 
908 sub move {
909  my $self = shift;
910  # flush the internal sequence cache
911  delete $self->{'_seq_cache'};
912  return $self->SUPER::move(@_);
913 }
914 
915 
916 =head2 transform
917 
918  Arg 1 : String $coordinate_system_name
919  Arg [2] : String $coordinate_system_version
920  Description: moves this exon to the given coordinate system. If this exon has
921  attached supporting evidence, they move as well.
922  Returntype : Bio::EnsEMBL::Exon
923  Exceptions : wrong parameters
924  Caller : general
925  Status : Stable
926 
927 =cut
928 
929 sub transform {
930  my $self = shift;
931 
932  my $new_exon = $self->SUPER::transform( @_ );
933  if (not defined $new_exon or
934  $new_exon->length != $self->length) {
935  return undef;
936  }
937 
938  if( exists $self->{'_supporting_evidence'} ) {
939  my @new_features;
940  for my $old_feature ( @{$self->{'_supporting_evidence'}} ) {
941  my $new_feature = $old_feature->transform( @_ );
942  if (defined $new_feature) {
943  push( @new_features, $new_feature );
944  }
945  }
946  $new_exon->{'_supporting_evidence'} = \@new_features;
947  }
948 
949  #dont want to share the same sequence cache
950  delete $new_exon->{'_seq_cache'};
951 
952  return $new_exon;
953 }
954 
955 
956 =head2 transfer
957 
958  Arg [1] : Bio::EnsEMBL::Slice $destination_slice
959  Example : none
960  Description: Moves this Exon to given target slice coordinates. If Features
961  are attached they are moved as well. Returns a new exon.
962  Returntype : Bio::EnsEMBL::Exon
963  Exceptions : none
964  Caller : general
965  Status : Stable
966 
967 =cut
968 
969 sub transfer {
970  my $self = shift;
971 
972  my $new_exon = $self->SUPER::transfer( @_ );
973  return undef unless $new_exon;
974 
975  if( exists $self->{'_supporting_evidence'} ) {
976  my @new_features;
977  for my $old_feature ( @{$self->{'_supporting_evidence'}} ) {
978  my $new_feature = $old_feature->transfer( @_ );
979  push( @new_features, $new_feature );
980  }
981  $new_exon->{'_supporting_evidence'} = \@new_features;
982  }
983 
984  #dont want to share the same sequence cache
985  delete $new_exon->{'_seq_cache'};
986 
987  return $new_exon;
988 }
989 
990 
991 =head2 add_supporting_features
992 
993  Arg [1] : Bio::EnsEMBL::Feature $feature
994  Example : $exon->add_supporting_features(@features);
995  Description: Adds a list of supporting features to this exon.
996  Duplicate features are not added.
997  If supporting features are added manually in this
998  way, prior to calling get_all_supporting_features then the
999  get_all_supporting_features call will not retrieve supporting
1000  features from the database.
1001  Returntype : none
1002  Exceptions : throw if any of the features are not Feature
1003  throw if any of the features are not in the same coordinate
1004  system as the exon
1005  Caller : general
1006  Status : Stable
1007 
1008 =cut
1009 
1010 sub add_supporting_features {
1011  my ($self,@features) = @_;
1012 
1013  return unless @features;
1014 
1015  $self->{_supporting_evidence} ||= [];
1016 
1017  # check whether this feature object has been added already
1018  FEATURE: foreach my $feature (@features) {
1019  unless($feature && $feature->isa("Bio::EnsEMBL::Feature")) {
1020  throw("Supporting feat [$feature] not a " .
1021  "Bio::EnsEMBL::Feature");
1022  }
1023 
1024  if ((defined $self->slice() && defined $feature->slice())&&
1025  ( $self->slice()->name() ne $feature->slice()->name())){
1026  throw("Supporting feat not in same coord system as exon\n" .
1027  "exon is attached to [".$self->slice()->name()."]\n" .
1028  "feat is attached to [".$feature->slice()->name()."]");
1029  }
1030 
1031  foreach my $added_feature ( @{ $self->{_supporting_evidence} } ){
1032  # compare objects
1033  if ( $feature == $added_feature ){
1034  # this feature has already been added
1035  next FEATURE;
1036  }
1037  }
1038 
1039  # no duplicate was found, add the feature
1040  push(@{$self->{_supporting_evidence}},$feature);
1041  }
1042 }
1043 
1044 
1045 =head2 flush_supporting_features
1046 
1047  Example : $exon->flush_supporting_features;
1048  Description : Removes all supporting evidence from the exon.
1049  Return type : (Empty) listref
1050  Exceptions : none
1051  Caller : general
1052  Status : Stable
1053 
1054 =cut
1055 
1056 sub flush_supporting_features {
1057  my $self = shift;
1058  $self->{'_supporting_evidence'} = [];
1059 }
1060 
1061 
1062 =head2 get_all_supporting_features
1063 
1064  Arg [1] : none
1065  Example : @evidence = @{$exon->get_all_supporting_features()};
1066  Description: Retrieves any supporting features added manually by
1067  calls to add_supporting_features. If no features have been
1068  added manually and this exon is in a database (i.e. it has
1069  an adaptor), fetch from the database
1070  Returntype : listreference of Bio::EnsEMBL::BaseAlignFeature objects
1071  Exceptions : none
1072  Caller : general
1073  Status : Stable
1074 
1075 =cut
1076 
1077 sub get_all_supporting_features {
1078  my $self = shift;
1079 
1080  if( !exists $self->{_supporting_evidence} ) {
1081  if($self->adaptor) {
1082  my $sfa = $self->adaptor->db->get_SupportingFeatureAdaptor();
1083  $self->{_supporting_evidence} = $sfa->fetch_all_by_Exon($self);
1084  }
1085  }
1086 
1087  return $self->{_supporting_evidence} || [];
1088 }
1089 
1090 
1091 =head2 find_supporting_evidence
1092 
1093 # This method is only for genebuild backwards compatibility.
1094 # Avoid using it if possible
1095 
1096  Arg [1] : Bio::EnsEMBL::Feature $features
1097  The list of features to search for supporting (i.e. overlapping)
1098  evidence.
1099  Arg [2] : (optional) boolean $sorted
1100  Used to speed up the calculation of overlapping features.
1101  Should be set to true if the list of features is sorted in
1102  ascending order on their start coordinates.
1103  Example : $exon->find_supporting_evidence(\@features);
1104  Description: Looks through all the similarity features and
1105  stores as supporting features any feature
1106  that overlaps with an exon.
1107  Returntype : none
1108  Exceptions : none
1109  Caller : general
1110  Status : Medium Risk
1111 
1112 =cut
1113 
1114 sub find_supporting_evidence {
1115  my ($self,$features,$sorted) = @_;
1116 
1117  foreach my $f (@$features) {
1118  # return if we have a sorted feature array
1119  if ($sorted == 1 && $f->start > $self->end) {
1120  return;
1121  }
1122  if ($f->sub_SeqFeature) {
1123  my @subf = $f->sub_SeqFeature;
1124 
1125  $self->find_supporting_evidence(\@subf);
1126  }
1127  else {
1128  if ($f->entire_seq()->name eq $self->slice()->name) {
1129  if ($f->end >= $self->start && $f->start <= $self->end && $f->strand == $self->strand) {
1130  $self->add_supporting_features($f);
1131  }
1132  }
1133  }
1134  }
1135 }
1136 
1137 
1138 =head2 stable_id
1139 
1140  Arg [1] : string $stable_id
1141  Example : none
1142  Description: get/set for attribute stable_id
1143  Returntype : string
1144  Exceptions : none
1145  Caller : general
1146  Status : Stable
1147 
1148 =cut
1149 
1150 sub stable_id {
1151  my $self = shift;
1152  $self->{'stable_id'} = shift if( @_ );
1153  return $self->{'stable_id'};
1154 }
1155 
1156 
1157 =head2 created_date
1158 
1159  Arg [1] : string $created_date
1160  Example : none
1161  Description: get/set for attribute created_date
1162  Returntype : string
1163  Exceptions : none
1164  Caller : general
1165  Status : Stable
1166 
1167 =cut
1168 
1169 sub created_date {
1170  my $self = shift;
1171  $self->{'created_date'} = shift if ( @_ );
1172  return $self->{'created_date'};
1173 }
1174 
1175 
1176 =head2 modified_date
1177 
1178  Arg [1] : string $modified_date
1179  Example : none
1180  Description: get/set for attribute modified_date
1181  Returntype : string
1182  Exceptions : none
1183  Caller : general
1184  Status : Stable
1185 
1186 =cut
1187 
1188 sub modified_date {
1189  my $self = shift;
1190  $self->{'modified_date'} = shift if ( @_ );
1191  return $self->{'modified_date'};
1192 }
1193 
1194 
1195 =head2 version
1196 
1197  Arg [1] : string $version
1198  Example : none
1199  Description: get/set for attribute version
1200  Returntype : string
1201  Exceptions : none
1202  Caller : general
1203  Status : Stable
1204 
1205 =cut
1206 
1207 sub version {
1208  my $self = shift;
1209  $self->{'version'} = shift if( @_ );
1210  return $self->{'version'};
1211 }
1212 
1213 =head2 stable_id_version
1214 
1215  Arg [1] : (optional) String - the stable ID with version to set
1216  Example : $exon->stable_id("ENSE0000000001.3");
1217  Description: Getter/setter for stable id with version for this exon.
1218  Returntype : String
1219  Exceptions : none
1220  Caller : general
1221  Status : Stable
1222 
1223 =cut
1224 
1225 sub stable_id_version {
1226  my $self = shift;
1227  if(my $stable_id = shift) {
1228  # See if there's an embedded period, assume that's a
1229  # version, might not work for some species but you
1230  # should use ->stable_id() and version() if you're worried
1231  # about ambiguity
1232  my $vindex = rindex($stable_id, '.');
1233  # Set the stable_id and version pair depending on if
1234  # we found a version delimiter in the stable_id
1235  ($self->{stable_id}, $self->{version}) = ($vindex > 0 ?
1236  (substr($stable_id,0,$vindex), substr($stable_id,$vindex+1)) :
1237  $stable_id, undef);
1238  }
1239  return $self->{stable_id} . ($self->{version} ? ".$self->{version}" : '');
1240 }
1241 
1242 =head2 is_current
1243 
1244  Arg [1] : Boolean $is_current
1245  Example : $exon->is_current(1)
1246  Description: Getter/setter for is_current state of this exon.
1247  Returntype : Int
1248  Exceptions : none
1249  Caller : general
1250  Status : Stable
1251 
1252 =cut
1253 
1254 sub is_current {
1255  my ( $self, $value ) = @_;
1256 
1257  if ( defined($value) ) {
1258  $self->{'is_current'} = $value;
1259  }
1260  return $self->{'is_current'};
1261 }
1262 
1263 =head2 is_constitutive
1264 
1265  Arg [1] : Boolean $is_constitutive
1266  Example : $exon->is_constitutive(0)
1267  Description: Getter/setter for is_constitutive state of this exon.
1268  Returntype : Int
1269  Exceptions : none
1270  Caller : general
1271  Status : Stable
1272 
1273 =cut
1274 
1275 sub is_constitutive {
1276  my ( $self, $value ) = @_;
1277 
1278  if ( defined($value) ) {
1279  $self->{'is_constitutive'} = $value;
1280  }
1281  return $self->{'is_constitutive'};
1282 }
1283 
1284 =head2 is_coding
1285 
1286  Arg [1] : Bio::EnsEMBL::Transcript
1287  Example : $exon->is_coding()
1288  Description: Says if the exon is within the translation or not
1289  Returntype : Int
1290  Exceptions : none
1291  Caller : general
1292  Status : Stable
1293 
1294 =cut
1295 
1296 sub is_coding {
1297  my ( $self, $transcript) = @_;
1298 
1299  if (!$transcript) { throw("Transcript parameter is required for " . __PACKAGE__ . "->is_coding()."); }
1300 
1301  if (!$transcript->translate) { return 0; }
1302 
1303  # coding region overlaps start of exon
1304  if ($transcript->coding_region_start <= $self->start && $self->start <= $transcript->coding_region_end) { return 1; }
1305 
1306  # coding region overlaps end of exon
1307  if ($transcript->coding_region_end >= $self->end && $self->end >= $transcript->coding_region_start) { return 1; }
1308 
1309  # to handle cases where transcript coding region can fall within the exon start and exon end, eg: if it is one exon transcript
1310  if ($transcript->coding_region_start >= $self->start && $transcript->coding_region_end <= $self->end ) { return 1; }
1311  return 0;
1312 }
1313 
1314 
1315 =head2 adjust_start_end
1316 
1317  Arg 1 : int $start_adjustment
1318  Arg 2 : int $end_adjustment
1319  Example : none
1320  Description: returns a new Exon with this much shifted coordinates
1321  Returntype : Bio::EnsEMBL::Exon
1322  Exceptions : none
1323  Caller : Transcript->get_all_translateable_Exons()
1324  Status : Stable
1325 
1326 =cut
1327 
1328 sub adjust_start_end {
1329  my ( $self, $start_adjust, $end_adjust ) = @_;
1330 
1331  my $new_exon = Bio::EnsEMBL::Exon->new();
1332  %{$new_exon} = %{$self};
1333 
1334  #invalidate the sequence cache
1335  delete $new_exon->{'_seq_cache'};
1336 
1337  if( $self->strand() == 1 ) {
1338  $new_exon->start( $self->start() + $start_adjust );
1339  $new_exon->end( $self->end() + $end_adjust )
1340  } else {
1341  $new_exon->start( $self->start() - $end_adjust );
1342  $new_exon->end( $self->end() - $start_adjust )
1343  }
1344 
1345  return $new_exon;
1346 }
1347 
1348 
1349 =head2 peptide
1350 
1351  Arg [1] : Bio::EnsEMBL::Transcript $tr
1352  Example : my $pep_str = $exon->peptide($transcript)->seq;
1353  Description: Retrieves the portion of the transcripts peptide
1354  encoded by this exon. The transcript argument is necessary
1355  because outside of the context of a transcript it is not
1356  possible to correctly determine the translation. Note that
1357  an entire amino acid will be present at the exon boundaries
1358  even if only a partial codon is present. Therefore the
1359  concatenation of all of the peptides of a transcripts exons
1360  is not the same as a transcripts translation because the
1361  summation may contain duplicated amino acids at splice sites.
1362  In the case that this exon is entirely UTR, a Bio::Seq object
1363  with an empty sequence string is returned.
1364  Returntype : Bio::Seq
1365  Exceptions : thrown if transcript argument is not provided
1366  Caller : general
1367  Status : Stable
1368 
1369 =cut
1370 
1371 sub peptide {
1372  my $self = shift;
1373  my $tr = shift;
1374 
1375  unless($tr && ref($tr) && $tr->isa('Bio::EnsEMBL::Transcript')) {
1376  throw("transcript arg must be Bio::EnsEMBL:::Transcript not [$tr]");
1377  }
1378 
1379  #convert exons coordinates to peptide coordinates
1380  my $tmp_exon = $self->transfer($tr->slice);
1381  if (!$tmp_exon) {
1382  throw("Couldn't transfer exon to transcript's slice");
1383  }
1384 
1385  my @coords =
1386  $tr->genomic2pep($tmp_exon->start, $tmp_exon->end, $tmp_exon->strand);
1387 
1388  #filter out gaps
1389  @coords = grep {$_->isa('Bio::EnsEMBL::Mapper::Coordinate')} @coords;
1390 
1391  #if this is UTR then the peptide will be empty string
1392  my $pep_str = '';
1393 
1394 
1395  if(scalar(@coords) > 1) {
1396  my $coord = $self->_merge_ajoining_coords(\@coords);
1397  if($coord) {
1398  @coords = ($coord);
1399  }
1400  else {
1401  my ($e_id, $tr_id) = ($self->stable_id(), $tr->stable_id());
1402  throw("Error. Exon maps to multiple locations in peptide and those".
1403  " locations are not continuous." .
1404  " Is this exon [$e_id] a member of this transcript [$tr_id]?");
1405  }
1406  }
1407  elsif(scalar(@coords) == 1) {
1408  my $c = $coords[0];
1409  my $pep = $tr->translate;
1410 
1411  #bioperl doesn't give back residues for incomplete codons
1412  #make sure we don't subseq too far...
1413  my ($start, $end);
1414  $end = ($c->end > $pep->length) ? $pep->length : $c->end;
1415  $start = ($c->start < $end) ? $c->start : $end;
1416  $pep_str = $tr->translate->subseq($start, $end);
1417  }
1418 
1419  return
1420  Bio::Seq->new( -seq => $pep_str,
1421  -moltype => 'protein',
1422  -alphabet => 'protein',
1423  -id => $self->display_id );
1424 }
1425 
1426 =head2 _merge_ajoining_coords
1427 
1428  Arg [1] : ArrayRef of Bio::EnsEMBL::Mapper::Coordinate objects
1429  Example :
1430  Description : Merges coords which are ajoining or overlapping
1431  Returntype : Bio::EnsEMBL::Mapper::Coordinate or undef if it cannot happen
1432  Exceptions : Exception if the cooords cannot be condensed into one location
1433  Caller : internal
1434  Status : Development
1435 
1436 =cut
1437 
1438 sub _merge_ajoining_coords {
1439  my ($self, $coords) = @_;
1440 
1441  my $okay = 1;
1442  my $coord = shift @{$coords};
1443  my $start = $coord->start();
1444  my $last_end = $coord->end();
1445  foreach my $other_coord (@{$coords}) {
1446  if( ($last_end + 1) >= $other_coord->start() ) {
1447  $last_end = $other_coord->end();
1448  }
1449  else {
1450  $okay = 0;
1451  last;
1452  }
1453  }
1454 
1455  if(!$okay) {
1456  return;
1457  }
1458 
1459  my $new_coord = Bio::EnsEMBL::Mapper::Coordinate->new(
1460  $coord->id(), $start, $last_end, $coord->strand(), $coord->rank());
1461  return $new_coord;
1462 }
1463 
1464 
1465 
1466 
1467 =head2 seq
1468 
1469  Arg [1] : none
1470  Example : my $seq_str = $exon->seq->seq;
1471  Description: Retrieves the dna sequence of this Exon.
1472  Returned in a Bio::Seq object. Note that the sequence may
1473  include UTRs (or even be entirely UTR).
1474  Returntype : Bio::Seq or undef
1475  Exceptions : warning if argument passed,
1476  warning if exon does not have attatched slice
1477  warning if exon strand is not defined (or 0)
1478  Caller : general
1479  Status : Stable
1480 
1481 =cut
1482 
1483 sub seq {
1484  my ( $self, $arg ) = @_;
1485 
1486  if ( defined $arg ) {
1487  warning("seq setting on Exon not supported currently");
1488  $self->{'_seq_cache'} = $arg->seq();
1489  }
1490 
1491  if ( !defined( $self->{'_seq_cache'} ) ) {
1492  my $seq;
1493 
1494  if ( !defined $self->slice() ) {
1495  warning("Cannot retrieve seq for exon without slice\n");
1496  return undef;
1497  }
1498 
1499  if ( !$self->strand() ) {
1500  warning("Cannot retrieve seq for unstranded exon\n");
1501  return undef;
1502  }
1503 
1504  if ($self->slice->is_circular() ) {
1505  if ( $self->slice->start > $self->slice->end) {
1506 # Normally exons overlapping chromosome origin will have negative feature start, but slice will be from 1 .. length
1507 # But in case you got an exon attached to a sub slice try this
1508  my $mid_point = $self->slice()->seq_region_length() - $self->slice()->start() + 1;
1509  my $seq1 = $self->slice()->subseq( $self->start(), $mid_point, $self->strand() );
1510 
1511  my $seq2 = $self->slice()->subseq( $mid_point + 1, $self->end(), $self->strand() );
1512 
1513  $seq = $self->strand() > 0 ? "$seq1$seq2" : "$seq2$seq1";
1514  } elsif ( $self->start < 0 || $self->start > $self->end) {
1515 # Normally exons overlapping chromosome origin will be 0 based, and can have negative start
1516 # But if you go via sub_Slice it gives you chromosome based coordinates, i.e it will have start greater then end
1517  my $start_point = $self->slice->seq_region_length + $self->slice->start;
1518  my $mid_point = $self->slice->seq_region_length;
1519  my $seq1 = $self->slice->subseq( $self->start, $mid_point, $self->strand);
1520  my $seq2 = $self->slice->subseq(1, $self->end, $self->strand );
1521  $seq = $self->strand > 0 ? "$seq1$seq2" : "$seq2$seq1";
1522  } else {
1523 # End this is the case for genes not overlapping the origin
1524  $seq = $self->slice()->subseq( $self->start(), $self->end(), $self->strand() );
1525  }
1526  } else {
1527  $seq = $self->slice()->subseq( $self->start(), $self->end(), $self->strand() );
1528  }
1529 
1530  $self->{'_seq_cache'} = $seq;
1531  } ## end if ( !defined( $self->...))
1532 
1533  return
1534  Bio::Seq->new( -seq => $self->{'_seq_cache'},
1535  -id => $self->display_id,
1536  -moltype => 'dna',
1537  -alphabet => 'dna' );
1538 } ## end sub seq
1539 
1540 
1541 =head2 hashkey
1542 
1543  Arg [1] : none
1544  Example : if(exists $hash{$exon->hashkey}) { do_something(); }
1545  Description: Returns a unique hashkey that can be used to uniquely identify
1546  this exon. Exons are considered to be identical if they share
1547  the same seq_region, start, end, strand, phase, end_phase.
1548  Note that this will consider two exons on different slices
1549  to be different, even if they actually are not.
1550  Returntype : string formatted as slice_name-start-end-strand-phase-end_phase
1551  Exceptions : thrown if not all the necessary attributes needed to generate
1552  a unique hash value are set
1553  set
1554  Caller : general
1555  Status : Stable
1556 
1557 =cut
1558 
1559 sub hashkey {
1560  my $self = shift;
1561 
1562  my $slice = $self->{'slice'};
1563  my $slice_name = ($slice) ? $slice->name() : undef;
1564  my $start = $self->{'start'};
1565  my $end = $self->{'end'};
1566  my $strand = $self->{'strand'};
1567  my $phase = $self->{'phase'};
1568  my $end_phase = $self->{'end_phase'};
1569 
1570  if(!defined($slice_name)) {
1571  throw('Slice must be set to generate correct hashkey.');
1572  }
1573 
1574  if(!defined($start)) {
1575  warning("start attribute must be defined to generate correct hashkey.");
1576  }
1577 
1578  if(!defined($end)) {
1579  throw("end attribute must be defined to generate correct hashkey.");
1580  }
1581 
1582  if(!defined($strand)) {
1583  throw("strand attribute must be defined to generate correct hashkey.");
1584  }
1585 
1586  if(!defined($phase)) {
1587  throw("phase attribute must be defined to generate correct hashkey.");
1588  }
1589 
1590  if(!defined($end_phase)) {
1591  throw("end_phase attribute must be defined to generate correct hashkey.");
1592  }
1593 
1594  return "$slice_name-$start-$end-$strand-$phase-$end_phase";
1595 }
1596 
1597 
1598 =head2 display_id
1599 
1600  Arg [1] : none
1601  Example : print $exons->display_id();
1602  Description: This method returns a string that is considered to be
1603  the 'display' identifier. For exons this is (depending on
1604  availability and in this order) the stable Id, the dbID or an
1605  empty string.
1606  Returntype : string
1607  Exceptions : none
1608  Caller : web drawing code
1609  Status : Stable
1610 
1611 =cut
1612 
1613 sub display_id {
1614  my $self = shift;
1615  return $self->{'stable_id'} || $self->dbID || '';
1616 }
1617 
1618 
1619 =head2 load
1620 
1621  Args : None
1622  Example : $exon->load();
1623  Description : The Ensembl API makes extensive use of
1624  lazy-loading. Under some circumstances (e.g.,
1625  when copying genes between databases), all data of
1626  an object needs to be fully loaded. This method
1627  loads the parts of the object that are usually
1628  lazy-loaded.
1629  Returns : Nothing.
1630 
1631 =cut
1632 
1633 sub load {
1634  my ($self) = @_;
1635 
1636  $self->analysis();
1637  $self->stable_id();
1638  $self->get_all_supporting_features();
1639 }
1640 
1641 
1642 =head2 summary_as_hash
1643 
1644  Example : $exon_summary = $exon->summary_as_hash();
1645  Description : Extends Feature::summary_as_hash
1646  Retrieves a summary of this Exon.
1647  Returns : hashref of descriptive strings
1648  Status : Intended for internal use
1649 =cut
1650 
1651 sub summary_as_hash {
1652  my $self = shift;
1653  my $summary_ref = $self->SUPER::summary_as_hash;
1654  $summary_ref->{'constitutive'} = $self->is_constitutive;
1655  $summary_ref->{'ensembl_phase'} = $self->phase;
1656  $summary_ref->{'ensembl_end_phase'} = $self->end_phase;
1657  $summary_ref->{'exon_id'} = $summary_ref->{'id'};
1658  return $summary_ref;
1659 }
1660 
1661 
1662 1;
transcript
public transcript()
EnsEMBL
Definition: Filter.pm:1
Bio::EnsEMBL::BaseAlignFeature
Definition: BaseAlignFeature.pm:90
Bio::EnsEMBL::Mapper::Coordinate
Definition: Coordinate.pm:14
Bio::EnsEMBL::Feature
Definition: Feature.pm:47
Bio::EnsEMBL::Exon::transfer
public Bio::EnsEMBL::Exon transfer()
Bio::EnsEMBL::DBSQL::SupportingFeatureAdaptor
Definition: SupportingFeatureAdaptor.pm:15
Bio::EnsEMBL::Slice::slice
public slice()
Bio::EnsEMBL::Mapper::Coordinate::start
public start()
Bio::EnsEMBL::Transcript::seq
public Bio::Seq seq()
Bio::EnsEMBL::Slice
Definition: Slice.pm:50
Bio::EnsEMBL::Feature::summary_as_hash
public Hashref summary_as_hash()
exon
public exon()
Bio::EnsEMBL::Exon
Definition: Exon.pm:42
Bio::EnsEMBL::Transcript::coding_region_start
public Int coding_region_start()
Bio::EnsEMBL::Transcript
Definition: Transcript.pm:44
Bio::EnsEMBL::DBSQL::BaseAdaptor
Definition: BaseAdaptor.pm:71
Bio::EnsEMBL::Utils::Scalar
Definition: Scalar.pm:66
Bio::EnsEMBL::DBSQL::BaseAdaptor::db
public Bio::EnsEMBL::DBSQL::DBAdaptor db()
Bio::EnsEMBL::Transcript::coding_region_end
public Int coding_region_end()
Bio::EnsEMBL::Exon::start
public Int start()
Bio::EnsEMBL::Mapper::Coordinate::new
public new()
Bio::EnsEMBL::Exon::new
public Bio::EnsEMBL::Exon new()
info
public info()
Bio
Definition: AltAlleleGroup.pm:4
Bio::EnsEMBL::Utils::Argument
Definition: Argument.pm:34
Bio::EnsEMBL::Utils::Exception
Definition: Exception.pm:68
Bio::EnsEMBL::Exon::transform
public Bio::EnsEMBL::Exon transform()
Bio::EnsEMBL::Feature::equals
public Boolean Or Undef equals()
Bio::EnsEMBL::Storable::adaptor
public Bio::EnsEMBL::DBSQL::BaseAdaptor adaptor()