1 package CXGN
::Phenome
::Locus
;
12 Access the phenome.locus table, find, add, and delete associated data
13 (images, alleles, dbxrefs, owners, cvterms, publications, etc.)
17 Naama Menda <nm249@cornell.edu>
24 use CXGN
::Phenome
::Allele
;
25 use CXGN
::Phenome
::LocusSynonym
;
26 use CXGN
::Phenome
::LocusMarker
;
27 use CXGN
::Phenome
::Locus
::LocusHistory
;
29 use CXGN
::Phenome
::LocusDbxref
;
30 use CXGN
::Phenome
::Locus
::LocusRanking
;
31 use CXGN
::Transcript
::Unigene
;
32 use CXGN
::Phenome
::Schema
;
33 use CXGN
::Phenome
::LocusGroup
;
35 use CXGN
::Chado
::Dbxref
;
37 use Bio
::Chado
::Schema
;
39 use base qw
/ CXGN::DB::ModifiableI CXGN::Phenome::Locus::LocusRanking /;
43 Usage: my $gene = CXGN::Phenome::Locus->new($dbh,$locus_id);
55 my $id= shift; # the primary key in the databaes of this object
57 unless( $dbh->can('selectall_arrayref') ) {
58 die "First argument to CXGN::Phenome::Locus constructor needs to be a database handle.";
60 my $self=$class->SUPER::new
($dbh);
62 $self->set_locus_id($id);
65 $self->fetch($id); #get the locus details
68 my $locus_marker_query=$self->get_dbh()->prepare(
69 "SELECT distinct locus_marker_id from phenome.locus_marker
70 JOIN sgn.marker_alias USING (marker_id)
71 JOIN sgn.marker_experiment USING (marker_id)
72 JOIN sgn.marker_location USING (location_id)
73 JOIN sgn.map_version USING (map_version_id)
74 WHERE current_version = 't' AND locus_id=?");
76 $locus_marker_query->execute($id);
77 while (my ($lm) = $locus_marker_query->fetchrow_array() ) {
78 push @locus_marker, $lm;
80 for my $lm_id (@locus_marker) {
82 my $locus_marker_obj = CXGN
::Phenome
::LocusMarker
->new($dbh, $lm_id);
83 $self->add_locus_marker($locus_marker_obj);
86 my @dbxrefs= $self->get_dbxrefs();
87 foreach my $d(@dbxrefs) { $self->add_dbxref(); }
92 =head2 new_with_symbol_and_species
94 Usage: CXGN::Phenome::Locus->new_with_symbol_and_species($dbh, $symbol,$species)
95 Desc: instanciate a new locus object using a symbol and a common_name
97 Args: dbh, symbol, and common_name
103 sub new_with_symbol_and_species
{
108 my $query = "SELECT locus_id FROM phenome.locus JOIN sgn.common_name using(common_name_id) WHERE locus_symbol=? AND common_name ilike ?";
109 my $sth = $dbh->prepare($query);
110 $sth->execute($symbol, $species);
111 my ($id) = $sth->fetchrow_array();
112 return $class->new($dbh, $id);
115 =head2 new_with_locusname
117 Usage: CXGN::Phenome::Locus->new_with_locusname($dbh, $genome_locus_name)
118 Desc: instanciate a new locus object using the locus field
120 Args: dbh, locus genome identifier (e.g. Solyc01g0000010)
125 sub new_with_locusname
{
128 my $locusname = shift;
129 # remove the version number, since loci are saved without them
130 if ( $locusname =~ m/(.*)\.\d+/ ) { $locusname = $1 ; }
131 my $query = "SELECT locus_id FROM phenome.locus WHERE locus ilike ? and obsolete = ? ";
132 my $sth = $dbh->prepare($query);
133 $sth->execute($locusname, 'f');
134 my ($id) = $sth->fetchrow_array();
135 return $class->new($dbh, $id);
141 =head2 get_locus_ids_by_editor
143 Usage: my @loci = CXGN::Phenome::Locus::get_loci_by_editor($dbh, 239)
144 Desc: returns a list of locus ids that belong to the given
145 editor. Class function.
146 Args: a database handle and a sp_person_id of the editor
147 Side Effects: accesses the database
152 sub get_locus_ids_by_editor
{
154 my $sp_person_id = shift;
155 my $query = "SELECT locus_id FROM phenome.locus JOIN phenome.locus_owner USING(locus_id)
156 WHERE locus_owner.sp_person_id=? AND locus.obsolete = 'f' ORDER BY locus.modified_date desc, locus.create_date desc";
157 my $sth = $dbh->prepare($query);
158 $sth->execute($sp_person_id);
160 while (my($locus_id) = $sth->fetchrow_array()) {
161 push @loci, $locus_id;
167 =head2 get_locus_ids_by_annotator
169 Usage: my @loci=CXGN::Phenome::Locus::get_loci_by_annotator($dbh, $sp_person_id)
170 Desc: returns a list of locus ids that belong to the given
171 contributing annotator. Class function.
172 Args: a database handle and a sp_person_id of the submitter
173 Side Effects: accesses the database
178 sub get_locus_ids_by_annotator
{
180 my $sp_person_id = shift;
182 my $query= "SELECT distinct locus.locus_id, locus.modified_date FROM phenome.locus
183 LEFT JOIN phenome.locus_dbxref USING (locus_id)
184 LEFT JOIN phenome.locus_unigene using (locus_id)
185 LEFT JOIN phenome.locus_marker using (locus_id)
186 LEFT JOIN phenome.locus_alias using (locus_id)
187 LEFT JOIN phenome.locus2locus ON (phenome.locus.locus_id = locus2locus.subject_id
188 OR phenome.locus.locus_id = locus2locus.subject_id )
189 JOIN phenome.allele USING (locus_id)
190 LEFT JOIN phenome.individual_allele USING (allele_id)
191 LEFT JOIN phenome.individual USING (individual_id)
192 LEFT JOIN phenome.individual_image USING (individual_id)
193 LEFT JOIN metadata.md_image USING (image_id)
195 WHERE locus.updated_by=? OR locus_dbxref.sp_person_id=? OR locus_unigene.sp_person_id=?
196 OR locus_marker.sp_person_id=? OR allele.sp_person_id=? OR locus_alias.sp_person_id=?
197 OR individual_allele.sp_person_id=? OR metadata.md_image.sp_person_id=? OR locus2locus.sp_person_id =?
198 ORDER BY locus.modified_date DESC";
201 my $sth = $dbh->prepare($query);
202 $sth->execute($sp_person_id, $sp_person_id, $sp_person_id, $sp_person_id, $sp_person_id, $sp_person_id, $sp_person_id, $sp_person_id, $sp_person_id);
204 while (my($locus_id, $modified_date) = $sth->fetchrow_array()) {
205 push @loci, $locus_id;
214 my $dbh=$self->get_dbh();
215 my $locus_query = "SELECT locus_id,locus,locus_name, locus_symbol, original_symbol, gene_activity, description, locus.sp_person_id, locus.create_date, locus.modified_date, linkage_group, lg_arm, common_name, common_name_id, updated_by, locus.obsolete
217 JOIN sgn.common_name USING(common_name_id)
219 my $sth=$dbh->prepare($locus_query);
220 $sth->execute($self->get_locus_id());
222 my ($locus_id,$genome_locus, $locus_name,$locus_symbol,$original_symbol, $gene_activity, $description, $sp_person_id, $create_date, $modified_date, $chromosome, $arm, $common_name, $common_name_id, $updated_by, $obsolete)=$sth->fetchrow_array();
223 $self->set_locus_id($locus_id);
224 $self->set_genome_locus($genome_locus);
225 $self->set_locus_name($locus_name);
226 $self->set_locus_symbol($locus_symbol);
227 $self->set_original_symbol($original_symbol);
228 $self->set_gene_activity($gene_activity);
229 $self->set_description($description);
231 $self->set_sp_person_id($sp_person_id);
232 $self->set_create_date($create_date);
233 $self->set_modification_date($modified_date);
234 $self->set_linkage_group($chromosome);
235 $self->set_lg_arm($arm);
236 $self->set_common_name($common_name);
237 $self->set_common_name_id($common_name_id);
238 $self->set_updated_by($updated_by);
239 $self->set_obsolete($obsolete);
242 =head2 exists_in_database
244 Usage: my $existing_locus_id = CXGN::Phenome::Locus::exists_in_database();
245 Desc: check if a locus symbol or name for a given organism exists in the database
246 Ret: an error message for the given symbol, name, and common_name_id
254 sub exists_in_database
{
256 my $locus_name=shift;
257 my $locus_symbol=shift;
259 my $locus_id= $self->get_locus_id();
260 my $common_name_id= $self->get_common_name_id();
261 if (!$locus_name) { $locus_name=$self->get_locus_name(); }
262 if (!$locus_symbol) { $locus_symbol=$self->get_locus_symbol(); }
263 $self->d("Locus.pm: exists_in _database--**$locus_name, $locus_symbol \n");
265 my $name_query = "SELECT locus_id, obsolete
267 WHERE locus_name ILIKE ? and common_name_id = ? ";
268 my $name_sth = $self->get_dbh()->prepare($name_query);
269 $name_sth->execute($locus_name, $common_name_id );
270 my ($name_id, $name_obsolete)= $name_sth->fetchrow_array();
272 my $symbol_query = "SELECT locus_id, obsolete
274 WHERE locus_symbol ILIKE ? and common_name_id = ? ";
275 my $symbol_sth = $self->get_dbh()->prepare($symbol_query);
276 $symbol_sth->execute($locus_symbol, $common_name_id );
277 my ($symbol_id, $symbol_obsolete) = $symbol_sth->fetchrow_array();
279 #loading new locus- $locus_id is undef
280 if (!$locus_id && ($name_id || $symbol_id) ) {
283 $message = "Existing name $name_id";
286 $message = "Existing symbol $symbol_id";
288 $self->d("***$message\n");
289 return ( $message ) ;
291 #trying to update a locus.. if both the name and symbol remain- it's probably an update of
292 #the other fields in the form
293 if ($locus_id && $symbol_id) {
294 if ( ($name_id==$locus_id) && ($symbol_id==$locus_id) ) {
295 $self->d("--locus.pm exists_in_database returned 0.......\n");
297 #trying to update the name and/or the symbol
298 } elsif ( ($name_id!=$locus_id && $name_id) || ($symbol_id!=$locus_id && $symbol_id)) {
299 my $message = " Can't update an existing locus $locus_id name:$name_id symbol:$symbol_id.";
300 $self->d("++++Locus.pm exists_in_database: $message\n");
302 # if the new name or symbol we're trying to update/insert do not exist in the locus table..
304 $self->d("--locus.pm exists_in_database returned 0.......\n");
313 #add another check here with a die/error message for loading scripts
314 my $exists= $self->exists_in_database();
315 die "Locus exists in database! Cannot insert or update! \n $exists \n " if $exists;
316 my $locus_id=$self->get_locus_id();
319 $self->store_history();
321 my $query = "UPDATE phenome.locus SET
331 modified_date = now(),
334 my $sth= $self->get_dbh()->prepare($query);
335 $sth->execute($self->get_genome_locus,$self->get_locus_name, $self->get_locus_symbol, $self->get_original_symbol, $self->get_gene_activity, $self->get_description, $self->get_linkage_group(), $self->get_lg_arm(), $self->get_updated_by(), $self->get_obsolete(), $locus_id );
337 foreach my $dbxref ( @
{$self->{locus_dbxrefs
}} ) {
338 my $locus_dbxref_obj= CXGN
::Phenome
::LocusDbxref
->new($self->get_dbh());
339 #$locus_dbxref_obj->store(); # what do I want to store here?
341 $self->d("Locus.pm store: Updated locus $locus_id ......+\n");
342 #Update locus_alias 'preferred' field
343 $self->update_locus_alias();
347 my $query = "INSERT INTO phenome.locus (locus,locus_name, locus_symbol, original_symbol, gene_activity, description, linkage_group, lg_arm, common_name_id, create_date) VALUES(?,?,?,?,?,?,?,?,?, now()) RETURNING locus_id";
348 my $sth= $self->get_dbh()->prepare($query);
349 $sth->execute($self->get_genome_locus, $self->get_locus_name, $self->get_locus_symbol, $self->get_original_symbol, $self->get_gene_activity, $self->get_description, $self->get_linkage_group(), $self->get_lg_arm(), $self->get_common_name_id);
351 ($locus_id) = $sth->fetchrow_array;
352 $self->set_locus_id($locus_id);
354 my $locus_owner_query="INSERT INTO phenome.locus_owner (locus_id, sp_person_id) VALUES (?,?)";
355 my $locus_owner_sth=$self->get_dbh()->prepare($locus_owner_query);
356 $locus_owner_sth->execute($locus_id, $self->get_sp_person_id());
358 my $alias_query= "INSERT INTO phenome.locus_alias(locus_id, alias, preferred) VALUES (?, ?,'t')";
359 my $alias_sth= $self->get_dbh()->prepare($alias_query);
360 $alias_sth->execute($self->get_locus_id(), $self->get_locus_symbol());
362 #the following query will insert a 'dummy' default allele. Each locus must have a default allele.
363 # This is important for associating individuals with loci. The locus_display code masks the dummy alleles.
364 my $allele= CXGN
::Phenome
::Allele
->new($self->get_dbh());
365 $allele->set_locus_id($locus_id);
366 $allele->set_allele_symbol( uc($self->get_locus_symbol) );
367 $allele->set_is_default('t');
370 $self->d("***#####Locus.pm store: inserting new locus $locus_id....\n");
373 if ($@
) { warn "locus.pm store failed! \n $@ \n" }
379 Usage: $self->delete()
380 Desc: set the locus to obsolete=t
383 Side Effects: sets locus name and symbol to 'ob$locus_id-$locus_name'
384 obsoletes the associated alleles (see Allele.pm: delete() )
391 my $locus_id = $self->get_locus_id();
392 $self->set_locus_symbol("ob". $self->get_locus_id() . "-" .$self->get_locus_symbol() );
393 $self->set_locus_name("ob" . $self->get_locus_id() . "-" . $self->get_locus_name() );
394 my $ob=$self->get_obsolete();
395 if ($ob eq 'f' && $locus_id) {
396 $self->d("Locus.pm is obsoleting locus " . $self->get_locus_id() . "(obsolete=$ob)!!!!\n");
397 $self->set_obsolete('t');
400 $self->d("trying to delete a locus that has not yet been stored to db.\n");
406 Usage: $self->remove_allele($allele_id)
407 Desc: set an allele of this locus to obsolete
410 Side Effects: updates the obsolete field in the allele table to 't'
416 my $allele_id = shift;
417 my $query = "UPDATE phenome.allele
419 WHERE locus_id=? AND allele_id=?";
420 my $sth = $self->get_dbh()->prepare($query);
421 $sth->execute($self->get_locus_id(), $allele_id);
424 =head2 remove_locus_alias
426 Usage: $self->remove_locus_alias($locus_alias_id)
427 Desc: delete a locus alias from the locus_alias table
429 Args: $locus_alias_id
430 Side Effects: deletes a row from the locus_alias table
435 sub remove_locus_alias
{
437 my $locus_synonym_id = shift;
438 my $query = "DELETE FROM phenome.locus_alias WHERE locus_id=? AND locus_alias_id=?";
439 my $sth = $self->get_dbh()->prepare($query);
440 $sth->execute($self->get_locus_id(), $locus_synonym_id);
443 =head2 update_locus_alias
445 Usage: $self->update_locus_alias()
446 Desc: after updating the locus synonym field, we need to make that synonym the
447 'preferred' alias, and set the currently preferred one to 'f'
450 Side Effects: updating rows in the locus_alias table
455 sub update_locus_alias
{
457 my $symbol= $self->get_locus_symbol();
458 my @aliases= $self->get_locus_aliases();
460 foreach my $a ( @aliases) {
461 my $alias=$a->get_locus_alias();
462 if ($alias eq $symbol) {
463 $self->d("alias = $alias , symbol =$symbol, preferred=" . $a->get_preferred() . " Setting prefrred = 't'\n");
464 $a->set_preferred('t');
467 elsif ($a->get_preferred() ==1) {
468 $self->d( "alias = $alias , symbol =$symbol, preferred=" . $a->get_preferred() . " Setting prefrred = 'f'\n");
469 $a->set_preferred('f');
479 Usage: $self->get_unigenes({full=>1, current=>1})
480 Desc: find unigenes associated with the locus
481 Ret: list of (lite) unigene objects (without the sequences- much faster)
482 Args: optional hashref with the following keys:
483 full (1) - get a list of full unigene objects
484 (much slower, but important if you want to access the sequences of the unigens)
485 current(1) - fetch only current unigenes
494 my $full = $opts->{full
};
495 my $current = $opts->{current
};
496 my $query = "SELECT unigene_id FROM phenome.locus_unigene";
497 $query .= " JOIN sgn.unigene USING (unigene_id) JOIN sgn.unigene_build USING (unigene_build_id) ";
498 $query .= " WHERE locus_id=? AND obsolete = 'f' ";
499 $query .= " AND status = 'C' " if $current;
501 my $sth = $self->get_dbh()->prepare($query);
502 $sth->execute($self->get_locus_id());
505 while (my ($unigene_id) = $sth->fetchrow_array()) {
506 if ($full) { $unigene = CXGN
::Transcript
::Unigene
->new($self->get_dbh(), $unigene_id); }
507 else { $unigene = CXGN
::Transcript
::Unigene
->new_lite_unigene($self->get_dbh(), $unigene_id); }
508 push @unigenes, $unigene;
513 =head2 get_locus_unigene_id
515 Usage: my $locus_unigene_id= $locus->get_locus_unigene_id($unigene_id)
516 Desc: find the locus_unigene database id for a given unigene id
517 useful for manipulating locus_unigene table (like obsoleting a locus-unigene association)
518 since we do not have a LocusUnigene object (not sure an object is necessary if all is done from the Locus object)
520 Ret: a database id from the table phenome.locus_unigene
527 sub get_locus_unigene_id
{
529 my $unigene_id=shift;
530 my $query= "SELECT locus_unigene_id FROM phenome.locus_unigene
531 WHERE locus_id=? AND unigene_id=?";
532 my $sth=$self->get_dbh()->prepare($query);
533 $sth->execute($self->get_locus_id(), $unigene_id);
534 my ($locus_unigene_id) = $sth->fetchrow_array();
535 return $locus_unigene_id;
540 Usage: $self->add_unigene($unigene_id, $sp_person_id)
541 Desc: store a unigene-locus association in the database. If the link exists the function will set obsolete=f
543 Args: unigene_id, sp_person_id
544 Side Effects: access the database. Adds a locus_dbxref for SolCyc reactions which are linked to $unigene_id
545 (see table unigene_dbxref)
552 my $unigene_id=shift;
553 my $sp_person_id=shift;
554 my $existing_id= $self->get_locus_unigene_id($unigene_id);
557 $self->d("Locus::add_unigene is updating locus_unigene_id $existing_id!!!!!!");
558 my $u_query="UPDATE phenome.locus_unigene SET obsolete='f' WHERE locus_unigene_id=?";
559 my $u_sth=$self->get_dbh()->prepare($u_query);
560 $u_sth->execute($existing_id);
563 $self->d( "Locus:add_unigene is inserting a new unigene $unigene_id for locus " . $self->get_locus_id() . " (by person $sp_person_id) !!!");
564 my $query="Insert INTO phenome.locus_unigene (locus_id, unigene_id,sp_person_id) VALUES (?,?,?) RETURNING locus_unigene_id " ;
565 my $sth=$self->get_dbh->prepare($query);
566 $sth->execute($self->get_locus_id(), $unigene_id, $sp_person_id);
567 my ($id) = $sth->fetchrow_array;
570 #see if the unigene has solcyc links
572 my $dbh=$self->get_dbh;
573 my $unigene= CXGN
::Transcript
::Unigene
->new($dbh, $unigene_id);
574 my @u_dbxrefs= $unigene->get_dbxrefs();
575 foreach my $d(@u_dbxrefs) {
576 $self->add_locus_dbxref($d, undef, $sp_person_id) if $d->get_db_name() eq 'solcyc_images';
580 =head2 obsolete_unigene
582 Usage: $self->obsolete_unigene
583 Desc: set locus_unigene to obsolete
585 Args: locus_unigene_id
591 sub obsolete_unigene
{
594 my $u_query="UPDATE phenome.locus_unigene SET obsolete='t' WHERE locus_unigene_id=?";
595 my $u_sth=$self->get_dbh()->prepare($u_query);
596 $u_sth->execute($lu_id);
600 =head2 get_associated_loci DEPRECATED. SEE get_locusgroups
603 Usage: my @locus_ids = $locus->get_associated_loci()
604 Desc: return the loci that are associated to this
605 locus from the locus2locus table
606 Ret: a list of locus ids
614 sub get_associated_loci
{
615 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
618 my $query = "SELECT object_id FROM phenome.locus2locus WHERE obsolete = 'f' AND subject_id=?";
619 my $sth = $self->get_dbh()->prepare($query);
620 $sth->execute($self->get_locus_id());
622 while (my ($associated_locus) = $sth->fetchrow_array()) {
623 push @associated_loci, $associated_locus;
625 return @associated_loci;
630 =head2 get_reciprocal_loci DEPRECATED - SEE get_locusgroups()
631 Usage: my $locus_ids = $locus->get_reciprocal_loci()
632 Desc: returns the loci that this locus is associated to
633 in the locus2locus table
642 sub get_reciprocal_loci
{
643 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
645 my $query = "SELECT DISTINCT subject_id FROM phenome.locus2locus WHERE obsolete = 'f' AND object_id=?";
646 my $sth = $self->get_dbh()->prepare($query);
647 $sth->execute($self->get_locus_id());
649 while (my ($reciprocal_locus) = $sth->fetchrow_array()) {
650 push @reciprocal_loci, $reciprocal_locus;
652 return @reciprocal_loci;
657 =head2 get_subject_locus2locus_objects DEPRECATED. SEE get_locusgroups()
660 Usage: @l2l = $locus->get_subject_locus2locus_objects()
661 Desc: returns all associated locus2locus objects, including
662 object and subject id based ones.
663 Ret: a list of CXGN::Phenome::Locus2Locus objects
670 sub get_subject_locus2locus_objects
{
671 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
675 my $q = "SELECT DISTINCT locus2locus_id FROM phenome.locus2locus WHERE (subject_id=?) and obsolete='f'";
676 my $sth = $self->get_dbh()->prepare($q);
677 $sth->execute($self->get_locus_id());
679 while( my ($l2l) = $sth->fetchrow_array()) {
680 push @l2l, CXGN
::Phenome
::Locus2Locus
->new($self->get_dbh(), $l2l);
687 =head2 get_object_locus2locus_objects DEPRECATED. SEE get_locusgroups()
690 Usage: @l2l = $locus->get_object_locus2locus_objects()
691 Desc: returns all associated locus2locus objects, including
693 Ret: a list of CXGN::Phenome::Locus2Locus objects
700 sub get_object_locus2locus_objects
{
701 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
705 my $q = "SELECT DISTINCT locus2locus_id FROM phenome.locus2locus WHERE object_id=? and obsolete='f'";
706 my $sth = $self->get_dbh()->prepare($q);
707 $sth->execute($self->get_locus_id());
709 while( my ($l2l) = $sth->fetchrow_array()) {
710 push @l2l, CXGN
::Phenome
::Locus2Locus
->new($self->get_dbh(), $l2l);
716 =head2 add_related_locus
718 Usage: $self->add_related_locus($locus_id)
719 Desc: an accessor for building an associated locus list for the locus
727 sub add_related_locus
{
730 push @
{ $self->{related_loci
} }, $locus;
734 =head2 accessors available (get/set)
751 return $self->{locus_id
};
757 $self->{locus_id
}=shift;
763 return $self->{locus_name
};
769 $self->{locus_name
}=shift;
772 sub get_locus_symbol
{
774 return $self->{locus_symbol
};
778 sub set_locus_symbol
{
780 $self->{locus_symbol
}=shift;
784 sub get_original_symbol
{
786 return $self->{original_symbol
};
790 sub set_original_symbol
{
792 $self->{original_symbol
}=shift;
795 sub get_gene_activity
{
797 return $self->{gene_activity
};
801 sub set_gene_activity
{
803 $self->{gene_activity
}=shift;
807 sub get_description
{
809 return $self->{description
};
813 sub set_description
{
815 $self->{description
}=shift;
819 sub get_linkage_group
{
821 return $self->{linkage_group
};
825 sub set_linkage_group
{
827 $self->{linkage_group
}=shift;
833 return $self->{lg_arm
};
839 $self->{lg_arm
}=shift;
843 sub get_common_name
{
845 return $self->{common_name
};
849 sub set_common_name
{
851 $self->{common_name
}=shift;
855 sub get_common_name_id
{
857 return $self->{common_name_id
};
861 sub set_common_name_id
{
863 $self->{common_name_id
}=shift;
866 sub get_genome_locus
{
868 return $self->{genome_locus
};
871 sub set_genome_locus
{
873 $self->{genome_locus
} = shift;
877 =head2 add_locus_alias
879 Usage: $self->add_locus_alias($locus_synonym_object)
880 Desc: add an alias to the locus
881 Ret: a locus_alias id
882 Args: LocusSynonym object
883 Side Effects: accesses the database
888 sub add_locus_alias
{
890 my $locus_alias = shift; #LocusSynonym object!!
891 $locus_alias->set_locus_alias_id(); #set the id to undef in case of the function was called from the merge_locus function
892 $locus_alias->set_locus_id($self->get_locus_id());
893 my $symbol = $self->get_locus_symbol();
894 #if the locus symbol and the alias are the same, then set the new alias to preferred = 't'
895 if ($symbol eq $locus_alias->get_locus_alias()) {
896 $locus_alias->set_preferred('t');
898 my $id=$locus_alias->store();
903 =head2 get_locus_aliases
905 Usage: $self->get_locus_aliases()
906 Desc: find the aliases of a locus
907 Ret: list of LocusSynonym objects
908 Args: optional : preffered and obsolete booleans
914 sub get_locus_aliases
{
916 my ($preferred, $obsolete) = @_;
917 my $query="SELECT locus_alias_id from phenome.locus_alias WHERE locus_id=? ";
918 $query .= " AND preferred = '$preferred' " if $preferred;
919 $query .= " AND obsolete = '$obsolete' " if $obsolete;
920 my $sth=$self->get_dbh()->prepare($query);
922 $sth->execute($self->get_locus_id());
923 while (my ($ls_id) = $sth->fetchrow_array()) {
924 my $lso=CXGN
::Phenome
::LocusSynonym
->new($self->get_dbh(), $ls_id);
925 push @locus_synonyms, $lso;
927 return @locus_synonyms;
932 Usage: $self->add_allele($allele)
933 Desc: add an allele to the locus
934 Ret: the new allele_id
936 Side Effects: accessed the database, Calls Allele->store().
943 my $allele=shift; #allele object
944 $allele->set_locus_id($self->get_locus_id() );
945 my $id = $allele->store();
949 =head2 add_allele_symbol
951 Usage: $self->add_allele_symbol($allele_symbol)
952 Desc: an accessor for building an allele list for the locus
960 sub add_allele_symbol
{
962 my $allele=shift; #allele symbol
963 push @
{ $self->{allele_symbols
} }, $allele;
968 Usage: my @alleles=$self->get_alleles()
969 Desc: find the alleles associated with the locus
970 Ret: a list of allele objects
979 $self->d("Getting alleles.... \n\n");
980 my $allele_query=("SELECT allele_id FROM phenome.allele WHERE locus_id=? AND obsolete='f' AND is_default='f'");
981 my $sth=$self->get_dbh()->prepare($allele_query);
983 $sth->execute($self->get_locus_id());
984 while (my ($a_id) = $sth->fetchrow_array()) {
985 my $allele= CXGN
::Phenome
::Allele
->new($self->get_dbh(), $a_id);
986 push @alleles, $allele;
990 =head2 get_default_allele
992 Usage: $self->get_default_allele()
993 Desc: find the database id from the default allele
1001 sub get_default_allele
{
1003 my $query = "SELECT allele_id from phenome.allele
1004 WHERE locus_id = ? AND is_default = 't'";
1005 my $sth=$self->get_dbh()->prepare($query);
1006 $sth->execute($self->get_locus_id());
1007 my ($allele_id) = $sth->fetchrow_array();
1024 my $synonym=shift; #synonym
1025 push @
{ $self->{synonyms
} }, $synonym;
1043 my $dbxref=shift; #dbxref object
1044 push @
{ $self->{dbxrefs
} }, $dbxref;
1049 Usage: $locus->get_dbxrefs();
1050 Desc: get all the dbxrefs associated with a locus
1051 Ret: array of dbxref objects
1053 Side Effects: accesses the database
1060 my $locus_id=$self->get_locus_id();
1062 my $dbxref_query="SELECT locus_dbxref.dbxref_id from phenome.locus_dbxref JOIN public.dbxref USING(dbxref_id) WHERE locus_id=? ORDER BY public.dbxref.accession";
1063 my $sth=$self->get_dbh()->prepare($dbxref_query);
1065 my @dbxrefs=(); #an array for storing dbxref objects
1066 $sth->execute($locus_id);
1067 while (my ($d) = $sth->fetchrow_array() ) {
1068 $dbxref= CXGN
::Chado
::Dbxref
->new($self->get_dbh(), $d);
1069 push @dbxrefs, $dbxref;
1074 =head2 get_dbxrefs_by_type
1076 Usage: $locus->get_dbxrefs_by_type("ontology");
1077 Desc: get all the dbxrefs terms associated with a locus
1078 Ret: array of dbxref objects
1079 Args: type (ontology, literature, genbank)
1080 Side Effects: accesses the database
1085 sub get_dbxrefs_by_type
{
1088 my $locus_id=$self->get_locus_id();
1090 my $dbh = $self->get_dbh();
1092 if ($type eq 'ontology') {
1093 $query="SELECT locus_dbxref.dbxref_id from phenome.locus_dbxref
1094 JOIN public.dbxref USING(dbxref_id)
1095 JOIN public.cvterm USING (dbxref_id)
1096 WHERE locus_id=? ORDER BY public.dbxref.accession";
1097 }elsif ($type eq 'literature') {
1098 $query="SELECT locus_dbxref.dbxref_id from phenome.locus_dbxref
1099 JOIN public.dbxref USING(dbxref_id)
1100 JOIN public.db USING (db_id)
1101 WHERE locus_id=? AND db.name IN ('PMID','SGN_ref') ORDER BY public.dbxref.accession";
1102 }elsif ($type eq 'genbank') {
1103 $query="SELECT locus_dbxref.dbxref_id from phenome.locus_dbxref
1104 JOIN public.dbxref USING(dbxref_id)
1105 JOIN public.db USING (db_id)
1106 WHERE locus_id=? AND db.name IN ('DB:GenBank_GI')
1107 AND locus_dbxref.obsolete= 'f' ORDER BY public.dbxref.accession";
1108 }else { warn "dbxref type '$type' not recognized! \n" ; return undef; }
1109 my $sth=$self->get_dbh()->prepare($query);
1111 my @dbxrefs=(); #an array for storing dbxref objects
1112 $sth->execute($locus_id);
1113 while (my ($d) = $sth->fetchrow_array() ) {
1114 $dbxref= CXGN
::Chado
::Dbxref
->new($self->get_dbh(), $d);
1115 push @dbxrefs, $dbxref;
1120 =head2 get_dbxref_lists
1122 Usage: $locus->get_dbxref_lists();
1123 Desc: get all the dbxrefs terms associated with a locus
1124 Ret: hash of 2D arrays . Keys are the db names values are [dbxref object, locus_dbxref.obsolete]
1131 sub get_dbxref_lists
{
1134 my $query= "SELECT db.name, dbxref.dbxref_id, locus_dbxref.obsolete FROM locus_dbxref
1135 JOIN public.dbxref USING (dbxref_id) JOIN public.db USING (db_id)
1136 WHERE locus_id= ? ORDER BY db.name, dbxref.accession";
1137 my $sth=$self->get_dbh()->prepare($query);
1138 $sth->execute($self->get_locus_id());
1139 while (my ($db_name, $dbxref_id, $obsolete) = $sth->fetchrow_array()) {
1140 push @
{$dbxrefs{$db_name} }, [CXGN
::Chado
::Dbxref
->new($self->get_dbh(), $dbxref_id), $obsolete] ;
1145 =head2 get_all_dbxrefs
1156 sub get_all_dbxrefs
{
1158 my $locus_name = $locus->get_locus_name() ;
1159 my %dbs = $locus->get_dbxref_lists() ; #hash of arrays. keys=dbname values= dbxref objects
1160 my @alleles = $locus->get_alleles();
1161 #add the allele dbxrefs to the locus dbxrefs hash...
1162 #This way the alleles associated publications and sequences are also printed on the locus page
1163 #it might be a good idea to print a link to the allele next to each allele-derived annotation
1165 foreach my $a (@alleles) {
1166 my %a_dbs = $a->get_dbxref_lists();
1168 foreach my $a_db_name ( keys %a_dbs ) {
1169 #add allele_dbxrefs to the locus_dbxrefs list
1170 my %seen = () ; #hash for assisting filtering of duplicated dbxrefs (from allele annotation)
1171 foreach my $xref ( @
{ $dbs{$a_db_name} } ) {
1172 $seen{ $xref->[0]->get_accession() }++;
1173 } #populate with the locus_dbxrefs
1174 foreach my $axref ( @
{ $a_dbs{$a_db_name} } ) { #and filter duplicates
1175 push @
{ $dbs{$a_db_name} }, $axref
1176 unless $seen{ $axref->[0]->get_accession() }++;
1185 =head2 get_locus_dbxrefs
1187 Usage: $self->get_locus_dbxrefs()
1188 Desc: get the LocusDbxref objects associated with this locus
1189 Ret: a hash of arrays. Keys=db_name, values = lists of LocusDbxref objects
1196 sub get_locus_dbxrefs
{
1199 my $query= "SELECT db.name, locus_dbxref.locus_dbxref_id FROM locus_dbxref
1200 JOIN public.dbxref USING (dbxref_id) JOIN public.db USING (db_id)
1201 WHERE locus_id= ? ORDER BY db.name, dbxref.accession";
1202 my $sth=$self->get_dbh()->prepare($query);
1203 $sth->execute($self->get_locus_id());
1204 while (my ($db_name, $ld_id) = $sth->fetchrow_array()) {
1205 push @
{$lds{$db_name} }, CXGN
::Phenome
::LocusDbxref
->new($self->get_dbh(), $ld_id) ;
1211 =head2 add_locus_marker
1222 sub add_locus_marker
{
1224 push @
{ $self->{locus_markers
} }, shift;
1227 =head2 get_locus_markers
1238 sub get_locus_markers
{
1240 return @
{$self->{locus_markers
} || [] };
1244 =head2 get_locus_dbxref
1246 Usage: $locus->get_locus_dbxref($dbxref)
1247 Desc: access locus_dbxref object for a given locus and
1249 Ret: a LocusDbxref object
1251 Side Effects: accesses the database
1256 sub get_locus_dbxref
{
1258 my $dbxref=shift; # my dbxref object..
1259 my $query="SELECT locus_dbxref_id from phenome.locus_dbxref
1260 WHERE locus_id=? AND dbxref_id=? ";
1261 my $sth=$self->get_dbh()->prepare($query);
1262 $sth->execute($self->get_locus_id(), $dbxref->get_dbxref_id() );
1263 my ($locus_dbxref_id) = $sth->fetchrow_array();
1264 my $locus_dbxref= CXGN
::Phenome
::LocusDbxref
->new($self->get_dbh(), $locus_dbxref_id);
1265 return $locus_dbxref;
1268 =head2 add_locus_dbxref
1270 Usage: $locus->add_locus_dbxref($dbxref_object,
1273 Desc: adds a locus_dbxref relationship
1276 Side Effects: calls store function in LocusDbxref
1281 sub add_locus_dbxref
{
1283 my $dbxref=shift; #dbxref object
1284 my $locus_dbxref_id=shift;
1285 my $sp_person_id=shift;
1287 my $locus_dbxref=CXGN
::Phenome
::LocusDbxref
->new($self->get_dbh(), $locus_dbxref_id );
1288 $locus_dbxref->set_locus_id($self->get_locus_id() );
1289 $locus_dbxref->set_dbxref_id($dbxref->get_dbxref_id() );
1290 $locus_dbxref->set_sp_person_id($sp_person_id);
1291 if (!$dbxref->get_dbxref_id()) {return undef };
1293 my $id = $locus_dbxref->store();
1297 =head2 function get_individuals
1299 Synopsis: DEPRECATED. Use get_stock_ids
1300 my @individuals=$locus->get_individuals();
1308 sub get_individuals
{
1310 warn "DEPRECATED. Use get_stocks.";
1314 =head2 get_stock_ids
1316 Usage: my $stock_ids = $self->get_stock_ids
1317 Desc: find stocks associated with the locus
1318 Ret: a list of stock_ids
1327 my $query = "select distinct stock_id FROM phenome.stock_allele
1328 JOIN phenome.allele USING (allele_id)
1329 WHERE locus_id = ? AND allele.obsolete = ? ";
1330 my $ids = $self->get_dbh->selectcol_arrayref
1333 $self->get_locus_id,
1340 =head2 get_locus_registry_symbol
1342 Usage: $locus->get_locus_registry_symbol()
1343 Desc: get the registered symbol of a locus
1344 Ret: a registry object?
1351 sub get_locus_registry_symbol
{
1354 my $query=$self->get_dbh()->prepare("SELECT registry_id from phenome.locus_registry
1355 WHERE locus_id=? ");
1356 $query->execute($self->get_locus_id() );
1357 my ($registry_id) = $query->fetchrow_array();
1359 my $registry= CXGN
::Phenome
::Registry
->new($self->get_dbh(), $registry_id);
1361 }else { return undef; }
1366 =head2 store_history
1368 Usage: $self->store_history()
1369 Desc: Inserts the current fields of a locus object into
1370 the locus_history table before updating the locus details
1381 my $locus=CXGN
::Phenome
::Locus
->new($self->get_dbh(), $self->get_locus_id() );
1382 $self->d( "Locus.pm:*Storing history for locus " . $self->get_locus_id() . "\n");
1383 my $history_query = "INSERT INTO phenome.locus_history (locus_id, locus_name, locus_symbol, original_symbol,gene_activity,locus_description,linkage_group, lg_arm, sp_person_id, updated_by, obsolete, create_date)
1384 VALUES(?,?,?,?,?,?,?,?,?,?,?, now())";
1385 my $history_sth= $self->get_dbh()->prepare($history_query);
1387 $history_sth->execute($locus->get_locus_id(), $locus->get_locus_name(), $locus->get_locus_symbol(), $locus->get_original_symbol(), $locus->get_gene_activity(), $locus->get_description(), $locus->get_linkage_group(), $locus->get_lg_arm(), $locus->get_sp_person_id, $self->get_updated_by(), $locus->get_obsolete() );
1394 Usage: $locus->show_history();
1395 Desc: Selects the data from locus_history table for a locus object
1405 my $locus_id= $self->get_locus_id();
1406 my $history_query=$self->get_dbh()->prepare("SELECT locus_history_id FROM phenome.locus_history WHERE locus_id=?");
1408 $history_query->execute($locus_id);
1409 while (my ($history_id) = $history_query->fetchrow_array()) {
1410 my $history_obj = CXGN
::Phenome
::Locus
::LocusHistory
->new($self->get_dbh(), $history_id);
1411 push @history, $history_obj;
1416 =head2 get_associated_registry
1420 Ret: the Registry symbol
1427 sub get_associated_registry
{
1429 my $locus_id= $self->get_locus_id();
1430 my $registry_query=$self->get_dbh()->prepare("SELECT locus_registry.registry_id, registry.name FROM phenome.locus_registry JOIN phenome.registry USING (registry_id) WHERE locus_id=?");
1431 $registry_query->execute($locus_id);
1432 my ($registry_id, $name) = $registry_query->fetchrow_array();
1436 =head2 associated_publication
1438 Usage: my $associated= $locus->associated_publication($accession)
1439 Desc: checks if a publication is already associated with the locus
1441 Args: publication accession (pubmed ID)
1447 sub associated_publication
{
1450 my $accession=shift;
1451 my $query = $self->get_dbh()->prepare("SELECT dbxref_id FROM phenome.locus_dbxref JOIN dbxref USING (dbxref_id) WHERE locus_id = ? AND dbxref.accession = ? AND obsolete = 'f'");
1452 $query->execute($self->get_locus_id(), $accession);
1453 my ($is_associated) = $query->fetchrow_array();
1454 return $is_associated;
1457 =head2 get_recent_annotated_loci
1459 Usage: my %edits= CXGN::Phenome::Locus::get_recent_annotated_loci($dbh, $date)
1460 Desc: find all the loci annotated after date $date
1461 Ret: hash of arrays of locus objects, aliases, alleles, locus_dbxrefs, unigenes, markers,stocks, and images
1462 Args: database handle and a date
1468 sub get_recent_annotated_loci
{
1475 #get all created and modified loci
1477 my $locus_query="SELECT locus_id FROM phenome.locus WHERE modified_date>? OR create_date>?
1478 ORDER BY modified_date desc";
1479 my $locus_sth=$dbh->prepare($locus_query);
1480 $locus_sth->execute($date,$date);
1481 while (my($locus_id) = $locus_sth->fetchrow_array()) {
1482 my $locus= CXGN
::Phenome
::Locus
->new($dbh, $locus_id);
1483 push @
{ $edits{loci
} }, $locus;
1486 #get all created and modified aliases
1488 my $locus_alias_query="SELECT locus_alias_id FROM phenome.locus_alias
1489 WHERE (modified_date>? OR create_date>?) AND preferred='f'
1490 ORDER BY modified_date desc";
1491 my $locus_alias_sth=$dbh->prepare($locus_alias_query);
1492 $locus_alias_sth->execute($date,$date);
1493 while (my($locus_alias_id) = $locus_alias_sth->fetchrow_array()) {
1494 my $locus_alias= CXGN
::Phenome
::LocusSynonym
->new($dbh, $locus_alias_id);
1495 push @
{ $edits{aliases
} }, $locus_alias;
1497 #get all created and modified alleles
1499 my $allele_query="SELECT allele_id FROM phenome.allele
1500 WHERE (modified_date>? OR create_date>?) and is_default='f'
1501 ORDER BY modified_date desc";
1502 my $allele_sth=$dbh->prepare($allele_query);
1503 $allele_sth->execute($date,$date);
1504 while (my($allele_id) = $allele_sth->fetchrow_array()) {
1505 my $allele= CXGN
::Phenome
::Allele
->new($dbh, $allele_id);
1506 push @
{ $edits{alleles
} }, $allele;
1510 #get all locus_dbxrefs
1512 my $locus_dbxref_query="SELECT locus_dbxref_id FROM phenome.locus_dbxref
1513 WHERE (modified_date>? OR create_date>?)
1514 ORDER BY modified_date desc, create_date desc";
1515 my $locus_dbxref_sth=$dbh->prepare($locus_dbxref_query);
1516 $locus_dbxref_sth->execute($date,$date);
1518 while (my($locus_dbxref_id) = $locus_dbxref_sth->fetchrow_array()) {
1519 my $locus_dbxref= CXGN
::Phenome
::LocusDbxref
->new($dbh, $locus_dbxref_id);
1520 push @
{ $edits{locus_dbxrefs
} }, $locus_dbxref;
1524 #get associated images
1526 my $image_query="SELECT locus_id, image_id , sp_person_id, create_date, modified_date, obsolete
1527 FROM phenome.locus_image
1528 WHERE (modified_date>? OR create_date>?)
1529 ORDER BY modified_date desc, create_date desc";
1530 my $image_sth=$dbh->prepare($image_query);
1531 $image_sth->execute($date,$date);
1533 while (my($locus_id, $image_id, $person_id, $cdate, $mdate, $obsolete) = $image_sth->fetchrow_array()) {
1534 my $image= CXGN
::Image
->new($dbh, $image_id);
1535 my $locus=CXGN
::Phenome
::Locus
->new($dbh, $locus_id);
1536 push @
{ $edits{locus_images
} }, [$locus, $image, $person_id, $cdate, $mdate, $obsolete];
1540 #get associated stocks
1542 my $schema= Bio
::Chado
::Schema
->connect( sub { $dbh->clone } ) ;
1543 my $stock_query = "SELECT * FROM phenome.stock_allele join metadata.md_metadata USING (metadata_id) WHERE create_date>? OR modified_date>? ORDER BY modified_date DESC, create_date DESC";
1544 my $stock_sth = $dbh->prepare($stock_query);
1545 $stock_sth->execute($date, $date);
1546 while ( my $hashref = $stock_sth->fetchrow_hashref() ) {
1547 my $stock = CXGN
::Chado
::Stock
->new($schema, $hashref->{stock_id
} );
1548 my $allele = CXGN
::Phenome
::Allele
->new($dbh, $hashref->{allele_id
} );
1549 push @
{ $edits{stocks
} }, [$stock, $allele, $hashref->{create_person_id
}, $hashref->{create_date
}, $hashref->{modified_date
}, $hashref->{obsolete
}];
1552 #get associated unigenes
1554 my $locus_unigene_query="SELECT locus_id, unigene_id, sp_person_id, create_date, modified_date, obsolete
1555 FROM phenome.locus_unigene
1556 WHERE (modified_date>? OR create_date>?)
1557 ORDER BY modified_date DESC, create_date DESC";
1559 my $locus_unigene_sth=$dbh->prepare($locus_unigene_query);
1560 $locus_unigene_sth->execute($date,$date);
1562 while (my($locus_id, $unigene_id, $person_id, $cdate,$mdate, $obsolete) = $locus_unigene_sth->fetchrow_array()) {
1563 my $unigene= CXGN
::Transcript
::Unigene
->new_lite_unigene($dbh, $unigene_id);
1564 my $locus=CXGN
::Phenome
::Locus
->new($dbh, $locus_id);
1565 push @
{ $edits{locus_unigenes
} }, [$unigene,$locus, $person_id, $cdate, $mdate, $obsolete];
1568 #get associated markers
1569 my $locus_marker_query="SELECT locus_marker_id
1570 FROM phenome.locus_marker
1571 WHERE (modified_date>? OR create_date>?)
1572 ORDER BY modified_date DESC, create_date DESC";
1573 my $locus_marker_sth=$dbh->prepare($locus_marker_query);
1574 $locus_marker_sth->execute($date,$date);
1576 while (my ($locus_marker_id) = $locus_marker_sth->fetchrow_array()) {
1577 my $locus_marker= CXGN
::Phenome
::LocusMaker
->new($dbh, $locus_marker_id);
1578 push @
{ $edits{locus_markers
} }, $locus_marker;
1587 Usage: my %edits= CXGN::Phenome::Locus::get_edits($locus)
1588 Desc: find all annotations by date for this locus
1589 Ret: hash of arrays of aliases, alleles, locus_dbxrefs, unigenes, markers,stocks, and images
1599 my $dbh=$self->get_dbh();
1601 #get all locus edits (LocusHistory objects
1604 push @
{ $edits{loci
} }, $self->show_history();
1607 #get all created and modified aliases
1609 my $locus_alias_query="SELECT locus_alias_id FROM phenome.locus_alias
1611 ORDER BY modified_date desc, create_date desc";
1612 my $locus_alias_sth=$dbh->prepare($locus_alias_query);
1613 $locus_alias_sth->execute($self->get_locus_id());
1614 while (my($locus_alias_id) = $locus_alias_sth->fetchrow_array()) {
1615 my $locus_alias= CXGN
::Phenome
::LocusSynonym
->new($dbh, $locus_alias_id);
1616 push @
{ $edits{aliases
} }, $locus_alias;
1618 #get all created and modified alleles
1620 my $allele_query="SELECT allele_id FROM phenome.allele
1621 WHERE is_default='f' AND locus_id =?
1622 ORDER BY modified_date DESC, create_date DESC";
1623 my $allele_sth=$dbh->prepare($allele_query);
1624 $allele_sth->execute($self->get_locus_id());
1625 while (my($allele_id) = $allele_sth->fetchrow_array()) {
1626 my $allele= CXGN
::Phenome
::Allele
->new($dbh, $allele_id);
1627 push @
{ $edits{alleles
} }, $allele;
1631 #get all locus_dbxrefs
1633 my $locus_dbxref_query="SELECT locus_dbxref_id FROM phenome.locus_dbxref
1635 ORDER BY modified_date desc, create_date desc";
1636 my $locus_dbxref_sth=$dbh->prepare($locus_dbxref_query);
1637 $locus_dbxref_sth->execute($self->get_locus_id());
1639 while (my($locus_dbxref_id) = $locus_dbxref_sth->fetchrow_array()) {
1640 my $locus_dbxref= CXGN
::Phenome
::LocusDbxref
->new($dbh, $locus_dbxref_id);
1641 push @
{ $edits{locus_dbxrefs
} }, $locus_dbxref;
1645 #get associated images
1647 my $image_query="SELECT image_id , sp_person_id, create_date, modified_date, obsolete
1648 FROM phenome.locus_image
1650 ORDER BY modified_date desc, create_date desc";
1651 my $image_sth=$dbh->prepare($image_query);
1652 $image_sth->execute($self->get_locus_id);
1654 while (my($image_id, $person_id, $cdate, $mdate, $obsolete) = $image_sth->fetchrow_array()) {
1655 my $image= CXGN
::Image
->new($dbh, $image_id);
1656 push @
{ $edits{images
} }, [$image, $person_id, $cdate, $mdate, $obsolete];
1660 #get associated stocks
1662 # need to figure out a way for storing stockprops of type 'sgn allele_id' with storage date
1663 #push @{ $edits{individuals} }, $individual;
1667 #get associated unigenes
1669 my $locus_unigene_query="SELECT unigene_id, sp_person_id, create_date, modified_date, obsolete
1670 FROM phenome.locus_unigene
1672 ORDER BY modified_date DESC, create_date DESC";
1674 my $locus_unigene_sth=$dbh->prepare($locus_unigene_query);
1675 $locus_unigene_sth->execute($self->get_locus_id());
1677 while (my($unigene_id, $person_id, $cdate,$mdate, $obsolete) = $locus_unigene_sth->fetchrow_array()) {
1678 my $unigene= CXGN
::Transcript
::Unigene
->new($dbh, $unigene_id);
1679 push @
{ $edits{unigenes
} }, [$unigene, $person_id, $cdate, $mdate, $obsolete];
1682 #get associated markers
1683 my $locus_marker_query="SELECT marker_id FROM phenome.locus_marker
1685 ORDER BY modified_date DESC, create_date DESC";
1686 my $locus_marker_sth=$dbh->prepare($locus_marker_query);
1687 $locus_marker_sth->execute($self-get_locus_id
());
1689 while (my($locus_marker_id) = $locus_marker_sth->fetchrow_array()) {
1690 my $locus_marker= CXGN
::Phenome
::LocusMaker
->new($dbh, $locus_marker_id);
1691 push @
{ $edits{markers
} }, $locus_marker;
1698 =head2 function get_figures
1700 Synopsis: my @figures=$locus->get_figures();
1702 Returns: list of CXGN::image objects
1704 Description: all images are stored in the locus_image linking table
1710 my $query = "SELECT image_id FROM phenome.locus_image
1711 WHERE obsolete = 'f' and locus_id=?";
1712 my $sth = $self->get_dbh()->prepare($query);
1713 $sth->execute($self->get_locus_id());
1716 while (my ($image_id) = $sth->fetchrow_array()) {
1717 $image = CXGN
::Image
->new($self->get_dbh(), $image_id);
1718 push @images, $image;
1723 =head2 get_figure_ids
1725 Usage: $self->get_figure_ids
1726 Desc: get a list of image_ids for figures associated with the locus
1727 Ret: a list of image ids
1734 sub get_figure_ids
{
1736 my $query = "SELECT image_id FROM phenome.locus_image
1737 WHERE obsolete = 'f' and locus_id=?";
1738 my $sth = $self->get_dbh()->prepare($query);
1739 $sth->execute($self->get_locus_id());
1741 while (my ($image_id) = $sth->fetchrow_array()) {
1742 push @image_ids, $image_id;
1751 Usage: $self->add_figure($image_id, $sp_person_id)
1752 Desc: associate an existing image/figure with the locus
1753 Ret: database id (locus_image_id)
1754 Args: image_id, sp_person_id
1755 Side Effects: accesses the database
1763 my $sp_person_id=shift;
1764 my $query="Insert INTO phenome.locus_image (locus_id, image_id,sp_person_id) VALUES (?,?,?)";
1765 my $sth=$self->get_dbh->prepare($query);
1766 $sth->execute($self->get_locus_id(), $image_id, $sp_person_id);
1767 my $id= $self->get_currval("phenome.locus_image_locus_image_id_seq");
1774 Usage: my @owners=$locus->get_owners(1)
1775 Desc: get all the owners of the current locus object
1776 Ret: an array of SGN person ids
1777 Args: [optional] boolean - if passed then return an arrayref of people objects
1785 my $return_obj = shift;
1786 my $query = "SELECT sp_person_id FROM phenome.locus_owner
1787 WHERE locus_id = ? AND obsolete = 'f' ORDER BY create_date";
1788 my $sth=$self->get_dbh()->prepare($query);
1789 $sth->execute($self->get_locus_id());
1793 while (my ($sp_person_id) = $sth->fetchrow_array()) {
1794 $person = CXGN
::People
::Person
->new($self->get_dbh(), $sp_person_id);
1795 push @owners, $sp_person_id;
1796 push @o_objects, $person;
1798 return \
@o_objects if $return_obj;
1804 Usage: $self->add_owner($owner_id,$sp_person_id)
1805 Desc: assign a locus owner
1807 Args: owner_id, user_id
1808 Side Effects: insert a new locus_owner
1816 my $sp_person_id=shift;
1818 if (!$self->owner_exists($owner_id)) {
1820 my $query = "INSERT INTO phenome.locus_owner (sp_person_id, locus_id, granted_by)
1822 my $sth=$self->get_dbh()->prepare($query);
1823 $sth->execute($owner_id, $self->get_locus_id(), $sp_person_id);
1824 my $id= $self->get_currval("phenome.locus_owner_locus_owner_id_seq");
1825 $self->d( "Locus.pm:add_owner: added owner id: $owner_id, granted by: $sp_person_id\n");
1827 }else { return undef; }
1833 Usage: $self->owner_exists($sp_person_id)
1834 Desc: check if the locus already has owner $sp_person_id
1835 Ret: database id (locus_owner_id) or undef
1844 my $sp_person_id=shift;
1845 my $q= "SELECT locus_owner_id, obsolete FROM phenome.locus_owner WHERE locus_id=? AND sp_person_id=? ";
1846 my $sth=$self->get_dbh()->prepare($q);
1847 $sth->execute($self->get_locus_id(), $sp_person_id);
1848 my ($id, $ob)= $sth->fetchrow_array();
1849 return $id || undef;
1854 =head2 get_individual_allele_id
1856 Usage: DEPRECATED. allele_ids are now stored in stock_allele
1857 my $individual_allele_id= $locus->get_individual_allele_id($individual_id)
1858 Desc: find the individual_allele database id for a given individual id
1859 useful for manipulating individual_allele table (like obsoleting an individual-allele association)
1861 Ret: a database id from the table phenome.individual_allele
1862 Args: $individual_id
1868 sub get_individual_allele_id
{
1870 my $individual_id=shift;
1871 my $query= "SELECT individual_allele_id FROM phenome.individual_allele
1872 JOIN phenome.allele USING (allele_id)
1873 WHERE locus_id=? AND individual_id=?";
1874 my $sth=$self->get_dbh()->prepare($query);
1875 $sth->execute($self->get_locus_id(), $individual_id);
1876 my ($individual_allele_id) = $sth->fetchrow_array();
1877 return $individual_allele_id;
1880 =head2 get_associated_locus DEPRECATED. SEE get_locusgroups()
1882 Usage: $locus->get_associated_locus($associated_locus_id)
1883 Desc: get a locus2locus object of the locus (object) associated to the current locus (subject)
1884 Ret: a Locus2Locus object or undef
1885 Args: $associated_locus_id
1891 sub get_associated_locus
{
1892 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
1895 my $associated_locus_id=shift;
1896 my $query = "SELECT locus2locus_id FROM phenome.locus2locus WHERE object_id=? AND subject_id = ? AND obsolete= 'f'";
1897 my $sth = $self->get_dbh()->prepare($query);
1898 $sth->execute($associated_locus_id, $self->get_locus_id());
1899 my ($l2l_id) = $sth->fetchrow_array();
1902 my $l2l=CXGN
::Phenome
::Locus2Locus
->new($self->get_dbh(), $l2l_id);
1904 } else { return undef };
1907 =head2 get_reciprocal_locus DEPRECATED. SEE get_locusgroups()
1910 Usage: $locus->get_reciprocal_locus($reciprocal_locus_id)
1911 Desc: get a locus2locus object of the reciprocal_locus (subject) associated to the current locus (object).
1912 This is used for printing the reciprocal loci associated with a specific locus.
1913 Ret: Locus2Locus object or undef
1914 Args: $reciprocal_locus_id
1920 sub get_reciprocal_locus
{
1921 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
1924 my $reciprocal_locus_id=shift;
1925 my $query = "SELECT locus2locus_id FROM phenome.locus2locus WHERE object_id=? AND subject_id = ? AND obsolete='f'";
1926 my $sth = $self->get_dbh()->prepare($query);
1927 $sth->execute( $self->get_locus_id(), $reciprocal_locus_id);
1928 my ($l2l_id) = $sth->fetchrow_array();
1930 my $l2l=CXGN
::Phenome
::Locus2Locus
->new($self->get_dbh(), $l2l_id);
1932 }else {return undef ; }
1936 =head2 get_locus_annotations
1938 Usage: $self->get_locus_annotations($dbh, $cv_name)
1939 Desc: find all cv_name annotations for loci
1940 Ret: list of LocusDbxref objects
1941 Args: database handle and a cv name
1947 sub get_locus_annotations
{
1952 my $query = "SELECT locus_dbxref_id FROM phenome.locus_dbxref
1953 JOIN public.dbxref USING (dbxref_id)
1954 JOIN public.cvterm USING (dbxref_id)
1955 JOIN public.cv USING (cv_id)
1956 WHERE cv.name = ? AND locus_dbxref.obsolete= 'f' ORDER BY locus_id";
1957 my $sth=$dbh->prepare($query);
1958 $sth->execute($cv_name);
1959 while (my ($locus_dbxref_id) = $sth->fetchrow_array()) {
1960 my $locus_dbxref= CXGN
::Phenome
::LocusDbxref
->new($dbh, $locus_dbxref_id);
1961 push @annotations , $locus_dbxref;
1963 return @annotations;
1966 =head2 get_curated_annotations
1968 Usage: $self->get_curated_annotations($dbh, $cv_name)
1969 Desc: find all cv_name non-electronic annotations for loci
1970 Ret: list of LocusDbxref objects
1971 Args: database handle and a cv name
1977 sub get_curated_annotations
{
1982 my $query = "SELECT locus_dbxref_id , locus_dbxref_evidence.evidence_code_id FROM phenome.locus_dbxref
1983 JOIN public.dbxref USING (dbxref_id)
1984 JOIN public.cvterm USING (dbxref_id)
1985 JOIN public.cv USING (cv_id)
1986 JOIN locus_dbxref_evidence USING (locus_dbxref_id)
1987 WHERE cv.name = ? AND locus_dbxref.obsolete= 'f'
1988 AND locus_dbxref_evidence.evidence_code_id !=(SELECT dbxref_id FROM public.cvterm WHERE name = 'inferred from electronic annotation') ORDER BY locus_id";
1989 my $sth=$dbh->prepare($query);
1990 $sth->execute($cv_name);
1991 while (my ($locus_dbxref_id) = $sth->fetchrow_array()) {
1992 my $locus_dbxref= CXGN
::Phenome
::LocusDbxref
->new($dbh, $locus_dbxref_id);
1993 push @annotations , $locus_dbxref;
1995 return @annotations;
1998 =head2 get_annotations_by_db
2000 Usage: $self->get_annotations_by_db('GO')
2001 Desc: find all locus cvterm annotations for a given db
2002 Ret: an array of locus_dbxref objects
2009 sub get_annotations_by_db
{
2014 my $query = "SELECT locus_dbxref_id FROM phenome.locus_dbxref
2015 JOIN phenome.locus_dbxref_evidence USING (locus_dbxref_id)
2016 JOIN public.dbxref USING (dbxref_id)
2017 JOIN public.db USING (db_id)
2018 JOIN public.cvterm USING (dbxref_id)
2019 WHERE db.name = ? AND locus_dbxref_evidence.obsolete= 'f'";
2020 my $sth=$dbh->prepare($query);
2021 $sth->execute($db_name);
2022 while (my ($locus_dbxref_id) = $sth->fetchrow_array()) {
2023 my $locus_dbxref= CXGN
::Phenome
::LocusDbxref
->new($dbh, $locus_dbxref_id);
2024 push @annotations , $locus_dbxref;
2026 return @annotations;
2033 Usage: $self->merge_locus($merged_locus_id, $sp_person_id)
2034 Desc: merge locus X with this locus. The merged locus will be set to obsolete.
2036 Args: the id of the locus to be merged
2037 Side Effects: all data associated with the merged locus will now be associated with the current locus.
2044 my $merged_locus_id=shift;
2045 my $sp_person_id=shift;
2046 my $m_locus=CXGN
::Phenome
::Locus
->new($self->get_dbh(), $merged_locus_id);
2047 $self->d( "*****locus.pm: calling merge_locus...merging locus " . $m_locus->get_locus_id() . " with locus ". $self->get_locus_id() . " \n");
2049 my @m_owners=$m_locus->get_owners();
2050 foreach my $o (@m_owners) {
2051 my $o_id= $self->add_owner($o, $sp_person_id);
2052 $self->d( "merge_locus is adding owner $o to locus " . $self->get_locus_id() . "\n**") if $o_id;
2054 $self->d( "merge_locus checking for aliases ....\n");
2055 my @m_aliases=$m_locus->get_locus_aliases();
2056 foreach my $alias(@m_aliases) {
2057 $self->add_locus_alias($alias);
2058 $self->d( "merge_locus is adding alias " . $alias->get_locus_alias() . " to locus " . $self->get_locus_id() . "\n**");
2060 my @unigenes=$m_locus->get_unigenes();
2061 foreach my $u(@unigenes) {
2062 my $u_id= $u->get_unigene_id();
2063 $self->add_unigene($u_id, $sp_person_id);
2064 $self->d( "merge_locus is adding unigene $u to locus" . $self->get_locus_id() . "\n**");
2066 my @alleles=$m_locus->get_alleles();
2067 foreach my $allele(@alleles) {
2068 $self->d( "adding allele ........\n");
2069 #reset allele id for storing a new one for the current locus
2070 $allele->set_allele_id(undef);
2071 my $allele_id=$self->add_allele($allele);
2072 $self->d( "merge_locus is adding allele $allele_id " . $allele->get_allele_symbol() . "to locus" . $self->get_locus_id() . "\n**");
2074 #find the stocks of the current allele
2075 my $stock_ids = $allele->get_stock_ids;
2076 #associated stocks with the newly inserted allele
2077 foreach my $stock_id(@
$stock_ids) {
2078 $allele->associate_stock($stock_id, $sp_person_id);
2079 $self->d( "merge_locus is adding allele $allele_id to *stock* $stock_id n**");
2083 my @figures=$m_locus->get_figures();
2084 foreach my $image(@figures) {
2085 $self->add_figure($image->get_image_id(), $sp_person_id);
2086 $self->d( "merge_locus is adding figure" . $image->get_image_id() . " to locus " . $self->get_locus_id() . "\n**");
2089 my @dbxrefs=$m_locus->get_dbxrefs();
2090 foreach my $dbxref(@dbxrefs) {
2091 my $ldbxref=$m_locus->get_locus_dbxref($dbxref); #the old locusDbxref object
2092 my @ld_evs=$ldbxref->get_locus_dbxref_evidence(); #some have evidence codes
2093 my $ldbxref_id=$self->add_locus_dbxref($dbxref, undef, $ldbxref->get_sp_person_id()); #store the new locus_dbxref..
2094 $self->d( "merge_locus is adding dbxref " . $dbxref->get_dbxref_id() . "to locus " . $self->get_locus_id() . "\n");
2095 foreach my $ld_ev ( @ld_evs) {
2096 if ($ld_ev->get_object_dbxref_evidence_id() ) {
2097 $ld_ev->set_object_dbxref_evidence_id(undef);
2098 $ld_ev->set_object_dbxref_id($ldbxref_id);
2099 $ld_ev->store(); #store the new locus_dbxref_evidence
2103 #Add this locus to all the groups of the merged locus
2104 my @groups=$m_locus->get_locusgroups();
2108 if ($groups[0]) { $schema = $groups[0]->get_schema(); }
2109 foreach my $group (@groups) {
2110 my $m_lgm = $group->get_object_row()->
2111 find_related
('locusgroup_members', { locus_id
=> $m_locus->get_locus_id() } );
2112 #see if the locus is already a member of the group
2113 my $existing_member= $group->get_object_row()->
2114 find_related
('locusgroup_members', { locus_id
=> $self->get_locus_id() } );
2115 if (!$existing_member) {
2116 my $lgm=CXGN
::Phenome
::LocusgroupMember
->new($schema);
2117 $lgm->set_locusgroup_id($m_lgm->get_column('locusgroup_id') );
2118 $lgm->set_locus_id($self->get_locus_id() );
2119 $lgm->set_evidence_id($m_lgm->get_column('evidence_id'));
2120 $lgm->set_reference_id($m_lgm->get_column('reference_id'));
2121 $lgm->set_sp_person_id($m_lgm->get_column('sp_person_id'));
2122 $lgm->set_direction($m_lgm->get_column('direction'));
2123 $lgm->set_obsolete($m_lgm->get_column('obsolete'));
2124 $lgm->set_create_date($m_lgm->get_column('create_date'));
2125 $lgm->set_modified_date($m_lgm->get_column('modified_date'));
2126 my $lgm_id= $lgm->store();
2128 $self->d( "obsoleting group member... \n");
2129 $m_lgm->set_column(obsolete
=> 't');
2132 #concatenate description
2133 my $self_description = $self->get_description . "\n" if $self->get_description ;
2134 $self->set_description($self_description . $m_locus->get_description) ;
2135 #update chromosome and arm, but only if null in $self locus
2136 $self->set_linkage_group($m_locus->get_linkage_group) if !$self->get_linkage_group;
2137 $self->set_lg_arm($m_locus->get_lg_arm) if !$self->get_lg_arm;
2138 ##update genome locus identifier
2139 $self->set_genome_locus($m_locus->get_genome_locus) if !$self->get_genome_locus;
2140 #update gene activity
2141 $self->set_gene_activity($m_locus->get_gene_activity) if !$self->get_gene_activity;
2144 $self->d( "Obsoleting merged locus... \n");
2145 #last step is to obsolete the old locus. All associated objects (images, alleles, individuals..) should not display obsolete objects on the relevant pages!
2149 my $error = "Merge locus failed! \n $@\n\nCould not merge locus $merged_locus_id with locus " . $self->get_locus_id() . "\n";
2152 $self->d( "merging locus succeded ! \n");
2157 =head2 get_locus_stats
2159 Usage: CXGN::Phenome::Locus->get_locus_stats($dbh)
2160 Desc: class function. Find the status of the locus database by month.
2161 Ret: List of lists [locus_count], [month/year]]
2169 sub get_locus_stats
{
2172 my $query = "select count (locus_id), date_part('month', create_date) as month , date_part('year', create_date) as year from phenome.locus group by month, year order by year, month asc";
2173 my $sth=$dbh->prepare($query);
2177 while (my ($loci, $month, $year) = $sth->fetchrow_array()) {
2178 $year= substr($year, -2);
2180 push @
{ $stats[0] }, "$month/$year";
2181 push @
{ $stats[1] }, $count;
2186 =head2 get_locusgroups
2188 Usage: $self->get_locusgroups()
2189 Desc: Find all the locus groups this locus is a member of
2190 Ret: a list of CXGN::Phenome::LocusGroup objects (DBIx::Class ojects! )
2192 Side Effects: connects to CXGN::Phenome::Schema
2197 sub get_locusgroups
{
2199 my $locus_id = $self->get_locus_id();
2200 my $schema= CXGN
::Phenome
::Schema
->connect(
2201 sub { $self->get_dbh->clone } ,
2202 { on_connect_do
=> ['set search_path to phenome'] },
2204 my @members= $schema->resultset('LocusgroupMember')->search(
2206 locus_id
=> $locus_id ,
2210 foreach my $member (@members) {
2211 my $group_id = $member->get_column('locusgroup_id');
2212 my $lg= CXGN
::Phenome
::LocusGroup
->new($schema, $group_id);
2218 =head2 count_associated_loci
2220 Usage: $self->count_associated_loci()
2221 Desc: count the number of loci associated with this locus
2229 sub count_associated_loci
{
2231 my $locus_id=$self->get_locus_id();
2233 my @locus_groups= $self->get_locusgroups();
2234 foreach my $group(@locus_groups) {
2235 my @members= $group->get_locusgroup_members();
2236 foreach my $member(@members) {
2237 my $member_locus_id= $member->get_column('locus_id');
2238 if (( $member->obsolete() == 0 ) && ($member_locus_id != $locus_id) ) {
2246 =head2 count_ontology_annotations
2248 Usage: $self->count_ontology_annotations()
2249 Desc: count the number of non-obsolete ontology terms with this locus directly or indirectly via alleles
2257 sub count_ontology_annotations
{
2259 my $locus_id=$self->get_locus_id();
2261 my $query = "SELECT count(distinct(cvterm_id)) FROM public.cvterm
2262 JOIN phenome.locus_dbxref USING (dbxref_id) JOIN phenome.locus_dbxref_evidence USING (locus_dbxref_id)
2263 LEFT JOIN phenome.allele_dbxref USING (dbxref_id)
2264 LEFT JOIN phenome.allele USING (allele_id)
2265 WHERE locus_dbxref.locus_id=? AND locus_dbxref.obsolete='f' AND locus_dbxref_evidence.obsolete='f'
2266 OR allele_dbxref.obsolete = 'f'";
2267 my $sth=$self->get_dbh()->prepare($query);
2268 $sth->execute($locus_id);
2269 my ($count)= $sth->fetchrow_array();
2274 =head2 get_src_feature
2275 Usage: $self->get_src_feature
2276 Desc: find the associated gene feature of this locus
2277 Ret: Bio:;CHado::Schema feature object of type 'gene' and its source feature (should be teh chromosome )
2284 sub get_src_feature
{
2286 my $genome_locus = $self->get_genome_locus;
2287 my ($feature, $src_feature ) ;
2288 print STDERR
"** GENOME LOCUS = $genome_locus\n\n";
2289 if ( defined($genome_locus) ) {
2290 my $dbh = $self->get_dbh;
2291 my $schema= Bio
::Chado
::Schema
->connect( sub { $dbh->clone } ) ;
2292 $feature = $schema->resultset('Sequence::Feature')->search(
2294 'me.name' => { 'ilike' => $genome_locus . '%' } ,
2295 'type.name' => 'gene',
2299 my $featurelocs = $feature ?
$feature->featureloc_features : undef;
2300 $src_feature = $featurelocs ?
$featurelocs->search({locgroup
=> 0,},)->single()->srcfeature() : undef ;
2301 if ( $src_feature) { print STDERR
"*** src_feature = " . $src_feature->name . "\n\n" ; }
2303 return ($feature, $src_feature) ;