diff --git a/tests/dataset.spec.js b/tests/dataset.spec.js index f650cd907..18292938a 100644 --- a/tests/dataset.spec.js +++ b/tests/dataset.spec.js @@ -1,4 +1,4 @@ -import { Dataset, DataSelection } from '../dist/deepscatter.js'; +import { Dataset, DataSelection, Bitmask } from '../dist/deepscatter.js'; import { Table, vectorFromArray, Utf8 } from 'apache-arrow'; import { test } from 'uvu'; import * as assert from 'uvu/assert'; @@ -59,6 +59,21 @@ test('Test composition of selections', async () => { ) < 0.01, 'sixes are 4x as big as twos over threes', ); + + // test null selections work. + const emptySelection = new DataSelection(dataset, { + name: 'empty', + tileFunction: async (t) => new Bitmask(t.record_batch.numRows).to_arrow(), + }); + + const selectNothing = new DataSelection(dataset, { + name: 'nothing and something is nothing', + composition: ['AND', selectThree, emptySelection], + }); + + await selectNothing.applyToAllLoadedTiles(); + const v = selectNothing.get(); + console.log(v); }); test.run(); diff --git a/tests/datasetHelpers.js b/tests/datasetHelpers.js index be190ebaf..df788179a 100644 --- a/tests/datasetHelpers.js +++ b/tests/datasetHelpers.js @@ -70,3 +70,76 @@ export function createIntegerDataset() { const table = createTable(num_batches); return Dataset.fromArrowTable(table); } + +const memo = {}; + +function buildDeepManifest( + startingKey = '0/0/0', + depth = 8, + // The probability of each child existing. + prob = 0.89, + // prob * decay is the probability of each grandchild existing. + decay = 0.89, + pointsPerManifest = 100, + extent = { x: [-1, 1], y: [-1, 1] }, + startingIx = 0, +) { + const [z, x, y] = startingKey.split('/').map(parseInt); + + const children = []; + const splits = { + x: [extent.x[0], (extent.x[0] + extent.x[1]) / 2, extent.x[1]], + y: [extent.y[0], (extent.y[0] + extent.y[1]) / 2, extent.y[1]], + }; + + function tilesPerLevel(z, prob, decay = undefined) { + if (z === 0) { + return 1; + } + if (z == 1) { + return 4 * prob + 1; + } + const key = `${z}-${prob}-${decay}`; + if (memo[key]) return memo[key]; + if (decay == undefined) { + decay = prob; + } + memo[key] = 4 * tilesPerLevel(z - 1, prob) * prob ** z; + return memo[key]; + } + + function tilesThroughLevel(z, prob) { + let v = 0; + for (let i = 0; i <= z; i += 1) { + v += tilesPerLevel(i, prob); + } + return v; + } + + // .89 produces about 18K tiles, which is a lot--could hold a trillion points under ideal circumstances + + for (let x_ of [0, 1]) { + for (let y_ of [0, 1]) { + if (Math.random() < prob && depth > 0) { + const child = buildDeepManifest( + `${z + 1}/${2 * x + x_}/${2 * y + y_}`, + depth - 1, + prob * decay, + decay, + pointsPerManifest, + { + x: [splits.x[x_], splits.x[x_ + 1]], + y: [splits.y[y_], splits.y[y_ + 1]], + }, + startingIx, + ); + children.push(child); + } + } + } + return { + key, + nPoints: pointsPerManifest, + children, + }; +}