@genome-spy/core 0.50.2 → 0.52.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/bundle/index.es.js +3128 -3000
- package/dist/bundle/index.js +216 -94
- package/dist/schema.json +52 -11
- package/dist/src/genome/genome.d.ts +24 -2
- package/dist/src/genome/genome.d.ts.map +1 -1
- package/dist/src/genome/genome.js +66 -28
- package/dist/src/genome/genome.test.js +43 -1
- package/dist/src/genome/genomes.d.ts +8 -0
- package/dist/src/genome/genomes.d.ts.map +1 -0
- package/dist/src/genome/genomes.js +164 -0
- package/dist/src/genome/genomes.test.d.ts +2 -0
- package/dist/src/genome/genomes.test.d.ts.map +1 -0
- package/dist/src/genome/genomes.test.js +8 -0
- package/dist/src/spec/genome.d.ts +19 -6
- package/dist/src/utils/addBaseUrl.d.ts +6 -0
- package/dist/src/utils/addBaseUrl.d.ts.map +1 -1
- package/dist/src/utils/addBaseUrl.js +18 -0
- package/dist/src/utils/addBaseUrl.test.js +9 -1
- package/dist/src/view/layerView.d.ts.map +1 -1
- package/dist/src/view/layerView.js +4 -1
- package/dist/src/view/paramMediator.d.ts +7 -2
- package/dist/src/view/paramMediator.d.ts.map +1 -1
- package/dist/src/view/paramMediator.js +3 -1
- package/dist/src/view/view.d.ts +20 -3
- package/dist/src/view/view.d.ts.map +1 -1
- package/dist/src/view/view.js +30 -2
- package/dist/src/view/view.test.js +15 -5
- package/dist/src/view/viewUtils.d.ts +0 -1
- package/dist/src/view/viewUtils.d.ts.map +1 -1
- package/dist/src/view/viewUtils.js +0 -5
- package/package.json +2 -2
package/dist/schema.json
CHANGED
|
@@ -2843,19 +2843,21 @@
|
|
|
2843
2843
|
"type": "object"
|
|
2844
2844
|
},
|
|
2845
2845
|
"GenomeConfig": {
|
|
2846
|
-
"
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
"description": "Base url of data files: chromsizes, cytobands, and gene annotations.\n\n**Default:** `\"https://genomespy.app/data/genomes/\"`",
|
|
2850
|
-
"type": "string"
|
|
2846
|
+
"anyOf": [
|
|
2847
|
+
{
|
|
2848
|
+
"$ref": "#/definitions/UrlGenomeConfig"
|
|
2851
2849
|
},
|
|
2852
|
-
|
|
2853
|
-
"
|
|
2854
|
-
"items": {
|
|
2855
|
-
"$ref": "#/definitions/Contig"
|
|
2856
|
-
},
|
|
2857
|
-
"type": "array"
|
|
2850
|
+
{
|
|
2851
|
+
"$ref": "#/definitions/InlineGenomeConfig"
|
|
2858
2852
|
},
|
|
2853
|
+
{
|
|
2854
|
+
"$ref": "#/definitions/GenomeConfigBase"
|
|
2855
|
+
}
|
|
2856
|
+
]
|
|
2857
|
+
},
|
|
2858
|
+
"GenomeConfigBase": {
|
|
2859
|
+
"additionalProperties": false,
|
|
2860
|
+
"properties": {
|
|
2859
2861
|
"name": {
|
|
2860
2862
|
"description": "Name of the genome assembly, e.g., `hg19` or `hg38`.",
|
|
2861
2863
|
"type": "string"
|
|
@@ -3286,6 +3288,27 @@
|
|
|
3286
3288
|
}
|
|
3287
3289
|
]
|
|
3288
3290
|
},
|
|
3291
|
+
"InlineGenomeConfig": {
|
|
3292
|
+
"additionalProperties": false,
|
|
3293
|
+
"properties": {
|
|
3294
|
+
"contigs": {
|
|
3295
|
+
"description": "An array of contigs/sequences in the genome assembly.",
|
|
3296
|
+
"items": {
|
|
3297
|
+
"$ref": "#/definitions/Contig"
|
|
3298
|
+
},
|
|
3299
|
+
"type": "array"
|
|
3300
|
+
},
|
|
3301
|
+
"name": {
|
|
3302
|
+
"description": "Name of the genome assembly, e.g., `hg19` or `hg38`.",
|
|
3303
|
+
"type": "string"
|
|
3304
|
+
}
|
|
3305
|
+
},
|
|
3306
|
+
"required": [
|
|
3307
|
+
"contigs",
|
|
3308
|
+
"name"
|
|
3309
|
+
],
|
|
3310
|
+
"type": "object"
|
|
3311
|
+
},
|
|
3289
3312
|
"IntervalSelectionConfig": {
|
|
3290
3313
|
"additionalProperties": false,
|
|
3291
3314
|
"properties": {
|
|
@@ -8385,6 +8408,24 @@
|
|
|
8385
8408
|
],
|
|
8386
8409
|
"type": "object"
|
|
8387
8410
|
},
|
|
8411
|
+
"UrlGenomeConfig": {
|
|
8412
|
+
"additionalProperties": false,
|
|
8413
|
+
"properties": {
|
|
8414
|
+
"name": {
|
|
8415
|
+
"description": "Name of the genome assembly, e.g., `hg19` or `hg38`.",
|
|
8416
|
+
"type": "string"
|
|
8417
|
+
},
|
|
8418
|
+
"url": {
|
|
8419
|
+
"description": "A URL to a `chrom.sizes` file, which is a tab-separated file with two columns: the sequence name and its size.\n\nYou may want to strip alternative loci, haplotypes, and other non-canonical contigs from the file.\n\nExample: `\"https://genomespy.app/data/genomes/hg19/chrom.sizes\"`",
|
|
8420
|
+
"type": "string"
|
|
8421
|
+
}
|
|
8422
|
+
},
|
|
8423
|
+
"required": [
|
|
8424
|
+
"name",
|
|
8425
|
+
"url"
|
|
8426
|
+
],
|
|
8427
|
+
"type": "object"
|
|
8428
|
+
},
|
|
8388
8429
|
"UrlImport": {
|
|
8389
8430
|
"additionalProperties": false,
|
|
8390
8431
|
"properties": {
|
|
@@ -18,6 +18,21 @@ export function isChromosomalLocus(value: any): value is import("../spec/genome.
|
|
|
18
18
|
* @return {value is ChromosomalLocus[]}
|
|
19
19
|
*/
|
|
20
20
|
export function isChromosomalLocusInterval(value: any[]): value is import("../spec/genome.js").ChromosomalLocus[];
|
|
21
|
+
/**
|
|
22
|
+
* @param {any} value
|
|
23
|
+
* @returns {value is GenomeConfig}
|
|
24
|
+
*/
|
|
25
|
+
export function isGenomeConfig(value: any): value is import("../spec/genome.js").GenomeConfig;
|
|
26
|
+
/**
|
|
27
|
+
* @param {any} value
|
|
28
|
+
* @returns {value is import("../spec/genome.js").UrlGenomeConfig }
|
|
29
|
+
*/
|
|
30
|
+
export function isUrlGenomeConfig(value: any): value is import("../spec/genome.js").UrlGenomeConfig;
|
|
31
|
+
/**
|
|
32
|
+
* @param {any} value
|
|
33
|
+
* @returns {value is import("../spec/genome.js").InlineGenomeConfig}
|
|
34
|
+
*/
|
|
35
|
+
export function isInlineGenomeConfig(value: any): value is import("../spec/genome.js").InlineGenomeConfig;
|
|
21
36
|
/**
|
|
22
37
|
* @typedef {import("../spec/genome.js").GenomeConfig} GenomeConfig
|
|
23
38
|
* @typedef {import("../spec/genome.js").ChromosomalLocus} ChromosomalLocus
|
|
@@ -44,7 +59,15 @@ export default class Genome {
|
|
|
44
59
|
* @param {GenomeConfig} config
|
|
45
60
|
*/
|
|
46
61
|
constructor(config: GenomeConfig);
|
|
47
|
-
config:
|
|
62
|
+
config: {
|
|
63
|
+
name: string;
|
|
64
|
+
} | {
|
|
65
|
+
url: string;
|
|
66
|
+
name: string;
|
|
67
|
+
} | {
|
|
68
|
+
contigs: import("../spec/genome.js").Contig[];
|
|
69
|
+
name: string;
|
|
70
|
+
};
|
|
48
71
|
/** @type {(Chromosome & ChromosomeAnnotation)[]} */
|
|
49
72
|
chromosomes: (Chromosome & ChromosomeAnnotation)[];
|
|
50
73
|
/** @type {Map<string | number, number>} */
|
|
@@ -59,7 +82,6 @@ export default class Genome {
|
|
|
59
82
|
* @param {string} baseUrl
|
|
60
83
|
*/
|
|
61
84
|
load(baseUrl: string): Promise<void>;
|
|
62
|
-
baseUrl: string;
|
|
63
85
|
hasChrPrefix(): boolean;
|
|
64
86
|
/**
|
|
65
87
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"genome.d.ts","sourceRoot":"","sources":["../../../src/genome/genome.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"genome.d.ts","sourceRoot":"","sources":["../../../src/genome/genome.js"],"names":[],"mappings":"AAwWA;;;GAGG;AACH,gDAFW,MAAM;;;IAOhB;AAED;;;;GAIG;AACH,0CAHW,GAAG,yDAKb;AAED;;;;GAIG;AACH,kDAHW,GAAG,EAAE,2DAKf;AAED;;;GAGG;AACH,sCAHW,GAAG,qDAUb;AAED;;;GAGG;AACH,yCAHW,GAAG,wDAKb;AAED;;;GAGG;AACH,4CAHW,GAAG,2DAKb;AAzZD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;IACI;;OAEG;IACH,oBAFW,YAAY,EA6CtB;IA1CG;;;;;;;;MAA2C;IAc3C,oDAAoD;IACpD,aADW,CAAC,UAAU,GAAG,oBAAoB,CAAC,EAAE,CAC3B;IAErB,2CAA2C;IAC3C,0BADW,IAAI,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,CACE;IAEzC,sEAAsE;IACtE,mBADW,IAAI,MAAM,GAAG,MAAM,EAAE,UAAU,GAAG,oBAAoB,CAAC,CAChC;IAElC,uBAAuB;IACvB,cADW,MAAM,EAAE,CACG;IAEtB,kBAAkB;IAkBtB,mBAEC;IAED;;OAEG;IACH,cAFW,MAAM,iBAmBhB;IAED,wBAEC;IAED;;;OAGG;IACH,0BAFW,UAAU,EAAE,QA2CtB;IAED,sBAEC;IAED;;;;;OAKG;IACH,oBAHW,MAAM,GAAG,MAAM,OACf,MAAM,UAShB;IAED;;;OAGG;IACH,4BAFW,MAAM,qCAgBhB;IAED;;;;OAIG;IACH,6BAHW,MAAM,GACJ,gBAAgB,CAY5B;IAED;;;OAGG;IACH,oBAFW,MAAM,qCAIhB;IAED;;;;;;;;;;OAUG;IACH,yBAHW,MAAM,EAAE,GACN,MAAM,CAIlB;IAED;;;OAGG;IACH,gCAHW,MAAM,EAAE,GACN,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAUhD;IAED;;;;;;OAMG;IACH,kCAFW,gBAAgB,EAAE,YAgB5B;IAED;;;;;OAKG;IACH,wCAHW,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,GAClC,0BAA0B,EAAE,CAiCxC;IAED;;;;OAIG;IACH,4DAFW,MAAM,EAAE,gCAOlB;IAED;;;;OAIG;IACH,mBAHW,MAAM,GACJ,CAAC,MAAM,EAAE,MAAM,CAAC,CAgC5B;CACJ;2BA9VY,OAAO,mBAAmB,EAAE,YAAY;+BACxC,OAAO,mBAAmB,EAAE,gBAAgB;;UAG/C,MAAM;UACN,MAAM;;;;;;WAGN,MAAM;;;;YACN,MAAM;;;;qBACN,MAAM;;;;mBACN,MAAM;wBACN,MAAM,EAAE;;;;SACR,OAAO;;;WAGP,MAAM;cACN,MAAM;YACN,MAAM"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { bisect } from "d3-array";
|
|
2
2
|
import { tsvParseRows } from "d3-dsv";
|
|
3
|
-
import { loader } from "vega-loader";
|
|
4
3
|
import { isObject } from "vega-util";
|
|
5
4
|
import { formatRange } from "./locusFormat.js";
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import { getContigs } from "./genomes.js";
|
|
6
|
+
import { concatUrl } from "../utils/url.js";
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* @typedef {import("../spec/genome.js").GenomeConfig} GenomeConfig
|
|
@@ -33,11 +32,17 @@ export default class Genome {
|
|
|
33
32
|
* @param {GenomeConfig} config
|
|
34
33
|
*/
|
|
35
34
|
constructor(config) {
|
|
36
|
-
this.config = config;
|
|
35
|
+
this.config = { name: "custom", ...config };
|
|
36
|
+
|
|
37
|
+
if ("baseUrl" in config) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
"The `baseUrl` property in genome config has been removed in GenomeSpy v0.52.0. Use `url` instead. See https://genomespy.app/docs/genomic-data/genomic-coordinates/."
|
|
40
|
+
);
|
|
41
|
+
}
|
|
37
42
|
|
|
38
|
-
if (!
|
|
43
|
+
if (!isGenomeConfig(config)) {
|
|
39
44
|
throw new Error(
|
|
40
|
-
"
|
|
45
|
+
"Not a genome configuration: " + JSON.stringify(config)
|
|
41
46
|
);
|
|
42
47
|
}
|
|
43
48
|
|
|
@@ -55,8 +60,19 @@ export default class Genome {
|
|
|
55
60
|
|
|
56
61
|
this.totalSize = 0;
|
|
57
62
|
|
|
58
|
-
if (this.config
|
|
63
|
+
if (isInlineGenomeConfig(this.config)) {
|
|
59
64
|
this.setChromSizes(this.config.contigs);
|
|
65
|
+
} else if (isUrlGenomeConfig(this.config)) {
|
|
66
|
+
// Nop
|
|
67
|
+
} else {
|
|
68
|
+
const contigs = getContigs(this.config.name);
|
|
69
|
+
if (contigs) {
|
|
70
|
+
this.setChromSizes(contigs);
|
|
71
|
+
} else {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`Unknown genome: ${this.config.name}. Please provide contigs or a URL. See https://genomespy.app/docs/genomic-data/genomic-coordinates/.`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
60
76
|
}
|
|
61
77
|
}
|
|
62
78
|
|
|
@@ -68,28 +84,21 @@ export default class Genome {
|
|
|
68
84
|
* @param {string} baseUrl
|
|
69
85
|
*/
|
|
70
86
|
async load(baseUrl) {
|
|
71
|
-
if (this.config
|
|
87
|
+
if (!isUrlGenomeConfig(this.config)) {
|
|
72
88
|
return;
|
|
73
89
|
}
|
|
74
90
|
|
|
75
|
-
if (this.config.baseUrl) {
|
|
76
|
-
this.baseUrl = /^http(s)?/.test(this.config.baseUrl)
|
|
77
|
-
? this.config.baseUrl
|
|
78
|
-
: baseUrl + "/" + this.config.baseUrl;
|
|
79
|
-
} else {
|
|
80
|
-
this.baseUrl = defaultBaseUrl;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
91
|
try {
|
|
84
|
-
this.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
);
|
|
92
|
+
const fullUrl = concatUrl(baseUrl, this.config.url);
|
|
93
|
+
const result = await fetch(fullUrl);
|
|
94
|
+
if (!result.ok) {
|
|
95
|
+
throw new Error(`${result.status} ${result.statusText}`);
|
|
96
|
+
}
|
|
97
|
+
this.setChromSizes(parseChromSizes(await result.text()));
|
|
91
98
|
} catch (e) {
|
|
92
|
-
throw new Error(
|
|
99
|
+
throw new Error(
|
|
100
|
+
`Could not load chrom sizes: ${this.config.url}. Reason: ${e.message}`
|
|
101
|
+
);
|
|
93
102
|
}
|
|
94
103
|
}
|
|
95
104
|
|
|
@@ -354,10 +363,10 @@ export default class Genome {
|
|
|
354
363
|
* @param {string} chromSizesData
|
|
355
364
|
*/
|
|
356
365
|
export function parseChromSizes(chromSizesData) {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
366
|
+
return tsvParseRows(chromSizesData).map(([name, size]) => ({
|
|
367
|
+
name,
|
|
368
|
+
size: parseInt(size),
|
|
369
|
+
}));
|
|
361
370
|
}
|
|
362
371
|
|
|
363
372
|
/**
|
|
@@ -377,3 +386,32 @@ export function isChromosomalLocus(value) {
|
|
|
377
386
|
export function isChromosomalLocusInterval(value) {
|
|
378
387
|
return value.every(isChromosomalLocus);
|
|
379
388
|
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* @param {any} value
|
|
392
|
+
* @returns {value is GenomeConfig}
|
|
393
|
+
*/
|
|
394
|
+
export function isGenomeConfig(value) {
|
|
395
|
+
return (
|
|
396
|
+
isObject(value) &&
|
|
397
|
+
("name" in value ||
|
|
398
|
+
isUrlGenomeConfig(value) ||
|
|
399
|
+
isInlineGenomeConfig(value))
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* @param {any} value
|
|
405
|
+
* @returns {value is import("../spec/genome.js").UrlGenomeConfig }
|
|
406
|
+
*/
|
|
407
|
+
export function isUrlGenomeConfig(value) {
|
|
408
|
+
return isGenomeConfig(value) && "url" in value;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* @param {any} value
|
|
413
|
+
* @returns {value is import("../spec/genome.js").InlineGenomeConfig}
|
|
414
|
+
*/
|
|
415
|
+
export function isInlineGenomeConfig(value) {
|
|
416
|
+
return isGenomeConfig(value) && "contigs" in value;
|
|
417
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
1
|
+
import { afterAll, describe, expect, test, vi } from "vitest";
|
|
2
2
|
import Genome from "./genome.js";
|
|
3
3
|
|
|
4
4
|
describe("Human genome, chromosome names prefixed with 'chr'", () => {
|
|
@@ -190,6 +190,48 @@ describe("C. elegans genome, chromosome names prefixed with 'chr'", () => {
|
|
|
190
190
|
});
|
|
191
191
|
});
|
|
192
192
|
|
|
193
|
+
describe("Load chrom.sizes file from a URL", () => {
|
|
194
|
+
const fetchSpy = vi.spyOn(global, "fetch");
|
|
195
|
+
fetchSpy.mockImplementation((/** @type {string} */ url) => {
|
|
196
|
+
if (url !== "http://example.com/chrom.sizes") {
|
|
197
|
+
throw new Error(`Unexpected URL: ${url}`);
|
|
198
|
+
}
|
|
199
|
+
return Promise.resolve(
|
|
200
|
+
// @ts-expect-error
|
|
201
|
+
{
|
|
202
|
+
text() {
|
|
203
|
+
return Promise.resolve(
|
|
204
|
+
"chr1\t1000\nchr2\t2000\nchr3\t3000\nchrX\t4000"
|
|
205
|
+
);
|
|
206
|
+
},
|
|
207
|
+
ok: true,
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
afterAll(() => {
|
|
213
|
+
fetchSpy.mockRestore();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
test("Throw if the deprecated baseUrl property is provided", () => {
|
|
217
|
+
expect(
|
|
218
|
+
() =>
|
|
219
|
+
new Genome({
|
|
220
|
+
name: "random",
|
|
221
|
+
// @ts-expect-error
|
|
222
|
+
baseUrl: "http://example.com",
|
|
223
|
+
})
|
|
224
|
+
).toThrow(/removed/);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test("Loads and parses a genome", async () => {
|
|
228
|
+
const g = new Genome({ name: "random", url: "chrom.sizes" });
|
|
229
|
+
await g.load("http://example.com");
|
|
230
|
+
|
|
231
|
+
expect(g.parseInterval("chr2")).toEqual([1000, 3000]);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
193
235
|
describe("Parse interval strings", () => {
|
|
194
236
|
const chromosomes = [
|
|
195
237
|
{ name: "chr1", size: 1000 },
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"genomes.d.ts","sourceRoot":"","sources":["../../../src/genome/genomes.js"],"names":[],"mappings":"AAwJA;;GAEG;AACH,qCAFW,MAAM;;;IAUhB"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Based on chrom.sizes files from UCSC Genome Browser
|
|
3
|
+
* https://hgdownload.cse.ucsc.edu/goldenpath/
|
|
4
|
+
*
|
|
5
|
+
* Alternative loci, patches, and random contigs are not included.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const dm6 = `chr3R 32079331
|
|
9
|
+
chr3L 28110227
|
|
10
|
+
chr2R 25286936
|
|
11
|
+
chrX 23542271
|
|
12
|
+
chr2L 23513712
|
|
13
|
+
chrY 3667352
|
|
14
|
+
chr4 1348131
|
|
15
|
+
chrM 19524`;
|
|
16
|
+
|
|
17
|
+
const hg18 = `chr1 247249719
|
|
18
|
+
chr2 242951149
|
|
19
|
+
chr3 199501827
|
|
20
|
+
chr4 191273063
|
|
21
|
+
chr5 180857866
|
|
22
|
+
chr6 170899992
|
|
23
|
+
chr7 158821424
|
|
24
|
+
chr8 146274826
|
|
25
|
+
chr9 140273252
|
|
26
|
+
chr10 135374737
|
|
27
|
+
chr11 134452384
|
|
28
|
+
chr12 132349534
|
|
29
|
+
chr13 114142980
|
|
30
|
+
chr14 106368585
|
|
31
|
+
chr15 100338915
|
|
32
|
+
chr16 88827254
|
|
33
|
+
chr17 78774742
|
|
34
|
+
chr18 76117153
|
|
35
|
+
chr19 63811651
|
|
36
|
+
chr20 62435964
|
|
37
|
+
chr21 46944323
|
|
38
|
+
chr22 49691432
|
|
39
|
+
chrX 154913754
|
|
40
|
+
chrY 57772954
|
|
41
|
+
chrM 16571`;
|
|
42
|
+
|
|
43
|
+
const hg19 = `chr1 249250621
|
|
44
|
+
chr2 243199373
|
|
45
|
+
chr3 198022430
|
|
46
|
+
chr4 191154276
|
|
47
|
+
chr5 180915260
|
|
48
|
+
chr6 171115067
|
|
49
|
+
chr7 159138663
|
|
50
|
+
chr8 146364022
|
|
51
|
+
chr9 141213431
|
|
52
|
+
chr10 135534747
|
|
53
|
+
chr11 135006516
|
|
54
|
+
chr12 133851895
|
|
55
|
+
chr13 115169878
|
|
56
|
+
chr14 107349540
|
|
57
|
+
chr15 102531392
|
|
58
|
+
chr16 90354753
|
|
59
|
+
chr17 81195210
|
|
60
|
+
chr18 78077248
|
|
61
|
+
chr19 59128983
|
|
62
|
+
chr20 63025520
|
|
63
|
+
chr21 48129895
|
|
64
|
+
chr22 51304566
|
|
65
|
+
chrX 155270560
|
|
66
|
+
chrY 59373566
|
|
67
|
+
chrM 16571`;
|
|
68
|
+
|
|
69
|
+
const hg38 = `chr1 248956422
|
|
70
|
+
chr2 242193529
|
|
71
|
+
chr3 198295559
|
|
72
|
+
chr4 190214555
|
|
73
|
+
chr5 181538259
|
|
74
|
+
chr6 170805979
|
|
75
|
+
chr7 159345973
|
|
76
|
+
chr8 145138636
|
|
77
|
+
chr9 138394717
|
|
78
|
+
chr10 133797422
|
|
79
|
+
chr11 135086622
|
|
80
|
+
chr12 133275309
|
|
81
|
+
chr13 114364328
|
|
82
|
+
chr14 107043718
|
|
83
|
+
chr15 101991189
|
|
84
|
+
chr16 90338345
|
|
85
|
+
chr17 83257441
|
|
86
|
+
chr18 80373285
|
|
87
|
+
chr19 58617616
|
|
88
|
+
chr20 64444167
|
|
89
|
+
chr21 46709983
|
|
90
|
+
chr22 50818468
|
|
91
|
+
chrX 156040895
|
|
92
|
+
chrY 57227415
|
|
93
|
+
chrM 16569`;
|
|
94
|
+
|
|
95
|
+
const mm9 = `chr1 197195432
|
|
96
|
+
chr2 181748087
|
|
97
|
+
chr3 159599783
|
|
98
|
+
chr4 155630120
|
|
99
|
+
chr5 152537259
|
|
100
|
+
chr6 149517037
|
|
101
|
+
chr7 152524553
|
|
102
|
+
chr8 131738871
|
|
103
|
+
chr9 124076172
|
|
104
|
+
chr10 129993255
|
|
105
|
+
chr11 121843856
|
|
106
|
+
chr12 121257530
|
|
107
|
+
chr13 120284312
|
|
108
|
+
chr14 125194864
|
|
109
|
+
chr15 103494974
|
|
110
|
+
chr16 98319150
|
|
111
|
+
chr17 95272651
|
|
112
|
+
chr18 90772031
|
|
113
|
+
chr19 61342430
|
|
114
|
+
chrX 166650296
|
|
115
|
+
chrY 15902555
|
|
116
|
+
chrM 16299`;
|
|
117
|
+
|
|
118
|
+
const mm10 = `chr1 195471971
|
|
119
|
+
chr2 182113224
|
|
120
|
+
chr3 160039680
|
|
121
|
+
chr4 156508116
|
|
122
|
+
chr5 151834684
|
|
123
|
+
chr6 149736546
|
|
124
|
+
chr7 145441459
|
|
125
|
+
chr8 129401213
|
|
126
|
+
chr9 124595110
|
|
127
|
+
chr10 130694993
|
|
128
|
+
chr11 122082543
|
|
129
|
+
chr12 120129022
|
|
130
|
+
chr13 120421639
|
|
131
|
+
chr14 124902244
|
|
132
|
+
chr15 104043685
|
|
133
|
+
chr16 98207768
|
|
134
|
+
chr17 94987271
|
|
135
|
+
chr18 90702639
|
|
136
|
+
chr19 61431566
|
|
137
|
+
chrX 171031299
|
|
138
|
+
chrY 91744698
|
|
139
|
+
chrM 16299`;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @type {Record<string, string>}
|
|
143
|
+
*/
|
|
144
|
+
const assemblies = {
|
|
145
|
+
dm6,
|
|
146
|
+
hg18,
|
|
147
|
+
hg19,
|
|
148
|
+
hg38,
|
|
149
|
+
mm9,
|
|
150
|
+
mm10,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @param {string} assembly
|
|
155
|
+
*/
|
|
156
|
+
export function getContigs(assembly) {
|
|
157
|
+
if (!(assembly in assemblies))
|
|
158
|
+
throw new Error(`Unknown assembly: ${assembly}`);
|
|
159
|
+
|
|
160
|
+
return assemblies[assembly].split("\n").map((line) => {
|
|
161
|
+
const arr = line.split("\t");
|
|
162
|
+
return { name: arr[0], size: parseInt(arr[1]) };
|
|
163
|
+
});
|
|
164
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"genomes.test.d.ts","sourceRoot":"","sources":["../../../src/genome/genomes.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { getContigs } from "./genomes.js";
|
|
3
|
+
|
|
4
|
+
test("getContigs", () => {
|
|
5
|
+
expect(getContigs("mm10")[0]).toEqual({ name: "chr1", size: 195471971 });
|
|
6
|
+
expect(getContigs("mm10")[5]).toEqual({ name: "chr6", size: 149736546 });
|
|
7
|
+
expect(getContigs("hg38")[19]).toEqual({ name: "chr20", size: 64444167 });
|
|
8
|
+
});
|
|
@@ -3,25 +3,38 @@ export interface Contig {
|
|
|
3
3
|
size: number;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
export interface
|
|
6
|
+
export interface GenomeConfigBase {
|
|
7
7
|
/**
|
|
8
8
|
* Name of the genome assembly, e.g., `hg19` or `hg38`.
|
|
9
9
|
*/
|
|
10
10
|
name: string;
|
|
11
|
+
}
|
|
11
12
|
|
|
13
|
+
export interface UrlGenomeConfig extends GenomeConfigBase {
|
|
12
14
|
/**
|
|
13
|
-
*
|
|
15
|
+
* A URL to a `chrom.sizes` file, which is a tab-separated file with two
|
|
16
|
+
* columns: the sequence name and its size.
|
|
17
|
+
*
|
|
18
|
+
* You may want to strip alternative loci, haplotypes, and other
|
|
19
|
+
* non-canonical contigs from the file.
|
|
14
20
|
*
|
|
15
|
-
*
|
|
21
|
+
* Example: `"https://genomespy.app/data/genomes/hg19/chrom.sizes"`
|
|
16
22
|
*/
|
|
17
|
-
|
|
23
|
+
url: string;
|
|
24
|
+
}
|
|
18
25
|
|
|
26
|
+
export interface InlineGenomeConfig extends GenomeConfigBase {
|
|
19
27
|
/**
|
|
20
|
-
*
|
|
28
|
+
* An array of contigs/sequences in the genome assembly.
|
|
21
29
|
*/
|
|
22
|
-
contigs
|
|
30
|
+
contigs: Contig[];
|
|
23
31
|
}
|
|
24
32
|
|
|
33
|
+
export type GenomeConfig =
|
|
34
|
+
| UrlGenomeConfig
|
|
35
|
+
| InlineGenomeConfig
|
|
36
|
+
| GenomeConfigBase;
|
|
37
|
+
|
|
25
38
|
export interface ChromosomalLocus {
|
|
26
39
|
/**
|
|
27
40
|
* The name of the chromosome. For example: `"chr1"`, `"CHR1"`, or `"1"`.
|
|
@@ -3,4 +3,10 @@
|
|
|
3
3
|
* @param {string} baseUrl
|
|
4
4
|
*/
|
|
5
5
|
export default function addBaseUrl(url: string, baseUrl: string): string;
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {string} url
|
|
9
|
+
* @returns {string}
|
|
10
|
+
*/
|
|
11
|
+
export function endWithSlash(url: string): string;
|
|
6
12
|
//# sourceMappingURL=addBaseUrl.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addBaseUrl.d.ts","sourceRoot":"","sources":["../../../src/utils/addBaseUrl.js"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wCAHW,MAAM,WACN,MAAM,UAgBhB"}
|
|
1
|
+
{"version":3,"file":"addBaseUrl.d.ts","sourceRoot":"","sources":["../../../src/utils/addBaseUrl.js"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wCAHW,MAAM,WACN,MAAM,UAgBhB;AAED;;;;GAIG;AACH,kCAHW,MAAM,GACJ,MAAM,CAalB"}
|
|
@@ -17,3 +17,21 @@ export default function addBaseUrl(url, baseUrl) {
|
|
|
17
17
|
|
|
18
18
|
return url;
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @param {string} url
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
export function endWithSlash(url) {
|
|
27
|
+
if (!url) {
|
|
28
|
+
return url;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (/[?#]/.test(url)) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Invalid base URL: ${url} - cannot contain query or hash.`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
return url.endsWith("/") ? url : url + "/";
|
|
37
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { expect, test } from "vitest";
|
|
2
|
-
import addBaseUrl from "./addBaseUrl.js";
|
|
2
|
+
import addBaseUrl, { endWithSlash } from "./addBaseUrl.js";
|
|
3
3
|
|
|
4
4
|
test("addBaseUrl adds baseUrl when needed", () => {
|
|
5
5
|
expect(addBaseUrl("foo.html", "https://site.com/")).toEqual(
|
|
@@ -20,3 +20,11 @@ test("addBaseUrl doesn't add baseUrl when not needed", () => {
|
|
|
20
20
|
expect(addBaseUrl("/foo.html", "https://site.com/")).toEqual("/foo.html");
|
|
21
21
|
expect(addBaseUrl("foo.html", undefined)).toEqual("foo.html");
|
|
22
22
|
});
|
|
23
|
+
|
|
24
|
+
test("endWithSlash adds slash when needed", () => {
|
|
25
|
+
expect(endWithSlash(null)).toBeNull();
|
|
26
|
+
expect(endWithSlash("https://site.com")).toEqual("https://site.com/");
|
|
27
|
+
expect(endWithSlash("https://site.com/")).toEqual("https://site.com/");
|
|
28
|
+
expect(() => endWithSlash("https://site.com/foo?bar")).toThrow();
|
|
29
|
+
expect(() => endWithSlash("https://site.com/foo#bar")).toThrow();
|
|
30
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layerView.d.ts","sourceRoot":"","sources":["../../../src/view/layerView.js"],"names":[],"mappings":"AAIA;IAQI;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,SAAS,WACnC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,aAAa,cACb,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"layerView.d.ts","sourceRoot":"","sources":["../../../src/view/layerView.js"],"names":[],"mappings":"AAIA;IAQI;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,SAAS,WACnC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,aAAa,cACb,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EAWzC;IAHG,0CAAgB;IAoCpB,gEAEC;;CA6CJ;0BA7GyB,oBAAoB"}
|
|
@@ -20,7 +20,10 @@ export default class LayerView extends ContainerView {
|
|
|
20
20
|
* @param {import("./view.js").ViewOptions} [options]
|
|
21
21
|
*/
|
|
22
22
|
constructor(spec, context, layoutParent, dataParent, name, options) {
|
|
23
|
-
super(spec, context, layoutParent, dataParent, name,
|
|
23
|
+
super(spec, context, layoutParent, dataParent, name, {
|
|
24
|
+
layersChildren: true,
|
|
25
|
+
...options,
|
|
26
|
+
});
|
|
24
27
|
|
|
25
28
|
this.spec = spec;
|
|
26
29
|
|