@genome-spy/core 0.43.3 → 0.45.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 (124) hide show
  1. package/dist/bundle/index.es.js +5231 -4324
  2. package/dist/bundle/index.js +197 -85
  3. package/dist/schema.json +723 -104
  4. package/dist/src/data/collector.d.ts.map +1 -1
  5. package/dist/src/data/collector.js +4 -2
  6. package/dist/src/data/flowOptimizer.test.js +12 -3
  7. package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
  8. package/dist/src/data/sources/dataUtils.js +3 -1
  9. package/dist/src/data/sources/lazy/axisTickSource.d.ts +1 -1
  10. package/dist/src/data/sources/lazy/axisTickSource.d.ts.map +1 -1
  11. package/dist/src/data/sources/lazy/axisTickSource.js +2 -2
  12. package/dist/src/data/sources/lazy/bigBedSource.d.ts +1 -1
  13. package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
  14. package/dist/src/data/sources/lazy/bigBedSource.js +52 -20
  15. package/dist/src/data/sources/lazy/bigWigSource.d.ts +6 -1
  16. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  17. package/dist/src/data/sources/lazy/bigWigSource.js +33 -9
  18. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +1 -1
  19. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  20. package/dist/src/data/sources/lazy/singleAxisLazySource.js +1 -3
  21. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts +13 -14
  22. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  23. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +70 -48
  24. package/dist/src/data/sources/sequenceSource.d.ts.map +1 -1
  25. package/dist/src/data/sources/sequenceSource.js +14 -5
  26. package/dist/src/data/sources/sequenceSource.test.js +23 -5
  27. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  28. package/dist/src/data/sources/urlSource.js +15 -2
  29. package/dist/src/data/transforms/aggregate.d.ts.map +1 -1
  30. package/dist/src/data/transforms/aggregate.js +5 -2
  31. package/dist/src/data/transforms/filterScoredLabels.js +1 -1
  32. package/dist/src/encoder/encoder.d.ts +2 -4
  33. package/dist/src/encoder/encoder.d.ts.map +1 -1
  34. package/dist/src/encoder/encoder.js +20 -10
  35. package/dist/src/encoder/encoder.test.js +3 -0
  36. package/dist/src/genomeSpy.d.ts +8 -5
  37. package/dist/src/genomeSpy.d.ts.map +1 -1
  38. package/dist/src/genomeSpy.js +121 -42
  39. package/dist/src/gl/glslScaleGenerator.d.ts +23 -3
  40. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  41. package/dist/src/gl/glslScaleGenerator.js +137 -42
  42. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  43. package/dist/src/gl/webGLHelper.js +5 -7
  44. package/dist/src/index.d.ts +1 -1
  45. package/dist/src/index.d.ts.map +1 -1
  46. package/dist/src/index.js +1 -1
  47. package/dist/src/marks/link.common.glsl.js +2 -0
  48. package/dist/src/marks/link.d.ts.map +1 -1
  49. package/dist/src/marks/link.js +19 -9
  50. package/dist/src/marks/link.vertex.glsl.js +1 -1
  51. package/dist/src/marks/mark.d.ts +25 -20
  52. package/dist/src/marks/mark.d.ts.map +1 -1
  53. package/dist/src/marks/mark.js +234 -129
  54. package/dist/src/marks/point.common.glsl.js +1 -1
  55. package/dist/src/marks/point.d.ts +1 -4
  56. package/dist/src/marks/point.d.ts.map +1 -1
  57. package/dist/src/marks/point.js +31 -23
  58. package/dist/src/marks/point.vertex.glsl.js +1 -1
  59. package/dist/src/marks/rect.common.glsl.js +2 -0
  60. package/dist/src/marks/rect.d.ts.map +1 -1
  61. package/dist/src/marks/rect.js +12 -12
  62. package/dist/src/marks/rect.vertex.glsl.js +1 -1
  63. package/dist/src/marks/rule.common.glsl.js +1 -1
  64. package/dist/src/marks/rule.js +2 -2
  65. package/dist/src/marks/text.common.glsl.js +1 -1
  66. package/dist/src/marks/text.d.ts.map +1 -1
  67. package/dist/src/marks/text.js +17 -9
  68. package/dist/src/spec/channel.d.ts +4 -3
  69. package/dist/src/spec/data.d.ts +11 -10
  70. package/dist/src/spec/mark.d.ts +28 -46
  71. package/dist/src/spec/parameter.d.ts +127 -0
  72. package/dist/src/spec/root.d.ts +1 -0
  73. package/dist/src/spec/scale.d.ts +2 -1
  74. package/dist/src/spec/title.d.ts +5 -4
  75. package/dist/src/spec/view.d.ts +20 -5
  76. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  77. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  78. package/dist/src/styles/genome-spy.css.js +52 -5
  79. package/dist/src/styles/genome-spy.scss +63 -10
  80. package/dist/src/styles/update.sh +6 -0
  81. package/dist/src/tooltip/dataTooltipHandler.js +1 -1
  82. package/dist/src/tooltip/refseqGeneTooltipHandler.js +1 -1
  83. package/dist/src/tooltip/tooltipHandler.d.ts +1 -1
  84. package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -1
  85. package/dist/src/tooltip/tooltipHandler.ts +1 -1
  86. package/dist/src/types/embedApi.d.ts +6 -0
  87. package/dist/src/types/scaleResolutionApi.d.ts +7 -3
  88. package/dist/src/types/viewContext.d.ts +2 -3
  89. package/dist/src/utils/debounce.d.ts +2 -2
  90. package/dist/src/utils/debounce.d.ts.map +1 -1
  91. package/dist/src/utils/debounce.js +5 -2
  92. package/dist/src/utils/expression.d.ts +2 -2
  93. package/dist/src/utils/expression.d.ts.map +1 -1
  94. package/dist/src/utils/expression.js +3 -3
  95. package/dist/src/utils/formatObject.d.ts +2 -2
  96. package/dist/src/utils/formatObject.d.ts.map +1 -1
  97. package/dist/src/utils/formatObject.js +2 -2
  98. package/dist/src/utils/inputBinding.d.ts +5 -0
  99. package/dist/src/utils/inputBinding.d.ts.map +1 -0
  100. package/dist/src/utils/inputBinding.js +115 -0
  101. package/dist/src/utils/ui/tooltip.js +1 -1
  102. package/dist/src/view/axisView.js +3 -3
  103. package/dist/src/view/paramMediator.d.ts +108 -0
  104. package/dist/src/view/paramMediator.d.ts.map +1 -0
  105. package/dist/src/view/paramMediator.js +337 -0
  106. package/dist/src/view/paramMediator.test.js +211 -0
  107. package/dist/src/view/scaleResolution.d.ts +8 -18
  108. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  109. package/dist/src/view/scaleResolution.js +225 -126
  110. package/dist/src/view/scaleResolution.test.js +7 -7
  111. package/dist/src/view/unitView.d.ts.map +1 -1
  112. package/dist/src/view/unitView.js +10 -3
  113. package/dist/src/view/view.d.ts +4 -1
  114. package/dist/src/view/view.d.ts.map +1 -1
  115. package/dist/src/view/view.js +21 -7
  116. package/dist/src/view/viewFactory.d.ts.map +1 -1
  117. package/dist/src/view/viewFactory.js +45 -0
  118. package/dist/src/view/viewUtils.d.ts +5 -1
  119. package/dist/src/view/viewUtils.d.ts.map +1 -1
  120. package/dist/src/view/viewUtils.js +9 -4
  121. package/package.json +16 -17
  122. package/dist/src/paramBroker.d.ts +0 -30
  123. package/dist/src/paramBroker.d.ts.map +0 -1
  124. package/dist/src/paramBroker.js +0 -102
@@ -1 +1 @@
1
- {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../../src/data/collector.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH;IAKI;;OAEG;IACH,qBAFW,OAAO,sBAAsB,EAAE,aAAa,EActD;IATG,qDAA2C;IAE3C,2CAA2C;IAC3C,WADW,QAAU,SAAS,KAAE,IAAI,CAAC,EAAE,CACpB;IAEnB,uFAAuF;IACvF,cADW,IAAI,GAAG,GAAG,GAAG,EAAE,EAAE,OAAO,eAAe,EAAE,IAAI,CAAC,CAC5B;IAKjC,cAOC;IANG,2CAA2C;IAC3C,OADW,OAAO,eAAe,EAAE,IAAI,CACxB;IA2FnB;;OAEG;IACH,WAFa,SAAS,OAAO,eAAe,EAAE,KAAK,CAAC,CAuBnD;IAED;;;OAGG;IACH,2BAFmB,OAAO,eAAe,EAAE,KAAK,KAAK,IAAI,QAUxD;IAED;;OAEG;IACH,uBAMC;IAED,qBAMC;CACJ;qBAvLyD,eAAe"}
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../../src/data/collector.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH;IAKI;;OAEG;IACH,qBAFW,OAAO,sBAAsB,EAAE,aAAa,EActD;IATG,qDAA2C;IAE3C,2CAA2C;IAC3C,WADW,QAAU,SAAS,KAAE,IAAI,CAAC,EAAE,CACpB;IAEnB,uFAAuF;IACvF,cADW,IAAI,GAAG,GAAG,GAAG,EAAE,EAAE,OAAO,eAAe,EAAE,IAAI,CAAC,CAC5B;IAKjC,cAOC;IANG,2CAA2C;IAC3C,OADW,OAAO,eAAe,EAAE,IAAI,CACxB;IA6FnB;;OAEG;IACH,WAFa,SAAS,OAAO,eAAe,EAAE,KAAK,CAAC,CAuBnD;IAED;;;OAGG;IACH,2BAFmB,OAAO,eAAe,EAAE,KAAK,KAAK,IAAI,QAUxD;IAED;;OAEG;IACH,uBAMC;IAED,qBAMC;CACJ;qBAzLyD,eAAe"}
@@ -89,8 +89,10 @@ export default class Collector extends FlowNode {
89
89
  );
90
90
  const groups =
91
91
  accessors.length > 1
92
- ? // @ts-ignore
93
- group(this._data, ...accessors)
92
+ ? // There's something strange in d3-array's typings
93
+ /** @type {Map<any, any>} */ /** @type {any} */ (
94
+ group(this._data, ...accessors)
95
+ )
94
96
  : // D3's group is SLOW!
95
97
  groupBy(this._data, accessors[0]);
96
98
 
@@ -132,20 +132,29 @@ describe("removeRedundantCloneTransforms", () => {
132
132
  });
133
133
  });
134
134
 
135
+ const viewStub = {
136
+ paramMediator: {
137
+ registerParam: () => {},
138
+ allocateSetter: () => {},
139
+ createExpression: () => {},
140
+ },
141
+ getBaseUrl: () => "",
142
+ };
143
+
135
144
  describe("Merge indentical data sources", () => {
136
145
  test("Merges correctly", () => {
137
146
  /** @type {DataFlow<string>} */
138
147
  const dataFlow = new DataFlow();
139
148
 
140
- const a = new UrlSource({ url: "http://genomespy.app/" });
149
+ const a = new UrlSource({ url: "http://genomespy.app/" }, viewStub);
141
150
  const ac = new Collector();
142
151
  a.addChild(ac);
143
152
 
144
- const b = new UrlSource({ url: "http://genomespy.app/" });
153
+ const b = new UrlSource({ url: "http://genomespy.app/" }, viewStub);
145
154
  const bc = new Collector();
146
155
  b.addChild(bc);
147
156
 
148
- const c = new UrlSource({ url: "http://helsinki.fi/" });
157
+ const c = new UrlSource({ url: "http://helsinki.fi/" }, viewStub);
149
158
  const cc = new Collector();
150
159
  c.addChild(cc);
151
160
 
@@ -1 +1 @@
1
- {"version":3,"file":"dataUtils.d.ts","sourceRoot":"","sources":["../../../../src/data/sources/dataUtils.js"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,kCAHW,OAAO,oBAAoB,EAAE,UAAU;;;;;;;;;;;;;EAqBjD;AAED;;GAEG;AACH,wCAFW,MAAM,GAAG,MAAM,EAAE,UAU3B;AAWD;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,UAAU,4DAKjD;AAED;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,UAAU,4DAKjD;AAED;;;GAGG;AACH,6CAHW,OAAO,oBAAoB,EAAE,UAAU,6DAKjD;AAED;;;;GAIG;AACH,sCAHW,OAAO,oBAAoB,EAAE,UAAU,sDAKjD;AAxCM,+BAAgC,GAAG,QAI3B,OAAO,uBAAuB,EAAE,MAAM;;UAGtB,OAAO,gBAAgB,EAAE,KAAK,qCANR"}
1
+ {"version":3,"file":"dataUtils.d.ts","sourceRoot":"","sources":["../../../../src/data/sources/dataUtils.js"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,kCAHW,OAAO,oBAAoB,EAAE,UAAU;;;;;;;;;;;;;EAsBjD;AAED;;GAEG;AACH,wCAFW,MAAM,GAAG,MAAM,EAAE,UAU3B;AAWD;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,UAAU,4DAKjD;AAED;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,UAAU,4DAKjD;AAED;;;GAGG;AACH,6CAHW,OAAO,oBAAoB,EAAE,UAAU,6DAKjD;AAED;;;;GAIG;AACH,sCAHW,OAAO,oBAAoB,EAAE,UAAU,sDAKjD;AAxCM,+BAAgC,GAAG,QAI3B,OAAO,uBAAuB,EAAE,MAAM;;UAGtB,OAAO,gBAAgB,EAAE,KAAK,qCANR"}
@@ -1,3 +1,4 @@
1
+ import { withoutExprRef } from "../../view/paramMediator.js";
1
2
  import { isInlineData } from "./inlineSource.js";
2
3
 
3
4
  /**
@@ -13,7 +14,8 @@ export function getFormat(params) {
13
14
  }
14
15
  const format = { ...params.format };
15
16
 
16
- format.type ??= isUrlData(params) && extractTypeFromUrl(params.url);
17
+ format.type ??=
18
+ isUrlData(params) && extractTypeFromUrl(withoutExprRef(params.url));
17
19
  // @ts-ignore TODO: Fix typing
18
20
  format.parse ??= "auto";
19
21
 
@@ -12,7 +12,7 @@ export default class AxisTickSource extends SingleAxisLazySource {
12
12
  */
13
13
  ticks: import("../../../spec/channel.js").Scalar[];
14
14
  params: import("../../../spec/data.js").AxisTicksData;
15
- onDomainChanged(): Promise<void>;
15
+ onDomainChanged(): void;
16
16
  }
17
17
  import SingleAxisLazySource from "./singleAxisLazySource.js";
18
18
  //# sourceMappingURL=axisTickSource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"axisTickSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/axisTickSource.js"],"names":[],"mappings":"AAYA;;GAEG;AACH;IAMI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,aAAa,QAC7C,OAAO,uBAAuB,EAAE,OAAO,EAYjD;IAnBD;;OAEG;IACH,OAFU,OAAO,0BAA0B,EAAE,MAAM,EAAE,CAE1C;IAeP,sDAAoB;IAGxB,iCAkCC;CACJ;iCA9DgC,2BAA2B"}
1
+ {"version":3,"file":"axisTickSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/axisTickSource.js"],"names":[],"mappings":"AAYA;;GAEG;AACH;IAMI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,aAAa,QAC7C,OAAO,uBAAuB,EAAE,OAAO,EAYjD;IAnBD;;OAEG;IACH,OAFU,OAAO,0BAA0B,EAAE,MAAM,EAAE,CAE1C;IAeP,sDAAoB;IAGxB,wBAkCC;CACJ;iCA9DgC,2BAA2B"}
@@ -35,11 +35,11 @@ export default class AxisTickSource extends SingleAxisLazySource {
35
35
  this.params = params;
36
36
  }
37
37
 
38
- async onDomainChanged() {
38
+ onDomainChanged() {
39
39
  // Note, although this function is async, it is not awaited. Data are updated
40
40
  // synchronously to ensure that the new ticks are available before the next frame is drawn.
41
41
 
42
- const scale = this.scaleResolution.getScale();
42
+ const scale = this.scaleResolution.scale;
43
43
  const axisParams = this.params.axis;
44
44
  const axisLength = this.getAxisLength();
45
45
 
@@ -15,7 +15,7 @@ export default class BigBedSource extends SingleAxisWindowedSource {
15
15
  rest?: string;
16
16
  }) => Record<string, any>;
17
17
  params: import("../../../spec/data.js").BigBedData;
18
- initializedPromise: Promise<any>;
18
+ #private;
19
19
  }
20
20
  import SingleAxisWindowedSource from "./singleAxisWindowedSource.js";
21
21
  //# sourceMappingURL=bigBedSource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bigBedSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/bigBedSource.js"],"names":[],"mappings":"AAGA;IAUI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,UAAU,QAC1C,OAAO,uBAAuB,EAAE,OAAO,EAsDjD;IAjED,0CAA0C;IAC1C,QADW,OAAO,WAAW,EAAE,OAAO,CAC/B;IAEP,yCAAyC;IACzC,KADW,OAAO,WAAW,EAAE,MAAM,CACjC;IAEJ,4GAA4G;IAC5G,mBADmB,MAAM,UAAU;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,MAAM,EAAE,GAAG,CAAC,CAC9F;IAkBN,mDAAgC;IAQhC,iCA+BE;CAuBT;qCA1FoC,+BAA+B"}
1
+ {"version":3,"file":"bigBedSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/bigBedSource.js"],"names":[],"mappings":"AAOA;IAUI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,UAAU,QAC1C,OAAO,uBAAuB,EAAE,OAAO,EAmCjD;IA9CD,0CAA0C;IAC1C,QADW,OAAO,WAAW,EAAE,OAAO,CAC/B;IAEP,yCAAyC;IACzC,KADW,OAAO,WAAW,EAAE,MAAM,CACjC;IAEJ,4GAA4G;IAC5G,mBADmB,MAAM,UAAU;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,MAAM,EAAE,GAAG,CAAC,CAC9F;IA8BN,mDAA6B;;CA8EpC;qCAtHoC,+BAA+B"}
@@ -1,3 +1,7 @@
1
+ import {
2
+ activateExprRefProps,
3
+ withoutExprRef,
4
+ } from "../../../view/paramMediator.js";
1
5
  import addBaseUrl from "../../../utils/addBaseUrl.js";
2
6
  import SingleAxisWindowedSource from "./singleAxisWindowedSource.js";
3
7
 
@@ -25,9 +29,21 @@ export default class BigBedSource extends SingleAxisWindowedSource {
25
29
  ...params,
26
30
  };
27
31
 
28
- super(view, paramsWithDefaults.channel);
32
+ const activatedParams = activateExprRefProps(
33
+ view.paramMediator,
34
+ paramsWithDefaults,
35
+ (props) => {
36
+ if (props.includes("url")) {
37
+ this.#initialize().then(() => this.reloadLastDomain());
38
+ } else if (props.includes("windowSize")) {
39
+ this.reloadLastDomain();
40
+ }
41
+ }
42
+ );
43
+
44
+ super(view, activatedParams.channel);
29
45
 
30
- this.params = paramsWithDefaults;
46
+ this.params = activatedParams;
31
47
 
32
48
  if (!this.params.url) {
33
49
  throw new Error("No URL provided for BigBedSource");
@@ -35,7 +51,11 @@ export default class BigBedSource extends SingleAxisWindowedSource {
35
51
 
36
52
  this.setupDebouncing(this.params);
37
53
 
38
- this.initializedPromise = new Promise((resolve) => {
54
+ this.#initialize();
55
+ }
56
+
57
+ #initialize() {
58
+ this.initializedPromise = new Promise((resolve, reject) => {
39
59
  Promise.all([
40
60
  import("@gmod/bed"),
41
61
  import("@gmod/bbi"),
@@ -45,28 +65,40 @@ export default class BigBedSource extends SingleAxisWindowedSource {
45
65
 
46
66
  this.bbi = new BigBed({
47
67
  filehandle: new RemoteFile(
48
- addBaseUrl(this.params.url, this.view.getBaseUrl())
68
+ addBaseUrl(
69
+ withoutExprRef(this.params.url),
70
+ this.view.getBaseUrl()
71
+ )
49
72
  ),
50
73
  });
51
74
 
52
- this.bbi.getHeader().then(async (header) => {
53
- // @ts-ignore TODO: Fix
54
- this.parser = new BED({ autoSql: header.autoSql });
55
- try {
56
- const fastParser = makeFastParser(this.parser);
57
- this.parseLine = (chrom, f) =>
58
- fastParser(chrom, f.start, f.end, f.rest);
59
- } catch (e) {
60
- this.parseLine = (chrom, f) =>
61
- this.parser.parseLine(
62
- `${chrom}\t${f.start}\t${f.end}\t${f.rest}`
63
- );
64
- }
65
-
66
- resolve();
67
- });
75
+ this.bbi
76
+ .getHeader()
77
+ .then(async (header) => {
78
+ // @ts-ignore TODO: Fix
79
+ this.parser = new BED({ autoSql: header.autoSql });
80
+ try {
81
+ const fastParser = makeFastParser(this.parser);
82
+ this.parseLine = (chrom, f) =>
83
+ fastParser(chrom, f.start, f.end, f.rest);
84
+ } catch (e) {
85
+ this.parseLine = (chrom, f) =>
86
+ this.parser.parseLine(
87
+ `${chrom}\t${f.start}\t${f.end}\t${f.rest}`
88
+ );
89
+ }
90
+
91
+ resolve();
92
+ })
93
+ .catch((e) => {
94
+ // Load empty data
95
+ this.load();
96
+ reject(e);
97
+ });
68
98
  });
69
99
  });
100
+
101
+ return this.initializedPromise;
70
102
  }
71
103
 
72
104
  /**
@@ -8,7 +8,12 @@ export default class BigWigSource extends SingleAxisWindowedSource {
8
8
  */
9
9
  constructor(params: import("../../../spec/data.js").BigWigData, view: import("../../../view/view.js").default);
10
10
  params: import("../../../spec/data.js").BigWigData;
11
- initializedPromise: Promise<any>;
11
+ /**
12
+ * Listen to the domain change event and update data when the covered windows change.
13
+ *
14
+ * @param {number[]} domain Linearized domain
15
+ */
16
+ onDomainChanged(domain: number[]): Promise<void>;
12
17
  /**
13
18
  * @param {number[]} interval linearized domain
14
19
  * @param {number} reductionLevel
@@ -1 +1 @@
1
- {"version":3,"file":"bigWigSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/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
+ {"version":3,"file":"bigWigSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/bigWigSource.js"],"names":[],"mappings":"AAOA;;GAEG;AACH;IAOI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,UAAU,QAC1C,OAAO,uBAAuB,EAAE,OAAO,EAmCjD;IATG,mDAA6B;IA8CjC;;;;OAIG;IACH,wBAFW,MAAM,EAAE,iBAqBlB;IAED;;;OAGG;IAEH,uBAJW,MAAM,EAAE,kBACR,MAAM,iBA2BhB;;CACJ;qCA9IoC,+BAA+B"}
@@ -1,3 +1,7 @@
1
+ import {
2
+ activateExprRefProps,
3
+ withoutExprRef,
4
+ } from "../../../view/paramMediator.js";
1
5
  import addBaseUrl from "../../../utils/addBaseUrl.js";
2
6
  import SingleAxisWindowedSource from "./singleAxisWindowedSource.js";
3
7
 
@@ -25,9 +29,21 @@ export default class BigWigSource extends SingleAxisWindowedSource {
25
29
  ...params,
26
30
  };
27
31
 
28
- super(view, paramsWithDefaults.channel);
32
+ const activatedParams = activateExprRefProps(
33
+ view.paramMediator,
34
+ paramsWithDefaults,
35
+ (props) => {
36
+ if (props.includes("url")) {
37
+ this.#initialize().then(() => this.reloadLastDomain());
38
+ } else if (props.includes("pixelsPerBin")) {
39
+ this.reloadLastDomain();
40
+ }
41
+ }
42
+ );
43
+
44
+ super(view, activatedParams.channel);
29
45
 
30
- this.params = paramsWithDefaults;
46
+ this.params = activatedParams;
31
47
 
32
48
  if (!this.params.url) {
33
49
  throw new Error("No URL provided for BigWigSource");
@@ -35,6 +51,10 @@ export default class BigWigSource extends SingleAxisWindowedSource {
35
51
 
36
52
  this.setupDebouncing(this.params);
37
53
 
54
+ this.#initialize();
55
+ }
56
+
57
+ #initialize() {
38
58
  this.initializedPromise = new Promise((resolve) => {
39
59
  Promise.all([
40
60
  import("@gmod/bbi"),
@@ -42,7 +62,10 @@ export default class BigWigSource extends SingleAxisWindowedSource {
42
62
  ]).then(([{ BigWig }, { RemoteFile }]) => {
43
63
  this.#bbi = new BigWig({
44
64
  filehandle: new RemoteFile(
45
- addBaseUrl(this.params.url, this.view.getBaseUrl())
65
+ addBaseUrl(
66
+ withoutExprRef(this.params.url),
67
+ this.view.getBaseUrl()
68
+ )
46
69
  ),
47
70
  });
48
71
 
@@ -62,6 +85,8 @@ export default class BigWigSource extends SingleAxisWindowedSource {
62
85
  });
63
86
  });
64
87
  });
88
+
89
+ return this.initializedPromise;
65
90
  }
66
91
 
67
92
  /**
@@ -85,11 +110,9 @@ export default class BigWigSource extends SingleAxisWindowedSource {
85
110
  // Using 5000 as a default to avoid too many requests.
86
111
  const windowSize = Math.max(reductionLevel * length, 5000);
87
112
 
88
- const quantizedInterval = this.quantizeInterval(domain, windowSize);
89
-
90
- if (this.checkAndUpdateLastInterval(quantizedInterval)) {
91
- this.loadInterval(quantizedInterval, reductionLevel);
92
- }
113
+ this.callIfWindowsChanged(domain, windowSize, (quantizedInterval) =>
114
+ this.loadInterval(quantizedInterval, reductionLevel)
115
+ );
93
116
  }
94
117
 
95
118
  /**
@@ -98,7 +121,8 @@ export default class BigWigSource extends SingleAxisWindowedSource {
98
121
  */
99
122
  // @ts-expect-error
100
123
  async loadInterval(interval, reductionLevel) {
101
- const scale = 1 / 2 / reductionLevel / this.params.pixelsPerBin;
124
+ const scale =
125
+ 1 / 2 / reductionLevel / withoutExprRef(this.params.pixelsPerBin);
102
126
  const featureChunks = await this.discretizeAndLoad(
103
127
  interval,
104
128
  (d, signal) =>
@@ -34,7 +34,7 @@ export default class SingleAxisLazySource extends DataSource {
34
34
  * @param {import("../../../spec/genome.js").ChromosomalLocus[]} complexDomain Chrom/Pos domain
35
35
  * @abstract
36
36
  */
37
- onDomainChanged(domain: number[], complexDomain: import("../../../spec/genome.js").ChromosomalLocus[]): Promise<void>;
37
+ onDomainChanged(domain: number[], complexDomain: import("../../../spec/genome.js").ChromosomalLocus[]): void;
38
38
  /**
39
39
  * Sets the loading status of the data source. The status is shown in the UI.
40
40
  *
@@ -1 +1 @@
1
- {"version":3,"file":"singleAxisLazySource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/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"}
1
+ {"version":3,"file":"singleAxisLazySource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/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,QAK9D;IAED;;;;;OAKG;IACH,mCAHW,OAAO,QAKjB;IAED;;;;;OAKG;IACH,gCAGC;IAQD;;;;;OAKG;IACH,8BAHW,OAAO,mBAAmB,EAAE,KAAK,EAAE,EAAE,QAgB/C;CACJ;uBAtJsB,kBAAkB"}
@@ -98,7 +98,7 @@ export default class SingleAxisLazySource extends DataSource {
98
98
  * @param {import("../../../spec/genome.js").ChromosomalLocus[]} complexDomain Chrom/Pos domain
99
99
  * @abstract
100
100
  */
101
- async onDomainChanged(domain, complexDomain) {
101
+ onDomainChanged(domain, complexDomain) {
102
102
  // Override me
103
103
  }
104
104
 
@@ -148,7 +148,5 @@ export default class SingleAxisLazySource extends DataSource {
148
148
  this.complete();
149
149
 
150
150
  reconfigureScales(this.view);
151
-
152
- this.requestRender();
153
151
  }
154
152
  }
@@ -1,13 +1,16 @@
1
1
  /**
2
+ * Divides the domain into windows and loads the data for one or two consecutive windows
3
+ * that cover the visible interval.
4
+ *
2
5
  * @abstract
3
6
  */
4
7
  export default class SingleAxisWindowedSource extends SingleAxisLazySource {
5
8
  /**
6
- * @type {{windowSize?: number}}
9
+ * @type {{windowSize?: number | import("../../../spec/parameter.js").ExprRef}}
7
10
  * @protected
8
11
  */
9
12
  protected params: {
10
- windowSize?: number;
13
+ windowSize?: number | import("../../../spec/parameter.js").ExprRef;
11
14
  };
12
15
  /**
13
16
  * @param {import("../../../spec/data.js").DebouncedData} debounceParams
@@ -19,7 +22,7 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
19
22
  *
20
23
  * @param {number[]} domain Linearized domain
21
24
  */
22
- onDomainChanged(domain: number[]): Promise<void>;
25
+ onDomainChanged(domain: number[]): void;
23
26
  /**
24
27
  * Listen to the domain change event and update data when the covered windows change.
25
28
  *
@@ -27,6 +30,10 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
27
30
  * @protected
28
31
  */
29
32
  protected loadInterval(interval: number[]): Promise<void>;
33
+ /**
34
+ * @protected
35
+ */
36
+ protected reloadLastDomain(): void;
30
37
  /**
31
38
  * Splits the interval into discrete chromosomal intervals – one for each chromosome –
32
39
  * and loads the data for each of them. Handles abort signals and errors.
@@ -39,21 +46,13 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
39
46
  */
40
47
  protected discretizeAndLoad<T>(interval: number[], loader: (discreteInteval: import("@genome-spy/core/genome/genome.js").DiscreteChromosomeInterval, signal: AbortSignal) => Promise<T>): Promise<T[]>;
41
48
  /**
42
- * Returns three consecutive windows. The idea is to immediately have some data
43
- * to show to the user when they pan the view. The windows are conceptually
44
- * similar to "tiles" but they are never loaded separately.
45
49
  *
46
- * @param {number[]} interval
50
+ * @param {number[]} interval Domain
47
51
  * @param {number} windowSize
52
+ * @param {function(number[]):void} callback
48
53
  * @protected
49
54
  */
50
- protected quantizeInterval(interval: number[], windowSize: number): number[];
51
- /**
52
- *
53
- * @param {number[]} interval
54
- * @protected
55
- */
56
- protected checkAndUpdateLastInterval(interval: number[]): boolean;
55
+ protected callIfWindowsChanged(interval: number[], windowSize: number, callback: (arg0: number[]) => void): void;
57
56
  #private;
58
57
  }
59
58
  import SingleAxisLazySource from "./singleAxisLazySource.js";
@@ -1 +1 @@
1
- {"version":3,"file":"singleAxisWindowedSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/singleAxisWindowedSource.js"],"names":[],"mappings":"AAIA;;GAEG;AACH;IAQI;;;OAGG;IACH,kBAHU;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAC,CAGxB;IAEP;;;OAGG;IACH,0CAHW,OAAO,uBAAuB,EAAE,aAAa,QAmBvD;IAED;;;;OAIG;IACH,wBAFW,MAAM,EAAE,iBAiBlB;IAED;;;;;OAKG;IACH,iCAHW,MAAM,EAAE,iBAKlB;IAED;;;;;;;;;OASG;IACH,yCANW,MAAM,EAAE,4BACU,OAAO,mCAAmC,EAAE,0BAA0B,UAAU,WAAW,+BAqCvH;IAED;;;;;;;;OAQG;IACH,qCAJW,MAAM,EAAE,cACR,MAAM,YAWhB;IAED;;;;OAIG;IACH,+CAHW,MAAM,EAAE,WAUlB;;CACJ;iCAvJgC,2BAA2B"}
1
+ {"version":3,"file":"singleAxisWindowedSource.d.ts","sourceRoot":"","sources":["../../../../../src/data/sources/lazy/singleAxisWindowedSource.js"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH;IAWI;;;OAGG;IACH,kBAHU;QAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,4BAA4B,EAAE,OAAO,CAAA;KAAC,CAGvE;IAEP;;;OAGG;IACH,0CAHW,OAAO,uBAAuB,EAAE,aAAa,QAqBvD;IAED;;;;OAIG;IACH,wBAFW,MAAM,EAAE,QAqBlB;IAcD;;;;;OAKG;IACH,iCAHW,MAAM,EAAE,iBAKlB;IApBD;;OAEG;IACH,mCAOC;IAYD;;;;;;;;;OASG;IACH,yCANW,MAAM,EAAE,4BACU,OAAO,mCAAmC,EAAE,0BAA0B,UAAU,WAAW,+BAqCvH;IAED;;;;;;OAMG;IACH,yCALW,MAAM,EAAE,cACR,MAAM,mBACG,MAAM,EAAE,KAAE,IAAI,QAyBjC;;CACJ;iCA3KgC,2BAA2B"}
@@ -1,20 +1,26 @@
1
+ import { withoutExprRef } from "../../../view/paramMediator.js";
2
+ import { debounce } from "../../../utils/debounce.js";
1
3
  import SingleAxisLazySource from "./singleAxisLazySource.js";
2
- import { shallowArrayEquals } from "../../../utils/arrayUtils.js";
3
- import { debounce } from "@genome-spy/core/utils/debounce.js";
4
4
 
5
5
  /**
6
+ * Divides the domain into windows and loads the data for one or two consecutive windows
7
+ * that cover the visible interval.
8
+ *
6
9
  * @abstract
7
10
  */
8
11
  export default class SingleAxisWindowedSource extends SingleAxisLazySource {
9
12
  #abortController = new AbortController();
10
13
 
11
- /**
12
- * @type {number[]}
13
- */
14
+ /** @type {number[]} */
14
15
  #lastQuantizedInterval = [0, 0];
15
16
 
17
+ /** @type {number[]} */
18
+ #lastDomain = [0, 0];
19
+
20
+ #lastWindowSize = 0;
21
+
16
22
  /**
17
- * @type {{windowSize?: number}}
23
+ * @type {{windowSize?: number | import("../../../spec/parameter.js").ExprRef}}
18
24
  * @protected
19
25
  */
20
26
  params;
@@ -24,20 +30,22 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
24
30
  * @protected
25
31
  */
26
32
  setupDebouncing(debounceParams) {
27
- if (debounceParams.debounce > 0) {
28
- if (debounceParams.debounceMode == "domain") {
29
- this.onDomainChanged = debounce(
30
- this.onDomainChanged.bind(this),
31
- debounceParams.debounce,
32
- false
33
- );
34
- } else if (debounceParams.debounceMode == "window") {
35
- this.loadInterval = debounce(
36
- this.loadInterval.bind(this),
37
- debounceParams.debounce,
38
- false
39
- );
40
- }
33
+ const wait = () => withoutExprRef(debounceParams.debounce);
34
+ const debounceMode = debounceParams.debounceMode;
35
+ if (debounceMode == "domain") {
36
+ this.onDomainChanged = debounce(
37
+ this.onDomainChanged.bind(this),
38
+ wait,
39
+ false
40
+ );
41
+ } else if (debounceMode == "window") {
42
+ this.loadInterval = debounce(
43
+ this.loadInterval.bind(this),
44
+ wait,
45
+ false
46
+ );
47
+ } else {
48
+ throw new Error("Invalid debounceMode: " + debounceMode);
41
49
  }
42
50
  }
43
51
 
@@ -46,21 +54,37 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
46
54
  *
47
55
  * @param {number[]} domain Linearized domain
48
56
  */
49
- async onDomainChanged(domain) {
50
- const windowSize = this.params?.windowSize ?? -1;
57
+ onDomainChanged(domain) {
58
+ this.#lastDomain = domain;
59
+
60
+ const windowSize = withoutExprRef(this.params?.windowSize) ?? -1;
51
61
 
52
62
  if (domain[1] - domain[0] > windowSize) {
53
63
  return;
54
64
  }
55
65
 
56
- const quantizedInterval = this.quantizeInterval(domain, windowSize);
66
+ this.callIfWindowsChanged(
67
+ domain,
68
+ windowSize,
69
+ async (quantizedInterval) => {
70
+ // Possible metadata must be loaded before the first request.
71
+ await this.initializedPromise;
57
72
 
58
- if (this.checkAndUpdateLastInterval(quantizedInterval)) {
59
- // Possible metadata must be loaded before the first request.
60
- await this.initializedPromise;
73
+ this.loadInterval(quantizedInterval);
74
+ }
75
+ );
76
+ }
61
77
 
62
- this.loadInterval(quantizedInterval);
63
- }
78
+ /**
79
+ * @protected
80
+ */
81
+ reloadLastDomain() {
82
+ const domain = this.#lastDomain;
83
+
84
+ this.#lastDomain = [0, 0];
85
+ this.#lastQuantizedInterval = [0, 0];
86
+
87
+ this.onDomainChanged(domain);
64
88
  }
65
89
 
66
90
  /**
@@ -118,35 +142,33 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
118
142
  }
119
143
 
120
144
  /**
121
- * Returns three consecutive windows. The idea is to immediately have some data
122
- * to show to the user when they pan the view. The windows are conceptually
123
- * similar to "tiles" but they are never loaded separately.
124
145
  *
125
- * @param {number[]} interval
146
+ * @param {number[]} interval Domain
126
147
  * @param {number} windowSize
148
+ * @param {function(number[]):void} callback
127
149
  * @protected
128
150
  */
129
- quantizeInterval(interval, windowSize) {
130
- return [
131
- Math.max(Math.floor(interval[0] / windowSize - 1) * windowSize, 0),
151
+ callIfWindowsChanged(interval, windowSize, callback) {
152
+ // One or two consecutive windows that cover the given interval.
153
+ // The windows are conceptually similar to "tiles" but they are never loaded separately.
154
+ const quantizedInterval = [
155
+ Math.max(Math.floor(interval[0] / windowSize) * windowSize, 0),
132
156
  Math.min(
133
- Math.ceil(interval[1] / windowSize + 1) * windowSize,
157
+ Math.ceil(interval[1] / windowSize) * windowSize,
134
158
  this.genome.totalSize // Perhaps scale domain should be used here
135
159
  ),
136
160
  ];
137
- }
138
161
 
139
- /**
140
- *
141
- * @param {number[]} interval
142
- * @protected
143
- */
144
- checkAndUpdateLastInterval(interval) {
145
- if (shallowArrayEquals(this.#lastQuantizedInterval, interval)) {
146
- return false;
147
- }
162
+ const last = this.#lastQuantizedInterval;
163
+ if (
164
+ windowSize !== this.#lastWindowSize ||
165
+ quantizedInterval[0] < last[0] ||
166
+ quantizedInterval[1] > last[1]
167
+ ) {
168
+ this.#lastQuantizedInterval = quantizedInterval;
169
+ this.#lastWindowSize = windowSize;
148
170
 
149
- this.#lastQuantizedInterval = interval;
150
- return true;
171
+ callback(quantizedInterval);
172
+ }
151
173
  }
152
174
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sequenceSource.d.ts","sourceRoot":"","sources":["../../../../src/data/sources/sequenceSource.js"],"names":[],"mappings":"AAEA;;;GAGG;AACH,0CAHW,QAAQ,OAAO,oBAAoB,EAAE,IAAI,CAAC,0DAKpD;AAED;IACI;;;;OAIG;IACH,oBAHW,OAAO,oBAAoB,EAAE,iBAAiB,QAC9C,OAAO,oBAAoB,EAAE,OAAO,EAY9C;IARG,sDAA+B;IAUnC,0BAaC;CAKJ;uBA9CsB,iBAAiB"}
1
+ {"version":3,"file":"sequenceSource.d.ts","sourceRoot":"","sources":["../../../../src/data/sources/sequenceSource.js"],"names":[],"mappings":"AAMA;;;GAGG;AACH,0CAHW,QAAQ,OAAO,oBAAoB,EAAE,IAAI,CAAC,0DAKpD;AAED;IACI;;;;OAIG;IACH,oBAHW,OAAO,oBAAoB,EAAE,iBAAiB,QAC9C,OAAO,oBAAoB,EAAE,OAAO,EAgB9C;IAZG,sDAIC;IAUL,0BAcC;CAKJ;uBAnDsB,iBAAiB"}