clean
[sgn.git] / lib / solGS / AnalysisReport.pm
blob874321a8e3fbcef81cf2670c95a9fbaf6b1066a0
1 package solGS::AnalysisReport;
3 use Moose;
4 use namespace::autoclean;
6 use Email::Sender::Simple qw /sendmail/;
7 use Email::Simple;
8 use Email::Simple::Creator;
9 use File::Spec::Functions qw /catfile catdir/;
10 use File::Slurp qw /write_file read_file/;
11 use Storable qw/ nstore retrieve /;
14 with 'MooseX::Getopt';
15 with 'MooseX::Runnable';
17 has 'output_details_file' => (
18 is => 'ro',
19 isa => 'Str',
20 required => 1,
25 sub run {
26 my $self = shift;
28 my $output_details = retrieve($self->output_details_file);
29 $self->check_analysis_status($output_details);
34 sub check_analysis_status {
35 my ($self, $output_details) = @_;
37 $output_details = $self->check_success($output_details);
39 $self->log_analysis_status($output_details);
40 $self->report_status($output_details);
45 sub check_success {
46 my ($self, $output_details) = @_;
48 my $analysis_profile = $output_details->{analysis_profile};
50 if ( $analysis_profile->{analysis_type} =~ /population download/ )
52 $output_details = $self->check_population_download($output_details);
54 elsif ( $analysis_profile->{analysis_type} =~ /(single|multiple) model/ )
56 if ($output_details->{data_set_type} =~ /combined populations/)
58 $output_details = $self->check_combined_pops_trait_modeling($output_details);
60 elsif ($output_details->{data_set_type} =~ /single population/)
62 $output_details = $self->check_trait_modeling($output_details);
65 elsif ( $analysis_profile->{analysis_type} =~ /combine populations/ )
67 $output_details = $self->check_multi_pops_data_download($output_details);
69 elsif ( $analysis_profile->{analysis_type} =~ /selection prediction/ )
71 if ($output_details->{data_set_type} =~ /combined populations/)
73 # $output_details = $self->check_combined_pops_trait_modeling($output_details);
74 $output_details = $self->check_selection_prediction($output_details);
76 elsif ($output_details->{data_set_type} =~ /single population/)
78 $output_details = $self->check_selection_prediction($output_details);
83 return $output_details;
87 sub check_combined_pops_trait_modeling {
88 my ($self, $output_details) = @_;
90 $output_details = $self->check_pops_trait_data_combination($output_details);
91 $output_details = $self->check_trait_modeling($output_details);
93 return $output_details;
97 sub check_pops_trait_data_combination {
98 my ($self, $output_details) = @_;
100 my $job_tempdir = $output_details->{r_job_tempdir};
102 foreach my $k (keys %{$output_details})
104 if ($k =~ /population_id/)
106 my $pheno_file;
107 my $geno_file;
109 if (ref $output_details->{$k} eq 'HASH')
111 $pheno_file = $output_details->{$k}->{phenotype_file};
112 $geno_file = $output_details->{$k}->{genotype_file};
115 if ($geno_file || $pheno_file)
117 my $pheno_size;
118 my $geno_size;
119 my $died_file;
121 while (1)
123 sleep 60;
124 $pheno_size = -s $pheno_file;
125 $geno_size = -s $geno_file;
127 if ($pheno_size)
129 $output_details->{$k}->{pheno_success} = 'pheno success';
132 if ($geno_size)
134 $output_details->{$k}->{geno_success} = 'geno success';
137 if ($pheno_size && $geno_size)
139 $output_details->{$k}->{success} = 1;
140 $output_details->{status} = 'Done';
141 last;
143 else
145 if ($job_tempdir)
147 $died_file = $self->get_file($job_tempdir, 'died');
148 if ($died_file)
150 $output_details->{$k}->{pheno_success} = 0;
151 $output_details->{$k}->{geno_success} = 0;
152 $output_details->{$k}->{success} = 0;
153 $output_details->{status} = 'Failed';
154 last;
160 else
162 if (ref $output_details->{$k} eq 'HASH')
164 $output_details->{$k}->{pheno_success} = 0;
165 $output_details->{$k}->{geno_success} = 0;
166 $output_details->{$k}->{success} = 0;
167 $output_details->{status} = 'Failed';
173 return $output_details;
178 sub check_multi_pops_data_download {
179 my ($self, $output_details) = @_;
181 my $job_tempdir = $output_details->{r_job_tempdir};
183 my $no_match = $output_details->{no_match};
185 foreach my $k (keys %{$output_details})
187 my $pheno_file;
188 my $geno_file;
189 if ($k =~ /population_id/)
191 if (ref $output_details->{$k} eq 'HASH')
193 $pheno_file = $output_details->{$k}->{phenotype_file};
194 $geno_file = $output_details->{$k}->{genotype_file};
195 print STDERR "\n $k - pheno_file: $pheno_file -- geno_file: $geno_file\n";
198 if ($geno_file && $pheno_file)
200 my $pheno_size;
201 my $geno_size;
202 my $died_file;
204 while (1)
206 sleep 60;
207 $pheno_size = -s $pheno_file;
208 $geno_size = -s $geno_file;
210 if ($pheno_size)
212 $output_details->{$k}->{pheno_success} = 'pheno success';
215 if ($geno_size)
217 $output_details->{$k}->{geno_success} = 'geno success';
220 if ($pheno_size && $geno_size)
222 $output_details->{$k}->{success} = 1;
223 $output_details->{status} = 'Done';
224 last;
226 else
228 if ($job_tempdir)
230 print STDERR "\n job_tempdir: $job_tempdir\n";
231 $died_file = $self->get_file($job_tempdir, 'died');
232 if ($died_file)
234 $output_details->{$k}->{pheno_success} = 0;
235 $output_details->{$k}->{geno_success} = 0;
236 $output_details->{$k}->{success} = 0;
237 $output_details->{status} = 'Failed';
238 last;
244 else
246 if (ref $output_details->{$k} eq 'HASH')
248 $output_details->{$k}->{pheno_success} = 0;
249 $output_details->{$k}->{geno_success} = 0;
250 $output_details->{$k}->{success} = 0;
251 $output_details->{status} = 'Failed';
257 return $output_details;
261 sub check_selection_prediction {
262 my ($self, $output_details) = @_;
264 my $job_tempdir = $output_details->{r_job_tempdir};
266 foreach my $k (keys %{$output_details})
268 if ($k =~ /trait_id/)
270 my $gebv_file;
271 if (ref $output_details->{$k} eq 'HASH')
273 if ($output_details->{$k}->{trait_id})
275 $gebv_file = $output_details->{$k}->{gebv_file};
278 if ($gebv_file)
280 my $gebv_size;
281 my $died_file;
283 while (1)
285 sleep 60;
286 $gebv_size = -s $gebv_file;
288 if ($gebv_size)
290 $output_details->{$k}->{success} = 1;
291 $output_details->{status} = 'Done';
292 last;
294 else
296 if ($job_tempdir)
298 $died_file = $self->get_file($job_tempdir, 'died');
299 if ($died_file)
301 $output_details->{$k}->{success} = 0;
302 $output_details->{status} = 'Failed';
303 last;
310 else
312 if (ref $output_details->{$k} eq 'HASH')
314 $output_details->{$k}->{success} = 0;
315 $output_details->{status} = 'Failed';
321 return $output_details;
326 sub check_trait_modeling {
327 my ($self, $output_details) = @_;
329 my $job_tempdir = $output_details->{r_job_tempdir};
331 foreach my $k (keys %{$output_details})
333 if ($k =~ /trait_id/)
335 my $gebv_file;
336 if (ref $output_details->{$k} eq 'HASH')
338 if ($output_details->{$k}->{trait_id})
340 $gebv_file = $output_details->{$k}->{gebv_file};
343 if ($gebv_file)
345 my $gebv_size;
346 my $died_file;
348 while (1)
350 sleep 60;
351 $gebv_size = -s $gebv_file;
353 if ($gebv_size)
355 $output_details->{$k}->{success} = 1;
356 $output_details->{status} = 'Done';
357 last;
359 else
361 if ($job_tempdir)
363 $died_file = $self->get_file($job_tempdir, 'died');
364 if ($died_file)
366 $output_details->{$k}->{success} = 0;
367 $output_details->{status} = 'Failed';
368 last;
375 else
377 if (ref $output_details->{$k} eq 'HASH')
379 $output_details->{$k}->{success} = 0;
380 $output_details->{status} = 'Failed';
386 return $output_details;
390 sub check_population_download {
391 my ($self, $output_details) = @_;
393 my $job_tempdir = $output_details->{r_job_tempdir};
395 foreach my $k (keys %{$output_details})
397 if ($k =~ /population_id/)
399 my $pheno_file;
400 my $geno_file;
402 if (ref $output_details->{$k} eq 'HASH')
404 if ($output_details->{$k}->{population_id})
406 $pheno_file = $output_details->{$k}->{phenotype_file};
407 $geno_file = $output_details->{$k}->{genotype_file};
409 if ($pheno_file && $geno_file)
411 my $pheno_size;
412 my $geno_size;
413 my $died_file;
415 while (1)
417 sleep 60;
418 $pheno_size = -s $pheno_file;
419 $geno_size = -s $geno_file;
421 unless (!$pheno_size)
423 $output_details->{$k}->{pheno_success} = 1;
426 unless (!$geno_size)
428 $output_details->{$k}->{geno_success} = 1;
431 if ($pheno_size && $geno_size)
433 $output_details->{$k}->{success} = 1;
434 $output_details->{status} = 'Done';
435 last;
437 else
439 if ($job_tempdir)
441 $died_file = $self->get_file($job_tempdir, 'died');
442 if ($died_file)
444 $output_details->{$k}->{pheno_success} = 0;
445 $output_details->{$k}->{geno_success} = 0;
446 $output_details->{$k}->{success} = 0;
447 $output_details->{status} = 'Failed';
448 last;
454 else
456 if (ref $output_details->{$k} eq 'HASH')
458 $output_details->{$k}->{pheno_success} = 0;
459 $output_details->{$k}->{geno_success} = 0;
460 $output_details->{$k}->{success} = 0;
461 $output_details->{status} = 'Failed';
469 return $output_details;
474 sub get_file {
475 my ($self, $dir, $exp) = @_;
477 opendir my $dh, $dir
478 or die "can't open $dir: $!\n";
480 my ($file) = grep { /$exp/ && -f "$dir/$_" } readdir($dh);
481 close $dh;
483 if ($file)
485 $file = catfile($dir, $file);
488 return $file;
492 sub report_status {
493 my ($self, $output_details) = @_;
495 my $analysis_profile = $output_details->{analysis_profile};
496 my $user_email = $analysis_profile->{user_email};
497 my $user_name = $analysis_profile->{user_name};
499 my $analysis_page = $analysis_profile->{analysis_page};
500 my $analysis_name = $analysis_profile->{analysis_name};
501 my $analysis_type = $analysis_profile->{analysis_type};
503 my $analysis_result;
505 if ($analysis_type =~ /multiple models/)
507 $analysis_result = $self->multi_modeling_message($output_details);
509 elsif ($analysis_type =~ /single model/)
511 $analysis_result = $self->single_modeling_message($output_details);
513 elsif ($analysis_type =~ /population download/ )
515 $analysis_result = $self->population_download_message($output_details);
517 elsif ($analysis_type =~ /combine populations/ )
519 $analysis_result = $self->combine_populations_message($output_details);
521 elsif ($analysis_type =~ /selection prediction/ )
523 $analysis_result = $self->selection_prediction_message($output_details);
526 my $closing = "If you have any remarks, please contact us:\n"
527 . $output_details->{contact_page}
528 ."\n\nThanks and regards,\nsolGS M Tool";
530 my $body = "Dear $user_name,\n"
531 . "\n$analysis_result"
532 . "$closing";
534 my $email_from;
535 my $email_to;
536 my $email_cc;
538 if ($output_details->{host} =~ /localhost/)
540 my $uid = getpwuid($<);
541 $email_from = '"' . $uid .'" <' . $uid . '@localhost.localdomain>';
542 $email_to = '"' . $uid .'" <' . $uid . '@localhost.localdomain>';
544 else
546 $email_from = '"solGS M Tool" <cluster-jobs@solgenomics.net>';
547 $email_to = "$user_name <$user_email>";
548 $email_cc = 'solGS Job <cluster-jobs@solgenomics.net>';
551 my $email = Email::Simple->create(
552 header => [
553 From => $email_from,
554 To => $email_to,
555 Cc => $email_cc,
556 Subject => "Analysis result of $analysis_name",
558 body => $body,
561 sendmail($email);
566 sub multi_modeling_message {
567 my ($self, $output_details) = @_;
569 my $message;
570 my $cnt = 0;
572 foreach my $k (keys %{$output_details})
574 if ($k =~ /trait_id/)
576 my $all_success;
578 if (ref $output_details->{$k} eq 'HASH')
580 if ($output_details->{$k}->{trait_id})
582 if ($output_details->{$k}->{success})
584 $cnt++;
585 $all_success = 1;
586 my $trait_name = uc($output_details->{$k}->{trait_name});
587 my $trait_page = $output_details->{$k}->{trait_page};
588 $message .= "The analysis for $trait_name is done."
589 ." You can view the model output here:"
590 ."\n\n$trait_page\n\n";
592 else
594 $all_success = 0;
595 my $trait_name = uc($output_details->{$k}->{trait_name});
596 $message .= "The analysis for $trait_name failed.\n\n";
602 if ($cnt > 1 )
604 $message .= "You can also view the summary of all the analyses in the page below."
605 ."\nAdditionally, you may find the analytical features in the page useful.\n"
606 . $output_details->{analysis_profile}->{analysis_page} ."\n\n";
609 return $message;
613 sub single_modeling_message {
614 my ($self, $output_details) = @_;
616 my $message;
617 foreach my $k (keys %{$output_details})
620 if ($k =~ /trait_id/)
622 my $gebv_file;
623 if (ref $output_details->{$k} eq 'HASH')
625 if ($output_details->{$k}->{trait_id})
627 my $trait_name = uc($output_details->{$k}->{trait_name});
628 my $trait_page = $output_details->{$k}->{trait_page};
629 $gebv_file = $output_details->{$k}->{gebv_file};
631 if ($output_details->{$k}->{success})
633 $message = "The analysis for $trait_name is done."
634 ."\nYou can view the model output here:"
635 ."\n\n$trait_page\n\n";
637 else
639 $message = "The analysis for $trait_name failed."
640 ."\n\nWe are troubleshooting the cause. "
641 . "We will contact you when we find out more.";
648 return $message;
652 sub selection_prediction_message {
653 my ($self, $output_details) = @_;
655 my $message;
656 my $cnt = 0;
657 foreach my $k (keys %{$output_details})
659 if ($k =~ /trait_id/)
661 my $gebv_file;
662 if (ref $output_details->{$k} eq 'HASH')
664 if ($output_details->{$k}->{trait_id})
666 my $trait_name = uc($output_details->{$k}->{trait_name});
667 my $training_pop_page = $output_details->{$k}->{training_pop_page};
668 my $model_page = $output_details->{$k}->{model_page};
669 my $prediction_pop_name = $output_details->{$k}->{prediction_pop_name};
671 if ($output_details->{$k}->{success})
673 $cnt++;
674 if($cnt == 1)
676 $message .= "The prediction of selection population $prediction_pop_name is done."
677 . "\nYou can view the prediction output by clicking the trait name "
678 . "\nat the bottom of the model page(s):\n\n";
681 $message .= "$model_page\n\n";
683 else
685 $message .= "The analysis for $trait_name failed."
686 ."\n\nWe are troubleshooting the cause. "
687 . "We will contact you when we find out more.";
690 if ($cnt > 1)
692 $message .= "You can also view the summary of all the analyses in the page below."
693 ."\nAdditionally, you may find the analytical features in the page useful.\n"
694 . $output_details->{referer} . "\n\n";
701 return $message;
705 sub population_download_message {
706 my ($self, $output_details) = @_;
708 my $message;
710 foreach my $k (keys %{$output_details})
712 if ($k =~ /population_id/)
714 if (ref $output_details->{$k} eq 'HASH')
716 if ($output_details->{$k}->{population_id})
718 my $pop_name = uc($output_details->{$k}->{population_name});
719 my $pop_page = $output_details->{$k}->{population_page};
721 if ($output_details->{$k}->{success})
723 $message = "The phenotype and genotype data for $pop_name is ready for analysis."
724 ."\nYou can view the training population page here:\n"
725 ."\n$pop_page.\n\n";
727 else
729 $message = "Downloading phenotype and genotype data for $pop_name failed."
730 ."\nWe are troubleshooting the cause. "
731 . "We will contact you when we find out more.";
738 return $message;
742 sub combine_populations_message {
743 my ($self, $output_details) = @_;
745 my $no_match = $output_details->{no_match};
747 my $message;
749 if ($no_match)
751 $message = $no_match
752 . " can not be combined.\n"
753 . "Possibly the the populations were genotyped\n"
754 . "with different marker sets or querying the data for one or more of the\n"
755 . "populations failed. See details below:\n\n";
757 my $troost_mededeling;
759 foreach my $k (keys %{$output_details})
761 if ($k =~ /population_id/)
763 if (ref $output_details->{$k} eq 'HASH')
765 if ($output_details->{$k}->{population_id})
767 my $pop_name = uc($output_details->{$k}->{population_name});
768 my $pop_page = $output_details->{$k}->{population_page};
770 if ($output_details->{$k}->{success})
772 $message .= "The phenotype and genotype data for $pop_name is succesfuly downloaded."
773 ."\nYou can view the population here:"
774 ."\n$pop_page.\n\n";
776 else
778 $message .= "Downloading phenotype and genotype data for $pop_name failed.";
779 $troost_mededeling = "\n\nWe are troubleshooting the cause. "
780 . "We will contact you when we find out more.";
787 $message .= $troost_mededeling;
789 else
791 my $combined_pops_page = $output_details->{combined_pops_page};
792 $message .= "Your combined training population is ready for analysis."
793 ."You can view it here:\n\n$combined_pops_page\n\n";
796 return $message;
800 sub log_analysis_status {
801 my ($self, $output_details) = @_;
803 my $log_file = $output_details->{analysis_log_file};
805 my $analysis_profile = $output_details->{analysis_profile};
806 my $analysis_name = $analysis_profile->{analysis_name};
808 my $status = $output_details->{status};
810 my @contents = read_file($log_file);
812 map{ $contents[$_] =~ m/\t$analysis_name\t/
813 ? $contents[$_] =~ s/error|submitted/$status/ig
814 : $contents[$_] } 0..$#contents;
816 write_file($log_file, @contents);
824 __PACKAGE__->meta->make_immutable;
829 ####
830 1; #
831 ####