@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.
Files changed (121) hide show
  1. package/LICENSE +1 -1
  2. package/dist/bundle/index.es.js +6842 -5365
  3. package/dist/bundle/index.js +159 -140
  4. package/dist/bundle/parquetRead-BnAGCa4_.js +1663 -0
  5. package/dist/schema.json +281 -17
  6. package/dist/src/data/formats/bed.d.ts +8 -0
  7. package/dist/src/data/formats/bed.d.ts.map +1 -0
  8. package/dist/src/data/formats/bed.js +53 -0
  9. package/dist/src/data/formats/bedpe.d.ts +8 -0
  10. package/dist/src/data/formats/bedpe.d.ts.map +1 -0
  11. package/dist/src/data/formats/bedpe.js +160 -0
  12. package/dist/src/data/formats/parquet.d.ts +12 -0
  13. package/dist/src/data/formats/parquet.d.ts.map +1 -0
  14. package/dist/src/data/formats/parquet.js +29 -0
  15. package/dist/src/data/formats/parquetRead.d.ts +18 -0
  16. package/dist/src/data/formats/parquetRead.d.ts.map +1 -0
  17. package/dist/src/data/formats/parquetRead.js +326 -0
  18. package/dist/src/data/sources/dataUtils.d.ts +16 -0
  19. package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
  20. package/dist/src/data/sources/dataUtils.js +53 -3
  21. package/dist/src/data/sources/urlSource.d.ts +4 -0
  22. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  23. package/dist/src/data/sources/urlSource.js +141 -17
  24. package/dist/src/encoder/encoder.d.ts +2 -2
  25. package/dist/src/fonts/bmFontManager.d.ts +1 -1
  26. package/dist/src/genome/assemblyPreflight.d.ts +31 -0
  27. package/dist/src/genome/assemblyPreflight.d.ts.map +1 -0
  28. package/dist/src/genome/assemblyPreflight.js +99 -0
  29. package/dist/src/genome/genome.d.ts +2 -2
  30. package/dist/src/genome/genome.d.ts.map +1 -1
  31. package/dist/src/genome/genome.js +4 -0
  32. package/dist/src/genome/genomeStore.d.ts +34 -3
  33. package/dist/src/genome/genomeStore.d.ts.map +1 -1
  34. package/dist/src/genome/genomeStore.js +409 -18
  35. package/dist/src/genome/rootGenomeConfig.d.ts +26 -0
  36. package/dist/src/genome/rootGenomeConfig.d.ts.map +1 -0
  37. package/dist/src/genome/rootGenomeConfig.js +94 -0
  38. package/dist/src/genomeSpy/interactionController.d.ts +5 -1
  39. package/dist/src/genomeSpy/interactionController.d.ts.map +1 -1
  40. package/dist/src/genomeSpy/interactionController.js +244 -29
  41. package/dist/src/genomeSpy/renderCoordinator.js +1 -1
  42. package/dist/src/genomeSpy.d.ts +13 -3
  43. package/dist/src/genomeSpy.d.ts.map +1 -1
  44. package/dist/src/genomeSpy.js +83 -7
  45. package/dist/src/gl/canvasSizeHelper.d.ts +74 -0
  46. package/dist/src/gl/canvasSizeHelper.d.ts.map +1 -0
  47. package/dist/src/gl/canvasSizeHelper.js +203 -0
  48. package/dist/src/gl/hashTable.d.ts +78 -0
  49. package/dist/src/gl/hashTable.d.ts.map +1 -0
  50. package/dist/src/gl/hashTable.js +164 -0
  51. package/dist/src/gl/includes/common.glsl.js +1 -1
  52. package/dist/src/gl/webGLHelper.d.ts +25 -11
  53. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  54. package/dist/src/gl/webGLHelper.js +71 -39
  55. package/dist/src/index.d.ts.map +1 -1
  56. package/dist/src/index.js +5 -2
  57. package/dist/src/marks/link.d.ts.map +1 -1
  58. package/dist/src/marks/link.js +5 -3
  59. package/dist/src/marks/mark.d.ts +1 -1
  60. package/dist/src/marks/mark.d.ts.map +1 -1
  61. package/dist/src/marks/mark.js +8 -4
  62. package/dist/src/scales/domainPlanner.d.ts +34 -3
  63. package/dist/src/scales/domainPlanner.d.ts.map +1 -1
  64. package/dist/src/scales/domainPlanner.js +247 -26
  65. package/dist/src/scales/scaleInstanceManager.d.ts +2 -1
  66. package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
  67. package/dist/src/scales/scaleInstanceManager.js +10 -11
  68. package/dist/src/scales/scaleInteractionController.d.ts.map +1 -1
  69. package/dist/src/scales/scaleInteractionController.js +16 -14
  70. package/dist/src/scales/scaleResolution.d.ts +16 -0
  71. package/dist/src/scales/scaleResolution.d.ts.map +1 -1
  72. package/dist/src/scales/scaleResolution.js +314 -54
  73. package/dist/src/scales/scaleResolutionTestUtils.d.ts +21 -0
  74. package/dist/src/scales/scaleResolutionTestUtils.d.ts.map +1 -0
  75. package/dist/src/scales/scaleResolutionTestUtils.js +33 -0
  76. package/dist/src/scales/selectionDomainUtils.d.ts +22 -0
  77. package/dist/src/scales/selectionDomainUtils.d.ts.map +1 -0
  78. package/dist/src/scales/selectionDomainUtils.js +79 -0
  79. package/dist/src/scales/zoomDomainUtils.d.ts +18 -0
  80. package/dist/src/scales/zoomDomainUtils.d.ts.map +1 -0
  81. package/dist/src/scales/zoomDomainUtils.js +69 -0
  82. package/dist/src/screenshotHarness.d.ts +16 -0
  83. package/dist/src/screenshotHarness.d.ts.map +1 -0
  84. package/dist/src/screenshotHarness.js +242 -0
  85. package/dist/src/singlePageApp.js +1 -1
  86. package/dist/src/spec/data.d.ts +23 -3
  87. package/dist/src/spec/genome.d.ts +22 -2
  88. package/dist/src/spec/parameter.d.ts +39 -2
  89. package/dist/src/spec/root.d.ts +20 -1
  90. package/dist/src/spec/scale.d.ts +41 -5
  91. package/dist/src/styles/genome-spy.css +8 -0
  92. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  93. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  94. package/dist/src/styles/genome-spy.css.js +8 -0
  95. package/dist/src/tooltip/dataTooltipHandler.js +59 -10
  96. package/dist/src/types/embedApi.d.ts +19 -0
  97. package/dist/src/utils/inferSpecBaseUrl.d.ts +14 -0
  98. package/dist/src/utils/inferSpecBaseUrl.d.ts.map +1 -0
  99. package/dist/src/utils/inferSpecBaseUrl.js +73 -0
  100. package/dist/src/utils/interactionEvent.d.ts +53 -3
  101. package/dist/src/utils/interactionEvent.d.ts.map +1 -1
  102. package/dist/src/utils/interactionEvent.js +62 -1
  103. package/dist/src/utils/radixSort.d.ts.map +1 -1
  104. package/dist/src/utils/radixSort.js +26 -1
  105. package/dist/src/view/containerMutationHelper.d.ts.map +1 -1
  106. package/dist/src/view/containerMutationHelper.js +8 -0
  107. package/dist/src/view/dataReadiness.d.ts +2 -2
  108. package/dist/src/view/dataReadiness.d.ts.map +1 -1
  109. package/dist/src/view/dataReadiness.js +63 -58
  110. package/dist/src/view/facetView.d.ts +1 -1
  111. package/dist/src/view/facetView.js +1 -1
  112. package/dist/src/view/gridView/gridChild.d.ts +7 -0
  113. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  114. package/dist/src/view/gridView/gridChild.js +180 -11
  115. package/dist/src/view/gridView/gridView.d.ts.map +1 -1
  116. package/dist/src/view/gridView/gridView.js +60 -17
  117. package/dist/src/view/unitView.d.ts +1 -1
  118. package/dist/src/view/zoom.d.ts +14 -2
  119. package/dist/src/view/zoom.d.ts.map +1 -1
  120. package/dist/src/view/zoom.js +373 -76
  121. package/package.json +5 -2
@@ -1 +1 @@
1
- {"version":3,"file":"urlSource.d.ts","sourceRoot":"","sources":["../../../../src/data/sources/urlSource.js"],"names":[],"mappings":"AASA;;;GAGG;AACH,gCAHW,OAAO,CAAC,OAAO,oBAAoB,EAAE,IAAI,CAAC,GACxC,IAAI,IAAI,OAAO,oBAAoB,EAAE,OAAO,CAIxD;AAED;IACI;;;OAGG;IACH,oBAHW,OAAO,oBAAoB,EAAE,OAAO,QACpC,OAAO,oBAAoB,EAAE,OAAO,EAc9C;IATG,6CAMC;IAED,gBAAiC;;CAuGxC;uBAtIsB,iBAAiB"}
1
+ {"version":3,"file":"urlSource.d.ts","sourceRoot":"","sources":["../../../../src/data/sources/urlSource.js"],"names":[],"mappings":"AA+IA;;;GAGG;AACH,gCAHW,OAAO,CAAC,OAAO,oBAAoB,EAAE,IAAI,CAAC,GACxC,IAAI,IAAI,OAAO,oBAAoB,EAAE,OAAO,CAIxD;AAzID;;;GAGG;AACH;IACI;;;OAGG;IACH,oBAHW,OAAO,oBAAoB,EAAE,OAAO,QACpC,OAAO,oBAAoB,EAAE,OAAO,EAc9C;IATG,6CAMC;IAED,gBAAiC;;CA6GxC;uBA3IsB,iBAAiB"}
@@ -1,5 +1,5 @@
1
1
  import { read } from "vega-loader";
2
- import { getFormat, responseType } from "./dataUtils.js";
2
+ import { getFormat, hasGzipExtension, responseType } from "./dataUtils.js";
3
3
  import DataSource from "./dataSource.js";
4
4
  import {
5
5
  activateExprRefProps,
@@ -7,14 +7,13 @@ import {
7
7
  } from "../../paramRuntime/paramUtils.js";
8
8
  import { concatUrl } from "../../utils/url.js";
9
9
 
10
+ const gzipMimeTypes = new Set(["application/gzip", "application/x-gzip"]);
11
+ const textDecoder = new TextDecoder();
12
+
10
13
  /**
11
- * @param {Partial<import("../../spec/data.js").Data>} data
12
- * @returns {data is import("../../spec/data.js").UrlData}
14
+ * Loads eager data from URLs and transparently decompresses gzip-compatible
15
+ * payloads before handing them to the registered format reader.
13
16
  */
14
- export function isUrlData(data) {
15
- return "url" in data;
16
- }
17
-
18
17
  export default class UrlSource extends DataSource {
19
18
  /**
20
19
  * @param {import("../../spec/data.js").UrlData} params
@@ -48,6 +47,7 @@ export default class UrlSource extends DataSource {
48
47
  */
49
48
  async #loadUrlsFromFile(props) {
50
49
  const listUrl = concatUrl(this.baseUrl, props.urlsFromFile);
50
+ const format = { type: props.type ?? "tsv" };
51
51
 
52
52
  const result = await fetch(listUrl);
53
53
 
@@ -56,10 +56,14 @@ export default class UrlSource extends DataSource {
56
56
  `Cannot load "${listUrl}": ${result.status} ${result.statusText}`
57
57
  );
58
58
  }
59
- const text = await result.text();
59
+ const content = await readResponseBody(
60
+ result,
61
+ listUrl,
62
+ responseType(format.type)
63
+ );
60
64
 
61
65
  const files = /** @type {string[] | {url: string}[]} */ (
62
- read(text, { type: props.type ?? "tsv" })
66
+ read(content, format)
63
67
  )
64
68
  .map((u) => (typeof u === "string" ? u : u.url))
65
69
  .map((u) => concatUrl(listUrl, u));
@@ -94,11 +98,7 @@ export default class UrlSource extends DataSource {
94
98
  if (!result.ok) {
95
99
  throw new Error(`${result.status} ${result.statusText}`);
96
100
  }
97
- // @ts-ignore
98
- return typeof result[type] == "function"
99
- ? // @ts-ignore
100
- result[type]()
101
- : result.text();
101
+ return await readResponseBody(result, url, type);
102
102
  } catch (e) {
103
103
  throw new Error(
104
104
  `Could not load data: ${url}. Reason: ${e.message}`
@@ -110,15 +110,20 @@ export default class UrlSource extends DataSource {
110
110
  * @param {any} content
111
111
  * @param {string} [url]
112
112
  */
113
- const readAndParse = (content, url) => {
113
+ const readAndParse = async (content, url) => {
114
114
  try {
115
- /** @type {any[]} */
116
- const data = read(content, format);
115
+ /** @type {any[] | Promise<any[]>} */
116
+ const dataOrPromise = read(content, format);
117
+ const data =
118
+ dataOrPromise instanceof Promise
119
+ ? await dataOrPromise
120
+ : dataOrPromise;
117
121
  this.beginBatch({ type: "file", url: url });
118
122
  for (const d of data) {
119
123
  this._propagate(d);
120
124
  }
121
125
  } catch (e) {
126
+ console.warn(e);
122
127
  throw new Error(`Cannot parse: ${url}: ${e.message}`);
123
128
  }
124
129
  };
@@ -135,3 +140,122 @@ export default class UrlSource extends DataSource {
135
140
  this.complete();
136
141
  }
137
142
  }
143
+
144
+ /**
145
+ * @param {Partial<import("../../spec/data.js").Data>} data
146
+ * @returns {data is import("../../spec/data.js").UrlData}
147
+ */
148
+ export function isUrlData(data) {
149
+ return "url" in data;
150
+ }
151
+
152
+ /**
153
+ * @param {Uint8Array} bytes
154
+ */
155
+ function hasGzipMagic(bytes) {
156
+ return (
157
+ bytes.length >= 10 &&
158
+ bytes[0] == 0x1f &&
159
+ bytes[1] == 0x8b &&
160
+ bytes[2] == 0x08 &&
161
+ (bytes[3] & 0xe0) == 0
162
+ );
163
+ }
164
+
165
+ /**
166
+ * @param {string | null} contentType
167
+ */
168
+ function isGzipMimeType(contentType) {
169
+ if (!contentType) {
170
+ return false;
171
+ }
172
+
173
+ return gzipMimeTypes.has(contentType.split(";")[0].trim().toLowerCase());
174
+ }
175
+
176
+ /**
177
+ * @param {string | null} contentEncoding
178
+ */
179
+ function hasGzipContentEncoding(contentEncoding) {
180
+ if (!contentEncoding) {
181
+ return false;
182
+ }
183
+
184
+ return contentEncoding
185
+ .toLowerCase()
186
+ .split(",")
187
+ .some((encoding) => encoding.trim() == "gzip");
188
+ }
189
+
190
+ /**
191
+ * @param {Uint8Array} bytes
192
+ * @returns {ArrayBuffer}
193
+ */
194
+ function toArrayBuffer(bytes) {
195
+ return new Uint8Array(bytes).buffer;
196
+ }
197
+
198
+ /**
199
+ * @param {Uint8Array} bytes
200
+ */
201
+ async function decompressGzip(bytes) {
202
+ if (typeof DecompressionStream != "function") {
203
+ throw new Error(
204
+ "Gzip-compressed URL data requires DecompressionStream support."
205
+ );
206
+ }
207
+
208
+ const body = new Response(toArrayBuffer(bytes)).body;
209
+ if (!body) {
210
+ throw new Error(
211
+ "Cannot create a readable stream for gzip decompression."
212
+ );
213
+ }
214
+
215
+ const stream = body.pipeThrough(new DecompressionStream("gzip"));
216
+ return new Uint8Array(await new Response(stream).arrayBuffer());
217
+ }
218
+
219
+ /**
220
+ * @param {Response} response
221
+ * @param {string} url
222
+ * @param {string} type
223
+ */
224
+ async function readResponseBody(response, url, type) {
225
+ const gzipHint =
226
+ hasGzipExtension(url) ||
227
+ isGzipMimeType(response.headers.get("content-type")) ||
228
+ hasGzipContentEncoding(response.headers.get("content-encoding"));
229
+
230
+ if (!gzipHint) {
231
+ return readResponseUsingType(response, type);
232
+ }
233
+
234
+ const bytes = new Uint8Array(await response.arrayBuffer());
235
+ const bodyBytes = hasGzipMagic(bytes) ? await decompressGzip(bytes) : bytes;
236
+ return deserializeBytes(bodyBytes, type);
237
+ }
238
+
239
+ /**
240
+ * @param {Response} response
241
+ * @param {string} type
242
+ */
243
+ function readResponseUsingType(response, type) {
244
+ // @ts-ignore
245
+ return typeof response[type] == "function"
246
+ ? // @ts-ignore
247
+ response[type]()
248
+ : response.text();
249
+ }
250
+
251
+ /**
252
+ * @param {Uint8Array} bytes
253
+ * @param {string} type
254
+ */
255
+ function deserializeBytes(bytes, type) {
256
+ if (type == "arrayBuffer") {
257
+ return toArrayBuffer(bytes);
258
+ } else {
259
+ return textDecoder.decode(bytes);
260
+ }
261
+ }
@@ -54,12 +54,12 @@ export function isChannelDefWithScale(channelDef: import("../spec/channel.js").C
54
54
  /**
55
55
  * @param {import("../spec/channel.js").ChannelDef} channelDef
56
56
  */
57
- export function findChannelDefWithScale(channelDef: import("../spec/channel.js").ChannelDef): import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, string> | import("../spec/channel.js").PositionFieldDef | import("../spec/channel.js").PositionDatumDef | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, number> | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").FieldDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").DatumDef<import("../spec/parameter.js").ExprRef | import("../spec/channel.js").Scalar> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").DomainContributionMixins) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").ValueDefBase<string | import("../spec/parameter.js").ExprRef> & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").DomainContributionMixins) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").ValueDefBase<number | import("../spec/parameter.js").ExprRef> & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").DomainContributionMixins);
57
+ export function findChannelDefWithScale(channelDef: import("../spec/channel.js").ChannelDef): import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, string> | import("../spec/channel.js").PositionFieldDef | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").PositionDatumDef | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, number> | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").ValueDefBase<string | import("../spec/parameter.js").ExprRef> & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").DomainContributionMixins) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").ValueDefBase<number | import("../spec/parameter.js").ExprRef> & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").DomainContributionMixins) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").FieldDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>) | (import("../spec/channel.js").ParameterPredicate & import("../spec/channel.js").DatumDef<import("../spec/parameter.js").ExprRef | import("../spec/channel.js").Scalar> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").DomainContributionMixins);
58
58
  /**
59
59
  * @param {import("../view/unitView.js").default} view
60
60
  * @param {import("../spec/channel.js").Channel} channel
61
61
  */
62
- export function getChannelDefWithScale(view: import("../view/unitView.js").default, channel: import("../spec/channel.js").Channel): import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, string> | import("../spec/channel.js").PositionFieldDef | import("../spec/channel.js").PositionDatumDef | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, number> | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").TypeForShape>, string> | (import("../spec/channel.js").FieldDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").DatumDef<import("../spec/parameter.js").ExprRef | import("../spec/channel.js").Scalar> & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ChromPosDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").TypeMixins<"locus"> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").XIndexDef);
62
+ export function getChannelDefWithScale(view: import("../view/unitView.js").default, channel: import("../spec/channel.js").Channel): import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, string> | import("../spec/channel.js").PositionFieldDef | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").PositionDatumDef | (import("../spec/channel.js").FieldDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ChromPosDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").TypeMixins<"locus"> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").DatumDef<import("../spec/parameter.js").ExprRef | import("../spec/channel.js").Scalar> & import("../spec/channel.js").DomainContributionMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").Type>, number> | import("../spec/channel.js").FieldOrDatumDefWithCondition<import("../spec/channel.js").MarkPropFieldDef<import("../spec/channel.js").TypeForShape>, string>;
63
63
  /**
64
64
  * @param {import("../spec/channel.js").ChannelDef} channelDef
65
65
  * @returns {channelDef is import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type>}
@@ -51,7 +51,7 @@ export default class BmFontManager {
51
51
  * @param {FontWeight | keyof WEIGHTS} weight
52
52
  * @returns {FontEntry}
53
53
  */
54
- getFont(family: string, style?: FontStyle, weight?: FontWeight | ("bold" | "normal" | "medium" | "thin" | "light" | "regular" | "black")): FontEntry;
54
+ getFont(family: string, style?: FontStyle, weight?: FontWeight | ("bold" | "normal" | "thin" | "light" | "regular" | "medium" | "black")): FontEntry;
55
55
  /**
56
56
  *
57
57
  * @param {FontEntry} fontEntry An uninitialized font entry
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @typedef {import("../spec/scale.js").Scale["assembly"]} AssemblyReference
3
+ */
4
+ /**
5
+ * @typedef {object} AssemblyPreflightResult
6
+ * @prop {AssemblyReference[]} assemblies
7
+ * @prop {boolean} needsDefaultAssembly
8
+ */
9
+ /**
10
+ * @param {import("../view/view.js").default} viewRoot
11
+ * @returns {AssemblyPreflightResult}
12
+ */
13
+ export function collectAssembliesFromViewHierarchy(viewRoot: import("../view/view.js").default): AssemblyPreflightResult;
14
+ /**
15
+ * Ensures that all assemblies required by the given view hierarchy are loaded
16
+ * before any scale initialization path can run.
17
+ *
18
+ * Reminder: call this immediately after view hierarchy creation and before
19
+ * operations that can implicitly initialize scales (for example, step-based
20
+ * size resolution, dynamic opacity setup, or encoder initialization).
21
+ *
22
+ * @param {import("../view/view.js").default} viewRoot
23
+ * @param {import("./genomeStore.js").default} genomeStore
24
+ */
25
+ export function ensureAssembliesForView(viewRoot: import("../view/view.js").default, genomeStore: import("./genomeStore.js").default): Promise<void>;
26
+ export type AssemblyReference = import("../spec/scale.js").Scale["assembly"];
27
+ export type AssemblyPreflightResult = {
28
+ assemblies: AssemblyReference[];
29
+ needsDefaultAssembly: boolean;
30
+ };
31
+ //# sourceMappingURL=assemblyPreflight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assemblyPreflight.d.ts","sourceRoot":"","sources":["../../../src/genome/assemblyPreflight.js"],"names":[],"mappings":"AAEA;;GAEG;AAEH;;;;GAIG;AAEH;;;GAGG;AACH,6DAHW,OAAO,iBAAiB,EAAE,OAAO,GAC/B,uBAAuB,CAsBnC;AAED;;;;;;;;;;GAUG;AACH,kDAHW,OAAO,iBAAiB,EAAE,OAAO,eACjC,OAAO,kBAAkB,EAAE,OAAO,iBAgB5C;gCA5DY,OAAO,kBAAkB,EAAE,KAAK,CAAC,UAAU,CAAC;;gBAK/C,iBAAiB,EAAE;0BACnB,OAAO"}
@@ -0,0 +1,99 @@
1
+ import { visitAddressableViews } from "../view/viewSelectors.js";
2
+
3
+ /**
4
+ * @typedef {import("../spec/scale.js").Scale["assembly"]} AssemblyReference
5
+ */
6
+
7
+ /**
8
+ * @typedef {object} AssemblyPreflightResult
9
+ * @prop {AssemblyReference[]} assemblies
10
+ * @prop {boolean} needsDefaultAssembly
11
+ */
12
+
13
+ /**
14
+ * @param {import("../view/view.js").default} viewRoot
15
+ * @returns {AssemblyPreflightResult}
16
+ */
17
+ export function collectAssembliesFromViewHierarchy(viewRoot) {
18
+ /** @type {AssemblyReference[]} */
19
+ const assemblies = [];
20
+ let needsDefaultAssembly = false;
21
+
22
+ const resolutions = collectRelevantScaleResolutions(viewRoot);
23
+ for (const resolution of resolutions) {
24
+ const requirement = resolution.getAssemblyRequirement();
25
+ if (requirement.assembly) {
26
+ assemblies.push(requirement.assembly);
27
+ }
28
+ if (requirement.needsDefaultAssembly) {
29
+ needsDefaultAssembly = true;
30
+ }
31
+ }
32
+
33
+ return {
34
+ assemblies,
35
+ needsDefaultAssembly,
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Ensures that all assemblies required by the given view hierarchy are loaded
41
+ * before any scale initialization path can run.
42
+ *
43
+ * Reminder: call this immediately after view hierarchy creation and before
44
+ * operations that can implicitly initialize scales (for example, step-based
45
+ * size resolution, dynamic opacity setup, or encoder initialization).
46
+ *
47
+ * @param {import("../view/view.js").default} viewRoot
48
+ * @param {import("./genomeStore.js").default} genomeStore
49
+ */
50
+ export async function ensureAssembliesForView(viewRoot, genomeStore) {
51
+ const { assemblies, needsDefaultAssembly } =
52
+ collectAssembliesFromViewHierarchy(viewRoot);
53
+ if (needsDefaultAssembly) {
54
+ const defaultAssembly = genomeStore.getDefaultAssemblyName();
55
+ if (!defaultAssembly) {
56
+ throw new Error(
57
+ "No default assembly has been configured. Set root `assembly`, define exactly one entry in root `genomes`, or set `scale.assembly` on each locus scale."
58
+ );
59
+ }
60
+ assemblies.push(defaultAssembly);
61
+ }
62
+
63
+ await genomeStore.ensureAssemblies(assemblies);
64
+ }
65
+
66
+ /**
67
+ * Collects scale resolutions that can influence user-authored views while
68
+ * excluding internal helper subtrees (axis/grid/etc.).
69
+ *
70
+ * Reminder: implicit root wrappers are marked non-addressable, so include the
71
+ * root ancestry explicitly before traversing addressable views.
72
+ *
73
+ * @param {import("../view/view.js").default} viewRoot
74
+ * @returns {Set<import("../scales/scaleResolution.js").default>}
75
+ */
76
+ function collectRelevantScaleResolutions(viewRoot) {
77
+ /** @type {Set<import("../scales/scaleResolution.js").default>} */
78
+ const resolutions = new Set();
79
+
80
+ /** @type {import("../spec/channel.js").PrimaryPositionalChannel[]} */
81
+ const locusChannels = ["x", "y"];
82
+
83
+ /**
84
+ * @param {import("../view/view.js").default} view
85
+ */
86
+ const collectFromView = (view) => {
87
+ for (const channel of locusChannels) {
88
+ const resolution = view.getScaleResolution(channel);
89
+ if (resolution) {
90
+ resolutions.add(resolution);
91
+ }
92
+ }
93
+ };
94
+
95
+ collectFromView(viewRoot);
96
+ visitAddressableViews(viewRoot, collectFromView);
97
+
98
+ return resolutions;
99
+ }
@@ -62,11 +62,11 @@ export default class Genome {
62
62
  config: {
63
63
  name: string;
64
64
  } | {
65
- url: string;
66
65
  name: string;
66
+ url: string;
67
67
  } | {
68
- contigs: import("../spec/genome.js").Contig[];
69
68
  name: string;
69
+ contigs: import("../spec/genome.js").Contig[];
70
70
  };
71
71
  /** @type {(Chromosome & ChromosomeAnnotation)[]} */
72
72
  chromosomes: (Chromosome & ChromosomeAnnotation)[];
@@ -1 +1 @@
1
- {"version":3,"file":"genome.d.ts","sourceRoot":"","sources":["../../../src/genome/genome.js"],"names":[],"mappings":"AAuXA;;;GAGG;AACH,gDAFW,MAAM;;;IAOhB;AAED;;;;GAIG;AACH,0CAHW,GAAG,GACF,KAAK,IAAI,gBAAgB,CAIpC;AAED;;;;GAIG;AACH,kDAHW,GAAG,EAAE,GACJ,KAAK,IAAI,gBAAgB,EAAE,CAItC;AAED;;;GAGG;AACH,sCAHW,GAAG,GACD,KAAK,IAAI,YAAY,CASjC;AAED;;;GAGG;AACH,yCAHW,GAAG,GACD,KAAK,IAAI,OAAO,mBAAmB,EAAE,eAAe,CAIhE;AAED;;;GAGG;AACH,4CAHW,GAAG,GACD,KAAK,IAAI,OAAO,mBAAmB,EAAE,kBAAkB,CAInE;AAxaD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;IACI;;OAEG;IACH,oBAFW,YAAY,EA6CtB;IA1CG;;;;;;;;MAA2C;IAc3C,oDAAoD;IACpD,aADW,CAAC,UAAU,GAAG,oBAAoB,CAAC,EAAE,CAC3B;IAErB,2CAA2C;IAC3C,0BADW,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,CACE;IAEzC,sEAAsE;IACtE,mBADW,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,UAAU,GAAG,oBAAoB,CAAC,CAChC;IAElC,uBAAuB;IACvB,cADW,MAAM,EAAE,CACG;IAEtB,kBAAkB;IAkBtB,mBAEC;IAED;;OAEG;IACH,cAFW,MAAM,iBAmBhB;IAED,wBAEC;IAED;;;OAGG;IACH,0BAFW,UAAU,EAAE,QA2CtB;IAED,sBAEC;IAED;;;;;OAKG;IACH,oBAHW,MAAM,GAAG,MAAM,OACf,MAAM,UAShB;IAED;;;OAGG;IACH,4BAFW,MAAM,qCAgBhB;IAED;;;;OAIG;IACH,6BAHW,MAAM,GACJ,gBAAgB,CAY5B;IAED;;;OAGG;IACH,oBAFW,MAAM,qCAIhB;IAED;;;;;;;;;;OAUG;IACH,yBAHW,MAAM,EAAE,GACN,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,2BAHW,MAAM,GACJ,MAAM,CAQlB;IAED;;;OAGG;IACH,gCAHW,MAAM,EAAE,GACN,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAUhD;IAED;;;;;;OAMG;IACH,kCAFW,gBAAgB,EAAE,YAgB5B;IAED;;;;;OAKG;IACH,wCAHW,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,GAClC,0BAA0B,EAAE,CAiCxC;IAED;;;;OAIG;IACH,4DAFW,MAAM,EAAE,gCAOlB;IAED;;;;OAIG;IACH,mBAHW,MAAM,GACJ,CAAC,MAAM,EAAE,MAAM,CAAC,CAgC5B;CACJ;2BA7WY,OAAO,mBAAmB,EAAE,YAAY;+BACxC,OAAO,mBAAmB,EAAE,gBAAgB;;UAG/C,MAAM;UACN,MAAM;;;;;;WAGN,MAAM;;;;YACN,MAAM;;;;qBACN,MAAM;;;;mBACN,MAAM;wBACN,MAAM,EAAE;;;;SACR,OAAO;;;WAGP,MAAM;cACN,MAAM;YACN,MAAM"}
1
+ {"version":3,"file":"genome.d.ts","sourceRoot":"","sources":["../../../src/genome/genome.js"],"names":[],"mappings":"AA2XA;;;GAGG;AACH,gDAFW,MAAM;;;IAOhB;AAED;;;;GAIG;AACH,0CAHW,GAAG,GACF,KAAK,IAAI,gBAAgB,CAIpC;AAED;;;;GAIG;AACH,kDAHW,GAAG,EAAE,GACJ,KAAK,IAAI,gBAAgB,EAAE,CAItC;AAED;;;GAGG;AACH,sCAHW,GAAG,GACD,KAAK,IAAI,YAAY,CASjC;AAED;;;GAGG;AACH,yCAHW,GAAG,GACD,KAAK,IAAI,OAAO,mBAAmB,EAAE,eAAe,CAIhE;AAED;;;GAGG;AACH,4CAHW,GAAG,GACD,KAAK,IAAI,OAAO,mBAAmB,EAAE,kBAAkB,CAInE;AA5aD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;IACI;;OAEG;IACH,oBAFW,YAAY,EA6CtB;IA1CG;;;;;;;;MAA2C;IAc3C,oDAAoD;IACpD,aADW,CAAC,UAAU,GAAG,oBAAoB,CAAC,EAAE,CAC3B;IAErB,2CAA2C;IAC3C,0BADW,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,CACE;IAEzC,sEAAsE;IACtE,mBADW,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,UAAU,GAAG,oBAAoB,CAAC,CAChC;IAElC,uBAAuB;IACvB,cADW,MAAM,EAAE,CACG;IAEtB,kBAAkB;IAkBtB,mBAEC;IAED;;OAEG;IACH,cAFW,MAAM,iBAmBhB;IAED,wBAEC;IAED;;;OAGG;IACH,0BAFW,UAAU,EAAE,QA+CtB;IAED,sBAEC;IAED;;;;;OAKG;IACH,oBAHW,MAAM,GAAG,MAAM,OACf,MAAM,UAShB;IAED;;;OAGG;IACH,4BAFW,MAAM,qCAgBhB;IAED;;;;OAIG;IACH,6BAHW,MAAM,GACJ,gBAAgB,CAY5B;IAED;;;OAGG;IACH,oBAFW,MAAM,qCAIhB;IAED;;;;;;;;;;OAUG;IACH,yBAHW,MAAM,EAAE,GACN,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,2BAHW,MAAM,GACJ,MAAM,CAQlB;IAED;;;OAGG;IACH,gCAHW,MAAM,EAAE,GACN,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAUhD;IAED;;;;;;OAMG;IACH,kCAFW,gBAAgB,EAAE,YAgB5B;IAED;;;;;OAKG;IACH,wCAHW,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,GAClC,0BAA0B,EAAE,CAiCxC;IAED;;;;OAIG;IACH,4DAFW,MAAM,EAAE,gCAOlB;IAED;;;;OAIG;IACH,mBAHW,MAAM,GACJ,CAAC,MAAM,EAAE,MAAM,CAAC,CAgC5B;CACJ;2BAjXY,OAAO,mBAAmB,EAAE,YAAY;+BACxC,OAAO,mBAAmB,EAAE,gBAAgB;;UAG/C,MAAM;UACN,MAAM;;;;;;WAGN,MAAM;;;;YACN,MAAM;;;;qBACN,MAAM;;;;mBACN,MAAM;wBACN,MAAM,EAAE;;;;SACR,OAAO;;;WAGP,MAAM;cACN,MAAM;YACN,MAAM"}
@@ -111,6 +111,10 @@ export default class Genome {
111
111
  * @param {Chromosome[]} chromSizes
112
112
  */
113
113
  setChromSizes(chromSizes) {
114
+ this.chromosomes = [];
115
+ this.cumulativeChromPositions = new Map();
116
+ this.chromosomesByName = new Map();
117
+
114
118
  let pos = 0;
115
119
  this.startByIndex = [0];
116
120
 
@@ -1,3 +1,15 @@
1
+ /**
2
+ * Resolves genome assemblies for locus scales.
3
+ *
4
+ * Keeps configured genome definitions and loaded `Genome` instances, supports
5
+ * named and inline assemblies, and deduplicates concurrent URL loads.
6
+ *
7
+ * `ensureAssembly(...)` is the async loading boundary. `getGenome(...)` is
8
+ * synchronous and expects required URL-backed assemblies to be ensured first.
9
+ *
10
+ * The default assembly comes from root `assembly`, a single configured genome,
11
+ * or a single already-loaded built-in genome.
12
+ */
1
13
  export default class GenomeStore {
2
14
  /**
3
15
  * @param {string} baseUrl
@@ -9,12 +21,31 @@ export default class GenomeStore {
9
21
  /**
10
22
  * @param {import("../spec/genome.js").GenomeConfig} genomeConfig
11
23
  */
12
- initialize(genomeConfig: import("../spec/genome.js").GenomeConfig): Promise<void[]>;
24
+ initialize(genomeConfig: import("../spec/genome.js").GenomeConfig): Promise<void>;
13
25
  /**
14
- * @param {string} [name] If not given, a default genome is returned.
26
+ * @param {Map<string, import("../spec/root.js").NamedGenomeConfig>} genomesByName
27
+ * @param {string} [defaultAssembly]
28
+ */
29
+ configureGenomes(genomesByName: Map<string, import("../spec/root.js").NamedGenomeConfig>, defaultAssembly?: string): void;
30
+ /**
31
+ * @returns {string | undefined}
32
+ */
33
+ getDefaultAssemblyName(): string | undefined;
34
+ /**
35
+ * @param {(string | import("../spec/scale.js").InlineLocusAssembly | undefined)[]} assemblies
36
+ */
37
+ ensureAssemblies(assemblies: (string | import("../spec/scale.js").InlineLocusAssembly | undefined)[]): Promise<void>;
38
+ /**
39
+ * @param {string | import("../spec/scale.js").InlineLocusAssembly} assembly
40
+ * @returns {Promise<Genome>}
41
+ */
42
+ ensureAssembly(assembly: string | import("../spec/scale.js").InlineLocusAssembly): Promise<Genome>;
43
+ /**
44
+ * @param {string | import("../spec/scale.js").InlineLocusAssembly} [name] If not given, a default genome is returned.
15
45
  * @returns {Genome}
16
46
  */
17
- getGenome(name?: string): Genome;
47
+ getGenome(name?: string | import("../spec/scale.js").InlineLocusAssembly): Genome;
48
+ #private;
18
49
  }
19
50
  import Genome from "./genome.js";
20
51
  //# sourceMappingURL=genomeStore.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"genomeStore.d.ts","sourceRoot":"","sources":["../../../src/genome/genomeStore.js"],"names":[],"mappings":"AAEA;IACI;;OAEG;IACH,qBAFW,MAAM,EAMhB;IAHG,kCAAkC;IAClC,SADW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CACN;IACxB,gBAAsB;IAG1B;;OAEG;IAEH,yBAHW,OAAO,mBAAmB,EAAE,YAAY,mBAYlD;IAED;;;OAGG;IACH,iBAHW,MAAM,GACJ,MAAM,CAuBlB;CACJ;mBArDkB,aAAa"}
1
+ {"version":3,"file":"genomeStore.d.ts","sourceRoot":"","sources":["../../../src/genome/genomeStore.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH;IACI;;OAEG;IACH,qBAFW,MAAM,EAahB;IAVG,kCAAkC;IAClC,SADW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CACN;IAQxB,gBAAsB;IAkB1B;;OAEG;IACH,yBAFW,OAAO,mBAAmB,EAAE,YAAY,iBAMlD;IAED;;;OAGG;IACH,gCAHW,GAAG,CAAC,MAAM,EAAE,OAAO,iBAAiB,EAAE,iBAAiB,CAAC,oBACxD,MAAM,QAShB;IAED;;OAEG;IACH,0BAFa,MAAM,GAAG,SAAS,CAmB9B;IAED;;OAEG;IACH,6BAFW,CAAC,MAAM,GAAG,OAAO,kBAAkB,EAAE,mBAAmB,GAAG,SAAS,CAAC,EAAE,iBAuBjF;IAED;;;OAGG;IACH,yBAHW,MAAM,GAAG,OAAO,kBAAkB,EAAE,mBAAmB,GACrD,OAAO,CAAC,MAAM,CAAC,CAuB3B;IAED;;;OAGG;IACH,iBAHW,MAAM,GAAG,OAAO,kBAAkB,EAAE,mBAAmB,GACrD,MAAM,CAuDlB;;CAwOJ;mBAhbkB,aAAa"}