fixed size/color of points

master
parent c7b739a2ce
commit 82cf81699f
  1. 11
      css/style.css
  2. 2
      data/Frogs_MFCCs_s.csv
  3. 2
      data/iris.csv
  4. 2
      data/mnist.csv
  5. 2
      data/winequality-red.csv
  6. 10
      index.html
  7. 284
      js/tsne_vis.js
  8. 0
      modules/bootstrap/bootstrap.min.js
  9. 0
      modules/d3-lasso/lasso.js
  10. 6
      modules/d3-star/d3-starPlot.js
  11. 548
      modules/pca/pca.js
  12. 107
      modules/savage.toggle-switch.js

@ -173,12 +173,12 @@ cursor: default;
/* Number of Points font-size */
text.legendtitle {
font-size: 12px;
font-size: 15px;
}
/* Number of Points font-size */
text.label {
font-size: 10px;
font-size: 12px;
}
/* Styling of the ShepardHeatmap */
@ -343,6 +343,7 @@ rect {
#starPlot{
border: 1px solid grey;
margin-left:10px;
margin-top:10px;
}
.parent-row{
@ -353,10 +354,10 @@ rect {
}
#extra-information {
margin-top: 25px;
margin-top: 40px;
margin-left: 10px;
}
#kNNInfo {
margin-top: 40px;
}
margin-top: 35px;
}

@ -1,4 +1,4 @@
MFCCs_ 1,MFCCs_ 2,MFCCs_ 3,MFCCs_ 4,MFCCs_ 5,MFCCs_ 6,MFCCs_ 7,MFCCs_ 8,MFCCs_ 9,MFCCs_10,MFCCs_11,MFCCs_12,MFCCs_13,MFCCs_14,MFCCs_15,MFCCs_16,MFCCs_17,MFCCs_18,MFCCs_19,MFCCs_20,MFCCs_21,MFCCs_22,Family,Genus,name,RecordID
MFCCs_ 1,MFCCs_ 2,MFCCs_ 3,MFCCs_ 4,MFCCs_ 5,MFCCs_ 6,MFCCs_ 7,MFCCs_ 8,MFCCs_ 9,MFCCs_10,MFCCs_11,MFCCs_12,MFCCs_13,MFCCs_14,MFCCs_15,MFCCs_16,MFCCs_17,MFCCs_18,MFCCs_19,MFCCs_20,MFCCs_21,MFCCs_22,Family,Genus,Species*,RecordID
1,0.666108754271193,0.731362010250012,0.425793611387935,-0.0923903533560614,0.0753933653354942,-0.0494833973257411,0.170614714842396,0.168954621377821,-0.314493168745296,0.0619854239467194,0.516799990257242,-0.133507530774317,-0.176176752468337,0.331092083947996,0.12857630021297,-0.0992389242138077,0.0386145965840293,0.0214557656923758,-0.00986113692290599,-0.0117793910208448,-0.179735670710639,Hylidae,Hypsiboas,HypsiboasCinerascens,36
1,0.0760281160308934,0.144443042939295,0.576311051440182,0.29390383880401,0.0922434101031376,-0.182238996214759,-0.0942232472071347,0.194344811989589,0.0462358570164354,-0.166049600331633,0.245487673567843,0.269489272912798,-0.241274927740399,-0.171701734508546,0.290623995847323,0.241672194740575,-0.10567666108919,-0.186795953907457,-0.0945262400639609,0.157150935997087,0.160444712738068,Leptodactylidae,Adenomera,AdenomeraHylaedactylus,24
1,0.741352655534938,0.699044230343737,0.373693368543064,-0.0259796735805141,0.0930768239776094,-0.0281500078164973,0.163415651291332,0.181305522630704,-0.222794036190088,-0.0650675375330755,0.333053821268184,-0.113786884104537,-0.216811134295506,0.219330115203743,0.0920761821844276,-0.165208098247927,-0.0467622097447633,-0.0535053024932768,0.00381257743781609,0.0229461938607687,-0.183302045259707,Hylidae,Hypsiboas,HypsiboasCinerascens,36

Can't render this file because it is too large.

@ -1,4 +1,4 @@
"sepalLength","sepalWidth","petalLength","petalWidth","name"
"sepalLen","sepalWid","petalLen","petalWid","name*"
5.1,3.5,1.4,.2,"Setosa"
4.9,3,1.4,.2,"Setosa"
4.7,3.2,1.3,.2,"Setosa"

1 sepalLength sepalLen sepalWidth sepalWid petalLength petalLen petalWidth petalWid name name*
2 5.1 3.5 1.4 .2 Setosa
3 4.9 3 1.4 .2 Setosa
4 4.7 3.2 1.3 .2 Setosa

@ -1,4 +1,4 @@
name,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,72,193,254,213,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,62,183,203,243,253,252,253,252,142,0,0,82,102,20,0,0,0,0,0,0,0,0,0,0,0,0,0,82,254,253,254,253,254,253,254,253,234,30,92,253,255,50,0,0,0,0,0,0,0,0,0,0,0,0,0,203,253,252,253,212,131,50,50,212,233,112,253,252,233,30,0,0,0,0,0,0,0,0,0,0,0,0,52,253,254,192,41,0,0,0,0,203,254,253,254,253,41,0,0,0,0,0,0,0,0,0,0,0,0,0,10,212,253,192,41,0,0,0,0,203,253,252,253,130,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,234,253,132,10,0,0,31,213,254,253,123,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,51,232,253,131,0,0,193,252,253,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,193,253,132,213,254,253,203,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,71,252,253,252,253,212,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,173,254,253,254,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,252,253,252,253,172,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,152,253,244,162,254,253,173,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,233,212,122,0,172,252,253,91,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,254,151,0,0,0,203,254,172,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,253,151,0,0,0,81,253,252,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,254,213,82,0,0,0,214,253,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,213,252,243,162,203,162,253,252,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,223,254,253,254,253,254,192,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,172,171,253,252,253,111,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,72,193,254,213,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,62,183,203,243,253,252,253,252,142,0,0,82,102,20,0,0,0,0,0,0,0,0,0,0,0,0,0,82,254,253,254,253,254,253,254,253,234,30,92,253,255,50,0,0,0,0,0,0,0,0,0,0,0,0,0,203,253,252,253,212,131,50,50,212,233,112,253,252,233,30,0,0,0,0,0,0,0,0,0,0,0,0,52,253,254,192,41,0,0,0,0,203,254,253,254,253,41,0,0,0,0,0,0,0,0,0,0,0,0,0,10,212,253,192,41,0,0,0,0,203,253,252,253,130,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,234,253,132,10,0,0,31,213,254,253,123,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,51,232,253,131,0,0,193,252,253,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,193,253,132,213,254,253,203,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,71,252,253,252,253,212,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,173,254,253,254,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,252,253,252,253,172,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,152,253,244,162,254,253,173,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,233,212,122,0,172,252,253,91,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,254,151,0,0,0,203,254,172,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,253,151,0,0,0,81,253,252,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,254,213,82,0,0,0,214,253,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,213,252,243,162,203,162,253,252,203,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,223,254,253,254,253,254,192,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,172,171,253,252,253,111,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,160,202,53,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,104,253,232,53,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,222,253,190,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,123,253,253,148,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,77,253,253,211,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,203,254,254,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,254,253,135,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,200,254,232,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,77,249,254,162,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,219,253,244,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,49,234,254,169,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,197,253,253,95,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,110,253,253,190,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,195,253,253,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,212,253,211,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,254,254,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,75,213,253,222,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,168,255,253,150,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,168,254,253,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,116,254,158,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,196,224,192,176,124,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44,251,254,254,254,254,254,201,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,205,205,205,205,127,213,254,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,246,236,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,219,215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,182,254,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,120,240,254,243,26,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,247,254,254,253,171,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,210,225,215,254,254,206,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,6,120,246,254,98,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,139,254,195,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,194,254,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,170,254,112,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,222,254,112,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,216,254,240,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,84,214,254,254,96,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,148,117,200,232,254,254,245,139,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,254,254,254,254,254,238,65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,137,253,254,239,123,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,111,143,143,191,143,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,162,220,252,252,252,252,252,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,166,241,252,253,252,252,252,252,252,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,229,252,252,252,226,121,128,248,252,245,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,160,252,252,252,156,39,0,171,252,252,140,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44,241,252,252,187,21,0,91,243,252,233,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,252,247,73,6,0,36,246,252,251,140,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,200,252,235,60,0,162,252,252,163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,62,212,252,232,187,253,252,222,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,209,252,252,253,252,58,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,253,253,255,253,58,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,223,252,252,224,252,222,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,55,252,252,161,52,252,252,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,238,252,246,34,16,212,252,121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,113,252,252,104,0,8,193,252,121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,44,241,252,237,43,0,34,252,252,121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,160,252,252,229,122,122,235,252,252,116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,237,252,252,252,252,252,253,252,235,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,165,252,252,252,252,252,253,252,72,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,180,156,185,142,190,81,33,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

Can't render this file because it is too large.

@ -1,4 +1,4 @@
"fixed acidity";"volatile acidity";"citric acid";"residual sugar";"chlorides";"free sulfur diox";"total sulfur diox";"density";"pH";"sulphates";"alcohol";"name"
"fixed acidity";"volatile acidity";"citric acid";"residual sugar";"chlorides";"free sulfur diox";"total sulfur diox";"density";"pH";"sulphates";"alcohol";"quality*"
7.4;0.7;0;1.9;0.076;11;34;0.9978;3.51;0.56;9.4;5
7.8;0.88;0;2.6;0.098;25;67;0.9968;3.2;0.68;9.8;5
7.8;0.76;0.04;2.3;0.092;15;54;0.997;3.26;0.65;9.8;5

1 fixed acidity volatile acidity citric acid residual sugar chlorides free sulfur diox total sulfur diox density pH sulphates alcohol name quality*
2 7.4 0.7 0 1.9 0.076 11 34 0.9978 3.51 0.56 9.4 5
3 7.8 0.88 0 2.6 0.098 25 67 0.9968 3.2 0.68 9.8 5
4 7.8 0.76 0.04 2.3 0.092 15 54 0.997 3.26 0.65 9.8 5

@ -17,7 +17,7 @@
<script src='./modules/d3-annotations/d3-annotator.js'></script>
<script src="./modules/d3-tip/tip.js"></script>
<script src="./modules/d3-legend/d3-legend.min.js"></script>
<script src="./modules/savage.toggle-switch.js" type="text/javascript"></script>
<script src="./modules/d3-lasso/lasso.js"></script>
<script src="./modules/papa/papaparse.min.js"></script>
<script src="./modules/jquery/jquery.min.js"></script>
@ -26,7 +26,7 @@
<script src="./js/tsne.js"></script>
<script src="./js/checkbox.js"></script>
<script src="./js/data_form_handler.js"></script>
<script src="./lasso.js"></script>
<script src="./modules/pca/pca.js"></script>
<!-- CSS - Styling -->
<link rel="stylesheet" href="./css/style.css"/>
@ -35,7 +35,7 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<!-- Bootstrap -->
<script src="./modules/bootstrap.min.js"></script>
<script src="./modules/bootstrap/bootstrap.min.js"></script>
</head>
@ -150,8 +150,8 @@
</div>
<div class="param">
<label for="param-maxiter">Max iterations</label>
<input id="param-maxiter" type="range" min="10" max="1000" value="10", step="10">
<output for="param-maxiter" id="param-maxiter-value">10</output>
<input id="param-maxiter" type="range" min="10" max="1000" value="500", step="10">
<output for="param-maxiter" id="param-maxiter-value">500</output>
</div>
<div class="param">
<label for="param-distance">Distance metric</label>

@ -3,7 +3,7 @@
var k; var points = []; var all_fields; var pointsbeta = []; var KNNEnabled = true;
// These are the dimensions for the square shape of the main panel\
var dimensions = document.getElementById('modtSNEcanvas').offsetWidth;
var prevRightClick;
var prevRightClick; var ColorsCategorical; var Category;
// These are the dimensions for the overview panel
var dim = document.getElementById('tSNEcanvas').offsetWidth;
@ -133,6 +133,18 @@ function setLayerSche(){
d3.select("#modtSNEcanvas_svg_Schema").style("z-index", 2);
d3.select("#modtSNEcanvas").style("z-index", 1);
d3.select("#modtSNEcanvas_svg").style("z-index", 1);
let c = 0;
for (var i=0; i < points.length; i++){
points[i].selected = true;
if (points[i].starplot == true){
c = c + 1;
if (c == 1){
alert("The starplot visualization will be lost!");
}
points[i].starplot = false;
}
}
redraw(points);
click();
}
@ -250,9 +262,58 @@ function setAnnotator(){
);
animate();
var Arrayx = [];
var Arrayy = [];
var XYDistId = [];
var Arrayxy = [];
var DistanceDrawing1D = [];
var allTransformPoints = [];
var p;
var pFinal = [];
var paths;
var path;
var ArrayLimit = [];
var minimum;
var correlationResults = [];
var ArrayContainsDataFeaturesLimit = [];
// function that executes after data is successfully loaded
function init(data, results_all, fields) {
d3.selectAll("#correlation > *").remove();
d3.selectAll("#modtSNEcanvas_svg > *").remove();
d3.selectAll("#modtSNEcanvas_svg_Schema > *").remove();
d3.selectAll("#SvgAnnotator > *").remove();
d3.selectAll("#sheparheat > *").remove();
var oldcanvOver = document.getElementById('tSNEcanvas');
var contxOver = oldcanvOver.getContext('experimental-webgl');
contxOver.clear(contxOver.COLOR_BUFFER_BIT);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
d3.selectAll("#legend1 > *").remove();
d3.selectAll("#legend3 > *").remove();
d3.selectAll("#legend4 > *").remove();
lassoEnable();
Arrayx = [];
Arrayy = [];
XYDistId = [];
Arrayxy = [];
DistanceDrawing1D = [];
allTransformPoints = [];
p;
pFinal = [];
paths;
path;
ArrayLimit = [];
minimum;
correlationResults = [];
ArrayContainsDataFeaturesLimit = [];
prevRightClick = false;
step_counter = 0;
max_counter = document.getElementById("param-maxiter-value").value;
@ -277,14 +338,35 @@ function init(data, results_all, fields) {
});
ArrayContainsDataFeaturesCleared.push(object);
}
all_labels = [];
dataFeatures.filter(function(obj) {
var temp = [];
temp.push(Object.keys(obj));
for (var object in temp[0]){
if(temp[0][object].indexOf("*") != -1){
Category = temp[0][object];
return Category;
}
}
});
$("#datasetDetails").html("Number of Dimensions: " + (ArrayContainsDataFeatures[0].length - 1) + ", Number of Samples: " + final_dataset.length);
var valCategExists = 0;
for (var i=0; i<Object.keys(dataFeatures[0]).length; i++){
if (Object.keys(dataFeatures[0])[i] == Category){
valCategExists = valCategExists + 1;
}
}
$("#datasetDetails").html("Number of Dimensions: " + (Object.keys(dataFeatures[0]).length - valCategExists) + ", Number of Samples: " + final_dataset.length);
dists = computeDistances(data, document.getElementById("param-distance").value, document.getElementById("param-transform").value);
tsne.initDataDist(dists);
all_labels = [];
for(var i = 0; i < data.length; i++) {
if (final_dataset[i]["name"] != "" || final_dataset[i]["name"] != "undefined"){
all_labels[i] = final_dataset[i]["name"];
for(var i = 0; i < dataFeatures.length; i++) {
if (dataFeatures[i][Category] != "" || dataFeatures[i][Category] != "undefined"){
all_labels[i] = dataFeatures[i][Category];
}
else{
all_labels[i];
@ -532,7 +614,7 @@ d3.tsv("./modules/heat.tsv").then(function(data) {
var maxNum = Math.round(d3.max(data,function(d){ return d.value; }));
var minNum = Math.round(d3.min(data,function(d){ return d.value; }));
var colors = ["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"];
var colors = ['#ffffff','#f0f0f0','#d9d9d9','#bdbdbd','#969696','#737373','#525252','#252525','#000000'];
let calcStep = (maxNum-minNum)/colors.length;
var colorScale = d3.scaleLinear()
.domain(d3.range(0, maxNum+calcStep,calcStep))
@ -657,41 +739,8 @@ function resize(canvas) {
}
}
var Arrayx = [];
var Arrayy = [];
var XYDistId = [];
var Arrayxy = [];
var DistanceDrawing1D = [];
var allTransformPoints = [];
var p;
var pFinal = [];
var paths;
var path;
var ArrayLimit = [];
var minimum;
var correlationResults = [];
var ArrayContainsDataFeaturesLimit = [];
function OverviewtSNE(points){
d3.selectAll("#correlation > *").remove();
d3.selectAll("#modtSNEcanvas_svg > *").remove();
lassoEnable();
d3.selectAll("#modtSNEcanvas_svg_Schema > *").remove();
d3.selectAll("#SvgAnnotator > *").remove();
Arrayx = [];
Arrayy = [];
XYDistId = [];
Arrayxy = [];
DistanceDrawing1D = [];
allTransformPoints = [];
p;
pFinal = [];
paths;
path;
ArrayLimit = [];
minimum;
correlationResults = [];
ArrayContainsDataFeaturesLimit = [];
var canvas = document.getElementById('tSNEcanvas');
gl = canvas.getContext('experimental-webgl');
@ -700,11 +749,14 @@ function OverviewtSNE(points){
alert('Unable to initialize WebGL. Your browser or machine may not support it.');
return;
}
ColorsCategorical = ['#a6cee3','#fb9a99','#b2df8a','#33a02c','#1f78b4','#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a'];
if (all_labels[0] == undefined){
var colorScale = d3.scaleOrdinal(d3.schemeCategory10).domain(["No Category"]).range(["#0000ff"]);
var colorScale = d3.scaleOrdinal().domain(["No Category"]).range(["#C0C0C0"]);
}
else{
var colorScale = d3.scaleOrdinal(d3.schemeCategory10).domain(all_labels);
var colorScale = d3.scaleOrdinal().domain(all_labels).range(ColorsCategorical);
}
d3.select("#legend3").select("svg").remove();
var svg = d3.select("#legend3").append("svg");
@ -755,7 +807,7 @@ function OverviewtSNE(points){
singleCol = colval.b/255;
colors.push(singleCol);
}else{
let colval = d3.rgb(colorScale(points[i].name));
let colval = d3.rgb(colorScale(points[i][Category]));
singleCol = colval.r/255;
colors.push(singleCol);
singleCol = colval.g/255;
@ -1172,6 +1224,7 @@ function CalculateCorrel(){
var SignStore = [];
correlationResults = [];
const arrayColumn = (arr, n) => arr.map(x => x[n]);
for (var temp = 0; temp < ArrayContainsDataFeaturesLimit[0].length - 2; temp++) {
var tempData = new Array(
@ -1181,7 +1234,7 @@ function CalculateCorrel(){
if (isNaN(pearsonCorrelation(tempData, 0, 1))) {
} else{
SignStore.push([temp, pearsonCorrelation(tempData, 0, 1)]);
correlationResults.push(["Dimension "+temp, Math.abs(pearsonCorrelation(tempData, 0, 1))]);
correlationResults.push([Object.keys(dataFeatures[0])[temp] + " (" + temp + ")", Math.abs(pearsonCorrelation(tempData, 0, 1))]);
}
}
correlationResults = correlationResults.sort(
@ -1265,6 +1318,8 @@ function drawBarChart(){
.tickSize(0)
.outerTickSize(0);
//Add group for the y axis
mainGroup.append("g")
.attr("class", "y axis")
@ -1658,7 +1713,6 @@ function mapOrder(array, order, key) {
.on('mousemove', function() {
x = d3.event.pageX;
y = d3.event.pageY;
console.log( d3.event.pageX, d3.event.pageY ) // log the mouse x,y position
});
@ -1736,7 +1790,7 @@ height = Math.min(width, window.innerHeight - margin.top - margin.bottom);
RadarChart("#starPlot", wrapData, colors, IDS, radarChartOptions);
function BetatSNE(points){
selectedPoints = [];
var findNearestTable = [];
for (let m=0; m<points.length; m++){
@ -1744,6 +1798,7 @@ function BetatSNE(points){
selectedPoints.push(points[m]);
}
}
if (KNNEnabled == true && selectedPoints.length != 0){
var distsFull = dists;
var dists2dFull = dists2d;
@ -1801,7 +1856,6 @@ function BetatSNE(points){
if (k == maxKNN){
// temporary array holds objects with position and sort-value
indices[i] = dists[i].map(function(el, i) {
return [ i, el ];
@ -1909,12 +1963,15 @@ function BetatSNE(points){
});
}
d3.select("#starPlot").selectAll('g').remove();
var coun = 0;
for (var i=0; i < selectedPoints.length; i++){
if (selectedPoints[i].starplot == true){
coun = coun + 1;
}
}
if(selectedPoints.length <= 10){
if(selectedPoints.length <= 10 && coun > 0){
var FeatureWise = [];
@ -1925,32 +1982,60 @@ function BetatSNE(points){
}
}
}
var sum = new Array(Object.values(dataFeatures[0]).length).fill(0);
var max = [];
var min = [];
var vectors = [];
var FeatureWiseSlicedArray = [];
for (var j=0; j<Object.values(dataFeatures[0]).length; j++){
var FeatureWiseSliced = FeatureWise.slice(0+(j*dataFeatures.length),dataFeatures.length+j*dataFeatures.length);
if (FeatureWiseSliced != ""){
FeatureWiseSlicedArray.push(FeatureWiseSliced);
}
max[j] = FeatureWiseSliced[0];
min[j] = FeatureWiseSliced[0];
for (var i=0; i<FeatureWiseSliced.length; i++){
sum[j] = FeatureWiseSliced[i] + sum[j];
if (max[j] < FeatureWiseSliced[i]){
max[j] = FeatureWiseSliced[i];
}
if (min[j] > FeatureWiseSliced[i]){
min[j] = FeatureWiseSliced[i];
}
}
}
var vectors = PCA.getEigenVectors(ArrayContainsDataFeaturesCleared);
var PCAResults = PCA.computeAdjustedData(ArrayContainsDataFeaturesCleared,vectors[0]);
var PCASelVec = [];
PCASelVec = PCAResults.selectedVectors[0];
var len = PCASelVec.length;
var indices = new Array(len);
for (var i = 0; i < len; ++i) indices[i] = i;
indices = indices.sort(function (a, b) { return PCASelVec[a] < PCASelVec[b] ? -1 : PCASelVec[a] > PCASelVec[b] ? 1 : 0; });
//const list = dataFeatures.sort((a,b) => a.index - b.index).map((dataFeatures, index, array) => dataFeatures[Category])
var wrapData = [];
var IDS = [];
for (var i=0; i<selectedPoints.length; i++){
var data = [];
for (var j=0; j< Object.keys(dataFeatures[selectedPoints[i].id]).length; j++){
if (!isNaN(Object.values(dataFeatures[i])[j])){
if (Object.keys(dataFeatures[i])[j] == "name") {
} else{
data.push({axis:Object.keys(dataFeatures[i])[j],value:Math.abs(Object.values(dataFeatures[i])[j]*100/sum[j])});
if (!isNaN(Object.values(dataFeatures[selectedPoints[i].id])[j])){
for (m=0; m < len; m++){
if (indices[m] == j){
if (Object.keys(dataFeatures[selectedPoints[i].id])[m] == Category) {
} else{
data.push({axis:Object.keys(dataFeatures[selectedPoints[i].id])[m],value:Math.abs((Object.values(dataFeatures[selectedPoints[i].id])[m] - min[m])/(max[m] - min[m]))});
}
}
}
}
}
}
wrapData.push(data);
IDS.push(selectedPoints[i].id);
}
}
//////////////////////////////////////////////////////////////
//////////////////// Draw the Chart //////////////////////////
//////////////////////////////////////////////////////////////
@ -1985,10 +2070,9 @@ function BetatSNE(points){
var maxSize1 = (d3.max(final_dataset,function(d){ return d.cost; }));
var minSize1 = (d3.min(final_dataset,function(d){ return d.cost; }));
var rscale1 = d3.scaleLinear()
.domain([minSize1, maxSize1])
.range([5,10]);
.range([3,10]);
var colorScale = d3.scaleLinear()
.domain(d3.range(0, max+calcStep, calcStep))
@ -2024,10 +2108,9 @@ var min = (d3.min(final_dataset,function(d){ return d.cost; }));
var maxSize2 = (d3.max(final_dataset,function(d){ return d.beta; }));
var minSize2 = (d3.min(final_dataset,function(d){ return d.beta; }));
var rscale2 = d3.scaleLinear()
.domain([minSize2, maxSize2])
.range([5,10]);
.range([3,10]);
var colorbrewer = ["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"];
var calcStep = (max-min)/9;
@ -2098,7 +2181,7 @@ var circle_sprite= new THREE.TextureLoader().load(
"./textures/circle-sprite.png"
)
let pointsGeometry = new THREE.Geometry();
clearThree(scene);
@ -2107,12 +2190,12 @@ var limitdist = document.getElementById("param-lim-value").value;
limitdist = parseFloat(limitdist).toFixed(1);
let pointsMaterial = [];
let factorPlusSize = [];
let factorPlusSize;
let pointsGeometry = [];
for (var i=0; i<points.length; i++) {
pointsGeometry[i] = new THREE.Geometry();
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[i].vertices.push(vertex);
if (points[i].selected == false){
var color = new THREE.Color("rgb(211, 211, 211)");
} else if (points[i].DimON != null) {
@ -2139,28 +2222,29 @@ for (var i=0; i<points.length; i++) {
}
if (ColSizeSelector == "color") {
let sizePoint = rscale1(points[i].cost);
factorPlusSize[i] = limitdist * sizePoint;
pointsGeometry.colors.push(color);
factorPlusSize = limitdist * sizePoint;
pointsGeometry[i].colors.push(color);
pointsMaterial[i] = new THREE.PointsMaterial({
size: factorPlusSize[i],
sizeAttenuation: false,
size: Number(factorPlusSize.toFixed(1)),
vertexColors: THREE.VertexColors,
map: circle_sprite,
transparent: true
});
} else{
let sizePoint = rscale2(points[i].beta);
factorPlusSize[i] = limitdist * sizePoint;
pointsGeometry.colors.push(color);
factorPlusSize = limitdist * sizePoint;
pointsGeometry[i].colors.push(color);
pointsMaterial[i] = new THREE.PointsMaterial({
size: factorPlusSize[i],
sizeAttenuation: false,
size: Number(factorPlusSize.toFixed(1)),
vertexColors: THREE.VertexColors,
map: circle_sprite,
transparent: true
});
}
var particles = new THREE.Points(pointsGeometry, pointsMaterial[i]);
console.log(Number(factorPlusSize.toFixed(1)));
var particles = new THREE.Points(pointsGeometry[i], pointsMaterial[i]);
scene.add(particles);
}
@ -2346,13 +2430,13 @@ function highlightPoint(datum) {
);
if (all_labels[0] == undefined){
var colorScaleCat = d3.scaleOrdinal(d3.schemeCategory10).domain(["No Category"]).range(["#0000ff"]);
var colorScaleCat = d3.scaleOrdinal().domain(["No Category"]).range(["#C0C0C0"]);
}
else{
var colorScaleCat = d3.scaleOrdinal(d3.schemeCategory10).domain(all_labels);
var colorScaleCat = d3.scaleOrdinal().domain(all_labels).range(ColorsCategorical);
}
geometry.colors = [ new THREE.Color(colorScaleCat(datum.name)) ];
geometry.colors = [ new THREE.Color(colorScaleCat(datum[Category])) ];
let material = new THREE.PointsMaterial({
size: 26,
@ -2389,17 +2473,31 @@ let $group_tip = document.querySelector('#group_tip');
function updateTooltip() {
if (all_labels[0] == undefined){
var colorScaleCat = d3.scaleOrdinal(d3.schemeCategory10).domain(["No Category"]).range(["#0000ff"]);
var colorScaleCat = d3.scaleOrdinal().domain(["No Category"]).range(["#C0C0C0"]);
}
else{
var colorScaleCat = d3.scaleOrdinal(d3.schemeCategory10).domain(all_labels);
var colorScaleCat = d3.scaleOrdinal().domain(all_labels).range(ColorsCategorical);
}
$tooltip.style.display = tooltip_state.display;
$tooltip.style.left = tooltip_state.left + 'px';
$tooltip.style.top = tooltip_state.top + 'px';
$point_tip.innerText = tooltip_state.name;
$point_tip.innerText = tooltip_state[Category];
$point_tip.style.background = colorScaleCat(tooltip_state.color);
$group_tip.innerText = `Data set's features: ${tooltip_dimensions}`;
var tooltipComb = [];
tooltipComb = "Data set's features: " + "\n";
if (tooltip_dimensions){
for (var i=0; i<tooltip_dimensions[0].length; i++){
if (tooltip_dimensions[0][i][0] == Category){
} else{
tooltipComb = tooltipComb + tooltip_dimensions[0][i];
tooltipComb = tooltipComb + "\n";
}
}
} else{
tooltipComb = "-";
}
$group_tip.innerText = tooltipComb;
}
function showTooltip(mouse_position, datum) {
@ -2410,18 +2508,16 @@ function showTooltip(mouse_position, datum) {
tooltip_state.left = mouse_position[0] + x_offset;
tooltip_state.top = mouse_position[1] + y_offset;
if (all_labels[0] == undefined){
tooltip_state.name = datum.id;
tooltip_state[Category] = "Point ID: " + datum.id;
tooltip_state.color = datum.id;
} else{
tooltip_state.name = datum.name + " (" + datum.id + ")";
tooltip_state.color = datum.name;
tooltip_state[Category] = datum[Category] + " (Point ID: " + datum.id + ")";
tooltip_state.color = datum[Category];
}
tooltip_dimensions = [];
for (var i=0; i < ArrayContainsDataFeaturesCleared.length; i++){
for (var i=0; i < dataFeatures.length - 1; i++){
if (datum.id == i){
for (var j=0; j < ArrayContainsDataFeaturesCleared[i].length; j++){
tooltip_dimensions.push(ArrayContainsDataFeaturesCleared[i][j]);
}
tooltip_dimensions.push(Object.entries(dataFeatures[i]));
}
}
updateTooltip();

@ -11,7 +11,7 @@ function RadarChart(id, data, color, IDS, options) {
h: 600, //Height of the circle
margin: {top: 20, right: 20, bottom: 20, left: 20}, //The margins of the SVG
levels: 3, //How many levels or inner circles should there be drawn
maxValue: 0, //What is the value that the biggest circle will represent
maxValue: 1, //What is the value that the biggest circle will represent
labelFactor: 1.3, //How much farther than the radius of the outer circle should the labels be placed
wrapWidth: 60, //The number of pixels after which a label needs to be given a new line
opacityArea: 0.35, //The opacity of the area of the blob
@ -34,7 +34,7 @@ function RadarChart(id, data, color, IDS, options) {
var allAxis = (data[0].map(function(i, j){return i.axis})), //Names of each axis
total = allAxis.length, //The number of different axes
radius = Math.min(cfg.w/2, cfg.h/2), //Radius of the outermost circle
Format = d3v3.format('%'), //Percentage formatting
Format = d3v3.format('.2f'), //Percentage formatting
angleSlice = Math.PI * 2 / total; //The width in radians of each "slice"
//Scale for the radius
@ -129,7 +129,7 @@ function RadarChart(id, data, color, IDS, options) {
.attr("text-anchor", "middle")
.attr("dy", "0.35em")
.attr("x", function(d, i){ return rScale(maxValue * cfg.labelFactor) * Math.cos(angleSlice*i - Math.PI/2); })
.attr("y", function(d, i){ return rScale(maxValue * cfg.labelFactor) * Math.sin(angleSlice*i - Math.PI/2) - 16; })
.attr("y", function(d, i){ return rScale(maxValue * cfg.labelFactor) * Math.sin(angleSlice*i - Math.PI/2); })
.text(function(d){return d})
.call(wrap, cfg.wrapWidth);

@ -0,0 +1,548 @@
var PCA = (function () {
/**
* The first step is to subtract the mean and center data
*
* @param {Array} matrix - data in an mXn matrix format
* @returns
*/
function computeDeviationMatrix(matrix) {
var unit = unitSquareMatrix(matrix.length);
return subtract(matrix, scale(multiply(unit, matrix), 1 / matrix.length));
}
/**
* Computes variance from deviation
*
* @param {Array} deviation - data minus mean as calculated from computeDeviationMatrix
* @returns
*/
function computeDeviationScores(deviation) {
var devSumOfSquares = multiply(transpose(deviation), deviation);
return devSumOfSquares;
}
/**
* Calculates the var covar square matrix using either population or sample
*
* @param {Array} devSumOfSquares
* @param {boolean} sample - true/false whether data is from sample or not
* @returns
*/
function computeVarianceCovariance(devSumOfSquares, sample) {
var varianceCovariance;
if (sample)
varianceCovariance = scale(devSumOfSquares, 1 / (devSumOfSquares.length - 1));
else
varianceCovariance = scale(devSumOfSquares, 1 / (devSumOfSquares.length));
return varianceCovariance;
}
/**
* Matrix is the deviation sum of squares as computed earlier
*
* @param {Array} matrix - output of computeDeviationScores
* @returns
*/
function computeSVD(matrix) {
var result = svd(matrix);
var eigenvectors = result.U;
var eigenvalues = result.S;
var results = eigenvalues.map(function (value, i) {
var obj = {};
obj.eigenvalue = value;
obj.vector = eigenvectors.map(function (vector, j) {
return -1 * vector[i]; //HACK prevent completely negative vectors
});
return obj;
});
return results;
}
/**
* Get reduced dataset after removing some dimensions
*
* @param {Array} data - initial matrix started out with
* @param {rest} vectors - eigenvectors selected as part of process
* @returns
*/
function computeAdjustedData(data, ...vectorObjs) {
//FIXME no need to transpose vectors since they're already in row normal form
var vectors = vectorObjs.map(function(v){return v.vector});
var matrixMinusMean = computeDeviationMatrix(data);
var adjustedData = multiply(vectors, transpose(matrixMinusMean));
var unit = unitSquareMatrix(data.length);
var avgData = scale(multiply(unit, data), -1 / data.length); //NOTE get the averages to add back
var formattedAdjustData = formatData(adjustedData, 2);
return {
adjustedData: adjustedData,
formattedAdjustedData: formattedAdjustData,
avgData: avgData,
selectedVectors: vectors
};
}
/**
* Get original data set from reduced data set (decompress)
* @param {*} adjustedData = formatted or unformatted adjusted data
* @param {*} vectors = selectedVectors
* @param {*} avgData = avgData
*/
function computeOriginalData(adjustedData, vectors, avgData) {
var originalWithoutMean = transpose(multiply(transpose(vectors), adjustedData));
var originalWithMean = subtract(originalWithoutMean, avgData);
var formattedData = formatData(originalWithMean, 2);
return {
originalData: originalWithMean,
formattedOriginalData: formattedData
}
}
/**
* Get percentage explained, or loss
* @param {*} vectors
* @param {*} selected
*/
function computePercentageExplained(vectors, ...selected) {
var total = vectors.map(function (v) {
return v.eigenvalue
}).reduce(function (a, b) {
return a + b;
});
var explained = selected.map(function (v) {
return v.eigenvalue
}).reduce(function (a, b) {
return a + b;
});
return (explained / total);
}
function getEigenVectors(data) {
return computeSVD(computeVarianceCovariance(computeDeviationScores(computeDeviationMatrix(data)), false));
}
function analyseTopResult(data) {
var eigenVectors = getEigenVectors(data);
var sorted = eigenVectors.sort(function (a, b) {
return b.eigenvalue - a.eigenvalue;
});
console.log('Sorted Vectors', sorted);
var selected = sorted[0].vector;
return computeAdjustedData(data, selected);
}
function formatData(data, precision) {
var TEN = Math.pow(10, precision || 2);
return data.map(function (d, i) {
return d.map(function (n) {
return Math.round(n * TEN) / TEN;
})
})
}
/**
* Multiplies AxB, where A and B are matrices of nXm and mXn dimensions
* @param {} a
* @param {*} b
*/
function multiply(a, b) {
if (!a[0] || !b[0] || !a.length || !b.length) {
throw new Error('Both A and B should be matrices');
}
if (b.length !== a[0].length) {
throw new Error('Columns in A should be the same as the number of rows in B');
}
var product = [];
for (var i = 0; i < a.length; i++) {
product[i] = []; //initialize a new row
for (var j = 0; j < b[0].length; j++) {
for (var k = 0; k < a[0].length; k++) {
(product[i])[j] = !!(product[i])[j] ? (product[i])[j] + (a[i])[k] * (b[k])[j] : (a[i])[k] * (b[k])[j];
}
}
}
return product;
}
/**
* Utility function to subtract matrix b from a
*
* @param {any} a
* @param {any} b
* @returns
*/
function subtract(a, b) {
if (!(a.length === b.length && a[0].length === b[0].length))
throw new Error('Both A and B should have the same dimensions');
var result = [];
for (var i = 0; i < a.length; i++) {
result[i] = [];
for (var j = 0; j < b[0].length; j++) {
(result[i])[j] = (a[i])[j] - (b[i])[j];
}
}
return result;
}
/**
* Multiplies a matrix into a factor
*
* @param {any} matrix
* @param {any} factor
* @returns
*/
function scale(matrix, factor) {
var result = [];
for (var i = 0; i < matrix.length; i++) {
result[i] = [];
for (var j = 0; j < matrix[0].length; j++) {
(result[i])[j] = (matrix[i])[j] * factor;
}
}
return result;
}
/**
* Generates a unit square matrix
* @param {*} rows = number of rows to fill
*/
function unitSquareMatrix(rows) {
var result = [];
for (var i = 0; i < rows; i++) {
result[i] = [];
for (var j = 0; j < rows; j++) {
(result[i])[j] = 1;
}
}
return result;
}
/**
* Transposes a matrix, converts rows to columns
* @param {*} matrix
*/
function transpose(matrix) {
var operated = clone(matrix);
return operated[0].map(function (m, c) {
return matrix.map(function (r) {
return r[c];
});
});
}
/**
* Deep Clones a matrix
* @param {*} arr
*/
function clone(arr) {
var string = JSON.stringify(arr);
var result = JSON.parse(string);
return result;
}
/**
* Compute the thin SVD from G. H. Golub and C. Reinsch, Numer. Math. 14, 403-420 (1970)
* From the Numeric JS Implementation Copyright (C) 2011 by Sébastien Loisel
* The C implementation from which this has been taken may be found here: http://www.public.iastate.edu/~dicook/JSS/paper/code/svd.c
* @param {*} A = m*n matrix
*/
function svd(A) {
var temp;
var prec = Math.pow(2, -52) // assumes double prec
var tolerance = 1.e-64 / prec;
var itmax = 50;
var c = 0;
var i = 0;
var j = 0;
var k = 0;
var l = 0;
var u = clone(A);
var m = u.length;
var n = u[0].length;
if (m < n) throw "Need more rows than columns"
var e = new Array(n); //vector1
var q = new Array(n); //vector2
for (i = 0; i < n; i++) e[i] = q[i] = 0.0;
var v = rep([n, n], 0);
function pythag(a, b) {
a = Math.abs(a)
b = Math.abs(b)
if (a > b)
return a * Math.sqrt(1.0 + (b * b / a / a))
else if (b == 0.0)
return a
return b * Math.sqrt(1.0 + (a * a / b / b))
}
//rep function
function rep(s, v, k) {
if (typeof k === "undefined") {
k = 0;
}
var n = s[k],
ret = Array(n),
i;
if (k === s.length - 1) {
for (i = n - 2; i >= 0; i -= 2) {
ret[i + 1] = v;
ret[i] = v;
}
if (i === -1) {
ret[0] = v;
}
return ret;
}
for (i = n - 1; i >= 0; i--) {
ret[i] = rep(s, v, k + 1);
}
return ret;
}
//Householder's reduction to bidiagonal form
var f = 0.0;
var g = 0.0;
var h = 0.0;
var x = 0.0;
var y = 0.0;
var z = 0.0;
var s = 0.0;
for (i = 0; i < n; i++) {
e[i] = g; //vector
s = 0.0; //sum
l = i + 1; //stays i+1
for (j = i; j < m; j++)
s += (u[j][i] * u[j][i]);
if (s <= tolerance)
g = 0.0;
else {
f = u[i][i];
g = Math.sqrt(s);
if (f >= 0.0) g = -g;
h = f * g - s
u[i][i] = f - g;
for (j = l; j < n; j++) {
s = 0.0
for (k = i; k < m; k++)
s += u[k][i] * u[k][j]
f = s / h
for (k = i; k < m; k++)
u[k][j] += f * u[k][i]
}
}
q[i] = g
s = 0.0
for (j = l; j < n; j++)
s = s + u[i][j] * u[i][j]
if (s <= tolerance)
g = 0.0
else {
f = u[i][i + 1]
g = Math.sqrt(s)
if (f >= 0.0) g = -g
h = f * g - s
u[i][i + 1] = f - g;
for (j = l; j < n; j++) e[j] = u[i][j] / h
for (j = l; j < m; j++) {
s = 0.0
for (k = l; k < n; k++)
s += (u[j][k] * u[i][k])
for (k = l; k < n; k++)
u[j][k] += s * e[k]
}
}
y = Math.abs(q[i]) + Math.abs(e[i])
if (y > x)
x = y
}
// accumulation of right hand transformations
for (i = n - 1; i != -1; i += -1) {
if (g != 0.0) {
h = g * u[i][i + 1]
for (j = l; j < n; j++)
v[j][i] = u[i][j] / h //u is array, v is square of columns
for (j = l; j < n; j++) {
s = 0.0
for (k = l; k < n; k++)
s += u[i][k] * v[k][j]
for (k = l; k < n; k++)
v[k][j] += (s * v[k][i])
}
}
for (j = l; j < n; j++) {
v[i][j] = 0;
v[j][i] = 0;
}
v[i][i] = 1;
g = e[i]
l = i
}
// accumulation of left hand transformations
for (i = n - 1; i != -1; i += -1) {
l = i + 1
g = q[i]
for (j = l; j < n; j++)
u[i][j] = 0;
if (g != 0.0) {
h = u[i][i] * g
for (j = l; j < n; j++) {
s = 0.0
for (k = l; k < m; k++) s += u[k][i] * u[k][j];
f = s / h
for (k = i; k < m; k++) u[k][j] += f * u[k][i];
}
for (j = i; j < m; j++) u[j][i] = u[j][i] / g;
} else
for (j = i; j < m; j++) u[j][i] = 0;
u[i][i] += 1;
}
// diagonalization of the bidiagonal form
prec = prec * x
for (k = n - 1; k != -1; k += -1) {
for (var iteration = 0; iteration < itmax; iteration++) { // test f splitting
var test_convergence = false
for (l = k; l != -1; l += -1) {
if (Math.abs(e[l]) <= prec) {
test_convergence = true
break
}
if (Math.abs(q[l - 1]) <= prec)
break
}
if (!test_convergence) { // cancellation of e[l] if l>0
c = 0.0
s = 1.0
var l1 = l - 1
for (i = l; i < k + 1; i++) {
f = s * e[i]
e[i] = c * e[i]
if (Math.abs(f) <= prec)
break
g = q[i]
h = pythag(f, g)
q[i] = h
c = g / h
s = -f / h
for (j = 0; j < m; j++) {
y = u[j][l1]
z = u[j][i]
u[j][l1] = y * c + (z * s)
u[j][i] = -y * s + (z * c)
}
}
}
// test f convergence
z = q[k]
if (l == k) { //convergence
if (z < 0.0) { //q[k] is made non-negative
q[k] = -z
for (j = 0; j < n; j++)
v[j][k] = -v[j][k]
}
break //break out of iteration loop and move on to next k value
}
if (iteration >= itmax - 1)
throw 'Error: no convergence.'
// shift from bottom 2x2 minor
x = q[l]
y = q[k - 1]
g = e[k - 1]
h = e[k]
f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y)
g = pythag(f, 1.0)
if (f < 0.0)
f = ((x - z) * (x + z) + h * (y / (f - g) - h)) / x
else
f = ((x - z) * (x + z) + h * (y / (f + g) - h)) / x
// next QR transformation
c = 1.0
s = 1.0
for (i = l + 1; i < k + 1; i++) {
g = e[i]
y = q[i]
h = s * g
g = c * g
z = pythag(f, h)
e[i - 1] = z
c = f / z
s = h / z
f = x * c + g * s
g = -x * s + g * c
h = y * s
y = y * c
for (j = 0; j < n; j++) {
x = v[j][i - 1]
z = v[j][i]
v[j][i - 1] = x * c + z * s
v[j][i] = -x * s + z * c
}
z = pythag(f, h)
q[i - 1] = z
c = f / z
s = h / z
f = c * g + s * y
x = -s * g + c * y
for (j = 0; j < m; j++) {
y = u[j][i - 1]
z = u[j][i]
u[j][i - 1] = y * c + z * s
u[j][i] = -y * s + z * c
}
}
e[l] = 0.0
e[k] = f
q[k] = x
}
}
for (i = 0; i < q.length; i++)
if (q[i] < prec) q[i] = 0
//sort eigenvalues
for (i = 0; i < n; i++) {
for (j = i - 1; j >= 0; j--) {
if (q[j] < q[i]) {
c = q[j]
q[j] = q[i]
q[i] = c
for (k = 0; k < u.length; k++) {
temp = u[k][i];
u[k][i] = u[k][j];
u[k][j] = temp;
}
for (k = 0; k < v.length; k++) {
temp = v[k][i];
v[k][i] = v[k][j];
v[k][j] = temp;
}
i = j
}
}
}
return {
U: u,
S: q,
V: v
}
}
return {
computeDeviationScores: computeDeviationScores,
computeDeviationMatrix: computeDeviationMatrix,
computeSVD: computeSVD,
computePercentageExplained: computePercentageExplained,
computeOriginalData: computeOriginalData,
computeVarianceCovariance: computeVarianceCovariance,
computeAdjustedData: computeAdjustedData,
getEigenVectors: getEigenVectors,
analyseTopResult: analyseTopResult,
transpose: transpose,
multiply: multiply,
clone: clone,
scale: scale
}
})();
if(typeof module !== 'undefined')
module.exports = PCA;

@ -1,107 +0,0 @@
/*
* Copyright (C) 2015 Jose F. Maldonado
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// Verify if the namespace is not already defined.
if(typeof SaVaGe !== 'object') SaVaGe = {};
/**
* Creates a SVG element representing a toggle switch.
*
* The parameter must be an object with the following attributes:
* 'container' (a selector of the element where the element must be appended),
* 'value' (a boolean indicating the initial value of the switch, by default 'false'),
* 'height' (a number indicating the height, in pixels, of the element, by default 50),
* 'width' (a number indicating the width, in pixels, of the element, by default 80),
* 'radius' (a number indicating the radius of the lever),
* 'border' (a number indicating the width, in pixels, the distance between the element background and the switch's button, by default 5),
* 'duration' (a number indicating the number of milliseconds that the toggle animation must last, by default 250),
* 'colors' (an object with the attributes 'backLeft', 'foreLeft', 'backRight' and 'foreRight' indicating the colors of the element in each state) and
* 'onChange' (a callback function which is invoked every time that the element is clicked).
*
* The object returned by this function contains the methods:
* 'svg', and instance of the SVG object created with D3.js,
* 'getValue()', for get the current state of the switch,
* 'serValue(newVal)', for change the state of the switch and
* 'remove()', for remove the element from the document.
*
* @param {object} params An collection of values for customize the element.
* @returns {object} An object with methods for manipulate the element.
*/
SaVaGe.ToggleSwitch = function(params) {
// Verify parameters.
if(typeof params !== 'object') params = {};
if(typeof params.container !== 'string') params.container = "body";
if(typeof params.value !== 'boolean') params.value = false;
if(typeof params.height !== 'number') params.height = 50;
if(typeof params.width !== 'number' || params.width < params.height) params.width = parseInt(params.height*1.6, 10);
if(typeof params.radius !== 'number') params.radius = params.height/2 - 4;
if(typeof params.duration !== 'number') params.duration = 250;
if(typeof params.colors !== 'object') params.colors = {};
if(params.colors.backLeft === undefined) params.colors.backLeft = "lightgray";
if(params.colors.foreLeft === undefined) params.colors.foreLeft = "white";
if(params.colors.backRight === undefined) params.colors.backRight = "#88f";
if(params.colors.foreRight === undefined) params.colors.foreRight = "white";
// Define internal variables.
var atRight = params.value;
// Calculate SVG dimensions and position offset.
var svgHeight = params.height;
var svgWidth = params.width;
var offsetX = 0;
var offsetY = 0;
if(params.radius*2 > params.height) {
svgHeight = params.radius*2;
svgWidth = parseInt(params.width + (params.radius*2 - params.height), 10);
offsetX = parseInt((svgWidth - params.width)/2, 10);
offsetY = parseInt((svgWidth - params.width)/2, 10);
}
// Create widget.
var svg = d3.select(params.container).append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight)
.style("cursor", "pointer");
var rect = svg.append("rect")
.attr("x", offsetX)
.attr("y", offsetY)
.attr("rx", params.height/2)
.attr("ry", params.height/2)
.style("fill", atRight? params.colors.backRight : params.colors.backLeft)
.attr("width", params.width)
.attr("height", params.height);
var circle = svg.append("circle")
.attr("cx", (atRight? (params.width-params.height/2) : (params.height/2)) + offsetX)
.attr("cy", params.height/2 + offsetY)
.attr("r", params.radius)
.style("fill", atRight? params.colors.foreRight : params.colors.foreLeft);
// Define internal functions.
var setAtRight = function(newValue) {
atRight = newValue;
circle.transition().duration(params.duration)
.attr("cx", (atRight? (params.width-params.height/2) : (params.height/2)) + offsetX)
.style("fill", atRight? params.colors.foreRight : params.colors.foreLeft);
rect.transition().duration(params.duration).style("fill", atRight? params.colors.backRight : params.colors.backLeft);
};
// Define result's object.
var res = {
'svg' : svg,
'getValue': function() { return atRight; },
'setValue': setAtRight,
'remove': function() { svg.remove(); }
};
// Define click listener.
svg.on('click', function(data, index){
setAtRight(!atRight);
if(typeof params.onChange === 'function') params.onChange(res);
});
return res;
};
Loading…
Cancel
Save