2 # BioPerl module for Bio::SeqFeature::Generic
4 # Please direct questions and support issues to <bioperl-l@bioperl.org>
6 # Cared for by Ewan Birney <birney@sanger.ac.uk>
8 # Copyright Ewan Birney
10 # You may distribute this module under the same terms as perl itself
12 # POD documentation - main docs before the code
16 Bio::SeqFeature::Generic - Generic SeqFeature
20 $feat = Bio::SeqFeature::Generic->new(
24 -primary => 'repeat', # -primary_tag is a synonym
25 -source_tag => 'repeatmasker',
26 -display_name => 'alu family',
30 sillytag => 'this is silly!' } );
32 $feat = Bio::SeqFeature::Generic->new( -gff_string => $string );
33 # if you want explicitly GFF1
34 $feat = Bio::SeqFeature::Generic->new( -gff1_string => $string );
36 # add it to an annotated sequence
38 $annseq->add_SeqFeature($feat);
42 Bio::SeqFeature::Generic is a generic implementation for the
43 Bio::SeqFeatureI interface, providing a simple object to provide all
44 the information for a feature on a sequence.
46 For many Features, this is all you will need to use (for example, this
47 is fine for Repeats in DNA sequence or Domains in protein
48 sequence). For other features, which have more structure, this is a
49 good base class to extend using inheritance to have new things: this
50 is what is done in the L<Bio::SeqFeature::Gene>,
51 L<Bio::SeqFeature::Transcript> and L<Bio::SeqFeature::Exon>, which provide
52 well coordinated classes to represent genes on DNA sequence (for
53 example, you can get the protein sequence out from a transcript
56 For many Features, you want to add some piece of information, for
57 example a common one is that this feature is 'new' whereas other
58 features are 'old'. The tag system, which here is implemented using a
59 hash can be used here. You can use the tag system to extend the
60 L<Bio::SeqFeature::Generic> programmatically: that is, you know that you have
61 read in more information into the tag 'mytag' which you can then
62 retrieve. This means you do not need to know how to write inherited
63 Perl to provide more complex information on a feature, and/or, if you
64 do know but you do not want to write a new class every time you need
65 some extra piece of information, you can use the tag system to easily
66 store and then retrieve information.
68 The tag system can be written in/out of GFF format, and also into EMBL
69 format via the L<Bio::SeqIO> system
71 =head1 Implemented Interfaces
73 This class implements the following interfaces.
77 =item L<Bio::SeqFeatureI>
79 Note that this includes implementing Bio::RangeI.
81 =item L<Bio::AnnotatableI>
83 =item L<Bio::FeatureHolderI>
85 Features held by a feature are essentially sub-features.
93 User feedback is an integral part of the evolution of this and other
94 Bioperl modules. Send your comments and suggestions preferably to one
95 of the Bioperl mailing lists. Your participation is much appreciated.
97 bioperl-l@bioperl.org - General discussion
98 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
102 Please direct usage questions or support issues to the mailing list:
104 I<bioperl-l@bioperl.org>
106 rather than to the module maintainer directly. Many experienced and
107 reponsive experts will be able look at the problem and quickly
108 address it. Please include a thorough description of the problem
109 with code and data examples if at all possible.
111 =head2 Reporting Bugs
113 Report bugs to the Bioperl bug tracking system to help us keep track
114 the bugs and their resolution. Bug reports can be submitted via
117 https://github.com/bioperl/bioperl-live/issues
119 =head1 AUTHOR - Ewan Birney
121 Ewan Birney E<lt>birney@sanger.ac.ukE<gt>
125 This class has been written with an eye out for inheritance. The fields
126 the actual object hash are:
128 _gsf_tag_hash = reference to a hash for the tags
129 _gsf_sub_array = reference to an array for subfeatures
133 The rest of the documentation details each of the object
134 methods. Internal methods are usually preceded with a _
139 # Let the code begin...
142 package Bio
::SeqFeature
::Generic
;
145 use Bio
::Annotation
::Collection
;
146 use Bio
::Location
::Simple
;
147 use Bio
::Location
::Split
;
151 use base
qw(Bio::Root::Root Bio::SeqFeatureI Bio::FeatureHolderI Bio::AnnotatableI);
154 my ( $caller, @args) = @_;
155 my ($self) = $caller->SUPER::new
(@args);
156 $self->_register_for_cleanup(\
&cleanup_generic
);
157 $self->{'_parse_h'} = {};
158 $self->{'_gsf_tag_hash'} = {};
160 # bulk-set attributes
161 $self->set_attributes(@args);
167 =head2 set_attributes
169 Title : set_attributes
171 Function: Sets a whole array of parameters at once.
174 Args : Named parameters, in the form as they would otherwise be passed
175 to new(). Currently recognized are:
177 -start start position
180 -phase the phase of the feature (0..2)
181 -primary_tag primary tag
182 -primary (synonym for -primary_tag)
183 -source_tag source tag
184 -source (synonym for -source_tag)
187 -tag a reference to a tag/value hash
188 -gff_string GFF v.2 string to initialize from
189 -gff1_string GFF v.1 string to initialize from
190 -seq_id the display name of the sequence
191 -annotation the AnnotationCollectionI object
192 -location the LocationI object
197 my ($self,@args) = @_;
198 my ($start, $end, $strand, $primary_tag, $source_tag, $primary,
199 $source, $frame, $score, $tag, $gff_string, $gff1_string,
200 $seqname, $seqid, $annot, $location, $display_name, $pid, $phase) =
201 $self->_rearrange([qw(START
221 $location && $self->location($location);
222 $gff_string && $self->_from_gff_string($gff_string);
224 $self->gff_format(Bio
::Tools
::GFF
->new('-gff_version' => 1));
225 $self->_from_gff_stream($gff1_string);
228 $pid && $self->primary_id($pid);
229 $primary_tag && $self->primary_tag($primary_tag);
230 $source_tag && $self->source_tag($source_tag);
231 $primary && $self->primary_tag($primary);
232 $source && $self->source_tag($source);
233 $annot && $self->annotation($annot);
234 defined $start && $self->start($start);
235 defined $end && $self->end($end);
236 defined $strand && $self->strand($strand);
237 defined $frame && $self->frame($frame);
238 defined $display_name && $self->display_name($display_name);
239 defined $score && $self->score($score);
240 defined $phase && $self->phase($phase);
243 $self->warn("-seqname is deprecated. Please use -seq_id instead.");
244 $seqid = $seqname unless $seqid;
246 $self->seq_id($seqid) if (defined($seqid));
248 foreach my $t ( keys %$tag ) {
249 $self->add_tag_value($t, UNIVERSAL
::isa
($tag->{$t}, "ARRAY") ? @
{$tag->{$t}} : $tag->{$t});
258 Usage : my $feat = Bio::SeqFeature::Generic->direct_new;
259 Function: create a blessed hash - for performance improvement in
261 Returns : Bio::SeqFeature::Generic object
279 Usage : my $location = $feat->location();
280 Function: returns a location object suitable for identifying location
281 of feature on sequence or parent feature
282 Returns : Bio::LocationI object
283 Args : [optional] Bio::LocationI object to set the value to.
288 my($self, $value ) = @_;
290 if (defined($value)) {
291 unless (ref($value) and $value->isa('Bio::LocationI')) {
292 $self->throw("object $value pretends to be a location but ".
293 "does not implement Bio::LocationI");
295 $self->{'_location'} = $value;
297 elsif (! $self->{'_location'}) {
298 # guarantees a real location object is returned every time
299 $self->{'_location'} = Bio
::Location
::Simple
->new();
301 return $self->{'_location'};
308 Usage : my $start = $feat->start;
310 Function: Get/set on the start coordinate of the feature
317 my ($self, $value) = @_;
318 # Return soon if setting value
319 if (defined $value) {
320 return $self->location->start($value);
323 return $self->location->start() if not defined $self->{'_gsf_seq'};
324 # Check circular sequences cut by origin
326 if ( $self->{'_gsf_seq'}->is_circular
327 and $self->location->isa('Bio::Location::SplitLocationI')
329 my $primary_seq_length = $self->{'_gsf_seq'}->length;
330 my @sublocs = $self->location->sub_Location;
332 my $cut_by_origin = 0;
333 my ($a_end, $a_strand) = (0, 0);
334 my ($b_start, $b_strand) = (0, 0);
335 for (my $i = 1; $i < scalar @sublocs; $i++) {
336 $a_end = $sublocs[$i-1]->end;
337 $a_strand = $sublocs[$i-1]->strand;
338 $b_start = $sublocs[$i]->start;
339 $b_strand = $sublocs[$i]->strand;
340 # cut by origin condition
341 if ( $a_end == $primary_seq_length
343 and $a_strand == $b_strand
349 $start = ($cut_by_origin == 1) ?
($sublocs[0]->start) : ($self->location->start);
352 $start = $self->location->start;
361 Usage : my $end = $feat->end;
363 Function: get/set on the end coordinate of the feature
370 my ($self, $value) = @_;
371 # Return soon if setting value
372 if (defined $value) {
373 return $self->location->end($value);
376 return $self->location->end() if not defined $self->{'_gsf_seq'};
377 # Check circular sequences cut by origin
379 if ( $self->{'_gsf_seq'}->is_circular
380 and $self->location->isa('Bio::Location::SplitLocationI')
382 my $primary_seq_length = $self->{'_gsf_seq'}->length;
383 my @sublocs = $self->location->sub_Location;
385 my $cut_by_origin = 0;
386 my ($a_end, $a_strand) = (0, 0);
387 my ($b_start, $b_strand) = (0, 0);
388 for (my $i = 1; $i < scalar @sublocs; $i++) {
389 $a_end = $sublocs[$i-1]->end;
390 $a_strand = $sublocs[$i-1]->strand;
391 $b_start = $sublocs[$i]->start;
392 $b_strand = $sublocs[$i]->strand;
393 # cut by origin condition
394 if ( $a_end == $primary_seq_length
396 and $a_strand == $b_strand
402 $end = ($cut_by_origin == 1) ?
($sublocs[-1]->end) : ($self->location->end);
405 $end = $self->location->end;
414 Usage : my $len = $feat->length;
415 Function: Get the feature length computed as:
416 $feat->end - $feat->start + 1
424 my $length = $self->end() - $self->start() + 1;
426 # In circular sequences cut by origin $start > $end,
427 # e.g., join(5075..5386,1..51)), $start = 5075, $end = 51,
428 # then adjust using the primary_seq length (5386)
429 if ($length < 0 and defined $self->{'_gsf_seq'}) {
430 $length += $self->{'_gsf_seq'}->length;
439 Usage : my $strand = $feat->strand();
440 $feat->strand($strand);
441 Function: get/set on strand information, being 1,-1 or 0
449 return $self->location->strand(@_);
456 Usage : my $score = $feat->score();
457 $feat->score($score);
458 Function: get/set on score information
460 Args : none if get, the new value if set
470 if ( defined $value && $value && $value !~ /^[A-Za-z]+$/ &&
471 $value !~ /^[+-]?\d+\.?\d*(e-\d+)?/ and $value != 0) {
472 $self->throw(-class=>'Bio::Root::BadParameter',
473 -text
=>"'$value' is not a valid score",
476 if ($self->has_tag('score')) {
477 $self->warn("Removing score value(s)");
478 $self->remove_tag('score');
480 $self->add_tag_value('score',$value);
482 my ($score) = $self->has_tag('score') ?
$self->get_tag_values('score') : undef;
490 Usage : my $frame = $feat->frame();
491 $feat->frame($frame);
492 Function: get/set on frame information
494 Args : none if get, the new value if set
503 if ( defined $value &&
504 $value !~ /^[0-2.]$/ ) {
505 $self->throw("'$value' is not a valid frame");
507 if( defined $value && $value eq '.' ) { $value = '.' }
508 return $self->{'_gsf_frame'} = $value;
510 return $self->{'_gsf_frame'};
517 Usage : my $tag = $feat->primary_tag();
518 $feat->primary_tag('exon');
519 Function: get/set on the primary tag for a feature,
528 return $self->{'_primary_tag'} = shift if @_;
529 return $self->{'_primary_tag'} || '';
536 Usage : my $tag = $feat->source_tag();
537 $feat->source_tag('genscan');
538 Function: Returns the source tag for a feature,
547 return $self->{'_source_tag'} = shift if @_;
548 return $self->{'_source_tag'} || '';
555 Usage : my $value = $feat->has_tag('some_tag');
556 Function: Tests whether a feature containings a tag
557 Returns : TRUE if the SeqFeature has the tag,
559 Args : The name of a tag
564 my ($self, $tag) = @_;
565 return exists $_[0]->{'_gsf_tag_hash'}->{$tag};
571 Title : add_tag_value
572 Usage : $feat->add_tag_value('note',"this is a note");
573 Returns : TRUE on success
574 Args : tag (string) and one or more values (any scalar(s))
581 $self->{'_gsf_tag_hash'}->{$tag} ||= [];
582 push(@
{$self->{'_gsf_tag_hash'}->{$tag}},@_);
586 =head2 get_tag_values
588 Title : get_tag_values
589 Usage : my @values = $feat->get_tag_values('note');
590 Function: Returns a list of all the values stored
591 under a particular tag.
592 Returns : A list of scalars
593 Args : The name of the tag
598 my ($self, $tag) = @_;
600 if( ! defined $tag ) { return (); }
601 if ( ! exists $self->{'_gsf_tag_hash'}->{$tag} ) {
602 $self->throw("asking for tag value that does not exist $tag");
604 return @
{$self->{'_gsf_tag_hash'}->{$tag}};
611 Usage : my @tags = $feat->get_all_tags();
612 Function: Get a list of all the tags in a feature
613 Returns : An array of tag names
616 # added a sort so that tags will be returned in a predictable order
617 # I still think we should be able to specify a sort function
618 # to the object at some point
624 my ($self, @args) = @_;
625 return sort keys %{ $self->{'_gsf_tag_hash'}};
632 Usage : $feat->remove_tag('some_tag');
633 Function: removes a tag from this feature
634 Returns : the array of values for this tag before removing it
640 my ($self, $tag) = @_;
642 if ( ! exists $self->{'_gsf_tag_hash'}->{$tag} ) {
643 $self->throw("trying to remove a tag that does not exist: $tag");
645 my @vals = @
{$self->{'_gsf_tag_hash'}->{$tag}};
646 delete $self->{'_gsf_tag_hash'}->{$tag};
654 Usage : $feat->attach_seq($seq);
655 Function: Attaches a Bio::Seq object to this feature. This
656 Bio::Seq object is for the *entire* sequence: ie
659 Returns : TRUE on success
660 Args : a Bio::PrimarySeqI compliant object
665 my ($self, $seq) = @_;
667 if ( ! ($seq && ref($seq) && $seq->isa("Bio::PrimarySeqI")) ) {
668 $self->throw("Must attach Bio::PrimarySeqI objects to SeqFeatures but got '".ref($seq)."'");
671 $self->{'_gsf_seq'} = $seq;
673 # attach to sub features if they want it
674 foreach ( $self->sub_SeqFeature() ) {
675 $_->attach_seq($seq);
684 Usage : my $tseq = $feat->seq();
685 Function: returns the truncated sequence (if there) for this
687 Returns : sub seq (a Bio::PrimarySeqI compliant object) on attached sequence
688 bounded by start & end, or undef if there is no sequence attached.
689 If the strand is defined and set to -1, the returned sequence is
690 the reverse-complement of the region
696 my ($self, $arg) = @_;
698 if ( defined $arg ) {
699 $self->throw("Calling SeqFeature::Generic->seq with an argument. You probably want attach_seq");
702 if ( ! exists $self->{'_gsf_seq'} ) {
706 # assumming our seq object is sensible, it should not have to yank
707 # the entire sequence out here.
709 my $start = $self->start;
710 my $end = $self->end;
711 # Check circular sequences cut by origin (e.g. join(2006035..2007700,1..257))
712 if ( $self->{'_gsf_seq'}->is_circular
713 and $self->location->isa('Bio::Location::SplitLocationI')
716 my $primary_seq_length = $self->{'_gsf_seq'}->length;
718 # Get duplicate object with the first sequence piece using trunc()
719 $seq = $self->{'_gsf_seq'}->trunc($start, $primary_seq_length);
721 # Get post-origin sequence and build the complete sequence
722 my $post_origin = $self->{'_gsf_seq'}->subseq(1, $end);
723 my $complete_seq = $seq->seq() . $post_origin;
725 # Add complete sequence to object
726 $seq->seq($complete_seq);
729 $seq = $self->{'_gsf_seq'}->trunc($start, $end);
732 if ( defined $self->strand && $self->strand == -1 ) {
743 Usage : my $whole_seq = $feat->entire_seq();
744 Function: gives the entire sequence that this seqfeature is attached to
746 Returns : a Bio::PrimarySeqI compliant object, or undef if there is no
753 return shift->{'_gsf_seq'};
760 Usage : $feat->seq_id($newval)
761 Function: There are many cases when you make a feature that you
762 do know the sequence name, but do not know its actual
763 sequence. This is an attribute such that you can store
764 the ID (e.g., display_id) of the sequence.
766 This attribute should *not* be used in GFF dumping, as
767 that should come from the collection in which the seq
769 Returns : value of seq_id
770 Args : newvalue (optional)
776 return $obj->{'_gsf_seq_id'} = shift if @_;
777 return $obj->{'_gsf_seq_id'};
784 Usage : my $featname = $feat->display_name;
785 Function: Implements the display_name() method, which is a human-readable
786 name for the feature.
787 Returns : value of display_name (a string)
788 Args : Optionally, on set the new value or undef
794 return $self->{'display_name'} = shift if @_;
795 return $self->{'display_name'} || '';
799 =head1 Methods for implementing Bio::AnnotatableI
804 Usage : $feat->annotation($annot_obj);
805 Function: Get/set the annotation collection object for annotating this
809 Returns : A Bio::AnnotationCollectionI object
810 Args : newvalue (optional)
815 my ($obj,$value) = @_;
817 # we are smart if someone references the object and there hasn't been
819 if(defined $value || ! defined $obj->{'annotation'} ) {
820 $value = Bio
::Annotation
::Collection
->new() unless ( defined $value );
821 $obj->{'annotation'} = $value;
823 return $obj->{'annotation'};
827 =head1 Methods to implement Bio::FeatureHolderI
829 This includes methods for retrieving, adding, and removing
830 features. Since this is already a feature, features held by this
831 feature holder are essentially sub-features.
833 =head2 get_SeqFeatures
835 Title : get_SeqFeatures
836 Usage : my @feats = $feat->get_SeqFeatures();
837 Function: Returns an array of sub Sequence Features
843 sub get_SeqFeatures
{
844 return @
{ shift->{'_gsf_sub_array'} || []};
848 =head2 add_SeqFeature
850 Title : add_SeqFeature
851 Usage : $feat->add_SeqFeature($subfeat);
852 $feat->add_SeqFeature($subfeat,'EXPAND');
853 Function: Adds a SeqFeature into the subSeqFeature array.
854 With no 'EXPAND' qualifer, subfeat will be tested
855 as to whether it lies inside the parent, and throw
858 If EXPAND is used, the parent's start/end/strand will
859 be adjusted so that it grows to accommodate the new
862 !IMPORTANT! The coordinates of the subfeature should not be relative
863 to the parent feature it is attached to, but relative to the sequence
864 the parent feature is located on.
867 Args : An object which has the SeqFeatureI interface
872 my ($self,$feat,$expand) = @_;
873 unless( defined $feat ) {
874 $self->warn("Called add_SeqFeature with no feature, ignoring");
877 if ( !$feat->isa('Bio::SeqFeatureI') ) {
878 $self->warn("$feat does not implement Bio::SeqFeatureI. Will add it anyway, but beware...");
881 if($expand && ($expand eq 'EXPAND')) {
882 $self->_expand_region($feat);
884 if ( !$self->contains($feat) ) {
885 $self->throw("$feat is not contained within parent feature, and expansion is not valid");
889 $self->{'_gsf_sub_array'} = [] unless exists($self->{'_gsf_sub_array'});
890 push(@
{$self->{'_gsf_sub_array'}},$feat);
895 =head2 remove_SeqFeatures
897 Title : remove_SeqFeatures
898 Usage : $feat->remove_SeqFeatures;
899 Function: Removes all SeqFeatures
901 If you want to remove only a subset of features then remove that
902 subset from the returned array, and add back the rest.
904 Returns : The array of Bio::SeqFeatureI implementing features that was
910 sub remove_SeqFeatures
{
912 my @subfeats = @
{$self->{'_gsf_sub_array'} || []};
913 $self->{'_gsf_sub_array'} = []; # zap the array implicitly.
918 =head1 GFF-related methods
924 my $gffio = $feat->gff_format();
925 # set (change the default version of GFF2):
926 $feat->gff_format(Bio::Tools::GFF->new(-gff_version => 1));
927 Function: Get/set the GFF format interpreter. This object is supposed to
928 format and parse GFF. See Bio::Tools::GFF for the interface.
930 If this method is called as class method, the default for all
931 newly created instances will be changed. Otherwise only this
932 instance will be affected.
934 Returns : a Bio::Tools::GFF compliant object
935 Args : On set, an instance of Bio::Tools::GFF or a derived object.
940 my ($self, $gffio) = @_;
941 if(defined($gffio)) {
943 $self->{'_gffio'} = $gffio;
945 $Bio::SeqFeatureI
::static_gff_formatter
= $gffio;
948 return (ref($self) && exists($self->{'_gffio'}) ?
949 $self->{'_gffio'} : $self->_static_gff_formatter);
956 Usage : my $str = $feat->gff_string;
957 my $str = $feat->gff_string($gff_formatter);
958 Function: Provides the feature information in GFF format.
960 We override this here from Bio::SeqFeatureI in order to use the
961 formatter returned by gff_format().
964 Args : Optionally, an object implementing gff_string().
969 my ($self,$formatter) = @_;
970 $formatter = $self->gff_format() unless $formatter;
971 return $formatter->gff_string($self);
975 =head2 slurp_gff_file
978 Usage : my @features = Bio::SeqFeature::Generic::slurp_gff_file(\*FILE);
979 Function: Sneaky function to load an entire file as in memory objects.
982 This method is deprecated. Use Bio::Tools::GFF instead, which can
983 also handle large files.
995 Bio
::Root
::Root
->throw("Must have a filehandle");
998 Bio
::Root
::Root
->deprecated( -message
=> "deprecated method slurp_gff_file() called in Bio::SeqFeature::Generic. Use Bio::Tools::GFF instead.",
999 -warn_version
=> '1.5',
1000 -throw_version
=> '1.7',
1004 my $sf = Bio
::SeqFeature
::Generic
->new('-gff_string' => $_);
1012 =head2 _from_gff_string
1014 Title : _from_gff_string
1016 Function: Set feature properties from GFF string.
1018 This method uses the object returned by gff_format() for the
1019 actual interpretation of the string. Set a different GFF format
1020 interpreter first if you need a specific version, like GFF1. (The
1024 Args : a GFF-formatted string
1028 sub _from_gff_string
{
1029 my ($self, $string) = @_;
1030 $self->gff_format()->from_gff_string($self, $string);
1034 =head2 _expand_region
1036 Title : _expand_region
1037 Usage : $feat->_expand_region($feature);
1038 Function: Expand the total region covered by this feature to
1039 accommodate for the given feature.
1041 May be called whenever any kind of subfeature is added to this
1042 feature. add_SeqFeature() already does this.
1044 Args : A Bio::SeqFeatureI implementing object.
1048 sub _expand_region
{
1049 my ($self, $feat) = @_;
1050 if(! $feat->isa('Bio::SeqFeatureI')) {
1051 $self->warn("$feat does not implement Bio::SeqFeatureI");
1053 # if this doesn't have start set - forget it!
1054 # changed to reflect sanity checks for LocationI
1055 if(!$self->location->valid_Location) {
1056 $self->start($feat->start);
1057 $self->end($feat->end);
1058 $self->strand($feat->strand) unless $self->strand;
1060 my ($start,$end,$strand) = $self->union($feat);
1061 $self->start($start);
1063 $self->strand($strand);
1072 Function: Parsing hints
1081 return $self->{'_parse_h'};
1089 Function: For internal use only. Convenience method for those tags that
1090 may only have a single value.
1091 Returns : The first value under the given tag as a scalar (string)
1092 Args : The tag as a string. Optionally, the value on set.
1100 if(@_ || (! $self->has_tag($tag))) {
1101 $self->remove_tag($tag) if($self->has_tag($tag));
1102 $self->add_tag_value($tag, @_);
1104 return ($self->get_tag_values($tag))[0];
1108 #######################################################################
1109 # aliases for methods that changed their names in an attempt to make #
1110 # bioperl names more consistent #
1111 #######################################################################
1115 $self->warn("SeqFeatureI::seqname() is deprecated. Please use seq_id() instead.");
1116 return $self->seq_id(@_);
1121 $self->warn("SeqFeatureI::display_id() is deprecated. Please use display_name() instead.");
1122 return $self->display_name(@_);
1125 # this is towards consistent naming
1126 sub each_tag_value
{ return shift->get_tag_values(@_); }
1127 sub all_tags
{ return shift->get_all_tags(@_); }
1129 # we revamped the feature containing property to implementing
1130 # Bio::FeatureHolderI
1131 *sub_SeqFeature
= \
&get_SeqFeatures
;
1132 *add_sub_SeqFeature
= \
&add_SeqFeature
;
1133 *flush_sub_SeqFeatures
= \
&remove_SeqFeatures
;
1134 # this one is because of inconsistent naming ...
1135 *flush_sub_SeqFeature
= \
&remove_SeqFeatures
;
1137 sub cleanup_generic
{
1139 foreach my $f ( @
{$self->{'_gsf_sub_array'} || []} ) {
1142 $self->{'_gsf_seq'} = undef;
1143 foreach my $t ( keys %{$self->{'_gsf_tag_hash'} } ) {
1144 $self->{'_gsf_tag_hash'}->{$t} = undef;
1145 delete($self->{'_gsf_tag_hash'}->{$t}); # bug 1720 fix