Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/Ontology/SimpleOntologyEngine.pm @ 0:1f6dce3d34e0
Uploaded
| author | mahtabm |
|---|---|
| date | Thu, 11 Apr 2013 02:01:53 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:1f6dce3d34e0 |
|---|---|
| 1 # $Id: SimpleOntologyEngine.pm,v 1.3.2.5 2003/07/03 00:41:40 lapp Exp $ | |
| 2 # | |
| 3 # BioPerl module for SimpleOntologyEngine | |
| 4 # | |
| 5 # Cared for by Peter Dimitrov <dimitrov@gnf.org> | |
| 6 # | |
| 7 # Copyright Peter Dimitrov | |
| 8 # (c) Peter Dimitrov, dimitrov@gnf.org, 2002. | |
| 9 # (c) GNF, Genomics Institute of the Novartis Research Foundation, 2002. | |
| 10 # | |
| 11 # You may distribute this module under the same terms as perl itself. | |
| 12 # Refer to the Perl Artistic License (see the license accompanying this | |
| 13 # software package, or see http://www.perl.com/language/misc/Artistic.html) | |
| 14 # for the terms under which you may use, modify, and redistribute this module. | |
| 15 # | |
| 16 # THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED | |
| 17 # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF | |
| 18 # MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
| 19 # | |
| 20 # POD documentation - main docs before the code | |
| 21 | |
| 22 =head1 NAME | |
| 23 | |
| 24 SimpleOntologyEngine - Implementation of OntologyEngineI interface | |
| 25 | |
| 26 =head1 SYNOPSIS | |
| 27 | |
| 28 my $soe = Bio::Ontology::SimpleOntologyEngine->new; | |
| 29 | |
| 30 | |
| 31 =head1 DESCRIPTION | |
| 32 | |
| 33 This is a "simple" implementation of Bio::Ontology::OntologyEngineI. | |
| 34 | |
| 35 =head1 FEEDBACK | |
| 36 | |
| 37 =head2 Mailing Lists | |
| 38 | |
| 39 User feedback is an integral part of the evolution of this and other | |
| 40 Bioperl modules. Send your comments and suggestions preferably to | |
| 41 the Bioperl mailing list. Your participation is much appreciated. | |
| 42 | |
| 43 bioperl-l@bioperl.org - General discussion | |
| 44 http://bioperl.org/MailList.shtml - About the mailing lists | |
| 45 | |
| 46 =head2 Reporting Bugs | |
| 47 | |
| 48 Report bugs to the Bioperl bug tracking system to help us keep track | |
| 49 of the bugs and their resolution. Bug reports can be submitted via | |
| 50 email or the web: | |
| 51 | |
| 52 bioperl-bugs@bioperl.org | |
| 53 http://bioperl.org/bioperl-bugs/ | |
| 54 | |
| 55 =head1 AUTHOR - Peter Dimitrov | |
| 56 | |
| 57 Email dimitrov@gnf.org | |
| 58 | |
| 59 =head1 CONTRIBUTORS | |
| 60 | |
| 61 Hilmar Lapp, hlapp at gmx.net | |
| 62 | |
| 63 =head1 APPENDIX | |
| 64 | |
| 65 The rest of the documentation details each of the object methods. | |
| 66 Internal methods are usually preceded with a _ | |
| 67 | |
| 68 =cut | |
| 69 | |
| 70 | |
| 71 # Let the code begin... | |
| 72 | |
| 73 | |
| 74 package Bio::Ontology::SimpleOntologyEngine; | |
| 75 use vars qw(@ISA); | |
| 76 use strict; | |
| 77 use Carp; | |
| 78 use Bio::Root::Root; | |
| 79 use Bio::Ontology::RelationshipFactory; | |
| 80 use Bio::Ontology::OntologyEngineI; | |
| 81 use Data::Dumper; | |
| 82 | |
| 83 @ISA = qw( Bio::Root::Root Bio::Ontology::OntologyEngineI ); | |
| 84 | |
| 85 =head2 new | |
| 86 | |
| 87 Title : new | |
| 88 Usage : $soe = Bio::Ontology::SimpleOntologyEngine->new; | |
| 89 Function: Initializes the ontology engine. | |
| 90 Example : $soe = Bio::Ontology::SimpleOntologyEngine->new; | |
| 91 Returns : Object of class SimpleOntologyEngine. | |
| 92 Args : | |
| 93 | |
| 94 | |
| 95 =cut | |
| 96 | |
| 97 sub new{ | |
| 98 my ($class, @args) = @_; | |
| 99 my $self = $class->SUPER::new(@args); | |
| 100 # my %param = @args; | |
| 101 | |
| 102 $self->_term_store( {} ); | |
| 103 $self->_relationship_store( {} ); | |
| 104 $self->_inverted_relationship_store( {} ); | |
| 105 $self->_relationship_type_store( {} ); | |
| 106 $self->_instantiated_terms_store( {} ); | |
| 107 | |
| 108 # set defaults for the factories | |
| 109 $self->relationship_factory(Bio::Ontology::RelationshipFactory->new( | |
| 110 -type => "Bio::Ontology::Relationship")); | |
| 111 return $self; | |
| 112 } | |
| 113 | |
| 114 =head2 _instantiated_terms_store | |
| 115 | |
| 116 Title : _instantiated_terms_store | |
| 117 Usage : $obj->_instantiated_terms_store($newval) | |
| 118 Function: | |
| 119 Example : | |
| 120 Returns : hash | |
| 121 Args : empty hash | |
| 122 | |
| 123 | |
| 124 =cut | |
| 125 | |
| 126 sub _instantiated_terms_store{ | |
| 127 my ($self, $value) = @_; | |
| 128 | |
| 129 if( defined $value) { | |
| 130 $self->{'_instantiated_terms_store'} = $value; | |
| 131 } | |
| 132 return $self->{'_instantiated_terms_store'}; | |
| 133 } | |
| 134 | |
| 135 =head2 mark_instantiated | |
| 136 | |
| 137 Title : mark_instantiated | |
| 138 Usage : $self->mark_instantiated(TermI[] terms): TermI[] | |
| 139 Function: Marks TermI objects as fully instantiated, | |
| 140 allowing for proper counting of the number of terms in the term store. | |
| 141 The TermI objects has to be already stored in the term store in order to | |
| 142 be marked. | |
| 143 Example : $self->mark_instantiated($term); | |
| 144 Returns : its argument or throws an exception if a term is not | |
| 145 in the term store. | |
| 146 Args : array of objects of class TermI. | |
| 147 | |
| 148 =cut | |
| 149 | |
| 150 sub mark_instantiated{ | |
| 151 my ($self, @terms) = @_; | |
| 152 | |
| 153 foreach my $term (@terms) { | |
| 154 $self->throw( "term ".$term->identifier." not in the term store\n" ) | |
| 155 if !defined $self->_term_store->{$term->identifier}; | |
| 156 $self->_instantiated_terms_store->{$term->identifier} = 1; | |
| 157 } | |
| 158 | |
| 159 return @terms; | |
| 160 } | |
| 161 | |
| 162 =head2 mark_uninstantiated | |
| 163 | |
| 164 Title : mark_uninstantiated | |
| 165 Usage : $self->mark_uninstantiated(TermI[] terms): TermI[] | |
| 166 Function: Marks TermI objects as not fully instantiated, | |
| 167 Example : $self->mark_uninstantiated($term); | |
| 168 Returns : its argument or throws an exception if a term is not | |
| 169 in the term store(if the term is not marked it does nothing). | |
| 170 Args : array of objects of class TermI. | |
| 171 | |
| 172 | |
| 173 =cut | |
| 174 | |
| 175 sub mark_uninstantiated{ | |
| 176 my ($self, @terms) = @_; | |
| 177 | |
| 178 foreach my $term (@terms) { | |
| 179 $self->throw( "term ".$term->identifier." not in the term store\n" ) | |
| 180 if !defined $self->_term_store->{$term->identifier}; | |
| 181 delete $self->_instantiated_terms_store->{$term->identifier} | |
| 182 if defined $self->_instantiated_terms_store->{$term->identifier}; | |
| 183 } | |
| 184 | |
| 185 return @terms; | |
| 186 } | |
| 187 | |
| 188 =head2 _term_store | |
| 189 | |
| 190 Title : term_store | |
| 191 Usage : $obj->_term_store($newval) | |
| 192 Function: | |
| 193 Example : | |
| 194 Returns : reference to an array of Bio::Ontology::TermI objects | |
| 195 Args : reference to an array of Bio::Ontology::TermI objects | |
| 196 | |
| 197 =cut | |
| 198 | |
| 199 sub _term_store{ | |
| 200 my ($self, $value) = @_; | |
| 201 | |
| 202 if( defined $value) { | |
| 203 if ( defined $self->{'_term_store'}) { | |
| 204 $self->throw("_term_store already defined\n"); | |
| 205 } | |
| 206 else { | |
| 207 $self->{'_term_store'} = $value; | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 return $self->{'_term_store'}; | |
| 212 } | |
| 213 | |
| 214 =head2 add_term | |
| 215 | |
| 216 Title : add_term | |
| 217 Usage : add_term(TermI term): TermI | |
| 218 Function: Adds TermI object to the ontology engine term store. | |
| 219 Marks the term fully instantiated by default. | |
| 220 Example : $soe->add_term($term) | |
| 221 Returns : its argument. | |
| 222 Args : object of class TermI. | |
| 223 | |
| 224 =cut | |
| 225 | |
| 226 sub add_term{ | |
| 227 my ($self, $term) = @_; | |
| 228 my $term_store = $self->_term_store; | |
| 229 | |
| 230 if ( defined $term_store -> {$term->identifier}) { | |
| 231 $self->throw( "term ".$term->identifier." already defined\n" ); | |
| 232 } | |
| 233 else { | |
| 234 $term_store->{$term->identifier} = $term; | |
| 235 $self->_instantiated_terms_store->{$term->identifier} = 1; | |
| 236 } | |
| 237 | |
| 238 return $term; | |
| 239 } | |
| 240 | |
| 241 =head2 get_term_by_identifier | |
| 242 | |
| 243 Title : get_term_by_identifier | |
| 244 Usage : get_term_by_identifier(String[] id): TermI[] | |
| 245 Function: Retrieves terms from the term store by their identifier | |
| 246 field, or undef if not there. | |
| 247 Example : $term = $soe->get_term_by_identifier("IPR000001"); | |
| 248 Returns : An array of zero or more Bio::Ontology::TermI objects. | |
| 249 Args : An array of identifier strings | |
| 250 | |
| 251 | |
| 252 =cut | |
| 253 | |
| 254 sub get_term_by_identifier{ | |
| 255 my ($self, @ids) = @_; | |
| 256 my @ans = (); | |
| 257 | |
| 258 foreach my $id (@ids) { | |
| 259 my $term = $self->_term_store->{$id}; | |
| 260 push @ans, $term if defined $term; | |
| 261 } | |
| 262 | |
| 263 return @ans; | |
| 264 } | |
| 265 | |
| 266 =head2 _get_number_rels | |
| 267 | |
| 268 Title : get_number_rels | |
| 269 Usage : | |
| 270 Function: | |
| 271 Example : | |
| 272 Returns : | |
| 273 Args : | |
| 274 | |
| 275 | |
| 276 =cut | |
| 277 | |
| 278 sub _get_number_rels{ | |
| 279 my ($self) = @_; | |
| 280 my $num_rels = 0; | |
| 281 | |
| 282 foreach my $entry ($self->_relationship_store) { | |
| 283 $num_rels += scalar keys %$entry; | |
| 284 } | |
| 285 return $num_rels; | |
| 286 } | |
| 287 | |
| 288 =head2 _get_number_terms | |
| 289 | |
| 290 Title : _get_number_terms | |
| 291 Usage : | |
| 292 Function: | |
| 293 Example : | |
| 294 Returns : | |
| 295 Args : | |
| 296 | |
| 297 | |
| 298 =cut | |
| 299 | |
| 300 sub _get_number_terms{ | |
| 301 my ($self) = @_; | |
| 302 | |
| 303 return scalar $self->_filter_unmarked( values %{$self->_term_store} ); | |
| 304 | |
| 305 } | |
| 306 | |
| 307 =head2 _relationship_store | |
| 308 | |
| 309 Title : _storerelationship_store | |
| 310 Usage : $obj->relationship_store($newval) | |
| 311 Function: | |
| 312 Example : | |
| 313 Returns : reference to an array of Bio::Ontology::TermI objects | |
| 314 Args : reference to an array of Bio::Ontology::TermI objects | |
| 315 | |
| 316 | |
| 317 =cut | |
| 318 | |
| 319 sub _relationship_store{ | |
| 320 my ($self, $value) = @_; | |
| 321 | |
| 322 if( defined $value) { | |
| 323 if ( defined $self->{'_relationship_store'}) { | |
| 324 $self->throw("_relationship_store already defined\n"); | |
| 325 } | |
| 326 else { | |
| 327 $self->{'_relationship_store'} = $value; | |
| 328 } | |
| 329 } | |
| 330 | |
| 331 return $self->{'_relationship_store'}; | |
| 332 } | |
| 333 | |
| 334 =head2 _inverted_relationship_store | |
| 335 | |
| 336 Title : _inverted_relationship_store | |
| 337 Usage : | |
| 338 Function: | |
| 339 Example : | |
| 340 Returns : reference to an array of Bio::Ontology::TermI objects | |
| 341 Args : reference to an array of Bio::Ontology::TermI objects | |
| 342 | |
| 343 | |
| 344 =cut | |
| 345 | |
| 346 sub _inverted_relationship_store{ | |
| 347 my ($self, $value) = @_; | |
| 348 | |
| 349 if( defined $value) { | |
| 350 if ( defined $self->{'_inverted_relationship_store'}) { | |
| 351 $self->throw("_inverted_relationship_store already defined\n"); | |
| 352 } | |
| 353 else { | |
| 354 $self->{'_inverted_relationship_store'} = $value; | |
| 355 } | |
| 356 } | |
| 357 | |
| 358 return $self->{'_inverted_relationship_store'}; | |
| 359 } | |
| 360 | |
| 361 =head2 _relationship_type_store | |
| 362 | |
| 363 Title : _relationship_type_store | |
| 364 Usage : $obj->_relationship_type_store($newval) | |
| 365 Function: | |
| 366 Example : | |
| 367 Returns : reference to an array of Bio::Ontology::RelationshipType objects | |
| 368 Args : reference to an array of Bio::Ontology::RelationshipType objects | |
| 369 | |
| 370 | |
| 371 =cut | |
| 372 | |
| 373 sub _relationship_type_store{ | |
| 374 my ($self, $value) = @_; | |
| 375 | |
| 376 if( defined $value) { | |
| 377 if ( defined $self->{'_relationship_type_store'}) { | |
| 378 $self->throw("_relationship_type_store already defined\n"); | |
| 379 } | |
| 380 else { | |
| 381 $self->{'_relationship_type_store'} = $value; | |
| 382 } | |
| 383 } | |
| 384 | |
| 385 return $self->{'_relationship_type_store'}; | |
| 386 } | |
| 387 | |
| 388 =head2 _add_relationship_simple | |
| 389 | |
| 390 Title : _add_relationship_simple | |
| 391 Usage : | |
| 392 Function: | |
| 393 Example : | |
| 394 Returns : | |
| 395 Args : | |
| 396 | |
| 397 | |
| 398 =cut | |
| 399 | |
| 400 sub _add_relationship_simple{ | |
| 401 my ($self, $store, $rel, $inverted) = @_; | |
| 402 my $parent_id; | |
| 403 my $child_id; | |
| 404 | |
| 405 if ($inverted) { | |
| 406 $parent_id = $rel->subject_term->identifier; | |
| 407 $child_id = $rel->object_term->identifier; | |
| 408 } | |
| 409 else { | |
| 410 $parent_id = $rel->object_term->identifier; | |
| 411 $child_id = $rel->subject_term->identifier; | |
| 412 } | |
| 413 if((defined $store->{$parent_id}->{$child_id}) && | |
| 414 ($store->{$parent_id}->{$child_id}->name != $rel->predicate_term->name)){ | |
| 415 $self->throw("relationship ".Dumper($rel->predicate_term). | |
| 416 " between ".$parent_id." and ".$child_id. | |
| 417 " already defined as ". | |
| 418 Dumper($store->{$parent_id}->{$child_id})."\n"); | |
| 419 } | |
| 420 else { | |
| 421 $store->{$parent_id}->{$child_id} = $rel->predicate_term; | |
| 422 } | |
| 423 } | |
| 424 | |
| 425 =head2 add_relationship | |
| 426 | |
| 427 Title : add_relationship | |
| 428 Usage : add_relationship(RelationshipI relationship): RelationshipI | |
| 429 Function: Adds a relationship object to the ontology engine. | |
| 430 Example : | |
| 431 Returns : Its argument. | |
| 432 Args : A RelationshipI object. | |
| 433 | |
| 434 | |
| 435 =cut | |
| 436 | |
| 437 sub add_relationship{ | |
| 438 my ($self, $rel) = @_; | |
| 439 | |
| 440 $self->_add_relationship_simple($self->_relationship_store, | |
| 441 $rel, 0); | |
| 442 $self->_add_relationship_simple($self->_inverted_relationship_store, | |
| 443 $rel, 1); | |
| 444 $self->_relationship_type_store->{ | |
| 445 $self->_unique_termid($rel->predicate_term)} = $rel->predicate_term; | |
| 446 | |
| 447 return $rel; | |
| 448 } | |
| 449 | |
| 450 =head2 get_relationships | |
| 451 | |
| 452 Title : get_relationships | |
| 453 Usage : get_relationships(): RelationshipI[] | |
| 454 Function: Retrieves all relationship objects. | |
| 455 Example : | |
| 456 Returns : Array of RelationshipI objects | |
| 457 Args : | |
| 458 | |
| 459 | |
| 460 =cut | |
| 461 | |
| 462 sub get_relationships{ | |
| 463 my $self = shift; | |
| 464 my $term = shift; | |
| 465 my @rels; | |
| 466 my $store = $self->_relationship_store; | |
| 467 my $relfact = $self->relationship_factory(); | |
| 468 | |
| 469 my @parent_ids = $term ? | |
| 470 # if a term is supplied then only get the term's parents | |
| 471 (map { $_->identifier(); } $self->get_parent_terms($term)) : | |
| 472 # otherwise use all parent ids | |
| 473 (keys %{$store}); | |
| 474 # add the term as a parent too if one is supplied | |
| 475 push(@parent_ids,$term->identifier) if $term; | |
| 476 | |
| 477 foreach my $parent_id (@parent_ids) { | |
| 478 my $parent_entry = $store->{$parent_id}; | |
| 479 | |
| 480 # if a term is supplied, add a relationship for the parent to the term | |
| 481 # except if the parent is the term itself (we added that one before) | |
| 482 if($term && ($parent_id ne $term->identifier())) { | |
| 483 my $parent_term = $self->get_term_by_identifier($parent_id); | |
| 484 push(@rels, | |
| 485 $relfact->create_object(-object_term => $parent_term, | |
| 486 -subject_term => $term, | |
| 487 -predicate_term => | |
| 488 $parent_entry->{$term->identifier}, | |
| 489 -ontology => $term->ontology() | |
| 490 ) | |
| 491 ); | |
| 492 | |
| 493 } else { | |
| 494 # otherwise, i.e., no term supplied, or the parent equals the | |
| 495 # supplied term | |
| 496 my $parent_term = $term ? | |
| 497 $term : $self->get_term_by_identifier($parent_id); | |
| 498 foreach my $child_id (keys %$parent_entry) { | |
| 499 my $rel_info = $parent_entry->{$child_id}; | |
| 500 | |
| 501 push(@rels, | |
| 502 $relfact->create_object(-object_term => $parent_term, | |
| 503 -subject_term => | |
| 504 $self->get_term_by_identifier( | |
| 505 $child_id), | |
| 506 -predicate_term => $rel_info, | |
| 507 -ontology =>$parent_term->ontology | |
| 508 ) | |
| 509 ); | |
| 510 } | |
| 511 } | |
| 512 } | |
| 513 | |
| 514 return @rels; | |
| 515 } | |
| 516 | |
| 517 =head2 get_all_relationships | |
| 518 | |
| 519 Title : get_all_relationships | |
| 520 Usage : get_all_relationships(): RelationshipI[] | |
| 521 Function: Retrieves all relationship objects. | |
| 522 Example : | |
| 523 Returns : Array of RelationshipI objects | |
| 524 Args : | |
| 525 | |
| 526 | |
| 527 =cut | |
| 528 | |
| 529 sub get_all_relationships{ | |
| 530 return shift->get_relationships(); | |
| 531 } | |
| 532 | |
| 533 =head2 get_predicate_terms | |
| 534 | |
| 535 Title : get_predicate_terms | |
| 536 Usage : get_predicate_terms(): TermI[] | |
| 537 Function: Retrives all relationship types stored in the engine | |
| 538 Example : | |
| 539 Returns : reference to an array of Bio::Ontology::RelationshipType objects | |
| 540 Args : | |
| 541 | |
| 542 | |
| 543 =cut | |
| 544 | |
| 545 sub get_predicate_terms{ | |
| 546 my ($self) = @_; | |
| 547 | |
| 548 return values %{$self->_relationship_type_store}; | |
| 549 } | |
| 550 | |
| 551 =head2 _is_rel_type | |
| 552 | |
| 553 Title : _is_rel_type | |
| 554 Usage : | |
| 555 Function: | |
| 556 Example : | |
| 557 Returns : | |
| 558 Args : | |
| 559 | |
| 560 | |
| 561 =cut | |
| 562 | |
| 563 sub _is_rel_type{ | |
| 564 my ($self, $term, @rel_types) = @_; | |
| 565 | |
| 566 foreach my $rel_type (@rel_types) { | |
| 567 if($rel_type->identifier || $term->identifier) { | |
| 568 return 1 if $rel_type->identifier eq $term->identifier; | |
| 569 } else { | |
| 570 return 1 if $rel_type->name eq $term->name; | |
| 571 } | |
| 572 } | |
| 573 | |
| 574 return 0; | |
| 575 } | |
| 576 | |
| 577 =head2 _typed_traversal | |
| 578 | |
| 579 Title : _typed_traversal | |
| 580 Usage : | |
| 581 Function: | |
| 582 Example : | |
| 583 Returns : | |
| 584 Args : | |
| 585 | |
| 586 | |
| 587 =cut | |
| 588 | |
| 589 sub _typed_traversal{ | |
| 590 my ($self, $rel_store, $level, $term_id, @rel_types) = @_; | |
| 591 return undef if !defined($rel_store->{$term_id}); | |
| 592 my %parent_entry = %{$rel_store->{$term_id}}; | |
| 593 my @children = keys %parent_entry; | |
| 594 | |
| 595 my @ans; | |
| 596 | |
| 597 if (@rel_types > 0) { | |
| 598 @ans = (); | |
| 599 | |
| 600 foreach my $child_id (@children) { | |
| 601 push @ans, $child_id | |
| 602 if $self->_is_rel_type( $rel_store->{$term_id}->{$child_id}, | |
| 603 @rel_types); | |
| 604 } | |
| 605 } | |
| 606 else { | |
| 607 @ans = @children; | |
| 608 } | |
| 609 if ($level < 1) { | |
| 610 my @ans1 = (); | |
| 611 | |
| 612 foreach my $child_id (@ans) { | |
| 613 push @ans1, $self->_typed_traversal($rel_store, | |
| 614 $level - 1, $child_id, @rel_types) | |
| 615 if defined $rel_store->{$child_id}; | |
| 616 } | |
| 617 push @ans, @ans1; | |
| 618 } | |
| 619 | |
| 620 return @ans; | |
| 621 } | |
| 622 | |
| 623 =head2 get_child_terms | |
| 624 | |
| 625 Title : get_child_terms | |
| 626 Usage : get_child_terms(TermI term, TermI[] predicate_terms): TermI[] | |
| 627 get_child_terms(TermI term, RelationshipType[] predicate_terms): TermI[] | |
| 628 Function: Retrieves all child terms of a given term, that satisfy a | |
| 629 relationship among those that are specified in the second | |
| 630 argument or undef otherwise. get_child_terms is a special | |
| 631 case of get_descendant_terms, limiting the search to the | |
| 632 direct descendants. | |
| 633 | |
| 634 Example : | |
| 635 Returns : Array of TermI objects. | |
| 636 Args : First argument is the term of interest, second is the list of relationship type terms. | |
| 637 | |
| 638 | |
| 639 =cut | |
| 640 | |
| 641 sub get_child_terms{ | |
| 642 my ($self, $term, @relationship_types) = @_; | |
| 643 | |
| 644 $self->throw("must provide TermI compliant object") | |
| 645 unless defined($term) && $term->isa("Bio::Ontology::TermI"); | |
| 646 | |
| 647 return $self->_filter_unmarked( | |
| 648 $self->get_term_by_identifier( | |
| 649 $self->_typed_traversal($self->_relationship_store, | |
| 650 1, | |
| 651 $term->identifier, | |
| 652 @relationship_types) ) ); | |
| 653 } | |
| 654 | |
| 655 =head2 get_descendant_terms | |
| 656 | |
| 657 Title : get_descendant_terms | |
| 658 Usage : get_descendant_terms(TermI term, TermI[] rel_types): TermI[] | |
| 659 get_child_terms(TermI term, RelationshipType[] predicate_terms): TermI[] | |
| 660 Function: Retrieves all descendant terms of a given term, that | |
| 661 satisfy a relationship among those that are specified in | |
| 662 the second argument or undef otherwise. Uses | |
| 663 _typed_traversal to find all descendants. | |
| 664 | |
| 665 Example : | |
| 666 Returns : Array of TermI objects. | |
| 667 Args : First argument is the term of interest, second is the list of relationship type terms. | |
| 668 | |
| 669 | |
| 670 =cut | |
| 671 | |
| 672 sub get_descendant_terms{ | |
| 673 my ($self, $term, @relationship_types) = @_; | |
| 674 | |
| 675 $self->throw("must provide TermI compliant object") | |
| 676 unless defined($term) && $term->isa("Bio::Ontology::TermI"); | |
| 677 | |
| 678 return $self->_filter_unmarked( | |
| 679 $self->_filter_repeated( | |
| 680 $self->get_term_by_identifier( | |
| 681 $self->_typed_traversal($self->_relationship_store, | |
| 682 0, | |
| 683 $term->identifier, | |
| 684 @relationship_types) ) ) ); | |
| 685 } | |
| 686 | |
| 687 =head2 get_parent_terms | |
| 688 | |
| 689 Title : get_parent_terms | |
| 690 Usage : get_parent_terms(TermI term, TermI[] predicate_terms): TermI[] | |
| 691 get_child_terms(TermI term, RelationshipType[] predicate_terms): TermI[] | |
| 692 Function: Retrieves all parent terms of a given term, that satisfy a | |
| 693 relationship among those that are specified in the second | |
| 694 argument or undef otherwise. get_parent_terms is a special | |
| 695 case of get_ancestor_terms, limiting the search to the | |
| 696 direct ancestors. | |
| 697 | |
| 698 Example : | |
| 699 Returns : Array of TermI objects. | |
| 700 Args : First argument is the term of interest, second is the list of relationship type terms. | |
| 701 | |
| 702 | |
| 703 =cut | |
| 704 | |
| 705 sub get_parent_terms{ | |
| 706 my ($self, $term, @relationship_types) = @_; | |
| 707 $self->throw("term must be a valid object, not undef") unless defined $term; | |
| 708 | |
| 709 return $self->_filter_unmarked( | |
| 710 $self->get_term_by_identifier( | |
| 711 $self->_typed_traversal($self->_inverted_relationship_store, | |
| 712 1, | |
| 713 $term->identifier, | |
| 714 @relationship_types) ) ); | |
| 715 } | |
| 716 | |
| 717 =head2 get_ancestor_terms | |
| 718 | |
| 719 Title : get_ancestor_terms | |
| 720 Usage : get_ancestor_terms(TermI term, TermI[] predicate_terms): TermI[] | |
| 721 get_child_terms(TermI term, RelationshipType[] predicate_terms): TermI[] | |
| 722 Function: Retrieves all ancestor terms of a given term, that satisfy | |
| 723 a relationship among those that are specified in the second | |
| 724 argument or undef otherwise. Uses _typed_traversal to find | |
| 725 all ancestors. | |
| 726 | |
| 727 Example : | |
| 728 Returns : Array of TermI objects. | |
| 729 Args : First argument is the term of interest, second is the list | |
| 730 of relationship type terms. | |
| 731 | |
| 732 | |
| 733 =cut | |
| 734 | |
| 735 sub get_ancestor_terms{ | |
| 736 my ($self, $term, @relationship_types) = @_; | |
| 737 $self->throw("term must be a valid object, not undef") unless defined $term; | |
| 738 | |
| 739 return $self->_filter_unmarked( | |
| 740 $self->_filter_repeated( | |
| 741 $self->get_term_by_identifier( | |
| 742 $self->_typed_traversal($self->_inverted_relationship_store, | |
| 743 0, | |
| 744 $term->identifier, | |
| 745 @relationship_types) ) ) ); | |
| 746 } | |
| 747 | |
| 748 =head2 get_leaf_terms | |
| 749 | |
| 750 Title : get_leaf_terms | |
| 751 Usage : get_leaf_terms(): TermI[] | |
| 752 Function: Retrieves all leaf terms from the ontology. Leaf term is a term w/o descendants. | |
| 753 Example : @leaf_terms = $obj->get_leaf_terms() | |
| 754 Returns : Array of TermI objects. | |
| 755 Args : | |
| 756 | |
| 757 | |
| 758 =cut | |
| 759 | |
| 760 sub get_leaf_terms{ | |
| 761 my ($self) = @_; | |
| 762 my @leaf_terms; | |
| 763 | |
| 764 foreach my $term (values %{$self->_term_store}) { | |
| 765 push @leaf_terms, $term | |
| 766 if !defined $self->_relationship_store->{$term->identifier} && | |
| 767 defined $self->_instantiated_terms_store->{$term->identifier}; | |
| 768 } | |
| 769 | |
| 770 return @leaf_terms; | |
| 771 } | |
| 772 | |
| 773 =head2 get_root_terms | |
| 774 | |
| 775 Title : get_root_terms | |
| 776 Usage : get_root_terms(): TermI[] | |
| 777 Function: Retrieves all root terms from the ontology. Root term is a term w/o descendants. | |
| 778 Example : @root_terms = $obj->get_root_terms() | |
| 779 Returns : Array of TermI objects. | |
| 780 Args : | |
| 781 | |
| 782 | |
| 783 =cut | |
| 784 | |
| 785 sub get_root_terms{ | |
| 786 my ($self) = @_; | |
| 787 my @root_terms; | |
| 788 | |
| 789 foreach my $term (values %{$self->_term_store}) { | |
| 790 push @root_terms, $term | |
| 791 if !defined $self->_inverted_relationship_store->{$term->identifier} && | |
| 792 defined $self->_instantiated_terms_store->{$term->identifier}; | |
| 793 } | |
| 794 | |
| 795 return @root_terms; | |
| 796 } | |
| 797 | |
| 798 =head2 _filter_repeated | |
| 799 | |
| 800 Title : _filter_repeated | |
| 801 Usage : @lst = $self->_filter_repeated(@old_lst); | |
| 802 Function: Removes repeated terms | |
| 803 Example : | |
| 804 Returns : List of unique TermI objects | |
| 805 Args : List of TermI objects | |
| 806 | |
| 807 | |
| 808 =cut | |
| 809 | |
| 810 sub _filter_repeated{ | |
| 811 my ($self, @args) = @_; | |
| 812 my %h; | |
| 813 | |
| 814 foreach my $element (@args) { | |
| 815 $h{$element->identifier} = $element if !defined $h{$element->identifier}; | |
| 816 } | |
| 817 | |
| 818 return values %h; | |
| 819 } | |
| 820 | |
| 821 =head2 get_all_terms | |
| 822 | |
| 823 Title : get_all_terms | |
| 824 Usage : get_all_terms(): TermI[] | |
| 825 Function: Retrieves all terms currently stored in the ontology. | |
| 826 Example : @all_terms = $obj->get_all_terms() | |
| 827 Returns : Array of TermI objects. | |
| 828 Args : | |
| 829 | |
| 830 | |
| 831 =cut | |
| 832 | |
| 833 sub get_all_terms{ | |
| 834 my ($self) = @_; | |
| 835 | |
| 836 return $self->_filter_unmarked( values %{$self->_term_store} ); | |
| 837 } | |
| 838 | |
| 839 =head2 find_terms | |
| 840 | |
| 841 Title : find_terms | |
| 842 Usage : ($term) = $oe->find_terms(-identifier => "SO:0000263"); | |
| 843 Function: Find term instances matching queries for their attributes. | |
| 844 | |
| 845 This implementation can efficiently resolve queries by | |
| 846 identifier. | |
| 847 | |
| 848 Example : | |
| 849 Returns : an array of zero or more Bio::Ontology::TermI objects | |
| 850 Args : Named parameters. The following parameters should be recognized | |
| 851 by any implementations: | |
| 852 | |
| 853 -identifier query by the given identifier | |
| 854 -name query by the given name | |
| 855 | |
| 856 | |
| 857 =cut | |
| 858 | |
| 859 sub find_terms{ | |
| 860 my ($self,@args) = @_; | |
| 861 my @terms; | |
| 862 | |
| 863 my ($id,$name) = $self->_rearrange([qw(IDENTIFIER NAME)],@args); | |
| 864 | |
| 865 if(defined($id)) { | |
| 866 @terms = $self->get_term_by_identifier($id); | |
| 867 } else { | |
| 868 @terms = $self->get_all_terms(); | |
| 869 } | |
| 870 if(defined($name)) { | |
| 871 @terms = grep { $_->name() eq $name; } @terms; | |
| 872 } | |
| 873 return @terms; | |
| 874 } | |
| 875 | |
| 876 | |
| 877 =head2 relationship_factory | |
| 878 | |
| 879 Title : relationship_factory | |
| 880 Usage : $fact = $obj->relationship_factory() | |
| 881 Function: Get/set the object factory to be used when relationship | |
| 882 objects are created by the implementation on-the-fly. | |
| 883 | |
| 884 Example : | |
| 885 Returns : value of relationship_factory (a Bio::Factory::ObjectFactoryI | |
| 886 compliant object) | |
| 887 Args : on set, a Bio::Factory::ObjectFactoryI compliant object | |
| 888 | |
| 889 | |
| 890 =cut | |
| 891 | |
| 892 sub relationship_factory{ | |
| 893 my $self = shift; | |
| 894 | |
| 895 return $self->{'relationship_factory'} = shift if @_; | |
| 896 return $self->{'relationship_factory'}; | |
| 897 } | |
| 898 | |
| 899 =head2 term_factory | |
| 900 | |
| 901 Title : term_factory | |
| 902 Usage : $fact = $obj->term_factory() | |
| 903 Function: Get/set the object factory to be used when term objects are | |
| 904 created by the implementation on-the-fly. | |
| 905 | |
| 906 Note that this ontology engine implementation does not | |
| 907 create term objects on the fly, and therefore setting this | |
| 908 attribute is meaningless. | |
| 909 | |
| 910 Example : | |
| 911 Returns : value of term_factory (a Bio::Factory::ObjectFactoryI | |
| 912 compliant object) | |
| 913 Args : on set, a Bio::Factory::ObjectFactoryI compliant object | |
| 914 | |
| 915 | |
| 916 =cut | |
| 917 | |
| 918 sub term_factory{ | |
| 919 my $self = shift; | |
| 920 | |
| 921 if(@_) { | |
| 922 $self->warn("setting term factory, but ".ref($self). | |
| 923 " does not create terms on-the-fly"); | |
| 924 return $self->{'term_factory'} = shift; | |
| 925 } | |
| 926 return $self->{'term_factory'}; | |
| 927 } | |
| 928 | |
| 929 =head2 _filter_unmarked | |
| 930 | |
| 931 Title : _filter_unmarked | |
| 932 Usage : _filter_unmarked(TermI[] terms): TermI[] | |
| 933 Function: Removes the uninstantiated terms from the list of terms | |
| 934 Example : | |
| 935 Returns : array of fully instantiated TermI objects | |
| 936 Args : array of TermI objects | |
| 937 | |
| 938 | |
| 939 =cut | |
| 940 | |
| 941 sub _filter_unmarked{ | |
| 942 my ($self, @terms) = @_; | |
| 943 my @filtered_terms = (); | |
| 944 | |
| 945 if ( scalar(@terms) >= 1) { | |
| 946 foreach my $term (@terms) { | |
| 947 push @filtered_terms, $term | |
| 948 if defined $self->_instantiated_terms_store->{$term->identifier}; | |
| 949 } | |
| 950 } | |
| 951 | |
| 952 return @filtered_terms; | |
| 953 } | |
| 954 | |
| 955 =head2 remove_term_by_id | |
| 956 | |
| 957 Title : remove_term_by_id | |
| 958 Usage : remove_term_by_id(String id): TermI | |
| 959 Function: Removes TermI object from the ontology engine using the | |
| 960 string id as an identifier. Current implementation does not | |
| 961 enforce consistency of the relationships using that term. | |
| 962 Example : $term = $soe->remove_term_by_id($id); | |
| 963 Returns : Object of class TermI or undef if not found. | |
| 964 Args : The string identifier of a term. | |
| 965 | |
| 966 | |
| 967 =cut | |
| 968 | |
| 969 sub remove_term_by_id{ | |
| 970 my ($self, $id) = @_; | |
| 971 | |
| 972 if ( $self->get_term_by_identifier($id) ) { | |
| 973 my $term = $self->{_term_store}->{$id}; | |
| 974 delete $self->{_term_store}->{$id}; | |
| 975 return $term; | |
| 976 } | |
| 977 else { | |
| 978 $self->warn("Term with id '$id' is not in the term store"); | |
| 979 return undef; | |
| 980 } | |
| 981 } | |
| 982 | |
| 983 =head2 to_string | |
| 984 | |
| 985 Title : to_string | |
| 986 Usage : print $sv->to_string(); | |
| 987 Function: Currently returns formatted string containing the number of | |
| 988 terms and number of relationships from the ontology engine. | |
| 989 Example : print $sv->to_string(); | |
| 990 Returns : | |
| 991 Args : | |
| 992 | |
| 993 | |
| 994 =cut | |
| 995 | |
| 996 sub to_string{ | |
| 997 my ($self) = @_; | |
| 998 my $s = ""; | |
| 999 | |
| 1000 $s .= "-- # Terms:\n"; | |
| 1001 $s .= scalar($self->get_all_terms)."\n"; | |
| 1002 $s .= "-- # Relationships:\n"; | |
| 1003 $s .= $self->_get_number_rels."\n"; | |
| 1004 | |
| 1005 return $s; | |
| 1006 } | |
| 1007 | |
| 1008 =head2 _unique_termid | |
| 1009 | |
| 1010 Title : _unique_termid | |
| 1011 Usage : | |
| 1012 Function: Returns a string that can be used as ID using fail-over | |
| 1013 approaches. | |
| 1014 | |
| 1015 If the identifier attribute is not set, it uses the | |
| 1016 combination of name and ontology name, provided both are | |
| 1017 set. If they aren't, it returns the name alone. | |
| 1018 | |
| 1019 Note that this is a private method. Call from inheriting | |
| 1020 classes but not from outside. | |
| 1021 | |
| 1022 Example : | |
| 1023 Returns : a string | |
| 1024 Args : a Bio::Ontology::TermI compliant object | |
| 1025 | |
| 1026 | |
| 1027 =cut | |
| 1028 | |
| 1029 sub _unique_termid{ | |
| 1030 my $self = shift; | |
| 1031 my $term = shift; | |
| 1032 | |
| 1033 return $term->identifier() if $term->identifier(); | |
| 1034 my $id = $term->ontology->name() if $term->ontology(); | |
| 1035 if($id) { | |
| 1036 $id .= '|'; | |
| 1037 } else { | |
| 1038 $id = ''; | |
| 1039 } | |
| 1040 $id .= $term->name(); | |
| 1041 } | |
| 1042 | |
| 1043 | |
| 1044 ################################################################# | |
| 1045 # aliases | |
| 1046 ################################################################# | |
| 1047 | |
| 1048 *get_relationship_types = \&get_predicate_terms; | |
| 1049 | |
| 1050 1; |
