function for finding the feature object based on the genome locus name #142
[phenome.git] / lib / CXGN / Phenome / Locus.pm
blob454419d45ed7f0e14e771dddc26d37dc8170ad08
1 package CXGN::Phenome::Locus;
3 =head1 NAME
5 CXGN::Phenome::Locus
7 SGN Locus object
10 =head1 SYNOPSIS
12 Access the phenome.locus table, find, add, and delete associated data
13 (images, alleles, dbxrefs, owners, cvterms, publications, etc.)
15 =head1 AUTHOR
17 Naama Menda <nm249@cornell.edu>
19 =cut
21 use strict;
22 use warnings;
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;
34 use CXGN::DB::Object;
35 use CXGN::Chado::Dbxref;
36 use CXGN::Image;
37 use Bio::Chado::Schema;
39 use base qw / CXGN::DB::ModifiableI CXGN::Phenome::Locus::LocusRanking /;
41 =head2 new
43 Usage: my $gene = CXGN::Phenome::Locus->new($dbh,$locus_id);
44 Desc:
45 Ret:
46 Args: $gene_id
47 Side Effects:
48 Example:
50 =cut
52 sub new {
53 my $class = shift;
54 my $dbh = shift;
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);
64 if ($id) {
65 $self->fetch($id); #get the locus details
67 #associated markers
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=?");
75 my @locus_marker;
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);
85 #dbxrefs
86 my @dbxrefs= $self->get_dbxrefs();
87 foreach my $d(@dbxrefs) { $self->add_dbxref(); }
89 return $self;
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
96 Ret: a locus object
97 Args: dbh, symbol, and common_name
98 Side Effects:
99 Example:
101 =cut
103 sub new_with_symbol_and_species {
104 my $class = shift;
105 my $dbh = shift;
106 my $symbol = shift;
107 my $species = shift;
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
119 Ret: a locus object
120 Args: dbh, locus genome identifier (e.g. Solyc01g0000010)
121 Side Effects:
122 Example:
123 =cut
125 sub new_with_locusname {
126 my $class = shift;
127 my $dbh = shift;
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
148 Example:
150 =cut
152 sub get_locus_ids_by_editor {
153 my $dbh = shift;
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);
159 my @loci = ();
160 while (my($locus_id) = $sth->fetchrow_array()) {
161 push @loci, $locus_id;
163 return @loci;
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
174 Example:
176 =cut
178 sub get_locus_ids_by_annotator {
179 my $dbh = shift;
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);
203 my @loci = ();
204 while (my($locus_id, $modified_date) = $sth->fetchrow_array()) {
205 push @loci, $locus_id;
207 return @loci;
212 sub fetch {
213 my $self=shift;
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
216 FROM phenome.locus
217 JOIN sgn.common_name USING(common_name_id)
218 WHERE locus_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
247 Args:
248 Side Effects: none
249 Example:
251 =cut
254 sub exists_in_database {
255 my $self = shift;
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
266 FROM phenome.locus
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
273 FROM phenome.locus
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) ) {
281 my $message = 1;
282 if($name_id){
283 $message = "Existing name $name_id";
285 elsif($symbol_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");
296 return 0;
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");
301 return ( $message );
302 # if the new name or symbol we're trying to update/insert do not exist in the locus table..
303 } else {
304 $self->d("--locus.pm exists_in_database returned 0.......\n");
305 return 0;
310 sub store {
311 my $self = shift;
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();
318 if ($locus_id) {
319 $self->store_history();
321 my $query = "UPDATE phenome.locus SET
322 locus = ?,
323 locus_name = ?,
324 locus_symbol = ?,
325 original_symbol = ?,
326 gene_activity = ?,
327 description= ?,
328 linkage_group= ?,
329 lg_arm = ?,
330 updated_by = ?,
331 modified_date = now(),
332 obsolete=?
333 where locus_id= ?";
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();
345 else {
346 eval {
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');
368 $allele->store();
370 $self->d("***#####Locus.pm store: inserting new locus $locus_id....\n");
373 if ($@) { warn "locus.pm store failed! \n $@ \n" }
374 return $locus_id;
377 =head2 delete
379 Usage: $self->delete()
380 Desc: set the locus to obsolete=t
381 Ret: nothing
382 Args: none
383 Side Effects: sets locus name and symbol to 'ob$locus_id-$locus_name'
384 obsoletes the associated alleles (see Allele.pm: delete() )
385 Example:
386 =cut
388 sub delete {
389 my $self = shift;
390 my ($symbol, $name);
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');
398 $self->store();
399 }else {
400 $self->d("trying to delete a locus that has not yet been stored to db.\n");
404 =head2 remove_allele
406 Usage: $self->remove_allele($allele_id)
407 Desc: set an allele of this locus to obsolete
408 Ret: nothing
409 Args: $allele_id
410 Side Effects: updates the obsolete field in the allele table to 't'
411 Example:
412 =cut
414 sub remove_allele {
415 my $self = shift;
416 my $allele_id = shift;
417 my $query = "UPDATE phenome.allele
418 SET obsolete= 't'
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
428 Ret: nothing
429 Args: $locus_alias_id
430 Side Effects: deletes a row from the locus_alias table
431 Example:
434 =cut
435 sub remove_locus_alias {
436 my $self = shift;
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'
448 Ret: nothing
449 Args: none
450 Side Effects: updating rows in the locus_alias table
451 Example:
453 =cut
455 sub update_locus_alias {
456 my $self=shift;
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');
465 $a->store();
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');
470 $a->store();
477 =head2 get_unigenes
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
486 Side Effects: none
487 Example:
489 =cut
491 sub get_unigenes {
492 my $self=shift;
493 my $opts = shift;
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());
503 my $unigene;
504 my @unigenes=();
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;
510 return @unigenes;
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
521 Args: $unigene_id
522 Side Effects:
523 Example:
525 =cut
527 sub get_locus_unigene_id {
528 my $self=shift;
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;
538 =head2 add_unigene
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
542 Ret: database id
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)
546 Example:
548 =cut
550 sub add_unigene {
551 my $self=shift;
552 my $unigene_id=shift;
553 my $sp_person_id=shift;
554 my $existing_id= $self->get_locus_unigene_id($unigene_id);
556 if ($existing_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);
561 return $existing_id;
562 }else {
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;
568 return $id;
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
584 Ret: nothing
585 Args: locus_unigene_id
586 Side Effects: none
587 Example:
589 =cut
591 sub obsolete_unigene {
592 my $self=shift;
593 my $lu_id= shift;
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
607 Args: none
608 Side Effects: none
609 Example:
611 =cut
614 sub get_associated_loci {
615 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
617 my $self = shift;
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());
621 my @associated_loci;
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
634 Ret:
635 Args:
636 Side Effects:
637 Example:
639 =cut
642 sub get_reciprocal_loci {
643 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
644 my $self = shift;
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());
648 my @reciprocal_loci;
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
664 Args:
665 Side Effects:
666 Example:
668 =cut
670 sub get_subject_locus2locus_objects {
671 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
673 my $self = shift;
674 my @l2l = ();
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);
682 return @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
692 based ones.
693 Ret: a list of CXGN::Phenome::Locus2Locus objects
694 Args:
695 Side Effects:
696 Example:
698 =cut
700 sub get_object_locus2locus_objects {
701 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
703 my $self = shift;
704 my @l2l = ();
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);
712 return @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
720 Ret: nothing
721 Args: locus symbol
722 Side Effects:
723 Example:
725 =cut
727 sub add_related_locus {
728 my $self=shift;
729 my $locus=shift;
730 push @{ $self->{related_loci} }, $locus;
734 =head2 accessors available (get/set)
736 locus_id
737 locus_name
738 locus_symbol
739 original_symbol
740 gene_activity
741 description
742 linkage_group
743 lg_arm
744 common_name
745 common_name_id
746 genome_locus
747 =cut
749 sub get_locus_id {
750 my $self=shift;
751 return $self->{locus_id};
755 sub set_locus_id {
756 my $self=shift;
757 $self->{locus_id}=shift;
761 sub get_locus_name {
762 my $self=shift;
763 return $self->{locus_name};
767 sub set_locus_name {
768 my $self=shift;
769 $self->{locus_name}=shift;
772 sub get_locus_symbol {
773 my $self=shift;
774 return $self->{locus_symbol};
778 sub set_locus_symbol {
779 my $self=shift;
780 $self->{locus_symbol}=shift;
784 sub get_original_symbol {
785 my $self=shift;
786 return $self->{original_symbol};
790 sub set_original_symbol {
791 my $self=shift;
792 $self->{original_symbol}=shift;
795 sub get_gene_activity {
796 my $self=shift;
797 return $self->{gene_activity};
801 sub set_gene_activity {
802 my $self=shift;
803 $self->{gene_activity}=shift;
807 sub get_description {
808 my $self=shift;
809 return $self->{description};
813 sub set_description {
814 my $self=shift;
815 $self->{description}=shift;
819 sub get_linkage_group {
820 my $self=shift;
821 return $self->{linkage_group};
825 sub set_linkage_group {
826 my $self=shift;
827 $self->{linkage_group}=shift;
831 sub get_lg_arm {
832 my $self=shift;
833 return $self->{lg_arm};
837 sub set_lg_arm {
838 my $self=shift;
839 $self->{lg_arm}=shift;
843 sub get_common_name {
844 my $self=shift;
845 return $self->{common_name};
849 sub set_common_name {
850 my $self=shift;
851 $self->{common_name}=shift;
855 sub get_common_name_id {
856 my $self=shift;
857 return $self->{common_name_id};
861 sub set_common_name_id {
862 my $self=shift;
863 $self->{common_name_id}=shift;
866 sub get_genome_locus {
867 my $self = shift;
868 return $self->{genome_locus};
871 sub set_genome_locus {
872 my $self = shift;
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
884 Example:
886 =cut
888 sub add_locus_alias {
889 my $self=shift;
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();
899 return $id;
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
909 Side Effects: none
910 Example:
912 =cut
914 sub get_locus_aliases {
915 my $self=shift;
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);
921 my @locus_synonyms;
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;
930 =head2 add_allele
932 Usage: $self->add_allele($allele)
933 Desc: add an allele to the locus
934 Ret: the new allele_id
935 Args: allele object
936 Side Effects: accessed the database, Calls Allele->store().
937 Example:
939 =cut
941 sub add_allele {
942 my $self=shift;
943 my $allele=shift; #allele object
944 $allele->set_locus_id($self->get_locus_id() );
945 my $id = $allele->store();
946 return $id;
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
953 Ret: nothing
954 Args: allele symbol
955 Side Effects:
956 Example:
958 =cut
960 sub add_allele_symbol {
961 my $self=shift;
962 my $allele=shift; #allele symbol
963 push @{ $self->{allele_symbols} }, $allele;
966 =head2 get_alleles
968 Usage: my @alleles=$self->get_alleles()
969 Desc: find the alleles associated with the locus
970 Ret: a list of allele objects
971 Args: none
972 Side Effects: none
973 Example:
975 =cut
977 sub get_alleles {
978 my $self=shift;
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);
982 my @alleles=();
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;
988 return @alleles;
990 =head2 get_default_allele
992 Usage: $self->get_default_allele()
993 Desc: find the database id from the default allele
994 Ret: database id
995 Args: none
996 Side Effects: none
997 Example:
999 =cut
1001 sub get_default_allele {
1002 my $self=shift;
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();
1008 return $allele_id;
1011 =head2 add_synonym
1013 Usage:
1014 Desc:
1015 Ret:
1016 Args:
1017 Side Effects:
1018 Example:
1020 =cut
1022 sub add_synonym {
1023 my $self=shift;
1024 my $synonym=shift; #synonym
1025 push @{ $self->{synonyms} }, $synonym;
1029 =head2 add_dbxref
1031 Usage:
1032 Desc:
1033 Ret:
1034 Args:
1035 Side Effects:
1036 Example:
1038 =cut
1041 sub add_dbxref {
1042 my $self=shift;
1043 my $dbxref=shift; #dbxref object
1044 push @{ $self->{dbxrefs} }, $dbxref;
1047 =head2 get_dbxrefs
1049 Usage: $locus->get_dbxrefs();
1050 Desc: get all the dbxrefs associated with a locus
1051 Ret: array of dbxref objects
1052 Args: none
1053 Side Effects: accesses the database
1054 Example:
1056 =cut
1058 sub get_dbxrefs {
1059 my $self=shift;
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);
1064 my $dbxref;
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;
1072 return @dbxrefs;
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
1081 Example:
1083 =cut
1085 sub get_dbxrefs_by_type {
1086 my $self=shift;
1087 my $type = shift;
1088 my $locus_id=$self->get_locus_id();
1089 my $query;
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);
1110 my $dbxref;
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;
1117 return @dbxrefs;
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]
1125 Args: none
1126 Side Effects: none
1127 Example:
1129 =cut
1131 sub get_dbxref_lists {
1132 my $self=shift;
1133 my %dbxrefs;
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] ;
1142 return %dbxrefs;
1145 =head2 get_all_dbxrefs
1147 Usage:
1148 Desc:
1149 Ret:
1150 Args:
1151 Side Effects:
1152 Example:
1154 =cut
1156 sub get_all_dbxrefs {
1157 my $locus = shift;
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() }++;
1180 return %dbs;
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
1190 Args: none
1191 Side Effects: none
1192 Example:
1194 =cut
1196 sub get_locus_dbxrefs {
1197 my $self=shift;
1198 my %lds;
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) ;
1207 return %lds;
1211 =head2 add_locus_marker
1213 Usage:
1214 Desc:
1215 Ret:
1216 Args:
1217 Side Effects:
1218 Example:
1220 =cut
1222 sub add_locus_marker {
1223 my $self=shift;
1224 push @{ $self->{locus_markers} }, shift;
1227 =head2 get_locus_markers
1229 Usage:
1230 Desc:
1231 Ret:
1232 Args:
1233 Side Effects:
1234 Example:
1236 =cut
1238 sub get_locus_markers {
1239 my $self=shift;
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
1248 its dbxref object
1249 Ret: a LocusDbxref object
1250 Args: dbxref object
1251 Side Effects: accesses the database
1252 Example:
1254 =cut
1256 sub get_locus_dbxref {
1257 my $self=shift;
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,
1271 $locus_dbxref_id,
1272 $sp_person_id);
1273 Desc: adds a locus_dbxref relationship
1274 Ret: database id
1275 Args:
1276 Side Effects: calls store function in LocusDbxref
1277 Example:
1279 =cut
1281 sub add_locus_dbxref {
1282 my $self=shift;
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();
1294 return $id;
1297 =head2 function get_individuals
1299 Synopsis: DEPRECATED. Use get_stock_ids
1300 my @individuals=$locus->get_individuals();
1301 Arguments: none
1302 Returns:
1303 Side effects:
1304 Description:
1306 =cut
1308 sub get_individuals {
1309 my $self = shift;
1310 warn "DEPRECATED. Use get_stocks.";
1311 $self->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
1319 Args: none
1320 Side Effects: none
1321 Example:
1323 =cut
1325 sub get_stock_ids {
1326 my $self = shift;
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
1331 ( $query,
1332 undef,
1333 $self->get_locus_id,
1334 'false'
1336 return $ids;
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?
1345 Args: none
1346 Side Effects:
1347 Example:
1349 =cut
1351 sub get_locus_registry_symbol {
1352 my $self=shift;
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();
1358 if ($registry_id) {
1359 my $registry= CXGN::Phenome::Registry->new($self->get_dbh(), $registry_id);
1360 return $registry;
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
1371 Ret:
1372 Args: none
1373 Side Effects:
1374 Example:
1376 =cut
1378 sub store_history {
1380 my $self=shift;
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() );
1392 =head2 show_history
1394 Usage: $locus->show_history();
1395 Desc: Selects the data from locus_history table for a locus object
1396 Ret:
1397 Args:
1398 Side Effects:
1399 Example:
1401 =cut
1403 sub show_history {
1404 my $self=shift;
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=?");
1407 my @history;
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;
1413 return @history;
1416 =head2 get_associated_registry
1418 Usage:
1419 Desc:
1420 Ret: the Registry symbol
1421 Args:
1422 Side Effects:
1423 Example:
1425 =cut
1427 sub get_associated_registry{
1428 my $self=shift;
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();
1433 return $name;
1436 =head2 associated_publication
1438 Usage: my $associated= $locus->associated_publication($accession)
1439 Desc: checks if a publication is already associated with the locus
1440 Ret: a dbxref_id
1441 Args: publication accession (pubmed ID)
1442 Side Effects:
1443 Example:
1445 =cut
1447 sub associated_publication {
1449 my $self=shift;
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
1463 Side Effects:
1464 Example:
1466 =cut
1468 sub get_recent_annotated_loci {
1470 my $dbh=shift;
1471 my $date= shift;
1472 my %edits={};
1474 ####
1475 #get all created and modified loci
1476 ####
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
1487 ####
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
1498 ####
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;
1509 ####
1510 #get all locus_dbxrefs
1511 ####
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
1525 ####
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
1541 ####
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
1553 ####
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;
1581 return %edits;
1585 =head2 get_edit
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
1590 Args: locus object
1591 Side Effects:
1592 Example:
1594 =cut
1596 sub get_edits {
1597 my $self= shift;
1598 my %edits={};
1599 my $dbh=$self->get_dbh();
1600 ####
1601 #get all locus edits (LocusHistory objects
1602 ####
1604 push @{ $edits{loci} }, $self->show_history();
1607 #get all created and modified aliases
1608 ####
1609 my $locus_alias_query="SELECT locus_alias_id FROM phenome.locus_alias
1610 WHERE locus_id= ?
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
1619 ####
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;
1630 ####
1631 #get all locus_dbxrefs
1632 ####
1633 my $locus_dbxref_query="SELECT locus_dbxref_id FROM phenome.locus_dbxref
1634 WHERE locus_id = ?
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
1646 ####
1647 my $image_query="SELECT image_id , sp_person_id, create_date, modified_date, obsolete
1648 FROM phenome.locus_image
1649 WHERE locus_id=?
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
1661 ####
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
1668 ####
1669 my $locus_unigene_query="SELECT unigene_id, sp_person_id, create_date, modified_date, obsolete
1670 FROM phenome.locus_unigene
1671 WHERE locus_id = ?
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
1684 WHERE locus_id = ?
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;
1694 return %edits;
1698 =head2 function get_figures
1700 Synopsis: my @figures=$locus->get_figures();
1701 Arguments: none
1702 Returns: list of CXGN::image objects
1703 Side effects:
1704 Description: all images are stored in the locus_image linking table
1706 =cut
1708 sub get_figures {
1709 my $self = shift;
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());
1714 my $image;
1715 my @images = ();
1716 while (my ($image_id) = $sth->fetchrow_array()) {
1717 $image = CXGN::Image->new($self->get_dbh(), $image_id);
1718 push @images, $image;
1720 return @images;
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
1728 Args: none
1729 Side Effects:
1730 Example:
1732 =cut
1734 sub get_figure_ids {
1735 my $self = shift;
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());
1740 my @image_ids = ();
1741 while (my ($image_id) = $sth->fetchrow_array()) {
1742 push @image_ids, $image_id;
1744 return @image_ids;
1749 =head2 add_figure
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
1756 Example:
1758 =cut
1760 sub add_figure {
1761 my $self=shift;
1762 my $image_id=shift;
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");
1768 return $id;
1772 =head2 get_owners
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
1778 Side Effects:
1779 Example:
1781 =cut
1783 sub get_owners {
1784 my $self=shift;
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());
1790 my $person;
1791 my @owners = ();
1792 my @o_objects = ();
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;
1799 return @owners;
1802 =head2 add_owner
1804 Usage: $self->add_owner($owner_id,$sp_person_id)
1805 Desc: assign a locus owner
1806 Ret: database id
1807 Args: owner_id, user_id
1808 Side Effects: insert a new locus_owner
1809 Example:
1811 =cut
1813 sub add_owner {
1814 my $self=shift;
1815 my $owner_id=shift;
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)
1821 VALUES (?,?,?)";
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");
1826 return $id;
1827 }else { return undef; }
1831 =head2 owner_exists
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
1836 Args: $sp_person_id
1837 Side Effects: none
1838 Example:
1840 =cut
1842 sub owner_exists {
1843 my $self=shift;
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
1863 Side Effects:
1864 Example:
1866 =cut
1868 sub get_individual_allele_id {
1869 my $self=shift;
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
1886 Side Effects: none
1887 Example:
1889 =cut
1891 sub get_associated_locus {
1892 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
1894 my $self=shift;
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();
1901 if ($l2l_id) {
1902 my $l2l=CXGN::Phenome::Locus2Locus->new($self->get_dbh(), $l2l_id);
1903 return $l2l;
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
1915 Side Effects: none
1916 Example:
1918 =cut
1920 sub get_reciprocal_locus {
1921 warn("DEPRECATED. SEE get_locusgroups() !!!!!!!\n");
1923 my $self=shift;
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();
1929 if ($l2l_id) {
1930 my $l2l=CXGN::Phenome::Locus2Locus->new($self->get_dbh(), $l2l_id);
1931 return $l2l;
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
1942 Side Effects: none
1943 Example:
1945 =cut
1947 sub get_locus_annotations {
1948 my $self=shift;
1949 my $dbh=shift;
1950 my $cv_name=shift;
1951 my @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
1972 Side Effects: none
1973 Example:
1975 =cut
1977 sub get_curated_annotations {
1978 my $self=shift;
1979 my $dbh=shift;
1980 my $cv_name=shift;
1981 my @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
2003 Args: $db_name
2004 Side Effects: none
2005 Example:
2007 =cut
2009 sub get_annotations_by_db {
2010 my $self=shift;
2011 my $dbh=shift;
2012 my $db_name=shift;
2013 my @annotations;
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;
2031 =head2 merge_locus
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.
2035 Ret: nothing
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.
2038 Example:
2040 =cut
2042 sub merge_locus {
2043 my $self=shift;
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");
2048 eval {
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();
2106 my $schema;
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');
2130 $m_lgm->update();
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;
2143 $self->store();
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!
2146 $m_locus->delete();
2148 if ($@) {
2149 my $error = "Merge locus failed! \n $@\n\nCould not merge locus $merged_locus_id with locus " . $self->get_locus_id() . "\n";
2150 return $error;
2151 } else {
2152 $self->d( "merging locus succeded ! \n");
2153 return undef;
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]]
2162 Args: dbh
2163 Side Effects: none
2164 Example:
2166 =cut
2169 sub get_locus_stats {
2170 my $self=shift;
2171 my $dbh=shift;
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);
2174 $sth->execute();
2175 my @stats;
2176 my $count;
2177 while (my ($loci, $month, $year) = $sth->fetchrow_array()) {
2178 $year= substr($year, -2);
2179 $count +=$loci;
2180 push @{ $stats[0] }, "$month/$year";
2181 push @{ $stats[1] }, $count;
2183 return @stats;
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! )
2191 Args: none
2192 Side Effects: connects to CXGN::Phenome::Schema
2193 Example:
2195 =cut
2197 sub get_locusgroups {
2198 my $self=shift;
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 ,
2207 obsolete => 'f',
2209 my @lgs;
2210 foreach my $member (@members) {
2211 my $group_id = $member->get_column('locusgroup_id');
2212 my $lg= CXGN::Phenome::LocusGroup->new($schema, $group_id);
2213 push @lgs, $lg;
2215 return @lgs;
2218 =head2 count_associated_loci
2220 Usage: $self->count_associated_loci()
2221 Desc: count the number of loci associated with this locus
2222 Ret: an integer
2223 Args: none
2224 Side Effects:
2225 Example:
2227 =cut
2229 sub count_associated_loci {
2230 my $self=shift;
2231 my $locus_id=$self->get_locus_id();
2232 my $count=0;
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) ) {
2239 $count++;
2243 return $count;
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
2250 Ret: an integer
2251 Args: none
2252 Side Effects:
2253 Example:
2255 =cut
2257 sub count_ontology_annotations {
2258 my $self=shift;
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();
2271 return $count;
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 )
2278 Args: none
2279 Side Effects:
2280 Example:
2282 =cut
2284 sub get_src_feature {
2285 my $self = shift ;
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',
2296 } ,
2297 { join => 'type', }
2298 )->single;
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) ;
2306 1;#do not remove