minor fixes
[sgn.git] / js / solGS / correlation.js
blob4e660de92888ad56367c98b6861b6dd0e82a1ee0
1 /** 
2 * correlation coefficients plotting using d3
3 * Isaak Y Tecle <iyt2@cornell.edu>
5 */
8 jQuery(document).ready( function() { 
9     var page = document.URL;
10    
11     if (page.match(/solgs\/traits\/all\//) != null || 
12         page.match(/solgs\/models\/combined\/trials\//) != null) {
13         
14         setTimeout(function() {listGenCorPopulations()}, 5000);
15         
16     } else {
18         var url = window.location.pathname;
20         if (url.match(/[solgs\/population|breeders_toolbox\/trial]/)) {
21             checkPhenoCorreResult();  
22         } 
23     }
24           
25 });
28 function checkPhenoCorreResult () {
29     
30     var popDetails = getPopulationDetails();
31     var popId      = popDetails.population_id;
32    
33     jQuery.ajax({
34         type: 'POST',
35         dataType: 'json',
36         url: '/phenotype/correlation/check/result/' + popId,
37         success: function(response) {
38             if (response.result === 'yes') {
39                 phenotypicCorrelation();                                        
40             } else { 
41                 jQuery("#run_pheno_correlation").show();        
42             }
43         }
44     });
45     
49 jQuery(document).ready( function() { 
51     jQuery("#run_pheno_correlation").click(function() {
52         phenotypicCorrelation();
53     }); 
54   
55 });
60 jQuery("#run_genetic_correlation").live("click", function() {        
61     var popId   = jQuery("#corre_selected_population_id").val();
62     var popType = jQuery("#corre_selected_population_type").val();
63     
64     jQuery("#correlation_canvas").empty();
65    
66     jQuery("#correlation_message")
67         .css({"padding-left": '0px'})
68         .html("Running genetic correlation analysis...");
69     
70     formatGenCorInputData(popId, popType);
71          
72 });
75 function listGenCorPopulations ()  {
76     var modelData = getTrainingPopulationData();
77    
78     var trainingPopIdName = JSON.stringify(modelData);
79    
80     var  popsList =  '<dl id="corre_selected_population" class="corre_dropdown">'
81         + '<dt> <a href="#"><span>Choose a population</span></a></dt>'
82         + '<dd>'
83         + '<ul>'
84         + '<li>'
85         + '<a href="#">' + modelData.name + '<span class=value>' + trainingPopIdName + '</span></a>'
86         + '</li>';  
88     popsList += '</ul></dd></dl>'; 
89    
90     jQuery("#corre_select_a_population_div").empty().append(popsList).show();
91      
92     var dbSelPopsList;
93     if (modelData.id.match(/uploaded/) == null) {
94         dbSelPopsList = addSelectionPopulations();
95     }
97     if (dbSelPopsList) {
98             jQuery("#corre_select_a_population_div ul").append(dbSelPopsList); 
99     }
100       
101     var userUploadedSelExists = jQuery("#uploaded_selection_pops_table").doesExist();
102     if (userUploadedSelExists == true) {
103       
104         var userSelPops = listUploadedSelPopulations();
105         if (userSelPops) {
107             jQuery("#corre_select_a_population_div ul").append(userSelPops);  
108         }
109     }
111     jQuery(".corre_dropdown dt a").click(function() {
112         jQuery(".corre_dropdown dd ul").toggle();
113     });
114                  
115     jQuery(".corre_dropdown dd ul li a").click(function() {
116       
117         var text = jQuery(this).html();
118            
119         jQuery(".corre_dropdown dt a span").html(text);
120         jQuery(".corre_dropdown dd ul").hide();
121                 
122         var idPopName = jQuery("#corre_selected_population").find("dt a span.value").html();
123         idPopName     = JSON.parse(idPopName);
124         modelId       = jQuery("#model_id").val();
125                    
126         selectedPopId   = idPopName.id;
127         selectedPopName = idPopName.name;
128         selectedPopType = idPopName.pop_type; 
129        
130         jQuery("#corre_selected_population_name").val(selectedPopName);
131         jQuery("#corre_selected_population_id").val(selectedPopId);
132         jQuery("#corre_selected_population_type").val(selectedPopType);
133                                 
134     });
135                        
136     jQuery(".corre_dropdown").bind('click', function(e) {
137         var clicked = jQuery(e.target);
138                
139         if (! clicked.parents().hasClass("corre_dropdown"))
140             jQuery(".corre_dropdown dd ul").hide();
142         e.preventDefault();
144     });           
148 function formatGenCorInputData (popId, type, indexFile) {
149     var modelDetail = getPopulationDetails();
150    
151     jQuery.ajax({
152         type: 'POST',
153         dataType: 'json',
154         data: {'model_id': modelDetail.population_id, 'corr_population_id': popId, 'type' : type, 'index_file': indexFile},
155         url: '/correlation/genetic/data/',
156         success: function(response) {
157            
158             if(response.status == 'success') {
159                 gebvsFile = response.gebvs_file;
160                    
161                 var divPlace;
162                 if(indexFile) {
163                     divPlace = '#si_correlation_canvas';
164                 }
166                 var args = {
167                     'model_id': modelDetail.population_id, 
168                     'corr_population_id': popId, 
169                     'type': type, 
170                     'gebvs_file': gebvsFile,
171                     'div_place' : divPlace,
172                 };
173               
174                 runGenCorrelationAnalysis(args);
176             } else {
177                 jQuery("#correlation_message")
178                     .css({"padding-left": '0px'})
179                     .html("This population has no valid traits to correlate.");
180             }
181         },
182         error: function(response) {
183             jQuery("#correlation_message")
184                 .css({"padding-left": '0px'})
185                 .html("Error occured preparing the additive genetic data for correlation analysis.");
186             
187             jQuery.unblockUI();
188         }         
189     });
193 function getPopulationDetails () {
195     var populationId = jQuery("#population_id").val();
196     var populationName = jQuery("#population_name").val();
197    
198     if (populationId == 'undefined') {       
199         populationId = jQuery("#model_id").val();
200         populationName = jQuery("#model_name").val();
201     }
203     return {'population_id' : populationId, 
204             'population_name' : populationName
205            };        
209 function phenotypicCorrelation () {
211     var population = getPopulationDetails();
212     
213     jQuery("#correlation_message").html("Running correlation... please wait...");
214          
215     jQuery.ajax({
216             type: 'POST',
217             dataType: 'json',
218             data: {'population_id': population.population_id },
219             url: '/correlation/phenotype/data/',
220             success: function(response) {
221                 if (response.status == 'success') {
222                     runPhenoCorrelationAnalysis();
223                 } else {
224                     jQuery("#correlation_message")
225                         .css({"padding-left": '0px'})
226                         .html("This population has no phenotype data.");
227                 }
228             },
229             error: function(response) {
230                 jQuery("#correlation_message")
231                     .css({"padding-left": '0px'})
232                     .html("Error occured preparing the phenotype data for correlation analysis.");
233             }
234     });     
238 function runPhenoCorrelationAnalysis () {
239     var population = getPopulationDetails();
240     var popId     = population.population_id;
241    
242     jQuery.ajax({
243         type: 'POST',
244         dataType: 'json',
245         data: {'population_id': popId },
246         url: '/phenotypic/correlation/analysis/output',
247         success: function(response) {
248             if (response.status == 'success') {
249                 plotCorrelation(response.data);
250                 
251                 var corrDownload = "<a href=\"/download/phenotypic/correlation/population/" 
252                                     + popId + "\">Download correlation coefficients</a>";
254                 jQuery("#correlation_canvas").append("<br />[ " + corrDownload + " ]").show();
255                 jQuery("#correlation_message").empty();
256                 jQuery("#run_pheno_correlation").hide();
257             } else {
258                 jQuery("#correlation_message")
259                     .css({"padding-left": '0px'})
260                     .html("There is no correlation output for this dataset.");               
261             }
262         },
263         error: function(response) {                          
264             jQuery("#correlation_message")
265                 .css({"padding-left": '0px'})
266                 .html("Error occured running the correlation analysis.");
267         }                
268     });
272 function runGenCorrelationAnalysis (args) {
273    
274     jQuery.ajax({
275         type: 'POST',
276         dataType: 'json',
277         data: args,
278         url: '/genetic/correlation/analysis/output',
279         success: function(response) {
280             if (response.status == 'success') {
281                 
282                 divPlace = args.div_place;
283                
284                 if (divPlace === '#si_correlation_canvas') {
285                     jQuery("#si_correlation_section").show();                 
286                 }
287                 
288                 plotCorrelation(response.data, divPlace);
289                 jQuery("#correlation_message").empty();
290                 jQuery("#si_correlation_message").empty();
291                 
292                 if (divPlace === '#si_correlation_canvas') {
293   
294                     var popName   = jQuery("#selected_population_name").val();                   
295                     var corLegDiv = "<div id=\"si_correlation_" 
296                         + popName.replace(/\s/g, "") 
297                         + "\"></div>";  
298                 
299                     var legendValues = legendParams();                 
300                     var corLegDivVal = jQuery(corLegDiv).html(legendValues.legend);
301             
302                     jQuery("#si_correlation_canvas").append(corLegDivVal).show();
303   
304                 } else {
305                     
306                     var popName = jQuery("#corre_selected_population_name").val(); 
307                     var corLegDiv  = "<div id=\"corre_correlation_" 
308                         + popName.replace(/\s/g, "") 
309                         + "\"></div>";
310                     
311                     var corLegDivVal = jQuery(corLegDiv).html(popName);            
312                     jQuery("#correlation_canvas").append(corLegDivVal).show(); 
313                 }                        
314                
315             } else {
316                 jQuery("#correlation_message")
317                     .css({"padding-left": '0px'})
318                     .html("There is no genetic correlation output for this dataset.");               
319             }
320             
321             jQuery.unblockUI();
322         },
323         error: function(response) {                          
324             jQuery("#correlation_message")
325                 .css({"padding-left": '0px'})
326                 .html("Error occured running the genetic correlation analysis.");
327              
328             jQuery.unblockUI();
329         }       
330     });
334 function plotCorrelation (data, divPlace) {
335    
336     data = data.replace(/\s/g, '');
337     data = data.replace(/\\/g, '');
338     data = data.replace(/^\"/, '');
339     data = data.replace(/\"$/, '');
340     data = data.replace(/\"NA\"/g, 100);
341     
342     data = JSON.parse(data);
343   
344     var height = 400;
345     var width  = 400;
347     var nTraits = data.traits.length;
349     if (nTraits < 8) {
350         height = height * 0.5;
351         width  = width  * 0.5;
352     }
354     var pad    = {left:70, top:20, right:100, bottom: 70}; 
355     var totalH = height + pad.top + pad.bottom;
356     var totalW = width + pad.left + pad.right;
358     var corXscale = d3.scale.ordinal().domain(d3.range(nTraits)).rangeBands([0, width]);
359     var corYscale = d3.scale.ordinal().domain(d3.range(nTraits)).rangeBands([height, 0]);
360     var corZscale = d3.scale.linear().domain([-1, 0, 1]).range(["#6A0888","white", "#86B404"]);
362     var xAxisScale = d3.scale.ordinal()
363         .domain(data.traits)
364         .rangeBands([0, width]);
366     var yAxisScale = d3.scale.ordinal()
367         .domain(data.traits)
368         .rangeRoundBands([height, 0]);
369   
370     if ( divPlace == null) {
371         divPlace = '#correlation_canvas'; 
372     }
374     var svg = d3.select(divPlace)
375         .append("svg")
376         .attr("height", totalH)
377         .attr("width", totalW);
379     var xAxis = d3.svg.axis()
380         .scale(xAxisScale)
381         .orient("bottom");
383     var yAxis = d3.svg.axis()
384         .scale(yAxisScale)
385         .orient("left");
386        
387     var corrplot = svg.append("g")
388         .attr("id", "correlation_plot")
389         .attr("transform", "translate(" + pad.left + "," + pad.top + ")");
390        
391     corrplot.append("g")
392         .attr("class", "x axis")
393         .attr("transform", "translate(0," + height +")")
394         .call(xAxis)
395         .selectAll("text")
396         .attr("y", 0)
397         .attr("x", 10)
398         .attr("dy", ".1em")         
399         .attr("transform", "rotate(90)")
400         .attr("fill", "#523CB5")
401         .style({"text-anchor":"start", "fill": "#523CB5"});
402           
403     corrplot.append("g")
404         .attr("class", "y axis")
405         .attr("transform", "translate(0,0)")
406         .call(yAxis)
407         .selectAll("text")
408         .attr("y", 0)
409         .attr("x", -10)
410         .attr("dy", ".1em")  
411         .attr("fill", "#523CB5")
412         .style("fill", "#523CB5");
413             
414     var corr = [];
415     var coefs = [];   
416     for (var i=0; i<data.coefficients.length; i++) {
417         for (var j=0;  j<data.coefficients[i].length; j++) {
418             corr.push({"row":i, "col":j, "value": data.coefficients[i][j]});
419             
420             if (data.coefficients[i][j] != 100) {
421                 coefs.push(data.coefficients[i][j]);
422             }
423         }
424     }
425                                  
426     var cell = corrplot.selectAll("rect")
427         .data(corr)  
428         .enter().append("rect")
429         .attr("class", "cell")
430         .attr("x", function (d) { return corXscale(d.col)})
431         .attr("y", function (d) { return corYscale(d.row)})
432         .attr("width", corXscale.rangeBand())
433         .attr("height", corYscale.rangeBand())      
434         .attr("fill", function (d) { 
435                 if (d.value === 100) {return "white";} 
436                 else {return corZscale(d.value)}
437             })
438         .attr("stroke", "white")
439         .attr("stroke-width", 1)
440         .on("mouseover", function (d) {
441                 if(d.value != 100) {
442                     d3.select(this)
443                         .attr("stroke", "green")
444                     corrplot.append("text")
445                         .attr("id", "corrtext")
446                         .text("[" + data.traits[d.row] 
447                               + " vs. " + data.traits[d.col] 
448                               + ": " + d3.format(".2f")(d.value) 
449                               + "]")
450                         .style("fill", function () { 
451                             if (d.value > 0) 
452                             { return "#86B404"; } 
453                             else if (d.value < 0) 
454                             { return "#6A0888"; }
455                         })  
456                         .attr("x", totalW * 0.5)
457                         .attr("y", totalH * 0.5)
458                         .attr("font-weight", "bold")
459                         .attr("dominant-baseline", "middle")
460                         .attr("text-anchor", "middle")                       
461                 }
462         })                
463         .on("mouseout", function() {
464                 d3.selectAll("text.corrlabel").remove()
465                 d3.selectAll("text#corrtext").remove()
466                 d3.select(this).attr("stroke","white")
467             });
468             
469     corrplot.append("rect")
470         .attr("height", height)
471         .attr("width", width)
472         .attr("fill", "none")
473         .attr("stroke", "#523CB5")
474         .attr("stroke-width", 1)
475         .attr("pointer-events", "none");
476    
477     var legendValues = []; 
478     
479     if (d3.min(coefs) > 0 && d3.max(coefs) > 0 ) {
480         legendValues = [[0, 0], [1, d3.max(coefs)]];
481     } else if (d3.min(coefs) < 0 && d3.max(coefs) < 0 )  {
482         legendValues = [[0, d3.min(coefs)], [1, 0]]; 
483     } else {
484         legendValues = [[0, d3.min(coefs)], [1, 0], [2, d3.max(coefs)]];
485     }
487     var legend = corrplot.append("g")
488         .attr("class", "cell")
489         .attr("transform", "translate(" + (width + 10) + "," +  (height * 0.25) + ")")
490         .attr("height", 100)
491         .attr("width", 100);
492        
493     var recLH = 20;
494     var recLW = 20;
496     legend = legend.selectAll("rect")
497         .data(legendValues)  
498         .enter()
499         .append("rect")
500         .attr("x", function (d) { return 1;})
501         .attr("y", function (d) {return 1 + (d[0] * recLH) + (d[0] * 5); })   
502         .attr("width", recLH)
503         .attr("height", recLW)
504         .style("stroke", "black")
505         .attr("fill", function (d) { 
506             if (d === 100) {return "white"} 
507             else {return corZscale(d[1])}
508         });
510     var legendTxt = corrplot.append("g")
511         .attr("transform", "translate(" + (width + 40) + "," + ((height * 0.25) + (0.5 * recLW)) + ")")
512         .attr("id", "legendtext");
514     legendTxt.selectAll("text")
515         .data(legendValues)  
516         .enter()
517         .append("text")              
518         .attr("fill", "#523CB5")
519         .style("fill", "#523CB5")
520         .attr("x", 1)
521         .attr("y", function (d) { return 1 + (d[0] * recLH) + (d[0] * 5); })
522         .text(function (d) { 
523             if (d[1] > 0) { return "Positive"; } 
524             else if (d[1] < 0) { return "Negative"; } 
525             else if (d[1] === 0) { return "Neutral"; }
526         })  
527         .attr("dominant-baseline", "middle")
528         .attr("text-anchor", "start");