Published
Edited
Jul 29, 2020
2 forks
Importers
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
config = ({
nComponents: 2,
minDist: 0.1,
nNeighbors: 15
})
Insert cell
color = d3
.scaleLinear()
.range(["red", "lime"])
.domain([0, N])
Insert cell
res = dynamic
? Generators.observe(
worker(
dynamic ? fitdynamic : fit,
{ N, precomputed, config },
`
const window = {};
importScripts("https://unpkg.com/umap-js@1.3.0/lib/umap-js.js");
const UMAP = window.UMAP;
`
)
)
: fit({ N, precomputed, config })
Insert cell
distance = {
if (mode === "loop") {
return function distance(i, j) {
return Math.min(Math.abs(i - j), N - Math.abs(i - j));
};
}

if (mode === "lattice") {
const n = Math.sqrt(N) | 0;
return function distance(i, j) {
const x = (Math.abs(i - j) / n) | 0,
y = Math.abs((i % n) - (j % n));
return x + y;
};
}

if (mode === "cylinder") {
const n = Math.sqrt(N) | 0;
return function distance(i, j) {
const x = (Math.abs(i - j) / n) | 0,
y = Math.abs((i % n) - (j % n));
return Math.min(y, n - y) + x;
};
}

if (mode === "torus") {
const n = Math.sqrt(N) | 0;
return function distance(i, j) {
const x = (Math.abs(i - j) / n) | 0,
y = Math.abs((i % n) - (j % n));
return Math.min(y, n - y) + Math.min(x, n - x);
};
}

// mode = line
return function distance(i, j) {
return Math.abs(i - j);
};
}
Insert cell
precomputed = Array.from({ length: N }, (_, i) =>
Array.from({ length: N }, (_, j) => distance(i, j))
)
Insert cell
function fit({ N, precomputed, config }) {
const time = performance.now();

const umap = new UMAP(config);

// mode = precomputed
umap.distanceFn = function distance(i, j) {
return precomputed[i][j];
};

return {
result: umap.fit(Array.from({ length: N }, (_, i) => i)),
time: performance.now() - time
};
}
Insert cell
function* fitdynamic({ N, precomputed, config }) {
const time = performance.now();

const umap = new UMAP(config);

// mode = precomputed
umap.distanceFn = function distance(i, j) {
return precomputed[i][j];
};

yield {
result: Array.from({ length: N }, () => [Math.random(), Math.random()]),
time: performance.now() - time,
epoch: -1
};

const nEpochs = umap.initializeFit(Array.from({ length: N }, (_, i) => i));

yield {
result: Array.from({ length: N }, () => [Math.random(), Math.random()]),
time: performance.now() - time,
epoch: 0
};

var t = performance.now(),
t0 = t;
for (let i = 0; i < nEpochs; i++) {
umap.step();
t = performance.now();
if (t - t0 > 200) {
t0 = t;
yield {
result: umap.getEmbedding(),
time: performance.now() - time,
epoch: i
};
}
}
yield {
result: umap.getEmbedding(),
time: performance.now() - time,
epoch: nEpochs
};
}
Insert cell
UMAP = (await require("umap-js@1.3.2")).UMAP
Insert cell
d3 = require("d3@5")
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more