@genome-spy/core 0.41.0 → 0.42.1

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.
Files changed (117) hide show
  1. package/dist/bundle/index--cKb-dKG.js +615 -0
  2. package/dist/bundle/{index-gn8bhQ8w.js → index-d7k3kkin.js} +365 -366
  3. package/dist/bundle/index.es.js +4225 -4040
  4. package/dist/bundle/index.js +122 -79
  5. package/dist/schema.json +58 -6
  6. package/dist/src/data/sources/dynamic/axisGenomeSource.js +1 -1
  7. package/dist/src/data/sources/dynamic/axisTickSource.js +3 -3
  8. package/dist/src/data/sources/dynamic/bamSource.d.ts +3 -21
  9. package/dist/src/data/sources/dynamic/bamSource.d.ts.map +1 -1
  10. package/dist/src/data/sources/dynamic/bamSource.js +38 -55
  11. package/dist/src/data/sources/dynamic/bigBedSource.d.ts +2 -38
  12. package/dist/src/data/sources/dynamic/bigBedSource.d.ts.map +1 -1
  13. package/dist/src/data/sources/dynamic/bigBedSource.js +14 -71
  14. package/dist/src/data/sources/dynamic/bigWigSource.d.ts +4 -42
  15. package/dist/src/data/sources/dynamic/bigWigSource.d.ts.map +1 -1
  16. package/dist/src/data/sources/dynamic/bigWigSource.js +23 -60
  17. package/dist/src/data/sources/dynamic/gff3Source.d.ts.map +1 -1
  18. package/dist/src/data/sources/dynamic/gff3Source.js +1 -0
  19. package/dist/src/data/sources/dynamic/indexedFastaSource.d.ts +2 -20
  20. package/dist/src/data/sources/dynamic/indexedFastaSource.d.ts.map +1 -1
  21. package/dist/src/data/sources/dynamic/indexedFastaSource.js +23 -41
  22. package/dist/src/data/sources/dynamic/singleAxisLazySource.d.ts +23 -4
  23. package/dist/src/data/sources/dynamic/singleAxisLazySource.d.ts.map +1 -1
  24. package/dist/src/data/sources/dynamic/singleAxisLazySource.js +29 -4
  25. package/dist/src/data/sources/dynamic/singleAxisWindowedSource.d.ts +60 -0
  26. package/dist/src/data/sources/dynamic/singleAxisWindowedSource.d.ts.map +1 -0
  27. package/dist/src/data/sources/dynamic/singleAxisWindowedSource.js +152 -0
  28. package/dist/src/data/sources/dynamic/tabixSource.d.ts +6 -40
  29. package/dist/src/data/sources/dynamic/tabixSource.d.ts.map +1 -1
  30. package/dist/src/data/sources/dynamic/tabixSource.js +29 -78
  31. package/dist/src/data/transforms/regexFold.d.ts.map +1 -1
  32. package/dist/src/data/transforms/regexFold.js +8 -0
  33. package/dist/src/data/transforms/regexFold.test.js +28 -0
  34. package/dist/src/encoder/encoder.d.ts +6 -1
  35. package/dist/src/encoder/encoder.d.ts.map +1 -1
  36. package/dist/src/encoder/encoder.js +10 -0
  37. package/dist/src/genomeSpy.d.ts +14 -0
  38. package/dist/src/genomeSpy.d.ts.map +1 -1
  39. package/dist/src/genomeSpy.js +114 -8
  40. package/dist/src/gl/arrayBuilder.js +1 -1
  41. package/dist/src/gl/colorUtils.d.ts.map +1 -0
  42. package/dist/src/{scale → gl}/colorUtils.js +1 -1
  43. package/dist/src/gl/dataToVertices.d.ts +1 -9
  44. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  45. package/dist/src/gl/dataToVertices.js +33 -73
  46. package/dist/src/{scale → gl}/glslScaleGenerator.d.ts +23 -1
  47. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -0
  48. package/dist/src/{scale → gl}/glslScaleGenerator.js +59 -8
  49. package/dist/src/gl/webGLHelper.d.ts +6 -21
  50. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  51. package/dist/src/gl/webGLHelper.js +8 -39
  52. package/dist/src/img/90-ring-with-bg.svg +1 -0
  53. package/dist/src/img/README.md +5 -0
  54. package/dist/src/marks/link.d.ts +7 -0
  55. package/dist/src/marks/link.d.ts.map +1 -1
  56. package/dist/src/marks/link.js +74 -39
  57. package/dist/src/marks/mark.d.ts +2 -1
  58. package/dist/src/marks/mark.d.ts.map +1 -1
  59. package/dist/src/marks/mark.js +31 -2
  60. package/dist/src/marks/{pointMark.d.ts → point.d.ts} +1 -1
  61. package/dist/src/marks/point.d.ts.map +1 -0
  62. package/dist/src/marks/{pointMark.js → point.js} +3 -3
  63. package/dist/src/marks/{rectMark.d.ts → rect.d.ts} +1 -1
  64. package/dist/src/marks/rect.d.ts.map +1 -0
  65. package/dist/src/marks/{rectMark.js → rect.js} +2 -3
  66. package/dist/src/marks/rect.vertex.glsl.js +2 -0
  67. package/dist/src/marks/rule.js +3 -3
  68. package/dist/src/marks/text.d.ts.map +1 -1
  69. package/dist/src/marks/text.js +19 -20
  70. package/dist/src/spec/data.d.ts +28 -13
  71. package/dist/src/spec/mark.d.ts +0 -8
  72. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  73. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  74. package/dist/src/styles/genome-spy.css.js +33 -4
  75. package/dist/src/styles/genome-spy.scss +40 -4
  76. package/dist/src/types/viewContext.d.ts +9 -0
  77. package/dist/src/utils/binnedIndex.d.ts +2 -0
  78. package/dist/src/utils/binnedIndex.d.ts.map +1 -1
  79. package/dist/src/utils/binnedIndex.js +59 -10
  80. package/dist/src/utils/binnedIndex.test.js +46 -0
  81. package/dist/src/utils/indexer.d.ts.map +1 -1
  82. package/dist/src/utils/indexer.js +10 -1
  83. package/dist/src/utils/indexer.test.js +2 -0
  84. package/dist/src/view/gridView.d.ts.map +1 -1
  85. package/dist/src/view/gridView.js +2 -0
  86. package/dist/src/view/layerView.d.ts.map +1 -1
  87. package/dist/src/view/layerView.js +2 -0
  88. package/dist/src/view/unitView.d.ts +1 -7
  89. package/dist/src/view/unitView.d.ts.map +1 -1
  90. package/dist/src/view/unitView.js +4 -11
  91. package/dist/src/view/view.d.ts +6 -0
  92. package/dist/src/view/view.d.ts.map +1 -1
  93. package/dist/src/view/view.js +11 -0
  94. package/dist/src/view/view.test.js +1 -1
  95. package/package.json +3 -3
  96. package/dist/bundle/index-Cbz74kpR.js +0 -638
  97. package/dist/src/data/sources/dynamic/windowedMixin.d.ts +0 -32
  98. package/dist/src/data/sources/dynamic/windowedMixin.d.ts.map +0 -1
  99. package/dist/src/data/sources/dynamic/windowedMixin.js +0 -53
  100. package/dist/src/gl/rect.vertex.glsl.js +0 -2
  101. package/dist/src/marks/pointMark.d.ts.map +0 -1
  102. package/dist/src/marks/rectMark.d.ts.map +0 -1
  103. package/dist/src/scale/colorUtils.d.ts.map +0 -1
  104. package/dist/src/scale/glslScaleGenerator.d.ts.map +0 -1
  105. /package/dist/src/{scale → gl}/colorUtils.d.ts +0 -0
  106. /package/dist/src/{gl → marks}/link.fragment.glsl.js +0 -0
  107. /package/dist/src/{gl → marks}/link.vertex.glsl.js +0 -0
  108. /package/dist/src/{gl → marks}/point.common.glsl.js +0 -0
  109. /package/dist/src/{gl → marks}/point.fragment.glsl.js +0 -0
  110. /package/dist/src/{gl → marks}/point.vertex.glsl.js +0 -0
  111. /package/dist/src/{gl → marks}/rect.fragment.glsl.js +0 -0
  112. /package/dist/src/{gl → marks}/rule.common.glsl.js +0 -0
  113. /package/dist/src/{gl → marks}/rule.fragment.glsl.js +0 -0
  114. /package/dist/src/{gl → marks}/rule.vertex.glsl.js +0 -0
  115. /package/dist/src/{gl → marks}/text.common.glsl.js +0 -0
  116. /package/dist/src/{gl → marks}/text.fragment.glsl.js +0 -0
  117. /package/dist/src/{gl → marks}/text.vertex.glsl.js +0 -0
package/dist/schema.json CHANGED
@@ -313,6 +313,18 @@
313
313
  "$ref": "#/definitions/PrimaryPositionalChannel",
314
314
  "description": "Which channel's scale domain to monitor.\n\n__Default value:__ `\"x\"`"
315
315
  },
316
+ "debounce": {
317
+ "description": "Debounce time for data updates, in milliseconds. Debouncing prevents excessive data updates when the user is zooming or panning around.\n\n__Default value:__ `200`",
318
+ "type": "number"
319
+ },
320
+ "debounceMode": {
321
+ "description": "The debounce mode for data updates. If set to `\"domain\"`, domain change events (panning and zooming) will be debounced. If set to `\"window\"`, the data fetches initiated by the changes to the visible window (or tile) will be debounced. If your data is small, the `\"window\"` is better as it will start fetching data while the user is still panning around, resulting in a shorter perceived latency.\n\n__Default value:__ `\"window\"`",
322
+ "enum": [
323
+ "domain",
324
+ "window"
325
+ ],
326
+ "type": "string"
327
+ },
316
328
  "indexUrl": {
317
329
  "description": "URL of the index file.\n\n__Default value:__ `url` + `\".bai\"`.",
318
330
  "type": "string"
@@ -352,6 +364,18 @@
352
364
  "$ref": "#/definitions/PrimaryPositionalChannel",
353
365
  "description": "Which channel's scale domain to monitor.\n\n__Default value:__ `\"x\"`"
354
366
  },
367
+ "debounce": {
368
+ "description": "Debounce time for data updates, in milliseconds. Debouncing prevents excessive data updates when the user is zooming or panning around.\n\n__Default value:__ `200`",
369
+ "type": "number"
370
+ },
371
+ "debounceMode": {
372
+ "description": "The debounce mode for data updates. If set to `\"domain\"`, domain change events (panning and zooming) will be debounced. If set to `\"window\"`, the data fetches initiated by the changes to the visible window (or tile) will be debounced. If your data is small, the `\"window\"` is better as it will start fetching data while the user is still panning around, resulting in a shorter perceived latency.\n\n__Default value:__ `\"window\"`",
373
+ "enum": [
374
+ "domain",
375
+ "window"
376
+ ],
377
+ "type": "string"
378
+ },
355
379
  "type": {
356
380
  "const": "bigbed",
357
381
  "type": "string"
@@ -378,6 +402,18 @@
378
402
  "$ref": "#/definitions/PrimaryPositionalChannel",
379
403
  "description": "Which channel's scale domain to monitor.\n\n__Default value:__ `\"x\"`"
380
404
  },
405
+ "debounce": {
406
+ "description": "Debounce time for data updates, in milliseconds. Debouncing prevents excessive data updates when the user is zooming or panning around.\n\n__Default value:__ `200`",
407
+ "type": "number"
408
+ },
409
+ "debounceMode": {
410
+ "description": "The debounce mode for data updates. If set to `\"domain\"`, domain change events (panning and zooming) will be debounced. If set to `\"window\"`, the data fetches initiated by the changes to the visible window (or tile) will be debounced. If your data is small, the `\"window\"` is better as it will start fetching data while the user is still panning around, resulting in a shorter perceived latency.\n\n__Default value:__ `\"window\"`",
411
+ "enum": [
412
+ "domain",
413
+ "window"
414
+ ],
415
+ "type": "string"
416
+ },
381
417
  "pixelsPerBin": {
382
418
  "description": "The approximate minimum width of each data bin, in pixels.\n\n__Default value:__ `2`",
383
419
  "type": "number"
@@ -1786,10 +1822,18 @@
1786
1822
  "$ref": "#/definitions/PrimaryPositionalChannel",
1787
1823
  "description": "Which channel's scale domain to monitor.\n\n__Default value:__ `\"x\"`"
1788
1824
  },
1789
- "debounceDomainChange": {
1790
- "description": "The debounce time for domain changes, in milliseconds. Debouncing prevents data fetches while the user is still panning around.\n\n__Default value:__ `200`",
1825
+ "debounce": {
1826
+ "description": "Debounce time for data updates, in milliseconds. Debouncing prevents excessive data updates when the user is zooming or panning around.\n\n__Default value:__ `200`",
1791
1827
  "type": "number"
1792
1828
  },
1829
+ "debounceMode": {
1830
+ "description": "The debounce mode for data updates. If set to `\"domain\"`, domain change events (panning and zooming) will be debounced. If set to `\"window\"`, the data fetches initiated by the changes to the visible window (or tile) will be debounced. If your data is small, the `\"window\"` is better as it will start fetching data while the user is still panning around, resulting in a shorter perceived latency.\n\n__Default value:__ `\"window\"`",
1831
+ "enum": [
1832
+ "domain",
1833
+ "window"
1834
+ ],
1835
+ "type": "string"
1836
+ },
1793
1837
  "indexUrl": {
1794
1838
  "description": "Url of the tabix index file.\n\n__Default value:__ `url` + `\".tbi\"`.",
1795
1839
  "type": "string"
@@ -2057,6 +2101,18 @@
2057
2101
  "$ref": "#/definitions/PrimaryPositionalChannel",
2058
2102
  "description": "Which channel's scale domain to monitor.\n\n__Default value:__ `\"x\"`"
2059
2103
  },
2104
+ "debounce": {
2105
+ "description": "Debounce time for data updates, in milliseconds. Debouncing prevents excessive data updates when the user is zooming or panning around.\n\n__Default value:__ `200`",
2106
+ "type": "number"
2107
+ },
2108
+ "debounceMode": {
2109
+ "description": "The debounce mode for data updates. If set to `\"domain\"`, domain change events (panning and zooming) will be debounced. If set to `\"window\"`, the data fetches initiated by the changes to the visible window (or tile) will be debounced. If your data is small, the `\"window\"` is better as it will start fetching data while the user is still panning around, resulting in a shorter perceived latency.\n\n__Default value:__ `\"window\"`",
2110
+ "enum": [
2111
+ "domain",
2112
+ "window"
2113
+ ],
2114
+ "type": "string"
2115
+ },
2060
2116
  "indexUrl": {
2061
2117
  "description": "URL of the index file.\n\n__Default value:__ `url` + `\".fai\"`.",
2062
2118
  "type": "string"
@@ -2505,10 +2561,6 @@
2505
2561
  "$ref": "#/definitions/Baseline",
2506
2562
  "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n**Default value:** `\"bottom\"`"
2507
2563
  },
2508
- "buildIndex": {
2509
- "description": "Builds and index for efficient rendering of subsets of the data. The data must be sorted by the x coordinate.\n\nTODO: This should be enabled automatically if the data are sorted.",
2510
- "type": "boolean"
2511
- },
2512
2564
  "clampApex": {
2513
2565
  "anyOf": [
2514
2566
  {
@@ -14,6 +14,6 @@ export default class AxisGenomeSource extends SingleAxisLazySource {
14
14
  }
15
15
 
16
16
  async load() {
17
- this.publishData(this.genome.chromosomes);
17
+ this.publishData([this.genome.chromosomes]);
18
18
  }
19
19
  }
@@ -65,9 +65,9 @@ export default class AxisTickSource extends SingleAxisLazySource {
65
65
  this.ticks = ticks;
66
66
 
67
67
  const format = tickFormat(scale, requestedCount, axisParams.format);
68
- this.publishData(
69
- ticks.map((tick) => ({ value: tick, label: format(tick) }))
70
- );
68
+ this.publishData([
69
+ ticks.map((tick) => ({ value: tick, label: format(tick) })),
70
+ ]);
71
71
  }
72
72
  }
73
73
  }
@@ -1,21 +1,9 @@
1
- declare const BamSource_base: {
2
- new (...args: any[]): {
3
- [x: string]: any;
4
- lastQuantizedInterval: number[];
5
- quantizeInterval(interval: number[], windowSize: number): number[];
6
- checkAndUpdateLastInterval(interval: number[]): boolean;
7
- };
8
- } & typeof SingleAxisLazySource;
9
- export default class BamSource extends BamSource_base {
1
+ export default class BamSource extends SingleAxisWindowedSource {
10
2
  /**
11
3
  * @param {import("../../../spec/data.js").BamData} params
12
4
  * @param {import("../../../view/view.js").default} view
13
5
  */
14
6
  constructor(params: import("../../../spec/data.js").BamData, view: import("../../../view/view.js").default);
15
- /** Keep track of the order of the requests */
16
- lastRequestId: number;
17
- /** @type {import("@gmod/bam").BamFile} */
18
- bam: import("@gmod/bam").BamFile;
19
7
  /**
20
8
  * Some BAM files lack the "chr" prefix on their reference names. For example:
21
9
  * http://genome.ucsc.edu/goldenPath/help/examples/bamExample.bam
@@ -28,13 +16,7 @@ export default class BamSource extends BamSource_base {
28
16
  chrPrefixFixer: (chr: string) => string;
29
17
  params: import("../../../spec/data.js").BamData;
30
18
  initializedPromise: Promise<any>;
31
- /**
32
- * Listen to the domain change event and update data when the covered windows change.
33
- *
34
- * @param {number[]} domain Linearized domain
35
- */
36
- onDomainChanged(domain: number[]): Promise<void>;
19
+ #private;
37
20
  }
38
- import SingleAxisLazySource from "./singleAxisLazySource.js";
39
- export {};
21
+ import SingleAxisWindowedSource from "./singleAxisWindowedSource.js";
40
22
  //# sourceMappingURL=bamSource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bamSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/bamSource.js"],"names":[],"mappings":";;;;;;;;AAIA;IAkBI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,OAAO,QACvC,OAAO,uBAAuB,EAAE,OAAO,EA+CjD;IAlED,8CAA8C;IAC9C,sBAAkB;IAElB,0CAA0C;IAC1C,KADW,OAAO,WAAW,EAAE,OAAO,CAClC;IAEJ;;;;;;;;OAQG;IACH,sBAFgB,MAAM,KAAK,MAAM,CAEH;IAgB1B,gDAAgC;IAMhC,iCA4BE;IAGN;;;;OAIG;IACH,wBAFW,MAAM,EAAE,iBA6ClB;CACJ;iCA1HgC,2BAA2B"}
1
+ {"version":3,"file":"bamSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/bamSource.js"],"names":[],"mappings":"AAGA;IAeI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,OAAO,QACvC,OAAO,uBAAuB,EAAE,OAAO,EAmDjD;IAhED;;;;;;;;OAQG;IACH,sBAFgB,MAAM,KAAK,MAAM,CAEH;IAkB1B,gDAAgC;IAQhC,iCA4BE;;CAmCT;qCAxGoC,+BAA+B"}
@@ -1,13 +1,9 @@
1
- import SingleAxisLazySource from "./singleAxisLazySource.js";
2
- import windowedMixin from "./windowedMixin.js";
3
1
  import addBaseUrl from "../../../utils/addBaseUrl.js";
2
+ import SingleAxisWindowedSource from "./singleAxisWindowedSource.js";
4
3
 
5
- export default class BamSource extends windowedMixin(SingleAxisLazySource) {
6
- /** Keep track of the order of the requests */
7
- lastRequestId = 0;
8
-
4
+ export default class BamSource extends SingleAxisWindowedSource {
9
5
  /** @type {import("@gmod/bam").BamFile} */
10
- bam;
6
+ #bam;
11
7
 
12
8
  /**
13
9
  * Some BAM files lack the "chr" prefix on their reference names. For example:
@@ -29,6 +25,8 @@ export default class BamSource extends windowedMixin(SingleAxisLazySource) {
29
25
  const paramsWithDefaults = {
30
26
  channel: "x",
31
27
  windowSize: 20000,
28
+ debounce: 200,
29
+ debounceMode: "domain",
32
30
  ...params,
33
31
  };
34
32
 
@@ -40,6 +38,8 @@ export default class BamSource extends windowedMixin(SingleAxisLazySource) {
40
38
  throw new Error("No URL provided for BamSource");
41
39
  }
42
40
 
41
+ this.setupDebouncing(this.params);
42
+
43
43
  this.initializedPromise = new Promise((resolve) => {
44
44
  Promise.all([
45
45
  import("@gmod/bam"),
@@ -48,17 +48,17 @@ export default class BamSource extends windowedMixin(SingleAxisLazySource) {
48
48
  const withBase = (/** @type {string} */ uri) =>
49
49
  new RemoteFile(addBaseUrl(uri, this.view.getBaseUrl()));
50
50
 
51
- this.bam = new BamFile({
51
+ this.#bam = new BamFile({
52
52
  bamFilehandle: withBase(this.params.url),
53
53
  baiFilehandle: withBase(
54
54
  this.params.indexUrl ?? this.params.url + ".bai"
55
55
  ),
56
56
  });
57
57
 
58
- this.bam.getHeader().then((_header) => {
58
+ this.#bam.getHeader().then((_header) => {
59
59
  const g = this.genome.hasChrPrefix();
60
60
  const b =
61
- this.bam.indexToChr?.[0]?.refName.startsWith("chr");
61
+ this.#bam.indexToChr?.[0]?.refName.startsWith("chr");
62
62
  if (g && !b) {
63
63
  this.chrPrefixFixer = (chr) => chr.replace("chr", "");
64
64
  } else if (!g && b) {
@@ -72,52 +72,35 @@ export default class BamSource extends windowedMixin(SingleAxisLazySource) {
72
72
  }
73
73
 
74
74
  /**
75
- * Listen to the domain change event and update data when the covered windows change.
76
- *
77
- * @param {number[]} domain Linearized domain
75
+ * @param {number[]} interval linearized domain
78
76
  */
79
- async onDomainChanged(domain) {
80
- const windowSize = this.params.windowSize;
81
-
82
- if (domain[1] - domain[0] > windowSize) {
83
- return;
84
- }
85
-
86
- await this.initializedPromise;
87
-
88
- const quantizedInterval = this.quantizeInterval(domain, windowSize);
89
-
90
- if (this.checkAndUpdateLastInterval(quantizedInterval)) {
91
- const discreteChromosomeIntervals =
92
- this.genome.continuousToDiscreteChromosomeIntervals(
93
- quantizedInterval
94
- );
95
-
96
- // TODO: Error handling
97
- const sequencesWithChrom = await Promise.all(
98
- discreteChromosomeIntervals.map((d) =>
99
- this.bam
100
- .getRecordsForRange(
101
- this.chrPrefixFixer(d.chrom),
102
- d.startPos,
103
- d.endPos
104
- )
105
- .then((records) =>
106
- records.map((record) => ({
107
- chrom: d.chrom,
108
- start: record.get("start"),
109
- end: record.get("end"),
110
- name: record.get("name"),
111
- MD: record.get("MD"),
112
- cigar: record.get("cigar"),
113
- mapq: record.get("mq"),
114
- strand: record.get("strand") === 1 ? "+" : "-",
115
- }))
116
- )
117
- )
118
- );
119
-
120
- this.publishData(sequencesWithChrom.flat());
77
+ async loadInterval(interval) {
78
+ const featureChunks = await this.discretizeAndLoad(
79
+ interval,
80
+ async (d, signal) =>
81
+ this.#bam
82
+ .getRecordsForRange(
83
+ this.chrPrefixFixer(d.chrom),
84
+ d.startPos,
85
+ d.endPos,
86
+ { signal }
87
+ )
88
+ .then((records) =>
89
+ records.map((record) => ({
90
+ chrom: d.chrom,
91
+ start: record.get("start"),
92
+ end: record.get("end"),
93
+ name: record.get("name"),
94
+ MD: record.get("MD"),
95
+ cigar: record.get("cigar"),
96
+ mapq: record.get("mq"),
97
+ strand: record.get("strand") === 1 ? "+" : "-",
98
+ }))
99
+ )
100
+ );
101
+
102
+ if (featureChunks) {
103
+ this.publishData(featureChunks);
121
104
  }
122
105
  }
123
106
  }
@@ -1,51 +1,15 @@
1
- declare const BigBedSource_base: {
2
- new (...args: any[]): {
3
- [x: string]: any;
4
- lastQuantizedInterval: number[];
5
- quantizeInterval(interval: number[], windowSize: number): number[];
6
- checkAndUpdateLastInterval(interval: number[]): boolean;
7
- };
8
- } & typeof SingleAxisLazySource;
9
- export default class BigBedSource extends BigBedSource_base {
1
+ export default class BigBedSource extends SingleAxisWindowedSource {
10
2
  /**
11
3
  * @param {import("../../../spec/data.js").BigBedData} params
12
4
  * @param {import("../../../view/view.js").default} view
13
5
  */
14
6
  constructor(params: import("../../../spec/data.js").BigBedData, view: import("../../../view/view.js").default);
15
- /** Keep track of the order of the requests */
16
- lastRequestId: number;
17
7
  /** @type {import("@gmod/bed").default} */
18
8
  parser: import("@gmod/bed").default;
19
9
  /** @type {import("@gmod/bbi").BigBed} */
20
10
  bbi: import("@gmod/bbi").BigBed;
21
11
  params: import("../../../spec/data.js").BigBedData;
22
- doDebouncedRequest: (...args: any[]) => Promise<any>;
23
12
  initializedPromise: Promise<any>;
24
- headerPromise: Promise<import("@gmod/bbi").Header>;
25
- /**
26
- * Listen to the domain change event and update data when the covered windows change.
27
- *
28
- * @param {number[]} domain Linearized domain
29
- */
30
- onDomainChanged(domain: number[]): Promise<void>;
31
- /**
32
- * Listen to the domain change event and update data when the covered windows change.
33
- *
34
- * @param {number[]} interval linearized domain
35
- */
36
- doRequest(interval: number[]): Promise<void>;
37
- /**
38
- *
39
- * @param {number[]} interval
40
- */
41
- getFeatures(interval: number[]): Promise<{
42
- requestId: number;
43
- abort: () => void;
44
- features: {
45
- [key: string]: any;
46
- }[];
47
- }>;
48
13
  }
49
- import SingleAxisLazySource from "./singleAxisLazySource.js";
50
- export {};
14
+ import SingleAxisWindowedSource from "./singleAxisWindowedSource.js";
51
15
  //# sourceMappingURL=bigBedSource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bigBedSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/bigBedSource.js"],"names":[],"mappings":";;;;;;;;AAKA;IAUI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,UAAU,QAC1C,OAAO,uBAAuB,EAAE,OAAO,EA+CjD;IA1DD,8CAA8C;IAC9C,sBAAkB;IAElB,0CAA0C;IAC1C,QADW,OAAO,WAAW,EAAE,OAAO,CAC/B;IAEP,yCAAyC;IACzC,KADW,OAAO,WAAW,EAAE,MAAM,CACjC;IAgBA,mDAAgC;IAMhC,qDAIC;IAED,iCAsBE;IARM,mDAAyC;IAWrD;;;;OAIG;IACH,wBAFW,MAAM,EAAE,iBAgBlB;IAED;;;;OAIG;IACH,oBAFW,MAAM,EAAE,iBAWlB;IAED;;;OAGG;IACH,sBAFW,MAAM,EAAE;;;;;;OAkClB;CACJ;iCA5IgC,2BAA2B"}
1
+ {"version":3,"file":"bigBedSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/bigBedSource.js"],"names":[],"mappings":"AAGA;IAOI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,UAAU,QAC1C,OAAO,uBAAuB,EAAE,OAAO,EA4CjD;IApDD,0CAA0C;IAC1C,QADW,OAAO,WAAW,EAAE,OAAO,CAC/B;IAEP,yCAAyC;IACzC,KADW,OAAO,WAAW,EAAE,MAAM,CACjC;IAkBA,mDAAgC;IAQhC,iCAqBE;CA4BT;qCAlFoC,+BAA+B"}
@@ -1,12 +1,7 @@
1
- import SingleAxisLazySource from "./singleAxisLazySource.js";
2
- import windowedMixin from "./windowedMixin.js";
3
- import { debounce } from "../../../utils/debounce.js";
4
1
  import addBaseUrl from "../../../utils/addBaseUrl.js";
2
+ import SingleAxisWindowedSource from "./singleAxisWindowedSource.js";
5
3
 
6
- export default class BigBedSource extends windowedMixin(SingleAxisLazySource) {
7
- /** Keep track of the order of the requests */
8
- lastRequestId = 0;
9
-
4
+ export default class BigBedSource extends SingleAxisWindowedSource {
10
5
  /** @type {import("@gmod/bed").default} */
11
6
  parser;
12
7
 
@@ -22,6 +17,8 @@ export default class BigBedSource extends windowedMixin(SingleAxisLazySource) {
22
17
  const paramsWithDefaults = {
23
18
  channel: "x",
24
19
  windowSize: 1000000,
20
+ debounce: 200,
21
+ debounceMode: "window",
25
22
  ...params,
26
23
  };
27
24
 
@@ -33,11 +30,7 @@ export default class BigBedSource extends windowedMixin(SingleAxisLazySource) {
33
30
  throw new Error("No URL provided for BigBedSource");
34
31
  }
35
32
 
36
- this.doDebouncedRequest = debounce(
37
- this.doRequest.bind(this),
38
- 200,
39
- false
40
- );
33
+ this.setupDebouncing(this.params);
41
34
 
42
35
  this.initializedPromise = new Promise((resolve) => {
43
36
  Promise.all([
@@ -53,8 +46,7 @@ export default class BigBedSource extends windowedMixin(SingleAxisLazySource) {
53
46
  ),
54
47
  });
55
48
 
56
- this.headerPromise = this.bbi.getHeader();
57
- this.headerPromise.then(async (header) => {
49
+ this.bbi.getHeader().then(async (header) => {
58
50
  // @ts-ignore TODO: Fix
59
51
  this.parser = new BED({ autoSql: header.autoSql });
60
52
 
@@ -65,61 +57,15 @@ export default class BigBedSource extends windowedMixin(SingleAxisLazySource) {
65
57
  }
66
58
 
67
59
  /**
68
- * Listen to the domain change event and update data when the covered windows change.
69
- *
70
- * @param {number[]} domain Linearized domain
71
- */
72
- async onDomainChanged(domain) {
73
- await this.initializedPromise;
74
-
75
- const windowSize = this.params.windowSize;
76
-
77
- if (domain[1] - domain[0] > windowSize) {
78
- return;
79
- }
80
-
81
- const quantizedInterval = this.quantizeInterval(domain, windowSize);
82
-
83
- if (this.checkAndUpdateLastInterval(quantizedInterval)) {
84
- this.doDebouncedRequest(quantizedInterval);
85
- }
86
- }
87
-
88
- /**
89
- * Listen to the domain change event and update data when the covered windows change.
90
- *
91
60
  * @param {number[]} interval linearized domain
92
61
  */
93
- async doRequest(interval) {
94
- const featureResponse = await this.getFeatures(interval);
95
-
96
- // Discard late responses
97
- if (featureResponse.requestId < this.lastRequestId) {
98
- return;
99
- }
100
-
101
- this.publishData(featureResponse.features);
102
- }
103
-
104
- /**
105
- *
106
- * @param {number[]} interval
107
- */
108
- async getFeatures(interval) {
109
- let requestId = ++this.lastRequestId;
110
-
111
- // TODO: Abort previous requests
112
- const abortController = new AbortController();
113
-
114
- const discreteChromosomeIntervals =
115
- this.genome.continuousToDiscreteChromosomeIntervals(interval);
116
-
117
- // TODO: Error handling
118
- const featuresWithChrom = await Promise.all(
119
- discreteChromosomeIntervals.map((d) =>
62
+ async loadInterval(interval) {
63
+ const features = await this.discretizeAndLoad(
64
+ interval,
65
+ async (d, signal) =>
120
66
  this.bbi
121
67
  .getFeatures(d.chrom, d.startPos, d.endPos, {
122
- signal: abortController.signal,
68
+ signal,
123
69
  })
124
70
  .then((features) =>
125
71
  features.map((f) =>
@@ -129,13 +75,10 @@ export default class BigBedSource extends windowedMixin(SingleAxisLazySource) {
129
75
  )
130
76
  )
131
77
  )
132
- )
133
78
  );
134
79
 
135
- return {
136
- requestId,
137
- abort: () => abortController.abort(),
138
- features: featuresWithChrom.flat(), // TODO: Use batches, not flat
139
- };
80
+ if (features) {
81
+ this.publishData(features);
82
+ }
140
83
  }
141
84
  }
@@ -1,58 +1,20 @@
1
- declare const BigWigSource_base: {
2
- new (...args: any[]): {
3
- [x: string]: any;
4
- lastQuantizedInterval: number[];
5
- quantizeInterval(interval: number[], windowSize: number): number[];
6
- checkAndUpdateLastInterval(interval: number[]): boolean;
7
- };
8
- } & typeof SingleAxisLazySource;
9
1
  /**
10
2
  *
11
3
  */
12
- export default class BigWigSource extends BigWigSource_base {
4
+ export default class BigWigSource extends SingleAxisWindowedSource {
13
5
  /**
14
6
  * @param {import("../../../spec/data.js").BigWigData} params
15
7
  * @param {import("../../../view/view.js").default} view
16
8
  */
17
9
  constructor(params: import("../../../spec/data.js").BigWigData, view: import("../../../view/view.js").default);
18
- /** @type {number[]} */
19
- reductionLevels: number[];
20
- /** Keep track of the order of the requests */
21
- lastRequestId: number;
22
- /** @type {import("@gmod/bbi").BigWig} */
23
- bbi: import("@gmod/bbi").BigWig;
24
10
  params: import("../../../spec/data.js").BigWigData;
25
- doDebouncedRequest: (...args: any[]) => Promise<any>;
26
11
  initializedPromise: Promise<any>;
27
12
  /**
28
- * Listen to the domain change event and update data when the covered windows change.
29
- *
30
- * @param {number[]} domain Linearized domain
31
- */
32
- onDomainChanged(domain: number[]): Promise<void>;
33
- /**
34
- * Listen to the domain change event and update data when the covered windows change.
35
- *
36
13
  * @param {number[]} interval linearized domain
37
14
  * @param {number} reductionLevel
38
15
  */
39
- doRequest(interval: number[], reductionLevel: number): Promise<void>;
40
- /**
41
- *
42
- * @param {number[]} interval
43
- * @param {number} scale
44
- */
45
- getFeatures(interval: number[], scale: number): Promise<{
46
- requestId: number;
47
- abort: () => void;
48
- features: {
49
- chrom: string;
50
- start: number;
51
- end: number;
52
- score: number;
53
- }[];
54
- }>;
16
+ loadInterval(interval: number[], reductionLevel: number): Promise<void>;
17
+ #private;
55
18
  }
56
- import SingleAxisLazySource from "./singleAxisLazySource.js";
57
- export {};
19
+ import SingleAxisWindowedSource from "./singleAxisWindowedSource.js";
58
20
  //# sourceMappingURL=bigWigSource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bigWigSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/bigWigSource.js"],"names":[],"mappings":";;;;;;;;AAKA;;GAEG;AACH;IAUI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,UAAU,QAC1C,OAAO,uBAAuB,EAAE,OAAO,EAmDjD;IA9DD,uBAAuB;IACvB,iBADW,MAAM,EAAE,CACE;IAErB,8CAA8C;IAC9C,sBAAkB;IAElB,yCAAyC;IACzC,KADW,OAAO,WAAW,EAAE,MAAM,CACjC;IAgBA,mDAAgC;IAMhC,qDAIC;IAED,iCA0BE;IAGN;;;;OAIG;IACH,wBAFW,MAAM,EAAE,iBAuBlB;IAED;;;;;OAKG;IACH,oBAHW,MAAM,EAAE,kBACR,MAAM,iBAchB;IAED;;;;OAIG;IACH,sBAHW,MAAM,EAAE,SACR,MAAM;;;;;;;;;OAmChB;CACJ;iCA/JgC,2BAA2B"}
1
+ {"version":3,"file":"bigWigSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/bigWigSource.js"],"names":[],"mappings":"AAGA;;GAEG;AACH;IAOI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,UAAU,QAC1C,OAAO,uBAAuB,EAAE,OAAO,EAiDjD;IAnCG,mDAAgC;IAQhC,iCA0BE;IA+BN;;;OAGG;IAEH,uBAJW,MAAM,EAAE,kBACR,MAAM,iBA0BhB;;CACJ;qCA1HoC,+BAA+B"}