Compare commits

...

11 Commits

Author SHA1 Message Date
Angelos Chatzimparmpas 19f6f21e82 Update 'README.md' 2 years ago
Angelos Chatzimparmpas 66e4f7e056 Update 'README.md' 3 years ago
Angelos Chatzimparmpas fd3c3c2479 Update 'README.md' 4 years ago
Angelos Chatzimparmpas 1acb88ac6c responsiveness 4 years ago
Angelos Chatzimparmpas 093766d48c responsiveness 4 years ago
Angelos Chatzimparmpas 2ab18b74b3 responsiveness 4 years ago
Angelos Chatzimparmpas 23a34d2ec2 fix responsiveness at first panel 4 years ago
Angelos Chatzimparmpas 17d75ed34c Update 'README.md' 4 years ago
Angelos Chatzimparmpas 7819370d17 Update 'README.md' 4 years ago
Angelos Chatzimparmpas 0c6880d310 new 4 years ago
Angelos Chatzimparmpas 0fe24e8710 new 4 years ago
  1. 14
      README.md
  2. 1000
      betas.txt
  3. 1000
      cost_per_iter.txt
  4. 1000
      cost_per_point.txt
  5. 174
      css/style.css
  6. 464
      index.html
  7. 3
      js/data_form_handler.js
  8. 318
      js/tsne_vis.js
  9. BIN
      result.dat

@ -1,10 +1,15 @@
# t-viSNE: Interactive Assessment and Interpretation of t-SNE Projections # # t-viSNE: Interactive Assessment and Interpretation of t-SNE Projections #
This Git repository contains the code that accompanies the research paper "t-viSNE: Interactive Assessment and Interpretation of t-SNE Projections". The details of the experiments and the research outcome are described in [the paper](https://arxiv.org/abs/2002.06910) (soon to appear in IEEE Transactions on Visualization and Computer Graphics).
**Note:** t-viSNE is optimized to work better for the 2560x1440 resolution (1440p/QHD (Quad High Definition)). Any other resolution might need manual adjustment of your browser's zoom level to work properly. This Git repository contains the code that accompanies the research paper "t-viSNE: Interactive Assessment and Interpretation of t-SNE Projections". The details of the experiments and the research outcome are described in [the paper](https://doi.org/10.1109/TVCG.2020.2986996).
**Note:** t-viSNE is optimized to work better for standard resolutions (such as 1440p/QHD (Quad High Definition) and 1080p). Any other resolution might need manual adjustment of your browser's zoom level to work properly.
**Note:** The tag `paper-version` matches the implementation at the time of the paper's publication. The current version might look significantly different depending on how much time has passed since then. **Note:** The tag `paper-version` matches the implementation at the time of the paper's publication. The current version might look significantly different depending on how much time has passed since then.
**Note**: This software is based on the bhtsne library, its native executable and the python interface that is used to call the native executable. This library is the official implementation of t-SNE, made by its authors. Using the exact same input data, different systems will generate slightly different outputs in this library, and such differences will propagate to our software.
**Note:** As any other software, the code is not bug free. There might be limitations in the views and functionalities of the tool that could be addressed in a future code update.
# Data Sets # # Data Sets #
All data sets used in the paper are in the `data` folder, formatted as comma separated values (csv). All data sets used in the paper are in the `data` folder, formatted as comma separated values (csv).
Most of them are available online from the [UCI Machine Learning Repository](http://archive.ics.uci.edu/ml/index.php): Iris, Breast Cancer Wisconsin (Original), Pima Indians Diabetes, and SPECTF. We also used a custom-made data set with Gaussian clusters. Most of them are available online from the [UCI Machine Learning Repository](http://archive.ics.uci.edu/ml/index.php): Iris, Breast Cancer Wisconsin (Original), Pima Indians Diabetes, and SPECTF. We also used a custom-made data set with Gaussian clusters.
@ -28,9 +33,8 @@ For the frontend:
There is no need to install anything for the frontend, since all modules are in the repository. There is no need to install anything for the frontend, since all modules are in the repository.
# Usage # # Usage #
Below is an example of how you can get t-viSNE running using Python for both frontend and backend. The frontend is written in Javascript/HTML, so it could be hosted in any other web server of your preference. The only hard requirement (currently) is that both frontend and backend must be running on the same machine. Below is an example of how you can get t-viSNE running using Python for both frontend and backend. The frontend is written in JavaScript/HTML, so it could be hosted in any other web server of your preference. The only hard requirement (currently) is that both frontend and backend must be running on the same machine.
``` ```
# first terminal: hosting the visualization side (client) # first terminal: hosting the visualization side (client)
# for Python3 # for Python3
@ -67,4 +71,4 @@ The following instructions describe how to reach the results present in Figure 1
**Outcome:** The above process describes how you will be able to reproduce precisely the results presented in Figures 1 and 7 of the paper. Thank you for your time! **Outcome:** The above process describes how you will be able to reproduce precisely the results presented in Figures 1 and 7 of the paper. Thank you for your time!
# Corresponding Author # # Corresponding Author #
For any questions with regard to the implementation or the paper, feel free to contact [Angelos Chatzimparmpas](mailto:angelos.chatzimparmpas@lnu.se). For any questions with regard to the implementation or the paper, feel free to contact [Angelos Chatzimparmpas](mailto:angelos.chatzimparmpas@lnu.se).

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,104 +1,95 @@
/* Custom styling */ /* Custom styling */
/* Main html/body configurations */
html, body { html, body {
max-width: 100%; max-width: 100% !important;
margin-top: -5px !important;
font-family: sans-serif !important; font-family: sans-serif !important;
font-size: 15px !important; font-size: calc(0.32em + 1vmin) !important;
/*overflow-x: hidden;
overflow-y: hidden;*/
} }
.container-fluid { h2 {
margin-top: 8px; font-size: calc(0.5em + 1vmin) !important;
} }
.btn{ select {
font-size: 15px !important; font-size: calc(0.35em + 1vmin) !important;
} }
button {
#param-correlation { font-size: calc(0.35em + 1vmin) !important;
flex: 1;
display: flex;
flex-direction: column;
} }
#param-correlation > .param { .container-fluid {
display: flex; margin-top: 15px;
margin: 5px 0px;
} }
#param-correlation > .param > label { .table {
width: 200px; padding: 0 !important;
text-align: left; margin: 0 !important;
padding: 4px 0 0 0px;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
cursor: default;
} }
#param-correlation > .param > input[type='range'] { table td {
width: 60%; vertical-align: middle !important;
margin-right: 10px; padding: 2 !important;
text-align: left; margin: 0 !important;
} }
#param-correlation > .param > select { .centerTable {
flex: 0 0 45%; text-align: center;
width: 100%;
text-align: left;
} }
#param-correlation > .param > output { .centerTable td {
flex: 1; padding: 0.9vh !important;
text-align: left;
padding:5px 0;
vertical-align: middle;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
cursor: default;
} }
/* Control panels on the left side are styled */ input[type='file'] {
color: transparent; /* Hides your "No File Selected" */
width: 95px;
}
#control-panel { #param-correlation {
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
#control-panel > .param { #param-correlation > .param {
display: flex; display: flex;
margin: 5px 0px; margin: 5px 0px;
} }
#control-panel > .param > label { #param-correlation > .param > label {
width: 200px; width: 200px;
text-align: left; text-align: left;
padding: 4px 0 0 8px; padding: 4px 0 0 0px;
user-select: none; user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
-moz-user-select: none; -moz-user-select: none;
cursor: default; cursor: default;
} }
#control-panel > .param > input[type='range'] { #param-correlation > .param > input[type='range'] {
width: 60%; width: 60%;
margin-right: 10px; margin-right: 10px;
text-align: left; text-align: left;
} }
#control-panel > .param > select { #param-corlim {
width: 75% !important;
}
#param-costlim {
width: 65% !important;
}
#param-correlation > .param > select {
flex: 0 0 45%; flex: 0 0 45%;
width: 100%; width: 100%;
text-align: left; text-align: left;
} }
#control-panel > .param > output { #param-correlation > .param > output {
flex: 1; flex: 1;
text-align: left; text-align: left;
padding:5px 0; padding:5px 0;
@ -115,11 +106,7 @@ cursor: default;
.right-side-hist { .right-side-hist {
margin-left:-2px; margin-left:-2px;
margin-top: 1px; margin-top: -0.5vh;
}
.right-side-PCP {
margin-top: -57px;
} }
#left-side-visual{ #left-side-visual{
@ -130,7 +117,7 @@ cursor: default;
/* Styling of the main canvas */ /* Styling of the main canvas */
#modtSNEcanvas { #modtSNEcanvas {
width: 50vw !important; width: 50vw !important;
height: 42.8vw !important; height: 66vh !important;
border: 1px solid black; border: 1px solid black;
position: absolute; position: absolute;
margin-left: -15px; margin-left: -15px;
@ -141,6 +128,10 @@ cursor: default;
fill: steelblue; fill: steelblue;
} }
.panel-body {
padding: 5px !important;
}
.bounding-rect { .bounding-rect {
stroke: red; stroke: red;
stroke-width: 1; stroke-width: 1;
@ -150,7 +141,7 @@ cursor: default;
#overviewRect { #overviewRect {
border: 1px solid black; border: 1px solid black;
width: 11vw; width: 11vw;
height: 11vw; height: 13vh;
position: absolute; position: absolute;
z-index: 1; z-index: 1;
} }
@ -158,46 +149,48 @@ cursor: default;
/* A little styling for knn's bar chart */ /* A little styling for knn's bar chart */
#knnBarChart { #knnBarChart {
width: 48.7vw !important; width: 48.7vw !important;
height: 2.8vw;
position: absolute !important; position: absolute !important;
z-index: 1; z-index: 1;
} }
#hider { #hider {
width: 48.7vw !important;
height: 3vw;
background-color: white; background-color: white;
position: absolute !important; position: absolute !important;
z-index: 2; z-index: 2;
} }
.med-bottom { .med-bottom-neigh {
margin-top: 6.7vw;
margin-left: -16px; margin-left: -16px;
margin-top: 67vh;
position: absolute;
width: 50.1vw !important; width: 50.1vw !important;
height: 5.4vw !important; height: 14.5vh !important;
} }
.med-bottomProv { .med-bottomProv {
margin-top: 6.7vw;
margin-left: -16px; margin-left: -16px;
width: 50.1vw !important; width: 50.1vw !important;
height: 6.4vw !important; height: 16vh !important;
}
#comment {
width: 8vw !important;
height: 2.5vh !important;
} }
/* Styling of the main SVG behind canvas */ /* Styling of the main SVG behind canvas */
#modtSNEcanvas_svg { #modtSNEcanvas_svg {
width: 50vw ; width: 50vw ;
height: 42.8vw ; margin-top: 17.5vh;
height: 66vh !important;
opacity: 1.0; opacity: 1.0;
margin-top: 178px;
position:absolute; position:absolute;
z-index: 2; z-index: 2;
} }
#modtSNEcanvas_svg_Schema { #modtSNEcanvas_svg_Schema {
width: 50vw; width: 50vw;
height: 42.8vw; height: 66vh !important;
opacity: 1.0; opacity: 1.0;
position:absolute; position:absolute;
margin-left: -15px; margin-left: -15px;
@ -210,50 +203,52 @@ circle.swatch{
/* Legend of the Overview t-SNE canvas */ /* Legend of the Overview t-SNE canvas */
#legend2 { #legend2 {
height: 9vw; height: 11vh;
width: 11vw; width: 10.5vw;
text-align: left; text-align: left;
overflow: auto; overflow: auto;
margin-left: -6px; margin-left: -6px;
margin-top: 2px;
} }
/* Legend of the Overview t-SNE canvas */ /* Legend of the Overview t-SNE canvas */
#legend1 { #legend1 {
height: 7vw; height: 19vh;
width: 5vw; margin-top: -0.5vh;
margin-top: -5px; width: 5.5vw;
text-align: left; text-align: left;
} }
/* Legend of the Overview t-SNE canvas */ /* Legend of the Overview t-SNE canvas */
#legend4 { #legend4 {
height: 7vw; height: 13.5vh;
width: 7vw; width: 7vw;
margin-left: -20px; margin-top: -1.5vh;
margin-top: -10px;
text-align: left; text-align: left;
} }
/* Styling of the ShepardHeatmap */ /* Styling of the ShepardHeatmap */
#sheparheat { #sheparheat {
width: 11vw; width: 10.65vw;
height: 11vw; height: 10.65vw;
position: absolute; position: absolute;
} }
/* Number of Points font-size */ /* Number of Points font-size */
text.legendtitle { text.legendtitle {
font-size: 15px; font-size: calc(0.35em + 0.8vmin) !important;
} }
/* Number of Points font-size */ /* Number of Points font-size */
text.label { text.label {
font-size: 15px; font-size: calc(0.35em + 0.8vmin) !important;
} }
/* Styling of the ShepardHeatmap */ /* Styling of the ShepardHeatmap */
svg#legend3 { svg#legend3 {
height: 8vw; height: 19.2vh;
width: 11vw; width: 10.65vw;
margin-top: 2px;
font-size: calc(0.35em + 1vmin) !important;
text-align: left; text-align: left;
overflow: auto; overflow: auto;
} }
@ -267,8 +262,6 @@ svg#legend3 {
} }
#hider2 { #hider2 {
height: 3vw;
width: 8.4vw;
margin-left: -5px; margin-left: -5px;
text-align: left; text-align: left;
background-color: white; background-color: white;
@ -357,8 +350,7 @@ svg#legend3 {
/* This is for the Correlation bar chart */ /* This is for the Correlation bar chart */
#correlation{ #correlation{
margin-left: -20px; margin-left: -0.5vw;
margin-top: -20px;
} }
.y.axis line { .y.axis line {
@ -413,14 +405,13 @@ svg#legend3 {
#selectionLabel{ #selectionLabel{
border: 1px solid black; border: 1px solid black;
padding: 5px 5px 5px 5px; padding: 1px 1px 1px 1px;
} }
#PCP{ #PCP{
margin-left:-15px;
margin-top:0px; margin-top:0px;
width: 23.2vw; width: 22.6vw;
height: 11.6vw; height: 17vh;
} }
.parent-row{ .parent-row{
@ -445,7 +436,6 @@ svg#legend3 {
text-decoration: none; text-decoration: none;
display: inline-block; display: inline-block;
font-size: 14px; font-size: 14px;
margin-left:10px;
} }
/* Load and Save Analysis Buttons Styling */ /* Load and Save Analysis Buttons Styling */
@ -501,7 +491,7 @@ ul {
#costHist { #costHist {
width: 6vw; width: 6vw;
height: 9.55vw; height: 16.5vh;
} }
#loader { #loader {

@ -4,6 +4,8 @@
<!-- Ignore Favicon -> Solved the warning in console of the browser. --> <!-- Ignore Favicon -> Solved the warning in console of the browser. -->
<link rel="icon" href="data:;base64,iVBORw0KGgo="> <link rel="icon" href="data:;base64,iVBORw0KGgo=">
<title>t-viSNE</title>
<!-- Three.js and Lodash libraries--> <!-- Three.js and Lodash libraries-->
<script src='./modules/three.js-r101/three.js'></script> <script src='./modules/three.js-r101/three.js'></script>
<script src='./modules/lodash/lodash.js'></script> <script src='./modules/lodash/lodash.js'></script>
@ -47,8 +49,8 @@
<div id="myModal" class="w3-modal"> <div id="myModal" class="w3-modal">
<div class="w3-modal-content w3-card-4 w3-animate-zoom"> <div class="w3-modal-content w3-card-4 w3-animate-zoom">
<header class="w3-container w3-blue"> <header class="w3-container w3-blue">
<h3 style="display:inline-block; font-size: 16px; margin-top: 15px; margin-left: 10px; margin-bottom:15px">t-SNE Grid Search Resulting Diverse Projections</h3> <h2 title="Tip: t-SNE grid search with 25 most diverse projections extracted from 500 generated embeddings (using Procrustes distance). " style="display:inline-block; font-size: 16px; margin-top: 15px; margin-left: 10px; margin-bottom:15px">t-SNE Grid Search</h3>
[Sorting Projections According to Metric: [Sorting:
<select id="param-SortMOver-view" name="param-SortMOver-view" style="color: black" onchange="ReSortOver()"> <select id="param-SortMOver-view" name="param-SortMOver-view" style="color: black" onchange="ReSortOver()">
<option value="1" selected>Quality Metrics Average (QMA)</option> <option value="1" selected>Quality Metrics Average (QMA)</option>
<option value="2">Neighborhood Hit (NH)</option> <option value="2">Neighborhood Hit (NH)</option>
@ -72,87 +74,83 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-lg-3">
<div class="panel panel-default" id="left-side-param"> <div class="panel panel-default" id="left-side-param">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title" style="display:inline-block" data-toggle="tooltip" data-placement="right" title="Tip: control t-SNE algorithm and its parameters.">t-SNE Parameters</h2> <h2 class="panel-title" style="display:inline-block" data-toggle="tooltip" data-placement="right" title="Tip: a panel for controlling the t-SNE algorithm and its parameters. There is also an option to choose between grid parameter search and single set mode.">Parameters</h2>
[Mode: [M:
<select id="param-EX-view" name="param-EX-view" data-toggle="tooltip" data-placement="right" title="Tip: change between grid search and a single set of parameters." onchange="ExecuteMode()"> <select id="param-EX-view" name="param-EX-view" data-toggle="tooltip" data-placement="right" title="Tip: the option of changing between grid search (generating 500 projections) and a single set of parameters (1 projection)." onchange="ExecuteMode()">
<option value="1" selected>Grid Search</option> <option value="1" selected>Grid Search</option>
<option value="2">Single Set</option> <option value="2">Single Set</option>
</select> </select>
] ]
<div id="cost" style="display:inline-block; margin-top:3px; float:right"></div> <div id="cost" title="Tip: the overall cost reduced by each iteration step of the t-SNE algorithm." style="display:inline-block; margin-top:3px; float:right"></div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div id="control-panel" data-sr="enter left over 8s"> <table class="table table-borderless paramTable">
<div class="param"> <tbody>
<label id="data" for="param-dataset" data-toggle="tooltip" data-placement="right" title="Tip: use one of the data sets already provided or upload a new file.">Data sets</label> <tr>
<select id="param-dataset" name="param-dataset" onChange="changeDataset(this.value);"> <td scope="row"><label id="data" for="param-dataset" data-toggle="tooltip" data-placement="right" title="Tip: use one of the data sets already provided (only numerical values supported) or upload a new file (do not forget to use * for the target label).">Data sets</label></td>
<option value="diabetes.csv" selected>Pima Indian Diabetes</option> <td>
<option value="breast-cancer-wisconsin.csv">Breast Cancer Wisconsin</option> <select id="param-dataset" name="param-dataset" onChange="changeDataset(this.value);">
<option value="iris.csv">Iris</option> <option value="diabetes.csv" selected>Diabetes</option>
<option value="SPECTF.csv">SPECTF</option> <option value="breast-cancer-wisconsin.csv">Breast Cancer</option>
<option value="blobs.csv">Gaussian Clusters</option> <option value="iris.csv">Iris</option>
<option value="empty">Upload New File</option> <option value="SPECTF.csv">SPECTF</option>
</select> <option value="blobs.csv">Gaussian Clusters</option>
<button type="button" class="button" id="FactRes" onclick="FactoryReset()" data-toggle="tooltip" data-placement="right" title="Tip: Restart the entire web page/application.">Factory reset</button> <option value="empty">Upload File</option>
</div> </select>
<div class="param"> </td>
<label for="param-perplexity" data-toggle="tooltip" data-placement="right" title="Tip: perplexity is a measure for information that is defined as 2 to the power of the Shannon entropy. The perplexity of a fair die with k sides is equal to k. In t-SNE, the perplexity may be viewed as a knob that sets the number of effective nearest neighbors. (Source: https://lvdmaaten.github.io/tsne/)">Perplexity</label> <td><button type="button" class="button" id="FactRes" onclick="FactoryReset()" data-toggle="tooltip" data-placement="right" title="Tip: Restart the entire web page/application.">Factory reset</button></td>
<input id="param-perplexity" type="range" min="5" max="100" value="30", step="1" > </tr>
<output for="param-perplexity" id="param-perplexity-value">30</output> <tr>
</div> <td scope="row"><label for="param-perplexity" data-toggle="tooltip" data-placement="right" title="Tip: perplexity is a measure for information that is defined as 2 to the power of the Shannon entropy. The perplexity of a fair die with k sides is equal to k. In t-SNE, the perplexity may be viewed as a knob that sets the number of effective nearest neighbors. (Source: https://lvdmaaten.github.io/tsne/).">Perplexity</label></td>
<div class="param"> <td><input id="param-perplexity" type="range" min="5" max="100" value="30", step="1" ></td>
<label for="param-learningrate" data-toggle="tooltip" data-placement="right" title="Tip: if the learning rate is too high, the data may look like a ‘ball’ with any point approximately equidistant from its nearest neighbours. If the learning rate is too low, most points may look compressed in a dense cloud with few outliers. If the cost function gets stuck in a bad local minimum increasing the learning rate may help. (Source: https://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html)">Learning rate</label> <td><output for="param-perplexity" id="param-perplexity-value">30</output></td>
<input id="param-learningrate" type="range" min="1" max="150" value="1", step="1"> </tr>
<output for="param-learningrate" id="param-learningrate-value">1</output> <tr>
</div> <td scope="row"><label for="param-learningrate" data-toggle="tooltip" data-placement="right" title="Tip: if the learning rate is too high, the data may look like a ‘ball’ with any point approximately equidistant from its nearest neighbours. If the learning rate is too low, most points may look compressed in a dense cloud with few outliers. If the cost function gets stuck in a bad local minimum increasing the learning rate may help. (Source: https://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html).">Learning rate</label></td>
<div class="param"> <td><input id="param-learningrate" type="range" min="1" max="150" value="1", step="1"></td>
<div class="row"> <td><output for="param-learningrate" id="param-learningrate-value">1</output></td>
<div class="col-md-3"> </tr>
<label for="param-maxiter" style="padding: 25px 0 0 8px" data-toggle="tooltip" data-placement="right" title="Tip: maximum number of iterations for the optimization. Should usually be around 250. (Source: https://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html)">Max iterations</label> <tr>
</div> <td scope="row"><label for="param-maxiter" data-toggle="tooltip" data-placement="right" title="Tip: maximum number of iterations for the optimization. Should usually be around 250. (Source: https://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html).">Max iterations</label></td>
<div class="col-md-4" style="padding: 25px 0 0 0px"> <td><input id="param-maxiter" type="range" min="10" max="1000" value="500", step="10"></td>
<input id="param-maxiter" type="range" min="10" max="1000" value="500", step="10" > <td><output for="param-maxiter" id="param-maxiter-value" >500</output></td>
</div> </tr>
<div class="col-md-1"> <tr style="margin-top: -4px !important;">
<output for="param-maxiter" id="param-maxiter-value" style="padding: 25px 0 0 0" >500</output> <td scope="row" colspan="3">
</div> <div id="hider2" title="Tip: wait for line chart to load (overall cost vs. iteration)."></div>
<div class="col-md-4">
<div id="hider2"></div>
<div id="PlotCost"></div> <div id="PlotCost"></div>
</div> </td>
</tr>
</div> <tr >
</div> <td scope="row" style="padding-top: 0.8vh !important">
<div class="param" style="margin-top: -10px"> <input id="file-input" type="file" name="name" style="display: none;"/>
<input id="file-input" type="file" name="name" style="display: none;" /> <button type="button" class="button" onclick='loadAnalysis();' data-toggle="tooltip" data-placement="right" title="Tip: load previously executed analysis in .txt format.">Load exec.</button>
<button type="button" class="button" onclick='loadAnalysis();' style="padding:15px 12px 15px 12px; margin-left:15px" data-toggle="tooltip" data-placement="right" title="Tip: load previously executed file in .txt format.">Load execution</button> </td>
<button type="button" class="button" onclick="SaveAnalysis()" style="padding:15px 12px 15px 12px; margin-left:20px" data-toggle="tooltip" data-placement="right" title="Tip: save/store previously executed file in .txt format.">Store execution</button> <td style="padding-top: 0.8vh !important"><label data-toggle="tooltip" data-placement="right" title="Tip: if you store distances the file size will be larger but on a loading of this execution it will be processed much quicker than without this option enabled.">
<div class="col-md-" style="margin-top: 14px; margin-left:15px"> <input id="downloadDists" checked type="checkbox" >
<label data-toggle="tooltip" data-placement="right" title="Tip: if you store distances the file size will be larger but on a loading of this execution it will be processed much quicker than without this option enabled."> Cache distances
<input id="downloadDists" checked type="checkbox" >
Distances cached on "Store execution"
</label> </label>
</div> </td>
</div> <td style="padding-top: 0.8vh !important">
<div class="row"> <button type="button" class="button" onclick="SaveAnalysis()" data-toggle="tooltip" data-placement="right" title="Tip: save/store previously executed analysis in .txt format.">Store exec.</button>
<div class="col-md-12" style="margin-top:10px"> </td>
<p><div id="run-button"><button id="ExecuteBut" class="btn btn-primary btn-block" onclick="getData();" value="Execute new t-SNE analysis" style="margin-top: 4px"><i class="fas fa-running fa-lg" style="margin-right: 10px"></i>Execute new t-SNE analysis</button></div></p> </tr>
</div> <tr>
<td scope="row" colspan="3"><button id="ExecuteBut" class="btn btn-primary btn-block" onclick="getData();" title="Tip: initialize a new t-SNE investigation or start a previous analysis, in case load execution is activated." value="Execute new t-SNE analysis"><i class="fas fa-running fa-lg"></i>Execute new t-SNE analysis</button></td>
</div> </tr>
</div> </tbody>
</table>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-lg-6">
<div class="panel panel-default med-bottomProv" style="margin-top:0.2px; margin-bottom:+14px"> <div class="panel panel-default med-bottomProv" style="margin-bottom:+1.4vh">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title" style="display:inline-block" data-toggle="tooltip" data-placement="right" title="Tip: a feature of this tool that supports clusters (and points) exploration. Checking the neighborhood preservation between the entire projection's average and a selection driven by the user.">Projections Provenance</h2> <h2 class="panel-title" style="display:inline-block" data-toggle="tooltip" data-placement="right" title="Tip: a feature of this tool that supports clusters (and points) exploration. Checking the neighborhood preservation between the entire projection's average and a selection driven by the user. You can also find the best projections based on a lasso selection of points (with optimize selection).">Projections Provenance</h2>
<div id="textToChange" style="display:inline-block">[Sorting Projections According to Metric:</div> <div id="textToChange" style="display:inline-block">[Sorting:</div>
<select id="param-SortM-view" name="param-SortM-view" onchange="ReSort(false)"> <select id="param-SortM-view" name="param-SortM-view" onchange="ReSort(false)">
<option value="1" selected>Quality Metrics Average (QMA)</option> <option value="1" selected>Quality Metrics Average (QMA)</option>
<option value="2">Neighborhood Hit (NH)</option> <option value="2">Neighborhood Hit (NH)</option>
@ -168,9 +166,27 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div id="ProjectionsVisual"></div> <div id="ProjectionsVisual"></div>
<div id="ProjectionsMetrics"></div>
</div> </div>
</div> </div>
<div class="panel panel-default med-bottom-neigh">
<div class="panel-heading">
<h2 class="panel-title" style="display:inline-block" data-toggle="tooltip" data-placement="right" title="Tip: a feature of this tool that supports clusters (and points) exploration. Checking the neighborhood preservation between the entire projection's average and a selection driven by the user.">Neighborhood Preservation </h2>
[Visualization:
<select id="param-NB-view" name="param-NB-view" onchange="LineBar()">
<option value="1" selected>Bar Chart</option>
<option value="2">Difference Bar Chart</option>
<option value="3">Line Plot</option>
<option value="4">Difference Line Plot</option>
</select>
]
<div id="knnBarChartDetails"style="display:inline-block; float:right">
</div>
</div>
<div class="panel-body">
<div id="knnBarChart"></div>
<div id="hider"></div>
</div>
</div>
<svg id="SvgAnnotator"></svg> <svg id="SvgAnnotator"></svg>
<svg id="modtSNEcanvas_svg"></svg> <svg id="modtSNEcanvas_svg"></svg>
<svg id="modtSNEcanvas_svg_Schema"></svg> <svg id="modtSNEcanvas_svg_Schema"></svg>
@ -178,34 +194,92 @@
<canvas id = "modtSNEcanvas" ></canvas> <canvas id = "modtSNEcanvas" ></canvas>
</div> </div>
</div> </div>
<div class="col-md-2" style="width: 24.999999995%"> <div class="col-lg-3">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title" data-toggle="tooltip" data-placement="right" title="Tip: various functionalities depending on the user. These modes enable different interactions in the main visualization view.">Interaction Modes</h2> <h2 class="panel-title" data-toggle="tooltip" data-placement="right" title="Tip: in this panel the user can adapt the visual encodings of the main visualization view. Furthermore, the dimension correlation capturing points thresholds are situated in this panel. For the main view, there is also an annotation functionality available.">Visual Mapping</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body" id="commBtn">
<div id="resetAllFilters" style="margin-bottom: 20px"> <table class="table table-borderless">
<button class="btn btn-info active" onclick="setLayerProj();" style="margin-left: -1px !important" ><i class="fas fa-mouse-pointer fa-lg" data-toggle="tooltip" data-placement="right" title="Tip: in this mode the user can zoom in and out in the main visualization view and when hovering on a particular point he/she receives the exact data set's instance dimensions."></i>t-SNE Points Exploration</button> <tbody>
<button class="btn btn-info" onclick="setLayerComp();" style="margin-left: -1.4px"><i class="far fa-object-group fa-lg" data-toggle="tooltip" data-placement="right" title="Tip: lasso selection in the main visualization view." ></i>Group Selection</button> <tr>
<button class="btn btn-info" onclick="setLayerSche();" style="margin-left: -2px !important"><i class="fas fa-draw-polygon fa-lg" data-toggle="tooltip" data-placement="right" title="Tip: draw a shape (polylines) and check the related dimensions correlations for your drawing/shape. With the left click you set one point and the right click you confirm the drawing for further analysis."></i>Dimension Correlation</button> <td scope="row"><label for="male" data-toggle="tooltip" data-placement="right" title="Tip: density in the high-dimensional space taken from the t-SNE itself.">Density</label>
</div> <select id="param-neighborHood" name ="param-neighborHood" onchange="setReInitialize(true);">
<button class="btn btn-info" onclick="setReset();" style="margin-left: 225px"><i class="fas fa-trash-alt fa-lg" style="margin-right: 10px" data-toggle="tooltip" data-placement="right" title="Tip: reset all filters applied in the visualizations without losing the execution."></i>Reset Filters</button> <option selected="selected" value="color">Color</option>
<option value="size">Size</option>
</select>
</td>
<td rowspan="3"><svg id="legend4"></svg></td>
<td></td>
<td rowspan="5"><svg id="legend1"></svg></td>
</tr>
<tr>
<td scope="row">
<output for="param-neighborHood" id="param-neighborHood-value " ></output>
<label for="male" data-toggle="tooltip" data-placement="right" title="Tip: remaining cost of each point throughout the entire projection.">Remaining cost</label>
<label id="selectionLabel" data-toggle="tooltip" data-placement="right" title="Tip: change between size/radius and color encodings.">Size</label>
</td>
</tr>
<tr>
<td scope="row"><label for="male" data-toggle="tooltip" data-placement="right" title="Tip: adapt the selection of points in the two-dimensional space. The options are a simple distance measurement between point and line or using the KNN algorithm.">Correl.</label>
<select id="param-correlationMeasur" name ="param-correlationMeasur" onchange="setReInitializeDistanceCorrelation(true);">
<option selected="selected" value="1">Distance</option>
<option value="2">KNN</option>
</select>
</td>
</tr>
<tr>
<td scope="row">
<label for="param-corr" id="param-corrLabel" data-toggle="tooltip" data-placement="right" title="Tip: percentage of all points taken into account by Dimension Correlation.">Correl. threshold (%)</label>
<label for="param-corr2" id="param-corrLabel2" data-toggle="tooltip" data-placement="right" style="display: none;">K-value nearest neighbor</label>
</td>
<td>
<input id="param-corr" type="range" min="0" max="100" value="50", step="1" onchange="CalculateCorrel(true, 1);">
<input id="param-corr2" type="range" min="1" max="250" value="10", step="1" onchange="CalculateCorrel(true, 2);" style="display: none">
</td>
<td>
<output for="param-corr" id="param-corr-value">50</output>
<output for="param-corr2" id="param-corr-value2" style="display: none">10</output>
</td>
</tr>
<tr>
<td scope="row"><label for="param-lim" data-toggle="tooltip" data-placement="right" title="Tip: x*times the actual radius (increases/decreases points' radius).">Point radius scaling</label></td>
<td><input id="param-lim" type="range" min="1" max="4" value="3", step="0.5" onchange="setReInitialize(false);"></td>
<td><output for="param-lim" id="param-lim-value">3</output></td>
</tr>
<tr>
<td scope="row">
<input id="controls" type="checkbox">
Disable annotator</input>
</td>
<td style="text-align:center;"><button class="btn btn-default" style="padding: 2px 10px 2px 10px !important;" onclick="deleteAnnotations();" ><i class="fas fa-comment-slash fa-lg"></i>Erase</button></td>
<td colspan="2"><button class="btn btn-default" style="padding: 2px 10px 2px 10px !important;" onclick="BringBackAnnotations();" ><i class="fas fa-eye fa-lg"></i>Reveal</button></td>
</tr>
<tr>
<td scope="row">
<textarea type="text" id="comment" name="textforAnnotator" placeholder="Write a comment."></textarea>
</td>
<td style="text-align:center;"><div id="toggleAnnotator"><button class="btn btn-default" style="padding: 2px 10px 2px 10px !important;" onclick="setAnnotator();" ><i class="fas fa-comment fa-lg"></i>Attach</button></div></td>
<td colspan="2"><div id="continue"><button class="btn btn-default active" style="padding: 2px 10px 2px 10px !important;" onclick="setContinue();" ><i class="fas fa-chart-line fa-lg"></i>Analysis</button></div></td>
</tr>
</tbody>
</table>
</div>
</div> </div>
</div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-3" style="margin-top:-4px"> <div class="col-lg-3" style="margin-top:-10px">
<div class="panel panel-default" style="padding-bottom: 35px;"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title" style="display:inline-block" data-toggle="tooltip" data-placement="right" title="Tip: t-SNE overview with or without labels depending on each data set. To determine the feature of a data set that corresponds to classes set a * mark after this feature.">t-SNE Overview</h2><div id="datasetDetails"style="display:inline-block; float:right"></div> <h2 class="panel-title" style="display:inline-block" data-toggle="tooltip" data-placement="right" title="Tip: t-SNE overview with or without labels depending on each data set. To determine the target label set a * mark after the appropriate dimension.">Overview</h2><div id="datasetDetails" title="Tip: the number of dimensions/features and instances of a data set." style="display:inline-block; float:right"></div>
</div> </div>
<div class="row"> <div class="row">
<div class="panel-body"> <div class="panel-body">
<div class="col-md-6"> <div class="col-lg-6">
<div id="overviewRect"></div> <div id="overviewRect"></div>
</div> </div>
<div class="col-md-6"> <div class="col-lg-6">
<div style="display:block" id="CategoryName"></div> <div style="display:block" id="CategoryName"></div>
<div class="legend" id = "legend2"></div> <div class="legend" id = "legend2"></div>
</div> </div>
@ -213,114 +287,48 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-3 col-md-offset-6"> <div class="col-lg-3 col-lg-offset-6" style="margin-top:-10px">
<div class="panel panel-default" style="margin-top: -200px"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title" data-toggle="tooltip" data-placement="right" title="Tip: in this panel the user can adapt the visual mappings of the main visualization view.">Visual Mapping</h2> <h2 class="panel-title" data-toggle="tooltip" data-placement="right" title="Tip: various functionalities depending on the user. These modes enable different interactions in the main visualization view.">Interaction Modes (M)</h2>
</div> </div>
<div class="row"> <div class="panel-body" id="resetAllFilters">
<div class="panel-body"> <table class="table table-borderless centerTable">
<div class="col-md-12"> <tbody>
<div class="row"> <tr>
<div class="col-md-8"> <td scope="row"><button class="btn btn-info active" onclick="setLayerProj();" style="margin-left: -1px !important" ><i class="fas fa-mouse-pointer fa-lg" data-toggle="tooltip" data-placement="right" title="Tip: in this mode the user can zoom in and out in the main visualization view and when hovering on a particular point he/she receives the exact data set's instance dimensions."></i>Points exploration</button></td>
<div class="param" style="padding: 5px 0 5px 0"> <td><button class="btn btn-info" onclick="setLayerComp();" style="margin-left: -1.4px"><i class="far fa-object-group fa-lg" data-toggle="tooltip" data-placement="right" title="Tip: lasso selection in the main visualization view." ></i>Group selection</button></td>
<label for="male" data-toggle="tooltip" data-placement="right" title="Tip: density in the high-dimensional space taken from the t-SNE itself.">Density</label> </tr>
<select id="param-neighborHood" name ="param-neighborHood" onchange="setReInitialize(true);" style="display:inline-block;margin-left: 60px"> <tr>
<option selected="selected" value="color">Color-encoding</option> <td scope="row"><button class="btn btn-info" onclick="setLayerSche();" style="margin-left: -2px !important"><i class="fas fa-draw-polygon fa-lg" data-toggle="tooltip" data-placement="right" title="Tip: draw a shape (polylines) and check the related dimensions correlations for your drawing/shape. With the left click you set one point and the right click you confirm the drawing for further analysis."></i>Dimension correl.</button></td>
<option value="size">Size-encoding</option> <td><button class="btn btn-info" onclick="setReset();"><i class="fas fa-trash-alt fa-lg" data-toggle="tooltip" data-placement="right" title="Tip: reset all filters applied in the visualizations without losing the execution."></i>Reset all filters</button></td>
</select> </tr>
</div> </tbody>
<div class="param" style="padding: 0px 0 0px 0" > </table>
<output for="param-neighborHood" id="param-neighborHood-value " ></output> </div>
<label for="male" data-toggle="tooltip" data-placement="right" title="Tip: remaining cost of each point throughout the entire projection.">Remaining cost</label> </div>
<label id="selectionLabel" style="margin-top:4px; margin-left: 15px" data-toggle="tooltip" data-placement="right" title="Tip: change between size/radius and color encodings.">Size-encoding</label>
</div>
<div class="param" style="padding: 20px 0 5px 0; margin-top: 5px;" >
<label for="male" data-toggle="tooltip" data-placement="right" title="Tip: adapt the selection of points in the two-dimensional space: from a simple distance measurement between point and line to KNN algorithm, and vice versa.">Correlation measurement</label>
<select id="param-correlationMeasur" name ="param-correlationMeasur" onchange="setReInitializeDistanceCorrelation(true);" style="display:inline-block;margin-left: 32px">
<option selected="selected" value="1">Distance</option>
<option value="2">KNN</option>
</select>
</div>
<div class="param">
<div class="row" style="margin-top: 10px;">
<div class="col-md-6">
<label for="param-corr" id="param-corrLabel" data-toggle="tooltip" data-placement="right" title="Tip: percentage of all points taken into account by Dimension Correlation.">Correlation threshold (%)</label>
<label for="param-corr2" id="param-corrLabel2" data-toggle="tooltip" data-placement="right" style="display: none;">K-value (KNN)</label>
</div>
<div class="col-md-5">
<input id="param-corr" type="range" min="0" max="100" value="50", step="1" onchange="CalculateCorrel(true, 1);" style="margin-left: -20px;">
<input id="param-corr2" type="range" min="1" max="250" value="10", step="1" onchange="CalculateCorrel(true, 2);" style="margin-left: -20px; display: none">
</div>
<div class="col-md-1">
<output for="param-corr" id="param-corr-value" style="margin-left: -20px;">50</output>
<output for="param-corr2" id="param-corr-value2" style="margin-left: -20px; display: none">10</output>
</div>
</div>
</div>
<div class="param">
<div class="row" style="margin-top: 30px">
<div class="col-md-6">
<label for="param-lim" data-toggle="tooltip" data-placement="right" title="Tip: x*times the actual radius (increase/decrease points radius).">Points radius scaling</label>
</div>
<div class="col-md-5">
<input id="param-lim" type="range" min="1" max="4" value="3", step="0.5" onchange="setReInitialize(false);" style="margin-left: -20px;">
</div>
<div class="col-md-1">
<output for="param-lim" id="param-lim-value" style="margin-left: -20px;">3</output>
</div>
</div>
</div>
</div>
<div class="col-md-1">
<svg id="legend1" style = "margin-left: -30px"></svg>
</div>
<div class="col-md-2">
<svg id="legend4" style = "margin-left: -10px"></svg>
</div>
</div>
<div class="annotationAllClass" style="margin-top: 20px">
<label style="padding-bottom: 0px">
<input id="controls" type="checkbox" style="margin-top: 18px">
Hide annotations' controllers</input>
<button class="btn btn-default" onclick="BringBackAnnotations();" style="display:inline-block; float:right; margin-left:178px"><i class="fas fa-eye fa-lg" style="margin-right: 10px"></i>Reveal annotations</button>
</label>
<div id="param-correlation">
Annotation: <textarea type="text" id="comment" name="textforAnnotator" placeholder="Please, provide your comment."></textarea>
</div>
<div id="commBtn">
<div class="param" style="margin-top:10px">
<div id="toggleAnnotator" style= "margin-left: -120px"><button class="btn btn-default" onclick="setAnnotator();" style="display:inline-block; float:left; margin-left: 120px" ><i class="fas fa-comment fa-lg" style="margin-right: 10px"></i>Add annotation</button></div>
<div id="continue"></div><button class="btn btn-default active" onclick="setContinue();" style="display:inline-block; float:middle; margin-left: 6px"><i class="fas fa-chart-line fa-lg" style="margin-right: 10px"></i>Continue the analysis</button></div>
<button class="btn btn-default" onclick="deleteAnnotations();" style="display:inline-block; float:right; margin-top: -45px" ><i class="fas fa-comment-slash fa-lg" style="margin-right: 10px"></i>Delete annotations</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-3" style="margin-top:-4px"> <div class="col-lg-3" style="margin-top:-10px">
<div class="panel panel-default" style="padding-bottom : 70px"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title" data-toggle="tooltip" data-placement="right" style="display:inline-block" title="Tip: a view related to the overall quality of the projection.">Shepard Heatmap</h2> <h2 class="panel-title" data-toggle="tooltip" data-placement="right" style="display:inline-block" title="Tip: a view related to the overall quality of the projection. If the points/values belong to the diagonal, then the distances are preserved in both spaces. If values are closer to N-D distances, then the visualization is too compressed. If values are closer to 2-D distances, then the visualization is too spread out.">Shepard Heatmap</h2>
<div style="display:inline-block; float:right"> <div style="display:inline-block; float:right">
[Visualization: [Visualization:
<select id="param-SH-view" name="param-SH-view" onchange="ShepardHeatMap()"> <select id="param-SH-view" name="param-SH-view" onchange="ShepardHeatMap()">
<option value="1" selected>Shepard Heatmap</option> <option value="1" selected>Heatmap</option>
<option value="2">Shepard Diagram</option> <option value="2">Diagram</option>
</select> </select>
] ]
</div> </div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-lg-6">
<svg id="sheparheat"></svg> <svg id="sheparheat"></svg>
</div> </div>
<div class="col-md-2"> <div class="col-lg-2">
<svg id="legend3"></svg> <svg id="legend3"></svg>
</div> </div>
</div> </div>
@ -328,12 +336,17 @@
</div> </div>
</div> </div>
<div class="col-md-3 col-md-offset-6" style="margin-top: -2px"> <div class="col-lg-3 col-lg-offset-6" style="margin-top:-10px">
<div class="panel panel-default right-side-cor"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title" style="display:inline-block" data-toggle="tooltip" data-placement="right" title="Tip: user-driven shape investigation of the most correlated dimensions.">Dimension Correlation</h2><div class="param" style="display:inline-block; margin-top:-5px; float:right"><label for="param-corlim" style="display:inline-block; float: right" data-toggle="tooltip" data-placement="right" title="Tip: the minimum acceptable visible correlation. Default is 0, so the tool accepts all the correlations.">Min. Visible Correlation: #<output for="param-corlim" id="param-corlim-value" style="display:inline-block; float:right">0.0</output></label> <h2 class="panel-title" style="display:inline-block" data-toggle="tooltip" data-placement="right" title="Tip: user-driven shape investigation of the most correlated dimensions.">Dimension Correlation</h2>
<div class="col-lg-8"></div>
<div class="col-lg-4">
<div class="param" style="display:inline-block; float:right; margin-top:-23px; margin-right: -18px">
<label for="param-corlim" style="display:inline-block; float: right" data-toggle="tooltip" data-placement="right" title="Tip: the minimum acceptable visible correlation. Default is 0, so the tool accepts all the correlations.">Min Correl.: #<output for="param-corlim" id="param-corlim-value" title="Tip: minimum visible correlation (range: 0.0 to 1.0)." style="display:inline-block; float:right">0.0</output></label>
<input id="param-corlim" type="range" min="0" max="1" value="0.0", step="0.1" style="display:inline-block; float:right" onchange="CalculateCorrel(true);"> <input id="param-corlim" type="range" min="0" max="1" value="0.0", step="0.1" style="display:inline-block; float:right" onchange="CalculateCorrel(true);">
</div> </div>
</div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<svg id="correlation"></svg> <svg id="correlation"></svg>
@ -342,16 +355,16 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-lg-3">
<div class="col-md-3" id="extra-information" style="width: 24.8vw"> <div class="col-lg-3" id="extra-information" style="width: 24.8vw">
<div class="panel panel-default right-side-hist"> <div class="panel panel-default right-side-hist">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title" style="display:inline-block;" data-toggle="tooltip" data-placement="right" title="Tip: it might be useful to take a look at this histogram, to observe the density and remaining cost distributions, when remaining cost values are low and have an idea about the distributions.">Density and Remaining Cost Distributions</h2> <h2 class="panel-title" style="display:inline-block;" data-toggle="tooltip" data-placement="right" title="Tip: the density and remaining cost distributions are important to look at along with the main visualization view individual values.">Density and Remaining Cost</h2>
<div class="col-md-7"></div> <div class="col-lg-7"></div>
<div class="col-md-5"> <div class="col-lg-5">
<div class="param" style="display:inline-block; float:right; margin-top:-21.5px; margin-right: -18px"> <div class="param" style="display:inline-block; float:right; margin-top:-23px; margin-right: -18px">
<label for="param-costlim" style="display:inline-block; float: right" data-toggle="tooltip" data-placement="right" title="Tip: set the rate of the limiter for the minimum acceptable visible cost at the main visualization view.">Min. Visible Cost Rate: #<output for="param-costlim" id="param-costlim-value" style="display:inline-block; float:right">1</output></label> <label for="param-costlim" style="display:inline-block; float: right" data-toggle="tooltip" data-placement="right" title="Tip: set the rate of the limiter for the minimum acceptable visible cost at the main visualization view.">Min Cost: #<output for="param-costlim" id="param-costlim-value" title="Tip: minimum visible cost rate (range: 0.1 to 1.0)." style="display:inline-block; float:right">1.0</output></label>
<input id="param-costlim" type="range" min="0.1" max="1" value="1", step="0.1" style="display:inline-block; float:right" onchange="setReInitialize(false);"> <input id="param-costlim" type="range" min="0.1" max="1" value="1", step="0.1" style="display:inline-block; float:right" onchange="setReInitialize(false);">
</div> </div>
</div> </div>
@ -361,34 +374,11 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class = col-md-6>
<div class="panel panel-default med-bottom" style="margin-top:+172px">
<div class="panel-heading">
<h2 class="panel-title" style="display:inline-block" data-toggle="tooltip" data-placement="right" title="Tip: a feature of this tool that supports clusters (and points) exploration. Checking the neighborhood preservation between the entire projection's average and a selection driven by the user.">Neighborhood Preservation </h2>
[Visualization:
<select id="param-NB-view" name="param-NB-view" onchange="LineBar()">
<option value="1" selected>Bar Chart</option>
<option value="2">Difference Bar Chart</option>
<option value="3">Line Plot</option>
<option value="4">Difference Line Plot</option>
</select>
]
<div id="knnBarChartDetails"style="display:inline-block; float:right">
</div>
</div>
<div class="panel-body">
<div id="hider"></div>
<div id="knnBarChart"></div>
</div>
</div>
</div> </div>
<div class="col-lg-3 col-lg-offset-6" style="margin-top:-1.5vh">
<div class="col-md-3"> <div class="panel panel-default">
<div class="panel panel-default right-side-PCP">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title" data-toggle="tooltip" data-placement="right" title="Tip: for every selection the tool runs a local Principal Component Analysis (PCA) algorithm and dynamically adapts and shows the top 8 dimensions in an order from left to right. This sorting from left to right presents the most related (with high variance) features of the data set to the least important (low variance).">Adaptive Parallel Coordinates Plot</h2> <h2 class="panel-title" data-toggle="tooltip" data-placement="right" title="Tip: for every selection the tool runs a local Principal Component Analysis (PCA) algorithm and dynamically adapts and shows the top 8 dimensions in an order from left to right. This sorting from left to right presents the most related (with high variance) features of the data set to the least important (low variance). It also works with local selections of points!">Adaptive Parallel Coordinates Plot</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div id="PCP" class="parcoords"></div> <div id="PCP" class="parcoords"></div>
@ -396,9 +386,33 @@
</div> </div>
</div> </div>
</div> </div>
<div class="footer" style="margin-top: -25px">
<hr>
<p class="text-muted credit no-top-margin no-bottom-margin">
&copy; ISOVIS group 2019&ndash;2020
</p>
<p class="text-muted credit no-top-margin no-bottom-margin">
Last updated: June 15, 2020
</p>
</div>
</div> </div>
<!-- Load the core visualization script. -->
<script src="./js/tsne_vis.js"></script>
<script> <script>
function render() {
myResponsiveComponent({
width: document.body.clientWidth,
height: document.body.clientHeight,
});
}
render();
window.addEventListener('resize', render);
// Tooltip // Tooltip
$(document).ready(function(){ $(document).ready(function(){
$("[rel='tooltip']").tooltip(); $("[rel='tooltip']").tooltip();
@ -420,10 +434,10 @@
$('#myModal').modal('hide'); $('#myModal').modal('hide');
} }
$("#cost").html('(Unknown Overall Cost)'); $("#cost").html('(Ov. Cost: ?)');
$("#datasetDetails").html('(Unknown Number of Dimensions and Instances)'); $("#datasetDetails").html('(Num. of Dim. and Ins.: ?)');
$("#CategoryName").html('No Classification'); $("#CategoryName").html('No labels');
$("#knnBarChartDetails").html('(Number of Selected Points: 0/0)'); $("#knnBarChartDetails").html('(Num. of Selected Points: 0/0)');
/* This script is used in order to give functionalities to the different buttons provide through the front-end. */ /* This script is used in order to give functionalities to the different buttons provide through the front-end. */
$('#param-lim').bind('input', function () { $('#param-lim-value').text($('#param-lim').val()); }); $('#param-lim').bind('input', function () { $('#param-lim-value').text($('#param-lim').val()); });
$('#param-corr').bind('input', function () { $('#param-corr-value').text($('#param-corr').val()); }); $('#param-corr').bind('input', function () { $('#param-corr-value').text($('#param-corr').val()); });
@ -453,18 +467,15 @@
// Get all buttons with class="btn" inside the container // Get all buttons with class="btn" inside the container
var btns2 = btnContainer2.getElementsByClassName("btn"); var btns2 = btnContainer2.getElementsByClassName("btn");
for (var i = 0; i < btns2.length; i++) { for (var i = 0; i < btns2.length; i++) {
btns2[i].addEventListener("click", function() { btns2[i].addEventListener("click", function() {
let current = document.getElementsByClassName("active"); let current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace("btn btn-info active", "btn btn-info"); current[1].className = current[1].className.replace("btn btn-info active", "btn btn-info");
this.className += " active"; this.className += " active";
}); });
} }
</script>
<script>
/* On resize refresh the shepardHeatmap */ /* On resize refresh the shepardHeatmap */
window.onresize = function(event) { window.onresize = function(event) {
if ( document.getElementById('cost').hasChildNodes() ) { if ( document.getElementById('cost').hasChildNodes() ) {
@ -505,9 +516,6 @@
} }
</script> </script>
<!-- Load the core visualization script. -->
<script src="./js/tsne_vis.js"></script>
</body> </body>
</html> </html>

@ -9,10 +9,11 @@ function changeDataset(value) {
d3.select("#data") d3.select("#data")
.append("input") .append("input")
.attr("type", "file") .attr("type", "file")
.style("font-size", "10px") .style("font-size", 'calc(0.35em + 0.9vmin)')
.on("change", function() { .on("change", function() {
var file = d3.event.target.files[0]; var file = d3.event.target.files[0];
getfile(file); getfile(file);
$("#data").html(file.name);
}) })
} else { } else {
$("#data").html('Data sets'); // Print on the screen the classification label. $("#data").html('Data sets'); // Print on the screen the classification label.

@ -1,8 +1,46 @@
// t-SNE Visualization and global variables // t-SNE Visualization and global variables
//BACKEND_API_URL = "https://sheldon.lnu.se/t-viSNE/tsneGrid"
BACKEND_API_URL = "http://127.0.0.1:5000"
// This variable is used when a new file is upload by a user. // This variable is used when a new file is upload by a user.
var new_file; var new_file;
// Scale - Responsiveness
var overallWidth = 0, overallHeight = 0;
// Initialize the horizontal (correlations) barchart's variables
var svg, defs, gBrush, brush, main_xScale, mini_xScale, main_yScale, mini_yScale, main_xAxis, main_yAxis, mini_width, textScale, main_margin, mini_margin;
// Added only for the mouse wheel
var zoomer = d3v3.behavior.zoom()
.on("zoom", null);
function myResponsiveComponent(props) {
overallWidth = props.width;
overallHeight = props.height;
// Margin of the main barchart
main_margin = {top: 8, right: 10, bottom: 30, left: 100},
main_width = overallWidth/5.2 - main_margin.left - main_margin.right,
main_height = overallHeight/5.2 - main_margin.top - main_margin.bottom;
// Margin of the mini barchart
mini_margin = {top: 8, right: 10, bottom: 30, left: 10},
mini_height = overallHeight/5.2 - mini_margin.top - mini_margin.bottom;
mini_width = overallWidth/23 - mini_margin.left - mini_margin.right;
// Create the svg correlation component
svg = d3v3.select("#correlation").attr("class", "svgWrapper")
.attr("width", main_width + main_margin.left + main_margin.right + mini_width + mini_margin.left + mini_margin.right)
.attr("height", main_height + main_margin.top + main_margin.bottom)
.call(zoomer)
.on("wheel.zoom", scroll)
.on("mousedown.zoom", null)
.on("touchstart.zoom", null)
.on("touchmove.zoom", null)
.on("touchend.zoom", null);
}
// The basic variables in order to execute t-SNE (opt is perplexity and learning rate). // 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 tsne; var opt; var step_counter; var max_counter; var runner;
@ -16,6 +54,7 @@ var dists; var dists2d; var all_labels; var dist_list = []; var dist_list2d = []
// These are the dimensions for the Overview view and the Main view // These are the dimensions for the Overview view and the Main view
var dim = document.getElementById('overviewRect').offsetWidth-2; var dimensions = document.getElementById('modtSNEcanvas').offsetWidth; var dimensionsY = document.getElementById('modtSNEcanvas').offsetHeight; var lassoFlag = false; var dim = document.getElementById('overviewRect').offsetWidth-2; var dimensions = document.getElementById('modtSNEcanvas').offsetWidth; var dimensionsY = document.getElementById('modtSNEcanvas').offsetHeight; var lassoFlag = false;
var dimh = document.getElementById('overviewRect').offsetHeight-2;
// 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. // 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). // ColorsCategorical = the categorical colors (maximum value = 10).
@ -53,7 +92,13 @@ var ParametersSet = []; var overallCost; var input;
var ringNotes = []; var gAnnotationsAll = []; var AnnotationsAll = []; var draggable = []; var ringNotes = []; var gAnnotationsAll = []; var AnnotationsAll = []; var draggable = [];
// These variables are set here in order to instatiate the very first Three.js scene. // These variables are set here in order to instatiate the very first Three.js scene.
var MainCanvas; var Child; var renderer; var fov = 18; var near = 10; var far = 7000; var camera; var scene; var MainCanvas; var Child; var renderer; var near = 10; var far = 7000; var camera; var scene;
if (getViewport()[0] >= 2560) {
var fov = 14.3;
} else {
var fov = 10.2;
}
// Initialize the Schema Investigation variables. // Initialize the Schema Investigation variables.
var Arrayx = []; var Arrayy = []; var XYDistId = []; var Arrayxy = []; var DistanceDrawing1D = []; var allTransformPoints = []; var p; var pFinal = []; var paths; var path; var ArrayLimit = []; var Arrayx = []; var Arrayy = []; var XYDistId = []; var Arrayxy = []; var DistanceDrawing1D = []; var allTransformPoints = []; var p; var pFinal = []; var paths; var path; var ArrayLimit = [];
@ -108,8 +153,8 @@ function OptimizePoints() {
} }
// ajax the JSON to the server // ajax the JSON to the server
$.post("http://127.0.0.1:5000/receiverOptimizer", JSON.stringify(FocusedIDs), function(){ $.post(BACKEND_API_URL+"/receiverOptimizer", JSON.stringify(FocusedIDs), function(){
$.get("http://127.0.0.1:5000/senderOptimizer", function( data ) { $.get(BACKEND_API_URL+"/senderOptimizer", function( data ) {
dataReceivedFromServerOptimized = data dataReceivedFromServerOptimized = data
ReSort(false) ReSort(false)
}); });
@ -128,7 +173,7 @@ function ReSort(flagInitialize) {
var width= dimensions*0.97; var width= dimensions*0.97;
var viewport = getViewport(); // Get the width and height of the main visualization var viewport = getViewport(); // Get the width and height of the main visualization
var vh = viewport[1] * 0.035; var vh = viewport[1] * 0.035;
var height= vh * 1.9; var height= vh * 2.8;
var graphDiv = 'ProjectionsVisual' var graphDiv = 'ProjectionsVisual'
@ -152,9 +197,9 @@ function ReSort(flagInitialize) {
metricsSorting = dataReceivedFromServerOptimized['metrics'] metricsSorting = dataReceivedFromServerOptimized['metrics']
metrics = dataReceivedFromServerOptimized['metricsEntire'] metrics = dataReceivedFromServerOptimized['metricsEntire']
if (FocusedIDs.length == points.length) { if (FocusedIDs.length == points.length) {
document.getElementById("textToChange").innerHTML = "[Sorting Projections According to Metric:"; document.getElementById("textToChange").innerHTML = "[Sorting:";
} else { } else {
document.getElementById("textToChange").innerHTML = "[Sorting Projections According to Metric for Current Selection:"; document.getElementById("textToChange").innerHTML = "[Sorting for Selection:";
} }
} else { } else {
if (!globalFlagCheck) { if (!globalFlagCheck) {
@ -278,8 +323,8 @@ if(k >= 6) {
zmax:1, zmax:1,
colorscale: colorscaleValue, colorscale: colorscaleValue,
colorbar: { colorbar: {
title: 'Met. Per.', title: 'Perform.',
tickvals:[0,0.2,0.4,0.6,0.8,1], tickvals:[0,0.5,1],
titleside:'right', titleside:'right',
}, },
xaxis: 'x'+parseInt(k+1), xaxis: 'x'+parseInt(k+1),
@ -589,7 +634,7 @@ if(k >= 6) {
margin: { margin: {
l: 10, l: 10,
r: 10, r: 10,
b: 15, b: 37,
t: 2, t: 2,
pad: 0 pad: 0
}, },
@ -824,15 +869,15 @@ function parseData(url) {
if (insideCall) { if (insideCall) {
init(results.data, results_all, results.meta.fields); // Call the init() function that starts everything! init(results.data, results_all, results.meta.fields); // Call the init() function that starts everything!
} else { } else {
$.post("http://127.0.0.1:5000/resetAll", JSON.stringify(''), function(){ $.post(BACKEND_API_URL+"/resetAll", JSON.stringify(''), function(){
}); });
var parametersLocal = [] var parametersLocal = []
parametersLocal.push(document.getElementById("param-perplexity-value").value) parametersLocal.push(document.getElementById("param-perplexity-value").value)
parametersLocal.push(document.getElementById("param-learningrate-value").value) parametersLocal.push(document.getElementById("param-learningrate-value").value)
parametersLocal.push(document.getElementById("param-maxiter-value").value) parametersLocal.push(document.getElementById("param-maxiter-value").value)
parametersLocal.push(results_all) parametersLocal.push(results_all)
$.post("http://127.0.0.1:5000/receiverSingle", JSON.stringify(parametersLocal), function(){ $.post(BACKEND_API_URL+"/receiverSingle", JSON.stringify(parametersLocal), function(){
$.get("http://127.0.0.1:5000/senderSingle", function( data ) { $.get(BACKEND_API_URL+"/senderSingle", function( data ) {
dataReceivedFromServer = data dataReceivedFromServer = data
projections = dataReceivedFromServer['projections'] projections = dataReceivedFromServer['projections']
betas = dataReceivedFromServer['betas'] betas = dataReceivedFromServer['betas']
@ -849,7 +894,7 @@ function parseData(url) {
if (flagAnalysis) { if (flagAnalysis) {
$('#myModal').modal('hide'); $('#myModal').modal('hide');
$.post("http://127.0.0.1:5000/resetAll", JSON.stringify(''), function(){ $.post(BACKEND_API_URL+"/resetAll", JSON.stringify(''), function(){
}); });
var parametersLocal = [] var parametersLocal = []
@ -857,8 +902,8 @@ function parseData(url) {
parametersLocal.push(document.getElementById("param-learningrate-value").value) parametersLocal.push(document.getElementById("param-learningrate-value").value)
parametersLocal.push(document.getElementById("param-maxiter-value").value) parametersLocal.push(document.getElementById("param-maxiter-value").value)
parametersLocal.push(results_all) parametersLocal.push(results_all)
$.post("http://127.0.0.1:5000/receiverSingle", JSON.stringify(parametersLocal), function(){ $.post(BACKEND_API_URL+"/receiverSingle", JSON.stringify(parametersLocal), function(){
$.get("http://127.0.0.1:5000/senderSingle", function( data ) { $.get(BACKEND_API_URL+"/senderSingle", function( data ) {
dataReceivedFromServer = data dataReceivedFromServer = data
projections = dataReceivedFromServer['projections'] projections = dataReceivedFromServer['projections']
betas = dataReceivedFromServer['betas'] betas = dataReceivedFromServer['betas']
@ -871,10 +916,10 @@ function parseData(url) {
}); });
} else { } else {
// ajax the JSON to the server // ajax the JSON to the server
$.post("http://127.0.0.1:5000/resetAll", JSON.stringify(''), function(){ $.post(BACKEND_API_URL+"/resetAll", JSON.stringify(''), function(){
}); });
$.post("http://127.0.0.1:5000/receiver", JSON.stringify(results_all), function(){ $.post(BACKEND_API_URL+"/receiver", JSON.stringify(results_all), function(){
$.get("http://127.0.0.1:5000/sender", function( data ) { $.get(BACKEND_API_URL+"/sender", function( data ) {
dataReceivedFromServer = data dataReceivedFromServer = data
ReSortOver() ReSortOver()
@ -987,11 +1032,12 @@ if (optionMetric == 1) {
zmin:0, zmin:0,
zmax:1, zmax:1,
colorbar: { colorbar: {
title: 'Normalized Metrics Performance', title: 'Metrics performance (normalized)',
tickvals:[0,0.2,0.4,0.6,0.8,1], tickvals:[0,0.2,0.4,0.6,0.8,1],
titleside:'right', titleside:'right',
}, },
xaxis: 'x'+parseInt(k+1), xaxis: 'x'+parseInt(k+1),
yaxis: 'y'+parseInt(k+1), yaxis: 'y'+parseInt(k+1),
}) })
} else { } else {
@ -2366,10 +2412,10 @@ function setReInitializeDistanceCorrelation(flag){
function setReInitialize(flag){ function setReInitialize(flag){
if(flag){ if(flag){
// Change between color-encoding and size-encoding mapped to 1/sigma and KLD. // Change between color-encoding and size-encoding mapped to 1/sigma and KLD.
if (document.getElementById('selectionLabel').innerHTML == 'Size-encoding'){ if (document.getElementById('selectionLabel').innerHTML == 'Size'){
document.getElementById('selectionLabel').innerHTML = 'Color-encoding'; document.getElementById('selectionLabel').innerHTML = 'Color';
} else{ } else{
document.getElementById('selectionLabel').innerHTML = 'Size-encoding'; document.getElementById('selectionLabel').innerHTML = 'Size';
} }
} }
@ -2547,7 +2593,7 @@ function setAnnotator(){ // Set a new annotation on top of the main visualizatio
// Unchecked! // Unchecked!
checkBox.checked = false; checkBox.checked = false;
// Print a message to the user. // Print a message to the user.
alert("Cannot hide the annotators' controls because, currently, there are no annotations into the visual representation.") alert("Cannot hide the annotator controls because there are no comments on top of the main visualization at the moment.")
} }
}); });
@ -2556,7 +2602,7 @@ function setAnnotator(){ // Set a new annotation on top of the main visualizatio
$('#downloadDists').change(function() { $('#downloadDists').change(function() {
if(!this.checked) { if(!this.checked) {
returnVal = confirm("Are you sure that you want to store the points and the parameters without the distances?"); returnVal = confirm("Are you sure that you want to store only the points and all the parameters without the distances?");
$(this).prop("checked", !returnVal); $(this).prop("checked", !returnVal);
} }
}); });
@ -2605,7 +2651,7 @@ function MainVisual(){
// fields variable is all the features (columns) plus beta and cost strings. // fields variable is all the features (columns) plus beta and cost strings.
function init(data, results_all, fields) { function init(data, results_all, fields) {
$('#comment').attr('placeholder', "Please, provide your comment."); $('#comment').attr('placeholder', "Write a comment.");
ArrayWithCosts = []; ArrayWithCosts = [];
Iterations = []; Iterations = [];
VisiblePoints = []; VisiblePoints = [];
@ -2624,9 +2670,13 @@ function init(data, results_all, fields) {
//pcpInitialize(); //pcpInitialize();
d3.select("#hider").style("z-index", 2); d3.select("#hider").style("z-index", 2);
d3.select("#hider").style("width", "48.7vw");
d3.select("#hider").style("height", overallHeight/11.8);
d3.select("#knnBarChart").style("z-index", 1); d3.select("#knnBarChart").style("z-index", 1);
d3.select("#hider2").style("z-index", 2); d3.select("#hider2").style("z-index", 2);
d3.select("#hider2").style("width", overallWidth/4.6);
d3.select("#hider2").style("height", overallHeight/16);
d3.select("#PlotCost").style("z-index", 1); d3.select("#PlotCost").style("z-index", 1);
// Clear the previously drawn main visualization canvas. // Clear the previously drawn main visualization canvas.
@ -2639,9 +2689,9 @@ function init(data, results_all, fields) {
d3.selectAll("#legend3 > *").remove(); d3.selectAll("#legend3 > *").remove();
d3.selectAll("#legend4 > *").remove(); d3.selectAll("#legend4 > *").remove();
$("#datasetDetails").html('(Unknown Number of Dimensions and Instances)'); $("#datasetDetails").html('(Num. of Dim. and Ins.: ?)');
$("#CategoryName").html('No Classification'); $("#CategoryName").html('No labels');
$("#knnBarChartDetails").html('(Number of Selected Points: 0/0)'); $("#knnBarChartDetails").html('(Num. of Selected Points: 0/0)');
// Enable again the lasso interaction. // Enable again the lasso interaction.
lassoEnable(); lassoEnable();
@ -2854,6 +2904,8 @@ function computeDistances(data, distFunc, transFunc) {
function OverallCostLineChart(){ function OverallCostLineChart(){
d3.select("#hider2").style("z-index", -1); d3.select("#hider2").style("z-index", -1);
d3.select("#hider2").style("width", 0);
d3.select("#hider2").style("height", 0);
d3.select("#PlotCost").style("z-index", 2); d3.select("#PlotCost").style("z-index", 2);
var trace1 = { var trace1 = {
@ -2874,27 +2926,30 @@ function OverallCostLineChart(){
var layout = { var layout = {
showlegend: false, showlegend: false,
width: 215, width: overallWidth/4.6,
height: 80, height: overallHeight/16,
xaxis:{title: 'Iterations', xaxis:{title: 'Iteration',
titlefont: { titlefont: {
size: 12, family: "sans-serif",
color: 'black' size: '11',
}}, color: 'black'
yaxis:{title: 'Ov. Cost', }},
titlefont: { yaxis:{title: 'Ov. cost',
size: 12, titlefont: {
color: 'black' family: "sans-serif",
}}, size: '11',
color: 'black'
},
y: 0.1,},
margin: { margin: {
l: 40, l: 32,
r: 15, r: 15,
b: 30, b: 25,
t: 5 t: 6
}, },
}; };
Plotly.newPlot('PlotCost', data, layout,{displayModeBar:false}, {staticPlot: true}); Plotly.newPlot('PlotCost', data, layout,{displayModeBar:false}, {staticPlot: true}, {responsive: true});
} }
// Function that updates embedding // Function that updates embedding
@ -2948,7 +3003,7 @@ function updateEmbedding(AnalysisResults) {
ArrayWithCostsList = AnalysisResults.slice(2*dataFeatures.length+length+10, 2*dataFeatures.length+length+11); ArrayWithCostsList = AnalysisResults.slice(2*dataFeatures.length+length+10, 2*dataFeatures.length+length+11);
Iterations = IterationsList[0]; Iterations = IterationsList[0];
ArrayWithCosts = ArrayWithCostsList[0]; ArrayWithCosts = ArrayWithCostsList[0];
$("#cost").html("(Overall Cost: " + overallCost + ")"); $("#cost").html("(Ov. Cost: " + overallCost + ")");
$('#param-perplexity-value').text(ParametersSet[1]); $('#param-perplexity-value').text(ParametersSet[1]);
$('#param-learningrate-value').text(ParametersSet[2]); $('#param-learningrate-value').text(ParametersSet[2]);
$('#param-maxiter-value').text(ParametersSet[3]); $('#param-maxiter-value').text(ParametersSet[3]);
@ -2962,7 +3017,7 @@ function updateEmbedding(AnalysisResults) {
ArrayWithCostsList = AnalysisResults.slice(2*length+8, 2*length+9); ArrayWithCostsList = AnalysisResults.slice(2*length+8, 2*length+9);
Iterations = IterationsList[0]; Iterations = IterationsList[0];
ArrayWithCosts = ArrayWithCostsList[0]; ArrayWithCosts = ArrayWithCostsList[0];
$("#cost").html("(Overall Cost: " + overallCost + ")"); $("#cost").html("(Ov. Cost: " + overallCost + ")");
$('#param-perplexity-value').text(ParametersSet[1]); $('#param-perplexity-value').text(ParametersSet[1]);
$('#param-learningrate-value').text(ParametersSet[2]); $('#param-learningrate-value').text(ParametersSet[2]);
$('#param-maxiter-value').text(ParametersSet[3]); $('#param-maxiter-value').text(ParametersSet[3]);
@ -3002,7 +3057,7 @@ function ShepardHeatMap () {
if (SHViewOptions == 1) { if (SHViewOptions == 1) {
// Set the margin of the shepard heatmap // Set the margin of the shepard heatmap
var margin = { top: 35, right: 15, bottom: 15, left: 35 }, var margin = { top: 35, right: 15, bottom: 15, left: 40 },
dim2 = Math.min(parseInt(d3.select("#sheparheat").style("width")), parseInt(d3.select("#sheparheat").style("height"))) dim2 = Math.min(parseInt(d3.select("#sheparheat").style("width")), parseInt(d3.select("#sheparheat").style("height")))
width = dim2- margin.left - margin.right, width = dim2- margin.left - margin.right,
height = dim2 - margin.top - margin.bottom, height = dim2 - margin.top - margin.bottom,
@ -3118,18 +3173,18 @@ function ShepardHeatMap () {
.attr("x", 0) .attr("x", 0)
.attr("y", function (d, i) { return i * gridSize * 2; }) .attr("y", function (d, i) { return i * gridSize * 2; })
.style("text-anchor", "end") .style("text-anchor", "end")
.style("font-size", "10px") .style("font-size", "calc(0.35em + 0.5vmin)")
.attr("transform", "translate(-6," + gridSize / 4 + ")") .attr("transform", "translate(-6," + gridSize / 4 + ")")
.attr("class","mono"); .attr("class","mono");
var tooltip2 = d3.select("body") /*var tooltip2 = d3.select("body")
.append("div") .append("div")
.style("position", "absolute") .style("position", "absolute")
.style("z-index", "12") .style("z-index", "12")
.style("text-align","center") .style("text-align","center")
.style("width","300px") .style("width","300px")
.style("height","50px") .style("height","60px")
.style("padding","2px") .style("padding","2px")
.style("background","lightsteelblue") .style("background","lightsteelblue")
.style("border-radius","8px") .style("border-radius","8px")
@ -3137,26 +3192,27 @@ function ShepardHeatMap () {
.style("pointer-events","centnoneer") .style("pointer-events","centnoneer")
.style("color","black") .style("color","black")
.style("visibility", "hidden") .style("visibility", "hidden")
.text("Hint: if values are closer to N-Dim. distances, then the visualization is too compressed."); .text("Tip: if values are closer to N-D distances, then the visualization is too compressed.");*/
var title = svg.append("text") // Title = Input Distance var title = svg.append("text") // Title = Input Distance
.attr("class", "mono") .attr("class", "mono")
.attr("x", -(gridSize * 8)) .attr("x", -(gridSize * 8))
.attr("y", -26) .attr("y", -28)
.style("font-size", "12px") .style("font-size", "calc(0.35em + 0.75vmin)")
.attr("transform", "rotate(-90)") .attr("transform", "rotate(-90)")
.on("mouseover", function(){return tooltip2.style("visibility", "visible");}) .attr("title","Tip: if values are closer to N-D distances, then the visualization is too compressed.")
.on("mousemove", function(){return tooltip2.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");}) //.on("mouseover", function(){return tooltip2.style("visibility", "visible");})
.on("mouseout", function(){return tooltip2.style("visibility", "hidden");}) //.on("mousemove", function(){return tooltip2.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");})
.text("N-Dimensional Distances"); //.on("mouseout", function(){return tooltip2.style("visibility", "hidden");})
.text("N-D distances");
var tooltip1 = d3.select("body") /*var tooltip1 = d3.select("body")
.append("div") .append("div")
.style("position", "absolute") .style("position", "absolute")
.style("z-index", "12") .style("z-index", "12")
.style("text-align","center") .style("text-align","center")
.style("width","300px") .style("width","300px")
.style("height","50px") .style("height","60px")
.style("padding","2px") .style("padding","2px")
.style("background","lightsteelblue") .style("background","lightsteelblue")
.style("border-radius","8px") .style("border-radius","8px")
@ -3164,17 +3220,18 @@ function ShepardHeatMap () {
.style("pointer-events","centnoneer") .style("pointer-events","centnoneer")
.style("color","black") .style("color","black")
.style("visibility", "hidden") .style("visibility", "hidden")
.text("Hint: if values are closer to 2-Dim. distances, then the visualization is too spread out."); .text("Tip: if values are closer to 2-D distances, then the visualization is too spread out.");*/
var title = svg.append("text") // Title = Output Distance var title = svg.append("text") // Title = Output Distance
.attr("class", "mono") .attr("class", "mono")
.attr("x", gridSize * 2 ) .attr("x", gridSize * 2.5)
.attr("y", -20) .attr("y", -20)
.on("mouseover", function(){return tooltip1.style("visibility", "visible");}) .attr("title","Tip: if values are closer to 2-D distances, then the visualization is too spread out.")
.on("mousemove", function(){return tooltip1.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");}) //.on("mouseover", function(){return tooltip1.style("visibility", "visible");})
.on("mouseout", function(){return tooltip1.style("visibility", "hidden");}) //.on("mousemove", function(){return tooltip1.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");})
.style("font-size", "12px") //.on("mouseout", function(){return tooltip1.style("visibility", "hidden");})
.text("2-Dimensional Distances"); .style("font-size", "calc(0.35em + 0.75vmin)")
.text("2-D distances");
var dim2Labels = svg.selectAll(".dim2Label") // Label var dim2Labels = svg.selectAll(".dim2Label") // Label
.data(dim_2) .data(dim_2)
@ -3183,7 +3240,7 @@ function ShepardHeatMap () {
.attr("x", function(d, i) { return i * gridSize * 3.2; }) .attr("x", function(d, i) { return i * gridSize * 3.2; })
.attr("y", 0) .attr("y", 0)
.style("text-anchor", "middle") .style("text-anchor", "middle")
.style("font-size", "10px") .style("font-size", "calc(0.35em + 0.5vmin)")
.attr("transform", "translate(" + gridSize / 4 + ", -6)") .attr("transform", "translate(" + gridSize / 4 + ", -6)")
.attr("class","mono"); .attr("class","mono");
@ -3215,8 +3272,10 @@ function ShepardHeatMap () {
var legend = d3.legendColor() // Legend color and title! var legend = d3.legendColor() // Legend color and title!
.labelFormat(d3.format(",.0f")) .labelFormat(d3.format(",.0f"))
.shapeWidth(14)
.shapeHeight(14)
.cells(9) .cells(9)
.title("Number of Points") .title("Num. of points")
.scale(colorScale); .scale(colorScale);
heatleg.select(".legendLinear") heatleg.select(".legendLinear")
@ -3284,13 +3343,13 @@ function ShepardHeatMap () {
tip(svg.append("g")); tip(svg.append("g"));
var tooltip2 = d3.select("body") /*var tooltip2 = d3.select("body")
.append("div") .append("div")
.style("position", "absolute") .style("position", "absolute")
.style("z-index", "12") .style("z-index", "12")
.style("text-align","center") .style("text-align","center")
.style("width","300px") .style("width","300px")
.style("height","50px") .style("height","60px")
.style("padding","2px") .style("padding","2px")
.style("background","lightsteelblue") .style("background","lightsteelblue")
.style("border-radius","8px") .style("border-radius","8px")
@ -3298,7 +3357,7 @@ function ShepardHeatMap () {
.style("pointer-events","centnoneer") .style("pointer-events","centnoneer")
.style("color","black") .style("color","black")
.style("visibility", "hidden") .style("visibility", "hidden")
.text("Hint: if values are closer to N-Dim. distances, then the visualization is too compressed."); .text("Tip: if values are closer to N-D distances, then the visualization is too compressed.");
var tooltip1 = d3.select("body") var tooltip1 = d3.select("body")
.append("div") .append("div")
@ -3306,7 +3365,7 @@ function ShepardHeatMap () {
.style("z-index", "12") .style("z-index", "12")
.style("text-align","center") .style("text-align","center")
.style("width","300px") .style("width","300px")
.style("height","50px") .style("height","60px")
.style("padding","2px") .style("padding","2px")
.style("background","lightsteelblue") .style("background","lightsteelblue")
.style("border-radius","8px") .style("border-radius","8px")
@ -3314,7 +3373,7 @@ function ShepardHeatMap () {
.style("pointer-events","centnoneer") .style("pointer-events","centnoneer")
.style("color","black") .style("color","black")
.style("visibility", "hidden") .style("visibility", "hidden")
.text("Hint: if values are closer to 2-Dim. distances, then the visualization is too spread out."); .text("Tip: if values are closer to 2-D distances, then the visualization is too spread out.");*/
svg.append("rect") svg.append("rect")
.attr("x",0) .attr("x",0)
@ -3346,13 +3405,14 @@ function ShepardHeatMap () {
var title = svg.append("text") // Title = Input Distance var title = svg.append("text") // Title = Input Distance
.attr("class", "mono") .attr("class", "mono")
.attr("x", -(gridSize * 8)) .attr("x", -(gridSize * 8))
.attr("y", -26) .attr("y", -28)
.style("font-size", "12px") .style("font-size", "calc(0.35em + 0.8vmin)")
.attr("transform", "rotate(-90)") .attr("transform", "rotate(-90)")
.on("mouseover", function(){return tooltip2.style("visibility", "visible");}) .attr("title","Tip: if values are closer to N-D distances, then the visualization is too compressed.")
.on("mousemove", function(){return tooltip2.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");}) //.on("mouseover", function(){return tooltip2.style("visibility", "visible");})
.on("mouseout", function(){return tooltip2.style("visibility", "hidden");}) //.on("mousemove", function(){return tooltip2.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");})
.text("N-Dimensional Distances"); //.on("mouseout", function(){return tooltip2.style("visibility", "hidden");})
.text("N-D distances");
// Add X axis label: // Add X axis label:
@ -3360,17 +3420,18 @@ function ShepardHeatMap () {
.attr("text-anchor", "end") .attr("text-anchor", "end")
.attr("x", width/2 + margin.left) .attr("x", width/2 + margin.left)
.attr("y", height + margin.top + 20) .attr("y", height + margin.top + 20)
.text("2-Dimensional Distances"); .text("2-D distances");
var title = svg.append("text") // Title = Output Distance var title = svg.append("text") // Title = Output Distance
.attr("class", "mono") .attr("class", "mono")
.attr("x", gridSize * 2 ) .attr("x", gridSize * 2.5)
.attr("y", -20) .attr("y", -20)
.style("font-size", "12px") .style("font-size", "calc(0.35em + 0.75vmin)")
.on("mouseover", function(){return tooltip1.style("visibility", "visible");}) .attr("title","Tip: if values are closer to 2-D distances, then the visualization is too spread out.")
.on("mousemove", function(){return tooltip1.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");}) //.on("mouseover", function(){return tooltip1.style("visibility", "visible");})
.on("mouseout", function(){return tooltip1.style("visibility", "hidden");}) //.on("mousemove", function(){return tooltip1.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");})
.text("2-Dimensional Distances"); //.on("mouseout", function(){return tooltip1.style("visibility", "hidden");})
.text("2-D distances");
//var colors = ["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"]; //var colors = ["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"];
// Add dots // Add dots
@ -3399,33 +3460,33 @@ function step() {
if (sliderTrigger) { if (sliderTrigger) {
if (sliderInsideTrigger) { if (sliderInsideTrigger) {
if (cost_overall[activeProjectionNumberProv][step_counter-1].toFixed(3) < 0) { if (cost_overall[activeProjectionNumberProv][step_counter-1].toFixed(3) < 0) {
$("#cost").html("(Overall Cost: 0.000)"); $("#cost").html("(Ov. Cost: 0.000)");
ArrayWithCosts.push(0); ArrayWithCosts.push(0);
Iterations.push(step_counter); Iterations.push(step_counter);
} else { } else {
$("#cost").html("(Overall Cost: " + cost_overall[activeProjectionNumberProv][step_counter-1].toFixed(3) + ")"); $("#cost").html("(Ov. Cost: " + cost_overall[activeProjectionNumberProv][step_counter-1].toFixed(3) + ")");
ArrayWithCosts.push(cost_overall[activeProjectionNumberProv][step_counter-1].toFixed(3)); ArrayWithCosts.push(cost_overall[activeProjectionNumberProv][step_counter-1].toFixed(3));
Iterations.push(step_counter); Iterations.push(step_counter);
} }
} else { } else {
if (cost_overall[activeProjectionNumber][step_counter-1].toFixed(3) < 0) { if (cost_overall[activeProjectionNumber][step_counter-1].toFixed(3) < 0) {
$("#cost").html("(Overall Cost: 0.000)"); $("#cost").html("(Ov. Cost: 0.000)");
ArrayWithCosts.push(0); ArrayWithCosts.push(0);
Iterations.push(step_counter); Iterations.push(step_counter);
} else { } else {
$("#cost").html("(Overall Cost: " + cost_overall[activeProjectionNumber][step_counter-1].toFixed(3) + ")"); $("#cost").html("(Ov. Cost: " + cost_overall[activeProjectionNumber][step_counter-1].toFixed(3) + ")");
ArrayWithCosts.push(cost_overall[activeProjectionNumber][step_counter-1].toFixed(3)); ArrayWithCosts.push(cost_overall[activeProjectionNumber][step_counter-1].toFixed(3));
Iterations.push(step_counter); Iterations.push(step_counter);
} }
} }
} else { } else {
if (cost_overall[activeProjectionNumber][step_counter-1].toFixed(3) < 0) { if (cost_overall[activeProjectionNumber][step_counter-1].toFixed(3) < 0) {
$("#cost").html("(Overall Cost: 0.000)"); $("#cost").html("(Ov. Cost: 0.000)");
ArrayWithCosts.push(0); ArrayWithCosts.push(0);
Iterations.push(step_counter); Iterations.push(step_counter);
} else { } else {
$("#cost").html("(Overall Cost: " + cost_overall[activeProjectionNumber][step_counter-1].toFixed(3) + ")"); $("#cost").html("(Ov. Cost: " + cost_overall[activeProjectionNumber][step_counter-1].toFixed(3) + ")");
ArrayWithCosts.push(cost_overall[activeProjectionNumber][step_counter-1].toFixed(3)); ArrayWithCosts.push(cost_overall[activeProjectionNumber][step_counter-1].toFixed(3));
Iterations.push(step_counter); Iterations.push(step_counter);
} }
@ -3469,11 +3530,11 @@ function OverviewtSNE(points){ // The overview t-SNE function
} }
} }
} }
$("#datasetDetails").html("(Number of Dimensions: " + (Object.keys(dataFeatures[0]).length - valCategExists) + ", Number of Instances: " + final_dataset.length + ")"); // Print on the screen the number of features and instances of the data set, which is being analyzed. $("#datasetDetails").html("(Num. of Dim.: " + (Object.keys(dataFeatures[0]).length - valCategExists) + ", Num. of Ins.: " + final_dataset.length + ")"); // Print on the screen the number of features and instances of the data set, which is being analyzed.
if (Category == undefined){ if (Category == undefined){
$("#CategoryName").html("Classification label: No category"); // Print on the screen the classification label. $("#CategoryName").html("Target label: N/A"); // Print on the screen the classification label.
} else { } else {
$("#CategoryName").html("Classification label: "+Category.replace('*','')); // Print on the screen the classification label. $("#CategoryName").html("Target label: "+Category.replace('*','')); // Print on the screen the classification label.
} }
//Make an SVG Container //Make an SVG Container
@ -3510,7 +3571,7 @@ if (format[0] == "diabetes"){
// CREATE THE SVG // CREATE THE SVG
var svg = d3.select('#overviewRect').append('svg') var svg = d3.select('#overviewRect').append('svg')
.attr('width', dim) .attr('width', dim)
.attr('height', dim) .attr('height', dimh)
.append('g'); .append('g');
// CREATE THE GROUP // CREATE THE GROUP
@ -3581,7 +3642,7 @@ var theRect = theGroup.append('rect')
.attr("id", function(d){return d.id;}) .attr("id", function(d){return d.id;})
.attr("r", 2) .attr("r", 2)
.attr("cx", function(d){return ((d.x/dimensions)*dim);}) .attr("cx", function(d){return ((d.x/dimensions)*dim);})
.attr("cy", function(d){return ((d.y/dimensionsY)*dim);}); .attr("cy", function(d){return ((d.y/dimensionsY)*dimh);});
} }
updateRect(); updateRect();
} }
@ -3661,8 +3722,8 @@ function CostHistogram(points){
barmode: "overlay", barmode: "overlay",
bargroupgap: points.length, bargroupgap: points.length,
autosize: false, autosize: false,
width: 560, width: overallWidth/4.4,
height: 250, height: overallHeight/6,
margin: { margin: {
l: 50, l: 50,
r: 20, r: 20,
@ -3670,15 +3731,15 @@ function CostHistogram(points){
t: 10, t: 10,
pad: 4 pad: 4
}, },
xaxis:{range: [0,1.01],title: 'Normalized bins from min to max values.', xaxis:{range: [0,1.01],title: 'Bins (normalized)',
titlefont: { titlefont: {
size: 14, size: 12,
color: 'black' color: 'black'
}}, }},
yaxis:{title: 'Number of Points (log)', yaxis:{title: 'Num. of points (log)',
type: "log", type: "log",
titlefont: { titlefont: {
size: 14, size: 12,
color: 'black' color: 'black'
}} }}
}; };
@ -3757,33 +3818,6 @@ function handleLassoStart(lassoPolygon) { // Empty we do not need to reset anyth
redraw(points);*/ redraw(points);*/
} }
// Initialize the horizontal (correlations) barchart's variables
var svg, defs, gBrush, brush, main_xScale, mini_xScale, main_yScale, mini_yScale, main_xAxis, main_yAxis, mini_width, textScale;
// Added only for the mouse wheel
var zoomer = d3v3.behavior.zoom()
.on("zoom", null);
// Margin of the main barchart
var main_margin = {top: 8, right: 10, bottom: 30, left: 100},
main_width = 500 - main_margin.left - main_margin.right,
main_height = 350 - main_margin.top - main_margin.bottom;
// Margin of the mini barchart
var mini_margin = {top: 8, right: 10, bottom: 30, left: 10},
mini_height = 350 - mini_margin.top - mini_margin.bottom;
mini_width = 100 - mini_margin.left - mini_margin.right;
// Create the svg correlation component
svg = d3v3.select("#correlation").attr("class", "svgWrapper")
.attr("width", main_width + main_margin.left + main_margin.right + mini_width + mini_margin.left + mini_margin.right)
.attr("height", main_height + main_margin.top + main_margin.bottom)
.call(zoomer)
.on("wheel.zoom", scroll)
.on("mousedown.zoom", null)
.on("touchstart.zoom", null)
.on("touchmove.zoom", null)
.on("touchend.zoom", null);
function click(){ // This is the click of the Schema Investigation scenario function click(){ // This is the click of the Schema Investigation scenario
svgClick = d3.select('#modtSNEcanvas_svg_Schema'); // Selecte the svg element svgClick = d3.select('#modtSNEcanvas_svg_Schema'); // Selecte the svg element
@ -5383,7 +5417,7 @@ if (points.length) { // If points exist (at least 1 point)
svg.append("g") svg.append("g")
.attr("class", "legendSize") .attr("class", "legendSize")
.attr("transform", "translate(45,20)"); .attr("transform", "translate(10,15)");
var SizeRange2 = []; var SizeRange2 = [];
SizeRange2.push(0); SizeRange2.push(0);
@ -5644,7 +5678,7 @@ if (points.length) { // If points exist (at least 1 point)
.labelFormat(d3.format(",.5f")) .labelFormat(d3.format(",.5f"))
.cells(7) .cells(7)
.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]]) .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]])
.title("Rem. Cost") .title("Remaining Cost")
.scale(colorScale); .scale(colorScale);
svg.select(".legendLinear") svg.select(".legendLinear")
@ -5906,16 +5940,16 @@ function LineBar() {
layout = { layout = {
barmode: 'group',autosize: false, barmode: 'group',autosize: false,
width: dimensions*0.97, width: dimensions*0.97,
height: vh * 1.3, height: overallHeight/11.8,
margin: { margin: {
l: 50, l: 50,
r: 30, r: 30,
b: 30, b: 30,
t: 5, t: 10,
pad: 4 pad: 4
}, },
xaxis: {range: [0, LimitXaxis], xaxis: {range: [0, LimitXaxis],
title: 'Number of neighbors', title: 'Num. of neighbors',
titlefont: { titlefont: {
size: 12, size: 12,
color: 'black' color: 'black'
@ -5963,16 +5997,16 @@ function LineBar() {
layout = { layout = {
barmode: 'group',autosize: false, barmode: 'group',autosize: false,
width: dimensions*0.97, width: dimensions*0.97,
height: vh * 1.3, height: overallHeight/11.8,
margin: { margin: {
l: 50, l: 50,
r: 30, r: 30,
b: 30, b: 30,
t: 5, t: 10,
pad: 4 pad: 4
}, },
xaxis: {range: [0, LimitXaxis], xaxis: {range: [0, LimitXaxis],
title: 'Number of neighbors', title: 'Num. of neighbors',
titlefont: { titlefont: {
size: 12, size: 12,
color: 'black' color: 'black'
@ -6011,16 +6045,16 @@ function LineBar() {
layout = { layout = {
barmode: 'group',autosize: false, barmode: 'group',autosize: false,
width: dimensions*0.97, width: dimensions*0.97,
height: vh * 1.3, height: overallHeight/11.8,
margin: { margin: {
l: 50, l: 50,
r: 30, r: 30,
b: 30, b: 30,
t: 5, t: 10,
pad: 4 pad: 4
}, },
xaxis: {range: [0, LimitXaxis], xaxis: {range: [0, LimitXaxis],
title: 'Number of neighbors', title: 'Num. of neighbors',
titlefont: { titlefont: {
size: 12, size: 12,
color: 'black' color: 'black'
@ -6034,7 +6068,7 @@ function LineBar() {
Plotly.newPlot('knnBarChart', data, layout, {displayModeBar:false}, {staticPlot: true}); Plotly.newPlot('knnBarChart', data, layout, {displayModeBar:false}, {staticPlot: true});
} }
$("#knnBarChartDetails").html("(Number of Selected Points: "+howManyPoints+"/"+dataFeatures.length+")"); $("#knnBarChartDetails").html("(Num. of Selected Points: "+howManyPoints+"/"+dataFeatures.length+")");
// If the checkbox is checked, display the output text // If the checkbox is checked, display the output text
} }

Binary file not shown.
Loading…
Cancel
Save