worldarray 0.1.0__tar.gz → 0.2.0__tar.gz
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.
- worldarray-0.2.0/CHANGELOG.md +80 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/PKG-INFO +35 -9
- {worldarray-0.1.0 → worldarray-0.2.0}/README.md +34 -8
- {worldarray-0.1.0 → worldarray-0.2.0}/docs/spec.md +485 -36
- {worldarray-0.1.0 → worldarray-0.2.0}/pyproject.toml +1 -1
- {worldarray-0.1.0 → worldarray-0.2.0}/src/worldarray/__init__.py +20 -3
- {worldarray-0.1.0 → worldarray-0.2.0}/src/worldarray/array.py +390 -55
- {worldarray-0.1.0 → worldarray-0.2.0}/src/worldarray/context.py +31 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/src/worldarray/levels.py +12 -4
- {worldarray-0.1.0 → worldarray-0.2.0}/src/worldarray/placement.py +83 -24
- {worldarray-0.1.0 → worldarray-0.2.0}/src/worldarray/store.py +39 -4
- {worldarray-0.1.0 → worldarray-0.2.0}/src/worldarray/units.py +22 -0
- worldarray-0.2.0/src/worldarray/write.py +829 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/tests/fixtures/metadata.json +8 -8
- worldarray-0.2.0/tests/fixtures/write.json +1690 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/tests/test_access.py +16 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/tests/test_metadata.py +33 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/tests/test_read.py +49 -8
- worldarray-0.2.0/tests/test_write.py +754 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/uv.lock +1 -1
- worldarray-0.1.0/CHANGELOG.md +0 -13
- {worldarray-0.1.0 → worldarray-0.2.0}/.github/workflows/ci.yml +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/.github/workflows/docs.yml +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/.github/workflows/publish.yml +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/.gitignore +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/LICENSE +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/docs/changelog.md +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/docs/index.md +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/mkdocs.yml +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/src/worldarray/geometry.py +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/src/worldarray/resample.py +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/src/worldarray/retry.py +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/tests/conftest.py +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/tests/test_geometry.py +0 -0
- {worldarray-0.1.0 → worldarray-0.2.0}/tests/test_resample.py +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0 (2026-10-22)
|
|
4
|
+
|
|
5
|
+
Metadata and placed creation, built to spec draft 3 (Behaviours 10 to 16). Nothing on the
|
|
6
|
+
read side changes.
|
|
7
|
+
|
|
8
|
+
- `ome_multiscales(axes, units, levels, version)` builds the complete OME-NGFF 0.4 or 0.5
|
|
9
|
+
group document with one explicit placement per level; `level_placement` and
|
|
10
|
+
`level_shape` derive a level from factors and an origin (Convention 1's rule inverted,
|
|
11
|
+
so a level built from a ROI origin is placed from it; `level_shape` absorbs float-noise
|
|
12
|
+
factors such as `0.3 / 0.1`). Units are written in OME's names (`"nm"` becomes
|
|
13
|
+
`"nanometer"`; `units.ome_name`), an unknown unit as given; the multiscale's `type` is
|
|
14
|
+
written when given. Expected documents are pinned in `tests/fixtures/write.json`, shared
|
|
15
|
+
with chunkmirage's TypeScript builder, each case with its resolved per-axis units and
|
|
16
|
+
types, fifteen cases.
|
|
17
|
+
- `create(path, shape, dtype, voxel_size, translation, chunks=..., ...)` writes the group
|
|
18
|
+
document (made when absent, else its one dataset entry added or replaced, every other
|
|
19
|
+
attribute kept) and then the array, as zarr v2 with OME 0.4 or zarr v3 with OME 0.5
|
|
20
|
+
following the group's format. `chunks` is required, codecs are explicit with a zstd
|
|
21
|
+
level 3 default, shards are a zarr v3 option. `exists` is `"error"` or `"adopt"` (an
|
|
22
|
+
identical array is opened for writing, a different one raises naming every difference,
|
|
23
|
+
a creation lost to another process is adopted after a short backoff). Nothing is ever
|
|
24
|
+
deleted, truncated or overwritten. Write units equal to the fill value are not stored
|
|
25
|
+
unless `store_fill=True`, and a stored unit written so loses its key, as zarr-python's
|
|
26
|
+
`write_empty_chunks=False` does. `create` also writes a bare group document for every
|
|
27
|
+
missing ancestor down from the `.zarr` root and follows the nearest existing ancestor's
|
|
28
|
+
zarr version, so a level made in a zarr v2 container is zarr v2 with OME 0.4 and the
|
|
29
|
+
hierarchy browses (cellmap-analyze, cellmap-flow). Adopting an identical array writes no
|
|
30
|
+
group document; after a write the document is read again and a lost entry is written
|
|
31
|
+
again, then raises (registration-station's concurrent block jobs).
|
|
32
|
+
- `ensure_group_entry` is public: list an array the package did not create, such as a
|
|
33
|
+
symlinked `s0` (mesh-n-bone), or a level filled before it is listed.
|
|
34
|
+
- `open(path, mode="r+")` opens an existing array for writing; a `WorldArray` pickles by
|
|
35
|
+
its arguments and its context's spec and reopens in the receiving process, a capped
|
|
36
|
+
context staying capped (mesh-n-bone's workers). `write.codecs_of` takes a path.
|
|
37
|
+
- `write_index(begin, end, data)` writes whole write units only (the shard when sharded,
|
|
38
|
+
else the chunk; the clipped last unit allowed), so writers in different processes need
|
|
39
|
+
no coordination; `partial=True` does tensorstore's read-modify-write. `write(box, data)`
|
|
40
|
+
maps a world box by the centre rule first. No cast, no padding, no resampling on write.
|
|
41
|
+
- `open_pyramid(path, mode="r+").add_level(name, factors=, origin=)` creates a level's
|
|
42
|
+
entry and empty array, placed and sized from the level below with its dtype, chunks,
|
|
43
|
+
shards, codecs and fill value copied; the downsampling itself stays with the caller.
|
|
44
|
+
- `chunk_key` and `parse_chunk_key` for zarr v2, zarr v3 (both encodings, sharded arrays
|
|
45
|
+
keyed by shard), N5 and precomputed, as free functions and on `WorldArray`;
|
|
46
|
+
`list_chunks` uses the same parser. `write_shape`, `ArrayMeta.shard_shape`,
|
|
47
|
+
`chunks_covering(write=True)`.
|
|
48
|
+
## 0.1.1 (2026-10-22)
|
|
49
|
+
|
|
50
|
+
- funlib `voxel_size`/`offset` on the parent group place an array that carries none, for
|
|
51
|
+
zarr and N5 alike; funlib's keys on an N5 array are read in the array's C order, as
|
|
52
|
+
zarr-python's N5 store writes them (both from mesh-n-bone's review of its PR #48).
|
|
53
|
+
- A precomputed path that names a scale is that scale under `level=0` or `"first"` too;
|
|
54
|
+
other levels warn and are ignored, as on an array path.
|
|
55
|
+
- The GCE metadata guard is applied only off Google Cloud (decided from the DMI product
|
|
56
|
+
name and the `GCE_METADATA_*` variables), so metadata-server credentials keep working on
|
|
57
|
+
a Google VM.
|
|
58
|
+
- `Pyramid.placements()`, `voxel_sizes()` and `translations()` read the group document when
|
|
59
|
+
the pyramid was opened through one of its level paths too; they used to open every level
|
|
60
|
+
from there, and a missing level made them raise.
|
|
61
|
+
- **Placement change.** An N5 level with `downsamplingFactors` and no offset now sits with
|
|
62
|
+
its corner at the origin at every level, as Neuroglancer draws N5: translation
|
|
63
|
+
`f / 2 * base`. 0.1.0 followed BigDataViewer for `pixelResolution` pyramids, centring the
|
|
64
|
+
base's voxel 0 on the origin (`(f - 1) / 2 * base`, half a base voxel lower), while
|
|
65
|
+
placing `resolution` pyramids with the corner at the origin, so the two disagreed. Two
|
|
66
|
+
shared fixture cases move and are renamed: `n5_group_pixelresolution_and_downsampling_factors_corner_at_origin`
|
|
67
|
+
(translation 4, 4, 4) and `n5_bigstitcher_resolution_with_downsampling_factors_corner_at_origin`
|
|
68
|
+
(0.5, 0.157, 0.157).
|
|
69
|
+
|
|
70
|
+
## 0.1.0 (2026-10-21)
|
|
71
|
+
|
|
72
|
+
- First version, built to `docs/spec.md`: open zarr v2, zarr v3, N5 and Neuroglancer
|
|
73
|
+
precomputed arrays and pyramids through tensorstore; one metadata precedence per format
|
|
74
|
+
with the voxel-centre rule for translations; index-space and world-box reads with
|
|
75
|
+
padding; level selection; nearest and linear resampling; retries; shared and capped
|
|
76
|
+
tensorstore contexts.
|
|
77
|
+
Built and trialled in one day against the readers it replaces in cellmap-flow,
|
|
78
|
+
cellmap-analyze, mesh-n-bone and chunkmirage, and checked on their own data by the
|
|
79
|
+
CineMap, liconn-err, registration-station and salamander repos; see `docs/spec.md`,
|
|
80
|
+
"Trial status". Hot-path reads cost 0.1 to 0.2 ms over a raw tensorstore read.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: worldarray
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Read zarr, N5 and Neuroglancer precomputed volumes in world coordinates through tensorstore: correct voxel placement, pyramid levels, padded region reads, resampling. numpy + tensorstore only.
|
|
5
5
|
Project-URL: Homepage, https://janeliascicomp.github.io/worldarray/
|
|
6
6
|
Project-URL: Documentation, https://janeliascicomp.github.io/worldarray/
|
|
@@ -67,8 +67,7 @@ pip install worldarray
|
|
|
67
67
|
|
|
68
68
|
## Why
|
|
69
69
|
|
|
70
|
-
Volumetric data
|
|
71
|
-
stores, on local disks, S3, GCS and HTTP. Each format records *where the array sits*,
|
|
70
|
+
Volumetric data lives in zarr v2, zarr v3, N5 and Neuroglancer precomputed stores, on local disks, S3, GCS and HTTP. Each format records *where the array sits*,
|
|
72
71
|
its voxel size, origin, units and axes, in its own dialect, and the dialects disagree on
|
|
73
72
|
the one thing that matters most: whether a stored origin means the centre of the first
|
|
74
73
|
voxel or its corner. Get that wrong and every object is half a voxel out of place, which
|
|
@@ -79,10 +78,12 @@ rule for each, picking a pyramid level for a wanted resolution, and reading a re
|
|
|
79
78
|
given in physical units as a plain numpy block, padded where the region leaves the data,
|
|
80
79
|
resampled when no level matches, fast enough for a model server or a thousand cluster
|
|
81
80
|
workers, with retries for flaky object stores and thread caps for shared hosts. No one
|
|
82
|
-
package did all of that, so every tool
|
|
83
|
-
apart. worldarray is that reader, written once, with the rules stated and tested.
|
|
81
|
+
package did all of that, so every tool wrote its own reader, and the readers drifted apart. worldarray is that reader, written once, with the rules stated and tested.
|
|
84
82
|
|
|
85
|
-
Its dependencies are `tensorstore` and `numpy`.
|
|
83
|
+
Its dependencies are `tensorstore` and `numpy`. Since 0.2 it also writes the one thing
|
|
84
|
+
every tool wrote for itself and got wrong in its own way: the OME-NGFF metadata of a placed
|
|
85
|
+
array or pyramid level, and the array itself, created once and filled by aligned writes
|
|
86
|
+
from any number of jobs. It never deletes, overwrites or downsamples. The
|
|
86
87
|
[specification](https://janeliascicomp.github.io/worldarray/spec/) is the contract it is
|
|
87
88
|
built to; every rule below is a test.
|
|
88
89
|
|
|
@@ -117,6 +118,13 @@ vol.read_index((0, 0, 0), (64, 64, 64), padding=0)
|
|
|
117
118
|
|
|
118
119
|
pyr = wa.open_pyramid(path) # every level, opened on first use
|
|
119
120
|
pyr.select((16, 16, 16), mode="floor") # the level to read at 16 nm
|
|
121
|
+
|
|
122
|
+
# writing: a placed level, its OME-NGFF group document written for it (zarr v3 + OME 0.5 here)
|
|
123
|
+
out = wa.create("out.zarr/s0", shape=(512, 512, 512), dtype="uint64",
|
|
124
|
+
voxel_size=(8, 8, 8), translation=(4, 4, 4), chunks=(64, 64, 64))
|
|
125
|
+
out.write_index((0, 0, 0), (64, 64, 64), block) # whole chunks only: many jobs, no locks
|
|
126
|
+
out.write(box, block) # or by world box
|
|
127
|
+
s1 = wa.open_pyramid("out.zarr", mode="r+").add_level("s1", factors=2) # placed and sized; you fill it
|
|
120
128
|
```
|
|
121
129
|
|
|
122
130
|
## What it does
|
|
@@ -141,6 +149,13 @@ pyr.select((16, 16, 16), mode="floor") # the level to read at 16 nm
|
|
|
141
149
|
cancelled future on timeout.
|
|
142
150
|
- **Carries the geometry**: `Box` with `intersect`, `union`, `contains`, `grow`, `shift`,
|
|
143
151
|
`snap` to a grid, and the voxel indices a world box selects.
|
|
152
|
+
- **Writes placed arrays** (0.2): the OME-NGFF 0.4 or 0.5 document from voxel size, centre
|
|
153
|
+
translation, axes and units, with each level's placement explicit or derived from
|
|
154
|
+
factors and an origin; `create` following the container's format and writing the group
|
|
155
|
+
documents an output needs down from its `.zarr` root, with explicit chunks and codecs,
|
|
156
|
+
and only two answers to "it exists": raise, or adopt an identical array after checking;
|
|
157
|
+
whole-unit writes from many processes with no coordination; `add_level` as metadata plus
|
|
158
|
+
an empty array; chunk keys for every format. Nothing is ever deleted or overwritten.
|
|
144
159
|
|
|
145
160
|
## The placement rule
|
|
146
161
|
|
|
@@ -154,7 +169,7 @@ moved half a voxel on reading:
|
|
|
154
169
|
| OME-NGFF `translation` | centre | as is |
|
|
155
170
|
| COSEM `transform.translate` | centre | as is |
|
|
156
171
|
| `offset` beside `resolution` / `voxel_size` (`offset` missing: 0) | corner | `offset + voxel_size / 2` |
|
|
157
|
-
| N5 `pixelResolution` or `resolution` with `downsamplingFactors f`, no offset |
|
|
172
|
+
| N5 `pixelResolution` or `resolution` with `downsamplingFactors f`, no offset | corner at the origin at every level, as Neuroglancer draws N5 | `f / 2 * base` |
|
|
158
173
|
| precomputed `voxel_offset` | corner | `(voxel_offset + 1/2) * resolution` |
|
|
159
174
|
| nothing | a plain array | voxels of 1, corner at the origin |
|
|
160
175
|
|
|
@@ -178,13 +193,24 @@ wa.open_tensorstore(path, level=None, context=None)
|
|
|
178
193
|
wa.shared_context(cache_bytes=0) ; wa.capped_context(cache_bytes=0, concurrency=1, network=True) ; wa.Retry(...)
|
|
179
194
|
wa.list_chunk_keys(path, separator=".") # chunk indices from keys alone, no metadata needed
|
|
180
195
|
wa.Box ; wa.units.TABLE
|
|
196
|
+
|
|
197
|
+
# writing (0.2)
|
|
198
|
+
wa.create(path, shape, dtype, voxel_size, translation, *, axes=None, units="nanometer", chunks=..., shards=None,
|
|
199
|
+
fill_value=0, codecs="zstd", format=None, attrs=None, group_attrs=None, exists="error", store_fill=False) -> WorldArray
|
|
200
|
+
wa.open(path, mode="r+") ; wa.open_pyramid(path, mode="r+").add_level(name, factors=, origin=0, ...)
|
|
201
|
+
wa.ome_multiscales(axes, units, levels, version="0.5", type=None) ; wa.level_placement(voxel_size, translation, factors, origin=0)
|
|
202
|
+
wa.level_shape(shape, factors, origin=0) ; wa.chunk_key(index, format, ...) ; wa.parse_chunk_key(key, format, ...)
|
|
203
|
+
wa.ensure_group_entry(group_path, name, voxel_size, translation, axes, units="nanometer") # list an array you made yourself
|
|
204
|
+
wa.units.ome_name("nm") -> "nanometer" ; wa.write.codecs_of(path) -> (codecs, shards)
|
|
181
205
|
```
|
|
182
206
|
|
|
183
207
|
`WorldArray`: `ts`, `meta`, `grid`, `shape`, `dtype`, `axes`, `voxel_size`, `translation`,
|
|
184
|
-
`corner`, `box`, `levels`, `level_name`, `level_path`, `source_voxel_size`, `resampled
|
|
208
|
+
`corner`, `box`, `levels`, `level_name`, `level_path`, `source_voxel_size`, `resampled`,
|
|
209
|
+
`writable`, `write_shape`;
|
|
185
210
|
`read(box, voxel_size=, padding=, method=, mask=, anchor=, transform=, post_transform=, select=, strict=)`,
|
|
186
211
|
`read_index(begin, end, padding=, mask=, select=, transform=)`, `index_box(box)`,
|
|
187
|
-
`chunks_covering(begin, end)`, `list_chunks()`, `
|
|
212
|
+
`chunks_covering(begin, end, write=)`, `list_chunks()`, `chunk_key(index)`, `parse_chunk_key(key)`,
|
|
213
|
+
`write_index(begin, end, data, partial=)`, `write(box, data, partial=)`, `reopen(context=)`.
|
|
188
214
|
|
|
189
215
|
A box is a `(begin, end)` pair of floats in your units, half-open per axis, over the
|
|
190
216
|
spatial axes or every axis; any object with `.begin`/`.end` or `.offset`/`.shape` also
|
|
@@ -8,8 +8,7 @@ pip install worldarray
|
|
|
8
8
|
|
|
9
9
|
## Why
|
|
10
10
|
|
|
11
|
-
Volumetric data
|
|
12
|
-
stores, on local disks, S3, GCS and HTTP. Each format records *where the array sits*,
|
|
11
|
+
Volumetric data lives in zarr v2, zarr v3, N5 and Neuroglancer precomputed stores, on local disks, S3, GCS and HTTP. Each format records *where the array sits*,
|
|
13
12
|
its voxel size, origin, units and axes, in its own dialect, and the dialects disagree on
|
|
14
13
|
the one thing that matters most: whether a stored origin means the centre of the first
|
|
15
14
|
voxel or its corner. Get that wrong and every object is half a voxel out of place, which
|
|
@@ -20,10 +19,12 @@ rule for each, picking a pyramid level for a wanted resolution, and reading a re
|
|
|
20
19
|
given in physical units as a plain numpy block, padded where the region leaves the data,
|
|
21
20
|
resampled when no level matches, fast enough for a model server or a thousand cluster
|
|
22
21
|
workers, with retries for flaky object stores and thread caps for shared hosts. No one
|
|
23
|
-
package did all of that, so every tool
|
|
24
|
-
apart. worldarray is that reader, written once, with the rules stated and tested.
|
|
22
|
+
package did all of that, so every tool wrote its own reader, and the readers drifted apart. worldarray is that reader, written once, with the rules stated and tested.
|
|
25
23
|
|
|
26
|
-
Its dependencies are `tensorstore` and `numpy`.
|
|
24
|
+
Its dependencies are `tensorstore` and `numpy`. Since 0.2 it also writes the one thing
|
|
25
|
+
every tool wrote for itself and got wrong in its own way: the OME-NGFF metadata of a placed
|
|
26
|
+
array or pyramid level, and the array itself, created once and filled by aligned writes
|
|
27
|
+
from any number of jobs. It never deletes, overwrites or downsamples. The
|
|
27
28
|
[specification](https://janeliascicomp.github.io/worldarray/spec/) is the contract it is
|
|
28
29
|
built to; every rule below is a test.
|
|
29
30
|
|
|
@@ -58,6 +59,13 @@ vol.read_index((0, 0, 0), (64, 64, 64), padding=0)
|
|
|
58
59
|
|
|
59
60
|
pyr = wa.open_pyramid(path) # every level, opened on first use
|
|
60
61
|
pyr.select((16, 16, 16), mode="floor") # the level to read at 16 nm
|
|
62
|
+
|
|
63
|
+
# writing: a placed level, its OME-NGFF group document written for it (zarr v3 + OME 0.5 here)
|
|
64
|
+
out = wa.create("out.zarr/s0", shape=(512, 512, 512), dtype="uint64",
|
|
65
|
+
voxel_size=(8, 8, 8), translation=(4, 4, 4), chunks=(64, 64, 64))
|
|
66
|
+
out.write_index((0, 0, 0), (64, 64, 64), block) # whole chunks only: many jobs, no locks
|
|
67
|
+
out.write(box, block) # or by world box
|
|
68
|
+
s1 = wa.open_pyramid("out.zarr", mode="r+").add_level("s1", factors=2) # placed and sized; you fill it
|
|
61
69
|
```
|
|
62
70
|
|
|
63
71
|
## What it does
|
|
@@ -82,6 +90,13 @@ pyr.select((16, 16, 16), mode="floor") # the level to read at 16 nm
|
|
|
82
90
|
cancelled future on timeout.
|
|
83
91
|
- **Carries the geometry**: `Box` with `intersect`, `union`, `contains`, `grow`, `shift`,
|
|
84
92
|
`snap` to a grid, and the voxel indices a world box selects.
|
|
93
|
+
- **Writes placed arrays** (0.2): the OME-NGFF 0.4 or 0.5 document from voxel size, centre
|
|
94
|
+
translation, axes and units, with each level's placement explicit or derived from
|
|
95
|
+
factors and an origin; `create` following the container's format and writing the group
|
|
96
|
+
documents an output needs down from its `.zarr` root, with explicit chunks and codecs,
|
|
97
|
+
and only two answers to "it exists": raise, or adopt an identical array after checking;
|
|
98
|
+
whole-unit writes from many processes with no coordination; `add_level` as metadata plus
|
|
99
|
+
an empty array; chunk keys for every format. Nothing is ever deleted or overwritten.
|
|
85
100
|
|
|
86
101
|
## The placement rule
|
|
87
102
|
|
|
@@ -95,7 +110,7 @@ moved half a voxel on reading:
|
|
|
95
110
|
| OME-NGFF `translation` | centre | as is |
|
|
96
111
|
| COSEM `transform.translate` | centre | as is |
|
|
97
112
|
| `offset` beside `resolution` / `voxel_size` (`offset` missing: 0) | corner | `offset + voxel_size / 2` |
|
|
98
|
-
| N5 `pixelResolution` or `resolution` with `downsamplingFactors f`, no offset |
|
|
113
|
+
| N5 `pixelResolution` or `resolution` with `downsamplingFactors f`, no offset | corner at the origin at every level, as Neuroglancer draws N5 | `f / 2 * base` |
|
|
99
114
|
| precomputed `voxel_offset` | corner | `(voxel_offset + 1/2) * resolution` |
|
|
100
115
|
| nothing | a plain array | voxels of 1, corner at the origin |
|
|
101
116
|
|
|
@@ -119,13 +134,24 @@ wa.open_tensorstore(path, level=None, context=None)
|
|
|
119
134
|
wa.shared_context(cache_bytes=0) ; wa.capped_context(cache_bytes=0, concurrency=1, network=True) ; wa.Retry(...)
|
|
120
135
|
wa.list_chunk_keys(path, separator=".") # chunk indices from keys alone, no metadata needed
|
|
121
136
|
wa.Box ; wa.units.TABLE
|
|
137
|
+
|
|
138
|
+
# writing (0.2)
|
|
139
|
+
wa.create(path, shape, dtype, voxel_size, translation, *, axes=None, units="nanometer", chunks=..., shards=None,
|
|
140
|
+
fill_value=0, codecs="zstd", format=None, attrs=None, group_attrs=None, exists="error", store_fill=False) -> WorldArray
|
|
141
|
+
wa.open(path, mode="r+") ; wa.open_pyramid(path, mode="r+").add_level(name, factors=, origin=0, ...)
|
|
142
|
+
wa.ome_multiscales(axes, units, levels, version="0.5", type=None) ; wa.level_placement(voxel_size, translation, factors, origin=0)
|
|
143
|
+
wa.level_shape(shape, factors, origin=0) ; wa.chunk_key(index, format, ...) ; wa.parse_chunk_key(key, format, ...)
|
|
144
|
+
wa.ensure_group_entry(group_path, name, voxel_size, translation, axes, units="nanometer") # list an array you made yourself
|
|
145
|
+
wa.units.ome_name("nm") -> "nanometer" ; wa.write.codecs_of(path) -> (codecs, shards)
|
|
122
146
|
```
|
|
123
147
|
|
|
124
148
|
`WorldArray`: `ts`, `meta`, `grid`, `shape`, `dtype`, `axes`, `voxel_size`, `translation`,
|
|
125
|
-
`corner`, `box`, `levels`, `level_name`, `level_path`, `source_voxel_size`, `resampled
|
|
149
|
+
`corner`, `box`, `levels`, `level_name`, `level_path`, `source_voxel_size`, `resampled`,
|
|
150
|
+
`writable`, `write_shape`;
|
|
126
151
|
`read(box, voxel_size=, padding=, method=, mask=, anchor=, transform=, post_transform=, select=, strict=)`,
|
|
127
152
|
`read_index(begin, end, padding=, mask=, select=, transform=)`, `index_box(box)`,
|
|
128
|
-
`chunks_covering(begin, end)`, `list_chunks()`, `
|
|
153
|
+
`chunks_covering(begin, end, write=)`, `list_chunks()`, `chunk_key(index)`, `parse_chunk_key(key)`,
|
|
154
|
+
`write_index(begin, end, data, partial=)`, `write(box, data, partial=)`, `reopen(context=)`.
|
|
129
155
|
|
|
130
156
|
A box is a `(begin, end)` pair of floats in your units, half-open per axis, over the
|
|
131
157
|
spatial axes or every axis; any object with `.begin`/`.end` or `.offset`/`.shape` also
|