more tweaking of image loading script.
[phenome.git] / lib / CXGN / Phenome.pm
blobb71ee82d859f193984e984052b3bbab30b98e207
1 package CXGN::Phenome;
2 use strict;
3 use warnings;
5 ####################
7 use base qw/CXGN::Search::DBI::Simple CXGN::Search::WWWSearch/;
9 __PACKAGE__->creates_result('CXGN::Phenome::Result');
10 __PACKAGE__->uses_query('CXGN::Phenome::Query');
12 #####################
14 package CXGN::Phenome::Result;
15 use base qw/CXGN::Search::BasicResult/;
17 #####################
19 package CXGN::Phenome::Query;
20 use CXGN::Page::FormattingHelpers
21 qw(
22 simple_selectbox_html
23 info_table_html
24 hierarchical_selectboxes_html
25 conditional_like_input_html
26 html_optional_show
29 use CXGN::Tools::Organism;
30 use CXGN::Phenome::Locus::LinkageGroup;
31 use base qw/CXGN::Search::DBI::Simple::WWWQuery/;
32 our %pname;
34 sub _cached_dbh() { our $_cached_dbc ||= CXGN::DB::Connection->new }
35 my $phenome = 'phenome';
36 my $sgn = 'sgn';
37 my $sgn_people = 'sgn_people';
38 my $public = 'public';
40 __PACKAGE__->selects_data("$phenome.locus.locus_id", "$phenome.locus.locus_name","$phenome.locus.locus_symbol", "$phenome.allele.allele_name", "$phenome.allele.allele_symbol", "$phenome.allele.allele_synonym", "$phenome.allele.allele_phenotype", "$phenome.locus.obsolete", "$phenome.allele.obsolete", "$phenome.locus.sp_person_id", "$phenome.locus.description", "$phenome.locus.linkage_group", "$phenome.locus.lg_arm", "$sgn.common_name.common_name_id", "$sgn.common_name.common_name");
44 __PACKAGE__->join_root("$phenome.locus");
46 #join locus with allele table. Filter out obsolete alleles and the empty "default" alleles
47 #(each locus should have one row in the allele table as a default space holder. This is important for making locus-stock associations, because these 2 are linked via the stockprop table, so that if we want to link a stock with a locus, without associating with a specific allele, the link will be made to the default allele_id)
48 __PACKAGE__->uses_joinpath('allelepath',
49 [ "$phenome.allele", "$phenome.allele.locus_id=$phenome.locus.locus_id AND $phenome.allele.obsolete=false AND $phenome.allele.is_default=false" ],
52 __PACKAGE__->uses_joinpath('locusaliaspath', [ "$phenome.locus_alias", "$phenome.locus_alias.locus_id=$phenome.locus.locus_id"]);
55 __PACKAGE__->uses_joinpath('locusmarkerpath', [ "$phenome.locus_marker", "$phenome.locus_marker.locus_id=$phenome.locus.locus_id"]);
56 __PACKAGE__->uses_joinpath('locusunigenepath', [ "$phenome.locus_unigene", "$phenome.locus_unigene.locus_id=$phenome.locus.locus_id"]);
57 __PACKAGE__->uses_joinpath('person_path',
58 ["$phenome.locus_owner", "$phenome.locus_owner.locus_id=$phenome.locus.locus_id"],
59 ["$sgn_people.sp_person", "$sgn_people.sp_person.sp_person_id=$phenome.locus_owner.sp_person_id"],
61 __PACKAGE__->uses_joinpath('organism_path', [ "$sgn.common_name", "$sgn.common_name.common_name_id=$phenome.locus.common_name_id"]);
64 __PACKAGE__->uses_joinpath('locusdbxrefpath',
65 [ "$phenome.locus_dbxref", "$phenome.locus_dbxref.locus_id=$phenome.locus.locus_id"],
66 [ "$public.dbxref", "$public.dbxref.dbxref_id=$phenome.locus_dbxref.dbxref_id"],
67 [ "$public.cvterm", "$public.dbxref.dbxref_id=$public.cvterm.dbxref_id"],
68 [ "$public.feature", "$public.dbxref.dbxref_id=$public.feature.dbxref_id"],
69 [ "public.cvtermsynonym", "$public.cvterm.cvterm_id=$public.cvtermsynonym.cvterm_id"],
70 [ "$public.db", "$public.dbxref.db_id=$public.db.db_id"],
74 __PACKAGE__->has_parameter(name => 'locus',
75 columns => "$phenome.locus.locus",
78 __PACKAGE__->has_parameter(name => 'locus_name',
79 columns => "$phenome.locus.locus_name",
82 __PACKAGE__->has_parameter(name => 'locus_alias',
83 columns => "$phenome.locus_alias.alias",
84 group =>1,
87 __PACKAGE__->has_parameter(name => 'locus_alias_obsolete',
88 columns => "$phenome.locus_alias.obsolete",
89 group =>1,
92 __PACKAGE__->has_parameter(name => 'locus_id',
93 columns => "$phenome.locus.locus_id",
97 __PACKAGE__->has_parameter(name => 'locus_symbol',
98 columns => "$phenome.locus.locus_symbol",
101 __PACKAGE__->has_parameter(name => 'allele_id',
102 columns => "$phenome.allele.allele_id",
104 __PACKAGE__->has_parameter(name => 'allele_name',
105 columns => "$phenome.allele.allele_name",
107 __PACKAGE__->has_parameter(name => 'allele_symbol',
108 columns => "$phenome.allele.allele_symbol",
111 __PACKAGE__->has_parameter(name => 'allele_synonym',
112 columns => "$phenome.allele.allele_synonym",
113 sqlexpr => "array_to_string($phenome.allele.allele_synonym, ',')",
116 __PACKAGE__->has_parameter(name => 'phenotype',
117 columns => "$phenome.allele.allele_phenotype",
121 __PACKAGE__->has_parameter(name =>'locus_obsolete',
122 columns=>"$phenome.locus.obsolete",
124 __PACKAGE__->has_parameter(name =>'allele_obsolete',
125 columns=>"$phenome.allele.obsolete",
129 __PACKAGE__->has_parameter(name =>'locus_description',
130 columns=>"$phenome.locus.description",
132 __PACKAGE__->has_parameter(name =>'locus_linkage_group',
133 columns=>"$phenome.locus.linkage_group",
135 __PACKAGE__->has_parameter(name =>'locus_lg_arm',
136 columns=>"$phenome.locus.lg_arm",
138 __PACKAGE__->has_parameter(name =>'common_name',
139 columns=>"$sgn.common_name.common_name",
141 __PACKAGE__->has_parameter(name =>'common_name_id',
142 columns=>"$sgn.common_name.common_name_id",
144 __PACKAGE__->has_parameter(name =>'editor',
145 columns=>["$sgn_people.sp_person.first_name",
146 "$sgn_people.sp_person.last_name",
147 "$sgn_people.sp_person.sp_person_id"],
148 sqlexpr=>"$sgn_people.sp_person.last_name || $sgn_people.sp_person.first_name
149 || $sgn_people.sp_person.sp_person_id",
152 __PACKAGE__->has_parameter(name =>'editor_id',
153 columns=>"$phenome.locus_owner.sp_person_id",
156 __PACKAGE__->has_parameter(name =>'has_sequence',
157 columns=>["$phenome.locus_dbxref.locus_id"],
158 sqlexpr=>"count(distinct $phenome.locus_dbxref.locus_id)",
159 group =>1,
160 aggregate=>1,
164 __PACKAGE__->has_parameter(name =>'has_marker',
165 columns=>["$phenome.locus_marker.locus_id"],
166 sqlexpr=>"count(distinct $phenome.locus_marker.locus_id)",
167 group =>1,
168 aggregate=>1,
171 __PACKAGE__->has_parameter(name =>'has_db_name',
172 columns=>"$public.db.name",
175 __PACKAGE__->has_parameter(name =>'has_annotation',
176 columns=>["$phenome.locus_dbxref.dbxref_id"],
177 sqlexpr=>"count (distinct $phenome.locus_dbxref.locus_id)",
178 group =>1,
179 aggregate=>1,
182 __PACKAGE__->has_parameter(name =>'has_reference',
183 columns=>["$phenome.locus_dbxref.locus_id"],
184 sqlexpr=>"count (distinct $phenome.locus_dbxref.locus_id)",
185 group =>1,
186 aggregate=>1,
189 __PACKAGE__->has_parameter(name =>'cvterm_synonym',
190 columns=>"$public.cvtermsynonym.synonym",
193 __PACKAGE__->has_parameter(name =>'ontology_term',
194 columns=>["$public.dbxref.accession",
195 "$public.cvterm.name"],
196 sqlexpr=>"$public.cvterm.name || $public.dbxref.accession",
197 group => 1,
200 __PACKAGE__->has_parameter(name =>'genbank_accession',
201 columns=>["$public.feature.name",
202 "$public.dbxref.accession"],
203 sqlexpr=>"$public.feature.name || $public.dbxref.accession",
204 group => 1,
208 __PACKAGE__->has_parameter(name =>'default_allele',
209 columns=>"$phenome.allele.is_default",
210 group =>1,
213 __PACKAGE__->has_complex_parameter( name => 'any_name',
214 uses => [qw/locus locus_name locus_symbol locus_alias locus_description allele_symbol allele_name allele_synonym phenotype/],
215 setter => sub {
216 my ($self, @args) = @_;
217 $self->locus(@args);
218 $self->locus_name(@args);
219 $self->locus_symbol(@args);
220 $self->locus_alias(@args);
221 $self->locus_description(@args);
222 $self->allele_symbol(@args);
223 $self->allele_name(@args);
224 $self->allele_synonym(@args);
225 $self->phenotype(@args);
227 $self->compound('&t OR &t OR &t OR &t OR &t OR &t OR &t OR &t OR&t' ,'locus' , 'locus_name', 'locus_symbol', 'locus_alias', 'locus_description', 'allele_symbol','allele_name', 'allele_synonym', 'phenotype');
231 ###### NOW WWW STUFF ###
233 sub request_to_params {
234 my($self, %params) = @_;
236 #sanitize all the parameters
237 foreach my $key (keys %params) {
238 if( $params{$key} ) {
239 $params{$key} =~ s/[;\'\",]//g;
240 $params{$key} =~ s/^\s+//;
241 $params{$key} =~ s/\s+$//;
245 $self->locus_obsolete("='f'");
247 if($params{any_name}) {
248 my $any_name = $params{any_name};
249 if ($any_name =~ m/(^solyc\d\dg\d{6})(\.*)/i ) { $any_name = substr($any_name, 0, 14); } #remove versions from solyc ids
250 $self->conditional_like_from_scalars('any_name',
251 @params{qw/any_name_matchtype/} , $any_name
255 if($params{phenotype}) {
256 $self->phenotype('ILIKE ?',"%$params{phenotype}%");
257 #$self->ind_phenotype('ILIKE ?',"%$params{phenotype}%");
258 #$self->compound('&t OR &t', 'phenotype','ind_phenotype');
261 if($params{common_name}) {
262 $self->common_name('= ?', "$params{common_name}");
265 #if ($params{editor} =~ m/^\d/) {
266 # $self->editor('= ?', "$params{editor}");
267 if ($params{editor}) {
268 $self->editor('ILIKE ?', "%$params{editor}%");
271 if ($params{has_sequence}) {
272 $self->has_sequence('>0');
273 $self->has_db_name("= 'DB:GenBank_GI'");
274 $self->terms_combine_op('AND');
276 if ($params{has_marker}) {
277 $self->has_marker('!=0');
279 if ($params{has_annotation} && !$params{has_reference}) {
280 $self->has_annotation('=1');
281 $self->has_db_name("IN ('GO', 'PO', 'SP')");
282 $self->terms_combine_op('AND');
284 if ($params{has_reference} && !$params{has_annotation}) {
285 $self->has_reference('=1');
286 $self->has_db_name("= 'PMID'");
287 $self->terms_combine_op('AND');
289 if ($params{locus_linkage_group}) {
290 $self->locus_linkage_group('= ?', "$params{locus_linkage_group}");
293 if ($params{ontology_term}) {
294 if ($params{ontology_term} =~m /(..)(:)(\d+)/i) { #PO: | GO: | SP:
295 $self->has_db_name('ILIKE ?', "$1");
296 $self->ontology_term('ILIKE ?', "%$3%");
297 $self->terms_combine_op('AND');
299 }else {
300 $self->has_db_name("IN ('GO', 'PO', 'SP')");
301 $self->cvterm_synonym('ILIKE ?', "%$params{ontology_term}%");
302 $self->ontology_term('ILIKE ?', "%$params{ontology_term}%");
303 $self->compound('&t AND (&t OR &t)','has_db_name','ontology_term', 'cvterm_synonym');
307 if ($params{genbank_accession}) {
308 $self->genbank_accession('ILIKE ?', "%$params{genbank_accession}%");
311 #page number
312 if( defined($params{page}) ) {
313 $self->page($params{page});
317 sub _to_scalars {
318 my $self= shift;
319 my $search= shift;
320 my %params;
322 no warnings 'uninitialized';
324 #this part defines the mapping from get/post data to search params
325 @params{qw/any_name_matchtype any_name/} = $self->conditional_like_to_scalars('any_name');
328 ($params{phenotype}) = $self->param_bindvalues('phenotype');
329 $params{phenotype} =~ s/%//g;
331 ($params{allele_obsolete}) = $self->param_bindvalues('allele_obsolete');
332 $params{allele_obsolete} =~ s/%//g;
334 ($params{common_name}) = $self->param_bindvalues('common_name');
335 ($params{common_name_id}) = $self->param_bindvalues('common_name_id');
337 ($params{editor}) = $self->param_bindvalues('editor');
338 $params{editor} =~ s/%//g;
341 $params{has_sequence} = $self->pattern_match_parameter('has_sequence', qr/>\s*0/);
342 $params{has_marker} = $self->pattern_match_parameter('has_marker', qr/!=\s*0/);
344 $params{has_annotation} = $self->pattern_match_parameter('has_annotation', qr/!=\=1/);
345 $params{has_annotation} = $self->pattern_match_parameter('has_db_name', qr/PO|GO|SP/);
347 $params{has_reference} = $self->pattern_match_parameter('has_reference', qr/=1/);
348 $params{has_reference} = $self->pattern_match_parameter('has_db_name', qr/PMID/);
350 ($params{locus_linkage_group}) = $self->param_bindvalues('locus_linkage_group');
352 ($params{ontology_term}) = $self->param_bindvalues('ontology_term');
353 $params{ontology_term} =~ s/%//g;
354 ($params{has_db_name}) = $self->param_bindvalues('has_db_name');
356 if ( $params{has_db_name} ) {
357 $params{ontology_term} = $params{has_db_name} . ":" . $params{ontology_term};
360 ($params{genbank_accession}) = $self->param_bindvalues('genbank_accession');
361 $params{genbank_accession} =~ s/%//g;
364 return %params;
367 sub to_html {
368 my $self = shift;
369 my $search = 'advanced';
370 my %scalars = $self->_to_scalars($search);
372 #make %pname, a tied hash that uniqifies names the make_pname
373 # function is in CXGN::Page::WebForm, which is a parent of
374 # CXGN::Search::DBI::Simple::WWWQuery
375 $self->make_pname;
376 our %pname;
378 my $any_name_select = conditional_like_input_html($pname{any_name}, $scalars{any_name_matchtype}, $scalars{any_name}, '30');
380 my $dbh=_cached_dbh();
381 my ($organism_names_ref, $organism_ids_ref) = CXGN::Tools::Organism::get_existing_organisms($dbh);
382 #add an empty entry to the front of the list
383 unshift @$organism_names_ref, '';
385 my $organism = simple_selectbox_html( choices => $organism_names_ref,
386 name => $pname{common_name},
387 selected => $scalars{common_name},
390 my ($lg_names_ref) = CXGN::Phenome::Locus::LinkageGroup::get_all_lgs($dbh);
391 my @lg_options = ();
393 for(my $i = 0; $i < scalar(@$lg_names_ref); $i++) {
394 push @lg_options, [$lg_names_ref->[$i], $lg_names_ref->[$i]];
397 my $linkage_group_select = simple_selectbox_html( choices => \@lg_options,
398 name => $pname{locus_linkage_group},
399 selected => $scalars{locus_linkage_group},
402 my $has_sequence= $self->uniqify_name('has_sequence');
403 my $has_marker = $self->uniqify_name('has_marker');
404 my $has_annotation= $self->uniqify_name('has_annotation');
405 my $has_reference= $self->uniqify_name('has_reference');
406 my $ontology_term = $self->uniqify_name('ontology_term');
407 my $genbank_accession = $self->uniqify_name('genbank_accession');
409 #check boxes
410 @scalars{qw/has_sequence has_marker has_annotation has_reference/} =
411 map {$_ ? 'checked="checked" ' : undef} @scalars{qw/has_sequence has_marker has_annotation has_reference/};
413 my $show_advanced_search =
414 grep {defined($_)} @scalars{qw/ common_name phenotype editor has_sequence
415 locus_linkage_group has_marker
416 has_annotation has_reference
417 ontology_term genbank_accession
419 no warnings 'uninitialized';
421 my $advanced_search=
422 html_optional_show('advanced_search',
423 'Advanced search options',
424 qq|<div class="minorbox">\n|
425 .info_table_html(
426 'Organism' => $organism,
427 'Chromosome / Linkage&nbsp;Group' => $linkage_group_select,
428 'Locus editor' =>qq|<input name="$pname{editor}" value="$scalars{editor}" size="20"/>|,
429 'Show only genes with' => <<EOH,
430 <input type="checkbox" name="$has_sequence" $scalars{has_sequence} />sequence <br />
431 <input type="checkbox" name="$has_marker" $scalars{has_marker} />markers<br />
432 <input type="checkbox" name="$has_annotation" $scalars{has_annotation} />GO/PO annotation<br />
434 'Phenotype' => qq|<input name="$pname{phenotype}" value="$scalars{phenotype}" size="30" /><a href="direct_search.pl?search=phenotypes"> [Advanced SGN phenotype search]</a>|,
435 'Ontology term' => qq|<input name="$ontology_term" value = "$scalars{ontology_term}" />
436 <br /><span class="ghosted">(Term name or ID: e.g. 'carotenoid' or 'PO:0007010')</span>|,
437 'Genbank ID' =>qq|<input name="$genbank_accession" value="$scalars{genbank_accession}"
438 <br /><span class="ghosted">(Accession or GI: e.g. 'EF091820' or '118185006')</span>|,
439 #'Associated publication' => "pubmedID insert text area/check box",
440 __border =>0,
441 __multicol =>2,
442 __tableattrs => 'width="100%"',
443 ) .qq|</div>|,
444 $show_advanced_search);
446 my $html_ret = <<EOHTML;
448 <table><tr>
449 <td colspan="2"><b>Search for any locus or allele</b> (<a href="../help/gene_search_help.pl">gene search help page</a>)</td></tr>
450 <tr><td>$any_name_select</td>
451 <td><a href="../phenome/locus_display.pl?action=new">[Submit new locus]</a></td>
452 </tr></table>
453 <br />
454 $advanced_search
455 <div align="center"><input type="submit" value="Search"/></div>
456 EOHTML
459 sub quick_search {
460 my ($self,$term) = @_;
461 $self->any_name('ILIKE ?', "%$term%");
462 $self->locus_obsolete('=?', "f");
463 #$self->allele_obsolete('=?', "f");
464 return $self;
468 1;#do not remove