@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/LICENSE.md +11 -0
- package/dist/main.js +1365 -0
- package/dist/main.js.map +1 -0
- package/dist/module.js +969 -0
- package/dist/module.js.map +1 -0
- package/dist/types.d.ts +418 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +58 -0
package/dist/module.js
ADDED
|
@@ -0,0 +1,969 @@
|
|
|
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} 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 {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$var$loadZarrArrayFileFromStore(store, path, version, loadV2Attrs);
|
|
415
|
+
return result.metadata;
|
|
416
|
+
}
|
|
417
|
+
async function $62574ebf548584b6$var$loadZarrArrayFileFromStore(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$var$loadZarrArrayFileFromStore(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
|
+
// feel free to freak out if the request is over or under determined or whatever
|
|
542
|
+
function $62574ebf548584b6$var$buildQuery(r, axes, shape) {
|
|
543
|
+
const ordered = axes.map((a)=>r[a.name]);
|
|
544
|
+
// if any are undefined, throw up
|
|
545
|
+
if (ordered.some((a)=>a === undefined)) throw new (0, $8af220877f5aad67$export$e819e674f1e05236)('request does not match expected dimensions of OME-Zarr dataset');
|
|
546
|
+
return ordered.map((d, i)=>{
|
|
547
|
+
const bounds = {
|
|
548
|
+
min: 0,
|
|
549
|
+
max: shape[i]
|
|
550
|
+
};
|
|
551
|
+
if (d === null) return d;
|
|
552
|
+
if (typeof d === 'number') return (0, $7soKB$limit)(bounds, d);
|
|
553
|
+
return $7soKB$slice((0, $7soKB$limit)(bounds, d.min), (0, $7soKB$limit)(bounds, d.max));
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
async function $62574ebf548584b6$export$151d38946e654182(z) {
|
|
557
|
+
(0, $7soKB$logger).dir(z);
|
|
558
|
+
}
|
|
559
|
+
async function $62574ebf548584b6$export$831e2eeffaa681(metadata, r, level, signal) {
|
|
560
|
+
// put the request in native order
|
|
561
|
+
const store = new $7soKB$FetchStore(metadata.url);
|
|
562
|
+
const scene = metadata.attrs.multiscales[0];
|
|
563
|
+
const { axes: axes } = scene;
|
|
564
|
+
if (!level) {
|
|
565
|
+
const message = 'invalid Zarr data: no datasets found';
|
|
566
|
+
(0, $7soKB$logger).error(message);
|
|
567
|
+
throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
|
|
568
|
+
}
|
|
569
|
+
const arr = metadata.arrays.find((a)=>a.path === level.path);
|
|
570
|
+
if (!arr) {
|
|
571
|
+
const message = `cannot load slice: no array found for path [${level.path}]`;
|
|
572
|
+
(0, $7soKB$logger).error(message);
|
|
573
|
+
throw new (0, $8af220877f5aad67$export$e819e674f1e05236)(message);
|
|
574
|
+
}
|
|
575
|
+
const { raw: raw } = await $62574ebf548584b6$var$loadZarrArrayFileFromStore(store, arr.path, metadata.zarrVersion, false);
|
|
576
|
+
const result = await $7soKB$get(raw, $62574ebf548584b6$var$buildQuery(r, axes, level.shape), {
|
|
577
|
+
opts: {
|
|
578
|
+
signal: signal ?? null
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
if (typeof result === 'number') throw new Error('oh noes, slice came back all weird');
|
|
582
|
+
return {
|
|
583
|
+
shape: result.shape,
|
|
584
|
+
buffer: result
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* given a image with @param size pixels, break it into tiles, each @param idealTilePx.
|
|
591
|
+
* for all such tiles which intersect the given bounds, call the visitor
|
|
592
|
+
* @param idealTilePx the size of a tile, in pixels
|
|
593
|
+
* @param size the size of the image at this level of detail
|
|
594
|
+
* @param bounds visit only the tiles that are within the given bounds (in pixels)
|
|
595
|
+
*/ function $4a90fbb98bec80dd$var$visitTilesWithin(idealTilePx, size, bounds, visit) {
|
|
596
|
+
const withinBoth = (0, $7soKB$Box2D).intersection(bounds, (0, $7soKB$Box2D).create([
|
|
597
|
+
0,
|
|
598
|
+
0
|
|
599
|
+
], size));
|
|
600
|
+
if (!withinBoth) return;
|
|
601
|
+
// convert the image into tile indexes:
|
|
602
|
+
const boundsInTiles = (0, $7soKB$Box2D).map(withinBoth, (corner)=>(0, $7soKB$Vec2).div(corner, idealTilePx));
|
|
603
|
+
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){
|
|
604
|
+
// all tiles visited are always within both the bounds, and the image itself
|
|
605
|
+
const lo = (0, $7soKB$Vec2).mul([
|
|
606
|
+
x,
|
|
607
|
+
y
|
|
608
|
+
], idealTilePx);
|
|
609
|
+
const hi = (0, $7soKB$Vec2).min(size, (0, $7soKB$Vec2).add(lo, idealTilePx));
|
|
610
|
+
visit((0, $7soKB$Box2D).create(lo, hi));
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
function $4a90fbb98bec80dd$var$getVisibleTilesInLayer(camera, plane, orthoVal, dataset, tileSize, level) {
|
|
614
|
+
const size = (0, $62574ebf548584b6$export$ba17f86721d4d0ce)(plane, dataset.attrs.multiscales[0].axes, level);
|
|
615
|
+
const realSize = (0, $62574ebf548584b6$export$c5890dae76bd0ad7)(plane, dataset.attrs.multiscales[0].axes, level);
|
|
616
|
+
if (!size || !realSize) return [];
|
|
617
|
+
const scale = (0, $7soKB$Vec2).div(realSize, size);
|
|
618
|
+
const vxlToReal = (vxl)=>(0, $7soKB$Box2D).scale(vxl, scale);
|
|
619
|
+
const realToVxl = (real)=>(0, $7soKB$Box2D).scale(real, (0, $7soKB$Vec2).div([
|
|
620
|
+
1,
|
|
621
|
+
1
|
|
622
|
+
], scale));
|
|
623
|
+
const visibleTiles = [];
|
|
624
|
+
$4a90fbb98bec80dd$var$visitTilesWithin([
|
|
625
|
+
tileSize,
|
|
626
|
+
tileSize
|
|
627
|
+
], size, realToVxl(camera.view), (uv)=>{
|
|
628
|
+
visibleTiles.push({
|
|
629
|
+
plane: plane.axes,
|
|
630
|
+
realBounds: vxlToReal(uv),
|
|
631
|
+
bounds: uv,
|
|
632
|
+
orthoVal: orthoVal,
|
|
633
|
+
level: level
|
|
634
|
+
});
|
|
635
|
+
});
|
|
636
|
+
return visibleTiles;
|
|
637
|
+
}
|
|
638
|
+
function $4a90fbb98bec80dd$export$2957f72eb8eb81d4(camera, plane, planeLocation, metadata, tileSize) {
|
|
639
|
+
// TODO (someday) open the array, look at its chunks, use that size for the size of the tiles I request!
|
|
640
|
+
const layer = (0, $62574ebf548584b6$export$8efeb0367ee93033)(metadata, plane, camera.view, camera.screenSize);
|
|
641
|
+
// figure out the index of the slice
|
|
642
|
+
const sliceIndex = (0, $62574ebf548584b6$export$81eb4b4b765d519)(layer, metadata.attrs.multiscales[0].axes, planeLocation, plane.ortho);
|
|
643
|
+
return $4a90fbb98bec80dd$var$getVisibleTilesInLayer(camera, plane, sliceIndex, metadata, tileSize, layer);
|
|
644
|
+
}
|
|
645
|
+
const $4a90fbb98bec80dd$export$e83f4de492e8b929 = (metadata, r, level, signal)=>{
|
|
646
|
+
return (0, $62574ebf548584b6$export$831e2eeffaa681)(metadata, r, level, signal).then((result)=>{
|
|
647
|
+
const { shape: shape, buffer: buffer } = result;
|
|
648
|
+
return {
|
|
649
|
+
shape: shape,
|
|
650
|
+
data: new Float32Array(buffer.data)
|
|
651
|
+
};
|
|
652
|
+
});
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
// render a slice of an ome-zarr file as a 2D image
|
|
657
|
+
// note that the ome-zarr data must have exactly 3 channels
|
|
658
|
+
// the channels may be mapped to color-channels (RGB) with a basic 2-post gamut control
|
|
659
|
+
const $3e6603f747b5a8a4$var$vert = /*glsl*/ `
|
|
660
|
+
precision highp float;
|
|
661
|
+
attribute vec2 pos;
|
|
662
|
+
|
|
663
|
+
uniform vec4 view;
|
|
664
|
+
uniform vec4 tile;
|
|
665
|
+
uniform float depth;
|
|
666
|
+
varying vec2 texCoord;
|
|
667
|
+
uniform float rot;
|
|
668
|
+
|
|
669
|
+
void main(){
|
|
670
|
+
vec2 tileSize = tile.zw-tile.xy;
|
|
671
|
+
texCoord = pos;
|
|
672
|
+
vec2 obj = (pos.xy*tileSize+tile.xy);
|
|
673
|
+
|
|
674
|
+
vec2 p = (obj-view.xy)/(view.zw-view.xy);
|
|
675
|
+
// now, to clip space
|
|
676
|
+
p = (p*2.0)-1.0;
|
|
677
|
+
gl_Position = vec4(p.x,p.y,depth,1.0);
|
|
678
|
+
}
|
|
679
|
+
`;
|
|
680
|
+
function $3e6603f747b5a8a4$export$36d69f6355ac98ab(regl) {
|
|
681
|
+
const cmd = regl({
|
|
682
|
+
vert: $3e6603f747b5a8a4$var$vert,
|
|
683
|
+
frag: `
|
|
684
|
+
precision highp float;
|
|
685
|
+
uniform sampler2D R;
|
|
686
|
+
uniform sampler2D G;
|
|
687
|
+
uniform sampler2D B; // for reasons which are pretty annoying
|
|
688
|
+
// its more direct to do 3 separate channels...
|
|
689
|
+
uniform vec2 Rgamut;
|
|
690
|
+
uniform vec2 Ggamut;
|
|
691
|
+
uniform vec2 Bgamut;
|
|
692
|
+
|
|
693
|
+
varying vec2 texCoord;
|
|
694
|
+
void main(){
|
|
695
|
+
vec3 mins = vec3(Rgamut.x,Ggamut.x,Bgamut.x);
|
|
696
|
+
vec3 maxs = vec3(Rgamut.y,Ggamut.y,Bgamut.y);
|
|
697
|
+
vec3 span = maxs-mins;
|
|
698
|
+
vec3 color = (vec3(
|
|
699
|
+
texture2D(R, texCoord).r,
|
|
700
|
+
texture2D(G, texCoord).r,
|
|
701
|
+
texture2D(B, texCoord).r
|
|
702
|
+
)-mins) /span;
|
|
703
|
+
|
|
704
|
+
gl_FragColor = vec4(color, 1.0);
|
|
705
|
+
}`,
|
|
706
|
+
framebuffer: regl.prop('target'),
|
|
707
|
+
attributes: {
|
|
708
|
+
pos: [
|
|
709
|
+
0,
|
|
710
|
+
0,
|
|
711
|
+
1,
|
|
712
|
+
0,
|
|
713
|
+
1,
|
|
714
|
+
1,
|
|
715
|
+
0,
|
|
716
|
+
1
|
|
717
|
+
]
|
|
718
|
+
},
|
|
719
|
+
uniforms: {
|
|
720
|
+
tile: regl.prop('tile'),
|
|
721
|
+
view: regl.prop('view'),
|
|
722
|
+
depth: regl.prop('depth'),
|
|
723
|
+
R: regl.prop('R'),
|
|
724
|
+
G: regl.prop('G'),
|
|
725
|
+
B: regl.prop('B'),
|
|
726
|
+
Rgamut: regl.prop('Rgamut'),
|
|
727
|
+
Ggamut: regl.prop('Ggamut'),
|
|
728
|
+
Bgamut: regl.prop('Bgamut')
|
|
729
|
+
},
|
|
730
|
+
depth: {
|
|
731
|
+
enable: true
|
|
732
|
+
},
|
|
733
|
+
count: 4,
|
|
734
|
+
primitive: 'triangle fan'
|
|
735
|
+
});
|
|
736
|
+
return (p)=>cmd(p);
|
|
737
|
+
}
|
|
738
|
+
function $3e6603f747b5a8a4$export$ecfa859e3c9f4021(regl, numChannels) {
|
|
739
|
+
const reglChannelUniforms = [];
|
|
740
|
+
const fragmentChannelUniformDefs = [];
|
|
741
|
+
const colorMerges = [];
|
|
742
|
+
for(let i = 0; i < numChannels; i++){
|
|
743
|
+
reglChannelUniforms.push({
|
|
744
|
+
[`gamut${i}`]: (_context, props)=>props.channels[i].gamut,
|
|
745
|
+
[`color${i}`]: (_context, props)=>props.channels[i].rgb,
|
|
746
|
+
[`tex${i}`]: (_context, props)=>props.channels[i].tex
|
|
747
|
+
});
|
|
748
|
+
fragmentChannelUniformDefs.push(`uniform vec2 gamut${i};`);
|
|
749
|
+
fragmentChannelUniformDefs.push(`uniform vec3 color${i};`);
|
|
750
|
+
fragmentChannelUniformDefs.push(`uniform sampler2D tex${i};`);
|
|
751
|
+
colorMerges.push(`
|
|
752
|
+
float ch${i}Val = texture2D(tex${i}, texCoord).r;
|
|
753
|
+
ch${i}Val = (ch${i}Val - gamut${i}.x) / (gamut${i}.y - gamut${i}.x);
|
|
754
|
+
color += (color${i} * ch${i}Val);
|
|
755
|
+
`);
|
|
756
|
+
}
|
|
757
|
+
const staticReglUniforms = {
|
|
758
|
+
tile: regl.prop('tile'),
|
|
759
|
+
view: regl.prop('view'),
|
|
760
|
+
depth: regl.prop('depth')
|
|
761
|
+
};
|
|
762
|
+
const uniforms = reglChannelUniforms.reduce((acc, curr)=>{
|
|
763
|
+
for(const key in curr)acc[key] = curr[key];
|
|
764
|
+
return acc;
|
|
765
|
+
}, staticReglUniforms);
|
|
766
|
+
const frag = `
|
|
767
|
+
precision highp float;
|
|
768
|
+
${fragmentChannelUniformDefs.join('\n')}
|
|
769
|
+
varying vec2 texCoord;
|
|
770
|
+
|
|
771
|
+
void main() {
|
|
772
|
+
vec3 color = vec3(0.0, 0.0, 0.0);
|
|
773
|
+
${colorMerges.join('\n')}
|
|
774
|
+
color = clamp(color, 0.0, 1.0);
|
|
775
|
+
gl_FragColor = vec4(color, 1.0);
|
|
776
|
+
}`;
|
|
777
|
+
// biome-ignore lint/suspicious/noExplicitAny: type of uniforms cannot be given explicitly due to dynamic nature of uniforms in these shaders
|
|
778
|
+
const cmd = regl({
|
|
779
|
+
vert: $3e6603f747b5a8a4$var$vert,
|
|
780
|
+
frag: frag,
|
|
781
|
+
framebuffer: regl.prop('target'),
|
|
782
|
+
attributes: {
|
|
783
|
+
pos: [
|
|
784
|
+
0,
|
|
785
|
+
0,
|
|
786
|
+
1,
|
|
787
|
+
0,
|
|
788
|
+
1,
|
|
789
|
+
1,
|
|
790
|
+
0,
|
|
791
|
+
1
|
|
792
|
+
]
|
|
793
|
+
},
|
|
794
|
+
uniforms: uniforms,
|
|
795
|
+
depth: {
|
|
796
|
+
enable: true
|
|
797
|
+
},
|
|
798
|
+
count: 4,
|
|
799
|
+
primitive: 'triangle fan'
|
|
800
|
+
});
|
|
801
|
+
return (p)=>cmd(p);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
function $6f9a458a1fcc6b82$var$toZarrRequest(tile, channel) {
|
|
806
|
+
const { plane: plane, orthoVal: orthoVal, bounds: bounds } = tile;
|
|
807
|
+
const { minCorner: min, maxCorner: max } = bounds;
|
|
808
|
+
const u = {
|
|
809
|
+
min: min[0],
|
|
810
|
+
max: max[0]
|
|
811
|
+
};
|
|
812
|
+
const v = {
|
|
813
|
+
min: min[1],
|
|
814
|
+
max: max[1]
|
|
815
|
+
};
|
|
816
|
+
switch(plane){
|
|
817
|
+
case 'xy':
|
|
818
|
+
return {
|
|
819
|
+
x: u,
|
|
820
|
+
y: v,
|
|
821
|
+
t: 0,
|
|
822
|
+
c: channel,
|
|
823
|
+
z: orthoVal
|
|
824
|
+
};
|
|
825
|
+
case 'xz':
|
|
826
|
+
return {
|
|
827
|
+
x: u,
|
|
828
|
+
z: v,
|
|
829
|
+
t: 0,
|
|
830
|
+
c: channel,
|
|
831
|
+
y: orthoVal
|
|
832
|
+
};
|
|
833
|
+
case 'yz':
|
|
834
|
+
return {
|
|
835
|
+
y: u,
|
|
836
|
+
z: v,
|
|
837
|
+
t: 0,
|
|
838
|
+
c: channel,
|
|
839
|
+
x: orthoVal
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
function $6f9a458a1fcc6b82$var$isPrepared(cacheData) {
|
|
844
|
+
if (!cacheData) return false;
|
|
845
|
+
const keys = Object.keys(cacheData);
|
|
846
|
+
if (keys.length < 1) return false;
|
|
847
|
+
return keys.every((key)=>cacheData[key]?.type === 'texture');
|
|
848
|
+
}
|
|
849
|
+
const $6f9a458a1fcc6b82$var$DEFAULT_NUM_CHANNELS = 3;
|
|
850
|
+
function $6f9a458a1fcc6b82$export$c97bf2bbe9bf6d5e(regl, decoder, options) {
|
|
851
|
+
const numChannels = options?.numChannels ?? $6f9a458a1fcc6b82$var$DEFAULT_NUM_CHANNELS;
|
|
852
|
+
function sliceAsTexture(slice) {
|
|
853
|
+
const { data: data, shape: shape } = slice;
|
|
854
|
+
return {
|
|
855
|
+
bytes: data.byteLength,
|
|
856
|
+
texture: regl.texture({
|
|
857
|
+
data: data,
|
|
858
|
+
width: shape[1],
|
|
859
|
+
height: shape[0],
|
|
860
|
+
format: 'luminance'
|
|
861
|
+
}),
|
|
862
|
+
type: 'texture'
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
const cmd = (0, $3e6603f747b5a8a4$export$ecfa859e3c9f4021)(regl, numChannels);
|
|
866
|
+
return {
|
|
867
|
+
cacheKey: (item, requestKey, dataset, settings)=>{
|
|
868
|
+
const channelKeys = Object.keys(settings.channels);
|
|
869
|
+
if (!channelKeys.includes(requestKey)) {
|
|
870
|
+
const message = `cannot retrieve cache key: unrecognized requestKey [${requestKey}]`;
|
|
871
|
+
(0, $7soKB$logger).error(message);
|
|
872
|
+
throw new Error(message);
|
|
873
|
+
}
|
|
874
|
+
return `${dataset.url}_${JSON.stringify(item)}_ch=${requestKey}`;
|
|
875
|
+
},
|
|
876
|
+
destroy: ()=>{},
|
|
877
|
+
getVisibleItems: (dataset, settings)=>{
|
|
878
|
+
const { camera: camera, plane: plane, planeLocation: planeLocation, tileSize: tileSize } = settings;
|
|
879
|
+
return (0, $4a90fbb98bec80dd$export$2957f72eb8eb81d4)(camera, plane, planeLocation, dataset, tileSize);
|
|
880
|
+
},
|
|
881
|
+
fetchItemContent: (item, dataset, settings)=>{
|
|
882
|
+
const contents = {};
|
|
883
|
+
for(const key in settings.channels)contents[key] = (signal)=>decoder(dataset, $6f9a458a1fcc6b82$var$toZarrRequest(item, settings.channels[key].index), item.level, signal).then(sliceAsTexture);
|
|
884
|
+
return contents;
|
|
885
|
+
},
|
|
886
|
+
isPrepared: $6f9a458a1fcc6b82$var$isPrepared,
|
|
887
|
+
renderItem: (target, item, dataset, settings, gpuData)=>{
|
|
888
|
+
const channels = Object.keys(gpuData).map((key)=>({
|
|
889
|
+
tex: gpuData[key].texture,
|
|
890
|
+
gamut: (0, $7soKB$intervalToVec2)(settings.channels[key].gamut),
|
|
891
|
+
rgb: settings.channels[key].rgb
|
|
892
|
+
}));
|
|
893
|
+
const layers = dataset.getNumLayers();
|
|
894
|
+
// per the spec, the highest resolution layer should be first
|
|
895
|
+
// we want that layer most in front, so:
|
|
896
|
+
const depth = item.level.datasetIndex / layers;
|
|
897
|
+
const { camera: camera } = settings;
|
|
898
|
+
cmd({
|
|
899
|
+
channels: channels,
|
|
900
|
+
target: target,
|
|
901
|
+
depth: depth,
|
|
902
|
+
tile: (0, $7soKB$Box2D).toFlatArray(item.realBounds),
|
|
903
|
+
view: (0, $7soKB$Box2D).toFlatArray(camera.view)
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
function $6f9a458a1fcc6b82$export$79b7536e23e20727(regl, decoder, options) {
|
|
909
|
+
return (0, $7soKB$buildAsyncRenderer)($6f9a458a1fcc6b82$export$c97bf2bbe9bf6d5e(regl, decoder, options), options?.queueOptions);
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
function $e7ae61881db7ab65$var$isSliceRequest(payload) {
|
|
922
|
+
return typeof payload === 'object' && payload !== null && 'type' in payload && payload.type === 'ZarrSliceRequest';
|
|
923
|
+
}
|
|
924
|
+
function $e7ae61881db7ab65$var$isCancellationRequest(payload) {
|
|
925
|
+
return typeof payload === 'object' && payload !== null && 'type' in payload && payload.type === 'cancel';
|
|
926
|
+
}
|
|
927
|
+
function $e7ae61881db7ab65$export$79bc3a420a6742ac(ctx) {
|
|
928
|
+
const cancelers = {};
|
|
929
|
+
ctx.onmessage = (msg)=>{
|
|
930
|
+
const { data: data } = msg;
|
|
931
|
+
try {
|
|
932
|
+
if ($e7ae61881db7ab65$var$isSliceRequest(data)) {
|
|
933
|
+
const { metadata: dehydratedMetadata, req: req, level: level, id: id } = data;
|
|
934
|
+
const abort = new AbortController();
|
|
935
|
+
cancelers[id] = abort;
|
|
936
|
+
(0, $0ff6a7cfdd9baaf1$export$c7c266bed5c41e68).rehydrate(dehydratedMetadata).then((metadata)=>{
|
|
937
|
+
(0, $62574ebf548584b6$export$831e2eeffaa681)(metadata, req, level, abort.signal).then((result)=>{
|
|
938
|
+
const { shape: shape, buffer: buffer } = result;
|
|
939
|
+
const data = new Float32Array(buffer.data);
|
|
940
|
+
ctx.postMessage({
|
|
941
|
+
type: 'slice',
|
|
942
|
+
id: id,
|
|
943
|
+
shape: shape,
|
|
944
|
+
data: data
|
|
945
|
+
}, {
|
|
946
|
+
transfer: [
|
|
947
|
+
data.buffer
|
|
948
|
+
]
|
|
949
|
+
});
|
|
950
|
+
}).catch((err)=>{
|
|
951
|
+
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);
|
|
952
|
+
// else ignore it
|
|
953
|
+
});
|
|
954
|
+
});
|
|
955
|
+
} else if ($e7ae61881db7ab65$var$isCancellationRequest(data)) {
|
|
956
|
+
const { id: id } = data;
|
|
957
|
+
cancelers[id]?.abort('cancelled');
|
|
958
|
+
} else (0, $7soKB$logger).error('web-worker slice-fetcher recieved incomprehensible message: ', msg);
|
|
959
|
+
} catch (err) {
|
|
960
|
+
(0, $7soKB$logger).error('OME-Zarr fetch onmessage error', err);
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
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$ecfa859e3c9f4021 as buildTileRenderer, $3e6603f747b5a8a4$export$36d69f6355ac98ab as buildRGBTileRenderer, $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};
|
|
969
|
+
//# sourceMappingURL=module.js.map
|