seedlot upload with accession synonyms. seedlot upload works to update existing seedlots
[sgn.git] / lib / SGN / Controller / AJAX / Analyze / Anova.pm
blob43efb9bc3586fadf323645c4b79477b69cc973b8
1 =head1 AUTHOR
3 Isaak Y Tecle <iyt2@cornell.edu>
5 =head1 Name
7 SGN::Controller::AJAX::Analyze::Anova - a controller for ANOVA. For now, this implements a one-way
8 single trial ANOVA with a possibility for simultanously running anova for multiple traits.
10 =cut
13 package SGN::Controller::AJAX::Analyze::Anova;
15 use Moose;
16 use namespace::autoclean;
18 use File::Slurp qw /write_file read_file/;
19 use JSON;
20 use CXGN::Trial;
21 use File::Copy;
22 use File::Basename;
23 use File::Spec::Functions;
24 use File::Path qw / mkpath /;
25 use URI::FromHash 'uri';
27 BEGIN { extends 'Catalyst::Controller::REST' }
31 __PACKAGE__->config(
32 default => 'application/json',
33 stash_key => 'rest',
34 map => { 'application/json' => 'JSON',
35 'text/html' => 'JSON' },
39 sub anova_check_design :Path('/anova/check/design/') Args(0) {
40 my ($self, $c) = @_;
42 $c->stash->{trial_id} = $c->req->param('trial_id');
44 $self->check_trial_design($c);
49 sub anova_traits_list :Path('/anova/traits/list/') Args(0) {
50 my ($self, $c) = @_;
52 my $trial_id = $c->req->param('trial_id');
54 $c->stash->{trial_id} = $trial_id;
56 $self->anova_traits($c);
61 sub anova_phenotype_data :Path('/anova/phenotype/data/') Args(0) {
62 my ($self, $c) = @_;
64 my $trial_id = $c->req->param('trial_id');
65 my @traits_ids = $c->req->param('traits_ids[]');
67 $c->stash->{rest}{trial_id} = $trial_id;
69 $c->stash->{trial_id} = $trial_id;
70 $c->stash->{traits_ids} = \@traits_ids;
72 $self->create_anova_phenodata_file($c);
73 $self->get_traits_abbrs($c);
78 sub anova_traits {
79 my ($self, $c) = @_;
81 my $trial_id = $c->stash->{trial_id};
83 my $trial = CXGN::Trial->new(bcs_schema => $self->schema($c),
84 trial_id => $trial_id);
86 my $traits = $trial->get_traits_assayed();
87 my $clean_traits = $self->remove_ontology($traits);
89 $c->stash->{rest}{anova_traits} = $clean_traits;
94 sub remove_ontology {
95 my ($self, $traits) = @_;
97 my @clean_traits;
99 foreach my $tr (@$traits) {
100 my $name = $tr->[1];
101 $name =~ s/\|CO_\d+:\d+//;
103 my $id_nm = {'trait_id' => $tr->[0], 'trait_name' => $name};
104 push @clean_traits, $id_nm;
107 return \@clean_traits;
112 sub create_anova_phenodata_file {
113 my ($self, $c) = @_;
115 $self->anova_pheno_file($c);
116 my $pheno_file = $c->stash->{phenotype_file};
118 $self->copy_pheno_file_to_anova_dir($c);
120 if (!-s $pheno_file) {
121 $c->stash->{rest}{'Error'} = 'There is no phenotype data for this trial.';
122 } else {
123 $c->stash->{rest}{'success'} = 'Success.';
126 if (@{$c->error}) {
127 $c->stash->{rest}{'Error'} = 'There was error querying for the phenotype data.';
133 sub check_trial_design {
134 my ($self, $c) = @_;
136 my $trial_id = $c->stash->{trial_id};
138 my $trial = CXGN::Trial->new(bcs_schema => $self->schema($c),
139 trial_id => $trial_id);
141 my $design = $trial->get_design_type();
143 my $supported;
144 $supported = $self->check_support($design) if $design;
146 if (!$design)
148 $c->stash->{rest}{'Error'} = 'This trial has no design to apply ANOVA.';
150 elsif ($design && !$supported)
152 $c->stash->{rest}{'Error'} = $design . ' design is not supported yet. Please report this to the database team. ';
154 else
156 $c->stash->{rest}{'Design'} = $design;
162 sub check_support {
163 my ($self, $design) = @_;
165 my $supported_designs = $self->supported_designs;
167 my ($match) = grep(/$design/, @$supported_designs);
169 return $match;
174 sub supported_designs {
175 my $self= shift;
177 my $supported_designs = [qw(Alpha, Augmented, RCBD, CRD)];
179 return $supported_designs;
183 sub get_traits_abbrs {
184 my ($self, $c) = @_;
186 my $trial_id = $c->stash->{trial_id};
187 my $traits_ids = $c->stash->{traits_ids};
189 $c->stash->{pop_id} = $trial_id;
190 $c->controller("solGS::solGS")->all_traits_file($c);
191 my $traits_file = $c->stash->{all_traits_file};
192 my @traits = read_file($traits_file);
194 my @traits_abbrs;
196 foreach my $id (@$traits_ids) {
197 my ($tr) = grep(/$id/, @traits);
198 chomp($tr);
199 my $abbr = (split('\t', $tr))[2] if $tr;
200 my $id_abbr = {'trait_id' => $id, 'trait_abbr' => $abbr};
201 push @traits_abbrs, $id_abbr;
204 $c->stash->{rest}{traits_abbrs} = \@traits_abbrs;
209 sub anova_analyis :Path('/anova/analysis/') Args(0) {
210 my ($self, $c) = @_;
212 my $trial_id = $c->req->param('trial_id');
213 my $traits = $c->req->param('traits[]');
215 $c->stash->{trial_id} = $trial_id;
217 my $json = JSON->new();
218 $traits = $json->decode($traits);
220 foreach my $tr (@$traits)
222 foreach my $k (keys $tr)
224 $c->stash->{$k} = $tr->{$k};
227 unless ($self->check_anova_output($c))
229 $self->run_anova($c);
230 $self->check_anova_output($c);
237 sub check_anova_output {
238 my ($self, $c) = @_;
240 $self->anova_table_file($c);
241 my $html_file = $c->stash->{anova_table_html_file};
243 if (-s $html_file) {
245 my $html_table = read_file($html_file);
247 $self->prep_download_files($c);
248 my $anova_table_file = $c->stash->{download_anova};
249 my $model_file = $c->stash->{download_model};
250 my $means_file = $c->stash->{download_means};
251 my $diagnostics_file = $c->stash->{download_diagnostics};
253 $c->stash->{rest}{anova_html_table} = $html_table;
254 $c->stash->{rest}{anova_table_file} = $anova_table_file;
255 $c->stash->{rest}{anova_model_file} = $model_file;
256 $c->stash->{rest}{adj_means_file} = $means_file;
257 $c->stash->{rest}{anova_diagnostics_file} = $diagnostics_file;
259 return 1;
261 } else {
262 return 0;
268 sub prep_download_files {
269 my ($self, $c) = @_;
271 my $tmp_dir = catfile($c->config->{tempfiles_subdir}, 'anova');
272 my $base_tmp_dir = catfile($c->config->{basepath}, $tmp_dir);
274 mkpath ([$base_tmp_dir], 0, 0755);
276 $self->anova_table_file($c);
277 my $anova_txt_file = $c->stash->{anova_table_txt_file};
278 my $anova_html_file = $c->stash->{anova_table_html_file};
280 $self->anova_model_file($c);
281 my $model_file = $c->stash->{anova_model_file};
283 $self->adj_means_file($c);
284 my $means_file = $c->stash->{adj_means_file};
286 $self->anova_diagnostics_file($c);
287 my $diagnostics_file = $c->stash->{anova_diagnostics_file};
289 copy($anova_txt_file, $base_tmp_dir)
290 or die "could not copy $anova_txt_file to $base_tmp_dir";
292 copy($model_file, $base_tmp_dir)
293 or die "could not copy $model_file to $base_tmp_dir";
295 copy($means_file, $base_tmp_dir)
296 or die "could not copy $means_file to $base_tmp_dir";
298 copy($diagnostics_file, $base_tmp_dir)
299 or die "could not copy $diagnostics_file to $base_tmp_dir";
301 $anova_txt_file = fileparse($anova_txt_file);
302 $anova_txt_file = catfile($tmp_dir, $anova_txt_file);
304 $model_file = fileparse($model_file);
305 $model_file = catfile($tmp_dir, $model_file);
307 $means_file = fileparse($means_file);
308 $means_file = catfile($tmp_dir, $means_file);
310 $diagnostics_file = fileparse($diagnostics_file);
311 $diagnostics_file = catfile($tmp_dir, $diagnostics_file);
313 $c->stash->{download_anova} = $anova_txt_file;
314 $c->stash->{download_model} = $model_file;
315 $c->stash->{download_means} = $means_file;
316 $c->stash->{download_diagnostics} = $diagnostics_file;
321 sub run_anova {
322 my ($self, $c) = @_;
324 my $trial_id = $c->stash->{trial_id};
325 my $trait_id = $c->stash->{trait_id};
327 $self->anova_input_files($c);
328 my $input_file = $c->stash->{anova_input_files};
330 $self->anova_output_files($c);
331 my $output_file = $c->stash->{anova_output_files};
333 $c->stash->{analysis_tempfiles_dir} = $c->stash->{anova_temp_dir};
335 $c->stash->{input_files} = $input_file;
336 $c->stash->{output_files} = $output_file;
337 $c->stash->{r_temp_file} = "anova-${trial_id}-${trait_id}";
338 $c->stash->{r_script} = 'R/anova.r';
340 $c->controller("solGS::solGS")->run_r_script($c);
345 sub copy_pheno_file_to_anova_dir {
346 my ($self, $c) = @_;
348 my $trial_id = $c->stash->{trial_id};
350 $c->controller('solGS::solGS')->phenotype_file_name($c, $trial_id);
351 my $pheno_file = $c->stash->{phenotype_file_name};
353 my $anova_cache = $c->stash->{anova_cache_dir};
355 copy($pheno_file, $anova_cache) or
356 die "could not copy $pheno_file to $anova_cache";
361 sub anova_input_files {
362 my ($self, $c) = @_;
364 my $trial_id = $c->stash->{trial_id};
365 my $trait_id = $c->stash->{trait_id};
367 $self->anova_pheno_file($c);
368 my $pheno_file = $c->stash->{phenotype_file};
370 $self->anova_traits_file($c);
371 my $traits_file = $c->stash->{anova_traits_file};
373 my $file_list = join ("\t",
374 $pheno_file,
375 $traits_file,
378 my $tmp_dir = $c->stash->{anova_temp_dir};
379 my $name = "anova_input_files_${trial_id}_${trait_id}";
380 my $tempfile = $c->controller("solGS::solGS")->create_tempfile($tmp_dir, $name);
381 write_file($tempfile, $file_list);
383 $c->stash->{anova_input_files} = $tempfile;
388 sub anova_pheno_file {
389 my ($self, $c) = @_;
391 $c->stash->{pop_id} = $c->stash->{trial_id};
393 $c->controller('solGS::solGS')->phenotype_file($c);
398 sub anova_traits_file {
399 my ($self, $c) = @_;
401 my $trial_id = $c->stash->{trial_id};
402 my $traits = $c->stash->{trait_abbr};
404 my $tmp_dir = $c->stash->{anova_temp_dir};
405 my $name = "anova_traits_file_${trial_id}";
406 my $traits_file = $c->controller("solGS::solGS")->create_tempfile($tmp_dir, $name);
407 write_file($traits_file, $traits);
409 $c->stash->{anova_traits_file} = $traits_file;
414 sub anova_output_files {
415 my ($self, $c) = @_;
417 my $trial_id = $c->stash->{trial_id};
418 my $trait_id = $c->stash->{trait_id};
420 $self->anova_table_file($c);
421 $self->anova_model_file($c);
422 $self->adj_means_file($c);
423 $self->anova_diagnostics_file($c);
425 my @files = $c->stash->{anova_table_file};
427 my $file_list = join ("\t",
428 $c->stash->{anova_model_file},
429 $c->stash->{anova_table_html_file},
430 $c->stash->{anova_table_txt_file},
431 $c->stash->{adj_means_file},
432 $c->stash->{anova_diagnostics_file},
435 my $tmp_dir = $c->stash->{anova_temp_dir};
436 my $name = "anova_output_files_${trial_id}_${trait_id}";
437 my $tempfile = $c->controller("solGS::solGS")->create_tempfile($tmp_dir, $name);
438 write_file($tempfile, $file_list);
440 $c->stash->{anova_output_files} = $tempfile;
445 sub anova_table_file {
446 my ($self, $c) = @_;
448 my $trial_id = $c->stash->{trial_id};
449 my $trait_id = $c->stash->{trait_id};
451 $c->stash->{cache_dir} = $c->stash->{anova_cache_dir};
453 my $cache_data = {key => "anova_table_${trial_id}_${trait_id}_html",
454 file => "anova_table_${trial_id}_${trait_id}.html",
455 stash_key => "anova_table_html_file"
458 $c->controller("solGS::solGS")->cache_file($c, $cache_data);
460 $c->stash->{cache_dir} = $c->stash->{anova_cache_dir};
462 $cache_data = {key => "anova_table_${trial_id}_${trait_id}_txt",
463 file => "anova_table_${trial_id}_${trait_id}.txt",
464 stash_key => "anova_table_txt_file"
467 $c->controller("solGS::solGS")->cache_file($c, $cache_data);
472 sub anova_diagnostics_file {
473 my ($self, $c) = @_;
475 my $trial_id = $c->stash->{trial_id};
476 my $trait_id = $c->stash->{trait_id};
478 $c->stash->{cache_dir} = $c->stash->{anova_cache_dir};
480 my $cache_data = {key => "anova_diagnosics_${trial_id}_${trait_id}",
481 file => "anova_diagnostics_${trial_id}_${trait_id}.png",
482 stash_key => "anova_diagnostics_file"
485 $c->controller("solGS::solGS")->cache_file($c, $cache_data);
490 sub anova_model_file {
491 my ($self, $c) = @_;
493 my $trial_id = $c->stash->{trial_id};
494 my $trait_id = $c->stash->{trait_id};
496 $c->stash->{cache_dir} = $c->stash->{anova_cache_dir};;
498 my $cache_data = {key => "anova_model_${trial_id}_${trait_id}",
499 file => "anova_model_${trial_id}_${trait_id}.txt",
500 stash_key => "anova_model_file"
503 $c->controller("solGS::solGS")->cache_file($c, $cache_data);
508 sub adj_means_file {
509 my ($self, $c) = @_;
511 my $trial_id = $c->stash->{trial_id};
512 my $trait_id = $c->stash->{trait_id};
514 $c->stash->{cache_dir} = $c->stash->{anova_cache_dir};;
516 my $cache_data = {key => "adj_means_${trial_id}_${trait_id}",
517 file => "adj_means_${trial_id}_${trait_id}.txt",
518 stash_key => "adj_means_file"
521 $c->controller("solGS::solGS")->cache_file($c, $cache_data);
526 sub schema {
527 my ($self, $c) = @_;
529 return $c->dbic_schema("Bio::Chado::Schema");
534 sub begin : Private {
535 my ($self, $c) = @_;
537 $c->controller("solGS::solGS")->get_solgs_dirs($c);
543 __PACKAGE__->meta->make_immutable;