diff --git a/.gitignore b/.gitignore
index 4c52107f..deff3fbd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,9 @@
target/
!.mvn/wrapper/maven-wrapper.jar
+
+### Notebooks ###
+notebooks/*_executed.ipynb
+**/.ipynb_checkpoints/
!**/src/main/**/target/
!**/src/test/**/target/
@@ -40,10 +44,16 @@ build/
### Custom ###
/testdata/l4_sample
/testdata/l4_sample.zip
+zarr-java-core/testdata/l4_sample
+zarr-java-core/testdata/l4_sample.zip
/testoutput
+zarr-java-core/testoutput
+zarr-java-ome/testoutput
/.python-version
/main.py
/pyproject.toml
/uv.lock
**/__pycache__
/dependency-reduced-pom.xml
+zarr-java-core/dependency-reduced-pom.xml
+zarr-java-ome/dependency-reduced-pom.xml
diff --git a/.gitmodules b/.gitmodules
index 37c054ac..3405e630 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
-[submodule "testdata/ome/v0.6/examples"]
- path = testdata/ome/v0.6/examples
+[submodule "zarr-java-ome/testdata/ome/v0.6/examples"]
+ path = zarr-java-ome/testdata/ome/v0.6/examples
url = https://github.com/jo-mueller/ngff-rfc5-coordinate-transformation-examples
diff --git a/README.md b/README.md
index faf0cf2f..f80f74cd 100644
--- a/README.md
+++ b/README.md
@@ -56,6 +56,31 @@ data
);
```
+## Interactive Notebooks
+
+The `notebooks/` directory contains IJava (Java kernel for Jupyter) notebooks that let you explore and verify the library interactively without publishing it.
+
+**Prerequisites:** Java 17+, Maven 3.6+, Python 3, `curl`, `unzip`
+
+```bash
+./notebooks/start.sh
+```
+
+This single command:
+1. Builds the project and installs JARs to your local Maven cache (`~/.m2`)
+2. Wires up the classpath so the notebooks can import the library directly — no internet access needed for the library itself
+3. Installs Jupyter and the IJava kernel into `~/.jupyter-venv` on first run (one-time, ~1 min)
+4. Opens JupyterLab in your browser
+
+Available notebooks (in `notebooks/notebooks/`):
+
+| Notebook | Covers |
+|---|---|
+| `zarr_core.ipynb` | v2/v3 arrays, stores, codecs, sharding, groups, attributes, ZIP |
+| `ome_zarr_integration.ipynb` | OME-Zarr v0.4/v0.5, multiscale images, HCS plates and wells |
+
+---
+
## Development Start-Guide
### Run Tests Locally
diff --git a/USERGUIDE-OME-ZARR.md b/USERGUIDE-OME-ZARR.md
index 313945af..d8221be8 100644
--- a/USERGUIDE-OME-ZARR.md
+++ b/USERGUIDE-OME-ZARR.md
@@ -1,8 +1,35 @@
# OME-Zarr Guide for zarr-java
+## Separate module
+
+OME-Zarr support lives in a dedicated module: **`zarr-java-ome`**.
+Add it alongside the core library:
+
+### Maven
+```xml
+
+ dev.zarr
+ zarr-java-core
+ 0.1.3
+
+
+ dev.zarr
+ zarr-java-ome
+ 0.1.3
+
+```
+
+### Gradle
+```gradle
+dependencies {
+ implementation 'dev.zarr:zarr-java-core:0.1.3'
+ implementation 'dev.zarr:zarr-java-ome:0.1.3'
+}
+```
+
## Scope and supported versions
-`dev.zarr.zarrjava.experimental.ome` supports:
+`dev.zarr.omezarr` supports:
- v0.4 (Zarr v2 layout)
- v0.5 (Zarr v3 layout)
@@ -32,7 +59,7 @@ MultiscaleImage image = MultiscaleImage.open(s3);
Metadata:
-- `getMultiscaleNode(int i)` → normalized `ome.metadata.MultiscalesEntry`
+- `getMultiscaleNode(int i)` → normalized `omezarr.metadata.MultiscalesEntry`
- `getAxisNames()` → axis names from multiscale `0`
- `getScaleLevelCount()` → number of datasets/levels in multiscale `0`
- `getLabels()` / `openLabel(String)` → labels subgroup helpers
@@ -64,7 +91,7 @@ If you need the raw version-specific metadata model instead of normalized `Multi
## v0.6 Scene metadata
-Scene roots (groups with `ome.scene`) are supported via `dev.zarr.zarrjava.experimental.ome.v0_6.Scene`:
+Scene roots (groups with `ome.scene`) are supported via `dev.zarr.omezarr.v0_6.Scene`:
- `Scene.openScene(StoreHandle)` / `Scene.open(StoreHandle)`
- `Scene.createScene(StoreHandle, SceneMetadata)` / `Scene.create(...)`
@@ -79,9 +106,10 @@ Notes:
## Read example
```java
-import dev.zarr.zarrjava.experimental.ome.MultiscaleImage;
-import dev.zarr.zarrjava.experimental.ome.Plate;
-import dev.zarr.zarrjava.experimental.ome.Well;
+import dev.zarr.omezarr.MultiscaleImage;
+import dev.zarr.omezarr.Plate;
+import dev.zarr.omezarr.Well;
+import dev.zarr.omezarr.metadata.MultiscalesEntry;
import dev.zarr.zarrjava.store.FilesystemStore;
import dev.zarr.zarrjava.store.StoreHandle;
@@ -90,7 +118,7 @@ MultiscaleImage image = MultiscaleImage.open(imageHandle);
int scaleCount = image.getScaleLevelCount();
java.util.List axisNames = image.getAxisNames();
-dev.zarr.zarrjava.experimental.ome.metadata.MultiscalesEntry entry0 = image.getMultiscaleNode(0);
+MultiscalesEntry entry0 = image.getMultiscaleNode(0);
dev.zarr.zarrjava.core.Array s0 = image.openScaleLevel(0);
ucar.ma2.Array full = s0.read();
@@ -112,9 +140,10 @@ MultiscaleImage wellImage = well.openImage("0");
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:
```java
-import dev.zarr.zarrjava.experimental.ome.metadata.Axis;
-import dev.zarr.zarrjava.experimental.ome.metadata.CoordinateTransformation;
-import dev.zarr.zarrjava.experimental.ome.metadata.MultiscalesEntry;
+import dev.zarr.omezarr.metadata.Axis;
+import dev.zarr.omezarr.metadata.Dataset;
+import dev.zarr.omezarr.metadata.MultiscalesEntry;
+import dev.zarr.omezarr.metadata.transform.CoordinateTransformation;
import dev.zarr.zarrjava.store.FilesystemStore;
import dev.zarr.zarrjava.store.StoreHandle;
import dev.zarr.zarrjava.v3.Array;
@@ -126,9 +155,9 @@ import java.util.Collections;
StoreHandle out = new FilesystemStore("/tmp/ome_v05.zarr").resolve();
MultiscalesEntry ms = new MultiscalesEntry(
Arrays.asList(new Axis("y", "space", "micrometer"), new Axis("x", "space", "micrometer")),
- Collections.emptyList());
+ Collections.emptyList()
);
-dev.zarr.zarrjava.experimental.ome.v0_5.MultiscaleImage written = dev.zarr.zarrjava.experimental.ome.v0_5.MultiscaleImage.create(out, ms);
+dev.zarr.omezarr.v0_5.MultiscaleImage written = dev.zarr.omezarr.v0_5.MultiscaleImage.create(out, ms);
written.createScaleLevel(
"s0",
@@ -144,8 +173,8 @@ written.createScaleLevel(
## Write entry points by version
-- `ome.v0_4.MultiscaleImage.create(...)`
-- `ome.v0_5.MultiscaleImage.create(...)`
-- `ome.v0_6.MultiscaleImage.create(...)`
+- `dev.zarr.omezarr.v0_4.MultiscaleImage.create(...)`
+- `dev.zarr.omezarr.v0_5.MultiscaleImage.create(...)`
+- `dev.zarr.omezarr.v0_6.MultiscaleImage.create(...)`
Use the corresponding metadata classes for each version package.
diff --git a/USERGUIDE.md b/USERGUIDE.md
index 65bf9944..966d2449 100644
--- a/USERGUIDE.md
+++ b/USERGUIDE.md
@@ -31,15 +31,25 @@ Add the following dependency to your `pom.xml`:
```xml
dev.zarr
- zarr-java
- 0.0.10
+ zarr-java-core
+ 0.1.3
+
+```
+For OME-Zarr support, also add:
+```xml
+
+ dev.zarr
+ zarr-java-ome
+ 0.1.3
```
### Gradle
Add the following to your `build.gradle`:
```gradle
dependencies {
- implementation 'dev.zarr:zarr-java:0.0.10'
+ implementation 'dev.zarr:zarr-java-core:0.1.3'
+ // Optional: OME-Zarr support
+ implementation 'dev.zarr:zarr-java-ome:0.1.3'
}
```
### Requirements
@@ -680,7 +690,9 @@ try {
## OME-Zarr (v0.4, v0.5, v0.6)
-For a focused OME-Zarr API guide (metadata access, array access, version behavior, and concise examples),
+OME-Zarr support is provided by the separate `zarr-java-ome` module (package `dev.zarr.omezarr`).
+
+For the full OME-Zarr API guide (installation, metadata access, array access, version behavior, and concise examples),
see:
- [`USERGUIDE-OME-ZARR.md`](USERGUIDE-OME-ZARR.md)
diff --git a/notebooks/notebooks/ome_zarr_integration.ipynb b/notebooks/notebooks/ome_zarr_integration.ipynb
new file mode 100644
index 00000000..24668172
--- /dev/null
+++ b/notebooks/notebooks/ome_zarr_integration.ipynb
@@ -0,0 +1,368 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "9d688d3c",
+ "metadata": {},
+ "source": [
+ "# zarr-java OME-Zarr — Integration Tests\n",
+ "\n",
+ "Verifies that the code examples from `USERGUIDE-OME-ZARR.md` work against the locally-built JARs.\n",
+ "\n",
+ "**Before opening this notebook**, launch it via `./notebooks/start.sh` from the repo root. \n",
+ "That script builds the project, sets up the classpath, and starts JupyterLab — no internet access needed for the library.\n",
+ "\n",
+ "Run cells top-to-bottom with **Run All Cells** or `Shift+Enter`."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b3446545",
+ "metadata": {},
+ "source": [
+ "## Setup"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "8fc41c8f",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Repo root : /home/konstantin/Documents/zarr-java\n",
+ "Library : zarr-java-ome (loaded via IJAVA_CLASSPATH)\n"
+ ]
+ }
+ ],
+ "source": [
+ "// Confirm the library and repo root are available (set by start.sh)\n",
+ "String REPO_ROOT = System.getenv(\"REPO_ROOT\");\n",
+ "if (REPO_ROOT == null) throw new IllegalStateException(\n",
+ " \"REPO_ROOT is not set. Please start JupyterLab via ./notebooks/start.sh\");\n",
+ "System.out.println(\"Repo root : \" + REPO_ROOT);\n",
+ "System.out.println(\"Library : zarr-java-ome (loaded via IJAVA_CLASSPATH)\");"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4fdab7a3",
+ "metadata": {},
+ "source": [
+ "## 1 · Open a v0.5 multiscale image"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "9c191317",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Scale levels : 2\n",
+ "Axis names : [t, c, z, y, x]\n",
+ "Dataset[0] : 0\n"
+ ]
+ }
+ ],
+ "source": [
+ "import dev.zarr.omezarr.MultiscaleImage;\n",
+ "import dev.zarr.zarrjava.store.FilesystemStore;\n",
+ "import dev.zarr.zarrjava.store.StoreHandle;\n",
+ "import dev.zarr.omezarr.metadata.MultiscalesEntry;\n",
+ "\n",
+ "StoreHandle imageHandle = new FilesystemStore(REPO_ROOT + \"/zarr-java-ome/testdata/ome/v0.5\").resolve();\n",
+ "MultiscaleImage image = MultiscaleImage.open(imageHandle);\n",
+ "\n",
+ "System.out.println(\"Scale levels : \" + image.getScaleLevelCount());\n",
+ "System.out.println(\"Axis names : \" + image.getAxisNames());\n",
+ "System.out.println(\"Dataset[0] : \" + image.getMultiscaleNode(0).datasets.get(0).path);"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "121ba8b0",
+ "metadata": {},
+ "source": [
+ "## 2 · Read a scale level array"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "8ba27406",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Full shape : [1, 2, 8, 16, 16]\n",
+ "Subset shape: [1, 1, 4, 8, 8]\n"
+ ]
+ }
+ ],
+ "source": [
+ "dev.zarr.zarrjava.core.Array s0 = image.openScaleLevel(0);\n",
+ "ucar.ma2.Array full = s0.read();\n",
+ "ucar.ma2.Array subset = s0.read(new long[]{0,0,0,0,0}, new long[]{1,1,4,8,8});\n",
+ "\n",
+ "System.out.println(\"Full shape : \" + java.util.Arrays.toString(full.getShape()));\n",
+ "System.out.println(\"Subset shape: \" + java.util.Arrays.toString(subset.getShape()));"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "815bedce",
+ "metadata": {},
+ "source": [
+ "## 3 · Labels sub-group"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "c67e9594",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Labels: [nuclei]\n",
+ "Label axis names: [z, y, x]\n"
+ ]
+ }
+ ],
+ "source": [
+ "java.util.List labels = image.getLabels();\n",
+ "System.out.println(\"Labels: \" + labels);\n",
+ "\n",
+ "MultiscaleImage labelImage = image.openLabel(labels.get(0));\n",
+ "System.out.println(\"Label axis names: \" + labelImage.getAxisNames());"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "623f5298",
+ "metadata": {},
+ "source": [
+ "## 4 · HCS plate and well (v0.5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "02080c03",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Well axis names: [t, c, z, y, x]\n"
+ ]
+ }
+ ],
+ "source": [
+ "import dev.zarr.omezarr.Plate;\n",
+ "import dev.zarr.omezarr.Well;\n",
+ "\n",
+ "StoreHandle plateHandle = new FilesystemStore(REPO_ROOT + \"/zarr-java-ome/testdata/ome/v0.5_hcs\").resolve();\n",
+ "Plate plate = Plate.open(plateHandle);\n",
+ "Well well = plate.openWell(\"A/1\");\n",
+ "MultiscaleImage wellImage = well.openImage(\"0\");\n",
+ "\n",
+ "System.out.println(\"Well axis names: \" + wellImage.getAxisNames());"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1f1c5464",
+ "metadata": {},
+ "source": [
+ "## 5 · Write: create a new v0.5 multiscale image"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "12a67adf",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Written to /tmp/ome_test_v05.zarr\n"
+ ]
+ }
+ ],
+ "source": [
+ "import dev.zarr.omezarr.metadata.Axis;\n",
+ "import dev.zarr.omezarr.metadata.Dataset;\n",
+ "import dev.zarr.omezarr.metadata.transform.CoordinateTransformation;\n",
+ "import dev.zarr.zarrjava.v3.Array;\n",
+ "import dev.zarr.zarrjava.v3.DataType;\n",
+ "import java.util.Arrays;\n",
+ "import java.util.Collections;\n",
+ "\n",
+ "new ProcessBuilder(\"rm\", \"-rf\", \"/tmp/ome_test_v05.zarr\").start().waitFor();\n",
+ "\n",
+ "StoreHandle out = new FilesystemStore(\"/tmp/ome_test_v05.zarr\").resolve();\n",
+ "MultiscalesEntry ms = new MultiscalesEntry(\n",
+ " Arrays.asList(new Axis(\"y\", \"space\", \"micrometer\"), new Axis(\"x\", \"space\", \"micrometer\")),\n",
+ " Collections.emptyList()\n",
+ ");\n",
+ "dev.zarr.omezarr.v0_5.MultiscaleImage written =\n",
+ " dev.zarr.omezarr.v0_5.MultiscaleImage.create(out, ms);\n",
+ "\n",
+ "written.createScaleLevel(\n",
+ " \"s0\",\n",
+ " Array.metadataBuilder().withShape(1024, 1024).withChunkShape(256, 256).withDataType(DataType.UINT16).build(),\n",
+ " Collections.singletonList(CoordinateTransformation.scale(Arrays.asList(1.0, 1.0)))\n",
+ ");\n",
+ "written.createScaleLevel(\n",
+ " \"s1\",\n",
+ " Array.metadataBuilder().withShape(512, 512).withChunkShape(256, 256).withDataType(DataType.UINT16).build(),\n",
+ " Collections.singletonList(CoordinateTransformation.scale(Arrays.asList(2.0, 2.0)))\n",
+ ");\n",
+ "System.out.println(\"Written to /tmp/ome_test_v05.zarr\");"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14e5217a",
+ "metadata": {},
+ "source": [
+ "## 6 · Re-open and verify the written image"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "1c8d9fb3",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Is v0.5 instance : true\n",
+ "Scale level count: 2\n",
+ "s0 path : s0\n",
+ "s1 path : s1\n",
+ "s1 scale : [2.0, 2.0]\n"
+ ]
+ }
+ ],
+ "source": [
+ "MultiscaleImage reopened = MultiscaleImage.open(out);\n",
+ "MultiscalesEntry reopenedMs = reopened.getMultiscaleNode(0);\n",
+ "var s1Tx = (dev.zarr.omezarr.metadata.transform.ScaleCoordinateTransformation)\n",
+ " reopenedMs.datasets.get(1).coordinateTransformations.get(0);\n",
+ "\n",
+ "System.out.println(\"Is v0.5 instance : \" + (reopened instanceof dev.zarr.omezarr.v0_5.MultiscaleImage));\n",
+ "System.out.println(\"Scale level count: \" + reopened.getScaleLevelCount());\n",
+ "System.out.println(\"s0 path : \" + reopenedMs.datasets.get(0).path);\n",
+ "System.out.println(\"s1 path : \" + reopenedMs.datasets.get(1).path);\n",
+ "System.out.println(\"s1 scale : \" + s1Tx.scale);"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8b2f872c",
+ "metadata": {},
+ "source": [
+ "## 7 · v0.4 image (Zarr v2 layout)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "6f7ed6d8",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "v0.4 scale levels: 2\n",
+ "v0.4 axis names : [t, c, z, y, x]\n",
+ "v0.4 typed : true\n"
+ ]
+ }
+ ],
+ "source": [
+ "StoreHandle v04Handle = new FilesystemStore(REPO_ROOT + \"/zarr-java-ome/testdata/ome/v0.4\").resolve();\n",
+ "MultiscaleImage v04 = MultiscaleImage.open(v04Handle);\n",
+ "\n",
+ "System.out.println(\"v0.4 scale levels: \" + v04.getScaleLevelCount());\n",
+ "System.out.println(\"v0.4 axis names : \" + v04.getAxisNames());\n",
+ "System.out.println(\"v0.4 typed : \" + (v04 instanceof dev.zarr.omezarr.v0_4.MultiscaleImage));"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4732ab34",
+ "metadata": {},
+ "source": [
+ "## 8 · v0.4 HCS plate and well"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "9acec5bd",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "v0.4 HCS well axis names: [t, c, z, y, x]\n"
+ ]
+ }
+ ],
+ "source": [
+ "StoreHandle hcs04 = new FilesystemStore(REPO_ROOT + \"/zarr-java-ome/testdata/ome/v0.4_hcs\").resolve();\n",
+ "Plate plate04 = Plate.open(hcs04);\n",
+ "Well well04 = plate04.openWell(\"A/1\");\n",
+ "MultiscaleImage wellImage04 = well04.openImage(\"0\");\n",
+ "\n",
+ "System.out.println(\"v0.4 HCS well axis names: \" + wellImage04.getAxisNames());"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "c52412ee-de6f-471e-a7b0-b3f0f1155482",
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Java",
+ "language": "java",
+ "name": "java"
+ },
+ "language_info": {
+ "codemirror_mode": "java",
+ "file_extension": ".jshell",
+ "mimetype": "text/x-java-source",
+ "name": "Java",
+ "pygments_lexer": "java",
+ "version": "17.0.11+9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/notebooks/notebooks/zarr_core.ipynb b/notebooks/notebooks/zarr_core.ipynb
new file mode 100644
index 00000000..486fe1b4
--- /dev/null
+++ b/notebooks/notebooks/zarr_core.ipynb
@@ -0,0 +1,534 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "523846ff",
+ "metadata": {},
+ "source": [
+ "# zarr-java Core Library — Integration Tests\n",
+ "\n",
+ "Verifies that the code examples from `USERGUIDE.md` work against the locally-built JARs.\n",
+ "\n",
+ "**Start via** `./notebooks/start.sh` from the repo root — that builds the project, wires up the classpath, and opens JupyterLab. No internet access needed for the library.\n",
+ "\n",
+ "Run cells top-to-bottom with **Run All Cells** or `Shift+Enter`."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "feda2c11",
+ "metadata": {},
+ "source": [
+ "## Setup"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "9eeec8cb",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Repo root : /home/konstantin/Documents/zarr-java\n",
+ "Library : zarr-java-core (loaded via IJAVA_CLASSPATH)\n"
+ ]
+ }
+ ],
+ "source": [
+ "String REPO_ROOT = System.getenv(\"REPO_ROOT\");\n",
+ "if (REPO_ROOT == null) throw new IllegalStateException(\n",
+ " \"REPO_ROOT not set — start JupyterLab via ./notebooks/start.sh\");\n",
+ "System.out.println(\"Repo root : \" + REPO_ROOT);\n",
+ "System.out.println(\"Library : zarr-java-core (loaded via IJAVA_CLASSPATH)\");"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "6c218e45",
+ "metadata": {},
+ "source": [
+ "## 1 · v3 Array — MemoryStore: create, write, read"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "7b261c23",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Shape : [100, 100]\n",
+ "Element[0]: 1.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "import dev.zarr.zarrjava.v3.Array;\n",
+ "import dev.zarr.zarrjava.v3.DataType;\n",
+ "import dev.zarr.zarrjava.store.MemoryStore;\n",
+ "import dev.zarr.zarrjava.store.StoreHandle;\n",
+ "\n",
+ "StoreHandle memHandle = new MemoryStore().resolve(\"myarray\");\n",
+ "Array array = Array.create(\n",
+ " memHandle,\n",
+ " Array.metadataBuilder()\n",
+ " .withShape(100, 100)\n",
+ " .withDataType(DataType.FLOAT32)\n",
+ " .withChunkShape(10, 10)\n",
+ " .withFillValue(0.0f)\n",
+ " .build()\n",
+ ");\n",
+ "\n",
+ "ucar.ma2.Array data = ucar.ma2.Array.factory(\n",
+ " ucar.ma2.DataType.FLOAT, new int[]{100, 100});\n",
+ "java.util.Arrays.fill((float[]) data.getStorage(), 1.0f);\n",
+ "array.write(data);\n",
+ "\n",
+ "ucar.ma2.Array readBack = array.read();\n",
+ "System.out.println(\"Shape : \" + java.util.Arrays.toString(readBack.getShape()));\n",
+ "System.out.println(\"Element[0]: \" + readBack.getFloat(0));"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a65f885a",
+ "metadata": {},
+ "source": [
+ "## 2 · v3 Array — FilesystemStore: create, write, read subset"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "adc24169",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Written value : 42\n",
+ "Read back [0] : 42\n",
+ "Subset shape : [10, 10, 10]\n"
+ ]
+ }
+ ],
+ "source": [
+ "import dev.zarr.zarrjava.store.FilesystemStore;\n",
+ "\n",
+ "new ProcessBuilder(\"rm\", \"-rf\", \"/tmp/zarr_core_fs\").start().waitFor();\n",
+ "StoreHandle fsHandle = new FilesystemStore(\"/tmp/zarr_core_fs\").resolve(\"myarray\");\n",
+ "\n",
+ "Array fsArray = Array.create(\n",
+ " fsHandle,\n",
+ " Array.metadataBuilder()\n",
+ " .withShape(50, 50, 50)\n",
+ " .withDataType(DataType.INT32)\n",
+ " .withChunkShape(10, 10, 10)\n",
+ " .withFillValue(0)\n",
+ " .build()\n",
+ ");\n",
+ "\n",
+ "ucar.ma2.Array writeData = ucar.ma2.Array.factory(\n",
+ " ucar.ma2.DataType.INT, new int[]{10, 10, 10});\n",
+ "java.util.Arrays.fill((int[]) writeData.getStorage(), 42);\n",
+ "fsArray.write(new long[]{0, 0, 0}, writeData);\n",
+ "\n",
+ "ucar.ma2.Array subset = fsArray.read(new long[]{0, 0, 0}, new long[]{10, 10, 10});\n",
+ "System.out.println(\"Written value : 42\");\n",
+ "System.out.println(\"Read back [0] : \" + subset.getInt(0));\n",
+ "System.out.println(\"Subset shape : \" + java.util.Arrays.toString(subset.getShape()));"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8d3136d6",
+ "metadata": {},
+ "source": [
+ "## 3 · v3 Codecs — Blosc, Gzip, Zstd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "78c49bce",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Blosc read[0]: 1.0\n",
+ "Gzip read[0]: 1.0\n",
+ "Zstd read[0]: 1.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "MemoryStore codecStore = new MemoryStore();\n",
+ "\n",
+ "Array bloscArray = Array.create(\n",
+ " codecStore.resolve(\"blosc\"),\n",
+ " Array.metadataBuilder()\n",
+ " .withShape(100, 100).withDataType(DataType.FLOAT32)\n",
+ " .withChunkShape(50, 50).withFillValue(0.0f)\n",
+ " .withCodecs(c -> c.withBlosc(\"zstd\", 5))\n",
+ " .build()\n",
+ ");\n",
+ "bloscArray.write(data);\n",
+ "System.out.println(\"Blosc read[0]: \" + bloscArray.read().getFloat(0));\n",
+ "\n",
+ "Array gzipArray = Array.create(\n",
+ " codecStore.resolve(\"gzip\"),\n",
+ " Array.metadataBuilder()\n",
+ " .withShape(100, 100).withDataType(DataType.FLOAT32)\n",
+ " .withChunkShape(50, 50).withFillValue(0.0f)\n",
+ " .withCodecs(c -> c.withGzip(6))\n",
+ " .build()\n",
+ ");\n",
+ "gzipArray.write(data);\n",
+ "System.out.println(\"Gzip read[0]: \" + gzipArray.read().getFloat(0));\n",
+ "\n",
+ "Array zstdArray = Array.create(\n",
+ " codecStore.resolve(\"zstd\"),\n",
+ " Array.metadataBuilder()\n",
+ " .withShape(100, 100).withDataType(DataType.FLOAT32)\n",
+ " .withChunkShape(50, 50).withFillValue(0.0f)\n",
+ " .withCodecs(c -> c.withZstd(3))\n",
+ " .build()\n",
+ ");\n",
+ "zstdArray.write(data);\n",
+ "System.out.println(\"Zstd read[0]: \" + zstdArray.read().getFloat(0));"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4f46c716",
+ "metadata": {},
+ "source": [
+ "## 4 · v3 Sharding"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "94d1dddb",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Sharded shape : [20, 20, 20]\n",
+ "Sharded val[0]: 7\n"
+ ]
+ }
+ ],
+ "source": [
+ "Array shardedArray = Array.create(\n",
+ " new MemoryStore().resolve(\"sharded\"),\n",
+ " Array.metadataBuilder()\n",
+ " .withShape(100, 100, 100)\n",
+ " .withDataType(DataType.UINT8)\n",
+ " .withChunkShape(20, 20, 20)\n",
+ " .withFillValue((byte) 0)\n",
+ " .withCodecs(c -> c.withSharding(\n",
+ " new int[]{10, 10, 10},\n",
+ " inner -> inner.withBlosc(\"zstd\", 5)\n",
+ " ))\n",
+ " .build()\n",
+ ");\n",
+ "\n",
+ "ucar.ma2.Array chunkData = ucar.ma2.Array.factory(\n",
+ " ucar.ma2.DataType.UBYTE, new int[]{20, 20, 20});\n",
+ "java.util.Arrays.fill((byte[]) chunkData.getStorage(), (byte) 7);\n",
+ "shardedArray.write(new long[]{0, 0, 0}, chunkData);\n",
+ "\n",
+ "ucar.ma2.Array shardRead = shardedArray.read(new long[]{0,0,0}, new long[]{20,20,20});\n",
+ "System.out.println(\"Sharded shape : \" + java.util.Arrays.toString(shardRead.getShape()));\n",
+ "System.out.println(\"Sharded val[0]: \" + shardRead.getByte(0));"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7c7a54fe",
+ "metadata": {},
+ "source": [
+ "## 5 · v3 Groups — create hierarchy, navigate, access members"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "5073409e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Root member count : 3\n",
+ "data/ member count: 1\n",
+ "Child array shape : [1000, 1000]\n",
+ "Child array dtype : UINT16\n"
+ ]
+ }
+ ],
+ "source": [
+ "import dev.zarr.zarrjava.v3.Group;\n",
+ "\n",
+ "new ProcessBuilder(\"rm\", \"-rf\", \"/tmp/zarr_groups\").start().waitFor();\n",
+ "StoreHandle groupRoot = new FilesystemStore(\"/tmp/zarr_groups\").resolve();\n",
+ "Group root = Group.create(groupRoot);\n",
+ "\n",
+ "Group dataGroup = root.createGroup(\"data\");\n",
+ "Group metaGroup = root.createGroup(\"metadata\");\n",
+ "\n",
+ "Array childArray = dataGroup.createArray(\n",
+ " \"raw\",\n",
+ " Array.metadataBuilder()\n",
+ " .withShape(1000, 1000)\n",
+ " .withDataType(DataType.UINT16)\n",
+ " .withChunkShape(100, 100)\n",
+ " .withFillValue(0)\n",
+ " .build()\n",
+ ");\n",
+ "\n",
+ "long rootCount = root.list().count();\n",
+ "long dataCount = dataGroup.list().count();\n",
+ "Array retrieved = (Array) dataGroup.get(\"raw\");\n",
+ "\n",
+ "System.out.println(\"Root member count : \" + rootCount);\n",
+ "System.out.println(\"data/ member count: \" + dataCount);\n",
+ "System.out.println(\"Child array shape : \" + java.util.Arrays.toString(retrieved.metadata().shape));\n",
+ "System.out.println(\"Child array dtype : \" + retrieved.metadata().dataType);"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8bfe46b7",
+ "metadata": {},
+ "source": [
+ "## 6 · Attributes — set and read"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "d5f3b2e1",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "description: my dataset\n",
+ "units : meters\n",
+ "version : 2\n"
+ ]
+ }
+ ],
+ "source": [
+ "import dev.zarr.zarrjava.core.Attributes;\n",
+ "\n",
+ "Array attrArray = Array.create(\n",
+ " new MemoryStore().resolve(\"withattrs\"),\n",
+ " Array.metadataBuilder()\n",
+ " .withShape(10, 10)\n",
+ " .withDataType(DataType.INT32)\n",
+ " .withChunkShape(5, 5)\n",
+ " .withFillValue(0)\n",
+ " .build()\n",
+ ");\n",
+ "\n",
+ "Attributes attrs = new Attributes();\n",
+ "attrs.put(\"description\", \"my dataset\");\n",
+ "attrs.put(\"units\", \"meters\");\n",
+ "attrs.put(\"version\", 2);\n",
+ "attrArray = attrArray.setAttributes(attrs);\n",
+ "\n",
+ "Attributes readAttrs = attrArray.metadata().attributes();\n",
+ "System.out.println(\"description: \" + readAttrs.get(\"description\"));\n",
+ "System.out.println(\"units : \" + readAttrs.get(\"units\"));\n",
+ "System.out.println(\"version : \" + readAttrs.get(\"version\"));"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "32b3d7dd",
+ "metadata": {},
+ "source": [
+ "## 7 · v2 Array — create, write, read with Blosc and Zlib"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "bac2a371",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "v2 Blosc shape : [10, 10]\n",
+ "v2 Blosc val[0] : 9\n",
+ "v2 Zlib shape : [15, 10]\n"
+ ]
+ }
+ ],
+ "source": [
+ "// Use fully-qualified names to avoid conflict with v3 Array/DataType imported above\n",
+ "dev.zarr.zarrjava.v2.Array v2Blosc = dev.zarr.zarrjava.v2.Array.create(\n",
+ " new MemoryStore().resolve(\"v2blosc\"),\n",
+ " dev.zarr.zarrjava.v2.Array.metadataBuilder()\n",
+ " .withShape(10, 10)\n",
+ " .withDataType(dev.zarr.zarrjava.v2.DataType.UINT8)\n",
+ " .withChunks(5, 5)\n",
+ " .withFillValue(1)\n",
+ " .withBloscCompressor(\"lz4\", \"shuffle\", 5)\n",
+ " .build()\n",
+ ");\n",
+ "ucar.ma2.Array v2Data = ucar.ma2.Array.factory(\n",
+ " ucar.ma2.DataType.UBYTE, new int[]{10, 10});\n",
+ "java.util.Arrays.fill((byte[]) v2Data.getStorage(), (byte) 9);\n",
+ "v2Blosc.write(v2Data);\n",
+ "System.out.println(\"v2 Blosc shape : \" + java.util.Arrays.toString(v2Blosc.read().getShape()));\n",
+ "System.out.println(\"v2 Blosc val[0] : \" + v2Blosc.read().getByte(0));\n",
+ "\n",
+ "dev.zarr.zarrjava.v2.Array v2Zlib = dev.zarr.zarrjava.v2.Array.create(\n",
+ " new MemoryStore().resolve(\"v2zlib\"),\n",
+ " dev.zarr.zarrjava.v2.Array.metadataBuilder()\n",
+ " .withShape(15, 10)\n",
+ " .withDataType(dev.zarr.zarrjava.v2.DataType.UINT8)\n",
+ " .withChunks(5, 5)\n",
+ " .withFillValue(0)\n",
+ " .withZlibCompressor(6)\n",
+ " .build()\n",
+ ");\n",
+ "v2Zlib.write(ucar.ma2.Array.factory(ucar.ma2.DataType.UBYTE, new int[]{15, 10}));\n",
+ "System.out.println(\"v2 Zlib shape : \" + java.util.Arrays.toString(v2Zlib.read().getShape()));"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9366e213",
+ "metadata": {},
+ "source": [
+ "## 8 · ZIP Store — write with BufferedZipStore, read with ReadOnlyZipStore"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "fc75c70a",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "ZIP shape : [100, 100]\n",
+ "ZIP val[0] : 3.14\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "java.io.PrintStream@69564c9a"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "import dev.zarr.zarrjava.store.BufferedZipStore;\n",
+ "import dev.zarr.zarrjava.store.ReadOnlyZipStore;\n",
+ "\n",
+ "java.nio.file.Path zipPath = java.nio.file.Paths.get(\"/tmp/zarr_test.zip\");\n",
+ "zipPath.toFile().delete();\n",
+ "\n",
+ "try (BufferedZipStore zipWrite = new BufferedZipStore(zipPath)) {\n",
+ " Array zipArray = Array.create(\n",
+ " zipWrite.resolve(\"myarray\"),\n",
+ " Array.metadataBuilder()\n",
+ " .withShape(100, 100)\n",
+ " .withDataType(DataType.FLOAT32)\n",
+ " .withChunkShape(10, 10)\n",
+ " .withFillValue(0.0f)\n",
+ " .build()\n",
+ " );\n",
+ " ucar.ma2.Array zipData = ucar.ma2.Array.factory(\n",
+ " ucar.ma2.DataType.FLOAT, new int[]{100, 100});\n",
+ " java.util.Arrays.fill((float[]) zipData.getStorage(), 3.14f);\n",
+ " zipArray.write(zipData);\n",
+ "} // auto-closes and flushes to disk\n",
+ "\n",
+ "ReadOnlyZipStore zipRead = new ReadOnlyZipStore(zipPath);\n",
+ "Array zipReadArray = Array.open(zipRead.resolve(\"myarray\"));\n",
+ "ucar.ma2.Array zipResult = zipReadArray.read();\n",
+ "System.out.println(\"ZIP shape : \" + java.util.Arrays.toString(zipResult.getShape()));\n",
+ "System.out.printf (\"ZIP val[0] : %.2f%n\", zipResult.getFloat(0));"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0e1cd514",
+ "metadata": {},
+ "source": [
+ "## 9 · Open existing testdata (v3 from repo)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "id": "f1f837c0",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Testdata shape : [16, 16, 16]\n",
+ "Testdata dtype : INT32\n",
+ "Testdata chunks : [16, 8, 8]\n"
+ ]
+ }
+ ],
+ "source": [
+ "Array existing = Array.open(\n",
+ " new FilesystemStore(REPO_ROOT +\n",
+ " \"/zarr-java-core/testdata/sharding_index_location/end\").resolve()\n",
+ ");\n",
+ "System.out.println(\"Testdata shape : \" + java.util.Arrays.toString(existing.metadata().shape));\n",
+ "System.out.println(\"Testdata dtype : \" + existing.metadata().dataType);\n",
+ "System.out.println(\"Testdata chunks : \" + java.util.Arrays.toString(existing.metadata().chunkShape()));"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Java",
+ "language": "java",
+ "name": "java"
+ },
+ "language_info": {
+ "codemirror_mode": "java",
+ "file_extension": ".jshell",
+ "mimetype": "text/x-java-source",
+ "name": "Java",
+ "pygments_lexer": "java",
+ "version": "17.0.11+9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/notebooks/start.sh b/notebooks/start.sh
new file mode 100755
index 00000000..c917b2df
--- /dev/null
+++ b/notebooks/start.sh
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# ---------------------------------------------------------------------------
+# Resolve repo root (parent of the notebooks/ directory this script lives in)
+# ---------------------------------------------------------------------------
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+export REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
+
+JUPYTER_VENV="$HOME/.jupyter-venv"
+IJAVA_VERSION="1.3.0"
+IJAVA_KERNEL_DIR="$JUPYTER_VENV/share/jupyter/kernels/java"
+
+echo "==> Repo root: $REPO_ROOT"
+
+# Check prerequisites
+for cmd in java mvn python3 curl unzip; do
+ if ! command -v "$cmd" &>/dev/null; then
+ echo "ERROR: '$cmd' not found. Please install it before running this script." >&2
+ exit 1
+ fi
+done
+
+# Build the project — installs JARs into ~/.m2 (no internet for the lib)
+echo "==> Building zarr-java (skipping tests)..."
+cd "$REPO_ROOT"
+mvn install -DskipTests -q
+echo " Build done."
+
+# Build IJAVA_CLASSPATH directly from ~/.m2 — no copying needed
+echo "==> Resolving classpath from local Maven repo..."
+CLASSPATH_FILE="$(mktemp)"
+mvn dependency:build-classpath \
+ -pl zarr-java-ome \
+ -DincludeScope=runtime \
+ -Dmdep.outputFile="$CLASSPATH_FILE" \
+ -q
+DEPS_CLASSPATH="$(cat "$CLASSPATH_FILE")"
+rm -f "$CLASSPATH_FILE"
+
+OME_JAR=$(find "$REPO_ROOT/zarr-java-ome/target" -name "zarr-java-ome-*.jar" \
+ ! -name "*sources*" ! -name "*javadoc*" | head -1)
+OME_JAR="$(cd "$(dirname "$OME_JAR")" && pwd)/$(basename "$OME_JAR")"
+
+export IJAVA_CLASSPATH="$OME_JAR:$DEPS_CLASSPATH"
+echo " Classpath ready ($(echo "$IJAVA_CLASSPATH" | tr ':' '\n' | wc -l) entries)."
+
+# Ensure Jupyter is installed in ~/.jupyter-venv
+if [ ! -x "$JUPYTER_VENV/bin/jupyter" ]; then
+ echo "==> Jupyter not found — creating venv and installing..."
+ python3 -m venv "$JUPYTER_VENV"
+ "$JUPYTER_VENV/bin/pip" install jupyter --quiet
+ echo " Jupyter installed."
+fi
+
+# Ensure IJava kernel is installed (one-time download from GitHub — only the tooling, not the library)
+if [ ! -f "$IJAVA_KERNEL_DIR/kernel.json" ]; then
+ echo "==> IJava kernel not found — downloading and installing (one-time)..."
+ TMP_IJAVA="$(mktemp -d)"
+ curl -sL "https://github.com/SpencerPark/IJava/releases/download/v${IJAVA_VERSION}/ijava-${IJAVA_VERSION}.zip" \
+ -o "$TMP_IJAVA/ijava.zip"
+ unzip -q "$TMP_IJAVA/ijava.zip" -d "$TMP_IJAVA"
+ JUPYTER_DATA_DIR="$JUPYTER_VENV/share/jupyter" \
+ "$JUPYTER_VENV/bin/python" "$TMP_IJAVA/install.py" --sys-prefix
+ rm -rf "$TMP_IJAVA"
+ echo " IJava kernel installed."
+fi
+
+# Launch JupyterLab — opens directly into the notebooks/ subfolder
+echo "==> Starting JupyterLab — press Ctrl+C to stop."
+echo ""
+JUPYTER_DATA_DIR="$JUPYTER_VENV/share/jupyter" \
+ "$JUPYTER_VENV/bin/jupyter" lab "$SCRIPT_DIR/notebooks"
diff --git a/pom.xml b/pom.xml
index 36eb31ca..ff478c58 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,9 +7,15 @@
dev.zarr
zarr-java
0.1.3
+ pom
zarr-java
+
+ zarr-java-core
+ zarr-java-ome
+
+
zarr-java is a Java library providing an implementation of chunked,
compressed, N-dimensional arrays close to the zarr-python package.
@@ -52,94 +58,6 @@
3.0.2
-
-
-
- org.junit.jupiter
- junit-jupiter-api
- ${junit-jupiter-version}
- test
-
-
- org.junit.jupiter
- junit-jupiter-engine
- ${junit-jupiter-version}
- test
-
-
- org.junit.jupiter
- junit-jupiter-params
- ${junit-jupiter-version}
- test
-
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
- ${jackson.version}
-
-
- com.fasterxml.jackson.datatype
- jackson-datatype-jdk8
- ${jackson.version}
-
-
- com.google.code.findbugs
- jsr305
- ${findbugs.version}
-
-
- edu.ucar
- cdm-core
- ${netcdfJavaVersion}
-
-
- software.amazon.awssdk
- s3
- ${aws.version}
-
-
- com.scalableminds
- blosc-java
- 0.3-1.21.6
-
-
- com.github.luben
- zstd-jni
- ${zstdVersion}
-
-
- com.squareup.okhttp3
- okhttp
- 4.12.0
-
-
- com.squareup.okhttp3
- mockwebserver
- 4.12.0
- test
-
-
-
- junit
- junit
- 4.13.1
- test
-
-
- org.apache.commons
- commons-compress
- 1.28.0
-
-
-
- info.picocli
- picocli
- 4.7.6
-
-
-
unidata-all
@@ -149,132 +67,131 @@
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 3.2.5
-
- false
-
-
- 1.44
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.13.0
-
- ${maven.compiler.release}
- UTF-8
-
- .gitignore
- temp/**
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 3.1.0
-
-
- verify
-
- jar
-
-
-
- temp.**
-
-
-
-
-
- true
-
-
-
- org.apache.maven.plugins
- maven-resources-plugin
- 3.1.0
-
- UTF-8
-
-
-
- org.codehaus.mojo
- build-helper-maven-plugin
- 1.10
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 3.5.0
-
-
- attach-javadoc
-
- jar
-
-
-
-
- 8
-
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 1.6
-
-
- sign-artifacts
- verify
-
- sign
-
-
- 9F88D86AD9A0D91E
-
-
-
-
-
- org.sonatype.central
- central-publishing-maven-plugin
- 0.8.0
- true
-
- central
- true
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 3.5.0
-
-
- package
-
- shade
-
-
- true
- shaded
- false
-
-
- dev.zarr.zarrjava.cli.Main
-
-
-
-
-
-
-
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.2.5
+
+ false
+
+ 1.44
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.13.0
+
+ ${maven.compiler.release}
+ UTF-8
+
+ .gitignore
+ temp/**
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.1.0
+
+
+ verify
+
+ jar
+
+
+
+ temp.**
+
+
+
+
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 3.1.0
+
+ UTF-8
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 1.10
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.5.0
+
+
+ attach-javadoc
+
+ jar
+
+
+
+
+ 8
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.8.0
+ true
+
+ central
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.5.0
+
+
+
+
+
+
+ release
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+ 9F88D86AD9A0D91E
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_6/MultiscaleImage.java b/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_6/MultiscaleImage.java
deleted file mode 100644
index 327f7187..00000000
--- a/src/main/java/dev/zarr/zarrjava/experimental/ome/v0_6/MultiscaleImage.java
+++ /dev/null
@@ -1,498 +0,0 @@
-package dev.zarr.zarrjava.experimental.ome.v0_6;
-
-import dev.zarr.zarrjava.ZarrException;
-import dev.zarr.zarrjava.experimental.ome.MultiscalesMetadataImage;
-import dev.zarr.zarrjava.experimental.ome.OmeV3Group;
-import dev.zarr.zarrjava.experimental.ome.metadata.Axis;
-import dev.zarr.zarrjava.experimental.ome.metadata.transform.CoordinateTransformation;
-import dev.zarr.zarrjava.experimental.ome.metadata.transform.IdentityCoordinateTransformation;
-import dev.zarr.zarrjava.experimental.ome.metadata.transform.ScaleCoordinateTransformation;
-import dev.zarr.zarrjava.experimental.ome.metadata.transform.TranslationCoordinateTransformation;
-import dev.zarr.zarrjava.experimental.ome.v0_6.metadata.CoordinateSystem;
-import dev.zarr.zarrjava.experimental.ome.v0_6.metadata.MultiscalesEntry;
-import dev.zarr.zarrjava.experimental.ome.v0_6.metadata.OmeMetadata;
-import dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.GenericCoordinateTransformation;
-import dev.zarr.zarrjava.store.StoreHandle;
-import dev.zarr.zarrjava.v3.Array;
-import dev.zarr.zarrjava.v3.Group;
-import dev.zarr.zarrjava.v3.GroupMetadata;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * OME-Zarr v0.6 (RFC-5) multiscale image backed by a Zarr v3 group.
- */
-public final class MultiscaleImage extends OmeV3Group implements MultiscalesMetadataImage {
-
- private OmeMetadata omeMetadata;
-
- private MultiscaleImage(
- @Nonnull StoreHandle storeHandle,
- @Nonnull GroupMetadata groupMetadata,
- @Nonnull OmeMetadata omeMetadata
- ) throws IOException {
- super(storeHandle, groupMetadata);
- this.omeMetadata = omeMetadata;
- }
-
- /**
- * Opens an existing OME-Zarr v0.6 multiscale image at the given store handle.
- */
- public static MultiscaleImage openMultiscaleImage(@Nonnull StoreHandle storeHandle) throws IOException, ZarrException {
- Group group = Group.open(storeHandle);
- OmeMetadata omeMetadata = readOmeAttribute(
- group.metadata.attributes, storeHandle, OmeMetadata.class);
- if (!omeMetadata.version.startsWith("0.6")) {
- throw new ZarrException(
- "Expected OME-Zarr version '0.6', got '" + omeMetadata.version + "' at " + storeHandle);
- }
- if (omeMetadata.multiscales == null || omeMetadata.multiscales.isEmpty()) {
- if (omeMetadata.scene != null) {
- throw new ZarrException(
- "OME-Zarr v0.6 scene metadata found at " + storeHandle
- + "; use dev.zarr.zarrjava.experimental.ome.v0_6.Scene.open(...)");
- }
- throw new ZarrException("No 'multiscales' found in ome metadata at " + storeHandle);
- }
- return new MultiscaleImage(storeHandle, group.metadata, omeMetadata);
- }
-
- /**
- * Creates a new OME-Zarr v0.6 multiscale image at the given store handle.
- */
- public static MultiscaleImage create(
- @Nonnull StoreHandle storeHandle,
- @Nonnull MultiscalesEntry multiscalesEntry
- ) throws IOException, ZarrException {
- OmeMetadata omeMetadata = new OmeMetadata("0.6", Collections.singletonList(multiscalesEntry));
- Group group = Group.create(storeHandle, omeAttributes(omeMetadata));
- return new MultiscaleImage(storeHandle, group.metadata, omeMetadata);
- }
-
- @Override
- public StoreHandle getStoreHandle() {
- return this.storeHandle;
- }
-
- @Override
- public MultiscalesEntry getMultiscalesEntry(int i) throws ZarrException {
- return omeMetadata.multiscales.get(i);
- }
-
- @Override
- @Nullable
- public dev.zarr.zarrjava.experimental.ome.metadata.OmeroMetadata getOmeroMetadata() {
- return omeMetadata.omero;
- }
-
- @Override
- @Nullable
- public Integer getBioformats2rawLayout() {
- return omeMetadata.bioformats2rawLayout;
- }
-
- OmeMetadata getRawOmeMetadata() {
- return omeMetadata;
- }
-
- @Override
- public dev.zarr.zarrjava.core.Array openScaleLevel(int i) throws IOException, ZarrException {
- String path = getMultiscalesEntry(0).datasets.get(i).path;
- return Array.open(storeHandle.resolve(path));
- }
-
- @Override
- public int getScaleLevelCount() throws ZarrException {
- return getMultiscalesEntry(0).datasets.size();
- }
-
- @Override
- public void createScaleLevel(
- String path,
- dev.zarr.zarrjava.core.ArrayMetadata arrayMetadata,
- List coordinateTransformations
- ) throws IOException, ZarrException {
- if (!(arrayMetadata instanceof dev.zarr.zarrjava.v3.ArrayMetadata)) {
- throw new ZarrException("Expected v3.ArrayMetadata for OME-Zarr v0.6, got " + arrayMetadata.getClass());
- }
- Array.create(storeHandle.resolve(path), (dev.zarr.zarrjava.v3.ArrayMetadata) arrayMetadata);
-
- // Convert ome.metadata.CoordinateTransformation to v0.6 CoordinateTransformation
- List v06Transforms = new ArrayList<>();
- for (CoordinateTransformation ct : coordinateTransformations) {
- String type = ct.type;
- List scale = null;
- List translation = null;
- String rawPath = null;
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.metadata.transform.ScaleCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.metadata.transform.ScaleCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.metadata.transform.ScaleCoordinateTransformation) ct;
- scale = t.scale;
- rawPath = t.path;
- } else if (ct instanceof dev.zarr.zarrjava.experimental.ome.metadata.transform.TranslationCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.metadata.transform.TranslationCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.metadata.transform.TranslationCoordinateTransformation) ct;
- translation = t.translation;
- rawPath = t.path;
- } else if (ct instanceof dev.zarr.zarrjava.experimental.ome.metadata.transform.IdentityCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.metadata.transform.IdentityCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.metadata.transform.IdentityCoordinateTransformation) ct;
- rawPath = t.path;
- } else if (ct instanceof dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation) {
- Map raw = ((dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation) ct).raw;
- Object s = raw.get("scale");
- Object tr = raw.get("translation");
- Object p = raw.get("path");
- if (s instanceof List) scale = castDoubleList((List>) s);
- if (tr instanceof List) translation = castDoubleList((List>) tr);
- if (p instanceof String) rawPath = (String) p;
-
- if ("sequence".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.SequenceCoordinateTransformation(
- null, null, null, castV06TransformList(raw.get("transformations"))));
- continue;
- }
- if ("mapAxis".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.MapAxisCoordinateTransformation(
- null, null, null, castIntList(raw.get("mapAxis")), castV06Transform(raw.get("transformation"))));
- continue;
- }
- if ("affine".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.AffineCoordinateTransformation(
- null, null, null, castMatrix(raw.get("affine")), rawPath));
- continue;
- }
- if ("rotation".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.RotationCoordinateTransformation(
- null, null, null, castMatrix(raw.get("rotation")), rawPath));
- continue;
- }
- if ("displacements".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.DisplacementsCoordinateTransformation(
- null, null, null, rawPath));
- continue;
- }
- if ("coordinates".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.CoordinatesCoordinateTransformation(
- null, null, null, rawPath));
- continue;
- }
- if ("bijection".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.BijectionCoordinateTransformation(
- null, null, null, castV06Transform(raw.get("forward")), castV06Transform(raw.get("inverse"))));
- continue;
- }
- if ("byDimension".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.ByDimensionCoordinateTransformation(
- null, null, null, castByDimensionTransformList(raw.get("transformations"))));
- continue;
- }
- }
- if ("scale".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.ScaleCoordinateTransformation(
- null, null, null, scale, rawPath));
- } else if ("translation".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.TranslationCoordinateTransformation(
- null, null, null, translation, rawPath));
- } else if ("identity".equals(type)) {
- v06Transforms.add(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.IdentityCoordinateTransformation(
- null, null, null, rawPath));
- } else {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.GenericCoordinateTransformation generic =
- new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.GenericCoordinateTransformation(type, null, null, null);
- if (scale != null) generic.raw.put("scale", scale);
- if (translation != null) generic.raw.put("translation", translation);
- if (rawPath != null) generic.raw.put("path", rawPath);
- v06Transforms.add(generic);
- }
- }
-
- MultiscalesEntry current = omeMetadata.multiscales.get(0);
- MultiscalesEntry updated = current.withDataset(new dev.zarr.zarrjava.experimental.ome.v0_6.metadata.Dataset(path, v06Transforms));
- List updatedList = new ArrayList<>(omeMetadata.multiscales);
- updatedList.set(0, updated);
- omeMetadata = new OmeMetadata(
- omeMetadata.version,
- updatedList,
- omeMetadata.omero,
- omeMetadata.bioformats2rawLayout,
- omeMetadata.scene,
- omeMetadata.plate,
- omeMetadata.well);
- setAttributes(omeAttributes(omeMetadata));
- }
-
- @Override
- public dev.zarr.zarrjava.experimental.ome.metadata.MultiscalesEntry getMultiscaleNode(int i) throws ZarrException {
- MultiscalesEntry entry = getMultiscalesEntry(i);
- List mappedDatasets = new ArrayList<>();
- for (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.Dataset ds : entry.datasets) {
- List mapped = new ArrayList<>();
- for (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.CoordinateTransformation ct : ds.coordinateTransformations) {
- mapped.add(mapTransform(ct));
- }
- mappedDatasets.add(new dev.zarr.zarrjava.experimental.ome.metadata.Dataset(ds.path, mapped));
- }
- List axes = entry.axes;
- if ((axes == null || axes.isEmpty()) && entry.coordinateSystems != null && !entry.coordinateSystems.isEmpty()) {
- axes = entry.coordinateSystems.get(0).axes;
- }
- return new dev.zarr.zarrjava.experimental.ome.metadata.MultiscalesEntry(
- axes != null ? axes : Collections.emptyList(),
- mappedDatasets, null, entry.name, null, null, null);
- }
-
- private static CoordinateTransformation mapTransform(
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.CoordinateTransformation ct) {
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.ScaleCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.ScaleCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.ScaleCoordinateTransformation) ct;
- return new ScaleCoordinateTransformation(t.scale, t.path);
- }
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.TranslationCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.TranslationCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.TranslationCoordinateTransformation) ct;
- return new TranslationCoordinateTransformation(t.translation, t.path);
- }
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.IdentityCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.IdentityCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.IdentityCoordinateTransformation) ct;
- return new IdentityCoordinateTransformation(t.path);
- }
- if (ct instanceof GenericCoordinateTransformation) {
- GenericCoordinateTransformation t = (GenericCoordinateTransformation) ct;
- dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation generic =
- new dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation(ct.getType());
- for (Map.Entry entry : t.raw.entrySet()) {
- generic.raw.put(entry.getKey(), convertRawValue(entry.getValue()));
- }
- return generic;
- }
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.SequenceCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.SequenceCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.SequenceCoordinateTransformation) ct;
- dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation generic =
- new dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation("sequence");
- generic.raw.put("transformations", mapTransformList(t.transformations));
- return generic;
- }
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.MapAxisCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.MapAxisCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.MapAxisCoordinateTransformation) ct;
- dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation generic =
- new dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation("mapAxis");
- generic.raw.put("mapAxis", t.mapAxis);
- if (t.transformation != null) {
- generic.raw.put("transformation", mapTransform(t.transformation));
- }
- return generic;
- }
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.AffineCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.AffineCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.AffineCoordinateTransformation) ct;
- dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation generic =
- new dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation("affine");
- generic.raw.put("affine", t.affine);
- if (t.path != null) {
- generic.raw.put("path", t.path);
- }
- return generic;
- }
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.RotationCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.RotationCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.RotationCoordinateTransformation) ct;
- dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation generic =
- new dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation("rotation");
- generic.raw.put("rotation", t.rotation);
- if (t.path != null) {
- generic.raw.put("path", t.path);
- }
- return generic;
- }
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.DisplacementsCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.DisplacementsCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.DisplacementsCoordinateTransformation) ct;
- dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation generic =
- new dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation("displacements");
- generic.raw.put("path", t.path);
- return generic;
- }
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.CoordinatesCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.CoordinatesCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.CoordinatesCoordinateTransformation) ct;
- dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation generic =
- new dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation("coordinates");
- generic.raw.put("path", t.path);
- return generic;
- }
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.BijectionCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.BijectionCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.BijectionCoordinateTransformation) ct;
- dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation generic =
- new dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation("bijection");
- if (t.forward != null) {
- generic.raw.put("forward", mapTransform(t.forward));
- }
- if (t.inverse != null) {
- generic.raw.put("inverse", mapTransform(t.inverse));
- }
- return generic;
- }
- if (ct instanceof dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.ByDimensionCoordinateTransformation) {
- dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.ByDimensionCoordinateTransformation t =
- (dev.zarr.zarrjava.experimental.ome.v0_6.metadata.transform.ByDimensionCoordinateTransformation) ct;
- dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation generic =
- new dev.zarr.zarrjava.experimental.ome.metadata.transform.GenericCoordinateTransformation("byDimension");
- if (t.transformations != null) {
- List