Skip to content

Instantly share code, notes, and snippets.

@alex-r-bigelow
Last active August 15, 2017 23:08
Show Gist options
  • Save alex-r-bigelow/bce2174cf2ed4a9efd93e65e5d1956cc to your computer and use it in GitHub Desktop.
Save alex-r-bigelow/bce2174cf2ed4a9efd93e65e5d1956cc to your computer and use it in GitHub Desktop.
tool-modality-attributes-and-pca
license: MIT
height: 1500
scrolling: no
border: yes
Modality Usability Threshold Expressiveness Ceiling Number of Tasks Supported Editing vs Starting From Scratch Separation From the Graphics Optimized for Algorithmic vs Immediate Tasks PCA 1 PCA 2
drawing tools 1 4 1 2 2 2 2.5401611 -1.95837756
direct manipulation-based tools 2 1 0 1 2 1 1.70458815 0.61036012
GUI-based tools 0 0 0 0 1 0 0.57795806 2.33751476
grammars 3 2 0 0 0 0 -1.09200032 1.20664758
libraries 4 3 2 1 0 0 -1.48451323 -1.35504455
programming languages 5 5 1 0 0 0 -2.24619376 -0.84110035
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>Tool modalities</title>
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab:700" rel="stylesheet">
<link type="text/css" rel="stylesheet" href="style.css"/>
</head>
<body>
<div id="container"></div>
<script src="http://d3js.org/d3.v4.min.js"></script>
<script src="script.js"></script>
</body>
</html>
import numpy as np
from sklearn.decomposition import PCA
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import scale
%matplotlib inline
#Load data set
data = pd.read_csv('data.csv')
#convert it to numpy arrays
X=data.values[:,1:7]
print 'Raw data:\n', X, '\n'
#Scaling the values
X = scale(X)
pca = PCA(n_components=2)
pca.fit(X)
print 'Components:\n', pca.components_, '\n'
newCoords = pca.transform(X)
print 'Transformed Coordinates:\n', newCoords, '\n'
#The amount of variance that each PC explains
var = pca.explained_variance_ratio_
#Cumulative Variance explains
var1 = np.cumsum(np.round(pca.explained_variance_ratio_, decimals=4)*100)
plt.plot(var1)
/* globals d3 */
const radius = 5;
const bigRadius = 4 * radius;
const bigPadding = 3 * bigRadius;
const jitter = 2 * radius;
const padding = 3 * radius;
const scales = {
'Usability Threshold': d3.scaleLinear()
.domain([0, 5])
.range([588 - padding, 490 + padding]),
'Expressiveness Ceiling': d3.scaleLinear()
.domain([0, 5])
.range([490 - padding, 392 + padding]),
'Number of Tasks Supported': d3.scaleLinear()
.domain([0, 2])
.range([392 - padding, 294 + padding]),
'Editing vs Starting From Scratch': d3.scaleLinear()
.domain([0, 2])
.range([294 - padding, 196 + padding]),
'Separation From the Graphics': d3.scaleLinear()
.domain([0, 2])
.range([196 - padding, 98 + padding]),
'Optimized for Algorithmic vs Immediate Tasks': d3.scaleLinear()
.domain([0, 2])
.range([98 - padding, 0 + padding])
};
const pcaScales = {
'x': d3.scaleLinear()
.range([bigPadding, 832 - bigPadding]),
'y': d3.scaleLinear()
.range([bigPadding, 832 - bigPadding])
};
const reverseLabels = {
'drawing tools': true,
'direct manipulation-based tools': true,
'GUI-based tools': false,
'grammars': false,
'libraries': false,
'programming languages': false
};
d3.text('template.svg', template => {
d3.select('#container').html(template);
const background = d3.select('#Background');
const scatterFrame = d3.select('#ScatterFrame');
const scatterGroup = d3.select('svg').append('g');
d3.csv('data.csv', data => {
// Clean the data
data = data.map(row => {
Object.keys(row).forEach(key => {
let floatValue = parseFloat(row[key]);
if (!isNaN(floatValue)) {
row[key] = floatValue;
}
});
return row;
});
// Figure out the PCA domains
pcaScales.x.domain(d3.extent(data, d => d['PCA 1']));
pcaScales.y.domain(d3.extent(data, d => d['PCA 2']));
// Generate a plot for each possible pairing
let pairwisePlots = [];
Object.keys(scales).forEach(xKey => {
Object.keys(scales).forEach(yKey => {
pairwisePlots.push({xKey, yKey});
});
});
let smallMultiples = scatterGroup.selectAll('.smallMultiple').data(pairwisePlots);
smallMultiples.exit().remove();
let smallMultiplesEnter = smallMultiples.enter().append('g')
.classed('smallMultiple', true);
smallMultiples = smallMultiplesEnter.merge(smallMultiples);
// Generate the points in those plots
let modalities = smallMultiples.selectAll('.modality').data((plot, index) => {
// Derive the location of each point in its plot
let locationHashTable = {};
data.forEach(d => {
let derivedPoint = {
Modality: d.Modality,
includeLabel: index === 0,
x: scales[plot.xKey](d[plot.xKey]),
y: scales[plot.yKey](d[plot.yKey]),
pcaX: pcaScales.x(d['PCA 1']),
pcaY: pcaScales.y(d['PCA 2'])
};
if (isNaN(derivedPoint.pcaX) || isNaN(derivedPoint.pcaY)) {
throw new Error();
}
let hash = derivedPoint.x + ',' + derivedPoint.y;
derivedPoint.hash = hash;
if (!locationHashTable[hash]) {
locationHashTable[hash] = [];
}
locationHashTable[hash].push(derivedPoint);
});
// Where there are hash collisions, jitter the points
Object.keys(locationHashTable).forEach(hash => {
let pointsAtLocation = locationHashTable[hash];
if (pointsAtLocation.length > 1) {
let center = hash.split(',').map(d => parseFloat(d));
pointsAtLocation.forEach((point, index) => {
let offset = ((index + 0.5) / pointsAtLocation.length) - 0.5;
point.x = center[0] + offset * jitter;
point.y = center[1] - offset * jitter;
});
}
});
// Finally convert the locationHashTable to an array of points
return Object.keys(locationHashTable).reduce((acc, hash) => {
return acc.concat(locationHashTable[hash]);
}, []);
}, d => d.Modality);
modalities.exit().remove();
let modalitiesEnter = modalities.enter().append('g')
.attr('class', d => 'modality ' + d.Modality.replace(/[ -]/g, ''));
modalities = modalitiesEnter.merge(modalities);
modalitiesEnter.append('circle');
modalitiesEnter.append('text')
.attr('x', d => reverseLabels[d.Modality] ? -1.5 * bigRadius : 1.5 * bigRadius)
.attr('text-anchor', d => reverseLabels[d.Modality] ? 'end' : 'start')
.attr('y', '0.35em')
.text(d => d.includeLabel ? d.Modality : '');
modalities.attr('transform', function (d) {
return 'translate(' + d.x + ',' + d.y + ')';
});
// Okay, now let's deal with animation. First, get the background to match
// the badge
let t = d3.transition()
.delay(10000)
.duration(2500);
background
// .attr('fill', '#000000')
// .transition(t)
.attr('fill', '#333333');
// Show the ScatterFrame
scatterFrame
.attr('opacity', 0)
.transition(t)
.attr('opacity', 1);
// Rotate the scatterGroup
scatterGroup
.attr('transform', 'translate(109,472) rotate(0)')
.transition(t)
.attr('transform', 'translate(525,472) rotate(45)');
// Move all the points into their scatterplot positions
modalities
.attr('transform', d => 'translate(' + d.pcaX + ',' + d.pcaY + ')')
.transition(t)
.attr('transform', d => 'translate(' + d.x + ',' + d.y + ')');
// Make the points smaller
modalities.select('circle')
.attr('r', bigRadius)
.transition(t)
.attr('r', radius);
// Hide the labels
modalities.select('text')
.attr('opacity', 1)
.transition(t)
.attr('opacity', 0);
});
});
html,
body {
padding: 0px;
margin: 0px;
}
.modality circle {
stroke: rgba(255,255,255,0.8);
stroke-width: 1px;
}
.modality text {
fill: rgba(255,255,255,0.8);
font-family: 'Roboto Slab', 'Helvetica', sans-serif;
font-size: 2em;
font-weight: 700;
}
.drawingtools circle {
fill: #1b9e77;
}
.directmanipulationbasedtools circle {
fill: #d95f02;
}
.GUIbasedtools circle {
fill: #7570b3;
}
.grammars circle {
fill: #e7298a;
}
.libraries circle {
fill: #e6ab02;
}
.programminglanguages circle {
fill: #666666;
}
Display the source blob
Display the rendered blob
Raw
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="1050px" height="1500px" viewBox="0 0 1050 1500" style="enable-background:new 0 0 1050 1500;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.8;fill:none;stroke:#FFFFFF;stroke-miterlimit:10;}
.st1{opacity:0.8;fill:#FFFFFF;enable-background:new ;}
.st2{font-family:'Roboto-Thin';}
.st3{font-size:12px;}
.st4{font-family:'RobotoSlab-Bold';}
.st5{font-size:16px;}
</style>
<rect id="Background" x="-21.5" y="-24.5" width="1088" height="1558"/>
<g id="ScatterFrame">
<rect x="129.2" y="838.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -575.4836 386.0279)" class="st0" width="98.1" height="98.1"/>
<rect x="198.5" y="769.3" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -506.14 414.751)" class="st0" width="98.1" height="98.1"/>
<rect x="267.9" y="700" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -436.7964 443.4741)" class="st0" width="98.1" height="98.1"/>
<rect x="337.2" y="630.6" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -367.4528 472.1971)" class="st0" width="98.1" height="98.1"/>
<rect x="406.6" y="561.2" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -298.062 500.9397)" class="st0" width="98.1" height="98.1"/>
<rect x="476" y="491.9" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -228.7184 529.6628)" class="st0" width="98.1" height="98.1"/>
<rect x="198.5" y="908" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -604.2067 455.3716)" class="st0" width="98.1" height="98.1"/>
<rect x="267.9" y="838.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -534.8631 484.0946)" class="st0" width="98.1" height="98.1"/>
<rect x="337.2" y="769.3" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -465.5195 512.8177)" class="st0" width="98.1" height="98.1"/>
<rect x="406.6" y="700" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -396.1758 541.5408)" class="st0" width="98.1" height="98.1"/>
<rect x="476" y="630.6" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -326.7851 570.2833)" class="st0" width="98.1" height="98.1"/>
<rect x="545.3" y="561.2" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -257.4415 599.0064)" class="st0" width="98.1" height="98.1"/>
<rect x="267.9" y="977.4" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -632.9493 524.7623)" class="st0" width="98.1" height="98.1"/>
<rect x="337.3" y="908" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -563.6057 553.4854)" class="st0" width="98.1" height="98.1"/>
<rect x="406.6" y="838.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -494.2621 582.2084)" class="st0" width="98.1" height="98.1"/>
<rect x="476" y="769.4" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -424.9184 610.9315)" class="st0" width="98.1" height="98.1"/>
<rect x="545.4" y="700" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -355.5277 639.6741)" class="st0" width="98.1" height="98.1"/>
<rect x="614.7" y="630.6" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -286.1841 668.3972)" class="st0" width="98.1" height="98.1"/>
<rect x="337.3" y="1046.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -661.6724 594.106)" class="st0" width="98.1" height="98.1"/>
<rect x="406.6" y="977.4" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -592.3288 622.829)" class="st0" width="98.1" height="98.1"/>
<rect x="476" y="908" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -522.9852 651.5521)" class="st0" width="98.1" height="98.1"/>
<rect x="545.3" y="838.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -453.6415 680.2751)" class="st0" width="98.1" height="98.1"/>
<rect x="614.7" y="769.3" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -384.2508 709.0178)" class="st0" width="98.1" height="98.1"/>
<rect x="684" y="700" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -314.9071 737.7408)" class="st0" width="98.1" height="98.1"/>
<rect x="406.6" y="1116.1" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -690.3954 663.4496)" class="st0" width="98.1" height="98.1"/>
<rect x="476" y="1046.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -621.0519 692.1726)" class="st0" width="98.1" height="98.1"/>
<rect x="545.3" y="977.4" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -551.7083 720.8957)" class="st0" width="98.1" height="98.1"/>
<rect x="614.7" y="908" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -482.3646 749.6188)" class="st0" width="98.1" height="98.1"/>
<rect x="684" y="838.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -412.9738 778.3614)" class="st0" width="98.1" height="98.1"/>
<rect x="753.4" y="769.3" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -343.6302 807.0844)" class="st0" width="98.1" height="98.1"/>
<rect x="476" y="1185.4" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -719.1185 732.7932)" class="st0" width="98.1" height="98.1"/>
<rect x="545.3" y="1116.1" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -649.7749 761.5162)" class="st0" width="98.1" height="98.1"/>
<rect x="614.7" y="1046.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -580.4313 790.2393)" class="st0" width="98.1" height="98.1"/>
<rect x="684" y="977.4" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -511.0876 818.9624)" class="st0" width="98.1" height="98.1"/>
<rect x="753.4" y="908" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -441.6969 847.705)" class="st0" width="98.1" height="98.1"/>
<rect x="822.7" y="838.7" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -372.3533 876.4281)" class="st0" width="98.1" height="98.1"/>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 457.2966 426.4646)" class="st1 st2 st3">immediate</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 334.3673 345.7969)" class="st1 st4 st5">Optimized for Algorithmic</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 355.923 389.98)" class="st1 st4 st5">vs Immediate Tasks</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 403.2278 476.4233)" class="st1 st2 st3">algorithmic</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 365.7668 473.6373)" class="st1 st2 st3">direct interaction</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 316.1775 466.3086)" class="st1 st4 st5">Separation From</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 326.4354 499.1939)" class="st1 st4 st5">the Graphics</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 309.1417 521.0397)" class="st1 st2 st3">distant interaction</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 333.2659 579.8389)" class="st1 st2 st3">editing</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 236.0694 524.9039)" class="st1 st4 st5">Editing vs Starting</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 252.6588 564.1207)" class="st1 st4 st5">From Scratch</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 228.3717 578.9722)" class="st1 st2 st3">starting from scratch</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 222.4488 607.7242)" class="st1 st2 st3">narrow task focus</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 210.1228 637.6589)" class="st1 st4 st5">Number of</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 165.0613 615.2248)" class="st1 st4 st5">Tasks Supported</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 175.0506 664.3535)" class="st1 st2 st3">broad task focus</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 97.5183 760.1987)" class="st1 st2 st3">high threshold</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 79.5582 784.4993)" class="st1 st4 st5">Usability</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 61.9185 789.4871)" class="st1 st4 st5">Threshold</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 48.3551 815.063)" class="st1 st2 st3">low threshold</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 178.1188 702.0958)" class="st1 st2 st3">high ceiling</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 113.7696 680.0082)" class="st1 st4 st5">Expressiveness</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 148.6167 737.4827)" class="st1 st4 st5">Ceiling</text>
<text transform="matrix(0.7071 0.7071 -0.7071 0.7071 128.9563 756.9608)" class="st1 st2 st3">low ceiling</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 553.6326 465.5358)" class="st1 st2 st3">immediate</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 574.763 486.6661)" class="st1 st4 st5">Optimized for Algorithmic</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 586.0767 497.9798)" class="st1 st4 st5">vs Immediate Tasks</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 605.6455 517.5491)" class="st1 st2 st3">algorithmic</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 622.9836 534.8868)" class="st1 st2 st3">direct interaction</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 644.114 556.0171)" class="st1 st4 st5">Separation From</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 655.4277 567.3308)" class="st1 st4 st5">the Graphics</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 674.9974 586.9006)" class="st1 st2 st3">distant interaction</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 692.3353 604.2385)" class="st1 st2 st3">editing</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 713.465 625.3681)" class="st1 st4 st5">Editing vs Starting</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 724.7787 636.6818)" class="st1 st4 st5">From Scratch</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 744.3484 656.2516)" class="st1 st2 st3">starting from scratch</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 761.6857 673.5888)" class="st1 st2 st3">narrow task focus</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 782.816 694.7191)" class="st1 st4 st5">Number of</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 794.1297 706.0328)" class="st1 st4 st5">Tasks Supported</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 813.6995 725.6026)" class="st1 st2 st3">broad task focus</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 900.3891 812.2922)" class="st1 st2 st3">high threshold</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 921.5181 833.4212)" class="st1 st4 st5">Usability</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 932.8325 844.7356)" class="st1 st4 st5">Threshold</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 952.4022 864.3053)" class="st1 st2 st3">low threshold</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 831.0367 742.9398)" class="st1 st2 st3">high ceiling</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 852.1677 764.0709)" class="st1 st4 st5">Expressiveness</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 863.4814 775.3846)" class="st1 st4 st5">Ceiling</text>
<text transform="matrix(0.7071 -0.7071 0.7071 0.7071 883.0511 794.9543)" class="st1 st2 st3">low ceiling</text>
<line class="st0" x1="455.7" y1="540.9" x2="297.5" y2="382.8"/>
<line class="st0" x1="594.3" y1="540.9" x2="752.5" y2="382.8"/>
<line class="st0" x1="386.3" y1="610.3" x2="280.1" y2="504"/>
<line class="st0" x1="663.8" y1="610.3" x2="770" y2="504"/>
<line class="st0" x1="317" y1="679.6" x2="199.3" y2="561.9"/>
<line class="st0" x1="733" y1="679.8" x2="850.7" y2="562.1"/>
<line class="st0" x1="247.6" y1="748.9" x2="139.8" y2="641.1"/>
<line class="st0" x1="802.4" y1="749" x2="910.2" y2="641.2"/>
<line class="st0" x1="178.3" y1="818.3" x2="77.1" y2="717.1"/>
<line class="st0" x1="871.8" y1="818.3" x2="973" y2="717.1"/>
</g>
</svg>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment