Commit 5bcd56c0 authored by marioromera's avatar marioromera

get top results

parent 3a91547d
......@@ -1481,6 +1481,51 @@
"randomfill": "^1.0.3"
}
},
"css-loader": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.5.3.tgz",
"integrity": "sha512-UEr9NH5Lmi7+dguAm+/JSPovNjYbm2k3TK58EiwQHzOHH5Jfq1Y+XoP2bQO6TMn7PptMd0opxxedAWcaSTRKHw==",
"dev": true,
"requires": {
"camelcase": "^5.3.1",
"cssesc": "^3.0.0",
"icss-utils": "^4.1.1",
"loader-utils": "^1.2.3",
"normalize-path": "^3.0.0",
"postcss": "^7.0.27",
"postcss-modules-extract-imports": "^2.0.0",
"postcss-modules-local-by-default": "^3.0.2",
"postcss-modules-scope": "^2.2.0",
"postcss-modules-values": "^3.0.0",
"postcss-value-parser": "^4.0.3",
"schema-utils": "^2.6.6",
"semver": "^6.3.0"
},
"dependencies": {
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
"schema-utils": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
"integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
"dev": true,
"requires": {
"ajv": "^6.12.0",
"ajv-keywords": "^3.4.1"
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
}
}
},
"css-select": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
......@@ -1499,6 +1544,12 @@
"integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
"dev": true
},
"cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true
},
"cwise": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/cwise/-/cwise-1.0.10.tgz",
......@@ -3744,6 +3795,15 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
"icss-utils": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz",
"integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==",
"dev": true,
"requires": {
"postcss": "^7.0.14"
}
},
"ieee754": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
......@@ -3788,6 +3848,12 @@
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
"dev": true
},
"indexes-of": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
"integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
"dev": true
},
"infer-owner": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
......@@ -5424,6 +5490,92 @@
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
"dev": true
},
"postcss": {
"version": "7.0.29",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz",
"integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==",
"dev": true,
"requires": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
"supports-color": "^6.1.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"postcss-modules-extract-imports": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz",
"integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==",
"dev": true,
"requires": {
"postcss": "^7.0.5"
}
},
"postcss-modules-local-by-default": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz",
"integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==",
"dev": true,
"requires": {
"icss-utils": "^4.1.1",
"postcss": "^7.0.16",
"postcss-selector-parser": "^6.0.2",
"postcss-value-parser": "^4.0.0"
}
},
"postcss-modules-scope": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz",
"integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==",
"dev": true,
"requires": {
"postcss": "^7.0.6",
"postcss-selector-parser": "^6.0.0"
}
},
"postcss-modules-values": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz",
"integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==",
"dev": true,
"requires": {
"icss-utils": "^4.0.0",
"postcss": "^7.0.6"
}
},
"postcss-selector-parser": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
"integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==",
"dev": true,
"requires": {
"cssesc": "^3.0.0",
"indexes-of": "^1.0.1",
"uniq": "^1.0.1"
}
},
"postcss-value-parser": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
"integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
"dev": true
},
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
......
......@@ -2,7 +2,7 @@ const d3 = require('d3');
const _ = require('lodash');
const { Corpus } = require('tiny-tfidf');
const stopWords = require('./stop-words');
require('./styles.css');
//https://www.debates.org/voter-education/debate-transcripts/september-26-1960-debate-transcript/
const fileName = 'The First Kennedy-Nixon Presidential Debate';
......@@ -29,7 +29,7 @@ let tsneOptions = {
perplexity: 30.0, // roughly how many neighbors each point influences (30 = default)
earlyExaggeration: 12.0,
learningRate: 100.0, // epsilon is learning rate (10 = default)
nIter: 100,
nIter: 1000,
metric: 'euclidean',
};
......@@ -41,8 +41,8 @@ const texts$ = Promise.all(
textFiles.map((tf) => fetch(tf).then((r) => r.text()))
);
texts$.then((documents) => {
var svgWidth = 1200;
var svgHeight = 800;
var svgWidth = window.innerWidth;
var svgHeight = window.innerHeight;
var margin = { top: 40, right: 120, bottom: 140, left: 50 };
var width = svgWidth - margin.left - margin.right;
var height = svgHeight - margin.top - margin.bottom;
......@@ -64,10 +64,22 @@ texts$.then((documents) => {
});
return acc;
}, {});
const rawTfidf = _.values(resultTfidf);
const data = _.keys(resultTfidf).map((p, i) => {
function sortByValuesArray(x, z) {
let xSum = x.reduce((a, b) => a + b);
let zSum = z.reduce((a, b) => a + b);
return xSum < zSum ? 1 : zSum < xSum ? -1 : 0;
}
const topResults = _.flow(
(d) => d.sort((a, b) => sortByValuesArray(a[1], b[1])),
(d) => _.slice(d, 0, 100)
)(Object.entries(resultTfidf));
const rawTfidf = topResults.map((r) => r[1]);
const data = topResults.map((p) => {
return {
word: p,
word: p[0],
doc: fileName,
points: [],
};
......@@ -86,32 +98,26 @@ texts$.then((documents) => {
.append('g')
.append('text')
.attr('class', 'iter')
.attr('fill', '#000')
.attr('y', 14)
.attr('x', width - 50)
.attr('text-anchor', 'center')
.text('Iterations');
const texts = svg.append('g');
const fileNameText = texts
.append('text')
.attr('fill', '#000')
.attr('y', 14)
.attr('x', 1)
.attr('text-anchor', 'center')
.text(fileName);
texts
.append('text')
.attr('y', 34)
.attr('x', 1)
.attr('text-anchor', 'center')
.attr('fill', color(0))
.text('Kennedy');
texts
.append('text')
.attr('y', 54)
.attr('x', 1)
.attr('text-anchor', 'center')
.attr('fill', color(1))
.text('Nixon');
......@@ -128,30 +134,26 @@ texts$.then((documents) => {
// ZOOOOOOOOM
var zoom = d3
.zoom()
.scaleExtent([1, 20]) // This control how much you can unzoom (x0.5) and zoom (x20)
.scaleExtent([0.8, 100]) // This control how much you can unzoom (x0.5) and zoom (x20)
.extent([
[0, 0],
[width, height],
])
.on('zoom', update);
svg
.append('rect')
g.append('rect')
.attr('width', width)
.attr('height', height)
.style('fill', 'none')
.style('pointer-events', 'all')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.call(zoom);
const clipPath = svg
const clipPath = g
.append('defs')
.append('SVG:clipPath')
.attr('id', 'clip')
.append('SVG:rect')
.attr('width', width)
.attr('height', height)
.attr('x', 0)
.attr('y', 0);
.attr('height', height);
var line = d3
.line()
......@@ -168,7 +170,6 @@ texts$.then((documents) => {
.x((d) => newX(d[0])) // apply the x scale to the x data
.y((d) => newY(d[1])) // apply the y scale to the y data
.curve(d3.curveMonotoneX);
// update circle position
points
.selectAll('circle')
......@@ -182,54 +183,58 @@ texts$.then((documents) => {
points
.selectAll('path')
.data(data)
.attr('d', (d) => newLine(d.points));
.attr('d', (d) => newLine(_.takeRight(d.points, 2)));
points
.selectAll('text')
.selectAll('.labels')
.data(data)
.attr('x', function (d) {
return newX(_.last(d.points)[0]);
})
.attr('y', function (d) {
return newY(_.last(d.points)[1]);
});
.attr(
'transform',
(d) =>
`translate(${newX(_.last(d.points)[0]) - 7},${
newY(_.last(d.points)[1]) - 7
})`
);
}
function drawSolution(solution) {
points.selectAll('path').remove();
function draw() {
points.selectAll('circle').remove();
points.selectAll('text').remove();
points.selectAll('.labels').remove();
solution.forEach((point, i) => {
data[i].points.push(point);
const wordScore = resultTfidf[data[i].word];
data.forEach((node) => {
const wordScore = resultTfidf[node.word];
const speakerColor = wordScore[1] > wordScore[0] ? color(1) : color(0);
const xCoord = _.last(node.points)[0];
const yCoord = _.last(node.points)[1];
const paths = points
.append('circle')
.attr('class', `point ${data[i].word}`)
.attr('cx', x(point[0]))
.attr('cy', y(point[1]))
.attr('class', `point ${node.word}`)
.attr('cx', x(xCoord))
.attr('cy', y(yCoord))
.attr('stroke', speakerColor)
.attr('stroke-width', 1)
.attr('r', '3')
.attr('fill', 'none');
points
const lines = points
.append('path')
.attr('class', `line ${data[i].word}`)
.attr('d', line(data[i].points))
.attr('class', `line ${node.word}`)
.attr('d', line(_.takeRight(node.points, 2)))
.attr('stroke', speakerColor)
.attr('opacity', 0.1)
.attr('stroke-width', 1)
.attr('fill', 'none');
points
const label = points
.append('g')
.attr('class', `labels ${node.word}`)
.attr('transform', `translate(${x(xCoord) - 7},${y(yCoord) - 7})`);
const labelsBg = label
.append('text')
.attr('class', `labelBg ${node.word}`)
.text(node.word);
label
.append('text')
.attr('class', `label ${data[i].word}`)
.attr('x', x(point[0]) - 7)
.attr('y', y(point[1]) - 7)
.attr('font-family', 'Segoe UI Italic') // Font type
.attr('font-size', '14px') // Font size
.attr('class', `label ${node.word}`)
.attr('fill', speakerColor)
.text(data[i].word);
.text(node.word);
});
}
......@@ -242,11 +247,15 @@ texts$.then((documents) => {
iterText.text(`Iteration: ${msg.data[0]}`);
break;
case 'PROGRESS_DATA':
drawSolution(msg.data);
msg.data.forEach((point, i) => {
data[i].points.push(point);
});
draw();
break;
case 'DONE':
iterText.text(`Done withing ${iter} iterations`);
drawSolution(msg.data);
draw();
break;
default:
}
......
text {
font-family: 'Segoe UI';
font-size: 15px;
}
text.label {
font-family: 'Segoe UI Italic';
font-size: 13px;
}
text.labelBg {
font-size: 13px;
font-family: 'Segoe UI Italic';
stroke: white;
stroke-width: 2px;
}
......@@ -72,12 +72,12 @@ model.on('progressIter', function (iter) {
});
});
model.on('progressStatus', function (status) {
postMessage({
type: 'PROGRESS_STATUS',
data: status,
});
});
// model.on('progressStatus', function (status) {
// postMessage({
// type: 'PROGRESS_STATUS',
// data: status,
// });
// });
model.on('progressData', function (data) {
postMessage({
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment