From 63d46f9520c6181b1184c4a82301062f7abf539b Mon Sep 17 00:00:00 2001 From: Angelos Chatzimparmpas Date: Mon, 18 Feb 2019 14:30:28 +0100 Subject: [PATCH] fixed correlation issue --- css/style.css | 9 +- data/dataR2.csv | 2 +- index.html | 95 ++- js/checkbox.js | 113 --- js/data_form_handler.js | 26 +- js/tsne.js | 3 +- js/tsne_vis.js | 1491 ++++++++++++++++++++------------------- 7 files changed, 838 insertions(+), 901 deletions(-) delete mode 100755 js/checkbox.js diff --git a/css/style.css b/css/style.css index fec494b..1633c4d 100755 --- a/css/style.css +++ b/css/style.css @@ -220,7 +220,6 @@ rect { box-sizing: border-box; display: inline; font-size: 10px; - width: 100%; line-height: 1; color: rgba(0, 0, 0, 0.8); content: "\25BC"; @@ -310,7 +309,7 @@ rect { } .bar { - /*shape-rendering: crispEdges;*/ + shape-rendering: crispEdges; } /* Styling for the annotation circle */ @@ -351,7 +350,7 @@ rect { .children-columns{ display: flex; } - +/* Margins for the extra-information panel and the kNNInfo */ #extra-information { margin-top: 40px; margin-left: 10px; @@ -370,6 +369,8 @@ rect { margin-left:10px; } +/* Draw a red colored button for reset */ #FactRes{ color: red; -} \ No newline at end of file +} + diff --git a/data/dataR2.csv b/data/dataR2.csv index dd971dd..615a57c 100644 --- a/data/dataR2.csv +++ b/data/dataR2.csv @@ -1,4 +1,4 @@ -Age,BMI,Glucose,Insulin,HOMA,Leptin,Adiponectin,Resistin,MCP.1,name +Age,BMI,Glucose,Insulin,HOMA,Leptin,Adiponectin,Resistin,MCP.1,Category* 48,23.5,70,2.707,0.467408667,8.8071,9.7024,7.99585,417.114,1 83,20.69049454,92,3.115,0.706897333,8.8438,5.429285,4.06405,468.786,1 82,23.12467037,91,4.498,1.009651067,17.9393,22.43204,9.27715,554.697,1 diff --git a/index.html b/index.html index 29fd0c0..f1edd62 100755 --- a/index.html +++ b/index.html @@ -12,7 +12,7 @@ - + @@ -24,7 +24,6 @@ - @@ -128,52 +127,52 @@
-
- - - -
-
- - - 30 -
-
- - - 10 -
-
- - - 500 -
-
- - - - -
-
- - - -
-

+
+ + + +
+
+ + + 30 +
+
+ + + 10 +
+
+ + + 500 +
+
+ + + + +
+
+ + + +
+

diff --git a/js/checkbox.js b/js/checkbox.js deleted file mode 100755 index 022cb93..0000000 --- a/js/checkbox.js +++ /dev/null @@ -1,113 +0,0 @@ -function d3CheckBox () { - - var size = 20, - x = 0, - y = 0, - rx = 0, - ry = 0, - markStrokeWidth = 3, - boxStrokeWidth = 3, - checked = false, - clickEvent; - - function checkBox (selection) { - - var g = selection.append("g"), - box = g.append("rect") - .attr("width", size) - .attr("height", size) - .attr("x", x) - .attr("y", y) - .attr("rx", rx) - .attr("ry", ry) - .style({ - "fill-opacity": 0, - "stroke-width": boxStrokeWidth, - "stroke": "black" - }); - - //Data to represent the check mark - var coordinates = [ - {x: x + (size / 8), y: y + (size / 3)}, - {x: x + (size / 2.2), y: (y + size) - (size / 4)}, - {x: (x + size) - (size / 8), y: (y + (size / 10))} - ]; - - var line = d3.svg.line() - .x(function(d){ return d.x; }) - .y(function(d){ return d.y; }) - .interpolate("basic"); - - var mark = g.append("path") - .attr("d", line(coordinates)) - .style({ - "stroke-width" : markStrokeWidth, - "stroke" : "black", - "fill" : "none", - "opacity": (checked)? 1 : 0 - }); - - g.on("click", function () { - checked = !checked; - mark.style("opacity", (checked)? 1 : 0); - - if(clickEvent) - clickEvent(); - - d3.event.stopPropagation(); - }); - - } - - checkBox.size = function (val) { - size = val; - return checkBox; - } - - checkBox.x = function (val) { - x = val; - return checkBox; - } - - checkBox.y = function (val) { - y = val; - return checkBox; - } - - checkBox.rx = function (val) { - rx = val; - return checkBox; - } - - checkBox.ry = function (val) { - ry = val; - return checkBox; - } - - checkBox.markStrokeWidth = function (val) { - markStrokeWidth = val; - return checkBox; - } - - checkBox.boxStrokeWidth = function (val) { - boxStrokeWidth = val; - return checkBox; - } - - checkBox.checked = function (val) { - - if(val === undefined) { - return checked; - } else { - checked = val; - return checkBox; - } - } - - checkBox.clickEvent = function (val) { - clickEvent = val; - return checkBox; - } - - return checkBox; -} diff --git a/js/data_form_handler.js b/js/data_form_handler.js index 1939b15..775be1c 100755 --- a/js/data_form_handler.js +++ b/js/data_form_handler.js @@ -1,16 +1,20 @@ function changeDataset(value) { - var format = value.split("."); //get the actual format - if (format[value.split(".").length-1] == "csv") { - }else{ - d3.select("#data").select("input").remove(); - d3.select("#data") - .append("input") - .attr("type", "file") - .on("change", function() { + var format = value.split("."); // Get the data set's format. + + if (format[value.split(".").length-1] != "csv") { // This is for a new file. + d3.select("#data").select("input").remove(); + d3.select("#data") + .append("input") + .attr("type", "file") + .style("font-size", "10px") + .on("change", function() { var file = d3.event.target.files[0]; - getfile(file); - }) - } + getfile(file); + }) + } else { + d3.select("#data").select("input").remove(); // Remove the selection field. + } + } diff --git a/js/tsne.js b/js/tsne.js index 6c0f325..17e7fc8 100755 --- a/js/tsne.js +++ b/js/tsne.js @@ -1,4 +1,5 @@ -// create main global object +// t-SNE Algorithm + var tsnejs = tsnejs || { REVISION: 'ALPHA' }; (function(global) { diff --git a/js/tsne_vis.js b/js/tsne_vis.js index 61f4556..d428ad6 100755 --- a/js/tsne_vis.js +++ b/js/tsne_vis.js @@ -1,24 +1,40 @@ -// t-SNE.js object and other global variables +// t-SNE Visualization and global variables -var k; var points = []; var all_fields; var pointsbeta = []; var KNNEnabled = true; var cost = []; var ParametersSet = []; var overallCost; -// form controls -var input; -// These are the dimensions for the square shape of the main panel\ -var dimensions = document.getElementById('modtSNEcanvas').offsetWidth; -var prevRightClick; var ColorsCategorical; var Category; +// This variable is used when a new file is upload by a user. +var new_file; -// These are the dimensions for the overview panel -var dim = document.getElementById('tSNEcanvas').offsetWidth; +// The basic variables in order to execute t-SNE (opt is perplexity and learning rate). +var tsne; var opt; var step_counter; var max_counter; var runner; -var format; var new_file; var opt; var step_counter; var final_dataset; var max_counter; var dists; var dists2d; var all_labels; var runner; var tsne; var count_canvas = 0; var x_position = []; var y_position = []; var x_position2 = []; var y_position2 = []; var cost_each; var beta_all = []; -var points2d = []; var ArrayContainsDataFeatures = []; var ArrayContainsDataFeaturesCleared = []; -var InitialStatePoints = []; +// These variables are initialized here in order to store the final dataset, the points, the cost, the cost for each iteration, the beta values, the positions, the 2D points positions, +// In addition, there is an array which keeps the initial information of the points (i.e., initial state), the data features (with the label of the category plus the id of the point), the data features without the category (only numbers). +var final_dataset; var points = []; var cost = []; var cost_each; var beta_all = []; var x_position = []; var y_position = []; var points2d = []; var ArrayContainsDataFeatures = []; var ArrayContainsDataFeaturesCleared = []; var InitialStatePoints = []; +// The distances in the high dimensional space and in the 2D space. All the labels that were found in the selected data set. +var dists; var dists2d; var all_labels; + +// These are the dimensions for the Overview view and the Main view +var dim = document.getElementById('tSNEcanvas').offsetWidth; var dimensions = document.getElementById('modtSNEcanvas').offsetWidth; + +// Category = the name of the category if it exists. The user has to add an asterisk ("*") mark in order to let the program identify this feature as a label/category name. +// ColorsCategorical = the categorical colors (maximum value = 10). +var Category; var ColorsCategorical; + +// Schema Investigation +// svgClick = Click a left mouse click in order to add a point. +// prevRightClick = When right click is pressed prevent any other action. Lock the current schema. +// if flagForSchema is false then send a message to the user that he/she has to: "Please, draw a schema first!"); +var svgClick; var prevRightClick; var flagForSchema = false; + +// Save the parameters for the current analysis, save the overallCost, and store in the "input" variable all the points and points2D. +var ParametersSet = []; var overallCost; var input; + +// This function is executed when the factory button is pressed in order to bring the visualization in the initial state. function FactoryReset(){ - lassoEnable(); - flag = false; + flagForSchema = false; d3.selectAll("#modtSNEcanvas_svg_Schema > *").remove(); - d3.selectAll("#SvgAnnotator > *").remove(); + d3.selectAll("#SvgAnnotator > *").remove(); + d3.select("#data").select("input").remove(); // Remove the selection field. Arrayx = []; Arrayy = []; XYDistId = []; @@ -95,15 +111,18 @@ function FactoryReset(){ } +// Load a previously executed analysis function. function loadAnalysis(){ document.getElementById('file-input').click(); document.getElementById("ExecuteBut").innerHTML = "Execute previous t-SNE analysis"; } +// This function is being used when the user selects to upload a new data set. function getfile(file){ - new_file = file; //uploaded file data + new_file = file; //uploaded data file } +// Read the previous analysis, which the user wants to upload. function fetchVal(callback) { var file, fr; file = input.files[0]; @@ -115,24 +134,25 @@ function fetchVal(callback) { fr.readAsText(file); } -// Parse data +// Parse the data set var getData = function() { - + + let format; + let value; + if (typeof window.FileReader !== 'function') { alert("The file API isn't supported on this browser yet."); } - var value; input = document.getElementById("file-input"); if (!input) { alert("Um, couldn't find the fileinput element."); - } - else if (!input.files) { + } else if (!input.files) { alert("This browser doesn't seem to support the `files` property of file inputs."); - } - else if (!input.files[0]) { - value = document.getElementById("param-dataset").value; - format = document.getElementById("param-dataset").value.split("."); //get the actual format + } else if (!input.files[0]) { + value = document.getElementById("param-dataset").value; // get the value of the data set + format = document.getElementById("param-dataset").value.split("."); //get the format + if (format[value.split(".").length-1] == "csv") { parseData("./data/"+value); }else{ @@ -168,8 +188,6 @@ function parseData(url) { for(key in el) { if(el.hasOwnProperty(key)) { var value = el[key]; - if (key === 'name'){ - }else{ if(typeof(value) !== 'number' || value === undefined || key === "Version"){ //add more limitations if needed! delete el[key]; }else{ @@ -177,7 +195,6 @@ function parseData(url) { delete el[key]; counter = counter + 1; } - } } } return el; @@ -211,7 +228,7 @@ function setReset(){ d3.selectAll("#correlation > *").remove(); d3.selectAll("#modtSNEcanvas_svg > *").remove(); lassoEnable(); - flag = false; + flagForSchema = false; d3.selectAll("#modtSNEcanvas_svg_Schema > *").remove(); d3.selectAll("#SvgAnnotator > *").remove(); Arrayx = []; @@ -259,7 +276,9 @@ function setLayerComp(){ d3.select("#modtSNEcanvas_svg").style("z-index", 2); d3.select("#modtSNEcanvas_svg_Schema").style("z-index", 1); d3.select("#modtSNEcanvas").style("z-index", 1); - lassoEnable(); + if (points.length){ + lassoEnable(); + } } function setLayerSche(){ @@ -355,6 +374,11 @@ function setAnnotator(){ .classed("shaded", function(d) { return d.shaded; }); } } else{ + // Get the checkbox. + var checkBox = document.getElementById("controls"); + // Unchecked! + checkBox.checked = false; + // Print a message to the user. alert("Cannot hide the annotators' controls because, currently, there are no annotations into the visual representation.") } }); @@ -458,7 +482,6 @@ function init(data, results_all, fields) { var fields; fields.push("beta"); fields.push("cost"); - all_fields = fields; opt.epsilon = document.getElementById("param-learningrate-value").value; // epsilon is learning rate (10 = default) opt.perplexity = document.getElementById("param-perplexity-value").value; // roughly how many neighbors each point influences (30 = default) tsne = new tsnejs.tSNE(opt); @@ -483,19 +506,17 @@ function init(data, results_all, fields) { for (let k = 0; k < dataFeatures.length; k++){ ArrayContainsDataFeatures.push(Object.values(dataFeatures[k]).concat(k)); object = []; - Object.values(dataFeatures[k]).forEach(function(dataFeature){ - if(typeof(dataFeature) == "number"){ - object.push(dataFeature); - } - }); + for (let j = 0; j < Object.keys(dataFeatures[k]).length; j++){ + if(typeof(Object.values(dataFeatures[k])[j]) == "number" && Object.keys(dataFeatures[k])[j] != Category){ + object.push(Object.values(dataFeatures[k])[j]); + } + } ArrayContainsDataFeaturesCleared.push(object); } - var valCategExists = 0; for (var i=0; i" + Math.round(d.value); }); @@ -1114,7 +1135,6 @@ function redraw(repoints){ function handleLassoEnd(lassoPolygon) { var countLassoFalse = 0; - KNNEnabled = true; for (var i = 0 ; i < points.length ; i ++) { x = points[i].x; @@ -1152,7 +1172,6 @@ function handleLassoEnd(lassoPolygon) { // reset selected points when starting a new polygon function handleLassoStart(lassoPolygon) { - KNNEnabled = false; for (var i = 0 ; i < points.length ; i ++) { points[i].selected = true; points[i].starplot = false; @@ -1198,9 +1217,6 @@ var svg, .on("touchmove.zoom", null) .on("touchend.zoom", null); -var svgClick; -var flag = false; - function click(){ svgClick = d3.select('#modtSNEcanvas_svg_Schema'); @@ -1251,7 +1267,7 @@ function click(){ // Prevent the default mouse action. Allow right click to be used for the confirmation of our schema. d3.event.preventDefault(); - flag = true; + flagForSchema = true; CalculateCorrel(); } }); @@ -1259,7 +1275,7 @@ function click(){ function CalculateCorrel(){ - if (flag == false){ + if (flagForSchema == false){ alert("Please, draw a schema first!"); } else{ var correlLimit = document.getElementById("param-corr-value").value; @@ -1317,7 +1333,7 @@ function CalculateCorrel(){ ArrayLimit = []; for (var i=0; i arr.map(x => x[n]); - for (var temp = 0; temp < ArrayContainsDataFeaturesLimit[0].length - 2; temp++) { - var tempData = new Array( - arrayColumn(ArrayContainsDataFeaturesLimit, temp), - arrayColumn(ArrayContainsDataFeaturesLimit, ArrayContainsDataFeaturesLimit[0].length - 1) - ); - if (isNaN(pearsonCorrelation(tempData, 0, 1))) { - } else{ - SignStore.push([temp, pearsonCorrelation(tempData, 0, 1)]); - correlationResults.push([Object.keys(dataFeatures[0])[temp] + " (" + temp + ")", Math.abs(pearsonCorrelation(tempData, 0, 1))]); + + if (ArrayContainsDataFeaturesLimit.length == 0){ + d3.selectAll("#correlation > *").remove(); + d3.selectAll("#modtSNEcanvas_svg > *").remove(); + flagForSchema = false; + d3.selectAll("#modtSNEcanvas_svg_Schema > *").remove(); + Arrayx = []; + Arrayy = []; + XYDistId = []; + Arrayxy = []; + DistanceDrawing1D = []; + allTransformPoints = []; + p; + pFinal = []; + paths; + path; + ArrayLimit = []; + minimum; + correlationResults = []; + ArrayContainsDataFeaturesLimit = []; + prevRightClick = false; + for (var i=0; i < InitialStatePoints.length; i++){ + InitialStatePoints[i].selected = true; + InitialStatePoints[i].starplot = false; } - } - correlationResults = correlationResults.sort( - function(a,b) { - if (a[1] == b[1]) - return a[0] < b[0] ? -1 : 1; - return a[1] < b[1] ? 1 : -1; + alert("No points selected! Please, try to increase the correlation threshold."); + redraw(InitialStatePoints); + } else { + for (var loop = 0; loop < ArrayContainsDataFeaturesLimit.length; loop++) { + ArrayContainsDataFeaturesLimit[loop].push(loop); } - ); - - for (var j = 0; j < correlationResults.length; j++) { - for (var i = 0; i < SignStore.length; i++) { - if (SignStore[i][1]*(-1) == correlationResults[j][1]) { - correlationResults[j][1] = parseInt(correlationResults[j][1] * 100) * (-1); - correlationResults[j].push(j); + + var SignStore = []; + correlationResults = []; + const arrayColumn = (arr, n) => arr.map(x => x[n]); + for (var temp = 0; temp < ArrayContainsDataFeaturesLimit[0].length - 2; temp++) { + var tempData = new Array( + arrayColumn(ArrayContainsDataFeaturesLimit, temp), + arrayColumn(ArrayContainsDataFeaturesLimit, ArrayContainsDataFeaturesLimit[0].length - 1) + ); + if (isNaN(pearsonCorrelation(tempData, 0, 1))) { + } else{ + SignStore.push([temp, pearsonCorrelation(tempData, 0, 1)]); + correlationResults.push([Object.keys(dataFeatures[0])[temp] + " (" + temp + ")", Math.abs(pearsonCorrelation(tempData, 0, 1))]); } - if (SignStore[i][1] == correlationResults[j][1]) { - correlationResults[j][1] = parseInt(correlationResults[j][1] * 100); - correlationResults[j].push(j); + } + correlationResults = correlationResults.sort( + function(a,b) { + if (a[1] == b[1]) + return a[0] < b[0] ? -1 : 1; + return a[1] < b[1] ? 1 : -1; + } + ); + + for (var j = 0; j < correlationResults.length; j++) { + for (var i = 0; i < SignStore.length; i++) { + if (SignStore[i][1]*(-1) == correlationResults[j][1]) { + correlationResults[j][1] = parseInt(correlationResults[j][1] * 100) * (-1); + correlationResults[j].push(j); + } + if (SignStore[i][1] == correlationResults[j][1]) { + correlationResults[j][1] = parseInt(correlationResults[j][1] * 100); + correlationResults[j].push(j); + } } } } - } - drawBarChart(); + drawBarChart(); + } } } @@ -1960,744 +2004,745 @@ height = Math.min(width, window.innerHeight - margin.top - margin.bottom); function BetatSNE(points){ - selectedPoints = []; - var findNearestTable = []; - for (let m=0; m0; k--){ + for (k=maxKNN; k>1; k--){ - findNearest = 0; - var indexOrderSliced = []; - var indexOrderSliced2d = []; - var count1 = new Array(selectedPoints.length).fill(0); - var count2 = new Array(selectedPoints.length).fill(0); - counter1 = 0; - counter2 = 0; + findNearest = 0; + var indexOrderSliced = []; + var indexOrderSliced2d = []; + var count1 = new Array(selectedPoints.length).fill(0); + var count2 = new Array(selectedPoints.length).fill(0); + counter1 = 0; + counter2 = 0; - for (var i=0; i -1) { - indices[i].splice(index, 1); - } - // sorting the mapped array containing the reduced values - indices[i].sort(function(a, b) { - if (a[1] > b[1]) { - return 1; + // temporary array holds objects with position and sort-value + indices[i] = dists[i].map(function(el, i) { + return [ i, el ]; + }) + var index = indices[i].indexOf(selectedPoints[i].id); + if (index > -1) { + indices[i].splice(index, 1); } - if (a[1] < b[1]) { - return -1; + // sorting the mapped array containing the reduced values + indices[i].sort(function(a, b) { + if (a[1] > b[1]) { + return 1; + } + if (a[1] < b[1]) { + return -1; + } + return 0; + }); + + indexOrder[i] = indices[i].map(function(value) { return value[0]; }); + + // temporary array holds objects with position and sort-value + indices2d[i] = dists2d[i].map(function(el, i) { + return [ i, el ]; + }) + var index2d = indices2d[i].indexOf(selectedPoints[i].id); + if (index2d > -1) { + indices2d[i].splice(index2d, 1); } - return 0; - }); - - indexOrder[i] = indices[i].map(function(value) { return value[0]; }); - - // temporary array holds objects with position and sort-value - indices2d[i] = dists2d[i].map(function(el, i) { - return [ i, el ]; - }) - var index2d = indices2d[i].indexOf(selectedPoints[i].id); - if (index2d > -1) { - indices2d[i].splice(index2d, 1); + + // sorting the mapped array containing the reduced values + indices2d[i].sort(function(a, b) { + if (a[1] > b[1]) { + return 1; + } + if (a[1] < b[1]) { + return -1; + } + return 0; + }); + indexOrder2d[i] = indices2d[i].map(function(value) { return value[0]; }); } - - // sorting the mapped array containing the reduced values - indices2d[i].sort(function(a, b) { - if (a[1] > b[1]) { - return 1; - } - if (a[1] < b[1]) { - return -1; - } - return 0; - }); - indexOrder2d[i] = indices2d[i].map(function(value) { return value[0]; }); - } - indexOrderSliced[i] = indexOrder[i].slice(0,k); - indexOrderSliced2d[i] = indexOrder2d[i].slice(0,k); + indexOrderSliced[i] = indexOrder[i].slice(0,k); + indexOrderSliced2d[i] = indexOrder2d[i].slice(0,k); - for (var m=0; m < indexOrderSliced2d[i].length; m++){ - if (indexOrderSliced[i].includes(indexOrderSliced2d[i][m])){ - count1[i] = count1[i] + 1; - temp[i] = temp[i] + 1; - } - if(indexOrderSliced[i][m] == indexOrderSliced2d[i][m]){ - count2[i] = count2[i] + 1; - temp2[i] = temp2[i] + 1; + for (var m=0; m < indexOrderSliced2d[i].length; m++){ + if (indexOrderSliced[i].includes(indexOrderSliced2d[i][m])){ + count1[i] = count1[i] + 1; + temp[i] = temp[i] + 1; + } + if(indexOrderSliced[i][m] == indexOrderSliced2d[i][m]){ + count2[i] = count2[i] + 1; + temp2[i] = temp2[i] + 1; + } + } + + if (count1[i] != 0){ + counter1 = (count1[i] / temp[i]) + counter1; + } + if (count2[i] != 0){ + counter2 = (count2[i] / temp2[i]) + counter2; } - } - if (count1[i] != 0){ - counter1 = (count1[i] / temp[i]) + counter1; - } - if (count2[i] != 0){ - counter2 = (count2[i] / temp2[i]) + counter2; } - } + sumUnion = counter1 / selectedPoints.length; + sumIntersection = counter2 / selectedPoints.length; + if (sumUnion == 0){ + findNearest = 0; + } else{ + findNearest = sumIntersection / sumUnion; + } - sumUnion = counter1 / selectedPoints.length; - sumIntersection = counter2 / selectedPoints.length; - if (sumUnion == 0){ - findNearest = 0; - } else{ - findNearest = sumIntersection / sumUnion; - } + if (isNaN(findNearest)){ + findNearest = 0; + } + findNearestTable.push(findNearest * vh * 2); + } + findNearestTable.reverse(); - if (isNaN(findNearest)){ - findNearest = 0; - } - findNearestTable.push(findNearest * vh * 2); - } - findNearestTable.reverse(); + var barPadding = 5; + d3v3.select("#knnBarChart").selectAll("rect").remove(); - var barPadding = 5; - d3v3.select("#knnBarChart").selectAll("rect").remove(); + var svg2 = d3v3.select('#knnBarChart') + .attr("class", "bar-chart"); - var svg2 = d3v3.select('#knnBarChart') - .attr("class", "bar-chart"); + + var barWidth = (vw / findNearestTable.length); - - var barWidth = (vw / findNearestTable.length); - - var knnBarChartSVG = svg2.selectAll("rect") - .data(findNearestTable) - .enter() - .append("rect") - .attr("y", function(d) { - return Math.round(vh*2 - d) - }) - .attr("height", function(d) { - return d; - }) - .attr("width", barWidth - barPadding) - .attr("transform", function (d, i) { - var translate = [barWidth * i, 0]; - return "translate("+ translate +")"; - }); - } + var knnBarChartSVG = svg2.selectAll("rect") + .data(findNearestTable) + .enter() + .append("rect") + .attr("y", function(d) { + return Math.round(vh*2 - d) + }) + .attr("height", function(d) { + return d; + }) + .attr("width", barWidth - barPadding) + .attr("transform", function (d, i) { + var translate = [barWidth * i, 0]; + return "translate("+ translate +")"; + }); + } - d3.select("#starPlot").selectAll('g').remove(); - var coun = 0; - for (var i=0; i < selectedPoints.length; i++){ - if (selectedPoints[i].starplot == true){ - coun = coun + 1; - } - } + d3.select("#starPlot").selectAll('g').remove(); + var coun = 0; + for (var i=0; i < selectedPoints.length; i++){ + if (selectedPoints[i].starplot == true){ + coun = coun + 1; + } + } - if(selectedPoints.length <= 10 && coun > 0){ - - var FeatureWise = []; - - for (var j=0; j 0){ + + var FeatureWise = []; + + for (var j=0; j FeatureWiseSliced[i]){ - min[j] = FeatureWiseSliced[i]; + + max[j] = FeatureWiseSliced[0]; + min[j] = FeatureWiseSliced[0]; + for (var i=0; i FeatureWiseSliced[i]){ + min[j] = FeatureWiseSliced[i]; + } } } - } - var vectors = PCA.getEigenVectors(ArrayContainsDataFeaturesCleared); - var PCAResults = PCA.computeAdjustedData(ArrayContainsDataFeaturesCleared,vectors[0]); - var PCASelVec = []; - PCASelVec = PCAResults.selectedVectors[0]; - - var len = PCASelVec.length; - var indices = new Array(len); - for (var i = 0; i < len; ++i) indices[i] = i; - indices = indices.sort(function (a, b) { return PCASelVec[a] < PCASelVec[b] ? -1 : PCASelVec[a] > PCASelVec[b] ? 1 : 0; }); - //const list = dataFeatures.sort((a,b) => a.index - b.index).map((dataFeatures, index, array) => dataFeatures[Category]) - - var wrapData = []; - var IDS = []; - for (var i=0; i PCASelVec[b] ? 1 : 0; }); + //const list = dataFeatures.sort((a,b) => a.index - b.index).map((dataFeatures, index, array) => dataFeatures[Category]) + + var wrapData = []; + var IDS = []; + for (var i=0; i { + dimensions = window.innerWidth; + dimensions = window.innerHeight; - var legend = d3.legendColor() - .labelFormat(d3.format(",.5f")) - .cells(9) - .labels([abbr_labels_cost[0],abbr_labels_cost[1],abbr_labels_cost[2],abbr_labels_cost[3],abbr_labels_cost[4],abbr_labels_cost[5],abbr_labels_cost[6],abbr_labels_cost[7],abbr_labels_cost[8]]) - .title("KLD(P||Q)") - .scale(colorScale); - - svg.select(".legendLinear") - .call(legend); -} + renderer.setSize(dimensions, dimensions); + camera.aspect = dimensions / dimensions; + camera.updateProjectionMatrix(); + }) -window.addEventListener('resize', () => { - dimensions = window.innerWidth; - dimensions = window.innerHeight; + let zoom = d3.zoom() + .scaleExtent([getScaleFromZ(far), getScaleFromZ(near)]) + .on('zoom', () => { + let d3_transform = d3.event.transform; + zoomHandler(d3_transform); + }); - renderer.setSize(dimensions, dimensions); - camera.aspect = dimensions / dimensions; - camera.updateProjectionMatrix(); -}) + view = d3.select(renderer.domElement); -let zoom = d3.zoom() - .scaleExtent([getScaleFromZ(far), getScaleFromZ(near)]) - .on('zoom', () => { - let d3_transform = d3.event.transform; - zoomHandler(d3_transform); - }); + function setUpZoom() { + view.call(zoom); + let initial_scale = getScaleFromZ(far); + var initial_transform = d3.zoomIdentity.translate(dimensions/2, dimensions/2).scale(initial_scale); + zoom.transform(view, initial_transform); + camera.position.set(0, 0, far); + } -view = d3.select(renderer.domElement); + //if(step_counter == max_counter){ + setUpZoom(); + //} -function setUpZoom() { - view.call(zoom); - let initial_scale = getScaleFromZ(far); - var initial_transform = d3.zoomIdentity.translate(dimensions/2, dimensions/2).scale(initial_scale); - zoom.transform(view, initial_transform); - camera.position.set(0, 0, far); -} + var circle_sprite= new THREE.TextureLoader().load( + "./textures/circle-sprite.png" + ) -//if(step_counter == max_counter){ -setUpZoom(); -//} -var circle_sprite= new THREE.TextureLoader().load( - "./textures/circle-sprite.png" -) + clearThree(scene); + // Increase/reduce size factor selected by the user + var limitdist = document.getElementById("param-lim-value").value; + limitdist = parseFloat(limitdist).toFixed(1); -clearThree(scene); + let pointsMaterial; + let factorPlusSize; + let geometry = new THREE.Geometry(); + for (var i=0; i { - let [mouseX, mouseY] = d3.mouse(view.node()); - let mouse_position = [mouseX, mouseY]; -checkIntersects(mouse_position); -}); + view.on("mousemove", () => { + let [mouseX, mouseY] = d3.mouse(view.node()); + let mouse_position = [mouseX, mouseY]; + checkIntersects(mouse_position); + }); -function mouseToThree(mouseX, mouseY) { - return new THREE.Vector3( - mouseX / dimensions * 2 - 1, - -(mouseY / dimensions) * 2 + 1, - 1 - ); -} -function checkIntersects(mouse_position) { - let mouse_vector = mouseToThree(...mouse_position); - raycaster.setFromCamera(mouse_vector, camera); - let intersects = raycaster.intersectObject(particlesDuplic); - if (intersects[0]) { - if (ColSizeSelector == "color"){ - points = points.sort(function(a, b) { - return a.beta - b.beta; - }) - } else{ + function mouseToThree(mouseX, mouseY) { + return new THREE.Vector3( + mouseX / dimensions * 2 - 1, + -(mouseY / dimensions) * 2 + 1, + 1 + ); + } + function checkIntersects(mouse_position) { + let mouse_vector = mouseToThree(...mouse_position); + raycaster.setFromCamera(mouse_vector, camera); + let intersects = raycaster.intersectObject(particlesDuplic); + if (intersects[0]) { + if (ColSizeSelector == "color"){ points = points.sort(function(a, b) { - return a.cost - b.cost; + return a.beta - b.beta; }) + } else{ + points = points.sort(function(a, b) { + return a.cost - b.cost; + }) + } + let sorted_intersects = sortIntersectsByDistanceToRay(intersects); + let intersect = sorted_intersects[0]; + let index = intersect.index; + let datum = points[index]; + highlightPoint(datum); + showTooltip(mouse_position, datum); + } else { + removeHighlights(); + hideTooltip(); } - let sorted_intersects = sortIntersectsByDistanceToRay(intersects); - let intersect = sorted_intersects[0]; - let index = intersect.index; - let datum = points[index]; - highlightPoint(datum); - showTooltip(mouse_position, datum); - } else { - removeHighlights(); - hideTooltip(); } -} -function sortIntersectsByDistanceToRay(intersects) { - return _.sortBy(intersects, "distanceToRay"); -} + function sortIntersectsByDistanceToRay(intersects) { + return _.sortBy(intersects, "distanceToRay"); + } -hoverContainer = new THREE.Object3D() -scene.add(hoverContainer); + hoverContainer = new THREE.Object3D() + scene.add(hoverContainer); -function highlightPoint(datum) { - removeHighlights(); - - let geometry = new THREE.Geometry(); + function highlightPoint(datum) { + removeHighlights(); + + let geometry = new THREE.Geometry(); + + geometry.vertices.push( + new THREE.Vector3( + (((datum.x/dimensions)*2) - 1)*dimensions, + (((datum.y/dimensions)*2) - 1)*dimensions*-1, + 0 + ) + ); - geometry.vertices.push( - new THREE.Vector3( - (((datum.x/dimensions)*2) - 1)*dimensions, - (((datum.y/dimensions)*2) - 1)*dimensions*-1, - 0 - ) - ); + if (all_labels[0] == undefined){ + var colorScaleCat = d3.scaleOrdinal().domain(["No Category"]).range(["#C0C0C0"]); + } + else{ + var colorScaleCat = d3.scaleOrdinal().domain(all_labels).range(ColorsCategorical); + } - if (all_labels[0] == undefined){ - var colorScaleCat = d3.scaleOrdinal().domain(["No Category"]).range(["#C0C0C0"]); - } - else{ - var colorScaleCat = d3.scaleOrdinal().domain(all_labels).range(ColorsCategorical); + geometry.colors = [ new THREE.Color(colorScaleCat(datum[Category])) ]; + + let material = new THREE.PointsMaterial({ + size: 26, + sizeAttenuation: false, + vertexColors: THREE.VertexColors, + map: circle_sprite, + transparent: true + }); + + let point = new THREE.Points(geometry, material); + hoverContainer.add(point); } - geometry.colors = [ new THREE.Color(colorScaleCat(datum[Category])) ]; + function removeHighlights() { + hoverContainer.remove(...hoverContainer.children); + } - let material = new THREE.PointsMaterial({ - size: 26, - sizeAttenuation: false, - vertexColors: THREE.VertexColors, - map: circle_sprite, - transparent: true + view.on("mouseleave", () => { + removeHighlights() }); - - let point = new THREE.Points(geometry, material); - hoverContainer.add(point); -} -function removeHighlights() { - hoverContainer.remove(...hoverContainer.children); -} - -view.on("mouseleave", () => { - removeHighlights() -}); - -// Initial tooltip state -let tooltip_state = { display: "none" } -let tooltip_dimensions; -let tooltip_template = document.createRange().createContextualFragment(``); -document.body.append(tooltip_template); - -let $tooltip = document.querySelector('#tooltip'); -let $point_tip = document.querySelector('#point_tip'); -let $group_tip = document.querySelector('#group_tip'); - -function updateTooltip() { - if (all_labels[0] == undefined){ - var colorScaleCat = d3.scaleOrdinal().domain(["No Category"]).range(["#C0C0C0"]); - } - else{ - var colorScaleCat = d3.scaleOrdinal().domain(all_labels).range(ColorsCategorical); - } - $tooltip.style.display = tooltip_state.display; - $tooltip.style.left = tooltip_state.left + 'px'; - $tooltip.style.top = tooltip_state.top + 'px'; - $point_tip.innerText = tooltip_state[Category]; - $point_tip.style.background = colorScaleCat(tooltip_state.color); - var tooltipComb = []; - tooltipComb = "Data set's features: " + "\n"; - if (tooltip_dimensions){ - for (var i=0; i