added a comment section..
[sgn.git] / cgi-bin / phenome / individual.pl
blob411104d982d0ae2d05a01bc351232c856b613c68
1 use strict;
3 my $individual_detail_page = CXGN::Phenome::IndividualDetailPage->new();
5 package CXGN::Phenome::IndividualDetailPage;
8 use CXGN::Page;
9 use CXGN::Page::FormattingHelpers qw /info_section_html
10 page_title_html
11 columnar_table_html
12 html_optional_show
13 info_table_html
14 tooltipped_text
15 html_alternate_show
17 use SGN::Image;
18 use CXGN::Phenome::Individual;
19 use CXGN::Phenome::Population;
20 use CXGN::Chado::Publication;
21 use CXGN::People::PageComment;
22 use CXGN::People::Person;
23 use CXGN::Cview::Map_overviews;
24 use CXGN::Contact;
25 use CXGN::Feed;
26 use CXGN::Tools::Organism;
27 use JSAN::ServerSide;
28 use HTML::Entities;
30 use base qw / CXGN::Page::Form::SimpleFormPage /;
32 sub new {
33 my $class = shift;
34 my $self = $class->SUPER::new(@_);
35 $self->set_script_name("individual.pl");
37 return $self;
40 sub define_object {
41 my $self = shift;
43 # call set_object_id, set_object and set_primary_key here
44 # with the appropriate parameters.
46 $self->set_dbh(CXGN::DB::Connection->new('phenome'));
47 my %args = $self->get_args();
48 my $individual_id= $args{individual_id};
49 my $individual_name= $args{individual_name};
50 if ($individual_name && !$individual_id ) {
51 my $individual_by_name = (CXGN::Phenome::Individual->new_with_name($self->get_dbh(), $individual_name))[0];
52 if ($individual_by_name) { $individual_id = $individual_by_name->get_individual_id(); }
55 unless ( ( $individual_id =~ m /^\d+$/ ) || ($args{action} eq 'new' && !$individual_id) )
57 $c->throw(is_error=>0,
58 message=>"No accession exists for identifier $individual_id",
61 my $individual=CXGN::Phenome::Individual->new($self->get_dbh(),$individual_id ) ;
62 $self->set_object_id($individual_id);
63 $self->set_object($individual);
64 $self->set_primary_key("individual_id");
67 if ( $individual->get_obsolete() eq 't' && $self->get_user()->get_user_type() ne 'curator' )
69 $c->throw(is_error=>0,
70 title => 'Obsolete accession',
71 message=>"Accession $individual_id is obsolete!",
72 developer_message => 'only curators can see obsolete accessions',
73 notify => 0, #< does not send an error email
76 my $action= $args{action};
77 if ( !$individual->get_individual_id() && $action ne 'new' ) {
78 $c->throw(is_error=>0, message=>'No accession exists for this identifier',);
81 $self->set_owners($self->get_object()->get_owners());
85 sub delete {
86 my $self = shift;
87 $self->check_modify_privileges();
88 my $individual = $self->get_object();
89 my %args = $self->get_args();
91 eval {
92 $individual->delete();
94 if ($@) {
95 $self->get_page()->message_page("An error occurred during deletion of the accession.");
98 $self->get_page()->header();
100 print qq {
101 The accession has been successfully deleted. };
102 $self->get_page()->footer();
103 exit();
107 sub generate_form {
108 my $self = shift;
110 $self->init_form();
112 my %args = $self->get_args();
114 my $individual = $self->get_object();
115 my $type_id = $args{type_id};
116 my $type=$args{type};
118 #my $individual_id = $self->get_object_id();
119 my $sp_person_id= $individual->get_sp_person_id();
120 my $submitter = CXGN::People::Person->new($self->get_dbh(), $individual->get_sp_person_id());
121 my $submitter_name = $submitter->get_first_name()." ".$submitter->get_last_name();
122 my $submitter_link = qq |<a href="/solpeople/personal-info.pl?sp_person_id=$sp_person_id">$submitter_name </a> |;
123 my $pop_name = $individual->get_population_name();
124 my $pop_id = $individual->get_population_id();
125 my $pop_link = qq |<a href="/phenome/population.pl?population_id=$pop_id">$pop_name </a> |;
126 my $population_names_ref = CXGN::Phenome::Population::get_all_populations($self->get_dbh());
128 my @p_names= map {$_->[1]} (@$population_names_ref);
129 my @p_ids= map {$_->[0]} (@$population_names_ref);
130 my ($organism_names_ref, $organism_ids_ref) = CXGN::Tools::Organism::get_all_organisms($self->get_dbh());
132 my $form = undef;
133 if ($self->get_action()=~/new|edit|store/ ) {
134 $form = CXGN::Page::Form::Editable->new();
136 else {
137 $form = CXGN::Page::Form::Static->new();
140 $form->add_field(
141 display_name=>"Accession",
142 field_name=>"name",
143 length=>15,
144 object=>$individual,
145 getter=>"get_name",
146 setter=>"set_name",
147 validate => 'string',
149 $form->add_textarea(
150 display_name=>"Description",
151 field_name=>"description",
152 object=>$individual,
153 getter=>"get_description", setter=>"set_description",
154 columns => 40,
155 rows =>4,
160 if ($self->get_action=~ /new|store/) {
161 $form->add_select(
162 display_name => "Population",
163 field_name => "population_id",
164 contents =>$individual->get_population_id(),
165 length=> 20,
166 object => $individual,
167 getter => "get_population_id",
168 setter => "set_population_id",
169 select_list_ref => \@p_names,
170 select_id_list_ref=>\@p_ids,
172 $form->add_select(
173 display_name => "Organism",
174 field_name => "common_name_id",
175 contents =>$individual->get_common_name_id(),
176 length=> 20,
177 object => $individual,
178 getter => "get_common_name_id",
179 setter => "set_common_name_id",
180 select_list_ref => $organism_names_ref,
181 select_id_list_ref=> $organism_ids_ref,
183 } else {
184 $form->add_label( display_name=>"Population",
185 field_name=>"population_name",
186 contents=>$pop_link,
188 $form->add_label( display_name=>"Organism",
189 field_name=>"common_name",
190 contents=>$individual->get_common_name(),
194 $form->add_hidden( field_name=>"individual_id", contents=>$args{individual_id});
195 $form->add_hidden( field_name=>"action", contents=>"store" );
196 $form->add_hidden (
197 field_name => "sp_person_id",
198 contents =>$self->get_user()->get_sp_person_id(),
199 object => $individual,
200 setter =>"set_sp_person_id",
203 $form->add_hidden (
204 field_name => "updated_by",
205 contents =>$self->get_user()->get_sp_person_id(),
206 object => $individual,
207 setter =>"set_updated_by",
210 $form->add_hidden( field_name=>"type", contents=>$args{type} );
211 $form->add_hidden( field_name=>"type_id", contents=>$args{type_id} );
213 #$form->add_hidden( field_name=>"locus_id", contents=>$locus_id);
215 $self->set_form($form);
217 if ($self->get_action=~ /view|edit/) {
218 $self->get_form->from_database();
220 $form->add_hidden (
221 field_name => "population_id",
222 contents =>$individual->get_population_id(),
225 $form->add_label( display_name=>"Uploaded by",
226 field_name=>"submitter",
227 contents=>$submitter_link,
230 }elsif ($self->get_action=~ /store/) {
231 $self->get_form->from_request($self->get_args());
232 #if ($type && $type_id) {
233 if ($type eq "locus") { $individual->associate_locus(); }
234 elsif ($type eq "allele") { $individual->associate_allele($type_id, $self->get_user()->get_sp_person_id() ); }
235 my $subject="[New accession details stored] individual $args{individual_id}";
236 my $username= $self->get_user()->get_first_name()." ".$self->get_user()->get_last_name();
237 my $sp_person_id=$self->get_user()->get_sp_person_id();
238 my $usermail=$self->get_user()->get_private_email();
239 my $fdbk_body="$username has submitted data for individual $args{individual_id}\nsp_person_id = $sp_person_id, $usermail";
240 CXGN::Contact::send_email($subject,$fdbk_body, 'sgn-db-curation@sgn.cornell.edu');
241 CXGN::Feed::update_feed($subject,$fdbk_body);
246 sub display_page {
247 my $self = shift;
248 my %args = $self->get_args();
250 my $individual = $self->get_object();
251 my $individual_id = $self->get_object_id();
252 my $individual_name = $individual->get_name();
254 #insert the necessary javascript for the ajax forms in this page
255 #$self->add_javascript();
256 $self->get_page->jsan_use("CXGN.Phenome.Individual");
257 $self->get_page->jsan_use("CXGN.Phenome.Tools");
259 $self->get_page->jsan_use("MochiKit.DOM");
260 $self->get_page->jsan_use("Prototype");
261 $self->get_page->jsan_use("jQuery");
262 $self->get_page->jsan_use("thickbox");
264 my $action = $args{action};
265 if (!$individual_id && $action ne 'new' && $action ne 'store') { $self->get_page->message_page("No accession exists for this identifier"); }
267 #used to show certain elements to only the proper users
268 my $login_user= $self->get_user();
269 my $login_user_id= $login_user->get_sp_person_id();
270 my $login_user_type= $login_user->get_user_type();
272 my $tag_link = qq { <a href="tag.pl?individual_id=$individual_id&amp;action=new">Add tag</a> };
274 $self->get_page()->header("SGN accession name: $individual_name");
276 print page_title_html("SGN accession: $individual_name \n");
278 my $page="../phenome/individual.pl?individual_id=$individual_id";
279 $args{calling_page} = $page;
281 my $individual_html = $self->get_edit_links()."<br />";
283 #print all editable form fields
284 $individual_html .= $self->get_form()->as_table_string();
286 ##############history:
288 my $object_owner = $individual->get_sp_person_id();
289 if ($login_user_type eq 'curator' || $login_user_id == $object_owner) {
291 my $history_data= $self->print_individual_history();
293 $individual_html .= $history_data;
295 ####### print associated loci
296 $individual_html .= qq { <br /><br /><b>Associated loci:</b> };
297 my @loci = $individual->get_loci();
298 foreach my $locus (@loci) {
299 unless ($locus->get_obsolete() eq 't') {
300 my $locus_id = $locus->get_locus_id();
301 my $locus_name = $locus->get_locus_name();
302 $individual_html .=qq{&nbsp<a href ="locus_display.pl?locus_id=$locus_id">$locus_name </a>&nbsp};
305 #######associate locus
306 if ($login_user_type eq 'curator' || $login_user_type eq 'submitter' || $login_user_type eq 'sequencer') {
307 if ($individual_name) { $individual_html .= $self->associate_loci(); }
308 } else { $individual_html .= qq |<span class = "ghosted"> [Associate locus]</span><br /> |; }
311 ####### dbxref data: ontology annotations, publications...:
312 my ($xref_source, $pubs, $pub_count, $genbank, $gb_count, $onto_ref) = $self->get_dbxref_info();
314 $individual_html .= $xref_source;
316 print info_section_html(title => 'Accession details',
317 contents => $individual_html,
319 ##############images:
321 my $image_html;
322 #$image_html .=qq|<table><tr valign="top">|;
323 my @images = $individual->get_image_ids(); #array of associated image objects
324 my $image_count = 0;
326 $image_html .=qq|<table><tr valign="top">|;
328 foreach my $image_id (@images) {
329 $image_count ++;
330 if ($image_count == 8) {
331 $image_html .= qq|</tr><tr valign="top">|;
332 $image_count=1;
334 my $image=SGN::Image->new($individual->get_dbh(), $image_id);
335 my $small_image=$image->get_image_url("thumbnail");
336 my $medium_image=$image->get_image_url("medium");
337 my $image_page= "/image/index.pl?image_id=$image_id";
338 $image_html .=qq|<td><a href="$medium_image" title="<a href=$image_page>Go to image page </a>" class="thickbox" rel="gallery-images"><img src="$small_image" alt="" /></a></td> |;
340 $image_html .= "</tr></table>";
341 #link for adding new images
342 if ($individual_name)
343 { $image_html .=
344 qq|<br /><a href="../image/add_image.pl?type_id=$individual_id&amp;action=new&amp;type=individual&amp;refering_page=$page">[Add new image]</a>|;
348 print info_section_html(title => 'Images',
349 contents => $image_html,
353 ############################### PHENOTYPE DATA
356 my @phenotypes= $individual->get_phenotypes();
357 my $population_obj = $individual->get_population();
358 my @phenotype;
359 my ($data_view, $term_obj, $term_name, $term_id, $min, $max, $ave, $value);
361 foreach my $p (@phenotypes)
364 if (!$population_obj->get_web_uploaded())
366 $term_obj = CXGN::Chado::Cvterm->new( $self->get_dbh(), $p->get_observable_id());
367 $term_name = $term_obj->get_cvterm_name();
368 $term_id = $term_obj->get_cvterm_id();
369 ($min, $max, $ave) = $population_obj->get_pop_data_summary($term_id);
370 $value = $p->get_value();
371 if (!defined($value)) {$value= 'N/A';}
372 elsif ($value == 0) {$value = '0.0';}
375 } else
377 $term_obj = CXGN::Phenome::UserTrait->new($self->get_dbh(), $p->get_observable_id());
378 $term_name = $term_obj->get_name();
379 $term_id = $term_obj->get_user_trait_id();
380 ($min, $max, $ave) = $population_obj->get_pop_data_summary($term_id);
381 $value = $p->get_value();
384 $term_obj = CXGN::Chado::Cvterm::get_cvterm_by_name( $self->get_dbh(), $term_name);
385 my $cvterm_id = $term_obj->get_cvterm_id();
387 if ($cvterm_id)
389 $term_id = $term_obj->get_cvterm_id();
390 if ($term_obj->get_definition() )
392 push @phenotype, [map {$_}
393 ((tooltipped_text(qq|<a href="/chado/cvterm.pl?cvterm_id=$term_id">$term_name</a>|,
394 $term_obj->get_definition() )), $value, $min, $max, $ave) ];
395 }else
397 push @phenotype, [map {$_} qq|<a href="/chado/cvterm.pl?cvterm_id=$term_id">$term_name</a>|,
398 $value, $min, $max, $ave ];
401 else
403 if ($term_obj->get_definition() )
405 push @phenotype, [map {$_}
406 ((tooltipped_text(qq|<a href="/phenome/trait.pl?trait_id=$term_id">$term_name</a>|,
407 $term_obj->get_definition() )), $value, $min, $max, $ave) ];
408 }else {
409 push @phenotype, [map {$_} qq|<a href="/phenome/trait.pl?trait_id=$term_id">$term_name</a>|,
410 $value, $min, $max, $ave ];
415 if (@phenotype) {
416 my $phenotype_data .= columnar_table_html(
417 headings =>
419 'Trait',
420 'Value',
421 'Pop min',
422 'Pop max',
423 'Pop mean',
425 data =>\@phenotype,
426 __alt_freq =>2,
427 __alt_width =>1,
428 __alt_offset =>3,
429 __align =>'l',
432 $data_view = html_optional_show("phenotype",
433 'View/hide phenotype data summary',
434 qq|$phenotype_data|,
435 1, #< show data by default
439 print info_section_html(title => 'Phenotype data',
440 contents => $data_view,
443 ######## map:
445 my $overview = CXGN::Cview::Map_overviews::Individual->new($individual_id);
446 my $map_html;
447 if ($overview) {
448 $overview->render_map();
449 #my ($url, $path) = $overview->get_file_png();
451 $map_html .= $overview->get_image_html();
453 print info_section_html(title => 'Mapping data',
454 contents => $map_html,
457 ######## alleles:
459 my @alleles = $individual->get_alleles(); #array of associated allele objects
460 my @allele_data;
461 my $allele_data;
462 foreach my $allele(@alleles) {
463 my $allele_id= $allele->get_allele_id();
464 my $locus_id = $allele->get_locus_id();
465 my $locus= CXGN::Phenome::Locus->new($self->get_dbh(), $locus_id);
466 my $locus_name= $locus->get_locus_name();
467 my $phenotype = $allele->get_allele_phenotype();
469 push @allele_data, [map {$_} ( qq|<a href= "locus_display.pl?locus_id=$locus_id">$locus_name</a>|,
470 $allele->get_allele_symbol(), qq|<div align="left"><a href= "allele.pl?allele_id=$allele_id">$phenotype</a></div>|,)
474 if (@allele_data) {
475 $allele_data .=columnar_table_html(headings => ['Locus name', 'Allele symbol', 'Phenotype',],
476 data =>\@allele_data,
479 print info_section_html(title =>'Known alleles',
480 contents => $allele_data,
483 ####### Germplasms:
485 my $germplasm_data="";
486 my @germplasms= $individual->get_germplasms(); #array of associated germplasm objects
488 print info_section_html(title =>'Available germplasms',
489 contents => $germplasm_data,
492 ##########literature ########################################
493 my ($pub_links, $pub_subtitle);
494 if ($pubs) {
495 $pub_links = info_table_html( " " =>$pubs,
496 __border => 0,
500 if ($individual_name && ($login_user_type eq 'curator' || $login_user_type eq 'submitter' || $login_user_type eq 'sequencer')) {
501 $pub_subtitle .= qq|<a href="/chado/add_publication.pl?type=individual&amp;type_id=$individual_id&amp;refering_page=$page&amp;action=new"> [Associate publication] </a>|;
502 }else { $pub_subtitle= qq|<span class=\"ghosted\">[Associate publication]</span>|;}
505 print info_section_html(title => "Literature annotation ($pub_count)",
506 subtitle=> $pub_subtitle,
507 contents =>$pub_links,
508 collapsible=>1,
509 collapsed=>1,
513 ######################################## Ontology details ##############
515 my ($ontology_links, $ontology_evidence, $ontology_info);
516 my $onto_hash;
517 #my ($po_str, $po_gro, $sp) ;
518 #my ( @po_str_evidence, @po_gro_evidence, @sp);
520 my @obs_annot;
521 my $ont_count=0 ;
522 my %ont_hash=(); #keys= cvterms, values= hash of arrays (keys= ontology details, values= list of evidences)
523 foreach (@$onto_ref ) { # ([dbxref_object, ind_dbxref_obsolete])
524 my $cv_name= $_->[0]->get_cv_name();
525 my $cvterm_id= $_->[0]->get_cvterm_id();
526 my $cvterm_name= $_->[0]->get_cvterm_name();
527 my $db_name= $_->[0]->get_db_name();
528 my $accession = $_->[0]->get_accession();
529 my $db_accession = $accession;
530 $db_accession= $cvterm_id if $db_name eq 'SP';
531 my $url= $_->[0]->get_urlprefix() . $_->[0]->get_url();
532 my $cvterm_link= qq |<a href="/chado/cvterm.pl?cvterm_id=$cvterm_id" target="blank">$cvterm_name</a>|;
533 my $ind_dbxref= $individual->get_individual_dbxref($_->[0]);
534 my @AoH= $ind_dbxref->evidence_details();
536 for my $href (@AoH) {
537 my $relationship= $href->{relationship};
539 if ($href->{obsolete} eq 't') {
540 push @obs_annot, $href->{relationship}." ".$cvterm_link." (".$href->{ev_code}.")"
541 . $self->unobsolete_ev($href->{dbxref_ev_object});
542 }else {
543 my $ontology_details= $href->{relationship}.qq| $cvterm_link ($db_name:<a href="$url$db_accession" target="blank"> $accession</a>)<br />|;
544 # add an empty row if there is more than 1 evidence code
545 my $ev_string;
546 $ev_string .= "<br /><hr>" if $ont_hash{$cv_name}{$ontology_details};
547 $ev_string .= $href->{ev_code}."<br />". $href->{ev_desc}."<br /><a href=\"". $href->{ev_with_url}. "\">" . $href->{ev_with_acc} . "</a><br /><a href=\"" . $href->{reference_url} ."\">" . $href->{reference_acc} . "</a><br />".$href->{submitter}. $self->get_ev_obs_link($href->{dbxref_ev_object}) ;
548 $ont_hash{$cv_name}{$ontology_details} .= $ev_string ;
553 #now we should have an %ont_hash with all the details we need for printing ...
554 #hash keys are the cv names ..
555 for my $cv_name (sort keys %ont_hash) {
556 my @evidence;
557 #create a string of ontology details from the end level hash keys, which are the values of each cv_name
558 my $cv_ont_details;
559 #and for each ontology annotation create an array ref of evidences
560 for my $ont_detail (sort keys %{ $ont_hash{$cv_name} } ) {
561 $ont_count++;
562 $cv_ont_details .= $ont_detail ;
563 push @evidence, [$ont_detail, $ont_hash{$cv_name}{$ont_detail}];
565 $ontology_links .= info_table_html($cv_name=> $cv_ont_details,
566 __border=>0,
568 my $ev_table= columnar_table_html(data=>\@evidence,__align=>'lll',__alt_freq=>2,__alt_offset => 1);
569 $ontology_evidence .= info_table_html($cv_name=>$ev_table, __border=>0,__tableattrs=>'width="100%"',);
572 #display ontology annotation form
573 my $ontology_add_link;
574 my $ontology_subtitle;
575 if (($login_user_type eq 'curator' || $login_user_type eq 'submitter' || $login_user_type eq 'sequencer') ) {
576 if ($individual_name) {
577 if (@obs_annot) { $ontology_links .=print_obsoleted(@obs_annot) } ;
578 $ontology_subtitle .= qq|<a href="javascript:Tools.toggleContent('associateOntForm', 'individual_ontology')">[Add ontology annotation]</a> |;
579 $ontology_add_link= $self->associate_ontology_term();
581 }else { $ontology_subtitle =qq |<span class = "ghosted"> [Add ontology annotations]</span> |; }
583 $ontology_info .=$ontology_add_link;#the javascript form for adding new annotations
584 if ($ontology_evidence) {
586 $ontology_info .= html_alternate_show('ontology_annotation',
587 'Annotation info',
588 $ontology_links,
589 $ontology_evidence,
591 }else { $ontology_info .= $ontology_links; }
592 print info_section_html(title =>"Ontology annotations ($ont_count)",
593 subtitle=>$ontology_subtitle,
594 contents => $ontology_info,
595 id =>"individual_ontology",
596 collapsible=>1,
599 ###########Page comments############
600 if ($individual_name) {
601 # change sgn_people.forum_topic.page_type and the CHECK constraint!!
602 my $page_comment_obj = CXGN::People::PageComment->new($self->get_dbh(), "individual", $individual_id);
603 print $page_comment_obj->get_html();
605 ######################################3
607 $self->get_page()->footer();
608 exit();
611 sub print_individual_history {
612 my $self=shift;
613 my $individual=$self->get_object();
615 my @history;
616 my $history_data;
617 my $print_history;
618 my @history_objs = $individual->show_history(); #array of individual_history objects
620 foreach my $h (@history_objs) {
622 my $created_date= $h->get_create_date();
623 $created_date = substr $created_date, 0, 10;
625 my $history_id = $h->{individual_history_id};
626 my $updated_by_id= $h->{updated_by};
627 my $updated=CXGN::People::Person->new($self->get_dbh(), $updated_by_id);
628 my $u_first_name = $updated->get_first_name();
629 my $u_last_name = $updated->get_last_name();
630 my $up_person_link =qq |<a href="/solpeople/personal-info.pl?sp_person_id=$updated_by_id">$u_first_name $u_last_name</a> ($created_date)|;
632 push @history, [map {$_} ($h->get_name,$h->get_description,$h->get_population()->get_name(),
633 $up_person_link,)
637 if (@history) {
638 $history_data .= columnar_table_html(headings => ['Name',
639 'Description',
640 'Population',
641 'Updated by',
643 data =>\@history,
644 __alt_freq =>2,
645 __alt_width =>1,
646 __alt_offset =>3,
648 $print_history=
649 html_optional_show('accession_history',
650 'Show accession history',
651 qq|<div class="minorbox">$history_data</div> |,
655 return $print_history;
656 }#print_individual_history
659 # override store to check if a locus with the submitted symbol/name already exists in the database
661 sub store {
662 my $self = shift;
663 my $individual = $self->get_object();
664 my $individual_id = $self->get_object_id();
665 my %args = $self->get_args();
668 my $message = $individual->exists_in_database( $args{name} );
670 if ($message ) {#&& $name_id!= $locus_id && $name_obsolete==0 ) {
671 $self->get_page()->message_page($message);
672 } else {
673 $self->SUPER::store(0);
678 sub get_ev_obs_link {
679 my $self =shift;
680 my $ind=$self->get_object();
681 my $ev_dbxref=shift;
682 my $delete_link = "";
683 my $user_type= $self->get_user->get_user_type();
684 my $logged_user= $self->get_user()->get_sp_person_id();
685 my $ev_dbxref_id= $ev_dbxref->get_object_dbxref_evidence_id();
686 #check obsolete permissions. Granted for
687 #curators, the individual owner(s) and the submitter of the annotation
688 #(in this case we go by the evidence code, since annotations can have multiple evidences)
689 if (($ind->get_sp_person_id == $logged_user) || ($ev_dbxref->get_sp_person_id() == $logged_user) || ($user_type eq 'curator' ) ) {
690 $delete_link=qq|
691 <a href="javascript:Tools.obsoleteAnnotEv('individual', '$ev_dbxref_id')">[delete]</a><br>
693 <div id='obsoleteIndividualOntologyForm' style="display: none">
694 <div id='ev_dbxref_id_hidden'>
695 <input type="hidden"
696 value=$ev_dbxref_id
697 id="$ev_dbxref_id">
698 </div>
699 </div>
704 sub unobsolete_ev {
705 my $self =shift;
706 my $ind=$self->get_object();
707 my $ev_dbxref= shift;
708 my $ev_dbxref_id= $ev_dbxref->get_object_dbxref_evidence_id();
709 my $unobsolete_link = "";
711 if (($self->get_user()->get_user_type() eq 'submitter') || ($self->get_user()->get_user_type() eq 'curator') || ($self->get_user()->get_user_type() eq 'sequencer')) {
712 $unobsolete_link=qq|
713 <a href="javascript:Tools.unobsoleteAnnotEv('individual','$ev_dbxref_id')">[unobsolete]</a>
715 <div id='unobsoleteAnnotationForm' style="display: none">
716 <div id='ev_dbxref_id_hidden'>
717 <input type="hidden"
718 value=$ev_dbxref_id
719 id="$ev_dbxref_id">
720 </div>
721 </div>
724 return $unobsolete_link;
728 ########################
730 sub print_obsoleted {
731 my @ontology_terms=@_;
732 my $obsoleted;
733 foreach my $term (@ontology_terms) {
734 $obsoleted .= qq |$term <br />\n |;
736 my $print_obsoleted=
737 html_optional_show('obsoleted_terms',
738 'Show obsolete',
739 qq|<div class="minorbox">$obsoleted</div> |,
741 return $print_obsoleted;
746 sub get_dbxref_info {
747 my $self=shift;
748 my $ind=$self->get_object();
749 my $ind_name=$ind->get_name();
750 my %dbs = $ind->get_dbxref_lists(); #hash of arrays. keys=dbname values= dbxref objects
751 my ($xref_source, $pubs, $genbank, $onto_ref, $ont_ev,$obs_annot);
752 ##tgrc
753 foreach (@{$dbs{'TGRC_accession'}} ) {
754 if ($_->[1] eq '0') {
755 my $url= $_->[0]->get_urlprefix() . $_->[0]->get_url();
756 my $accession= $_->[0]->get_accession();
757 $xref_source .= qq|$ind_name is a <a href="$url$accession" target="blank">TGRC accession</a><br />|;
760 foreach (@{$dbs{'EUSOL:accession'}} ) {
761 if ($_->[1] eq '0') {
762 my $url= $_->[0]->get_urlprefix() . $_->[0]->get_url();
763 my $accession= $_->[0]->get_accession();
764 $xref_source .= qq|<br />Available at <br /><a href="$url$accession" target="blank"><img src= "/documents/img/eusol_logo_small.jpg" border="0" /></a><br />|;
767 my $abs_count=0;
768 foreach (@{$dbs{'PMID'}} ) {
769 $pubs .= $self->get_pub_info($_->[0],$abs_count++) if $_->[1] eq '0'; }
770 foreach (@ {$dbs{'SGN_ref'}} ) { $pubs .= $self->get_pub_info($_->[0],$abs_count++) if $_->[1] eq '0'; }
771 my @pop_dbxrefs=$ind->get_population()->get_all_population_dbxrefs();
772 foreach (@pop_dbxrefs) {
773 my $db_name = $_->get_db_name();
774 if ($db_name eq 'PMID' || $db_name eq 'SGN_ref' ) {
775 $pubs .= $self->get_pub_info($_, $abs_count++);
778 my $gb_count=0;
779 foreach (@{$dbs{'DB:GenBank_GI'}} ) {
780 if ($_->[1] eq '0') {
781 $gb_count++;
782 my $url= $_->[0]->get_urlprefix() . $_->[0]->get_url();
783 my $gb_accession=$self->CXGN::Chado::Feature::get_feature_name_by_gi($_->[0]->get_accession());
784 my $description=$_->[0]->get_description();
785 $genbank .=qq|<a href="$url$gb_accession" target="blank">$gb_accession</a> $description<br />|;
788 my @ont_annot;
789 foreach ( @{$dbs{'GO'}}) { push @ont_annot, $_; }
790 foreach ( @{$dbs{'PO'}}) { push @ont_annot, $_; }
791 foreach ( @{$dbs{'SP'}}) { push @ont_annot, $_; }
793 return ($xref_source, $pubs, $abs_count, $genbank, $gb_count, \@ont_annot);
796 sub abstract_view {
797 my $self=shift;
798 my $pub=shift;
799 my $abs_count=shift;
800 my $abstract=encode_entities($pub->get_abstract());
801 my $authors=encode_entities($pub->get_authors_as_string() ) ;#self->author_info($pub->get_pub_id());
802 my $journal=$pub->get_series_name() ;
803 my $pyear=$pub->get_pyear();
804 my $volume=$pub->get_volume() ;
805 my $issue=$pub->get_issue();
806 my $pages=$pub->get_pages();
807 my $abstract_view = html_optional_show("abstracts$abs_count",
808 'Show/hide abstract',
809 qq|$abstract <b> <i>$authors.</i> $journal. $pyear. $volume($issue). $pages. </b>|,
810 0, #< do not show by default
811 'abstract_optional_show', #< don't use the default button-like style
813 return $abstract_view;
816 sub get_pub_info {
817 my $self=shift;
818 my ($dbxref, $count)=@_;
819 my $db=$dbxref->get_db_name();
820 my $pub_info;
821 my $accession= $dbxref->get_accession();
822 my $pub_title=$dbxref->get_publication()->get_title();
823 my $pub_id= $dbxref->get_publication()->get_pub_id();
824 my $abstract_view=$self->abstract_view($dbxref->get_publication(), $count);
825 $pub_info = qq|<div><a href="/chado/publication.pl?pub_id=$pub_id" >$db:$accession</a> $pub_title $abstract_view </div> |;
826 return $pub_info;
830 #################################
831 sub associate_loci {
832 my $self=shift;
833 my $individual_id=$self->get_object_id();
834 my $sp_person_id= $self->get_user->get_sp_person_id();
835 my $user_type = $self->get_user->get_user_type();
836 # my $locus_tip= tooltipped_text('Locus name or symbol', 'To filter your locus search by the organism of interest, enter a locus name or symbol followed by comma and the organism name (eg. flower, tomato).');
837 my $associate_html = qq^
838 <br><a href=javascript:Individual.toggleAssociateFormDisplay()>[associate new locus]</a>
839 <div id="associationForm" style="display: none">
841 <input type="text"
842 style="width: 50%"
843 id="locus_name"
844 onkeyup="Tools.getLoci(this.value, '$individual_id');">
845 <select id = "organism_select" onchange="Tools.getLoci( MochiKit.DOM.getElement('locus_name').value, '$individual_id')">
846 <option value="Tomato">tomato</option>
847 <option value="Potato">potato</option>
848 <option value="Pepper">pepper</option>
849 <option value="Eggplant">eggplant</option>
850 <option value="Coffee">coffee</option>
851 </select>
852 <select id="locus_select"
853 style="width: 100%"
854 size=10
855 onchange="Individual.getAlleles(this.value, '$individual_id');MochiKit.DOM.getElement('associate_locus_button').disabled=false;">
856 </select>
857 <span id ="alleleSelect" style="display: none">
858 <b>Would you Like to specify an allele?</b>
859 <select id="allele_select"
860 style="width: 100%">
861 </select>
862 </span>
863 <input type="button"
864 id="associate_locus_button"
865 value="associate locus"
866 disabled="true"
867 onclick="Individual.associateAllele('$sp_person_id', '$individual_id');this.disabled=true;">
868 </div><br><br>^;
870 return $associate_html;
874 sub associate_ontology_term{
875 my $self=shift;
876 my $individual_id=$self->get_object_id();
877 my $sp_person_id= $self->get_user->get_sp_person_id();
879 # <a href=javascript:Tools.toggleAssociateOntology()>[Add ontology annotations]</a><br>
880 my $associate = qq^
881 <div id='associateOntForm' style="display: none">
882 <div id='ontology_search'>
884 Ontology term:
885 <input type="text"
886 style="width: 50%"
887 id="ontology_input"
888 onkeyup="Tools.getOntologies(this.value)">
889 <select id = "cv_select" onchange="Tools.getOntologies(MochiKit.DOM.getElement('ontology_input').value, this.value)">
890 <option value="PO">PO (plant ontology)</option>
891 <option value="SP">SP (Solanaceae phenotypes)</option>
892 </select><br>
894 <select id="ontology_select"
895 style="width: 100%"
896 name="ontology_select"
897 size=10
899 onchange="Tools.getRelationship()">
901 </select>
903 <b>Relationship type:</b>
904 <select id="relationship_select" style="width: 100%"
905 onchange="Tools.getEvidenceCode()">
906 </select>
907 <b>Evidence code:</b>
908 <select id="evidence_code_select" style="width: 100%"
909 onchange="Tools.getEvidenceDescription();Individual.getEvidenceWith('$individual_id');Individual.getReference('$individual_id')">
910 </select>
912 <b>Evidence description:</b>
913 <select id="evidence_description_select" style="width: 100%">
914 </select>
916 <b>Evidence with:</b>
917 <select id="evidence_with_select" style="width: 100%">
918 </select>
920 <b>Reference:</b>
921 <select id="reference_select" style="width: 100%">
922 </select>
924 <input type="button"
925 id="associate_ontology_button"
926 value="associate ontology"
927 disabled="true"
928 onclick="Individual.associateOntology('$individual_id', '$sp_person_id');this.disabled=true;">
929 </div>
930 </div>
932 return $associate;