omezarr-tilesource 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +188 -58
- package/dist/omezarr-tilesource.d.ts +521 -24
- package/dist/omezarr-tilesource.js +229 -104
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,33 +38,47 @@ import { OMEZarrTileSource } from "omezarr-tilesource";
|
|
|
38
38
|
|
|
39
39
|
const url = ...;
|
|
40
40
|
|
|
41
|
-
//
|
|
41
|
+
// register the tile source and its data type converters with OpenSeadragon
|
|
42
|
+
// (required for inline configurations and URLs, see "Data pipeline" below)
|
|
43
|
+
OMEZarrTileSource.enable(OpenSeadragon);
|
|
44
|
+
|
|
45
|
+
// configuration with URL (only works with zipped OME-Zarr URLs, path ending in .ozx)
|
|
42
46
|
const tileSource1 = url;
|
|
43
47
|
|
|
44
|
-
// inline configuration with options object
|
|
45
|
-
OMEZarrTileSource.enable(OpenSeadragon);
|
|
48
|
+
// inline configuration with options object
|
|
46
49
|
const tileSource2 = {
|
|
47
50
|
type: "ome-zarr",
|
|
48
51
|
url: url,
|
|
49
|
-
// zip: undefined, // undefined = OME-Zarr ZIP auto-detection based on .ozx suffix
|
|
50
|
-
// c: undefined, // undefined = composite of all active channels (requires dataType "context2d")
|
|
51
|
-
// z: undefined, // undefined = omero rdefs default (middle z-slice if missing)
|
|
52
|
+
// zip: undefined, // undefined = OME-Zarr ZIP auto-detection based on .ozx path suffix
|
|
52
53
|
// t: undefined, // undefined = omero rdefs default (middle timepoint if missing)
|
|
53
|
-
//
|
|
54
|
+
// z: undefined, // undefined = omero rdefs default (middle z-slice if missing)
|
|
55
|
+
// c: undefined, // channel index or array of indices; undefined = all active channels
|
|
56
|
+
// range: undefined, // contrast limits [min, max] or array thereof; undefined = omero windows
|
|
57
|
+
// color: undefined, // RGB color or array of colors; undefined = omero channel colors
|
|
58
|
+
// lutOrColorMap: undefined, // LUT/color map or array thereof; undefined = omero LUTs
|
|
59
|
+
// inverted: undefined, // boolean or array of booleans; undefined = omero inversion
|
|
54
60
|
// autoBoost: undefined // boost brightness of dark tiles (default false)
|
|
55
61
|
};
|
|
56
62
|
|
|
57
63
|
// direct instantiation with URL (works with any OME-Zarr storage backend)
|
|
58
64
|
const tileSource3 = new OMEZarrTileSource(url);
|
|
59
65
|
|
|
60
|
-
// direct instantiation with
|
|
61
|
-
|
|
66
|
+
// direct instantiation with a File (or any Blob) holding a zipped OME-Zarr file,
|
|
67
|
+
// e.g. from an <input type="file"> or a drop event; also accepted as `url` in
|
|
68
|
+
// inline configurations and options objects (but not directly as a tile source)
|
|
69
|
+
const tileSource4 = new OMEZarrTileSource(file);
|
|
70
|
+
|
|
71
|
+
// direct instantiation with options object
|
|
72
|
+
const tileSource5 = new OMEZarrTileSource({
|
|
62
73
|
url: url,
|
|
63
|
-
// zip: undefined, // undefined = OME-Zarr ZIP auto-detection based on .ozx suffix
|
|
64
|
-
// c: undefined, // undefined = composite of all active channels (requires dataType "context2d")
|
|
65
|
-
// z: undefined, // undefined = omero rdefs default (middle z-slice if missing)
|
|
74
|
+
// zip: undefined, // undefined = OME-Zarr ZIP auto-detection based on .ozx path suffix
|
|
66
75
|
// t: undefined, // undefined = omero rdefs default (middle timepoint if missing)
|
|
67
|
-
//
|
|
76
|
+
// z: undefined, // undefined = omero rdefs default (middle z-slice if missing)
|
|
77
|
+
// c: undefined, // channel index or array of indices; undefined = all active channels
|
|
78
|
+
// range: undefined, // contrast limits [min, max] or array thereof; undefined = omero windows
|
|
79
|
+
// color: undefined, // RGB color or array of colors; undefined = omero channel colors
|
|
80
|
+
// lutOrColorMap: undefined, // LUT/color map or array thereof; undefined = omero LUTs
|
|
81
|
+
// inverted: undefined, // boolean or array of booleans; undefined = omero inversion
|
|
68
82
|
// autoBoost: undefined // boost brightness of dark tiles (default false)
|
|
69
83
|
});
|
|
70
84
|
|
|
@@ -74,86 +88,202 @@ const viewer = OpenSeadragon({
|
|
|
74
88
|
tileSource1,
|
|
75
89
|
tileSource2,
|
|
76
90
|
tileSource3,
|
|
77
|
-
tileSource4
|
|
91
|
+
tileSource4,
|
|
92
|
+
tileSource5
|
|
78
93
|
]
|
|
79
94
|
});
|
|
80
95
|
```
|
|
81
96
|
|
|
97
|
+
### Options
|
|
98
|
+
|
|
99
|
+
| Option | Type | Default | Description |
|
|
100
|
+
| --------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
101
|
+
| `url` | `string \| URL \| Blob` | (required) | URL of the OME-Zarr image (group) or of a zipped OME-Zarr file, relative to the document base URL, or a `Blob` (e.g. a `File`) holding a zipped OME-Zarr file |
|
|
102
|
+
| `zip` | `boolean` | `true` if the `url` path ends with `.ozx` or `url` is a `Blob` | Whether `url` points to a zipped OME-Zarr file; must not be `false` for a `Blob` |
|
|
103
|
+
| `t` | `number` | omero `rdefs.defaultT`, else middle plane | Timepoint index (0-based) |
|
|
104
|
+
| `z` | `number` | omero `rdefs.defaultZ`, else middle plane | Z-slice index (0-based) |
|
|
105
|
+
| `c` | `number \| number[]` | all channels marked active in omero | Channel index or indices (0-based) to render, composited in the given order. Arrays must be non-empty |
|
|
106
|
+
| `range` | `[number, number] \| ([number, number] \| undefined)[]` | omero channel windows (`window.start`, `window.end`), else the data type range | Contrast limits (`[min, max]`) to render the channels with. Ignored for channels rendered with a color map |
|
|
107
|
+
| `color` | `Color \| (Color \| undefined)[]` | colors of the rendered omero channels, else white | RGB color or colors (`[r, g, b]`, 0-255) to render the channels with. Ignored for channels rendered with a LUT or color map |
|
|
108
|
+
| `lutOrColorMap` | `LUTOrColorMap \| (LUTOrColorMap \| undefined)[]` | omero channel LUTs and color maps, else none | Color LUT (a color per scaled value) or color map (a color per raw value, `Map`) to render the channels with; colors may carry alpha. A color map also overrides `range` and `inverted` |
|
|
109
|
+
| `inverted` | `boolean \| (boolean \| undefined)[]` | omero channel inversion, else `false` | Whether to invert the channels. Ignored for channels rendered with a color map |
|
|
110
|
+
| `autoBoost` | `boolean` | `false` | Boost the brightness of dark tiles (ome-zarr.js `renderChunks` option) |
|
|
111
|
+
|
|
112
|
+
`range`, `color`, `lutOrColorMap` and `inverted` take a single value, which
|
|
113
|
+
applies to all rendered channels, or one entry per rendered channel. An
|
|
114
|
+
`undefined` entry falls back to the omero metadata of that channel, as does the
|
|
115
|
+
option as a whole. The `ranges`, `colors`, `lutsOrColorMaps` and `inverteds`
|
|
116
|
+
getters return the resolved per-channel arrays.
|
|
117
|
+
|
|
118
|
+
`t`, `z` and `c` are validated against the image shape when the OME-Zarr
|
|
119
|
+
metadata is loaded; invalid indices fail with `open-failed`. Images without
|
|
120
|
+
`c` fail if the omero metadata marks no channel as active. An invalid `c`,
|
|
121
|
+
`url` or rendering setting is rejected by the constructor, which throws
|
|
122
|
+
synchronously before any request is made; the length of a rendering setting
|
|
123
|
+
array is only checked against `c` if that is configured too.
|
|
124
|
+
|
|
125
|
+
`url` is resolved against the document base URL when the tile source is
|
|
126
|
+
created; the resolved absolute URL is available as `tileSource.url` (always a
|
|
127
|
+
string) and is used for loading, for the tile cache keys and for comparing tile
|
|
128
|
+
sources.
|
|
129
|
+
|
|
130
|
+
A `Blob` (e.g. a `File` picked by the user) is read with the zarrita
|
|
131
|
+
`ZipFileStore.fromBlob` store, so it must hold a zipped OME-Zarr file
|
|
132
|
+
(`zip: false` is rejected by the constructor). The `Blob` is available as
|
|
133
|
+
`tileSource.blob`, and `tileSource.url` is an object URL created once per
|
|
134
|
+
`Blob` instance (never revoked), so tile sources for the same `Blob` share
|
|
135
|
+
cached tiles. OpenSeadragon only passes strings and plain objects to
|
|
136
|
+
`supports`, so a `File` must be wrapped in an inline configuration
|
|
137
|
+
(`{ type: "ome-zarr", url: file }`) or passed to the constructor rather than
|
|
138
|
+
given to the viewer directly.
|
|
139
|
+
|
|
82
140
|
### Accessing OME-Zarr metadata
|
|
83
141
|
|
|
84
142
|
Directly instantiated tile sources start loading the OME-Zarr metadata
|
|
85
143
|
immediately. Await `whenReady()` (or use the `OMEZarrTileSource.open` shortcut)
|
|
86
|
-
to access the `
|
|
87
|
-
(one per resolution level
|
|
144
|
+
to access the loaded image (`loaded.image`, an ome-zarr.js `NgffImage`) and the
|
|
145
|
+
opened zarrita arrays (`loaded.arrays`, one per resolution level, highest
|
|
146
|
+
resolution first) before adding the tile source to a viewer:
|
|
88
147
|
|
|
89
148
|
```javascript
|
|
90
149
|
const tileSource = await OMEZarrTileSource.open({ url: url, c: 0 });
|
|
91
150
|
// equivalent: await new OMEZarrTileSource({ url: url, c: 0 }).whenReady();
|
|
92
151
|
|
|
93
|
-
console.log(tileSource.image.getAxesNames()); // e.g. ["t", "
|
|
94
|
-
console.log(tileSource.image.omero?.channels); // omero channel metadata
|
|
95
|
-
console.log(tileSource.arrays[0].shape); // full-resolution array shape
|
|
152
|
+
console.log(tileSource.loaded.image.getAxesNames()); // e.g. ["t", "c", "z", "y", "x"]
|
|
153
|
+
console.log(tileSource.loaded.image.omero?.channels); // omero channel metadata
|
|
154
|
+
console.log(tileSource.loaded.arrays[0].shape); // full-resolution array shape
|
|
155
|
+
|
|
156
|
+
console.log(tileSource.t, tileSource.z, tileSource.cs); // resolved indices
|
|
157
|
+
console.log(tileSource.channels); // omero channels of the rendered channel indices
|
|
158
|
+
console.log(tileSource.ranges, tileSource.colors); // resolved rendering settings
|
|
159
|
+
console.log(tileSource.lutsOrColorMaps, tileSource.inverteds);
|
|
160
|
+
console.log(tileSource.getWidth(), tileSource.getHeight()); // full resolution
|
|
161
|
+
console.log(tileSource.getWidth(0), tileSource.getHeight(0)); // lowest resolution
|
|
96
162
|
|
|
97
163
|
viewer.addTiledImage({ tileSource: tileSource }); // no second metadata request
|
|
98
164
|
```
|
|
99
165
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
166
|
+
`OMEZarrTileSource.open` accepts an `AbortSignal` as `signal` in its third
|
|
167
|
+
argument to cancel loading. The metadata is loaded once per tile source
|
|
168
|
+
instance: OpenSeadragon reuses a tile source instance passed to it as-is
|
|
169
|
+
(waiting for it to become ready if necessary), whereas a URL or an inline
|
|
170
|
+
configuration object makes OpenSeadragon create (and load) a new instance.
|
|
171
|
+
`whenReady()` rejects (and `loaded` throws) if loading or validation fails.
|
|
172
|
+
|
|
173
|
+
The `t`, `z` and `cs` getters return the resolved values (the omero defaults or
|
|
174
|
+
active channels if the option was not given); `cs` is always an array (the
|
|
175
|
+
`c` option may be a single index), and `channels` returns the omero channel
|
|
176
|
+
objects for `cs`. Before the tile source is ready, they return the configured
|
|
177
|
+
options. The `ranges`, `colors`, `lutsOrColorMaps` and `inverteds` getters
|
|
178
|
+
return the resolved rendering settings of the rendered channels, merging the
|
|
179
|
+
configured values with the omero metadata per channel: `undefined` before the
|
|
180
|
+
tile source is ready or if the image has no omero metadata, like `channels`.
|
|
181
|
+
Entries that are still `undefined` fall back at render time to the data type
|
|
182
|
+
range, white, no LUT and not inverted.
|
|
105
183
|
|
|
106
184
|
### Sharing OME-Zarr metadata between tile sources
|
|
107
185
|
|
|
108
|
-
|
|
109
|
-
for the same URL (e.g. one tile source per channel)
|
|
110
|
-
constructor argument (also supported by
|
|
111
|
-
loading the OME-Zarr metadata (the `zip`
|
|
112
|
-
opened zarrita arrays
|
|
113
|
-
|
|
186
|
+
The loaded image and arrays (`OMEZarr`) can be reused by other directly
|
|
187
|
+
instantiated tile sources for the same URL (e.g. one tile source per channel)
|
|
188
|
+
by passing them as the second constructor argument (also supported by
|
|
189
|
+
`OMEZarrTileSource.open`). This skips loading the OME-Zarr metadata (the `zip`
|
|
190
|
+
option is ignored) and reuses the opened zarrita arrays. The tile source never
|
|
191
|
+
modifies the loaded image, so sharing is safe:
|
|
114
192
|
|
|
115
193
|
```javascript
|
|
116
|
-
|
|
194
|
+
// load once with the tile source's loader ...
|
|
195
|
+
const loaded = await OMEZarrTileSource.loadOMEZarr(url);
|
|
196
|
+
const tileSources = loaded.image.omero.channels.map(
|
|
197
|
+
(_, c) => new OMEZarrTileSource({ url: url, c: c }, loaded),
|
|
198
|
+
);
|
|
117
199
|
|
|
118
|
-
//
|
|
200
|
+
// ... or reuse what a first tile source has loaded
|
|
119
201
|
const tileSource1 = await OMEZarrTileSource.open({ url: url, c: 0 });
|
|
120
202
|
const tileSource2 = new OMEZarrTileSource(
|
|
121
203
|
{ url: url, c: 1 },
|
|
122
|
-
tileSource1.
|
|
204
|
+
tileSource1.loaded,
|
|
123
205
|
);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
`loadOMEZarr(url, zip?, { signal })` loads the metadata with ome-zarr.js and
|
|
209
|
+
opens the arrays of all resolution levels; `url` may also be a `Blob` holding a
|
|
210
|
+
zipped OME-Zarr file. An `OMEZarr` can also be assembled
|
|
211
|
+
from an `NgffImage` loaded by the app, as long as `arrays` lists the
|
|
212
|
+
opened arrays of `image.paths` in order. It is not checked against the URL of
|
|
213
|
+
the tile source it is passed to.
|
|
214
|
+
|
|
215
|
+
### Loading chunks directly
|
|
124
216
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
217
|
+
`loadChunks(level, tile, { signal })` returns the (y, x) zarrita chunks of the
|
|
218
|
+
rendered channels at the rendered timepoint and z-slice, either for one tile
|
|
219
|
+
(`{ x, y }` tile coordinates, as passed to OpenSeadragon) or for the whole
|
|
220
|
+
level plane (`tile` `undefined`):
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
const chunks = await tileSource.loadChunks(tileSource.maxLevel, { x: 0, y: 0 });
|
|
224
|
+
const plane = await tileSource.loadChunks(0, undefined); // lowest resolution
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
`OMEZarrTileSource.render(tileData)` composites such chunks into a 2D canvas
|
|
228
|
+
context, the same way the `ome-zarr` to `context2d` converter does:
|
|
229
|
+
|
|
230
|
+
```javascript
|
|
231
|
+
import { getDataTypeRange } from "omezarr-tilesource";
|
|
232
|
+
|
|
233
|
+
const ctx = OMEZarrTileSource.render({
|
|
234
|
+
chunks: plane,
|
|
235
|
+
// the tile data holds the renderChunks arguments, one per chunk, with the
|
|
236
|
+
// defaults of the tile source getters applied
|
|
237
|
+
ranges: plane.map(
|
|
238
|
+
(chunk, c) => tileSource.ranges?.[c] ?? getDataTypeRange(chunk),
|
|
239
|
+
),
|
|
240
|
+
colors: plane.map((_, c) => tileSource.colors?.[c] ?? [255, 255, 255]),
|
|
241
|
+
lutsOrColorMaps: plane.map((_, c) => tileSource.lutsOrColorMaps?.[c]),
|
|
242
|
+
inverteds: plane.map((_, c) => tileSource.inverteds?.[c] ?? false),
|
|
243
|
+
autoBoost: tileSource.autoBoost,
|
|
244
|
+
});
|
|
128
245
|
```
|
|
129
246
|
|
|
130
247
|
## Data pipeline
|
|
131
248
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
`OpenSeadragon.converter` when the module is
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
249
|
+
Tiles are downloaded as raw zarrita chunks, one per rendered channel, together
|
|
250
|
+
with the rendering settings resolved for that tile, and passed to OpenSeadragon
|
|
251
|
+
with the data type `ome-zarr` (see the `OMEZarrTileData` type: `chunks`,
|
|
252
|
+
`ranges`, `colors`, `lutsOrColorMaps`, `inverteds` and `autoBoost` — the
|
|
253
|
+
arguments of ome-zarr.js `renderChunks`, one entry per chunk). A converter from
|
|
254
|
+
`ome-zarr` to `context2d` calls `OMEZarrTileSource.render` on demand, which
|
|
255
|
+
composites them into a 2D canvas context. Because the raw chunks stay in the
|
|
256
|
+
tile cache, tiles can be re-rendered without re-downloading them.
|
|
257
|
+
|
|
258
|
+
Settings that are neither configured nor in the omero metadata are resolved
|
|
259
|
+
when the tile is downloaded: to the data type range for integer types (e.g.
|
|
260
|
+
`[0, 65535]` for `uint16`) and `[0, 1]` for floating point types, to white, to
|
|
261
|
+
no LUT and to not inverted — so an image without omero metadata is rendered in
|
|
262
|
+
white over its full data type range.
|
|
263
|
+
|
|
264
|
+
The converters are registered on `OpenSeadragon.converter` when the module is
|
|
265
|
+
imported (for the OpenSeadragon instance it imports, and for a global
|
|
266
|
+
`OpenSeadragon` if present) and by `OMEZarrTileSource.enable`. Tiles cannot be
|
|
267
|
+
rendered without them, so call `enable` if the app uses a different
|
|
268
|
+
OpenSeadragon instance than the one resolved by this module (e.g. a separately
|
|
269
|
+
bundled copy).
|
|
270
|
+
|
|
271
|
+
All rendering settings in `OMEZarrTileData` are plain values, resolved from the
|
|
272
|
+
tile source configuration and the omero metadata when the tile is downloaded.
|
|
273
|
+
Editing the omero channels of a loaded image therefore does not affect tiles
|
|
274
|
+
that are already cached, with or without `viewer.requestInvalidate()`; render
|
|
275
|
+
them differently by creating a tile source with the corresponding options
|
|
276
|
+
instead. Tile sources that configure rendering settings do not share cached
|
|
277
|
+
tiles with tile sources that configure different ones.
|
|
153
278
|
|
|
154
279
|
## Example
|
|
155
280
|
|
|
156
|
-
[
|
|
281
|
+
[https://tissuumaps.github.io/OMEZarrTileSource?url=https://livingobjects.ebi.ac.uk/idr/zarr/v0.5/idr0062A/6001240_labels.zarr](https://tissuumaps.github.io/OMEZarrTileSource?url=https%3A%2F%2Flivingobjects.ebi.ac.uk%2Fidr%2Fzarr%2Fv0.5%2Fidr0062A%2F6001240_labels.zarr)
|
|
282
|
+
|
|
283
|
+
The example page takes the URL of the OME-Zarr image from the mandatory `url`
|
|
284
|
+
query parameter, and the timepoint index, the z-slice index and the channel
|
|
285
|
+
indices from the optional `t`, `z` and `c` query parameters (repeat `c` for
|
|
286
|
+
multiple channels).
|
|
157
287
|
|
|
158
288
|
[Source code](index.html)
|
|
159
289
|
|