@genome-spy/core 0.43.2 → 0.44.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 (65) hide show
  1. package/dist/bundle/index.es.js +5621 -5346
  2. package/dist/bundle/index.js +156 -104
  3. package/dist/schema.json +412 -43
  4. package/dist/src/data/sources/lazy/axisTickSource.d.ts +1 -1
  5. package/dist/src/data/sources/lazy/axisTickSource.d.ts.map +1 -1
  6. package/dist/src/data/sources/lazy/axisTickSource.js +2 -2
  7. package/dist/src/data/sources/lazy/bigBedSource.js +70 -28
  8. package/dist/src/data/sources/lazy/bigWigSource.d.ts +6 -0
  9. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  10. package/dist/src/data/sources/lazy/bigWigSource.js +3 -5
  11. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +1 -1
  12. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  13. package/dist/src/data/sources/lazy/singleAxisLazySource.js +1 -1
  14. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts +7 -12
  15. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  16. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +33 -29
  17. package/dist/src/data/transforms/filterScoredLabels.js +1 -1
  18. package/dist/src/encoder/encoder.d.ts.map +1 -1
  19. package/dist/src/encoder/encoder.js +16 -6
  20. package/dist/src/genomeSpy.d.ts +1 -0
  21. package/dist/src/genomeSpy.d.ts.map +1 -1
  22. package/dist/src/genomeSpy.js +108 -6
  23. package/dist/src/gl/glslScaleGenerator.d.ts +23 -3
  24. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  25. package/dist/src/gl/glslScaleGenerator.js +137 -42
  26. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  27. package/dist/src/gl/webGLHelper.js +5 -7
  28. package/dist/src/marks/link.common.glsl.js +2 -0
  29. package/dist/src/marks/link.d.ts.map +1 -1
  30. package/dist/src/marks/link.js +19 -9
  31. package/dist/src/marks/link.vertex.glsl.js +1 -1
  32. package/dist/src/marks/mark.d.ts +19 -17
  33. package/dist/src/marks/mark.d.ts.map +1 -1
  34. package/dist/src/marks/mark.js +181 -120
  35. package/dist/src/marks/point.common.glsl.js +1 -1
  36. package/dist/src/marks/rect.common.glsl.js +2 -0
  37. package/dist/src/marks/rect.d.ts.map +1 -1
  38. package/dist/src/marks/rect.js +12 -12
  39. package/dist/src/marks/rect.vertex.glsl.js +1 -1
  40. package/dist/src/marks/rule.common.glsl.js +1 -1
  41. package/dist/src/marks/rule.js +2 -2
  42. package/dist/src/marks/text.common.glsl.js +1 -1
  43. package/dist/src/marks/text.js +2 -2
  44. package/dist/src/paramBroker.d.ts +19 -3
  45. package/dist/src/paramBroker.d.ts.map +1 -1
  46. package/dist/src/paramBroker.js +18 -2
  47. package/dist/src/spec/channel.d.ts +4 -3
  48. package/dist/src/spec/mark.d.ts +17 -25
  49. package/dist/src/spec/parameter.d.ts +123 -0
  50. package/dist/src/spec/root.d.ts +9 -0
  51. package/dist/src/spec/scale.d.ts +2 -1
  52. package/dist/src/spec/view.d.ts +1 -1
  53. package/dist/src/types/scaleResolutionApi.d.ts +7 -3
  54. package/dist/src/utils/expression.d.ts +2 -2
  55. package/dist/src/utils/expression.d.ts.map +1 -1
  56. package/dist/src/utils/expression.js +3 -3
  57. package/dist/src/view/axisView.js +3 -3
  58. package/dist/src/view/scaleResolution.d.ts +8 -18
  59. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  60. package/dist/src/view/scaleResolution.js +220 -126
  61. package/dist/src/view/scaleResolution.test.js +7 -7
  62. package/dist/src/view/unitView.d.ts.map +1 -1
  63. package/dist/src/view/unitView.js +10 -3
  64. package/dist/src/view/view.js +2 -2
  65. package/package.json +2 -2
@@ -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
 
@@ -92,11 +92,22 @@ export default class BigBedSource extends SingleAxisWindowedSource {
92
92
  }
93
93
 
94
94
  /**
95
- * A specific optimization for Hautaniemi Lab's Methylation project, where
96
- * we have hundreds of columns having small integers (0-100).
97
- * This parser avoids generating piles of garbage to be collected by the GC.
98
- * We don't split the line into an array of strings, but instead parse the
99
- * integer fields directly from the original string.
95
+ * An optimized parser for Hautaniemi Lab's Methylation project, where
96
+ * we have hundreds of columns having small integers (0-100). This is over 5x
97
+ * faster than @gmod/bed's parser.
98
+ *
99
+ * Techniques used:
100
+ *
101
+ * 1. Avoid generating garbage by parsing integers directly from the string,
102
+ * i.e., without splitting the line into an array of strings.
103
+ * 2. Use a template object to avoid hidden class changes after each property
104
+ * assignment. Avoids garbage generation.
105
+ * 3. Generate and compile code that uses constants to access object properties,
106
+ * avoiding Map lookups during assignment.
107
+ * 4. Input chrom, startPos, and endPos as parameters so that @gmod/bbi's
108
+ * output doesn't first need to be converted to a string just to be parsed
109
+ * again.
110
+ *
100
111
  * This parser doesn't support arrays, etc. at the moment. This could, however,
101
112
  * be extended into a fully-featured parser.
102
113
  *
@@ -152,28 +163,11 @@ function makeFastParser(bed) {
152
163
  return value * sign;
153
164
  }
154
165
 
155
- const fieldParsers = fields.map((field) => {
156
- const { name, type } = field;
157
-
158
- if (["ubyte", "int", "uint"].includes(type)) {
159
- return () => {
160
- currentObject[name] = parseInt();
161
- };
162
- } else if (field.isNumeric) {
163
- return () => {
164
- currentObject[name] = Number(parseString());
165
- };
166
- } else if (["char", "string", "lstring"].includes(type)) {
167
- return () => {
168
- currentObject[name] = parseString();
169
- };
170
- } else {
171
- throw new Error("Unsupported type: " + type);
172
- }
173
- });
174
-
175
166
  const templateFields = fields.map(
176
- (field) => `"${field.name}": ${field.isNumeric ? "0" : "emptyString"}`
167
+ (field) =>
168
+ `${JSON.stringify(field.name)}: ${
169
+ field.isNumeric ? "0" : "emptyString"
170
+ }`
177
171
  );
178
172
 
179
173
  /**
@@ -196,6 +190,42 @@ function makeFastParser(bed) {
196
190
  }
197
191
  };`)();
198
192
 
193
+ /*
194
+ * Generate setter code that uses constant field names to access the
195
+ * object's properties. This avoids Map lookups and allows for efficient
196
+ * machine code to be generated by the VM.
197
+ */
198
+ const fieldParsers = fields.map((field) => {
199
+ const type = field.type;
200
+ const name = JSON.stringify(field.name);
201
+
202
+ if (["ubyte", "int", "uint"].includes(type)) {
203
+ return `d[${name}] = parseInt();`;
204
+ } else if (field.isNumeric) {
205
+ return `d[${name}] = Number(parseString());`;
206
+ } else if (["char", "string", "lstring"].includes(type)) {
207
+ return `d[${name}] = parseString();`;
208
+ } else {
209
+ throw new Error("Unsupported type: " + type);
210
+ // TODO: Implement them
211
+ }
212
+ });
213
+
214
+ /*
215
+ * Split the field parsers into chunks to avoid creating so large
216
+ * functions that the JavaScript VM would decline to optimize it.
217
+ * Not sure if this is really necessary, but the added cost is minimal.
218
+ */
219
+ const chunckedFieldParsers = chunk(fieldParsers, 50).map((chunk, i) =>
220
+ Function(
221
+ "parseInt",
222
+ "parseString",
223
+ `return function parseFieldChunk${i}(d) {
224
+ ${chunk.join("\n")}
225
+ }`
226
+ )(parseInt, parseString)
227
+ );
228
+
199
229
  /**
200
230
  * @param {string} line
201
231
  */
@@ -216,8 +246,8 @@ function makeFastParser(bed) {
216
246
 
217
247
  currentObject = makeTemplate(chrom, chromStart, chromEnd);
218
248
 
219
- for (let j = 0, n = fieldParsers.length; j < n; j++) {
220
- fieldParsers[j]();
249
+ for (const parser of chunckedFieldParsers) {
250
+ parser(currentObject);
221
251
  }
222
252
 
223
253
  return currentObject;
@@ -225,3 +255,15 @@ function makeFastParser(bed) {
225
255
 
226
256
  return parseLine;
227
257
  }
258
+
259
+ /**
260
+ * @param {T[]} arr
261
+ * @param {number} size
262
+ * @template T
263
+ */
264
+ function chunk(arr, size) {
265
+ // https://www.30secondsofcode.org/js/s/split-array-into-chunks/
266
+ return Array.from({ length: Math.ceil(arr.length / size) }, (_v, i) =>
267
+ arr.slice(i * size, i * size + size)
268
+ );
269
+ }
@@ -9,6 +9,12 @@ export default class BigWigSource extends SingleAxisWindowedSource {
9
9
  constructor(params: import("../../../spec/data.js").BigWigData, view: import("../../../view/view.js").default);
10
10
  params: import("../../../spec/data.js").BigWigData;
11
11
  initializedPromise: Promise<any>;
12
+ /**
13
+ * Listen to the domain change event and update data when the covered windows change.
14
+ *
15
+ * @param {number[]} domain Linearized domain
16
+ */
17
+ onDomainChanged(domain: number[]): Promise<void>;
12
18
  /**
13
19
  * @param {number[]} interval linearized domain
14
20
  * @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":"AAGA;;GAEG;AACH;IAOI;;;OAGG;IACH,oBAHW,OAAO,uBAAuB,EAAE,UAAU,QAC1C,OAAO,uBAAuB,EAAE,OAAO,EAiDjD;IAnCG,mDAAgC;IAQhC,iCA0BE;IAGN;;;;OAIG;IACH,wBAFW,MAAM,EAAE,iBAqBlB;IAED;;;OAGG;IAEH,uBAJW,MAAM,EAAE,kBACR,MAAM,iBA0BhB;;CACJ;qCAxHoC,+BAA+B"}
@@ -85,11 +85,9 @@ export default class BigWigSource extends SingleAxisWindowedSource {
85
85
  // Using 5000 as a default to avoid too many requests.
86
86
  const windowSize = Math.max(reductionLevel * length, 5000);
87
87
 
88
- const quantizedInterval = this.quantizeInterval(domain, windowSize);
89
-
90
- if (this.checkAndUpdateLastInterval(quantizedInterval)) {
91
- this.loadInterval(quantizedInterval, reductionLevel);
92
- }
88
+ this.callIfWindowsChanged(domain, windowSize, (quantizedInterval) =>
89
+ this.loadInterval(quantizedInterval, reductionLevel)
90
+ );
93
91
  }
94
92
 
95
93
  /**
@@ -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,QAkB/C;CACJ;uBAxJsB,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
 
@@ -1,4 +1,7 @@
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 {
@@ -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
  *
@@ -39,21 +42,13 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
39
42
  */
40
43
  protected discretizeAndLoad<T>(interval: number[], loader: (discreteInteval: import("@genome-spy/core/genome/genome.js").DiscreteChromosomeInterval, signal: AbortSignal) => Promise<T>): Promise<T[]>;
41
44
  /**
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
45
  *
46
- * @param {number[]} interval
46
+ * @param {number[]} interval Domain
47
47
  * @param {number} windowSize
48
+ * @param {function(number[]):void} callback
48
49
  * @protected
49
50
  */
50
- protected quantizeInterval(interval: number[], windowSize: number): number[];
51
- /**
52
- *
53
- * @param {number[]} interval
54
- * @protected
55
- */
56
- protected checkAndUpdateLastInterval(interval: number[]): boolean;
51
+ protected callIfWindowsChanged(interval: number[], windowSize: number, callback: (arg0: number[]) => void): void;
57
52
  #private;
58
53
  }
59
54
  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":"AAGA;;;;;GAKG;AACH;IAUI;;;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,QAmBlB;IAED;;;;;OAKG;IACH,iCAHW,MAAM,EAAE,iBAKlB;IAED;;;;;;;;;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;iCA3JgC,2BAA2B"}
@@ -1,8 +1,10 @@
1
1
  import SingleAxisLazySource from "./singleAxisLazySource.js";
2
- import { shallowArrayEquals } from "../../../utils/arrayUtils.js";
3
2
  import { debounce } from "@genome-spy/core/utils/debounce.js";
4
3
 
5
4
  /**
5
+ * Divides the domain into windows and loads the data for one or two consecutive windows
6
+ * that cover the visible interval.
7
+ *
6
8
  * @abstract
7
9
  */
8
10
  export default class SingleAxisWindowedSource extends SingleAxisLazySource {
@@ -13,6 +15,8 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
13
15
  */
14
16
  #lastQuantizedInterval = [0, 0];
15
17
 
18
+ #lastWindowSize = 0;
19
+
16
20
  /**
17
21
  * @type {{windowSize?: number}}
18
22
  * @protected
@@ -46,21 +50,23 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
46
50
  *
47
51
  * @param {number[]} domain Linearized domain
48
52
  */
49
- async onDomainChanged(domain) {
53
+ onDomainChanged(domain) {
50
54
  const windowSize = this.params?.windowSize ?? -1;
51
55
 
52
56
  if (domain[1] - domain[0] > windowSize) {
53
57
  return;
54
58
  }
55
59
 
56
- const quantizedInterval = this.quantizeInterval(domain, windowSize);
57
-
58
- if (this.checkAndUpdateLastInterval(quantizedInterval)) {
59
- // Possible metadata must be loaded before the first request.
60
- await this.initializedPromise;
60
+ this.callIfWindowsChanged(
61
+ domain,
62
+ windowSize,
63
+ async (quantizedInterval) => {
64
+ // Possible metadata must be loaded before the first request.
65
+ await this.initializedPromise;
61
66
 
62
- this.loadInterval(quantizedInterval);
63
- }
67
+ this.loadInterval(quantizedInterval);
68
+ }
69
+ );
64
70
  }
65
71
 
66
72
  /**
@@ -118,35 +124,33 @@ export default class SingleAxisWindowedSource extends SingleAxisLazySource {
118
124
  }
119
125
 
120
126
  /**
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
127
  *
125
- * @param {number[]} interval
128
+ * @param {number[]} interval Domain
126
129
  * @param {number} windowSize
130
+ * @param {function(number[]):void} callback
127
131
  * @protected
128
132
  */
129
- quantizeInterval(interval, windowSize) {
130
- return [
131
- Math.max(Math.floor(interval[0] / windowSize - 1) * windowSize, 0),
133
+ callIfWindowsChanged(interval, windowSize, callback) {
134
+ // One or two consecutive windows that cover the given interval.
135
+ // The windows are conceptually similar to "tiles" but they are never loaded separately.
136
+ const quantizedInterval = [
137
+ Math.max(Math.floor(interval[0] / windowSize) * windowSize, 0),
132
138
  Math.min(
133
- Math.ceil(interval[1] / windowSize + 1) * windowSize,
139
+ Math.ceil(interval[1] / windowSize) * windowSize,
134
140
  this.genome.totalSize // Perhaps scale domain should be used here
135
141
  ),
136
142
  ];
137
- }
138
143
 
139
- /**
140
- *
141
- * @param {number[]} interval
142
- * @protected
143
- */
144
- checkAndUpdateLastInterval(interval) {
145
- if (shallowArrayEquals(this.#lastQuantizedInterval, interval)) {
146
- return false;
147
- }
144
+ const last = this.#lastQuantizedInterval;
145
+ if (
146
+ windowSize !== this.#lastWindowSize ||
147
+ quantizedInterval[0] < last[0] ||
148
+ quantizedInterval[1] > last[1]
149
+ ) {
150
+ this.#lastQuantizedInterval = quantizedInterval;
151
+ this.#lastWindowSize = windowSize;
148
152
 
149
- this.#lastQuantizedInterval = interval;
150
- return true;
153
+ callback(quantizedInterval);
154
+ }
151
155
  }
152
156
  }
@@ -75,7 +75,7 @@ export default class FilterScoredLabelsTransform extends FlowNode {
75
75
  _filterAndPropagate() {
76
76
  super.reset();
77
77
 
78
- const scale = this.resolution.getScale();
78
+ const scale = this.resolution.scale;
79
79
  const rangeSpan =
80
80
  this.resolution.members[0].view.coords?.[
81
81
  this.channel == "x" ? "width" : "height"
@@ -1 +1 @@
1
- {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.js"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,6CAJW,OAAO,kBAAkB,EAAE,OAAO,aAClC,OAAO,oBAAoB,EAAE,QAAQ,gGAsC/C;AAED;;;;;;;GAOG;AACH,0CANW,OAAO,oBAAoB,EAAE,UAAU,SACvC,GAAG,0IA2Fb;AAED;;;;;GAKG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,mEAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,uDAKjD;AAED;;;GAGG;AACH,kDAHW,OAAO,oBAAoB,EAAE,UAAU,kEAWjD;AAED;;;GAGG;AACH,6CAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,oBAAoB,EAAE,OAAO,27CAS9C;AAED;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,0CAHW,OAAO,oBAAoB,EAAE,UAAU,0DAKjD;AAED;;;GAGG;AACH,sCAHW,OAAO,oBAAoB,EAAE,UAAU,sDAKjD;AAoBD;;;GAGG;AACH,oDAHW,OAAO,oBAAoB,EAAE,OAAO,oEAM9C;AAED;;;GAGG;AACH,6CAHW,OAAO,oBAAoB,EAAE,OAAO,6DAM9C;AAqBD;;;GAGG;AACH,4CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,oDAFW,OAAO,oBAAoB,EAAE,OAAO,2DAS9C;AAED;;;;;GAKG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,wCAI9C;AAED;;;;GAIG;AACH,kDAFW,OAAO,oBAAoB,EAAE,OAAO,0CAM9C;AAED;;GAEG;AACH,wCAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;;GAIG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,OAAO,4DAuB9C;AAED;;;;;GAKG;AACH,0CAHW,OAAO,oBAAoB,EAAE,OAAO,GAClC,GAAG,EAAE,CAsBjB;AAED;;;GAGG;AACH,gDAHW,OAAO,oBAAoB,EAAE,OAAO,UACzB,GAAG,KAAE,MAAM,CAmBhC;AA7LD;;GAEG;AACH,wCAFU,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,CAEb;AAEpD;;GAEG;AACH,0CAFU,OAAO,oBAAoB,EAAE,0BAA0B,EAAE,CAEX;AAExD;;GAEG;AACH,iCAFU,OAAO,oBAAoB,EAAE,iBAAiB,EAAE,CAKxD;AAoBF;;;;GAIG;AACH,gCAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,0BAA0B,CAAC,CAAC,CAKtH;AAEF;;;;GAIG;AACH,8BAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAInG"}
1
+ {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.js"],"names":[],"mappings":"AAKA;;;;;;;;;;GAUG;AACH,6CAJW,OAAO,kBAAkB,EAAE,OAAO,aAClC,OAAO,oBAAoB,EAAE,QAAQ,gGAsC/C;AAED;;;;;;;GAOG;AACH,0CANW,OAAO,oBAAoB,EAAE,UAAU,SACvC,GAAG,0IAoGb;AAED;;;;;GAKG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,mEAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,uDAKjD;AAED;;;GAGG;AACH,kDAHW,OAAO,oBAAoB,EAAE,UAAU,kEAWjD;AAED;;;GAGG;AACH,6CAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,oBAAoB,EAAE,OAAO,27CAS9C;AAED;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,0CAHW,OAAO,oBAAoB,EAAE,UAAU,0DAKjD;AAED;;;GAGG;AACH,sCAHW,OAAO,oBAAoB,EAAE,UAAU,sDAKjD;AAoBD;;;GAGG;AACH,oDAHW,OAAO,oBAAoB,EAAE,OAAO,oEAM9C;AAED;;;GAGG;AACH,6CAHW,OAAO,oBAAoB,EAAE,OAAO,6DAM9C;AAqBD;;;GAGG;AACH,4CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,oDAFW,OAAO,oBAAoB,EAAE,OAAO,2DAS9C;AAED;;;;;GAKG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,wCAI9C;AAED;;;;GAIG;AACH,kDAFW,OAAO,oBAAoB,EAAE,OAAO,0CAM9C;AAED;;GAEG;AACH,wCAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;;GAIG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,OAAO,4DAuB9C;AAED;;;;;GAKG;AACH,0CAHW,OAAO,oBAAoB,EAAE,OAAO,GAClC,GAAG,EAAE,CAsBjB;AAED;;;GAGG;AACH,gDAHW,OAAO,oBAAoB,EAAE,OAAO,UACzB,GAAG,KAAE,MAAM,CAmBhC;AA7LD;;GAEG;AACH,wCAFU,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,CAEb;AAEpD;;GAEG;AACH,0CAFU,OAAO,oBAAoB,EAAE,0BAA0B,EAAE,CAEX;AAExD;;GAEG;AACH,iCAFU,OAAO,oBAAoB,EAAE,iBAAiB,EAAE,CAKxD;AAoBF;;;;GAIG;AACH,gCAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,0BAA0B,CAAC,CAAC,CAKtH;AAEF;;;;GAIG;AACH,8BAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAInG"}
@@ -1,6 +1,7 @@
1
1
  import { isDiscrete } from "vega-scale";
2
2
  import createIndexer from "../utils/indexer.js";
3
3
  import scaleNull from "../utils/scaleNull.js";
4
+ import { isExprRef } from "../marks/mark.js";
4
5
 
5
6
  /**
6
7
  * Creates an object that contains encoders for every channel of a mark
@@ -41,7 +42,7 @@ export default function createEncoders(mark, encoding) {
41
42
 
42
43
  encoders[channel] = createEncoder(
43
44
  encoding[channel],
44
- resolution?.getScale(),
45
+ resolution?.scale,
45
46
  mark.unitView.getAccessor(channel),
46
47
  channel
47
48
  );
@@ -69,11 +70,20 @@ export function createEncoder(channelDef, scale, accessor, channel) {
69
70
  let encoder;
70
71
 
71
72
  if (isValueDef(channelDef)) {
72
- const value = channelDef.value;
73
- encoder = /** @type {Encoder} */ ((datum) => value);
74
- encoder.constant = true;
75
- encoder.constantValue = true;
76
- encoder.accessor = undefined;
73
+ if (isExprRef(channelDef.value)) {
74
+ // TODO: Should get the value expression as the accessor
75
+ encoder = /** @type {Encoder} */ ((datum) => undefined);
76
+ //encoder = /** @type {Encoder} */ (/** @type {any} */ (accessor));
77
+ encoder.constant = true;
78
+ encoder.constantValue = false;
79
+ encoder.accessor = accessor;
80
+ } else {
81
+ const value = channelDef.value;
82
+ encoder = /** @type {Encoder} */ ((datum) => value);
83
+ encoder.constant = true;
84
+ encoder.constantValue = true;
85
+ encoder.accessor = undefined;
86
+ }
77
87
  } else if (accessor) {
78
88
  if (channel == "text") {
79
89
  // TODO: Define somewhere channels that don't use a scale
@@ -139,6 +139,7 @@ export default class GenomeSpy {
139
139
  renderPickingFramebuffer(): void;
140
140
  getSearchableViews(): UnitView[];
141
141
  getNamedScaleResolutions(): Map<string, import("./view/scaleResolution.js").default>;
142
+ #private;
142
143
  }
143
144
  /**
144
145
  * Events that are broadcasted to all views.
@@ -1 +1 @@
1
- {"version":3,"file":"genomeSpy.d.ts","sourceRoot":"","sources":["../../src/genomeSpy.js"],"names":[],"mappings":"AA6CA;IACI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EAyFpD;IAtFG,uBAA0B;IAE1B,6BAA6B;IAC7B,uBADW,CAAC,MAAM,IAAI,CAAC,EAAE,CACM;IAM/B,sCAAsC;IACtC,wCAAgB;IAEhB,iCAA4C;IAC5C,yBAAoC;IAEpC,4CAA4C;IAC5C,oBADW,QAAU,MAAM,KAAE,MAAM,EAAE,CAAC,EAAE,CACZ;IAE5B,mBAAoD;IAEpD,0BAA0B;IAC1B,aADW,WAAW,CACM;IAE5B;;;;;OAKG;IACH,qEAF0B,OAAO,CAE8B;IAE/D,2CAA2C;IAC3C,mBADW,4BAA4B,CACL;IAClC,2CAA2C;IAC3C,iBADW,4BAA4B,CACP;IAEhC,oDAAoD;IACpD,6BAAgC;IAEhC;;;OAGG;IACH,eAFU;QAAE,IAAI,EAAE,OAAO,iBAAiB,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,oBAAoB,EAAE,KAAK,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAEpF;IAE9B,uBAA+C;IAE/C;;;OAGG;IACH,oBAFU,IAAI,MAAM,EAAE,QAAU,aAAa,KAAE,IAAI,CAAC,EAAE,CAAC,CAEpB;IAEnC;;;;;;OAMG;IACH,yCAFkC,GAAG,KAAK,IAAI,GAEd;IAEhC;;;OAGG;IACH,kDAFkC,GAAG,KAAK,IAAI,GAEL;IAEzC,oFAAoF;IACpF,iBADW,OAAO,MAAM,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC,CAK9E;IAED,mBAAmB;IACnB,2CAAyB;IAEzB,0BAAqC;IAErC;;;;OAIG;IACH,8DAA8B;IAGlC;;;OAGG;IACH,2CAFkB,MAAM,KAAK,GAAG,EAAE,QAIjC;IAED;;OAEG;IACH,+BAFW,MAAM,YAShB;IAED;;;;OAIG;IACH,sBAHW,MAAM,QACN,GAAG,EAAE,QAaf;IAED;;;;;OAKG;IACH,gBAHW,kBAAkB,YAClB,GAAG,QAQb;IAED;;;OAGG;IACH,iCAyCC;IAED,0BA0EC;IAtEG,uBAOC;IAyCD,sCAA0D;IAS1D,yCAA6D;IAI7D,iBAA0C;IAW9C;;OAEG;IACH,gBAmBC;IAED,sCA8MC;IAED;;;OAGG;IACH,UAFa,QAAQ,OAAO,CAAC,CA6B5B;IAED,4BA6IC;IAjIe,iCAAoC;IAmIpD;;;OAGG;IACH,kBAHW,MAAM,KACN,MAAM,QAiEhB;IAED;;;;;;;OAOG;IACH,oDAHuB,QAAQ,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAYlF;IAED,sBAyCC;IAED,kBAIC;IAED,iCAOC;IAED,iCASC;IAED,qFAWC;CACJ;;;;iCA51BY,eAAe,GAAG,YAAY,GAAG,QAAQ,GAAG,gBAAgB;4BAhC7C,uBAAuB;4BA0BP,uBAAuB;qBAZ9C,qBAAqB;wBAIlB,yBAAyB;yCARR,yDAAyD;oBAYvD,oBAAoB;wBAMvC,kBAAkB;wBApBlB,qBAAqB;oBAVzB,uBAAuB;qBAQtB,oBAAoB"}
1
+ {"version":3,"file":"genomeSpy.d.ts","sourceRoot":"","sources":["../../src/genomeSpy.js"],"names":[],"mappings":"AA+CA;IACI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EA0FpD;IAvFG,uBAA0B;IAE1B,6BAA6B;IAC7B,uBADW,CAAC,MAAM,IAAI,CAAC,EAAE,CACM;IAM/B,sCAAsC;IACtC,wCAAgB;IAEhB,iCAA4C;IAC5C,yBAAoC;IAEpC,4CAA4C;IAC5C,oBADW,QAAU,MAAM,KAAE,MAAM,EAAE,CAAC,EAAE,CACZ;IAE5B,mBAAoD;IAEpD,0BAA0B;IAC1B,aADW,WAAW,CACM;IAE5B;;;;;OAKG;IACH,qEAF0B,OAAO,CAE8B;IAE/D,2CAA2C;IAC3C,mBADW,4BAA4B,CACL;IAClC,2CAA2C;IAC3C,iBADW,4BAA4B,CACP;IAEhC,oDAAoD;IACpD,6BAAgC;IAEhC;;;OAGG;IACH,eAFU;QAAE,IAAI,EAAE,OAAO,iBAAiB,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,oBAAoB,EAAE,KAAK,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAEpF;IAE9B,uBAA+C;IAE/C;;;OAGG;IACH,oBAFU,IAAI,MAAM,EAAE,QAAU,aAAa,KAAE,IAAI,CAAC,EAAE,CAAC,CAEpB;IAEnC;;;;;;OAMG;IACH,yCAFkC,GAAG,KAAK,IAAI,GAEd;IAEhC;;;OAGG;IACH,kDAFkC,GAAG,KAAK,IAAI,GAEL;IAEzC,oFAAoF;IACpF,iBADW,OAAO,MAAM,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC,CAK9E;IAED,mBAAmB;IACnB,2CAAyB;IAEzB,0BAAqC;IAGrC;;;;OAIG;IACH,8DAA8B;IA4GlC;;;OAGG;IACH,2CAFkB,MAAM,KAAK,GAAG,EAAE,QAIjC;IAED;;OAEG;IACH,+BAFW,MAAM,YAShB;IAED;;;;OAIG;IACH,sBAHW,MAAM,QACN,GAAG,EAAE,QAaf;IAED;;;;;OAKG;IACH,gBAHW,kBAAkB,YAClB,GAAG,QAQb;IAED;;;OAGG;IACH,iCAyCC;IAED,0BA0EC;IAtEG,uBAOC;IAyCD,sCAA0D;IAS1D,yCAA6D;IAI7D,iBAA0C;IAW9C;;OAEG;IACH,gBAmBC;IAED,sCAwMC;IAED;;;OAGG;IACH,UAFa,QAAQ,OAAO,CAAC,CA6B5B;IAED,4BA6IC;IAjIe,iCAAoC;IAmIpD;;;OAGG;IACH,kBAHW,MAAM,KACN,MAAM,QAiEhB;IAED;;;;;;;OAOG;IACH,oDAHuB,QAAQ,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAYlF;IAED,sBAyCC;IAED,kBAIC;IAED,iCAOC;IAED,iCASC;IAED,qFAWC;;CACJ;;;;iCAh8BY,eAAe,GAAG,YAAY,GAAG,QAAQ,GAAG,gBAAgB;4BAlC7C,uBAAuB;4BA0BP,uBAAuB;qBAZ9C,qBAAqB;wBAIlB,yBAAyB;yCARR,yDAAyD;oBAYvD,oBAAoB;wBAMvC,kBAAkB;wBApBlB,qBAAqB;oBAVzB,uBAAuB;qBAQtB,oBAAoB"}
@@ -35,6 +35,8 @@ import { invalidatePrefix } from "./utils/propertyCacher.js";
35
35
  import { VIEW_ROOT_NAME, ViewFactory } from "./view/viewFactory.js";
36
36
  import { reconfigureScales } from "./view/scaleResolution.js";
37
37
  import ParamBroker from "./paramBroker.js";
38
+ import { debounce } from "./utils/debounce.js";
39
+ import { tickStep } from "d3-array";
38
40
 
39
41
  /**
40
42
  * Events that are broadcasted to all views.
@@ -137,6 +139,7 @@ export default class GenomeSpy {
137
139
  this.viewRoot = undefined;
138
140
 
139
141
  this._paramBroker = new ParamBroker();
142
+ this.#initializeParameters();
140
143
 
141
144
  /**
142
145
  * Views that are currently loading data using lazy sources.
@@ -146,6 +149,111 @@ export default class GenomeSpy {
146
149
  this._loadingViews = new Map();
147
150
  }
148
151
 
152
+ #initializeParameters() {
153
+ /** @type {import("lit-html").TemplateResult[]} */
154
+ const inputs = [];
155
+
156
+ for (const param of this.spec.params ?? []) {
157
+ const { name, value, bind } = param;
158
+ const setter = this._paramBroker.allocateSetter(name);
159
+
160
+ if (value != null) {
161
+ setter(value);
162
+ }
163
+
164
+ // TODO: Implement two-way data binding, e.g. when an external agent changes
165
+ // the parameter value, the UI components should be updated.
166
+
167
+ if (bind && "input" in bind) {
168
+ const debouncedSetter = bind.debounce
169
+ ? debounce(setter, bind.debounce, false)
170
+ : setter;
171
+
172
+ if (bind.input == "range") {
173
+ // TODO: Show the value next to the slider
174
+ inputs.push(
175
+ html`<label
176
+ >${bind.name ?? name}
177
+ <input
178
+ type="range"
179
+ min=${bind.min ?? 0}
180
+ max=${bind.max ?? 100}
181
+ step=${bind.step ??
182
+ tickStep(bind.min, bind.max, 100)}
183
+ .value=${value}
184
+ @input=${(/** @type {any} */ e) =>
185
+ debouncedSetter(e.target.valueAsNumber)}
186
+ /></label>`
187
+ );
188
+ } else if (bind.input == "checkbox") {
189
+ inputs.push(
190
+ html`<label
191
+ >${bind.name ?? name}
192
+ <input
193
+ type="checkbox"
194
+ ?checked=${value}
195
+ @input=${(/** @type {any} */ e) =>
196
+ debouncedSetter(e.target.checked)}
197
+ /></label>`
198
+ );
199
+ } else if (bind.input == "radio") {
200
+ inputs.push(
201
+ html`<span class="label">${bind.name ?? name}</span>
202
+ ${bind.options.map(
203
+ (option, i) => html`<label>
204
+ <input
205
+ type="radio"
206
+ name=${name}
207
+ value=${option}
208
+ .checked=${value == option}
209
+ @input=${(/** @type {any} */ e) =>
210
+ debouncedSetter(e.target.value)}
211
+ />${bind.labels?.[i] ?? option}</label
212
+ >`
213
+ )}`
214
+ );
215
+ } else if (bind.input == "select") {
216
+ inputs.push(
217
+ html`<label
218
+ >${bind.name ?? name}
219
+ <select
220
+ @input=${(/** @type {any} */ e) =>
221
+ debouncedSetter(e.target.value)}
222
+ >
223
+ ${bind.options.map(
224
+ (option, i) => html`<option
225
+ value=${option}
226
+ ?selected=${value == option}
227
+ >
228
+ ${bind.labels?.[i] ?? option}
229
+ </option>`
230
+ )}
231
+ </select></label
232
+ >`
233
+ );
234
+ } else {
235
+ // TODO: Support other types: "text", "number", "color".
236
+ throw new Error("Unsupported input type: " + bind.input);
237
+ }
238
+ }
239
+ }
240
+
241
+ if (inputs.length) {
242
+ const inputsDiv = document.createElement("div");
243
+ this.container.appendChild(inputsDiv);
244
+
245
+ // TODO: Move to css
246
+ // @ts-ignore
247
+ inputsDiv.style =
248
+ "position: absolute; bottom: 10px; right: 10px; background: rgba(255, 255, 255, 0.8); padding: 10px; z-index: 1; border: 1px solid lightgray";
249
+
250
+ render(
251
+ html`${inputs.map((input) => html`<div>${input}</div>`)}`,
252
+ inputsDiv
253
+ );
254
+ }
255
+ }
256
+
149
257
  /**
150
258
  *
151
259
  * @param {(name: string) => any[]} provider
@@ -533,12 +641,6 @@ export default class GenomeSpy {
533
641
 
534
642
  await graphicsInitialized;
535
643
 
536
- this.viewRoot.visit((view) => {
537
- for (const resolution of Object.values(view.resolutions.scale)) {
538
- this._glHelper.createRangeTexture(resolution);
539
- }
540
- });
541
-
542
644
  for (const view of unitViews) {
543
645
  view.mark.finalizeGraphicsInitialization();
544
646
  }
@@ -1,21 +1,40 @@
1
1
  /// <reference types="external-typings/internmap.js" />
2
2
  /**
3
+ * Generates GLSL code for a constant value.
3
4
  *
4
5
  * @param {Channel} channel
5
6
  * @param {number | number[] | string | boolean} value
6
7
  */
7
- export function generateValueGlsl(channel: Channel, value: number | number[] | string | boolean): string;
8
+ export function generateConstantValueGlsl(channel: Channel, value: number | number[] | string | boolean): string;
8
9
  /**
10
+ * Generates GLSL code for a dynamic, parameter-driven values. These are mainly
11
+ * used as dynamic mark properties that map to encoding channels.
9
12
  *
10
13
  * @param {Channel} channel
11
- * @param {any} scale TODO: typing
14
+ */
15
+ export function generateDynamicValueGlslAndUniform(channel: Channel): {
16
+ channel: import("../spec/channel.js").Channel;
17
+ uniformName: string;
18
+ uniformGlsl: string;
19
+ scaleGlsl: string;
20
+ adjuster: (x: any) => any;
21
+ };
22
+ /**
23
+ *
24
+ * @param {Channel} channel
25
+ * @param {import("../view/scaleResolution.js").default} scaleResolution TODO: typing
12
26
  * @param {import("../spec/channel.js").ChannelDef} channelDef
13
27
  * @param {Channel[]} [sharedQuantitativeChannels] Channels that share the same quantitative field
14
28
  */
15
- export function generateScaleGlsl(channel: Channel, scale: any, channelDef: import("../spec/channel.js").ChannelDef, sharedQuantitativeChannels?: Channel[]): {
29
+ export function generateScaleGlsl(channel: Channel, scaleResolution: import("../view/scaleResolution.js").default, channelDef: import("../spec/channel.js").ChannelDef, sharedQuantitativeChannels?: Channel[]): {
30
+ attributeName: string;
16
31
  attributeGlsl: string;
32
+ markUniformGlsl: string;
17
33
  glsl: string;
34
+ domainUniformName: string;
18
35
  domainUniform: string;
36
+ rangeName: string;
37
+ rangeUniform: string;
19
38
  };
20
39
  /**
21
40
  * True if scale needs more than 24 bits (float32) of precision.
@@ -63,6 +82,7 @@ export const RANGE_PREFIX: "range_";
63
82
  export const SCALE_FUNCTION_PREFIX: "scale_";
64
83
  export const SCALED_FUNCTION_PREFIX: "getScaled_";
65
84
  export const RANGE_TEXTURE_PREFIX: "uRangeTexture_";
85
+ export function getRangeForGlsl(scale: any, channel: Channel): number[];
66
86
  export type Channel = import("../spec/channel.js").Channel;
67
87
  /**
68
88
  * Turns a number or number array to float or vec[234] string.
@@ -1 +1 @@
1
- {"version":3,"file":"glslScaleGenerator.d.ts","sourceRoot":"","sources":["../../../src/gl/glslScaleGenerator.js"],"names":[],"mappings":";AAmDA;;;;GAIG;AACH,2CAHW,OAAO,SACP,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,OAAO,UAsC9C;AAED;;;;;;GAMG;AAEH,2CANW,OAAO,SACP,GAAG,cACH,OAAO,oBAAoB,EAAE,UAAU,+BACvC,OAAO,EAAE;;;;EA8RnB;AA+FD;;;;GAIG;AACH,2CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,sCAFW,MAAM,EAAE,WAIlB;AAMD;;;GAGG;AACH,sCAHW,MAAM,QACN,MAAM,EAAE,YAYlB;AAED;;;GAGG;AACH,2CAHW,MAAM,QACN,MAAM,EAAE,YAUlB;AAYD;;GAEG;AACH,qDAFW,MAAM,EAAE,YAIlB;AAED;;GAEG;AAEH;;;;;GAKG;AACH,+CAFW,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CAAC,+DA4BtG;AAED;;GAEG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,GAAG,OAAO,oBAAoB,EAAE,OAAO,EAAE,UAIvF;AA3jBD,uCAAwC;AACxC,uCAAwC;AACxC,oCAAqC;AACrC,6CAA8C;AAC9C,kDAAmD;AACnD,oDAAqD;sBAMxC,OAAO,oBAAoB,EAAE,OAAO;;;;8BAiYpC,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE;;;;uBAqIhD,CAAC,MAAM,EAAE,OAAO,CAAC;0BAnhBJ,WAAW"}
1
+ {"version":3,"file":"glslScaleGenerator.d.ts","sourceRoot":"","sources":["../../../src/gl/glslScaleGenerator.js"],"names":[],"mappings":";AAqDA;;;;;GAKG;AACH,mDAHW,OAAO,SACP,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,OAAO,UAoC9C;AAED;;;;;GAKG;AACH,4DAFW,OAAO;;;;;kBAIC,GAAG,KAAK,GAAG;EA0B7B;AAED;;;;;;GAMG;AAEH,2CANW,OAAO,mBACP,OAAO,4BAA4B,EAAE,OAAO,cAC5C,OAAO,oBAAoB,EAAE,UAAU,+BACvC,OAAO,EAAE;;;;;;;;;EAiTnB;AAgHD;;;;GAIG;AACH,2CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,sCAFW,MAAM,EAAE,WAIlB;AAMD;;;GAGG;AACH,sCAHW,MAAM,QACN,MAAM,EAAE,YAYlB;AAED;;;GAGG;AACH,2CAHW,MAAM,QACN,MAAM,EAAE,YAUlB;AAYD;;GAEG;AACH,qDAFW,MAAM,EAAE,YAIlB;AAED;;GAEG;AAEH;;;;;GAKG;AACH,+CAFW,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CAAC,+DA4BtG;AAED;;GAEG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,GAAG,OAAO,oBAAoB,EAAE,OAAO,EAAE,UAIvF;AAloBD,uCAAwC;AACxC,uCAAwC;AACxC,oCAAqC;AACrC,6CAA8C;AAC9C,kDAAmD;AACnD,oDAAqD;AA6oB9C,uCAJI,GAAG,WACH,OAAO,GACL,MAAM,EAAE,CAQF;sBA7oBN,OAAO,oBAAoB,EAAE,OAAO;;;;8BAubpC,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE;;;;uBAsJhD,CAAC,MAAM,EAAE,OAAO,CAAC;0BA5lBJ,WAAW"}