0
|
1 # $Id: AnnotationAdaptor.pm,v 1.4 2002/11/11 18:16:31 lapp Exp $
|
|
2 #
|
|
3 # BioPerl module for Bio::SeqFeature::AnnotationAdaptor
|
|
4 #
|
|
5 # Cared for by Hilmar Lapp <hlapp at gmx.net>
|
|
6 #
|
|
7 # Copyright Hilmar Lapp
|
|
8 #
|
|
9 # You may distribute this module under the same terms as perl itself
|
|
10
|
|
11 #
|
|
12 # (c) Hilmar Lapp, hlapp at gmx.net, 2002.
|
|
13 # (c) GNF, Genomics Institute of the Novartis Research Foundation, 2002.
|
|
14 #
|
|
15 # You may distribute this module under the same terms as perl itself.
|
|
16 # Refer to the Perl Artistic License (see the license accompanying this
|
|
17 # software package, or see http://www.perl.com/language/misc/Artistic.html)
|
|
18 # for the terms under which you may use, modify, and redistribute this module.
|
|
19 #
|
|
20 # THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
|
21 # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
|
22 # MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
23 #
|
|
24
|
|
25 # POD documentation - main docs before the code
|
|
26
|
|
27 =head1 NAME
|
|
28
|
|
29 Bio::SeqFeature::AnnotationAdaptor - integrates SeqFeatureIs annotation
|
|
30
|
|
31 =head1 SYNOPSIS
|
|
32
|
|
33 use Bio::SeqFeature::Generic;
|
|
34 use Bio::SeqFeature::AnnotationAdaptor;
|
|
35
|
|
36 # obtain a SeqFeatureI implementing object somehow
|
|
37 my $feat = Bio::SeqFeature::Generic->new(-start => 10, -end => 20);
|
|
38
|
|
39 # add tag/value annotation
|
|
40 $feat->add_tag_value("mytag", "value of tag mytag");
|
|
41 $feat->add_tag_value("mytag", "another value of tag mytag");
|
|
42
|
|
43 # Bio::SeqFeature::Generic also provides annotation(), which returns a
|
|
44 # Bio::AnnotationCollectionI compliant object
|
|
45 $feat->annotation->add_Annotation("dbxref", $dblink);
|
|
46
|
|
47 # to integrate tag/value annotation with AnnotationCollectionI
|
|
48 # annotation, use this adaptor, which also implements
|
|
49 # Bio::AnnotationCollectionI
|
|
50 my $anncoll = Bio::SeqFeature::AnnotationAdaptor(-feature => $feat);
|
|
51
|
|
52 # this will now return tag/value pairs as
|
|
53 # Bio::Annotation::SimpleValue objects
|
|
54 my @anns = $anncoll->get_Annotations("mytag");
|
|
55 # other added before annotation is available too
|
|
56 my @dblinks = $anncoll->get_Annotations("dbxref");
|
|
57
|
|
58 # also supports transparent adding of tag/value pairs in
|
|
59 # Bio::AnnotationI flavor
|
|
60 my $tagval = Bio::Annotation::SimpleValue->new(-value => "some value",
|
|
61 -tagname => "some tag");
|
|
62 $anncoll->add_Annotation($tagval);
|
|
63 # this is now also available from the feature's tag/value system
|
|
64 my @vals = $feat->each_tag_value("some tag");
|
|
65
|
|
66 =head1 DESCRIPTION
|
|
67
|
|
68 L<Bio::SeqFeatureI> defines light-weight annotation of features
|
|
69 through tag/value pairs. Conversely, L<Bio::AnnotationCollectionI>
|
|
70 together with L<Bio::AnnotationI> defines an annotation bag, which is
|
|
71 better typed, but more heavy-weight because it contains every single
|
|
72 piece of annotation as objects. The frequently used base
|
|
73 implementation of Bio::SeqFeatureI, Bio::SeqFeature::Generic, defines
|
|
74 an additional slot for AnnotationCollectionI-compliant annotation.
|
|
75
|
|
76 This adaptor provides a L<Bio::AnnotationCollectionI> compliant,
|
|
77 unified, and integrated view on the annotation of L<Bio::SeqFeatureI>
|
|
78 objects, including tag/value pairs, and annotation through the
|
|
79 annotation() method, if the object supports it. Code using this
|
|
80 adaptor does not need to worry about the different ways of possibly
|
|
81 annotating a SeqFeatureI object, but can instead assume that it
|
|
82 strictly follows the AnnotationCollectionI scheme. The price to pay is
|
|
83 that retrieving and adding annotation will always use objects instead
|
|
84 of light-weight tag/value pairs.
|
|
85
|
|
86 In other words, this adaptor allows us to keep the best of both
|
|
87 worlds. If you create tens of thousands of feature objects, and your
|
|
88 only annotation is tag/value pairs, you are best off using the
|
|
89 features' native tag/value system. If you create a smaller number of
|
|
90 features, but with rich and typed annotation mixed with tag/value
|
|
91 pairs, this adaptor may be for you. Since its implementation is by
|
|
92 double-composition, you only need to create one instance of the
|
|
93 adaptor. In order to transparently annotate a feature object, set the
|
|
94 feature using the feature() method. Every annotation you add will be
|
|
95 added to the feature object, and hence will not be lost when you set
|
|
96 feature() to the next object.
|
|
97
|
|
98 =head1 FEEDBACK
|
|
99
|
|
100 =head2 Mailing Lists
|
|
101
|
|
102 User feedback is an integral part of the evolution of this and other
|
|
103 Bioperl modules. Send your comments and suggestions preferably to
|
|
104 the Bioperl mailing list. Your participation is much appreciated.
|
|
105
|
|
106 bioperl-l@bioperl.org - General discussion
|
|
107 http://bioperl.org/MailList.shtml - About the mailing lists
|
|
108
|
|
109 =head2 Reporting Bugs
|
|
110
|
|
111 Report bugs to the Bioperl bug tracking system to help us keep track
|
|
112 of the bugs and their resolution. Bug reports can be submitted via
|
|
113 email or the web:
|
|
114
|
|
115 bioperl-bugs@bioperl.org
|
|
116 http://bugzilla.bioperl.org/
|
|
117
|
|
118 =head1 AUTHOR - Hilmar Lapp
|
|
119
|
|
120 Email hlapp at gmx.net
|
|
121
|
|
122 Describe contact details here
|
|
123
|
|
124 =head1 CONTRIBUTORS
|
|
125
|
|
126 Additional contributors names and emails here
|
|
127
|
|
128 =head1 APPENDIX
|
|
129
|
|
130 The rest of the documentation details each of the object methods.
|
|
131 Internal methods are usually preceded with a _
|
|
132
|
|
133 =cut
|
|
134
|
|
135
|
|
136 # Let the code begin...
|
|
137
|
|
138
|
|
139 package Bio::SeqFeature::AnnotationAdaptor;
|
|
140 use vars qw(@ISA);
|
|
141 use strict;
|
|
142
|
|
143 # Object preamble - inherits from Bio::Root::Root
|
|
144
|
|
145 use Bio::Root::Root;
|
|
146 use Bio::AnnotatableI;
|
|
147 use Bio::AnnotationCollectionI;
|
|
148 use Bio::Annotation::SimpleValue;
|
|
149
|
|
150 @ISA = qw(Bio::Root::Root Bio::AnnotationCollectionI Bio::AnnotatableI);
|
|
151
|
|
152 =head2 new
|
|
153
|
|
154 Title : new
|
|
155 Usage : my $obj = new Bio::SeqFeature::AnnotationAdaptor();
|
|
156 Function: Builds a new Bio::SeqFeature::AnnotationAdaptor object
|
|
157 Returns : an instance of Bio::SeqFeature::AnnotationAdaptor
|
|
158 Args : Named parameters
|
|
159 -feature the Bio::SeqFeatureI implementing object to adapt
|
|
160 (mandatory to be passed here, or set via feature()
|
|
161 before calling other methods)
|
|
162 -annotation the Bio::AnnotationCollectionI implementing object
|
|
163 for storing richer annotation (this will default to
|
|
164 the $feature->annotation() if it supports it)
|
|
165 -tagvalue_factory the object factory to use for creating tag/value
|
|
166 pair representing objects
|
|
167
|
|
168
|
|
169 =cut
|
|
170
|
|
171 sub new {
|
|
172 my($class,@args) = @_;
|
|
173
|
|
174 my $self = $class->SUPER::new(@args);
|
|
175
|
|
176 my ($feat,$anncoll,$fact) =
|
|
177 $self->_rearrange([qw(FEATURE
|
|
178 ANNOTATION
|
|
179 TAGVALUE_FACTORY)], @args);
|
|
180
|
|
181 $self->feature($feat) if $feat;
|
|
182 $self->annotation($anncoll) if $feat;
|
|
183 $self->tagvalue_object_factory($fact) if $fact;
|
|
184
|
|
185 return $self;
|
|
186 }
|
|
187
|
|
188 =head2 feature
|
|
189
|
|
190 Title : feature
|
|
191 Usage : $obj->feature($newval)
|
|
192 Function: Get/set the feature that this object adapts to an
|
|
193 AnnotationCollectionI.
|
|
194 Example :
|
|
195 Returns : value of feature (a Bio::SeqFeatureI compliant object)
|
|
196 Args : new value (a Bio::SeqFeatureI compliant object, optional)
|
|
197
|
|
198
|
|
199 =cut
|
|
200
|
|
201 sub feature{
|
|
202 my ($self,$value) = @_;
|
|
203 if( defined $value) {
|
|
204 $self->{'feature'} = $value;
|
|
205 }
|
|
206 return $self->{'feature'};
|
|
207 }
|
|
208
|
|
209 =head2 annotation
|
|
210
|
|
211 Title : annotation
|
|
212 Usage : $obj->annotation($newval)
|
|
213 Function: Get/set the AnnotationCollectionI implementing object used by
|
|
214 this adaptor to store additional annotation that cannot be stored
|
|
215 by the SeqFeatureI itself.
|
|
216
|
|
217 If requested before having been set, the value will default to the
|
|
218 annotation object of the feature if it has one.
|
|
219 Example :
|
|
220 Returns : value of annotation (a Bio::AnnotationCollectionI compliant object)
|
|
221 Args : new value (a Bio::AnnotationCollectionI compliant object, optional)
|
|
222
|
|
223
|
|
224 =cut
|
|
225
|
|
226 sub annotation{
|
|
227 my ($self,$value) = @_;
|
|
228
|
|
229 if( defined $value) {
|
|
230 $self->{'annotation'} = $value;
|
|
231 }
|
|
232 if((! exists($self->{'annotation'})) &&
|
|
233 $self->feature()->can('annotation')) {
|
|
234 return $self->feature()->annotation();
|
|
235 }
|
|
236 return $self->{'annotation'};
|
|
237 }
|
|
238
|
|
239 =head1 AnnotationCollectionI implementing methods
|
|
240
|
|
241 =cut
|
|
242
|
|
243 =head2 get_all_annotation_keys
|
|
244
|
|
245 Title : get_all_annotation_keys
|
|
246 Usage : $ac->get_all_annotation_keys()
|
|
247 Function: gives back a list of annotation keys, which are simple text strings
|
|
248 Returns : list of strings
|
|
249 Args : none
|
|
250
|
|
251 =cut
|
|
252
|
|
253 sub get_all_annotation_keys{
|
|
254 my ($self) = @_;
|
|
255 my @keys = ();
|
|
256
|
|
257 # get the tags from the feature object
|
|
258 push(@keys, $self->feature()->all_tags());
|
|
259 # ask the annotation implementation in addition, while avoiding duplicates
|
|
260 if($self->annotation()) {
|
|
261 push(@keys,
|
|
262 grep { ! $self->feature->has_tag($_); }
|
|
263 $self->annotation()->get_all_annotation_keys());
|
|
264 }
|
|
265 # done
|
|
266 return @keys;
|
|
267 }
|
|
268
|
|
269
|
|
270 =head2 get_Annotations
|
|
271
|
|
272 Title : get_Annotations
|
|
273 Usage : my @annotations = $collection->get_Annotations('key')
|
|
274 Function: Retrieves all the Bio::AnnotationI objects for a specific key
|
|
275 Returns : list of Bio::AnnotationI - empty if no objects stored for a key
|
|
276 Args : string which is key for annotations
|
|
277
|
|
278 =cut
|
|
279
|
|
280 sub get_Annotations{
|
|
281 my ($self, $key) = @_;
|
|
282 my @anns = ();
|
|
283
|
|
284 # if the feature has tag/value pair for this key as the tag
|
|
285 if($self->feature()->has_tag($key)) {
|
|
286 my $fact = $self->tagvalue_object_factory();
|
|
287 # add each tag/value pair as a SimpleValue object
|
|
288 foreach my $val ($self->feature()->each_tag_value($key)) {
|
|
289 my $ann;
|
|
290 if($fact) {
|
|
291 $ann = $fact->create_object(-value => $val, -tagname => $key);
|
|
292 } else {
|
|
293 $ann = Bio::Annotation::SimpleValue->new(-value => $val,
|
|
294 -tagname => $key);
|
|
295 }
|
|
296 push(@anns, $ann);
|
|
297 }
|
|
298 }
|
|
299 # add what is in the annotation implementation if any
|
|
300 if($self->annotation()) {
|
|
301 push(@anns, $self->annotation->get_Annotations($key));
|
|
302 }
|
|
303 # done
|
|
304 return @anns;
|
|
305 }
|
|
306
|
|
307 =head2 get_num_of_annotations
|
|
308
|
|
309 Title : get_num_of_annotations
|
|
310 Usage : my $count = $collection->get_num_of_annotations()
|
|
311 Function: Returns the count of all annotations stored in this collection
|
|
312 Returns : integer
|
|
313 Args : none
|
|
314
|
|
315
|
|
316 =cut
|
|
317
|
|
318 sub get_num_of_annotations{
|
|
319 my ($self) = @_;
|
|
320
|
|
321 # first, count the number of tags on the feature
|
|
322 my $num_anns = 0;
|
|
323 foreach ($self->feature()->all_tags()) {
|
|
324 $num_anns += $self->feature()->each_tag_value($_);
|
|
325 }
|
|
326 # add from the annotation implementation if any
|
|
327 if($self->annotation()) {
|
|
328 $num_anns += $self->annotation()->get_num_of_annotations();
|
|
329 }
|
|
330 # done
|
|
331 return $num_anns;
|
|
332 }
|
|
333
|
|
334 =head1 Implementation specific functions - to allow adding
|
|
335
|
|
336 =cut
|
|
337
|
|
338 =head2 add_Annotation
|
|
339
|
|
340 Title : add_Annotation
|
|
341 Usage : $self->add_Annotation('reference',$object);
|
|
342 $self->add_Annotation($object,'Bio::MyInterface::DiseaseI');
|
|
343 $self->add_Annotation($object);
|
|
344 $self->add_Annotation('disease',$object,'Bio::MyInterface::DiseaseI');
|
|
345 Function: Adds an annotation for a specific key.
|
|
346
|
|
347 If the key is omitted, the object to be added must provide a value
|
|
348 via its tagname().
|
|
349
|
|
350 If the archetype is provided, this and future objects added under
|
|
351 that tag have to comply with the archetype and will be rejected
|
|
352 otherwise.
|
|
353
|
|
354 This implementation will add all Bio::Annotation::SimpleValue
|
|
355 objects to the adapted features as tag/value pairs. Caveat: this
|
|
356 may potentially result in information loss if a derived object
|
|
357 is supplied.
|
|
358
|
|
359 Returns : none
|
|
360 Args : annotation key ('disease', 'dblink', ...)
|
|
361 object to store (must be Bio::AnnotationI compliant)
|
|
362 [optional] object archetype to map future storage of object
|
|
363 of these types to
|
|
364
|
|
365 =cut
|
|
366
|
|
367 sub add_Annotation{
|
|
368 my ($self,$key,$object,$archetype) = @_;
|
|
369
|
|
370 # if there's no key we use the tagname() as key
|
|
371 if(ref($key) && $key->isa("Bio::AnnotationI") &&
|
|
372 (! ($object && ref($object)))) {
|
|
373 $archetype = $object if $object;
|
|
374 $object = $key;
|
|
375 $key = $object->tagname();
|
|
376 $key = $key->name() if $key && ref($key); # OntologyTermI
|
|
377 $self->throw("Annotation object must have a tagname if key omitted")
|
|
378 unless $key;
|
|
379 }
|
|
380
|
|
381 if( !defined $object ) {
|
|
382 $self->throw("Must have at least key and object in add_Annotation");
|
|
383 }
|
|
384
|
|
385 if( ! (ref($object) && $object->isa("Bio::AnnotationI")) ) {
|
|
386 $self->throw("object must be a Bio::AnnotationI compliant object, otherwise we wont add it!");
|
|
387 }
|
|
388
|
|
389 # ready to add -- if it's a SimpleValue, we add to the feature's tags,
|
|
390 # otherwise we'll add to the annotation collection implementation
|
|
391
|
|
392 if($object->isa("Bio::Annotation::SimpleValue") &&
|
|
393 $self->feature()->can('add_tag_value')) {
|
|
394 return $self->feature()->add_tag_value($key, $object->value());
|
|
395 } else {
|
|
396 my $anncoll = $self->annotation();
|
|
397 if(! $anncoll) {
|
|
398 $anncoll = Bio::Annotation::Collection->new();
|
|
399 $self->annotation($anncoll);
|
|
400 }
|
|
401 if($anncoll->can('add_Annotation')) {
|
|
402 return $anncoll->add_Annotation($key,$object,$archetype);
|
|
403 }
|
|
404 $self->throw("Annotation implementation does not allow adding!");
|
|
405 }
|
|
406 }
|
|
407
|
|
408 =head1 Additional methods
|
|
409
|
|
410 =cut
|
|
411
|
|
412 =head2 tagvalue_object_factory
|
|
413
|
|
414 Title : tagvalue_object_factory
|
|
415 Usage : $obj->tagval_object_factory($newval)
|
|
416 Function: Get/set the object factory to use for creating objects that
|
|
417 represent tag/value pairs (e.g.,
|
|
418 Bio::Annotation::SimpleValue).
|
|
419
|
|
420 The object to be created is expected to follow
|
|
421 Bio::Annotation::SimpleValue in terms of supported
|
|
422 arguments at creation time, and the methods.
|
|
423
|
|
424 Example :
|
|
425 Returns : A Bio::Factory::ObjectFactoryI compliant object
|
|
426 Args : new value (a Bio::Factory::ObjectFactoryI compliant object,
|
|
427 optional)
|
|
428
|
|
429
|
|
430 =cut
|
|
431
|
|
432 sub tagvalue_object_factory{
|
|
433 my ($self,$value) = @_;
|
|
434 if( defined $value) {
|
|
435 $self->{'tagval_object_factory'} = $value;
|
|
436 }
|
|
437 return $self->{'tagval_object_factory'};
|
|
438 }
|
|
439
|
|
440 1;
|