higlass 1.13.4 → 1.13.5

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.
@@ -1,16 +1,16 @@
1
1
  import slugid from 'slugid';
2
2
  import { scaleLinear } from 'd3-scale';
3
- import {
4
- trimTrailingSlash as tts,
5
- dictValues,
6
- minNonZero,
7
- maxNonZero,
8
- DenseDataExtrema1D,
9
- DenseDataExtrema2D,
10
- } from '../utils';
3
+
4
+ // Utils
5
+ import tts from '../utils/trim-trailing-slash';
6
+ import dictValues from '../utils/dict-values';
7
+ import minNonZero from '../utils/min-non-zero';
8
+ import maxNonZero from '../utils/max-non-zero';
9
+ import DenseDataExtrema1D from '../utils/DenseDataExtrema1D';
10
+ import DenseDataExtrema2D from '../utils/DenseDataExtrema2D';
11
11
 
12
12
  // Services
13
- import { tileProxy } from '../services';
13
+ import * as tileProxy from '../services/tile-proxy';
14
14
 
15
15
  /** @typedef {import('../types').DataConfig} DataConfig */
16
16
  /** @typedef {import('../types').TilesetInfo} TilesetInfo */
@@ -18,6 +18,10 @@ import { tileProxy } from '../services';
18
18
  * @template T
19
19
  * @typedef {import('../types').AbstractDataFetcher<T>} AbstractDataFetcher
20
20
  */
21
+ /**
22
+ * @template T
23
+ * @typedef {import('../types').TileSource<T>} TileSource
24
+ */
21
25
 
22
26
  /**
23
27
  * @typedef Tile
@@ -49,13 +53,50 @@ function isTuple(x) {
49
53
  return x.length === 2;
50
54
  }
51
55
 
56
+ /**
57
+ * @param {import("pub-sub-es").PubSub} pubSub
58
+ * @returns {TileSource<Tile>}
59
+ */
60
+ function createDefaultTileSource(pubSub) {
61
+ return {
62
+ fetchTiles(request) {
63
+ const ids = request.tileIds;
64
+ return new Promise((done, _reject) => {
65
+ tileProxy.fetchTilesDebounced({ ...request, ids, done }, pubSub, true);
66
+ });
67
+ },
68
+ fetchTilesetInfo({ server, tilesetUid }) {
69
+ return new Promise((resolve, reject) => {
70
+ tileProxy.trackInfo(server, tilesetUid, resolve, reject, pubSub);
71
+ });
72
+ },
73
+ registerTileset({ server, url, filetype, coordSystem }) {
74
+ const serverUrl = `${tts(server)}/register_url/`;
75
+ const payload = {
76
+ fileurl: url,
77
+ filetype,
78
+ coordSystem,
79
+ };
80
+ return fetch(serverUrl, {
81
+ method: 'POST',
82
+ body: JSON.stringify(payload),
83
+ headers: {
84
+ 'Content-Type': 'application/json; charset=utf-8',
85
+ },
86
+ });
87
+ },
88
+ };
89
+ }
90
+
52
91
  /** @implements {AbstractDataFetcher<Tile | DividedTile>} */
53
92
  export default class DataFetcher {
54
93
  /**
55
94
  * @param {import('../types').DataConfig} dataConfig
56
95
  * @param {import('pub-sub-es').PubSub} pubSub
96
+ * @param {TileSource<Tile>} [tileSource]
57
97
  */
58
- constructor(dataConfig, pubSub) {
98
+ constructor(dataConfig, pubSub, tileSource) {
99
+ this._tileSource = tileSource || createDefaultTileSource(pubSub);
59
100
  /** @type {boolean} */
60
101
  this.tilesetInfoLoading = true;
61
102
 
@@ -95,20 +136,11 @@ export default class DataFetcher {
95
136
  * @param {string=} opts.coordSystem - The coordinate system being served (e.g. 'hg38')
96
137
  */
97
138
  async registerFileUrl({ server, url, filetype, coordSystem }) {
98
- const serverUrl = `${tts(server)}/register_url/`;
99
-
100
- const payload = {
101
- fileurl: url,
139
+ return this._tileSource.registerTileset({
140
+ server,
141
+ url,
102
142
  filetype,
103
143
  coordSystem,
104
- };
105
-
106
- return fetch(serverUrl, {
107
- method: 'POST',
108
- body: JSON.stringify(payload),
109
- headers: {
110
- 'Content-Type': 'application/json; charset=utf-8',
111
- },
112
144
  });
113
145
  }
114
146
 
@@ -160,22 +192,18 @@ export default class DataFetcher {
160
192
  );
161
193
  finished(null);
162
194
  } else {
163
- // pass in the callback
164
- tileProxy.trackInfo(
165
- server,
166
- tilesetUid,
167
- (/** @type {Record<string, TilesetInfo>} */ tilesetInfo) => {
195
+ this._tileSource
196
+ .fetchTilesetInfo({ server, tilesetUid })
197
+ .then((tilesetInfo) => {
168
198
  // tileset infos are indxed by by tilesetUids, we can just resolve
169
199
  // that here before passing it back to the track
170
200
  this.dataConfig.tilesetInfo = tilesetInfo[tilesetUid];
171
201
  finished(tilesetInfo[tilesetUid], tilesetUid);
172
- },
173
- (/** @type {string} */ error) => {
202
+ })
203
+ .catch((error) => {
174
204
  this.tilesetInfoLoading = false;
175
205
  finished({ error });
176
- },
177
- this.pubSub,
178
- );
206
+ });
179
207
  }
180
208
  } else {
181
209
  // this data source has children, so we need to wait to get
@@ -231,35 +259,28 @@ export default class DataFetcher {
231
259
 
232
260
  if (!this.dataConfig.children && this.dataConfig.tilesetUid) {
233
261
  // no children, just return the fetched tiles as is
234
- /** @type {Promise<Record<string, Tile>>} */
235
- const promise = new Promise((resolve) => {
236
- tileProxy.fetchTilesDebounced(
237
- {
238
- id: slugid.nice(),
239
- server: this.dataConfig.server,
240
- done: resolve,
241
- ids: tileIds.map((x) => `${this.dataConfig.tilesetUid}.${x}`),
242
- options: this.dataConfig.options,
243
- },
244
- this.pubSub,
245
- true,
246
- );
262
+ const promise = this._tileSource.fetchTiles({
263
+ id: slugid.nice(),
264
+ server: this.dataConfig.server,
265
+ tileIds: tileIds.map((x) => `${this.dataConfig.tilesetUid}.${x}`),
266
+ options: this.dataConfig.options,
247
267
  });
268
+ return /** @type {Promise<Record<string, Tile>>} */ (promise).then(
269
+ (returnedTiles) => {
270
+ const tilesetUid = dictValues(returnedTiles)[0].tilesetUid;
271
+ /** @type {Record<string, Tile>} */
272
+ const newTiles = {};
248
273
 
249
- return promise.then((returnedTiles) => {
250
- const tilesetUid = dictValues(returnedTiles)[0].tilesetUid;
251
- /** @type {Record<string, Tile>} */
252
- const newTiles = {};
253
-
254
- for (let i = 0; i < tileIds.length; i++) {
255
- const fullTileId = this.fullTileId(tilesetUid, tileIds[i]);
274
+ for (let i = 0; i < tileIds.length; i++) {
275
+ const fullTileId = this.fullTileId(tilesetUid, tileIds[i]);
256
276
 
257
- returnedTiles[fullTileId].tilePositionId = tileIds[i];
258
- newTiles[tileIds[i]] = returnedTiles[fullTileId];
259
- }
260
- receivedTiles(newTiles);
261
- return newTiles;
262
- });
277
+ returnedTiles[fullTileId].tilePositionId = tileIds[i];
278
+ newTiles[tileIds[i]] = returnedTiles[fullTileId];
279
+ }
280
+ receivedTiles(newTiles);
281
+ return newTiles;
282
+ },
283
+ );
263
284
  }
264
285
 
265
286
  // multiple child tracks, need to wait for all of them to
@@ -325,12 +346,12 @@ export default class DataFetcher {
325
346
  /**
326
347
  * Extract a slice from a matrix at a given position.
327
348
  *
328
- * @param {Array<number>} inputData - An array containing a matrix stored row-wise
349
+ * @param {Array<number> | Float32Array} inputData - An array containing a matrix stored row-wise
329
350
  * @param {Array<number>} arrayShape - The shape of the array, should be a
330
351
  * two element array e.g. [256,256].
331
352
  * @param {number} sliceIndex - The index across which to take the slice
332
353
  * @param {number=} axis - The axis along which to take the slice
333
- * @returns {Array<number>} an array corresponding to a slice of this matrix
354
+ * @returns {Array<number> | Float32Array} an array corresponding to a slice of this matrix
334
355
  */
335
356
  extractDataSlice(inputData, arrayShape, sliceIndex, axis) {
336
357
  if (!axis) {
@@ -419,18 +440,12 @@ export default class DataFetcher {
419
440
  }
420
441
 
421
442
  // actually fetch the new tileIds
422
- const promise = new Promise((resolve) => {
423
- tileProxy.fetchTilesDebounced(
424
- {
425
- id: slugid.nice(),
426
- server: this.dataConfig.server,
427
- done: resolve,
428
- ids: newTileIds.map((x) => `${this.dataConfig.tilesetUid}.${x}`),
429
- },
430
- this.pubSub,
431
- true,
432
- );
443
+ const promise = this._tileSource.fetchTiles({
444
+ id: slugid.nice(),
445
+ server: this.dataConfig.server,
446
+ tileIds: newTileIds.map((x) => `${this.dataConfig.tilesetUid}.${x}`),
433
447
  });
448
+
434
449
  return promise.then((returnedTiles) => {
435
450
  // we've received some new tiles, but they're 2D
436
451
  // we need to extract the row corresponding to the data we need
@@ -489,7 +504,9 @@ export default class DataFetcher {
489
504
  }
490
505
 
491
506
  const newTile = {
507
+ // @ts-expect-error - this is ok because float32 array can be spread as number[]
492
508
  min_value: Math.min.apply(null, dataSlice),
509
+ // @ts-expect-error - this is ok because float32 array can be spread as number[]
493
510
  max_value: Math.max.apply(null, dataSlice),
494
511
  denseDataExtrema: new DenseDataExtrema1D(dataSlice),
495
512
  minNonZero: minNonZero(dataSlice),
@@ -0,0 +1,29 @@
1
+ // These are all exports that are used is Gosling.js
2
+
3
+ /**
4
+ * Tracks
5
+ */
6
+ export { default as Track } from './Track';
7
+ export { default as PixiTrack } from './PixiTrack';
8
+ export { default as TiledPixiTrack } from './TiledPixiTrack';
9
+ export { default as SVGTrack } from './SVGTrack';
10
+ export { default as ViewportTrackerHorizontal } from './ViewportTrackerHorizontal';
11
+ export { default as HeatmapTiledPixiTrack } from './HeatmapTiledPixiTrack';
12
+
13
+ /**
14
+ * Data Fetcher
15
+ */
16
+ export { default as DataFetcher } from './data-fetchers/DataFetcher';
17
+ /**
18
+ * Utils
19
+ */
20
+ export { default as tileProxy } from './services/tile-proxy';
21
+ export { default as fakePubSub } from './utils/fake-pub-sub';
22
+ export { default as DenseDataExtrema1D } from './utils/DenseDataExtrema1D';
23
+ export { default as absToChr } from './utils/abs-to-chr';
24
+ export { default as chrToAbs } from './utils/chr-to-abs';
25
+ export { default as colorToHex } from './utils/color-to-hex';
26
+ export { default as chromInfoBisector } from './utils/chrom-info-bisector';
27
+ export { default as pixiTextToSvg } from './utils/pixi-text-to-svg';
28
+ export { default as svgLine } from './utils/svg-line';
29
+ export { default as showMousePosition } from './utils/show-mouse-position';
@@ -114,3 +114,5 @@ export const viewer = (element, viewConfig, options) => {
114
114
  const hg = launch(element, viewConfig, options);
115
115
  return hg.api;
116
116
  };
117
+
118
+ export * as hggos from './gosling-exports';
@@ -0,0 +1,19 @@
1
+ // @ts-nocheck
2
+ import React from 'react';
3
+
4
+ import fakePubSub from '../utils/fake-pub-sub';
5
+
6
+ const { Provider, Consumer } = React.createContext(fakePubSub);
7
+
8
+ // Written without JSX to make it so we don't need JSX-transformation to load this file
9
+ function withPubSub(Component) {
10
+ return React.forwardRef((props, ref) =>
11
+ React.createElement(Consumer, null, (pubSub) =>
12
+ React.createElement(Component, { ref, ...props, pubSub }),
13
+ ),
14
+ );
15
+ }
16
+
17
+ export default withPubSub;
18
+
19
+ export { Provider };
@@ -4,10 +4,11 @@ import slugid from 'slugid';
4
4
 
5
5
  import { workerGetTiles, workerSetPix } from './worker';
6
6
 
7
- import { trimTrailingSlash as tts, timeout as sleep } from '../utils';
7
+ import tts from '../utils/trim-trailing-slash';
8
+ import sleep from '../utils/timeout';
8
9
 
9
10
  // Config
10
- import { TILE_FETCH_DEBOUNCE } from '../configs';
11
+ import { TILE_FETCH_DEBOUNCE } from '../configs/primitives';
11
12
 
12
13
  const MAX_FETCH_TILES = 15;
13
14
 
@@ -1,10 +1,10 @@
1
1
  import { scaleLog, scaleLinear } from 'd3-scale';
2
- import {
3
- DenseDataExtrema1D,
4
- DenseDataExtrema2D,
5
- getAggregationFunction,
6
- selectedItemsToSize,
7
- } from '../utils';
2
+
3
+ // utils
4
+ import DenseDataExtrema1D from '../utils/DenseDataExtrema1D';
5
+ import DenseDataExtrema2D from '../utils/DenseDataExtrema2D';
6
+ import getAggregationFunction from '../utils/get-aggregation-function';
7
+ import selectedItemsToSize from '../utils/selected-items-to-size';
8
8
 
9
9
  /**
10
10
  * This function helps to fill in pixData by calling setPixData()
@@ -140,3 +140,32 @@ export interface AbstractDataFetcher<TileType> {
140
140
  tileIds: string[],
141
141
  ): Promise<Record<string, TileType>>;
142
142
  }
143
+
144
+ // Tileset API
145
+
146
+ type TilesRequest = {
147
+ id: string;
148
+ server?: string;
149
+ tileIds: string[];
150
+ options?: unknown;
151
+ };
152
+
153
+ type TilesetInfoRequest = {
154
+ server: string;
155
+ tilesetUid: string;
156
+ };
157
+
158
+ type RegisterTilesetRequest = {
159
+ server: string;
160
+ url: string;
161
+ filetype: string;
162
+ coordSystem?: string;
163
+ };
164
+
165
+ export type TileSource<T> = {
166
+ fetchTiles: (request: TilesRequest) => Promise<Record<string, T>>;
167
+ fetchTilesetInfo: (
168
+ request: TilesetInfoRequest,
169
+ ) => Promise<Record<string, TilesetInfo>>;
170
+ registerTileset: (request: RegisterTilesetRequest) => Promise<Response>;
171
+ };
@@ -1,4 +1,4 @@
1
- import { NUM_PRECOMP_SUBSETS_PER_1D_TTILE } from '../configs';
1
+ import { NUM_PRECOMP_SUBSETS_PER_1D_TTILE } from '../configs/dense-data-extrema-config';
2
2
 
3
3
  /**
4
4
  * @template {ArrayLike<number>} [T=ArrayLike<number>]
@@ -1,5 +1,6 @@
1
1
  import ndarray from 'ndarray';
2
- import { NUM_PRECOMP_SUBSETS_PER_2D_TTILE } from '../configs';
2
+
3
+ import { NUM_PRECOMP_SUBSETS_PER_2D_TTILE } from '../configs/dense-data-extrema-config';
3
4
 
4
5
  /**
5
6
  * @typedef View2D
@@ -1,7 +1,7 @@
1
1
  import { color } from 'd3-color';
2
2
 
3
3
  // Configs
4
- import { GLOBALS } from '../configs';
4
+ import GLOBALS from '../configs/globals';
5
5
 
6
6
  /**
7
7
  * Convert a regular color value (e.g. 'red', '#FF0000', 'rgb(255,0,0)') to a
@@ -0,0 +1,12 @@
1
+ const fakePubSub = {
2
+ __fake__: true,
3
+ publish: () => {},
4
+ subscribe: () => ({
5
+ event: '',
6
+ handler: () => {},
7
+ }),
8
+ unsubscribe: () => {},
9
+ clear: () => {},
10
+ };
11
+
12
+ export default fakePubSub;
@@ -3,7 +3,7 @@ import { globalPubSub } from 'pub-sub-es';
3
3
  import hexStrToInt from './hex-string-to-int';
4
4
 
5
5
  // Configs
6
- import { GLOBALS } from '../configs';
6
+ import GLOBALS from '../configs/globals';
7
7
 
8
8
  const COLOR = 0xaaaaaa;
9
9
  const ALPHA = 1.0;