@genome-spy/core 0.30.0 → 0.30.3
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 +16379 -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,101 +0,0 @@
|
|
|
1
|
-
import FlowNode from "../flowNode";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A reservoir sampler, based on: https://www.wikiwand.com/en/Reservoir_sampling
|
|
5
|
-
*
|
|
6
|
-
* @typedef {import("../../spec/transform").SampleParams} SampleParams
|
|
7
|
-
*/
|
|
8
|
-
export default class SampleTransform extends FlowNode {
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
* @param {SampleParams} params
|
|
12
|
-
*/
|
|
13
|
-
constructor(params) {
|
|
14
|
-
super();
|
|
15
|
-
|
|
16
|
-
this.k = params.size || 500;
|
|
17
|
-
this.reset();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
reset() {
|
|
21
|
-
super.reset();
|
|
22
|
-
|
|
23
|
-
/** @type {any[]} */
|
|
24
|
-
this.reservoir = [];
|
|
25
|
-
/** @type {number} */
|
|
26
|
-
this.W = undefined;
|
|
27
|
-
this.ingester = this._initialIngester;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
*
|
|
32
|
-
* @param {any} item
|
|
33
|
-
*/
|
|
34
|
-
_initialIngester(item) {
|
|
35
|
-
this.reservoir.push(item);
|
|
36
|
-
|
|
37
|
-
if (this.reservoir.length == this.k) {
|
|
38
|
-
this.W = Math.exp(Math.log(Math.random()) / this.k);
|
|
39
|
-
this.i = this.k;
|
|
40
|
-
this.next = this.i;
|
|
41
|
-
this.ingester = this._finalIngester;
|
|
42
|
-
this._setNextStop();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
*
|
|
48
|
-
* @param {any} item
|
|
49
|
-
*/
|
|
50
|
-
_finalIngester(item) {
|
|
51
|
-
if (++this.i == this.next) {
|
|
52
|
-
this.reservoir[Math.floor(Math.random() * this.k)] = item;
|
|
53
|
-
this.W *= Math.exp(Math.log(Math.random()) / this.k);
|
|
54
|
-
this._setNextStop();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
_setNextStop() {
|
|
59
|
-
this.next +=
|
|
60
|
-
Math.floor(Math.log(Math.random()) / Math.log(1 - this.W)) + 1;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
65
|
-
* @param {import("../flowNode").Datum} datum
|
|
66
|
-
*/
|
|
67
|
-
handle(datum) {
|
|
68
|
-
this.ingester(datum);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
complete() {
|
|
72
|
-
for (const datum of this.reservoir) {
|
|
73
|
-
this._propagate(datum);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
super.complete();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* A convenience function that uses SampleTransform to sample an iterable.
|
|
82
|
-
*
|
|
83
|
-
* @param {number} n
|
|
84
|
-
* @param {Iterable<T>} iterable
|
|
85
|
-
* @param {function(T):R} accessor
|
|
86
|
-
* @returns {R[]}
|
|
87
|
-
* @template T
|
|
88
|
-
* @template R
|
|
89
|
-
*/
|
|
90
|
-
export function sampleIterable(n, iterable, accessor) {
|
|
91
|
-
const sampler = new SampleTransform({
|
|
92
|
-
type: "sample",
|
|
93
|
-
size: n,
|
|
94
|
-
});
|
|
95
|
-
for (const d of iterable) {
|
|
96
|
-
sampler.handle(accessor(d));
|
|
97
|
-
}
|
|
98
|
-
sampler.complete();
|
|
99
|
-
|
|
100
|
-
return sampler.reservoir;
|
|
101
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest";
|
|
2
|
-
import SampleTransform from "./sample";
|
|
3
|
-
import { extent } from "d3-array";
|
|
4
|
-
import { createChain } from "../../view/flowBuilder";
|
|
5
|
-
|
|
6
|
-
test("SampleTransform produces roughly uniform distributions", () => {
|
|
7
|
-
const size = 10;
|
|
8
|
-
const n = 20;
|
|
9
|
-
const rounds = 10000;
|
|
10
|
-
|
|
11
|
-
const freqs = [];
|
|
12
|
-
for (let i = 0; i < n; i++) {
|
|
13
|
-
freqs[i] = 0;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const { dataSource, collector } = createChain(
|
|
17
|
-
new SampleTransform({ type: "sample", size })
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
for (let r = 0; r < rounds; r++) {
|
|
21
|
-
for (let i = 0; i < n; i++) {
|
|
22
|
-
dataSource.handle({ data: i });
|
|
23
|
-
}
|
|
24
|
-
dataSource.complete();
|
|
25
|
-
|
|
26
|
-
for (const datum of collector.getData()) {
|
|
27
|
-
freqs[datum.data] = freqs[datum.data] + 1;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
dataSource.reset();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const e = extent(freqs);
|
|
34
|
-
|
|
35
|
-
// Not a deterministic test! TODO: Come up with some sensical testing method
|
|
36
|
-
expect(e[0]).toBeGreaterThan(4800);
|
|
37
|
-
expect(e[1]).toBeLessThan(5200);
|
|
38
|
-
});
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { compare } from "vega-util";
|
|
2
|
-
import { groups as d3groups, sum as d3sum } from "d3-array";
|
|
3
|
-
import FlowNode, { BEHAVIOR_MODIFIES } from "../flowNode";
|
|
4
|
-
import { field } from "../../utils/field";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @typedef {import("../../spec/transform").StackParams} StackParams
|
|
8
|
-
*/
|
|
9
|
-
export default class StackTransform extends FlowNode {
|
|
10
|
-
get behavior() {
|
|
11
|
-
return BEHAVIOR_MODIFIES;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @param {StackParams} params
|
|
16
|
-
*/
|
|
17
|
-
constructor(params) {
|
|
18
|
-
super();
|
|
19
|
-
this.params = params;
|
|
20
|
-
|
|
21
|
-
/** @type {any[]} */
|
|
22
|
-
this.buffer = [];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
reset() {
|
|
26
|
-
this.buffer = [];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
*
|
|
31
|
-
* @param {import("../flowNode").Datum} datum
|
|
32
|
-
*/
|
|
33
|
-
handle(datum) {
|
|
34
|
-
this.buffer.push(datum);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
complete() {
|
|
38
|
-
const params = this.params;
|
|
39
|
-
|
|
40
|
-
const as = params.as || ["y0", "y1"]; // TODO: Validate
|
|
41
|
-
|
|
42
|
-
const comparator = params.sort
|
|
43
|
-
? compare(params.sort.field, params.sort.order)
|
|
44
|
-
: undefined;
|
|
45
|
-
|
|
46
|
-
const valueAccessor = params.field ? field(params.field) : () => 1;
|
|
47
|
-
|
|
48
|
-
const groupFields = params.groupby.map((f) => field(f));
|
|
49
|
-
|
|
50
|
-
const groups = d3groups(this.buffer, (row) =>
|
|
51
|
-
groupFields.map((f) => f(row)).join()
|
|
52
|
-
).map((a) => a[1]);
|
|
53
|
-
|
|
54
|
-
/** @type {(datum: any) => boolean} */
|
|
55
|
-
let inclusionPredicate = (_datum) => true;
|
|
56
|
-
|
|
57
|
-
if (params.baseField) {
|
|
58
|
-
const baseAccessor = field(params.baseField);
|
|
59
|
-
inclusionPredicate = (datum) => baseAccessor(datum) !== null;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** @type {(value: number, sum: number) => number} */
|
|
63
|
-
let offsetF;
|
|
64
|
-
|
|
65
|
-
/** @type {(values: number[], accessor: (datum: any) => number) => number} */
|
|
66
|
-
let sumF;
|
|
67
|
-
|
|
68
|
-
switch (params.offset) {
|
|
69
|
-
case "normalize":
|
|
70
|
-
offsetF = (value, sum) => value / sum;
|
|
71
|
-
sumF = (values, accessor) => d3sum(values, accessor);
|
|
72
|
-
break;
|
|
73
|
-
case "center":
|
|
74
|
-
offsetF = (value, sum) => value - sum / 2;
|
|
75
|
-
sumF = (values, accessor) => d3sum(values, accessor);
|
|
76
|
-
break;
|
|
77
|
-
case "information":
|
|
78
|
-
{
|
|
79
|
-
// Sequence logos: a new way to display consensus sequences (Schneider and Stephens)
|
|
80
|
-
// doi://10.1093/nar/18.20.6097
|
|
81
|
-
|
|
82
|
-
const maxBits = Math.log2(params.cardinality ?? 4);
|
|
83
|
-
offsetF = (value, sum) => value / sum;
|
|
84
|
-
sumF = (values, accessor) => {
|
|
85
|
-
const e = 0; // TODO: Correction factor for small sample sizes
|
|
86
|
-
|
|
87
|
-
const gaps = d3sum(
|
|
88
|
-
values,
|
|
89
|
-
(d) => +!inclusionPredicate(d)
|
|
90
|
-
);
|
|
91
|
-
const total = d3sum(values, accessor);
|
|
92
|
-
const nonGaps = total - gaps;
|
|
93
|
-
|
|
94
|
-
let H = 0;
|
|
95
|
-
for (let i = 0; i < values.length; i++) {
|
|
96
|
-
const datum = values[i];
|
|
97
|
-
if (inclusionPredicate(datum)) {
|
|
98
|
-
const b = accessor(datum) / nonGaps;
|
|
99
|
-
H -= b * Math.log2(b);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return (
|
|
104
|
-
(nonGaps / (maxBits - (H + e))) * (nonGaps / total)
|
|
105
|
-
);
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
break;
|
|
109
|
-
default:
|
|
110
|
-
offsetF = (value, sum) => value;
|
|
111
|
-
sumF = (_values, _accessor) => 1;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
for (const group of groups) {
|
|
115
|
-
if (comparator) {
|
|
116
|
-
group.sort(comparator);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const sum = sumF(group, valueAccessor);
|
|
120
|
-
|
|
121
|
-
let prev = 0;
|
|
122
|
-
for (const datum of group) {
|
|
123
|
-
const current = prev + valueAccessor(datum);
|
|
124
|
-
|
|
125
|
-
if (inclusionPredicate(datum)) {
|
|
126
|
-
datum[as[0]] = offsetF(prev, sum);
|
|
127
|
-
datum[as[1]] = offsetF(current, sum);
|
|
128
|
-
|
|
129
|
-
this._propagate(datum);
|
|
130
|
-
prev = current;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
super.complete();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
2
|
-
import { processData } from "../flowTestUtils";
|
|
3
|
-
import StackTransform from "./stack";
|
|
4
|
-
|
|
5
|
-
const sampleData = [
|
|
6
|
-
{ group: "a", choice: "q", value: 1 },
|
|
7
|
-
{ group: "b", choice: "x", value: 1 },
|
|
8
|
-
{ group: "b", choice: "y", value: 3 },
|
|
9
|
-
];
|
|
10
|
-
|
|
11
|
-
/** @type {import("./stack").StackParams} */
|
|
12
|
-
const baseConf = {
|
|
13
|
-
type: "stack",
|
|
14
|
-
field: "value",
|
|
15
|
-
groupby: ["group"],
|
|
16
|
-
sort: {
|
|
17
|
-
field: "value",
|
|
18
|
-
order: "ascending",
|
|
19
|
-
},
|
|
20
|
-
offset: "zero",
|
|
21
|
-
as: ["z0", "z1"],
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
* @param {import("./stack").StackParams} params
|
|
27
|
-
* @param {any[]} data
|
|
28
|
-
*/
|
|
29
|
-
function transform(params, data) {
|
|
30
|
-
return processData(new StackTransform(params), data);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
describe("Stack transform", () => {
|
|
34
|
-
test("No field", () => {
|
|
35
|
-
const conf = Object.assign({}, baseConf, {
|
|
36
|
-
field: undefined,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
expect(transform(conf, sampleData)).toEqual([
|
|
40
|
-
{ group: "a", choice: "q", value: 1, z0: 0, z1: 1 },
|
|
41
|
-
{ group: "b", choice: "x", value: 1, z0: 0, z1: 1 },
|
|
42
|
-
{ group: "b", choice: "y", value: 3, z0: 1, z1: 2 },
|
|
43
|
-
]);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test("Zero offset", () => {
|
|
47
|
-
expect(transform(baseConf, sampleData)).toEqual([
|
|
48
|
-
{ group: "a", choice: "q", value: 1, z0: 0, z1: 1 },
|
|
49
|
-
{ group: "b", choice: "x", value: 1, z0: 0, z1: 1 },
|
|
50
|
-
{ group: "b", choice: "y", value: 3, z0: 1, z1: 4 },
|
|
51
|
-
]);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test("Normalize offset", () => {
|
|
55
|
-
const conf = Object.assign({}, baseConf, {
|
|
56
|
-
offset: "normalize",
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
expect(transform(conf, sampleData)).toEqual([
|
|
60
|
-
{ group: "a", choice: "q", value: 1, z0: 0, z1: 1 },
|
|
61
|
-
{ group: "b", choice: "x", value: 1, z0: 0, z1: 0.25 },
|
|
62
|
-
{ group: "b", choice: "y", value: 3, z0: 0.25, z1: 1 },
|
|
63
|
-
]);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test("Center offset", () => {
|
|
67
|
-
const conf = Object.assign({}, baseConf, {
|
|
68
|
-
offset: "center",
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
expect(transform(conf, sampleData)).toEqual([
|
|
72
|
-
{ group: "a", choice: "q", value: 1, z0: -0.5, z1: 0.5 },
|
|
73
|
-
{ group: "b", choice: "x", value: 1, z0: -2, z1: -1 },
|
|
74
|
-
{ group: "b", choice: "y", value: 3, z0: -1, z1: 2 },
|
|
75
|
-
]);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test("Descending sort", () => {
|
|
79
|
-
const conf = Object.assign({}, baseConf, {
|
|
80
|
-
sort: {
|
|
81
|
-
field: "value",
|
|
82
|
-
order: "descending",
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
expect(transform(conf, sampleData)).toEqual([
|
|
86
|
-
{ group: "a", choice: "q", value: 1, z0: 0, z1: 1 },
|
|
87
|
-
{ group: "b", choice: "y", value: 3, z0: 0, z1: 3 },
|
|
88
|
-
{ group: "b", choice: "x", value: 1, z0: 3, z1: 4 },
|
|
89
|
-
]);
|
|
90
|
-
});
|
|
91
|
-
});
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import Collector from "../collector";
|
|
2
|
-
import CoverageTransform from "./coverage";
|
|
3
|
-
import FilterScoredLabelsTransform from "./filterScoredLabels";
|
|
4
|
-
import FilterTransform from "./filter";
|
|
5
|
-
import FlattenCompressedExonsTransform from "./flattenCompressedExons";
|
|
6
|
-
import FlattenDelimitedTransform from "./flattenDelimited";
|
|
7
|
-
import FormulaTransform from "./formula";
|
|
8
|
-
import LinearizeGenomicCoordinate from "./linearizeGenomicCoordinate";
|
|
9
|
-
import MeasureTextTransform from "./measureText";
|
|
10
|
-
import PileupTransform from "./pileup";
|
|
11
|
-
import ProjectTransform from "./project";
|
|
12
|
-
import RegexExtractTransform from "./regexExtract";
|
|
13
|
-
import RegexFoldTransform from "./regexFold";
|
|
14
|
-
import SampleTransform from "./sample";
|
|
15
|
-
import StackTransform from "./stack";
|
|
16
|
-
import FlattenSequenceTransform from "./flattenSequence";
|
|
17
|
-
import AggregateTransform from "./aggregate";
|
|
18
|
-
import IdentifierTransform from "./identifier";
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* TODO: Make this dynamic
|
|
22
|
-
*
|
|
23
|
-
* @typedef {import("../../view/view").default} View
|
|
24
|
-
* @typedef {import("../flowNode").default} FlowNode
|
|
25
|
-
*
|
|
26
|
-
* @type {Record<string, new (params: any, view?: View) => FlowNode>}
|
|
27
|
-
*/
|
|
28
|
-
export const transforms = {
|
|
29
|
-
aggregate: AggregateTransform,
|
|
30
|
-
collect: Collector,
|
|
31
|
-
coverage: CoverageTransform,
|
|
32
|
-
filterScoredLabels: FilterScoredLabelsTransform,
|
|
33
|
-
filter: FilterTransform,
|
|
34
|
-
flattenCompressedExons: FlattenCompressedExonsTransform,
|
|
35
|
-
flattenDelimited: FlattenDelimitedTransform,
|
|
36
|
-
flattenSequence: FlattenSequenceTransform,
|
|
37
|
-
formula: FormulaTransform,
|
|
38
|
-
identifier: IdentifierTransform,
|
|
39
|
-
linearizeGenomicCoordinate: LinearizeGenomicCoordinate,
|
|
40
|
-
measureText: MeasureTextTransform,
|
|
41
|
-
pileup: PileupTransform,
|
|
42
|
-
project: ProjectTransform,
|
|
43
|
-
regexExtract: RegexExtractTransform,
|
|
44
|
-
regexFold: RegexFoldTransform,
|
|
45
|
-
sample: SampleTransform,
|
|
46
|
-
stack: StackTransform,
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @param {import("../../spec/transform").TransformParamsBase} params
|
|
51
|
-
* @param {View} [view]
|
|
52
|
-
*/
|
|
53
|
-
export default function createTransform(params, view) {
|
|
54
|
-
const Transform = transforms[params.type];
|
|
55
|
-
if (Transform) {
|
|
56
|
-
return new Transform(params, view);
|
|
57
|
-
} else {
|
|
58
|
-
throw new Error("Unknown transform: " + params.type);
|
|
59
|
-
}
|
|
60
|
-
}
|
package/src/embedApi.d.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { ScaleResolutionApi } from "./view/scaleResolutionApi";
|
|
2
|
-
import { TooltipHandler } from "./tooltip/tooltipHandler";
|
|
3
|
-
import { RootSpec } from "./spec/root";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Embeds GenomeSpy into the DOM
|
|
7
|
-
*
|
|
8
|
-
* @param el HTMLElement or a query selector
|
|
9
|
-
* @param spec A spec object or an URL to a JSON spec
|
|
10
|
-
* @param options Options
|
|
11
|
-
*/
|
|
12
|
-
export type EmbedFunction = (
|
|
13
|
-
el: HTMLElement | string,
|
|
14
|
-
spec: RootSpec | string,
|
|
15
|
-
options?: EmbedOptions
|
|
16
|
-
) => EmbedResult;
|
|
17
|
-
|
|
18
|
-
export interface EmbedOptions {
|
|
19
|
-
/**
|
|
20
|
-
* A function that allows retrieval of named data. There are two ways to provide named data:
|
|
21
|
-
* 1. A data provider (this)
|
|
22
|
-
* 2. Explicit updates using the `updateNamedData` method (the other).
|
|
23
|
-
*/
|
|
24
|
-
namedDataProvider?: (name: string) => any[];
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Custom tooltip handlers. Use `"default"` to override the default handler
|
|
28
|
-
*/
|
|
29
|
-
tooltipHandlers?: Record<string, TooltipHandler>;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* An API for controlling the embedded GenomeSpy instance.
|
|
34
|
-
*/
|
|
35
|
-
export interface EmbedResult {
|
|
36
|
-
/**
|
|
37
|
-
* Releases all resources and unregisters event listeners, etc.
|
|
38
|
-
*/
|
|
39
|
-
finalize: () => void;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Adds an event listener, which is called when the user interacts with a mark
|
|
43
|
-
* instance. Currently, only `"click"` events are supported. The callback receives
|
|
44
|
-
* an event object as its first (and only) parameter. Its `datum` property
|
|
45
|
-
* contains the datum that the user interacted with.
|
|
46
|
-
*/
|
|
47
|
-
addEventListener: (type: string, listener: (event: any) => void) => void;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Removes a registered event listener.
|
|
51
|
-
*/
|
|
52
|
-
removeEventListener: (type: string, listener: (event: any) => void) => void;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Returns a named `ScaleResolution` object that allows for attaching event
|
|
56
|
-
* listeners and controlling the scale domain.
|
|
57
|
-
*/
|
|
58
|
-
getScaleResolutionByName: (name: string) => ScaleResolutionApi;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Updates a named dataset
|
|
62
|
-
*
|
|
63
|
-
* @param name data source to update
|
|
64
|
-
* @param data new data. If left undefined, the data is retrieved from a provider.
|
|
65
|
-
*/
|
|
66
|
-
updateNamedData: (name: string, data?: any[]) => void;
|
|
67
|
-
}
|
package/src/encoder/accessor.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import createFunction from "../utils/expression";
|
|
2
|
-
|
|
3
|
-
import { accessorFields, constant } from "vega-util";
|
|
4
|
-
import { isDatumDef, isExprDef, isFieldDef } from "./encoder";
|
|
5
|
-
import { field } from "../utils/field";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {Object} AccessorMetadata
|
|
9
|
-
* @prop {boolean} constant True if the accessor returns the same value for all objects
|
|
10
|
-
* @prop {string[]} fields The fields that the return value is based on (if any)
|
|
11
|
-
*
|
|
12
|
-
* @typedef {(function(any):any) & AccessorMetadata} Accessor
|
|
13
|
-
*
|
|
14
|
-
* @typedef {import("../view/viewUtils").ChannelDef} ChannelDef
|
|
15
|
-
*/
|
|
16
|
-
export default class AccessorFactory {
|
|
17
|
-
constructor() {
|
|
18
|
-
/** @type {(function(ChannelDef):Accessor)[]} */
|
|
19
|
-
this.accessorCreators = [];
|
|
20
|
-
|
|
21
|
-
this.register((channelDef) => {
|
|
22
|
-
if (isFieldDef(channelDef)) {
|
|
23
|
-
try {
|
|
24
|
-
const accessor = /** @type {Accessor} */ (
|
|
25
|
-
field(channelDef.field)
|
|
26
|
-
);
|
|
27
|
-
accessor.constant = false;
|
|
28
|
-
accessor.fields = accessorFields(accessor);
|
|
29
|
-
return accessor;
|
|
30
|
-
} catch (e) {
|
|
31
|
-
throw new Error(`Invalid field definition: ${e.message}`);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
this.register((channelDef) =>
|
|
37
|
-
isExprDef(channelDef)
|
|
38
|
-
? createExpressionAccessor(channelDef.expr)
|
|
39
|
-
: undefined
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
this.register((channelDef) => {
|
|
43
|
-
if (isDatumDef(channelDef)) {
|
|
44
|
-
const c = /** @type {any} */ (constant(channelDef.datum));
|
|
45
|
-
const accessor = /** @type {Accessor} */ (c);
|
|
46
|
-
accessor.constant = true; // Can be optimized downstream
|
|
47
|
-
accessor.fields = [];
|
|
48
|
-
return accessor;
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
*
|
|
55
|
-
* @param {function(ChannelDef):Accessor} creator
|
|
56
|
-
*/
|
|
57
|
-
register(creator) {
|
|
58
|
-
this.accessorCreators.push(creator);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
*
|
|
63
|
-
* @param {ChannelDef} encoding
|
|
64
|
-
*/
|
|
65
|
-
createAccessor(encoding) {
|
|
66
|
-
for (const creator of this.accessorCreators) {
|
|
67
|
-
const accessor = creator(encoding);
|
|
68
|
-
if (accessor) {
|
|
69
|
-
return accessor;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* @param {string} expr
|
|
77
|
-
*/
|
|
78
|
-
function createExpressionAccessor(expr) {
|
|
79
|
-
const accessor = /** @type {Accessor} */ (createFunction(expr));
|
|
80
|
-
accessor.constant = accessor.fields.length == 0; // Not bulletproof, eh
|
|
81
|
-
return accessor;
|
|
82
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "vitest";
|
|
2
|
-
import AccessorFactory from "./accessor";
|
|
3
|
-
|
|
4
|
-
const af = new AccessorFactory();
|
|
5
|
-
|
|
6
|
-
const datum = {
|
|
7
|
-
a: 1,
|
|
8
|
-
b: 2,
|
|
9
|
-
"x.c": 3,
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
test("Creates a field accessor", () => {
|
|
13
|
-
const a = af.createAccessor({ field: "a" });
|
|
14
|
-
expect(a(datum)).toEqual(1);
|
|
15
|
-
expect(a.constant).toBeFalsy();
|
|
16
|
-
expect(a.fields).toEqual(["a"]);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("Creates an expression accessor", () => {
|
|
20
|
-
const a = af.createAccessor({ expr: `datum.b + datum['x\.c']` });
|
|
21
|
-
expect(a(datum)).toEqual(5);
|
|
22
|
-
expect(a.constant).toBeFalsy();
|
|
23
|
-
expect(a.fields.sort()).toEqual(["b", "x.c"].sort());
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("Creates a constant accessor", () => {
|
|
27
|
-
const a = af.createAccessor({ datum: 0 });
|
|
28
|
-
expect(a(datum)).toEqual(0);
|
|
29
|
-
expect(a.constant).toBeTruthy();
|
|
30
|
-
expect(a.fields).toEqual([]);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test("Returns undefined on incomplete encoding spec", () => {
|
|
34
|
-
expect(af.createAccessor({})).toBeUndefined();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("Registers and creates a custom accessor", () => {
|
|
38
|
-
const af = new AccessorFactory();
|
|
39
|
-
af.register((encoding) => {
|
|
40
|
-
if (encoding.iddqd && encoding.idkfa) {
|
|
41
|
-
return (datum) =>
|
|
42
|
-
`${datum[encoding.iddqd]}-${datum[encoding.idkfa]}`;
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
expect(af.createAccessor({ iddqd: "a", idkfa: "b" })(datum)).toEqual("1-2");
|
|
47
|
-
});
|