@genome-spy/core 0.30.0 → 0.30.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.es.js +16373 -0
- package/dist/index.js +43 -43
- package/package.json +10 -7
- package/src/data/collector.js +0 -183
- package/src/data/collector.test.js +0 -84
- package/src/data/dataFlow.js +0 -148
- package/src/data/dataFlow.test.js +0 -5
- package/src/data/facetNode.js +0 -17
- package/src/data/flow.test.js +0 -72
- package/src/data/flowBatch.d.ts +0 -40
- package/src/data/flowNode.js +0 -283
- package/src/data/flowNode.test.js +0 -50
- package/src/data/flowOptimizer.js +0 -123
- package/src/data/flowOptimizer.test.js +0 -193
- package/src/data/flowTestUtils.js +0 -63
- package/src/data/formats/fasta.js +0 -32
- package/src/data/formats/fasta.test.js +0 -27
- package/src/data/sources/dataSource.js +0 -22
- package/src/data/sources/dataSourceFactory.js +0 -24
- package/src/data/sources/dataUtils.js +0 -78
- package/src/data/sources/dynamicCallbackSource.js +0 -57
- package/src/data/sources/dynamicSource.js +0 -37
- package/src/data/sources/inlineSource.js +0 -67
- package/src/data/sources/inlineSource.test.js +0 -56
- package/src/data/sources/namedSource.js +0 -79
- package/src/data/sources/sequenceSource.js +0 -46
- package/src/data/sources/sequenceSource.test.js +0 -46
- package/src/data/sources/urlSource.js +0 -74
- package/src/data/transforms/aggregate.js +0 -70
- package/src/data/transforms/clone.js +0 -40
- package/src/data/transforms/clone.test.js +0 -11
- package/src/data/transforms/coverage.js +0 -187
- package/src/data/transforms/coverage.test.js +0 -123
- package/src/data/transforms/filter.js +0 -37
- package/src/data/transforms/filter.test.js +0 -18
- package/src/data/transforms/filterScoredLabels.js +0 -134
- package/src/data/transforms/flattenCompressedExons.js +0 -57
- package/src/data/transforms/flattenDelimited.js +0 -74
- package/src/data/transforms/flattenDelimited.test.js +0 -87
- package/src/data/transforms/flattenSequence.js +0 -39
- package/src/data/transforms/flattenSequence.test.js +0 -34
- package/src/data/transforms/formula.js +0 -39
- package/src/data/transforms/formula.test.js +0 -19
- package/src/data/transforms/identifier.js +0 -108
- package/src/data/transforms/identifier.test.js +0 -83
- package/src/data/transforms/linearizeGenomicCoordinate.js +0 -101
- package/src/data/transforms/measureText.js +0 -44
- package/src/data/transforms/pileup.js +0 -128
- package/src/data/transforms/pileup.test.js +0 -70
- package/src/data/transforms/project.js +0 -41
- package/src/data/transforms/project.test.js +0 -32
- package/src/data/transforms/regexExtract.js +0 -61
- package/src/data/transforms/regexExtract.test.js +0 -67
- package/src/data/transforms/regexFold.js +0 -141
- package/src/data/transforms/regexFold.test.js +0 -160
- package/src/data/transforms/sample.js +0 -101
- package/src/data/transforms/sample.test.js +0 -38
- package/src/data/transforms/stack.js +0 -137
- package/src/data/transforms/stack.test.js +0 -91
- package/src/data/transforms/transformFactory.js +0 -60
- package/src/embedApi.d.ts +0 -67
- package/src/encoder/accessor.js +0 -82
- package/src/encoder/accessor.test.js +0 -47
- package/src/encoder/encoder.js +0 -394
- package/src/encoder/encoder.test.js +0 -98
- package/src/fonts/Lato-Regular.json +0 -1267
- package/src/fonts/Lato-Regular.png +0 -0
- package/src/fonts/OFL.txt +0 -93
- package/src/fonts/README.md +0 -3
- package/src/fonts/bmFont.d.ts +0 -58
- package/src/fonts/bmFontManager.js +0 -357
- package/src/fonts/bmFontMetrics.js +0 -108
- package/src/genome/genome.js +0 -317
- package/src/genome/genome.test.js +0 -188
- package/src/genome/genomeStore.js +0 -54
- package/src/genome/locusFormat.js +0 -31
- package/src/genome/scaleIndex.d.ts +0 -38
- package/src/genome/scaleIndex.js +0 -166
- package/src/genome/scaleIndex.test.js +0 -78
- package/src/genome/scaleLocus.d.ts +0 -11
- package/src/genome/scaleLocus.js +0 -108
- package/src/genome/scaleLocus.test.js +0 -4
- package/src/genomeSpy.js +0 -785
- package/src/gl/arrayBuilder.js +0 -199
- package/src/gl/dataToVertices.js +0 -636
- package/src/gl/includes/common.glsl +0 -63
- package/src/gl/includes/picking.fragment.glsl +0 -1
- package/src/gl/includes/picking.vertex.glsl +0 -27
- package/src/gl/includes/sampleFacet.glsl +0 -107
- package/src/gl/includes/scales.glsl +0 -112
- package/src/gl/link.fragment.glsl +0 -18
- package/src/gl/link.vertex.glsl +0 -111
- package/src/gl/point.fragment.glsl +0 -123
- package/src/gl/point.vertex.glsl +0 -129
- package/src/gl/rect.fragment.glsl +0 -51
- package/src/gl/rect.vertex.glsl +0 -114
- package/src/gl/rule.fragment.glsl +0 -52
- package/src/gl/rule.vertex.glsl +0 -89
- package/src/gl/text.fragment.glsl +0 -31
- package/src/gl/text.vertex.glsl +0 -246
- package/src/gl/webGLHelper.js +0 -504
- package/src/img/bowtie.svg +0 -1
- package/src/img/genomespy-favicon.svg +0 -34
- package/src/index.html +0 -11
- package/src/index.js +0 -128
- package/src/marks/link.js +0 -175
- package/src/marks/mark.js +0 -975
- package/src/marks/markUtils.js +0 -125
- package/src/marks/pointMark.js +0 -251
- package/src/marks/rectMark.js +0 -241
- package/src/marks/rule.js +0 -250
- package/src/marks/text.js +0 -278
- package/src/node_modules/.vitest/results.json +0 -1
- package/src/scale/colorUtils.js +0 -184
- package/src/scale/glslScaleGenerator.js +0 -502
- package/src/scale/scale.js +0 -451
- package/src/scale/scale.test.js +0 -324
- package/src/scale/ticks.js +0 -203
- package/src/scale/ticks.test.js +0 -40
- package/src/singlePageApp.js +0 -13
- package/src/spec/axis.d.ts +0 -296
- package/src/spec/channel.d.ts +0 -430
- package/src/spec/data.d.ts +0 -196
- package/src/spec/font.d.ts +0 -15
- package/src/spec/genome.d.ts +0 -35
- package/src/spec/mark.d.ts +0 -429
- package/src/spec/root.d.ts +0 -17
- package/src/spec/sampleView.d.ts +0 -180
- package/src/spec/scale.d.ts +0 -273
- package/src/spec/title.d.ts +0 -102
- package/src/spec/tooltip.d.ts +0 -9
- package/src/spec/transform.d.ts +0 -479
- package/src/spec/view.d.ts +0 -201
- package/src/styles/genome-spy.scss +0 -153
- package/src/tooltip/dataTooltipHandler.js +0 -64
- package/src/tooltip/refseqGeneTooltipHandler.js +0 -78
- package/src/tooltip/tooltipHandler.ts +0 -12
- package/src/types/filetypes.d.ts +0 -14
- package/src/types/flatqueue.d.ts +0 -53
- package/src/types/glsl.d.ts +0 -4
- package/src/types/internmap.d.ts +0 -22
- package/src/types/object.d.ts +0 -21
- package/src/types/vega-loader.d.ts +0 -1
- package/src/types/vega-scale.d.ts +0 -60
- package/src/utils/addBaseUrl.js +0 -19
- package/src/utils/addBaseUrl.test.js +0 -22
- package/src/utils/animator.js +0 -83
- package/src/utils/arrayUtils.js +0 -61
- package/src/utils/binnedIndex.js +0 -167
- package/src/utils/binnedIndex.test.js +0 -155
- package/src/utils/clamp.js +0 -8
- package/src/utils/cloner.js +0 -34
- package/src/utils/cloner.test.js +0 -24
- package/src/utils/coalesce.js +0 -11
- package/src/utils/coalesce.test.js +0 -16
- package/src/utils/concatIterables.js +0 -26
- package/src/utils/concatIterables.test.js +0 -8
- package/src/utils/debounce.js +0 -37
- package/src/utils/domainArray.js +0 -216
- package/src/utils/domainArray.test.js +0 -130
- package/src/utils/eerp.js +0 -13
- package/src/utils/expression.js +0 -32
- package/src/utils/field.js +0 -28
- package/src/utils/formatObject.js +0 -31
- package/src/utils/indexer.js +0 -43
- package/src/utils/indexer.test.js +0 -47
- package/src/utils/inertia.js +0 -124
- package/src/utils/interactionEvent.js +0 -33
- package/src/utils/iterateNestedMaps.js +0 -21
- package/src/utils/iterateNestedMaps.test.js +0 -33
- package/src/utils/kWayMerge.js +0 -42
- package/src/utils/kWayMerge.test.js +0 -26
- package/src/utils/layout/flexLayout.js +0 -368
- package/src/utils/layout/flexLayout.test.js +0 -311
- package/src/utils/layout/grid.js +0 -95
- package/src/utils/layout/grid.test.js +0 -71
- package/src/utils/layout/padding.js +0 -120
- package/src/utils/layout/point.js +0 -23
- package/src/utils/layout/rectangle.js +0 -288
- package/src/utils/layout/rectangle.test.js +0 -172
- package/src/utils/mergeObjects.js +0 -99
- package/src/utils/mergeObjects.test.js +0 -42
- package/src/utils/numberExtractor.js +0 -24
- package/src/utils/numberExtractor.test.js +0 -6
- package/src/utils/point.js +0 -14
- package/src/utils/propertyCacher.js +0 -70
- package/src/utils/propertyCacher.test.js +0 -85
- package/src/utils/propertyCoalescer.js +0 -42
- package/src/utils/propertyCoalescer.test.js +0 -22
- package/src/utils/reservationMap.js +0 -103
- package/src/utils/reservationMap.test.js +0 -20
- package/src/utils/scaleNull.js +0 -19
- package/src/utils/setOperations.js +0 -75
- package/src/utils/smoothstep.js +0 -10
- package/src/utils/throttle.js +0 -34
- package/src/utils/topK.js +0 -76
- package/src/utils/topK.test.js +0 -64
- package/src/utils/transition.js +0 -74
- package/src/utils/ui/tooltip.js +0 -189
- package/src/utils/url.js +0 -22
- package/src/utils/variableTools.js +0 -24
- package/src/utils/variableTools.test.js +0 -13
- package/src/view/axisResolution.js +0 -140
- package/src/view/axisResolution.test.js +0 -201
- package/src/view/axisView.js +0 -747
- package/src/view/concatView.js +0 -45
- package/src/view/containerView.js +0 -159
- package/src/view/facetView.js +0 -491
- package/src/view/flowBuilder.js +0 -367
- package/src/view/flowBuilder.test.js +0 -125
- package/src/view/gridView.js +0 -786
- package/src/view/implicitRootView.js +0 -14
- package/src/view/importView.js +0 -19
- package/src/view/layerView.js +0 -74
- package/src/view/rendering.d.ts +0 -44
- package/src/view/renderingContext/compositeViewRenderingContext.js +0 -51
- package/src/view/renderingContext/deferredViewRenderingContext.js +0 -176
- package/src/view/renderingContext/layoutRecorderViewRenderingContext.js +0 -128
- package/src/view/renderingContext/simpleViewRenderingContext.js +0 -64
- package/src/view/renderingContext/svgViewRenderingContext.js +0 -125
- package/src/view/renderingContext/viewRenderingContext.js +0 -41
- package/src/view/scaleResolution.js +0 -797
- package/src/view/scaleResolution.test.js +0 -572
- package/src/view/scaleResolutionApi.d.ts +0 -40
- package/src/view/testUtils.js +0 -51
- package/src/view/title.js +0 -165
- package/src/view/unitView.js +0 -382
- package/src/view/view.js +0 -612
- package/src/view/view.test.js +0 -214
- package/src/view/viewContext.d.ts +0 -62
- package/src/view/viewFactory.js +0 -181
- package/src/view/viewFactory.test.js +0 -17
- package/src/view/viewUtils.js +0 -327
- package/src/view/zoom.js +0 -89
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
const cacheMapKey = Symbol("cacheMap");
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @param {object} host The object that uses caching
|
|
5
|
-
* @param {any} key string
|
|
6
|
-
* @param {function(key?):T} callable A function that produces a value to be cached
|
|
7
|
-
* @returns {T}
|
|
8
|
-
* @template T
|
|
9
|
-
*/
|
|
10
|
-
export function getCachedOrCall(host, key, callable) {
|
|
11
|
-
let value = getCacheMap(host).get(key);
|
|
12
|
-
if (value === undefined) {
|
|
13
|
-
value = callable(key);
|
|
14
|
-
getCacheMap(host).set(key, value);
|
|
15
|
-
}
|
|
16
|
-
return value;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
21
|
-
* @param {object} host The object that uses caching
|
|
22
|
-
* @param {string} key
|
|
23
|
-
*/
|
|
24
|
-
export function invalidate(host, key) {
|
|
25
|
-
getCacheMap(host).delete(key);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
*
|
|
30
|
-
* @param {object} host The object that uses caching
|
|
31
|
-
* @param {string} keyPrefix
|
|
32
|
-
*/
|
|
33
|
-
export function invalidatePrefix(host, keyPrefix) {
|
|
34
|
-
const m = getCacheMap(host);
|
|
35
|
-
for (const key of m.keys()) {
|
|
36
|
-
if (key.startsWith(keyPrefix)) {
|
|
37
|
-
m.delete(key);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
getCacheMap(host).delete(keyPrefix);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
* @param {object} host The object that uses caching
|
|
45
|
-
*/
|
|
46
|
-
export function invalidateAll(host) {
|
|
47
|
-
getCacheMap(host).clear();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* @param {any} host The object that uses caching
|
|
52
|
-
*/
|
|
53
|
-
export function initPropertyCache(host) {
|
|
54
|
-
/** @type {Map<string, any>} */
|
|
55
|
-
host[cacheMapKey] = new Map();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* @param {any} host The object that uses caching
|
|
60
|
-
* @returns {Map<string, any>}
|
|
61
|
-
*/
|
|
62
|
-
function getCacheMap(host) {
|
|
63
|
-
if (host[cacheMapKey]) {
|
|
64
|
-
return host[cacheMapKey];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
initPropertyCache(host);
|
|
68
|
-
|
|
69
|
-
return host[cacheMapKey];
|
|
70
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest";
|
|
2
|
-
import { getCachedOrCall, invalidate, invalidateAll } from "./propertyCacher";
|
|
3
|
-
|
|
4
|
-
class TestClass {
|
|
5
|
-
constructor() {
|
|
6
|
-
/** @type {number} */
|
|
7
|
-
this._x;
|
|
8
|
-
/** @type {number} */
|
|
9
|
-
this._y;
|
|
10
|
-
|
|
11
|
-
this._xCalls = 0;
|
|
12
|
-
this._yCalls = 0;
|
|
13
|
-
|
|
14
|
-
this.resetAll();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
get x() {
|
|
18
|
-
return getCachedOrCall(this, "x", () => {
|
|
19
|
-
this._xCalls++;
|
|
20
|
-
return this._x;
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
set x(x) {
|
|
25
|
-
this._x = x;
|
|
26
|
-
invalidate(this, "x");
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
get y() {
|
|
30
|
-
return getCachedOrCall(this, "y", () => {
|
|
31
|
-
this._yCalls++;
|
|
32
|
-
return this._y;
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
set y(y) {
|
|
37
|
-
this._y = y;
|
|
38
|
-
invalidate(this, "y");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
resetAll() {
|
|
42
|
-
this._x = 10;
|
|
43
|
-
this._y = 20;
|
|
44
|
-
invalidateAll(this);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
test("Initial cached get returns correct values and calls callable only once", () => {
|
|
49
|
-
const instance = new TestClass();
|
|
50
|
-
|
|
51
|
-
expect(instance._xCalls).toEqual(0);
|
|
52
|
-
expect(instance.x).toEqual(10);
|
|
53
|
-
expect(instance._xCalls).toEqual(1);
|
|
54
|
-
expect(instance.x).toEqual(10);
|
|
55
|
-
expect(instance._xCalls).toEqual(1);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
test("Invalidate invalidates", () => {
|
|
59
|
-
const instance = new TestClass();
|
|
60
|
-
|
|
61
|
-
expect(instance._xCalls).toEqual(0);
|
|
62
|
-
expect(instance.x).toEqual(10);
|
|
63
|
-
expect(instance._xCalls).toEqual(1);
|
|
64
|
-
|
|
65
|
-
instance.x = 123;
|
|
66
|
-
expect(instance._xCalls).toEqual(1);
|
|
67
|
-
|
|
68
|
-
expect(instance.x).toEqual(123);
|
|
69
|
-
expect(instance._xCalls).toEqual(2);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test("InvalidateAll invalidates everything", () => {
|
|
73
|
-
const instance = new TestClass();
|
|
74
|
-
|
|
75
|
-
instance.x = 123;
|
|
76
|
-
instance.y = 321;
|
|
77
|
-
|
|
78
|
-
expect(instance.x).toEqual(123);
|
|
79
|
-
expect(instance.y).toEqual(321);
|
|
80
|
-
|
|
81
|
-
instance.resetAll();
|
|
82
|
-
|
|
83
|
-
expect(instance.x).toEqual(10);
|
|
84
|
-
expect(instance.y).toEqual(20);
|
|
85
|
-
});
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Coalesces properties. Allows for creating chains of defaults without
|
|
3
|
-
* using object destructuring, which may generate piles of garbage for GC.
|
|
4
|
-
*
|
|
5
|
-
* Still WIP.
|
|
6
|
-
* TODO: Efficient computed defaults.
|
|
7
|
-
* TODO: Make sense of the types
|
|
8
|
-
*
|
|
9
|
-
* @param {...function():T} sources
|
|
10
|
-
* @returns {T}
|
|
11
|
-
*
|
|
12
|
-
* @template {Record<string | symbol, any>} [T=object]
|
|
13
|
-
*/
|
|
14
|
-
export default function coalesceProperties(...sources) {
|
|
15
|
-
/** @type {ProxyHandler<T>} */
|
|
16
|
-
const handler = {
|
|
17
|
-
get(_target, prop, _receiver) {
|
|
18
|
-
for (const source of sources) {
|
|
19
|
-
const props = source();
|
|
20
|
-
const value = props[prop];
|
|
21
|
-
if (value !== undefined) {
|
|
22
|
-
return value;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return undefined;
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
// @ts-ignore
|
|
29
|
-
has(target, prop, _receiver) {
|
|
30
|
-
for (const source of sources) {
|
|
31
|
-
const props = source();
|
|
32
|
-
if (prop in props) {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return false;
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// @ts-ignore
|
|
41
|
-
return new Proxy({}, handler);
|
|
42
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest";
|
|
2
|
-
import coalesceProperties from "./propertyCoalescer";
|
|
3
|
-
|
|
4
|
-
test("CoalesceProperties works as expected", () => {
|
|
5
|
-
const defaults = { a: 10, b: 11 };
|
|
6
|
-
const props = { a: 1, c: 2 };
|
|
7
|
-
|
|
8
|
-
const coalesced = coalesceProperties(
|
|
9
|
-
() => props,
|
|
10
|
-
() => defaults
|
|
11
|
-
);
|
|
12
|
-
|
|
13
|
-
expect(coalesced.a).toEqual(1);
|
|
14
|
-
expect(coalesced.b).toEqual(11);
|
|
15
|
-
expect(coalesced.c).toEqual(2);
|
|
16
|
-
expect(coalesced.undef).toBeUndefined();
|
|
17
|
-
|
|
18
|
-
expect("a" in coalesced).toBeTruthy();
|
|
19
|
-
expect("b" in coalesced).toBeTruthy();
|
|
20
|
-
expect("c" in coalesced).toBeTruthy();
|
|
21
|
-
expect("undef" in coalesced).toBeFalsy();
|
|
22
|
-
});
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A simple data structure for keeping track of unreserved space in one dimension.
|
|
3
|
-
* Doesn't do any balancing, reservations must be done in random order.
|
|
4
|
-
* Uses arrays to minimize object allocation and burden on GC.
|
|
5
|
-
*
|
|
6
|
-
* Note: this data structure appears to have some similarities to "Segment Tree".
|
|
7
|
-
* TODO: Balancing ideas: https://cp-algorithms.com/data_structures/segment_tree.html
|
|
8
|
-
*/
|
|
9
|
-
export default class ReservationMap {
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
* @param {number} maxSize Max number of free slots that can be tracked
|
|
13
|
-
* @param {number} [lowerLimit]
|
|
14
|
-
* @param {number} [upperLimit]
|
|
15
|
-
*/
|
|
16
|
-
constructor(maxSize, lowerLimit = -Infinity, upperLimit = Infinity) {
|
|
17
|
-
this.maxSize = maxSize;
|
|
18
|
-
this.lowerLimit = lowerLimit;
|
|
19
|
-
this.upperLimit = upperLimit;
|
|
20
|
-
|
|
21
|
-
const count = this.maxSize * 2 + 1; // TODO: The factor could be lower
|
|
22
|
-
|
|
23
|
-
this.lowerLimits = new Float64Array(count);
|
|
24
|
-
this.upperLimits = new Float64Array(count);
|
|
25
|
-
this.lowerChildren = new Int32Array(count);
|
|
26
|
-
this.upperChildren = new Int32Array(count);
|
|
27
|
-
|
|
28
|
-
this.reset();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
reset() {
|
|
32
|
-
this.lowerLimits.fill(0);
|
|
33
|
-
this.upperLimits.fill(0);
|
|
34
|
-
this.lowerChildren.fill(0);
|
|
35
|
-
this.upperChildren.fill(0);
|
|
36
|
-
|
|
37
|
-
// Initial node
|
|
38
|
-
this.n = 1;
|
|
39
|
-
this.lowerLimits[0] = this.lowerLimit;
|
|
40
|
-
this.upperLimits[0] = this.upperLimit;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
*
|
|
45
|
-
* @param {number} lower
|
|
46
|
-
* @param {number} upper
|
|
47
|
-
* @param {number} i
|
|
48
|
-
* @returns {number} Node index or -1 if not found
|
|
49
|
-
*/
|
|
50
|
-
_findSlot(lower, upper, i = 0) {
|
|
51
|
-
if (lower >= this.lowerLimits[i] && upper <= this.upperLimits[i]) {
|
|
52
|
-
const lowerChild = this.lowerChildren[i];
|
|
53
|
-
if (!lowerChild) {
|
|
54
|
-
// Node has no children, found a free slot
|
|
55
|
-
return i;
|
|
56
|
-
} else {
|
|
57
|
-
const lowerResult = this._findSlot(lower, upper, lowerChild);
|
|
58
|
-
if (lowerResult >= 0) {
|
|
59
|
-
return lowerResult;
|
|
60
|
-
}
|
|
61
|
-
return this._findSlot(lower, upper, this.upperChildren[i]);
|
|
62
|
-
}
|
|
63
|
-
} else {
|
|
64
|
-
return -1;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
*
|
|
70
|
-
* @param {number} lower
|
|
71
|
-
* @param {number} upper
|
|
72
|
-
* @returns {boolean} true if reservation succeeded
|
|
73
|
-
*/
|
|
74
|
-
reserve(lower, upper) {
|
|
75
|
-
if (upper - lower <= 0) {
|
|
76
|
-
throw new Error("Cannot reserve an empty or negative-size slot!");
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (this.n + 1 > this.lowerLimits.length) {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const i = this._findSlot(lower, upper);
|
|
84
|
-
if (i < 0) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// TODO: if the requested range is connected to an edge of the free slot,
|
|
89
|
-
// adjust the found slot instead
|
|
90
|
-
|
|
91
|
-
const lowerIndex = this.n++;
|
|
92
|
-
const upperIndex = this.n++;
|
|
93
|
-
|
|
94
|
-
this.lowerLimits[lowerIndex] = this.lowerLimits[i];
|
|
95
|
-
this.upperLimits[lowerIndex] = lower;
|
|
96
|
-
this.lowerLimits[upperIndex] = upper;
|
|
97
|
-
this.upperLimits[upperIndex] = this.upperLimits[i];
|
|
98
|
-
this.lowerChildren[i] = lowerIndex;
|
|
99
|
-
this.upperChildren[i] = upperIndex;
|
|
100
|
-
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest";
|
|
2
|
-
import ReservationMap from "./reservationMap";
|
|
3
|
-
|
|
4
|
-
test("ReservationMap works correctly", () => {
|
|
5
|
-
const m = new ReservationMap(20);
|
|
6
|
-
|
|
7
|
-
expect(m.reserve(0, 3)).toBeTruthy();
|
|
8
|
-
expect(m.reserve(15, 17)).toBeTruthy();
|
|
9
|
-
expect(m.reserve(5, 11)).toBeTruthy();
|
|
10
|
-
expect(m.reserve(19, 22)).toBeTruthy();
|
|
11
|
-
expect(m.reserve(23, 26)).toBeTruthy();
|
|
12
|
-
expect(m.reserve(12, 13)).toBeTruthy();
|
|
13
|
-
expect(m.reserve(13, 14)).toBeTruthy();
|
|
14
|
-
expect(m.reserve(4, 5)).toBeTruthy();
|
|
15
|
-
|
|
16
|
-
expect(m.reserve(6, 8)).toBeFalsy();
|
|
17
|
-
expect(m.reserve(10, 13)).toBeFalsy();
|
|
18
|
-
expect(m.reserve(-2, 1)).toBeFalsy();
|
|
19
|
-
expect(m.reserve(25, 28)).toBeFalsy();
|
|
20
|
-
});
|
package/src/utils/scaleNull.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Like scaleIdentity but passes everything thru. Doesn't support domains or ranges or anything.
|
|
3
|
-
*/
|
|
4
|
-
export default function scaleNull() {
|
|
5
|
-
/** @param {any} x */
|
|
6
|
-
const scale = (x) => x;
|
|
7
|
-
|
|
8
|
-
/** @param {any} x */
|
|
9
|
-
scale.invert = (x) => x;
|
|
10
|
-
|
|
11
|
-
scale.copy = scaleNull;
|
|
12
|
-
|
|
13
|
-
/** Keep vega-scale happy */
|
|
14
|
-
scale.invertRange = () => {
|
|
15
|
-
//
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
return scale;
|
|
19
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Adapted from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#implementing_basic_set_operations
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @param {Set<T>} set
|
|
7
|
-
* @param {Set<T>} subset
|
|
8
|
-
* @template T
|
|
9
|
-
*/
|
|
10
|
-
export function isSuperset(set, subset) {
|
|
11
|
-
for (let elem of subset) {
|
|
12
|
-
if (!set.has(elem)) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @param {Set<T>} setA
|
|
21
|
-
* @param {Set<T>} setB
|
|
22
|
-
* @template T
|
|
23
|
-
*/
|
|
24
|
-
export function union(setA, setB) {
|
|
25
|
-
let _union = new Set(setA);
|
|
26
|
-
for (let elem of setB) {
|
|
27
|
-
_union.add(elem);
|
|
28
|
-
}
|
|
29
|
-
return _union;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @param {Set<T>} setA
|
|
34
|
-
* @param {Set<T>} setB
|
|
35
|
-
* @template T
|
|
36
|
-
*/
|
|
37
|
-
export function intersection(setA, setB) {
|
|
38
|
-
let _intersection = new Set();
|
|
39
|
-
for (let elem of setB) {
|
|
40
|
-
if (setA.has(elem)) {
|
|
41
|
-
_intersection.add(elem);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return _intersection;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @param {Set<T>} setA
|
|
49
|
-
* @param {Set<T>} setB
|
|
50
|
-
* @template T
|
|
51
|
-
*/
|
|
52
|
-
export function symmetricDifference(setA, setB) {
|
|
53
|
-
let _difference = new Set(setA);
|
|
54
|
-
for (let elem of setB) {
|
|
55
|
-
if (_difference.has(elem)) {
|
|
56
|
-
_difference.delete(elem);
|
|
57
|
-
} else {
|
|
58
|
-
_difference.add(elem);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return _difference;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* @param {Set<T>} setA
|
|
66
|
-
* @param {Set<T>} setB
|
|
67
|
-
* @template T
|
|
68
|
-
*/
|
|
69
|
-
export function difference(setA, setB) {
|
|
70
|
-
let _difference = new Set(setA);
|
|
71
|
-
for (let elem of setB) {
|
|
72
|
-
_difference.delete(elem);
|
|
73
|
-
}
|
|
74
|
-
return _difference;
|
|
75
|
-
}
|
package/src/utils/smoothstep.js
DELETED
package/src/utils/throttle.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/* eslint-disable consistent-this */
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* https://codeburst.io/throttling-and-debouncing-in-javascript-b01cad5c8edf
|
|
5
|
-
*
|
|
6
|
-
* @param {function} func
|
|
7
|
-
* @param {number} limit
|
|
8
|
-
*/
|
|
9
|
-
export default function throttle(func, limit) {
|
|
10
|
-
/** @type {number} */
|
|
11
|
-
let lastFunc;
|
|
12
|
-
|
|
13
|
-
/** @type {number} */
|
|
14
|
-
let lastRan;
|
|
15
|
-
|
|
16
|
-
return function () {
|
|
17
|
-
// eslint-disable-next-line no-invalid-this
|
|
18
|
-
const context = this;
|
|
19
|
-
// eslint-disable-next-line prefer-rest-params
|
|
20
|
-
const args = arguments;
|
|
21
|
-
if (!lastRan) {
|
|
22
|
-
func.apply(context, args);
|
|
23
|
-
lastRan = Date.now();
|
|
24
|
-
} else {
|
|
25
|
-
clearTimeout(lastFunc);
|
|
26
|
-
lastFunc = window.setTimeout(function () {
|
|
27
|
-
if (Date.now() - lastRan >= limit) {
|
|
28
|
-
func.apply(context, args);
|
|
29
|
-
lastRan = Date.now();
|
|
30
|
-
}
|
|
31
|
-
}, limit - (Date.now() - lastRan));
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
}
|
package/src/utils/topK.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import FlatQueue from "flatqueue";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Finds the top k
|
|
5
|
-
*
|
|
6
|
-
* Based on ideas at https://lemire.me/blog/2017/06/21/top-speed-for-top-k-queries/
|
|
7
|
-
*
|
|
8
|
-
* @param {T[]} data
|
|
9
|
-
* @param {number} k
|
|
10
|
-
* @param {(datum: T) => number} priorityAccessor
|
|
11
|
-
* @template T
|
|
12
|
-
*/
|
|
13
|
-
export function topK(data, k, priorityAccessor) {
|
|
14
|
-
/** @type {FlatQueue<number>} */
|
|
15
|
-
const queue = new FlatQueue();
|
|
16
|
-
|
|
17
|
-
let i;
|
|
18
|
-
for (i = 0; i < k && i < data.length; i++) {
|
|
19
|
-
queue.push(i, priorityAccessor(data[i]));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
for (; i < data.length; i++) {
|
|
23
|
-
const p = priorityAccessor(data[i]);
|
|
24
|
-
if (p >= queue.peekValue()) {
|
|
25
|
-
queue.push(i, p);
|
|
26
|
-
queue.pop();
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const result = [];
|
|
31
|
-
|
|
32
|
-
let index;
|
|
33
|
-
while ((index = queue.pop()) !== undefined) {
|
|
34
|
-
result.push(data[index]);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return result.reverse();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Takes an array of priorities and returns the top k indices from the
|
|
42
|
-
* specified slice
|
|
43
|
-
*
|
|
44
|
-
* @param {number[]} priorities An array of priorities
|
|
45
|
-
* @param {number} k
|
|
46
|
-
* @param {number} [start] Default: 0
|
|
47
|
-
* @param {number} [end] Exclusive. Default: priorities.length
|
|
48
|
-
*/
|
|
49
|
-
export function topKSlice(priorities, k, start = 0, end = priorities.length) {
|
|
50
|
-
/** @type {FlatQueue<number>} */
|
|
51
|
-
const queue = new FlatQueue();
|
|
52
|
-
|
|
53
|
-
const sliceLength = end - start;
|
|
54
|
-
|
|
55
|
-
let i;
|
|
56
|
-
for (i = 0; i < k && i < sliceLength; i++) {
|
|
57
|
-
queue.push(i, priorities[start + i]);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
for (; i < sliceLength; i++) {
|
|
61
|
-
const p = priorities[start + i];
|
|
62
|
-
if (p >= queue.peekValue()) {
|
|
63
|
-
queue.push(i, p);
|
|
64
|
-
queue.pop();
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const result = [];
|
|
69
|
-
|
|
70
|
-
let index;
|
|
71
|
-
while ((index = queue.pop()) !== undefined) {
|
|
72
|
-
result.push(start + index);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return result.reverse();
|
|
76
|
-
}
|
package/src/utils/topK.test.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest";
|
|
2
|
-
import { range } from "d3-array";
|
|
3
|
-
import { topK, topKSlice } from "./topK";
|
|
4
|
-
|
|
5
|
-
test("topK returns top k numbers in priority order", () => {
|
|
6
|
-
/** @param {number} x */
|
|
7
|
-
const priorityAccessor = (x) => x;
|
|
8
|
-
|
|
9
|
-
expect(topK([1, 2, 3], 3, priorityAccessor)).toEqual([3, 2, 1]);
|
|
10
|
-
expect(topK([1, 2, 3], 1, priorityAccessor)).toEqual([3]);
|
|
11
|
-
expect(topK([1, 2, 3], 6, priorityAccessor)).toEqual([3, 2, 1]);
|
|
12
|
-
expect(topK([1, 2, 3, 4, 5, 6], 3, priorityAccessor)).toEqual([6, 5, 4]);
|
|
13
|
-
expect(topK([0, 9, 1, 8, 2, 7, 3, 6, 4, 5], 3, priorityAccessor)).toEqual([
|
|
14
|
-
9, 8, 7,
|
|
15
|
-
]);
|
|
16
|
-
expect(topK([1, 1, 1], 3, priorityAccessor)).toEqual([1, 1, 1]);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("topK returns top k objects in priority order", () => {
|
|
20
|
-
/** @param {{priority: number}} d */
|
|
21
|
-
const priorityAccessor = (d) => d.priority;
|
|
22
|
-
|
|
23
|
-
expect(
|
|
24
|
-
topK(
|
|
25
|
-
[0, 9, 1, 8, 2, 7, 3, 6, 4, 5].map((x) => ({ priority: x })),
|
|
26
|
-
3,
|
|
27
|
-
priorityAccessor
|
|
28
|
-
)
|
|
29
|
-
).toEqual([9, 8, 7].map((x) => ({ priority: x })));
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test("topK returns top k objects in priority order with large datasets", () => {
|
|
33
|
-
/** @param {number} x */
|
|
34
|
-
const priorityAccessor = (x) => x;
|
|
35
|
-
|
|
36
|
-
const n = 10000;
|
|
37
|
-
const bigArray = range(n).map((x) => Math.floor(Math.random() * 100));
|
|
38
|
-
const sortedBigArray = bigArray.slice().sort((a, b) => b - a);
|
|
39
|
-
|
|
40
|
-
for (let k = 0; k < 13000; k += 1000) {
|
|
41
|
-
expect(topK(bigArray, k, priorityAccessor)).toEqual(
|
|
42
|
-
sortedBigArray.slice(0, k)
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test("topKSlice returns top k indexes in priority order", () => {
|
|
48
|
-
expect(topKSlice([0, 1, 2], 3)).toEqual([2, 1, 0]);
|
|
49
|
-
expect(topKSlice([1, 2, 3], 3)).toEqual([2, 1, 0]);
|
|
50
|
-
expect(topKSlice([0, 1, 2], 1)).toEqual([2]);
|
|
51
|
-
expect(topKSlice([0, 1, 2], 6)).toEqual([2, 1, 0]);
|
|
52
|
-
expect(topKSlice([0, 1, 2, 3, 4, 5], 3)).toEqual([5, 4, 3]);
|
|
53
|
-
expect(topKSlice([0, 9, 1, 8, 2, 7, 3, 6, 4, 5], 3)).toEqual([1, 3, 5]);
|
|
54
|
-
expect(new Set(topKSlice([1, 1, 1, 2, 2, 2], 3))).toEqual(
|
|
55
|
-
new Set([3, 4, 5])
|
|
56
|
-
);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("topKSlice returns top k indexes from a slice in priority order", () => {
|
|
60
|
-
expect(topKSlice([0, 1, 2, 3, 4, 5], 2, 1, 5)).toEqual([4, 3]);
|
|
61
|
-
expect(topKSlice([0, 9, 1, 8, 2, 7, 3, 6, 4, 5], 3, 1, 5)).toEqual([
|
|
62
|
-
1, 3, 4,
|
|
63
|
-
]);
|
|
64
|
-
});
|
package/src/utils/transition.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/** @param {number} ms */
|
|
2
|
-
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @param {TransitionOptions} options
|
|
6
|
-
*
|
|
7
|
-
* @typedef {Object} TransitionOptions
|
|
8
|
-
* @prop {number} [from] default: 0
|
|
9
|
-
* @prop {number} [to] default: 1
|
|
10
|
-
* @prop {number} [duration] in milliseconds, default: 1000
|
|
11
|
-
* @prop {number} [delay] milliseconds to wait before the transition starts, default: 0
|
|
12
|
-
* @prop {function(number):void} onUpdate
|
|
13
|
-
* @prop {function(number):number} [easingFunction] default: linear
|
|
14
|
-
* @prop {function(function(number):void):void} [requestAnimationFrame]
|
|
15
|
-
* default: window.requestAnimationFrame
|
|
16
|
-
* @prop {AbortSignal} [signal]
|
|
17
|
-
*/
|
|
18
|
-
export default function transition(options) {
|
|
19
|
-
const requestAnimationFrame =
|
|
20
|
-
options.requestAnimationFrame || window.requestAnimationFrame;
|
|
21
|
-
|
|
22
|
-
const signal = options.signal;
|
|
23
|
-
|
|
24
|
-
const makePromise = () =>
|
|
25
|
-
new Promise((resolve, reject) => {
|
|
26
|
-
if (signal?.aborted) {
|
|
27
|
-
return reject("aborted");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const beginTimestamp = performance.now();
|
|
31
|
-
const endTimestamp = beginTimestamp + (options.duration || 1000);
|
|
32
|
-
|
|
33
|
-
const from = typeof options.from == "number" ? options.from : 0;
|
|
34
|
-
const to = typeof options.to == "number" ? options.to : 1;
|
|
35
|
-
const ease = options.easingFunction || ((x) => x);
|
|
36
|
-
|
|
37
|
-
/** @param {number} x */
|
|
38
|
-
const toUnit = (x) =>
|
|
39
|
-
(x - beginTimestamp) / (endTimestamp - beginTimestamp);
|
|
40
|
-
|
|
41
|
-
/** @param {number} x */
|
|
42
|
-
const toRange = (x) => x * (to - from) + from;
|
|
43
|
-
|
|
44
|
-
/** @param {number} x */
|
|
45
|
-
const clamp = (x) => Math.max(0, Math.min(1, x));
|
|
46
|
-
|
|
47
|
-
/** @param {number} stamp */
|
|
48
|
-
const step = (stamp) => {
|
|
49
|
-
if (signal?.aborted) {
|
|
50
|
-
reject("aborted");
|
|
51
|
-
} else {
|
|
52
|
-
options.onUpdate(toRange(ease(clamp(toUnit(stamp)))));
|
|
53
|
-
if (stamp < endTimestamp) {
|
|
54
|
-
requestAnimationFrame(step);
|
|
55
|
-
} else {
|
|
56
|
-
options.onUpdate(toRange(ease(1)));
|
|
57
|
-
resolve();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
requestAnimationFrame(step);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
if (options.delay) {
|
|
66
|
-
if (signal?.aborted) {
|
|
67
|
-
return Promise.reject("aborted");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return wait(options.delay).then(makePromise);
|
|
71
|
-
} else {
|
|
72
|
-
return makePromise();
|
|
73
|
-
}
|
|
74
|
-
}
|