@genome-spy/core 0.71.0 → 0.73.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.
- package/LICENSE +1 -1
- package/dist/bundle/index.es.js +6842 -5365
- package/dist/bundle/index.js +159 -140
- package/dist/bundle/parquetRead-BnAGCa4_.js +1663 -0
- package/dist/schema.json +281 -17
- package/dist/src/data/formats/bed.d.ts +8 -0
- package/dist/src/data/formats/bed.d.ts.map +1 -0
- package/dist/src/data/formats/bed.js +53 -0
- package/dist/src/data/formats/bedpe.d.ts +8 -0
- package/dist/src/data/formats/bedpe.d.ts.map +1 -0
- package/dist/src/data/formats/bedpe.js +160 -0
- package/dist/src/data/formats/parquet.d.ts +12 -0
- package/dist/src/data/formats/parquet.d.ts.map +1 -0
- package/dist/src/data/formats/parquet.js +29 -0
- package/dist/src/data/formats/parquetRead.d.ts +18 -0
- package/dist/src/data/formats/parquetRead.d.ts.map +1 -0
- package/dist/src/data/formats/parquetRead.js +326 -0
- package/dist/src/data/sources/dataUtils.d.ts +16 -0
- package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
- package/dist/src/data/sources/dataUtils.js +53 -3
- package/dist/src/data/sources/urlSource.d.ts +4 -0
- package/dist/src/data/sources/urlSource.d.ts.map +1 -1
- package/dist/src/data/sources/urlSource.js +141 -17
- package/dist/src/encoder/encoder.d.ts +2 -2
- package/dist/src/fonts/bmFontManager.d.ts +1 -1
- package/dist/src/genome/assemblyPreflight.d.ts +31 -0
- package/dist/src/genome/assemblyPreflight.d.ts.map +1 -0
- package/dist/src/genome/assemblyPreflight.js +99 -0
- package/dist/src/genome/genome.d.ts +2 -2
- package/dist/src/genome/genome.d.ts.map +1 -1
- package/dist/src/genome/genome.js +4 -0
- package/dist/src/genome/genomeStore.d.ts +34 -3
- package/dist/src/genome/genomeStore.d.ts.map +1 -1
- package/dist/src/genome/genomeStore.js +409 -18
- package/dist/src/genome/rootGenomeConfig.d.ts +26 -0
- package/dist/src/genome/rootGenomeConfig.d.ts.map +1 -0
- package/dist/src/genome/rootGenomeConfig.js +94 -0
- package/dist/src/genomeSpy/interactionController.d.ts +5 -1
- package/dist/src/genomeSpy/interactionController.d.ts.map +1 -1
- package/dist/src/genomeSpy/interactionController.js +244 -29
- package/dist/src/genomeSpy/renderCoordinator.js +1 -1
- package/dist/src/genomeSpy.d.ts +13 -3
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +83 -7
- package/dist/src/gl/canvasSizeHelper.d.ts +74 -0
- package/dist/src/gl/canvasSizeHelper.d.ts.map +1 -0
- package/dist/src/gl/canvasSizeHelper.js +203 -0
- package/dist/src/gl/hashTable.d.ts +78 -0
- package/dist/src/gl/hashTable.d.ts.map +1 -0
- package/dist/src/gl/hashTable.js +164 -0
- package/dist/src/gl/includes/common.glsl.js +1 -1
- package/dist/src/gl/webGLHelper.d.ts +25 -11
- package/dist/src/gl/webGLHelper.d.ts.map +1 -1
- package/dist/src/gl/webGLHelper.js +71 -39
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -2
- package/dist/src/marks/link.d.ts.map +1 -1
- package/dist/src/marks/link.js +5 -3
- package/dist/src/marks/mark.d.ts +1 -1
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +8 -4
- package/dist/src/scales/domainPlanner.d.ts +34 -3
- package/dist/src/scales/domainPlanner.d.ts.map +1 -1
- package/dist/src/scales/domainPlanner.js +247 -26
- package/dist/src/scales/scaleInstanceManager.d.ts +2 -1
- package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
- package/dist/src/scales/scaleInstanceManager.js +10 -11
- package/dist/src/scales/scaleInteractionController.d.ts.map +1 -1
- package/dist/src/scales/scaleInteractionController.js +16 -14
- package/dist/src/scales/scaleResolution.d.ts +16 -0
- package/dist/src/scales/scaleResolution.d.ts.map +1 -1
- package/dist/src/scales/scaleResolution.js +314 -54
- package/dist/src/scales/scaleResolutionTestUtils.d.ts +21 -0
- package/dist/src/scales/scaleResolutionTestUtils.d.ts.map +1 -0
- package/dist/src/scales/scaleResolutionTestUtils.js +33 -0
- package/dist/src/scales/selectionDomainUtils.d.ts +22 -0
- package/dist/src/scales/selectionDomainUtils.d.ts.map +1 -0
- package/dist/src/scales/selectionDomainUtils.js +79 -0
- package/dist/src/scales/zoomDomainUtils.d.ts +18 -0
- package/dist/src/scales/zoomDomainUtils.d.ts.map +1 -0
- package/dist/src/scales/zoomDomainUtils.js +69 -0
- package/dist/src/screenshotHarness.d.ts +16 -0
- package/dist/src/screenshotHarness.d.ts.map +1 -0
- package/dist/src/screenshotHarness.js +242 -0
- package/dist/src/singlePageApp.js +1 -1
- package/dist/src/spec/data.d.ts +23 -3
- package/dist/src/spec/genome.d.ts +22 -2
- package/dist/src/spec/parameter.d.ts +39 -2
- package/dist/src/spec/root.d.ts +20 -1
- package/dist/src/spec/scale.d.ts +41 -5
- package/dist/src/styles/genome-spy.css +8 -0
- package/dist/src/styles/genome-spy.css.d.ts +1 -1
- package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
- package/dist/src/styles/genome-spy.css.js +8 -0
- package/dist/src/tooltip/dataTooltipHandler.js +59 -10
- package/dist/src/types/embedApi.d.ts +19 -0
- package/dist/src/utils/inferSpecBaseUrl.d.ts +14 -0
- package/dist/src/utils/inferSpecBaseUrl.d.ts.map +1 -0
- package/dist/src/utils/inferSpecBaseUrl.js +73 -0
- package/dist/src/utils/interactionEvent.d.ts +53 -3
- package/dist/src/utils/interactionEvent.d.ts.map +1 -1
- package/dist/src/utils/interactionEvent.js +62 -1
- package/dist/src/utils/radixSort.d.ts.map +1 -1
- package/dist/src/utils/radixSort.js +26 -1
- package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
- package/dist/src/view/containerMutationHelper.js +8 -0
- package/dist/src/view/dataReadiness.d.ts +2 -2
- package/dist/src/view/dataReadiness.d.ts.map +1 -1
- package/dist/src/view/dataReadiness.js +63 -58
- package/dist/src/view/facetView.d.ts +1 -1
- package/dist/src/view/facetView.js +1 -1
- package/dist/src/view/gridView/gridChild.d.ts +7 -0
- package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
- package/dist/src/view/gridView/gridChild.js +180 -11
- package/dist/src/view/gridView/gridView.d.ts.map +1 -1
- package/dist/src/view/gridView/gridView.js +60 -17
- package/dist/src/view/unitView.d.ts +1 -1
- package/dist/src/view/zoom.d.ts +14 -2
- package/dist/src/view/zoom.d.ts.map +1 -1
- package/dist/src/view/zoom.js +373 -76
- package/package.json +5 -2
|
@@ -82,11 +82,29 @@ export default class InteractionController {
|
|
|
82
82
|
return this.#currentHover;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
registerInteractionEvents() {
|
|
86
86
|
const canvas = this.#glHelper.canvas;
|
|
87
87
|
|
|
88
88
|
let lastWheelEvent = performance.now();
|
|
89
89
|
let longPressTriggered = false;
|
|
90
|
+
/** @type {{ pointerCount: 1 | 2, centerX: number, centerY: number, distance: number } | undefined} */
|
|
91
|
+
let previousTouchGesture;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param {Point} point
|
|
95
|
+
* @param {import("../utils/interactionEvent.js").InteractionUiEvent} uiEvent
|
|
96
|
+
* @returns {InteractionEvent}
|
|
97
|
+
*/
|
|
98
|
+
const dispatchInteractionEvent = (point, uiEvent) => {
|
|
99
|
+
const interactionEvent = new InteractionEvent(point, uiEvent);
|
|
100
|
+
this.#viewRoot.propagateInteractionEvent(interactionEvent);
|
|
101
|
+
|
|
102
|
+
if (!this.#tooltipUpdateRequested) {
|
|
103
|
+
this.#tooltip.clear();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return interactionEvent;
|
|
107
|
+
};
|
|
90
108
|
|
|
91
109
|
/** @param {Event} event */
|
|
92
110
|
const listener = (event) => {
|
|
@@ -117,13 +135,7 @@ export default class InteractionController {
|
|
|
117
135
|
* @param {MouseEvent} dispatchedEvent
|
|
118
136
|
*/
|
|
119
137
|
const dispatchEvent = (dispatchedEvent) => {
|
|
120
|
-
|
|
121
|
-
new InteractionEvent(point, dispatchedEvent)
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
if (!this.#tooltipUpdateRequested) {
|
|
125
|
-
this.#tooltip.clear();
|
|
126
|
-
}
|
|
138
|
+
dispatchInteractionEvent(point, dispatchedEvent);
|
|
127
139
|
};
|
|
128
140
|
|
|
129
141
|
if (event.type != "wheel") {
|
|
@@ -156,26 +168,41 @@ export default class InteractionController {
|
|
|
156
168
|
|
|
157
169
|
this.#wheelInertia.cancel();
|
|
158
170
|
} else {
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
171
|
+
// We must decide on the native wheel event whether to
|
|
172
|
+
// call preventDefault() (to block page scrolling).
|
|
173
|
+
// This probe asks the pointed view hierarchy to claim
|
|
174
|
+
// wheel ownership without running real wheel side
|
|
175
|
+
// effects first. Inertia is layered on top of that
|
|
176
|
+
// decision and is not the reason for the probe.
|
|
177
|
+
const probeEvent = dispatchInteractionEvent(point, {
|
|
178
|
+
type: "wheelclaimprobe",
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
if (probeEvent.wheelClaimed) {
|
|
182
|
+
// Vertical wheeling zooms.
|
|
183
|
+
// We use inertia to generate fake wheel events for smoother zooming
|
|
184
|
+
|
|
185
|
+
const template = makeEventTemplate(wheelEvent);
|
|
186
|
+
|
|
187
|
+
this.#wheelInertia.setMomentum(
|
|
188
|
+
wheelEvent.deltaY *
|
|
189
|
+
(wheelEvent.deltaMode ? 80 : 1),
|
|
190
|
+
(delta) => {
|
|
191
|
+
const e = new WheelEvent("wheel", {
|
|
192
|
+
...template,
|
|
193
|
+
deltaMode: 0,
|
|
194
|
+
deltaX: 0,
|
|
195
|
+
deltaY: delta,
|
|
196
|
+
});
|
|
197
|
+
dispatchEvent(e);
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
wheelEvent.preventDefault();
|
|
202
|
+
return;
|
|
203
|
+
} else {
|
|
204
|
+
this.#wheelInertia.cancel();
|
|
205
|
+
}
|
|
179
206
|
}
|
|
180
207
|
}
|
|
181
208
|
|
|
@@ -223,11 +250,168 @@ export default class InteractionController {
|
|
|
223
250
|
"wheel",
|
|
224
251
|
"click",
|
|
225
252
|
"mousemove",
|
|
226
|
-
"gesturechange",
|
|
227
253
|
"contextmenu",
|
|
228
254
|
"dblclick",
|
|
229
255
|
].forEach((type) => canvas.addEventListener(type, listener));
|
|
230
256
|
|
|
257
|
+
/**
|
|
258
|
+
* @param {number} clientX
|
|
259
|
+
* @param {number} clientY
|
|
260
|
+
*/
|
|
261
|
+
const toCanvasPoint = (clientX, clientY) => {
|
|
262
|
+
const rect = canvas.getBoundingClientRect();
|
|
263
|
+
return new Point(
|
|
264
|
+
clientX - rect.left - canvas.clientLeft,
|
|
265
|
+
clientY - rect.top - canvas.clientTop
|
|
266
|
+
);
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* @param {TouchList} touches
|
|
271
|
+
*/
|
|
272
|
+
const readTouchGesture = (touches) => {
|
|
273
|
+
if (touches.length <= 0) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const first = touches[0];
|
|
278
|
+
|
|
279
|
+
if (touches.length === 1) {
|
|
280
|
+
return {
|
|
281
|
+
pointerCount: /** @type {1} */ (1),
|
|
282
|
+
centerX: first.clientX,
|
|
283
|
+
centerY: first.clientY,
|
|
284
|
+
distance: 0,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const second = touches[1];
|
|
289
|
+
return {
|
|
290
|
+
pointerCount: /** @type {2} */ (2),
|
|
291
|
+
centerX: (first.clientX + second.clientX) / 2,
|
|
292
|
+
centerY: (first.clientY + second.clientY) / 2,
|
|
293
|
+
distance: getClientDistance(first, second),
|
|
294
|
+
};
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* @param {number} x
|
|
299
|
+
* @param {number} y
|
|
300
|
+
* @param {"move" | "end"} phase
|
|
301
|
+
* @param {1 | 2} pointerCount
|
|
302
|
+
* @param {number} xDelta
|
|
303
|
+
* @param {number} yDelta
|
|
304
|
+
* @param {number} zDelta
|
|
305
|
+
*/
|
|
306
|
+
const dispatchTouchGestureEvent = (
|
|
307
|
+
x,
|
|
308
|
+
y,
|
|
309
|
+
phase,
|
|
310
|
+
pointerCount,
|
|
311
|
+
xDelta,
|
|
312
|
+
yDelta,
|
|
313
|
+
zDelta
|
|
314
|
+
) => {
|
|
315
|
+
const point = toCanvasPoint(x, y);
|
|
316
|
+
dispatchInteractionEvent(point, {
|
|
317
|
+
type: "touchgesture",
|
|
318
|
+
phase,
|
|
319
|
+
pointerCount,
|
|
320
|
+
xDelta,
|
|
321
|
+
yDelta,
|
|
322
|
+
zDelta,
|
|
323
|
+
});
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* @param {TouchEvent} touchEvent
|
|
328
|
+
*/
|
|
329
|
+
const handleTouchStartOrMove = (touchEvent) => {
|
|
330
|
+
touchEvent.preventDefault();
|
|
331
|
+
this.#wheelInertia.cancel();
|
|
332
|
+
this.#tooltipUpdateRequested = false;
|
|
333
|
+
|
|
334
|
+
const currentGesture = readTouchGesture(touchEvent.touches);
|
|
335
|
+
if (!currentGesture) {
|
|
336
|
+
previousTouchGesture = undefined;
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (
|
|
341
|
+
!previousTouchGesture ||
|
|
342
|
+
previousTouchGesture.pointerCount !==
|
|
343
|
+
currentGesture.pointerCount
|
|
344
|
+
) {
|
|
345
|
+
previousTouchGesture = currentGesture;
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const xDelta =
|
|
350
|
+
currentGesture.centerX - previousTouchGesture.centerX;
|
|
351
|
+
const yDelta =
|
|
352
|
+
currentGesture.centerY - previousTouchGesture.centerY;
|
|
353
|
+
const zDelta =
|
|
354
|
+
currentGesture.pointerCount === 2
|
|
355
|
+
? pinchDistanceToZoomDelta(
|
|
356
|
+
previousTouchGesture.distance,
|
|
357
|
+
currentGesture.distance
|
|
358
|
+
)
|
|
359
|
+
: 0;
|
|
360
|
+
|
|
361
|
+
if (
|
|
362
|
+
(xDelta !== 0 || yDelta !== 0 || zDelta !== 0) &&
|
|
363
|
+
Number.isFinite(xDelta) &&
|
|
364
|
+
Number.isFinite(yDelta) &&
|
|
365
|
+
Number.isFinite(zDelta)
|
|
366
|
+
) {
|
|
367
|
+
dispatchTouchGestureEvent(
|
|
368
|
+
previousTouchGesture.centerX,
|
|
369
|
+
previousTouchGesture.centerY,
|
|
370
|
+
"move",
|
|
371
|
+
currentGesture.pointerCount,
|
|
372
|
+
xDelta,
|
|
373
|
+
yDelta,
|
|
374
|
+
zDelta
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
previousTouchGesture = currentGesture;
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @param {TouchEvent} touchEvent
|
|
383
|
+
*/
|
|
384
|
+
const handleTouchEndOrCancel = (touchEvent) => {
|
|
385
|
+
touchEvent.preventDefault();
|
|
386
|
+
this.#tooltipUpdateRequested = false;
|
|
387
|
+
if (previousTouchGesture && touchEvent.touches.length === 0) {
|
|
388
|
+
dispatchTouchGestureEvent(
|
|
389
|
+
previousTouchGesture.centerX,
|
|
390
|
+
previousTouchGesture.centerY,
|
|
391
|
+
"end",
|
|
392
|
+
previousTouchGesture.pointerCount,
|
|
393
|
+
0,
|
|
394
|
+
0,
|
|
395
|
+
0
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
previousTouchGesture = readTouchGesture(touchEvent.touches);
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
canvas.addEventListener("touchstart", handleTouchStartOrMove, {
|
|
403
|
+
passive: false,
|
|
404
|
+
});
|
|
405
|
+
canvas.addEventListener("touchmove", handleTouchStartOrMove, {
|
|
406
|
+
passive: false,
|
|
407
|
+
});
|
|
408
|
+
canvas.addEventListener("touchend", handleTouchEndOrCancel, {
|
|
409
|
+
passive: false,
|
|
410
|
+
});
|
|
411
|
+
canvas.addEventListener("touchcancel", handleTouchEndOrCancel, {
|
|
412
|
+
passive: false,
|
|
413
|
+
});
|
|
414
|
+
|
|
231
415
|
canvas.addEventListener("mousedown", (/** @type {MouseEvent} */ e) => {
|
|
232
416
|
this.#mouseDownCoords = Point.fromMouseEvent(e);
|
|
233
417
|
if (this.#tooltip.sticky) {
|
|
@@ -375,3 +559,34 @@ export default class InteractionController {
|
|
|
375
559
|
}
|
|
376
560
|
}
|
|
377
561
|
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* @typedef {{clientX: number, clientY: number}} ClientPointLike
|
|
565
|
+
*/
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Returns euclidean distance between two client-space points.
|
|
569
|
+
*
|
|
570
|
+
* @param {ClientPointLike} a
|
|
571
|
+
* @param {ClientPointLike} b
|
|
572
|
+
*/
|
|
573
|
+
function getClientDistance(a, b) {
|
|
574
|
+
const dx = b.clientX - a.clientX;
|
|
575
|
+
const dy = b.clientY - a.clientY;
|
|
576
|
+
return Math.hypot(dx, dy);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Converts a pinch distance ratio to a zDelta used by interactionToZoom:
|
|
581
|
+
* scaleFactor = 2 ** zDelta.
|
|
582
|
+
*
|
|
583
|
+
* @param {number} previousDistance
|
|
584
|
+
* @param {number} currentDistance
|
|
585
|
+
*/
|
|
586
|
+
function pinchDistanceToZoomDelta(previousDistance, currentDistance) {
|
|
587
|
+
if (previousDistance <= 0 || currentDistance <= 0) {
|
|
588
|
+
return 0;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return Math.log2(previousDistance / currentDistance);
|
|
592
|
+
}
|
|
@@ -70,7 +70,7 @@ export default class RenderCoordinator {
|
|
|
70
70
|
const commonOptions = {
|
|
71
71
|
webGLHelper: this.#glHelper,
|
|
72
72
|
canvasSize,
|
|
73
|
-
devicePixelRatio:
|
|
73
|
+
devicePixelRatio: this.#glHelper.getDevicePixelRatio(canvasSize),
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
this.#renderingContext = new BufferedViewRenderingContext(
|
package/dist/src/genomeSpy.d.ts
CHANGED
|
@@ -77,7 +77,13 @@ export default class GenomeSpy {
|
|
|
77
77
|
*/
|
|
78
78
|
launch(): Promise<boolean>;
|
|
79
79
|
initializeVisibleViewData(): Promise<void>;
|
|
80
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Waits until lazy sources under the root view have loaded data for the
|
|
82
|
+
* current visible positional domain.
|
|
83
|
+
*
|
|
84
|
+
* @param {AbortSignal} [signal]
|
|
85
|
+
*/
|
|
86
|
+
awaitVisibleLazyData(signal?: AbortSignal): Promise<void>;
|
|
81
87
|
/**
|
|
82
88
|
* This method should be called in a mouseMove handler. If not called, the
|
|
83
89
|
* tooltip will be hidden.
|
|
@@ -98,8 +104,12 @@ export default class GenomeSpy {
|
|
|
98
104
|
*/
|
|
99
105
|
exportCanvas(logicalWidth?: number, logicalHeight?: number, devicePixelRatio?: number, clearColor?: string): string;
|
|
100
106
|
getLogicalCanvasSize(): {
|
|
101
|
-
width:
|
|
102
|
-
height:
|
|
107
|
+
width: number;
|
|
108
|
+
height: number;
|
|
109
|
+
};
|
|
110
|
+
getRenderedBounds(): {
|
|
111
|
+
width: number | undefined;
|
|
112
|
+
height: number | undefined;
|
|
103
113
|
};
|
|
104
114
|
computeLayout(): void;
|
|
105
115
|
renderAll(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"genomeSpy.d.ts","sourceRoot":"","sources":["../../src/genomeSpy.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"genomeSpy.d.ts","sourceRoot":"","sources":["../../src/genomeSpy.js"],"names":[],"mappings":"AAyDA;IAoBI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EA0CpD;IAvCG,uBAA0B;IAC1B,oDAAsB;IAItB,sCAAsC;IACtC,wCAAgB;IAEhB,yBAAoC;IAEpC,4CAA4C;IAC5C,oBADW,CAAC,CAAS,IAAM,EAAN,MAAM,KAAE,MAAM,EAAE,CAAC,EAAE,CACZ;IAE5B,mBAAoD;IAEpD,0BAA0B;IAC1B,aADW,WAAW,CACM;IAE5B;;;;;OAKG;IACH,yBAFU,CAAC,IAAI,qEAAM,KAAK,OAAO,CAE8B;IAE/D,oFAAoF;IACpF,iBADW,MAAM,CAAC,MAAM,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC,CAK9E;IAED,mBAAmB;IACnB,8EAAyB;IAIzB,YAAkC;IAatC;;;OAGG;IACH,oCAFW,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,EAAE,QAIjC;IAED;;OAEG;IACH,+BAFW,MAAM,YAShB;IAED;;;;OAIG;IACH,sBAHW,MAAM,QACN,GAAG,EAAE,QAYf;IAED;;;OAGG;IACH,uBAHW,MAAM,YACN,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,QAI9B;IAED;;;OAGG;IACH,0BAHW,MAAM,YACN,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,QAI9B;IAED;;;;;OAKG;IACH,gBAHW,kBAAkB,YAClB,GAAG,QAMb;IAgEG,iDAAsB;IAQ1B;;OAEG;IACH,gBAqBC;IA0LD;;;OAGG;IACH,UAFa,OAAO,CAAC,OAAO,CAAC,CAyC5B;IAED,2CAiBC;IAED;;;;;OAKG;IACH,8BAFW,WAAW,iBAgBrB;IAED;;;;;;;OAOG;IACH,cAFa,CAAC,SAFH,CAAC,cACD,CAAS,IAAC,EAAD,CAAC,KAAE,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAKlF;IAED;;;;;;;;OAQG;IACH,4BANW,MAAM,kBACN,MAAM,qBACN,MAAM,eACN,MAAM,UAuBhB;IAED;;;MAEC;IAED;eACwB,MAAM,GAAG,SAAS;gBAAU,MAAM,GAAG,SAAS;MAcrE;IAED,sBAEC;IAED,kBAEC;IAED,iCAEC;IAED,oEAYC;IAED,uFAWC;;CACJ;;;;iCAlnBY,eAAe,GAAG,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB;4BApBnC,uBAAuB;qBAR9C,qBAAqB;wBAElB,yBAAyB;qBAL5B,oBAAoB"}
|
package/dist/src/genomeSpy.js
CHANGED
|
@@ -37,6 +37,13 @@ import {
|
|
|
37
37
|
} from "./genomeSpy/viewHierarchyConfig.js";
|
|
38
38
|
import { exportCanvas } from "./genomeSpy/canvasExport.js";
|
|
39
39
|
import { validateSelectorConstraints } from "./view/viewSelectors.js";
|
|
40
|
+
import parquet from "./data/formats/parquet.js";
|
|
41
|
+
import bed from "./data/formats/bed.js";
|
|
42
|
+
import bedpe from "./data/formats/bedpe.js";
|
|
43
|
+
import SingleAxisWindowedSource from "./data/sources/lazy/singleAxisWindowedSource.js";
|
|
44
|
+
import { ensureAssembliesForView } from "./genome/assemblyPreflight.js";
|
|
45
|
+
import { resolveRootGenomeConfig } from "./genome/rootGenomeConfig.js";
|
|
46
|
+
import { awaitSubtreeLazyReady } from "./view/dataReadiness.js";
|
|
40
47
|
|
|
41
48
|
/**
|
|
42
49
|
* Events that are broadcasted to all views.
|
|
@@ -44,6 +51,9 @@ import { validateSelectorConstraints } from "./view/viewSelectors.js";
|
|
|
44
51
|
*/
|
|
45
52
|
|
|
46
53
|
vegaFormats("fasta", fasta);
|
|
54
|
+
vegaFormats("parquet", parquet);
|
|
55
|
+
vegaFormats("bed", bed);
|
|
56
|
+
vegaFormats("bedpe", bedpe);
|
|
47
57
|
|
|
48
58
|
export default class GenomeSpy {
|
|
49
59
|
/** @type {(() => void)[]} */
|
|
@@ -196,6 +206,8 @@ export default class GenomeSpy {
|
|
|
196
206
|
}
|
|
197
207
|
|
|
198
208
|
#setupDpr() {
|
|
209
|
+
this.dpr = this.#glHelper.getDevicePixelRatio();
|
|
210
|
+
|
|
199
211
|
const dprSetter = this.viewRoot.paramRuntime.allocateSetter(
|
|
200
212
|
"devicePixelRatio",
|
|
201
213
|
this.dpr
|
|
@@ -203,7 +215,7 @@ export default class GenomeSpy {
|
|
|
203
215
|
|
|
204
216
|
const resizeCallback = () => {
|
|
205
217
|
this.#glHelper.invalidateSize();
|
|
206
|
-
this.dpr =
|
|
218
|
+
this.dpr = this.#glHelper.getDevicePixelRatio();
|
|
207
219
|
dprSetter(this.dpr);
|
|
208
220
|
this.computeLayout();
|
|
209
221
|
// Render immediately, without RAF
|
|
@@ -303,9 +315,15 @@ export default class GenomeSpy {
|
|
|
303
315
|
}
|
|
304
316
|
|
|
305
317
|
async #initializeGenomeStore() {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
318
|
+
this.genomeStore = new GenomeStore(this.spec.baseUrl);
|
|
319
|
+
|
|
320
|
+
const { genomesByName, defaultAssembly, deprecationWarning } =
|
|
321
|
+
resolveRootGenomeConfig(this.spec);
|
|
322
|
+
this.genomeStore.configureGenomes(genomesByName, defaultAssembly);
|
|
323
|
+
|
|
324
|
+
if (deprecationWarning) {
|
|
325
|
+
// eslint-disable-next-line no-console
|
|
326
|
+
console.warn(deprecationWarning);
|
|
309
327
|
}
|
|
310
328
|
}
|
|
311
329
|
|
|
@@ -396,6 +414,11 @@ export default class GenomeSpy {
|
|
|
396
414
|
VIEW_ROOT_NAME
|
|
397
415
|
);
|
|
398
416
|
|
|
417
|
+
// Reminder: assemblies must be ensured after view creation (imports and
|
|
418
|
+
// inheritance resolved), but before any code path that may touch scales
|
|
419
|
+
// (e.g. step-based sizes, dynamic opacity, encoder initialization).
|
|
420
|
+
await ensureAssembliesForView(this.viewRoot, this.genomeStore);
|
|
421
|
+
|
|
399
422
|
this.#loadingStatusRegistry.set(this.viewRoot, "loading");
|
|
400
423
|
|
|
401
424
|
this.#canvasWrapper.style.flexGrow =
|
|
@@ -473,7 +496,7 @@ export default class GenomeSpy {
|
|
|
473
496
|
|
|
474
497
|
await this.#prepareViewsAndData();
|
|
475
498
|
|
|
476
|
-
this.
|
|
499
|
+
this.#interactionController.registerInteractionEvents();
|
|
477
500
|
|
|
478
501
|
this.computeLayout();
|
|
479
502
|
this.animator.requestRender();
|
|
@@ -526,8 +549,26 @@ export default class GenomeSpy {
|
|
|
526
549
|
this.animator.requestRender();
|
|
527
550
|
}
|
|
528
551
|
|
|
529
|
-
|
|
530
|
-
|
|
552
|
+
/**
|
|
553
|
+
* Waits until lazy sources under the root view have loaded data for the
|
|
554
|
+
* current visible positional domain.
|
|
555
|
+
*
|
|
556
|
+
* @param {AbortSignal} [signal]
|
|
557
|
+
*/
|
|
558
|
+
async awaitVisibleLazyData(signal) {
|
|
559
|
+
if (!this.viewRoot) {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
await awaitSubtreeLazyReady(
|
|
564
|
+
this.viewRoot.context,
|
|
565
|
+
this.viewRoot,
|
|
566
|
+
undefined,
|
|
567
|
+
signal,
|
|
568
|
+
(view) =>
|
|
569
|
+
view.isConfiguredVisible() &&
|
|
570
|
+
hasWindowedLazyDataSource(view)
|
|
571
|
+
);
|
|
531
572
|
}
|
|
532
573
|
|
|
533
574
|
/**
|
|
@@ -577,6 +618,23 @@ export default class GenomeSpy {
|
|
|
577
618
|
return this.#glHelper.getLogicalCanvasSize();
|
|
578
619
|
}
|
|
579
620
|
|
|
621
|
+
getRenderedBounds() {
|
|
622
|
+
/** @type {{ width: number | undefined, height: number | undefined }} */
|
|
623
|
+
const bounds = {
|
|
624
|
+
width: undefined,
|
|
625
|
+
height: undefined,
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
this.viewRoot.visit((view) => {
|
|
629
|
+
for (const coords of view.facetCoords.values()) {
|
|
630
|
+
bounds.width = Math.max(bounds.width ?? 0, coords.x2);
|
|
631
|
+
bounds.height = Math.max(bounds.height ?? 0, coords.y2);
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
return bounds;
|
|
636
|
+
}
|
|
637
|
+
|
|
580
638
|
computeLayout() {
|
|
581
639
|
this.#renderCoordinator.computeLayout();
|
|
582
640
|
}
|
|
@@ -616,3 +674,21 @@ export default class GenomeSpy {
|
|
|
616
674
|
return resolutions;
|
|
617
675
|
}
|
|
618
676
|
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* @param {View} view
|
|
680
|
+
*/
|
|
681
|
+
function hasWindowedLazyDataSource(view) {
|
|
682
|
+
/** @type {View | null} */
|
|
683
|
+
let current = view;
|
|
684
|
+
|
|
685
|
+
while (current) {
|
|
686
|
+
const dataSource = current.flowHandle?.dataSource;
|
|
687
|
+
if (dataSource) {
|
|
688
|
+
return dataSource instanceof SingleAxisWindowedSource;
|
|
689
|
+
}
|
|
690
|
+
current = current.dataParent;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return false;
|
|
694
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles logical/physical canvas size calculations and optional
|
|
3
|
+
* device-pixel-content-box observation.
|
|
4
|
+
*/
|
|
5
|
+
export default class CanvasSizeHelper {
|
|
6
|
+
/**
|
|
7
|
+
* @param {HTMLElement} container
|
|
8
|
+
* @param {HTMLCanvasElement} canvas
|
|
9
|
+
* @param {() => {width: number, height: number}} sizeSource
|
|
10
|
+
* @param {() => void} [onPhysicalSizeChange]
|
|
11
|
+
*/
|
|
12
|
+
constructor(container: HTMLElement, canvas: HTMLCanvasElement, sizeSource: () => {
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
}, onPhysicalSizeChange?: () => void);
|
|
16
|
+
_container: HTMLElement;
|
|
17
|
+
_canvas: HTMLCanvasElement;
|
|
18
|
+
_sizeSource: () => {
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
};
|
|
22
|
+
_onPhysicalSizeChange: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* @type {{ width: number, height: number } | undefined}
|
|
25
|
+
*/
|
|
26
|
+
_logicalCanvasSize: {
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
} | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* @type {{ width: number, height: number } | undefined}
|
|
32
|
+
*/
|
|
33
|
+
_devicePixelContentBoxSize: {
|
|
34
|
+
width: number;
|
|
35
|
+
height: number;
|
|
36
|
+
} | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* @type {ResizeObserver | undefined}
|
|
39
|
+
*/
|
|
40
|
+
_devicePixelContentBoxObserver: ResizeObserver | undefined;
|
|
41
|
+
invalidate(): void;
|
|
42
|
+
finalize(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Returns the canvas size in true display pixels
|
|
45
|
+
*
|
|
46
|
+
* @param {{ width: number, height: number }} [logicalSize]
|
|
47
|
+
*/
|
|
48
|
+
getPhysicalCanvasSize(logicalSize?: {
|
|
49
|
+
width: number;
|
|
50
|
+
height: number;
|
|
51
|
+
}): {
|
|
52
|
+
width: number;
|
|
53
|
+
height: number;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Returns the ratio between true display pixels and logical pixels.
|
|
57
|
+
*
|
|
58
|
+
* @param {{ width: number, height: number }} [logicalSize]
|
|
59
|
+
*/
|
|
60
|
+
getDevicePixelRatio(logicalSize?: {
|
|
61
|
+
width: number;
|
|
62
|
+
height: number;
|
|
63
|
+
}): number;
|
|
64
|
+
/**
|
|
65
|
+
* Returns the size of the canvas canvas container size in logical pixels,
|
|
66
|
+
* without devicePixelRatio correction.
|
|
67
|
+
*/
|
|
68
|
+
getLogicalCanvasSize(): {
|
|
69
|
+
width: number;
|
|
70
|
+
height: number;
|
|
71
|
+
};
|
|
72
|
+
_observeDevicePixelContentBox(): void;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=canvasSizeHelper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvasSizeHelper.d.ts","sourceRoot":"","sources":["../../../src/gl/canvasSizeHelper.js"],"names":[],"mappings":"AAAA;;;GAGG;AACH;IACI;;;;;OAKG;IACH,uBALW,WAAW,UACX,iBAAiB,cACjB,MAAM;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,yBACrC,MAAM,IAAI,EAwBpB;IArBG,wBAA2B;IAC3B,2BAAqB;IACrB,mBANa;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,CAMf;IAC7B,6BANa,IAAI,CAM8C;IAE/D;;OAEG;IACH,oBAFU;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAEpB;IAEnC;;OAEG;IACH,4BAFU;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAEZ;IAE3C;;OAEG;IACH,gCAFU,cAAc,GAAG,SAAS,CAEW;IAKnD,mBAGC;IAED,iBAIC;IAED;;;;OAIG;IACH,oCAFW;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;eA1BrB,MAAM;gBAAU,MAAM;MA0C5C;IAED;;;;OAIG;IACH,kCAFW;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,UA2B3C;IAED;;;OAGG;IACH;eArFuB,MAAM;gBAAU,MAAM;MA8H5C;IAED,sCAuDC;CACJ"}
|