@genome-spy/core 0.71.0 → 0.72.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/dist/bundle/index.es.js +3081 -2990
- package/dist/bundle/index.js +150 -143
- package/dist/bundle/parquetRead-BnAGCa4_.js +1663 -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/urlSource.d.ts.map +1 -1
- package/dist/src/data/sources/urlSource.js +8 -3
- package/dist/src/encoder/encoder.d.ts +2 -2
- package/dist/src/fonts/bmFontManager.d.ts +1 -1
- package/dist/src/genome/genome.d.ts +1 -1
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +2 -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.map +1 -1
- package/dist/src/gl/webGLHelper.js +12 -6
- 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 +2 -3
- package/dist/src/utils/radixSort.d.ts.map +1 -1
- package/dist/src/utils/radixSort.js +26 -1
- package/dist/src/view/facetView.d.ts +1 -1
- package/dist/src/view/unitView.d.ts +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load a data set in Apache Parquet format for use in Vega.
|
|
3
|
+
* @param {ArrayBuffer|Uint8Array} data Parquet binary data.
|
|
4
|
+
* @returns {Promise<Record<string,any>[]>} A promise that resolves to an array of data objects representing
|
|
5
|
+
* rows of a data table.
|
|
6
|
+
*/
|
|
7
|
+
declare function parquet(data: ArrayBuffer | Uint8Array): Promise<Record<string, any>[]>;
|
|
8
|
+
declare namespace parquet {
|
|
9
|
+
let responseType: string;
|
|
10
|
+
}
|
|
11
|
+
export default parquet;
|
|
12
|
+
//# sourceMappingURL=parquet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parquet.d.ts","sourceRoot":"","sources":["../../../../src/data/formats/parquet.js"],"names":[],"mappings":"AAYA;;;;;GAKG;AACH,+BAJW,WAAW,GAAC,UAAU,GACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAC,GAAG,CAAC,EAAE,CAAC,CAWzC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Adapted from: https://github.com/vega/vega-loader-parquet/blob/main/src/index.js
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @returns {Promise<typeof import("./parquetRead.js").parquetReadObjects>}
|
|
7
|
+
*/
|
|
8
|
+
async function loadParquetReadObjects() {
|
|
9
|
+
const { parquetReadObjects } = await import("./parquetRead.js");
|
|
10
|
+
return parquetReadObjects;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Load a data set in Apache Parquet format for use in Vega.
|
|
15
|
+
* @param {ArrayBuffer|Uint8Array} data Parquet binary data.
|
|
16
|
+
* @returns {Promise<Record<string,any>[]>} A promise that resolves to an array of data objects representing
|
|
17
|
+
* rows of a data table.
|
|
18
|
+
*/
|
|
19
|
+
export default async function parquet(data) {
|
|
20
|
+
const parquetReadObjects = await loadParquetReadObjects();
|
|
21
|
+
const buffer =
|
|
22
|
+
data instanceof Uint8Array
|
|
23
|
+
? /** @type {ArrayBuffer} */ (data.buffer)
|
|
24
|
+
: data;
|
|
25
|
+
|
|
26
|
+
return await parquetReadObjects({ file: buffer });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
parquet.responseType = "arrayBuffer";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {ObjectParquetReadOptions} options
|
|
3
|
+
* @returns {Promise<void>}
|
|
4
|
+
*/
|
|
5
|
+
export function parquetRead(options: ObjectParquetReadOptions): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* @param {Omit<ObjectParquetReadOptions, "onComplete">} options
|
|
8
|
+
* @returns {Promise<Record<string, any>[]>}
|
|
9
|
+
*/
|
|
10
|
+
export function parquetReadObjects(options: Omit<ObjectParquetReadOptions, "onComplete">): Promise<Record<string, any>[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Object-row variant of Parquet read options used by this trimmed reader.
|
|
13
|
+
*/
|
|
14
|
+
export type ObjectParquetReadOptions = Omit<import("hyparquet").ParquetReadOptions, "rowFormat" | "filter" | "filterStrict" | "onComplete"> & {
|
|
15
|
+
onComplete?: (rows: Record<string, any>[]) => void;
|
|
16
|
+
};
|
|
17
|
+
export type RowGroupObjectBuilder = (groupData: Record<string, any>[], selectStart: number, selectCount: number, columnData: import("hyparquet").DecodedArray[], columnSkipped: number[]) => Record<string, any>[];
|
|
18
|
+
//# sourceMappingURL=parquetRead.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parquetRead.d.ts","sourceRoot":"","sources":["../../../../src/data/formats/parquetRead.js"],"names":[],"mappings":"AAqOA;;;GAGG;AACH,qCAHW,wBAAwB,GACtB,OAAO,CAAC,IAAI,CAAC,CAiFzB;AAED;;;GAGG;AACH,4CAHW,IAAI,CAAC,wBAAwB,EAAE,YAAY,CAAC,GAC1C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,CAS1C;;;;uCAlTY,IAAI,CAChB,OAAU,WAAW,EAAE,kBAAkB,EACzC,WAAc,GAAG,QAAQ,GAAG,cAAc,GAAG,YAAY,CACtD,GAAG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,IAAI,CAAA;CAClD;oCAIS,CACT,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAChC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,OAAO,WAAW,EAAE,YAAY,EAAE,EAC9C,aAAa,EAAE,MAAM,EAAE,KACnB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE"}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Adapted from hyparquet internals:
|
|
3
|
+
* https://github.com/hyparam/hyparquet (notably src/read.js and src/rowgroup.js).
|
|
4
|
+
*
|
|
5
|
+
* GenomeSpy-specific changes in this copy:
|
|
6
|
+
* - object-row output only (array row format removed)
|
|
7
|
+
* - filtering support removed
|
|
8
|
+
* - hot row transpose path optimized with cached codegen for typical schemas
|
|
9
|
+
* - fallback to interpreted row builder for very wide schemas
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { parquetMetadataAsync, parquetSchema } from "hyparquet/src/metadata.js";
|
|
13
|
+
import { parquetPlan, prefetchAsyncBuffer } from "hyparquet/src/plan.js";
|
|
14
|
+
import { assembleAsync, readRowGroup } from "hyparquet/src/rowgroup.js";
|
|
15
|
+
import { concat } from "hyparquet/src/utils.js";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Object-row variant of Parquet read options used by this trimmed reader.
|
|
19
|
+
*
|
|
20
|
+
* @typedef {Omit<
|
|
21
|
+
* import("hyparquet").ParquetReadOptions,
|
|
22
|
+
* "rowFormat" | "filter" | "filterStrict" | "onComplete"
|
|
23
|
+
* > & {
|
|
24
|
+
* onComplete?: (rows: Record<string, any>[]) => void
|
|
25
|
+
* }} ObjectParquetReadOptions
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @typedef {(
|
|
30
|
+
* groupData: Record<string, any>[],
|
|
31
|
+
* selectStart: number,
|
|
32
|
+
* selectCount: number,
|
|
33
|
+
* columnData: import("hyparquet").DecodedArray[],
|
|
34
|
+
* columnSkipped: number[]
|
|
35
|
+
* ) => Record<string, any>[]} RowGroupObjectBuilder
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/** @type {Map<string, RowGroupObjectBuilder>} */
|
|
39
|
+
const rowGroupObjectBuilderCache = new Map();
|
|
40
|
+
|
|
41
|
+
const MAX_CODEGEN_COLUMNS = 200;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {ObjectParquetReadOptions} options
|
|
45
|
+
* @returns {import("hyparquet").AsyncRowGroup[]}
|
|
46
|
+
*/
|
|
47
|
+
function parquetReadAsync(options) {
|
|
48
|
+
if (!options.metadata) {
|
|
49
|
+
throw new Error("parquet requires metadata");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const plan = parquetPlan(options);
|
|
53
|
+
options.file = prefetchAsyncBuffer(options.file, plan);
|
|
54
|
+
|
|
55
|
+
return plan.groups.map((groupPlan) =>
|
|
56
|
+
readRowGroup(options, plan, groupPlan)
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Flatten decoded data pages into a single decoded array.
|
|
62
|
+
* This local version avoids chunked slice/push overhead in hot paths.
|
|
63
|
+
*
|
|
64
|
+
* @param {import("hyparquet").DecodedArray[] | undefined} chunks
|
|
65
|
+
* @returns {import("hyparquet").DecodedArray}
|
|
66
|
+
*/
|
|
67
|
+
function flattenColumnChunks(chunks) {
|
|
68
|
+
if (!chunks) {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (chunks.length === 1) {
|
|
73
|
+
return chunks[0];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let totalLength = 0;
|
|
77
|
+
for (const chunk of chunks) {
|
|
78
|
+
totalLength += chunk.length;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const output = Array(totalLength);
|
|
82
|
+
let offset = 0;
|
|
83
|
+
for (const chunk of chunks) {
|
|
84
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
85
|
+
output[offset + i] = chunk[i];
|
|
86
|
+
}
|
|
87
|
+
offset += chunk.length;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return output;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param {string[]} columnNames
|
|
95
|
+
* @returns {RowGroupObjectBuilder}
|
|
96
|
+
*/
|
|
97
|
+
function getRowGroupObjectBuilder(columnNames) {
|
|
98
|
+
// Compile one builder per column layout to keep object writes monomorphic.
|
|
99
|
+
const signature = columnNames.join("\u001f");
|
|
100
|
+
const cached = rowGroupObjectBuilderCache.get(signature);
|
|
101
|
+
if (cached) {
|
|
102
|
+
return cached;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const assignments = columnNames
|
|
106
|
+
.map(
|
|
107
|
+
(columnName, i) =>
|
|
108
|
+
JSON.stringify(columnName) +
|
|
109
|
+
": columnData[" +
|
|
110
|
+
i +
|
|
111
|
+
"][row - columnSkipped[" +
|
|
112
|
+
i +
|
|
113
|
+
"]]"
|
|
114
|
+
)
|
|
115
|
+
.join(",\n");
|
|
116
|
+
|
|
117
|
+
const builder = /** @type {RowGroupObjectBuilder} */ (
|
|
118
|
+
new Function(
|
|
119
|
+
"groupData",
|
|
120
|
+
"selectStart",
|
|
121
|
+
"selectCount",
|
|
122
|
+
"columnData",
|
|
123
|
+
"columnSkipped",
|
|
124
|
+
// Keep generated code focused on the tight row loop only.
|
|
125
|
+
"for (let selectRow = 0; selectRow < selectCount; selectRow++) {\n" +
|
|
126
|
+
" const row = selectStart + selectRow;\n" +
|
|
127
|
+
" groupData[selectRow] = {\n" +
|
|
128
|
+
assignments +
|
|
129
|
+
"\n" +
|
|
130
|
+
" };\n" +
|
|
131
|
+
"}\n" +
|
|
132
|
+
"return groupData;"
|
|
133
|
+
)
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
rowGroupObjectBuilderCache.set(signature, builder);
|
|
137
|
+
|
|
138
|
+
return builder;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @param {Record<string, any>[]} groupData
|
|
143
|
+
* @param {number} selectStart
|
|
144
|
+
* @param {number} selectCount
|
|
145
|
+
* @param {string[]} columnNames
|
|
146
|
+
* @param {import("hyparquet").DecodedArray[]} columnData
|
|
147
|
+
* @param {number[]} columnSkipped
|
|
148
|
+
* @returns {Record<string, any>[]}
|
|
149
|
+
*/
|
|
150
|
+
function buildRowsInterpreted(
|
|
151
|
+
groupData,
|
|
152
|
+
selectStart,
|
|
153
|
+
selectCount,
|
|
154
|
+
columnNames,
|
|
155
|
+
columnData,
|
|
156
|
+
columnSkipped
|
|
157
|
+
) {
|
|
158
|
+
for (let selectRow = 0; selectRow < selectCount; selectRow++) {
|
|
159
|
+
const row = selectStart + selectRow;
|
|
160
|
+
/** @type {Record<string, any>} */
|
|
161
|
+
const rowData = {};
|
|
162
|
+
for (let i = 0; i < columnNames.length; i++) {
|
|
163
|
+
rowData[columnNames[i]] = columnData[i][row - columnSkipped[i]];
|
|
164
|
+
}
|
|
165
|
+
groupData[selectRow] = rowData;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return groupData;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Object-only copy of hyparquet's asyncGroupToRows.
|
|
173
|
+
*
|
|
174
|
+
* @param {import("hyparquet").AsyncRowGroup} asyncGroup
|
|
175
|
+
* @param {number} selectStart
|
|
176
|
+
* @param {number} selectEnd
|
|
177
|
+
* @returns {Promise<Record<string, any>[]>}
|
|
178
|
+
*/
|
|
179
|
+
async function asyncGroupToRowsObject(
|
|
180
|
+
{ asyncColumns },
|
|
181
|
+
selectStart,
|
|
182
|
+
selectEnd
|
|
183
|
+
) {
|
|
184
|
+
// Resolve all async column pages once before entering the hot transpose loop.
|
|
185
|
+
const pages = await Promise.all(asyncColumns.map((column) => column.data));
|
|
186
|
+
const columnCount = asyncColumns.length;
|
|
187
|
+
|
|
188
|
+
/** @type {string[]} */
|
|
189
|
+
const columnNames = Array(columnCount);
|
|
190
|
+
/** @type {import("hyparquet").DecodedArray[]} */
|
|
191
|
+
const columnData = Array(columnCount);
|
|
192
|
+
/** @type {number[]} */
|
|
193
|
+
const columnSkipped = Array(columnCount);
|
|
194
|
+
|
|
195
|
+
// Precompute all indirections outside the generated function.
|
|
196
|
+
for (let i = 0; i < columnCount; i++) {
|
|
197
|
+
columnNames[i] = asyncColumns[i].pathInSchema[0];
|
|
198
|
+
columnData[i] = flattenColumnChunks(pages[i].data);
|
|
199
|
+
columnSkipped[i] = pages[i].skipped;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const selectCount = selectEnd - selectStart;
|
|
203
|
+
|
|
204
|
+
/** @type {Record<string, any>[]} */
|
|
205
|
+
const groupData = Array(selectCount);
|
|
206
|
+
|
|
207
|
+
// Avoid excessively large generated functions for very wide schemas.
|
|
208
|
+
if (columnCount > MAX_CODEGEN_COLUMNS) {
|
|
209
|
+
return buildRowsInterpreted(
|
|
210
|
+
groupData,
|
|
211
|
+
selectStart,
|
|
212
|
+
selectCount,
|
|
213
|
+
columnNames,
|
|
214
|
+
columnData,
|
|
215
|
+
columnSkipped
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const buildRows = getRowGroupObjectBuilder(columnNames);
|
|
220
|
+
|
|
221
|
+
return buildRows(
|
|
222
|
+
groupData,
|
|
223
|
+
selectStart,
|
|
224
|
+
selectCount,
|
|
225
|
+
columnData,
|
|
226
|
+
columnSkipped
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* @param {ObjectParquetReadOptions} options
|
|
232
|
+
* @returns {Promise<void>}
|
|
233
|
+
*/
|
|
234
|
+
export async function parquetRead(options) {
|
|
235
|
+
if ("rowFormat" in options) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
'parquetRead supports only object rows; use rowFormat: "object" implicitly'
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
if ("filter" in options || "filterStrict" in options) {
|
|
241
|
+
throw new Error("parquetRead does not support filtering");
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
options.metadata ??= await parquetMetadataAsync(options.file, options);
|
|
245
|
+
|
|
246
|
+
const { rowStart = 0, rowEnd, onChunk, onComplete } = options;
|
|
247
|
+
|
|
248
|
+
const asyncGroups = parquetReadAsync(options);
|
|
249
|
+
|
|
250
|
+
if (!onComplete && !onChunk) {
|
|
251
|
+
for (const { asyncColumns } of asyncGroups) {
|
|
252
|
+
for (const { data } of asyncColumns) {
|
|
253
|
+
await data;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const schemaTree = parquetSchema(options.metadata);
|
|
260
|
+
const assembled = asyncGroups.map((group) =>
|
|
261
|
+
assembleAsync(group, schemaTree, options.parsers)
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
if (onChunk) {
|
|
265
|
+
for (const asyncGroup of assembled) {
|
|
266
|
+
for (const asyncColumn of asyncGroup.asyncColumns) {
|
|
267
|
+
asyncColumn.data.then(
|
|
268
|
+
/**
|
|
269
|
+
* @param {{ data: import("hyparquet").DecodedArray[]; skipped: number }} chunk
|
|
270
|
+
*/
|
|
271
|
+
(chunk) => {
|
|
272
|
+
let chunkRowStart =
|
|
273
|
+
asyncGroup.groupStart + chunk.skipped;
|
|
274
|
+
for (const columnData of chunk.data) {
|
|
275
|
+
onChunk({
|
|
276
|
+
columnName: asyncColumn.pathInSchema[0],
|
|
277
|
+
columnData,
|
|
278
|
+
rowStart: chunkRowStart,
|
|
279
|
+
rowEnd: chunkRowStart + columnData.length,
|
|
280
|
+
});
|
|
281
|
+
chunkRowStart += columnData.length;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (onComplete) {
|
|
290
|
+
/** @type {Record<string, any>[]} */
|
|
291
|
+
const rows = [];
|
|
292
|
+
for (const asyncGroup of assembled) {
|
|
293
|
+
const selectStart = Math.max(rowStart - asyncGroup.groupStart, 0);
|
|
294
|
+
const selectEnd = Math.min(
|
|
295
|
+
(rowEnd ?? Infinity) - asyncGroup.groupStart,
|
|
296
|
+
asyncGroup.groupRows
|
|
297
|
+
);
|
|
298
|
+
const groupData = await asyncGroupToRowsObject(
|
|
299
|
+
asyncGroup,
|
|
300
|
+
selectStart,
|
|
301
|
+
selectEnd
|
|
302
|
+
);
|
|
303
|
+
concat(rows, groupData);
|
|
304
|
+
}
|
|
305
|
+
onComplete(rows);
|
|
306
|
+
} else {
|
|
307
|
+
for (const { asyncColumns } of assembled) {
|
|
308
|
+
for (const { data } of asyncColumns) {
|
|
309
|
+
await data;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* @param {Omit<ObjectParquetReadOptions, "onComplete">} options
|
|
317
|
+
* @returns {Promise<Record<string, any>[]>}
|
|
318
|
+
*/
|
|
319
|
+
export function parquetReadObjects(options) {
|
|
320
|
+
return new Promise((onComplete, reject) => {
|
|
321
|
+
parquetRead({
|
|
322
|
+
...options,
|
|
323
|
+
onComplete,
|
|
324
|
+
}).catch(reject);
|
|
325
|
+
});
|
|
326
|
+
}
|
|
@@ -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;;
|
|
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;;CA4GxC;uBA3IsB,iBAAiB"}
|
|
@@ -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
|
|
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
|
};
|
|
@@ -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").
|
|
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").
|
|
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" | "
|
|
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
|
|
@@ -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":"AAiDA;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;IA8DG,iDAAsB;IAQ1B;;OAEG;IACH,gBAqBC;IA+KD;;;OAGG;IACH,UAFa,OAAO,CAAC,OAAO,CAAC,CAyC5B;IAED,2CAiBC;IAED,4BAEC;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,sBAEC;IAED,kBAEC;IAED,iCAEC;IAED,oEAYC;IAED,uFAWC;;CACJ;;;;iCAhkBY,eAAe,GAAG,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB;4BAdnC,uBAAuB;qBAR9C,qBAAqB;wBAElB,yBAAyB;qBAL5B,oBAAoB"}
|
package/dist/src/genomeSpy.js
CHANGED
|
@@ -37,6 +37,7 @@ 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";
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
43
|
* Events that are broadcasted to all views.
|
|
@@ -44,6 +45,7 @@ import { validateSelectorConstraints } from "./view/viewSelectors.js";
|
|
|
44
45
|
*/
|
|
45
46
|
|
|
46
47
|
vegaFormats("fasta", fasta);
|
|
48
|
+
vegaFormats("parquet", parquet);
|
|
47
49
|
|
|
48
50
|
export default class GenomeSpy {
|
|
49
51
|
/** @type {(() => void)[]} */
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build-time options for sizing the hash table.
|
|
3
|
+
*
|
|
4
|
+
* @typedef {object} HashTableBuildOptions
|
|
5
|
+
* @property {number} [capacity] Power-of-two table size override.
|
|
6
|
+
* @property {number} [maxLoadFactor] Maximum load factor before resizing.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Packed table payload ready for WebGL texture upload.
|
|
10
|
+
*
|
|
11
|
+
* @typedef {object} HashTableBuildResult
|
|
12
|
+
* @property {Uint32Array} table Hash table slots that contain keys.
|
|
13
|
+
* @property {number} capacity Table capacity (number of slots).
|
|
14
|
+
* @property {number} size Number of stored keys.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* 32-bit integer hash for u32 keys. Keep in sync with GLSL hash32.
|
|
18
|
+
*
|
|
19
|
+
* @param {number} value
|
|
20
|
+
* @returns {number}
|
|
21
|
+
*/
|
|
22
|
+
export function hash32(value: number): number;
|
|
23
|
+
/**
|
|
24
|
+
* Build a hash table for set membership checks.
|
|
25
|
+
*
|
|
26
|
+
* @param {Iterable<number>} keys
|
|
27
|
+
* @param {HashTableBuildOptions} [options]
|
|
28
|
+
* @returns {HashTableBuildResult}
|
|
29
|
+
*/
|
|
30
|
+
export function buildHashTableSet(keys: Iterable<number>, options?: HashTableBuildOptions): HashTableBuildResult;
|
|
31
|
+
/**
|
|
32
|
+
* Computes a 2D texture layout for a power-of-two hash table capacity.
|
|
33
|
+
*
|
|
34
|
+
* The returned dimensions satisfy `width * height === capacity`.
|
|
35
|
+
*
|
|
36
|
+
* @param {number} capacity
|
|
37
|
+
* @param {number} maxTextureSize
|
|
38
|
+
* @returns {{ width: number, height: number }}
|
|
39
|
+
*/
|
|
40
|
+
export function computeHashTextureDimensions(capacity: number, maxTextureSize: number): {
|
|
41
|
+
width: number;
|
|
42
|
+
height: number;
|
|
43
|
+
};
|
|
44
|
+
/** Sentinel key that marks an empty hash slot. */
|
|
45
|
+
export const HASH_EMPTY_KEY: 4294967295;
|
|
46
|
+
/** Default maximum load factor for table sizing. */
|
|
47
|
+
export const DEFAULT_MAX_LOAD_FACTOR: 0.6;
|
|
48
|
+
/**
|
|
49
|
+
* Build-time options for sizing the hash table.
|
|
50
|
+
*/
|
|
51
|
+
export type HashTableBuildOptions = {
|
|
52
|
+
/**
|
|
53
|
+
* Power-of-two table size override.
|
|
54
|
+
*/
|
|
55
|
+
capacity?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Maximum load factor before resizing.
|
|
58
|
+
*/
|
|
59
|
+
maxLoadFactor?: number;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Packed table payload ready for WebGL texture upload.
|
|
63
|
+
*/
|
|
64
|
+
export type HashTableBuildResult = {
|
|
65
|
+
/**
|
|
66
|
+
* Hash table slots that contain keys.
|
|
67
|
+
*/
|
|
68
|
+
table: Uint32Array;
|
|
69
|
+
/**
|
|
70
|
+
* Table capacity (number of slots).
|
|
71
|
+
*/
|
|
72
|
+
capacity: number;
|
|
73
|
+
/**
|
|
74
|
+
* Number of stored keys.
|
|
75
|
+
*/
|
|
76
|
+
size: number;
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=hashTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hashTable.d.ts","sourceRoot":"","sources":["../../../src/gl/hashTable.js"],"names":[],"mappings":"AAQA;;;;;;GAMG;AAEH;;;;;;;GAOG;AAEH;;;;;GAKG;AACH,8BAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;GAMG;AACH,wCAJW,QAAQ,CAAC,MAAM,CAAC,YAChB,qBAAqB,GACnB,oBAAoB,CAkDhC;AAED;;;;;;;;GAQG;AACH,uDAJW,MAAM,kBACN,MAAM,GACJ;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CA+B7C;AAxID,kDAAkD;AAClD,6BAA8B,UAAW,CAAC;AAE1C,oDAAoD;AACpD,sCAAuC,GAAG,CAAC;;;;;;;;eAQ7B,MAAM;;;;oBACN,MAAM;;;;;;;;;WAON,WAAW;;;;cACX,MAAM;;;;UACN,MAAM"}
|