@ -1,24 +1,40 @@
// t-SNE.js object and other global variables
// t-SNE Visualization and global variables
var k ; var points = [ ] ; var all _fields ; var pointsbeta = [ ] ; var KNNEnabled = true ; var cost = [ ] ; var ParametersSet = [ ] ; var overallCost ;
// This variable is used when a new file is upload by a user.
// form controls
var new _file ;
var input ;
// These are the dimensions for the square shape of the main panel\
var dimensions = document . getElementById ( 'modtSNEcanvas' ) . offsetWidth ;
var prevRightClick ; var ColorsCategorical ; var Category ;
// These are the dimensions for the overview panel
// The basic variables in order to execute t-SNE (opt is perplexity and learning rate).
var dim = document . getElementById ( 'tSNEcanvas' ) . offsetWidth ;
var tsne ; var opt ; var step _counter ; var max _counter ; var runner ;
var format ; var new _file ; var opt ; var step _counter ; var final _dataset ; var max _counter ; var dists ; var dists2d ; var all _labels ; var runner ; var tsne ; var count _canvas = 0 ; var x _position = [ ] ; var y _position = [ ] ; var x _position2 = [ ] ; var y _position2 = [ ] ; var cost _each ; var beta _all = [ ] ;
// These variables are initialized here in order to store the final dataset, the points, the cost, the cost for each iteration, the beta values, the positions, the 2D points positions,
var points2d = [ ] ; var ArrayContainsDataFeatures = [ ] ; var ArrayContainsDataFeaturesCleared = [ ] ;
// In addition, there is an array which keeps the initial information of the points (i.e., initial state), the data features (with the label of the category plus the id of the point), the data features without the category (only numbers).
var InitialStatePoints = [ ] ;
var final _dataset ; var points = [ ] ; var cost = [ ] ; var cost _each ; var beta _all = [ ] ; var x _position = [ ] ; var y _position = [ ] ; var points2d = [ ] ; var ArrayContainsDataFeatures = [ ] ; var ArrayContainsDataFeaturesCleared = [ ] ; var InitialStatePoints = [ ] ;
// The distances in the high dimensional space and in the 2D space. All the labels that were found in the selected data set.
var dists ; var dists2d ; var all _labels ;
// These are the dimensions for the Overview view and the Main view
var dim = document . getElementById ( 'tSNEcanvas' ) . offsetWidth ; var dimensions = document . getElementById ( 'modtSNEcanvas' ) . offsetWidth ;
// Category = the name of the category if it exists. The user has to add an asterisk ("*") mark in order to let the program identify this feature as a label/category name.
// ColorsCategorical = the categorical colors (maximum value = 10).
var Category ; var ColorsCategorical ;
// Schema Investigation
// svgClick = Click a left mouse click in order to add a point.
// prevRightClick = When right click is pressed prevent any other action. Lock the current schema.
// if flagForSchema is false then send a message to the user that he/she has to: "Please, draw a schema first!");
var svgClick ; var prevRightClick ; var flagForSchema = false ;
// Save the parameters for the current analysis, save the overallCost, and store in the "input" variable all the points and points2D.
var ParametersSet = [ ] ; var overallCost ; var input ;
// This function is executed when the factory button is pressed in order to bring the visualization in the initial state.
function FactoryReset ( ) {
function FactoryReset ( ) {
lassoEnable ( ) ;
flagForSchema = false ;
flag = false ;
d3 . selectAll ( "#modtSNEcanvas_svg_Schema > *" ) . remove ( ) ;
d3 . selectAll ( "#modtSNEcanvas_svg_Schema > *" ) . remove ( ) ;
d3 . selectAll ( "#SvgAnnotator > *" ) . remove ( ) ;
d3 . selectAll ( "#SvgAnnotator > *" ) . remove ( ) ;
d3 . select ( "#data" ) . select ( "input" ) . remove ( ) ; // Remove the selection field.
Arrayx = [ ] ;
Arrayx = [ ] ;
Arrayy = [ ] ;
Arrayy = [ ] ;
XYDistId = [ ] ;
XYDistId = [ ] ;
@ -95,15 +111,18 @@ function FactoryReset(){
}
}
// Load a previously executed analysis function.
function loadAnalysis ( ) {
function loadAnalysis ( ) {
document . getElementById ( 'file-input' ) . click ( ) ;
document . getElementById ( 'file-input' ) . click ( ) ;
document . getElementById ( "ExecuteBut" ) . innerHTML = "Execute previous t-SNE analysis" ;
document . getElementById ( "ExecuteBut" ) . innerHTML = "Execute previous t-SNE analysis" ;
}
}
// This function is being used when the user selects to upload a new data set.
function getfile ( file ) {
function getfile ( file ) {
new _file = file ; //uploaded file data
new _file = file ; //uploaded data file
}
}
// Read the previous analysis, which the user wants to upload.
function fetchVal ( callback ) {
function fetchVal ( callback ) {
var file , fr ;
var file , fr ;
file = input . files [ 0 ] ;
file = input . files [ 0 ] ;
@ -115,24 +134,25 @@ function fetchVal(callback) {
fr . readAsText ( file ) ;
fr . readAsText ( file ) ;
}
}
// Parse data
// Parse the data set
var getData = function ( ) {
var getData = function ( ) {
let format ;
let value ;
if ( typeof window . FileReader !== 'function' ) {
if ( typeof window . FileReader !== 'function' ) {
alert ( "The file API isn't supported on this browser yet." ) ;
alert ( "The file API isn't supported on this browser yet." ) ;
}
}
var value ;
input = document . getElementById ( "file-input" ) ;
input = document . getElementById ( "file-input" ) ;
if ( ! input ) {
if ( ! input ) {
alert ( "Um, couldn't find the fileinput element." ) ;
alert ( "Um, couldn't find the fileinput element." ) ;
}
} else if ( ! input . files ) {
else if ( ! input . files ) {
alert ( "This browser doesn't seem to support the `files` property of file inputs." ) ;
alert ( "This browser doesn't seem to support the `files` property of file inputs." ) ;
}
} else if ( ! input . files [ 0 ] ) {
else if ( ! input . files [ 0 ] ) {
value = document . getElementById ( "param-dataset" ) . value ; // get the value of the data set
value = document . getElementById ( "param-dataset" ) . value ;
format = document . getElementById ( "param-dataset" ) . value . split ( "." ) ; //get the format
format = document . getElementById ( "param-dataset" ) . value . split ( "." ) ; //get the actual format
if ( format [ value . split ( "." ) . length - 1 ] == "csv" ) {
if ( format [ value . split ( "." ) . length - 1 ] == "csv" ) {
parseData ( "./data/" + value ) ;
parseData ( "./data/" + value ) ;
} else {
} else {
@ -168,8 +188,6 @@ function parseData(url) {
for ( key in el ) {
for ( key in el ) {
if ( el . hasOwnProperty ( key ) ) {
if ( el . hasOwnProperty ( key ) ) {
var value = el [ key ] ;
var value = el [ key ] ;
if ( key === 'name' ) {
} else {
if ( typeof ( value ) !== 'number' || value === undefined || key === "Version" ) { //add more limitations if needed!
if ( typeof ( value ) !== 'number' || value === undefined || key === "Version" ) { //add more limitations if needed!
delete el [ key ] ;
delete el [ key ] ;
} else {
} else {
@ -179,7 +197,6 @@ function parseData(url) {
}
}
}
}
}
}
}
return el ;
return el ;
} ) ;
} ) ;
Papa . parse ( url , { //for csv file!
Papa . parse ( url , { //for csv file!
@ -211,7 +228,7 @@ function setReset(){
d3 . selectAll ( "#correlation > *" ) . remove ( ) ;
d3 . selectAll ( "#correlation > *" ) . remove ( ) ;
d3 . selectAll ( "#modtSNEcanvas_svg > *" ) . remove ( ) ;
d3 . selectAll ( "#modtSNEcanvas_svg > *" ) . remove ( ) ;
lassoEnable ( ) ;
lassoEnable ( ) ;
flag = false ;
flagForSchema = false ;
d3 . selectAll ( "#modtSNEcanvas_svg_Schema > *" ) . remove ( ) ;
d3 . selectAll ( "#modtSNEcanvas_svg_Schema > *" ) . remove ( ) ;
d3 . selectAll ( "#SvgAnnotator > *" ) . remove ( ) ;
d3 . selectAll ( "#SvgAnnotator > *" ) . remove ( ) ;
Arrayx = [ ] ;
Arrayx = [ ] ;
@ -259,7 +276,9 @@ function setLayerComp(){
d3 . select ( "#modtSNEcanvas_svg" ) . style ( "z-index" , 2 ) ;
d3 . select ( "#modtSNEcanvas_svg" ) . style ( "z-index" , 2 ) ;
d3 . select ( "#modtSNEcanvas_svg_Schema" ) . style ( "z-index" , 1 ) ;
d3 . select ( "#modtSNEcanvas_svg_Schema" ) . style ( "z-index" , 1 ) ;
d3 . select ( "#modtSNEcanvas" ) . style ( "z-index" , 1 ) ;
d3 . select ( "#modtSNEcanvas" ) . style ( "z-index" , 1 ) ;
if ( points . length ) {
lassoEnable ( ) ;
lassoEnable ( ) ;
}
}
}
function setLayerSche ( ) {
function setLayerSche ( ) {
@ -355,6 +374,11 @@ function setAnnotator(){
. classed ( "shaded" , function ( d ) { return d . shaded ; } ) ;
. classed ( "shaded" , function ( d ) { return d . shaded ; } ) ;
}
}
} else {
} else {
// Get the checkbox.
var checkBox = document . getElementById ( "controls" ) ;
// Unchecked!
checkBox . checked = false ;
// Print a message to the user.
alert ( "Cannot hide the annotators' controls because, currently, there are no annotations into the visual representation." )
alert ( "Cannot hide the annotators' controls because, currently, there are no annotations into the visual representation." )
}
}
} ) ;
} ) ;
@ -458,7 +482,6 @@ function init(data, results_all, fields) {
var fields ;
var fields ;
fields . push ( "beta" ) ;
fields . push ( "beta" ) ;
fields . push ( "cost" ) ;
fields . push ( "cost" ) ;
all _fields = fields ;
opt . epsilon = document . getElementById ( "param-learningrate-value" ) . value ; // epsilon is learning rate (10 = default)
opt . epsilon = document . getElementById ( "param-learningrate-value" ) . value ; // epsilon is learning rate (10 = default)
opt . perplexity = document . getElementById ( "param-perplexity-value" ) . value ; // roughly how many neighbors each point influences (30 = default)
opt . perplexity = document . getElementById ( "param-perplexity-value" ) . value ; // roughly how many neighbors each point influences (30 = default)
tsne = new tsnejs . tSNE ( opt ) ;
tsne = new tsnejs . tSNE ( opt ) ;
@ -483,19 +506,17 @@ function init(data, results_all, fields) {
for ( let k = 0 ; k < dataFeatures . length ; k ++ ) {
for ( let k = 0 ; k < dataFeatures . length ; k ++ ) {
ArrayContainsDataFeatures . push ( Object . values ( dataFeatures [ k ] ) . concat ( k ) ) ;
ArrayContainsDataFeatures . push ( Object . values ( dataFeatures [ k ] ) . concat ( k ) ) ;
object = [ ] ;
object = [ ] ;
Object . values ( dataFeatures [ k ] ) . forEach ( function ( dataFeature ) {
for ( let j = 0 ; j < Object . keys ( dataFeatures [ k ] ) . length ; j ++ ) {
if ( typeof ( dataFeature ) == "number" ) {
if ( typeof ( Object . values ( dataFeatures [ k ] ) [ j ] ) == "number" && Object . keys ( dataFeatures [ k ] ) [ j ] != Category ) {
object . push ( dataFeature ) ;
object . push ( Object . values ( dataFeatures [ k ] ) [ j ] ) ;
}
}
}
} ) ;
ArrayContainsDataFeaturesCleared . push ( object ) ;
ArrayContainsDataFeaturesCleared . push ( object ) ;
}
}
var valCategExists = 0 ;
var valCategExists = 0 ;
for ( var i = 0 ; i < Object . keys ( dataFeatures [ 0 ] ) . length ; i ++ ) {
for ( var i = 0 ; i < Object . keys ( dataFeatures [ 0 ] ) . length ; i ++ ) {
if ( Object . keys ( dataFeatures [ 0 ] ) [ i ] == Category ) {
if ( Object . keys ( dataFeatures [ 0 ] ) [ i ] == Category ) {
valCategExists = valCategExists + 1 ;
valCategExists = valCategExists + 1 ;
}
}
}
}
@ -792,7 +813,7 @@ d3.tsv("./modules/heat.tsv").then(function(data) {
var tip = d3 . tip ( )
var tip = d3 . tip ( )
. attr ( 'class' , 'd3-tip' )
. attr ( 'class' , 'd3-tip' )
. style ( "visibility" , "visible" )
. style ( "visibility" , "visible" )
. offset ( [ - 20 , 0 ] )
. offset ( [ - 10 , 36.5 ] )
. html ( function ( d ) {
. html ( function ( d ) {
return "Value: <span style='color:red'>" + Math . round ( d . value ) ;
return "Value: <span style='color:red'>" + Math . round ( d . value ) ;
} ) ;
} ) ;
@ -1114,7 +1135,6 @@ function redraw(repoints){
function handleLassoEnd ( lassoPolygon ) {
function handleLassoEnd ( lassoPolygon ) {
var countLassoFalse = 0 ;
var countLassoFalse = 0 ;
KNNEnabled = true ;
for ( var i = 0 ; i < points . length ; i ++ ) {
for ( var i = 0 ; i < points . length ; i ++ ) {
x = points [ i ] . x ;
x = points [ i ] . x ;
@ -1152,7 +1172,6 @@ function handleLassoEnd(lassoPolygon) {
// reset selected points when starting a new polygon
// reset selected points when starting a new polygon
function handleLassoStart ( lassoPolygon ) {
function handleLassoStart ( lassoPolygon ) {
KNNEnabled = false ;
for ( var i = 0 ; i < points . length ; i ++ ) {
for ( var i = 0 ; i < points . length ; i ++ ) {
points [ i ] . selected = true ;
points [ i ] . selected = true ;
points [ i ] . starplot = false ;
points [ i ] . starplot = false ;
@ -1198,9 +1217,6 @@ var svg,
. on ( "touchmove.zoom" , null )
. on ( "touchmove.zoom" , null )
. on ( "touchend.zoom" , null ) ;
. on ( "touchend.zoom" , null ) ;
var svgClick ;
var flag = false ;
function click ( ) {
function click ( ) {
svgClick = d3 . select ( '#modtSNEcanvas_svg_Schema' ) ;
svgClick = d3 . select ( '#modtSNEcanvas_svg_Schema' ) ;
@ -1251,7 +1267,7 @@ function click(){
// Prevent the default mouse action. Allow right click to be used for the confirmation of our schema.
// Prevent the default mouse action. Allow right click to be used for the confirmation of our schema.
d3 . event . preventDefault ( ) ;
d3 . event . preventDefault ( ) ;
flag = true ;
flagForSchema = true ;
CalculateCorrel ( ) ;
CalculateCorrel ( ) ;
}
}
} ) ;
} ) ;
@ -1259,7 +1275,7 @@ function click(){
function CalculateCorrel ( ) {
function CalculateCorrel ( ) {
if ( flag == false ) {
if ( flagForSchema == false ) {
alert ( "Please, draw a schema first!" ) ;
alert ( "Please, draw a schema first!" ) ;
} else {
} else {
var correlLimit = document . getElementById ( "param-corr-value" ) . value ;
var correlLimit = document . getElementById ( "param-corr-value" ) . value ;
@ -1317,7 +1333,7 @@ function CalculateCorrel(){
ArrayLimit = [ ] ;
ArrayLimit = [ ] ;
for ( var i = 0 ; i < arraysCleared . length ; i ++ ) {
for ( var i = 0 ; i < arraysCleared . length ; i ++ ) {
if ( arraysCleared [ i ] [ 5 ] < correlLimit ) {
if ( arraysCleared [ i ] [ arraysCleared [ 0 ] . length - 2 ] < correlLimit ) {
ArrayLimit . push ( arraysCleared [ i ] ) ;
ArrayLimit . push ( arraysCleared [ i ] ) ;
}
}
}
}
@ -1326,7 +1342,7 @@ function CalculateCorrel(){
var count = new Array ( paths . nodes ( ) . length ) . fill ( 0 ) ;
var count = new Array ( paths . nodes ( ) . length ) . fill ( 0 ) ;
for ( var m = 0 ; m < paths . nodes ( ) . length ; m ++ ) {
for ( var m = 0 ; m < paths . nodes ( ) . length ; m ++ ) {
for ( var i = 0 ; i < ArrayLimit . length ; i ++ ) {
for ( var i = 0 ; i < ArrayLimit . length ; i ++ ) {
if ( ArrayLimit [ i ] [ 2 ] == m ) {
if ( ArrayLimit [ i ] [ ArrayLimit [ 0 ] . length - 5 ] == m ) {
count [ m ] = count [ m ] + 1 ;
count [ m ] = count [ m ] + 1 ;
temparray . push ( ArrayLimit [ i ] ) ;
temparray . push ( ArrayLimit [ i ] ) ;
}
}
@ -1361,33 +1377,60 @@ function CalculateCorrel(){
}
}
var Order = [ ] ;
var Order = [ ] ;
for ( var temp = 0 ; temp < arraysConnected . length ; temp ++ ) {
for ( var temp = 0 ; temp < arraysConnected . length ; temp ++ ) {
Order . push ( arraysConnected [ temp ] [ 6 ] ) ;
Order . push ( arraysConnected [ temp ] [ arraysConnected [ 0 ] . length - 1 ] ) ;
}
}
for ( var i = 0 ; i < points . length ; i ++ ) {
for ( var i = 0 ; i < points . length ; i ++ ) {
points [ i ] . selected = false ;
points [ i ] . selected = false ;
for ( var j = 0 ; j < ArrayLimit . length ; j ++ ) {
for ( var j = 0 ; j < ArrayLimit . length ; j ++ ) {
if ( ArrayLimit [ j ] [ 6 ] == points [ i ] . id ) {
if ( ArrayLimit [ j ] [ ArrayLimit [ 0 ] . length - 1 ] == points [ i ] . id ) {
points [ i ] . selected = true ;
points [ i ] . selected = true ;
}
}
}
}
}
}
redraw ( points ) ;
redraw ( points ) ;
for ( let k = 0 ; k < dataFeatures . length ; k ++ ) {
for ( let k = 0 ; k < dataFeatures . length ; k ++ ) {
ArrayContainsDataFeatures . push ( Object . values ( dataFeatures [ k ] ) . concat ( k ) ) ;
ArrayContainsDataFeaturesCleared . push ( ArrayContainsDataFeaturesCleared [ k ] . concat ( k ) ) ;
}
}
ArrayContainsDataFeatures = mapOrder ( ArrayContainsDataFeatures , Order , 5 ) ;
ArrayContainsDataFeaturesCleared = mapOrder ( ArrayContainsDataFeaturesCleared , Order , arraysConnected [ 0 ] . length - 2 ) ;
ArrayContainsDataFeaturesLimit = [ ] ;
ArrayContainsDataFeaturesLimit = [ ] ;
for ( var i = 0 ; i < ArrayContainsDataFeatures . length ; i ++ ) {
for ( var i = 0 ; i < ArrayContainsDataFeaturesCleared . length ; i ++ ) {
for ( var j = 0 ; j < arraysConnected . length ; j ++ ) {
for ( var j = 0 ; j < arraysConnected . length ; j ++ ) {
if ( ArrayContainsDataFeatures [ i ] [ 5 ] == arraysConnected [ j ] [ 6 ] ) {
if ( ArrayContainsDataFeaturesCleared [ i ] [ ArrayContainsDataFeaturesCleared [ 0 ] . length - 1 ] == arraysConnected [ j ] [ arraysConnected [ 0 ] . length - 1 ] ) {
ArrayContainsDataFeaturesLimit . push ( ArrayContainsDataFeatures [ i ] ) ;
ArrayContainsDataFeaturesLimit . push ( ArrayContainsDataFeaturesCleared [ i ] ) ;
}
}
}
}
}
}
if ( ArrayContainsDataFeaturesLimit . length == 0 ) {
d3 . selectAll ( "#correlation > *" ) . remove ( ) ;
d3 . selectAll ( "#modtSNEcanvas_svg > *" ) . remove ( ) ;
flagForSchema = false ;
d3 . selectAll ( "#modtSNEcanvas_svg_Schema > *" ) . remove ( ) ;
Arrayx = [ ] ;
Arrayy = [ ] ;
XYDistId = [ ] ;
Arrayxy = [ ] ;
DistanceDrawing1D = [ ] ;
allTransformPoints = [ ] ;
p ;
pFinal = [ ] ;
paths ;
path ;
ArrayLimit = [ ] ;
minimum ;
correlationResults = [ ] ;
ArrayContainsDataFeaturesLimit = [ ] ;
prevRightClick = false ;
for ( var i = 0 ; i < InitialStatePoints . length ; i ++ ) {
InitialStatePoints [ i ] . selected = true ;
InitialStatePoints [ i ] . starplot = false ;
}
alert ( "No points selected! Please, try to increase the correlation threshold." ) ;
redraw ( InitialStatePoints ) ;
} else {
for ( var loop = 0 ; loop < ArrayContainsDataFeaturesLimit . length ; loop ++ ) {
for ( var loop = 0 ; loop < ArrayContainsDataFeaturesLimit . length ; loop ++ ) {
ArrayContainsDataFeaturesLimit [ loop ] . push ( loop ) ;
ArrayContainsDataFeaturesLimit [ loop ] . push ( loop ) ;
}
}
@ -1429,6 +1472,7 @@ function CalculateCorrel(){
}
}
drawBarChart ( ) ;
drawBarChart ( ) ;
}
}
}
}
}
function drawBarChart ( ) {
function drawBarChart ( ) {
@ -1960,6 +2004,7 @@ height = Math.min(width, window.innerHeight - margin.top - margin.bottom);
function BetatSNE ( points ) {
function BetatSNE ( points ) {
if ( points . length ) {
selectedPoints = [ ] ;
selectedPoints = [ ] ;
var findNearestTable = [ ] ;
var findNearestTable = [ ] ;
for ( let m = 0 ; m < points . length ; m ++ ) {
for ( let m = 0 ; m < points . length ; m ++ ) {
@ -1968,7 +2013,7 @@ function BetatSNE(points){
}
}
}
}
if ( KNNEnabled == true && selectedPoints . length != 0 ) {
if ( selectedPoints . length != 0 ) {
var distsFull = dists ;
var distsFull = dists ;
var dists2dFull = dists2d ;
var dists2dFull = dists2d ;
@ -2008,7 +2053,7 @@ function BetatSNE(points){
$ ( "#kNNDetails" ) . html ( "Purity of the cluster was checked for k values starting from " + ( 1 ) + " to " + maxKNN + "." ) ;
$ ( "#kNNDetails" ) . html ( "Purity of the cluster was checked for k values starting from " + ( 1 ) + " to " + maxKNN + "." ) ;
for ( k = maxKNN ; k > 0 ; k -- ) {
for ( k = maxKNN ; k > 1 ; k -- ) {
findNearest = 0 ;
findNearest = 0 ;
var indexOrderSliced = [ ] ;
var indexOrderSliced = [ ] ;
@ -2271,19 +2316,19 @@ function BetatSNE(points){
svg . select ( ".legendLinear" )
svg . select ( ".legendLinear" )
. call ( legend ) ;
. call ( legend ) ;
} else {
} else {
var max = ( d3 . max ( points , function ( d ) { return d . cost ; } ) ) ;
var max = ( d3 . max ( points , function ( d ) { return d . cost ; } ) ) ;
var min = ( d3 . min ( points , function ( d ) { return d . cost ; } ) ) ;
var min = ( d3 . min ( points , function ( d ) { return d . cost ; } ) ) ;
var maxSize2 = ( d3 . max ( points , function ( d ) { return d . beta ; } ) ) ;
var maxSize2 = ( d3 . max ( points , function ( d ) { return d . beta ; } ) ) ;
var minSize2 = ( d3 . min ( points , function ( d ) { return d . beta ; } ) ) ;
var minSize2 = ( d3 . min ( points , function ( d ) { return d . beta ; } ) ) ;
var rscale2 = d3 . scaleLinear ( )
var rscale2 = d3 . scaleLinear ( )
. domain ( [ minSize2 , maxSize2 ] )
. domain ( [ minSize2 , maxSize2 ] )
. range ( [ 5 , 12 ] ) ;
. range ( [ 5 , 12 ] ) ;
var colorbrewer = [ "#ffffe5" , "#f7fcb9" , "#d9f0a3" , "#addd8e" , "#78c679" , "#41ab5d" , "#238443" , "#006837" , "#004529" ] ;
var colorbrewer = [ "#ffffe5" , "#f7fcb9" , "#d9f0a3" , "#addd8e" , "#78c679" , "#41ab5d" , "#238443" , "#006837" , "#004529" ] ;
var calcStep = ( max - min ) / 9 ;
var calcStep = ( max - min ) / 9 ;
var colorScale = d3 . scaleLinear ( )
var colorScale = d3 . scaleLinear ( )
. domain ( d3 . range ( min , max , calcStep ) )
. domain ( d3 . range ( min , max , calcStep ) )
. range ( colorbrewer ) ;
. range ( colorbrewer ) ;
@ -2314,54 +2359,54 @@ var colorScale = d3.scaleLinear()
svg . select ( ".legendLinear" )
svg . select ( ".legendLinear" )
. call ( legend ) ;
. call ( legend ) ;
}
}
window . addEventListener ( 'resize' , ( ) => {
window . addEventListener ( 'resize' , ( ) => {
dimensions = window . innerWidth ;
dimensions = window . innerWidth ;
dimensions = window . innerHeight ;
dimensions = window . innerHeight ;
renderer . setSize ( dimensions , dimensions ) ;
renderer . setSize ( dimensions , dimensions ) ;
camera . aspect = dimensions / dimensions ;
camera . aspect = dimensions / dimensions ;
camera . updateProjectionMatrix ( ) ;
camera . updateProjectionMatrix ( ) ;
} )
} )
let zoom = d3 . zoom ( )
let zoom = d3 . zoom ( )
. scaleExtent ( [ getScaleFromZ ( far ) , getScaleFromZ ( near ) ] )
. scaleExtent ( [ getScaleFromZ ( far ) , getScaleFromZ ( near ) ] )
. on ( 'zoom' , ( ) => {
. on ( 'zoom' , ( ) => {
let d3 _transform = d3 . event . transform ;
let d3 _transform = d3 . event . transform ;
zoomHandler ( d3 _transform ) ;
zoomHandler ( d3 _transform ) ;
} ) ;
} ) ;
view = d3 . select ( renderer . domElement ) ;
view = d3 . select ( renderer . domElement ) ;
function setUpZoom ( ) {
function setUpZoom ( ) {
view . call ( zoom ) ;
view . call ( zoom ) ;
let initial _scale = getScaleFromZ ( far ) ;
let initial _scale = getScaleFromZ ( far ) ;
var initial _transform = d3 . zoomIdentity . translate ( dimensions / 2 , dimensions / 2 ) . scale ( initial _scale ) ;
var initial _transform = d3 . zoomIdentity . translate ( dimensions / 2 , dimensions / 2 ) . scale ( initial _scale ) ;
zoom . transform ( view , initial _transform ) ;
zoom . transform ( view , initial _transform ) ;
camera . position . set ( 0 , 0 , far ) ;
camera . position . set ( 0 , 0 , far ) ;
}
}
//if(step_counter == max_counter){
//if(step_counter == max_counter){
setUpZoom ( ) ;
setUpZoom ( ) ;
//}
//}
var circle _sprite = new THREE . TextureLoader ( ) . load (
var circle _sprite = new THREE . TextureLoader ( ) . load (
"./textures/circle-sprite.png"
"./textures/circle-sprite.png"
)
)
clearThree ( scene ) ;
clearThree ( scene ) ;
// Increase/reduce size factor selected by the user
// Increase/reduce size factor selected by the user
var limitdist = document . getElementById ( "param-lim-value" ) . value ;
var limitdist = document . getElementById ( "param-lim-value" ) . value ;
limitdist = parseFloat ( limitdist ) . toFixed ( 1 ) ;
limitdist = parseFloat ( limitdist ) . toFixed ( 1 ) ;
let pointsMaterial ;
let pointsMaterial ;
let factorPlusSize ;
let factorPlusSize ;
let geometry = new THREE . Geometry ( ) ;
let geometry = new THREE . Geometry ( ) ;
for ( var i = 0 ; i < points . length ; i ++ ) {
for ( var i = 0 ; i < points . length ; i ++ ) {
let pointsGeometry = new THREE . Geometry ( ) ;
let pointsGeometry = new THREE . Geometry ( ) ;
let vertex = new THREE . Vector3 ( ( ( ( points [ i ] . x / dimensions ) * 2 ) - 1 ) * dimensions , ( ( ( points [ i ] . y / dimensions ) * 2 ) - 1 ) * dimensions * - 1 , 0 ) ;
let vertex = new THREE . Vector3 ( ( ( ( points [ i ] . x / dimensions ) * 2 ) - 1 ) * dimensions , ( ( ( points [ i ] . y / dimensions ) * 2 ) - 1 ) * dimensions * - 1 , 0 ) ;
pointsGeometry . vertices . push ( vertex ) ;
pointsGeometry . vertices . push ( vertex ) ;
@ -2416,25 +2461,25 @@ for (var i=0; i<points.length; i++) {
var particlesDuplic = new THREE . Points ( geometry , pointsMaterial ) ;
var particlesDuplic = new THREE . Points ( geometry , pointsMaterial ) ;
var particles = new THREE . Points ( pointsGeometry , pointsMaterial ) ;
var particles = new THREE . Points ( pointsGeometry , pointsMaterial ) ;
scene . add ( particles ) ;
scene . add ( particles ) ;
}
}
let tempSort = - 1 ;
let tempSort = - 1 ;
for ( var i = 0 ; i < points . length ; i ++ ) {
for ( var i = 0 ; i < points . length ; i ++ ) {
if ( points [ i ] . DimON != null ) {
if ( points [ i ] . DimON != null ) {
tempSort = points [ i ] . DimON . match ( /\d+/ ) [ 0 ] ;
tempSort = points [ i ] . DimON . match ( /\d+/ ) [ 0 ] ;
}
}
}
}
if ( tempSort != - 1 ) {
if ( tempSort != - 1 ) {
points = points . sort ( function ( a , b ) {
points = points . sort ( function ( a , b ) {
return a [ tempSort ] - b [ tempSort ] ;
return a [ tempSort ] - b [ tempSort ] ;
} )
} )
}
}
var temporal = 0 ;
var temporal = 0 ;
for ( var j = 0 ; j < points . length ; j ++ ) {
for ( var j = 0 ; j < points . length ; j ++ ) {
if ( points [ j ] . DimON != null ) {
if ( points [ j ] . DimON != null ) {
temporal = temporal + 1 ;
temporal = temporal + 1 ;
var labels _dim = [ ] ;
var labels _dim = [ ] ;
var abbr _labels _dim = [ ] ;
var abbr _labels _dim = [ ] ;
@ -2462,10 +2507,10 @@ if(points[j].DimON != null) {
. call ( legend ) ;
. call ( legend ) ;
break ;
break ;
}
}
}
}
// This is for the legend
// This is for the legend
for ( var j = 0 ; j < points . length ; j ++ ) {
for ( var j = 0 ; j < points . length ; j ++ ) {
if ( temporal == 0 && points [ j ] . DimON == null ) {
if ( temporal == 0 && points [ j ] . DimON == null ) {
if ( ColSizeSelector == "color" ) {
if ( ColSizeSelector == "color" ) {
d3 . select ( "#legend1" ) . selectAll ( '*' ) . remove ( ) ;
d3 . select ( "#legend1" ) . selectAll ( '*' ) . remove ( ) ;
var svg = d3 . select ( "#legend1" ) ;
var svg = d3 . select ( "#legend1" ) ;
@ -2504,56 +2549,56 @@ if(temporal == 0 && points[j].DimON == null){
break ;
break ;
}
}
}
}
}
}
function zoomHandler ( d3 _transform ) {
function zoomHandler ( d3 _transform ) {
let scale = d3 _transform . k ;
let scale = d3 _transform . k ;
let x = - ( d3 _transform . x - dimensions / 2 ) / scale ;
let x = - ( d3 _transform . x - dimensions / 2 ) / scale ;
let y = ( d3 _transform . y - dimensions / 2 ) / scale ;
let y = ( d3 _transform . y - dimensions / 2 ) / scale ;
let z = getZFromScale ( scale ) ;
let z = getZFromScale ( scale ) ;
camera . position . set ( x , y , z ) ;
camera . position . set ( x , y , z ) ;
}
}
function getScaleFromZ ( camera _z _position ) {
function getScaleFromZ ( camera _z _position ) {
let half _fov = fov / 2 ;
let half _fov = fov / 2 ;
let half _fov _radians = toRadians ( half _fov ) ;
let half _fov _radians = toRadians ( half _fov ) ;
let half _fov _height = Math . tan ( half _fov _radians ) * camera _z _position ;
let half _fov _height = Math . tan ( half _fov _radians ) * camera _z _position ;
let fov _height = half _fov _height * 2 ;
let fov _height = half _fov _height * 2 ;
let scale = dimensions / fov _height ; // Divide visualization height by height derived from field of view
let scale = dimensions / fov _height ; // Divide visualization height by height derived from field of view
return scale ;
return scale ;
}
}
function getZFromScale ( scale ) {
function getZFromScale ( scale ) {
let half _fov = fov / 2 ;
let half _fov = fov / 2 ;
let half _fov _radians = toRadians ( half _fov ) ;
let half _fov _radians = toRadians ( half _fov ) ;
let scale _height = dimensions / scale ;
let scale _height = dimensions / scale ;
let camera _z _position = scale _height / ( 2 * Math . tan ( half _fov _radians ) ) ;
let camera _z _position = scale _height / ( 2 * Math . tan ( half _fov _radians ) ) ;
return camera _z _position ;
return camera _z _position ;
}
}
function toRadians ( angle ) {
function toRadians ( angle ) {
return angle * ( Math . PI / 180 ) ;
return angle * ( Math . PI / 180 ) ;
}
}
// Hover and tooltip interaction
// Hover and tooltip interaction
raycaster = new THREE . Raycaster ( ) ;
raycaster = new THREE . Raycaster ( ) ;
raycaster . params . Points . threshold = 10 ;
raycaster . params . Points . threshold = 10 ;
view . on ( "mousemove" , ( ) => {
view . on ( "mousemove" , ( ) => {
let [ mouseX , mouseY ] = d3 . mouse ( view . node ( ) ) ;
let [ mouseX , mouseY ] = d3 . mouse ( view . node ( ) ) ;
let mouse _position = [ mouseX , mouseY ] ;
let mouse _position = [ mouseX , mouseY ] ;
checkIntersects ( mouse _position ) ;
checkIntersects ( mouse _position ) ;
} ) ;
} ) ;
function mouseToThree ( mouseX , mouseY ) {
function mouseToThree ( mouseX , mouseY ) {
return new THREE . Vector3 (
return new THREE . Vector3 (
mouseX / dimensions * 2 - 1 ,
mouseX / dimensions * 2 - 1 ,
- ( mouseY / dimensions ) * 2 + 1 ,
- ( mouseY / dimensions ) * 2 + 1 ,
1
1
) ;
) ;
}
}
function checkIntersects ( mouse _position ) {
function checkIntersects ( mouse _position ) {
let mouse _vector = mouseToThree ( ... mouse _position ) ;
let mouse _vector = mouseToThree ( ... mouse _position ) ;
raycaster . setFromCamera ( mouse _vector , camera ) ;
raycaster . setFromCamera ( mouse _vector , camera ) ;
let intersects = raycaster . intersectObject ( particlesDuplic ) ;
let intersects = raycaster . intersectObject ( particlesDuplic ) ;
@ -2577,16 +2622,16 @@ function checkIntersects(mouse_position) {
removeHighlights ( ) ;
removeHighlights ( ) ;
hideTooltip ( ) ;
hideTooltip ( ) ;
}
}
}
}
function sortIntersectsByDistanceToRay ( intersects ) {
function sortIntersectsByDistanceToRay ( intersects ) {
return _ . sortBy ( intersects , "distanceToRay" ) ;
return _ . sortBy ( intersects , "distanceToRay" ) ;
}
}
hoverContainer = new THREE . Object3D ( )
hoverContainer = new THREE . Object3D ( )
scene . add ( hoverContainer ) ;
scene . add ( hoverContainer ) ;
function highlightPoint ( datum ) {
function highlightPoint ( datum ) {
removeHighlights ( ) ;
removeHighlights ( ) ;
let geometry = new THREE . Geometry ( ) ;
let geometry = new THREE . Geometry ( ) ;
@ -2618,30 +2663,30 @@ function highlightPoint(datum) {
let point = new THREE . Points ( geometry , material ) ;
let point = new THREE . Points ( geometry , material ) ;
hoverContainer . add ( point ) ;
hoverContainer . add ( point ) ;
}
}
function removeHighlights ( ) {
function removeHighlights ( ) {
hoverContainer . remove ( ... hoverContainer . children ) ;
hoverContainer . remove ( ... hoverContainer . children ) ;
}
}
view . on ( "mouseleave" , ( ) => {
view . on ( "mouseleave" , ( ) => {
removeHighlights ( )
removeHighlights ( )
} ) ;
} ) ;
// Initial tooltip state
// Initial tooltip state
let tooltip _state = { display : "none" }
let tooltip _state = { display : "none" }
let tooltip _dimensions ;
let tooltip _dimensions ;
let tooltip _template = document . createRange ( ) . createContextualFragment ( ` <div id="tooltip" style="display: none; z-index: 2; position: absolute; pointer-events: none; font-size: 13px; width: 240px; text-align: center; line-height: 1; padding: 6px; background: white; font-family: sans-serif;">
let tooltip _template = document . createRange ( ) . createContextualFragment ( ` <div id="tooltip" style="display: none; z-index: 2; position: absolute; pointer-events: none; font-size: 13px; width: 240px; text-align: center; line-height: 1; padding: 6px; background: white; font-family: sans-serif;">
< div id = "point_tip" style = "padding: 4px; margin-bottom: 4px;" > < / d i v >
< div id = "point_tip" style = "padding: 4px; margin-bottom: 4px;" > < / d i v >
< div id = "group_tip" style = "padding: 4px;" > < / d i v >
< div id = "group_tip" style = "padding: 4px;" > < / d i v >
< / d i v > ` ) ;
< / d i v > ` ) ;
document . body . append ( tooltip _template ) ;
document . body . append ( tooltip _template ) ;
let $tooltip = document . querySelector ( '#tooltip' ) ;
let $tooltip = document . querySelector ( '#tooltip' ) ;
let $point _tip = document . querySelector ( '#point_tip' ) ;
let $point _tip = document . querySelector ( '#point_tip' ) ;
let $group _tip = document . querySelector ( '#group_tip' ) ;
let $group _tip = document . querySelector ( '#group_tip' ) ;
function updateTooltip ( ) {
function updateTooltip ( ) {
if ( all _labels [ 0 ] == undefined ) {
if ( all _labels [ 0 ] == undefined ) {
var colorScaleCat = d3 . scaleOrdinal ( ) . domain ( [ "No Category" ] ) . range ( [ "#C0C0C0" ] ) ;
var colorScaleCat = d3 . scaleOrdinal ( ) . domain ( [ "No Category" ] ) . range ( [ "#C0C0C0" ] ) ;
}
}
@ -2668,9 +2713,9 @@ function updateTooltip() {
tooltipComb = "-" ;
tooltipComb = "-" ;
}
}
$group _tip . innerText = tooltipComb ;
$group _tip . innerText = tooltipComb ;
}
}
function showTooltip ( mouse _position , datum ) {
function showTooltip ( mouse _position , datum ) {
let tooltip _width = 240 ;
let tooltip _width = 240 ;
let x _offset = tooltip _width + tooltip _width ;
let x _offset = tooltip _width + tooltip _width ;
let y _offset = 30 ;
let y _offset = 30 ;
@ -2691,13 +2736,13 @@ function showTooltip(mouse_position, datum) {
}
}
}
}
updateTooltip ( ) ;
updateTooltip ( ) ;
}
}
function hideTooltip ( ) {
function hideTooltip ( ) {
tooltip _state . display = "none" ;
tooltip _state . display = "none" ;
updateTooltip ( ) ;
updateTooltip ( ) ;
}
}
}
}
}