higlass 1.13.5 → 1.13.6

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 (131) hide show
  1. package/README.md +48 -54
  2. package/app/globals.d.ts +1 -1
  3. package/app/missing-types.d.ts +4 -1
  4. package/app/scripts/AddTrackDialog.jsx +3 -3
  5. package/app/scripts/AddTrackPositionMenu.jsx +2 -2
  6. package/app/scripts/Annotations1dTrack.js +1 -1
  7. package/app/scripts/Annotations2dTrack.js +3 -5
  8. package/app/scripts/Autocomplete.jsx +14 -21
  9. package/app/scripts/AxisPixi.js +6 -10
  10. package/app/scripts/BarTrack.js +3 -3
  11. package/app/scripts/BedLikeTrack.js +12 -13
  12. package/app/scripts/Button.jsx +1 -1
  13. package/app/scripts/CNVIntervalTrack.js +1 -1
  14. package/app/scripts/CenterTrack.jsx +8 -7
  15. package/app/scripts/Chromosome2DAnnotations.js +1 -1
  16. package/app/scripts/Chromosome2DLabels.js +1 -1
  17. package/app/scripts/ChromosomeGrid.js +49 -38
  18. package/app/scripts/ChromosomeInfo.js +1 -1
  19. package/app/scripts/CombinedTrack.js +3 -1
  20. package/app/scripts/ConfigTrackMenu.jsx +1 -1
  21. package/app/scripts/ConfigViewMenu.jsx +2 -2
  22. package/app/scripts/ContextMenuContainer.jsx +1 -2
  23. package/app/scripts/ContextMenuItem.jsx +1 -0
  24. package/app/scripts/CrossRule.js +1 -1
  25. package/app/scripts/CustomTrackDialog.jsx +2 -2
  26. package/app/scripts/Dialog.jsx +2 -2
  27. package/app/scripts/DragListeningDiv.jsx +1 -1
  28. package/app/scripts/DraggableDiv.jsx +2 -3
  29. package/app/scripts/ExportLinkDialog.jsx +1 -1
  30. package/app/scripts/GalleryTracks.jsx +77 -78
  31. package/app/scripts/GenomePositionSearchBox.jsx +10 -9
  32. package/app/scripts/HeatmapOptions.jsx +4 -2
  33. package/app/scripts/HeatmapTiledPixiTrack.js +23 -32
  34. package/app/scripts/HiGlassComponent.jsx +75 -98
  35. package/app/scripts/Horizontal1dHeatmapTrack.js +1 -1
  36. package/app/scripts/Horizontal2DDomainsTrack.js +1 -1
  37. package/app/scripts/HorizontalChromosomeLabels.js +28 -22
  38. package/app/scripts/HorizontalGeneAnnotationsTrack.js +1 -1
  39. package/app/scripts/HorizontalHeatmapTrack.js +2 -2
  40. package/app/scripts/HorizontalMultivecTrack.js +6 -7
  41. package/app/scripts/HorizontalRule.js +1 -2
  42. package/app/scripts/HorizontalTiled1DPixiTrack.js +4 -4
  43. package/app/scripts/HorizontalTiledPlot.jsx +9 -9
  44. package/app/scripts/LeftTrackModifier.js +4 -0
  45. package/app/scripts/ListWrapper.jsx +1 -2
  46. package/app/scripts/MapboxTilesTrack.js +1 -2
  47. package/app/scripts/Modal.jsx +2 -2
  48. package/app/scripts/MoveableTrack.jsx +10 -12
  49. package/app/scripts/NestedContextMenu.jsx +2 -1
  50. package/app/scripts/OSMTileIdsTrack.js +1 -1
  51. package/app/scripts/OverlayTrack.js +4 -4
  52. package/app/scripts/PixiTrack.js +27 -13
  53. package/app/scripts/PlotTypeChooser.jsx +3 -4
  54. package/app/scripts/SearchField.js +5 -5
  55. package/app/scripts/SeriesListItems.jsx +3 -4
  56. package/app/scripts/SeriesListMenu.jsx +6 -11
  57. package/app/scripts/SeriesListSubmenuMixin.jsx +1 -1
  58. package/app/scripts/SketchInlinePicker.jsx +2 -2
  59. package/app/scripts/SortableList.jsx +1 -1
  60. package/app/scripts/Tiled1DPixiTrack.js +5 -1
  61. package/app/scripts/TiledPixiTrack.js +232 -99
  62. package/app/scripts/TiledPlot.jsx +33 -43
  63. package/app/scripts/TilesetFinder.jsx +12 -4
  64. package/app/scripts/Track.js +1 -1
  65. package/app/scripts/TrackArea.jsx +4 -0
  66. package/app/scripts/TrackControl.jsx +2 -2
  67. package/app/scripts/TrackRenderer.jsx +30 -31
  68. package/app/scripts/ValueIntervalTrack.js +1 -1
  69. package/app/scripts/VerticalRule.js +2 -2
  70. package/app/scripts/VerticalTiledPlot.jsx +7 -7
  71. package/app/scripts/ViewConfigEditor.jsx +1 -1
  72. package/app/scripts/ViewContextMenu.jsx +4 -4
  73. package/app/scripts/ViewHeader.jsx +6 -7
  74. package/app/scripts/ViewportTracker2D.js +1 -1
  75. package/app/scripts/api.js +5 -6
  76. package/app/scripts/configs/available-track-types.js +1 -1
  77. package/app/scripts/configs/positions-by-datatype.js +2 -2
  78. package/app/scripts/configs/themes.js +0 -1
  79. package/app/scripts/configs/tracks-info-by-type.js +11 -8
  80. package/app/scripts/configs/tracks-info.js +2 -2
  81. package/app/scripts/d3-context-menu.js +3 -4
  82. package/app/scripts/data-fetchers/DataFetcher.js +35 -36
  83. package/app/scripts/data-fetchers/genbank-fetcher.js +6 -10
  84. package/app/scripts/data-fetchers/local-tile-fetcher.js +2 -6
  85. package/app/scripts/hglib.jsx +1 -1
  86. package/app/scripts/hocs/with-modal.jsx +32 -10
  87. package/app/scripts/hocs/with-pub-sub.js +12 -3
  88. package/app/scripts/hocs/with-theme.jsx +21 -14
  89. package/app/scripts/icons.jsx +3 -2
  90. package/app/scripts/mixwith.js +2 -2
  91. package/app/scripts/plugins/get-data-fetcher.js +2 -3
  92. package/app/scripts/services/chrom-info.js +32 -4
  93. package/app/scripts/services/element-resize-listener.js +2 -2
  94. package/app/scripts/services/index.js +0 -1
  95. package/app/scripts/services/tile-proxy.js +368 -281
  96. package/app/scripts/services/worker.js +30 -28
  97. package/app/scripts/test-helpers/test-helpers.jsx +3 -3
  98. package/app/scripts/types.ts +50 -44
  99. package/app/scripts/utils/LruCache.js +3 -2
  100. package/app/scripts/utils/assert.js +19 -0
  101. package/app/scripts/utils/background-task-scheduler.js +2 -0
  102. package/app/scripts/utils/color-domain-to-rgba-array.js +13 -3
  103. package/app/scripts/utils/dict-items.js +1 -0
  104. package/app/scripts/utils/dict-keys.js +1 -0
  105. package/app/scripts/utils/dict-values.js +1 -0
  106. package/app/scripts/utils/expand-combined-tracks.js +11 -7
  107. package/app/scripts/utils/fill-in-min-widths.js +47 -21
  108. package/app/scripts/utils/flatten.js +0 -1
  109. package/app/scripts/utils/get-aggregation-function.js +1 -1
  110. package/app/scripts/utils/get-default-track-for-datatype.js +36 -10
  111. package/app/scripts/utils/get-higlass-components.js +27 -3
  112. package/app/scripts/utils/get-track-position-by-uid.js +8 -1
  113. package/app/scripts/utils/get-xylofon.js +12 -9
  114. package/app/scripts/utils/has-parent.js +5 -5
  115. package/app/scripts/utils/hex-string-to-int.js +1 -1
  116. package/app/scripts/utils/interval-tree.js +222 -177
  117. package/app/scripts/utils/load-chrom-infos.js +4 -1
  118. package/app/scripts/utils/pixi-text-to-svg.js +5 -9
  119. package/app/scripts/utils/range-query-2d.js +3 -3
  120. package/app/scripts/utils/reduce.js +12 -5
  121. package/app/scripts/utils/segments-to-rows.js +14 -11
  122. package/app/scripts/utils/show-mouse-position.js +16 -0
  123. package/app/scripts/utils/svg-line.js +7 -8
  124. package/app/scripts/utils/type-guards.js +16 -7
  125. package/app/scripts/utils/visit-positioned-tracks.js +7 -5
  126. package/app/styles/d3-context-menu.css +0 -1
  127. package/app/styles/prism.css +1 -0
  128. package/dist/hglib.js +78064 -77770
  129. package/dist/hglib.min.js +109 -109
  130. package/dist/higlass.mjs +82736 -82442
  131. package/package.json +13 -18
@@ -1,20 +1,22 @@
1
- // @ts-nocheck
2
- import { scaleLinear, scaleLog, scaleQuantile } from 'd3-scale';
3
1
  import { median, range, ticks } from 'd3-array';
2
+ import { scaleLinear, scaleLog, scaleQuantile } from 'd3-scale';
4
3
  import slugid from 'slugid';
5
4
 
6
- import DataFetcher from './data-fetchers/DataFetcher';
7
5
  import PixiTrack from './PixiTrack';
6
+ import { DataFetcher } from './data-fetchers';
8
7
 
9
- // Utils
10
- import throttleAndDebounce from './utils/throttle-and-debounce';
11
- import parseChromsizesRows from './utils/parse-chromsizes-rows';
12
8
  import backgroundTaskScheduler from './utils/background-task-scheduler';
9
+ // Utils
10
+ import parseChromsizesRows from './utils/parse-chromsizes-rows.js';
11
+ import throttleAndDebounce from './utils/throttle-and-debounce.js';
12
+ import { isResolutionsTilesetInfo, isTilesetInfo } from './utils/type-guards';
13
13
 
14
14
  // Configs
15
15
  import GLOBALS from './configs/globals';
16
16
  import { ZOOM_DEBOUNCE } from './configs/primitives';
17
17
 
18
+ /** @import * as t from './types' */
19
+
18
20
  /**
19
21
  * Get a valueScale for a heatmap.
20
22
  *
@@ -22,13 +24,13 @@ import { ZOOM_DEBOUNCE } from './configs/primitives';
22
24
  *
23
25
  * @param {string} scalingType: The type of the (e.g. 'linear', or 'log')
24
26
  * @param {number} minValue: The minimum data value to which this scale will apply
25
- * @param {number} pseudocount: A value to add to all numbers to prevent taking the log of 0
27
+ * @param {number} pseudocountIn: A value to add to all numbers to prevent taking the log of 0
26
28
  * @param {number} maxValue: The maximum data value to which this scale will apply
27
29
  * @param {string} defaultScaling: The default scaling type to use in case
28
30
  * 'scalingType' is null (e.g. 'linear' or 'log')
29
31
  *
30
- * @returns {array} An array of [string, scale] containin the scale type
31
- * and a scale with an appropriately set domain and range
32
+ * @returns {[string, import('d3-scale').ScaleLogarithmic<number, number> | import('d3-scale').ScaleLinear<number, number>]}
33
+ * An array of [string, scale] containing the scale type and a scale with an appropriately set domain and range
32
34
  */
33
35
  export function getValueScale(
34
36
  scalingType,
@@ -60,22 +62,81 @@ export function getValueScale(
60
62
  return ['linear', scaleLinear().range([254, 0]).domain([minValue, maxValue])];
61
63
  }
62
64
 
65
+ /**
66
+ * @typedef Scale
67
+ * @property {number | null} [minValue]
68
+ * @property {number | null} [maxValue]
69
+ * @property {number | null} [maxRawValue]
70
+ * @property {number | null} [minRawValue]
71
+ */
72
+
73
+ /**
74
+ * An alternative to Tile. Perhaps the worst data type. An array of numbers with some extra properties.
75
+ * @typedef {Array<number> & Pick<Tile, 'mirrored' | 'tilePositionId'>} TilePositionArrayObject
76
+ */
77
+
78
+ /**
79
+ * @typedef Tile
80
+ * @property {string} tileId
81
+ * @property {TileData} tileData
82
+ * @property {string} remoteId
83
+ * @property {unknown} mirrored
84
+ * @property {string} tilePositionId
85
+ * @property {import("pixi.js").Graphics} graphics
86
+ */
87
+
88
+ /**
89
+ * @typedef TileData
90
+ * @property {string} tilesetUid
91
+ * @property {number} zoomLevel
92
+ * @property {Array<number>} tilePos
93
+ * @property {string} error
94
+ * @property {Float32Array} dense
95
+ * @property {number} minNonZero
96
+ * @property {number} maxNonZero
97
+ */
98
+
99
+ /**
100
+ * @typedef TiledPixiTrackContextBase
101
+ * @property {DataFetcher} dataFetcher
102
+ * @property {t.DataConfig} dataConfig
103
+ * @property {function} animate A function to redraw this track. Typically called when an
104
+ * asynchronous event occurs (i.e. tiles loaded)
105
+ * @property {() => void} onValueScaleChanged The range of values has changed so we need to inform
106
+ * the higher ups that the value scale has changed. Only occurs on tracks with ``dense`` data.
107
+ * @property {function} handleTilesetInfoReceived A callback to do something once once the tileset
108
+ * info is received. Usually it registers some information about the tileset with its definition
109
+ */
110
+ /**
111
+ * @typedef {import('./PixiTrack').ExtendedPixiContext<TiledPixiTrackContextBase>} TiledPixiTrackContext
112
+ */
113
+
114
+ /**
115
+ * @typedef TiledPixiTrackOptions
116
+ * @property {string} labelPosition - If the label is to be drawn, where should it be drawn?
117
+ * @property {string} labelText - What should be drawn in the label.
118
+ * @property {number} maxZoom
119
+ * @property {string} name
120
+ */
121
+
122
+ /**
123
+ * @template T
124
+ * @typedef {T & TiledPixiTrackOptions} ExtendedTiledPixiTrackOptions
125
+ */
126
+
127
+ /**
128
+ * The TiledPixiTrack requires an options parameter, which should be an object containing properties specified in
129
+ * TiledPixiTrackOptions. It is capable of accepting any property defined in any of its superclasses.
130
+ * @template {ExtendedTiledPixiTrackOptions<{[key: string]: any}>} Options
131
+ * @extends {PixiTrack<Options>}
132
+ * */
63
133
  class TiledPixiTrack extends PixiTrack {
64
134
  /**
65
- * A track that must pull remote tiles
66
135
  *
67
- * @param (PIXI.scene) scene A PIXI.js scene to draw everything to.
68
- * @param (Object) dataConfig: A data source. Usually a
69
- * ``{{server: 'x/api/v1/', tilesetUuid: 'y'}}`` Object.
70
- * @param {Object} handleTilesetInfoReceived: A callback to do something once once the tileset
71
- * info is received. Usually it registers some information about the tileset with its
72
- * definition
73
- * @param {Object} options The track's options
74
- * @param {function} animate A function to redraw this track. Typically called when an
75
- * asynchronous event occurs (i.e. tiles loaded)
76
- * @param {function} onValueScaleChanged The range of values has changed so we need to inform
77
- * the higher ups that the value scale has changed. Only occurs on tracks with ``dense`` data.
136
+ * @param {TiledPixiTrackContext} context
137
+ * @param {Options} options
78
138
  */
139
+
79
140
  constructor(context, options) {
80
141
  super(context, options);
81
142
  const {
@@ -90,10 +151,13 @@ class TiledPixiTrack extends PixiTrack {
90
151
  // rerendering all rendering in the same version will have the same
91
152
  // scaling so tiles rendered in the same version will have the same
92
153
  // output. Mostly useful for heatmap tiles.
154
+ /** @type {number} */
93
155
  this.renderVersion = 1;
94
156
 
95
157
  // the tiles which should be visible (although they're not necessarily fetched)
96
- this.visibleTiles = new Set();
158
+ /** @type {Array<Pick<Tile, 'tileId' |'remoteId' | 'mirrored'>>} */
159
+ this.visibleTiles = [];
160
+ /** @type {Set<string>} */
97
161
  this.visibleTileIds = new Set();
98
162
 
99
163
  // keep track of tiles that are currently being rendered
@@ -101,14 +165,18 @@ class TiledPixiTrack extends PixiTrack {
101
165
 
102
166
  // the tiles we already have requests out for
103
167
  this.fetching = new Set();
168
+ /** @type {Scale} */
104
169
  this.scale = {};
105
170
 
106
171
  // tiles we have fetched and ready to be rendered
172
+ /** @type {{[id: string]: Tile}} */
107
173
  this.fetchedTiles = {};
108
174
 
109
175
  // the graphics that have already been drawn for this track
176
+ /** @type {Object.<string, import('pixi.js').DisplayObject>} */
110
177
  this.tileGraphics = {};
111
178
 
179
+ /** @type {number} */
112
180
  this.maxZoom = 0;
113
181
  this.medianVisibleValue = null;
114
182
 
@@ -123,8 +191,11 @@ class TiledPixiTrack extends PixiTrack {
123
191
  this.valueScaleMax = null;
124
192
  this.fixedValueScaleMax = null;
125
193
 
194
+ /** @type {Object.<string, Array<Function>>} */
126
195
  this.listeners = {};
127
196
 
197
+ /** @type {import('pub-sub-es').PubSub & { __fake__?: boolean }} */
198
+ // @ts-expect-error This is always defined in Track.js
128
199
  this.pubSub = pubSub;
129
200
  this.animate = animate;
130
201
  this.onValueScaleChanged = onValueScaleChanged;
@@ -140,6 +211,8 @@ class TiledPixiTrack extends PixiTrack {
140
211
  }
141
212
 
142
213
  // To indicate that this track is requiring a tileset info
214
+ /** @type {t.TilesetInfo} */
215
+ // @ts-expect-error This has to be initialized to null
143
216
  this.tilesetInfo = null;
144
217
  this.uuid = slugid.nice();
145
218
 
@@ -163,7 +236,29 @@ class TiledPixiTrack extends PixiTrack {
163
236
  this.dataFetcher.tilesetInfo((tilesetInfo, tilesetUid) => {
164
237
  if (!tilesetInfo) return;
165
238
 
166
- this.tilesetInfo = tilesetInfo;
239
+ if (isTilesetInfo(tilesetInfo)) {
240
+ this.tilesetInfo = tilesetInfo;
241
+
242
+ if (this.tilesetInfo.chromsizes) {
243
+ // We got chromosome info from the tileset info so let's parse it
244
+ // into an object we can use
245
+ this.chromInfo = parseChromsizesRows(this.tilesetInfo.chromsizes);
246
+ }
247
+ } else {
248
+ // no tileset info for this track
249
+ console.warn(
250
+ 'Error retrieving tilesetInfo:',
251
+ dataConfig,
252
+ tilesetInfo.error,
253
+ );
254
+
255
+ this.setError(tilesetInfo.error);
256
+ // Fritz: Not sure why it's reset
257
+ // this.trackNotFoundText = '';
258
+ this.tilesetInfo = undefined;
259
+ return;
260
+ }
261
+
167
262
  // If the dataConfig contained a fileUrl, then
168
263
  // we need to update the tilesetUid based
169
264
  // on the registration of the fileUrl.
@@ -174,33 +269,17 @@ class TiledPixiTrack extends PixiTrack {
174
269
  this.tilesetUid = this.dataFetcher.dataConfig.tilesetUid;
175
270
  this.server = this.dataFetcher.dataConfig.server || 'unknown';
176
271
 
177
- if (this.tilesetInfo && this.tilesetInfo.chromsizes) {
272
+ if (this.tilesetInfo?.chromsizes) {
178
273
  this.chromInfo = parseChromsizesRows(this.tilesetInfo.chromsizes);
179
274
  }
180
275
 
181
- if ('error' in this.tilesetInfo) {
182
- // no tileset info for this track
183
- console.warn(
184
- 'Error retrieving tilesetInfo:',
185
- dataConfig,
186
- this.tilesetInfo.error,
187
- );
188
-
189
- // Fritz: Not sure why it's reset
190
- // this.trackNotFoundText = '';
191
- this.tilesetInfo = null;
192
-
193
- this.setError(this.tilesetInfo.error);
194
- return;
195
- }
196
-
197
- if (this.tilesetInfo.resolutions) {
276
+ if (isResolutionsTilesetInfo(this.tilesetInfo)) {
198
277
  this.maxZoom = this.tilesetInfo.resolutions.length;
199
278
  } else {
200
279
  this.maxZoom = +this.tilesetInfo.max_zoom;
201
280
  }
202
281
 
203
- if (this.options && this.options.maxZoom) {
282
+ if (this.options?.maxZoom) {
204
283
  if (this.options.maxZoom >= 0) {
205
284
  this.maxZoom = Math.min(this.options.maxZoom, this.maxZoom);
206
285
  } else {
@@ -210,8 +289,13 @@ class TiledPixiTrack extends PixiTrack {
210
289
 
211
290
  this.refreshTiles();
212
291
 
292
+ // Let this track know that tileset info was received
293
+ this.tilesetInfoReceived();
294
+
295
+ // Let external listeners know that tileset info was received
213
296
  if (handleTilesetInfoReceived) handleTilesetInfoReceived(tilesetInfo);
214
297
 
298
+ // @ts-expect-error This should never happen since options is set in Track
215
299
  if (!this.options) this.options = {};
216
300
 
217
301
  this.options.name = this.options.name || tilesetInfo.name;
@@ -224,11 +308,20 @@ class TiledPixiTrack extends PixiTrack {
224
308
  });
225
309
  }
226
310
 
311
+ /** @param {string} error */
312
+ setError(error) {
313
+ this.errorTextText = error;
314
+ this.draw();
315
+ this.animate();
316
+ }
317
+
318
+ /** @param {number | string} value */
227
319
  setFixedValueScaleMin(value) {
228
320
  if (!Number.isNaN(+value)) this.fixedValueScaleMin = +value;
229
321
  else this.fixedValueScaleMin = null;
230
322
  }
231
323
 
324
+ /** @param {number | string} value */
232
325
  setFixedValueScaleMax(value) {
233
326
  if (!Number.isNaN(+value)) this.fixedValueScaleMax = +value;
234
327
  else this.fixedValueScaleMax = null;
@@ -275,6 +368,11 @@ class TiledPixiTrack extends PixiTrack {
275
368
 
276
369
  this.listeners[event].push(callback);
277
370
  }
371
+ /**
372
+ * @param {string} event The event to listen for
373
+ * @param {function} callback The callback to call when the event occurs. The
374
+ * parameters for the event depend on the event called.
375
+ */
278
376
 
279
377
  off(event, callback) {
280
378
  const id = this.listeners[event].indexOf(callback);
@@ -283,6 +381,7 @@ class TiledPixiTrack extends PixiTrack {
283
381
  this.listeners[event].splice(id, 1);
284
382
  }
285
383
 
384
+ /** @param {Options} options */
286
385
  rerender(options) {
287
386
  super.rerender(options);
288
387
 
@@ -294,13 +393,13 @@ class TiledPixiTrack extends PixiTrack {
294
393
 
295
394
  this.checkValueScaleLimits();
296
395
 
297
- if (this.tilesetInfo.resolutions) {
396
+ if (isResolutionsTilesetInfo(this.tilesetInfo)) {
298
397
  this.maxZoom = this.tilesetInfo.resolutions.length;
299
398
  } else {
300
399
  this.maxZoom = +this.tilesetInfo.max_zoom;
301
400
  }
302
401
 
303
- if (this.options && this.options.maxZoom) {
402
+ if (this.options?.maxZoom) {
304
403
  if (this.options.maxZoom >= 0) {
305
404
  this.maxZoom = Math.min(this.options.maxZoom, this.maxZoom);
306
405
  } else {
@@ -309,6 +408,13 @@ class TiledPixiTrack extends PixiTrack {
309
408
  }
310
409
  }
311
410
 
411
+ /** Called when tileset info is received. The actual tileset info
412
+ * can be found in this.tilesetInfo.
413
+ *
414
+ * Child tracks can implement this method.
415
+ */
416
+ tilesetInfoReceived() {}
417
+
312
418
  /**
313
419
  * Return the set of ids of all tiles which are both visible and fetched.
314
420
  */
@@ -325,12 +431,13 @@ class TiledPixiTrack extends PixiTrack {
325
431
  /**
326
432
  * Set which tiles are visible right now.
327
433
  *
328
- * @param tiles: A set of tiles which will be considered the currently visible
329
- * tile positions.
434
+ * @param {Array<TilePositionArrayObject>} tilePositions
330
435
  */
331
436
  setVisibleTiles(tilePositions) {
332
437
  this.visibleTiles = tilePositions.map((x) => ({
438
+ // @ts-expect-error Classes which extend TiledPixiTrack have this
333
439
  tileId: this.tileToLocalId(x),
440
+ // @ts-expect-error Classes which extend TiledPixiTrack have this
334
441
  remoteId: this.tileToRemoteId(x),
335
442
  mirrored: x.mirrored,
336
443
  }));
@@ -339,6 +446,7 @@ class TiledPixiTrack extends PixiTrack {
339
446
  }
340
447
 
341
448
  removeOldTiles() {
449
+ // @ts-expect-error Classes which extend TiledPixiTrack have this
342
450
  this.calculateVisibleTiles();
343
451
 
344
452
  // tiles that are fetched
@@ -357,7 +465,7 @@ class TiledPixiTrack extends PixiTrack {
357
465
  if (!this.tilesetInfo) {
358
466
  return;
359
467
  }
360
-
468
+ // @ts-expect-error Classes which extend TiledPixiTrack have this
361
469
  this.calculateVisibleTiles();
362
470
 
363
471
  // tiles that are fetched
@@ -377,6 +485,7 @@ class TiledPixiTrack extends PixiTrack {
377
485
  this.fetchNewTiles(toFetch);
378
486
  }
379
487
 
488
+ /** @param {Tile} tile */
380
489
  parentInFetched(tile) {
381
490
  const uid = tile.tileData.tilesetUid;
382
491
  let zl = tile.tileData.zoomLevel;
@@ -395,6 +504,7 @@ class TiledPixiTrack extends PixiTrack {
395
504
  return false;
396
505
  }
397
506
 
507
+ /** @param {Tile} tile */
398
508
  parentTileId(tile) {
399
509
  const parentZoomLevel = tile.tileData.zoomLevel - 1;
400
510
  const parentPos = tile.tileData.tilePos.map((x) => Math.floor(x / 2));
@@ -406,7 +516,7 @@ class TiledPixiTrack extends PixiTrack {
406
516
  /**
407
517
  * Remove obsolete tiles
408
518
  *
409
- * @param toRemoveIds: An array of tile ids to remove from the list of fetched tiles.
519
+ * @param {Array<string>} toRemoveIds: An array of tile ids to remove from the list of fetched tiles.
410
520
  */
411
521
  removeTiles(toRemoveIds) {
412
522
  // if there's nothing to remove, don't bother doing anything
@@ -434,10 +544,15 @@ class TiledPixiTrack extends PixiTrack {
434
544
  this.draw();
435
545
  }
436
546
 
547
+ /**
548
+ * @param {t.Scale} newXScale
549
+ * @param {t.Scale} newYScale
550
+ */
437
551
  zoomed(newXScale, newYScale, k = 1, tx = 0, ty = 0) {
438
552
  this.xScale(newXScale);
439
553
  this.yScale(newYScale);
440
554
 
555
+ // @ts-expect-error Not sure why this is called without an argument
441
556
  this.refreshTilesDebounced();
442
557
 
443
558
  this.pMobile.position.x = tx;
@@ -447,12 +562,14 @@ class TiledPixiTrack extends PixiTrack {
447
562
  this.pMobile.scale.y = 1;
448
563
  }
449
564
 
565
+ /** @param {[number, number]} newPosition */
450
566
  setPosition(newPosition) {
451
567
  super.setPosition(newPosition);
452
568
 
453
569
  // this.draw();
454
570
  }
455
571
 
572
+ /** @param {[number, number]} newDimensions */
456
573
  setDimensions(newDimensions) {
457
574
  super.setDimensions(newDimensions);
458
575
 
@@ -485,6 +602,7 @@ class TiledPixiTrack extends PixiTrack {
485
602
  */
486
603
  allTilesLoaded() {}
487
604
 
605
+ /** @param {number} _ */
488
606
  minValue(_) {
489
607
  if (_) {
490
608
  this.scale.minValue = _;
@@ -495,6 +613,7 @@ class TiledPixiTrack extends PixiTrack {
495
613
  : this.scale.minValue;
496
614
  }
497
615
 
616
+ /** @param {number} _ */
498
617
  maxValue(_) {
499
618
  if (_) {
500
619
  this.scale.maxValue = _;
@@ -517,7 +636,8 @@ class TiledPixiTrack extends PixiTrack {
517
636
  return this.scale.maxRawValue;
518
637
  }
519
638
 
520
- initTile(/* tile */) {
639
+ /** @param {Tile} tile */
640
+ initTile(tile) {
521
641
  // create the tile
522
642
  // should be overwritten by child classes
523
643
  this.scale.minRawValue = this.continuousScaling
@@ -531,9 +651,11 @@ class TiledPixiTrack extends PixiTrack {
531
651
  this.scale.maxValue = this.scale.maxRawValue;
532
652
  }
533
653
 
534
- updateTile(/* tile */) {}
654
+ /** @param {Tile} tile */
655
+ updateTile(tile) {}
535
656
 
536
- destroyTile(/* tile */) {
657
+ /** @param {Tile} tile */
658
+ destroyTile(tile) {
537
659
  // remove all data structures needed to draw this tile
538
660
  }
539
661
 
@@ -596,6 +718,20 @@ class TiledPixiTrack extends PixiTrack {
596
718
  }
597
719
  }
598
720
 
721
+ /**
722
+ * @typedef TiledAreaTile
723
+ * @property {string} tileId
724
+ * @property {string} type
725
+ * @property {unknown} data
726
+ */
727
+
728
+ /**
729
+ *
730
+ * @param {TiledAreaTile} tile A tile returned by a TiledArea.
731
+ * @param {function} dataLoader A function for extracting drawable data from a tile. This
732
+ * usually means differentiating the between dense and sparse tiles and putting the data into an array.
733
+ * @returns
734
+ */
599
735
  loadTileData(tile, dataLoader) {
600
736
  /**
601
737
  * Extract drawable data from a tile loaded by a generic tile loader
@@ -607,21 +743,21 @@ class TiledPixiTrack extends PixiTrack {
607
743
  */
608
744
 
609
745
  // see if the data is already cached
746
+ // @ts-expect-error this.lruCache exists in classes that extend this one
610
747
  let loadedTileData = this.lruCache.get(tile.tileId);
611
748
 
612
749
  // if not, load it and put it in the cache
613
750
  if (!loadedTileData) {
614
751
  loadedTileData = dataLoader(tile.data, tile.type);
752
+ // @ts-expect-error this.lruCache exists in classes that extend this one
615
753
  this.lruCache.put(tile.tileId, loadedTileData);
616
754
  }
617
755
 
618
756
  return loadedTileData;
619
757
  }
620
758
 
759
+ /** @param {Pick<Tile,'remoteId'>[]} toFetch */
621
760
  fetchNewTiles(toFetch) {
622
- this._checkForErrors();
623
- this.draw();
624
-
625
761
  if (toFetch.length > 0) {
626
762
  const toFetchList = [...new Set(toFetch.map((x) => x.remoteId))];
627
763
 
@@ -636,6 +772,7 @@ class TiledPixiTrack extends PixiTrack {
636
772
  * We've gotten a bunch of tiles from the server in
637
773
  * response to a request from fetchTiles.
638
774
  */
775
+ /** @param {Object<string, import('./data-fetchers/DataFetcher').DividedTile | Tile | TilePositionArrayObject>} loadedTiles */
639
776
  receivedTiles(loadedTiles) {
640
777
  for (let i = 0; i < this.visibleTiles.length; i++) {
641
778
  const { tileId } = this.visibleTiles[i];
@@ -645,6 +782,7 @@ class TiledPixiTrack extends PixiTrack {
645
782
  if (this.visibleTiles[i].remoteId in loadedTiles) {
646
783
  if (!(tileId in this.fetchedTiles)) {
647
784
  // this tile may have graphics associated with it
785
+ // @ts-expect-error more properties will be added to this.fetchedTiles[tileId] later (such as by synchronizeTilesAndGraphics())
648
786
  this.fetchedTiles[tileId] = this.visibleTiles[i];
649
787
  }
650
788
 
@@ -654,14 +792,17 @@ class TiledPixiTrack extends PixiTrack {
654
792
  // object but an object array...
655
793
  if (Array.isArray(loadedTiles[this.visibleTiles[i].remoteId])) {
656
794
  const tileData = loadedTiles[this.visibleTiles[i].remoteId];
795
+ // @ts-expect-error this.fetchedTiles[tileId].tileData will get more defined in the next lines
657
796
  this.fetchedTiles[tileId].tileData = [...tileData];
658
797
  // Fritz: this is sooo hacky... we should really not use object arrays
659
798
  Object.keys(tileData)
660
799
  .filter((key) => Number.isNaN(+key))
661
800
  .forEach((key) => {
801
+ // @ts-expect-error Since tileData is an array, the properties have to be copied over manually
662
802
  this.fetchedTiles[tileId].tileData[key] = tileData[key];
663
803
  });
664
804
  } else {
805
+ // @ts-expect-error The object doesn't at this point have all of the properties that it will have later
665
806
  this.fetchedTiles[tileId].tileData = {
666
807
  ...loadedTiles[this.visibleTiles[i].remoteId],
667
808
  };
@@ -700,12 +841,15 @@ class TiledPixiTrack extends PixiTrack {
700
841
 
701
842
  // Let HiGlass know we need to re-render
702
843
  // check if the value scale has changed
844
+ // @ts-expect-error This is defined by classes which extend this one
703
845
  if (this.valueScale) {
704
846
  if (
705
847
  !this.prevValueScale ||
848
+ // @ts-expect-error This is defined by classes which extend this one
706
849
  JSON.stringify(this.valueScale.domain()) !==
707
850
  JSON.stringify(this.prevValueScale.domain())
708
851
  ) {
852
+ // @ts-expect-error This is defined by classes which extend this one
709
853
  this.prevValueScale = this.valueScale.copy();
710
854
 
711
855
  if (this.onValueScaleChanged) {
@@ -726,29 +870,6 @@ class TiledPixiTrack extends PixiTrack {
726
870
  }
727
871
  }
728
872
 
729
- _checkForErrors() {
730
- const errors = Object.values(this.fetchedTiles)
731
- .map(
732
- (x) =>
733
- x.tileData && x.tileData.error && `${x.tileId}: ${x.tileData.error}`,
734
- )
735
- .filter((x) => x);
736
-
737
- if (errors.length) {
738
- this.errorTexts.TiledPixiTrack = errors.join('\n');
739
- } else {
740
- this.errorTexts.TiledPixiTrack = '';
741
- }
742
-
743
- if (this.tilesetInfoError) {
744
- this.errorTexts.TiledPixiTrack = this.tilesetInfoError;
745
-
746
- errors.push(this.tilesetInfoError);
747
- }
748
-
749
- return errors;
750
- }
751
-
752
873
  draw() {
753
874
  if (this.delayDrawing) return;
754
875
 
@@ -776,8 +897,15 @@ class TiledPixiTrack extends PixiTrack {
776
897
  uuid: this.uuid,
777
898
  });
778
899
  }
900
+ const errors = Object.values(this.fetchedTiles)
901
+ .map((x) => x.tileData?.error && `${x.tileId}: ${x.tileData.error}`)
902
+ .filter((x) => x);
779
903
 
780
- this._checkForErrors();
904
+ if (errors.length) {
905
+ this.errorTextText = errors.join('\n');
906
+ } else {
907
+ this.errorTextText = '';
908
+ }
781
909
 
782
910
  super.draw();
783
911
 
@@ -793,8 +921,9 @@ class TiledPixiTrack extends PixiTrack {
793
921
 
794
922
  /**
795
923
  * Draw a tile on some graphics
924
+ * @param {Tile} tile
796
925
  */
797
- drawTile(/* tileData, graphics */) {}
926
+ drawTile(tile) {}
798
927
 
799
928
  calculateMedianVisibleValue() {
800
929
  if (this.areAllVisibleTilesLoaded()) {
@@ -807,7 +936,11 @@ class TiledPixiTrack extends PixiTrack {
807
936
  visibleAndFetchedIds = Object.keys(this.fetchedTiles);
808
937
  }
809
938
 
810
- const values = []
939
+ // Get all of the dense values in the currently visible tiles
940
+ /** @type {number[]} */
941
+ let values = [];
942
+
943
+ values = values
811
944
  .concat(
812
945
  ...visibleAndFetchedIds
813
946
  .filter((x) => this.fetchedTiles[x].tileData.dense)
@@ -820,7 +953,10 @@ class TiledPixiTrack extends PixiTrack {
820
953
  }
821
954
 
822
955
  allVisibleValues() {
823
- return [].concat(
956
+ /** @type {number[]} */
957
+ const values = [];
958
+
959
+ return values.concat(
824
960
  ...this.visibleAndFetchedIds().map((x) =>
825
961
  Array.from(this.fetchedTiles[x].tileData.dense),
826
962
  ),
@@ -841,6 +977,7 @@ class TiledPixiTrack extends PixiTrack {
841
977
  visibleAndFetchedIds = Object.keys(this.fetchedTiles);
842
978
  }
843
979
 
980
+ /** @type {number | null} */
844
981
  let min = Math.min(
845
982
  ...visibleAndFetchedIds.map(
846
983
  (x) => this.fetchedTiles[x].tileData.minNonZero,
@@ -870,7 +1007,7 @@ class TiledPixiTrack extends PixiTrack {
870
1007
  if (visibleAndFetchedIds.length === 0) {
871
1008
  visibleAndFetchedIds = Object.keys(this.fetchedTiles);
872
1009
  }
873
-
1010
+ /** @type {number | null} */
874
1011
  let max = Math.max(
875
1012
  ...visibleAndFetchedIds.map(
876
1013
  (x) => this.fetchedTiles[x].tileData.maxNonZero,
@@ -887,25 +1024,19 @@ class TiledPixiTrack extends PixiTrack {
887
1024
  return this.valueScaleMax !== null ? this.valueScaleMax : max;
888
1025
  }
889
1026
 
1027
+ /**
1028
+ * Create a value scale that will be used to position values
1029
+ * along the y axis.
1030
+ * @param {number} minValue The minimum value of the data
1031
+ * @param {number} medianValue The median value of the data. Potentially used for adding a pseudocount
1032
+ * @param {number} maxValue The maximum value of the data
1033
+ * @param {number} inMargin A number of pixels to be left free on the top and bottom
1034
+ * of the track. For example if the glyphs have a certain
1035
+ * width and we want all of them to fit into the space
1036
+ * @returns
1037
+ */
890
1038
  makeValueScale(minValue, medianValue, maxValue, inMargin) {
891
1039
  /*
892
- * Create a value scale that will be used to position values
893
- * along the y axis.
894
- *
895
- * Parameters
896
- * ----------
897
- * minValue: number
898
- * The minimum value of the data
899
- * medianValue: number
900
- * The median value of the data. Potentially used for adding
901
- * a pseudocount
902
- * maxValue: number
903
- * The maximum value of the data
904
- * margin: number
905
- * A number of pixels to be left free on the top and bottom
906
- * of the track. For example if the glyphs have a certain
907
- * width and we want all of them to fit into the space.
908
- *
909
1040
  * Returns
910
1041
  * -------
911
1042
  * valueScale: d3.scale
@@ -947,6 +1078,7 @@ class TiledPixiTrack extends PixiTrack {
947
1078
  } else if (this.options.valueScaling === 'quantile') {
948
1079
  const start = this.dimensions[1] - margin;
949
1080
  const end = margin;
1081
+ /** @type {import('d3-scale').ScaleQuantile<number, never> & { ticks?: (count: number) => number[] }} */
950
1082
  const quantScale = scaleQuantile()
951
1083
  .domain(this.allVisibleValues())
952
1084
  .range(range(start, end, (end - start) / 256));
@@ -957,6 +1089,7 @@ class TiledPixiTrack extends PixiTrack {
957
1089
  const start = this.dimensions[1] - margin;
958
1090
  const end = margin;
959
1091
  const s = new Set(this.allVisibleValues());
1092
+ /** @type {import('d3-scale').ScaleQuantile<number, never> & { ticks?: (count: number) => number[] }} */
960
1093
  const quantScale = scaleQuantile()
961
1094
  .domain([...s])
962
1095
  .range(range(start, end, (end - start) / 256));