@genome-spy/core 0.18.1 → 0.19.0
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.js +29 -29
- package/package.json +2 -2
- package/src/data/collector.js +9 -4
- package/src/data/flowOptimizer.js +6 -0
- package/src/genome/genome.js +14 -2
- package/src/genome/genome.test.js +35 -0
- package/src/view/unitView.js +8 -4
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"contributors": [],
|
|
9
9
|
"license": "BSD-2-Clause",
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.19.0",
|
|
11
11
|
"main": "dist/index.js",
|
|
12
12
|
"module": "src/index.js",
|
|
13
13
|
"exports": {
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"vega-scale": "^7.1.1",
|
|
53
53
|
"vega-util": "^1.16.0"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "282eb640bf4c29be3755ef5de3992b8d76ad5f4c"
|
|
56
56
|
}
|
package/src/data/collector.js
CHANGED
|
@@ -27,7 +27,7 @@ export default class Collector extends FlowNode {
|
|
|
27
27
|
/** @type {(function(Collector):void)[]} */
|
|
28
28
|
this.observers = [];
|
|
29
29
|
|
|
30
|
-
/** @type {Map<any | any[], Data>} */
|
|
30
|
+
/** @type {Map<any | any[], Data>} TODO: proper type for key */
|
|
31
31
|
this.facetBatches = undefined;
|
|
32
32
|
|
|
33
33
|
this._init();
|
|
@@ -59,8 +59,6 @@ export default class Collector extends FlowNode {
|
|
|
59
59
|
* @param {import("./flowBatch").FlowBatch} flowBatch
|
|
60
60
|
*/
|
|
61
61
|
beginBatch(flowBatch) {
|
|
62
|
-
// TODO: Propagate batches to children(?)
|
|
63
|
-
|
|
64
62
|
if (isFacetBatch(flowBatch)) {
|
|
65
63
|
this._data = [];
|
|
66
64
|
this.facetBatches.set(asArray(flowBatch.facetId), this._data);
|
|
@@ -103,7 +101,14 @@ export default class Collector extends FlowNode {
|
|
|
103
101
|
}
|
|
104
102
|
|
|
105
103
|
if (this.children.length) {
|
|
106
|
-
for (const data of this.facetBatches.
|
|
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
|
+
}
|
|
107
112
|
for (const datum of data) {
|
|
108
113
|
this._propagate(datum);
|
|
109
114
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Collector from "./collector";
|
|
1
2
|
import { BEHAVIOR_CLONES } from "./flowNode";
|
|
2
3
|
import CloneTransform from "./transforms/clone";
|
|
3
4
|
|
|
@@ -31,6 +32,11 @@ export function validateLinks(node, parent = undefined) {
|
|
|
31
32
|
* @param {FlowNode} node
|
|
32
33
|
*/
|
|
33
34
|
export function removeRedundantCloneTransforms(node, cloneRequired = false) {
|
|
35
|
+
if (node instanceof Collector) {
|
|
36
|
+
// If an object is modified downstream of Collector, it must be cloned
|
|
37
|
+
cloneRequired = true;
|
|
38
|
+
}
|
|
39
|
+
|
|
34
40
|
if (node instanceof CloneTransform) {
|
|
35
41
|
if (cloneRequired) {
|
|
36
42
|
cloneRequired = false;
|
package/src/genome/genome.js
CHANGED
|
@@ -257,15 +257,27 @@ export default class Genome {
|
|
|
257
257
|
parseInterval(str) {
|
|
258
258
|
// TODO: consider changing [0-9XY] to support other species besides humans
|
|
259
259
|
const matches = str.match(
|
|
260
|
-
/^(chr[0-9A-Z]+)
|
|
260
|
+
/^(chr[0-9A-Z]+)(?::([0-9,]+)(?:-(?:(chr[0-9A-Z]+):)?([0-9,]+))?)?$/
|
|
261
261
|
);
|
|
262
262
|
|
|
263
263
|
if (matches) {
|
|
264
264
|
const startChr = matches[1];
|
|
265
|
+
|
|
266
|
+
if (matches.slice(2).every((x) => x === undefined)) {
|
|
267
|
+
const chrom = this.getChromosome(startChr);
|
|
268
|
+
if (chrom) {
|
|
269
|
+
return [chrom.continuousStart, chrom.continuousEnd];
|
|
270
|
+
}
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
265
274
|
const endChr = matches[3] || startChr;
|
|
266
275
|
|
|
267
276
|
const startIndex = parseInt(matches[2].replace(/,/g, ""));
|
|
268
|
-
const endIndex =
|
|
277
|
+
const endIndex =
|
|
278
|
+
matches[4] !== undefined
|
|
279
|
+
? parseInt(matches[4].replace(/,/g, ""))
|
|
280
|
+
: startIndex;
|
|
269
281
|
|
|
270
282
|
return [
|
|
271
283
|
this.toContinuous(startChr, startIndex - 1),
|
|
@@ -150,3 +150,38 @@ describe("C. elegans genome, chromosome names prefixed with 'chr'", () => {
|
|
|
150
150
|
expect(g.toContinuous("III", 10)).toEqual(30351865);
|
|
151
151
|
});
|
|
152
152
|
});
|
|
153
|
+
|
|
154
|
+
describe("Parse interval strings", () => {
|
|
155
|
+
const chromosomes = [
|
|
156
|
+
{ name: "chr1", size: 1000 },
|
|
157
|
+
{ name: "chr2", size: 2000 },
|
|
158
|
+
{ name: "chr3", size: 3000 },
|
|
159
|
+
{ name: "chrX", size: 4000 },
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
const g = new Genome({ name: "random", contigs: chromosomes });
|
|
163
|
+
|
|
164
|
+
test("Parses a single chromosome, returns an interval spanning the chromosome", () => {
|
|
165
|
+
expect(g.parseInterval("chr2")).toEqual([1000, 3000]);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test("Returns undefined on unknown chromosome", () => {
|
|
169
|
+
expect(g.parseInterval("chrZ")).toBeUndefined();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test("Parses a single coordinate without a thousand separator", () => {
|
|
173
|
+
expect(g.parseInterval("chr2:1500")).toEqual([2499, 2500]);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test("Parses a single coordinate with a thousand separator", () => {
|
|
177
|
+
expect(g.parseInterval("chr2:1,500")).toEqual([2499, 2500]);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("Parses an interval within a single chromosome", () => {
|
|
181
|
+
expect(g.parseInterval("chr2:1,500-1,700")).toEqual([2499, 2700]);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("Parses an interval spanning multiple chromosomes", () => {
|
|
185
|
+
expect(g.parseInterval("chr2:1,500-chr3:1,500")).toEqual([2499, 4500]);
|
|
186
|
+
});
|
|
187
|
+
});
|
package/src/view/unitView.js
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
import createDomain from "../utils/domainArray";
|
|
18
18
|
import AxisResolution from "./axisResolution";
|
|
19
19
|
import { isAggregateSamplesSpec } from "./viewFactory";
|
|
20
|
+
import { peek } from "../utils/arrayUtils";
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
*
|
|
@@ -337,10 +338,13 @@ export default class UnitView extends ContainerView {
|
|
|
337
338
|
if (isAggregateSamplesSpec(this.spec)) {
|
|
338
339
|
// TODO: Support multiple
|
|
339
340
|
for (const sumSpec of this.spec.aggregateSamples) {
|
|
340
|
-
sumSpec.transform
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
341
|
+
const transform = sumSpec.transform ?? [];
|
|
342
|
+
if (transform.length && peek(transform).type != "collect") {
|
|
343
|
+
// MergeFacets must be a direct child of Collector
|
|
344
|
+
transform.push({ type: "collect" });
|
|
345
|
+
}
|
|
346
|
+
transform.push({ type: "mergeFacets" });
|
|
347
|
+
sumSpec.transform = transform;
|
|
344
348
|
|
|
345
349
|
sumSpec.encoding = {
|
|
346
350
|
...(sumSpec.encoding ?? {}),
|