@genome-spy/core 0.40.0 → 0.42.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.
Files changed (104) 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 +4260 -3928
  4. package/dist/bundle/index.js +115 -80
  5. package/dist/schema.json +254 -52
  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/accessor.js +4 -2
  35. package/dist/src/genomeSpy.d.ts +16 -0
  36. package/dist/src/genomeSpy.d.ts.map +1 -1
  37. package/dist/src/genomeSpy.js +119 -8
  38. package/dist/src/gl/link.vertex.glsl.js +1 -1
  39. package/dist/src/gl/point.common.glsl.js +2 -0
  40. package/dist/src/gl/point.fragment.glsl.js +1 -1
  41. package/dist/src/gl/point.vertex.glsl.js +1 -1
  42. package/dist/src/gl/rect.vertex.glsl.js +1 -1
  43. package/dist/src/gl/rule.common.glsl.js +2 -0
  44. package/dist/src/gl/rule.fragment.glsl.js +1 -1
  45. package/dist/src/gl/rule.vertex.glsl.js +1 -1
  46. package/dist/src/gl/text.common.glsl.js +2 -0
  47. package/dist/src/gl/text.fragment.glsl.js +1 -1
  48. package/dist/src/gl/text.vertex.glsl.js +1 -1
  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 +7 -38
  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 +99 -50
  57. package/dist/src/marks/mark.d.ts +34 -0
  58. package/dist/src/marks/mark.d.ts.map +1 -1
  59. package/dist/src/marks/mark.js +83 -1
  60. package/dist/src/marks/pointMark.d.ts.map +1 -1
  61. package/dist/src/marks/pointMark.js +21 -9
  62. package/dist/src/marks/rectMark.d.ts +1 -2
  63. package/dist/src/marks/rectMark.d.ts.map +1 -1
  64. package/dist/src/marks/rectMark.js +28 -17
  65. package/dist/src/marks/rule.d.ts.map +1 -1
  66. package/dist/src/marks/rule.js +17 -6
  67. package/dist/src/marks/text.d.ts.map +1 -1
  68. package/dist/src/marks/text.js +32 -18
  69. package/dist/src/paramBroker.d.ts +30 -0
  70. package/dist/src/paramBroker.d.ts.map +1 -0
  71. package/dist/src/paramBroker.js +102 -0
  72. package/dist/src/spec/data.d.ts +28 -13
  73. package/dist/src/spec/mark.d.ts +27 -26
  74. package/dist/src/spec/view.d.ts +2 -1
  75. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  76. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  77. package/dist/src/styles/genome-spy.css.js +33 -4
  78. package/dist/src/styles/genome-spy.scss +40 -4
  79. package/dist/src/types/viewContext.d.ts +11 -0
  80. package/dist/src/utils/binnedIndex.d.ts +2 -0
  81. package/dist/src/utils/binnedIndex.d.ts.map +1 -1
  82. package/dist/src/utils/binnedIndex.js +59 -10
  83. package/dist/src/utils/binnedIndex.test.js +46 -0
  84. package/dist/src/utils/expression.d.ts +12 -2
  85. package/dist/src/utils/expression.d.ts.map +1 -1
  86. package/dist/src/utils/expression.js +68 -9
  87. package/dist/src/utils/linearstep.d.ts +7 -0
  88. package/dist/src/utils/linearstep.d.ts.map +1 -0
  89. package/dist/src/utils/linearstep.js +10 -0
  90. package/dist/src/view/gridView.d.ts.map +1 -1
  91. package/dist/src/view/gridView.js +2 -0
  92. package/dist/src/view/layerView.d.ts.map +1 -1
  93. package/dist/src/view/layerView.js +2 -0
  94. package/dist/src/view/unitView.d.ts +0 -6
  95. package/dist/src/view/unitView.d.ts.map +1 -1
  96. package/dist/src/view/unitView.js +2 -9
  97. package/dist/src/view/view.d.ts +6 -0
  98. package/dist/src/view/view.d.ts.map +1 -1
  99. package/dist/src/view/view.js +17 -0
  100. package/package.json +3 -3
  101. package/dist/bundle/index-Cbz74kpR.js +0 -638
  102. package/dist/src/data/sources/dynamic/windowedMixin.d.ts +0 -32
  103. package/dist/src/data/sources/dynamic/windowedMixin.d.ts.map +0 -1
  104. package/dist/src/data/sources/dynamic/windowedMixin.js +0 -53
@@ -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"}
@@ -1,20 +1,15 @@
1
- import { debounce } from "../../../utils/debounce.js";
2
- import SingleAxisLazySource from "./singleAxisLazySource.js";
3
- import windowedMixin from "./windowedMixin.js";
4
1
  import addBaseUrl from "../../../utils/addBaseUrl.js";
2
+ import SingleAxisWindowedSource from "./singleAxisWindowedSource.js";
5
3
 
6
4
  /**
7
5
  *
8
6
  */
9
- export default class BigWigSource extends windowedMixin(SingleAxisLazySource) {
7
+ export default class BigWigSource extends SingleAxisWindowedSource {
10
8
  /** @type {number[]} */
11
- reductionLevels = [];
12
-
13
- /** Keep track of the order of the requests */
14
- lastRequestId = 0;
9
+ #reductionLevels = [];
15
10
 
16
11
  /** @type {import("@gmod/bbi").BigWig} */
17
- bbi;
12
+ #bbi;
18
13
 
19
14
  /**
20
15
  * @param {import("../../../spec/data.js").BigWigData} params
@@ -25,6 +20,8 @@ export default class BigWigSource extends windowedMixin(SingleAxisLazySource) {
25
20
  const paramsWithDefaults = {
26
21
  pixelsPerBin: 2,
27
22
  channel: "x",
23
+ debounce: 200,
24
+ debounceMode: "window",
28
25
  ...params,
29
26
  };
30
27
 
@@ -36,25 +33,21 @@ export default class BigWigSource extends windowedMixin(SingleAxisLazySource) {
36
33
  throw new Error("No URL provided for BigWigSource");
37
34
  }
38
35
 
39
- this.doDebouncedRequest = debounce(
40
- this.doRequest.bind(this),
41
- 200,
42
- false
43
- );
36
+ this.setupDebouncing(this.params);
44
37
 
45
38
  this.initializedPromise = new Promise((resolve) => {
46
39
  Promise.all([
47
40
  import("@gmod/bbi"),
48
41
  import("generic-filehandle"),
49
42
  ]).then(([{ BigWig }, { RemoteFile }]) => {
50
- this.bbi = new BigWig({
43
+ this.#bbi = new BigWig({
51
44
  filehandle: new RemoteFile(
52
45
  addBaseUrl(this.params.url, this.view.getBaseUrl())
53
46
  ),
54
47
  });
55
48
 
56
- this.bbi.getHeader().then((header) => {
57
- this.reductionLevels =
49
+ this.#bbi.getHeader().then((header) => {
50
+ this.#reductionLevels =
58
51
  /** @type {{reductionLevel: number}[]} */ (
59
52
  header.zoomLevels
60
53
  )
@@ -63,7 +56,7 @@ export default class BigWigSource extends windowedMixin(SingleAxisLazySource) {
63
56
 
64
57
  // Add the non-reduced level. Not sure if this is the best way to do it.
65
58
  // Afaik, the non-reduced bin size is not available in the header.
66
- this.reductionLevels.push(1);
59
+ this.#reductionLevels.push(1);
67
60
 
68
61
  resolve();
69
62
  });
@@ -85,7 +78,7 @@ export default class BigWigSource extends windowedMixin(SingleAxisLazySource) {
85
78
  const reductionLevel = findReductionLevel(
86
79
  domain,
87
80
  length,
88
- this.reductionLevels
81
+ this.#reductionLevels
89
82
  );
90
83
 
91
84
  // The sensible minimum window size actually depends on the non-reduced data density...
@@ -95,51 +88,24 @@ export default class BigWigSource extends windowedMixin(SingleAxisLazySource) {
95
88
  const quantizedInterval = this.quantizeInterval(domain, windowSize);
96
89
 
97
90
  if (this.checkAndUpdateLastInterval(quantizedInterval)) {
98
- this.doDebouncedRequest(quantizedInterval, reductionLevel);
91
+ this.loadInterval(quantizedInterval, reductionLevel);
99
92
  }
100
93
  }
101
94
 
102
95
  /**
103
- * Listen to the domain change event and update data when the covered windows change.
104
- *
105
96
  * @param {number[]} interval linearized domain
106
97
  * @param {number} reductionLevel
107
98
  */
108
- async doRequest(interval, reductionLevel) {
109
- const featureResponse = await this.getFeatures(
99
+ // @ts-expect-error
100
+ async loadInterval(interval, reductionLevel) {
101
+ const scale = 1 / 2 / reductionLevel / this.params.pixelsPerBin;
102
+ const featureChunks = await this.discretizeAndLoad(
110
103
  interval,
111
- 1 / 2 / reductionLevel / this.params.pixelsPerBin
112
- );
113
-
114
- // Discard late responses
115
- if (featureResponse.requestId < this.lastRequestId) {
116
- return;
117
- }
118
-
119
- this.publishData(featureResponse.features);
120
- }
121
-
122
- /**
123
- *
124
- * @param {number[]} interval
125
- * @param {number} scale
126
- */
127
- async getFeatures(interval, scale) {
128
- let requestId = ++this.lastRequestId;
129
-
130
- // TODO: Abort previous requests
131
- const abortController = new AbortController();
132
-
133
- const discreteChromosomeIntervals =
134
- this.genome.continuousToDiscreteChromosomeIntervals(interval);
135
-
136
- // TODO: Error handling
137
- const featuresWithChrom = await Promise.all(
138
- discreteChromosomeIntervals.map((d) =>
139
- this.bbi
104
+ (d, signal) =>
105
+ this.#bbi
140
106
  .getFeatures(d.chrom, d.startPos, d.endPos, {
141
107
  scale,
142
- signal: abortController.signal,
108
+ signal,
143
109
  })
144
110
  .then((features) =>
145
111
  features.map((f) => ({
@@ -149,14 +115,11 @@ export default class BigWigSource extends windowedMixin(SingleAxisLazySource) {
149
115
  score: f.score,
150
116
  }))
151
117
  )
152
- )
153
118
  );
154
119
 
155
- return {
156
- requestId,
157
- abort: () => abortController.abort(),
158
- features: featuresWithChrom.flat(), // TODO: Use batches, not flat
159
- };
120
+ if (featureChunks) {
121
+ this.publishData(featureChunks);
122
+ }
160
123
  }
161
124
  }
162
125
 
@@ -1 +1 @@
1
- {"version":3,"file":"gff3Source.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/gff3Source.js"],"names":[],"mappings":"AAEA;;GAEG;AACH;IAII;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,SAAS,QACzC,OAAO,uBAAuB,EAAE,OAAO,EASjD;IAED;;OAEG;IACH,sBAFW,MAAM,EAAE,OASlB;;CACJ;wBAjCuB,kBAAkB"}
1
+ {"version":3,"file":"gff3Source.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/gff3Source.js"],"names":[],"mappings":"AAEA;;GAEG;AACH;IAII;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,SAAS,QACzC,OAAO,uBAAuB,EAAE,OAAO,EASjD;IAED;;OAEG;IACH,sBAFW,MAAM,EAAE,OAUlB;;CACJ;wBAlCuB,kBAAkB"}
@@ -24,6 +24,7 @@ export default class Gff3Source extends TabixSource {
24
24
  * @param {string[]} lines
25
25
  */
26
26
  _parseFeatures(lines) {
27
+ // Hmm. It's silly that we have to first collect individual lines and then join them.
27
28
  // eslint-disable-next-line no-sync
28
29
  const features = this.#gff?.parseStringSync(lines.join("\n"), {
29
30
  parseSequences: false,
@@ -1,15 +1,4 @@
1
- declare const IndexedFastaSource_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
- /**
10
- *
11
- */
12
- export default class IndexedFastaSource extends IndexedFastaSource_base {
1
+ export default class IndexedFastaSource extends SingleAxisWindowedSource {
13
2
  /**
14
3
  * @param {import("../../../spec/data.js").IndexedFastaData} params
15
4
  * @param {import("../../../view/view.js").default} view
@@ -18,13 +7,6 @@ export default class IndexedFastaSource extends IndexedFastaSource_base {
18
7
  params: import("../../../spec/data.js").IndexedFastaData;
19
8
  initializedPromise: Promise<any>;
20
9
  fasta: import("@gmod/indexedfasta").IndexedFasta;
21
- /**
22
- * Listen to the domain change event and update data when the covered windows change.
23
- *
24
- * @param {number[]} domain Linearized domain
25
- */
26
- onDomainChanged(domain: number[]): Promise<void>;
27
10
  }
28
- import SingleAxisLazySource from "./singleAxisLazySource.js";
29
- export {};
11
+ import SingleAxisWindowedSource from "./singleAxisWindowedSource.js";
30
12
  //# sourceMappingURL=indexedFastaSource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"indexedFastaSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/indexedFastaSource.js"],"names":[],"mappings":";;;;;;;;AAIA;;GAEG;AACH;IAGI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,gBAAgB,QAChD,OAAO,uBAAuB,EAAE,OAAO,EA2CjD;IA/BG,yDAAgC;IAMhC,iCAwBE;IATM,iDAKE;IAOd;;;;OAIG;IACH,wBAFW,MAAM,EAAE,iBAkClB;CACJ;iCA/FgC,2BAA2B"}
1
+ {"version":3,"file":"indexedFastaSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/indexedFastaSource.js"],"names":[],"mappings":"AAGA;IACI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,gBAAgB,QAChD,OAAO,uBAAuB,EAAE,OAAO,EA+CjD;IAjCG,yDAAgC;IAQhC,iCAwBE;IATM,iDAKE;CA6BjB;qCA5EoC,+BAA+B"}
@@ -1,13 +1,7 @@
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
- /**
6
- *
7
- */
8
- export default class IndexedFastaSource extends windowedMixin(
9
- SingleAxisLazySource
10
- ) {
4
+ export default class IndexedFastaSource extends SingleAxisWindowedSource {
11
5
  /**
12
6
  * @param {import("../../../spec/data.js").IndexedFastaData} params
13
7
  * @param {import("../../../view/view.js").default} view
@@ -17,6 +11,8 @@ export default class IndexedFastaSource extends windowedMixin(
17
11
  const paramsWithDefaults = {
18
12
  channel: "x",
19
13
  windowSize: 7000,
14
+ debounce: 200,
15
+ debounceMode: "window",
20
16
  ...params,
21
17
  };
22
18
 
@@ -28,6 +24,8 @@ export default class IndexedFastaSource extends windowedMixin(
28
24
  throw new Error("No URL provided for IndexedFastaSource");
29
25
  }
30
26
 
27
+ this.setupDebouncing(this.params);
28
+
31
29
  this.initializedPromise = new Promise((resolve) => {
32
30
  Promise.all([
33
31
  import("buffer"),
@@ -56,41 +54,25 @@ export default class IndexedFastaSource extends windowedMixin(
56
54
  }
57
55
 
58
56
  /**
59
- * Listen to the domain change event and update data when the covered windows change.
60
- *
61
- * @param {number[]} domain Linearized domain
57
+ * @param {number[]} interval linearized domain
62
58
  */
63
- async onDomainChanged(domain) {
64
- const windowSize = this.params.windowSize;
65
-
66
- if (domain[1] - domain[0] > windowSize) {
67
- return;
68
- }
69
-
70
- await this.initializedPromise;
71
-
72
- const quantizedInterval = this.quantizeInterval(domain, windowSize);
73
-
74
- if (this.checkAndUpdateLastInterval(quantizedInterval)) {
75
- const discreteChromosomeIntervals =
76
- this.genome.continuousToDiscreteChromosomeIntervals(
77
- quantizedInterval
78
- );
79
-
80
- // TODO: Error handling
81
- const sequencesWithChrom = await Promise.all(
82
- discreteChromosomeIntervals.map((d) =>
83
- this.fasta
84
- .getSequence(d.chrom, d.startPos, d.endPos)
85
- .then((sequence) => ({
86
- chrom: d.chrom,
87
- start: d.startPos,
88
- sequence,
89
- }))
90
- )
91
- );
59
+ async loadInterval(interval) {
60
+ const features = await this.discretizeAndLoad(
61
+ interval,
62
+ async (d, signal) =>
63
+ this.fasta
64
+ .getSequence(d.chrom, d.startPos, d.endPos, {
65
+ signal,
66
+ })
67
+ .then((sequence) => ({
68
+ chrom: d.chrom,
69
+ start: d.startPos,
70
+ sequence,
71
+ }))
72
+ );
92
73
 
93
- this.publishData(sequencesWithChrom);
74
+ if (features) {
75
+ this.publishData([features]);
94
76
  }
95
77
  }
96
78
  }
@@ -7,6 +7,11 @@ export default class SingleAxisLazySource extends DataSource {
7
7
  * @param {import("../../../spec/channel.js").PrimaryPositionalChannel} channel
8
8
  */
9
9
  constructor(view: import("../../../view/view.js").default, channel: import("../../../spec/channel.js").PrimaryPositionalChannel);
10
+ /**
11
+ * Has to be resolved before any data can be requested upon domain changes.
12
+ * @protected
13
+ */
14
+ protected initializedPromise: Promise<void>;
10
15
  view: import("../../../view/view.js").default;
11
16
  /** @type {import("../../../spec/channel.js").PrimaryPositionalChannel} */
12
17
  channel: import("../../../spec/channel.js").PrimaryPositionalChannel;
@@ -18,25 +23,39 @@ export default class SingleAxisLazySource extends DataSource {
18
23
  getAxisLength(): number;
19
24
  /**
20
25
  * Convenience getter for genome.
26
+ *
27
+ * @protected
21
28
  */
22
- get genome(): import("../../../genome/genome.js").default;
29
+ protected get genome(): import("../../../genome/genome.js").default;
23
30
  /**
24
31
  * Listen to the domain change event and update data when the covered windows change.
25
32
  *
26
33
  * @param {number[]} domain Linearized domain
27
34
  * @param {import("../../../spec/genome.js").ChromosomalLocus[]} complexDomain Chrom/Pos domain
35
+ * @abstract
28
36
  */
29
37
  onDomainChanged(domain: number[], complexDomain: import("../../../spec/genome.js").ChromosomalLocus[]): Promise<void>;
38
+ /**
39
+ * Sets the loading status of the data source. The status is shown in the UI.
40
+ *
41
+ * @param {boolean} status true if loading, false otherwise
42
+ * @protected
43
+ */
44
+ protected setLoadingStatus(status: boolean): void;
30
45
  /**
31
46
  * TODO: Get rid of this method.
32
47
  * Rendering should be requested by the collector.
48
+ *
49
+ * @protected
33
50
  */
34
- requestRender(): void;
51
+ protected requestRender(): void;
35
52
  /**
53
+ * Resets the data flow and propagates the data.
36
54
  *
37
- * @param {import("../../flowNode.js").Datum[]} data
55
+ * @param {import("../../flowNode.js").Datum[][]} chunks An array of data chunks.
56
+ * @protected
38
57
  */
39
- publishData(data: import("../../flowNode.js").Datum[]): void;
58
+ protected publishData(chunks: import("../../flowNode.js").Datum[][]): void;
40
59
  }
41
60
  import DataSource from "../dataSource.js";
42
61
  //# sourceMappingURL=singleAxisLazySource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"singleAxisLazySource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/singleAxisLazySource.js"],"names":[],"mappings":"AAIA;;GAEG;AACH;IACI;;;OAGG;IACH,kBAHW,OAAO,uBAAuB,EAAE,OAAO,WACvC,OAAO,0BAA0B,EAAE,wBAAwB,EAiDrE;IA5CG,8CAAgB;IAYhB,2EAA2E;IAC3E,SADW,OAAO,0BAA0B,EAAE,wBAAwB,CAChD;IAEtB,oEAA4D;IA+BhE;;;OAGG;IACH,wBAWC;IAED;;OAEG;IACH,0DAEC;IAED;;;;;OAKG;IACH,wBAHW,MAAM,EAAE,iBACR,OAAO,yBAAyB,EAAE,gBAAgB,EAAE,iBAI9D;IAED;;;OAGG;IACH,sBAGC;IAQD;;;OAGG;IACH,kBAFW,OAAO,mBAAmB,EAAE,KAAK,EAAE,QAe7C;CACJ;uBA/HsB,kBAAkB"}
1
+ {"version":3,"file":"singleAxisLazySource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/dynamic/singleAxisLazySource.js"],"names":[],"mappings":"AAIA;;GAEG;AACH;IAOI;;;OAGG;IACH,kBAHW,OAAO,uBAAuB,EAAE,OAAO,WACvC,OAAO,0BAA0B,EAAE,wBAAwB,EAiDrE;IAzDD;;;OAGG;IACH,4CAAuC;IASnC,8CAAgB;IAYhB,2EAA2E;IAC3E,SADW,OAAO,0BAA0B,EAAE,wBAAwB,CAChD;IAEtB,oEAA4D;IA+BhE;;;OAGG;IACH,wBAWC;IAED;;;;OAIG;IACH,oEAEC;IAED;;;;;;OAMG;IACH,wBAJW,MAAM,EAAE,iBACR,OAAO,yBAAyB,EAAE,gBAAgB,EAAE,iBAK9D;IAED;;;;;OAKG;IACH,mCAHW,OAAO,QAKjB;IAED;;;;;OAKG;IACH,gCAGC;IAQD;;;;;OAKG;IACH,8BAHW,OAAO,mBAAmB,EAAE,KAAK,EAAE,EAAE,QAkB/C;CACJ;uBAxJsB,kBAAkB"}