Merge pull request #5205 from solgenomics/topic/generic_trial_upload
[sgn.git] / js / source / legacy / solGS / kinship.js
blob92659c791c6fc8a8a9eb83bac5492510136ddb5b
1 /**
2  * kinship analysis and result plotting using d3
3  * Isaak Y Tecle <iyt2@cornell.edu>
4  *
5  */
7 var solGS = solGS || function solGS() {};
9 solGS.kinship = {
10   canvas: "#kinship_canvas",
11   kinshipPlotDivPrefix: "#kinship_plot",
12   kinshipMsgDiv: "#kinship_message",
13   kinshipPopsSelectMenuId: "#kinship_pops_select",
14   kinshipPopsDiv: "#kinship_pops_select_div",
15   kinshipPopsDataDiv: "#kinship_pops_data_div",
17   getKinshipArgs: function () {
18     var page = location.pathname;
19     var kinshipPopId;
20     var kinshipUrlArgs;
21     var dataStr;
22     var trainingPopId;
23     var selectionPopId;
25     if (page.match(/solgs\/trait\/|solgs\/model\/combined\/trials\/|\/breeders\/trial\//)) {
26       trainingPopId = jQuery("#training_pop_id").val();
27       if (!trainingPopId) {
28         trainingPopId = jQuery("#trial_id").val();
29       }
30       kinshipPopId = trainingPopId;
31     } else if (page.match(/kinship\/analysis/)) {
32       kinshipUrlArgs = this.getKinshipArgsFromUrl();
33       kinshipPopId = kinshipUrlArgs.kinship_pop_id;
34       dataStr = kinshipUrlArgs.data_structure;
35       protocolId = kinshipUrlArgs.genotyping_protocol_id;
36     } else if (page.match(/\/selection\/|\/prediction\//)) {
37       selectionPopId = jQuery("#selection_pop_id").val();
38       kinshipPopId = selectionPopId;
39     } else if (page.match(/solgs\/traits\/all\/population\/|models\/combined\/trials\//)) {
40       trainingPopId = jQuery("#training_pop_id").val();
41       kinshipPopId = trainingPopId;
42     }
44     if (page.match(/combined/)) {
45       var comboPopsId = trainingPopId;
46     }
48     var listId;
49     var datasetId;
50     var datasetName;
52       if (String(kinshipPopId).match(/list/)) {
53         dataStr = "list";
54       } else if (String(kinshipPopId).match(/dataset/)) {
55         dataStr = "dataset";
56       }
58       if (dataStr == "list") {
59         if (isNaN(kinshipPopId)) {
60           listId = kinshipPopId.replace("list_", "");
61         } else {
62           listId = kinshipPopId;
63         }
64       } else if (dataStr == "dataset") {
65         if (isNaN(kinshipPopId)) {
66           datasetId = kinshipPopId.replace("dataset_", "");
67         } else {
68           datasetId = kinshipPopId;
69         }
70       }
72     var protocolId = jQuery("#genotyping_protocol_id").val();
73     var traitId = jQuery("#trait_id").val();
75     return {
76       kinship_pop_id: kinshipPopId,
77       training_pop_id: trainingPopId,
78       list_id: listId,
79       dataset_id: datasetId,
80       combo_pops_id: comboPopsId,
81       selection_pop_id: selectionPopId,
82       data_structure: dataStr,
83       genotyping_protocol_id: protocolId,
84       trait_id: traitId,
85       analysis_type: "kinship analysis",
86     };
87   },
89   getKinshipArgsFromUrl: function () {
90     var page = location.pathname;
91     if (page == "/kinship/analysis/") {
92       page = "/kinship/analysis";
93     }
94     var urlArgs = page.replace("/kinship/analysis", "");
96     if (urlArgs) {
97       var args = urlArgs.split(/\/+/);
98       var selectId = args[1];
99       var protocolId = args[3];
101       var dataStr;
102       var reg = /\d+/;
103       var popId = selectId.match(reg)[0];
104       if (selectId.match(/dataset/)) {
105         dataStr = "dataset";
106       } else if (selectId.match(/list/)) {
107         dataStr = "list";
108       }
110       var args = {
111         kinship_pop_id: popId,
112         data_structure: dataStr,
113         genotyping_protocol_id: protocolId,
114       };
116       return args;
117     } else {
118       return {};
119     }
120   },
123   getTableTdId: function (kinshipPopId) {
124     return `kinship_${kinshipPopId}`;
125   },
127   
128   createTable: function (tableId) {
129     var kinshipTable =
130       `<table id="${tableId}" class="table table-striped"><thead><tr>` +
131       "<th>Population</th>" +
132       "<th>Data structure type</th>" +
133       "<th>Ownership</th>" +
134       "<th>Data type</th>" +
135       "<th>Run Kinship</th>" +
136       "</tr></thead></table>";
138     return kinshipTable;
139   },
141   getKinshipPopId: function (selectedId, dataStr) {
143     var pcaPopId;
144     if (dataStr) {
145       pcaPopId = `${dataStr}_${selectedId}`;
146     } else {
147       pcaPopId = selectedId;
148     }
150     return pcaPopId;
151   },
152   
153   createRowElements: function (kinshipPop) {
154     var popId = kinshipPop.id;
155     var popName = kinshipPop.name;
156     var dataStr = kinshipPop.data_str;
158     var kinshipPopId = solGS.kinship.getKinshipPopId(popId, dataStr);
159    
160     var dataTypeOpts = this.getDataTypeOpts({
161       id: popId,
162       name: popName,
163       data_str: dataStr,
164     });
166     dataTypeOpts = this.createDataTypeSelect(dataTypeOpts, kinshipPopId);
167     
169     var listId;
170     var datasetId;
172     if (dataStr.match(/dataset/)) {
173       datasetId = popId;
174     } else if (dataStr.match(/list/)) {
175       listId = popId;
176     }
177     var protocolId = solGS.genotypingProtocol.getGenotypingProtocolId("kinship_div");
179     var kinshipArgs = {
180       kinship_pop_id: kinshipPopId,
181       data_structure: dataStr,
182       dataset_id: datasetId,
183       list_id: listId,
184       kinship_pop_name: popName,
185       genotyping_protocol_id: protocolId,
186       analysis_type: "kinship analysis",
187     };
189     kinshipArgs = JSON.stringify(kinshipArgs);
191     var runKinshipBtnId = this.getRunKinshipBtnId(kinshipPopId);
192     var runKinshipBtn =
193       `<button type="button" id=${runKinshipBtnId}` +
194       ` class="btn btn-success" data-selected-pop='${kinshipArgs}'>Run kinship</button>`;
196     if (dataStr.match(/dataset/)) {
197       popName = `<a href="/dataset/${popId}">${popName}</a>`;
198     }
199     var rowData = [popName,
200       dataStr, kinshipPop.owner, dataTypeOpts, runKinshipBtn, `${dataStr}_${popId}`];
202     return rowData;
203   },
205   displayKinshipPopsTable: function (tableId, data) {
207     var table = jQuery(`#${tableId}`).DataTable({
208       'searching': true,
209       'ordering': true,
210       'processing': true,
211       'paging': true,
212       'info': false,
213       'pageLength': 5,
214       'rowId': function (a) {
215         return a[5]
216       }
217     });
219     table.rows.add(data).draw();
221   },
224   getKinshipPopsRows: function(kinshipPops) {
226     var kinshipPopsRows = [];
228     for (var i = 0; i < kinshipPops.length; i++) {
229       if (kinshipPops[i]) {
230         var kinshipPopRow = this.createRowElements(kinshipPops[i]);
231         kinshipPopsRows.push(kinshipPopRow);
232       }
233     }
235     return kinshipPopsRows;
237   },
239   getKinshipPops: function () {
241     var list = new solGSList();
242     var lists = list.getLists(["accessions", "trials"]);
243     lists = list.addDataStrAttr(lists);
245     var datasets = solGS.dataset.getDatasetPops(["accessions", "trials"]);
247     var kinshipPops = [lists, datasets];
249     return kinshipPops.flat();
251   },
253   getDataTypeOpts: function (args) {
254     var dataTypeOpts = ["Genotype"];
255     return dataTypeOpts;
257   },
260   createDataTypeSelect: function (opts) {
261     var dataTypeGroup = '<select class="form-control" id="kinship_data_type_select">';
263     for (var i = 0; i < opts.length; i++) {
264       dataTypeGroup += '<option value="' + opts[i] + '">' + opts[i] + "</option>";
265     }
266     dataTypeGroup += "</select>";
268     return dataTypeGroup;
269   },
271   getSelectedPopKinshipArgs: function (runKinshipElemId) {
272     var kinshipArgs;
274     var selectedPopDiv = document.getElementById(runKinshipElemId);
275     if (selectedPopDiv) {
276       var selectedPopData = selectedPopDiv.dataset;
278       kinshipArgs = JSON.parse(selectedPopData.selectedPop);
279       var kinshipPopId = kinshipArgs.data_str + "_" + kinshipArgs.id;
281       var protocolId = solGS.genotypingProtocol.getGenotypingProtocolId("kinship_div");
282       var page = `/kinship/analysis/${kinshipPopId}/gp/${protocolId}`;
284       kinshipArgs["analysis_type"] = "kinship analysis";
285       kinshipArgs["genotyping_protocol_id"] = protocolId;
286       kinshipArgs["analysis_page"] = page;
287     }
289     return kinshipArgs;
290   },
292   checkCachedKinship: function (page, args) {
293     args = JSON.stringify(args);
295     var checkCached = jQuery.ajax({
296       type: "POST",
297       dataType: "json",
298       data: {
299         page: page,
300         arguments: args,
301       },
302       url: "/solgs/check/cached/result/",
303     });
305     return checkCached;
306   },
308   runKinshipAnalysis: function (args) {
309     var kinArgs = JSON.stringify(args);
311     var runKinship = jQuery.ajax({
312       type: "POST",
313       dataType: "json",
314       data: { arguments: kinArgs },
315       url: "/run/kinship/analysis/",
316     });
318     return runKinship;
319   },
321   addDowloandLinks: function (res) {
322     var popName = res.kinship_pop_name;
323     var kinFileId = res.kinship_file_id;
324     var kinshipFile = res.kinship_table_file;
326     var aveFile = res.kinship_averages_file;
327     var inbreedingFile = res.inbreeding_file;
329     var fileNameKinship = kinshipFile.split("/").pop();
330     var fileNameAve = aveFile.split("/").pop();
331     var fileNameInbreeding = inbreedingFile.split("/").pop();
333     kinshipFile =
334       '<a href="' + kinshipFile + '" download=' + fileNameKinship + ">Kinship matrix</a>";
336     aveFile = '<a href="' + aveFile + '" download=' + fileNameAve + ">Average kinship</a>";
338     inbreedingFile =
339       '<a href="' +
340       inbreedingFile +
341       '" download=' +
342       fileNameInbreeding +
343       ">Inbreeding coefficients</a>";
345     var kinDownloadBtn = "download_" + "kinship_plot_" + kinFileId;
346     var kinPlotLink =
347       "<a href='#'  onclick='event.preventDefault();' id='" + kinDownloadBtn + "'> plot</a>";
349     var links = "<strong>Download:</strong> ";
351     if (popName) {
352       links = links + popName + " ";
353     }
355     links = links + kinshipFile + " | " + aveFile + " | " + inbreedingFile + " | " + kinPlotLink;
357     return links;
358   },
360   getRunKinshipBtnId: function (rowId) {
361     if (location.pathname.match(/kinship\/analysis/) && rowId) {
362       return `run_kinship_${rowId}`;
363     } else {
364       return "run_kinship";
365     }
366   },
368   getKinshipPopId: function (selectId, dataStr) {
369     var kinshipPopId;
370     if (dataStr) {
371       kinshipPopId = `${dataStr}_${selectId}`;
372     } else {
373       kinshipPopId = selectId;
374     }
376     return kinshipPopId;
377   },
379   ///////
382 jQuery(document).ready(function () {
383   jQuery("#kinship_div").on("click", function (e) {
384     var runKinshipBtnId = e.target.id;
385     if (runKinshipBtnId.match(/run_kinship/)) {
386       var kinshipArgs = solGS.kinship.getKinshipArgs();
387       var kinshipPopId = kinshipArgs.kinship_pop_id;
388       if (!kinshipPopId) {
389         kinshipArgs = solGS.kinship.getSelectedPopKinshipArgs(runKinshipBtnId);
390       }
392       kinshipPopId = kinshipArgs.kinship_pop_id;
393       var protocolId = solGS.genotypingProtocol.getGenotypingProtocolId("kinship_div");
395       var canvas = solGS.kinship.canvas;
396       var kinshipPlotDivId = solGS.kinship.kinshipPlotDivPrefix;
397       var kinshipMsgDiv = solGS.kinship.kinshipMsgDiv;
398       runKinshipBtnId = `#${runKinshipBtnId}`;
399       var kinshipUrl = `/kinship/analysis/${kinshipPopId}/gp/${protocolId}`;
400       //    solGS.kinship.generateKinshipUrl(kinshipPopId);
401       kinshipArgs["analysis_page"] = kinshipUrl;
403       jQuery(runKinshipBtnId).hide();
404       jQuery(`${canvas} .multi-spinner-container`).show();
406       jQuery(runKinshipBtnId).hide();
407       jQuery(kinshipMsgDiv).text("Running kinship... please wait...it may take minutes.").show();
409       jQuery(`${canvas} .multi-spinner-container`).show();
410       solGS.kinship
411         .checkCachedKinship(kinshipUrl, kinshipArgs)
412         .done(function (res) {
413           if (res.data) {
414             jQuery(kinshipMsgDiv).html("Generating heatmap... please wait...").show();
416             kinshipPlotDivId = `${kinshipPlotDivId}_${res.kinship_file_id}`;
418             var links = solGS.kinship.addDowloandLinks(res);
419             solGS.heatmap.plot(res.data, canvas, kinshipPlotDivId, links);
421             jQuery(`${canvas} .multi-spinner-container`).hide();
422             jQuery(kinshipMsgDiv).empty();
423             jQuery(runKinshipBtnId).show();
424           } else {
426                         jQuery(`${canvas} .multi-spinner-container`).hide();
427             jQuery(kinshipMsgDiv).empty();
429             var title =
430               "<p>This analysis may take a long time. " +
431               "Do you want to submit the analysis and get an email when it completes?</p>";
433             var jobSubmit = '<div id= "kinship_submit">' + title + "</div>";
435             jQuery(jobSubmit).appendTo("body");
437             jQuery("#kinship_submit").dialog({
438               height: "auto",
439               width: "auto",
440               modal: true,
441               title: "Kinship job submission",
442               buttons: {
443                 OK: {
444                   text: "Yes",
445                   class: "btn btn-success",
446                   id: "queue_job",
447                   click: function () {
448                     jQuery(this).dialog("close");
450                     solGS.submitJob.checkUserLogin(kinshipUrl, kinshipArgs);
451                   },
452                 },
454                 No: {
455                   text: "No, I will wait till it completes.",
456                   class: "btn btn-warning",
457                   id: "no_queue",
458                   click: function () {
459                     jQuery(this).dialog("close");
461                                         jQuery(kinshipMsgDiv).text("Running kinship... please wait...it may take minutes.").show();
462                                         jQuery(`${canvas} .multi-spinner-container`).show();
464                     solGS.kinship
465                       .runKinshipAnalysis(kinshipArgs)
466                       .done(function (res) {
467                         if (res.data) {
468                           jQuery(kinshipMsgDiv)
469                             .html("Generating heatmap... please wait...")
470                             .show();
472                           kinshipPlotDivId = `${kinshipPlotDivId}_${res.kinship_file_id}`;
474                           var links = solGS.kinship.addDowloandLinks(res);
475                           solGS.heatmap.plot(res.data, canvas, kinshipPlotDivId, links);
477                           jQuery(`${canvas} .multi-spinner-container`).hide();
478                           jQuery(kinshipMsgDiv).empty();
479                           jQuery(runKinshipBtnId).show();
480                         } else {
481                           jQuery(`${canvas} .multi-spinner-container`).hide();
482                           jQuery(kinshipMsgDiv)
483                             .css({
484                               "padding-left": "0px",
485                             })
486                             .html("This population has no kinship output data.")
487                             .fadeOut(8400);
489                           jQuery(runKinshipBtnId).show();
490                         }
491                       })
492                       .fail(function () {
493                         jQuery(kinshipMsgDiv)
494                           .html("Error occured running the kinship.")
495                           .show()
496                           .fadeOut(8400);
498                         jQuery(`${canvas} .multi-spinner-container`).hide();
499                       });
500                   },
501                 },
503                 Cancel: {
504                   text: "Cancel",
505                   class: "btn btn-info",
506                   id: "cancel_queue_info",
507                   click: function () {
508                     jQuery(this).dialog("close");
509                     jQuery(runKinshipBtnId).show();
510                   },
511                 },
512               },
513             });
514           }
515         })
516         .fail(function () {
517           jQuery(kinshipMsgDiv).html("Error occured running the kinship.").show().fadeOut(8400);
518           jQuery(`${canvas} .multi-spinner-container`).hide();
519         });
520     }
521   });
524 jQuery(document).ready(function () {
525   var url = location.pathname;
527   if (url.match(/kinship\/analysis/)) {
528     var args = solGS.kinship.getKinshipArgsFromUrl();
529     if (args.kinship_pop_id) {
530       if (args.data_structure) {
531         args["kinship_pop_id"] = args.data_structure + "_" + args.kinship_pop_id;
532       }
533       solGS.kinship.checkCachedKinship(url, args).done(function (res) {
534         if (res.data) {
535           var kinshipMsgDiv = solGS.kinship.kinshipMsgDiv;
536           var canvas = solGS.kinship.canvas;
538           jQuery(kinshipMsgDiv).html("Generating heatmap... please wait...").show();
539           jQuery(`${canvas} .multi-spinner-container`).show();
541           var kinshipPlotDivId = solGS.kinship.kinshipPlotDivPrefix;
542           kinshipPlotDivId = `${kinshipPlotDivId}_${res.kinship_file_id}`;
544           var links = solGS.kinship.addDowloandLinks(res);
545           solGS.heatmap.plot(res.data, canvas, kinshipPlotDivId, links);
547           jQuery(`${canvas} .multi-spinner-container`).hide();
548           jQuery(kinshipMsgDiv).empty();
549         }
550     })
551   }
555 jQuery(document).ready(function () {
556   var kinshipCanvas = solGS.kinship.canvas;
557   jQuery(kinshipCanvas).on("click", "a", function (e) {
558     var buttonId = e.target.id;
559     var kinshipPlotId = buttonId.replace(/download_/, "");
560     saveSvgAsPng(document.getElementById("#" + kinshipPlotId), kinshipPlotId + ".png", { scale: 1 });
561   });
564 jQuery(document).ready(function () {
565   var url = location.pathname;
567   if (url.match(/kinship\/analysis/)) {
568     kinshipPopsDataDiv = solGS.kinship.kinshipPopsDataDiv;
569     var tableId = 'kinship_pops_table';
570     var kinshipPopsTable = solGS.kinship.createTable(tableId);
571     jQuery(kinshipPopsDataDiv).append(kinshipPopsTable).show();
573     var kinshipPops = solGS.kinship.getKinshipPops();
574     var kinshipPopsRows = solGS.kinship.getKinshipPopsRows(kinshipPops);
576     solGS.kinship.displayKinshipPopsTable(tableId, kinshipPopsRows);
577     jQuery("#add_new_pops").show();
578   }