2 # BioPerl module for Bio::Annotation::Collection.pm
4 # Please direct questions and support issues to <bioperl-l@bioperl.org>
6 # Cared for by Ewan Birney <birney@ebi.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::Annotation::Collection - Default Perl implementation of
21 # get an AnnotationCollectionI somehow, eg
23 $ac = $seq->annotation();
25 foreach $key ( $ac->get_all_annotation_keys() ) {
26 @values = $ac->get_Annotations($key);
27 foreach $value ( @values ) {
28 # value is an Bio::AnnotationI, and defines a "as_text" method
29 print "Annotation ",$key," stringified value ",$value->as_text,"\n";
31 # also defined hash_tree method, which allows data orientated
32 # access into this object
33 $hash = $value->hash_tree();
39 Bioperl implementation for Bio::AnnotationCollectionI
45 User feedback is an integral part of the evolution of this and other
46 Bioperl modules. Send your comments and suggestions preferably to one
47 of the Bioperl mailing lists. Your participation is much appreciated.
49 bioperl-l@bioperl.org - General discussion
50 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
54 Please direct usage questions or support issues to the mailing list:
56 I<bioperl-l@bioperl.org>
58 rather than to the module maintainer directly. Many experienced and
59 reponsive experts will be able look at the problem and quickly
60 address it. Please include a thorough description of the problem
61 with code and data examples if at all possible.
65 Report bugs to the Bioperl bug tracking system to help us keep track
66 the bugs and their resolution. Bug reports can be submitted via
69 https://github.com/bioperl/bioperl-live/issues
71 =head1 AUTHOR - Ewan Birney
73 Email birney@ebi.ac.uk
77 The rest of the documentation details each of the object
78 methods. Internal methods are usually preceded with a _
83 # Let the code begin...
86 package Bio
::Annotation
::Collection
;
92 # Object preamble - inherits from Bio::Root::Root
94 use Bio
::Annotation
::TypeManager
;
95 use Bio
::Annotation
::SimpleValue
;
98 use base
qw(Bio::Root::Root Bio::AnnotationCollectionI Bio::AnnotationI);
104 Usage : $coll = Bio::Annotation::Collection->new()
105 Function: Makes a new Annotation::Collection object.
106 Returns : Bio::Annotation::Collection
112 my ($class,@args) = @_;
114 my $self = $class->SUPER::new
(@args);
116 $self->{'_annotation'} = {};
117 $self->_typemap(Bio
::Annotation
::TypeManager
->new());
123 =head1 L<Bio::AnnotationCollectionI> implementing methods
127 =head2 get_all_annotation_keys
129 Title : get_all_annotation_keys
130 Usage : $ac->get_all_annotation_keys()
131 Function: gives back a list of annotation keys, which are simple text strings
132 Returns : list of strings
137 sub get_all_annotation_keys
{
139 return keys %{$self->{'_annotation'}};
142 =head2 get_Annotations
144 Title : get_Annotations
145 Usage : my @annotations = $collection->get_Annotations('key')
146 Function: Retrieves all the Bio::AnnotationI objects for one or more
149 If no key is given, returns all annotation objects.
151 The returned objects will have their tagname() attribute set to
152 the key under which they were attached, unless the tagname was
155 Returns : list of Bio::AnnotationI - empty if no objects stored for a key
156 Args : keys (list of strings) for annotations (optional)
161 my ($self,@keys) = @_;
164 @keys = $self->get_all_annotation_keys() unless @keys;
165 foreach my $key (@keys) {
166 if(exists($self->{'_annotation'}->{$key})) {
169 $_->tagname($key) if ! $_->tagname(); $_;
170 } @
{$self->{'_annotation'}->{$key}});
177 =head2 get_nested_Annotations
179 Title : get_nested_Annotations
180 Usage : my @annotations = $collection->get_nested_Annotations(
183 Function: Retrieves all the Bio::AnnotationI objects for one or more
184 specific key(s). If -recursive is set to true, traverses the nested
185 annotation collections recursively and returns all annotations
188 If no key is given, returns all annotation objects.
190 The returned objects will have their tagname() attribute set to
191 the key under which they were attached, unless the tagname was
194 Returns : list of Bio::AnnotationI - empty if no objects stored for a key
195 Args : -keys => arrayref of keys to search for (optional)
196 -recursive => boolean, whether or not to recursively traverse the
197 nested annotations and return annotations with matching keys.
201 sub get_nested_Annotations
{
202 my ($self, @args) = @_;
203 my ($keys, $recursive) = $self->_rearrange([qw(KEYS RECURSIVE)], @args);
207 # if not recursive behave exactly like get_Annotations()
209 my @keys = $keys? @
$keys : $self->get_all_annotation_keys();
210 foreach my $key (@keys) {
211 if(exists($self->{'_annotation'}->{$key})) {
214 $_->tagname($key) if ! $_->tagname(); $_;
215 } @
{$self->{'_annotation'}->{$key}});
219 # if recursive search for keys recursively
221 my @allkeys = $self->get_all_annotation_keys();
222 foreach my $key (@allkeys) {
224 foreach my $searchkey (@
$keys) {
225 if ($key eq $searchkey) { $keymatch = 1;}
228 if(exists($self->{'_annotation'}->{$key})) {
231 $_->tagname($key) if ! $_->tagname(); $_;
232 } @
{$self->{'_annotation'}->{$key}});
236 my @annotations = @
{$self->{'_annotation'}->{$key}};
237 foreach (@annotations) {
238 if ($_->isa("Bio::AnnotationCollectionI")) {
240 $_->get_nested_Annotations('-keys' => $keys, '-recursive' => 1)
250 =head2 get_all_Annotations
252 Title : get_all_Annotations
254 Function: Similar to get_Annotations, but traverses and flattens nested
255 annotation collections. This means that collections in the
256 tree will be replaced by their components.
258 Keys will not be passed on to nested collections. I.e., if the
259 tag name of a nested collection matches the key, it will be
260 flattened in its entirety.
262 Hence, for un-nested annotation collections this will be identical
265 Returns : an array of L<Bio::AnnotationI> compliant objects
266 Args : keys (list of strings) for annotations (optional)
271 sub get_all_Annotations
{
272 my ($self,@keys) = @_;
275 $_->isa("Bio::AnnotationCollectionI") ?
276 $_->get_all_Annotations() : $_;
277 } $self->get_Annotations(@keys);
281 =head2 get_num_of_annotations
283 Title : get_num_of_annotations
284 Usage : my $count = $collection->get_num_of_annotations()
285 Function: Returns the count of all annotations stored in this collection
292 sub get_num_of_annotations
{
295 map { $count += scalar @
$_ } values %{$self->{'_annotation'}};
299 =head1 Implementation specific functions - mainly for adding
303 =head2 add_Annotation
305 Title : add_Annotation
306 Usage : $self->add_Annotation('reference',$object);
307 $self->add_Annotation($object,'Bio::MyInterface::DiseaseI');
308 $self->add_Annotation($object);
309 $self->add_Annotation('disease',$object,'Bio::MyInterface::DiseaseI');
310 Function: Adds an annotation for a specific key.
312 If the key is omitted, the object to be added must provide a value
315 If the archetype is provided, this and future objects added under
316 that tag have to comply with the archetype and will be rejected
320 Args : annotation key ('disease', 'dblink', ...)
321 object to store (must be Bio::AnnotationI compliant)
322 [optional] object archetype to map future storage of object
328 my ($self,$key,$object,$archetype) = @_;
330 # if there's no key we use the tagname() as key
331 if(ref($key) && $key->isa("Bio::AnnotationI") && (!ref($object))) {
332 $archetype = $object if defined($object);
334 $key = $object->tagname();
335 $key = $key->name() if ref($key); # OntologyTermI
336 $self->throw("Annotation object must have a tagname if key omitted")
340 if( !defined $object ) {
341 $self->throw("Must have at least key and object in add_Annotation");
345 $self->throw("Must add an object. Use Bio::Annotation::{Comment,SimpleValue,OntologyTerm} for simple text additions");
348 if( !$object->isa("Bio::AnnotationI") ) {
349 $self->throw("object must be AnnotationI compliant, otherwise we won't add it!");
352 # ok, now we are ready! If we don't have an archetype, set it
353 # from the type of the object
355 if( !defined $archetype ) {
356 $archetype = ref $object;
359 # check typemap, storing if needed.
360 my $stored_map = $self->_typemap->type_for_key($key);
362 if( defined $stored_map ) {
363 # check validity, irregardless of archetype. A little cheeky
364 # this means isa stuff is executed correctly
366 if( !$self->_typemap()->is_valid($key,$object) ) {
367 $self->throw("Object $object was not valid with key $key. ".
368 "If you were adding new keys in, perhaps you want to make use\n".
369 "of the archetype method to allow registration to a more basic type");
372 $self->_typemap->_add_type_map($key,$archetype);
377 if( !defined $self->{'_annotation'}->{$key} ) {
378 $self->{'_annotation'}->{$key} = [];
381 push(@
{$self->{'_annotation'}->{$key}},$object);
386 =head2 remove_Annotations
388 Title : remove_Annotations
390 Function: Remove the annotations for the specified key from this collection.
392 Returns : an array Bio::AnnotationI compliant objects which were stored
393 under the given key(s)
394 Args : the key(s) (tag name(s), one or more strings) for which to
395 remove annotations (optional; if none given, flushes all
401 sub remove_Annotations
{
402 my ($self, @keys) = @_;
404 @keys = $self->get_all_annotation_keys() unless @keys;
405 my @anns = $self->get_Annotations(@keys);
407 foreach my $key (@keys) {
408 delete $self->{'_annotation'}->{$key};
409 delete $self->{'_typemap'}->{'_type'}->{$key};
414 =head2 flatten_Annotations
416 Title : flatten_Annotations
418 Function: Flattens part or all of the annotations in this collection.
420 This is a convenience method for getting the flattened
421 annotation for the given keys, removing the annotation for
422 those keys, and adding back the flattened array.
424 This should not change anything for un-nested collections.
426 Returns : an array Bio::AnnotationI compliant objects which were stored
427 under the given key(s)
428 Args : list of keys (strings) the annotation for which to flatten,
429 defaults to all keys if not given
434 sub flatten_Annotations
{
435 my ($self,@keys) = @_;
437 my @anns = $self->get_all_Annotations(@keys);
438 my @origanns = $self->remove_Annotations(@keys);
440 $self->add_Annotation($_);
445 =head1 Bio::AnnotationI methods implementations
447 This is to allow nested annotation: you can use a collection as an
448 annotation object for an annotation collection.
456 Function: See L<Bio::AnnotationI>
467 my $txt = "Collection consisting of ";
469 foreach my $ann ($self->get_Annotations()) {
470 push(@texts, $ann->as_text());
473 $txt .= join(", ", map { '['.$_.']'; } @texts);
475 $txt .= "no elements";
483 Usage : my $str = $ann->display_text();
484 Function: returns a string. Unlike as_text(), this method returns a string
485 formatted as would be expected for te specific implementation.
487 One can pass a callback as an argument which allows custom text
488 generation; the callback is passed the current instance and any text
492 Args : [optional] callback
497 # this just calls the default display_text output for
499 my $DEFAULT_CB = sub {
502 foreach my $ann ($obj->get_Annotations()) {
503 $txt .= $ann->display_text()."\n";
509 my ($self, $cb) = @_;
511 $self->throw("") if ref $cb ne 'CODE';
521 Function: See L<Bio::AnnotationI>
523 Returns : a hash reference
533 foreach my $key ($self->get_all_annotation_keys()) {
534 # all contained objects will support hash_tree()
535 # (they are AnnotationIs)
536 $tree->{$key} = [$self->get_Annotations($key)];
544 Usage : $obj->tagname($newval)
545 Function: Get/set the tagname for this annotation value.
547 Setting this is optional. If set, it obviates the need to
548 provide a tag to Bio::AnnotationCollectionI when adding
549 this object. When obtaining an AnnotationI object from the
550 collection, the collection will set the value to the tag
551 under which it was stored unless the object has a tag
555 Returns : value of tagname (a scalar)
556 Args : new value (a scalar, optional)
564 return $self->{'tagname'} = shift if @_;
565 return $self->{'tagname'};
569 =head1 Backward compatible functions
571 Functions put in for backward compatibility with old
572 Bio::Annotation.pm stuff
589 my ($self,$value) = @_;
591 Carp
::carp
("old style annotation called on new Annotation::Collection object");
593 if( defined $value ) {
594 my $val = Bio
::Annotation
::SimpleValue
->new();
596 $self->add_Annotation('description',$val);
599 my ($desc) = $self->get_Annotations('description');
601 # If no description tag exists, do not attempt to call value on undef:
602 return $desc ?
$desc->value : undef;
608 Title : add_gene_name
619 my ($self,$value) = @_;
621 Carp
::carp
("Old style add_gene_name called on new style Annotation::Collection");
623 my $val = Bio
::Annotation
::SimpleValue
->new();
625 $self->add_Annotation('gene_name',$val);
628 =head2 each_gene_name
630 Title : each_gene_name
643 Carp
::carp
("Old style each_gene_name called on new style Annotation::Collection");
646 my @gene = $self->get_Annotations('gene_name');
648 foreach my $g ( @gene ) {
649 push(@out,$g->value);
657 Title : add_Reference
668 my ($self, @values) = @_;
670 Carp
::carp
("add_Reference (old style Annotation) on new style Annotation::Collection");
672 # Allow multiple (or no) references to be passed, as per old method
673 foreach my $value (@values) {
674 $self->add_Annotation('reference',$value);
678 =head2 each_Reference
680 Title : each_Reference
693 Carp
::carp
("each_Reference (old style Annotation) on new style Annotation::Collection");
695 return $self->get_Annotations('reference');
712 my ($self,$value) = @_;
714 Carp
::carp
("add_Comment (old style Annotation) on new style Annotation::Collection");
716 $self->add_Annotation('comment',$value);
735 Carp
::carp
("each_Comment (old style Annotation) on new style Annotation::Collection");
737 return $self->get_Annotations('comment');
755 my ($self,$value) = @_;
757 Carp
::carp
("add_DBLink (old style Annotation) on new style Annotation::Collection");
759 $self->add_Annotation('dblink',$value);
778 Carp
::carp
("each_DBLink (old style Annotation) on new style Annotation::Collection - use get_Annotations('dblink')");
780 return $self->get_Annotations('dblink');
785 =head1 Implementation management functions
792 Usage : $obj->_typemap($newval)
795 Returns : value of _typemap
796 Args : newvalue (optional)
802 my ($self,$value) = @_;
803 if( defined $value) {
804 $self->{'_typemap'} = $value;
806 return $self->{'_typemap'};