5 use CXGN
::Apache
::Error
;
6 use CXGN
::DB
::Connection
;
7 use CXGN
::People
::PageComment
;
10 use CXGN
::Page
::FormattingHelpers
qw(
19 use CXGN
::Page
::Widgets qw
/ collapser /;
20 use CXGN
::Phenome
::Locus
;
21 use CXGN
::Phenome
::Locus
::LinkageGroup
;
23 use CXGN
::Cview
::ChrMarkerImage
;
24 use CXGN
::Cview
::MapFactory
;
26 use CXGN
::Cview
::Marker
::RangeMarker
;
30 use CXGN
::Chado
::Feature
;
31 use CXGN
::Chado
::Publication
;
32 use CXGN
::Chado
::Pubauthor
;
35 use CXGN
::Sunshine
::Browser
;
36 use CXGN
::Tools
::Identifiers qw
/parse_identifier/;
37 use CXGN
::Tools
::List qw
/distinct/;
39 use CXGN
::Phenome
::Locus
::LocusPage
;
43 my $d = CXGN
::Debug
->new();
47 my $page= CXGN
::Page
->new("Locus display", "Naama");
48 my $dbh=$page->get_dbh();
51 $d->d("start time = $time ! \n");
53 my %args = $page->cgi_params();
54 my $locus_id = $args{locus_id
};
56 my $person_id = CXGN
::Login
->new($dbh)->has_session();
57 my $user = CXGN
::People
::Person
->new($dbh, $person_id);
58 my $user_type = $user->get_user_type();
59 my $script = "/phenome/locus_display.pl?locus_id=$locus_id";
61 unless ( ( $locus_id =~ m
/^\d+$/ ) || ($args{action
} eq 'new' && !$locus_id) ) {
62 $c->throw(is_error
=>0,
63 message
=>"No locus exists for identifier $locus_id",
65 $d->d("No locus exists for identifier $locus_id");
68 my $locus= CXGN
::Phenome
::Locus
->new( $dbh, $locus_id );
69 if ( $locus->get_obsolete() eq 't' && $user_type ne 'curator' )
71 $d->d("locus is obsolete!!" );
73 $c->throw(is_error
=>0,
74 title
=> 'Obsolete locus',
75 message
=>"Locus $locus_id is obsolete!",
76 developer_message
=> 'only curators can see obsolete loci',
77 notify
=> 0, #< does not send an error email
79 #$page->message_page("Locus $locus_id is obsolete!");
83 my $locus_name = $locus->get_locus_name();
84 my $organism = $locus->get_common_name();
86 $page->jsan_use("CXGN.Phenome.Tools");
87 $page->jsan_use("CXGN.Phenome.Locus");
88 $page->jsan_use("MochiKit.DOM");
89 $page->jsan_use("Prototype");
90 $page->jsan_use("jQuery");
91 $page->jsan_use("thickbox");
92 $page->jsan_use("MochiKit.Async");
93 $page->jsan_use("CXGN.Sunshine.NetworkBrowser");
94 $page->jsan_use("CXGN.Phenome.Locus.LocusPage");
95 $page->jsan_use("CXGN.Page.Form.JSFormPage");
97 #used to show certain elements to only the proper users
99 my @owners = $locus->get_owners();
101 my $action = $args{action
};
103 if ( !$locus->get_locus_id() && $action ne 'new' && $action ne 'store' ) {
104 $c->throw(is_error
=>0, message
=>'No locus exists for this identifier',);
105 $d->d('No locus exists for this identifier');
106 #$page->message_page("No locus exists for this identifier");
109 $page->header("SGN $organism locus: $locus_name");
111 print page_title_html
("$organism \t'$locus_name'\n");
113 print CXGN
::Phenome
::Locus
::LocusPage
::initialize
($locus_id);
115 $d->d("!!!Printing page title : " . ( time() - $time ) . "\n");
116 ####################################################
117 #get all dbxref annotations: pubmed, ncbi sequences, GO, PO, tgrc link
118 ####################################################
119 my @allele_objs = $locus->get_alleles(); #array of allele objects
120 my ( $tgrc, $pubs, $pub_count, $genbank, $gb_count, $onto_ref ) =
121 get_dbxref_info
($locus, @allele_objs);
123 $d->d( "!!!Got all dbxrefs! : " . ( time() - $time ) . "\n");
125 ##############################
126 #display locus details section
127 #############################
129 my ( $synonyms, $symbol, $symbol_link, $activity, $description, $lg_name,
130 $arm, $locus_details );
132 qq |<a href
="/phenome/editors_note.pl">Note to Editors
</a
>|;
134 qq|<a href
="http://docs.google.com/View?docid=ddhncntn_0cz2wj6">Annotation guidelines
</a
>|;
136 my $locus_html= qq| <table width
="100%"><tr
><td
>|
137 . CXGN
::Phenome
::Locus
::LocusPage
::init_locus_form
($locus_id);
138 #Only show if you are a curator or the object owner and there is no registry already assocaited with the locus
141 $user_type eq 'curator'
142 || grep { /^$person_id$/ } @owners
144 && !( $locus->get_associated_registry() )
147 if ($locus_name) { $locus_html .= associate_registry
($locus, $person_id); }
150 qq |<span
class = "ghosted"> [Associate registry name
]</span
> |;
155 if ( $user_type eq 'curator' ) {
156 $curator_html .= "<br />" . merge_locus
($locus, $person_id);
159 my $locus_synonym_count = scalar( $locus->get_locus_aliases('f', 'f') ) || "";
161 qq { <br
/><br /><b
>Locus synonyms
</b> <b>$locus_synonym_count:</b
> };
163 foreach my $synonym ( $locus->get_locus_aliases('f','f') ) {
164 $locus_html .= $synonym->get_locus_alias() . " ";
169 qq|<a href
="locus_synonym.pl?locus_id=$locus_id&action=new">[Add
/Remove]</a><br
/>|;
171 $locus_html .= "<br />" . $tgrc;
174 $locus_html .= print_locus_editor_info
($locus) . "<br>";
177 if ( $user_type eq 'curator' ) {
178 $curator_html .= assign_owner
($locus);
180 if ( ( !( grep { $_ =~ /^$person_id$/ } @owners ) )
181 && ( $user_type ne 'curator' ) )
185 qq|<a href
="claim_locus_ownership.pl?locus_id=$locus_id&action=confirm"> [Request editor privileges
]</a><br /><br
/>|;
188 my $created_date = $locus->get_create_date();
189 $created_date = substr $created_date, 0, 10;
190 my $modified_date = $locus->get_modification_date() || "";
191 $modified_date = substr $modified_date, 0, 10;
193 my $updated_by = $locus->get_updated_by();
195 CXGN
::People
::Person
->new( $locus->get_dbh(), $updated_by );
196 my $u_first_name = $updated->get_first_name();
197 my $u_last_name = $updated->get_last_name();
198 $locus_html .= qq |Created on
: $created_date |;
199 if ($modified_date) {
201 qq | Last updated on
: $modified_date by
<a href
="/solpeople/personal-info.pl?sp_person_id=$updated_by">$u_first_name $u_last_name</a><br />|;
204 #build a chromosome, map/s and marker/s objects
205 $locus_html .= get_location
($locus);
208 my $name = $locus->get_associated_registry();
210 $locus_html .= "This locus is associated with registry name: $name<br />";
213 ##############history ############
215 if ( $user_type eq 'curator'
216 || grep { /^$person_id$/ } @owners )
218 my $history_data = print_locus_history
($locus) || "";
219 $locus_html .= $history_data;
221 my $locus_xml = $locus_id ?
qq |<a href
= "generic_gene_page.pl?locus_id=$locus_id">Download GMOD XML
</a
>|
222 : qq |<span
class="ghosted">Download GMOD XML
</span
>|;
224 #print locus details section
225 print info_section_html
(
226 title
=> 'Locus details',
227 subtitle
=> $locus_xml . " |" . " "
228 . $editor_note . " " . "|" . " "
230 contents
=> $locus_html,
233 print info_section_html
(
234 title
=> 'Curator tools',
236 contents
=> $curator_html,
241 print STDERR
"!!!Printing locus_details : " . ( time() - $time ) . "\n";
247 my $figure_html = "";
248 my $m_figure_html = "";
249 my $figure_subtitle = "";
256 && ( $user_type eq 'submitter'
257 || $user_type eq 'curator'
258 || $user_type eq 'sequencer' )
261 $figure_subtitle .= associated_figures
($locus, $person_id);
265 qq|<span
class= "ghosted">[Add notes
, figures
or images
]</span
> |;
268 my @figures = $locus->get_figure_ids();
270 if (@figures) { # don't display anything for empty list of figures
271 $figure_html .= qq|<table cellpadding
="5">|;
272 foreach my $figure_id (@figures) {
274 my $figure= SGN
::Image
->new($locus->get_dbh(), $figure_id);
275 my $figure_name = $figure->get_name();
276 my $figure_description = $figure->get_description();
277 my $figure_img = $figure->get_image_url("medium");
278 my $small_image = $figure->get_image_url("thumbnail");
279 my $image_page = "/image/index.pl?image_id=$figure_id";
282 qq|<a href
="$figure_img" title
="<a href=$image_page>Go to image page ($figure_name)</a>" class="thickbox" rel
="gallery-figures"><img src
="$small_image" alt
="$figure_description" /></a
> |;
284 qq|<tr
><td width
=120>|
288 . $figure_description
290 if ( $figures_count < 3 ) { $figure_html .= $fhtml; }
292 push @more_is, $fhtml;
293 } #more than 3 figures- show these in a hidden div
295 $figure_html .= "</table>"; #close the table tag or the first 3 figures
298 "<table cellpadding=5>"; #open table tag for the hidden figures #4 and on
299 my $more = scalar(@more_is);
300 foreach (@more_is) { $m_figure_html .= $_; }
302 $m_figure_html .= "</table>"; #close tabletag for the hidden figures
304 if (@more_is) { #html_optional_show if there are more than 3 figures
305 $more_images = html_optional_show
(
307 "<b>See $more more figures...</b>",
308 qq| $m_figure_html |,
309 0, #< do not show by default
310 'abstract_optional_show', #< don't use the default button-like style
313 print info_section_html
(
314 title
=> "Notes and figures (" . scalar(@figures) . ")",
315 subtitle
=> $figure_subtitle,
316 contents
=> $figure_html . $more_images,
320 print STDERR
"!!!Printing notes and figures : "
321 . ( time() - $time ) . "\n";
323 #################################
324 #display individuals section
325 #################################
326 my $individuals_html = "";
327 my $ind_subtitle = "";
330 && ( $user_type eq 'curator'
331 || $user_type eq 'submitter'
332 || $user_type eq 'sequencer' )
336 qq| <a href
="javascript:Tools.toggleContent('associateIndividualForm', 'locus_accessions')">[Associate accession
]</a
> |;
337 $individuals_html = associate_individual
($locus, $person_id);
341 qq|<span
class= "ghosted">[Associate accession
]</span
> |;
343 my ( $html, $ind_count ) = get_individuals_html
($locus, $user_type);
344 $individuals_html .= $html;
346 print info_section_html
(
347 title
=> "Accessions and images ($ind_count)",
348 subtitle
=> $ind_subtitle,
349 contents
=> $individuals_html,
350 id
=> "locus_accessions",
354 print STDERR
"!!!Printing individuas section : "
355 . ( time() - $time ) . "\n";
357 #################################
358 #display alleles section
359 #################################
361 my $allele_count = scalar(@allele_objs);
363 #map the allele objects to an array ref of the alleles data
369 && ( $user_type eq 'submitter'
370 || $user_type eq 'curator'
371 || $user_type eq 'sequencer' )
375 qq { <a href
="allele.pl?locus_id=$locus_id&action=new">[Add new allele
]</a
>};
379 qq | <span
class="ghosted">[Add new Allele
]</span
> |;
382 foreach my $a (@allele_objs) {
384 my $allele_id = $a->{allele_id
};
387 my @allele_aliases = $a->get_allele_aliases();
388 foreach my $a_synonym (@allele_aliases) {
389 $allele_synonyms .= $a_synonym->get_allele_alias() . " ";
391 if ( !$allele_synonyms ) { $allele_synonyms = "[add new]"; }
392 my $allele_synonym_link =
393 qq |<a href
= "allele_synonym.pl?allele_id=$allele_id&action=new">$allele_synonyms</a
> |;
394 my $allele_edit_link = get_allele_edit_links
($a, $user);
395 my $phenotype = $a->get_allele_phenotype();
396 my @individuals = $a->get_individuals();
397 my $individual_link = "";
398 my $ind_count = scalar(@individuals);
401 qq|<a href
="allele.pl?action=view&allele_id=$allele_id">$ind_count </a
>|;
406 "<i>" . $a->get_allele_symbol . "</i>",
408 $allele_synonym_link,
409 qq|<div align
="left"><a href
="allele.pl?action=view&allele_id=$allele_id"> |
420 $allele_data .= columnar_table_html
(
422 'Allele symbol', 'Allele name',
423 'Synonyms', 'Phenotype',
426 data
=> \
@allele_data,
433 print info_section_html
(
434 title
=> "Known alleles ($allele_count)",
435 subtitle
=> $allele_subtitle,
436 contents
=> $allele_data,
440 print STDERR
"!!!Printing alleles : " . ( time() - $time ) . "\n";
444 ########################### ASSOCIATED LOCI
445 #my @locus_groups= $locus->get_locusgroups();
447 my $al_count = $locus->count_associated_loci();
449 my $associated_locus_sub;
450 my $associate_locus_form;
453 $user_type eq 'curator'
454 || $user_type eq 'submitter'
455 || $user_type eq 'sequencer'
461 $associated_locus_sub .=
462 qq |<a href
="javascript:Tools.toggleContent('associateLocusForm', 'locus2locus');Tools.getOrganisms()">[Associate new locus
]</a
> |;
463 $associate_locus_form =
464 CXGN
::Phenome
::Locus
::LocusPage
::associate_locus_form
($locus_id);
468 $associated_locus_sub .=
469 qq |<span
class ="ghosted"> [Associate new locus
] </span
> |;
472 #printing associated loci section dynamically
473 my $dyn = CXGN
::Phenome
::Locus
::LocusPage
::include_locus_network
();
475 print info_section_html
(
476 title
=> "Associated loci ($al_count) ",
477 subtitle
=> $associated_locus_sub,
478 contents
=> $associate_locus_form . $dyn,
484 $d->d( "!!!Printing locus2locus : " . ( time() - $time ) . "\n");
486 ################## SUNSHINE BROWSER
488 my $locus2locus_graph =
489 CXGN
::Sunshine
::Browser
::include_on_page
( 'locus', $locus_id );
491 my $networkbrowser_link =
492 qq { View
<b
>$locus_name</b> relationships in the stand-alone <a href="/tools
/networkbrowser
/?type
=locus
&name
=$locus_id">network browser</a>. Please note that this tool is a prototype.<br /><br /><br /> };
494 if ( $al_count > 0 ) {
495 print info_section_html(
496 title => "Associated loci
- graphical view
[beta version
]",
497 contents => $networkbrowser_link . $locus2locus_graph,
498 id => 'locus2locus_graph',
504 print info_section_html(
505 title => "Associated loci
- graphical view
",
508 id => 'locus2locus_graph'
514 ##################### UNIGENES AND SOLCYC
516 my @unigenes = $locus->get_unigenes();
519 foreach (@unigenes) {
520 $unigene_count++ if $_->get_status eq 'C';
523 my $dyn_solcyc = CXGN::Phenome::Locus::LocusPage::include_solcyc_links();
525 print info_section_html(
526 title => "SolCyc links
",
527 contents => $dyn_solcyc,
532 $d->d( "!!!Got SolCyc links
: " . ( time() - $time ) . "\n");
534 my $associate_unigene_form;
537 $user_type eq 'curator'
538 || $user_type eq 'submitter'
539 || $user_type eq 'sequencer'
544 $associate_unigene_form= qq|<a href="javascript
:Tools
.toggleContent
('associateUnigeneForm', 'unigenes' )">[Associate new unigene]</a> |;
545 $associate_unigene_form .=
546 CXGN::Phenome::Locus::LocusPage::associate_unigene_form($locus_id);
552 $genbank = qq|<span class=\"ghosted\">none </span>|;
555 qq|<a href="/chado/add_feature
.pl?type
=locus
&
;type_id
=$locus_id&
;refering_page
=$script&
;action
=new
">[Associate new genbank sequence]</a><br />|;
558 #printing associated unigenes section dynamically
559 my $dyn_unigenes = CXGN::Phenome::Locus::LocusPage::include_locus_unigenes();
560 $d->d( "!!!Got unigenes
: " . ( time() - $time ) . "\n");
562 $sequence_links = info_table_html(
563 'SGN Unigenes' => $dyn_unigenes . $associate_unigene_form,
564 'GenBank Accessions' => $genbank,
565 'Genome Matches' => genomic_annots_html($locus),
569 my $seq_count = $gb_count + $unigene_count;
570 print info_section_html(
571 title => "Sequence annotations
($seq_count)",
572 contents => $sequence_links,
577 $d->d("!!!got sequence
: " . ( time() - $time ) . "\n");
579 ##########literature ########################################
580 my ( $pub_links, $pub_subtitle );
582 $pub_links = info_table_html(
590 && ( $user_type eq 'curator'
591 || $user_type eq 'submitter'
592 || $user_type eq 'sequencer' )
596 qq|<a href="/chado/add_publication
.pl?type
=locus
&
;type_id
=$locus_id&
;refering_page
=$script&
;action
=new
"> [Associate publication] </a>|;
600 qq|<span class=\"ghosted\">[Associate publication]</span>|;
603 my $disabled = "true
";
604 if ($person_id) { $disabled = "false
"; }
606 qq | <a href="javascript
:void
(0)"onclick="window
.open('locus_pub_rank.pl?locus_id=$locus_id','publication_list','width=600,height=400,status=1,location=1,scrollbars=1')">[Matching publications]</a> |;
608 $d->d("!!!Printing pub links
: " . ( time() - $time ) . "\n");
610 print info_section_html(
611 title => "Literature annotation
($pub_count)",
612 subtitle => $pub_subtitle,
613 contents => $pub_links,
618 ######################################## Ontology details ##############
620 my $ont_count = $locus->count_ontology_annotations(); #= scalar(@$onto_ref);
622 my $ontology_add_link = "";
623 my $ontology_subtitle;
626 $user_type eq 'curator'
627 || $user_type eq 'submitter'
628 || $user_type eq 'sequencer'
633 $ontology_subtitle .=
634 qq|<a href="javascript
:Tools
.toggleContent
('associateOntologyForm', 'locus_ontology')">[Add ontology annotations]</a> |;
636 CXGN::Phenome::Locus::LocusPage::associate_ontology_form(
642 qq |<span class = "ghosted
"> [Add ontology annotations]</span> |;
645 my $dyn_ontology_info =
646 CXGN::Phenome::Locus::LocusPage::include_locus_ontology();
648 print info_section_html(
649 title => "Ontology annotations
($ont_count)",
650 subtitle => $ontology_subtitle,
651 contents => $ontology_add_link . $dyn_ontology_info,
652 id => "locus_ontology
",
657 $d->d( "!!!Printing ontology links
! : " . ( time() - $time ) . "\n");
659 ####add page comments
661 my $page_comment_obj =
662 CXGN::People::PageComment->new( $locus->get_dbh(), "locus
",
664 print $page_comment_obj->get_html();
671 #########################################################
672 #functions used in the locus page:
682 <b>No locus was specified or this locus ID does not exist</b>
689 sub get_allele_edit_links
{
692 my $login_user_id = $user->get_sp_person_id();
693 my $locus = $allele->get_locus();
694 my $locus_id = $locus->get_locus_id();
696 my $allele_edit_link = "";
698 my $allele_id = $allele->get_allele_id();
699 if ( ( $allele->get_sp_person_id() == $login_user_id )
700 || ( $user->get_user_type() eq 'curator' ) )
703 qq | <a href
="allele.pl?action=edit&allele_id=$allele_id">[Edit
]</a
> |;
705 else { $allele_edit_link = qq | <span
class="ghosted">[Edit
]</span
> |; }
711 my $lg_name = $locus->get_linkage_group();
712 my $arm = $locus->get_lg_arm();
714 my @locus_marker_objs =
715 $locus->get_locus_markers(); #array of locus_marker objects
716 foreach my $lmo (@locus_marker_objs) {
717 my $marker_id = $lmo->get_marker_id(); #{marker_id};
719 CXGN
::Marker
->new( $locus->get_dbh(), $marker_id )
720 ; #a new marker object
722 my $marker_name = $marker->name_that_marker();
723 my $experiments = $marker->current_mapping_experiments();
726 and grep { $_->{location
} } @
{$experiments} )
729 for my $experiment ( @
{$experiments} ) {
730 if ( my $loc = $experiment->{location
} ) {
731 my $map_version_id = $loc->map_version_id();
732 my $lg_name = $loc->lg_name();
734 if ($map_version_id) {
736 CXGN
::Cview
::MapFactory
->new( $locus->get_dbh() );
737 my $map = $map_factory->create(
738 { map_version_id
=> $map_version_id } );
739 my $map_version_id = $map->get_id();
740 my $map_name = $map->get_short_name();
743 CXGN
::Cview
::ChrMarkerImage
->new( "", 100, 150,
744 $locus->get_dbh(), $lg_name, $map, $marker_name );
745 my ( $image_path, $image_url ) =
746 $chromosome->get_image_filename();
748 qq|<img src
="$image_url" usemap
="#map$count" border
="0" alt
="" />|;
750 $chromosome->get_image_map("map$count") . "<br />";
751 $chr_link .= $map_name;
754 $location_html .= "<td>" . $chr_link . "</td>";
761 #draw chromosome with marker-range for loci w/o associated marker, only a chromosome arm annotation
762 if ( scalar(@locus_marker_objs) == 0 && $lg_name ) {
763 my $organism = $locus->get_common_name();
765 'Tomato' => 9, #F2 2000 map
770 my $map_id = $org_hash{$organism};
771 my $map_factory = CXGN
::Cview
::MapFactory
->new( $locus->get_dbh() );
773 my $map = $map_factory->create( { map_id
=> $map_id } );
775 my $map_name = $map->get_short_name();
776 my ( $north, $south, $center ) = $map->get_centromere($lg_name);
779 $dummy_name = "$arm arm" if $arm;
781 CXGN
::Cview
::ChrMarkerImage
->new( "", 150, 150, $locus->get_dbh(),
782 $lg_name, $map, $dummy_name );
784 my ($chr) = $chr_image->get_chromosomes();
786 my $range_marker = CXGN
::Cview
::Marker
::RangeMarker
->new($chr);
788 my ( $offset, $nrange, $srange );
789 if ( $arm eq 'short' ) {
790 $offset = $nrange = $srange = $center / 2;
792 elsif ( $arm eq 'long' ) {
793 my $stelomere = $chr->get_length();
794 $offset = ( $center + $stelomere ) / 2;
795 $nrange = $srange = ( $stelomere - $center ) / 2;
798 $range_marker->set_offset($offset); #center of north/south arm
799 $range_marker->set_north_range($nrange);
800 $range_marker->set_south_range($srange);
801 $range_marker->set_marker_name($dummy_name);
802 if ( !$dummy_name ) { $range_marker->hide_label(); }
804 #$range_marker->show_label();
806 $range_marker->set_label_spacer(20);
808 $range_marker->get_label()->set_name($dummy_name);
809 $range_marker->get_label->set_stacking_level(2);
811 $chr->add_marker($range_marker);
813 my ( $image_path, $image_url ) = $chr_image->get_image_filename();
815 qq|<img src
="$image_url" usemap
="#chr_arm_map" border
="0" alt
="" />|;
816 $chr_link .= $chr_image->get_image_map("chr_arm_map") . "<br />";
817 $chr_link .= $map_name;
819 $location_html .= "<td>" . $chr_link . "</td>";
823 $location_html .= "</td></tr></table>";
824 return $location_html;
827 sub print_locus_history
{
832 my @history_objs = $locus->show_history(); #array of locus_history objects
834 foreach my $h (@history_objs) {
836 my $created_date = $h->get_create_date();
837 $created_date = substr $created_date, 0, 10;
839 my $history_id = $h->{locus_history_id
};
840 my $updated_by_id = $h->{updated_by
};
842 CXGN
::People
::Person
->new( $locus->get_dbh(), $updated_by_id );
843 my $u_first_name = $updated->get_first_name();
844 my $u_last_name = $updated->get_last_name();
846 qq |<a href
="/solpeople/personal-info.pl?sp_person_id=$updated_by_id">$u_first_name $u_last_name</a
> ($created_date)|;
851 $h->get_locus_symbol, $h->get_locus_name,
852 $h->get_gene_activity, $h->get_description,
853 $h->get_linkage_group, $h->get_lg_arm,
861 $history_data .= columnar_table_html
(
863 'Symbol', 'Name', 'Activity', 'Description',
864 'Chromosome', 'Arm', 'Updated by',
871 $print_history = html_optional_show
(
873 'Show locus history',
874 qq|<div
class="minorbox">$history_data</div
> |,
878 return $print_history;
879 } #print_locus_history
881 sub get_dbxref_info
{
883 my $locus_name = $locus->get_locus_name();
884 my %dbs = $locus->get_dbxref_lists()
885 ; #hash of arrays. keys=dbname values= dbxref objects
886 my (@alleles) = @_; #$locus->get_alleles();
887 #add the allele dbxrefs to the locus dbxrefs hash...
888 #This way the alleles associated publications and sequences are also printed on the locus page
889 #it might be a good idea to pring a link to the allele next to each allele-derived annotation
891 foreach my $a (@alleles) {
892 my %a_dbs = $a->get_dbxref_lists();
894 foreach my $a_db_name ( keys %a_dbs )
895 { #add allele_dbxrefs to the locus_dbxrefs list
897 ; #hash for assisting filtering of duplicated dbxrefs (from allele annotation)
898 foreach ( @
{ $dbs{$a_db_name} } ) {
899 $seen{ $_->[0]->get_accession() }++;
900 } #populate with the locus_dbxrefs
901 foreach ( @
{ $a_dbs{$a_db_name} } ) { #and filter duplicates
902 push @
{ $dbs{$a_db_name} }, $_
903 unless $seen{ $_->[0]->get_accession() }++;
907 my ( $tgrc, $pubs, $genbank );
909 foreach ( @
{ $dbs{'tgrc'} } ) {
910 if ( $_->[1] eq '0' ) {
911 my $url = $_->[0]->get_urlprefix() . $_->[0]->get_url();
912 my $accession = $_->[0]->get_accession();
914 qq|$locus_name is a
<a href
="$url$accession" target
="blank">TGRC gene
</a><br />|;
919 foreach ( @
{ $dbs{'PMID'} } ) {
920 if ( $_->[1] eq '0' ) { #if the pub is not obsolete
921 $pubs .= get_pub_info
( $_->[0], 'PMID', $abs_count++ );
924 foreach ( @
{ $dbs{'SGN_ref'} } ) {
925 $pubs .= get_pub_info
( $_->[0], 'SGN_ref', $abs_count++ )
930 foreach ( @
{ $dbs{'DB:GenBank_GI'} } ) {
931 if ( $_->[1] eq '0' ) {
933 my $url = $_->[0]->get_urlprefix() . $_->[0]->get_url();
935 $locus->CXGN::Chado
::Feature
::get_feature_name_by_gi
(
936 $_->[0]->get_accession() );
937 my $description = $_->[0]->get_description();
939 qq|<a href
="$url$gb_accession" target
="blank">$gb_accession</a> $description<br />|;
944 # foreach ( @{$dbs{'GO'}}) { push @ont_annot, $_; }
945 # foreach ( @{$dbs{'PO'}}) { push @ont_annot, $_; }
946 # foreach ( @{$dbs{'SP'}}) { push @ont_annot, $_; }
948 return ( $tgrc, $pubs, $abs_count, $genbank, $gb_count, \
@ont_annot );
951 ########################
955 my $abs_count = shift;
956 my $abstract = encode_entities
($pub->get_abstract() );
957 my $authors = encode_entities
($pub->get_authors_as_string() );
958 my $journal = $pub->get_series_name();
959 my $pyear = $pub->get_pyear();
960 my $volume = $pub->get_volume();
961 my $issue = $pub->get_issue();
962 my $pages = $pub->get_pages();
963 my $abstract_view = html_optional_show
(
964 "abstracts$abs_count",
965 'Show/hide abstract',
966 qq|$abstract <b
> <i
>$authors.</i> $journal. $pyear. $volume($issue). $pages.</b
>|,
967 0, #< do not show by default
968 'abstract_optional_show', #< don't use the default button-like style
970 return $abstract_view;
974 my ( $dbxref, $db, $count ) = @_;
976 my $accession = $dbxref->get_accession();
977 my $pub_title = $dbxref->get_publication()->get_title();
978 my $year= $dbxref->get_publication()->get_pyear();
979 my $pub_id = $dbxref->get_publication()->get_pub_id();
981 abstract_view
( $dbxref->get_publication(), $count );
983 qq|<div
><a href
="/chado/publication.pl?pub_id=$pub_id" >$db:$accession</a> $pub_title ($year). $abstract_view </div
> |;
987 sub print_locus_editor_info
{
989 my $html = "Locus editors: ";
990 my @owners = $locus->get_owners();
992 foreach my $id (@owners) {
993 my $person = CXGN
::People
::Person
->new( $locus->get_dbh(), $id );
995 my $first_name = $person->get_first_name();
996 my $last_name = $person->get_last_name();
997 if ($person->get_user_type() eq 'curator' && scalar(@owners) == 1 ) {
998 $html .= '<b>No editor assigned</b>';
1001 qq |<a href
="/solpeople/personal-info.pl?sp_person_id=$id">$first_name $last_name</a
>;|;
1008 sub get_individuals_html
{
1010 my $user_type=shift;
1011 my @individuals = $locus->get_individuals();
1015 ; # hash of image arrays. Keys are individual_ids, values are arrays of image_ids
1020 my $more; #count the number of accessions in the optional_show box
1022 ; # a scalar for checking if there are accessions with images in the optional box
1026 $more_html .= "<table>";
1029 ; # hash of image arrays. Keys are individual ids values are arrays of image ids
1030 foreach my $i (@individuals) {
1031 my $individual_id = $i->get_individual_id();
1032 my $individual_name = $i->get_name();
1033 $individualHash{$individual_id} = $individual_name;
1036 $i->get_images(); #array of all associated image objects
1037 foreach my $image (@images) {
1038 my $image_id = $image->get_image_id();
1040 #my $img_src_tag= $image->get_img_src_tag("thumbnail");
1041 $imageHash{$image_id} = $image;
1042 push @
{ $imageHoA{$individual_id} }, $image_id;
1045 #if there are no associated images with this individual:
1046 if ( !@images ) { push @no_image, $individual_id; }
1050 # Print the whole thing sorted by number of members and name.
1052 my $individual_id ( sort { @
{ $imageHoA{$b} } <=> @
{ $imageHoA{$a} } }
1056 my $individual_name = $individualHash{$individual_id};
1057 my $individual_obsolete_link =
1058 get_individual_obsolete_link
($locus,$individual_id, $user_type);
1060 qq|<a href
="individual.pl?individual_id=$individual_id">$individual_name </a
> |;
1061 if ( $ind_count < 4 )
1062 { #print the first 3 individuals by default. The rest will be hidden
1064 qq|<tr valign
="top"><td
>$link</td> <td> $individual_obsolete_link </td
>|;
1070 qq|<tr
><td
>$link </td><td> $individual_obsolete_link</td
> |;
1073 #print only 5 images, if there are more write the number of total images
1074 my $image_count = ( $#{ $imageHoA{$individual_id} } ); #+1;
1075 if ( $image_count > 4 ) { $image_count = 4; }
1076 for my $i ( 0 .. $image_count ) {
1077 my $image_id = $imageHoA{$individual_id}[$i];
1078 #my $image = $imageHash{$image_id};
1079 my $image = SGN
::Image
->new($locus->get_dbh(), $image_id);
1080 my $small_image = $image->get_image_url("thumbnail");
1081 my $medium_image = $image->get_image_url("medium");
1082 my $image_page = "/image/index.pl?image_id=$image_id";
1084 qq|<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
> |;
1085 if ( $ind_count < 4 ) { $html .= qq|<td
>$thickbox</td
>|; }
1086 else { $more_html .= qq|<td
>$thickbox</td
>|; }
1089 if ( $#{ $imageHoA{$individual_id} } > 4 ) {
1090 my $image_count = ( $#{ $imageHoA{$individual_id} } ) + 1;
1091 $html .= qq|<td
>... (Total
$image_count images
)</td
>|;
1093 if ( $ind_count < 4 ) { $html .= "</tr>"; }
1094 else { $more_html .= "</tr>"; }
1096 $html .= "</table><br />";
1097 $more_html .= "</table><br />";
1099 my $individual_name;
1100 my $no_image_count = 0;
1101 foreach my $individual_id (@no_image) {
1103 my $individual_obsolete_link =
1104 get_individual_obsolete_link
($locus, $individual_id, $user_type);
1105 if ( $no_image_count < 26 ) {
1106 $individual_name = $individualHash{$individual_id};
1108 qq|<a href
="individual.pl?individual_id=$individual_id">$individual_name</a
> 
$individual_obsolete_link |;
1113 qq|<a href
="individual.pl?individual_id=$individual_id">$individual_name</a
> 
$individual_obsolete_link |;
1118 foreach my $individual_id (@no_image) {
1120 my $individual_obsolete_link =
1121 get_individual_obsolete_link
($locus, $individual_id, $user_type);
1122 my $individual_name = $individualHash{$individual_id};
1124 qq|<a href
="individual.pl?individual_id=$individual_id">$individual_name</a
> 
$individual_obsolete_link |;
1130 my ( $more_link, $contents ) = collapser
(
1132 linktext
=> "<b> See $more more accessions </b>",
1134 #hide_state_linktext => $title,
1135 content
=> $more_html,
1137 id
=> "more_individuals_display"
1140 $html .= "$more_link\n$contents";
1142 return ( $html, scalar(@individuals) );
1143 } #get_individuals_html
1145 ############################javascript code
1147 sub associate_registry
{
1149 my $locus_id = $locus->get_locus_id();
1150 my $sp_person_id = shift;
1154 <a href
=javascript
:Locus
.toggleAssociateRegistry
()>[Associate a registry name with this locus
]</a
><br
>
1155 <div id
='associateRegistryForm' style
="display: none">
1156 <div id
='registry_search'>
1161 onkeyup
="Locus.getRegistries(this.value)">
1162 <input type
="button"
1163 id
="associate_registry_button"
1164 value
="associate registry"
1166 onclick
="Locus.associateRegistry('$locus_id','$sp_person_id');this.disabled=false;">
1168 <select id
="registry_select"
1170 name
="registry_select"
1172 onchange
="Locus.updateRegistryInput()">
1176 Click
<a href
=javascript
:Locus
.addRegistryView
()>here
</a
> to add a new registry name to
our database
1179 <div id
="registry_add" style
="display: none">
1180 <b
>Please enter the
values for the new registry name below
(* is required
)</b
><br
><br
>
1181 <table cellspacing
="0" cellpadding
="0">
1182 <tr
><td
>*Registry Symbol
: </td><td width="20"> </td
>
1183 <td
><input type
="text" id
="registry_symbol" onblur
="Locus.enableButton();" onchange
="Locus.enableButton();"></td></tr
>
1184 <tr
><td
>*Registry Name
: </td><td width="20"> </td
>
1185 <td
><input type
="text" id
="registry_name" onblur
="Locus.enableButton();" onchange
="Locus.enableButton();"></td></tr
>
1187 Registry Description
:<br
>
1188 <textarea id
="registry_description" style
="width: 100%"></textarea
><br
>
1189 <input type
="button" disabled
="true" id
="add_registry_button" value
="Add New Registry" onclick
="Locus.addRegistry('$locus_id', '$sp_person_id');this.disabled=true;"><br
>
1190 Click
<a href
=javascript
:Locus
.searchRegistries
()>here
</a
> to go back to the registry search
1200 sub associate_individual
{
1203 my $locus_id = $locus->get_locus_id();
1204 my $sp_person_id = shift;
1206 my $associate_html = qq^
1208 <div id
="associateIndividualForm" style
="display: none">
1213 onkeyup
="Locus.getIndividuals(this.value, '$locus_id');">
1214 <input type
="button"
1215 id
="associate_individual_button"
1216 value
="associate accession"
1218 onclick
="Locus.associateAllele('$sp_person_id');this.disabled=true;">
1219 <select id
="individual_select"
1221 onchange
="Locus.getAlleles('$locus_id')"
1225 <b
>Would you Like to specify an allele?
</b
>
1226 <select id
="allele_select"
1227 style
="width: 100%">
1233 return $associate_html;
1239 my $locus_id = $locus->get_locus_id();
1240 my $object_type = "locus";
1243 <a href
=javascript
:Tools
.toggleAssignFormDisplay
()>[Assign a locus owner
]</a
> Notice
: 'user' account will be updated to
'submitter' <br
>
1244 <div id
='assignOwnerForm' style
="display:none">
1245 <div id
='user_search'>
1246 First name
or last name
:
1250 onkeyup
="Tools.getUsers(this.value)">
1251 <input type
="button"
1252 id
="associate_button"
1253 value
="assign owner"
1255 onclick
="Tools.assignOwner('$locus_id', '$object_type');this.disabled=false;">
1257 <select id
="user_select"
1259 onchange
= "Tools.enableButton('associate_button');"
1271 sub associated_figures
{
1274 my $locus_id = $locus->get_locus_id();
1275 my $sp_person_id = shift;
1277 my $associate_html = qq^
1279 <a href
="/image/add_image.pl?type_id=$locus_id&type=locus&action=new&refering_page=/phenome/locus_display.pl?locus_id=$locus_id">
1280 [Add notes
, figures
or images
]</a></span
>
1283 return $associate_html;
1287 sub get_individual_obsolete_link
{
1289 my $individual_id = shift;
1290 my $user_type = shift;
1291 my $individual_obsolete_link = "";
1292 my $individual_allele_id = $locus->get_individual_allele_id($individual_id);
1293 if ( ( $user_type eq 'submitter' )
1294 || ( $user_type eq 'curator' )
1295 || ( $user_type eq 'sequencer' ) )
1297 $individual_obsolete_link = qq|
1298 <a href
="javascript:Locus.obsoleteIndividualAllele('$individual_allele_id')">[Remove
]</a
>
1300 <div id
='obsoleteIndividualAlleleForm' style
="display: none">
1301 <div id
='individual_allele_id_hidden'>
1302 <input type
="hidden"
1303 value
=$individual_allele_id
1304 id
="$individual_allele_id">
1310 return $individual_obsolete_link;
1315 my $locus_id = $locus->get_locus_id();
1316 my $object_type = "locus";
1317 my $common_name = $locus->get_common_name();
1319 <a href
=javascript
:Tools
.toggleMergeFormDisplay
()>[Merge locus
]</a
> Warning
: Merged locus will be set to obsolete
! Unobsoleting is possible only directly via the database
! <br
>
1320 <div id
='mergeLocusForm' style
="display:none">
1322 <div id
='locus_merge'>
1323 <input type
="hidden"
1331 onkeyup
="Locus.getMergeLocus(this.value, $locus_id)">
1332 <input type
="button"
1333 id
="merge_locus_button"
1336 onclick
="Locus.mergeLocus('$locus_id');this.disabled=false;">
1338 <select id
="locus_list"
1340 onchange
= "Locus.enableMergeButton();"
1351 #returns string html listing of locus sequence matches found in ITAG gbrowse DBs
1352 sub genomic_annots_html
{
1355 my $locus_id = $locus->get_locus_id();
1358 # look up any gbrowse cross-refs for this locus id, if any
1360 $_->xrefs({ -types
=> ['match'],
1361 -attributes
=> { sgn_locus_id
=> $locus_id },
1363 } $c->enabled_feature('gbrowse2');
1365 return '<span class="ghosted">None</span>'
1369 # and now convert each of the matched regions into HTML strings
1371 return join "\n", map _render_genomic_xref
( $_ ), @xrefs;
1374 sub _render_genomic_xref
{
1377 # look up all the matching locus sequence names
1378 my @locus_seqnames =
1382 my $p = parse_identifier
(
1384 'sgn_locus_sequence'
1385 ) or die "cannot parse " . $f->target->seq_id;
1388 @
{$xref->seqfeatures};
1390 my $linked_img = CGI
->a( { href
=> $xref->url },
1391 CGI
->img({ #style => "border: 1px solid #ddd; border-top: 0; padding: 1em 0; margin:0",
1392 style
=> 'border: none',
1393 src
=> $xref->preview_image_url })
1397 my $sequences_matched =
1398 @locus_seqnames > 1 ?
'Sequences matched'
1399 : 'Sequence matched';
1402 '<div style="border: 1px solid #777; padding-bottom: 10px">',
1404 'Annotation Set' => $xref->data_source->description,
1405 'Feature(s) matched' => join( ', ', map $_->display_name || $_->primary_id, @
{$xref->seqfeatures} ),
1406 'Reference Sequence' => $xref->seqfeatures->[0]->seq_id,
1407 $sequences_matched => join( ', ', @locus_seqnames ),
1408 #__tableattrs => qq|summary="" style="margin: 1em auto -1px auto"|,
1412 '<hr style="width: 95%" />',