@genome-spy/core 0.29.0 → 0.30.2
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/dist/index.es.js +16373 -0
- package/dist/index.js +43 -43
- package/package.json +10 -7
- package/src/data/collector.js +0 -183
- package/src/data/collector.test.js +0 -84
- package/src/data/dataFlow.js +0 -148
- package/src/data/dataFlow.test.js +0 -5
- package/src/data/facetNode.js +0 -17
- package/src/data/flow.test.js +0 -72
- package/src/data/flowBatch.d.ts +0 -40
- package/src/data/flowNode.js +0 -283
- package/src/data/flowNode.test.js +0 -50
- package/src/data/flowOptimizer.js +0 -123
- package/src/data/flowOptimizer.test.js +0 -193
- package/src/data/flowTestUtils.js +0 -63
- package/src/data/formats/fasta.js +0 -32
- package/src/data/formats/fasta.test.js +0 -27
- package/src/data/sources/dataSource.js +0 -22
- package/src/data/sources/dataSourceFactory.js +0 -24
- package/src/data/sources/dataUtils.js +0 -78
- package/src/data/sources/dynamicCallbackSource.js +0 -57
- package/src/data/sources/dynamicSource.js +0 -37
- package/src/data/sources/inlineSource.js +0 -67
- package/src/data/sources/inlineSource.test.js +0 -56
- package/src/data/sources/namedSource.js +0 -79
- package/src/data/sources/sequenceSource.js +0 -46
- package/src/data/sources/sequenceSource.test.js +0 -46
- package/src/data/sources/urlSource.js +0 -74
- package/src/data/transforms/aggregate.js +0 -70
- package/src/data/transforms/clone.js +0 -40
- package/src/data/transforms/clone.test.js +0 -11
- package/src/data/transforms/coverage.js +0 -187
- package/src/data/transforms/coverage.test.js +0 -123
- package/src/data/transforms/filter.js +0 -37
- package/src/data/transforms/filter.test.js +0 -18
- package/src/data/transforms/filterScoredLabels.js +0 -134
- package/src/data/transforms/flattenCompressedExons.js +0 -57
- package/src/data/transforms/flattenDelimited.js +0 -74
- package/src/data/transforms/flattenDelimited.test.js +0 -87
- package/src/data/transforms/flattenSequence.js +0 -39
- package/src/data/transforms/flattenSequence.test.js +0 -34
- package/src/data/transforms/formula.js +0 -39
- package/src/data/transforms/formula.test.js +0 -19
- package/src/data/transforms/identifier.js +0 -108
- package/src/data/transforms/identifier.test.js +0 -83
- package/src/data/transforms/linearizeGenomicCoordinate.js +0 -101
- package/src/data/transforms/measureText.js +0 -44
- package/src/data/transforms/pileup.js +0 -128
- package/src/data/transforms/pileup.test.js +0 -70
- package/src/data/transforms/project.js +0 -41
- package/src/data/transforms/project.test.js +0 -32
- package/src/data/transforms/regexExtract.js +0 -61
- package/src/data/transforms/regexExtract.test.js +0 -67
- package/src/data/transforms/regexFold.js +0 -141
- package/src/data/transforms/regexFold.test.js +0 -160
- package/src/data/transforms/sample.js +0 -101
- package/src/data/transforms/sample.test.js +0 -38
- package/src/data/transforms/stack.js +0 -137
- package/src/data/transforms/stack.test.js +0 -91
- package/src/data/transforms/transformFactory.js +0 -60
- package/src/embedApi.d.ts +0 -67
- package/src/encoder/accessor.js +0 -82
- package/src/encoder/accessor.test.js +0 -47
- package/src/encoder/encoder.js +0 -394
- package/src/encoder/encoder.test.js +0 -98
- package/src/fonts/Lato-Regular.json +0 -1267
- package/src/fonts/Lato-Regular.png +0 -0
- package/src/fonts/OFL.txt +0 -93
- package/src/fonts/README.md +0 -3
- package/src/fonts/bmFont.d.ts +0 -58
- package/src/fonts/bmFontManager.js +0 -357
- package/src/fonts/bmFontMetrics.js +0 -108
- package/src/genome/genome.js +0 -317
- package/src/genome/genome.test.js +0 -188
- package/src/genome/genomeStore.js +0 -54
- package/src/genome/locusFormat.js +0 -31
- package/src/genome/scaleIndex.d.ts +0 -38
- package/src/genome/scaleIndex.js +0 -166
- package/src/genome/scaleIndex.test.js +0 -78
- package/src/genome/scaleLocus.d.ts +0 -11
- package/src/genome/scaleLocus.js +0 -108
- package/src/genome/scaleLocus.test.js +0 -4
- package/src/genomeSpy.js +0 -784
- package/src/gl/arrayBuilder.js +0 -199
- package/src/gl/dataToVertices.js +0 -636
- package/src/gl/includes/common.glsl +0 -63
- package/src/gl/includes/picking.fragment.glsl +0 -1
- package/src/gl/includes/picking.vertex.glsl +0 -27
- package/src/gl/includes/sampleFacet.glsl +0 -107
- package/src/gl/includes/scales.glsl +0 -112
- package/src/gl/link.fragment.glsl +0 -18
- package/src/gl/link.vertex.glsl +0 -111
- package/src/gl/point.fragment.glsl +0 -123
- package/src/gl/point.vertex.glsl +0 -129
- package/src/gl/rect.fragment.glsl +0 -51
- package/src/gl/rect.vertex.glsl +0 -114
- package/src/gl/rule.fragment.glsl +0 -52
- package/src/gl/rule.vertex.glsl +0 -89
- package/src/gl/text.fragment.glsl +0 -31
- package/src/gl/text.vertex.glsl +0 -246
- package/src/gl/webGLHelper.js +0 -489
- package/src/img/bowtie.svg +0 -1
- package/src/img/genomespy-favicon.svg +0 -34
- package/src/index.html +0 -11
- package/src/index.js +0 -128
- package/src/marks/link.js +0 -175
- package/src/marks/mark.js +0 -975
- package/src/marks/markUtils.js +0 -125
- package/src/marks/pointMark.js +0 -251
- package/src/marks/rectMark.js +0 -241
- package/src/marks/rule.js +0 -250
- package/src/marks/text.js +0 -278
- package/src/node_modules/.vitest/results.json +0 -1
- package/src/scale/colorUtils.js +0 -184
- package/src/scale/glslScaleGenerator.js +0 -488
- package/src/scale/scale.js +0 -451
- package/src/scale/scale.test.js +0 -324
- package/src/scale/ticks.js +0 -203
- package/src/scale/ticks.test.js +0 -40
- package/src/singlePageApp.js +0 -13
- package/src/spec/axis.d.ts +0 -296
- package/src/spec/channel.d.ts +0 -430
- package/src/spec/data.d.ts +0 -196
- package/src/spec/font.d.ts +0 -15
- package/src/spec/genome.d.ts +0 -35
- package/src/spec/mark.d.ts +0 -429
- package/src/spec/root.d.ts +0 -17
- package/src/spec/sampleView.d.ts +0 -180
- package/src/spec/scale.d.ts +0 -273
- package/src/spec/title.d.ts +0 -102
- package/src/spec/tooltip.d.ts +0 -9
- package/src/spec/transform.d.ts +0 -479
- package/src/spec/view.d.ts +0 -201
- package/src/styles/genome-spy.scss +0 -153
- package/src/tooltip/dataTooltipHandler.js +0 -64
- package/src/tooltip/refseqGeneTooltipHandler.js +0 -78
- package/src/tooltip/tooltipHandler.ts +0 -12
- package/src/types/filetypes.d.ts +0 -14
- package/src/types/flatqueue.d.ts +0 -53
- package/src/types/glsl.d.ts +0 -4
- package/src/types/internmap.d.ts +0 -22
- package/src/types/object.d.ts +0 -21
- package/src/types/vega-loader.d.ts +0 -1
- package/src/types/vega-scale.d.ts +0 -60
- package/src/utils/addBaseUrl.js +0 -19
- package/src/utils/addBaseUrl.test.js +0 -22
- package/src/utils/animator.js +0 -83
- package/src/utils/arrayUtils.js +0 -61
- package/src/utils/binnedIndex.js +0 -167
- package/src/utils/binnedIndex.test.js +0 -155
- package/src/utils/clamp.js +0 -8
- package/src/utils/cloner.js +0 -34
- package/src/utils/cloner.test.js +0 -24
- package/src/utils/coalesce.js +0 -11
- package/src/utils/coalesce.test.js +0 -16
- package/src/utils/concatIterables.js +0 -26
- package/src/utils/concatIterables.test.js +0 -8
- package/src/utils/debounce.js +0 -37
- package/src/utils/domainArray.js +0 -216
- package/src/utils/domainArray.test.js +0 -130
- package/src/utils/eerp.js +0 -13
- package/src/utils/expression.js +0 -32
- package/src/utils/field.js +0 -28
- package/src/utils/formatObject.js +0 -31
- package/src/utils/indexer.js +0 -43
- package/src/utils/indexer.test.js +0 -47
- package/src/utils/inertia.js +0 -124
- package/src/utils/interactionEvent.js +0 -33
- package/src/utils/iterateNestedMaps.js +0 -21
- package/src/utils/iterateNestedMaps.test.js +0 -33
- package/src/utils/kWayMerge.js +0 -42
- package/src/utils/kWayMerge.test.js +0 -26
- package/src/utils/layout/flexLayout.js +0 -368
- package/src/utils/layout/flexLayout.test.js +0 -311
- package/src/utils/layout/grid.js +0 -95
- package/src/utils/layout/grid.test.js +0 -71
- package/src/utils/layout/padding.js +0 -120
- package/src/utils/layout/point.js +0 -23
- package/src/utils/layout/rectangle.js +0 -288
- package/src/utils/layout/rectangle.test.js +0 -172
- package/src/utils/mergeObjects.js +0 -99
- package/src/utils/mergeObjects.test.js +0 -42
- package/src/utils/numberExtractor.js +0 -24
- package/src/utils/numberExtractor.test.js +0 -6
- package/src/utils/point.js +0 -14
- package/src/utils/propertyCacher.js +0 -70
- package/src/utils/propertyCacher.test.js +0 -85
- package/src/utils/propertyCoalescer.js +0 -42
- package/src/utils/propertyCoalescer.test.js +0 -22
- package/src/utils/reservationMap.js +0 -103
- package/src/utils/reservationMap.test.js +0 -20
- package/src/utils/scaleNull.js +0 -19
- package/src/utils/setOperations.js +0 -75
- package/src/utils/smoothstep.js +0 -10
- package/src/utils/throttle.js +0 -34
- package/src/utils/topK.js +0 -76
- package/src/utils/topK.test.js +0 -64
- package/src/utils/transition.js +0 -74
- package/src/utils/ui/tooltip.js +0 -189
- package/src/utils/url.js +0 -22
- package/src/utils/variableTools.js +0 -24
- package/src/utils/variableTools.test.js +0 -13
- package/src/view/axisResolution.js +0 -140
- package/src/view/axisResolution.test.js +0 -201
- package/src/view/axisView.js +0 -747
- package/src/view/concatView.js +0 -45
- package/src/view/containerView.js +0 -159
- package/src/view/facetView.js +0 -491
- package/src/view/flowBuilder.js +0 -367
- package/src/view/flowBuilder.test.js +0 -125
- package/src/view/gridView.js +0 -786
- package/src/view/implicitRootView.js +0 -14
- package/src/view/importView.js +0 -19
- package/src/view/layerView.js +0 -74
- package/src/view/rendering.d.ts +0 -44
- package/src/view/renderingContext/compositeViewRenderingContext.js +0 -51
- package/src/view/renderingContext/deferredViewRenderingContext.js +0 -176
- package/src/view/renderingContext/layoutRecorderViewRenderingContext.js +0 -128
- package/src/view/renderingContext/simpleViewRenderingContext.js +0 -64
- package/src/view/renderingContext/svgViewRenderingContext.js +0 -125
- package/src/view/renderingContext/viewRenderingContext.js +0 -41
- package/src/view/scaleResolution.js +0 -791
- package/src/view/scaleResolution.test.js +0 -572
- package/src/view/scaleResolutionApi.d.ts +0 -40
- package/src/view/testUtils.js +0 -51
- package/src/view/title.js +0 -165
- package/src/view/unitView.js +0 -382
- package/src/view/view.js +0 -612
- package/src/view/view.test.js +0 -214
- package/src/view/viewContext.d.ts +0 -62
- package/src/view/viewFactory.js +0 -181
- package/src/view/viewFactory.test.js +0 -17
- package/src/view/viewUtils.js +0 -327
- package/src/view/zoom.js +0 -89
package/src/gl/webGLHelper.js
DELETED
|
@@ -1,489 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addExtensionsToContext,
|
|
3
|
-
createFramebufferInfo,
|
|
4
|
-
createTexture,
|
|
5
|
-
getContext,
|
|
6
|
-
isWebGL2,
|
|
7
|
-
resizeFramebufferInfo,
|
|
8
|
-
setTextureFromArray,
|
|
9
|
-
} from "twgl.js";
|
|
10
|
-
import { isArray, isString } from "vega-util";
|
|
11
|
-
|
|
12
|
-
import { isDiscrete, isDiscretizing, isInterpolating } from "vega-scale";
|
|
13
|
-
import {
|
|
14
|
-
createDiscreteColorTexture,
|
|
15
|
-
createDiscreteTexture,
|
|
16
|
-
createInterpolatedColorTexture,
|
|
17
|
-
createSchemeTexture,
|
|
18
|
-
} from "../scale/colorUtils";
|
|
19
|
-
import {
|
|
20
|
-
getDiscreteRangeMapper,
|
|
21
|
-
isColorChannel,
|
|
22
|
-
isDiscreteChannel,
|
|
23
|
-
} from "../encoder/encoder";
|
|
24
|
-
|
|
25
|
-
export default class WebGLHelper {
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
* @param {HTMLElement} container
|
|
29
|
-
* @param {() => {width: number, height: number}} [sizeSource]
|
|
30
|
-
* A function that returns the content size. If a dimension is undefined,
|
|
31
|
-
* the canvas fills the container, otherwise the canvas is adjusted to the content size.
|
|
32
|
-
*/
|
|
33
|
-
constructor(container, sizeSource) {
|
|
34
|
-
this._container = container;
|
|
35
|
-
this._sizeSource = sizeSource;
|
|
36
|
-
|
|
37
|
-
/** @type {Map<string, WebGLShader>} */
|
|
38
|
-
this._shaderCache = new Map();
|
|
39
|
-
|
|
40
|
-
/** @type {{ type: string, listener: function}[]} */
|
|
41
|
-
this._listeners = [];
|
|
42
|
-
|
|
43
|
-
/** @type {WeakMap<import("../view/scaleResolution").default, WebGLTexture>} */
|
|
44
|
-
this.rangeTextures = new WeakMap();
|
|
45
|
-
|
|
46
|
-
// --------------------------------------------------------
|
|
47
|
-
|
|
48
|
-
const canvas = document.createElement("canvas");
|
|
49
|
-
|
|
50
|
-
container.appendChild(canvas);
|
|
51
|
-
|
|
52
|
-
// TODO: Consider using high-performance powerPreference:
|
|
53
|
-
// https://www.khronos.org/webgl/public-mailing-list/public_webgl/1912/msg00001.php
|
|
54
|
-
|
|
55
|
-
const gl = /** @type {WebGL2RenderingContext} */ (
|
|
56
|
-
getContext(canvas, {
|
|
57
|
-
antialias: true,
|
|
58
|
-
// Disable depth writes. We don't use depth testing.
|
|
59
|
-
depth: false,
|
|
60
|
-
premultipliedAlpha: true,
|
|
61
|
-
})
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
if (!gl) {
|
|
65
|
-
throw new Error(
|
|
66
|
-
"Unable to initialize WebGL. Your browser or machine may not support it."
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (!isWebGL2(gl)) {
|
|
71
|
-
throw new Error(
|
|
72
|
-
"Your web browser does not support WebGL 2.0. Chrome, Firefox, and Safari Tech Preview should work."
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
addExtensionsToContext(gl);
|
|
77
|
-
|
|
78
|
-
// TODO: view background: https://vega.github.io/vega-lite/docs/spec.html#view-background
|
|
79
|
-
|
|
80
|
-
// Always use pre-multiplied alpha
|
|
81
|
-
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
|
82
|
-
|
|
83
|
-
this.canvas = canvas;
|
|
84
|
-
this.gl = gl;
|
|
85
|
-
|
|
86
|
-
// Setup framebuffer for piccking
|
|
87
|
-
/** @type {import("twgl.js").AttachmentOptions[]} */
|
|
88
|
-
this._pickingAttachmentOptions = [
|
|
89
|
-
{
|
|
90
|
-
format: gl.RGBA,
|
|
91
|
-
type: gl.UNSIGNED_BYTE,
|
|
92
|
-
minMag: gl.LINEAR,
|
|
93
|
-
wrap: gl.CLAMP_TO_EDGE,
|
|
94
|
-
},
|
|
95
|
-
];
|
|
96
|
-
this._pickingBufferInfo = createFramebufferInfo(
|
|
97
|
-
gl,
|
|
98
|
-
this._pickingAttachmentOptions
|
|
99
|
-
);
|
|
100
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
101
|
-
|
|
102
|
-
this.adjustGl();
|
|
103
|
-
|
|
104
|
-
// TODO: Size should be observed only if the content is not absolutely sized
|
|
105
|
-
this._resizeObserver = new ResizeObserver((entries) => {
|
|
106
|
-
this.invalidateSize();
|
|
107
|
-
this._emit("resize");
|
|
108
|
-
});
|
|
109
|
-
this._resizeObserver.observe(this._container);
|
|
110
|
-
|
|
111
|
-
// TODO: Observe devicePixelRatio
|
|
112
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#Monitoring_screen_resolution_or_zoom_level_changes
|
|
113
|
-
|
|
114
|
-
this._updateDpr();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
invalidateSize() {
|
|
118
|
-
this._logicalCanvasSize = undefined;
|
|
119
|
-
this._updateDpr();
|
|
120
|
-
this.adjustGl();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
_updateDpr() {
|
|
124
|
-
this.dpr = window.devicePixelRatio;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Compiles and caches a shader. The shader source is used as a cache key.
|
|
129
|
-
*
|
|
130
|
-
* @param {number} type gl.VERTEX_SHADER or gl.FRAGMENT_SHADER
|
|
131
|
-
* @param {string | string[]} glsl
|
|
132
|
-
*/
|
|
133
|
-
compileShader(type, glsl) {
|
|
134
|
-
const VERSION = "#version 300 es";
|
|
135
|
-
const PRECISION = "precision mediump float;";
|
|
136
|
-
|
|
137
|
-
if (isArray(glsl)) {
|
|
138
|
-
glsl = glsl.join("\n\n");
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const gl = this.gl;
|
|
142
|
-
const cacheKey = glsl.replaceAll(/ {2,}|^\s*\/\/.*$/gm, "");
|
|
143
|
-
|
|
144
|
-
let shader = this._shaderCache.get(cacheKey);
|
|
145
|
-
if (!shader) {
|
|
146
|
-
const stitchedSource = [VERSION, PRECISION, glsl].join("\n\n");
|
|
147
|
-
|
|
148
|
-
shader = gl.createShader(type);
|
|
149
|
-
gl.shaderSource(shader, stitchedSource);
|
|
150
|
-
gl.compileShader(shader);
|
|
151
|
-
|
|
152
|
-
// Don't check errors here. Only check them if linking fails.
|
|
153
|
-
|
|
154
|
-
this._shaderCache.set(cacheKey, shader);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return shader;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
adjustGl() {
|
|
161
|
-
const logicalSize = this.getLogicalCanvasSize();
|
|
162
|
-
this.canvas.style.width = `${logicalSize.width}px`;
|
|
163
|
-
this.canvas.style.height = `${logicalSize.height}px`;
|
|
164
|
-
|
|
165
|
-
const physicalSize = this.getPhysicalCanvasSize(logicalSize);
|
|
166
|
-
this.canvas.width = physicalSize.width;
|
|
167
|
-
this.canvas.height = physicalSize.height;
|
|
168
|
-
|
|
169
|
-
resizeFramebufferInfo(
|
|
170
|
-
this.gl,
|
|
171
|
-
this._pickingBufferInfo,
|
|
172
|
-
this._pickingAttachmentOptions
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
finalize() {
|
|
177
|
-
this._resizeObserver.unobserve(this._container);
|
|
178
|
-
this.canvas.remove();
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Returns the canvas size in true display pixels
|
|
183
|
-
*
|
|
184
|
-
* @param {{ width: number, height: number }} [logicalSize]
|
|
185
|
-
*/
|
|
186
|
-
getPhysicalCanvasSize(logicalSize) {
|
|
187
|
-
logicalSize = logicalSize || this.getLogicalCanvasSize();
|
|
188
|
-
return {
|
|
189
|
-
width: logicalSize.width * this.dpr,
|
|
190
|
-
height: logicalSize.height * this.dpr,
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Returns the canvas size in logical pixels (without devicePixelRatio correction)
|
|
196
|
-
*/
|
|
197
|
-
getLogicalCanvasSize() {
|
|
198
|
-
if (this._logicalCanvasSize) {
|
|
199
|
-
return this._logicalCanvasSize;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// TODO: The size should never be smaller than the minimum content size!
|
|
203
|
-
const contentSize = this._sizeSource?.() ?? {
|
|
204
|
-
width: undefined,
|
|
205
|
-
height: undefined,
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
const cs = window.getComputedStyle(this._container, null);
|
|
209
|
-
const width =
|
|
210
|
-
contentSize.width ??
|
|
211
|
-
this._container.clientWidth -
|
|
212
|
-
parseFloat(cs.paddingLeft) -
|
|
213
|
-
parseFloat(cs.paddingRight);
|
|
214
|
-
|
|
215
|
-
const height =
|
|
216
|
-
contentSize.height ??
|
|
217
|
-
this._container.clientHeight -
|
|
218
|
-
parseFloat(cs.paddingTop) -
|
|
219
|
-
parseFloat(cs.paddingBottom);
|
|
220
|
-
|
|
221
|
-
this._logicalCanvasSize = { width, height };
|
|
222
|
-
return this._logicalCanvasSize;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* @param {"render"|"resize"} eventType
|
|
227
|
-
* @param {function} listener
|
|
228
|
-
*/
|
|
229
|
-
addEventListener(eventType, listener) {
|
|
230
|
-
this._listeners.push({ type: eventType, listener });
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* @param {string} eventType
|
|
235
|
-
*/
|
|
236
|
-
_emit(eventType) {
|
|
237
|
-
for (const entry of this._listeners) {
|
|
238
|
-
if (entry.type === eventType) {
|
|
239
|
-
entry.listener();
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
*
|
|
246
|
-
* @param {number} x
|
|
247
|
-
* @param {number} y
|
|
248
|
-
*/
|
|
249
|
-
readPickingPixel(x, y) {
|
|
250
|
-
const gl = this.gl;
|
|
251
|
-
|
|
252
|
-
x *= this.dpr;
|
|
253
|
-
y *= this.dpr;
|
|
254
|
-
|
|
255
|
-
const height = this.getPhysicalCanvasSize().height;
|
|
256
|
-
|
|
257
|
-
const pixel = new Uint8Array(4);
|
|
258
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, this._pickingBufferInfo.framebuffer);
|
|
259
|
-
gl.readPixels(
|
|
260
|
-
x,
|
|
261
|
-
height - y - 1,
|
|
262
|
-
1,
|
|
263
|
-
1,
|
|
264
|
-
gl.RGBA,
|
|
265
|
-
gl.UNSIGNED_BYTE,
|
|
266
|
-
pixel
|
|
267
|
-
);
|
|
268
|
-
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
269
|
-
|
|
270
|
-
return pixel;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
clearAll() {
|
|
274
|
-
const gl = this.gl;
|
|
275
|
-
const { width, height } = this.getPhysicalCanvasSize();
|
|
276
|
-
gl.viewport(0, 0, width, height);
|
|
277
|
-
gl.disable(gl.SCISSOR_TEST);
|
|
278
|
-
gl.clearColor(0, 0, 0, 0);
|
|
279
|
-
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Creates textures for color schemes and discrete/discretizing ranges.
|
|
284
|
-
* N.B. Discrete range textures need domain. Thus, this cannot be called
|
|
285
|
-
* before the final domains are resolved.
|
|
286
|
-
*
|
|
287
|
-
* TODO: This may be too specific to be included in WebGLHelper. Find a better place.
|
|
288
|
-
*
|
|
289
|
-
* @param {import("../view/scaleResolution").default} resolution
|
|
290
|
-
* @param {boolean} update Update the texture if it exists already.
|
|
291
|
-
*/
|
|
292
|
-
createRangeTexture(resolution, update = false) {
|
|
293
|
-
const existingTexture = this.rangeTextures.get(resolution);
|
|
294
|
-
if (!update && existingTexture) {
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* TODO: The count configuration logic etc should be combined
|
|
300
|
-
* with scale.js that configures d3 scales using vega specs
|
|
301
|
-
* @param {number} count
|
|
302
|
-
* @param {any} scale
|
|
303
|
-
* @returns {number}
|
|
304
|
-
*/
|
|
305
|
-
function fixCount(count, scale) {
|
|
306
|
-
if (isDiscrete(scale.type)) {
|
|
307
|
-
return scale.domain().length;
|
|
308
|
-
} else if (scale.type == "threshold") {
|
|
309
|
-
return scale.domain().length + 1;
|
|
310
|
-
} else if (scale.type == "quantize") {
|
|
311
|
-
return count ?? 4;
|
|
312
|
-
} else if (scale.type == "quantile") {
|
|
313
|
-
return count ?? 4;
|
|
314
|
-
}
|
|
315
|
-
return count;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const channel = resolution.channel;
|
|
319
|
-
|
|
320
|
-
if (isColorChannel(channel)) {
|
|
321
|
-
const props = resolution.getScaleProps();
|
|
322
|
-
|
|
323
|
-
const scale = resolution.getScale();
|
|
324
|
-
|
|
325
|
-
/** @type {WebGLTexture} */
|
|
326
|
-
let texture;
|
|
327
|
-
|
|
328
|
-
if (props.scheme) {
|
|
329
|
-
let count = isString(props.scheme)
|
|
330
|
-
? undefined
|
|
331
|
-
: props.scheme.count;
|
|
332
|
-
|
|
333
|
-
count = fixCount(count, scale);
|
|
334
|
-
|
|
335
|
-
texture = createSchemeTexture(
|
|
336
|
-
props.scheme,
|
|
337
|
-
this.gl,
|
|
338
|
-
count,
|
|
339
|
-
existingTexture
|
|
340
|
-
);
|
|
341
|
-
} else {
|
|
342
|
-
// No scheme, assume that colors are specified in the range
|
|
343
|
-
|
|
344
|
-
const range = /** @type {any[]} */ (scale.range());
|
|
345
|
-
|
|
346
|
-
if (isInterpolating(scale.type)) {
|
|
347
|
-
texture = createInterpolatedColorTexture(
|
|
348
|
-
range,
|
|
349
|
-
props.interpolate,
|
|
350
|
-
this.gl,
|
|
351
|
-
existingTexture
|
|
352
|
-
);
|
|
353
|
-
} else {
|
|
354
|
-
texture = createDiscreteColorTexture(
|
|
355
|
-
range,
|
|
356
|
-
this.gl,
|
|
357
|
-
scale.domain().length,
|
|
358
|
-
existingTexture
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
this.rangeTextures.set(resolution, texture);
|
|
364
|
-
} else {
|
|
365
|
-
const scale = resolution.getScale();
|
|
366
|
-
|
|
367
|
-
if (scale.type === "ordinal" || isDiscretizing(scale.type)) {
|
|
368
|
-
/** @type {function(any):number} Handle "shape" etc */
|
|
369
|
-
const mapper = isDiscreteChannel(channel)
|
|
370
|
-
? getDiscreteRangeMapper(channel)
|
|
371
|
-
: (x) => x;
|
|
372
|
-
|
|
373
|
-
const range = /** @type {any[]} */ (
|
|
374
|
-
resolution.getScale().range()
|
|
375
|
-
);
|
|
376
|
-
|
|
377
|
-
this.rangeTextures.set(
|
|
378
|
-
resolution,
|
|
379
|
-
createDiscreteTexture(
|
|
380
|
-
range.map(mapper),
|
|
381
|
-
this.gl,
|
|
382
|
-
scale.domain().length,
|
|
383
|
-
existingTexture
|
|
384
|
-
)
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Copy-pasted from twgl.js:
|
|
393
|
-
* https://github.com/greggman/twgl.js/blob/master/src/programs.js
|
|
394
|
-
* Copyright 2019 Gregg Tavares, MIT license
|
|
395
|
-
*
|
|
396
|
-
* @param {string} src
|
|
397
|
-
*/
|
|
398
|
-
function addLineNumbersWithError(src, log = "", lineOffset = 0) {
|
|
399
|
-
const errorRE = /ERROR:\s*\d+:(\d+)/gi;
|
|
400
|
-
// Note: Error message formats are not defined by any spec so this may or may not work.
|
|
401
|
-
const matches = [...log.matchAll(errorRE)];
|
|
402
|
-
const lineNoToErrorMap = new Map(
|
|
403
|
-
matches.map((m, ndx) => {
|
|
404
|
-
const lineNo = parseInt(m[1]);
|
|
405
|
-
const next = matches[ndx + 1];
|
|
406
|
-
const end = next ? next.index : log.length;
|
|
407
|
-
const msg = log.substring(m.index, end);
|
|
408
|
-
return [lineNo - 1, msg];
|
|
409
|
-
})
|
|
410
|
-
);
|
|
411
|
-
return src
|
|
412
|
-
.split("\n")
|
|
413
|
-
.map((line, lineNo) => {
|
|
414
|
-
const err = lineNoToErrorMap.get(lineNo);
|
|
415
|
-
return `${lineNo + 1 + lineOffset}: ${line}${
|
|
416
|
-
err ? `\n\n^^^ ${err}` : ""
|
|
417
|
-
}`;
|
|
418
|
-
})
|
|
419
|
-
.join("\n");
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* @param {WebGL2RenderingContext} gl
|
|
424
|
-
* @param {WebGLShader} vertexShader
|
|
425
|
-
* @param {WebGLShader} fragmentShader
|
|
426
|
-
*/
|
|
427
|
-
export function createProgram(gl, vertexShader, fragmentShader) {
|
|
428
|
-
const program = gl.createProgram();
|
|
429
|
-
gl.attachShader(program, vertexShader);
|
|
430
|
-
gl.attachShader(program, fragmentShader);
|
|
431
|
-
gl.linkProgram(program);
|
|
432
|
-
|
|
433
|
-
function getProgramErrors() {
|
|
434
|
-
/** @type {string} */
|
|
435
|
-
let errorMsg;
|
|
436
|
-
/** @type {string} */
|
|
437
|
-
let errorDetail;
|
|
438
|
-
|
|
439
|
-
const linked = gl.getProgramParameter(program, gl.LINK_STATUS);
|
|
440
|
-
if (!linked) {
|
|
441
|
-
errorMsg = gl.getProgramInfoLog(program);
|
|
442
|
-
|
|
443
|
-
for (const shader of [vertexShader, fragmentShader]) {
|
|
444
|
-
const compiled = gl.getShaderParameter(
|
|
445
|
-
shader,
|
|
446
|
-
gl.COMPILE_STATUS
|
|
447
|
-
);
|
|
448
|
-
if (!compiled) {
|
|
449
|
-
errorMsg = gl.getShaderInfoLog(shader);
|
|
450
|
-
errorDetail =
|
|
451
|
-
addLineNumbersWithError(
|
|
452
|
-
gl.getShaderSource(shader),
|
|
453
|
-
errorMsg,
|
|
454
|
-
0
|
|
455
|
-
) + `\nError compiling: ${errorMsg}`;
|
|
456
|
-
gl.deleteShader(shader);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
gl.deleteProgram(program);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
if (errorMsg) {
|
|
463
|
-
return { message: errorMsg, detail: errorDetail };
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
return {
|
|
468
|
-
program,
|
|
469
|
-
getProgramErrors,
|
|
470
|
-
};
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* @param {WebGLRenderingContext} gl
|
|
475
|
-
* @param {Omit<import("twgl.js").TextureOptions, "src">} options
|
|
476
|
-
* @param {number[] | ArrayBufferView} src
|
|
477
|
-
* @param {WebGLTexture} [texture]
|
|
478
|
-
*/
|
|
479
|
-
export function createOrUpdateTexture(gl, options, src, texture) {
|
|
480
|
-
if (texture) {
|
|
481
|
-
setTextureFromArray(gl, texture, src, options);
|
|
482
|
-
} else {
|
|
483
|
-
texture = createTexture(gl, {
|
|
484
|
-
...options,
|
|
485
|
-
src,
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
return texture;
|
|
489
|
-
}
|
package/src/img/bowtie.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5"><path d="M4.7 21.2s.4 2.3 1.3 3.6C7 26 9.8 28 9.8 28s3.4-2.6 6.4-8.5c0 0 1 .1 1.9-.4.9-.6.8-.4 1-1.2 0 0 2.9.5 6.6 0 2.1-.3 4.3-1 6.2-2.5 0 0-1.1-1.7-2.5-5.1-.5-1.3-2-1.8-4.6-4.6l-8.2 8.6-11.9 6.9z" fill-opacity=".1"/><path d="M12.7 14.8s-4-1.8-12 2.7c0 0 1 3.7 2.5 5.3 1.4 1.5 2.3 3.6 4.6 4.6 0 0 4.7-3 6.9-9.2l3-2s4.7 2.8 12.6-1.6c0 0-.6-3.3-3-6-2.6-3-3.8-4.7-3.8-4.7s-4.1 2.3-7.5 9.3l-3.3 1.6z" fill="#7fbbdd"/><path d="M12.4 15.5c-.7-.5-2.4-.8-4.4-.4-2 .4-4 1.3-4.8 1.8-.5.3-1.2 1-1.2 1.4 0 .7.3 1.8.8 2.4.3.3.7.5 1.4.6.8 0 2.5-1.4 3.5-2 1-.6 1.6-.8 2.7-1.2l-2.9 2.4c-1.3 1.2-2.2 1.5-2.4 2.3 0 .5 0 1.4.5 1.8.4.5.6.8 1.6.8.6 0 1 0 2.6-1.5.9-.9 2.3-3 2.7-3.7.6-1.1 1-2.2.7-3-.2-1-.4-1.4-.8-1.7zM17.4 14.2c-.3-.5-.9-1.2-.2-2.5l1.9-3c.5-.8 2-2.3 2.6-2.6.6-.4 1.5-.6 2-.2.6.4 1 1 1.3 1.5.4.6.7 1.3.2 2-.7 1-1.6.9-2.8 1.7-1.2.8-1.9 1.2-2.5 1.9l3.8-1.8c1.3-.6 2.7-1.1 3.4-.7.8.5.8.7 1 1.4.3 1-.2 1.9-.8 2.4-.5.6-1.5.9-2.6 1.2-1.4.4-4.5 1-5.8.5-1.3-.5-1.3-1.4-1.5-1.8z" fill="#fff"/><path d="M12.7 14.8s-4-1.8-12 2.7c0 0 1 3.7 2.5 5.3 1.4 1.5 2.3 3.6 4.6 4.6 0 0 4.7-3 6.9-9.2l3-2s4.7 2.8 12.6-1.6c0 0-.6-3.3-3-6-2.6-3-3.8-4.7-3.8-4.7s-4.1 2.3-7.5 9.3l-3.3 1.6z" fill="none" stroke="#000" stroke-width=".5"/><path d="M12.4 14.9s2.1-2 3-2c1.1 0 2.3 2.7 2.3 3.5 0 .8-2.1 2.4-3.1 2.3 0 0 0-1.2-.7-2.6-.8-1.3-1.5-1.2-1.5-1.2z" fill="#7fbbdd"/><path d="M13.8 15.3c.9.8.6 2 1.4 1.8 1-.2 1.4-.8 1.3-1.5 0-.7 0-.8-.4-1.6-.3-.7-1-1.1-2-.5-.7.5-1.4 1.3-1.4 1.3s.2-.3 1.1.5z" fill="#fff"/><path d="M12.4 14.9s2.1-2 3-2c1.1 0 2.3 2.7 2.3 3.5 0 .8-2.1 2.4-3.1 2.3 0 0 0-1.2-.7-2.6-.8-1.3-1.5-1.2-1.5-1.2z" fill="none" stroke="#000" stroke-width=".5"/></svg>
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
-
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
3
|
-
<svg width="100%" height="100%" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
|
4
|
-
<g transform="matrix(0.10221,0.00683825,-0.0067136,0.100347,-8.03424,-13.2222)">
|
|
5
|
-
<path d="M208.629,548.17C208.629,548.17 219.768,594.389 239.814,619.222C259.86,644.055 319.119,680.831 319.119,680.831C319.119,680.831 385.557,622.915 437.87,498.346C437.87,498.346 456.021,499.236 473.808,486.446C491.594,473.656 490.239,478.534 494.883,461.62C494.883,461.62 551.848,467.937 625.826,451.863C667.634,442.778 710.238,425.649 747.382,393.142C747.382,393.142 721.992,360.244 689.422,291.45C677.029,265.275 647.518,257.098 590.747,203.309L438.083,391.273L208.629,548.17Z" style="fill-opacity:0.11;"/>
|
|
6
|
-
</g>
|
|
7
|
-
<g transform="matrix(0.081985,-0.0582493,0.0582493,0.081985,-40.4754,34.7668)">
|
|
8
|
-
<path d="M561.588,349.155C561.588,349.155 516.297,271.341 328.841,252.044C328.841,252.044 302.342,325.189 307.686,368.056C313.031,410.922 303.001,456.147 329.132,501.174C329.132,501.174 443.114,506.743 554.649,428.469L629.204,432.112C629.204,432.112 673.755,534.351 856.964,554.375C856.964,554.375 886.717,491.768 879.193,417.478C871.211,338.673 871.716,293.443 871.716,293.443C871.716,293.443 775.485,283.928 635.418,361.795L561.588,349.155Z" style="fill:rgb(127,187,221);"/>
|
|
9
|
-
<clipPath id="_clip1">
|
|
10
|
-
<path d="M561.588,349.155C561.588,349.155 516.297,271.341 328.841,252.044C328.841,252.044 302.342,325.189 307.686,368.056C313.031,410.922 303.001,456.147 329.132,501.174C329.132,501.174 443.114,506.743 554.649,428.469L629.204,432.112C629.204,432.112 673.755,534.351 856.964,554.375C856.964,554.375 886.717,491.768 879.193,417.478C871.211,338.673 871.716,293.443 871.716,293.443C871.716,293.443 775.485,283.928 635.418,361.795L561.588,349.155Z"/>
|
|
11
|
-
</clipPath>
|
|
12
|
-
<g clip-path="url(#_clip1)">
|
|
13
|
-
<g transform="matrix(0.758637,0.45892,-0.45892,0.758637,425.635,-121.213)">
|
|
14
|
-
<path d="M386.873,397.241C371.345,383.628 335.138,374.782 290.644,380.543C246.149,386.304 196.827,402.266 178.802,412.065C168.202,417.828 151.494,429.354 150.682,439.334C149.527,453.528 153.593,477.066 165.625,491.284C171.69,498.451 179.927,503.445 193.838,505.423C211.701,507.963 252.714,480.627 275.399,469.22C299.332,457.187 313.981,454.56 338.386,447.014C338.386,447.014 291.346,478.587 270.205,494.393C239.61,517.268 218.575,522.444 212.859,539.897C209.766,549.34 212.237,567.767 220.354,577.538C229.427,588.461 233.197,595.069 254.591,597.624C267.303,599.143 276.685,598.802 314.37,568.95C336.06,551.767 370.297,509.817 381.412,494.616C397.581,472.506 405.165,451.462 402.656,435.04C399.045,411.391 394.259,403.716 386.873,397.241Z" style="fill:white;"/>
|
|
15
|
-
</g>
|
|
16
|
-
<g transform="matrix(0.752145,0.454993,-0.454993,0.752145,468.36,-108.293)">
|
|
17
|
-
<path d="M484.733,378.934C479.33,367.886 467.092,350.452 483.886,325.205C502.172,297.717 514.898,280.938 528.117,264.632C541.335,248.326 574.793,218.447 587.739,212.53C600.684,206.613 621.026,203.852 631.889,212.841C642.874,221.93 648.416,233.377 654.92,245.478C662.331,259.267 667.318,274.808 656.518,288.278C641.093,307.515 622.242,305.294 594.912,319.844C567.244,334.573 552.644,342.943 539.244,355.703C539.244,355.703 591.431,334.114 621.229,324.474C651.027,314.833 680.952,304.461 695.995,315.975C711.038,327.49 710.631,331.463 714.425,347.187C719.107,366.59 707.231,385.165 694.294,395.838C681.356,406.51 659.958,411.756 636.875,416.852C606.42,423.576 540.278,431.917 512.819,419.366C485.361,406.815 488.488,386.613 484.733,378.934Z" style="fill:white;"/>
|
|
18
|
-
</g>
|
|
19
|
-
</g>
|
|
20
|
-
<path d="M561.588,349.155C561.588,349.155 516.297,271.341 328.841,252.044C328.841,252.044 302.342,325.189 307.686,368.056C313.031,410.922 303.001,456.147 329.132,501.174C329.132,501.174 443.114,506.743 554.649,428.469L629.204,432.112C629.204,432.112 673.755,534.351 856.964,554.375C856.964,554.375 886.717,491.768 879.193,417.478C871.211,338.673 871.716,293.443 871.716,293.443C871.716,293.443 775.485,283.928 635.418,361.795L561.588,349.155Z" style="fill:none;stroke:black;stroke-width:16.57px;"/>
|
|
21
|
-
</g>
|
|
22
|
-
<g transform="matrix(0.100298,-0.00740488,0.00740488,0.100298,-15.7457,-5.17528)">
|
|
23
|
-
<path d="M384.916,385.459C384.916,385.459 430.781,347.868 450.027,350.093C471.685,352.596 490.49,407.747 490.208,424.416C489.927,441.085 442.948,469.866 422.537,466.24C422.537,466.24 425.525,442.129 412.114,413.335C398.702,384.54 384.916,385.459 384.916,385.459Z" style="fill:rgb(127,187,221);"/>
|
|
24
|
-
<clipPath id="_clip2">
|
|
25
|
-
<path d="M384.916,385.459C384.916,385.459 430.781,347.868 450.027,350.093C471.685,352.596 490.49,407.747 490.208,424.416C489.927,441.085 442.948,469.866 422.537,466.24C422.537,466.24 425.525,442.129 412.114,413.335C398.702,384.54 384.916,385.459 384.916,385.459Z"/>
|
|
26
|
-
</clipPath>
|
|
27
|
-
<g clip-path="url(#_clip2)">
|
|
28
|
-
<g transform="matrix(0.909069,3.67641e-17,-3.79818e-17,0.85852,37.051,52.1829)">
|
|
29
|
-
<path d="M413.282,402.697C430.77,421.58 423.307,448.426 441.683,446.137C463.409,443.431 472.604,430.356 473.316,413.402C474.028,396.448 472.245,393.911 466.172,375.321C460.099,356.731 447.953,352.176 422.842,357.179C401.957,361.339 405.039,360.215 398.735,367.228C392.43,374.242 384.315,393.182 384.315,393.182C384.315,393.182 392.715,380.492 413.282,402.697Z" style="fill:white;"/>
|
|
30
|
-
</g>
|
|
31
|
-
</g>
|
|
32
|
-
<path d="M384.916,385.459C384.916,385.459 430.781,347.868 450.027,350.093C471.685,352.596 490.49,407.747 490.208,424.416C489.927,441.085 442.948,469.866 422.537,466.24C422.537,466.24 425.525,442.129 412.114,413.335C398.702,384.54 384.916,385.459 384.916,385.459Z" style="fill:none;stroke:black;stroke-width:16.57px;"/>
|
|
33
|
-
</g>
|
|
34
|
-
</svg>
|
package/src/index.html
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>GenomeSpy</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<script type="module" src="/singlePageApp.js"></script>
|
|
10
|
-
</body>
|
|
11
|
-
</html>
|
package/src/index.js
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { isObject, isString } from "vega-util";
|
|
2
|
-
import { loader as vegaLoader } from "vega-loader";
|
|
3
|
-
import { html } from "lit-html";
|
|
4
|
-
|
|
5
|
-
import GenomeSpy from "./genomeSpy.js";
|
|
6
|
-
import icon from "./img/bowtie.svg";
|
|
7
|
-
|
|
8
|
-
export { GenomeSpy, html, icon };
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Embeds GenomeSpy into the DOM
|
|
12
|
-
*
|
|
13
|
-
* @type {import("./embedApi.js").EmbedFunction}
|
|
14
|
-
* @returns {Promise<import("./embedApi").EmbedResult>}
|
|
15
|
-
*/
|
|
16
|
-
export async function embed(el, spec, options = {}) {
|
|
17
|
-
/** @type {HTMLElement} */
|
|
18
|
-
let element;
|
|
19
|
-
|
|
20
|
-
if (isString(el)) {
|
|
21
|
-
element = document.querySelector(el);
|
|
22
|
-
if (!element) {
|
|
23
|
-
throw new Error(`No such element: ${el}`);
|
|
24
|
-
}
|
|
25
|
-
} else if (el instanceof HTMLElement) {
|
|
26
|
-
element = el;
|
|
27
|
-
} else {
|
|
28
|
-
throw new Error(`Invalid element: ${el}`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** @type {GenomeSpy} */
|
|
32
|
-
let genomeSpy;
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
const specObject = isObject(spec) ? spec : await loadSpec(spec);
|
|
36
|
-
|
|
37
|
-
specObject.baseUrl ??= "";
|
|
38
|
-
specObject.width ??= "container";
|
|
39
|
-
specObject.padding ??= 10;
|
|
40
|
-
|
|
41
|
-
if (element == document.body) {
|
|
42
|
-
// Need to add a wrapper to make sizing behavior more stable
|
|
43
|
-
const wrapper = document.createElement("div");
|
|
44
|
-
wrapper.style.position = "fixed";
|
|
45
|
-
wrapper.style.inset = "0";
|
|
46
|
-
wrapper.style.overflow = "hidden";
|
|
47
|
-
element.appendChild(wrapper);
|
|
48
|
-
element = wrapper;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
genomeSpy = new GenomeSpy(element, specObject, options);
|
|
52
|
-
applyOptions(genomeSpy, options);
|
|
53
|
-
await genomeSpy.launch();
|
|
54
|
-
} catch (e) {
|
|
55
|
-
// eslint-disable-next-line require-atomic-updates
|
|
56
|
-
element.innerText = e.toString();
|
|
57
|
-
console.error(e);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
finalize() {
|
|
62
|
-
genomeSpy.destroy();
|
|
63
|
-
while (element.firstChild) {
|
|
64
|
-
element.firstChild.remove();
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
addEventListener(type, listener) {
|
|
69
|
-
const listenersByType = genomeSpy._eventListeners;
|
|
70
|
-
|
|
71
|
-
let listeners = listenersByType.get(type);
|
|
72
|
-
if (!listeners) {
|
|
73
|
-
listeners = new Set();
|
|
74
|
-
listenersByType.set(type, listeners);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
listeners.add(listener);
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
-
removeEventListener(type, listener) {
|
|
81
|
-
const listenersByType = genomeSpy._eventListeners;
|
|
82
|
-
|
|
83
|
-
listenersByType.get(type)?.delete(listener);
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
getScaleResolutionByName(name) {
|
|
87
|
-
return genomeSpy.getNamedScaleResolutions().get(name);
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
updateNamedData: genomeSpy.updateNamedData.bind(genomeSpy),
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
*
|
|
96
|
-
* @param {import("./genomeSpy").default} genomeSpy
|
|
97
|
-
* @param {import("./embedApi.js").EmbedOptions} options options
|
|
98
|
-
*/
|
|
99
|
-
function applyOptions(genomeSpy, options) {
|
|
100
|
-
if (options.namedDataProvider) {
|
|
101
|
-
genomeSpy.registerNamedDataProvider(options.namedDataProvider);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Loads the spec from the given url and sets the baseUrl if it is not
|
|
107
|
-
* defined in the spec.
|
|
108
|
-
*
|
|
109
|
-
* @param {string} url
|
|
110
|
-
*/
|
|
111
|
-
export async function loadSpec(url) {
|
|
112
|
-
let spec;
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
spec = JSON.parse(await vegaLoader().load(url));
|
|
116
|
-
} catch (e) {
|
|
117
|
-
throw new Error(
|
|
118
|
-
`Could not load or parse configuration: ${url}, reason: ${e.message}`
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (!spec.baseUrl) {
|
|
123
|
-
const m = url.match(/^[^?#]*\//);
|
|
124
|
-
spec.baseUrl = (m && m[0]) || "./";
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return spec;
|
|
128
|
-
}
|