diff --git a/dev/Main.svelte b/dev/Main.svelte
index 8d6c17607..56d372e89 100644
--- a/dev/Main.svelte
+++ b/dev/Main.svelte
@@ -1,49 +1,49 @@
-
-
+
+
-
-
-
+
\ No newline at end of file
+
diff --git a/dev/svelte/SizeSlider.svelte b/dev/svelte/SizeSlider.svelte
new file mode 100644
index 000000000..a24146f1a
--- /dev/null
+++ b/dev/svelte/SizeSlider.svelte
@@ -0,0 +1,21 @@
+
+
+
diff --git a/package-lock.json b/package-lock.json
index 2e2b013e6..77bb6a0d5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -54,6 +54,7 @@
"terser": "^5.28.1",
"typedoc": "^0.25.8",
"typescript": "^5.3.3",
+ "uvu": "^0.5.6",
"vite": "^5.1.4"
},
"peerDependencies": {
@@ -2470,6 +2471,15 @@
"node": ">=6"
}
},
+ "node_modules/diff": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -4729,6 +4739,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/ms": {
"version": "2.1.2",
"dev": true,
@@ -5597,6 +5616,18 @@
"queue-microtask": "^1.2.2"
}
},
+ "node_modules/sade": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
+ "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
+ "dev": true,
+ "dependencies": {
+ "mri": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/safe-array-concat": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz",
@@ -6423,6 +6454,24 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/uvu": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz",
+ "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.0",
+ "diff": "^5.0.0",
+ "kleur": "^4.0.3",
+ "sade": "^1.7.3"
+ },
+ "bin": {
+ "uvu": "bin.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@@ -8213,6 +8262,12 @@
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"dev": true
},
+ "diff": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
+ "dev": true
+ },
"dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -9867,6 +9922,12 @@
"version": "1.2.6",
"dev": true
},
+ "mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "dev": true
+ },
"ms": {
"version": "2.1.2",
"dev": true
@@ -10466,6 +10527,15 @@
"queue-microtask": "^1.2.2"
}
},
+ "sade": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
+ "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
+ "dev": true,
+ "requires": {
+ "mri": "^1.1.0"
+ }
+ },
"safe-array-concat": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz",
@@ -11051,6 +11121,18 @@
"version": "1.0.2",
"dev": true
},
+ "uvu": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz",
+ "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==",
+ "dev": true,
+ "requires": {
+ "dequal": "^2.0.0",
+ "diff": "^5.0.0",
+ "kleur": "^4.0.3",
+ "sade": "^1.7.3"
+ }
+ },
"validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
diff --git a/package.json b/package.json
index 921be1aa6..69c4a18fa 100644
--- a/package.json
+++ b/package.json
@@ -90,6 +90,7 @@
"terser": "^5.28.1",
"typedoc": "^0.25.8",
"typescript": "^5.3.3",
+ "uvu": "^0.5.6",
"vite": "^5.1.4"
}
}
diff --git a/src/Dataset.ts b/src/Dataset.ts
index e72392fa3..60a37e4b8 100644
--- a/src/Dataset.ts
+++ b/src/Dataset.ts
@@ -32,6 +32,7 @@ import { wrapArrowTable } from './wrap_arrow';
type Key = string;
type ArrowBuildable = DS.ArrowBuildable;
+
type Transformation = DS.Transformation;
// Some variables are universally available.
diff --git a/src/scatterplot.ts b/src/scatterplot.ts
index ce8d73efa..f7d948808 100644
--- a/src/scatterplot.ts
+++ b/src/scatterplot.ts
@@ -251,7 +251,7 @@ export class Scatterplot {
return old_version.selection;
}
}
- const selection = new DataSelection(this, params);
+ const selection = new DataSelection(this.dataset, params);
this.selection_history.push({
selection,
name: selection.name,
diff --git a/src/selection.ts b/src/selection.ts
index 0e9ee387e..527cc0a37 100644
--- a/src/selection.ts
+++ b/src/selection.ts
@@ -66,6 +66,12 @@ type BinaryOperation = 'AND' | 'OR' | 'XOR';
type UnaryOperation = 'NOT';
type CompArgs = DataSelection | Composition;
+
+/**
+ * A composition represents an operation on selections. The syntax is basically
+ * a lisp-like list of operations and selections. The first element is the operation,
+ * and the rest of the elements are the arguments.
+ */
type Composition =
| [UnaryOperation, CompArgs]
| [BinaryOperation, CompArgs, CompArgs]
@@ -329,15 +335,14 @@ export class DataSelection {
private events: { [key: string]: Array<(args) => void> } = {};
constructor(
- plot: Scatterplot,
+ dataset: Dataset,
params:
| IdSelectParams
| BooleanColumnParams
| FunctionSelectParams
| CompositeSelectParams,
) {
- this.plot = plot;
- this.dataset = plot.dataset;
+ this.dataset = dataset;
this.name = params.name;
let markReady = function () {};
this.ready = new Promise((resolve) => {
@@ -424,7 +429,7 @@ export class DataSelection {
* selection that is the union of the two.
*/
union(other: DataSelection, name: string | undefined): DataSelection {
- return new DataSelection(this.plot, {
+ return new DataSelection(this.dataset, {
name: name || this.name + ' union ' + other.name,
composition: ['OR', this, other],
});
@@ -438,7 +443,7 @@ export class DataSelection {
* disjunctive normal form constructor.
*/
intersection(other: DataSelection, name: string | undefined): DataSelection {
- return new DataSelection(this.plot, {
+ return new DataSelection(this.dataset, {
name: name || this.name + ' intersection ' + other.name,
composition: ['AND', this, other],
});
@@ -606,7 +611,7 @@ export class DataSelection {
}
return mask.to_arrow();
};
- const selection = new DataSelection(this.plot, {
+ const selection = new DataSelection(this.dataset, {
name: newName,
tileFunction,
});
@@ -648,7 +653,7 @@ export class DataSelection {
if (this.dataset.has_column(name)) {
throw new Error(`Column ${name} already exists, can't create`);
}
- this.plot.dataset.transformations[name] =
+ this.dataset.transformations[name] =
this.wrapWithSelectionMetadata(tileFunction);
// Await the application to the root tile, which may be necessary
await this.dataset.root_tile.apply_transformation(name);
@@ -766,43 +771,22 @@ export class DataSelection {
}
if (typeof codes[0] === 'string') {
const matcher = stringmatcher(key_field, codes as string[]);
- this.plot.dataset.transformations[name] =
+ this.dataset.transformations[name] =
this.wrapWithSelectionMetadata(matcher);
await this.dataset.root_tile.apply_transformation(name);
} else if (typeof codes[0] === 'bigint') {
const matcher = bigintmatcher(key_field, codes as bigint[]);
- this.plot.dataset.transformations[name] =
+ this.dataset.transformations[name] =
this.wrapWithSelectionMetadata(matcher);
await this.dataset.root_tile.apply_transformation(name);
} else {
console.error('Unable to match type', typeof codes[0]);
}
- if (options.plot_after) {
- return this.apply_to_foreground({});
- }
}
async add_boolean_column(name: string, field: string): Promise {
throw new Error('Method not implemented.');
}
-
- apply_to_foreground(params: DS.BackgroundOptions): Promise {
- const field = this.name;
- const background_options: DS.BackgroundOptions = {
- size: [0.5, 10],
- ...params,
- };
- return this.plot.plotAPI({
- background_options,
- encoding: {
- foreground: {
- field,
- op: 'gt',
- a: 0,
- },
- },
- });
- }
}
function bigintmatcher(field: string, matches: bigint[]) {
diff --git a/src/shared.d.ts b/src/shared.d.ts
index befb12c50..bd4768fa1 100644
--- a/src/shared.d.ts
+++ b/src/shared.d.ts
@@ -134,6 +134,7 @@ export type ArrowBuildable =
| Uint8Array;
type MaybePromise = T | Promise;
+
/**
* A transformation is a batchwise operation that can be used to construct
* a new column in the data table. It runs asynchronously so that it
diff --git a/src/tile.ts b/src/tile.ts
index a9c1ef89a..ab47fe700 100644
--- a/src/tile.ts
+++ b/src/tile.ts
@@ -39,9 +39,15 @@ export type RecordBatchCache =
let tile_identifier = 0;
/**
- * A Tile is, essentially, code to create an Arrow RecordBatch
- * and to associate metadata with it, in the context of a larger dataset.
- *
+ * A Tile is a collection of points in the dataset that are grouped together:
+ * it represents the basic unit of operation for most batched operations in
+ * deepscatter including network packets, GPU calculations,
+ * transformations on data, and render calls. It corresponds to a record batch
+ * of data in the Arrow format, but a tile object can be instantiated without
+ * having the record batch present, and includes instructions for building it.
+ * The Tile object also holds its own place in a tree (usually, but not always,
+ * a quadtree), and is responsible for certain information about all of its descendants
+ * in the tree as well as itself.
*/
export class Tile {
// public max_ix = -1;