Public
Edited
Mar 24, 2023
Insert cell
Insert cell
Insert cell
Insert cell
listener = {
// This being observable, the code below will run every time 'searchterm' changes.

// It creates a new async transformation on deepscatter that returns `1` for each entry where the regex matches, and `0` for each where it doesn't.
if (searchterm == "") {
return;
}
await scatterplot.ready;
scatterplot._root.transformations[searchterm] = async function (tile) {
// First ensure it exists in duckdb.
const encoded = encode_string(searchterm);
const key = tile.key;
await tile.promise;
const data = tile.record_batch.getChild("title").data[0];
let match_start = 0;
let match_length = 0;
// The first zero in the buffer
let target_length = encoded.findIndex((d) => d === 0);
const matches = [];
for (let i = 0; i < data.values.length; i++) {
if (data.values[i] === encoded[match_length]) {
match_length += 1;
if (match_length === 1) {
match_start = i;
}
if (match_length === target_length) {
matches.push(match_start);
match_length = 0;
}
} else {
if (match_length > 0) {
match_length = 0;
}
}
}
const output = new Float32Array(tile.record_batch.numRows);
let offsets_index = 0;
while (matches.length > 0) {
const searching = matches.shift();
while (data.valueOffsets[offsets_index + 1] < searching) {
offsets_index += 1;
}
output[offsets_index] = 1;
}
return output;
};
}
Insert cell
r.shift(0)
Insert cell
r.shift()
Insert cell
r = [1, 2, 3]
Insert cell
d3.part
Insert cell
test_batch.getChild("title").data[0]
Insert cell
encode_string("foo").findIndex((d) => d === 0)
Insert cell
function encode_string(searchterm) {
const arr = new Uint8Array(128);
const encoder = new TextEncoder();
encoder.encodeInto(searchterm, arr);
return arr;
}
Insert cell
test_batch = {
await scatterplot.ready;
return new Promise((resolve) => {
setTimeout(function () {
resolve(scatterplot._root.root_tile.children[3].record_batch);
}, 8000);
});
}
Insert cell
transformation_plot = {
listener;
if (searchterm != "") {
//
scatterplot.plotAPI({
background_options: {
size: [0.4, 2] // Background half normal size, foreground double normal size.
},
encoding: {
foreground: {
field: searchterm,
op: "eq",
a: 1
}
}
});
} else {
scatterplot.plotAPI({
background_options: {
size: [0.4, 1] // Bring the foreground size back down to normal.
},
encoding: {
foreground: null
}
});
}
}
Insert cell
scatterplot = {
const plot = new deepscatter.default("#plot", 900, 600);
await plot.plotAPI({
source_url: "http://localhost:8080/pmed_original",
point_size: 1,
max_points: 1e6,
zoom_balance: 0.35,
alpha: 40,
background_color: "#FFFAF2",
encoding: {
x: {
field: "x",
transform: "literal"
},
y: {
field: "y",
transform: "literal"
},
color: {
field: "labels",
range: "category10"
}
}
});

invalidation.then(() => plot.destroy());
return plot;
}
Insert cell
html`
<style type="text/css">

.tooltip {
background-color: black;
width: 400px;
font-family: sans-serif;
}

.rect {
fill: white;
}

</style>
`
Insert cell
deepscatter = import("https://benschmidt.org/deepscatter@2.9.3")
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
arrow = scatterplot.arrow
Insert cell
db = {
const db = await DuckDBClient.of({});
return db;
}
Insert cell
Insert cell
import {
DuckDBClient,
} from "@bmschmidt/duckdb-client-1-24-0-arrow-11-0-0"
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