mdsjs
Version:
MDS and PCA projections in JavaScript
175 lines (158 loc) • 5.13 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<!-- Google tag (gtag.js) -->
<script
async
src="https://www.googletagmanager.com/gtag/js?id=G-4DHJEMESJD"
></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-4DHJEMESJD');
</script>
<!-- Google tag end -->
<title>mds - js</title>
<link rel="canonical" href="https://mdsjs.josuakrause.com/" />
<link rel="stylesheet" href="./index.css" />
</head>
<body style="margin: 20px auto; width: 800px">
<p style="float: right">
<canvas
id="canvas"
width="400"
height="400"
style="width: 400px; height: 400px"
></canvas>
</p>
<p>
<button id="recompute">recompute</button>
<button id="switch">switch</button>
<button id="source">source</button>
</p>
<p>Computing: <span id="mode"></span></p>
Input:
<pre id="matrix" style="height: 200px; overflow: auto"></pre>
Output:
<pre id="output" style="height: 200px; overflow: auto"></pre>
<pre id="sourceview"></pre>
<script type="module" id="jsmain" defer>
import mdsjs from './mdsjs.js';
mdsjs.DEBUG = true;
function start() {
if (mds) {
computeMDS();
} else {
computePCA();
}
updateSource();
}
document.getElementById('recompute').addEventListener('click', start);
let mds = true;
function chg() {
mds = !mds;
start();
}
document.getElementById('switch').addEventListener('click', chg);
let showSource = false;
function toggleSource() {
showSource = !showSource;
updateSource();
}
document
.getElementById('source')
.addEventListener('click', toggleSource);
function updateSource() {
const elem = document.getElementById('sourceview');
if (showSource) {
elem.innerText = mds ? computeMDS : computePCA;
} else {
elem.innerText = '';
}
}
function computeMDS() {
const a = mdsjs.convertToMatrix(
[
[0, 2, 2, 4, 6, 6, 4, 6, 6],
[2, 0, 2, 2, 3, 4, 2, 3, 4],
[2, 2, 0, 4, 4, 6, 4, 4, 6],
[4, 2, 4, 0, 1, 1, 4, 6, 6],
[6, 3, 4, 1, 0, 1, 2, 3, 4],
[6, 4, 6, 1, 1, 0, 4, 4, 6],
[4, 2, 4, 4, 2, 4, 0, 1, 1],
[6, 3, 4, 6, 3, 4, 1, 0, 1],
[6, 4, 6, 6, 4, 6, 1, 1, 0],
],
true,
);
mdsjs.landmarkMDSAsync(a, 2, (points) => {
const ctx = document.getElementById('canvas').getContext('2d');
ctx.clearRect(0, 0, 400, 400);
ctx.beginPath();
ctx.rect(0, 0, 400, 400);
ctx.stroke();
points.rowsIter((row) => {
const x = row[0] * 50 + 200;
const y = row[1] * 50 + 200;
ctx.fillRect(x - 2, y - 2, 4, 4);
});
document.getElementById('mode').innerText = 'mds';
document.getElementById('output').innerText = '' + points;
document.getElementById('matrix').innerText = '' + a;
});
}
function computePCA() {
const /** @type {number[][]} */ posArr = [];
const /** @type {number} */ xspread = 180;
const /** @type {number} */ yspread = 150;
for (let ix = 0; ix < 1000; ix += 1) {
const rnd = Math.random() * 2 * Math.PI;
posArr.push([Math.cos(rnd) * xspread, Math.sin(rnd) * yspread]);
}
const pos = mdsjs.convertToMatrix(posArr);
mdsjs.pcaAsync(pos, (pca) => {
const points = pos.mul(pca);
const ctx = document.getElementById('canvas').getContext('2d');
ctx.clearRect(0, 0, 400, 400);
ctx.beginPath();
ctx.rect(0, 0, 400, 400);
ctx.stroke();
ctx.save();
ctx.fillStyle = 'blue';
pos.rowsIter((row) => {
const x = row[0] + 200;
const y = row[1] + 200;
ctx.fillRect(x - 2, y - 2, 4, 4);
});
ctx.restore();
ctx.save();
ctx.fillStyle = 'red';
points.rowsIter((row) => {
const x = row[0] + 200;
const y = row[1] + 200;
ctx.fillRect(x - 2, y - 2, 4, 4);
});
ctx.restore();
document.getElementById('mode').innerText = 'pca';
document.getElementById('output').innerText = `${pca}\n${points}`;
document.getElementById('matrix').innerText = `${pos}`;
});
}
start();
</script>
<footer>
<div class="footer-style">
© jk 2023
<a href="https://github.com/JosuaKrause/mdsjs" target="_blank">
[source]
</a>
</div>
</footer>
</body>
</html>