add forward slash to contact form path
[sgn.git] / lib / SGN / Controller / solGS / AnalysisQueue.pm
blob04dc2f8f8876b662a9d2a4dfc3dd1897bca7ca93
1 package SGN::Controller::solGS::AnalysisQueue;
3 use Moose;
4 use namespace::autoclean;
5 use File::Path qw / mkpath /;
6 use File::Spec::Functions qw / catfile catdir/;
7 use File::Slurp qw /write_file read_file/;
8 use JSON;
9 use CXGN::Tools::Run;
10 use Try::Tiny;
11 use Storable qw/ nstore retrieve /;
12 use Carp qw/ carp confess croak /;
13 use Scalar::Util 'reftype';
14 use URI;
16 BEGIN { extends 'Catalyst::Controller' }
19 sub check_user_login :Path('/solgs/check/user/login') Args(0) {
20 my ($self, $c) = @_;
22 my $user = $c->user();
23 my $ret->{loggedin} = 0;
25 if ($user)
27 my $contact = $self->get_user_detail($c);
29 $ret->{contact} = $contact;
30 $ret->{loggedin} = 1;
33 $ret = to_json($ret);
35 $c->res->content_type('application/json');
36 $c->res->body($ret);
41 sub save_analysis_profile :Path('/solgs/save/analysis/profile') Args(0) {
42 my ($self, $c) = @_;
44 my $analysis_profile = $c->req->params;
45 $c->stash->{analysis_profile} = $analysis_profile;
47 my $analysis_page = $analysis_profile->{analysis_page};
48 $c->stash->{analysis_page} = $analysis_page;
50 my $ret->{result} = 0;
52 $self->save_profile($c);
53 my $error_saving = $c->stash->{error};
55 if (!$error_saving)
57 $ret->{result} = 1;
60 $ret = to_json($ret);
62 $c->res->content_type('application/json');
63 $c->res->body($ret);
68 sub run_saved_analysis :Path('/solgs/run/saved/analysis/') Args(0) {
69 my ($self, $c) = @_;
71 my $analysis_profile = $c->req->params;
72 $c->stash->{analysis_profile} = $analysis_profile;
74 $self->parse_arguments($c);
75 $self->structure_output_details($c);
76 $self->run_analysis($c);
78 my $ret->{result} = $c->stash->{status};
79 $ret->{arguments} = $analysis_profile->{arguments};
81 $ret = to_json($ret);
83 $c->res->content_type('application/json');
84 $c->res->body($ret);
89 sub check_analysis_name :Path('/solgs/check/analysis/name') Args() {
90 my ($self, $c) = @_;
92 my $new_name = $c->req->param('name');
94 my $match = $self->check_analyses_names($c, $new_name);
96 my $ret->{analysis_exists} = $match;
97 $ret = to_json($ret);
99 $c->res->content_type('application/json');
100 $c->res->body($ret);
105 sub submission_feedback :Path('/solgs/submission/feedback/') Args() {
106 my ($self, $c) = @_;
108 my $job = $c->req->param('job');
109 # $c->controller('solGS::Utils')->stash_json_args($c, $args);
111 my $job_type = $self->get_confirm_msg($c, $job);
112 my $user_id = $c->user()->get_object()->get_sp_person_id();
113 my $referer = $c->req->referer;
115 my $msg = "<p>$job_type</p>"
116 . "<p>You will receive an email when it is completed. "
117 . "You can also check the status of the job on "
118 . "<a href=\"/solpeople/profile/$user_id\">your profile page</a>"
119 . "<p><a href=\"$referer\">[ Go back ]</a></p>";
121 $c->controller('solGS::Utils')->generic_message($c, $msg);
126 sub display_analysis_status :Path('/solgs/display/analysis/status') Args(0) {
127 my ($self, $c) = @_;
129 my $panel_data = $self->get_user_solgs_analyses($c);
131 my $ret->{data} = $panel_data;
132 my $json = JSON->new();
133 $ret = $json->encode($ret);
135 $c->res->content_type('application/json');
136 $c->res->body($ret);
141 sub check_analyses_names {
142 my ($self, $c, $new_name) = @_;
144 my $logged_names = $self->check_log_analyses_names($c);
146 my $log_match;
147 if ($logged_names)
149 $log_match = grep { $_ =~ /$new_name/i } @$logged_names;
152 my $db_match;
154 if ($new_name)
156 my $schema = $c->dbic_schema("Bio::Chado::Schema");
157 $db_match = $schema->resultset("Project::Project")->find({ name => $new_name });
160 my $match = $log_match || $db_match ? 1 : 0;
162 return $match;
167 sub check_log_analyses_names {
168 my ($self, $c) = @_;
170 my $log_file = $self->analysis_log_file($c);
171 my $names = qx(cut -f 2 $log_file);
173 if ($names)
175 my @names = split(/\n/, $names);
177 shift(@names);
178 return \@names;
180 else
182 return 0;
187 sub save_profile {
188 my ($self, $c) = @_;
190 $self->analysis_log_file($c);
191 my $log_file = $c->stash->{analysis_log_file};
193 $self->add_log_headers($c);
195 $self->format_log_entry($c);
196 my $log_entry = $c->stash->{formatted_log_entry};
198 write_file($log_file, {binmode => ':utf8', append => 1}, $log_entry);
203 sub add_log_headers {
204 my ($self, $c) = @_;
206 $self->analysis_log_file($c);
207 my $log_file = $c->stash->{analysis_log_file};
209 my $headers = read_file($log_file, {binmode => ':utf8'});
211 unless ($headers)
213 $headers = 'User_name' .
214 "\t" . 'Analysis_name' .
215 "\t" . "Analysis_page" .
216 "\t" . "Status" .
217 "\t" . "Submitted on" .
218 "\t" . "Arguments" .
219 "\n";
221 write_file($log_file, {binmode => ':utf8'}, $headers);
227 sub index_log_file_headers {
228 my ($self, $c) = @_;
230 no warnings 'uninitialized';
232 $self->analysis_log_file($c);
233 my $log_file = $c->stash->{analysis_log_file};
235 my @headers = split(/\t/, (read_file($log_file, {binmode => ':utf8'}))[0]);
237 my $header_index = {};
238 my $cnt = 0;
240 foreach my $header (@headers)
242 $header_index->{$header} = $cnt;
243 $cnt++;
246 $c->stash->{header_index} = $header_index;
251 sub create_itemized_prediction_log_entries {
252 my ($self, $c, $analysis_log) = @_;
254 $analysis_log = $self->log_analysis_time($analysis_log);
256 my $json = JSON->new;
257 my $args = $json->decode($analysis_log->{arguments});
259 my $trait_ids = $args->{training_traits_ids};
261 my $analysis_type = $args->{analysis_type};
263 my $url_args = {
264 'training_pop_id' => $args->{training_pop_id}->[0],
265 'selection_pop_id' => $args->{selection_pop_id}->[0],
266 'genotyping_protocol_id' => $args->{genotyping_protocol_id},
267 'data_set_type' => $args->{data_set_type},
270 my $entries;
271 foreach my $trait_id (@$trait_ids)
273 $c->controller('solGS::solGS')->get_trait_details($c, $trait_id);
274 my $trait_abbr = $c->stash->{trait_abbr};
275 $url_args->{trait_id} = $trait_id;
277 my $analysis_page;
278 if ($analysis_type =~ /selection prediction/)
280 $analysis_page = $c->controller('solGS::Path')->selection_page_url($url_args);
282 else
284 $analysis_page = $c->controller('solGS::Path')->model_page_url($url_args);
285 $analysis_type = 'single model';
288 my $analysis_name = $analysis_log->{analysis_name} . ' -- ' . $trait_abbr;
290 $args->{analysis_page} = $analysis_page;
291 $args->{analysis_name} = $analysis_name;
292 $args->{trait_id} = [$trait_id];
293 $args->{training_traits_ids} = [$trait_id];
294 $args->{analysis_type} = $analysis_type;
296 $entries .= join("\t", (
297 $analysis_log->{user_name},
298 $analysis_name,
299 $analysis_page,
300 'Submitted',
301 $args->{analysis_time},
302 $json->encode($args),)
305 $entries .= "\n";
309 return $entries;
314 sub log_analysis_time {
315 my ($self, $analysis_log ) = @_;
317 my $analysis_time = POSIX::strftime("%m/%d/%Y %H:%M", localtime);
319 my $json = JSON->new;
320 my $args = $json->decode($analysis_log->{arguments});
322 $args->{analysis_time} = $analysis_time;
323 $analysis_log->{arguments} = $json->encode($args);
325 return $analysis_log;
330 sub format_log_entry {
331 my ($self, $c) = @_;
333 my $profile = $c->stash->{analysis_profile};
334 $profile= $self->log_analysis_time($profile);
335 my $args = $profile->{arguments};
337 my $json = JSON->new;
338 my $time = $json->decode($args)->{analysis_time};
340 my $traits_args = $json->decode($args);
341 my $traits_ids = $traits_args->{training_traits_ids} || $traits_args->{trait_id};
342 my @traits_ids = ref($traits_ids) eq 'ARRAY' ? @$traits_ids : ($traits_ids);
344 my $analysis_page;
345 my $analysis_type = $traits_args->{analysis_type};
347 if (@traits_ids > 1 && $analysis_type =~ /selection/)
349 $analysis_page = $traits_args->{referer};
351 else
353 $analysis_page = $traits_args->{analysis_page};
356 my $entry = join("\t", (
357 $profile->{user_name},
358 $profile->{analysis_name},
359 $analysis_page,
360 'Submitted',
361 $time,
362 $args)
365 $entry .= "\n";
367 if (@traits_ids > 1 && $analysis_type =~ /model|selection/ )
369 my $traits_entries = $self->create_itemized_prediction_log_entries($c, $profile);
370 $entry .= $traits_entries;
373 $c->stash->{formatted_log_entry} = $entry;
378 sub analysis_report_job_args {
379 my ($self, $c, $status_check_duration) = @_;
381 my $analysis_details = $c->stash->{bg_job_output_details};
383 my $temp_dir = $c->stash->{analysis_tempfiles_dir} || $c->stash->{solgs_tempfiles_dir} ;
385 my $temp_file_template = "analysis-status";
386 my $cluster_files = $c->controller('solGS::AsyncJob')->create_cluster_accessible_tmp_files($c, $temp_file_template);
387 my $out_file = $cluster_files->{out_file_temp};
388 my $err_file = $cluster_files->{err_file_temp};
389 my $in_file = $cluster_files->{in_file_temp};
391 my $config_args = {
392 'temp_dir' => $temp_dir,
393 'out_file' => $out_file,
394 'err_file' => $err_file,
395 'cluster_host' => 'localhost'
398 my $report_file = $c->controller('solGS::Files')->create_tempfile($temp_dir, 'analysis-report-args');
399 nstore $analysis_details, $report_file
400 or croak "analysis_report_job_args: $! serializing output_details to $report_file";
402 my $job_config = $c->controller('solGS::AsyncJob')->create_cluster_config($c, $config_args);
404 $status_check_duration = ' --status_check_duration ' . $status_check_duration if $status_check_duration;
406 my $cmd = 'mx-run solGS::AnalysisReport'
407 . ' --output_details_file ' . $report_file
408 . $status_check_duration;
411 my $job_args = {
412 'cmd' => $cmd,
413 'config' => $job_config,
414 'background_job'=> $c->stash->{background_job},
415 'temp_dir' => $temp_dir,
418 $c->stash->{analysis_report_job_args} = $job_args;
423 sub get_analysis_report_job_args_file {
424 my ($self, $c, $status_check_duration) = @_;
426 $self->analysis_report_job_args($c, $status_check_duration);
427 my $analysis_job_args = $c->stash->{analysis_report_job_args};
429 my $temp_dir = $c->stash->{solgs_tempfiles_dir};
431 my $report_file = $c->controller('solGS::Files')->create_tempfile($temp_dir, 'analysis-report-job-args');
432 nstore $analysis_job_args, $report_file
433 or croak "get_analysis_report_job_args_file: $! serializing output_details to $report_file";
435 $c->stash->{analysis_report_job_args_file} = $report_file;
440 sub email_analysis_report {
441 my ($self, $c) = @_;
443 $self->analysis_report_job_args($c);
444 my $job_args = $c->stash->{analysis_report_job_args};
446 my $job = $c->controller('solGS::AsyncJob')->submit_job_cluster($c, $job_args);
450 sub parse_arguments {
451 my ($self, $c) = @_;
453 my $analysis_data = $c->stash->{analysis_profile};
454 my $arguments = $analysis_data->{arguments};
455 my $data_set_type = $analysis_data->{data_set_type};
457 if ($arguments)
459 $c->controller('solGS::Utils')->stash_json_args($c, $arguments);
465 sub structure_output_details {
466 my ($self, $c) = @_;
468 my $analysis_data = $c->stash->{analysis_profile};
469 my $analysis_page = $analysis_data->{analysis_page};
471 my $referer = $c->req->referer;
472 my $base = $c->controller('solGS::Path')->clean_base_name($c);
473 my $output_details = {};
475 my $match_pages = 'solgs\/traits\/all\/population\/'
476 . '|solgs\/trait\/'
477 . '|solgs\/model\/combined\/trials\/'
478 . '|solgs\/models\/combined\/trials\/';
480 if ($analysis_page =~ m/$match_pages/)
482 $output_details = $self->structure_training_modeling_output($c);
484 elsif ( $analysis_page =~ m/solgs\/population\// )
486 $output_details = $self->structure_training_single_pop_data_output($c);
488 elsif ($analysis_page =~ m/solgs\/populations\/combined\//)
490 $output_details = $self->structure_training_combined_pops_data_output($c);
492 elsif ( $analysis_page =~ m/solgs\/selection\/(\d+|\w+_\d+)\/model\/|solgs\/combined\/model\/\d+\/selection\// )
494 $output_details = $self->structure_selection_prediction_output($c);
496 elsif ( $analysis_page =~ m/kinship\/analysis/ )
498 $output_details = $self->structure_kinship_analysis_output($c);
500 elsif ( $analysis_page =~ m/pca\/analysis/ )
502 $output_details = $self->structure_pca_analysis_output($c);
504 elsif ( $analysis_page =~ m/cluster\/analysis/ )
506 $output_details = $self->structure_cluster_analysis_output($c);
509 $self->analysis_log_file($c);
510 my $log_file = $c->stash->{analysis_log_file};
512 my $mail_list = $self->mailing_list($c);
514 $output_details->{analysis_profile} = $analysis_data;
515 $output_details->{contact_page} = $base . '/contact/form';
516 $output_details->{data_set_type} = $c->stash->{data_set_type};
517 $output_details->{analysis_log_file} = $log_file;
518 $output_details->{host} = qq | $base |;
519 $output_details->{referer} = qq | $referer |;
520 $output_details->{mailing_list} = $mail_list;
522 $c->stash->{bg_job_output_details} = $output_details;
526 sub mailing_list {
527 my ($self, $c) = @_;
529 my $mail_list = $c->config->{cluster_job_email};
531 if (!$mail_list)
533 $mail_list = 'cluster-jobs@solgenomics.net';
536 return $mail_list;
539 sub structure_kinship_analysis_output {
540 my ($self, $c) = @_;
542 my $analysis_data = $c->stash->{analysis_profile};
543 my $analysis_page = $analysis_data->{analysis_page};
545 my $protocol_id = $c->stash->{genotyping_protocol_id};
547 $c->controller('solGS::Kinship')->stash_data_str_kinship_pop_id($c);
548 my $pop_id = $c->stash->{kinship_pop_id};
550 my $base = $c->controller('solGS::Path')->clean_base_name($c);
552 my $kinship_page = $base . $analysis_page;
553 $analysis_data->{analysis_page} = $kinship_page;
555 my %output_details = ();
557 my $trait_id = $c->stash->{trait_id};
559 $c->controller('solGS::Files')->genotype_file_name($c, $pop_id, $protocol_id);
560 my $geno_file = $c->stash->{genotype_file_name};
562 my $coef_files = $c->controller('solGS::Kinship')->get_kinship_coef_files($c, $pop_id, $protocol_id, $trait_id);
563 my $matrix_file = $coef_files->{matrix_file_adj};
565 $output_details{'kinship_' . $pop_id} = {
566 'output_page' => $kinship_page,
567 'kinship_pop_id' => $pop_id,
568 'genotype_file' => $geno_file,
569 'matrix_file' => $matrix_file,
572 return \%output_details;
576 sub structure_pca_analysis_output {
577 my ($self, $c) = @_;
579 my $analysis_data = $c->stash->{analysis_profile};
580 my $analysis_page = $analysis_data->{analysis_page};
582 my $pop_id = $c->stash->{pca_pop_id};
584 my $base = $c->controller('solGS::Path')->clean_base_name($c);
586 my $pca_page = $base . $analysis_page;
587 $analysis_data->{analysis_page} = $pca_page;
589 my %output_details = ();
590 # $c->controller('solGS::Files')->genotype_file_name($c, $pop_id, $protocol_id);
591 my $geno_file = $c->stash->{genotype_file_name};
593 $c->stash->{file_id} = $c->controller('solGS::Files')->create_file_id($c);
594 $c->controller('solGS::pca')->pca_scores_file($c);
595 my $scores_file = $c->stash->{pca_scores_file};
597 $output_details{'pca_' . $pop_id} = {
598 'output_page' => $pca_page,
599 'pca_pop_id' => $pop_id,
600 'genotype_file' => $geno_file,
601 'scores_file' => $scores_file,
604 return \%output_details;
609 sub structure_cluster_analysis_output {
610 my ($self, $c) = @_;
612 my $analysis_data = $c->stash->{analysis_profile};
613 my $analysis_page = $analysis_data->{analysis_page};
615 my $pop_id = $c->stash->{cluster_pop_id};
617 my $base = $c->controller('solGS::Path')->clean_base_name($c);
618 my $cluster_page = $base . $analysis_page;
619 $analysis_data->{analysis_page} = $cluster_page;
621 my %output_details = ();
622 # $c->controller('solGS::Files')->genotype_file_name($c, $pop_id, $protocol_id);
623 # my $geno_file = $c->stash->{genotype_file_name};
624 my $input_file;
625 $c->stash->{file_id} = $c->controller('solGS::Files')->create_file_id($c);
626 $c->controller('solGS::Cluster')->kcluster_result_file($c);
627 my $result_file = $c->stash->{'k-means_result_file'};
629 $output_details{'cluster_' . $pop_id} = {
630 'output_page' => $cluster_page,
631 'cluster_pop_id' => $pop_id,
632 'input_file' => $input_file,
633 'result_file' => $result_file,
636 return \%output_details;
641 sub structure_training_modeling_output {
642 my ($self, $c) = @_;
644 my $analysis_data = $c->stash->{analysis_profile};
645 my $analysis_page = $analysis_data->{analysis_page};
647 my $pop_id = $c->stash->{pop_id};
648 my $combo_pops_id = $c->stash->{combo_pops_id};
649 my $protocol_id = $c->stash->{genotyping_protocol_id};
651 my @traits_ids = @{$c->stash->{training_traits_ids}} if $c->stash->{training_traits_ids};
652 my $referer = $c->req->referer;
654 my $base = $c->controller('solGS::Path')->clean_base_name($c);
655 my $url_args = {
656 'training_pop_id' => $pop_id,
657 'genotyping_protocol_id' => $protocol_id,
660 my %output_details = ();
662 foreach my $trait_id (@traits_ids)
664 $url_args->{trait_id} = $trait_id;
666 $c->stash->{cache_dir} = $c->stash->{solgs_cache_dir};
668 $c->controller('solGS::solGS')->get_trait_details($c, $trait_id);
669 $c->controller('solGS::Files')->rrblup_training_gebvs_file($c);
671 my $trait_abbr = $c->stash->{trait_abbr};
672 my $trait_page;
675 if ( $referer =~ m/solgs\/population\// )
677 $url_args->{data_set_type} = 'single population';
679 my $model_page = $c->controller('solGS::Path')->model_page_url($url_args);
680 $trait_page = $base . $model_page;
682 if ($analysis_page =~ m/solgs\/traits\/all\/population\//)
684 my $traits_selection_id = $c->controller('solGS::Gebvs')->create_traits_selection_id(\@traits_ids);
685 $analysis_data->{analysis_page} = $base . "solgs/traits/all/population/" . $pop_id
686 . '/traits/' . $traits_selection_id
687 . '/gp/' . $protocol_id;
689 $c->controller('solGS::Gebvs')->catalogue_traits_selection($c, \@traits_ids);
693 if ( $referer =~ m/solgs\/search\/trials\/trait\// && $analysis_page =~ m/solgs\/trait\// )
695 $url_args->{data_set_type} = 'single population';
697 my $model_page = $c->controller('solGS::Path')->model_page_url($url_args);
698 $trait_page = $base . $model_page;
701 if ( $referer =~ m/solgs\/populations\/combined\// )
703 $url_args->{data_set_type} = 'combined populations';
705 my $model_page = $c->controller('solGS::Path')->model_page_url($url_args);
706 $trait_page = $base . $model_page;
708 if ($analysis_page =~ m/solgs\/models\/combined\/trials\//)
710 my $traits_selection_id = $c->controller('solGS::Gebvs')->create_traits_selection_id(\@traits_ids);
711 $analysis_data->{analysis_page} = $base . "solgs/models/combined/trials/"
712 . $combo_pops_id
713 . '/traits/' . $traits_selection_id
714 . '/gp/' . $protocol_id;
716 $c->controller('solGS::Gebvs')->catalogue_traits_selection($c, \@traits_ids);
720 if ( $analysis_page =~ m/solgs\/model\/combined\/trials\// )
722 $url_args->{data_set_type} = 'combined populations';
724 my $model_page = $c->controller('solGS::Path')->model_page_url($url_args);
726 $trait_page = $base . $model_page;
728 $c->stash->{combo_pops_id} = $combo_pops_id;
729 $c->controller('solGS::combinedTrials')->cache_combined_pops_data($c);
732 $output_details{'trait_id_' . $trait_abbr} = {
733 'trait_id' => $trait_id,
734 'trait_name' => $c->stash->{trait_name},
735 'trait_page' => $trait_page,
736 'gebv_file' => $c->stash->{rrblup_training_gebvs_file},
737 'pop_id' => $pop_id,
738 'phenotype_file' => $c->stash->{trait_combined_pheno_file},
739 'genotype_file' => $c->stash->{trait_combined_geno_file},
740 'data_set_type' => $c->stash->{data_set_type},
744 return \%output_details;
748 sub structure_training_single_pop_data_output {
749 my ($self, $c) = @_;
751 my $pop_id = $c->stash->{pop_id};
752 my $protocol_id = $c->stash->{genotyping_protocol_id};
754 my $base = $c->controller('solGS::Path')->clean_base_name($c);
755 my $args = {
756 'training_pop_id' => $pop_id,
757 'genotyping_protocol_id' => $protocol_id,
758 'data_set_type' => 'single population'
761 my $training_pop_page = $c->controller('solGS::Path')->training_page_url($args);
762 my $population_page = $base . $training_pop_page;
764 my $data_set_type = $c->stash->{data_set_type};
765 my $pheno_file;
766 my $geno_file;
767 my $pop_name;
769 my %output_details = ();
771 if ($pop_id =~ /list/)
773 my $files = $c->controller('solGS::List')->create_list_pop_data_files($c);
774 $pheno_file = $files->{pheno_file};
775 $geno_file = $files->{geno_file};
777 $c->controller('solGS::List')->create_list_population_metadata_file($c, $pop_id);
778 $c->controller('solGS::List')->list_population_summary($c);
779 $pop_name = $c->stash->{project_name};
781 elsif ($pop_id =~ /dataset/)
783 my $files = $c->controller('solGS::Dataset')->create_dataset_pop_data_files($c,);
784 $pheno_file = $files->{pheno_file};
785 $geno_file = $files->{geno_file};
787 $c->controller('solGS::Dataset')->create_dataset_population_metadata_file($c);
788 $c->controller('solGS::Dataset')->dataset_population_summary($c);
789 $pop_name = $c->stash->{project_name};
791 else
793 $c->controller('solGS::Files')->phenotype_file_name($c, $pop_id);
794 $c->controller('solGS::Files')->genotype_file_name($c, $pop_id, $protocol_id);
795 $pheno_file = $c->stash->{phenotype_file_name};
796 $geno_file = $c->stash->{genotype_file_name};
798 $c->controller('solGS::Search')->get_project_details($c, $pop_id);
799 $pop_name = $c->stash->{project_name};
802 $output_details{'population_id_' . $pop_id} = {
803 'population_page' => $population_page,
804 'population_id' => $pop_id,
805 'population_name' => $pop_name,
806 'phenotype_file' => $pheno_file,
807 'genotype_file' => $geno_file,
808 'data_set_type' => $data_set_type,
811 return \%output_details;
815 sub structure_training_combined_pops_data_output {
816 my ($self, $c) = @_;
818 my $combo_pops_id = $c->stash->{combo_pops_id};
819 my $protocol_id = $c->stash->{genotyping_protocol_id};
821 my $base = $c->controller('solGS::Path')->clean_base_name($c);
822 my $args = {
823 'training_pop_id' => $combo_pops_id,
824 'genotyping_protocol_id' => $protocol_id,
825 'data_set_type' => 'combined populations'
828 my $training_pop_page = $c->controller('solGS::Path')->training_page_url($args);
830 my $combined_pops_page = $base . $training_pop_page;
831 my @combined_pops_ids = @{$c->stash->{combo_pops_list}};
833 $c->controller('solGS::combinedTrials')->multi_pops_pheno_files($c, \@combined_pops_ids);
834 $c->controller('solGS::combinedTrials')->multi_pops_geno_files($c, \@combined_pops_ids, $protocol_id);
836 my $multi_ph_files = $c->stash->{multi_pops_pheno_files};
837 my @pheno_files = split(/\t/, $multi_ph_files);
838 my $multi_gen_files = $c->stash->{multi_pops_geno_files};
839 my @geno_files = split(/\t/, $multi_gen_files);
840 my $match_status = $c->stash->{pops_with_no_genotype_match};
842 my %output_details = ();
843 foreach my $pop_id (@combined_pops_ids)
845 $c->controller('solGS::Search')->get_project_details($c, $pop_id);
846 my $population_name = $c->stash->{project_name};
848 $args = {
849 'training_pop_id' => $pop_id,
850 'genotyping_protocol_id' => $protocol_id,
851 'data_set_type' => 'single population'
854 my $training_pop_page = $c->controller('solGS::Path')->training_page_url($args);
856 my $population_page = $base . $training_pop_page;
858 $c->controller('solGS::Files')->phenotype_file_name($c, $pop_id);
859 my $pheno_file = $c->stash->{phenotype_file_name};
861 $c->controller('solGS::Files')->phenotype_file_name($c, $pop_id, $protocol_id);
862 my $geno_file = $c->stash->{genotype_file_name};
864 $output_details{'population_id_' . $pop_id} = {
865 'population_page' => $population_page,
866 'population_id' => $pop_id,
867 'population_name' => $population_name,
868 'combo_pops_id' => $combo_pops_id,
869 'phenotype_file' => $pheno_file,
870 'genotype_file' => $geno_file,
871 'data_set_type' => $c->stash->{data_set_type},
875 $output_details{no_match} = $match_status;
876 $output_details{combined_pops_page} = $combined_pops_page;
878 return \%output_details;
882 sub structure_selection_prediction_output {
883 my ($self, $c) = @_;
885 my @traits_ids = @{$c->stash->{training_traits_ids}} if $c->stash->{training_traits_ids};
886 my $protocol_id = $c->stash->{genotyping_protocol_id};
888 my $referer = $c->req->referer;
889 my $base = $c->controller('solGS::Path')->clean_base_name($c);
890 my $data_set_type = $c->stash->{data_set_type};
891 my %output_details = ();
893 foreach my $trait_id (@traits_ids)
895 $c->controller('solGS::solGS')->get_trait_details($c, $trait_id);
896 my $trait_id = $c->stash->{trait_id};
897 my $trait_abbr = $c->stash->{trait_abbr};
898 my $trait_name = $c->stash->{trait_name};
900 my $tr_pop_id = $c->stash->{training_pop_id};
901 my $sel_pop_id = $c->stash->{selection_pop_id};
903 my $tr_pop_page;
904 my $model_page;
905 my $sel_pop_page;
906 my $tr_pop_name;
907 my $sel_pop_name;
909 my $url_args = {
910 'training_pop_id' => $tr_pop_id,
911 'selection_pop_id' => $sel_pop_id,
912 'trait_id' => $trait_id,
913 'genotyping_protocol_id' => $protocol_id,
914 'data_set_type' => $data_set_type,
917 if ($data_set_type =~ /combined populations/)
919 $tr_pop_page = $c->controller('solGS::Path')->training_page_url($url_args);
921 $tr_pop_page = $base . $tr_pop_page;
922 $tr_pop_name = 'Training population ' . $tr_pop_id;
923 $sel_pop_page = $c->controller('solGS::Path')->selection_page_url($url_args);
924 $sel_pop_page = $base . $sel_pop_page;
926 $model_page = $c->controller('solGS::Path')->model_page_url($url_args);
927 $model_page = $base . $model_page;
929 else
931 my $training_pop_page = $c->controller('solGS::Path')->training_page_url($url_args);
933 $tr_pop_page = $base . $training_pop_page;
934 if ($tr_pop_id =~ /list/)
936 $c->stash->{list_id} = $tr_pop_id =~ s/\w+_//r;
937 $c->controller('solGS::List')->list_population_summary($c);
938 $tr_pop_name = $c->stash->{project_name};
940 elsif ($tr_pop_id =~ /dataset/)
942 $c->stash->{dataset_id} = $tr_pop_id =~ s/\w+_//r;
943 $c->controller('solGS::Dataset')->dataset_population_summary($c);
944 $tr_pop_name = $c->stash->{project_name};
946 else
948 $c->controller('solGS::Search')->get_project_details($c, $tr_pop_id);
949 $tr_pop_name = $c->stash->{project_name};
952 $sel_pop_page = $c->controller('solGS::Path')->selection_page_url($url_args);
953 $sel_pop_page = $base . $sel_pop_page;
955 $model_page = $c->controller('solGS::Path')->model_page_url($url_args);
956 $model_page = $base . $model_page;
959 if ($sel_pop_id =~ /list/)
961 $c->stash->{list_id} = $sel_pop_id =~ s/\w+_//r;
962 $c->controller('solGS::List')->list_population_summary($c, $sel_pop_id);
963 $c->controller('solGS::List')->create_list_population_metadata_file($c, $sel_pop_id);
965 $sel_pop_name = $c->stash->{selection_pop_name};
967 elsif ($sel_pop_id =~ /dataset/)
969 $c->stash->{dataset_id} = $sel_pop_id =~ s/\w+_//r;
970 $c->controller('solGS::Dataset')->create_dataset_population_metadata_file($c);
971 $c->controller('solGS::Dataset')->dataset_population_summary($c);
972 $sel_pop_name = $c->stash->{selection_pop_name};
974 else
976 $c->controller('solGS::Search')->get_project_details($c, $sel_pop_id);
977 $sel_pop_name = $c->stash->{project_name};
980 $c->controller('solGS::Files')->rrblup_selection_gebvs_file($c, $tr_pop_id, $sel_pop_id, $trait_id);
981 my $gebv_file = $c->stash->{rrblup_selection_gebvs_file};
983 $c->controller('solGS::Files')->genotype_file_name($c, $sel_pop_id, $protocol_id);
984 my $selection_geno_file = $c->stash->{genotype_file_name};
986 $output_details{'trait_id_' . $trait_id} = {
987 'training_pop_page' => $tr_pop_page,
988 'training_pop_id' => $tr_pop_id,
989 'training_pop_name' => $tr_pop_name,
990 'selection_pop_name' => $sel_pop_name,
991 'selection_pop_page' => $sel_pop_page,
992 'trait_name' => $trait_name,
993 'trait_id' => $trait_id,
994 'model_page' => $model_page,
995 'gebv_file' => $gebv_file,
996 'selection_geno_file' => $selection_geno_file,
997 'data_set_type' => $data_set_type
1002 return \%output_details;
1007 sub run_analysis {
1008 my ($self, $c) = @_;
1010 $c->stash->{background_job} = 1;
1012 my $analysis_profile = $c->stash->{analysis_profile};
1013 my $analysis_page = $analysis_profile->{analysis_page};
1014 $c->stash->{analysis_page} = $analysis_page;
1016 my $base = $c->controller('solGS::Path')->clean_base_name($c);
1017 $analysis_page =~ s/$base//;
1018 my $referer = $c->req->referer;
1020 my @selected_traits = @{$c->stash->{training_traits_ids}} if $c->stash->{training_traits_ids};
1022 eval
1024 my $modeling_pages = 'solgs\/traits\/all\/population\/'
1025 . '|solgs\/models\/combined\/trials\/'
1026 . '|solgs\/trait\/'
1027 . '|solgs\/model\/combined\/trials\/';
1029 my $selection_pages = '/solgs\/selection\/(\d+|\w+_\d+)\/model\/'
1030 . '|solgs\/combined\/model\/(\d+|\w+_\d+)\/selection\/';
1032 my $training_pages = '/solgs\/population\/'
1033 . '|solgs\/populations\/combined\/';
1035 if ($analysis_page =~ $training_pages)
1037 $self->create_training_data($c);
1039 elsif ($analysis_page =~ /$modeling_pages/)
1041 $self->predict_training_traits($c);
1043 elsif ($analysis_page =~ /$selection_pages/)
1045 $self->predict_selection_traits($c);
1047 elsif ($analysis_page =~ /kinship\/analysis/)
1049 $self->run_kinship_analysis($c);
1051 elsif ($analysis_page =~ /pca\/analysis/)
1053 $self->run_pca_analysis($c);
1055 elsif ($analysis_page =~ /cluster\/analysis/)
1057 $self->run_cluster_analysis($c);
1059 else
1061 $c->stash->{status} = 'Error: Unknown job';
1062 print STDERR "\n Uknown job.\n";
1066 my @error = $@;
1068 if ($error[0])
1070 $c->stash->{status} = "run_analysis failed. Please try re-running the analysis and wait for it to finish. $error[0]";
1072 else
1074 $c->stash->{status} = 'Submitted';
1075 $self->update_analysis_progress($c);
1083 sub create_training_data {
1084 my ($self, $c) = @_;
1086 my $analysis_page = $c->stash->{analysis_page};
1087 my $protocol_id = $c->stash->{genotyping_protocol_id};
1089 # if ($analysis_page =~ /solgs\/population\//)
1091 my $pop_id = $c->stash->{model_id};
1093 if ($analysis_page =~ /solgs\/population\//)
1095 my $pop_id = $c->stash->{model_id};
1097 if ($pop_id =~ /list/)
1099 $c->controller('solGS::List')->submit_list_training_data_query($c);
1100 $c->controller('solGS::List')->create_list_population_metadata_file($c, $pop_id);
1102 elsif ($pop_id =~ /dataset/)
1104 $c->controller('solGS::Dataset')->submit_dataset_training_data_query($c);
1105 $c->controller('solGS::Dataset')->create_dataset_population_metadata_file($c);
1107 else
1109 $c->controller('solGS::AsyncJob')->submit_cluster_training_pop_data_query($c, [$pop_id], $protocol_id);
1112 elsif ($analysis_page =~ /solgs\/populations\/combined\//)
1114 my $trials = $c->stash->{combo_pops_list};
1115 $c->controller('solGS::AsyncJob')->submit_cluster_training_pop_data_query($c, $trials, $protocol_id);
1121 sub predict_training_traits {
1122 my ($self, $c) = @_;
1124 my $analysis_page = $c->stash->{analysis_page};
1125 my $selected_traits = $c->stash->{training_traits_ids};
1127 $c->stash->{training_traits_ids} = [$c->stash->{trait_id}] if !$c->stash->{training_traits_ids};
1129 if ($analysis_page =~ /solgs\/traits\/all\/population\/|solgs\/trait\//)
1131 $c->controller('solGS::solGS')->build_multiple_traits_models($c);
1133 elsif ($analysis_page =~ /solgs\/models\/combined\/trials\/|solgs\/model\/combined\/trials\// )
1135 if ($c->stash->{data_set_type} =~ /combined populations/)
1137 $c->controller('solGS::combinedTrials')->combine_data_build_multiple_traits_models($c);
1144 sub predict_selection_traits {
1145 my ($self, $c) = @_;
1147 $c->stash->{prerequisite_type} = 'selection_pop_download_data';
1148 my $training_pop_id = $c->stash->{training_pop_id};
1149 my $selection_pop_id = $c->stash->{selection_pop_id};
1151 if ($selection_pop_id =~ /list/)
1153 $c->stash->{list_id} = $selection_pop_id =~ s/\w+_//r;
1154 $c->controller('solGS::List')->get_genotypes_list_details($c);
1155 $c->controller('solGS::List')->create_list_population_metadata_file($c, $selection_pop_id);
1157 elsif ($selection_pop_id =~ /dataset/)
1159 $c->stash->{dataset_id} = $selection_pop_id =~ s/\w+_//r;
1160 $c->controller('solGS::Dataset')->create_dataset_population_metadata_file($c);
1163 my $referer = $c->req->referer;
1164 if ($referer =~ /solgs\/trait\/|solgs\/traits\/all\/population\//)
1166 $c->controller('solGS::solGS')->predict_selection_pop_multi_traits($c);
1168 elsif ($referer =~ /\/combined\//)
1170 $c->stash->{data_set_type} = 'combined populations';
1171 $c->controller('solGS::combinedTrials')->predict_selection_pop_combined_pops_model($c);
1177 sub run_kinship_analysis {
1178 my ($self, $c) = @_;
1180 my $analysis_page = $c->stash->{analysis_page};
1182 if ($analysis_page = ~/kinship\/analysis/)
1184 $c->controller('solGS::Kinship')->run_kinship($c);
1190 sub run_pca_analysis {
1191 my ($self, $c) = @_;
1193 my $analysis_page = $c->stash->{analysis_page};
1195 if ($analysis_page = ~/pca\/analysis/)
1197 $c->controller('solGS::pca')->run_pca($c);
1203 sub run_cluster_analysis {
1204 my ($self, $c) = @_;
1206 my $analysis_page = $c->stash->{analysis_page};
1208 if ($analysis_page = ~/cluster\/analysis/)
1210 $c->controller('solGS::Cluster')->run_cluster($c);
1215 sub update_analysis_progress {
1216 my ($self, $c) = @_;
1218 my $analysis_data = $c->stash->{analysis_profile};
1219 my $analysis_name= $analysis_data->{analysis_name};
1220 my $status = $c->stash->{status};
1222 $self->analysis_log_file($c);
1223 my $log_file = $c->stash->{analysis_log_file};
1225 my @contents = read_file($log_file, {binmode => ':utf8'});
1227 map{ $contents[$_] =~ m/\t$analysis_name\t/
1228 ? $contents[$_] =~ s/error|submitted/$status/ig
1229 : $contents[$_] } 0..$#contents;
1231 write_file($log_file, {binmode => ':utf8'}, @contents);
1236 sub get_user_detail {
1237 my ($self, $c) = @_;
1239 my $user = $c->user();
1241 my $contact;
1242 if ($user)
1244 my $private_email = $user->get_private_email();
1245 my $public_email = $user->get_contact_email();
1247 my $email = $public_email
1248 ? $public_email
1249 : $private_email;
1251 my $salutation = $user->get_salutation();
1252 my $first_name = $user->get_first_name();
1253 my $last_name = $user->get_last_name();
1254 my $user_role = $user->get_object->get_user_type();
1255 my $user_id = $user->get_object()->get_sp_person_id();
1256 my $user_name = $user->id();
1258 $contact = {
1259 'first_name' => $first_name,
1260 'email'=> $email,
1261 'user_role' => $user_role,
1262 'user_id' => $user_id,
1263 'user_name' => $user_name,
1268 return $contact;
1273 sub analysis_log_file {
1274 my ($self, $c) = @_;
1276 $self->create_analysis_log_dir($c);
1277 my $log_dir = $c->stash->{analysis_log_dir};
1279 $c->stash->{cache_dir} = $log_dir;
1281 my $cache_data = {
1282 key => 'analysis_log',
1283 file => 'analysis_log',
1284 stash_key => 'analysis_log_file'
1287 $c->controller('solGS::Files')->cache_file($c, $cache_data);
1292 sub get_confirm_msg {
1293 my ($self, $c, $job) = @_;
1295 $job =~ s/[_|-]/ /g;
1296 $job = lc($job);
1298 my $msg = "Your $job job is submitted.";
1299 return $msg;
1304 sub get_user_solgs_analyses {
1305 my ($self, $c) = @_;
1307 $self->analysis_log_file($c);
1308 my $log_file = $c->stash->{analysis_log_file};
1310 my $ret = {};
1311 my @panel_data;
1313 no warnings 'uninitialized';
1315 if ($log_file)
1317 my @user_analyses = grep{$_ !~ /User_name\s+/i }
1318 read_file($log_file, {binmode => ':utf8'});
1320 $self->index_log_file_headers($c);
1321 my $header_index = $c->stash->{header_index};
1323 my $json = JSON->new();
1324 foreach my $row (@user_analyses)
1326 my @analysis = split(/\t/, $row);
1328 my $arguments = $analysis[5];
1329 $arguments = $json->decode($arguments);
1330 my $analysis_type = $arguments->{analysis_type};
1331 my $analysis_name = $analysis[$header_index->{'Analysis_name'}];
1332 my $result_page = $analysis[$header_index->{'Analysis_page'}];
1333 my $analysis_status = $analysis[$header_index->{'Status'}];
1334 my $submitted_on = $analysis[$header_index->{'Submitted on'}];
1336 if ($analysis_status =~ /Failed/i)
1338 $result_page = 'N/A';
1340 elsif ($analysis_status =~ /Submitted/i)
1342 $result_page = 'In progress...'
1344 else
1346 $result_page = qq |<a href=$result_page>[ View ]</a>|;
1349 my $row = [$analysis_name, $analysis_type, $submitted_on, $analysis_status, $result_page];
1350 push @panel_data, $row;
1354 return \@panel_data;
1358 sub create_analysis_log_dir {
1359 my ($self, $c) = @_;
1361 my $user_id = $c->user->id;
1363 $c->controller('solGS::Files')->get_solgs_dirs($c);
1365 my $log_dir = $c->stash->{analysis_log_dir};
1367 $log_dir = catdir($log_dir, $user_id);
1368 mkpath ($log_dir, 0, 0755);
1370 $c->stash->{analysis_log_dir} = $log_dir;
1375 sub begin : Private {
1376 my ($self, $c) = @_;
1378 $c->controller('solGS::Files')->get_solgs_dirs($c);
1385 __PACKAGE__->meta->make_immutable;
1388 ####
1390 ####