3 # BioPerl module for Bio::SeqFeature::AnnotationAdaptor
5 # Please direct questions and support issues to <bioperl-l@bioperl.org>
7 # Cared for by Hilmar Lapp <hlapp at gmx.net>
9 # Copyright Hilmar Lapp
11 # You may distribute this module under the same terms as perl itself
14 # (c) Hilmar Lapp, hlapp at gmx.net, 2002.
15 # (c) GNF, Genomics Institute of the Novartis Research Foundation, 2002.
17 # You may distribute this module under the same terms as perl itself.
18 # Refer to the Perl Artistic License (see the license accompanying this
19 # software package, or see http://www.perl.com/language/misc/Artistic.html)
20 # for the terms under which you may use, modify, and redistribute this module.
22 # THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
23 # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
24 # MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27 # POD documentation - main docs before the code
31 Bio::SeqFeature::AnnotationAdaptor - integrates SeqFeatureIs annotation
35 use Bio::SeqFeature::Generic;
36 use Bio::SeqFeature::AnnotationAdaptor;
38 # obtain a SeqFeatureI implementing object somehow
39 my $feat = Bio::SeqFeature::Generic->new(-start => 10, -end => 20);
41 # add tag/value annotation
42 $feat->add_tag_value("mytag", "value of tag mytag");
43 $feat->add_tag_value("mytag", "another value of tag mytag");
45 # Bio::SeqFeature::Generic also provides annotation(), which returns a
46 # Bio::AnnotationCollectionI compliant object
47 $feat->annotation->add_Annotation("dbxref", $dblink);
49 # to integrate tag/value annotation with AnnotationCollectionI
50 # annotation, use this adaptor, which also implements
51 # Bio::AnnotationCollectionI
52 my $anncoll = Bio::SeqFeature::AnnotationAdaptor->new(-feature => $feat);
54 # this will now return tag/value pairs as
55 # Bio::Annotation::SimpleValue objects
56 my @anns = $anncoll->get_Annotations("mytag");
57 # other added before annotation is available too
58 my @dblinks = $anncoll->get_Annotations("dbxref");
60 # also supports transparent adding of tag/value pairs in
61 # Bio::AnnotationI flavor
62 my $tagval = Bio::Annotation::SimpleValue->new(-value => "some value",
63 -tagname => "some tag");
64 $anncoll->add_Annotation($tagval);
65 # this is now also available from the feature's tag/value system
66 my @vals = $feat->each_tag_value("some tag");
70 L<Bio::SeqFeatureI> defines light-weight annotation of features
71 through tag/value pairs. Conversely, L<Bio::AnnotationCollectionI>
72 together with L<Bio::AnnotationI> defines an annotation bag, which is
73 better typed, but more heavy-weight because it contains every single
74 piece of annotation as objects. The frequently used base
75 implementation of Bio::SeqFeatureI, Bio::SeqFeature::Generic, defines
76 an additional slot for AnnotationCollectionI-compliant annotation.
78 This adaptor provides a L<Bio::AnnotationCollectionI> compliant,
79 unified, and integrated view on the annotation of L<Bio::SeqFeatureI>
80 objects, including tag/value pairs, and annotation through the
81 annotation() method, if the object supports it. Code using this
82 adaptor does not need to worry about the different ways of possibly
83 annotating a SeqFeatureI object, but can instead assume that it
84 strictly follows the AnnotationCollectionI scheme. The price to pay is
85 that retrieving and adding annotation will always use objects instead
86 of light-weight tag/value pairs.
88 In other words, this adaptor allows us to keep the best of both
89 worlds. If you create tens of thousands of feature objects, and your
90 only annotation is tag/value pairs, you are best off using the
91 features' native tag/value system. If you create a smaller number of
92 features, but with rich and typed annotation mixed with tag/value
93 pairs, this adaptor may be for you. Since its implementation is by
94 double-composition, you only need to create one instance of the
95 adaptor. In order to transparently annotate a feature object, set the
96 feature using the feature() method. Every annotation you add will be
97 added to the feature object, and hence will not be lost when you set
98 feature() to the next object.
104 User feedback is an integral part of the evolution of this and other
105 Bioperl modules. Send your comments and suggestions preferably to
106 the Bioperl mailing list. Your participation is much appreciated.
108 bioperl-l@bioperl.org - General discussion
109 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
113 Please direct usage questions or support issues to the mailing list:
115 L<bioperl-l@bioperl.org>
117 rather than to the module maintainer directly. Many experienced and
118 reponsive experts will be able look at the problem and quickly
119 address it. Please include a thorough description of the problem
120 with code and data examples if at all possible.
122 =head2 Reporting Bugs
124 Report bugs to the Bioperl bug tracking system to help us keep track
125 of the bugs and their resolution. Bug reports can be submitted via the
128 http://bugzilla.open-bio.org/
130 =head1 AUTHOR - Hilmar Lapp
132 Email hlapp at gmx.net
136 The rest of the documentation details each of the object methods.
137 Internal methods are usually preceded with a _
142 #' Let the code begin...
145 package Bio
::SeqFeature
::AnnotationAdaptor
;
148 # Object preamble - inherits from Bio::Root::Root
150 use Bio
::Annotation
::SimpleValue
;
152 use base
qw(Bio::Root::Root Bio::AnnotationCollectionI Bio::AnnotatableI);
157 Usage : my $obj = Bio::SeqFeature::AnnotationAdaptor->new();
158 Function: Builds a new Bio::SeqFeature::AnnotationAdaptor object
159 Returns : an instance of Bio::SeqFeature::AnnotationAdaptor
160 Args : Named parameters
161 -feature the Bio::SeqFeatureI implementing object to adapt
162 (mandatory to be passed here, or set via feature()
163 before calling other methods)
164 -annotation the Bio::AnnotationCollectionI implementing object
165 for storing richer annotation (this will default to
166 the $feature->annotation() if it supports it)
167 -tagvalue_factory the object factory to use for creating tag/value
168 pair representing objects
174 my($class,@args) = @_;
176 my $self = $class->SUPER::new
(@args);
178 my ($feat,$anncoll,$fact) =
179 $self->_rearrange([qw(FEATURE
181 TAGVALUE_FACTORY)], @args);
183 $self->feature($feat) if $feat;
184 $self->annotation($anncoll) if $feat;
185 $self->tagvalue_object_factory($fact) if $fact;
193 Usage : $obj->feature($newval)
194 Function: Get/set the feature that this object adapts to an
195 AnnotationCollectionI.
197 Returns : value of feature (a Bio::SeqFeatureI compliant object)
198 Args : new value (a Bio::SeqFeatureI compliant object, optional)
204 my ($self,$value) = @_;
205 if( defined $value) {
206 $self->{'feature'} = $value;
208 return $self->{'feature'};
214 Usage : $obj->annotation($newval)
215 Function: Get/set the AnnotationCollectionI implementing object used by
216 this adaptor to store additional annotation that cannot be stored
217 by the SeqFeatureI itself.
219 If requested before having been set, the value will default to the
220 annotation object of the feature if it has one.
222 Returns : value of annotation (a Bio::AnnotationCollectionI compliant object)
223 Args : new value (a Bio::AnnotationCollectionI compliant object, optional)
229 my ($self,$value) = @_;
231 if( defined $value) {
232 $self->{'annotation'} = $value;
234 if((! exists($self->{'annotation'})) &&
235 $self->feature()->can('annotation')) {
236 return $self->feature()->annotation();
238 return $self->{'annotation'};
241 =head1 AnnotationCollectionI implementing methods
245 =head2 get_all_annotation_keys
247 Title : get_all_annotation_keys
248 Usage : $ac->get_all_annotation_keys()
249 Function: gives back a list of annotation keys, which are simple text strings
250 Returns : list of strings
255 sub get_all_annotation_keys
{
259 # get the tags from the feature object
260 if ($self->feature()->can('get_all_tags')) {
261 push(@keys, $self->feature()->get_all_tags());
263 push(@keys, $self->feature()->all_tags());
265 # ask the annotation implementation in addition, while avoiding duplicates
266 if($self->annotation()) {
268 grep { ! $self->feature->has_tag($_); }
269 $self->annotation()->get_all_annotation_keys());
276 =head2 get_Annotations
278 Title : get_Annotations
279 Usage : my @annotations = $collection->get_Annotations('key')
280 Function: Retrieves all the Bio::AnnotationI objects for a specific key
281 Returns : list of Bio::AnnotationI - empty if no objects stored for a key
282 Args : string which is key for annotations
287 my ($self, @keys) = @_;
290 # we need a annotation object factory
291 my $fact = $self->tagvalue_object_factory();
293 # get all tags if no keys have been provided
294 @keys = $self->feature->all_tags() unless @keys;
296 # build object for each value for each tag
297 foreach my $key (@keys) {
298 # protect against keys that aren't tags
299 next unless $self->feature->has_tag($key);
300 # add each tag/value pair as a SimpleValue object
301 foreach my $val ($self->feature()->get_tag_values($key)) {
304 $ann = $fact->create_object(-value
=> $val, -tagname
=> $key);
306 $ann = Bio
::Annotation
::SimpleValue
->new(-value
=> $val,
313 # add what is in the annotation implementation if any
314 if($self->annotation()) {
315 push(@anns, $self->annotation->get_Annotations(@keys));
322 =head2 get_num_of_annotations
324 Title : get_num_of_annotations
325 Usage : my $count = $collection->get_num_of_annotations()
326 Function: Returns the count of all annotations stored in this collection
333 sub get_num_of_annotations
{
336 # first, count the number of tags on the feature
339 foreach ($self->feature()->all_tags()) {
340 $num_anns += scalar( $self->feature()->each_tag_value($_));
343 # add from the annotation implementation if any
344 if($self->annotation()) {
345 $num_anns += $self->annotation()->get_num_of_annotations();
352 =head1 Implementation specific functions - to allow adding
356 =head2 add_Annotation
358 Title : add_Annotation
359 Usage : $self->add_Annotation('reference',$object);
360 $self->add_Annotation($object,'Bio::MyInterface::DiseaseI');
361 $self->add_Annotation($object);
362 $self->add_Annotation('disease',$object,'Bio::MyInterface::DiseaseI');
363 Function: Adds an annotation for a specific key.
365 If the key is omitted, the object to be added must provide a value
368 If the archetype is provided, this and future objects added under
369 that tag have to comply with the archetype and will be rejected
372 This implementation will add all Bio::Annotation::SimpleValue
373 objects to the adapted features as tag/value pairs. Caveat: this
374 may potentially result in information loss if a derived object
378 Args : annotation key ('disease', 'dblink', ...)
379 object to store (must be Bio::AnnotationI compliant)
380 [optional] object archetype to map future storage of object
386 my ($self,$key,$object,$archetype) = @_;
388 # if there's no key we use the tagname() as key
389 if(ref($key) && $key->isa("Bio::AnnotationI") &&
390 (! ($object && ref($object)))) {
391 $archetype = $object if $object;
393 $key = $object->tagname();
394 $key = $key->name() if $key && ref($key); # OntologyTermI
395 $self->throw("Annotation object must have a tagname if key omitted")
399 if( !defined $object ) {
400 $self->throw("Must have at least key and object in add_Annotation");
403 if( ! (ref($object) && $object->isa("Bio::AnnotationI")) ) {
404 $self->throw("object must be a Bio::AnnotationI compliant object, otherwise we wont add it!");
407 # ready to add -- if it's a SimpleValue, we add to the feature's tags,
408 # otherwise we'll add to the annotation collection implementation
410 if($object->isa("Bio::Annotation::SimpleValue") &&
411 $self->feature()->can('add_tag_value')) {
412 return $self->feature()->add_tag_value($key, $object->value());
414 my $anncoll = $self->annotation();
416 $anncoll = Bio
::Annotation
::Collection
->new();
417 $self->annotation($anncoll);
419 if($anncoll->can('add_Annotation')) {
420 return $anncoll->add_Annotation($key,$object,$archetype);
422 $self->throw("Annotation implementation does not allow adding!");
426 =head2 remove_Annotations
428 Title : remove_Annotations
430 Function: Remove the annotations for the specified key from this
433 If the key happens to be a tag, then the tag is removed
437 Returns : an array Bio::AnnotationI compliant objects which were stored
438 under the given key(s)
439 Args : the key(s) (tag name(s), one or more strings) for which to
440 remove annotations (optional; if none given, flushes all
446 sub remove_Annotations
{
447 my ($self, @keys) = @_;
449 # set to all keys if none are supplied
450 @keys = $self->get_all_annotation_keys() unless @keys;
451 # collect existing annotation
452 my @anns = $self->get_Annotations(@keys);
454 foreach my $key (@keys) {
455 # delete the tag if it is one
456 $self->feature->remove_tag($key) if $self->feature->has_tag($key);
457 # and delegate to the annotation implementation
458 my $anncoll = $self->annotation();
459 if($anncoll && $anncoll->can('remove_Annotations')) {
460 $anncoll->remove_Annotations($key);
462 $self->warn("Annotation bundle implementation ".ref($anncoll).
463 " does not allow remove!");
469 =head1 Additional methods
473 =head2 tagvalue_object_factory
475 Title : tagvalue_object_factory
476 Usage : $obj->tagval_object_factory($newval)
477 Function: Get/set the object factory to use for creating objects that
478 represent tag/value pairs (e.g.,
479 Bio::Annotation::SimpleValue).
481 The object to be created is expected to follow
482 Bio::Annotation::SimpleValue in terms of supported
483 arguments at creation time, and the methods.
486 Returns : A Bio::Factory::ObjectFactoryI compliant object
487 Args : new value (a Bio::Factory::ObjectFactoryI compliant object,
493 sub tagvalue_object_factory
{
494 my ($self,$value) = @_;
495 if( defined $value) {
496 $self->{'tagval_object_factory'} = $value;
498 return $self->{'tagval_object_factory'};