2 package SGN
::Controller
::AJAX
::MixedModels
;
8 use File
::Spec qw
| catfile
|;
10 use File
::Basename qw
| basename
|;
12 use CXGN
::Dataset
::File
;
13 use CXGN
::Phenotypes
::File
;
14 use CXGN
::MixedModels
;
16 BEGIN { extends
'Catalyst::Controller::REST' };
19 default => 'application/json',
21 map => { 'application/json' => 'JSON' },
28 sub model_string
: Path
('/ajax/mixedmodels/modelstring') Args
(0) {
32 my $params = $c->req->body_data();
34 my $engine = $params->{engine
};
35 print STDERR
"ENGINE: $engine\n";
36 my $fixed_factors = $params->{fixed_factors
};
37 print STDERR
"FIXED FACTORS IN MODEL STRING: ".Dumper
($fixed_factors)."\n";
39 my $fixed_factors_interaction = $params->{fixed_factors_interaction
};
41 my $variable_slope_intersects = $params->{variable_slope_intersects
};
43 my $random_factors = $params->{random_factors
};
44 my $dependent_variables = $params->{dependent_variables
};
46 my $mm = CXGN
::MixedModels
->new();
47 if ($dependent_variables) {
48 $mm->dependent_variables($dependent_variables);
51 $mm->fixed_factors( $fixed_factors );
53 if ($fixed_factors_interaction) {
54 $mm->fixed_factors_interaction( $fixed_factors_interaction );
56 if ($variable_slope_intersects) {
57 $mm->variable_slope_intersects( $variable_slope_intersects);
59 if ($random_factors) {
60 $mm->random_factors( $random_factors );
64 if ($engine eq "sommer") {
65 print STDERR
"Generating sommer model...\n";
66 ($model, $error) = $mm->generate_model_sommer();
68 elsif ($engine eq "lme4") {
69 print STDERR
"Generating lme4 model...\n";
70 ($model, $error) = $mm->generate_model();
73 die "Do not know what engine $engine is!\n";
76 print STDERR
"MODEL: ".Dumper
($model)." ERROR: $error\n";
81 dependent_variables
=> $dependent_variables,
86 sub prepare
: Path
('/ajax/mixedmodels/prepare') Args
(0) {
89 my $dataset_id = $c->req->param('dataset_id');
92 $c->stash->{rest
} = {error
=>'You must be logged in first!'};
96 $c->tempfiles_subdir("mixedmodels");
98 my ($fh, $tempfile) = $c->tempfile(TEMPLATE
=>"mixedmodels/mm_XXXXX");
100 my $people_schema = $c->dbic_schema("CXGN::People::Schema");
101 my $schema = $c->dbic_schema("Bio::Chado::Schema", "sgn_chado");
102 my $temppath = $c->config->{basepath
}."/".$tempfile;
104 my $ds = CXGN
::Dataset
::File
->new(people_schema
=> $people_schema, schema
=> $schema, sp_dataset_id
=> $dataset_id, file_name
=> $temppath, quotes
=> 0);
105 $ds->retrieve_phenotypes();
107 # Note: file is cleaned by run_model function in CXGN::MixedModel
109 my $pf = CXGN
::Phenotypes
::File
->new( { file
=> $temppath."_phenotype.txt" });
113 # only use if factor has multiple levels, start from appropriate hardcoded list
115 my @factors = qw
| studyYear programName studyName studyDesign plantingDate locationName replicate rowNumber colNumber germplasmName
|;
116 foreach my $factor (@factors) {
117 if ($pf->distinct_levels_for_factor($factor) > 1) {
118 push @factor_select, $factor;
122 my @traits_select = ();
123 my $traits = $pf->traits();
125 #my $trait_select_checkbox = "trait_select_checkbox";
126 my $dependent_variable_select = "dependent_variable_select";
130 foreach my $trait (@
$traits) {
131 if ($trait =~ m/.+\d{7}/){
132 $trait_html .= '<input type="checkbox" class= "trait_box" name="'.$dependent_variable_select.'" value="'.$trait.'">'.$trait.'</input> </br>';
135 #$html .= "</tbody></table>";
137 #$html .= "<script>jQuery(document).ready(function() { jQuery('#html-dependent_variable_select').DataTable({ 'lengthMenu': [[2, 4, 6, 8, 10, 25, 50, -1], [2, 4, 6, 8, 10, 25, 50, 'All']] }); } );</script>";
139 #$c->stash->{rest} = { select => $html };
141 $c->stash->{rest
} = {
143 dependent_variable
=> $trait_html,
145 factors
=> \
@factor_select,
146 tempfile
=> $tempfile."_phenotype.txt",
149 if (!@factor_select) {
150 $c->stash->{rest
}->{error
} = "There are no factors with multiple levels in this dataset.";
154 sub run
: Path
('/ajax/mixedmodels/run') Args
(0) {
158 my $params = $c->req()->params();
160 my $tempfile = $params->{tempfile
};
161 my $dependent_variables = $params->{'dependent_variables[]'};
162 if (!ref($dependent_variables)) {
163 $dependent_variables = [ $dependent_variables ];
165 my $model = $params->{model
};
166 my $random_factors = $params->{'random_factors[]'}; #
167 if (!ref($random_factors)) {
168 $random_factors = [ $random_factors ];
170 my $fixed_factors = $params->{'fixed_factors[]'}; # "
171 if (!ref($fixed_factors)) {
172 $fixed_factors = [ $fixed_factors ];
175 print STDERR
"sub run: FIXED FACTORS: ".Dumper
($fixed_factors)." RANDOM FACTORS: ".Dumper
($random_factors)."\n";
176 my $engine = $params->{engine
};
178 print STDERR
"ENGINE = $engine\n";
180 my $mm = CXGN
::MixedModels
->new( { tempfile
=> $c->config->{basepath
}."/".$tempfile });
182 $mm->dependent_variables($dependent_variables);
183 $mm->random_factors($random_factors);
184 $mm->fixed_factors($fixed_factors);
185 $mm->engine($engine);
186 my $error = $mm->run_model($c->config->{backend
}, $c->config->{cluster_host
}, $c->config->{cluster_shared_tempdir
} . "/mixed_models" );
188 my $temppath = $c->config->{basepath
}."/".$tempfile;
190 my $adjusted_blups_file = $temppath.".adjustedBLUPs";
191 #print STDERR "ADJUSTED BLUP FILES: ".Dumper($adjusted_blups_file);
192 my $blupfile = $temppath.".BLUPs";
193 my $bluefile = $temppath.".BLUEs";
194 my $adjusted_blues_file = $temppath.".adjustedBLUEs";
195 my $anovafile = $temppath.".anova";
196 my $varcompfile = $temppath.".varcomp";
201 my $adjusted_blups_html;
202 my $adjusted_blups_data;
204 my $adjusted_blues_html;
205 my $adjusted_blues_data;
211 # we need either a blup or blue result file. Check for these and otherwise return an error!
215 if ( -e
$adjusted_blups_file) {
217 ($adjusted_blups_data, $adjusted_blups_html, $accession_names, $traits) = $self->result_file_to_hash($c, $adjusted_blups_file);
219 elsif (-e
$adjusted_blues_file) {
221 ($adjusted_blues_data, $adjusted_blues_html, $accession_names, $traits) = $self->result_file_to_hash($c, $adjusted_blues_file);
225 $error = "The analysis could not be completed. The factors may not have sufficient numbers of levels to complete the analysis. Please choose other parameters.";
227 $c->stash->{rest
} = { error
=> $error };
231 # read other result files, if they exist and parse into data structures
239 ($blups_data, $blups_html, $accession_names, $traits) = $self->result_file_to_hash($c, $blupfile);
242 elsif (-e
$bluefile) {
244 ($blues_data, $blues_html, $accession_names, $traits) = $self->result_file_to_hash($c, $bluefile);
248 $error = "The analysis could not be completed. The factors may not have sufficient numbers of levels to complete the analysis. Please choose other parameters.";
249 $c->stash->{rest
} = { error
=> $error };
255 accession_names
=> $accession_names,
256 adjusted_blups_data
=> $adjusted_blups_data,
257 adjusted_blups_html
=> $adjusted_blups_html,
258 adjusted_blues_data
=> $adjusted_blues_data,
259 adjusted_blues_html
=> $adjusted_blues_html,
260 blups_data
=> $blups_data,
261 blups_html
=> $blups_html,
262 blues_data
=> $blues_data,
263 blues_html
=> $blues_html,
265 input_file
=> $temppath,
269 $c->stash->{rest
} = $response;
272 sub result_file_to_hash
{
277 print STDERR
"result_file_to_hash(): Processing file $file...\n";
278 my @lines = read_file
($file);
281 my $header_line = shift(@lines);
282 my ($accession_header, @value_cols) = split /\t/, $header_line;
284 my $now = DateTime
->now();
285 my $timestamp = $now->ymd()."T".$now->hms();
287 my $operator = $c->user()->get_object()->get_first_name()." ".$c->user()->get_object()->get_last_name();
293 my $html = qq | <style
> th
, td
{padding
: 10px
;} </style
> \n <table cellpadding
="20" cellspacing
="20"> |;
295 $html .= "<br><tr><th>accession name</th>";
296 for (my $m=0; $m<@value_cols; $m++) {
297 $html .= "<th scope=\"col\">".($value_cols[$m])."</th>";
299 $html .= "</tr><tr>";
300 foreach my $line (@lines) {
301 my ($accession_name, @values) = split /\t/, $line;
302 push @accession_names, $accession_name;
303 $html .= "<tr><td>$accession_name</td>";
305 for (my $k=0; $k<@value_cols; $k++) {
306 #print STDERR "adding $values[$k] to column $value_cols[$k]\n";
307 $html .= "<td>".($values[$k])."</td>";
310 for(my $n=0; $n<@values; $n++) {
311 #print STDERR "Building hash for trait $accession_name and value $value_cols[$n]\n";
312 $analysis_data{$accession_name}->{$value_cols[$n]} = [ $values[$n], $timestamp, $operator, "", "" ];
321 #print STDERR "Analysis data formatted: ".Dumper(\%analysis_data);
323 return (\
%analysis_data, $html, \
@accession_names, \
@value_cols);
327 sub extract_trait_data
:Path
('/ajax/mixedmodels/grabdata') Args
(0) {
331 my $file = $c->req->param("file");
332 my $trait = $c->req->param("trait");
334 $file = basename
($file);
336 my $temppath = File
::Spec
->catfile($c->config->{basepath
}, "static/documents/tempfiles/mixedmodels/".$file);
339 if (! open($F, "<", $temppath)) {
340 $c->stash->{rest
} = { error
=> "Can't find data." };
347 my @keys = split("\t", $header);
354 my @fields = split "\t";
356 for(my $n=0; $n <@keys; $n++) {
357 if (exists($fields[$n]) && defined($fields[$n])) {
358 $line{$keys[$n]}=$fields[$n];
364 $c->stash->{rest
} = { data
=> \
@data, trait
=> $trait};
368 sub make_R_trait_name
{