4 CXGN::Chado::Cvterm - a class to handle controlled vocabulary terms.
10 Naama Menda <nm249@cornell.edu>
11 Lukas Mueller <lam87@cornell.edu> (added implementation of Bio::Ontology::TermI)
12 (added map_to_slim function [March 3, 2008])
16 package CXGN
::Chado
::Cvterm
;
19 use CXGN
::DB
::Connection
;
20 use CXGN
::Chado
::Dbxref
;
21 use CXGN
::Phenome
::Population
;
22 use CXGN
::Chado
::Cvterm
::CvtermRanking
;
23 use CXGN
::Phenome
::Locus
;
24 use CXGN
::Phenome
::Individual
;
25 use CXGN
::Phenome
::Qtl
::Tools
;
26 use List
::MoreUtils qw
/uniq/;
29 use base qw
/ CXGN::DB::Object CXGN::Chado::Cvterm::CvtermRanking / ;
32 =head1 IMPLEMENTATION OF THE Bio::Ontology::TermI INTERFACE
36 Usage: $t->set_identifier("0000001");
37 Desc: this identifier function maps to the accession.
38 it is a synonym for set_accession and get_accession.
39 For the go accession GO:000222, this would have to
40 be set to 000222, for example.
41 Property: the accession of the term.
49 my $identifier = shift;
50 $self->set_accession($identifier) if $identifier;
51 return $self->get_accession();
57 Usage: $t->name($name);
58 Desc: a synonym for the set_cvterm_name/get_cvterm_name accessors
69 $self->set_cvterm_name($name) if $name;
70 return $self->get_cvterm_name();
75 Usage: $t->definition($definition);
76 Desc: a synonym for the set_definition/get_definition
87 my $definition = shift;
88 $self->set_definition($definition) if defined($definition);
89 return $self->get_definition();
94 Usage: $t->ontology( CXGN::Chado::Ontology->new_with_name($dbh, "gene_ontology");
95 Desc: setter/getter for the ontology object this terms belongs to
96 Property: a CXGN::Chado::Ontology object.
104 my $ontology = shift;
106 $self->set_cv_id($ontology->identifier());
109 return CXGN
::Chado
::Ontology
->new($self->get_dbh(), $self->get_cv_id());
116 Usage: my $v = $t->version($version)
117 Desc: synonym for get/set_version . See L<Bio::Ontology::OntologyI>.
118 Ret: $self->get_version()
128 $self->set_version($version) if defined($version);
129 return $self->get_version();
134 Usage: $cvterm->comment("This is a useful term!");
135 my $comment = $cvterm->comment();
136 Desc: setter/getter for the comment
137 Args/Ret: the comment, a string.
138 Side Effects: accesses the database and retrieves/stores comments
139 on the fly. Thus, the cvterm needs to be stored in the
140 database and have a legal cvterm_id. The function emits
141 a warning and does nothing if that is not the case.
149 my $type_id=CXGN
::Chado
::Cvterm
::get_cvterm_by_name
($self->get_dbh(), "comment")->get_cvterm_id();
151 $self->d("WARNING. Cvterm has not yet been stored. Skipping the comment update.\n");
155 # check if there is already a comment associated with this term.
156 my $query = "SELECT cvtermprop_id from cvtermprop WHERE cvterm_id=? and value=?";
157 my $sth = $self->get_dbh()->prepare($query);
158 $sth->execute($self->get_cvterm_id(), $comment);
159 my %props; #hash of arrays for cvtermprop_id => comment pairs
160 my ($cvtermprop_id) = $sth->fetchrow_array();
162 #while (my ($value) = $sth->fetchrow_array()) { push @comments , $value; }
164 #if ($cvtermprop_id) {
165 # my $update = "UPDATE cvtermprop SET value=? WHERE cvtermprop_id=?";
166 # my $update_h = $self->get_dbh()->prepare($update);
167 # $update_h->execute($comment, $cvtermprop_id);
169 # if does not exist- insert a new one.
170 if (!$cvtermprop_id) {
171 my $insert = "INSERT INTO cvtermprop (cvterm_id, type_id, value, rank)
172 VALUES (?, ?, ?, ?)";
173 my $insert_h = $self->get_dbh()->prepare($insert);
174 $insert_h->execute($self->get_cvterm_id(),
182 # query the comment out of the database
183 my $query = "SELECT value FROM cvtermprop WHERE cvterm_id=?";
184 my $sth = $self->get_dbh()->prepare($query);
185 $sth->execute($self->get_cvterm_id());
186 my ($comment) = $sth->fetchrow_array();
204 return $self->get_dbxref_id();
208 =head1 ORIGINAL CXGN::Chado::Cvterm functions
216 Usage: my @roots = CXGN::Chado::Cvterm::get_roots($dbh, "PO");
217 Desc: a static function that returns a list of root
218 terms for a given namespace such as "GO" or "PO"
220 Ret: a list of cvterm objects that are roots of ontologies
221 Args: $dbh and a namespace
229 my $namespace = shift;
231 my $query = "select cvterm.cvterm_id, cvterm.name from cv join cvterm using (cv_id) join dbxref using(dbxref_id) join db using(db_id) left join cvterm_relationship on (cvterm.cvterm_id=cvterm_relationship.subject_id) where cvterm_relationship.subject_id is null and is_obsolete=0 and is_relationshiptype =0 and db.name=? order by cvterm.name asc";
232 my $sth = $dbh->prepare($query);
233 $sth->execute($namespace);
235 while (my ($cvterm_id) = $sth->fetchrow_array()) {
236 push @roots, CXGN
::Chado
::Cvterm
->new($dbh, $cvterm_id);
243 =head2 get_namespaces
245 Usage: my @namespaces = CXGN::Chado::Cvterm::get_namespaces($dbh)
246 Desc: currently provides a list of supported namespaces that
247 are hardcoded. Needs to be refactored somehow to
248 get the useful namespaces from the database (public.db table).
259 return ("PO", "GO", "SP", "SO", "PATO");
268 Usage: my $cvterm = CXGN::Chado::Cvterm->new($dbh, $cvterm_id);
269 Desc: an object for handling controlled vocabullary term objects
271 Args:$dbh a database handle
272 $cvterm_id = an id of a controlled vocabulary term (from chado cvterm table)
282 my $cvterm_id = shift; #id of the cvterm
284 my $self= $class->SUPER::new
($dbh);
287 $self->set_cvterm_id($cvterm_id);
289 if (!$self->get_cvterm_id()) { # the cvterm supplied was not one that exists
297 =head2 new_with_term_name
299 Usage: my $isa = CXGN::Chado::Cvterm->new_with_term_name($dbh, "isa", $cv_id);
300 Desc: useful for getting the term objects for relationship terms.
301 limited usefulness for any other type of term.
303 Args: a database handle, a term name and a cv_id
309 sub new_with_term_name
{
315 if (!$name && !$cv_id) { die "[Cvterm.pm] new_with_term_name: Need name and cv_id."; }
317 my $query = "SELECT cvterm_id from cvterm where name ilike ? and cv_id=?";
318 my $sth = $dbh->prepare($query);
319 $sth->execute($name, $cv_id);
320 my ($cvterm_id) = $sth->fetchrow_array();
322 my $self = CXGN
::Chado
::Cvterm
->new($dbh, $cvterm_id);
326 =head2 new_with_accession
328 Usage: my $t = CXGN::Chado::Cvterm->new_with_accession($dbh, "InterPro:IPR000001", $cv_id);
329 Desc: an alternate constructor using the accession to define the term.
331 Args: a database handle [CXGN::DB::Connection], an accession [string], cv_id (optional. Can be useful if you think the accession might exist in another other cv)
337 sub new_with_accession
{
340 my $accession = shift;
343 my ($name_space, $id) = split "\:", $accession;
345 if ($accession =~ m/^IPR*/ ) {
346 $name_space = 'InterPro';
350 my $query = "SELECT cvterm_id FROM cvterm join dbxref using(dbxref_id) JOIN db USING (db_id) WHERE db.name=? AND dbxref.accession ilike ?";
351 $query .= " AND cv_id = $cv_id" if $cv_id;
353 my $sth = $dbh->prepare($query);
354 $sth->execute($name_space, $id);
356 my ($cvterm_id) = $sth->fetchrow_array();
358 my $self = $class->new($dbh, $cvterm_id);
366 my $cvterm_query = $self->get_dbh()->prepare("SELECT cvterm.cvterm_id, cv.cv_id, cv.name, cvterm.name, cvterm.definition, cvterm.dbxref_id, cvterm.is_obsolete, cvterm.is_relationshiptype, dbxref.accession, db.name FROM public.cvterm join public.cv using(cv_id) join public.dbxref using(dbxref_id) join public.db using (db_id) WHERE cvterm_id=? ");
368 $cvterm_query->execute( $self->get_cvterm_id() );
371 my ($cvterm_id, $cv_id, $cv_name, $cvterm_name, $definition, $dbxref_id, $obsolete,$is_rel,$accession, $db_name)=$cvterm_query->fetchrow_array();
372 $self->set_cvterm_id($cvterm_id);
373 $self->set_cv_id($cv_id);
374 $self->set_cv_name($cv_name);
375 $self->set_cvterm_name($cvterm_name);
376 $self->set_definition($definition);
377 $self->set_dbxref_id($dbxref_id);
378 $self->set_obsolete($obsolete);
379 $self->set_is_relationshiptype($is_rel);
380 $self->set_accession($accession);
381 $self->set_db_name($db_name);
386 Usage: $self->store()
387 Desc: store a new cvterm. Update if cvterm_id exists
390 Side Effects: store a new dbxref for the cvterm if does not exists already
397 my $cvterm_id=$self->get_cvterm_id();
401 my $existing_cvterm_id=$self->cvterm_exists();
402 if ($existing_cvterm_id) {
403 $self->d( "Cvterm.pm found existing cvterm_id $existing_cvterm_id.. can't update term " .$self->get_cvterm_id() . "! \n");
406 my $query = "UPDATE cvterm set cv_id=?, name=?, dbxref_id=?, definition=?, is_obsolete=? WHERE cvterm_id=?";
407 my $sth = $self->get_dbh()->prepare($query);
408 $sth->execute($self->get_cv_id(), $self->get_cvterm_name(), $self->get_dbxref_id(), $self->get_definition(), $self->get_obsolete(), $self->get_cvterm_id());
411 if (!$self->get_dbxref_id()) {
412 if (!$self->get_accession()) { die "Need an accession for a CV term!"; }
413 my $dbxref = CXGN
::Chado
::Dbxref
->new($self->get_dbh());
414 $dbxref->set_accession($self->get_accession());
415 $dbxref->set_version($self->get_version());
416 $dbxref->set_description($self->definition());
417 my $db_name = $self->get_db_name();
418 if ($db_name) { $dbxref->set_db_name($db_name); }
419 else { die "Need a DB name to store cvterm object.\n"; }
421 my $dbxref_id = $dbxref->store();
422 $self->set_dbxref_id($dbxref_id);
423 $self->d("Inserted new dbxref for accession " . $self->get_db_name() . ":" . $self->get_accession ."\n");
426 my $query = "INSERT INTO cvterm (cv_id, name, dbxref_id, definition, is_obsolete, is_relationshiptype) VALUES (?, ?, ?, ?,?,?)";
428 my $sth = $self->get_dbh()->prepare($query);
429 $sth->execute($self->get_cv_id(), $self->get_cvterm_name(), $self->get_dbxref_id(), $self->get_definition(), $self->get_obsolete(), $self->get_is_relationshiptype());
431 $cvterm_id = $self->get_dbh()->last_insert_id("cvterm", "public");
432 $self->set_cvterm_id($cvterm_id);
440 =head2 Class properties
442 The following class properties have accessors (get_cvterm_id, set_cvterm_id...):
460 return $self->{cvterm_id
};
465 $self->{cvterm_id
}=shift;
470 return $self->{cv_id
};
476 $self->{cv_id
}=shift;
481 return $self->{cv_name
};
487 $self->{cv_name
}=shift;
490 sub get_cvterm_name
{
492 return $self->{cvterm_name
};
496 sub set_cvterm_name
{
498 $self->{cvterm_name
}=shift;
503 return $self->{definition
};
509 $self->{definition
}=shift;
515 return $self->{dbxref_id
};
521 $self->{dbxref_id
}=shift;
526 Usage: my $self->get_dbxref();
527 Desc: get a dbxref object associated with the cvterm
537 return CXGN
::Chado
::Dbxref
->new($self->get_dbh(), $self->get_dbxref_id());
542 return $self->{accession
};
547 $self->{accession
}=shift;
551 return $self->{version
};
556 $self->{version
}=shift;
561 return $self->{db_name
};
567 $self->{db_name
}=shift;
572 return $self->{obsolete
};
577 $self->{obsolete
}=shift;
581 sub get_is_relationshiptype
{
583 return $self->{is_relationshiptype
} || 0;
587 sub set_is_relationshiptype
{
589 $self->{is_relationshiptype
}=shift;
593 =head2 get_full_accession
595 Usage: $self->get_full_accession()
596 Desc: Usse this accessor to find the full accession of your cvterm
597 instead of concatenating db_name and accession (e.g. GO:0001234)
598 Ret: db_name:accession
605 sub get_full_accession
{
607 return $self->get_db_name() . ":" . $self->get_accession();
611 =head2 get_recursive_parents
613 Usage: my @parents = $self->get_recursive_parents()
614 Desc: a method for finding all the parents up to the root of the cvterm, and the cvterm-parent relationship
615 Ret: a list of listrefs containing CXGN::Chado::Cvterm objects and relationship types
623 sub get_recursive_parents
{
626 my $parents_q = "SELECT distinct(cvtermpath.object_id)
628 JOIN cvterm ON (cvtermpath.object_id = cvterm_id)
629 WHERE cvtermpath.subject_id =? AND cvterm.is_obsolete=0 AND pathdistance>0";
631 my $type_q = "SELECT type_id FROM cvterm_relationship
632 WHERE subject_id = ? AND object_id = ?";
633 my $type_sth = $self->get_dbh->prepare($type_q);
634 my $parents_sth = $self->get_dbh()->prepare($parents_q);
636 $parents_sth->execute($self->get_cvterm_id() );
638 while (my ($parent_term_id) = $parents_sth->fetchrow_array()) {
639 my $parent_term = CXGN
::Chado
::Cvterm
->new($self->get_dbh(), $parent_term_id);
640 $type_sth->execute($self->get_cvterm_id, $parent_term_id);
641 my ($type_id) = $type_sth->fetchrow_array();
642 my $relationship_term = CXGN
::Chado
::Cvterm
->new($self->get_dbh(), $type_id);
644 push @parents, [ $parent_term, $relationship_term ];
652 Usage: $self->get_parents
653 Desc: find the direct parents of the cvterm
654 Ret: a list of listrefs containing CXGN::Chado::Cvterm objects and relationship types
663 my $parents_q = "SELECT object_id , type_id
664 FROM cvterm_relationship
665 WHERE subject_id = ? ";
666 my $parents_sth = $self->get_dbh()->prepare($parents_q);
667 $parents_sth->execute($self->get_cvterm_id() );
669 while (my ($parent_term_id, $type_id) = $parents_sth->fetchrow_array()) {
670 my $parent_term = CXGN
::Chado
::Cvterm
->new($self->get_dbh(), $parent_term_id);
671 my $relationship_term = CXGN
::Chado
::Cvterm
->new($self->get_dbh(), $type_id);
673 push @parents, [ $parent_term, $relationship_term ];
680 Usage: $self->get_parents
681 Desc: find the direct parents of the cvterm
682 Ret: a list of listrefs containing CXGN::Chado::Cvterm objects and relationship types
691 my $parents_q = "SELECT object_id , type_id
692 FROM cvterm_relationship
693 WHERE subject_id = ? ";
694 my $parents_sth = $self->get_dbh()->prepare($parents_q);
695 $parents_sth->execute($self->get_cvterm_id() );
697 while (my ($parent_term_id, $type_id) = $parents_sth->fetchrow_array()) {
698 my $parent_term = CXGN
::Chado
::Cvterm
->new($self->get_dbh(), $parent_term_id);
699 my $relationship_term = CXGN
::Chado
::Cvterm
->new($self->get_dbh(), $type_id);
701 push @parents, [ $parent_term, $relationship_term ];
708 Usage: my @children = $self->get_children()
709 Desc: a method for finding all the child terms of a cv term and their relationship
710 Ret: a list of lists with two elements: a cvterm object for the child and a
711 cvterm object for the relationship
722 my $children_q = "select subject_id , type_id , name from cvterm_relationship join cvterm on (subject_id = cvterm_id ) where cv_id = ? AND object_id =? ";
724 my $children_sth= $self->get_dbh()->prepare($children_q);
725 $children_sth->execute( $self->get_cv_id, $self->get_cvterm_id() );
727 $self->d( "Parent cvterm id = ".$self->get_cvterm_id()."\n" );
729 while (my ($child_term_id, $type_id, $cvterm_name) = $children_sth->fetchrow_array()) {
730 $self->d( "retrieved child $child_term_id, $type_id\n" );
731 my $child_term = CXGN
::Chado
::Cvterm
->new($self->get_dbh(), $child_term_id);
732 my $relationship_term = CXGN
::Chado
::Cvterm
->new($self->get_dbh(), $type_id);
733 push @children, [ $child_term, $relationship_term ];
739 =head2 get_recursive_children
741 Usage: $self->get_recursive_children
742 Desc: find all recursive child terms of this cvterm
743 Ret: a list of lists with two elements: a cvterm object for the child and a
744 cvterm object for the relationship
751 sub get_recursive_children
{
753 my $q = "SELECT distinct(cvtermpath.subject_id)
755 JOIN cvterm ON (cvtermpath.object_id = cvterm_id)
756 WHERE cvtermpath.object_id =? AND cvterm.is_obsolete=0 AND pathdistance>0 ";
758 my $sth = $self->get_dbh()->prepare($q);
759 $sth->execute($self->get_cvterm_id() );
761 my $type_q = "SELECT type_id FROM cvterm_relationship
762 WHERE subject_id = ? AND object_id = ?";
763 my $type_sth = $self->get_dbh->prepare($type_q);
766 while (my ($child_term_id) = $sth->fetchrow_array()) {
767 my $child_term = CXGN
::Chado
::Cvterm
->new($self->get_dbh(), $child_term_id);
768 $type_sth->execute($child_term_id, $self->get_cvterm_id);
769 my ($type_id) = $type_sth->fetchrow_array();
770 my $relationship_term = CXGN
::Chado
::Cvterm
->new($self->get_dbh(), $type_id);
771 push @children, [ $child_term, $relationship_term ];
777 =head2 count_children
779 Usage: my $childrenNumber = $self->count_children()
780 Desc: a method for fetching the number of children of a cvterm
781 Ret: the number of children for the current db name (this is to avoid counting InterPro children of GO terms)
792 my $child_sth = $self->get_dbh()->prepare("SELECT count( cvterm_relationship.subject_id )FROM cvterm_relationship join cvterm on cvterm.cvterm_id = cvterm_relationship.subject_id JOIN dbxref USING (dbxref_id) WHERE cvterm_relationship.object_id= ? and cvterm.is_obsolete = 0 ");
793 $child_sth->execute($self->get_cvterm_id() );
794 ($childNumber) = $child_sth->fetchrow_array();
802 Usage: my @synonyms = $self->get_synonyms()
803 Desc: a method for fetching all synonyms of a cvterm
804 Ret: an array of synonyms
814 my $cvterm_id= $self->get_cvterm_id();
815 my $query= "SELECT synonym FROM cvtermsynonym WHERE cvterm_id= ?";
817 my $synonym_sth = $self->get_dbh()->prepare($query);
819 $synonym_sth->execute($cvterm_id);
821 while (my ($synonym) = $synonym_sth->fetchrow_array()) {
822 push @synonyms, $synonym;
827 =head2 get_synonym_name
829 Usage: $self->get_synonym_name();
830 Desc: an alias for get_synonyms
831 Ret: an array of synonym names
838 sub get_synonym_name
{
840 my @synonyms=$self->get_synonyms();
847 Usage: $t->add_synonym($new_synonym);
848 Desc: adds the synonym $new_synonym to the term $t.
849 If the synonym $new_synonym already exists,
851 Note that in order to call add_synonym(), the
852 term needs to be stored in the database, otherwise
854 Side Effects: accesses the database. Debug message.
862 if (!$self->has_synonym($synonym)) {
863 my $query = "INSERT INTO cvtermsynonym (cvterm_id, synonym) VALUES (?, ?)";
864 my $sth = $self->get_dbh()->prepare($query);
865 $sth->execute($self->get_cvterm_id(), $synonym);
866 $self->d( "Cvterm.pm: adding synonym '$synonym' to cvterm ". $self->get_cvterm_name() ."\n") ;
869 $self->d("$synonym is already a synonym of term ".($self->get_cvterm_name())."\n");
877 Usage: my $flag = $t->has_synonym("gobbledegook");
878 Desc: returns true if the synonym exists, false otherwise
888 my $putative_synonym = shift;
889 my $synonym_sth = $self->get_dbh()->prepare("SELECT synonym FROM cvtermsynonym WHERE
890 cvterm_id= ? and synonym ilike ?");
891 $synonym_sth->execute($self->get_cvterm_id(), $putative_synonym);
892 my ($synonym) = $synonym_sth->fetchrow_array();
901 =head2 delete_synonym
903 Usage: $cvterm->delete_synonym($synonym)
904 Desc: delete synonym $synonym from cvterm object
907 Side Effects: accesses the database
915 my $query = "DELETE FROM cvtermsynonym WHERE cvterm_id= ? AND synonym = ?";
916 my $sth=$self->get_dbh()->prepare($query);
917 $sth->execute($self->get_cvterm_id(), $synonym);
922 =head2 term_is_obsolete
924 Usage: my $obsolete = $self->term_is_obsolete($cvterm_id);
925 Desc: a method for determining if a term is obsolete
926 Ret: false if not obsolete, true if obsolete
927 Args: $cvterm_id - an id of a controlled vocabulary term
933 sub term_is_obsolete
{
937 my $obsolete_sth = $self->get_dbh()->prepare("SELECT is_obsolete FROM cvterm WHERE cvterm_id= ?");
938 $obsolete_sth->execute($self->get_cvterm_id() );
939 my ($obsolete) = $obsolete_sth->fetchrow_array();
941 if( $obsolete == 1 ) {
948 =head2 associate_feature
950 Usage: $cvterm->associate_feature($feature_id, $pub_id)
951 Desc: associates the feature with $feature_id to the
954 Args: feature_id and a pub_id
955 Side Effects: accesses the database
960 sub associate_feature
{
962 my $feature_id = shift;
964 if (!($pub_id && $feature_id)) {
965 die "[CXGN::Chado::Cvterm] associate_feature(): Need feature_id and pub_id\n";
968 my $query = "INSERT INTO cvterm_feature (cvterm_id, feature_id, pub_id) VALUES (?, ?, ?)";
969 my $sth = $self->get_dbh()->prepare($query);
970 $sth->execute($self->get_cvterm_id(), $feature_id, $pub_id);
975 Usage: my @features = $cvterm->get_features()
976 Desc: returns a list of feature objects that are associated to this
977 cvterm using cvterm_feature table.
978 Ret: a list of CXGN::Chado::Feature objects
980 Side Effects: accesses the database
987 my $query = "SELECT feature_id FROM cvterm_feature WHERE cvterm_id=?";
988 my $sth = $self->get_dbh()->prepare($query);
989 $sth->execute($self->get_cvterm_id());
991 while (my ($feature_id) = $sth->fetchrow_array()) {
992 push @features, CXGN
::Chado
::Feature
->new($self->get_dbh(), $feature_id);
997 =head2 add_secondary_dbxref
999 Usage: $self->add_secondary_dbxref(accession)
1000 Desc: add an alternative id to cvterm. Stores in cvterm_dbxref
1002 Args: an alternative id (i.e. "GO:0001234")
1003 Side Effects: stors a new dbxref if accession is not found in dbxref table
1008 sub add_secondary_dbxref
{
1010 my $accession=shift;
1011 my ($db_name, $acc) = split (/:/, $accession);
1012 my $db=CXGN
::Chado
::Db
->new_with_name($self->get_dbh(), $db_name);
1013 if ( !($db->get_db_id()) ) {
1014 $db->set_db_name($db_name);
1015 $self->d( "Cvterm.pm: Storing a new DB: $db_name\n");
1018 #check is $accession exists:
1019 my $dbxref_id= CXGN
::Chado
::Dbxref
::get_dbxref_id_by_db_id
($self->get_dbh(), $acc, $db->get_db_id());
1021 $self->d("No dbxref_id found for db_name '$db_name' accession '$acc' adding new dbxref...\n");
1022 my $dbxref=CXGN
::Chado
::Dbxref
->new($self->get_dbh());
1023 $dbxref->set_accession($acc);
1024 $dbxref->set_db_name($db->get_db_name());
1026 $dbxref_id=$dbxref->get_dbxref_id();
1028 if (!$self->has_secondary_dbxref($dbxref_id) ) {
1029 my $query = "INSERT INTO cvterm_dbxref (cvterm_id, dbxref_id) VALUES (?,?)";
1030 my $sth=$self->get_dbh()->prepare($query);
1031 $sth->execute($self->get_cvterm_id(), $dbxref_id);
1032 $self->d( "Cvterm.pm: adding secondary id '$accession' to cvterm ". $self->get_cvterm_name() . "\n");
1034 $self->d("Cvterm.pm: $dbxref_id ($accession) is already a secondary id of term '".($self->get_cvterm_name())."'\n");
1038 =head2 has_secondary_dbxref
1040 Usage: $self->has_secondary_dbxref($dbxref_id)
1041 Desc: checks in the database if dbxref_id os already associated with the cvterm
1049 sub has_secondary_dbxref
{
1051 my $dbxref_id=shift;
1052 my $query = "SELECT cvterm_dbxref_id FROM cvterm_dbxref WHERE cvterm_id= ? AND dbxref_id= ?";
1053 my $sth=$self->get_dbh()->prepare($query);
1054 $sth->execute($self->get_cvterm_id(), $dbxref_id);
1055 my ($id) = $sth->fetchrow_array();
1056 if ($id) { return 1; }
1060 =head2 get_secondary_dbxrefs
1062 Usage: $self->get_secondary_dbxrefs()
1063 Desc: find all secondary accessions associated with the cvterm
1064 These are stored in cvterm_dbxref table as dbxref_ids
1065 Ret: an array of accessions (PO:0001234)
1072 sub get_secondary_dbxrefs
{
1074 my $query= "SELECT dbxref_id FROM cvterm_dbxref WHERE cvterm_id=? AND is_for_definition = 0";
1075 my $sth=$self->get_dbh()->prepare($query);
1076 $sth->execute($self->get_cvterm_id() );
1078 while (my ($dbxref_id) = $sth->fetchrow_array() ) {
1079 my $dbxref= CXGN
::Chado
::Dbxref
->new($self->get_dbh(),$dbxref_id);
1080 my $accession = $dbxref->get_db_name() . ":" . $dbxref->get_accession();
1081 push @secondary, $accession;
1086 =head2 delete_secondary_dbxref
1088 Usage: $self->delete_secondary_dbxref()
1089 Desc: delete a cvterm_dbxref from the database
1091 Args: accession (PO:0001234)
1097 sub delete_secondary_dbxref
{
1099 my $accession=shift;
1100 my ($db_name, $acc) = split (/:/, $accession);
1101 my $query= "DELETE FROM cvterm_dbxref where cvterm_id=? AND is_for_definition = 0
1102 AND dbxref_id=(SELECT dbxref_id FROM dbxref WHERE db_id= (SELECT db_id FROM db WHERE name =?)
1103 AND accession = ?)";
1104 my $sth=$self->get_dbh()->prepare($query);
1105 $sth->execute($self->get_cvterm_id(), $db_name, $accession);
1110 =head2 add_def_dbxref
1112 Usage: $self->add_def_dbxref($dbname, $accession)
1113 Desc: add a cvterm definition dbxref to cvterm_dbxref
1115 Args: a db name and a dbxref accession
1116 Side Effects: stores a new db and a new dbxref if $dbname or $accession
1117 do not exist in db and/or dbxref tables
1122 sub add_def_dbxref
{
1125 my $accession=shift;
1126 #check if $dbname exist:
1127 my $db=CXGN
::Chado
::Db
->new_with_name($self->get_dbh(), $dbname);
1128 if ( !($db->get_db_id()) ) {
1129 $db->set_db_name($dbname);
1130 $self->d( "Cvterm.pm: Storing a new DB: $dbname\n");
1133 #check is $accession exists:
1134 my $dbxref_id= CXGN
::Chado
::Dbxref
::get_dbxref_id_by_db_id
($self->get_dbh(), $accession, $db->get_db_id());
1136 my $dbxref=CXGN
::Chado
::Dbxref
->new($self->get_dbh());
1137 $dbxref->set_db_name($db->get_db_name());
1138 $dbxref->set_accession($accession);
1139 $self->d( "Cvterm.pm: Storing a new Dbxref for db $dbname: $accession\n");
1141 $dbxref_id=$dbxref->store();
1143 if (!$self->has_secondary_dbxref($dbxref_id)) {
1144 my $query = "INSERT INTO cvterm_dbxref (cvterm_id, dbxref_id, is_for_definition)
1146 my $sth=$self->get_dbh()->prepare($query);
1147 $sth->execute($self->get_cvterm_id(), $dbxref_id);
1148 $self->d( "Cvterm.pm: Storing a new definition dbxref ($dbname:$accession) for cvterm". $self->get_cvterm_name() . "\n");
1151 my $query = "UPDATE cvterm_dbxref set is_for_definition=1
1152 WHERE cvterm_id=? and dbxref_id=?";
1153 my $sth=$self->get_dbh()->prepare($query);
1154 $sth->execute($self->get_cvterm_id(), $dbxref_id);
1159 =head2 get_def_dbxref
1161 Usage: $self->get_def_dbxref();
1162 Desc: find the definition dbxrefs of the cvterm (stored in cvterm_dbxref)
1163 Ret: an array of dbxref object
1170 sub get_def_dbxref
{
1173 my $query = "SELECT dbxref_id FROM cvterm_dbxref WHERE cvterm_id=? and is_for_definition =1";
1174 my $sth=$self->get_dbh()->prepare($query);
1175 $sth->execute($self->get_cvterm_id());
1177 while (my ($dbxref_id) = $sth->fetchrow_array() ) {
1178 my $dbxref=CXGN
::Chado
::Dbxref
->new($self->get_dbh(), $dbxref_id);
1179 push @dbxrefs, $dbxref;
1185 =head2 delete_def_dbxref
1187 Usage: $self->delete_def_dbxref($dbxref)
1188 Desc: remove from the database a cvterm_dbxref
1191 Side Effects: accesses the database
1196 sub delete_def_dbxref
{
1199 my $query = "DELETE FROM cvterm_dbxref WHERE cvterm_id=? AND dbxref_id=? AND is_for_definition = 1";
1200 my $sth=$self->get_dbh()->prepare($query);
1202 $sth->execute($self->get_cvterm_id(), $dbxref->get_dbxref_id());
1205 =head2 get_cvterm_by_name
1207 Usage: CXGN::Chado::Cvterm::get_cvterm_by_name($dbh, $name)
1208 Desc: get a cvterm object with name $name
1209 Ret: cvterm object. Empty object if name does not exist in cvterm table
1210 Args: database handle and a cvterm name (and '1' if you want to check for an existing relationship type! )
1216 sub get_cvterm_by_name
{
1219 my $is_rel=shift; #optional!
1220 my $query = "SELECT cvterm_id FROM public.cvterm WHERE name ilike ?";
1221 $query .=" AND is_relationshiptype =1 " if $is_rel;
1222 my $sth=$dbh->prepare($query);
1223 $sth->execute($name);
1224 my ($cvterm_id) = $sth->fetchrow_array();
1225 my $cvterm= CXGN
::Chado
::Cvterm
->new($dbh, $cvterm_id);
1229 =head2 cvterm_exists
1231 Usage: $self->cvterm_exists()
1232 Desc: check if another cvterm exists with the same cv_id, name, and is_obsolete value
1234 Ret: cvterm_id or undef if no other cvterm exists
1244 my $cvterm_id= $self->get_cvterm_id();
1245 my $query="SELECT cvterm_id FROM public.cvterm WHERE cv_id=? AND name=? AND is_obsolete=?";
1246 my $sth=$self->get_dbh()->prepare($query);
1247 $sth->execute($self->get_cv_id(), $self->get_cvterm_name(), $self->get_obsolete());
1248 my ($existing_cvterm_id) = $sth->fetchrow_array();
1249 if ($cvterm_id == $existing_cvterm_id) { return undef; }
1250 else { return $existing_cvterm_id ; }
1257 Usage: $self->obsolete()
1258 Desc: set a cvterm is_obsolete = 1
1261 Side Effects: accesses the database
1268 if ($self->get_cvterm_id() ) {
1269 my $query= "UPDATE public.cvterm SET is_obsolete = 1 WHERE cvterm_id=?";
1270 my $sth=$self->get_dbh()->prepare($query);
1271 $sth->execute($self->get_cvterm_id() );
1273 $self->d( "Trying to obsolete a term that hasn't been stored yet! \n");
1279 Usage: $self->get_alt_id();
1280 Desc: find the alternative id of a term. Meant to be used for finding
1281 an alternative cvterm for an obsolete term
1282 Ret: list of dbxref_ids or undef
1291 my $query = "SELECT cvterm.dbxref_id FROM cvterm WHERE cvterm_id IN
1292 (SELECT cvterm_id FROM cvterm_dbxref WHERE dbxref_id= ?)";
1294 my $sth=$self->get_dbh()->prepare($query);
1295 $sth->execute($self->get_dbxref_id() );
1296 while (my ($alt_id) = $sth->fetchrow_array()) {
1297 push @alt_ids, $alt_id ;
1299 return @alt_ids || undef ;
1304 Usage: my @match_list = $cvterm->map_to_slim(@term_list)
1305 Desc: returns a list of terms in the @term_list that
1306 are parents of the term object. This function is
1307 useful for mapping terms to a slim vocabulary.
1308 Ret: a list of term identifiers
1309 Args: a list of term identifiers that are in the slim vocabulary
1310 Side Effects: accesses the database
1311 Note: the db name is stripped off if provided (GO:0003832 is
1321 my %slim_counts = ();
1322 for (my $i=0; $i<@slim; $i++) {
1324 # strip db name off id
1326 $slim[$i]=~s/.*?(\d+).*/$1/;
1328 # make a unique list of slim terms
1330 $slim_counts{$slim[$i]}=0;
1332 $self->get_slim_counts(\
%slim_counts);
1334 print Data
::Dumper
::Dumper
(\
%slim_counts);
1337 foreach my $k (keys %slim_counts) {
1338 if ($slim_counts{$k}>0) { push @matches, $k; }
1343 sub get_slim_counts
{
1345 my $slim_counts = shift;
1347 my $id = $self->identifier();
1349 if (exists($slim_counts->{$id}) && defined($slim_counts->{$id})) {
1350 $slim_counts->{$id}++;
1354 foreach my $p ($self->get_parents()) {
1355 $p->[0]->get_slim_counts($slim_counts);
1360 # sub get_slim_counts {
1362 # my $slim_counts = shift;
1364 # foreach my $p ($self->get_parents()) {
1365 # my $id = $p->[0]->identifier();
1366 # $self->d("Checking $id\n");
1367 # if (exists($slim_counts->{$id}) && defined($slim_counts->{$id})) {
1368 # $slim_counts->{$id}++;
1371 # $p->[0]->get_slim_counts($slim_counts);
1376 # return $slim_counts;
1379 # # sub get_slim_term {
1381 # my $slim_counts = shift;
1384 # foreach my $p ($self->get_parents()) {
1385 # my $id = $p->[0]->identifier();
1386 # if (exists($slim_counts->{$id}) && defined($slim_counts->{$id})) {
1396 =head2 get_all_populations_cvterm
1398 Usage: my @pops = $cvterm->get_all_populations_cvterm();
1399 Desc: returns a list of populations phenotyped for the particular trait (cvterm).
1400 Ret: list of population objects
1402 Side Effects: accesses database
1407 sub get_all_populations_cvterm
{
1409 my $query = "SELECT DISTINCT(phenome.population.population_id) FROM public.phenotype
1411 LEFT JOIN phenome.individual USING (individual_id)
1412 LEFT JOIN phenome.population USING (population_id)
1413 WHERE observable_id = ?";
1414 my $sth=$self->get_dbh->prepare($query);
1415 $sth->execute($self->get_cvterm_id());
1417 while (my ($pop_id) = $sth->fetchrow_array()) {
1418 my $pop = CXGN
::Phenome
::Population
->new($self->get_dbh(), $pop_id);
1419 push @populations, $pop;
1421 return @populations;
1427 =head2 get_individuals
1429 Usage: $self->get_individuals
1430 Desc: find all individuals annotated with this cvterm
1431 Ret: list of Individual objects
1438 sub get_individuals
{
1440 my $query = "SELECT individual_id FROM phenome.individual
1441 JOIN phenome.individual_dbxref USING (individual_id)
1443 my $sth=$self->get_dbh()->prepare($query);;
1444 $sth->execute($self->get_dbxref_id);
1446 while ( my ($individual_id) = $sth->fetchrow_array() ) {
1447 my $ind= CXGN
::Phenome
::Individual
->new($self->get_dbh(), $individual_id);
1448 push @individuals, $ind;
1450 return @individuals;
1455 Usage: $self->get_loci()
1456 Desc: find the loci with annotations of this cvterm
1457 Ret: a list of Locus objects
1466 my $query = "SELECT locus_id FROM phenome.locus
1467 JOIN phenome.locus_dbxref USING (locus_id)
1469 ORDER BY locus.locus_symbol";
1470 my $sth=$self->get_dbh()->prepare($query);;
1471 $sth->execute($self->get_dbxref_id);
1473 while ( my ($locus_id) = $sth->fetchrow_array() ) {
1474 my $locus= CXGN
::Phenome
::Locus
->new($self->get_dbh(), $locus_id);
1480 =head2 get_recursive_loci
1482 Usage: my @loci= $self->get_recursive_loci()
1483 Desc: find all the loci annotated with the cvterm or any of its recursive children
1484 Ret: a list of locus ojects
1491 sub get_recursive_loci
{
1493 my $query = "select distinct locus_id from cvtermpath join cvterm on (cvtermpath.object_id = cvterm.cvterm_id or cvtermpath.subject_id = cvterm.cvterm_id) join phenome.locus_dbxref using (dbxref_id ) join phenome.locus using (locus_id) where (cvtermpath.object_id = ?) and locus_dbxref.obsolete = 'f' and locus.obsolete = 'f' and pathdistance > 0";
1495 my $sth=$self->get_dbh()->prepare($query);
1497 $sth->execute($self->get_cvterm_id() );
1498 while ( my ($locus_id) = $sth->fetchrow_array() ) {
1499 my $locus= CXGN
::Phenome
::Locus
->new($self->get_dbh(), $locus_id);
1506 =head2 get_recursive_individuals
1508 Usage: my @ind= $self->get_recursive_individuals()
1509 Desc: find all the individuals annotated with the cvterm or any of its recursive children
1510 Ret: a list of Individual ojects
1517 sub get_recursive_individuals
{
1520 my $query = "select distinct individual_id from cvtermpath join cvterm on (cvtermpath.object_id = cvterm.cvterm_id or cvtermpath.subject_id = cvterm.cvterm_id) join phenome.individual_dbxref using (dbxref_id ) join phenome.individual using (individual_id) where ( cvtermpath.object_id =?) and individual_dbxref.obsolete = 'f' and individual.obsolete = 'f' and pathdistance > 0 ";
1523 my $sth=$self->get_dbh()->prepare($query);;
1525 $sth->execute($self->get_cvterm_id() );
1526 while ( my ($individual_id) = $sth->fetchrow_array() ) {
1527 my $individual= CXGN
::Phenome
::Individual
->new($self->get_dbh(), $individual_id);
1528 push @ind, $individual;