seedlot upload with accession synonyms. seedlot upload works to update existing seedlots
[sgn.git] / lib / SGN / Controller / AJAX / DeriveTrait.pm
blob5eee39cee9d037063a5452fa98d7ae1b53bf4f0e
1 package SGN::Controller::AJAX::DeriveTrait;
3 use Moose;
4 use Data::Dumper;
5 use List::Util 'max';
6 use Bio::Chado::Schema;
7 use List::Util qw | any sum |;
8 use DBI;
9 use DBIx::Class;
10 use SGN::Model::Cvterm;
11 use JSON;
12 use POSIX;
13 use URI::Encode qw(uri_encode uri_decode);
14 use CXGN::BreedersToolbox::DeriveTrait;
15 use CXGN::Phenotypes::StorePhenotypes;
17 BEGIN {extends 'Catalyst::Controller::REST'}
19 __PACKAGE__->config(
20 default => 'application/json',
21 stash_key => 'rest',
22 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
25 has 'trial_id' => (isa => 'Int',
26 is => 'rw',
27 reader => 'get_trial_id',
28 writer => 'set_trial_id',
32 sub get_all_derived_trait : Path('/ajax/breeders/trial/trait_formula') Args(0) {
33 my $self = shift;
34 my $c = shift;
35 my $schema = $c->dbic_schema('Bio::Chado::Schema');
36 my $dbh = $c->dbc->dbh();
37 my (@cvterm_ids, @derived_traits, @formulas, @derived_traits_array, @trait_ids, @trait_db_ids, @formulas_array, @formulas_array_msg, $formula_json_array);
39 my $h = $dbh->prepare("select cvterm.name, cvterm.cvterm_id, a.value, dbxref.accession, db.name from cvterm join cvtermprop as a using(cvterm_id) join dbxref using(dbxref_id) join db using(db_id) join cvterm as b on (a.type_id=b.cvterm_id) where b.name='formula';");
41 $h->execute();
42 while (my ($cvterm_id, $derived_trait, $derived_trait_formula, $trait_id, $trait_db_id) = $h->fetchrow_array()) {
43 push @cvterm_ids, $cvterm_id;
44 push @derived_traits, $derived_trait;
45 push @formulas, $derived_trait_formula;
46 push @trait_ids, $trait_id;
47 push @trait_db_ids, $trait_db_id;
50 for (my $n=0; $n<scalar(@derived_traits); $n++) {
51 push @formulas_array, $formulas[$n];
52 push @derived_traits_array, $cvterm_ids[$n]."|".$trait_db_ids[$n].":".$trait_ids[$n];
55 #print STDERR Dumper (@formulas_array);
56 $c->stash->{rest} = { derived_traits => \@derived_traits_array, formula => \@formulas_array };
60 sub compute_derive_traits : Path('/ajax/phenotype/create_derived_trait') Args(0) {
62 my $self = shift;
63 my $c = shift;
64 my $trial_id = $c->req->param('trial_id');
65 my $selected_trait = $c->req->param('trait');
66 my %parse_result;
67 my $trait_found;
68 my $time = DateTime->now();
69 my $timestamp = $time->ymd()."_".$time->hms();
71 print "TRAIT NAME: $selected_trait\n";
72 print "TRIAl ID: $trial_id\n";
74 my $schema = $c->dbic_schema("Bio::Chado::Schema");
75 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
76 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
77 my $selected_trait_cvterm = SGN::Model::Cvterm->get_cvterm_row_from_trait_name($schema, $selected_trait);
78 if (!$selected_trait_cvterm) {
79 print STDERR "The trait $selected_trait is not in the database.\n";
82 my $selected_trait_cvterm_id = $selected_trait_cvterm->cvterm_id();
83 print "Selected Trait Cvterm_id: $selected_trait_cvterm_id\n";
85 if (!$c->user()) {
86 print STDERR "User not logged in... not computing trait.\n";
87 $c->stash->{rest} = {error => "You need to be logged in to compute trait." };
88 return;
91 if (!any { $_ eq "curator" || $_ eq "submitter" } ($c->user()->roles) ) {
92 $c->stash->{rest} = {error => "You have insufficient privileges to compute trait." };
93 return;
96 my $trait_id = shift;
97 my $trial = CXGN::Trial->new({ bcs_schema => $schema,
98 trial_id => $trial_id
99 });
101 my $triat_name = $trial->get_traits_assayed();
103 #print STDERR Dumper($triat_name);
106 if (scalar(@{$triat_name}) == 0) {
107 $c->stash->{rest} = {error => "No trait assayed for this trial." };
108 return;
112 foreach $trait_found (@{$triat_name}) {
113 if ($selected_trait_cvterm_id && ($trait_found->[0] eq $selected_trait_cvterm_id)) {
114 print "Trait found = $trait_found->[1] with id $trait_found->[0]\n";
115 $c->stash->{rest} = {error => "$trait_found->[1] has been computed and uploaded for this trial." };
116 return;
119 elsif ($selected_trait_cvterm_id eq '') {
120 $c->stash->{rest} = {error => "Select trait to compute." };
121 return;
125 my $dbh = $c->dbc->dbh();
126 my @plots;
127 my %data;
128 my @traits;
129 my @trait_cvterm_id;
130 my $trait = 0;
131 my $counter_trait = 0;
132 push @traits, $selected_trait;
134 my (@cvterm_ids, @formulas, @regres, $formula_json_array, @formulas_array_msg, $eval_formula, $msg_formula);
136 my $h = $dbh->prepare("select cvterm.cvterm_id, a.value from cvterm join cvtermprop as a using(cvterm_id) join cvterm as b on (a.type_id=b.cvterm_id) where b.name='formula';");
138 $h->execute();
139 while (my ($cvterm_id, $derived_trait_formula ) = $h->fetchrow_array()) {
140 push @cvterm_ids, $cvterm_id;
141 push @formulas, $derived_trait_formula;
145 for (my $n=0; $n<scalar(@formulas); $n++) {
146 if ($selected_trait_cvterm_id eq $cvterm_ids[$n]) {
147 print "formula_msg: $formulas[$n]\n";
148 $msg_formula = $formulas[$n];
153 my @dependent_trait_ids;
154 my ($db_id, $accession, @traits_cvterm_ids, $cvterm_id, @found_trait_cvterm_ids, @accessions, @trait_values);
155 my (%hash1, %hash2, %hash3, @trait_values1, @trait_values2, @trait_values3);
156 while ($msg_formula =~ /(\w{2}\:\d+)/g){
157 push @dependent_trait_ids, [$1];
158 ($db_id,$accession) = split (/:/, $1);
159 push @accessions, $accession;
161 print "DB ID: $db_id\n";
162 #print STDERR Dumper (\@dependent_trait_ids);
163 foreach my $accession (@accessions) {
164 my $h1 = $dbh->prepare("select cvterm.cvterm_id from cvterm join dbxref using(dbxref_id) join db using(db_id) where dbxref.accession=? and db.name=?;");
166 $h1->execute($accession, $db_id);
167 while ($cvterm_id = $h1->fetchrow_array()) {
168 push @traits_cvterm_ids, $cvterm_id;
171 #print STDERR Dumper (\@traits_cvterm_ids);
172 for (my $x=0; $x<scalar(@traits_cvterm_ids); $x++){
173 foreach $trait_found (@{$triat_name}) {
174 if ($trait_found->[0] eq $traits_cvterm_ids[$x]) {
175 push @found_trait_cvterm_ids, $trait_found->[0];
180 while ($msg_formula =~ /([\w\s-]+\|\w{2}\:\d+)/g){
181 my $full_name = $1;
182 if ($full_name =~ m/\s-\s/g){
183 $full_name =~ s/-\s//g;
185 push @regres, $full_name;
187 #print STDERR Dumper (\@regres);
188 my ($stock_name, $stock_id, $plot_name, $value);
189 if (@found_trait_cvterm_ids != @traits_cvterm_ids) {
190 $c->stash->{rest} = {error => "Upload or compute trait(s) required for computing \n\n$selected_trait = $msg_formula." };
191 return;
193 else {
195 print Dumper (\@found_trait_cvterm_ids);
196 my $h2 = $dbh->prepare("SELECT object.uniquename AS stock_name, object.stock_id AS stock_id, me.uniquename AS plot_name, phenotype.value FROM stock me LEFT JOIN
197 nd_experiment_stock nd_experiment_stocks ON nd_experiment_stocks.stock_id =
198 me.stock_id LEFT JOIN nd_experiment nd_experiment ON nd_experiment.nd_experiment_id = nd_experiment_stocks.nd_experiment_id LEFT JOIN nd_experiment_phenotype nd_experiment_phenotypes ON nd_experiment_phenotypes.nd_experiment_id = nd_experiment.nd_experiment_id LEFT JOIN phenotype phenotype ON phenotype.phenotype_id =
199 nd_experiment_phenotypes.phenotype_id LEFT JOIN cvterm observable ON
200 observable.cvterm_id = phenotype.observable_id LEFT JOIN nd_experiment_project
201 nd_experiment_projects ON nd_experiment_projects.nd_experiment_id =
202 nd_experiment.nd_experiment_id LEFT JOIN project project ON project.project_id =
203 nd_experiment_projects.project_id LEFT JOIN stock_relationship
204 stock_relationship_subjects ON stock_relationship_subjects.subject_id =
205 me.stock_id LEFT JOIN stock object ON object.stock_id =
206 stock_relationship_subjects.object_id WHERE ( ( observable.cvterm_id =? AND
207 project.project_id=? ) );");
209 my %cvterm_hash;
210 my %plot_hash;
211 my %valid_plots;
212 foreach (@found_trait_cvterm_ids) {
213 $h2->execute($_, $trial_id);
214 while ( ($stock_name, $stock_id, $plot_name, $value) = $h2->fetchrow_array()) {
215 $cvterm_hash{$_}->{$plot_name} = $value;
216 $plot_hash{$plot_name}->{$_} = $value;
221 foreach my $plot_name (keys %plot_hash) {
222 my $valid_plot_check = 1;
223 my @value_array;
224 foreach (@found_trait_cvterm_ids) {
225 if (!exists ($plot_hash{$plot_name}->{$_})) {
226 $valid_plot_check = 0;
228 push @value_array, $plot_hash{$plot_name}->{$_};
231 if ($valid_plot_check) {
232 $valid_plots{$plot_name} = \@value_array;
233 push @plots, $plot_name;
237 foreach my $valid_plot_name (keys %valid_plots){
238 my $value_array = $valid_plots{$valid_plot_name};
239 #print STDERR Dumper $value_array;
240 my %map_hash;
241 for( my $i =0; $i<scalar(@regres); $i++) {
242 $map_hash{$regres[$i]} = $value_array->[$i];
244 #print STDERR Dumper \%map_hash;
245 my $msg_formula_sub = $msg_formula;
246 foreach my $full_trait (keys %map_hash) {
247 $full_trait =~ /([\w\s-]+)\|(\w{2}\:\d+)/g;
248 #print STDERR Dumper $full_trait;
249 $msg_formula_sub =~ s/($1\|$2)/$map_hash{$full_trait}/g;
251 #print STDERR Dumper $msg_formula_sub;
252 my $calc_value = eval "$msg_formula_sub";
253 #print STDERR Dumper $calc_value;
254 $data{$valid_plot_name}->{$selected_trait} = [$calc_value,$timestamp];
259 #print STDERR Dumper (\%data);
260 #print STDERR Dumper (\@plots);
261 #print STDERR Dumper (\@traits);
263 $parse_result{'data'} = \%data;
264 $parse_result{'plots'} = \@plots;
265 $parse_result{'traits'} = \@traits;
267 my %phenotype_metadata;
268 $phenotype_metadata{'archived_file'} = 'none';
269 $phenotype_metadata{'archived_file_type'}="generated from derived traits";
270 $phenotype_metadata{'operator'}=$c->user()->get_object()->get_sp_person_id();
271 $phenotype_metadata{'date'}="$timestamp";
272 my $user_id = $c->can('user_exists') ? $c->user->get_object->get_sp_person_id : $c->sp_person_id;
274 my $store_phenotypes = CXGN::Phenotypes::StorePhenotypes->new(
275 bcs_schema=>$schema,
276 metadata_schema=>$metadata_schema,
277 phenome_schema=>$phenome_schema,
278 user_id=>$user_id,
279 stock_list=>\@plots,
280 trait_list=>\@traits,
281 values_hash=>\%data,
282 has_timestamps=>1,
283 overwrite_values=>0,
284 metadata_hash=>\%phenotype_metadata,
287 my ($store_error, $store_success) = $store_phenotypes->store();
288 if ($store_error) {
289 $c->stash->{rest} = {error => $store_error};
292 $c->stash->{rest} = {success => 1};
296 sub generate_plot_phenotypes : Path('/ajax/breeders/trial/generate_plot_phenotypes') Args(0) {
297 my $self = shift;
298 my $c = shift;
299 my $trial_id = $c->req->param('trial_id');
300 my $trait_name = uri_decode($c->req->param('trait_name'));
301 my $method = $c->req->param('method');
302 my $rounding = $c->req->param('rounding');
303 #print STDERR "Trial: $trial_id\n";
304 #print STDERR "Trait: $trait_name\n";
305 #print STDERR "Method: $method\n";
306 #print STDERR "Round: $rounding\n";
307 my $schema = $c->dbic_schema('Bio::Chado::Schema');
309 my @traits;
310 if ($trait_name eq 'all') {
311 my $trial = CXGN::Trial->new({trial_id=>$trial_id, bcs_schema=>$schema});
312 my $traits_assayed = $trial->get_traits_assayed('plant');
313 foreach (@$traits_assayed) {
314 push @traits, $_->[1];
316 } else {
317 @traits = ($trait_name);
320 my @return_info;
321 my @return_plots;
322 my @return_traits;
323 my @return_store_hash;
324 foreach (@traits) {
325 my $derive_trait = CXGN::BreedersToolbox::DeriveTrait->new({
326 bcs_schema=>$schema,
327 trait_name=>$_,
328 trial_id=>$trial_id,
329 method=>$method,
330 rounding=>$rounding
332 my ($info, $plots, $traits, $store_hash) = $derive_trait->generate_plot_phenotypes();
333 push @return_info, $info;
334 push @return_plots, $plots;
335 push @return_traits, $traits;
336 push @return_store_hash, $store_hash;
338 #print STDERR Dumper \%store_hash;
339 #print STDERR Dumper \@return;
340 $c->stash->{rest} = {
341 success => 1,
342 info=>\@return_info,
343 method=>$method,
344 trait_name=>$trait_name,
345 rounding=>$rounding,
346 store_plots=>encode_json(\@return_plots),
347 store_traits=>encode_json(\@return_traits),
348 store_data=>encode_json(\@return_store_hash)
354 sub store_generated_plot_phenotypes : Path('/ajax/breeders/trial/store_generated_plot_phenotypes') Args(0) {
355 my $self = shift;
356 my $c = shift;
357 my %parse_result;
358 my $data = decode_json($c->req->param('store_data'));
359 my $plots = decode_json($c->req->param('store_plots'));
360 my $traits = decode_json($c->req->param('store_traits'));
361 my $overwrite_values = $c->req->param('overwrite_values');
362 #print STDERR Dumper $data;
363 #print STDERR Dumper $plots;
364 #print STDERR Dumper $traits;
365 #print STDERR $overwrite_values;
367 my $schema = $c->dbic_schema("Bio::Chado::Schema");
368 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
369 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
371 my $overwrite = 0;
372 if ($overwrite_values) {
373 $overwrite = 1;
374 my $user_type = $c->user()->get_object->get_user_type();
375 #print STDERR $user_type."\n";
376 if ($user_type ne 'curator') {
377 $c->stash->{rest} = {error => 'Must be a curator to overwrite values! Please contact us!'};
378 $c->detach;
382 my %phenotype_metadata;
383 my $time = DateTime->now();
384 my $timestamp = $time->ymd()."_".$time->hms();
385 my $user_id = $c->user ? $c->user->get_object->get_sp_person_id : $c->req->param('user_id');
386 $phenotype_metadata{'archived_file'} = 'none';
387 $phenotype_metadata{'archived_file_type'}="generated from plot from plant phenotypes";
388 $phenotype_metadata{'operator'}=$user_id;
389 $phenotype_metadata{'date'}="$timestamp";
391 for (my $i=0; $i<scalar(@$data); $i++) {
392 my $store_phenotypes = CXGN::Phenotypes::StorePhenotypes->new(
393 bcs_schema=>$schema,
394 metadata_schema=>$metadata_schema,
395 phenome_schema=>$phenome_schema,
396 user_id=>$user_id,
397 stock_list=>$plots->[$i],
398 trait_list=>$traits->[$i],
399 values_hash=>$data->[$i],
400 has_timestamps=>0,
401 overwrite_values=>$overwrite,
402 metadata_hash=>\%phenotype_metadata,
404 my ($store_error, $store_success) = $store_phenotypes->store();
405 if ($store_error) {
406 $c->stash->{rest} = {error => $store_error};
409 $c->stash->{rest} = {success => 1};