Merge pull request #5205 from solgenomics/topic/generic_trial_upload
[sgn.git] / js / source / entries / mixedmodels.js
blobbe743b3738e406804436427b7350c5c56191af2b
2 import '../legacy/jquery.js';
3 import '../legacy/d3/d3Min.js';
5 var version = '0.01';
7 export function init(main_div) {
8     if (!(main_div instanceof HTMLElement)) {
9         main_div = document.getElementById(main_div.startsWith("#") ? main_div.slice(1) : main_div);
10     }
12     var dataset_id;
14     alert("WELCOME TO MIXED MODELS!");
15     get_select_box("datasets", "mixed_model_dataset_select", { "checkbox_name": "mixed_model_dataset_select_checkbox" });
17     jQuery('#mixed_model_analysis_prepare_button').removeClass('active').addClass('inactive');
19     $(document).on('click', 'input[name=select_engine]', function (e) {
20         //alert('clicked select engine!');
21         get_model_string();
22     });
25     $(document).on('click', '#open_store_adjusted_blups_dialog_button', function (e) {
26         $('#generic_save_analysis_dialog').modal("show");
27         $('#generic_save_analysis_model_properties').val(model_properties);
28         $('#generic_save_analysis_protocol').val($('#model_string').html());
29         $('#generic_save_analysis_dataset_id').val(dataset_id);
30         $('#generic_save_analysis_accession_names').val(accession_names);
31         $('#generic_save_analysis_dataset_id').val(get_dataset_id());
32         $('#generic_save_analysis_trait_names').val(traits);
33         $('#generic_save_analysis_statistical_ontology_term').val('Adjusted means from BLUPs using LMER R|SGNSTAT:0000034');
34         $('#generic_save_analysis_model_language').val('R');
35         $('#generic_save_analysis_model_application_name').val('Breedbase Mixed Model Tool');
36         $('#generic_save_analysis_model_application_version').val(version);
37         $('#generic_save_analysis_model_type').val('mixed_model_lmer');
38         $('#generic_save_analysis_result_values').val(adjusted_blups_data);
39         $('#generic_save_analysis_result_values_type').val('analysis_result_values_match_accession_names');
40         $('#generic_save_analysis_result_summary_values').val(result_summary);
41         $('#generic_save_analysis_model_training_data_file').val(input_file);
42         $('#generic_save_analysis_model_archived_training_data_file_type').val('mixed_model_input_data');
43     });
45     $(document).on('click', '#open_store_blups_dialog_button', function (e) {
46         $('#generic_save_analysis_dialog').modal("show");
47         $('#generic_save_analysis_model_properties').val(model_properties);
48         $('#generic_save_analysis_protocol').val($('#model_string').html());
49         $('#generic_save_analysis_dataset_id').val(dataset_id);
50         $('#generic_save_analysis_accession_names').val(accession_names);
51         $('#generic_save_analysis_dataset_id').val(get_dataset_id());
52         $('#generic_save_analysis_trait_names').val(traits);
53         $('#generic_save_analysis_statistical_ontology_term').val('Phenotypic BLUPs using LMER R|SGNSTAT:0000035');
54         $('#generic_save_analysis_model_language').val('R');
55         $('#generic_save_analysis_model_application_name').val('Breedbase Mixed Model Tool');
56         $('#generic_save_analysis_model_application_version').val(version);
57         $('#generic_save_analysis_model_type').val('mixed_model_lmer');
58         $('#generic_save_analysis_result_values').val(blups_data);
59         $('#generic_save_analysis_result_values_type').val('analysis_result_values_match_accession_names');
60         $('#generic_save_analysis_result_summary_values').val(result_summary);
61         $('#generic_save_analysis_model_training_data_file').val(input_file);
62         $('#generic_save_analysis_model_archived_training_data_file_type').val('mixed_model_input_data');
63     });
65     $(document).on('click', '#open_store_adjusted_blues_dialog_button', function (e) {
66         $('#generic_save_analysis_dialog').modal("show");
67         $('#generic_save_analysis_model_properties').val(model_properties);
68         $('#generic_save_analysis_protocol').val($('#model_string').html());
69         $('#generic_save_analysis_dataset_id').val(dataset_id);
70         $('#generic_save_analysis_accession_names').val(accession_names);
71         $('#generic_save_analysis_dataset_id').val(get_dataset_id());
72         $('#generic_save_analysis_trait_names').val(traits);
73         $('#generic_save_analysis_statistical_ontology_term').val('Adjusted means from BLUEs using LMER R|SGNSTAT:0000036');
74         $('#generic_save_analysis_model_language').val('R');
75         $('#generic_save_analysis_model_application_name').val('Breedbase Mixed Model Tool');
76         $('#generic_save_analysis_model_application_version').val(version);
77         $('#generic_save_analysis_model_type').val('mixed_model_lmer');
78         $('#generic_save_analysis_result_summary_values').val(result_summary);
79         $('#generic_save_analysis_result_values_type').val('analysis_result_values_match_accession_names');
80         $('#generic_save_analysis_model_training_data_file').val(input_file);
81         $('#generic_save_analysis_model_archived_training_data_file_type').val('mixed_model_input_data');
82     });
84     $(document).on('click', '#open_store_blues_dialog_button', function (e) {
85         $('#generic_save_analysis_dialog').modal("show");
86         $('#generic_save_analysis_model_properties').val(model_properties);
87         $('#generic_save_analysis_protocol').val($('#model_string').html());
88         $('#generic_save_analysis_dataset_id').val(dataset_id);
89         $('#generic_save_analysis_accession_names').val(accession_names);
90         $('#generic_save_analysis_dataset_id').val(get_dataset_id());
91         $('#generic_save_analysis_trait_names').val(traits);
92         $('#generic_save_analysis_statistical_ontology_term').val('Phenotypic BLUEs using LMER R|SGNSTAT:0000037');
93         $('#generic_save_analysis_model_language').val('R');
94         $('#generic_save_analysis_model_application_name').val('Breedbase Mixed Model Tool');
95         $('#generic_save_analysis_model_application_version').val(version);
96         $('#generic_save_analysis_model_type').val('mixed_model_lmer');
97         $('#generic_save_analysis_result_values_type').val('analysis_result_values_match_accession_names');
98         $('#generic_save_analysis_result_summary_values').val(result_summary);
99         $('#generic_save_analysis_model_training_data_file').val(input_file);
100         $('#generic_save_analysis_model_archived_training_data_file_type').val('mixed_model_input_data');
101     });
103     $('#mixed_model_analysis_prepare_button').click(function () {
105         dataset_id = get_dataset_id();
106         if (dataset_id != false) {
107             $.ajax({
108                 url: '/ajax/mixedmodels/prepare',
109                 data: { 'dataset_id': get_dataset_id() },
110                 success: function (r) {
111                     if (r.error) {
112                         alert(r.error);
113                     }
114                     else {
115                         $('#dependent_variable').html(r.dependent_variable);
116                         var html = "";
118                         for (var n = 0; n < r.factors.length; n++) {
119                             html += "<div id=\"factor_" + n + "\" class=\"container factor\">" + r.factors[n] + "</div>";
120                         }
121                         $('#factors').html(html);
123                         for (var n = 0; n < r.factors.length; n++) {
124                             $('#factor_' + n).draggable({ helper: "clone", revert: "invalid" });
125                         }
127                         $('#tempfile').html(r.tempfile);
128                         //$('#workflow').
130                     }
131                     $('#fixed_factors').droppable({
132                         drop: function (event, ui) {
133                             $(this)
134                                 //.addClass( "ui-state-highlight" )
135                                 .find("p")
136                                 .html("Dropped!");
137                             var droppable = $(this);
138                             var draggable = ui.draggable;
139                             // Move draggable into droppable
140                             var clone = draggable.clone();
141                             clone.draggable({ revert: "invalid", helper: "clone" });
142                             clone.css("z-index", 3);
143                             if (!isCloned(clone)) {
144                                 setClonedTagProperties(clone);
145                             }
147                             clone.appendTo(droppable);
148                             get_model_string();
149                         }
150                     });
152                     $('#random_factors').droppable({
153                         drop: function (event, ui) {
154                             $(this)
155                                 //.addClass( "ui-state-highlight" )
156                                 .find("p")
157                                 .html("Dropped!");
158                             var droppable = $(this);
159                             var draggable = ui.draggable;
160                             // Move draggable into droppable
161                             var clone = draggable.clone();
162                             clone.draggable({ revert: "invalid", helper: "clone" });
163                             clone.css("z-index", 3);
164                             if (!isCloned(clone)) {
165                                 setClonedTagProperties(clone);
166                             }
168                             clone.appendTo(droppable);
169                             get_model_string();
170                         }
171                     });
173                 },
174                 error: function (r) {
175                     alert("ERROR!!!!!");
176                 }
177             });
178         }
179     });
182     $('#add_interaction_factor_button').click(function (e) {
184         add_sub_div("interaction_factors_collection", "interaction", "Interaction");
185     });
187     $('#add_variable_slope_intersect_button').click(function (e) {
188         add_sub_div("variable_slope_intersect_collection", "variable_slope_intersect", "Variable slope/intersect");
189     });
192     var factor_count;
193     var accession_names;
195     var adjusted_blups_data;
196     var blups_data;
198     var adjusted_blues_data;
199     var blues_data;
201     var traits;
202     var stat_ontology_term;
204     var model_properties;
205     var result_summary;
206     var input_file;
208     function add_sub_div(collection_div, div_prefix, collection_name) {
210         if (factor_count === undefined) { factor_count = 0; }
212         var previous_div = factor_count;
213         factor_count++;
215         var div_name = div_prefix + factor_count;
217         var div = '<div id="' + div_name + '_panel" class="panel panel-default" style="border-width:0px"><div id="' + div_name + '_header" class="panel-header"><span id="close_interaction_div_' + factor_count + '" class="remove">X</span> ' + collection_name + ' Term ' + factor_count + '</div><div id="' + div_name + '" class="panel-body factor_panel" ></div></div>';
219         $('#' + collection_div).append(div);
221         $('#' + div_name).droppable({
222             drop: function (event, ui) {
223                 var droppable = $(this);
224                 var draggable = ui.draggable;
225                 // Move draggable into droppable
226                 var clone = draggable.clone();
227                 clone.draggable({ revert: "invalid", helper: "clone" });
228                 clone.css("z-index", 2);
229                 if (!isCloned(clone)) {
230                     setClonedTagProperties(clone);
231                 }
233                 clone.appendTo(droppable);
234                 get_model_string();
235             }
236         });
238         $(document).on("click", "span.remove", function (e) {
239             this.parentNode.parentNode.remove(); get_model_string();
240         });
243     }
245     function isCloned(e) {
246         if (e.text().includes('X')) {
247             return true;
248         }
250         return false;
251     }
252     //onclick="this.parentNode.parentNode.removeChild(this.parentNode); return false;">
253     function setClonedTagProperties(e) {
254         e.id = e.html() + 'C';
255         var html = '<span id="' + e.id + '_remove" class="remove_factor">X</a></span> ' + e.html();
256         e.html(html);
257         $(document).on("click", "span.remove_factor", function (e) { this.parentNode.remove(); get_model_string() });
258     }
260     $('#dependent_variable').click('#dependent_variable_select', function () {
261         var tempfile = $('#tempfile').html();
262         var trait_selected = [];
263         $('.trait_box:checked').each(function () {
264             trait_selected.push($(this).val());
265         });
267         if (trait_selected.length > 1 || trait_selected.length == 0) {
268             jQuery('#trait_histogram').html('Please select only one trait at a time to see the histogram!');
269         } else {
271             var trait = trait_selected[0];
274             $.ajax({
275                 url: '/ajax/mixedmodels/grabdata',
276                 data: { 'file': tempfile },
277                 success: function (r) {
278                     var v = {
279                         "$schema": "https://vega.github.io/schema/vega-lite/v2.json",
280                         "width": 200,
281                         "height": 100,
282                         "padding": 5,
283                         "data": { 'values': r.data },
284                         "mark": "bar",
285                         "encoding": {
286                             "x": {
287                                 "bin": true,
288                                 "field": trait,
289                                 "type": "quantitative"
290                             },
291                             "y": {
292                                 "aggregate": "count",
293                                 "type": "quantitative"
294                             }
295                         }
296                     };
298                     vegaEmbed("#trait_histogram", v);
299                 },
302                 error: function (e) { alert('error!'); }
303             });
305         }
307     });
309     $('#run_mixed_model_button').click(function () {
310         var model = $('#model_string').text();
311         var fixed_factors = parse_simple_factors("fixed_factors");
312         //alert("FIXED FACTORS: "+fixed_factors);
313         var random_factors = parse_simple_factors("random_factors");
314         var engine = $('input[name="select_engine"]:checked').val();
315         //alert("Engine is "+engine);
316         var tempfile = $('#tempfile').text();
318         var dependent_variables = [];
320         $('input[name=dependent_variable_select]:checked').each(function () {
321             dependent_variables.push(jQuery(this).val());
322         });
323         console.log(dependent_variables);
324         $('#working_modal').modal("show");
325         $.ajax({
326             "url": '/ajax/mixedmodels/run',
327             "method": "POST",
328             "data": {
329                 "model": model,
330                 "tempfile": tempfile,
331                 "dependent_variables": dependent_variables,
332                 "fixed_factors": fixed_factors,
333                 "random_factors": random_factors,
334                 "engine": engine
335             },
336             "success": function (r) {
337                 $('#working_modal').modal("hide");
338                 if (r.error) { alert(r.error); }
339                 else {
340                     if (r.method === 'random') {
341                         $('#mixed_models_adjusted_blups_results_div').html(r.adjusted_blups_html);
342                         $('#mixed_models_blups_results_div').html(r.blups_html);
344                         $('#adjusted_blups_tab_link').show();
345                         $('#adjusted_blups_tab_link').addClass('active');
346                         $('#blups_tab_link').show();
348                         $('#adjusted_blues_tab_link').removeClass('active');
349                         $('#adjusted_blues_tab_link').hide();
350                         $('#blues_tab_link').hide();
351                     }
352                     else {
353                         $('#mixed_models_adjusted_blues_results_div').html(r.adjusted_blues_html);
354                         $('#mixed_models_blues_results_div').html(r.blues_html);
357                         $('#adjusted_blups_tab_link').removeClass('active');
358                         $('#adjusted_blups_tab_link').hide();
359                         $('#blups_tab_link').hide();
362                         $('#adjusted_blues_tab_link').tab('show');
363                         $('#adjusted_blues_tab_link').addClass('active');
364                         $('#blues_tab_link').show();
365                     }
367                     accession_names = JSON.stringify(r.accession_names);
369                     adjusted_blups_data = JSON.stringify(r.adjusted_blups_data);
371                     adjusted_blues_data = JSON.stringify(r.adjusted_blues_data);
372                     blups_data = JSON.stringify(r.blups_data);
373                     blues_data = JSON.stringify(r.blues_data);
374                     traits = JSON.stringify(r.traits);
375                     input_file = r.input_file;
376                     result_summary = '{ "method" : "Breedbase mixed model analysis tool" }';
378                     var model_properties_data = { "properties": { "traits": traits } };
379                     model_properties = JSON.stringify(model_properties_data);
382                 }
383             },
384             "error": function (r) {
385                 alert(r);
386             }
387         });
388     });
392 function get_dataset_id() {
393     var selected_datasets = [];
394     jQuery('input[name="mixed_model_dataset_select_checkbox"]:checked').each(function () {
395         selected_datasets.push(jQuery(this).val());
396     });
397     if (selected_datasets.length < 1) {
398         alert('Please select at least one dataset!');
399         return false;
400     } else if (selected_datasets.length > 1) {
401         alert('Please select only one dataset!');
402         return false;
403     } else {
404         var dataset_id = selected_datasets[0];
405         return dataset_id;
406     }
409 function extract_model_parameters() {
411     var fixed_factors = parse_simple_factors("fixed_factors");
413     var interaction_factors = parse_factor_collection("interaction_factor_collection_panel");
415     var variable_slope_intersects = parse_factor_collection("variable_slope_intersect_collection_panel");
417     var random_factors = parse_simple_factors("random_factors");
419     var engine = jQuery('input[name=select_engine]:checked').val();
421     //alert("ENGINE IS NOW: "+engine);
423     // var random_factors = $('#random_factors').text();
424     // random_factors = random_factors.replace(/X /g, '","');
425     // random_factors = random_factors.replace(/\s/g, '');
426     // random_factors = random_factors.substr(3);
427     // if (random_factors) {
428     //     random_factors = '["'+random_factors+'"]';
429     // }
430     // var random_factors_json;
431     // if (random_factors) {
432     //     random_factors_json = JSON.parse(random_factors);
433     // }
435     var dependent_variables = [];
436     $('input[name=dependent_variable_select]:checked').each(function () {
437         dependent_variables.push(jQuery(this).val());
438     });
440     var json = {
441         'fixed_factors': fixed_factors,
442         'fixed_factors_interaction': interaction_factors,
443         'variable_slope_intersects': variable_slope_intersects,
444         'random_factors': random_factors,
445         'dependent_variables': dependent_variables,
446         'engine': engine
447     };
448     console.log(json);
449     return json;
452 function parse_simple_factors(simple_div) {
454     var factors = $('#' + simple_div).children();
455     var factor_list = new Array();
456     for (var n = 0; n < factors.length; n++) {
457         var factor_string = $(factors[n]).text();
458         factor_string = factor_string.replace(/X /g, '');
460         if (factor_string) {
461             factor_list.push(factor_string);
462         }
463     }
464     return factor_list;
467 function parse_factor_collection(collection_div) {
469     // Structure:
470     // interaction_factors_collection panel
471     //    interaction_factors_collection panel-header
472     //    interaction_1_panel panel
473     //       interaction_1_header panel-header
474     //       interaction_1  panel-body
475     //         factor_1 span X FACTOR_NAME1
476     //         factor_2 span X FACTOR_NAME2
477     //       interaction_2_header panel-header
478     //         factor_3 span X FACTOR_NAME3
479     //         factor_4 span X FACTOR_NAME4
480     //
482     var collection_divs = $('#' + collection_div).children();
484     var collection = new Array();
485     var grouped_factors = new Array();
487     for (var i = 1; i < collection_divs.length; i++) { // skip interaction_factors_collection panel header
489         var $div = $(collection_divs[i]);
491         var top_panels = $div.children();
493         for (var n = 0; n < top_panels.length; n++) {
495             var panel_components = $(top_panels[n]).children();
496             var $panel_body = $(panel_components[1]);
498             var factors = $panel_body.children();
500             for (var m = 0; m < factors.length; m++) {
501                 var $factor = $(factors[m]);
502                 var label = $factor.text();
504                 // remove X closing box
505                 label = label.substr(2);
506                 grouped_factors.push(label);
507             }
508             collection.push(grouped_factors);
509             grouped_factors = new Array();
510         }
511     }
513     var fixed_factors_interaction_json;
514     if (collection) {
515         //fixed_factors_interaction_collection = '[["'+fixed_factors_interaction_collection+'"]]';
516     }
517     return collection;
521 function parse_random_factors() {
527 function get_model_string() {
528     var params = extract_model_parameters();
530     //alert("PARAMS: "+JSON.stringify(params));
531     $.ajax({
532         url: '/ajax/mixedmodels/modelstring',
533         method: 'POST',
534         data: params,
535         error: function (e) {
536             alert("An error occurred" + e);
537         },
538         success: function (r) {
539             if (r.error) {
540                 alert(r.error);
541             }
542             else {
544                 console.log("ENGINE AGAIN: " + r.engine + " " + JSON.stringify(r));
545                 if (r.engine == 'sommer') {
546                     jQuery('#model_string').text(r.model[0] + " , random = " + r.model[1]);
547                 }
548                 else {
549                     jQuery('#model_string').text(r.model);
550                 }
551             }
552         }
553     });
556 function store_blup_file() {