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.
- package/README.md +48 -54
- package/app/globals.d.ts +1 -1
- package/app/missing-types.d.ts +4 -1
- package/app/scripts/AddTrackDialog.jsx +3 -3
- package/app/scripts/AddTrackPositionMenu.jsx +2 -2
- package/app/scripts/Annotations1dTrack.js +1 -1
- package/app/scripts/Annotations2dTrack.js +3 -5
- package/app/scripts/Autocomplete.jsx +14 -21
- package/app/scripts/AxisPixi.js +6 -10
- package/app/scripts/BarTrack.js +3 -3
- package/app/scripts/BedLikeTrack.js +12 -13
- package/app/scripts/Button.jsx +1 -1
- package/app/scripts/CNVIntervalTrack.js +1 -1
- package/app/scripts/CenterTrack.jsx +8 -7
- package/app/scripts/Chromosome2DAnnotations.js +1 -1
- package/app/scripts/Chromosome2DLabels.js +1 -1
- package/app/scripts/ChromosomeGrid.js +49 -38
- package/app/scripts/ChromosomeInfo.js +1 -1
- package/app/scripts/CombinedTrack.js +3 -1
- package/app/scripts/ConfigTrackMenu.jsx +1 -1
- package/app/scripts/ConfigViewMenu.jsx +2 -2
- package/app/scripts/ContextMenuContainer.jsx +1 -2
- package/app/scripts/ContextMenuItem.jsx +1 -0
- package/app/scripts/CrossRule.js +1 -1
- package/app/scripts/CustomTrackDialog.jsx +2 -2
- package/app/scripts/Dialog.jsx +2 -2
- package/app/scripts/DragListeningDiv.jsx +1 -1
- package/app/scripts/DraggableDiv.jsx +2 -3
- package/app/scripts/ExportLinkDialog.jsx +1 -1
- package/app/scripts/GalleryTracks.jsx +77 -78
- package/app/scripts/GenomePositionSearchBox.jsx +10 -9
- package/app/scripts/HeatmapOptions.jsx +4 -2
- package/app/scripts/HeatmapTiledPixiTrack.js +23 -32
- package/app/scripts/HiGlassComponent.jsx +75 -98
- package/app/scripts/Horizontal1dHeatmapTrack.js +1 -1
- package/app/scripts/Horizontal2DDomainsTrack.js +1 -1
- package/app/scripts/HorizontalChromosomeLabels.js +28 -22
- package/app/scripts/HorizontalGeneAnnotationsTrack.js +1 -1
- package/app/scripts/HorizontalHeatmapTrack.js +2 -2
- package/app/scripts/HorizontalMultivecTrack.js +6 -7
- package/app/scripts/HorizontalRule.js +1 -2
- package/app/scripts/HorizontalTiled1DPixiTrack.js +4 -4
- package/app/scripts/HorizontalTiledPlot.jsx +9 -9
- package/app/scripts/LeftTrackModifier.js +4 -0
- package/app/scripts/ListWrapper.jsx +1 -2
- package/app/scripts/MapboxTilesTrack.js +1 -2
- package/app/scripts/Modal.jsx +2 -2
- package/app/scripts/MoveableTrack.jsx +10 -12
- package/app/scripts/NestedContextMenu.jsx +2 -1
- package/app/scripts/OSMTileIdsTrack.js +1 -1
- package/app/scripts/OverlayTrack.js +4 -4
- package/app/scripts/PixiTrack.js +27 -13
- package/app/scripts/PlotTypeChooser.jsx +3 -4
- package/app/scripts/SearchField.js +5 -5
- package/app/scripts/SeriesListItems.jsx +3 -4
- package/app/scripts/SeriesListMenu.jsx +6 -11
- package/app/scripts/SeriesListSubmenuMixin.jsx +1 -1
- package/app/scripts/SketchInlinePicker.jsx +2 -2
- package/app/scripts/SortableList.jsx +1 -1
- package/app/scripts/Tiled1DPixiTrack.js +5 -1
- package/app/scripts/TiledPixiTrack.js +232 -99
- package/app/scripts/TiledPlot.jsx +33 -43
- package/app/scripts/TilesetFinder.jsx +12 -4
- package/app/scripts/Track.js +1 -1
- package/app/scripts/TrackArea.jsx +4 -0
- package/app/scripts/TrackControl.jsx +2 -2
- package/app/scripts/TrackRenderer.jsx +30 -31
- package/app/scripts/ValueIntervalTrack.js +1 -1
- package/app/scripts/VerticalRule.js +2 -2
- package/app/scripts/VerticalTiledPlot.jsx +7 -7
- package/app/scripts/ViewConfigEditor.jsx +1 -1
- package/app/scripts/ViewContextMenu.jsx +4 -4
- package/app/scripts/ViewHeader.jsx +6 -7
- package/app/scripts/ViewportTracker2D.js +1 -1
- package/app/scripts/api.js +5 -6
- package/app/scripts/configs/available-track-types.js +1 -1
- package/app/scripts/configs/positions-by-datatype.js +2 -2
- package/app/scripts/configs/themes.js +0 -1
- package/app/scripts/configs/tracks-info-by-type.js +11 -8
- package/app/scripts/configs/tracks-info.js +2 -2
- package/app/scripts/d3-context-menu.js +3 -4
- package/app/scripts/data-fetchers/DataFetcher.js +35 -36
- package/app/scripts/data-fetchers/genbank-fetcher.js +6 -10
- package/app/scripts/data-fetchers/local-tile-fetcher.js +2 -6
- package/app/scripts/hglib.jsx +1 -1
- package/app/scripts/hocs/with-modal.jsx +32 -10
- package/app/scripts/hocs/with-pub-sub.js +12 -3
- package/app/scripts/hocs/with-theme.jsx +21 -14
- package/app/scripts/icons.jsx +3 -2
- package/app/scripts/mixwith.js +2 -2
- package/app/scripts/plugins/get-data-fetcher.js +2 -3
- package/app/scripts/services/chrom-info.js +32 -4
- package/app/scripts/services/element-resize-listener.js +2 -2
- package/app/scripts/services/index.js +0 -1
- package/app/scripts/services/tile-proxy.js +368 -281
- package/app/scripts/services/worker.js +30 -28
- package/app/scripts/test-helpers/test-helpers.jsx +3 -3
- package/app/scripts/types.ts +50 -44
- package/app/scripts/utils/LruCache.js +3 -2
- package/app/scripts/utils/assert.js +19 -0
- package/app/scripts/utils/background-task-scheduler.js +2 -0
- package/app/scripts/utils/color-domain-to-rgba-array.js +13 -3
- package/app/scripts/utils/dict-items.js +1 -0
- package/app/scripts/utils/dict-keys.js +1 -0
- package/app/scripts/utils/dict-values.js +1 -0
- package/app/scripts/utils/expand-combined-tracks.js +11 -7
- package/app/scripts/utils/fill-in-min-widths.js +47 -21
- package/app/scripts/utils/flatten.js +0 -1
- package/app/scripts/utils/get-aggregation-function.js +1 -1
- package/app/scripts/utils/get-default-track-for-datatype.js +36 -10
- package/app/scripts/utils/get-higlass-components.js +27 -3
- package/app/scripts/utils/get-track-position-by-uid.js +8 -1
- package/app/scripts/utils/get-xylofon.js +12 -9
- package/app/scripts/utils/has-parent.js +5 -5
- package/app/scripts/utils/hex-string-to-int.js +1 -1
- package/app/scripts/utils/interval-tree.js +222 -177
- package/app/scripts/utils/load-chrom-infos.js +4 -1
- package/app/scripts/utils/pixi-text-to-svg.js +5 -9
- package/app/scripts/utils/range-query-2d.js +3 -3
- package/app/scripts/utils/reduce.js +12 -5
- package/app/scripts/utils/segments-to-rows.js +14 -11
- package/app/scripts/utils/show-mouse-position.js +16 -0
- package/app/scripts/utils/svg-line.js +7 -8
- package/app/scripts/utils/type-guards.js +16 -7
- package/app/scripts/utils/visit-positioned-tracks.js +7 -5
- package/app/styles/d3-context-menu.css +0 -1
- package/app/styles/prism.css +1 -0
- package/dist/hglib.js +78064 -77770
- package/dist/hglib.min.js +109 -109
- package/dist/higlass.mjs +82736 -82442
- 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}
|
|
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 {
|
|
31
|
-
*
|
|
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
|
|
68
|
-
* @param
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
272
|
+
if (this.tilesetInfo?.chromsizes) {
|
|
178
273
|
this.chromInfo = parseChromsizesRows(this.tilesetInfo.chromsizes);
|
|
179
274
|
}
|
|
180
275
|
|
|
181
|
-
if (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
654
|
+
/** @param {Tile} tile */
|
|
655
|
+
updateTile(tile) {}
|
|
535
656
|
|
|
536
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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));
|