ensembl-hive  2.8.1
Feature.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::Feature - Ensembl specific sequence feature.
34 
35 =head1 SYNOPSIS
36 
37  my $feat = new Bio::EnsEMBL::Feature(
38  -start => 100,
39  -end => 220,
40  -strand => -1,
41  -slice => $slice,
42  -analysis => $analysis
43  );
44 
45  my $start = $feat->start();
46  my $end = $feat->end();
47  my $strand = $feat->strand();
48 
49  # Move the feature to the chromosomal coordinate system
50  $feature = $feature->transform('chromosome');
51 
52  # Move the feature to a different slice (possibly on another coord
53  # system)
54  $feature = $feature->transfer($new_slice);
55 
56  # Project the feature onto another coordinate system possibly across
57  # boundaries:
58  @projection = @{ $feature->project('contig') };
59 
60  # Change the start, end, and strand of the feature in place
61  $feature->move( $new_start, $new_end, $new_strand );
62 
63 =head1 DESCRIPTION
64 
65 This is the Base feature class from which all Ensembl features inherit.
66 It provides a bare minimum functionality that all features require. It
67 basically describes a location on a sequence in an arbitrary coordinate
68 system.
69 
70 =head1 METHODS
71 
72 =cut
73 
74 
75 package Bio::EnsEMBL::Feature;
76 
77 use strict;
78 use warnings;
79 
81 use Bio::EnsEMBL::Utils::Argument qw(rearrange);
82 use Bio::EnsEMBL::Utils::Exception qw(throw warning);
83 use Bio::EnsEMBL::Utils::Scalar qw(check_ref assert_ref);
85 
86 use vars qw(@ISA);
87 
88 use Scalar::Util qw(weaken);
89 
90 @ISA = qw(Bio::EnsEMBL::Storable);
91 
92 
93 =head2 new
94 
95  Arg [-SLICE]: Bio::EnsEMBL::SLice - Represents the sequence that this
96  feature is on. The coordinates of the created feature are
97  relative to the start of the slice.
98  Arg [-START]: The start coordinate of this feature relative to the start
99  of the slice it is sitting on. Coordinates start at 1 and
100  are inclusive.
101  Arg [-END] : The end coordinate of this feature relative to the start of
102  the slice it is sitting on. Coordinates start at 1 and are
103  inclusive.
104  Arg [-STRAND]: The orientation of this feature. Valid values are 1,-1,0.
105  Arg [-SEQNAME] : A seqname to be used instead of the default name of the
106  of the slice. Useful for features that do not have an
107  attached slice such as protein features.
108  Arg [-dbID] : (optional) internal database id
109  Arg [-ADAPTOR]: (optional) Bio::EnsEMBL::DBSQL::BaseAdaptor
110  Example : $feature = Bio::EnsEMBL::Feature->new(-start => 1,
111  -end => 100,
112  -strand => 1,
113  -slice => $slice,
114  -analysis => $analysis);
115  Description: Constructs a new Bio::EnsEMBL::Feature. Generally subclasses
116  of this method are instantiated, rather than this class itself.
117  Returntype : Bio::EnsEMBL::Feature
118  Exceptions : Thrown on invalid -SLICE, -ANALYSIS, -STRAND ,-ADAPTOR arguments
119  Caller : general, subclass constructors
120  Status : Stable
121 
122 =cut
123 
124 
125 sub new {
126  my $caller = shift;
127 
128  my $class = ref($caller) || $caller;
129  my ( $start, $end, $strand, $slice, $analysis,$seqname, $dbID, $adaptor ) =
130  rearrange(['START','END','STRAND','SLICE','ANALYSIS', 'SEQNAME',
131  'DBID', 'ADAPTOR'], @_);
132  if($slice) {
133  if(!ref($slice) || !($slice->isa('Bio::EnsEMBL::Slice') or $slice->isa('Bio::EnsEMBL::LRGSlice')) ) {
134  throw('-SLICE argument must be a Bio::EnsEMBL::Slice not '.$slice);
135  }
136  }
137 
138  if($analysis) {
139  if(!ref($analysis) || !$analysis->isa('Bio::EnsEMBL::Analysis')) {
140  throw('-ANALYSIS argument must be a Bio::EnsEMBL::Analysis not '.
141  $analysis);
142  }
143  }
144 
145  if(defined($strand)) {
146  if(!($strand == 1) && !($strand == -1) && !($strand == 0)) {
147  throw('-STRAND argument must be 1, -1, or 0');
148  }
149  }
150 
151  if(defined($start) && defined($end)) {
152  if (($start =~ /\d+/) && ($end =~ /\d+/)) {
153  if($end+1 < $start and $slice and !$slice->is_circular()) {
154  throw(sprintf('Start (%d) must be less than or equal to end+1 (%d)', $start, ($end+1)));
155  }
156  } else {
157  throw('Start and end must be integers');
158  }
159  }
160 
161  my $self = bless({'start' => $start,
162  'end' => $end,
163  'strand' => $strand,
164  'slice' => $slice,
165  'analysis' => $analysis,
166  'seqname' => $seqname,
167  'dbID' => $dbID}, $class);
168 
169  $self->adaptor($adaptor);
170  return $self;
171 }
172 
173 
174 =head2 start
175 
176  Arg [1] : (optional) int $start
177  The start of this feature relative to the start of the slice
178  that it is on.
179  Example : $start = $feat->start()
180  Description: Getter/Setter for the start of this feature relative to the
181  start of the slice it is on. Note that negative values, or
182  values exceeding the length of the slice are permitted.
183  Start must be less than or equal to the end regardless of the
184  strand. Coordinate values start at 1 and are inclusive.
185  Returntype : int
186  Exceptions : none
187  Caller : general
188  Status : Stable
189 
190 =cut
191 
192 sub start {
193  my ( $self, $value ) = @_;
194 
195  if ( defined($value) ) {
196  $self->{'start'} = $value;
197  }
198 
199  return $self->{'start'};
200 }
201 
202 
203 
204 =head2 end
205 
206  Arg [1] : (optional) int $end
207  Example : $end = $feat->end();
208  Description: Getter/Setter for the end of this feature relative to the
209  start of the slice that it is on. Note that negative values,
210  of values exceeding the length of the slice are permitted. End
211  must be greater than or equal to start regardless of the strand.
212  Coordinate values start at 1 and are inclusive.
213  Returntype : int
214  Exceptions : none
215  Caller : general
216  Status : Stable
217 
218 =cut
219 
220 sub end {
221  my ( $self, $value ) = @_;
222 
223  if ( defined($value) ) {
224  $self->{'end'} = $value;
225  }
226 
227  return $self->{'end'};
228 }
229 
230 
231 
232 
233 =head2 strand
234 
235  Arg [1] : (optional) int $strand
236  Example : $feat->strand(-1);
237  Description: Getter/Setter for the strand of this feature relative to the
238  slice it is on. 0 is an unknown or non-applicable strand.
239  -1 is the reverse (negative) strand and 1 is the forward
240  (positive) strand. No other values are permitted.
241  Returntype : int
242  Exceptions : thrown if an invalid strand argument is passed
243  Caller : general
244  Status : Stable
245 
246 =cut
247 
248 sub strand {
249  my ( $self, $strand ) = @_;
250 
251  if ( defined($strand) ) {
252  if ( $strand != 0 && $strand != 1 && $strand != -1 ) {
253  throw('strand argument must be 0, -1 or 1');
254  }
255 
256  $self->{'strand'} = $strand;
257  }
258 
259  return $self->{'strand'};
260 }
261 
262 =head2 move
263 
264  Arg [1] : int start
265  Arg [2] : int end
266  Arg [3] : (optional) int strand
267  Description: Sets the start, end and strand in one call rather than in
268  3 seperate calls to the start(), end() and strand() methods.
269  This is for convenience and for speed when this needs to be
270  done within a tight loop.
271  Returntype : none
272  Exceptions : Thrown is invalid arguments are provided
273  Caller : general
274  Status : Stable
275 
276 =cut
277 
278 sub move {
279  my $self = shift;
280 
281  throw('start and end arguments are required') if(@_ < 2);
282 
283  my $start = shift;
284  my $end = shift;
285  my $strand = shift;
286 
287  if(defined($start) && defined($end) && $end < $start) {
288  throw('start must be less than or equal to end');
289  }
290  if(defined($strand) && $strand != 0 && $strand != -1 && $strand != 1) {
291  throw('strand must be 0, -1 or 1');
292  }
293 
294  $self->{'start'} = $start;
295  $self->{'end'} = $end;
296  $self->{'strand'} = $strand if(defined($strand));
297 }
298 
299 
300 
301 =head2 length
302 
303  Arg [1] : none
304  Example : $length = $feat->length();
305  Description: Returns the length of this feature
306  Returntype : Integer
307  Exceptions : Throws if end < start and the feature is not on a
308  circular slice
309  Caller : general
310  Status : Stable
311 
312 =cut
313 
314 sub length {
315  my ($self) = @_;
316 
317  if ( $self->{'end'} < $self->{'start'} ) {
318  # if circular, we can work out the length of an origin-spanning
319  # feature using the size of the underlying region.
320  if ( $self->slice() && $self->slice()->is_circular() ) {
321  my $len =
322  $self->slice()->seq_region_length() -
323  ( $self->{'start'} - $self->{'end'} ) + 1;
324  return $len;
325  } else {
326  throw( "Cannot determine length of non-circular feature "
327  . "where start > end" );
328  }
329  }
330 
331  return $self->{'end'} - $self->{'start'} + 1;
332 }
333 
334 =head2 analysis
335 
336  Arg [1] : (optional) Bio::EnsEMBL::Analysis $analysis
337  Example : $feature->analysis(new Bio::EnsEMBL::Analysis(...))
338  Description: Getter/Setter for the analysis that is associated with
339  this feature. The analysis describes how this feature
340  was derived.
341  Returntype : Bio::EnsEMBL::Analysis
342  Exceptions : thrown if an invalid argument is passed
343  Caller : general
344  Status : Stable
345 
346 =cut
347 
348 sub analysis {
349  my $self = shift;
350 
351  if(@_) {
352  my $an = shift;
353  if(defined($an) && (!ref($an) || !$an->isa('Bio::EnsEMBL::Analysis'))) {
354  throw('analysis argument must be a Bio::EnsEMBL::Analysis');
355  }
356  $self->{'analysis'} = $an;
357  }
358 
359  return $self->{'analysis'};
360 }
361 
362 
363 
364 =head2 slice
365 
366  Arg [1] : (optional) Bio::EnsEMBL::Slice $slice
367  Example : $seqname = $feature->slice()->name();
368  Description: Getter/Setter for the Slice that is associated with this
369  feature. The slice represents the underlying sequence that this
370  feature is on. Note that this method call is analagous to the
371  old SeqFeature methods contig(), entire_seq(), attach_seq(),
372  etc.
373  Returntype : Bio::EnsEMBL::Slice
374  Exceptions : thrown if an invalid argument is passed
375  Caller : general
376  Status : Stable
377 
378 =cut
379 
380 sub slice {
381  my ( $self, $slice ) = @_;
382 
383  if ( defined($slice) ) {
384  if ( !check_ref( $slice, 'Bio::EnsEMBL::Slice' )
385  && !check_ref( $slice, 'Bio::EnsEMBL::LRGSlice' ) )
386  {
387  throw('slice argument must be a Bio::EnsEMBL::Slice');
388  }
389 
390  $self->{'slice'} = $slice;
391  } elsif ( @_ > 1 ) {
392  delete($self->{'slice'});
393  }
394 
395  return $self->{'slice'};
396 }
397 
398 =head2 equals
399 
400  Arg [1] : Bio::EnsEMBL::Feature object
401  Example : if ($featureA->equals($featureB)) { ... }
402  Description : Compares two features using various criteria. The
403  test for eqality goes through the following list and
404  terminates at the first true match:
405 
406  1. If the two features are the same object, they are
407  equal.
408  2. If they are of different types (e.g., transcript
409  and gene), they are *not* equal.
410  3. If they both have dbIDs: if these are the same,
411  then they are equal, otherwise not.
412  4. If they both have slices and analysis objects:
413  if the analysis dbIDs are the same and the
414  seq_region_id are the same, along with
415  seq_region_start and seq_region_end, then they are
416  equal, otherwise not.
417 
418  If none of the above is able to determine equality,
419  undef is returned.
420 
421  Return type : tri-Boolean (0, 1, undef = "unknown")
422 
423  Exceptions : Thrown if a non-feature is passed as the argument.
424 
425 =cut
426 
427 sub equals {
428  my ( $self, $feature ) = @_;
429 
430  # If the features are the same object, they are equal.
431  if ( !defined($feature) ) { return 0 }
432  if ( $self eq $feature ) { return 1 }
433 
434  assert_ref( $feature, 'Bio::EnsEMBL::Feature' );
435 
436  # If the features have different types, they are *not* equal.
437  if ( ref($self) ne ref($feature) ) {
438  return 0;
439  }
440 
441  # If the features has the same dbID, they are equal.
442  if ( defined( $self->dbID() ) && defined( $feature->dbID() ) ) {
443  if ( $self->dbID() == $feature->dbID() ) { return 1 }
444  else { return 0 }
445  }
446 
447  # We now know that one of the features do not have a dbID.
448 
449  # If the features have the same start, end, strand and seq_region_id,
450  # and analysis_id, they are equal.
451  if (
452  ( defined( $self->analysis() ) && defined( $feature->analysis() ) )
453  && ( defined( $self->slice() ) && defined( $feature->slice() ) ) )
454  {
455  if ( ( $self->start() == $feature->start() ) &&
456  ( $self->end() == $feature->end() ) &&
457  ( $self->strand() == $feature->strand() ) &&
458  ( $self->slice()->get_seq_region_id() ==
459  $feature->slice()->get_seq_region_id() ) &&
460  ( $self->analysis()->dbID() == $feature->analysis()->dbID() ) )
461  {
462  return 1;
463  }
464  else { return 0 }
465  }
466 
467  # We now know that one of the features does not have either analysis
468  # or slice.
469 
470  # We don't know if the features are equal. This happens if they are
471  # not the same object but are of the same type, and one of them lacks
472  # dbID, and if there aren't slice and analysis objects attached to
473  # them both.
474  return undef;
475 } ## end sub equals
476 
477 
478 =head2 transform
479 
480  Arg [1] : string $coord_system
481  The coord system to transform this feature to.
482  Arg [2] : string $version (optional)
483  The version of the coord system to transform this feature to.
484  Arg [3] : Bio::EnsEMBL::Slice (optional)
485  Specified when a projection may land on many overlapping slices
486  and disambiguation is required.
487  Example : $feature = $feature->transform('contig');
488  next if(!defined($feature));
489  Description: Returns a copy of this feature, but converted to a different
490  coordinate system. The converted feature will be placed on a
491  slice which spans an entire sequence region of the new
492  coordinate system. If the requested coordinate system is the
493  same coordinate system it is simply placed on a slice which
494  spans the entire seq_region (as opposed to the original slice
495  which may have only partially covered the seq_region).
496 
497  If a feature spans a boundary in the new coordinate system,
498  undef is returned instead.
499 
500  For example, transforming an exon in contig coordinates to one
501  in chromosomal coodinates will place the exon on a slice of an
502  entire chromosome.
503  Returntype : Bio::EnsEMBL::Feature (or undef)
504  Exceptions : thrown if an invalid coordinate system is provided
505  warning if Feature is not attached to a slice
506  Caller : general, transfer()
507  Status : Stable
508 
509 =cut
510 
511 sub transform {
512  my $self = shift;
513  my $cs_name = shift;
514  my $cs_version = shift;
515  my $to_slice = shift;
516 
517  my $slice = $self->{'slice'};
518 
519  if(!$slice) {
520  warning("Feature cannot be transformed without attached slice.");
521  return undef;
522  }
523 
524  if(!$slice->adaptor()) {
525  warning("Feature cannot be transformed without adaptor on" .
526  " attached slice.");
527  return undef;
528  }
529 
530  #use db from slice since this feature may not yet be stored in a database
531  my $db = $slice->adaptor->db();
532  my $cs = $db->get_CoordSystemAdaptor->fetch_by_name($cs_name, $cs_version);
533  my $current_cs = $slice->coord_system();
534 
535  if(!$current_cs) {
536  warning("Feature cannot be transformed without CoordSystem on " .
537  "attached slice.");
538  return undef;
539  }
540 
541  if(!$cs) {
542  throw("Cannot transform to unknown coordinate system " .
543  "[$cs_name $cs_version]\n");
544  }
545 
546  # if feature is already in the requested coordinate system, we can just
547  # return a copy
548  if( $cs->equals( $current_cs ) && $slice->start() == 1 &&
549  $slice->strand() == 1 ) {
550  my $new_feature;
551  %$new_feature = %$self;
552  bless $new_feature, ref $self;
553  return $new_feature;
554  }
555  my $projection;
556  if(defined($to_slice)){
557  $projection = $self->project_to_slice( $to_slice ); }
558  else{
559  $projection = $self->project( $cs_name, $cs_version );
560  }
561 
562  if(@$projection == 0){
563  return undef;
564  }
565  if( @$projection != 1 and !defined($to_slice)) {
566 # warn "MORE than one projection and NO slice specified ";
567 # warn "from ".$self->slice->name." to $cs_name, $cs_version\n";
568  return undef;
569  }
570  my $index = 0;
571  if(defined($to_slice)){
572  my $found = 0;
573  my $i = 0;
574  foreach my $proj (@{$projection}) {
575  my $slice = $proj->[2];
576  if($to_slice->get_seq_region_id eq $slice->get_seq_region_id){
577  $found =1;
578  $index = $i;
579  }
580  $i++;
581  }
582  if(!$found){
583  if(@$projection != 1){
584  if(@$projection == 0){
585  warn "number of mappings is ".@$projection."\n";
586  warn "could not project feature ".ref($self)." from ".$self->slice->seq_region_name." to ".$to_slice->seq_region_name."\n";
587  warn "In the region of ".$self->slice->start." <-> ".$self->slice->end."\n";
588  warn "feat start=".($self->slice->start+$self->start)."\tend=".($self->slice->start+$self->end)."\n";
589  }
590  else{
591  foreach my $proj (@{$projection}) {
592  my $slice = $proj->[2];
593  warn "available slice ".$slice->seq_region_name."\n";
594  }
595  warn "MORE than one projection and no to slice specified (".$to_slice->seq_region_name.")\n";
596  }
597  }
598  else {
599  foreach my $proj (@{$projection}) {
600  warn "Mapping is to ".$proj->[2]->seq_region_name."\n";
601  }
602  warn "One projection but none to slice specified\n";
603  }
604  return undef;
605  }
606  }
607 
608  my $p_slice = $projection->[$index]->[2];
609  my $slice_adaptor = $db->get_SliceAdaptor;
610  $slice = $slice_adaptor->fetch_by_region($p_slice->coord_system()->name(),
611  $p_slice->seq_region_name(),
612  undef, #start
613  undef, #end
614  1, #strand
615  $p_slice->coord_system()->version);
616 
617  my $new_feature;
618  %$new_feature = %$self;
619  bless $new_feature, ref $self;
620  $new_feature->{'start'} = $p_slice->start();
621  $new_feature->{'end'} = $p_slice->end();
622  $new_feature->{'strand'} =
623  ($self->{'strand'} == 0) ? 0 : $p_slice->strand();
624  $new_feature->{'slice'} = $slice;
625  return $new_feature;
626 
627 }
628 
629 
630 
631 =head2 transfer
632 
633  Arg [1] : Bio::EnsEMBL::Slice $slice
634  The slice to transfer this feature to
635  Example : $feature = $feature->transfer($slice);
636  next if(!defined($feature));
637  Description: Returns a copy of this feature which has been shifted onto
638  another slice.
639 
640  If the new slice is in a different coordinate system the
641  feature is transformed first and then placed on the slice.
642  If the feature would be split across a coordinate system
643  boundary or mapped to a gap undef is returned instead.
644 
645  If the feature cannot be placed on the provided slice because
646  it maps to an entirely different location, undef is returned
647  instead.
648 
649  Returntype : Bio::EnsEMBL::Feature (or undef)
650  Exceptions : throw on incorrect argument
651  throw if feature does not have attached slice
652  Caller : general, transform()
653  Status : Stable
654 
655 =cut
656 
657 
658 sub transfer {
659  my $self = shift;
660  my $slice = shift;
661 
662  if(!$slice || !ref($slice) || (!$slice->isa('Bio::EnsEMBL::Slice') && !$slice->isa('Bio::EnsEMBL::LRGSlice'))) {
663  throw('Slice argument is required');
664  }
665 
666  #make a shallow copy of the feature to be transfered
667  my $feature;
668  %{$feature} = %{$self};
669  bless $feature, ref($self);
670  weaken $feature->{adaptor};
671 
672  my $current_slice = $self->{'slice'};
673 
674  if(!$current_slice) {
675  warning("Feature cannot be transfered without attached slice.");
676  return undef;
677  }
678 
679  my $cur_cs = $current_slice->coord_system();
680  my $dest_cs = $slice->coord_system();
681 
682  #if we are not in the same coord system a transformation step is needed first
683  if(!$dest_cs->equals($cur_cs)) {
684  $feature = $feature->transform($dest_cs->name, $dest_cs->version, $slice);
685  return undef if(!defined($feature));
686  $current_slice = $feature->{'slice'};
687  }
688 
689  # feature went to entirely different seq_region
690  if($current_slice->seq_region_name() ne $slice->seq_region_name()) {
691  return undef;
692  }
693 
694  #if the current feature positions are not relative to the start of the
695  #seq region, convert them so they are
696  my $cur_slice_start = $current_slice->start();
697  my $cur_slice_strand = $current_slice->strand();
698  if($cur_slice_start != 1 || $cur_slice_strand != 1) {
699  my $fstart = $feature->{'start'};
700  my $fend = $feature->{'end'};
701 
702  if($cur_slice_strand == 1) {
703  $feature->{'start'} = $fstart + $cur_slice_start - 1;
704  $feature->{'end'} = $fend + $cur_slice_start - 1;
705  } else {
706  my $cur_slice_end = $current_slice->end();
707  $feature->{'start'} = $cur_slice_end - $fend + 1;
708  $feature->{'end'} = $cur_slice_end - $fstart + 1;
709  $feature->{'strand'} *= -1;
710  }
711  }
712 
713  my $fstart = $feature->{'start'};
714  my $fend = $feature->{'end'};
715 
716  #convert to destination slice coords
717  if($slice->strand == 1) {
718  $feature->{'start'} = $fstart - $slice->start() + 1;
719  $feature->{'end'} = $fend - $slice->start() + 1;
720  } else {
721  $feature->{'start'} = $slice->end() - $fend + 1;
722  $feature->{'end'} = $slice->end() - $fstart + 1;
723  $feature->{'strand'} *= -1;
724  }
725 
726  $feature->{'slice'} = $slice;
727 
728  return $feature;
729 }
730 
731 =head2 project_to_slice
732 
733  Arg [1] : slice to project to
734 
735 
736  Example :
737  my $clone_projection = $feature->project_to_slice($slice);
738 
739  foreach my $seg (@$clone_projection) {
740  my $clone = $seg->to_Slice();
741  print "Features current coords ", $seg->from_start, '-',
742  $seg->from_end, " project onto clone coords " .
743  $clone->seq_region_name, ':', $clone->start, '-', $clone->end,
744  $clone->strand, "\n";
745  }
746  Description: Returns the results of 'projecting' this feature onto another
747  slice . This is useful to see where a feature
748  would lie in a coordinate system in which it
749  crosses a boundary.
750 
751  This method returns a reference to a list of
753  ProjectionSegments are blessed arrays and can also be used as
754  triplets [from_start,from_end,to_Slice]. The from_start and
755  from_end are the coordinates relative to the feature start.
756  For example, if a feature is current 100-200bp on a slice
757  then the triplets returned might be:
758  [1,50,$slice1],
759  [51,101,$slice2]
760 
761  The to_Slice is a slice spanning the region on the requested
762  coordinate system that this feature projected to.
763 
764  If the feature projects entirely into a gap then a reference to
765  an empty list is returned.
766 
767  Returntype : listref of Bio::EnsEMBL::ProjectionSegments
768  which can also be used as [$start,$end,$slice] triplets
769  Exceptions : slice does not have an adaptor
770  Caller : general
771  Status : At Risk
772 
773 =cut
774 
775 sub project_to_slice {
776  my $self = shift;
777  my $to_slice = shift;
778  my $slice = $self->{'slice'};
779 
780  if(!$slice) {
781  warning("Feature cannot be projected without attached slice.");
782  return [];
783  }
784 
785 
786  #get an adaptor from the attached slice because this feature may not yet
787  #be stored and may not have its own adaptor
788  my $slice_adaptor = $slice->adaptor();
789 
790  if(!$slice_adaptor) {
791  throw("Cannot project feature because associated slice does not have an " .
792  " adaptor");
793  }
794 
795  my $strand = $self->strand() * $slice->strand();
796  #fetch by feature always gives back forward strand slice:
797  $slice = $slice_adaptor->fetch_by_Feature($self);
798  $slice = $slice->invert if($strand == -1);
799  return $slice->project_to_slice($to_slice);
800 }
801 
802 
803 =head2 project
804 
805  Arg [1] : string $name
806  The name of the coordinate system to project this feature onto
807  Arg [2] : string $version (optional)
808  The version of the coordinate system (such as 'NCBI34') to
809  project this feature onto
810  Example :
811  my $clone_projection = $feature->project('clone');
812 
813  foreach my $seg (@$clone_projection) {
814  my $clone = $seg->to_Slice();
815  print "Features current coords ", $seg->from_start, '-',
816  $seg->from_end, " project onto clone coords " .
817  $clone->seq_region_name, ':', $clone->start, '-', $clone->end,
818  $clone->strand, "\n";
819  }
820  Description: Returns the results of 'projecting' this feature onto another
821  coordinate system. This is useful to see where a feature
822  would lie in a coordinate system in which it
823  crosses a boundary.
824 
825  This method returns a reference to a list of
827  ProjectionSegments are blessed arrays and can also be used as
828  triplets [from_start,from_end,to_Slice]. The from_start and
829  from_end are the coordinates relative to the feature start.
830  For example, if a feature is current 100-200bp on a slice
831  then the triplets returned might be:
832  [1,50,$slice1],
833  [51,101,$slice2]
834 
835  The to_Slice is a slice spanning the region on the requested
836  coordinate system that this feature projected to.
837 
838  If the feature projects entirely into a gap then a reference to
839  an empty list is returned.
840 
841  Returntype : listref of Bio::EnsEMBL::ProjectionSegments
842  which can also be used as [$start,$end,$slice] triplets
843  Exceptions : slice does not have an adaptor
844  Caller : general
845  Status : Stable
846 
847 =cut
848 
849 sub project {
850  my $self = shift;
851  my $cs_name = shift;
852  my $cs_version = shift;
853 
854  my $slice = $self->{'slice'};
855 
856  if(!$slice) {
857  warning("Feature cannot be projected without attached slice.");
858  return [];
859  }
860 
861 
862  #get an adaptor from the attached slice because this feature may not yet
863  #be stored and may not have its own adaptor
864  my $slice_adaptor = $slice->adaptor();
865 
866  if(!$slice_adaptor) {
867  throw("Cannot project feature because associated slice does not have an " .
868  " adaptor");
869  }
870 
871  my $strand = $self->strand() * $slice->strand();
872  #fetch by feature always gives back forward strand slice:
873  $slice = $slice_adaptor->fetch_by_Feature($self);
874  $slice = $slice->invert if($strand == -1);
875  return $slice->project($cs_name, $cs_version);
876 }
877 
878 
879 
880 =head2 seqname
881 
882  Arg [1] : (optional) $seqname
883  Example : $seqname = $feat->seqname();
884  Description: Getter/Setter for the name of the sequence that this feature
885  is on. Normally you can get away with not setting this value
886  and it will default to the name of the slice on which this
887  feature is on. It is useful to set this value on features which
888  do not ordinarily sit on features such as ProteinFeatures which
889  sit on peptides.
890  Returntype : string
891  Exceptions : none
892  Caller : general
893  Status : Stable
894 
895 =cut
896 
897 sub seqname {
898  my $self = shift;
899 
900  if(@_) {
901  $self->{'seqname'} = shift;
902  }
903 
904  if(!$self->{'seqname'} && $self->slice()) {
905  return $self->slice->name();
906  }
907 
908  return $self->{'seqname'};
909 }
910 
911 
912 
913 
914 =head2 display_id
915 
916  Arg [1] : none
917  Example : print $f->display_id();
918  Description: This method returns a string that is considered to be
919  the 'display' identifier. It is overridden by subclasses to
920  return an appropriate value for objects of that particular
921  class. If no appropriate display id is available an empty
922  string is returned instead.
923  Returntype : string
924  Exceptions : none
925  Caller : web drawing code
926  Status : Stable
927 
928 =cut
929 
930 sub display_id {
931  my $self = shift;
932  return '';
933 }
934 
935 =head2 version
936 
937  Arg [1] : none
938  Example : print $f->version();
939  Description: This method returns a string that is considered to be
940  the identifier version. It is overridden by subclasses to
941  return an appropriate value for objects of that particular
942  class. If no appropriate version is available an empty
943  string is returned instead.
944  Returntype : string
945  Exceptions : none
946  Caller : general
947  Status : Stable
948 
949 =cut
950 
951 sub version {
952  my $self = shift;
953  return '';
954 }
955 
956 
957 =head2 feature_Slice
958 
959  Args : none
960  Example : $slice = $feature->feature_Slice()
961  Description: This is a convenience method to return a slice that covers the
962  Area of this feature. The feature start will be at 1 on it, and
963  it will have the length of this feature.
964  Returntype : Bio::EnsEMBL::Slice or undef if this feature has no attached
965  Slice.
966  Exceptions : warning if Feature does not have attached slice.
967  Caller : web drawing code
968  Status : Stable
969 
970 =cut
971 
972 sub feature_Slice {
973  my $self = shift;
974 
975  my $slice = $self->slice();
976 
977  if(!$slice) {
978  warning('Cannot obtain Feature_Slice for feature without attached slice');
979  return undef;
980  }
981 
982  return Bio::EnsEMBL::Slice->new
983  (-seq_region_name => $slice->seq_region_name,
984  -seq_region_length => $slice->seq_region_length,
985  -coord_system => $slice->coord_system,
986  -start => $self->seq_region_start(),
987  -end => $self->seq_region_end(),
988  -strand => $self->seq_region_strand(),
989  -adaptor => $slice->adaptor());
990 }
991 
992 
993 =head2 seq_region_name
994 
995  Arg [1] : none
996  Example : print $feature->seq_region_name();
997  Description: Gets the name of the seq_region which this feature is on.
998  Returns undef if this Feature is not on a slice.
999  Returntype : string or undef
1000  Exceptions : none
1001  Caller : general
1002  Status : Stable
1003 
1004 =cut
1005 
1006 sub seq_region_name {
1007  my $self = shift;
1008  my $slice = $self->{'slice'};
1009 
1010  return ($slice) ? $slice->seq_region_name() : undef;
1011 }
1012 
1013 
1014 =head2 seq_region_length
1015 
1016  Arg [1] : none
1017  Example : print $feature->seq_region_length();
1018  Description: Returns the length of the seq_region which this feature is on
1019  Returns undef if this Feature is not on a slice.
1020  Returntype : int (unsigned) or undef
1021  Exceptions : none
1022  Caller : general
1023  Status : Stable
1024 
1025 =cut
1026 
1027 
1028 sub seq_region_length {
1029  my $self = shift;
1030  my $slice = $self->{'slice'};
1031 
1032  return ($slice) ? $slice->seq_region_length() : undef;
1033 }
1034 
1035 
1036 =head2 seq_region_strand
1037 
1038  Arg [1] : none
1039  Example : print $feature->seq_region_strand();
1040  Description: Returns the strand of the seq_region which this feature is on
1041  (i.e. feature_strand * slice_strand)
1042  Returns undef if this Feature is not on a slice.
1043  Returntype : 1,0,-1 or undef
1044  Exceptions : none
1045  Caller : general
1046  Status : Stable
1047 
1048 =cut
1049 
1050 
1051 sub seq_region_strand {
1052  my $self = shift;
1053  my $slice = $self->{'slice'};
1054 
1055  return ($slice) ? $slice->strand() * $self->{'strand'} : undef;
1056 }
1057 
1058 
1059 =head2 seq_region_start
1060 
1061  Arg [1] : none
1062  Example : print $feature->seq_region_start();
1063  Description: Convenience method which returns the absolute start of this
1064  feature on the seq_region, as opposed to the relative (slice)
1065  position.
1066 
1067  Returns undef if this feature is not on a slice or slice is
1068  circular and cannot determine the position of the feature from
1069  the db.
1070  Returntype : int or undef
1071  Exceptions : none
1072  Caller : general
1073  Status : Stable
1074 
1075 =cut
1076 
1077 sub seq_region_start {
1078  my ($self) = @_;
1079 
1080  my $slice = $self->slice();
1081 
1082  if ( defined($slice) ) {
1083  if ($slice->is_circular()) {
1084  return $self->adaptor->_seq_region_boundary_from_db($self, 'start')
1085  if $self->adaptor();
1086  return undef;
1087  }
1088 
1089  my $start;
1090  if ( $slice->strand() == 1 ) {
1091  $start = $slice->start() + $self->start() - 1
1092  if defined $self->start();
1093  } else {
1094  $start = $slice->end() - $self->end() + 1
1095  if defined $self->end();
1096  }
1097 
1098  return $start;
1099  }
1100 
1101  return undef;
1102 } ## end sub seq_region_start
1103 
1104 
1105 =head2 seq_region_end
1106 
1107  Arg [1] : none
1108  Example : print $feature->seq_region_end();
1109  Description: Convenience method which returns the absolute end of this
1110  feature on the seq_region, as opposed to the relative (slice)
1111  position.
1112 
1113  Returns undef if this feature is not on a slice or slice is
1114  circular and cannot determine the position of the feature from
1115  the db.
1116  Returntype : int or undef
1117  Exceptions : none
1118  Caller : general
1119  Status : Stable
1120 
1121 =cut
1122 
1123 sub seq_region_end {
1124  my ($self) = @_;
1125 
1126  my $slice = $self->slice();
1127 
1128  if ( defined($slice) ) {
1129  if ($slice->is_circular()) {
1130  return $self->adaptor->_seq_region_boundary_from_db($self, 'end')
1131  if $self->adaptor();
1132  return undef;
1133  }
1134 
1135  my $end;
1136  if ( $slice->strand() == 1 ) {
1137  $end = $slice->start() + $self->end() - 1
1138  if defined $self->end();
1139  } else {
1140  $end = $slice->end() - $self->start() + 1
1141  if defined $self->start()
1142  }
1143 
1144  return $end;
1145  }
1146 
1147  return undef;
1148 } ## end sub seq_region_end
1149 
1150 
1151 =head2 coord_system_name
1152 
1153  Arg [1] : none
1154  Example : print $feature->coord_system_name()
1155  Description: Gets the name of the coord_system which this feature is on.
1156  Returns undef if this Feature is not on a slice.
1157  Returntype : string or undef
1158  Exceptions : none
1159  Caller : general
1160  Status : Stable
1161 
1162 =cut
1163 
1164 sub coord_system_name {
1165  my $self = shift;
1166  my $slice = $self->{'slice'};
1167  return ($slice) ? $slice->coord_system_name() : undef;
1168 }
1169 
1170 
1171 =head2 seq
1172 
1173  Args : none
1174  Example : my $dna_sequence = $simple_feature->seq();
1175  Description: Returns the dna sequence from the attached slice and
1176  attached database that overlaps with this feature.
1177  Returns undef if there is no slice or no database.
1178  Returns undef if this feature is unstranded (i.e. strand=0).
1179  Returntype : String or undef
1180  Exceptions : warning if this feature is not stranded
1181  Caller : general
1182  Status : Stable
1183 
1184 =cut
1185 
1186 
1187 sub seq {
1188  my $self = shift;
1189 
1190  if( ! defined $self->{'slice'} ) {
1191  return undef;
1192  }
1193 
1194  if(!$self->strand()) {
1195  warning("Cannot retrieve sequence for unstranded feature.");
1196  return undef;
1197  }
1198 
1199  return $self->{'slice'}->subseq($self->start(), $self->end(),
1200  $self->strand());
1201 
1202 }
1203 
1204 
1205 
1206 
1207 =head2 get_all_alt_locations
1208 
1209  Arg [1] : Boolean override flag to force the method to return all
1210  Features on the reference sequence as well.
1211 
1212  Example : @features = @{$feature->get_all_alt_locations()};
1213  foreach $f (@features) {
1214  print $f->slice->seq_region_name,' ',$f->start, $f->end,"\n";
1215  }
1216 
1217  Description: Retrieves shallow copies of this feature in its alternate
1218  locations. A feature can be considered to have multiple
1219  locations when it sits on a alternative structural haplotype
1220  or when it is on a Pseudo Autosomal Region. Most features will
1221  just return a reference to an empty list though.
1222  The features returned by this method will be on a slice which
1223  covers the entire alternate region.
1224 
1225  Currently this method does not take into account alternate
1226  locations on the alternate locations (e.g. a reference
1227  sequence may have multiple alternate haplotypes. Asking
1228  for alternate locations of a feature on one of the alternate
1229  haplotypes will give you back the reference location, but not
1230  locations on the other alternate haplotypes).
1231 
1232  Returntype : listref of features of the same type of this feature.
1233  Exceptions : none
1234  Caller : general
1235  Status : Stable
1236 
1237 =cut
1238 
1239 sub get_all_alt_locations {
1240  my $self = shift;
1241  my $return_all = shift || 0;
1242 
1243  my $slice = $self->{'slice'} or return [];
1244  my $sa = $slice->adaptor() or return [];
1245 
1246  # get slice of entire region
1247  $slice = $sa->fetch_by_seq_region_id($slice->get_seq_region_id);
1248 
1249  my $axfa = $sa->db->get_AssemblyExceptionFeatureAdaptor();
1250  my $axfs = $axfa->fetch_all_by_Slice($slice);
1251 
1252  my (@haps, @alt);
1253 
1254  foreach my $axf (@$axfs) {
1255  if(uc($axf->type()) eq 'HAP') {
1256  push @haps, $axf;
1257  } elsif(uc($axf->type()) =~ 'PAR') {
1258  push @alt, $axf;
1259  } elsif( $axf->type() eq "PATCH_FIX"){
1260  push @haps, $axf;
1261  } elsif( $axf->type() eq "PATCH_FIX REF"){
1262  push @haps, $axf if $return_all > 0 ;
1263  } elsif( $axf->type() eq "HAP REF" ) {
1264  push @haps, $axf if $return_all > 0 ;
1265  # do nothing when you are on REF
1266  } elsif( $axf->type() eq "PATCH_NOVEL"){
1267  push @haps, $axf;
1268  }elsif( $axf->type() eq "PATCH_NOVEL REF"){
1269  push @haps, $axf if $return_all > 0 ;
1270  } else {
1271  warning("Unknown exception feature type ". $axf->type()."- ignoring.");
1272  }
1273  }
1274 
1275  # regions surrounding hap are those of interest, not hap itself
1276  # convert hap alt. exc. features to regions around haps instead
1277  foreach my $h (@haps) {
1278  my $haslice = $h->alternate_slice();
1279  my $hacs = $haslice->coord_system();
1280 
1281  if($h->start() > 1 && $haslice->start() > 1) {
1282  my $aslice = $sa->fetch_by_region($hacs->name(),
1283  $haslice->seq_region_name(),
1284  1,
1285  $haslice->start()-1,
1286  $haslice->strand(),
1287  $hacs->version());
1288 
1290  (-start => 1,
1291  -end => $h->start()-1,
1292  -alternate_slice => $aslice);
1293  }
1294 
1295  if($h->end() < $slice->seq_region_length() &&
1296  $haslice->end < $haslice->seq_region_length()) {
1297  my $aslice = $sa->fetch_by_region($hacs->name(),
1298  $haslice->seq_region_name(),
1299  $haslice->end()+1,
1300  $haslice->seq_region_length(),
1301  $haslice->strand(),
1302  $hacs->version());
1303 
1305  (-start => $h->end() + 1,
1306  -end => $slice->seq_region_length(),
1307  -alternate_slice => $aslice);
1308  }
1309  }
1310 
1311 
1312  # check if exception regions contain our feature
1313 
1314  my @features;
1315 
1316  foreach my $axf (@alt) {
1317  # ignore other region if feature is not entirely on it
1318  next if($self->seq_region_start() < $axf->start() ||
1319  $self->seq_region_end() > $axf->end());
1320 
1321  # quick shallow copy of the feature
1322  my $f;
1323  %$f = %$self;
1324  bless $f, ref($self);
1325 
1326  my $aslice = $axf->alternate_slice();
1327 
1328  # position feature on entire slice of other region
1329 
1330  # Cache seq_region_* to prevent contamination when changing feature coordinates.
1331  my $seq_region_start = $f->seq_region_start();
1332  my $seq_region_end = $f->seq_region_end();
1333 
1334  $f->{'start'} = $seq_region_start - $axf->start() + $aslice->start();
1335  $f->{'end'} = $seq_region_end - $axf->start() + $aslice->start();
1336  $f->{'strand'} *= $aslice->strand();
1337 
1338  $f->{'slice'} = $sa->fetch_by_seq_region_id($aslice->get_seq_region_id());
1339 
1340  push @features, $f;
1341  }
1342 
1343  return \@features;
1344 }
1345 
1346 
1347 =head2 overlaps
1348 
1349  Arg [1] : Bio::EnsEMBL::Feature $f
1350  The other feature you want to check overlap with this feature
1351  for.
1352  Description: This method does a range comparison of this feature's C<seq_region_start> and
1353  C<seq_region_end> and compares it with another feature's C<seq_region_start>
1354  and C<seq_region_end>. It will return true if these ranges overlap
1355  and the features are on the same seq_region.
1356 
1357  For local coordinate overlaps tests (those values returned from
1358  start and end) use C<overlaps_local()>.
1359  Returntype : TRUE if features overlap, FALSE if they don't
1360  Exceptions : warning if features are on different seq_regions
1361  Caller : general
1362  Status : Stable
1363 
1364 =cut
1365 
1366 sub overlaps {
1367  my ($self, $f) = @_;
1368  my ($sr1, $sr2) = ($self->seq_region_name, $f->seq_region_name);
1369  if($sr1 && $sr2 && ($sr1 ne $sr2)) {
1370  warning("Bio::EnsEMBL::Feature->overlaps(): features are on different seq regions. \$self is on $sr1 and \$feature is on $sr2");
1371  return 0;
1372  }
1373  return ($self->seq_region_end >= $f->seq_region_start and $self->seq_region_start <= $f->seq_region_end) ? 1 : 0;
1374 }
1375 
1376 =head2 overlaps_local
1377 
1378  Arg [1] : Bio::EnsEMBL::Feature $f
1379  The other feature you want to check overlap with this feature
1380  for.
1381  Description: This method does a range comparison of this feature's start and
1382  end and compares it with another feature's start and end. It
1383  will return true if these ranges overlap and the features are
1384  on the same seq_region.
1385 
1386  This method will not attempt to resolve starts and ends with
1387  reference to the feature's backing Slice.
1388 
1389  For global coordinate overlaps tests (with reference to the feature's
1390  backing sequence region) use C<overlaps()>.
1391  Returntype : TRUE if features overlap, FALSE if they don't
1392  Exceptions : warning if features are on different seq_regions
1393  Caller : general
1394  Status : Stable
1395 
1396 =cut
1397 
1398 sub overlaps_local {
1399  my ($self, $f) = @_;
1400  my ($sr1, $sr2) = ($self->seq_region_name, $f->seq_region_name);
1401  if($sr1 && $sr2 && ($sr1 ne $sr2)) {
1402  warning("Bio::EnsEMBL::Feature->overlaps_local(): features are on different seq regions. \$self is on $sr1 and \$feature is on $sr2");
1403  return;
1404  }
1405  return ($self->end >= $f->start and $self->start <= $f->end) ? 1 : 0;
1406 }
1407 
1408 =head2 get_overlapping_Genes
1409  Arg [1] : Optional Boolean: Stranded match i.e. match strand of Feature and Genes
1410  Arg [2] : Optional Boolean: Get Genes with an overlapping 5' end
1411  Arg [3] : Optional Boolean: Get Genes with an overlapping 3' end
1412  Description: Get all the genes that overlap this feature.
1413  Returntype : list ref of Bio::EnsEMBL::Gene
1414  Caller : general
1415  Status : UnStable
1416 
1417 =cut
1418 
1419 sub get_overlapping_Genes{
1420  my ($self, $match_strands, $five_prime, $three_prime) = @_;
1421  my $ga = Bio::EnsEMBL::Registry->get_adaptor($self->species,'core','Gene');
1422  my $list = $ga->fetch_all_nearest_by_Feature(-FEATURE => $self, -RANGE => 0, -THREE_PRIME => $three_prime, -FIVE_PRIME => $five_prime, -MATCH_STRAND => $match_strands);
1423  return [ map { $_->[0] } @$list ];
1424 }
1425 
1426 # query for absolute nearest.
1427 
1428 =head2 get_nearest_Gene
1429 
1430  Description: Get the nearest genes to the feature
1431  Returntype : Bio::EnsEMBL::Gene or undef if none can be found nearby
1432  Caller : general
1433  Status : At risk
1434 
1435 =cut
1436 
1437 sub get_nearest_Gene {
1438  my $self = shift;
1439  my $ga = Bio::EnsEMBL::Registry->get_adaptor($self->species,'core','Gene');
1440  my $list = $ga->fetch_nearest_by_Feature($self);
1441  if ($list && @$list >0) {
1442  my ($gene, $distance) = @{ $list };
1443  return $gene;
1444  } else {
1445  return;
1446  }
1447 }
1448 
1449 =head2 feature_so_acc
1450 
1451  Description: This method returns a string containing the SO accession number of the feature
1452  Define constant SEQUENCE_ONTOLOGY in classes that require it, or override it for multiple possible values for a class.
1453  Returntype : String (Sequence Ontology accession number)
1454  Exceptions : Thrown if caller SEQUENCE_ONTOLOGY is undefined and is not a Bio::EnsEMBL::Feature
1455 
1456 =cut
1457 
1458 sub feature_so_acc {
1459  my ($self) = @_;
1460 
1461  my $ref = ref $self;
1462  my $so_acc;
1463 
1464  # Get the caller class SO acc
1465  eval {
1466  $so_acc = $ref->SEQUENCE_ONTOLOGY->{'acc'};
1467  };
1468 
1469  if (!$so_acc && $ref ne 'Bio::EnsEMBL::Feature' ) {
1470  throw( "constant SEQUENCE_ONTOLOGY in ${ref} is not defined");
1471  }
1472 
1473  return $so_acc // 'SO:0000001';
1474 }
1475 
1476 =head2 feature_so_term
1477 
1478  Description: This method returns a string containing the SO term of the feature
1479  Define constant SEQUENCE_ONTOLOGY in classes that require it, or override it for multiple possible values for a class.
1480  Returntype : String (Sequence Ontology term)
1481  Exceptions : Thrown if caller SEQUENCE_ONTOLOGY is undefined and is not a Bio::EnsEMBL::Feature
1482 
1483 =cut
1484 
1485 sub feature_so_term {
1486  my ($self) = @_;
1487 
1488  my $ref = ref $self;
1489  my $so_term;
1490 
1491  # Get the caller class SO acc
1492  eval {
1493  $so_term = $ref->SEQUENCE_ONTOLOGY->{'term'};
1494  };
1495 
1496  if (!$so_term && $ref ne 'Bio::EnsEMBL::Feature' ) {
1497  throw( "constant SEQUENCE_ONTOLOGY in ${ref} is not defined");
1498  }
1499 
1500  return $so_term // 'region';
1501 }
1502 
1503 =head2 summary_as_hash
1504 
1505  Example : $feature_summary = $feature->summary_as_hash();
1506  Description : Retrieves a textual summary of this Feature.
1507  Should be overidden by subclasses for specific tweaking
1508  Returns : hashref of arrays of descriptive strings
1509  Status : Intended for internal use
1510 =cut
1511 
1512 sub summary_as_hash {
1513  my $self = shift;
1514  my %summary;
1515  $summary{'id'} = $self->display_id;
1516  $summary{'version'} = $self->version() if $self->version();
1517  $summary{'start'} = $self->seq_region_start;
1518  $summary{'end'} = $self->seq_region_end;
1519  $summary{'strand'} = $self->strand;
1520  $summary{'seq_region_name'} = $self->seq_region_name;
1521  return \%summary;
1522 }
1523 
1524 =head2 species
1525 
1526  Example : $feature->species();
1527  Description : Shortcut to the feature's DBAdaptor and returns its species name
1528  Returntype : String the species name
1529  Exceptions : Thrown if there is no attached adaptor
1530  Caller : Webcode
1531 
1532 =cut
1533 
1534 sub species {
1535  my ($self) = @_;
1536  throw "Can only call this method if you have attached an adaptor" if ! $self->adaptor();
1537  return $self->adaptor()->db()->species();
1538 }
1539 
1540 
1541 
1542 =head2 sub_SeqFeature
1543 
1544  Deprecated - For genebuild backwards compatibility.
1545  Avoid using it if possible
1546 =cut
1547 sub sub_SeqFeature{
1548  my ($self) = @_;
1549  return @{$self->{'_gsf_sub_array'}} if($self->{'_gsf_sub_array'});
1550 }
1551 
1552 =head2 add_sub_SeqFeature
1553 
1554  Deprecated - only for genebuild backward compatibility.
1555  Avoid using it if possible
1556 =cut
1557 sub add_sub_SeqFeature{
1558  my ($self,$feat,$expand) = @_;
1559  my ($p, $f, $l) = caller;
1560  if( $expand eq 'EXPAND' ) {
1561  # if this doesn't have start/end set - forget it!
1562  if( ! $self->start && ! $self->end ) {
1563 
1564  $self->start($feat->start());
1565  $self->end($feat->end());
1566  $self->strand($feat->strand);
1567  } else {
1568  if( $feat->start < $self->start ) {
1569  $self->start($feat->start);
1570  }
1571 
1572  if( $feat->end > $self->end ) {
1573  $self->end($feat->end);
1574  }
1575  }
1576  } else {
1577  if($self->start > $feat->start || $self->end < $feat->end) {
1578  throw("$feat is not contained within parent feature, " .
1579  "and expansion is not valid");
1580  }
1581  }
1582 
1583  push(@{$self->{'_gsf_sub_array'}},$feat);
1584 }
1585 
1586 =head2 flush_sub_SeqFeature
1587 
1588  Deprecated - Only for genebuild backwards compatibility.
1589  Avoid using it if possible
1590 =cut
1591 sub flush_sub_SeqFeature {
1592  my ($self) = @_;
1593  $self->{'_gsf_sub_array'} = [];
1594 }
1595 
1596 
1597 1;
transcript
public transcript()
Bio::EnsEMBL::Registry::get_adaptor
public Adaptor get_adaptor()
Bio::EnsEMBL::ProjectionSegment
Definition: ProjectionSegment.pm:27
map
public map()
Bio::EnsEMBL::Feature
Definition: Feature.pm:47
Bio::EnsEMBL::Slice::slice
public slice()
accession
public accession()
Bio::EnsEMBL::Storable
Definition: Storable.pm:23
Bio::EnsEMBL::Gene
Definition: Gene.pm:37
Bio::EnsEMBL::Slice
Definition: Slice.pm:50
Bio::EnsEMBL::Registry
Definition: Registry.pm:113
Bio::EnsEMBL::Feature::summary_as_hash
public Hashref summary_as_hash()
Bio::EnsEMBL::Slice::new
public Bio::EnsEMBL::Slice new()
exon
public exon()
Bio::EnsEMBL::Slice::seq_region_name
public String seq_region_name()
Bio::EnsEMBL::Analysis
Definition: PairAlign.pm:3
Bio::EnsEMBL::DBSQL::BaseAdaptor
Definition: BaseAdaptor.pm:71
Bio::EnsEMBL::Utils::Scalar
Definition: Scalar.pm:66
Bio::EnsEMBL::Feature::new
public Bio::EnsEMBL::Feature new()
Bio::EnsEMBL::AssemblyExceptionFeature::new
public Bio::EnsEMBL::Feature new()
Bio::EnsEMBL::Utils::Argument
Definition: Argument.pm:34
Bio::EnsEMBL::AssemblyExceptionFeature
Definition: AssemblyExceptionFeature.pm:27
Bio::EnsEMBL::Utils::Exception
Definition: Exception.pm:68