Add tests for memory leaks and weaken for Issue #81
[bioperl-live.git] / Bio / FeatureHolderI.pm
blob2ddd1e4315370c15c8a5743cc098b9504d83a91d
2 # BioPerl module for Bio::FeatureHolderI
4 # Please direct questions and support issues to <bioperl-l@bioperl.org>
6 # Cared for by Hilmar Lapp <hlapp at gmx.net>
8 # Copyright Hilmar Lapp
10 # You may distribute this module under the same terms as perl itself
12 # POD documentation - main docs before the code
14 =head1 NAME
16 Bio::FeatureHolderI - the base interface an object with features must implement
18 =head1 SYNOPSIS
20 use Bio::SeqIO;
21 # get a feature-holding object somehow: for example, Bio::SeqI objects
22 # have features
23 my $seqio = Bio::SeqIO->new(-fh => \*STDIN, -format => 'genbank');
24 while (my $seq = $seqio->next_seq()) {
25 # $seq is-a Bio::FeatureHolderI, hence:
26 my @feas = $seq->get_SeqFeatures();
27 # each element is-a Bio::SeqFeatureI
28 foreach my $fea (@feas) {
29 # do something with the feature objects
33 =head1 DESCRIPTION
35 This is the base interface that all feature-holding objects must
36 implement.
38 Popular feature-holders are for instance L<Bio::Seq> objects. Since
39 L<Bio::SeqFeatureI> defines a sub_SeqFeature() method, most
40 Bio::SeqFeatureI implementations like L<Bio::SeqFeature::Generic> will
41 implement the feature holder interface as well.
43 =head1 FEEDBACK
45 =head2 Mailing Lists
47 User feedback is an integral part of the evolution of this and other
48 Bioperl modules. Send your comments and suggestions preferably to
49 the Bioperl mailing list. Your participation is much appreciated.
51 bioperl-l@bioperl.org - General discussion
52 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
54 =head2 Support
56 Please direct usage questions or support issues to the mailing list:
58 I<bioperl-l@bioperl.org>
60 rather than to the module maintainer directly. Many experienced and
61 reponsive experts will be able look at the problem and quickly
62 address it. Please include a thorough description of the problem
63 with code and data examples if at all possible.
65 =head2 Reporting Bugs
67 Report bugs to the Bioperl bug tracking system to help us keep track
68 of the bugs and their resolution. Bug reports can be submitted via the
69 web:
71 https://github.com/bioperl/bioperl-live/issues
73 =head1 AUTHOR - Hilmar Lapp
75 Email hlapp at gmx.net
77 =head1 CONTRIBUTORS
79 Steffen Grossmann [SG], grossman-at-molgen.mpg.de
80 Mark A. Jensen, maj -at- fortinbras -dot- us
82 =head1 APPENDIX
84 The rest of the documentation details each of the object methods.
85 Internal methods are usually preceded with a _
87 =cut
90 # Let the code begin...
94 package Bio::FeatureHolderI;
95 use strict;
96 use Carp;
98 use base qw(Bio::Root::RootI);
100 =head2 get_SeqFeatures()
102 Usage : @feats = $obj->get_SeqFeatures()
103 Function: Get the feature objects held by this feature holder.
104 Example :
105 Returns : an array of Bio::SeqFeatureI implementing objects
106 if tag specified, return features having that tag
107 Args : [optional] scalar string (feature tag)
109 =cut
111 sub get_SeqFeatures {
112 shift->throw_not_implemented();
115 =head2 add_SeqFeature()
117 Usage : $feat->add_SeqFeature($subfeat);
118 $feat->add_SeqFeature($subfeat,'EXPAND')
119 Function: Add a SeqFeature into the subSeqFeature array.
120 with no 'EXPAND' qualifer, subfeat will be tested
121 as to whether it lies inside the parent, and throw
122 an exception if not.
124 If EXPAND is used and the object implements Bio::RangeI
125 (which is not guaranteed), the parent''s start/end/strand
126 will be extended so that the new subFeature can be accomodated.
127 Example :
128 Returns : nothing
129 Args : a Bio::SeqFeatureI object
131 =cut
133 sub add_SeqFeature {
134 shift->throw_not_implemented();
138 =head2 remove_SeqFeatures()
140 Usage : $obj->remove_SeqFeatures
141 Function: Removes all sub SeqFeatures. If you want to remove only a subset,
142 remove that subset from the returned array, and add back the rest.
143 Returns : The array of Bio::SeqFeatureI implementing sub-features that was
144 deleted from this feature.
145 Args : none
147 =cut
149 sub remove_SeqFeatures {
150 shift->throw_not_implemented();
153 =head2 feature_count
155 Title : feature_count
156 Usage : $obj->feature_count()
157 Function: Return the number of SeqFeatures attached to a feature holder.
159 This is before flattening a possible sub-feature tree.
161 We provide a default implementation here that just counts
162 the number of objects returned by get_SeqFeatures().
163 Implementors may want to override this with a more
164 efficient implementation.
166 Returns : integer representing the number of SeqFeatures
167 Args : None
169 At some day we may want to expand this method to allow for a feature
170 filter to be passed in.
172 Our default implementation allows for any number of additional
173 arguments and will pass them on to get_SeqFeatures(). I.e., in order to
174 support filter arguments, just support them in get_SeqFeatures().
176 =cut
178 sub feature_count {
179 return scalar(shift->get_SeqFeatures(@_));
182 =head2 get_all_SeqFeatures
184 Title : get_all_SeqFeatures
185 Usage :
186 Function: Get the flattened tree of feature objects held by this
187 feature holder. The difference to get_SeqFeatures is that
188 the entire tree of sub-features will be flattened out.
190 We provide a default implementation here, so implementors
191 don''t necessarily need to implement this method.
193 Example :
194 Returns : an array of Bio::SeqFeatureI implementing objects
195 Args : none
197 At some day we may want to expand this method to allow for a feature
198 filter to be passed in.
200 Our default implementation allows for any number of additional
201 arguments and will pass them on to any invocation of
202 get_SeqFeatures(), wherever a component of the tree implements
203 FeatureHolderI. I.e., in order to support filter arguments, just
204 support them in get_SeqFeatures().
206 =cut
208 sub get_all_SeqFeatures{
209 my $self = shift;
210 my @flatarr;
212 foreach my $feat ( $self->get_SeqFeatures(@_) ){
213 push(@flatarr,$feat);
214 &_add_flattened_SeqFeatures(\@flatarr,$feat,@_);
217 # needed to deal with subfeatures which appear more than once in the hierarchy [SG]
218 my %seen = ();
219 my @uniq_flatarr = ();
220 foreach my $feat (@flatarr) {
221 push(@uniq_flatarr, $feat) unless $seen{$feat}++;
223 return @uniq_flatarr;
226 sub _add_flattened_SeqFeatures {
227 my ($arrayref,$feat,@args) = @_;
228 my @subs = ();
230 if($feat->isa("Bio::FeatureHolderI")) {
231 @subs = $feat->get_SeqFeatures(@args);
232 } elsif($feat->isa("Bio::SeqFeatureI")) {
233 @subs = $feat->sub_SeqFeature();
234 } else {
235 confess ref($feat)." is neither a FeatureHolderI nor a SeqFeatureI. ".
236 "Don't know how to flatten.";
238 foreach my $sub (@subs) {
239 push(@$arrayref,$sub);
240 &_add_flattened_SeqFeatures($arrayref,$sub);
245 sub set_ParentIDs_from_hierarchy(){
246 # DEPRECATED - use IDHandler
247 my $self = shift;
248 require "Bio/SeqFeature/Tools/IDHandler.pm";
249 Bio::SeqFeature::Tools::IDHandler->new->set_ParentIDs_from_hierarchy($self);
252 sub create_hierarchy_from_ParentIDs(){
253 # DEPRECATED - use IDHandler
254 my $self = shift;
255 require "Bio/SeqFeature/Tools/IDHandler.pm";
256 Bio::SeqFeature::Tools::IDHandler->new->create_hierarchy_from_ParentIDs($self);