@alleninstitute/vis-omezarr 0.0.17

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/main.js ADDED
@@ -0,0 +1,1365 @@
1
+ import {intervalToVec2 as $7soKB$intervalToVec2, Box2D as $7soKB$Box2D, Vec2 as $7soKB$Vec2, limit as $7soKB$limit} from "@alleninstitute/vis-geometry";
2
+ import {logger as $7soKB$logger, buildAsyncRenderer as $7soKB$buildAsyncRenderer, getResourceUrl as $7soKB$getResourceUrl, VisError as $7soKB$VisError, makeRGBAColorVector as $7soKB$makeRGBAColorVector, PriorityCache as $7soKB$PriorityCache, WorkerPool as $7soKB$WorkerPool, HEARTBEAT_RATE_MS as $7soKB$HEARTBEAT_RATE_MS} from "@alleninstitute/vis-core";
3
+ import {FetchStore as $7soKB$FetchStore, open as $7soKB$open, root as $7soKB$root, slice as $7soKB$slice, get as $7soKB$get} from "zarrita";
4
+ import $7soKB$zod, {ZodError as $7soKB$ZodError, z as $7soKB$z} from "zod";
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+ class $8af220877f5aad67$export$96bea966bad52d02 extends (0, $7soKB$VisError) {
13
+ }
14
+ class $8af220877f5aad67$export$e819e674f1e05236 extends $8af220877f5aad67$export$96bea966bad52d02 {
15
+ }
16
+ class $8af220877f5aad67$export$d7f857358a0dbda6 extends $8af220877f5aad67$export$96bea966bad52d02 {
17
+ }
18
+
19
+
20
+
21
+
22
+
23
+ // these dimension indices are given for a 4-element shape array
24
+ const $0ff6a7cfdd9baaf1$var$SHAPE_Z_DIM_INDEX = 1;
25
+ const $0ff6a7cfdd9baaf1$var$SHAPE_Y_DIM_INDEX = 2;
26
+ const $0ff6a7cfdd9baaf1$var$SHAPE_X_DIM_INDEX = 3;
27
+ const $0ff6a7cfdd9baaf1$export$9989519d74cf4fd0 = (0, $7soKB$z).object({
28
+ name: (0, $7soKB$z).string().toLowerCase(),
29
+ type: (0, $7soKB$z).string(),
30
+ scale: (0, $7soKB$z).number().optional(),
31
+ unit: (0, $7soKB$z).string().optional()
32
+ });
33
+ const $0ff6a7cfdd9baaf1$export$13526d3947c5c7c2 = (0, $7soKB$z).object({
34
+ translation: (0, $7soKB$z).number().array().min(4).max(5),
35
+ type: (0, $7soKB$z).literal('translation')
36
+ });
37
+ const $0ff6a7cfdd9baaf1$export$f0f448c9214bb1a1 = (0, $7soKB$z).object({
38
+ scale: (0, $7soKB$z).number().array().min(4).max(5),
39
+ type: (0, $7soKB$z).literal('scale')
40
+ });
41
+ const $0ff6a7cfdd9baaf1$export$2e1c7be8e43a67e3 = (0, $7soKB$z).discriminatedUnion('type', [
42
+ $0ff6a7cfdd9baaf1$export$13526d3947c5c7c2,
43
+ $0ff6a7cfdd9baaf1$export$f0f448c9214bb1a1
44
+ ]);
45
+ const $0ff6a7cfdd9baaf1$export$a535e1d8aa90b3c9 = (0, $7soKB$z).object({
46
+ coordinateTransformations: $0ff6a7cfdd9baaf1$export$2e1c7be8e43a67e3.array().nonempty(),
47
+ path: (0, $7soKB$z).string()
48
+ });
49
+ const $0ff6a7cfdd9baaf1$export$d7d6a65692bb1dc0 = (0, $7soKB$z).object({
50
+ name: (0, $7soKB$z).string(),
51
+ version: (0, $7soKB$z).string().optional(),
52
+ type: (0, $7soKB$z).string().optional(),
53
+ axes: $0ff6a7cfdd9baaf1$export$9989519d74cf4fd0.array().nonempty(),
54
+ datasets: $0ff6a7cfdd9baaf1$export$a535e1d8aa90b3c9.array().nonempty()
55
+ });
56
+ const $0ff6a7cfdd9baaf1$export$90729eda236ba57 = (0, $7soKB$z).object({
57
+ min: (0, $7soKB$z).number(),
58
+ start: (0, $7soKB$z).number(),
59
+ end: (0, $7soKB$z).number(),
60
+ max: (0, $7soKB$z).number()
61
+ });
62
+ const $0ff6a7cfdd9baaf1$export$bb4e42bb52e6d21d = (0, $7soKB$z).object({
63
+ active: (0, $7soKB$z).boolean().optional(),
64
+ color: (0, $7soKB$z).string(),
65
+ label: (0, $7soKB$z).string().optional(),
66
+ window: $0ff6a7cfdd9baaf1$export$90729eda236ba57
67
+ });
68
+ const $0ff6a7cfdd9baaf1$export$51e803dddccc5479 = (0, $7soKB$z).object({
69
+ channels: $0ff6a7cfdd9baaf1$export$bb4e42bb52e6d21d.array().nonempty()
70
+ });
71
+ const $0ff6a7cfdd9baaf1$export$fd8824855129d20 = (0, $7soKB$z).object({
72
+ multiscales: $0ff6a7cfdd9baaf1$export$d7d6a65692bb1dc0.array().nonempty(),
73
+ omero: $0ff6a7cfdd9baaf1$export$51e803dddccc5479.optional()
74
+ });
75
+ const $0ff6a7cfdd9baaf1$export$abb89b3cbbc08888 = $0ff6a7cfdd9baaf1$export$fd8824855129d20;
76
+ const $0ff6a7cfdd9baaf1$export$4a10f5b26a59ff84 = (0, $7soKB$z).object({
77
+ ome: $0ff6a7cfdd9baaf1$export$fd8824855129d20
78
+ });
79
+ const $0ff6a7cfdd9baaf1$export$a3b48a0a4f3d252 = (0, $7soKB$z).union([
80
+ $0ff6a7cfdd9baaf1$export$abb89b3cbbc08888,
81
+ $0ff6a7cfdd9baaf1$export$4a10f5b26a59ff84
82
+ ]).transform((v)=>{
83
+ if ('ome' in v) return {
84
+ zarrVersion: 3,
85
+ ...v.ome
86
+ };
87
+ return {
88
+ zarrVersion: 2,
89
+ ...v
90
+ };
91
+ });
92
+ function $0ff6a7cfdd9baaf1$export$ac32486ec3a6add8(omero) {
93
+ return omero.channels.map($0ff6a7cfdd9baaf1$export$9b3c6a55077c31a1);
94
+ }
95
+ function $0ff6a7cfdd9baaf1$export$9b3c6a55077c31a1(omeroChannel) {
96
+ const active = omeroChannel.active;
97
+ const label = omeroChannel.label;
98
+ const rgba = (0, $7soKB$makeRGBAColorVector)(omeroChannel.color);
99
+ const rgb = [
100
+ rgba[0],
101
+ rgba[1],
102
+ rgba[2]
103
+ ];
104
+ const { min: winMin, max: winMax } = omeroChannel.window;
105
+ const { start: ranMin, end: ranMax } = omeroChannel.window;
106
+ const window = {
107
+ min: winMin,
108
+ max: winMax
109
+ };
110
+ const range = {
111
+ min: ranMin,
112
+ max: ranMax
113
+ };
114
+ return {
115
+ rgb: rgb,
116
+ rgba: rgba,
117
+ window: window,
118
+ range: range,
119
+ active: active,
120
+ label: label
121
+ };
122
+ }
123
+ class $0ff6a7cfdd9baaf1$export$c7c266bed5c41e68 {
124
+ #url;
125
+ #attrs;
126
+ #arrays;
127
+ #zarrVersion;
128
+ constructor(url, attrs, arrays, zarrVersion){
129
+ this.#url = url;
130
+ this.#attrs = attrs;
131
+ this.#arrays = arrays;
132
+ this.#zarrVersion = zarrVersion;
133
+ }
134
+ get url() {
135
+ return this.#url;
136
+ }
137
+ get attrs() {
138
+ return this.#attrs;
139
+ }
140
+ get arrays() {
141
+ return this.#arrays;
142
+ }
143
+ get zarrVersion() {
144
+ return this.#zarrVersion;
145
+ }
146
+ toJSON() {
147
+ return {
148
+ url: this.url,
149
+ attrs: this.attrs,
150
+ arrays: this.arrays,
151
+ zarrVersion: this.zarrVersion,
152
+ colorChannels: this.colorChannels,
153
+ redChannel: this.redChannel,
154
+ blueChannel: this.blueChannel,
155
+ greenChannel: this.greenChannel
156
+ };
157
+ }
158
+ #getMultiscaleIndex(multiscale) {
159
+ if (multiscale !== undefined) {
160
+ if (typeof multiscale === 'number') {
161
+ if (multiscale < 0) return -1;
162
+ return multiscale;
163
+ }
164
+ return this.#attrs.multiscales.findIndex((m)=>m.name === multiscale);
165
+ }
166
+ return 0;
167
+ }
168
+ #getValidMultiscaleIndex(multiscale) {
169
+ const multiscaleIndex = this.#getMultiscaleIndex(multiscale);
170
+ if (multiscaleIndex < 0) {
171
+ const message = `invalid multiscale requested: identifier [${multiscale}]`;
172
+ (0, $7soKB$logger).error(message);
173
+ throw new (0, $8af220877f5aad67$export$d7f857358a0dbda6)(message);
174
+ }
175
+ return multiscaleIndex;
176
+ }
177
+ #getDatasetIndex(dataset, multiscaleIndex) {
178
+ const datasets = this.#attrs.multiscales[multiscaleIndex]?.datasets ?? null;
179
+ if (!datasets) return -1;
180
+ if (typeof dataset === 'number') {
181
+ if (dataset < 0 || dataset >= datasets.length) return -1;
182
+ return dataset;
183
+ }
184
+ return datasets.findIndex((d)=>d.path === dataset);
185
+ }
186
+ #getValidDatasetIndex(dataset, multiscaleIndex) {
187
+ const datasetIndex = this.#getDatasetIndex(dataset, multiscaleIndex);
188
+ if (datasetIndex < 0) {
189
+ const message = `invalid dataset requested: identifier [${dataset}]`;
190
+ (0, $7soKB$logger).error(message);
191
+ throw new (0, $8af220877f5aad67$export$d7f857358a0dbda6)(message);
192
+ }
193
+ return datasetIndex;
194
+ }
195
+ /** Private function that retrieves the X value from the `shape` of a given array, within a
196
+ * specific multiscale representation of the data.
197
+ */ #getShapeX(array, multiscaleIndex) {
198
+ const shape = array.shape;
199
+ if (!shape || shape.length < 4) {
200
+ const message = `invalid dataset: .zarray formatting invalid, found array without valid shape; path [${multiscaleIndex}/${array.path}]`;
201
+ (0, $7soKB$logger).error(message);
202
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
203
+ }
204
+ const shapeIndex = shape.length === 5 ? $0ff6a7cfdd9baaf1$var$SHAPE_X_DIM_INDEX + 1 : $0ff6a7cfdd9baaf1$var$SHAPE_X_DIM_INDEX;
205
+ return shape[shapeIndex];
206
+ }
207
+ /** Private function that retrieves the Y value from the `shape` of a given array, within a
208
+ * specific multiscale representation of the data.
209
+ */ #getShapeY(array, multiscaleIndex) {
210
+ const shape = array.shape;
211
+ if (!shape || shape.length < 4) {
212
+ const message = `invalid dataset: .zarray formatting invalid, found array without valid shape; path [${multiscaleIndex}/${array.path}]`;
213
+ (0, $7soKB$logger).error(message);
214
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
215
+ }
216
+ const shapeIndex = shape.length === 5 ? $0ff6a7cfdd9baaf1$var$SHAPE_Y_DIM_INDEX + 1 : $0ff6a7cfdd9baaf1$var$SHAPE_Y_DIM_INDEX;
217
+ return shape[shapeIndex];
218
+ }
219
+ /** Private function that retrieves the Z value from the `shape` of a given array, within a
220
+ * specific multiscale representation of the data.
221
+ */ #getShapeZ(array, multiscaleIndex) {
222
+ const shape = array.shape;
223
+ if (!shape || shape.length < 4) {
224
+ const message = `invalid dataset: .zarray formatting invalid, found array without valid shape; path [${multiscaleIndex}/${array.path}]`;
225
+ (0, $7soKB$logger).error(message);
226
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
227
+ }
228
+ // This checks to see if the shape provided has all 5 official OME-Zarr dimensions (t, c, z, y, x),
229
+ // or just the 4 that we typically have in our data files (c, z, y, x)
230
+ const shapeIndex = shape.length === 5 ? $0ff6a7cfdd9baaf1$var$SHAPE_Z_DIM_INDEX + 1 : $0ff6a7cfdd9baaf1$var$SHAPE_Z_DIM_INDEX;
231
+ return shape[shapeIndex];
232
+ }
233
+ /** Private function to retrieve the maximum value for a given shape element, e.g.
234
+ * the maximum value of one of the dimensions (t, c, z, y, x). It compares across all
235
+ * the values of that dimension for all zarrays/datasets within a given multiscale
236
+ * representation of the data.
237
+ *
238
+ * Note: Typically, we only receive the last 4 elements in the `shape` of a zarray.
239
+ *
240
+ * @param getShapeElement a function that retrieves one element from the `shape` of
241
+ * a zarray
242
+ * @returns the maxium value of that element across all arrays within the given
243
+ * multiscale representation
244
+ */ #getShapeElementMax(getShapeElement, multiscale) {
245
+ const multiscaleIndex = this.#getValidMultiscaleIndex(multiscale);
246
+ return this.#attrs.multiscales[multiscaleIndex].datasets.map((dataset)=>{
247
+ const array = this.#arrays.find((a)=>a.path === dataset.path);
248
+ if (!array) {
249
+ const message = `invalid dataset: .zarray missing for dataset [${multiscaleIndex}/${dataset.path}]`;
250
+ (0, $7soKB$logger).error(message);
251
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
252
+ }
253
+ return getShapeElement(array, multiscaleIndex);
254
+ }).reduce((prev, curr)=>Math.max(prev, curr));
255
+ }
256
+ /**
257
+ * Given a specific @param multiscale representation of the Zarr data, finds the
258
+ * largest X shape component among the shapes of the different dataset arrays.
259
+ * @param multiscale the index or path of a specific multiscale representation (defaults to 0)
260
+ * @returns the largest Z scale for the specified multiscale representation
261
+ */ maxX(multiscale = 0) {
262
+ return this.#getShapeElementMax(this.#getShapeX, multiscale);
263
+ }
264
+ /**
265
+ * Given a specific @param multiscale representation of the Zarr data, finds the
266
+ * largest Y shape component among the shapes of the different dataset arrays.
267
+ * @param multiscale the index or path of a specific multiscale representation (defaults to 0)
268
+ * @returns the largest Z scale for the specified multiscale representation
269
+ */ maxY(multiscale = 0) {
270
+ return this.#getShapeElementMax(this.#getShapeY, multiscale);
271
+ }
272
+ /**
273
+ * Given a specific @param multiscale representation of the Zarr data, finds the
274
+ * largest Z shape component among the shapes of the different dataset arrays.
275
+ * @param multiscale the index or path of a specific multiscale representation (defaults to 0)
276
+ * @returns the largest Z scale for the specified multiscale representation
277
+ */ maxZ(multiscale = 0) {
278
+ return this.#getShapeElementMax(this.#getShapeZ, multiscale);
279
+ }
280
+ maxOrthogonal(plane, multiscale = 0) {
281
+ if (plane.ortho === 'x') return this.maxX(multiscale);
282
+ if (plane.ortho === 'y') return this.maxY(multiscale);
283
+ if (plane.ortho === 'z') return this.maxZ(multiscale);
284
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(`invalid plane: ortho set to '${plane.ortho}'`);
285
+ }
286
+ #makeShapedDataset(dataset, multiscaleIndex, datasetIndex) {
287
+ const array = this.#arrays.find((a)=>a.path === dataset.path);
288
+ if (!array) {
289
+ const message = `invalid dataset: .zarray missing for dataset [${multiscaleIndex}][${datasetIndex}]`;
290
+ (0, $7soKB$logger).error(message);
291
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
292
+ }
293
+ return {
294
+ ...dataset,
295
+ shape: array.shape,
296
+ multiscaleIndex: multiscaleIndex,
297
+ datasetIndex: datasetIndex
298
+ };
299
+ }
300
+ getShapedDataset(indexOrPath, multiscale = 0) {
301
+ try {
302
+ const multiscaleIndex = this.#getValidMultiscaleIndex(multiscale);
303
+ const datasetIndex = this.#getValidDatasetIndex(indexOrPath, multiscaleIndex);
304
+ const dataset = this.#attrs.multiscales[multiscaleIndex].datasets[datasetIndex];
305
+ return this.#makeShapedDataset(dataset, multiscaleIndex, datasetIndex);
306
+ } catch (e) {
307
+ if (e instanceof (0, $8af220877f5aad67$export$d7f857358a0dbda6)) {
308
+ (0, $7soKB$logger).debug('encountered index error when retrieving shaped dataset; returning undefined');
309
+ return undefined;
310
+ }
311
+ throw e;
312
+ }
313
+ }
314
+ getFirstShapedDataset(multiscale = 0) {
315
+ let multiscaleIndex;
316
+ try {
317
+ multiscaleIndex = this.#getValidMultiscaleIndex(multiscale);
318
+ const dataset = this.#attrs.multiscales[multiscaleIndex].datasets[0];
319
+ return this.#makeShapedDataset(dataset, multiscaleIndex, 0);
320
+ } catch (e) {
321
+ if (e instanceof (0, $8af220877f5aad67$export$d7f857358a0dbda6)) {
322
+ (0, $7soKB$logger).debug('encountered index error when retrieving shaped dataset; returning undefined');
323
+ return undefined;
324
+ }
325
+ throw e;
326
+ }
327
+ }
328
+ getLastShapedDataset(multiscale = 0) {
329
+ let multiscaleIndex;
330
+ try {
331
+ multiscaleIndex = this.#getValidMultiscaleIndex(multiscale);
332
+ const datasets = this.#attrs.multiscales[multiscaleIndex].datasets;
333
+ const dataset = datasets[datasets.length - 1];
334
+ return this.#makeShapedDataset(dataset, multiscaleIndex, 0);
335
+ } catch (e) {
336
+ if (e instanceof (0, $8af220877f5aad67$export$d7f857358a0dbda6)) {
337
+ (0, $7soKB$logger).debug('encountered index error when retrieving shaped dataset; returning undefined');
338
+ return undefined;
339
+ }
340
+ throw e;
341
+ }
342
+ }
343
+ getNumLayers(multiscale = 0) {
344
+ const multiscaleIndex = this.#getValidMultiscaleIndex(multiscale);
345
+ return this.#attrs.multiscales[multiscaleIndex].datasets.length;
346
+ }
347
+ getAllShapedDatasets(multiscale = 0) {
348
+ const multiscaleIndex = this.#getValidMultiscaleIndex(multiscale);
349
+ const datasets = this.#attrs.multiscales[multiscaleIndex].datasets;
350
+ return datasets.map((dataset, i)=>this.#makeShapedDataset(dataset, multiscaleIndex, i));
351
+ }
352
+ dehydrate() {
353
+ return {
354
+ url: this.#url,
355
+ attrs: this.#attrs,
356
+ arrays: [
357
+ ...this.#arrays
358
+ ],
359
+ zarrVersion: this.#zarrVersion
360
+ };
361
+ }
362
+ static async rehydrate(dehydrated) {
363
+ const { url: url, attrs: attrs, arrays: arrays, zarrVersion: zarrVersion } = dehydrated;
364
+ return new $0ff6a7cfdd9baaf1$export$c7c266bed5c41e68(url, attrs, arrays, zarrVersion);
365
+ }
366
+ #getChannelByMask(colorMask) {
367
+ if (!this.#attrs.omero || !this.#attrs.omero.channels) {
368
+ (0, $7soKB$logger).debug(`no omero data found for color mask ${colorMask}, returning undefined`);
369
+ return undefined;
370
+ }
371
+ const omeroChannel = this.#attrs.omero.channels.find((ch)=>ch.color === colorMask);
372
+ if (!omeroChannel) {
373
+ (0, $7soKB$logger).debug(`no matching omero channel found for color mask ${colorMask}, returning undefined`);
374
+ return undefined;
375
+ }
376
+ return $0ff6a7cfdd9baaf1$export$9b3c6a55077c31a1(omeroChannel);
377
+ }
378
+ get colorChannels() {
379
+ return this.#attrs.omero ? $0ff6a7cfdd9baaf1$export$ac32486ec3a6add8(this.#attrs.omero) : [];
380
+ }
381
+ get redChannel() {
382
+ return this.#getChannelByMask('#FF0000');
383
+ }
384
+ get greenChannel() {
385
+ return this.#getChannelByMask('#00FF00');
386
+ }
387
+ get blueChannel() {
388
+ return this.#getChannelByMask('#0000FF');
389
+ }
390
+ }
391
+
392
+
393
+
394
+
395
+ async function $62574ebf548584b6$export$78b8536ed7d8a60d(res) {
396
+ const url = (0, $7soKB$getResourceUrl)(res);
397
+ const store = new $7soKB$FetchStore(url);
398
+ return $62574ebf548584b6$var$loadZarrAttrsFileFromStore(store);
399
+ }
400
+ async function $62574ebf548584b6$var$loadZarrAttrsFileFromStore(store) {
401
+ const group = await $7soKB$open(store, {
402
+ kind: 'group'
403
+ });
404
+ try {
405
+ return (0, $0ff6a7cfdd9baaf1$export$a3b48a0a4f3d252).parse(group.attrs);
406
+ } catch (e) {
407
+ if (e instanceof (0, $7soKB$ZodError)) (0, $7soKB$logger).error('could not load Zarr file: parsing failed');
408
+ throw e;
409
+ }
410
+ }
411
+ async function $62574ebf548584b6$export$7f36aeab32ab33f7(res, path, version = 2, loadV2Attrs = true) {
412
+ const url = (0, $7soKB$getResourceUrl)(res);
413
+ const store = new $7soKB$FetchStore(url);
414
+ const result = await $62574ebf548584b6$export$ab574f5010f64a15(store, path, version, loadV2Attrs);
415
+ return result.metadata;
416
+ }
417
+ async function $62574ebf548584b6$export$ab574f5010f64a15(store, path, version = 2, loadV2Attrs = true) {
418
+ const root = $7soKB$root(store);
419
+ let array;
420
+ if (version === 3) array = await $7soKB$open.v3(root.resolve(path), {
421
+ kind: 'array'
422
+ });
423
+ else if (version === 2) array = await $7soKB$open.v2(root.resolve(path), {
424
+ kind: 'array',
425
+ attrs: loadV2Attrs
426
+ });
427
+ else {
428
+ const message = `unsupported Zarr format version specified: ${version}`;
429
+ (0, $7soKB$logger).error(message);
430
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
431
+ }
432
+ const { shape: shape, attrs: attrs } = array;
433
+ try {
434
+ return {
435
+ metadata: {
436
+ path: path,
437
+ shape: shape,
438
+ attrs: attrs
439
+ },
440
+ raw: array
441
+ };
442
+ } catch (e) {
443
+ if (e instanceof (0, $7soKB$ZodError)) (0, $7soKB$logger).error('could not load Zarr file: parsing failed');
444
+ throw e;
445
+ }
446
+ }
447
+ async function $62574ebf548584b6$export$7999b0bb51b3dcb8(res, loadV2ArrayAttrs = true) {
448
+ const url = (0, $7soKB$getResourceUrl)(res);
449
+ const store = new $7soKB$FetchStore(url);
450
+ const attrs = await $62574ebf548584b6$var$loadZarrAttrsFileFromStore(store);
451
+ const version = attrs.zarrVersion;
452
+ const arrays = await Promise.all(attrs.multiscales.map((multiscale)=>{
453
+ return multiscale.datasets?.map(async (dataset)=>{
454
+ return (await $62574ebf548584b6$export$ab574f5010f64a15(store, dataset.path, version, loadV2ArrayAttrs)).metadata;
455
+ }) ?? [];
456
+ }).reduce((prev, curr)=>prev.concat(curr)).filter((v)=>v !== undefined));
457
+ return new (0, $0ff6a7cfdd9baaf1$export$c7c266bed5c41e68)(url, attrs, arrays, version);
458
+ }
459
+ function $62574ebf548584b6$export$8efeb0367ee93033(zarr, plane, relativeView, displayResolution) {
460
+ const datasets = zarr.getAllShapedDatasets(0);
461
+ const axes = zarr.attrs.multiscales[0].axes;
462
+ const firstDataset = datasets[0];
463
+ if (!firstDataset) {
464
+ const message = 'invalid Zarr data: no datasets found';
465
+ (0, $7soKB$logger).error(message);
466
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
467
+ }
468
+ const realSize = $62574ebf548584b6$export$c5890dae76bd0ad7(plane, axes, firstDataset);
469
+ if (!realSize) {
470
+ const message = 'invalid Zarr data: could not determine the size of the plane in the given units';
471
+ (0, $7soKB$logger).error(message);
472
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
473
+ }
474
+ const vxlPitch = (size)=>(0, $7soKB$Vec2).div(realSize, size);
475
+ // size, in dataspace, of a pixel 1/res
476
+ const pxPitch = (0, $7soKB$Vec2).div((0, $7soKB$Box2D).size(relativeView), displayResolution);
477
+ const dstToDesired = (a, goal)=>{
478
+ const diff = (0, $7soKB$Vec2).sub(a, goal);
479
+ if (diff[0] * diff[1] > 0) // the res (a) is higher than our goal -
480
+ // weight this heavily to prefer smaller than the goal
481
+ return 1000 * (0, $7soKB$Vec2).length((0, $7soKB$Vec2).sub(a, goal));
482
+ return (0, $7soKB$Vec2).length((0, $7soKB$Vec2).sub(a, goal));
483
+ };
484
+ // we assume the datasets are ordered... hmmm TODO
485
+ const choice = datasets.reduce((bestSoFar, cur)=>{
486
+ const planeSizeBest = $62574ebf548584b6$export$ba17f86721d4d0ce(plane, axes, bestSoFar);
487
+ const planeSizeCur = $62574ebf548584b6$export$ba17f86721d4d0ce(plane, axes, cur);
488
+ if (!planeSizeBest || !planeSizeCur) return bestSoFar;
489
+ return dstToDesired(vxlPitch(planeSizeBest), pxPitch) > dstToDesired(vxlPitch(planeSizeCur), pxPitch) ? cur : bestSoFar;
490
+ }, datasets[0]);
491
+ return choice ?? datasets[datasets.length - 1];
492
+ }
493
+ // TODO this is a duplicate of indexOfDimension... delete one of them!
494
+ function $62574ebf548584b6$var$indexFor(dim, axes) {
495
+ return axes.findIndex((axis)=>axis.name === dim);
496
+ }
497
+ function $62574ebf548584b6$export$81eb4b4b765d519(layer, axes, parameter, dim) {
498
+ const dimIndex = $62574ebf548584b6$var$indexFor(dim, axes);
499
+ return Math.floor(layer.shape[dimIndex] * Math.max(0, Math.min(1, parameter)));
500
+ }
501
+ function $62574ebf548584b6$export$ca023b1dd6252668(zarr, plane, relativeView, displayResolution) {
502
+ // figure out what layer we'd be viewing
503
+ const layer = $62574ebf548584b6$export$8efeb0367ee93033(zarr, plane, relativeView, displayResolution);
504
+ const axes = zarr.attrs.multiscales[0].axes;
505
+ const slices = $62574ebf548584b6$export$fcb1a44ca126ee5c(plane.ortho, axes, layer);
506
+ return slices === undefined ? undefined : 1 / slices;
507
+ }
508
+ function $62574ebf548584b6$export$c5890dae76bd0ad7(plane, axes, dataset) {
509
+ const vxls = $62574ebf548584b6$export$ba17f86721d4d0ce(plane, axes, dataset);
510
+ if (vxls === undefined) return undefined;
511
+ let size = vxls;
512
+ // now, just apply the correct transforms, if they exist...
513
+ for (const trn of dataset.coordinateTransformations)if (trn.type === 'scale') {
514
+ // try to apply it!
515
+ const uIndex = $62574ebf548584b6$var$indexFor(plane.u, axes);
516
+ const vIndex = $62574ebf548584b6$var$indexFor(plane.v, axes);
517
+ size = (0, $7soKB$Vec2).mul(size, [
518
+ trn.scale[uIndex],
519
+ trn.scale[vIndex]
520
+ ]);
521
+ }
522
+ return size;
523
+ }
524
+ function $62574ebf548584b6$export$fcb1a44ca126ee5c(dim, axes, dataset) {
525
+ const uI = $62574ebf548584b6$var$indexFor(dim, axes);
526
+ if (uI === -1) return undefined;
527
+ return dataset.shape[uI];
528
+ }
529
+ function $62574ebf548584b6$export$ba17f86721d4d0ce(plane, axes, dataset) {
530
+ // first - u&v must not refer to the same dimension,
531
+ // and both should exist in the axes...
532
+ if (!plane.isValid()) return undefined;
533
+ const uI = $62574ebf548584b6$var$indexFor(plane.u, axes);
534
+ const vI = $62574ebf548584b6$var$indexFor(plane.v, axes);
535
+ if (uI === -1 || vI === -1) return undefined;
536
+ return [
537
+ dataset.shape[uI],
538
+ dataset.shape[vI]
539
+ ];
540
+ }
541
+ function $62574ebf548584b6$export$d7b58f10109feb02(r, axes, shape) {
542
+ const ordered = axes.map((a)=>r[a.name]);
543
+ // if any are undefined, throw up
544
+ if (ordered.some((a)=>a === undefined)) throw new (0, $8af220877f5aad67$export$e819e674f1e05236)('request does not match expected dimensions of OME-Zarr dataset');
545
+ return ordered.map((d, i)=>{
546
+ const bounds = {
547
+ min: 0,
548
+ max: shape[i]
549
+ };
550
+ if (d === null) return d;
551
+ if (typeof d === 'number') return (0, $7soKB$limit)(bounds, d);
552
+ return $7soKB$slice((0, $7soKB$limit)(bounds, d.min), (0, $7soKB$limit)(bounds, d.max));
553
+ });
554
+ }
555
+ async function $62574ebf548584b6$export$151d38946e654182(z) {
556
+ (0, $7soKB$logger).dir(z);
557
+ }
558
+ async function $62574ebf548584b6$export$831e2eeffaa681(metadata, r, level, signal) {
559
+ // put the request in native order
560
+ const store = new $7soKB$FetchStore(metadata.url);
561
+ const scene = metadata.attrs.multiscales[0];
562
+ const { axes: axes } = scene;
563
+ if (!level) {
564
+ const message = 'invalid Zarr data: no datasets found';
565
+ (0, $7soKB$logger).error(message);
566
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
567
+ }
568
+ const arr = metadata.arrays.find((a)=>a.path === level.path);
569
+ if (!arr) {
570
+ const message = `cannot load slice: no array found for path [${level.path}]`;
571
+ (0, $7soKB$logger).error(message);
572
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
573
+ }
574
+ const { raw: raw } = await $62574ebf548584b6$export$ab574f5010f64a15(store, arr.path, metadata.zarrVersion, false);
575
+ const result = await $7soKB$get(raw, $62574ebf548584b6$export$d7b58f10109feb02(r, axes, level.shape), {
576
+ opts: {
577
+ signal: signal ?? null
578
+ }
579
+ });
580
+ if (typeof result === 'number') throw new Error('oh noes, slice came back all weird');
581
+ return {
582
+ shape: result.shape,
583
+ buffer: result
584
+ };
585
+ }
586
+
587
+
588
+ /**
589
+ * given a image with @param size pixels, break it into tiles, each @param idealTilePx.
590
+ * for all such tiles which intersect the given bounds, call the visitor
591
+ * @param idealTilePx the size of a tile, in pixels
592
+ * @param size the size of the image at this level of detail
593
+ * @param bounds visit only the tiles that are within the given bounds (in pixels)
594
+ */ function $4a90fbb98bec80dd$var$visitTilesWithin(idealTilePx, size, bounds, visit) {
595
+ const withinBoth = (0, $7soKB$Box2D).intersection(bounds, (0, $7soKB$Box2D).create([
596
+ 0,
597
+ 0
598
+ ], size));
599
+ if (!withinBoth) return;
600
+ // convert the image into tile indexes:
601
+ const boundsInTiles = (0, $7soKB$Box2D).map(withinBoth, (corner)=>(0, $7soKB$Vec2).div(corner, idealTilePx));
602
+ for(let x = Math.floor(boundsInTiles.minCorner[0]); x < Math.ceil(boundsInTiles.maxCorner[0]); x += 1)for(let y = Math.floor(boundsInTiles.minCorner[1]); y < Math.ceil(boundsInTiles.maxCorner[1]); y += 1){
603
+ // all tiles visited are always within both the bounds, and the image itself
604
+ const lo = (0, $7soKB$Vec2).mul([
605
+ x,
606
+ y
607
+ ], idealTilePx);
608
+ const hi = (0, $7soKB$Vec2).min(size, (0, $7soKB$Vec2).add(lo, idealTilePx));
609
+ visit((0, $7soKB$Box2D).create(lo, hi));
610
+ }
611
+ }
612
+ function $4a90fbb98bec80dd$var$getVisibleTilesInLayer(camera, plane, orthoVal, dataset, tileSize, level) {
613
+ const size = (0, $62574ebf548584b6$export$ba17f86721d4d0ce)(plane, dataset.attrs.multiscales[0].axes, level);
614
+ const realSize = (0, $62574ebf548584b6$export$c5890dae76bd0ad7)(plane, dataset.attrs.multiscales[0].axes, level);
615
+ if (!size || !realSize) return [];
616
+ const scale = (0, $7soKB$Vec2).div(realSize, size);
617
+ const vxlToReal = (vxl)=>(0, $7soKB$Box2D).scale(vxl, scale);
618
+ const realToVxl = (real)=>(0, $7soKB$Box2D).scale(real, (0, $7soKB$Vec2).div([
619
+ 1,
620
+ 1
621
+ ], scale));
622
+ const visibleTiles = [];
623
+ $4a90fbb98bec80dd$var$visitTilesWithin([
624
+ tileSize,
625
+ tileSize
626
+ ], size, realToVxl(camera.view), (uv)=>{
627
+ visibleTiles.push({
628
+ plane: plane.axes,
629
+ realBounds: vxlToReal(uv),
630
+ bounds: uv,
631
+ orthoVal: orthoVal,
632
+ level: level
633
+ });
634
+ });
635
+ return visibleTiles;
636
+ }
637
+ function $4a90fbb98bec80dd$export$2957f72eb8eb81d4(camera, plane, planeLocation, metadata, tileSize) {
638
+ // TODO (someday) open the array, look at its chunks, use that size for the size of the tiles I request!
639
+ const layer = (0, $62574ebf548584b6$export$8efeb0367ee93033)(metadata, plane, camera.view, camera.screenSize);
640
+ // figure out the index of the slice
641
+ const sliceIndex = (0, $62574ebf548584b6$export$81eb4b4b765d519)(layer, metadata.attrs.multiscales[0].axes, planeLocation, plane.ortho);
642
+ return $4a90fbb98bec80dd$var$getVisibleTilesInLayer(camera, plane, sliceIndex, metadata, tileSize, layer);
643
+ }
644
+ const $4a90fbb98bec80dd$export$e83f4de492e8b929 = (metadata, r, level, signal)=>{
645
+ return (0, $62574ebf548584b6$export$831e2eeffaa681)(metadata, r, level, signal).then((result)=>{
646
+ const { shape: shape, buffer: buffer } = result;
647
+ return {
648
+ shape: shape,
649
+ data: new Float32Array(buffer.data)
650
+ };
651
+ });
652
+ };
653
+
654
+
655
+ // render a slice of an ome-zarr file as a 2D image
656
+ // note that the ome-zarr data must have exactly 3 channels
657
+ // the channels may be mapped to color-channels (RGB) with a basic 2-post gamut control
658
+ /* ================ TILE RENDERING VERTEX SHADER ================ */ const $3e6603f747b5a8a4$var$tileVert = /*glsl*/ `
659
+ precision highp float;
660
+ attribute vec2 pos;
661
+
662
+ uniform vec4 view;
663
+ uniform vec4 tile;
664
+ uniform float depth;
665
+ varying vec2 texCoord;
666
+ uniform float rot;
667
+
668
+ void main(){
669
+ vec2 tileSize = tile.zw-tile.xy;
670
+ texCoord = pos;
671
+ vec2 obj = (pos.xy*tileSize+tile.xy);
672
+
673
+ vec2 p = (obj-view.xy)/(view.zw-view.xy);
674
+ // now, to clip space
675
+ p = (p*2.0)-1.0;
676
+ gl_Position = vec4(p.x,p.y,depth,1.0);
677
+ }
678
+ `;
679
+ /* -------------------------------------------------------------- */ /* ============= RGB TILE RENDERING FRAGMENT SHADER ============= */ const $3e6603f747b5a8a4$var$rgbFrag = /*glsl*/ `
680
+ precision highp float;
681
+ uniform sampler2D R;
682
+ uniform sampler2D G;
683
+ uniform sampler2D B;
684
+ // for reasons which are pretty annoying
685
+ // its more direct to do 3 separate channels...
686
+ uniform vec2 Rgamut;
687
+ uniform vec2 Ggamut;
688
+ uniform vec2 Bgamut;
689
+ varying vec2 texCoord;
690
+
691
+ void main(){
692
+ vec3 mins = vec3(Rgamut.x, Ggamut.x, Bgamut.x);
693
+ vec3 maxs = vec3(Rgamut.y, Ggamut.y, Bgamut.y);
694
+ vec3 span = maxs - mins;
695
+ vec3 color = (vec3(
696
+ texture2D(R, texCoord).r,
697
+ texture2D(G, texCoord).r,
698
+ texture2D(B, texCoord).r
699
+ ) - mins) / span;
700
+
701
+ gl_FragColor = vec4(color, 1.0);
702
+ }
703
+ `;
704
+ function $3e6603f747b5a8a4$export$e1c4d8365a017448(regl) {
705
+ const cmd = regl({
706
+ vert: $3e6603f747b5a8a4$var$tileVert,
707
+ frag: $3e6603f747b5a8a4$var$rgbFrag,
708
+ framebuffer: regl.prop('target'),
709
+ attributes: {
710
+ pos: [
711
+ 0,
712
+ 0,
713
+ 1,
714
+ 0,
715
+ 1,
716
+ 1,
717
+ 0,
718
+ 1
719
+ ]
720
+ },
721
+ uniforms: {
722
+ tile: regl.prop('tile'),
723
+ view: regl.prop('view'),
724
+ depth: regl.prop('depth'),
725
+ R: regl.prop('R'),
726
+ G: regl.prop('G'),
727
+ B: regl.prop('B'),
728
+ Rgamut: regl.prop('Rgamut'),
729
+ Ggamut: regl.prop('Ggamut'),
730
+ Bgamut: regl.prop('Bgamut')
731
+ },
732
+ depth: {
733
+ enable: true
734
+ },
735
+ count: 4,
736
+ primitive: 'triangle fan'
737
+ });
738
+ return (p)=>cmd(p);
739
+ }
740
+ function $3e6603f747b5a8a4$export$640f994018c81008(regl, numChannels) {
741
+ const reglChannelUniforms = [];
742
+ const fragmentChannelUniformDefs = [];
743
+ const colorMerges = [];
744
+ for(let i = 0; i < numChannels; i++){
745
+ reglChannelUniforms.push({
746
+ [`gamut${i}`]: (_context, props)=>props.channels[i].gamut,
747
+ [`color${i}`]: (_context, props)=>props.channels[i].rgb,
748
+ [`tex${i}`]: (_context, props)=>props.channels[i].tex
749
+ });
750
+ fragmentChannelUniformDefs.push(`uniform vec2 gamut${i};`);
751
+ fragmentChannelUniformDefs.push(`uniform vec3 color${i};`);
752
+ fragmentChannelUniformDefs.push(`uniform sampler2D tex${i};`);
753
+ colorMerges.push(`
754
+ float ch${i}Val = texture2D(tex${i}, texCoord).r;
755
+ ch${i}Val = (ch${i}Val - gamut${i}.x) / (gamut${i}.y - gamut${i}.x);
756
+ color += (color${i} * ch${i}Val);
757
+ `);
758
+ }
759
+ const staticReglUniforms = {
760
+ tile: regl.prop('tile'),
761
+ view: regl.prop('view'),
762
+ depth: regl.prop('depth')
763
+ };
764
+ const uniforms = reglChannelUniforms.reduce((acc, curr)=>{
765
+ for(const key in curr)acc[key] = curr[key];
766
+ return acc;
767
+ }, staticReglUniforms);
768
+ const frag = `
769
+ precision highp float;
770
+ ${fragmentChannelUniformDefs.join('\n')}
771
+ varying vec2 texCoord;
772
+
773
+ void main() {
774
+ vec3 color = vec3(0.0, 0.0, 0.0);
775
+ ${colorMerges.join('\n')}
776
+ color = clamp(color, 0.0, 1.0);
777
+ gl_FragColor = vec4(color, 1.0);
778
+ }`;
779
+ // biome-ignore lint/suspicious/noExplicitAny: type of uniforms cannot be given explicitly due to dynamic nature of uniforms in these shaders
780
+ const cmd = regl({
781
+ vert: $3e6603f747b5a8a4$var$tileVert,
782
+ frag: frag,
783
+ framebuffer: regl.prop('target'),
784
+ attributes: {
785
+ pos: [
786
+ 0,
787
+ 0,
788
+ 1,
789
+ 0,
790
+ 1,
791
+ 1,
792
+ 0,
793
+ 1
794
+ ]
795
+ },
796
+ uniforms: uniforms,
797
+ depth: {
798
+ enable: true
799
+ },
800
+ count: 4,
801
+ primitive: 'triangle fan'
802
+ });
803
+ return (p)=>cmd(p);
804
+ }
805
+
806
+
807
+ function $6f9a458a1fcc6b82$var$toZarrRequest(tile, channel) {
808
+ const { plane: plane, orthoVal: orthoVal, bounds: bounds } = tile;
809
+ const { minCorner: min, maxCorner: max } = bounds;
810
+ const u = {
811
+ min: min[0],
812
+ max: max[0]
813
+ };
814
+ const v = {
815
+ min: min[1],
816
+ max: max[1]
817
+ };
818
+ switch(plane){
819
+ case 'xy':
820
+ return {
821
+ x: u,
822
+ y: v,
823
+ t: 0,
824
+ c: channel,
825
+ z: orthoVal
826
+ };
827
+ case 'xz':
828
+ return {
829
+ x: u,
830
+ z: v,
831
+ t: 0,
832
+ c: channel,
833
+ y: orthoVal
834
+ };
835
+ case 'yz':
836
+ return {
837
+ y: u,
838
+ z: v,
839
+ t: 0,
840
+ c: channel,
841
+ x: orthoVal
842
+ };
843
+ }
844
+ }
845
+ function $6f9a458a1fcc6b82$var$isPrepared(cacheData) {
846
+ if (!cacheData) return false;
847
+ const keys = Object.keys(cacheData);
848
+ if (keys.length < 1) return false;
849
+ return keys.every((key)=>cacheData[key]?.type === 'texture');
850
+ }
851
+ const $6f9a458a1fcc6b82$var$DEFAULT_NUM_CHANNELS = 3;
852
+ function $6f9a458a1fcc6b82$export$c97bf2bbe9bf6d5e(regl, decoder, options) {
853
+ const numChannels = options?.numChannels ?? $6f9a458a1fcc6b82$var$DEFAULT_NUM_CHANNELS;
854
+ function sliceAsTexture(slice) {
855
+ const { data: data, shape: shape } = slice;
856
+ return {
857
+ bytes: data.byteLength,
858
+ texture: regl.texture({
859
+ data: data,
860
+ width: shape[1],
861
+ height: shape[0],
862
+ format: 'luminance'
863
+ }),
864
+ type: 'texture'
865
+ };
866
+ }
867
+ const cmd = (0, $3e6603f747b5a8a4$export$640f994018c81008)(regl, numChannels);
868
+ return {
869
+ cacheKey: (item, requestKey, dataset, settings)=>{
870
+ const channelKeys = Object.keys(settings.channels);
871
+ if (!channelKeys.includes(requestKey)) {
872
+ const message = `cannot retrieve cache key: unrecognized requestKey [${requestKey}]`;
873
+ (0, $7soKB$logger).error(message);
874
+ throw new Error(message);
875
+ }
876
+ return `${dataset.url}_${JSON.stringify(item)}_ch=${requestKey}`;
877
+ },
878
+ destroy: ()=>{},
879
+ getVisibleItems: (dataset, settings)=>{
880
+ const { camera: camera, plane: plane, planeLocation: planeLocation, tileSize: tileSize } = settings;
881
+ return (0, $4a90fbb98bec80dd$export$2957f72eb8eb81d4)(camera, plane, planeLocation, dataset, tileSize);
882
+ },
883
+ fetchItemContent: (item, dataset, settings)=>{
884
+ const contents = {};
885
+ for(const key in settings.channels)contents[key] = (signal)=>decoder(dataset, $6f9a458a1fcc6b82$var$toZarrRequest(item, settings.channels[key].index), item.level, signal).then(sliceAsTexture);
886
+ return contents;
887
+ },
888
+ isPrepared: $6f9a458a1fcc6b82$var$isPrepared,
889
+ renderItem: (target, item, dataset, settings, gpuData)=>{
890
+ const channels = Object.keys(gpuData).map((key)=>({
891
+ tex: gpuData[key].texture,
892
+ gamut: (0, $7soKB$intervalToVec2)(settings.channels[key].gamut),
893
+ rgb: settings.channels[key].rgb
894
+ }));
895
+ const layers = dataset.getNumLayers();
896
+ // per the spec, the highest resolution layer should be first
897
+ // we want that layer most in front, so:
898
+ const depth = item.level.datasetIndex / layers;
899
+ const { camera: camera } = settings;
900
+ cmd({
901
+ channels: channels,
902
+ target: target,
903
+ depth: depth,
904
+ tile: (0, $7soKB$Box2D).toFlatArray(item.realBounds),
905
+ view: (0, $7soKB$Box2D).toFlatArray(camera.view)
906
+ });
907
+ }
908
+ };
909
+ }
910
+ function $6f9a458a1fcc6b82$export$79b7536e23e20727(regl, decoder, options) {
911
+ return (0, $7soKB$buildAsyncRenderer)($6f9a458a1fcc6b82$export$c97bf2bbe9bf6d5e(regl, decoder, options), options?.queueOptions);
912
+ }
913
+
914
+
915
+
916
+
917
+
918
+
919
+
920
+
921
+
922
+
923
+ function $e7ae61881db7ab65$var$isSliceRequest(payload) {
924
+ return typeof payload === 'object' && payload !== null && 'type' in payload && payload.type === 'ZarrSliceRequest';
925
+ }
926
+ function $e7ae61881db7ab65$var$isCancellationRequest(payload) {
927
+ return typeof payload === 'object' && payload !== null && 'type' in payload && payload.type === 'cancel';
928
+ }
929
+ function $e7ae61881db7ab65$export$79bc3a420a6742ac(ctx) {
930
+ const cancelers = {};
931
+ ctx.onmessage = (msg)=>{
932
+ const { data: data } = msg;
933
+ try {
934
+ if ($e7ae61881db7ab65$var$isSliceRequest(data)) {
935
+ const { metadata: dehydratedMetadata, req: req, level: level, id: id } = data;
936
+ const abort = new AbortController();
937
+ cancelers[id] = abort;
938
+ (0, $0ff6a7cfdd9baaf1$export$c7c266bed5c41e68).rehydrate(dehydratedMetadata).then((metadata)=>{
939
+ (0, $62574ebf548584b6$export$831e2eeffaa681)(metadata, req, level, abort.signal).then((result)=>{
940
+ const { shape: shape, buffer: buffer } = result;
941
+ const data = new Float32Array(buffer.data);
942
+ ctx.postMessage({
943
+ type: 'slice',
944
+ id: id,
945
+ shape: shape,
946
+ data: data
947
+ }, {
948
+ transfer: [
949
+ data.buffer
950
+ ]
951
+ });
952
+ }).catch((err)=>{
953
+ if (!(err === 'cancelled' || typeof err === 'object' && ('name' in err && err.name === 'AbortError' || 'code' in err && err.code === 20))) (0, $7soKB$logger).error('error in slice fetch worker: ', err);
954
+ // else ignore it
955
+ });
956
+ });
957
+ } else if ($e7ae61881db7ab65$var$isCancellationRequest(data)) {
958
+ const { id: id } = data;
959
+ cancelers[id]?.abort('cancelled');
960
+ } else (0, $7soKB$logger).error('web-worker slice-fetcher recieved incomprehensible message: ', msg);
961
+ } catch (err) {
962
+ (0, $7soKB$logger).error('OME-Zarr fetch onmessage error', err);
963
+ }
964
+ };
965
+ }
966
+
967
+
968
+
969
+
970
+
971
+
972
+
973
+
974
+
975
+ const $5b408c6c3c009876$export$c73be2def9fc3425 = 'fetch';
976
+ const $5b408c6c3c009876$export$d7c94d771e5d9aa7 = 'fetch-response';
977
+ const $5b408c6c3c009876$export$75e5bf1b92806f35 = 'cancel';
978
+ const $5b408c6c3c009876$var$FetchMessagePayloadSchema = (0, $7soKB$zod).object({
979
+ rootUrl: (0, $7soKB$zod).string().nonempty(),
980
+ path: (0, $7soKB$zod).string().nonempty().startsWith('/'),
981
+ range: (0, $7soKB$zod).union([
982
+ (0, $7soKB$zod).object({
983
+ offset: (0, $7soKB$zod).number(),
984
+ length: (0, $7soKB$zod).number()
985
+ }),
986
+ (0, $7soKB$zod).object({
987
+ suffixLength: (0, $7soKB$zod).number()
988
+ })
989
+ ]).optional(),
990
+ options: (0, $7soKB$zod).unknown().optional()
991
+ });
992
+ const $5b408c6c3c009876$var$FetchMessageSchema = (0, $7soKB$zod).object({
993
+ type: (0, $7soKB$zod).literal($5b408c6c3c009876$export$c73be2def9fc3425),
994
+ id: (0, $7soKB$zod).string().nonempty(),
995
+ payload: $5b408c6c3c009876$var$FetchMessagePayloadSchema
996
+ });
997
+ const $5b408c6c3c009876$var$FetchResponseMessageSchema = (0, $7soKB$zod).object({
998
+ type: (0, $7soKB$zod).literal($5b408c6c3c009876$export$d7c94d771e5d9aa7),
999
+ id: (0, $7soKB$zod).string().nonempty(),
1000
+ payload: (0, $7soKB$zod).unknown().optional()
1001
+ });
1002
+ const $5b408c6c3c009876$var$CancelMessageSchema = (0, $7soKB$zod).object({
1003
+ type: (0, $7soKB$zod).literal($5b408c6c3c009876$export$75e5bf1b92806f35),
1004
+ id: (0, $7soKB$zod).string().nonempty()
1005
+ });
1006
+ function $5b408c6c3c009876$export$ced8a9318e8c4d3d(val) {
1007
+ return $5b408c6c3c009876$var$FetchMessageSchema.safeParse(val).success;
1008
+ }
1009
+ function $5b408c6c3c009876$export$87cac8e8f93fed1d(val) {
1010
+ return $5b408c6c3c009876$var$FetchResponseMessageSchema.safeParse(val).success;
1011
+ }
1012
+ function $5b408c6c3c009876$export$a77d75797e75745f(val) {
1013
+ return $5b408c6c3c009876$var$CancelMessageSchema.safeParse(val).success;
1014
+ }
1015
+ function $5b408c6c3c009876$export$2b3d06107d1323d4(err) {
1016
+ return err === 'cancelled' || typeof err === 'object' && err !== null && ('name' in err && err.name === 'AbortError' || 'code' in err && err.code === 20);
1017
+ }
1018
+
1019
+
1020
+ const $81959a80f9a6789a$var$DEFAULT_NUM_WORKERS = 6;
1021
+ const $81959a80f9a6789a$var$DEFAULT_MAX_DATA_CACHE_BYTES = 262144; // 256 MB -- aribtrarily chosen at this point
1022
+ // @TODO implement a much more context-aware cache size limiting mechanism
1023
+ const $81959a80f9a6789a$var$getDataCacheSizeLimit = ()=>{
1024
+ return $81959a80f9a6789a$var$DEFAULT_MAX_DATA_CACHE_BYTES;
1025
+ };
1026
+ const $81959a80f9a6789a$export$d09252bd498a9707 = (key, range)=>{
1027
+ const keyStr = JSON.stringify(key);
1028
+ const rangeStr = range ? JSON.stringify(range) : 'no-range';
1029
+ return `${keyStr} ${rangeStr}`;
1030
+ };
1031
+ class $81959a80f9a6789a$var$CacheableByteArray {
1032
+ #arr;
1033
+ constructor(arr){
1034
+ this.#arr = arr;
1035
+ }
1036
+ destroy() {}
1037
+ sizeInBytes() {
1038
+ return this.#arr.byteLength;
1039
+ }
1040
+ get array() {
1041
+ return this.#arr;
1042
+ }
1043
+ }
1044
+ const $81959a80f9a6789a$var$copyToTransferableHeaders = (headers)=>{
1045
+ if (Array.isArray(headers)) {
1046
+ const result = {};
1047
+ headers.forEach(([key, val])=>{
1048
+ // TODO is key, val the correct order here?
1049
+ result[key] = val;
1050
+ });
1051
+ return result;
1052
+ }
1053
+ if (headers instanceof Headers) {
1054
+ const result = {};
1055
+ headers.forEach((val, key)=>{
1056
+ result[key] = val;
1057
+ });
1058
+ return result;
1059
+ }
1060
+ return headers;
1061
+ };
1062
+ const $81959a80f9a6789a$var$copyToTransferableRequestInit = (req)=>{
1063
+ if (req === undefined) return {};
1064
+ const updReq = {
1065
+ ...req
1066
+ };
1067
+ delete updReq.signal;
1068
+ delete updReq.window;
1069
+ return {
1070
+ ...updReq,
1071
+ body: req.body?.toString(),
1072
+ headers: $81959a80f9a6789a$var$copyToTransferableHeaders(req.headers)
1073
+ };
1074
+ };
1075
+ class $81959a80f9a6789a$export$927188fe483fb171 extends $7soKB$FetchStore {
1076
+ /**
1077
+ * Maintains a pool of available worker threads.
1078
+ *
1079
+ * TODO: Enable end-to-end Message-based type constraints for these that
1080
+ * enable us to restrict what types of messages can be sent to workers
1081
+ * for a given store instance.
1082
+ */ // biome-ignore lint/suspicious/noExplicitAny: the type system for these parameters is a future feature
1083
+ #workerPool;
1084
+ /**
1085
+ * Stores the current set of cached data that has been successfully
1086
+ * fetched. This data is stored in raw byte array form so that it
1087
+ * integrates properly with the Zarrita framework.
1088
+ */ #dataCache;
1089
+ /**
1090
+ * Maps cache keys to numeric times; the higher the time, the higher the priority.
1091
+ *
1092
+ * This effectively means that more frequently-requested items will be kept longer.
1093
+ */ #priorityByTimestamp;
1094
+ /**
1095
+ * Stores in-progress requests that have not yet resolved.
1096
+ */ #pendingRequests;
1097
+ /**
1098
+ * Stores one instance of a cache key for each time that cache key was requested,
1099
+ * removing them all once that particular request is fulfilled. This allows us to
1100
+ * keep track of whether or not it is safe to abort a pending request: as long as
1101
+ * there are at least 2 instances of the same cache key in this array, then that
1102
+ * means multiple requestors are waiting on a particular piece of data, and it is
1103
+ * not safe to abort that request.
1104
+ */ #pendingRequestKeyCounts;
1105
+ /**
1106
+ * A callback form of the `score` function.
1107
+ */ #scoreFn;
1108
+ // biome-ignore lint/suspicious/noExplicitAny: the type system for these parameters is a future feature
1109
+ constructor(url, handler, options){
1110
+ super(url, options?.fetchStoreOptions);
1111
+ this.#scoreFn = (h)=>this.score(h);
1112
+ this.#dataCache = new (0, $7soKB$PriorityCache)(new Map(), this.#scoreFn, options?.maxBytes ?? $81959a80f9a6789a$var$getDataCacheSizeLimit());
1113
+ this.#priorityByTimestamp = new Map();
1114
+ this.#workerPool = handler;
1115
+ this.#pendingRequests = new Map();
1116
+ this.#pendingRequestKeyCounts = new Map();
1117
+ }
1118
+ /**
1119
+ * Warning - nothing in this class should be considered useable after
1120
+ * calling this method - any/all methods called should be expected to be
1121
+ * completely unreliable. dont call me unless you're about to dispose of all references to this object
1122
+ */ destroy() {
1123
+ // release all the web-workers!
1124
+ this.#workerPool.destroy();
1125
+ // todo: reject all promises
1126
+ this.#pendingRequests.forEach((p)=>{
1127
+ p.reject('cancelled');
1128
+ });
1129
+ }
1130
+ score(key) {
1131
+ return this.#priorityByTimestamp.get(key) ?? 0;
1132
+ }
1133
+ #fromCache(cacheKey) {
1134
+ const cached = this.#dataCache.get(cacheKey);
1135
+ if (cached === undefined) return undefined;
1136
+ this.#priorityByTimestamp.set(cacheKey, Date.now());
1137
+ return cached.array;
1138
+ }
1139
+ #incrementKeyCount(cacheKey) {
1140
+ const count = this.#pendingRequestKeyCounts.get(cacheKey);
1141
+ const newCount = count !== undefined ? count + 1 : 1;
1142
+ this.#pendingRequestKeyCounts.set(cacheKey, newCount);
1143
+ return newCount;
1144
+ }
1145
+ #decrementKeyCount(cacheKey) {
1146
+ const count = this.#pendingRequestKeyCounts.get(cacheKey);
1147
+ if (count === undefined) {
1148
+ (0, $7soKB$logger).warn('attempted to decrement a non-existent request key');
1149
+ return 0;
1150
+ }
1151
+ if (count <= 1) {
1152
+ this.#pendingRequestKeyCounts.delete(cacheKey);
1153
+ return 0;
1154
+ }
1155
+ const newCount = count - 1;
1156
+ this.#pendingRequestKeyCounts.set(cacheKey, newCount);
1157
+ return newCount;
1158
+ }
1159
+ async #doFetch(key, range, options, abort) {
1160
+ const cacheKey = $81959a80f9a6789a$export$d09252bd498a9707(key, range);
1161
+ this.#priorityByTimestamp.set(cacheKey, Date.now());
1162
+ this.#dataCache.reprioritize(this.#scoreFn);
1163
+ this.#incrementKeyCount(cacheKey);
1164
+ const pending = this.#pendingRequests.get(cacheKey);
1165
+ if (pending !== undefined) return pending.promise;
1166
+ const { promise: promise, resolve: resolve, reject: reject } = Promise.withResolvers();
1167
+ this.#pendingRequests.set(cacheKey, {
1168
+ promise: promise,
1169
+ resolve: resolve,
1170
+ reject: reject
1171
+ });
1172
+ const chain = new AbortController();
1173
+ if (abort) abort.addEventListener('abort', ()=>{
1174
+ const count = this.#decrementKeyCount(cacheKey);
1175
+ if (count === 0) {
1176
+ this.#priorityByTimestamp.set(cacheKey, 0);
1177
+ this.#dataCache.reprioritize(this.#scoreFn);
1178
+ chain.abort();
1179
+ }
1180
+ });
1181
+ const request = this.#workerPool.submitRequest({
1182
+ type: (0, $5b408c6c3c009876$export$c73be2def9fc3425),
1183
+ payload: {
1184
+ rootUrl: this.url,
1185
+ path: key,
1186
+ range: range,
1187
+ options: options
1188
+ }
1189
+ }, (0, $5b408c6c3c009876$export$87cac8e8f93fed1d), [], chain.signal);
1190
+ request.then((response)=>{
1191
+ const payload = response.payload;
1192
+ if (payload === undefined) {
1193
+ resolve(undefined);
1194
+ return;
1195
+ }
1196
+ const arr = new Uint8Array(payload);
1197
+ this.#dataCache.put(cacheKey, new $81959a80f9a6789a$var$CacheableByteArray(arr));
1198
+ resolve(arr);
1199
+ }).catch((e)=>{
1200
+ reject(e);
1201
+ }).finally(()=>{
1202
+ this.#pendingRequests.delete(cacheKey);
1203
+ this.#pendingRequestKeyCounts.delete(cacheKey);
1204
+ });
1205
+ return promise;
1206
+ }
1207
+ async get(key, options) {
1208
+ const cacheKey = $81959a80f9a6789a$export$d09252bd498a9707(key);
1209
+ const cached = this.#fromCache(cacheKey);
1210
+ if (cached !== undefined) return cached;
1211
+ const workerOptions = $81959a80f9a6789a$var$copyToTransferableRequestInit(options);
1212
+ const abort = options?.signal ?? undefined;
1213
+ return this.#doFetch(key, undefined, workerOptions, abort);
1214
+ }
1215
+ async getRange(key, range, options) {
1216
+ const cacheKey = $81959a80f9a6789a$export$d09252bd498a9707(key, range);
1217
+ const cached = this.#fromCache(cacheKey);
1218
+ if (cached !== undefined) return cached;
1219
+ const workerOptions = $81959a80f9a6789a$var$copyToTransferableRequestInit(options);
1220
+ const abort = options?.signal ?? undefined;
1221
+ return this.#doFetch(key, range, workerOptions, abort);
1222
+ }
1223
+ }
1224
+ class $81959a80f9a6789a$export$80a50be84de8c993 extends $81959a80f9a6789a$export$927188fe483fb171 {
1225
+ constructor(url, workerModule, options){
1226
+ super(url, new (0, $7soKB$WorkerPool)(options?.numWorkers ?? $81959a80f9a6789a$var$DEFAULT_NUM_WORKERS, workerModule), options);
1227
+ }
1228
+ }
1229
+
1230
+
1231
+ function $845a7aab26aa4fe6$export$fc561c682218655c(url, workerModule, options) {
1232
+ const store = new (0, $81959a80f9a6789a$export$80a50be84de8c993)(url, workerModule, options);
1233
+ const getSlice = async (metadata, req, level, signal)=>{
1234
+ if (metadata.url !== url) throw new Error('trying to use a decoder from a different store - we cant do that yet, although we could build a map of url->stores here if we wanted later - TODO');
1235
+ const scene = metadata.attrs.multiscales[0];
1236
+ const { axes: axes } = scene;
1237
+ if (!level) {
1238
+ const message = 'invalid Zarr data: no datasets found';
1239
+ (0, $7soKB$logger).error(message);
1240
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
1241
+ }
1242
+ const arr = metadata.arrays.find((a)=>a.path === level.path);
1243
+ if (!arr) {
1244
+ const message = `cannot load slice: no array found for path [${level.path}]`;
1245
+ (0, $7soKB$logger).error(message);
1246
+ throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
1247
+ }
1248
+ const { raw: raw } = await (0, $62574ebf548584b6$export$ab574f5010f64a15)(store, arr.path, metadata.zarrVersion, false);
1249
+ const result = await $7soKB$get(raw, (0, $62574ebf548584b6$export$d7b58f10109feb02)(req, axes, level.shape), {
1250
+ opts: {
1251
+ signal: signal ?? null
1252
+ }
1253
+ });
1254
+ if (typeof result === 'number') throw new Error('oh noes, slice came back all weird');
1255
+ const { shape: shape, data: data } = result;
1256
+ if (typeof data !== 'object' || !('buffer' in data)) throw new Error('slice was malformed, array-buffer response required');
1257
+ // biome-ignore lint/suspicious/noExplicitAny: <hard to prove - but the typeof check above is sufficient for this to be safe>
1258
+ return {
1259
+ shape: shape,
1260
+ data: new Float32Array(data)
1261
+ };
1262
+ };
1263
+ return {
1264
+ decoder: getSlice,
1265
+ destroy: ()=>{
1266
+ store.destroy();
1267
+ }
1268
+ };
1269
+ }
1270
+
1271
+
1272
+ // a web-worker which fetches slices of data, decodes them, and returns the result as a flat float32 array, using transferables
1273
+
1274
+
1275
+
1276
+ const $b2fe35b4140f0787$var$NUM_RETRIES = 2;
1277
+ const $b2fe35b4140f0787$var$RETRY_DELAY_MS = 500;
1278
+ const $b2fe35b4140f0787$var$fetchFile = async (rootUrl, path, options, abortController)=>{
1279
+ const store = new (0, $7soKB$FetchStore)(rootUrl);
1280
+ return store.get(path, {
1281
+ ...options || {},
1282
+ signal: abortController?.signal ?? null
1283
+ });
1284
+ };
1285
+ const $b2fe35b4140f0787$var$fetchSlice = async (rootUrl, path, range, options, abortController)=>{
1286
+ const store = new (0, $7soKB$FetchStore)(rootUrl);
1287
+ const wait = async (ms)=>new Promise((resolve)=>{
1288
+ setTimeout(resolve, ms);
1289
+ });
1290
+ for(let i = 0; i < $b2fe35b4140f0787$var$NUM_RETRIES; i++)try {
1291
+ return await store.getRange(path, range, {
1292
+ ...options || {},
1293
+ signal: abortController?.signal ?? null
1294
+ });
1295
+ } catch (e) {
1296
+ (0, $7soKB$logger).error('getRange request failed:', e);
1297
+ const hasRetries = i < $b2fe35b4140f0787$var$NUM_RETRIES - 1;
1298
+ const message = `getRange request ${i < $b2fe35b4140f0787$var$NUM_RETRIES - 1 ? `will retry in ${$b2fe35b4140f0787$var$RETRY_DELAY_MS}ms` : 'has no retries left'}`;
1299
+ (0, $7soKB$logger).warn(message);
1300
+ if (hasRetries) await wait($b2fe35b4140f0787$var$RETRY_DELAY_MS);
1301
+ }
1302
+ return undefined;
1303
+ };
1304
+ const $b2fe35b4140f0787$var$handleFetch = (message, abortControllers)=>{
1305
+ const { id: id, payload: payload } = message;
1306
+ const { rootUrl: rootUrl, path: path, range: range, options: options } = payload;
1307
+ if (id in abortControllers) {
1308
+ (0, $7soKB$logger).error('cannot send message: request ID already in use');
1309
+ return;
1310
+ }
1311
+ const abort = new AbortController();
1312
+ abortControllers[id] = abort;
1313
+ const fetchFn = range !== undefined ? ()=>$b2fe35b4140f0787$var$fetchSlice(rootUrl, path, range, options, abort) : ()=>$b2fe35b4140f0787$var$fetchFile(rootUrl, path, options, abort);
1314
+ fetchFn().then((result)=>{
1315
+ const buffer = result?.buffer;
1316
+ const options = buffer !== undefined ? {
1317
+ transfer: [
1318
+ buffer
1319
+ ]
1320
+ } : {};
1321
+ self.postMessage({
1322
+ type: (0, $5b408c6c3c009876$export$d7c94d771e5d9aa7),
1323
+ id: id,
1324
+ payload: result?.buffer
1325
+ }, {
1326
+ ...options
1327
+ });
1328
+ }).catch((e)=>{
1329
+ if (!(0, $5b408c6c3c009876$export$2b3d06107d1323d4)(e)) (0, $7soKB$logger).error('error in slice fetch worker: ', e);
1330
+ // can ignore if it is a cancellation error
1331
+ });
1332
+ };
1333
+ const $b2fe35b4140f0787$var$handleCancel = (message, abortControllers)=>{
1334
+ const { id: id } = message;
1335
+ const abortController = abortControllers[id];
1336
+ if (!abortController) (0, $7soKB$logger).warn('attempted to cancel a non-existent request');
1337
+ else abortController.abort('cancelled');
1338
+ };
1339
+ const $b2fe35b4140f0787$var$startHeartbeat = ()=>setInterval(()=>{
1340
+ self.postMessage({
1341
+ type: 'heartbeat'
1342
+ });
1343
+ }, (0, $7soKB$HEARTBEAT_RATE_MS));
1344
+ const $b2fe35b4140f0787$var$setupOnMessage = ()=>{
1345
+ const abortControllers = {};
1346
+ const onmessage = async (e)=>{
1347
+ const { data: message } = e;
1348
+ if ((0, $5b408c6c3c009876$export$ced8a9318e8c4d3d)(message)) $b2fe35b4140f0787$var$handleFetch(message, abortControllers);
1349
+ else if ((0, $5b408c6c3c009876$export$a77d75797e75745f)(message)) $b2fe35b4140f0787$var$handleCancel(message, abortControllers);
1350
+ };
1351
+ return onmessage;
1352
+ };
1353
+ const $b2fe35b4140f0787$export$4908e147e219e01a = (ctx)=>{
1354
+ ctx.onmessage = $b2fe35b4140f0787$var$setupOnMessage();
1355
+ return {
1356
+ startHeartbeat: $b2fe35b4140f0787$var$startHeartbeat
1357
+ };
1358
+ };
1359
+
1360
+
1361
+
1362
+
1363
+
1364
+ export {$6f9a458a1fcc6b82$export$c97bf2bbe9bf6d5e as buildOmeZarrSliceRenderer, $6f9a458a1fcc6b82$export$79b7536e23e20727 as buildAsyncOmezarrRenderer, $8af220877f5aad67$export$96bea966bad52d02 as VisZarrError, $8af220877f5aad67$export$e819e674f1e05236 as VisZarrDataError, $8af220877f5aad67$export$d7f857358a0dbda6 as VisZarrIndexError, $4a90fbb98bec80dd$export$e83f4de492e8b929 as defaultDecoder, $4a90fbb98bec80dd$export$2957f72eb8eb81d4 as getVisibleTiles, $3e6603f747b5a8a4$export$640f994018c81008 as buildTileRenderCommand, $3e6603f747b5a8a4$export$e1c4d8365a017448 as buildRGBTileRenderCommand, $0ff6a7cfdd9baaf1$export$9989519d74cf4fd0 as OmeZarrAxisSchema, $0ff6a7cfdd9baaf1$export$13526d3947c5c7c2 as OmeZarrCoordinateTranslationSchema, $0ff6a7cfdd9baaf1$export$f0f448c9214bb1a1 as OmeZarrCoordinateScaleSchema, $0ff6a7cfdd9baaf1$export$2e1c7be8e43a67e3 as OmeZarrCoordinateTransformSchema, $0ff6a7cfdd9baaf1$export$a535e1d8aa90b3c9 as OmeZarrDatasetSchema, $0ff6a7cfdd9baaf1$export$d7d6a65692bb1dc0 as OmeZarrMultiscaleSchema, $0ff6a7cfdd9baaf1$export$90729eda236ba57 as OmeZarrOmeroChannelWindowSchema, $0ff6a7cfdd9baaf1$export$bb4e42bb52e6d21d as OmeZarrOmeroChannelSchema, $0ff6a7cfdd9baaf1$export$51e803dddccc5479 as OmeZarrOmeroSchema, $0ff6a7cfdd9baaf1$export$a3b48a0a4f3d252 as OmeZarrAttrsSchema, $0ff6a7cfdd9baaf1$export$c7c266bed5c41e68 as OmeZarrMetadata, $62574ebf548584b6$export$7999b0bb51b3dcb8 as loadMetadata, $62574ebf548584b6$export$7f36aeab32ab33f7 as loadZarrArrayFile, $62574ebf548584b6$export$78b8536ed7d8a60d as loadZarrAttrsFile, $62574ebf548584b6$export$8efeb0367ee93033 as pickBestScale, $62574ebf548584b6$export$831e2eeffaa681 as loadSlice, $62574ebf548584b6$export$c5890dae76bd0ad7 as sizeInUnits, $62574ebf548584b6$export$fcb1a44ca126ee5c as sizeInVoxels, $62574ebf548584b6$export$ca023b1dd6252668 as nextSliceStep, $62574ebf548584b6$export$ba17f86721d4d0ce as planeSizeInVoxels, $e7ae61881db7ab65$export$79bc3a420a6742ac as makeOmeZarrSliceLoaderWorker, $845a7aab26aa4fe6$export$fc561c682218655c as decoderFactory, $b2fe35b4140f0787$export$4908e147e219e01a as setupFetchDataWorker, $5b408c6c3c009876$export$ced8a9318e8c4d3d as isFetchMessage, $5b408c6c3c009876$export$87cac8e8f93fed1d as isFetchResponseMessage, $5b408c6c3c009876$export$a77d75797e75745f as isCancelMessage, $5b408c6c3c009876$export$2b3d06107d1323d4 as isCancellationError};
1365
+ //# sourceMappingURL=main.js.map