2 * Principal component analysis and scores plotting
4 * Isaak Y Tecle <iyt2@cornell.edu>
8 var solGS = solGS || function solGS() {};
11 canvas: "#pca_canvas",
12 pcaPlotDivPrefix: "#pca_plot",
13 pcaMsgDiv: "#pca_message",
14 pcaPopsDiv: "#pca_pops_select_div",
15 pcaPopsSelectMenuId: "#pca_pops_select",
16 pcaPopsDataDiv: "#pca_pops_data_div",
18 getPcaArgs: function () {
19 var page = location.pathname;
20 var protocolId = solGS.genotypingProtocol.getGenotypingProtocolId("pca_div");
21 var dataType = this.getSelectedDataType();
23 if (page.match(/pca\/analysis/)) {
24 pcaArgs = this.getPcaArgsFromUrl();
32 var trainingPopId = jQuery("#training_pop_id").val();
33 if (page.match(/solgs\/trait\/|solgs\/model\/combined\/trials\/|\/breeders\/trial\//)) {
35 trainingPopId = jQuery("#trial_id").val();
37 pcaPopId = trainingPopId;
38 } else if (page.match(/\/selection\/|\/prediction\//)) {
39 selectionPopId = jQuery("#selection_pop_id").val();
40 pcaPopId = selectionPopId;
41 } else if (page.match(/solgs\/traits\/all\/population\/|models\/combined\/trials\//)) {
42 pcaPopId = trainingPopId;
45 var traitId = jQuery("#trait_id").val();
47 if (page.match(/combined/)) {
48 var dataSetType = "combined_populations";
49 var comboPopsId = trainingPopId;
51 var dataSetType = "combined_populations";
57 training_pop_id: trainingPopId,
58 combo_pops_id: comboPopsId,
59 selection_pop_id: selectionPopId,
60 data_structure: dataStr,
62 data_set_type: dataSetType,
63 genotyping_protocol_id: protocolId,
65 analysis_type: "pca analysis",
72 getPcaArgsFromUrl: function () {
73 var page = location.pathname;
74 if (page == "/pca/analysis/") {
75 page = "/pca/analysis";
78 var urlArgs = page.replace("/pca/analysis", "");
85 var args = urlArgs.split(/\/+/);
86 if (urlArgs.match(/trait/)) {
97 dataType = "genotype";
99 dataType = "phenotype";
106 if (pcaPopId.match(/dataset/)) {
108 datasetId = pcaPopId.replace(/dataset_/, "");
109 } else if (pcaPopId.match(/list/)) {
111 listId = pcaPopId.replace(/list_/, "");
115 pca_pop_id: pcaPopId,
118 dataset_id: datasetId,
119 data_structure: dataStr,
121 genotyping_protocol_id: protocolId,
124 var reg = /\d+-+\d+/;
125 if (pcaPopId.match(reg)) {
126 var ids = pcaPopId.split("-");
127 args["training_pop_id"] = ids[0];
128 args["selection_pop_id"] = ids[1];
136 getRunPcaId: function (pcaPopId) {
138 return `run_pca_${pcaPopId}`;
145 getSelectedPopPcaArgs: function (runPcaElemId) {
148 var selectedPopDiv = document.getElementById(runPcaElemId);
149 if (selectedPopDiv) {
150 var selectedPopData = selectedPopDiv.dataset;
152 var selectedPop = JSON.parse(selectedPopData.selectedPop);
153 pcaPopId = selectedPop.pca_pop_id;
155 var dataType = this.getSelectedDataType(pcaPopId);
156 var pcaUrl = this.generatePcaUrl(pcaPopId);
158 pcaArgs = selectedPopData.selectedPop;
159 pcaArgs = JSON.parse(pcaArgs);
160 pcaArgs["data_type"] = dataType;
161 pcaArgs["analysis_page"] = pcaUrl;
168 getPcaPopId: function (selectedId, dataStr) {
172 pcaPopId = `${dataStr}_${selectedId}`;
174 pcaPopId = selectedId;
180 createRowElements: function (pcaPop) {
181 var popId = pcaPop.id;
182 var popName = pcaPop.name;
183 var dataStr = pcaPop.data_str;
185 var pcaPopId = solGS.pca.getPcaPopId(popId, dataStr);
188 if (location.pathname.match(/pca\/analysis/)) {
189 dataTypes = pcaPop.data_type;
191 dataTypes = this.getDataTypeOpts();
194 var dataTypeOpts = this.createDataTypeSelect(dataTypes, pcaPopId);
196 var runPcaBtnId = this.getRunPcaId(pcaPopId);
201 if (dataStr.match(/dataset/)) {
203 } else if (dataStr.match(/list/)) {
206 var protocolId = solGS.genotypingProtocol.getGenotypingProtocolId("pca_div");
209 pca_pop_id: pcaPopId,
210 data_structure: dataStr,
211 dataset_id: datasetId,
213 pca_pop_name: popName,
214 genotyping_protocol_id: protocolId,
215 analysis_type: "pca analysis",
218 pcaArgs = JSON.stringify(pcaArgs);
221 `<button type="button" id=${runPcaBtnId}` +
222 ` class="btn btn-success" data-selected-pop='${pcaArgs}'>Run PCA</button>`;
224 if (dataStr.match(/dataset/)) {
225 popName = `<a href="/dataset/${popId}">${popName}</a>`;
227 var rowData = [popName,
228 dataStr, pcaPop.owner, dataTypeOpts, runPcaBtn, `${dataStr}_${popId}`];
233 displayPcaPopsTable: function (tableId, data) {
235 var table = jQuery(`#${tableId}`).DataTable({
242 'rowId': function (a) {
247 table.rows.add(data).draw();
252 getPcaPopsRows: function(pcaPops) {
254 var pcaPopsRows = [];
256 for (var i = 0; i < pcaPops.length; i++) {
258 var pcaPopRow = this.createRowElements(pcaPops[i]);
259 pcaPopsRows.push(pcaPopRow);
267 getPcaPops: function () {
269 var list = new solGSList();
270 var lists = list.getLists(["accessions", "plots", "trials"]);
271 lists = list.addDataStrAttr(lists);
272 lists = list.addDataTypeAttr(lists);
273 var datasets = solGS.dataset.getDatasetPops(["accessions", "trials"]);
274 datasets = solGS.dataset.addDataTypeAttr(datasets);
275 var pcaPops = [lists, datasets];
277 return pcaPops.flat();
281 getDataTypeOpts: function () {
283 var dataTypeOpts = [];
285 if (location.pathname.match(/breeders\/trial/)) {
286 dataTypeOpts = ["Genotype", "Phenotype"];
287 } else if (page.match(/solgs\/trait\/\d+\/population\/|solgs\/model\/combined\/trials\//)) {
288 dataTypeOpts = ["Genotype"];
294 checkCachedPca: function (pcaArgs) {
295 if (document.URL.match(/pca\/analysis/)) {
296 var message = this.validatePcaParams(pcaArgs);
299 jQuery(this.pcaMsgDiv).prependTo(jQuery(this.canvas)).html(message).show().fadeOut(9400);
302 var page = pcaArgs.analysis_page;
303 pcaArgs = JSON.stringify(pcaArgs);
305 var checkCache = jQuery.ajax({
312 url: "/solgs/check/cached/result/",
318 pcaDataTypeSelectId: function (pcaPopId) {
319 if (location.pathname.match(/pca\/analysis/) && pcaPopId) {
320 return `pca_data_type_select_${pcaPopId}`;
322 return "pca_data_type_select";
326 getSelectedDataType: function (pcaPopId) {
329 var pcaDataSelectedId = this.pcaDataTypeSelectId(pcaPopId);
330 dataType = jQuery("#" + pcaDataSelectedId).val();
332 dataType = jQuery("#pca_data_type_select").val();
338 runPcaAnalysis: function (pcaArgs) {
339 pcaArgs = JSON.stringify(pcaArgs);
341 var pcaAnalysis = jQuery.ajax({
347 url: "/run/pca/analysis",
353 validatePcaParams: function (valArgs) {
354 var dataType = valArgs.data_type;
355 var dataStr = valArgs.data_structure;
356 var pcaPopId = valArgs.pca_pop_id;
359 if (dataStr && dataStr.match("list")) {
360 var listId = pcaPopId.replace(/\w+_/, "");
361 var list = new CXGN.List();
362 var listType = list.getListType(listId);
364 if (listType.match(/accessions/) && dataType.match(/phenotype/i)) {
365 msg = "With list of clones, you can only do PCA based on <em>genotype</em>.";
368 if (listType.match(/plots/) && dataType.match(/genotype/i)) {
369 msg = "With list of plots, you can only do PCA based on <em>phenotype</em>.";
376 createTable: function (tableId) {
379 `<table id="${tableId}" class="table table-striped"><thead><tr>` +
380 "<th>Population</th>" +
381 "<th>Data structure type</th>" +
382 "<th>Ownership</th>" +
383 "<th>Data type</th>" +
385 "</tr></thead></table>";
392 createDataTypeSelect: function (opts, pcaPopId) {
393 var pcaDataTypeId = this.pcaDataTypeSelectId(pcaPopId);
394 var dataTypeGroup = '<select class="form-control" id="' + pcaDataTypeId + '">';
396 for (var i = 0; i < opts.length; i++) {
397 dataTypeGroup += '<option value="' + opts[i] + '">' + opts[i] + "</option>";
399 dataTypeGroup += "</select>";
401 return dataTypeGroup;
405 pcaDownloadLinks: function (res) {
406 var screePlotFile = res.scree_plot_file;
407 var scoresFile = res.scores_file;
408 var loadingsFile = res.loadings_file;
409 var variancesFile = res.variances_file;
411 var screePlot = screePlotFile.split("/").pop();
412 var screePlotLink = '<a href="' + screePlotFile + '" download=' + screePlot + ">Scree plot</a>";
414 var scores = scoresFile.split("/").pop();
415 var scoresLink = '<a href="' + scoresFile + '" download=' + scores + "> Scores </a>";
417 var loadings = loadingsFile.split("/").pop();
418 var loadingsLink = '<a href="' + loadingsFile + '" download=' + loadings + ">Loadings</a>";
420 var variances = variancesFile.split("/").pop();
421 var variancesLink = '<a href="' + variancesFile + '" download=' + variances + ">Variances</a>";
423 var pcaPlotDiv = this.pcaPlotDivPrefix.replace(/#/, '');
424 var plotId = res.file_id;
425 var pcaDownloadLinkId = `download_${pcaPlotDiv}_${plotId}`;
427 `<a href='#' onclick='event.preventDefault();' id='${pcaDownloadLinkId}'>PCA plot</a>`;
440 return downloadLinks;
443 structurePlotData: function (res) {
444 var listId = res.list_id;
448 var list = new CXGN.List();
449 listName = list.listNameById(listId);
450 res['list_id'] = listId;
451 res['list_name'] = listName;
457 generatePcaUrl: function (pcaPopId) {
458 var traitId = jQuery("#trait_id").val();
459 var protocolId = solGS.genotypingProtocol.getGenotypingProtocolId("pca_div");
462 "solgs/population/" +
463 "|solgs/populations/combined/" +
465 "|solgs/model/combined/trials/" +
466 "|solgs/selection/\\d+|\\w+_\\d+/model/" +
467 "|solgs/combined/model/\\d+|\\w+_\\d+/selection/" +
468 "|solgs/models/combined/trials/" +
469 "|solgs/traits/all/population/";
471 var url = "/pca/analysis/" + pcaPopId;
474 if (location.pathname.match(solgsPages)) {
475 url = url + "/trait/" + traitId;
478 var pcaDataSelectedId = this.pcaDataTypeSelectId(pcaPopId);
479 dataType = jQuery("#" + pcaDataSelectedId).val();
481 if (dataType.match(/genotype/i)) {
482 url = url + "/gp/" + protocolId;
488 cleanUpOnSuccess: function (pcaPopId) {
490 jQuery(this.pcaMsgDiv).empty();
491 jQuery(`${this.canvas} .multi-spinner-container`).hide();
492 jQuery(`#${this.getRunPcaId(pcaPopId)}`).show();
496 feedBackOnFailure: function (pcaPopId, msg) {
497 jQuery(`${this.canvas} .multi-spinner-container`).hide();
499 jQuery(this.pcaMsgDiv)
503 jQuery(`#${this.getRunPcaId(pcaPopId)}`).show();
508 plotPca: function (plotData, downloadLinks) {
509 var scores = plotData.scores;
510 var variances = plotData.variances;
511 var loadings = plotData.loadings;
512 var trialsNames = plotData.trials_names;
519 jQuery.each(scores, function (i, pc) {
523 pc1: parseFloat(pc[2]),
524 pc2: parseFloat(pc[3]),
528 pc1.push(parseFloat(pc[2]));
529 pc2.push(parseFloat(pc[3]));
531 if (!trials.includes(pc[1])) {
544 var totalH = height + pad.top + pad.bottom + 100;
545 var totalW = width + pad.left + pad.right + 400;
547 var pcaCanvasDivId = this.canvas;
548 var pcaPlotPopId = plotData.file_id;
549 var pcaPlotDivId = `${this.pcaPlotDivPrefix}_${pcaPlotPopId}`;
551 pcaPlotDivId = pcaPlotDivId.replace(/#/, "");
552 jQuery(pcaCanvasDivId).append("<div id=" + pcaPlotDivId + "></div>");
554 pcaPlotDivId = "#" + pcaPlotDivId;
556 .select(pcaPlotDivId)
557 .insert("svg", ":first-child")
558 .attr("width", totalW)
559 .attr("height", totalH);
561 var pcaPlot = svg.append("g")
562 .attr("id", pcaPlotDivId)
563 .attr("transform", "translate(0,0)");
565 var pc1Min = d3.min(pc1);
566 var pc1Max = d3.max(pc1);
568 var pc1Limits = d3.max([Math.abs(d3.min(pc1)), d3.max(pc1)]);
569 var pc2Limits = d3.max([Math.abs(d3.min(pc2)), d3.max(pc2)]);
571 var pc1AxisScale = d3.scaleLinear()
572 .domain([0, pc1Limits])
573 .range([0, width / 2]);
575 var pc1AxisLabel = d3.scaleLinear()
576 .domain([-1 * pc1Limits, pc1Limits])
579 var pc2AxisScale = d3.scaleLinear()
580 .domain([0, pc2Limits])
581 .range([0, height / 2]);
583 var pc1Axis = d3.axisBottom(pc1AxisLabel).tickSize(3);
585 var pc2AxisLabel = d3.scaleLinear()
586 .domain([-1 * pc2Limits, pc2Limits])
590 var pc2Axis = d3.axisLeft(pc2AxisLabel).tickSize(3);
592 var pc1AxisMid = 0.5 * height + pad.top;
593 var pc2AxisMid = 0.5 * width + pad.left;
595 var verMidLineData = [
607 var horMidLineData = [
610 y: pad.top + height / 2,
613 x: pad.left + width + rightNudge,
614 y: pad.top + height / 2,
618 var lineFunction = d3.line()
625 // .interpolate("linear");
627 var pc1Color = "green";
628 var pc2Color = "red";
629 var axisValColor = "#86B404";
634 .attr("class", "PC1 axis")
635 .attr("transform", "translate(" + pad.left + "," + (pad.top + height) + ")")
641 .attr("transform", "rotate(90)")
642 .attr("fill", pc1Color)
644 "text-anchor": "start",
650 .attr("transform", "translate(" + pc1AxisMid + "," + height + ")")
652 .text("PC1 (" + variances[0][1] + "%)")
653 .attr("y", pad.top + 40)
655 .attr("font-size", labelFs)
656 .style("fill", pc1Color);
660 .attr("transform", "translate(" + pad.left + "," + pc2AxisMid + ")")
662 .text("PC2 (" + variances[1][1] + "%)")
665 .attr("transform", "rotate(-90)")
666 .attr("font-size", labelFs)
667 .style("fill", pc2Color);
671 .attr("class", "PC2 axis")
672 .attr("transform", "translate(" + pad.left + "," + pad.top + ")")
677 .style("fill", axisValColor);
681 .attr("d", lineFunction(verMidLineData))
682 .attr("stroke", pc2Color)
683 .attr("stroke-width", 1)
684 .attr("fill", "none");
688 .attr("d", lineFunction(horMidLineData))
689 .attr("stroke", pc1Color)
690 .attr("stroke-width", 1)
691 .attr("fill", "none");
693 var grpColor = d3.scaleOrdinal(d3.schemeCategory10);
699 .style("fill", function (d) {
700 return grpColor(trials.indexOf(d[0].trial));
703 .attr("cx", function (d) {
706 return pad.left + width / 2 + pc1AxisScale(xVal);
708 return pad.left + width / 2 - -1 * pc1AxisScale(xVal);
711 .attr("cy", function (d) {
715 return pad.top + height / 2 - pc2AxisScale(yVal);
717 return pad.top + height / 2 + -1 * pc2AxisScale(yVal);
720 .on("mouseover", function (d) {
721 d3.select(this).attr("r", 5).style("fill", axisValColor);
724 .attr("id", "dLabel")
725 .style("fill", axisValColor)
726 .text(d[0].name + "(" + d[0].pc1 + "," + d[0].pc2 + ")")
727 .attr("x", width + pad.left + rightNudge)
728 .attr("y", height / 2);
730 .on("mouseout", function (d) {
733 .style("fill", function (d) {
734 return grpColor(trials.indexOf(d[0].trial));
736 d3.selectAll("text#dLabel").remove();
741 .attr("transform", "translate(" + pad.left + "," + pad.top + ")")
742 .attr("height", height)
743 .attr("width", width + rightNudge)
744 .attr("fill", "none")
745 .attr("stroke", "#523CB5")
746 .attr("stroke-width", 1)
747 .attr("pointer-events", "none");
750 if (plotData.list_name) {
751 popName = plotData.list_name;
754 popName = popName ? popName + " (" + plotData.data_type + ")" : " (" + plotData.data_type + ")";
755 var dld = "Download PCA " + popName + ": ";
758 jQuery(pcaPlotDivId).append('<p style="margin-left: 40px">' + dld + downloadLinks + "</p>");
761 if (trialsNames && Object.keys(trialsNames).length > 1) {
762 var trialsIds = jQuery.uniqueSort(trials);
763 trialsIds = jQuery.uniqueSort(trialsIds);
765 var legendValues = [];
767 var allTrialsNames = [];
769 for (var tr in trialsNames) {
770 allTrialsNames.push(trialsNames[tr]);
773 trialsIds.forEach(function (id) {
776 if (id.match(/\d+-\d+/)) {
777 var ids = id.split("-");
779 ids.forEach(function (id) {
780 groupName.push(trialsNames[id]);
783 groupName = "common: " + groupName.join(",");
785 groupName = trialsNames[id];
787 legendValues.push([cnt, id, groupName]);
793 var legendXOrig = pad.left + 10 + width;
794 var legendYOrig = height * 0.25;
798 .attr("class", "cell")
799 .attr("transform", "translate(" + legendXOrig + "," + legendYOrig + ")")
808 .attr("x", function (d) {
811 .attr("y", function (d) {
812 return 1 + d[0] * recLH + d[0] * 5;
814 .attr("width", recLH)
815 .attr("height", recLW)
816 .style("stroke", "black")
817 .style("fill", function (d) {
818 return grpColor(trials.indexOf(d[1]));
821 var legendTxt = pcaPlot
825 "translate(" + (legendXOrig + 30) + "," + (legendYOrig + 0.5 * recLW) + ")"
827 .attr("id", "legendtext");
834 .attr("fill", "#523CB5")
835 .style("fill", "#523CB5")
837 .attr("y", function (d) {
838 return 1 + d[0] * recLH + d[0] * 5;
843 .attr("dominant-baseline", "middle")
844 .attr("text-anchor", "start");
852 jQuery(document).ready(function () {
853 var url = location.pathname;
854 var canvas = solGS.pca.canvas;
856 if (url.match(/pca\/analysis/)) {
858 var pcaArgs = solGS.pca.getPcaArgsFromUrl();
859 var pcaPopId = pcaArgs.pca_pop_id;
861 if (pcaArgs.data_structure && !pcaPopId.match(/list|dataset/)) {
862 pcaArgs["pca_pop_id"] = pcaArgs.data_structure + "_" + pcaPopId;
864 pcaArgs["analysis_page"] = url;
866 solGS.pca.checkCachedPca(pcaArgs).done(function (res) {
869 var plotData = solGS.pca.structurePlotData(res);
870 var downloadLinks = solGS.pca.pcaDownloadLinks(res);
871 solGS.pca.plotPca(plotData, downloadLinks);
878 jQuery(document).ready(function () {
879 var canvas = solGS.pca.canvas;
881 jQuery(canvas).on("click", "a", function (e) {
882 var linkId = e.target.id;
883 var pcaPlotId = linkId.replace(/download_/, "");
885 if (pcaPlotId.match(/pca_plot_/)) {
886 saveSvgAsPng(document.getElementById("#" + pcaPlotId), pcaPlotId + ".png", { scale: 2 });
892 jQuery(document).ready(function () {
893 var url = location.pathname;
895 if (url.match(/solgs\/selection\/|solgs\/combined\/model\/\d+\/selection\//)) {
896 jQuery("#pca_data_type_select").html('<option selected="genotype">Genotype</option>');
900 jQuery(document).ready(function () {
901 jQuery("#pca_div").on("click", function (e) {
902 var runPcaBtnId = e.target.id;
903 if (runPcaBtnId.match(/run_pca/)) {
906 if (document.URL.match(/pca\/analysis\//)) {
907 pcaArgs = solGS.pca.getSelectedPopPcaArgs(runPcaBtnId);
909 pcaArgs = solGS.pca.getPcaArgs();
912 pcaPopId = pcaArgs.pca_pop_id;
913 var canvas = solGS.pca.canvas;
914 var pcaMsgDiv = solGS.pca.pcaMsgDiv;
915 var pcaUrl = solGS.pca.generatePcaUrl(pcaPopId);
916 pcaArgs["analysis_page"] = pcaUrl;
919 .checkCachedPca(pcaArgs)
920 .done(function (res) {
922 var plotData = solGS.pca.structurePlotData(res);
923 var downloadLinks = solGS.pca.pcaDownloadLinks(res);
924 solGS.pca.plotPca(plotData, downloadLinks);
926 solGS.pca.cleanUpOnSuccess(pcaPopId);
928 var page = location.pathname;
929 var pcaUrl = solGS.pca.generatePcaUrl(pcaArgs.pca_pop_id);
930 pcaArgs["analysis_page"] = pcaUrl;
932 runPcaBtnId = `#${runPcaBtnId}`;
935 "<p>This analysis may take a long time. " +
936 "Do you want to submit the analysis and get an email when it completes?</p>";
938 var jobSubmit = '<div id= "pca_submit">' + title + "</div>";
940 jQuery(jobSubmit).appendTo("body");
942 jQuery("#pca_submit").dialog({
946 title: "pca job submission",
950 class: "btn btn-success",
953 jQuery(this).dialog("close");
954 solGS.submitJob.checkUserLogin(pcaUrl, pcaArgs);
959 text: "No, I will wait till it completes.",
960 class: "btn btn-warning",
963 jQuery(this).dialog("close");
965 jQuery(runPcaBtnId).hide();
967 jQuery(`${canvas} .multi-spinner-container`).show();
968 jQuery(pcaMsgDiv).html("Running pca... please wait...").show();
971 .runPcaAnalysis(pcaArgs)
972 .done(function (res) {
974 var downloadLinks = solGS.pca.pcaDownloadLinks(res);
975 var plotData = solGS.pca.structurePlotData(res);
976 solGS.pca.plotPca(plotData, downloadLinks);
978 solGS.pca.cleanUpOnSuccess(pcaPopId);
980 var msg = "There is no PCA output for this dataset.";
981 solGS.pca.feedBackOnFailure(pcaPopId, msg);
983 jQuery(runPcaBtnId).show();
986 .fail(function (res) {
987 var msg = "Error occured running the PCA.";
988 solGS.pca.feedBackOnFailure(pcaPopId, msg);
989 jQuery(runPcaBtnId).show();
996 class: "btn btn-info",
997 id: "cancel_queue_info",
999 jQuery(this).dialog("close");
1004 jQuery(jobSubmit).show();
1006 jQuery("#queue_job").on("click", function (e) {
1007 solGS.submitJob.checkUserLogin(page, args);
1010 jQuery("#queue_no").on("click", function (e) {
1012 .runPcaAnalysis(pcaArgs)
1013 .done(function (res) {
1015 var plotData = solGS.pca.structurePlotData(res);
1016 var downloadLinks = solGS.pca.pcaDownloadLinks(res);
1017 solGS.pca.plotPca(plotData, downloadLinks);
1019 solGS.pca.cleanUpOnSuccess(pcaPopId);
1021 var msg = "There is no PCA output for this dataset.";
1022 solGS.pca.feedBackOnFailure(pcaPopId, msg);
1025 .fail(function (res) {
1026 var msg = "Error occured running the PCA.";
1027 solGS.pca.feedBackOnFailure(pcaPopId,msg);
1030 jQuery(runPcaBtnId).show();
1035 var msg = "Error occured checking for cached output.";
1036 solGS.pca.feedBackOnFailure(pcaPopId,msg);
1038 jQuery(runPcaBtnId).show();
1043 jQuery(document).ready(function () {
1044 if (location.pathname.match(/pca\/analysis/)) {
1046 pcaPopsDataDiv = solGS.pca.pcaPopsDataDiv;
1047 var tableId = 'pca_pops_table';
1048 var pcaPopsTable = solGS.pca.createTable(tableId)
1049 jQuery(pcaPopsDataDiv).append(pcaPopsTable).show();
1051 var pcaPops = solGS.pca.getPcaPops();
1052 var pcaPopsRows = solGS.pca.getPcaPopsRows(pcaPops);
1054 solGS.pca.displayPcaPopsTable(tableId, pcaPopsRows);
1056 jQuery("#add_new_pops").show();
1062 jQuery.fn.doesExist = function () {
1063 return jQuery(this).length > 0;