|
| 1 | +# OME-Zarr Guide for zarr-java |
| 2 | + |
| 3 | +## Scope and supported versions |
| 4 | + |
| 5 | +`dev.zarr.zarrjava.experimental.ome` supports: |
| 6 | + |
| 7 | +- v0.4 (Zarr v2 layout) |
| 8 | +- v0.5 (Zarr v3 layout) |
| 9 | +- v0.6 / RFC-5 |
| 10 | + |
| 11 | +## Primary entry points |
| 12 | + |
| 13 | +Use these static open methods: |
| 14 | + |
| 15 | +- `MultiscaleImage.open(StoreHandle)` for multiscale images (auto-detects v0.4/v0.5/v0.6 image nodes) |
| 16 | +- `Plate.open(StoreHandle)` for HCS plates (v0.4/v0.5) |
| 17 | +- `Well.open(StoreHandle)` for HCS wells (v0.4/v0.5) |
| 18 | + |
| 19 | +### StoreHandle and stores |
| 20 | + |
| 21 | +OME-Zarr APIs are store-agnostic: pass any `StoreHandle` (filesystem, S3, HTTP, ZIP, memory) to `open(...)`. |
| 22 | +See storage backend setup in [`USERGUIDE.md#storage-backends`](USERGUIDE.md#storage-backends). |
| 23 | + |
| 24 | +```java |
| 25 | +StoreHandle s3 = new S3Store(client, "idr", "zarr/v0.5/idr0083").resolve("9822152.zarr"); |
| 26 | +MultiscaleImage image = MultiscaleImage.open(s3); |
| 27 | +``` |
| 28 | + |
| 29 | +## Essential methods |
| 30 | + |
| 31 | +### MultiscaleImage |
| 32 | + |
| 33 | +Metadata: |
| 34 | + |
| 35 | +- `getMultiscaleNode(int i)` → normalized `ome.metadata.MultiscalesEntry` |
| 36 | +- `getAxisNames()` → axis names from multiscale `0` |
| 37 | +- `getScaleLevelCount()` → number of datasets/levels in multiscale `0` |
| 38 | +- `getLabels()` / `openLabel(String)` → labels subgroup helpers |
| 39 | + |
| 40 | +Array access: |
| 41 | + |
| 42 | +- `openScaleLevel(int i)` → `dev.zarr.zarrjava.core.Array` |
| 43 | +- then call `read()` or `read(offset, shape)` on that array |
| 44 | +- typical viewer flow: read axes + scale count first, then select a level by `i` |
| 45 | + |
| 46 | +### Plate and Well (HCS) |
| 47 | + |
| 48 | +Metadata: |
| 49 | + |
| 50 | +- `Plate.getPlateMetadata()` |
| 51 | +- `Well.getWellMetadata()` |
| 52 | + |
| 53 | +Navigation: |
| 54 | + |
| 55 | +- `Plate.openWell(String rowColPath)` (for example `"A/1"`) |
| 56 | +- `Well.openImage(String path)` (for example `"0"`) |
| 57 | + |
| 58 | +## Version-specific typed metadata |
| 59 | + |
| 60 | +If you need the raw version-specific metadata model instead of normalized `MultiscalesEntry`: |
| 61 | + |
| 62 | +- Cast to `MultiscalesMetadataImage<?>` and call `getMultiscalesEntry(i)` |
| 63 | + |
| 64 | + |
| 65 | +## v0.6 Scene metadata |
| 66 | + |
| 67 | +Scene roots (groups with `ome.scene`) are supported via `dev.zarr.zarrjava.experimental.ome.v0_6.Scene`: |
| 68 | + |
| 69 | +- `Scene.openScene(StoreHandle)` / `Scene.open(StoreHandle)` |
| 70 | +- `Scene.createScene(StoreHandle, SceneMetadata)` / `Scene.create(...)` |
| 71 | +- `listImageNodes()` and `openImageNode(String)` for sibling multiscale images |
| 72 | +- `getCoordinateTransformationGraph()` for lightweight metadata graph inspection |
| 73 | + |
| 74 | +Notes: |
| 75 | +- Parsing is permissive and explicit (no strict full-spec validation). |
| 76 | +- Scene-level references (`input`/`output`) are resolved against scene-root coordinate systems and child image coordinate systems for graph inspection. |
| 77 | +- Path-based transform assets can be normalized with `Scene.normalizeCoordinateTransformPath(...)` and grouped under `coordinateTransformations/` via `createCoordinateTransformationsGroup()`. |
| 78 | + |
| 79 | +## Read example |
| 80 | + |
| 81 | +```java |
| 82 | +import dev.zarr.zarrjava.experimental.ome.MultiscaleImage; |
| 83 | +import dev.zarr.zarrjava.experimental.ome.Plate; |
| 84 | +import dev.zarr.zarrjava.experimental.ome.Well; |
| 85 | +import dev.zarr.zarrjava.store.FilesystemStore; |
| 86 | +import dev.zarr.zarrjava.store.StoreHandle; |
| 87 | + |
| 88 | +StoreHandle imageHandle = new FilesystemStore("/data/ome/image.zarr").resolve(); |
| 89 | +MultiscaleImage image = MultiscaleImage.open(imageHandle); |
| 90 | + |
| 91 | +int scaleCount = image.getScaleLevelCount(); |
| 92 | +java.util.List<String> axisNames = image.getAxisNames(); |
| 93 | +dev.zarr.zarrjava.experimental.ome.metadata.MultiscalesEntry entry0 = image.getMultiscaleNode(0); |
| 94 | + |
| 95 | +dev.zarr.zarrjava.core.Array s0 = image.openScaleLevel(0); |
| 96 | +ucar.ma2.Array full = s0.read(); |
| 97 | +ucar.ma2.Array subset = s0.read(new long[]{0, 0, 0, 0, 0}, new long[]{1, 1, 4, 8, 8}); |
| 98 | + |
| 99 | +java.util.List<String> labels = image.getLabels(); |
| 100 | +if (!labels.isEmpty()) { |
| 101 | + MultiscaleImage label = image.openLabel(labels.get(0)); |
| 102 | +} |
| 103 | + |
| 104 | +StoreHandle plateHandle = new FilesystemStore("/data/ome/plate.zarr").resolve(); |
| 105 | +Plate plate = Plate.open(plateHandle); |
| 106 | +Well well = plate.openWell("A/1"); |
| 107 | +MultiscaleImage wellImage = well.openImage("0"); |
| 108 | +``` |
| 109 | + |
| 110 | +## Write example |
| 111 | + |
| 112 | +Creation is version-specific, but the pattern is the same: create node with version metadata, then append levels/datasets with scale transforms. For example, for v0.5: |
| 113 | + |
| 114 | +```java |
| 115 | +import dev.zarr.zarrjava.experimental.ome.metadata.Axis; |
| 116 | +import dev.zarr.zarrjava.experimental.ome.metadata.CoordinateTransformation; |
| 117 | +import dev.zarr.zarrjava.experimental.ome.metadata.MultiscalesEntry; |
| 118 | +import dev.zarr.zarrjava.store.FilesystemStore; |
| 119 | +import dev.zarr.zarrjava.store.StoreHandle; |
| 120 | +import dev.zarr.zarrjava.v3.Array; |
| 121 | +import dev.zarr.zarrjava.v3.DataType; |
| 122 | + |
| 123 | +import java.util.Arrays; |
| 124 | +import java.util.Collections; |
| 125 | + |
| 126 | +StoreHandle out = new FilesystemStore("/tmp/ome_v05.zarr").resolve(); |
| 127 | +MultiscalesEntry ms = new MultiscalesEntry( |
| 128 | + Arrays.asList(new Axis("y", "space", "micrometer"), new Axis("x", "space", "micrometer")), |
| 129 | + Collections.<Dataset>emptyList()); |
| 130 | +); |
| 131 | +dev.zarr.zarrjava.experimental.ome.v0_5.MultiscaleImage written = dev.zarr.zarrjava.experimental.ome.v0_5.MultiscaleImage.create(out, ms); |
| 132 | + |
| 133 | +written.createScaleLevel( |
| 134 | + "s0", |
| 135 | + Array.metadataBuilder().withShape(1024, 1024).withChunkShape(256, 256).withDataType(DataType.UINT16).build(), |
| 136 | + Collections.singletonList(CoordinateTransformation.scale(Arrays.asList(1.0, 1.0))) |
| 137 | +); |
| 138 | +written.createScaleLevel( |
| 139 | + "s1", |
| 140 | + Array.metadataBuilder().withShape(512, 512).withChunkShape(256, 256).withDataType(DataType.UINT16).build(), |
| 141 | + Collections.singletonList(CoordinateTransformation.scale(Arrays.asList(2.0, 2.0))) |
| 142 | +); |
| 143 | +``` |
| 144 | + |
| 145 | +## Write entry points by version |
| 146 | + |
| 147 | +- `ome.v0_4.MultiscaleImage.create(...)` |
| 148 | +- `ome.v0_5.MultiscaleImage.create(...)` |
| 149 | +- `ome.v0_6.MultiscaleImage.create(...)` |
| 150 | + |
| 151 | +Use the corresponding metadata classes for each version package. |
0 commit comments