bug 2549; fixed small bug in Bio::Taxon which doesn't catch -common_name
[bioperl-live.git] / Bio / Ontology / Ontology.pm
blob8fb361360d509e31499b4488459e504fc6921181
1 # $Id$
3 # BioPerl module for Bio::Ontology::Ontology
5 # Cared for by Hilmar Lapp <hlapp at gmx.net>
7 # Copyright Hilmar Lapp
9 # You may distribute this module under the same terms as perl itself
12 # (c) Hilmar Lapp, hlapp at gmx.net, 2003.
13 # (c) GNF, Genomics Institute of the Novartis Research Foundation, 2003.
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.
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.
25 # POD documentation - main docs before the code
27 =head1 NAME
29 Bio::Ontology::Ontology - standard implementation of an Ontology
31 =head1 SYNOPSIS
33 use Bio::Ontology::Ontology;
34 use Bio::Ontology::Term;
36 # create ontology object
37 my $ont = Bio::Ontology::Ontology->new(-name => "OBF");
39 # add terms, relationships ...
40 my $bp = Bio::Ontology::Term->new(-identifier => '02', -name => "Bioperl");
41 my $obf = Bio::Ontology::Term->new(-identifier => '01', -name => "OBF");
42 my $partof = Bio::Ontology::RelationshipType->get_instance("PART_OF");
43 $ont->add_term($bp);
44 $ont->add_term($obf);
45 $ont->add_relationship($bp, $obf, $partof);
47 # then query
48 my @terms = $ont->get_root_terms(); # "OBF"
49 my @desc = $ont->get_descendant_terms($terms[0], $partof); # "Bioperl"
50 # ... see methods for other ways to query
52 # for advanced users, you can re-use the query engine outside of an
53 # ontology to let one instance manage multiple ontologies
54 my $ont2 = Bio::Ontology::Ontology->new(-name => "Foundations",
55 -engine => $ont->engine());
58 =head1 DESCRIPTION
60 This is a no-frills implementation of L<Bio::Ontology::OntologyI>.
62 The query functions are implemented by delegation to an
63 OntologyEngineI implementation.
65 =head1 FEEDBACK
67 =head2 Mailing Lists
69 User feedback is an integral part of the evolution of this and other
70 Bioperl modules. Send your comments and suggestions preferably to
71 the Bioperl mailing list. Your participation is much appreciated.
73 bioperl-l@bioperl.org - General discussion
74 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
76 =head2 Reporting Bugs
78 Report bugs to the Bioperl bug tracking system to help us keep track
79 of the bugs and their resolution. Bug reports can be submitted via
80 the web:
82 http://bugzilla.open-bio.org/
84 =head1 AUTHOR - Hilmar Lapp
86 Email hlapp at gmx.net
88 =head1 APPENDIX
90 The rest of the documentation details each of the object methods.
91 Internal methods are usually preceded with a _
93 =cut
96 # Let the code begin...
99 package Bio::Ontology::Ontology;
100 use strict;
102 # Object preamble - inherits from Bio::Root::Root
104 #use Bio::Ontology::SimpleOntologyEngine; # loaded dynamically now!
106 use base qw(Bio::Root::Root Bio::Ontology::OntologyI Bio::AnnotatableI);
108 =head2 new
110 Title : new
111 Usage : my $obj = Bio::Ontology::Ontology->new();
112 Function: Builds a new Bio::Ontology::Ontology object
113 Returns : an instance of Bio::Ontology::Ontology
114 Args : any number of named arguments. The following names will be
115 recognized by this module:
117 -name the name of the ontology
118 -authority the name of the authority for the ontology
119 -identifier an identifier for the ontology, if any
120 -engine the Bio::Ontology::OntologyEngineI
121 implementation that this instance should use;
122 default is Bio::Ontology::SimpleOntologyEngine
124 See the corresponding get/set methods for further documentation
125 on individual properties.
127 =cut
129 sub new {
130 my($class,@args) = @_;
132 my $self = $class->SUPER::new(@args);
133 my ($name,$auth,$def,$id,$engine) =
134 $self->_rearrange([qw(NAME
135 AUTHORITY
136 DEFINITION
137 IDENTIFIER
138 ENGINE)
140 @args);
141 defined($name) && $self->name($name);
142 defined($auth) && $self->authority($auth);
143 defined($def) && $self->definition($def);
144 defined($id) && $self->identifier($id);
145 defined($engine) && $self->engine($engine);
147 return $self;
150 =head1 Methods from L<Bio::Ontology::OntologyI>
152 =cut
154 =head2 name
156 Title : name
157 Usage : $obj->name($newval)
158 Function: Get/set the name of the ontology.
159 Example :
160 Returns : value of name (a scalar)
161 Args : on set, new value (a scalar or undef, optional)
164 =cut
166 sub name{
167 my $self = shift;
169 return $self->{'name'} = shift if @_;
170 return $self->{'name'};
173 =head2 authority
175 Title : authority
176 Usage : $obj->authority($newval)
177 Function: Get/set the authority for this ontology, for instance the
178 DNS base for the organization granting the name of the
179 ontology and identifiers for the terms.
181 This attribute is optional and should not generally
182 expected by applications to have been set. It is here to
183 follow the rules for namespaces, which ontologies serve as
184 for terms.
186 Example :
187 Returns : value of authority (a scalar)
188 Args : on set, new value (a scalar or undef, optional)
191 =cut
193 sub authority{
194 my $self = shift;
196 return $self->{'authority'} = shift if @_;
197 return $self->{'authority'};
200 =head2 definition
202 Title : definition
203 Usage : $obj->definition($newval)
204 Function: Get/set a descriptive definition of the ontology.
205 Example :
206 Returns : value of definition (a scalar)
207 Args : on set, new value (a scalar or undef, optional)
210 =cut
212 sub definition{
213 my $self = shift;
215 return $self->{'definition'} = shift if @_;
216 return $self->{'definition'};
219 =head2 identifier
221 Title : identifier
222 Usage : $id = $obj->identifier()
223 Function: Get an identifier for this ontology.
225 This is primarily intended for look-up purposes. The value
226 is not modifiable and is determined automatically by the
227 implementation. Also, the identifier's uniqueness will only
228 hold within the scope of a particular application's run
229 time since it is derived from a memory location.
231 Example :
232 Returns : value of identifier (a scalar)
233 Args :
236 =cut
238 sub identifier{
239 my $self = shift;
241 if(@_) {
242 $self->throw("cannot modify identifier for ".ref($self))
243 if exists($self->{'identifier'});
244 my $id = shift;
245 $self->{'identifier'} = $id if $id;
247 if(! exists($self->{'identifier'})) {
248 ($self->{'identifier'}) = "$self" =~ /(0x[0-9a-fA-F]+)/;
250 return $self->{'identifier'};
253 =head2 close
255 Title : close
256 Usage :
257 Function: Release any resources this ontology may occupy. In order
258 to efficiently release unused memory or file handles, you
259 should call this method once you are finished with an
260 ontology.
262 Example :
263 Returns : TRUE on success and FALSE otherwise
264 Args : none
267 =cut
269 sub close{
270 my $self = shift;
272 # if it is in the ontology store, remove it from there
273 my $store = Bio::Ontology::OntologyStore->get_instance();
274 $store->remove_ontology($self);
275 # essentially we need to dis-associate from the engine here
276 $self->engine(undef);
277 return 1;
280 =head1 Implementation-specific public methods
282 =cut
284 =head2 engine
286 Title : engine
287 Usage : $engine = $obj->engine()
288 Function: Get/set the ontology engine to which all the query methods
289 delegate.
290 Example :
291 Returns : an object implementing Bio::Ontology::OntologyEngineI
292 Args : on set, new value (an object implementing
293 Bio::Ontology::OntologyEngineI, or undef)
295 See L<Bio::Ontology::OntologyEngineI>.
297 =cut
299 sub engine{
300 my $self = shift;
302 if (@_) {
303 my $engine = shift;
304 if($engine &&
305 (! (ref($engine) &&
306 $engine->isa("Bio::Ontology::OntologyEngineI")))) {
307 $self->throw("object of class ".ref($engine)." does not implement".
308 " Bio::Ontology::OntologyEngineI. Bummer!");
310 $self->{'engine'} = $engine;
311 } elsif (! exists($self->{'engine'})) {
312 # instantiate on demand
313 eval {
314 # this introduces a dependency on Graph.pm, so load dynamically
315 require Bio::Ontology::SimpleOntologyEngine;
317 if ($@) {
318 $self->throw("failed to load SimpleOntologyEngine, possibly "
319 ."Graph.pm is not installed; either install or supply "
320 ."another OntologyEngineI implementation:\n"
321 .$@);
323 $self->{'engine'} = Bio::Ontology::SimpleOntologyEngine->new();
325 return $self->{'engine'};
328 =head1 Methods defined in L<Bio::Ontology::OntologyEngineI>
330 =cut
332 =head2 add_term
334 Title : add_term
335 Usage : add_term(TermI term): TermI
336 Function: Adds TermI object to the ontology engine term store
338 If the ontology property of the term object was not set,
339 this implementation will set it to itself upon adding the
340 term.
342 Example : $oe->add_term($term)
343 Returns : its argument.
344 Args : object of class TermI.
347 =cut
349 sub add_term{
350 my $self = shift;
351 my $term = shift;
353 # set ontology if not set already
354 $term->ontology($self) if $term && (! $term->ontology());
355 return $self->engine->add_term($term,@_);
358 =head2 add_relationship
360 Title : add_relationship
361 Usage : add_relationship(RelationshipI relationship): RelationshipI
362 add_relatioship(TermI subject, TermI predicate, TermI object)
363 Function: Adds a relationship object to the ontology engine.
364 Example :
365 Returns : Its argument.
366 Args : A RelationshipI object.
369 =cut
371 sub add_relationship {
372 my $self = shift;
373 my $rel = shift;
375 if($rel && $rel->isa("Bio::Ontology::TermI")) {
376 # we need to construct the relationship object on the fly
377 my ($predicate,$object) = @_;
378 $rel = Bio::Ontology::Relationship->new(
379 -subject_term => $rel,
380 -object_term => $object,
381 -predicate_term => $predicate,
382 -ontology => $self,
385 # set ontology if not set already
386 $rel->ontology($self) unless $rel->ontology();
387 return $self->engine->add_relationship($rel);
390 =head2 get_relationship_type
392 Title : get_relationship_type
393 Usage : get_relationship_type(scalar): RelationshipTypeI
394 Function: Get a relationshiptype object from the ontology engine.
395 Example :
396 Returns : A RelationshipTypeI object.
397 Args : The name (scalar) of the RelationshipTypeI object desired.
400 =cut
402 sub get_relationship_type{
403 my $self = shift;
404 return $self->engine->get_relationship_type(@_);
407 =head2 get_relationships
409 Title : get_relationships
410 Usage : get_relationships(TermI term): RelationshipI[]
411 Function: Retrieves all relationship objects in the ontology, or all
412 relationships of a given term.
413 Example :
414 Returns : Array of Bio::Ontology::RelationshipI objects
415 Args : Optionally, a Bio::Ontology::TermI compliant object
418 =cut
420 sub get_relationships {
421 my $self = shift;
422 my $term = shift;
423 if($term) {
424 # we don't need to filter in this case
425 return $self->engine->get_relationships($term);
427 # else we need to filter by ontology
428 return grep { my $ont = $_->ontology;
429 # the first condition is a superset of the second, but
430 # we add it here for efficiency reasons, as many times
431 # it will short-cut to true and is supposedly faster than
432 # string comparison
433 ($ont == $self) || ($ont->name eq $self->name);
434 } $self->engine->get_relationships(@_);
437 =head2 get_predicate_terms
439 Title : get_predicate_terms
440 Usage : get_predicate_terms(): TermI
441 Function: Retrieves all relationship types.
442 Example :
443 Returns : Array of TermI objects
444 Args :
447 =cut
449 sub get_predicate_terms{
450 my $self = shift;
452 return grep { $_->ontology->name eq $self->name;
453 } $self->engine->get_predicate_terms(@_);
456 =head2 get_child_terms
458 Title : get_child_terms
459 Usage : get_child_terms(TermI term, TermI predicate_terms): TermI
460 Function: Retrieves all child terms of a given term, that satisfy a
461 relationship among those that are specified in the second
462 argument or undef otherwise. get_child_terms is a special
463 case of get_descendant_terms, limiting the search to the
464 direct descendants.
466 Note that a returned term may possibly be in another
467 ontology than this one, because the underlying engine may
468 manage multiple ontologies and the relationships of terms
469 between them. If you only want descendants within this
470 ontology, you need to filter the returned array.
472 Example :
473 Returns : Array of TermI objects.
474 Args : First argument is the term of interest, second is the list
475 of relationship type terms.
478 =cut
480 sub get_child_terms{
481 return shift->engine->get_child_terms(@_);
484 =head2 get_descendant_terms
486 Title : get_descendant_terms
487 Usage : get_descendant_terms(TermI term, TermI rel_types): TermI
488 Function: Retrieves all descendant terms of a given term, that
489 satisfy a relationship among those that are specified in
490 the second argument or undef otherwise.
492 Note that a returned term may possibly be in another
493 ontology than this one, because the underlying engine may
494 manage multiple ontologies and the relationships of terms
495 between them. If you only want descendants within this
496 ontology, you need to filter the returned array.
498 Example :
499 Returns : Array of TermI objects.
500 Args : First argument is the term of interest, second is the list
501 of relationship type terms.
504 =cut
506 sub get_descendant_terms{
507 return shift->engine->get_descendant_terms(@_);
510 =head2 get_parent_terms
512 Title : get_parent_terms
513 Usage : get_parent_terms(TermI term, TermI predicate_terms): TermI
514 Function: Retrieves all parent terms of a given term, that satisfy a
515 relationship among those that are specified in the second
516 argument or undef otherwise. get_parent_terms is a special
517 case of get_ancestor_terms, limiting the search to the
518 direct ancestors.
520 Note that a returned term may possibly be in another
521 ontology than this one, because the underlying engine may
522 manage multiple ontologies and the relationships of terms
523 between them. If you only want descendants within this
524 ontology, you need to filter the returned array.
526 Example :
527 Returns : Array of TermI objects.
528 Args : First argument is the term of interest, second is the list
529 of relationship type terms.
532 =cut
534 sub get_parent_terms{
535 return shift->engine->get_parent_terms(@_);
538 =head2 get_ancestor_terms
540 Title : get_ancestor_terms
541 Usage : get_ancestor_terms(TermI term, TermI predicate_terms): TermI
542 Function: Retrieves all ancestor terms of a given term, that satisfy
543 a relationship among those that are specified in the second
544 argument or undef otherwise.
546 Note that a returned term may possibly be in another
547 ontology than this one, because the underlying engine may
548 manage multiple ontologies and the relationships of terms
549 between them. If you only want descendants within this
550 ontology, you need to filter the returned array.
552 Example :
553 Returns : Array of TermI objects.
554 Args : First argument is the term of interest, second is the list
555 of relationship type terms.
558 =cut
560 sub get_ancestor_terms{
561 return shift->engine->get_ancestor_terms(@_);
564 =head2 get_leaf_terms
566 Title : get_leaf_terms
567 Usage : get_leaf_terms(): TermI
568 Function: Retrieves all leaf terms from the ontology. Leaf term is a
569 term w/o descendants.
571 Example : @leaf_terms = $obj->get_leaf_terms()
572 Returns : Array of TermI objects.
573 Args :
575 =cut
577 sub get_leaf_terms{
578 my $self = shift;
579 return grep { my $ont = $_->ontology;
580 # the first condition is a superset of the second, but
581 # we add it here for efficiency reasons, as many times
582 # it will short-cut to true and is supposedly faster than
583 # string comparison
584 ($ont == $self) || ($ont->name eq $self->name);
585 } $self->engine->get_leaf_terms(@_);
588 =head2 get_root_terms()
590 Title : get_root_terms
591 Usage : get_root_terms(): TermI
592 Function: Retrieves all root terms from the ontology. Root term is a
593 term w/o parents.
595 Example : @root_terms = $obj->get_root_terms()
596 Returns : Array of TermI objects.
597 Args :
599 =cut
601 sub get_root_terms{
602 my $self = shift;
603 return grep { my $ont = $_->ontology;
604 # the first condition is a superset of the second, but
605 # we add it here for efficiency reasons, as many times
606 # it will short-cut to true and is supposedly faster than
607 # string comparison
608 ($ont == $self) || ($ont->name eq $self->name);
609 } $self->engine->get_root_terms(@_);
612 =head2 get_all_terms
614 Title : get_all_terms
615 Usage : get_all_terms: TermI
616 Function: Retrieves all terms from the ontology.
618 We do not mandate an order here in which the terms are
619 returned. In fact, the default implementation will return
620 them in unpredictable order.
622 Example : @terms = $obj->get_all_terms()
623 Returns : Array of TermI objects.
624 Args :
626 =cut
628 sub get_all_terms{
629 my $self = shift;
630 return grep { my $ont = $_->ontology;
631 # the first condition is a superset of the second, but
632 # we add it here for efficiency reasons, as many times
633 # it will short-cut to true and is supposedly faster than
634 # string comparison
635 ($ont == $self) || ($ont->name eq $self->name);
636 } $self->engine->get_all_terms(@_);
639 =head2 find_terms
641 Title : find_terms
642 Usage : ($term) = $oe->find_terms(-identifier => "SO:0000263");
643 Function: Find term instances matching queries for their attributes.
645 An implementation may not support querying for arbitrary
646 attributes, but can generally be expected to accept
647 -identifier and -name as queries. If both are provided,
648 they are implicitly intersected.
650 Example :
651 Returns : an array of zero or more Bio::Ontology::TermI objects
652 Args : Named parameters. The following parameters should be recognized
653 by any implementations:
655 -identifier query by the given identifier
656 -name query by the given name
658 =cut
660 sub find_terms{
661 my $self = shift;
662 return grep { $_->ontology->name eq $self->name;
663 } $self->engine->find_terms(@_);
666 =head2 find_identical_terms
668 Title : find_identical_terms
669 Usage : ($term) = $oe->find_identical_terms($term0);
670 Function: Find term instances where name or synonym
671 matches the query exactly
672 Example :
673 Returns : an array of zero or more Bio::Ontology::TermI objects
674 Args : a Bio::Ontology::TermI object
676 =cut
678 sub find_identical_terms{
679 my $self = shift;
680 return grep { $_->ontology->name eq $self->name;
681 } $self->engine->find_identical_terms(@_);
685 =head2 find_similar_terms
687 Title : find_similar_terms
688 Usage : ($term) = $oe->find_similar_terms($term0);
689 Function: Find term instances where name or synonym, or part of one,
690 matches the query.
691 Example :
692 Returns : an array of zero or more Bio::Ontology::TermI objects
693 Args : a Bio::Ontology::TermI object
695 =cut
697 sub find_similar_terms{
698 my $self = shift;
699 return grep { $_->ontology->name eq $self->name;
700 } $self->engine->find_similar_terms(@_);
703 =head2 find_identically_named_terms
705 Title : find_identically_named_terms
706 Usage : ($term) = $oe->find_identically_named_terms($term0);
707 Function: Find term instances where names match the query term
708 name exactly
709 Example :
710 Returns : an array of zero or more Bio::Ontology::TermI objects
711 Args : a Bio::Ontology::TermI object
713 =cut
715 sub find_identically_named_terms{
716 my $self = shift;
717 return grep { $_->ontology->name eq $self->name
718 } $self->engine->find_identically_named_terms(@_);
721 =head1 Factory for relationships and terms
723 =cut
725 =head2 relationship_factory
727 Title : relationship_factory
728 Usage : $fact = $obj->relationship_factory()
729 Function: Get (and set, if the engine supports it) the object
730 factory to be used when relationship objects are created by
731 the implementation on-the-fly.
733 Example :
734 Returns : value of relationship_factory (a Bio::Factory::ObjectFactoryI
735 compliant object)
736 Args :
738 =cut
740 sub relationship_factory{
741 return shift->engine->relationship_factory(@_);
744 =head2 term_factory
746 Title : term_factory
747 Usage : $fact = $obj->term_factory()
748 Function: Get (and set, if the engine supports it) the object
749 factory to be used when term objects are created by
750 the implementation on-the-fly.
752 Example :
753 Returns : value of term_factory (a Bio::Factory::ObjectFactoryI
754 compliant object)
755 Args :
757 =cut
759 sub term_factory{
760 return shift->engine->term_factory(@_);
764 =head2 annotation
766 Title : annotation
767 Usage : $annos = $obj->annotation()
768 Function: Get/Set the Bio::Annotation::Collection object
769 The collection contains Bio::Annotation::SimpleValue
770 objects to store header information like the version
771 and date present in the header section of an Ontology
772 file.
774 Example :
775 Returns : value of annotation (a Bio::Annotation::Collection
776 compliant object)
777 Args : A Bio::Annotation::Collection object (Optional)
779 =cut
781 sub annotation{
782 my $self = shift;
783 $self->{'annotation'} = shift if @_;
784 return $self->{'annotation'};
788 #################################################################
789 # aliases
790 #################################################################
792 *get_relationship_types = \&get_predicate_terms;