Merge pull request #5205 from solgenomics/topic/generic_trial_upload
[sgn.git] / js / source / legacy / solGS / geneticGain.js
blob17c9e6b8fdfc3d2c34aa92db82c3826f6ccdc5f7
1 /** 
2 * visualize and compare gebvs of a training population
3 * and a selection population (genetic gain).
4 * normal distribution plotting using d3.
5 * uses methods from solGS.normalDistribution and solGS.linePlot js libraries
7 * Isaak Y Tecle <iyt2@cornell.edu>
9 */
11 var solGS = solGS || function solGS() {};
13 solGS.geneticGain = {
14   canvas: "#gg_canvas",
15   ggPlotDivPrefix: "#gg_plot",
16   ggMsgDiv: "#gg_message",
17   ggPopsDiv: "#gg_pops_select_div",
18   ggPopsSelectMenuId: "#gg_pops_select",
20   gebvsComparison: function () {
21     var gebvParams = this.getGeneticGainArgs();
23     var missing;
24     if (!gebvParams.training_pop_id) {
25       missing = "training population id";
26     }
28     if (!gebvParams.selection_pop_id) {
29       missing += ", selection population id";
30     }
32     if (!gebvParams.trait_id) {
33       missing += ", trait id";
34     }
36     var ggMsgDiv = this.ggMsgDiv;
37     if (missing) {
38       jQuery(ggMsgDiv)
39         .html("Can not compare GEBVs. I am missing " + missing + ".")
40         .show();
41     } else {
42       this.plotGeneticGainBoxplot(gebvParams);
43     }
44   },
46   getGeneticGainArgs: function () {
47     var canvas = this.canvas;
49     var trainingPopId = jQuery(`${canvas} #training_pop_id`).val();
50     var trainingPopName = jQuery(`${canvas} #training_pop_name`).val();
51     var selectionPopId = jQuery("#gg_selected_pop_id").val() || jQuery("#selection_pop_id").val();
52     var trainingTraitsIds = jQuery(canvas).find("#training_traits_ids").val();
53     var traitId = jQuery("#trait_id").val();
54     var protocolId = jQuery("#genotyping_protocol_id").val();
56     if (document.URL.match(/solgs\/traits\/all\/population\/|solgs\/models\/combined\/trials\//)) {
57       if (trainingTraitsIds) {
58         trainingTraitsIds = trainingTraitsIds.split(",");
59       }
60     }
62     var ggArgs = {
63       training_pop_id: trainingPopId,
64       training_pop_name: trainingPopName,
65       selection_pop_id: selectionPopId,
66       training_traits_ids: trainingTraitsIds,
67       trait_id: traitId,
68       genotyping_protocol_id: protocolId,
69     };
71     return ggArgs;
72   },
74   plotGeneticGainBoxplot: function (ggArgs) {
75     var canvas = this.canvas;
76     var ggMsgDiv = this.ggMsgDiv;
79         ggArgs = JSON.stringify(ggArgs)
80     jQuery(` ${canvas} .multi-spinner-container`).show();
81     jQuery("#check_genetic_gain").hide();
82     jQuery(ggMsgDiv).html("Please wait... plotting genetic gain").show();
84     jQuery.ajax({
85       type: "POST",
86       dataType: "json",
87       data: {'arguments': ggArgs},
88       url: "/solgs/genetic/gain/boxplot",
89       success: function (res) {
90         if (res.Error) {
91           jQuery(`${canvas} .multi-spinner-container`).hide();
92           jQuery(ggMsgDiv).empty();
94           solGS.showMessage(ggMsgDiv, res.Error);
96           if (
97             document.URL.match(
98               /\/solgs\/traits\/all\/population\/|solgs\/models\/combined\/trials\//
99             )
100           ) {
101             jQuery("#check_genetic_gain").show();
102           }
103         } else {
104           var boxplot = res.boxplot;
105           var boxplotData = res.boxplot_data;
106           var plot = '<img  src= "' + boxplot + '">';
108           if (boxplot) {
109             var fileNameBoxplot = boxplot.split("/").pop();
110             boxplotFile = '<a href="' + boxplot + '" download=' + fileNameBoxplot + ">boxplot</a>";
112             var fileNameData = boxplotData.split("/").pop();
113             var dataFile = '<a href="' + boxplotData + '" download=' + fileNameData + ">Data</a>";
114             jQuery("#gg_plot")
115               .prepend(
116                 '<div style="margin-top: 20px">' +
117                   plot +
118                   "</div>" +
119                   "<br /> <strong>Download:</strong> " +
120                   boxplotFile +
121                   " | " +
122                   dataFile
123               )
124               .show();
126             jQuery(`${canvas} .multi-spinner-container`).hide();
127             jQuery("#gg_message").empty();
129             if (
130               document.URL.match(
131                 /\/solgs\/traits\/all\/population\/|solgs\/models\/combined\/trials\//
132               )
133             ) {
134               jQuery("#check_genetic_gain").show();
135             }
136           } else {
137             jQuery(`${canvas} .multi-spinner-container`).hide();
138             showMessage("There is no genetic gain plot for this dataset.");
139             jQuery("#check_genetic_gain").show();
140           }
141         }
142       },
143       error: function (res) {
144         jQuery(`${canvas} .multi-spinner-container`).hide();
145         solGS.showMessage(ggMsgDiv, "Error occured plotting the genetic gain.");
146         jQuery("#check_genetic_gain").show();
147       },
148     });
149   },
151   getTrainingPopulationGEBVs: function (gebvParams) {
152     var ggMsgDiv = this.ggMsgDiv;
153     jQuery.ajax({
154       type: "POST",
155       dataType: "json",
156       data: gebvParams,
157       url: "/solgs/get/gebvs/training/population",
158       success: function (res) {
159         if (res.gebv_exists) {
160           jQuery(ggMsgDiv).empty();
161           trainingGEBVs = res.gebv_arrayref;
163           if (trainingGEBVs) {
164             solGS.geneticGain.getSelectionPopulationGEBVs(gebvParams);
165           }
166         } else {
167           jQuery(ggMsgDiv).html("There is no GEBV data for the training population.").show();
168         }
169       },
170       error: function () {
171         jQuery(ggMsgDiv)
172           .html("Error occured checking for GEBV data for the training population.")
173           .show();
174       },
175     });
176   },
178   getSelectionPopulationGEBVs: function (gebvParams) {
179     var ggMsgDiv = this.ggMsgDiv;
181     jQuery.ajax({
182       type: "POST",
183       dataType: "json",
184       data: gebvParams,
185       url: "/solgs/get/gebvs/selection/population",
186       success: function (res) {
187         if (res.gebv_exists) {
188           jQuery(ggMsgDiv).empty();
190           selectionGEBVs = res.gebv_arrayref;
192           if (selectionGEBVs && trainingGEBVs) {
193             jQuery(ggMsgDiv).html("Please wait... plotting gebvs").show();
195             solGS.geneticGain.plotGEBVs(trainingGEBVs, selectionGEBVs);
197             jQuery(ggMsgDiv).empty();
198             jQuery("#check_genetic_gain").hide();
199           }
200         } else {
201           jQuery(ggMsgDiv).html("There is no GEBV data for the selection population.").show();
202         }
203       },
204       error: function () {
205         jQuery(ggMsgDiv)
206           .html("Error occured checking for GEBV data for the selection population.")
207           .show();
208       },
209     });
210   },
212   populateGeneticGainMenu: function (newPop) {
213     var ggArgs = this.getGeneticGainArgs();
215     var ggPops = [];
216     if (ggArgs.training_pop_id.match(/list/) == null) {
217       var trialSelPopsList = solGS.selectionPopulation.getPredictedTrialTypeSelectionPops();
218       if (trialSelPopsList) {
219         ggPops.push(trialSelPopsList);
220       }
221     }
223     var menu = new SelectMenu(this.ggPopsDiv, this.ggPopsSelectMenuId);
224     
225     if (newPop){
226         menu.updateOptions(newPop);   
227     } else {
228       menu.populateMenu(ggPops);
229     }
231   },
233   getSelPopPredictedTraits: function (ggArgs) {
234     var ggMsgDiv = this.ggMsgDiv;
235         var canvas = this.canvas;
237         var args = JSON.stringify(ggArgs);
238     jQuery.ajax({
239       type: "POST",
240       dataType: "json",
241       data: {'arguments': args},
242       url: "/solgs/selection/population/predicted/traits",
243       success: function (res) {
244         if (res.selection_traits) {
245           var ggArgs = solGS.geneticGain.getGeneticGainArgs();
246           jQuery(`${canvas} #selection_traits_ids`).val(res.selection_traits);
247           solGS.geneticGain.plotGeneticGainBoxplot(ggArgs);
248         } else {
249           jQuery(ggMsgDiv).html("This selection population has no predicted traits.").show();
250         }
251       },
252       error: function () {
253         jQuery(ggMsgDiv)
254           .html(
255             "Error occured checking for predicted traits for the selection population " +
256               selectionPopId
257           )
258           .show();
259       },
260     });
261   },
263   plotGEBVs: function (trainingGEBVs, selectionGEBVs) {
264     var normalDistTraining = new solGS.normalDistribution();
266     var trainingNormalDistData = normalDistTraining.getNormalDistData(trainingGEBVs);
268     var gebvZScoresT = normalDistTraining.getYValuesZScores(trainingNormalDistData);
270     var yValuesT = normalDistTraining.getPValues(trainingNormalDistData);
272     var zScoresPT = normalDistTraining.getZScoresP(trainingNormalDistData);
274     var xYT = normalDistTraining.getYValuesP(trainingNormalDistData);
276     var xValuesT = normalDistTraining.getYValues(trainingGEBVs);
278     var trMean = ss.mean(xValuesT);
280     var stdT = trMean <= 0 ? -1.0 : 1.0;
282     var xMT = normalDistTraining.getObsValueZScore(gebvZScoresT, stdT);
284     var normalDistSelection = new solGS.normalDistribution();
286     var selectionNormalDistData = normalDistSelection.getNormalDistData(selectionGEBVs);
288     var gebvZScoresS = normalDistSelection.getYValuesZScores(selectionNormalDistData);
290     var yValuesS = normalDistSelection.getPValues(selectionNormalDistData);
292     var zScoresPS = normalDistSelection.getZScoresP(selectionNormalDistData);
294     var xYS = normalDistSelection.getYValuesP(selectionNormalDistData);
296     var xValuesS = normalDistSelection.getYValues(selectionGEBVs);
298     var slMean = ss.mean(xValuesS);
300     var stdS = slMean <= 0 ? -1.0 : 1.0;
302     var xMS = normalDistTraining.getObsValueZScore(gebvZScoresS, stdS);
304     var svgId = "#compare_gebvs_canvas";
305     var plotId = "#compare_gebvs_plot";
307     var trColor = "#02bcff";
308     var slColor = "#ff1302";
309     var axLabelColor = "#ff8d02";
310     var yLabel = "Probability";
311     var xLabel = "GEBVs";
313     var title =
314       "Normal distribution curves of GEBVs " + "for the training and selection populations.";
316     var allData = {
317       div_id: svgId,
318       plot_title: title,
319       x_axis_label: xLabel,
320       y_axis_label: yLabel,
321       axis_label_color: axLabelColor,
322       lines: [
323         {
324           data: xYT,
325           legend: "Training population",
326           color: trColor,
327         },
328         {
329           data: xYS,
330           legend: "Selection population",
331           color: slColor,
332         },
333       ],
334     };
336     var linePlot = solGS.linePlot(allData);
338     var trainingMidlineData = [
339       [trMean, 0],
340       [trMean, d3.max(yValuesT)],
341     ];
343     var selectionMidlineData = [
344       [slMean, 0],
345       [slMean, d3.max(yValuesS)],
346     ];
348     var midLine = d3.svg
349       .line()
350       .x(function (d) {
351         return linePlot.xScale(d[0]);
352       })
353       .y(function (d) {
354         return linePlot.yScale(d[1]);
355       });
357     linePlot.graph
358       .append("path")
359       .attr("d", midLine(trainingMidlineData))
360       .attr("stroke", trColor)
361       .attr("stroke-width", "3")
362       .attr("fill", "none")
363       .on("mouseover", function (d) {
364         if ((d = trMean)) {
365           linePlot.graph
366             .append("text")
367             .attr("id", "tr_mean")
368             .text(d3.format(".2f")(trMean))
369             .style({
370               fill: trColor,
371               "font-weight": "bold",
372             })
373             .attr("x", linePlot.xScale(xMT[0]))
374             .attr("y", linePlot.yScale(d3.max(yValuesT) * 0.5));
375         }
376       })
377       .on("mouseout", function () {
378         d3.selectAll("text#tr_mean").remove();
379       });
381     linePlot.graph
382       .append("path")
383       .attr("d", midLine(selectionMidlineData))
384       .attr("stroke", slColor)
385       .attr("stroke-width", "3")
386       .attr("fill", "none")
387       .on("mouseover", function (d) {
388         if ((d = slMean)) {
389           linePlot.graph
390             .append("text")
391             .attr("id", "sl_mean")
392             .text(d3.format(".2f")(slMean))
393             .style({
394               fill: slColor,
395               "font-weight": "bold",
396             })
397             .attr("x", linePlot.xScale(xMS[0]))
398             .attr("y", linePlot.yScale(d3.max(yValuesS) * 0.5));
399         }
400       })
401       .on("mouseout", function () {
402         d3.selectAll("text#sl_mean").remove();
403       });
404   },
406   //////////
408 /////////
410 jQuery(document).ready(function () {
411   jQuery("#check_genetic_gain").on("click", function () {
412     var page = document.URL;
414     if (page.match(/solgs\/selection\//)) {
415       solGS.geneticGain.gebvsComparison();
416     } else {
417       var selectedPopId = jQuery("#gg_selected_pop_id").val();
418       var selectedPopType = jQuery("#gg_selected_pop_type").val();
419       var selectedPopName = jQuery("#gg_selected_pop_name").val();
421       jQuery("#gg_message")
422         .css({ "padding-left": "0px" })
423         .html("checking predicted traits for selection population " + selectedPopName);
425       var ggArgs = solGS.geneticGain.getGeneticGainArgs();
426       solGS.geneticGain.getSelPopPredictedTraits(ggArgs);
427     }
428   });
431 jQuery(document).ready(function () {
432   var page = document.URL;
434   if (page.match(/solgs\/traits\/all\/|solgs\/models\/combined\/trials\//) != null) {
435     setTimeout(function () {
436       solGS.geneticGain.populateGeneticGainMenu();
437     }, 5000);
438   }
441 jQuery(document).ready(function () {
442         var ggPopsDiv = solGS.geneticGain.ggPopsDiv;
443         jQuery(ggPopsDiv).change(function () {
445           var selectedPop = jQuery("option:selected", this).data("pop");
446   
447           jQuery("#gg_selected_pop_name").val(selectedPop.name);
448           jQuery("#gg_selected_pop_id").val(selectedPop.id);
449           jQuery("#gg_selected_pop_type").val(selectedPop.pop_type);
450         });
451   
452   });