3 See the NOTICE file distributed with
this work
for additional information
4 regarding copyright ownership.
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
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.
23 Please email comments or questions to the
public Ensembl
24 developers list at <http:
26 Questions may also be sent to the Ensembl help desk at
42 -analysis => $analysis
45 my $start = $feat->start();
46 my $end = $feat->end();
47 my $strand = $feat->strand();
49 # Move the feature to the chromosomal coordinate system
50 $feature = $feature->transform(
'chromosome');
52 # Move the feature to a different slice (possibly on another coord
54 $feature = $feature->transfer($new_slice);
56 # Project the feature onto another coordinate system possibly across
58 @projection = @{ $feature->project(
'contig') };
60 # Change the start, end, and strand of the feature in place
61 $feature->move( $new_start, $new_end, $new_strand );
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
75 package Bio::EnsEMBL::Feature;
88 use Scalar::Util qw(weaken);
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
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
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
114 -analysis => $analysis);
116 of
this method are instantiated, rather than
this class itself.
118 Exceptions : Thrown on invalid -SLICE, -ANALYSIS, -STRAND ,-ADAPTOR arguments
119 Caller : general, subclass constructors
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'], @_);
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);
139 if(!ref($analysis) || !$analysis->isa(
'Bio::EnsEMBL::Analysis')) {
140 throw(
'-ANALYSIS argument must be a Bio::EnsEMBL::Analysis not '.
145 if(defined($strand)) {
146 if(!($strand == 1) && !($strand == -1) && !($strand == 0)) {
147 throw(
'-STRAND argument must be 1, -1, or 0');
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)));
157 throw(
'Start and end must be integers');
161 my $self = bless({
'start' => $start,
165 'analysis' => $analysis,
166 'seqname' => $seqname,
167 'dbID' => $dbID}, $class);
169 $self->adaptor($adaptor);
176 Arg [1] : (optional)
int $start
177 The start of
this feature relative to the start of the slice
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.
193 my ( $self, $value ) = @_;
195 if ( defined($value) ) {
196 $self->{
'start'} = $value;
199 return $self->{
'start'};
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.
221 my ( $self, $value ) = @_;
223 if ( defined($value) ) {
224 $self->{
'end'} = $value;
227 return $self->{
'end'};
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.
242 Exceptions : thrown
if an invalid strand argument is passed
249 my ( $self, $strand ) = @_;
251 if ( defined($strand) ) {
252 if ( $strand != 0 && $strand != 1 && $strand != -1 ) {
253 throw(
'strand argument must be 0, -1 or 1');
256 $self->{
'strand'} = $strand;
259 return $self->{
'strand'};
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.
272 Exceptions : Thrown is invalid arguments are provided
281 throw(
'start and end arguments are required')
if(@_ < 2);
287 if(defined($start) && defined($end) && $end < $start) {
288 throw(
'start must be less than or equal to end');
290 if(defined($strand) && $strand != 0 && $strand != -1 && $strand != 1) {
291 throw(
'strand must be 0, -1 or 1');
294 $self->{
'start'} = $start;
295 $self->{
'end'} = $end;
296 $self->{
'strand'} = $strand
if(defined($strand));
304 Example : $length = $feat->length();
305 Description: Returns the length of
this feature
307 Exceptions : Throws
if end < start and the feature is not on a
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() ) {
322 $self->slice()->seq_region_length() -
323 ( $self->{
'start'} - $self->{
'end'} ) + 1;
326 throw(
"Cannot determine length of non-circular feature "
327 .
"where start > end" );
331 return $self->{
'end'} - $self->{
'start'} + 1;
338 Description: Getter/Setter
for the analysis that is associated with
339 this feature. The analysis describes how
this feature
342 Exceptions : thrown
if an invalid argument is passed
353 if(defined($an) && (!ref($an) || !$an->isa(
'Bio::EnsEMBL::Analysis'))) {
354 throw(
'analysis argument must be a Bio::EnsEMBL::Analysis');
356 $self->{
'analysis'} = $an;
359 return $self->{
'analysis'};
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(),
374 Exceptions : thrown
if an invalid argument is passed
381 my ( $self, $slice ) = @_;
383 if ( defined($slice) ) {
384 if ( !check_ref( $slice,
'Bio::EnsEMBL::Slice' )
385 && !check_ref( $slice,
'Bio::EnsEMBL::LRGSlice' ) )
387 throw(
'slice argument must be a Bio::EnsEMBL::Slice');
390 $self->{
'slice'} = $slice;
392 delete($self->{
'slice'});
395 return $self->{
'slice'};
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:
406 1. If the two features are the same object, they are
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.
418 If none of the above is able to determine equality,
421 Return type : tri-Boolean (0, 1, undef =
"unknown")
423 Exceptions : Thrown if a non-feature is passed as the argument.
428 my ( $self, $feature ) = @_;
430 # If the features are the same object, they are equal.
431 if ( !defined($feature) ) {
return 0 }
432 if ( $self eq $feature ) {
return 1 }
434 assert_ref( $feature,
'Bio::EnsEMBL::Feature' );
436 # If the features have different types, they are *not* equal.
437 if ( ref($self) ne ref($feature) ) {
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 }
447 # We now know that one of the features do not have a dbID.
449 # If the features have the same start, end, strand and seq_region_id,
450 # and analysis_id, they are equal.
452 ( defined( $self->analysis() ) && defined( $feature->analysis() ) )
453 && ( defined( $self->slice() ) && defined( $feature->slice() ) ) )
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() ) )
467 # We now know that one of the features does not have either analysis
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
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.
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).
497 If a feature spans a boundary in the
new coordinate system,
498 undef is returned instead.
500 For example, transforming an
exon in contig coordinates to one
501 in chromosomal coodinates will place the
exon on a slice of an
504 Exceptions : thrown
if an invalid coordinate system is provided
505 warning
if Feature is not attached to a slice
506 Caller : general, transfer()
514 my $cs_version = shift;
515 my $to_slice = shift;
517 my $slice = $self->{
'slice'};
520 warning(
"Feature cannot be transformed without attached slice.");
524 if(!$slice->adaptor()) {
525 warning(
"Feature cannot be transformed without adaptor on" .
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();
536 warning(
"Feature cannot be transformed without CoordSystem on " .
542 throw(
"Cannot transform to unknown coordinate system " .
543 "[$cs_name $cs_version]\n");
546 # if feature is already in the requested coordinate system, we can just
548 if( $cs->equals( $current_cs ) && $slice->start() == 1 &&
549 $slice->strand() == 1 ) {
551 %$new_feature = %$self;
552 bless $new_feature, ref $self;
556 if(defined($to_slice)){
557 $projection = $self->project_to_slice( $to_slice ); }
559 $projection = $self->project( $cs_name, $cs_version );
562 if(@$projection == 0){
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";
571 if(defined($to_slice)){
574 foreach my $proj (@{$projection}) {
575 my $slice = $proj->[2];
576 if($to_slice->get_seq_region_id eq $slice->get_seq_region_id){
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";
591 foreach my $proj (@{$projection}) {
592 my $slice = $proj->[2];
593 warn
"available slice ".$slice->seq_region_name.
"\n";
595 warn
"MORE than one projection and no to slice specified (".$to_slice->seq_region_name.
")\n";
599 foreach my $proj (@{$projection}) {
600 warn
"Mapping is to ".$proj->[2]->seq_region_name.
"\n";
602 warn
"One projection but none to slice specified\n";
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(),
615 $p_slice->coord_system()->version);
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;
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
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.
645 If the feature cannot be placed on the provided slice because
646 it maps to an entirely different location, undef is returned
650 Exceptions :
throw on incorrect argument
651 throw if feature does not have attached slice
652 Caller : general, transform()
662 if(!$slice || !ref($slice) || (!$slice->isa(
'Bio::EnsEMBL::Slice') && !$slice->isa(
'Bio::EnsEMBL::LRGSlice'))) {
663 throw(
'Slice argument is required');
666 #make a shallow copy of the feature to be transfered
668 %{$feature} = %{$self};
669 bless $feature, ref($self);
670 weaken $feature->{adaptor};
672 my $current_slice = $self->{
'slice'};
674 if(!$current_slice) {
675 warning(
"Feature cannot be transfered without attached slice.");
679 my $cur_cs = $current_slice->coord_system();
680 my $dest_cs = $slice->coord_system();
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'};
689 # feature went to entirely different seq_region
690 if($current_slice->seq_region_name() ne $slice->seq_region_name()) {
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'};
702 if($cur_slice_strand == 1) {
703 $feature->{
'start'} = $fstart + $cur_slice_start - 1;
704 $feature->{
'end'} = $fend + $cur_slice_start - 1;
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;
713 my $fstart = $feature->{
'start'};
714 my $fend = $feature->{
'end'};
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;
721 $feature->{
'start'} = $slice->end() - $fend + 1;
722 $feature->{
'end'} = $slice->end() - $fstart + 1;
723 $feature->{
'strand'} *= -1;
726 $feature->{
'slice'} = $slice;
731 =head2 project_to_slice
733 Arg [1] : slice to project to
737 my $clone_projection = $feature->project_to_slice($slice);
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";
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
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:
761 The to_Slice is a slice spanning the region on the requested
762 coordinate system that
this feature projected to.
764 If the feature projects entirely into a gap then a reference to
765 an empty list is returned.
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
775 sub project_to_slice {
777 my $to_slice = shift;
778 my $slice = $self->{
'slice'};
781 warning(
"Feature cannot be projected without attached slice.");
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();
790 if(!$slice_adaptor) {
791 throw(
"Cannot project feature because associated slice does not have an " .
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);
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
811 my $clone_projection = $feature->project(
'clone');
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";
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
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:
835 The to_Slice is a slice spanning the region on the requested
836 coordinate system that
this feature projected to.
838 If the feature projects entirely into a gap then a reference to
839 an empty list is returned.
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
852 my $cs_version = shift;
854 my $slice = $self->{
'slice'};
857 warning(
"Feature cannot be projected without attached slice.");
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();
866 if(!$slice_adaptor) {
867 throw(
"Cannot project feature because associated slice does not have an " .
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);
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
901 $self->{
'seqname'} = shift;
904 if(!$self->{
'seqname'} && $self->slice()) {
905 return $self->slice->name();
908 return $self->{
'seqname'};
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.
925 Caller : web drawing code
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.
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.
966 Exceptions : warning
if Feature does not have attached slice.
967 Caller : web drawing code
975 my $slice = $self->
slice();
978 warning(
'Cannot obtain Feature_Slice for feature without attached slice');
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());
993 =head2 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
1006 sub seq_region_name {
1008 my $slice = $self->{
'slice'};
1010 return ($slice) ? $slice->seq_region_name() : undef;
1014 =head2 seq_region_length
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
1028 sub seq_region_length {
1030 my $slice = $self->{
'slice'};
1032 return ($slice) ? $slice->seq_region_length() : undef;
1036 =head2 seq_region_strand
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
1051 sub seq_region_strand {
1053 my $slice = $self->{
'slice'};
1055 return ($slice) ? $slice->strand() * $self->{
'strand'} : undef;
1059 =head2 seq_region_start
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)
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
1070 Returntype :
int or undef
1077 sub seq_region_start {
1080 my $slice = $self->slice();
1082 if ( defined($slice) ) {
1083 if ($slice->is_circular()) {
1084 return $self->adaptor->_seq_region_boundary_from_db($self,
'start')
1085 if $self->adaptor();
1090 if ( $slice->strand() == 1 ) {
1091 $start = $slice->start() + $self->start() - 1
1092 if defined $self->start();
1094 $start = $slice->end() - $self->end() + 1
1095 if defined $self->end();
1102 } ## end sub seq_region_start
1105 =head2 seq_region_end
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)
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
1116 Returntype :
int or undef
1123 sub seq_region_end {
1126 my $slice = $self->slice();
1128 if ( defined($slice) ) {
1129 if ($slice->is_circular()) {
1130 return $self->adaptor->_seq_region_boundary_from_db($self,
'end')
1131 if $self->adaptor();
1136 if ( $slice->strand() == 1 ) {
1137 $end = $slice->start() + $self->end() - 1
1138 if defined $self->end();
1140 $end = $slice->end() - $self->start() + 1
1141 if defined $self->start()
1148 } ## end sub seq_region_end
1151 =head2 coord_system_name
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
1164 sub coord_system_name {
1166 my $slice = $self->{
'slice'};
1167 return ($slice) ? $slice->coord_system_name() : undef;
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
1190 if( ! defined $self->{
'slice'} ) {
1194 if(!$self->strand()) {
1195 warning(
"Cannot retrieve sequence for unstranded feature.");
1199 return $self->{
'slice'}->subseq($self->start(), $self->end(),
1207 =head2 get_all_alt_locations
1209 Arg [1] : Boolean
override flag to force the method to
return all
1210 Features on the reference sequence as well.
1212 Example : @features = @{$feature->get_all_alt_locations()};
1213 foreach $f (@features) {
1214 print $f->slice->seq_region_name,
' ',$f->start, $f->end,
"\n";
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.
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).
1232 Returntype : listref of features of the same type of
this feature.
1239 sub get_all_alt_locations {
1241 my $return_all = shift || 0;
1243 my $slice = $self->{
'slice'} or
return [];
1244 my $sa = $slice->adaptor() or
return [];
1246 # get slice of entire region
1247 $slice = $sa->fetch_by_seq_region_id($slice->get_seq_region_id);
1249 my $axfa = $sa->db->get_AssemblyExceptionFeatureAdaptor();
1250 my $axfs = $axfa->fetch_all_by_Slice($slice);
1254 foreach my $axf (@$axfs) {
1255 if(uc($axf->type()) eq
'HAP') {
1257 } elsif(uc($axf->type()) =~
'PAR') {
1259 } elsif( $axf->type() eq
"PATCH_FIX"){
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"){
1268 }elsif( $axf->type() eq
"PATCH_NOVEL REF"){
1269 push @haps, $axf
if $return_all > 0 ;
1271 warning(
"Unknown exception feature type ". $axf->type().
"- ignoring.");
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();
1281 if($h->start() > 1 && $haslice->start() > 1) {
1282 my $aslice = $sa->fetch_by_region($hacs->name(),
1283 $haslice->seq_region_name(),
1285 $haslice->start()-1,
1291 -end => $h->start()-1,
1292 -alternate_slice => $aslice);
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(),
1300 $haslice->seq_region_length(),
1305 (-start => $h->end() + 1,
1306 -end => $slice->seq_region_length(),
1307 -alternate_slice => $aslice);
1312 # check if exception regions contain our feature
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());
1321 # quick shallow copy of the feature
1324 bless $f, ref($self);
1326 my $aslice = $axf->alternate_slice();
1328 # position feature on entire slice of other region
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();
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();
1338 $f->{
'slice'} = $sa->fetch_by_seq_region_id($aslice->get_seq_region_id());
1350 The other feature you want to check overlap with
this feature
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.
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
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");
1373 return ($self->seq_region_end >= $f->seq_region_start and $self->seq_region_start <= $f->seq_region_end) ? 1 : 0;
1376 =head2 overlaps_local
1378 Arg [1] : Bio::EnsEMBL::Feature $f
1379 The other feature you want to check overlap with this feature
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.
1386 This method will not attempt to resolve starts and ends with
1387 reference to the feature's backing Slice.
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
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");
1405 return ($self->end >= $f->start and $self->start <= $f->end) ? 1 : 0;
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.
1419 sub get_overlapping_Genes{
1420 my ($self, $match_strands, $five_prime, $three_prime) = @_;
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 ];
1426 # query for absolute nearest.
1428 =head2 get_nearest_Gene
1430 Description: Get the nearest genes to the feature
1437 sub get_nearest_Gene {
1440 my $list = $ga->fetch_nearest_by_Feature($self);
1441 if ($list && @$list >0) {
1442 my ($gene, $distance) = @{ $list };
1449 =head2 feature_so_acc
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)
1458 sub feature_so_acc {
1461 my $ref = ref $self;
1464 # Get the caller class SO acc
1466 $so_acc = $ref->SEQUENCE_ONTOLOGY->{
'acc'};
1469 if (!$so_acc && $ref ne
'Bio::EnsEMBL::Feature' ) {
1470 throw(
"constant SEQUENCE_ONTOLOGY in ${ref} is not defined");
1476 =head2 feature_so_term
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)
1485 sub feature_so_term {
1488 my $ref = ref $self;
1491 # Get the caller class SO acc
1493 $so_term = $ref->SEQUENCE_ONTOLOGY->{
'term'};
1496 if (!$so_term && $ref ne
'Bio::EnsEMBL::Feature' ) {
1497 throw(
"constant SEQUENCE_ONTOLOGY in ${ref} is not defined");
1503 =head2 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
1512 sub summary_as_hash {
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;
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
1536 throw "Can only call this method if you have attached an adaptor" if ! $self->adaptor();
1537 return $self->adaptor()->db()->species();
1542 =head2 sub_SeqFeature
1544 Deprecated - For genebuild backwards compatibility.
1545 Avoid using it if possible
1549 return @{$self->{'_gsf_sub_array
'}} if($self->{'_gsf_sub_array
'});
1552 =head2 add_sub_SeqFeature
1554 Deprecated - only for genebuild backward compatibility.
1555 Avoid using it if possible
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 ) {
1564 $self->start($feat->start());
1565 $self->end($feat->end());
1566 $self->strand($feat->strand);
1568 if( $feat->start < $self->start ) {
1569 $self->start($feat->start);
1572 if( $feat->end > $self->end ) {
1573 $self->end($feat->end);
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");
1583 push(@{$self->{
'_gsf_sub_array'}},$feat);
1586 =head2 flush_sub_SeqFeature
1588 Deprecated - Only
for genebuild backwards compatibility.
1589 Avoid
using it
if possible
1591 sub flush_sub_SeqFeature {
1593 $self->{
'_gsf_sub_array'} = [];