Skip to content

Repository files navigation

DruidJS — A JavaScript Library for Dimensionality Reduction.

Project high-dimensional data down to two or three dimensions while preserving the structure each method is designed to keep. DruidJS gives you 20 dimensionality reduction methods, 7 nearest-neighbor indices and 7 clustering algorithms behind one API, with SIMD-accelerated WebAssembly kernels and a pure-JavaScript fallback everywhere.


Codecov NPM Downloads CI License DOI:10.1109/VIS47514.2020.00029

Installation

If you use npm, install with npm install @saehrimnir/druidjs, and use it with

import * as druid from "@saehrimnir/druidjs";

Otherwise download the files here, or use for instance unpkg this way:

<script src="https://unpkg.com/@saehrimnir/druidjs"></script>

Quick start

import * as druid from "@saehrimnir/druidjs";

const X = druid.Matrix.from(data); // n ⨯ d
const Y = new druid.UMAP(X, { d: 2, seed: 1212 }).transform();

Y.to2dArray(); // [[x, y], ...] — ready for d3

Every method has the same shape: construct it with the data and a parameters object, then call transform(). For a one-off projection there is a static shorthand:

const Y = druid.PCA.transform(X, { d: 2 });

The iterative methods can be stepped instead of run to completion, so you can draw the embedding while it converges:

for (const Y of new druid.TSNE(X, { d: 2, perplexity: 30 }).generator()) {
    draw(Y.to2dArray());
}

Methods

Dimensionality reductionPCA · LDA · MDS · SMACOF · StressMDS · KKMDS · SQDMDS · t-SNE · UMAP · TriMap · PaCMAP · LocalMAP · Sammon · ISOMAP · LLE · LTSA · LSP · FastMap · TopoMap · MINFOTree

Nearest neighbors — BallTree, KDTree, HNSW, Annoy, LSH, NNDescent, NaiveKNN

const index = new druid.HNSW(points, { seed: 1212 });
index.search(points[0], 10); // the 10 nearest points

Clustering — KMeans, KMedoids, XMeans, OPTICS, CURE, MeanShift, HierarchicalClustering (single, complete, average and Ward linkage)

Performance

The hot paths run through WebAssembly kernels once the input is large enough to pay for crossing the boundary, and fall back to JavaScript otherwise — automatically, with no difference in the API. Measured between the published 0.8.0 and 0.9.0 packages: 2.35⨯ on dimensionality reduction, 2.24⨯ on nearest-neighbor search, 2.21⨯ on matrix operations.

The kernels can be turned off, which is the easiest way to compare them against the fallback:

druid.setWasmEnabled(false);
druid.isWasmAvailable();

Matrix

DruidJS uses internally the Matrix class for storing data. You can use it by creating a druid.Matrix object for instance with the function from, in example:

import * as druid from "@saehrimnir/druidjs";

let data = [[...], [...], ...];
let matrix = druid.Matrix.from(data);

You can create a druid.Matrix object programmatically by:

let fn = (row, col) => (row == col ? 1 : 0);
let matrix = new druid.Matrix(rows, columns, fn);

If rows == columns, then matrix would be a identity matrix. A shortcut for a identity matrix is:

let matrix = new druid.Matrix(rows, columns, "I");
// or
let matrix = new druid.Matrix(rows, columns, "identity");

There are more shortcuts for creating matrices:

let matrix = new druid.Matrix(3, 3, "zeros"); // matrix would be a 3x3 matrix with zeroes
let matrix = new druid.Matrix(3, 3, "center"); // matrix would be a 3x3 center matrix;
let number = 12;
let matrix = new druid.Matrix(3, 3, number); // matrix would be a 3x3 matrix filled with 'number'

If you want to use a druid.Matrix object, for instance, with d3, you can use either the to2dArray method, the iterate_rows generator function, or just use the druid.Matrix object as an iterable (works with d3 since version 6).

let data = await d3.csv("data.csv");
let matrix = druid.Matrix.from(data);
d3.selectAll("datapoints").data(matrix.to2dArray()); //...
d3.selectAll("datapoints").data(matrix.iterate_rows()); //...
d3.selectAll("datapoints").data(matrix); //...

Showcases

Live, interactive examples in the documentation:

All showcases → · Every method, one page each →

Resources

@inproceedings{cutura2020druid,
  title={{DRUIDJS — A JavaScript Library for Dimensionality Reduction}},
  author={Cutura, Rene and Kralj, Christoph and Sedlmair, Michael},
  booktitle={2020 IEEE Visualization Conference (VIS)},
  pages={111--115},
  year={2020},
  organization={IEEE}
}

Releases

Used by

Contributors

Languages