From 37721e5a5a00acc83e7aa535bc5a64c31c2240b8 Mon Sep 17 00:00:00 2001 From: Ben Schmidt Date: Sun, 3 Nov 2024 11:50:39 -0500 Subject: [PATCH] cleaner deeptable instantiation pattern --- src/Deeptable.ts | 52 +++++++++++++++++++++++++++++++++++++++++----- src/scatterplot.ts | 6 +++++- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/Deeptable.ts b/src/Deeptable.ts index 8b3e2b46d..3c1b6dd7b 100644 --- a/src/Deeptable.ts +++ b/src/Deeptable.ts @@ -138,15 +138,57 @@ export class Deeptable { // Must come after manifest is set. this.base_url = baseUrl; this.root_tile = new Tile(defaultManifest, null, this); - const preProcessRootTile = this.root_tile.preprocessRootTileInfo(); - // At instantiation, the deeptable isn't ready; only once this // async stuff is done can the deeptable be used. // TODO: Add an async static method as the preferred initialization method. - this.promise = preProcessRootTile.then(async () => { + this.promise = this._makePromise(defaultManifest); + } + + /** + * Loads a quadtree created by version 2.0 or great of the quadfeather package (including manifests). + * + * @param tileProxy A tileProxy to use for fetching tiles. Can be used to wrap authentication. + * @param baseUrl The base URL of the quadfeather data. + * + */ + static async fromQuadfeather({ + tileProxy, + baseUrl, + plot = null, + }: { + tileProxy?: DS.TileProxy; + baseUrl: string; + plot?: Scatterplot | null; + }) { + let manifest: DS.TileManifest; + if (tileProxy !== undefined) { + throw new Error('Not yet supported'); + } else { + manifest = await loadTileManifest(baseUrl + '/manifest.feather'); + } + + const dt = new Deeptable({ + tileProxy, + tileManifest: manifest, + baseUrl, + rootKey: '0/0/0', + plot, + }); + await dt.promise; + return dt; + } + + /** + * Internal function to ensure + */ + protected _makePromise( + tileManifest: Partial & { key: string }, + ): Promise { + return this.root_tile.preprocessRootTileInfo().then(async () => { const batch = await this.root_tile.get_arrow(null); const schema = batch.schema; - if (!tileManifest) { + // TODO: Cleaner check that it's a lazy manifest + if (!tileManifest.max_ix) { this.root_tile.manifest = await this.root_tile.deriveManifestInfoFromTileMetadata(); } @@ -1188,7 +1230,7 @@ export type TileManifest = { extent: Rectangle; }; -export async function tileManifest(url: string) { +export async function loadTileManifest(url: string): Promise { const data = await fetch(url).then((d) => d.arrayBuffer()); const tb = tableFromIPC(data); const rows: RowFormatManifest[] = [...tb].map( diff --git a/src/scatterplot.ts b/src/scatterplot.ts index b1a932f07..1c92016e1 100644 --- a/src/scatterplot.ts +++ b/src/scatterplot.ts @@ -373,7 +373,11 @@ export class Scatterplot { tileProxy, }: DS.DataSpec): Promise { if (source_url !== undefined) { - this._root = Deeptable.from_quadfeather(source_url, this, tileProxy); + this._root = await Deeptable.fromQuadfeather({ + baseUrl: source_url, + plot: this, + tileProxy, + }); } else if (arrow_table !== undefined) { this._root = Deeptable.fromArrowTable(arrow_table, this); } else if (arrow_buffer !== undefined) {