@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
package/package.json
CHANGED
|
@@ -7,17 +7,20 @@
|
|
|
7
7
|
},
|
|
8
8
|
"contributors": [],
|
|
9
9
|
"license": "MIT",
|
|
10
|
-
"version": "0.30.
|
|
10
|
+
"version": "0.30.2",
|
|
11
11
|
"main": "dist/index.js",
|
|
12
|
-
"module": "
|
|
12
|
+
"module": "dist/index.es.js",
|
|
13
13
|
"exports": {
|
|
14
|
-
".":
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./dist/index.es.js",
|
|
16
|
+
"require": "./dist/index.js"
|
|
17
|
+
},
|
|
15
18
|
"./*": "./src/*",
|
|
16
|
-
"./schema.json": "./dist/schema.json"
|
|
19
|
+
"./schema.json": "./dist/schema.json",
|
|
20
|
+
"./style.css": "./dist/style.css"
|
|
17
21
|
},
|
|
18
22
|
"files": [
|
|
19
|
-
"dist/"
|
|
20
|
-
"src/"
|
|
23
|
+
"dist/"
|
|
21
24
|
],
|
|
22
25
|
"repository": {
|
|
23
26
|
"type": "git",
|
|
@@ -53,5 +56,5 @@
|
|
|
53
56
|
"vega-scale": "^7.1.1",
|
|
54
57
|
"vega-util": "^1.16.0"
|
|
55
58
|
},
|
|
56
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "26530163d4f60172bfe45c45cd488c54a69942ca"
|
|
57
60
|
}
|
package/src/data/collector.js
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import { InternMap } from "internmap";
|
|
2
|
-
import { group } from "d3-array";
|
|
3
|
-
import { compare } from "vega-util";
|
|
4
|
-
import iterateNestedMaps from "../utils/iterateNestedMaps";
|
|
5
|
-
import FlowNode, { isFacetBatch } from "./flowNode";
|
|
6
|
-
import { field } from "../utils/field";
|
|
7
|
-
import { asArray } from "../utils/arrayUtils";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Collects (materializes) the data that flows through this node.
|
|
11
|
-
* The collected data can be optionally grouped and sorted.
|
|
12
|
-
*
|
|
13
|
-
* Grouping is primarily intended for handling faceted data.
|
|
14
|
-
*
|
|
15
|
-
* @typedef {import("../spec/transform").CollectParams} CollectParams
|
|
16
|
-
* @typedef {import("./flowNode").Data} Data
|
|
17
|
-
*/
|
|
18
|
-
export default class Collector extends FlowNode {
|
|
19
|
-
/**
|
|
20
|
-
* @param {CollectParams} [params]
|
|
21
|
-
*/
|
|
22
|
-
constructor(params) {
|
|
23
|
-
super();
|
|
24
|
-
|
|
25
|
-
this.params = params ?? { type: "collect" };
|
|
26
|
-
|
|
27
|
-
/** @type {(function(Collector):void)[]} */
|
|
28
|
-
this.observers = [];
|
|
29
|
-
|
|
30
|
-
/** @type {Map<any | any[], Data>} TODO: proper type for key */
|
|
31
|
-
this.facetBatches = undefined;
|
|
32
|
-
|
|
33
|
-
this._init();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
_init() {
|
|
37
|
-
/** @type {Data} */
|
|
38
|
-
this._data = [];
|
|
39
|
-
|
|
40
|
-
// TODO: Consider nested maps
|
|
41
|
-
this.facetBatches = new InternMap([], JSON.stringify);
|
|
42
|
-
this.facetBatches.set(undefined, this._data);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
reset() {
|
|
46
|
-
super.reset();
|
|
47
|
-
this._init();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
*
|
|
52
|
-
* @param {import("./flowNode").Datum} datum
|
|
53
|
-
*/
|
|
54
|
-
handle(datum) {
|
|
55
|
-
this._data.push(datum);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* @param {import("./flowBatch").FlowBatch} flowBatch
|
|
60
|
-
*/
|
|
61
|
-
beginBatch(flowBatch) {
|
|
62
|
-
if (isFacetBatch(flowBatch)) {
|
|
63
|
-
this._data = [];
|
|
64
|
-
this.facetBatches.set(asArray(flowBatch.facetId), this._data);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
complete() {
|
|
69
|
-
const sort = this.params?.sort;
|
|
70
|
-
// Vega's "compare" function is incredibly slow (uses megamorphic field accessor)
|
|
71
|
-
// TODO: Implement a replacement for static data types
|
|
72
|
-
const comparator = sort ? compare(sort.field, sort.order) : undefined;
|
|
73
|
-
|
|
74
|
-
/** @param {any[]} data */
|
|
75
|
-
const sortData = (data) => {
|
|
76
|
-
if (comparator) {
|
|
77
|
-
data.sort(comparator);
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
if (this.params.groupby?.length) {
|
|
82
|
-
if (this.facetBatches.size > 1) {
|
|
83
|
-
throw new Error("TODO: Support faceted data!");
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const accessors = this.params.groupby.map((fieldName) =>
|
|
87
|
-
field(fieldName)
|
|
88
|
-
);
|
|
89
|
-
// @ts-ignore
|
|
90
|
-
const groups = group(this._data, ...accessors);
|
|
91
|
-
|
|
92
|
-
this.facetBatches.clear();
|
|
93
|
-
for (const [key, data] of iterateNestedMaps(groups)) {
|
|
94
|
-
this.facetBatches.set(key, data);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
for (const data of this.facetBatches.values()) {
|
|
99
|
-
// TODO: Only sort if not already sorted
|
|
100
|
-
sortData(data);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (this.children.length) {
|
|
104
|
-
for (const [key, data] of this.facetBatches.entries()) {
|
|
105
|
-
if (key) {
|
|
106
|
-
/** @type {import("./flowBatch").FacetBatch} */
|
|
107
|
-
const facetBatch = { type: "facet", facetId: key };
|
|
108
|
-
for (const child of this.children) {
|
|
109
|
-
child.beginBatch(facetBatch);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
for (const datum of data) {
|
|
113
|
-
this._propagate(datum);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
super.complete();
|
|
119
|
-
|
|
120
|
-
for (const observer of this.observers) {
|
|
121
|
-
observer(this);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* @returns {Iterable<import("./flowNode").Datum>}
|
|
127
|
-
*/
|
|
128
|
-
getData() {
|
|
129
|
-
this._checkStatus();
|
|
130
|
-
|
|
131
|
-
switch (this.facetBatches.size) {
|
|
132
|
-
case 0:
|
|
133
|
-
return [];
|
|
134
|
-
case 1:
|
|
135
|
-
return [...this.facetBatches.values()][0];
|
|
136
|
-
default: {
|
|
137
|
-
const groups = this.facetBatches;
|
|
138
|
-
return {
|
|
139
|
-
[Symbol.iterator]: function* generator() {
|
|
140
|
-
for (const data of groups.values()) {
|
|
141
|
-
for (let i = 0; i < data.length; i++) {
|
|
142
|
-
yield data[i];
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
*
|
|
153
|
-
* @param {(datum: import("./flowNode").Datum) => void} visitor
|
|
154
|
-
*/
|
|
155
|
-
visitData(visitor) {
|
|
156
|
-
this._checkStatus();
|
|
157
|
-
|
|
158
|
-
for (const data of this.facetBatches.values()) {
|
|
159
|
-
for (let i = 0; i < data.length; i++) {
|
|
160
|
-
visitor(data[i]);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Returns the total number of data items collected.
|
|
167
|
-
*/
|
|
168
|
-
getItemCount() {
|
|
169
|
-
let count = 0;
|
|
170
|
-
for (const data of this.facetBatches.values()) {
|
|
171
|
-
count += data.length;
|
|
172
|
-
}
|
|
173
|
-
return count;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
_checkStatus() {
|
|
177
|
-
if (!this.completed) {
|
|
178
|
-
throw new Error(
|
|
179
|
-
"Data propagation is not completed! No data are available."
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest";
|
|
2
|
-
|
|
3
|
-
import Collector from "./collector";
|
|
4
|
-
|
|
5
|
-
const data = [1, 5, 2, 4, 3].map((x) => ({ x }));
|
|
6
|
-
|
|
7
|
-
test("Collector collects data", () => {
|
|
8
|
-
const collector = new Collector();
|
|
9
|
-
|
|
10
|
-
for (const d of data) {
|
|
11
|
-
collector.handle(d);
|
|
12
|
-
}
|
|
13
|
-
collector.complete();
|
|
14
|
-
|
|
15
|
-
expect(collector.getData()).toEqual(data);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test("Collector collects and sorts data", () => {
|
|
19
|
-
const collector = new Collector({
|
|
20
|
-
type: "collect",
|
|
21
|
-
sort: { field: ["x"] },
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
for (const d of data) {
|
|
25
|
-
collector.handle(d);
|
|
26
|
-
}
|
|
27
|
-
collector.complete();
|
|
28
|
-
|
|
29
|
-
expect([...collector.getData()]).toEqual(
|
|
30
|
-
[1, 2, 3, 4, 5].map((x) => ({ x }))
|
|
31
|
-
);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test("Collector collects, groups, and sorts data", () => {
|
|
35
|
-
const collector = new Collector({
|
|
36
|
-
type: "collect",
|
|
37
|
-
sort: { field: ["x"] },
|
|
38
|
-
groupby: ["a", "b"],
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const data = [
|
|
42
|
-
{ a: 1, b: 1, x: 1 },
|
|
43
|
-
{ a: 1, b: 2, x: 2 },
|
|
44
|
-
{ a: 1, b: 2, x: 3 },
|
|
45
|
-
{ a: 2, b: 1, x: 4 },
|
|
46
|
-
{ a: 2, b: 1, x: 5 },
|
|
47
|
-
{ a: 2, b: 2, x: 6 },
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
for (const d of data) {
|
|
51
|
-
collector.handle(d);
|
|
52
|
-
}
|
|
53
|
-
collector.complete();
|
|
54
|
-
|
|
55
|
-
const cd = [...collector.getData()];
|
|
56
|
-
|
|
57
|
-
expect(cd.map((d) => ({ x: d.x }))).toEqual(
|
|
58
|
-
[1, 2, 3, 4, 5, 6].map((x) => ({ x }))
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
/** @param {any[]} group*/
|
|
62
|
-
const getGroupX = (group) =>
|
|
63
|
-
collector.facetBatches.get(group).map((d) => d.x);
|
|
64
|
-
|
|
65
|
-
expect(getGroupX([1, 1])).toEqual([1]);
|
|
66
|
-
expect(getGroupX([1, 2])).toEqual([2, 3]);
|
|
67
|
-
expect(getGroupX([2, 1])).toEqual([4, 5]);
|
|
68
|
-
expect(getGroupX([2, 2])).toEqual([6]);
|
|
69
|
-
|
|
70
|
-
expect(new Set(collector.facetBatches.keys())).toEqual(
|
|
71
|
-
new Set([
|
|
72
|
-
[1, 1],
|
|
73
|
-
[1, 2],
|
|
74
|
-
[2, 1],
|
|
75
|
-
[2, 2],
|
|
76
|
-
])
|
|
77
|
-
);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("Collector throws on incomplete flow", () => {
|
|
81
|
-
const collector = new Collector();
|
|
82
|
-
|
|
83
|
-
expect(() => collector.getData()).toThrow();
|
|
84
|
-
});
|
package/src/data/dataFlow.js
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* @typedef {import("./sources/dataSource").default} DataSource
|
|
4
|
-
* @typedef {import("./collector").default} Collector
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import NamedSource from "./sources/namedSource";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @template H A key (string, object, whatever) that is used to retrieve
|
|
11
|
-
* data sources and collectors.
|
|
12
|
-
*/
|
|
13
|
-
export default class DataFlow {
|
|
14
|
-
constructor() {
|
|
15
|
-
/** @type {Map<H, DataSource>} */
|
|
16
|
-
this._dataSourcesByHost = new Map();
|
|
17
|
-
|
|
18
|
-
/** @type {Map<H, Collector>} */
|
|
19
|
-
this._collectorsByHost = new Map();
|
|
20
|
-
|
|
21
|
-
/** @type {Map<H, (function(Collector):void)[]>} */
|
|
22
|
-
this._observers = new Map();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get dataSources() {
|
|
26
|
-
return [...new Set(this._dataSourcesByHost.values()).values()];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
get collectors() {
|
|
30
|
-
return [...this._collectorsByHost.values()];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Adds a callback function that will be called when a collector has completed.
|
|
35
|
-
*
|
|
36
|
-
* @param {function(Collector):void} callback
|
|
37
|
-
* @param {H} key
|
|
38
|
-
*/
|
|
39
|
-
addObserver(callback, key) {
|
|
40
|
-
let arr = this._observers.get(key);
|
|
41
|
-
if (!arr) {
|
|
42
|
-
arr = [];
|
|
43
|
-
this._observers.set(key, arr);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
arr.push(callback);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
* @param {Collector} collector
|
|
52
|
-
* @param {H} key
|
|
53
|
-
*/
|
|
54
|
-
_relayObserverCallback(collector, key) {
|
|
55
|
-
const arr = this._observers.get(key);
|
|
56
|
-
if (arr) {
|
|
57
|
-
for (const callback of arr) {
|
|
58
|
-
// eslint-disable-next-line callback-return
|
|
59
|
-
callback(collector);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
*
|
|
66
|
-
* @param {DataSource} dataSource
|
|
67
|
-
* @param {H} key
|
|
68
|
-
*/
|
|
69
|
-
addDataSource(dataSource, key) {
|
|
70
|
-
this._dataSourcesByHost.set(key, dataSource);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
*
|
|
75
|
-
* @param {H} key
|
|
76
|
-
*/
|
|
77
|
-
findDataSourceByKey(key) {
|
|
78
|
-
return this._dataSourcesByHost.get(key);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
*
|
|
83
|
-
* @param {string} name
|
|
84
|
-
*/
|
|
85
|
-
findNamedDataSource(name) {
|
|
86
|
-
/** @type {NamedSource} */
|
|
87
|
-
let namedSource;
|
|
88
|
-
/** @type {H[]} */
|
|
89
|
-
let hosts = [];
|
|
90
|
-
|
|
91
|
-
// Note: If a named sources with the same name are present at multiple locations in the
|
|
92
|
-
// view hierarchy, the should actually be exactly the same instance. It's arranged that
|
|
93
|
-
// way in the data flow optimization phase.
|
|
94
|
-
|
|
95
|
-
for (const [host, dataSource] of this._dataSourcesByHost.entries()) {
|
|
96
|
-
if (dataSource instanceof NamedSource) {
|
|
97
|
-
if (name == dataSource.identifier) {
|
|
98
|
-
if (namedSource && namedSource !== dataSource) {
|
|
99
|
-
// TODO: Write a test case for this and remove the runtime check.
|
|
100
|
-
throw new Error(
|
|
101
|
-
`Found multiple instances of named data: ${name}. Data flow optimization is broken (it's a bug).`
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
namedSource = dataSource;
|
|
105
|
-
hosts.push(host);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (namedSource) {
|
|
111
|
-
return {
|
|
112
|
-
dataSource: namedSource,
|
|
113
|
-
hosts,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
*
|
|
120
|
-
* @param {Collector} collector
|
|
121
|
-
* @param {H} key
|
|
122
|
-
*/
|
|
123
|
-
addCollector(collector, key) {
|
|
124
|
-
this._collectorsByHost.set(key, collector);
|
|
125
|
-
collector.observers.push((collector) =>
|
|
126
|
-
this._relayObserverCallback(collector, key)
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
*
|
|
132
|
-
* @param {H} key
|
|
133
|
-
*/
|
|
134
|
-
findCollectorByKey(key) {
|
|
135
|
-
return this._collectorsByHost.get(key);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Allows the flow nodes to perform final initialization after the flow
|
|
140
|
-
* structure has been built and optimized.
|
|
141
|
-
* Must be called before any data are to be propagated.
|
|
142
|
-
*/
|
|
143
|
-
initialize() {
|
|
144
|
-
for (const ds of this.dataSources) {
|
|
145
|
-
ds.visit((node) => node.initialize());
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
package/src/data/facetNode.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import FlowNode from "./flowNode";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {object} FacetParams
|
|
5
|
-
* @prop {string[]} groupby
|
|
6
|
-
*/
|
|
7
|
-
export default class FacetNode extends FlowNode {
|
|
8
|
-
/**
|
|
9
|
-
* @param {FacetParams} params
|
|
10
|
-
*/
|
|
11
|
-
constructor(params) {
|
|
12
|
-
super();
|
|
13
|
-
|
|
14
|
-
/** @type {Map<any | any[], FlowNode>} */
|
|
15
|
-
this.subflows = new Map();
|
|
16
|
-
}
|
|
17
|
-
}
|
package/src/data/flow.test.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
2
|
-
import FilterTransform from "./transforms/filter";
|
|
3
|
-
import FormulaTransform from "./transforms/formula";
|
|
4
|
-
import Collector from "./collector";
|
|
5
|
-
import { SynchronousSequenceSource } from "./flowTestUtils";
|
|
6
|
-
|
|
7
|
-
describe("Test flow graphs", () => {
|
|
8
|
-
test("Trivial graph: sequence to collector", () => {
|
|
9
|
-
const source = new SynchronousSequenceSource(5);
|
|
10
|
-
const collector = new Collector();
|
|
11
|
-
source.addChild(collector);
|
|
12
|
-
|
|
13
|
-
source.dispatch();
|
|
14
|
-
|
|
15
|
-
expect(collector.getData()).toEqual(
|
|
16
|
-
[0, 1, 2, 3, 4].map((d) => ({
|
|
17
|
-
data: d,
|
|
18
|
-
}))
|
|
19
|
-
);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test("Trivial branching: sequence to two collectors", () => {
|
|
23
|
-
const source = new SynchronousSequenceSource(5);
|
|
24
|
-
const collector1 = new Collector();
|
|
25
|
-
source.addChild(collector1);
|
|
26
|
-
const collector2 = new Collector();
|
|
27
|
-
source.addChild(collector2);
|
|
28
|
-
|
|
29
|
-
source.dispatch();
|
|
30
|
-
|
|
31
|
-
expect(collector1.getData()).not.toBe(collector2._data);
|
|
32
|
-
|
|
33
|
-
expect(collector1.getData()).toEqual(
|
|
34
|
-
[0, 1, 2, 3, 4].map((d) => ({
|
|
35
|
-
data: d,
|
|
36
|
-
}))
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
expect(collector2.getData()).toEqual(
|
|
40
|
-
[0, 1, 2, 3, 4].map((d) => ({
|
|
41
|
-
data: d,
|
|
42
|
-
}))
|
|
43
|
-
);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test("Longer chain of nodes", () => {
|
|
47
|
-
const source = new SynchronousSequenceSource(10);
|
|
48
|
-
const filter = new FilterTransform({
|
|
49
|
-
type: "filter",
|
|
50
|
-
expr: "datum.data < 5",
|
|
51
|
-
});
|
|
52
|
-
const formula = new FormulaTransform({
|
|
53
|
-
type: "formula",
|
|
54
|
-
expr: "datum.data * 2",
|
|
55
|
-
as: "data",
|
|
56
|
-
});
|
|
57
|
-
const collector = new Collector();
|
|
58
|
-
|
|
59
|
-
source.addChild(filter);
|
|
60
|
-
filter.addChild(formula);
|
|
61
|
-
formula.addChild(collector);
|
|
62
|
-
|
|
63
|
-
source.visit((node) => node.initialize());
|
|
64
|
-
source.dispatch();
|
|
65
|
-
|
|
66
|
-
expect(collector.getData()).toEqual(
|
|
67
|
-
[0, 2, 4, 6, 8].map((d) => ({
|
|
68
|
-
data: d,
|
|
69
|
-
}))
|
|
70
|
-
);
|
|
71
|
-
});
|
|
72
|
-
});
|
package/src/data/flowBatch.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Field } from "../spec/transform";
|
|
2
|
-
|
|
3
|
-
export interface FlowBatchBase {
|
|
4
|
-
type: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Indicates that the contents of a new file will be propagated. The fields of
|
|
9
|
-
* the file may or may not differ from the previous file. The data items within
|
|
10
|
-
* a single batch must have homogenous fields.
|
|
11
|
-
*
|
|
12
|
-
* FlowNodes can react to FileBatches and, for example, clear their internal
|
|
13
|
-
* states that expect specific fields in a specific layout.
|
|
14
|
-
*/
|
|
15
|
-
export interface FileBatch {
|
|
16
|
-
type: "file";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* An absolute or relative url where the file was loaded from.
|
|
20
|
-
*/
|
|
21
|
-
url?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Indicates that a new group/facet will be propagated. All data items that
|
|
26
|
-
* belong to a specific facet must be propagated within a single batch.
|
|
27
|
-
*/
|
|
28
|
-
export interface FacetBatch {
|
|
29
|
-
type: "facet";
|
|
30
|
-
|
|
31
|
-
facetId: any | any[];
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* The field or fields that were used for partitioning the data.
|
|
35
|
-
* May be missing if partitioning is not based on the fields.
|
|
36
|
-
*/
|
|
37
|
-
facetField?: Field | Field[];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type FlowBatch = FileBatch | FacetBatch;
|