Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f5431eb
Use zarr v3 and updated ome-zarr-py
will-moore May 27, 2025
9ba766b
Fix tests for writing v0.4
will-moore Jun 18, 2025
f852803
temp use PR to install ome-zarr-py
will-moore Jun 19, 2025
b2b311f
Install ome-zarr-py PR413 in .omeroci/py-setup
will-moore Jun 19, 2025
c4ab8c1
Add zarr>=3.0.8 to install_requires
will-moore Jun 19, 2025
d5edd5d
Add --version arg for export Image. '0.5' by default
will-moore Jun 19, 2025
61f5f2f
Support --version for labels export
will-moore Jun 19, 2025
3d9bbfc
TEMP set compressor
will-moore Aug 12, 2025
99a2d79
Rename --version to --format
will-moore Aug 18, 2025
d052831
Update tests to use --format for all tests
will-moore Aug 18, 2025
369b46f
Use ome-zarr==0.12rc1 release candidate
will-moore Aug 18, 2025
2407fc0
Use jburel/omero-test-infra branch python3.12
will-moore Aug 19, 2025
99c447a
Review dependencies
jburel Aug 26, 2025
5cdeb1e
Use frombuffer
jburel Aug 25, 2025
c8726ba
Review import
jburel Aug 26, 2025
38befa5
Merge remote-tracking branch 'origin/master' into zarr_v3
will-moore Sep 26, 2025
7fb1d3f
Fix export with zarr v3
will-moore Sep 26, 2025
12ef133
Try to workaround mypy fail with different import
will-moore Sep 26, 2025
72d41ab
fix LocalStore() for import
will-moore Sep 26, 2025
0f9cb71
Let zarr handle store creation
will-moore Sep 26, 2025
1021eca
Use ome-zarr>=0.12.0 to use Zarr v3 dependency
will-moore Oct 13, 2025
a2075d0
Don't use ome-zarr parse_url()
will-moore Nov 4, 2025
34b94cf
write_multiscales_metadata() uses fmt=FormatV05()
will-moore Nov 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/omero_plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ jobs:
- name: Checkout omero-test-infra
uses: actions/checkout@master
with:
repository: ome/omero-test-infra
repository: jburel/omero-test-infra
path: .omero
ref: ${{ secrets.OMERO_TEST_INFRA_REF }}
ref: python3.12
# ref: ${{ secrets.OMERO_TEST_INFRA_REF }}
- name: Build and run OMERO tests
run: .omero/docker $STAGE
2 changes: 1 addition & 1 deletion .isort.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[settings]
known_third_party = dask,numpy,ome_zarr,omero,omero_rois,omero_version,omero_zarr,pytest,setuptools,skimage,zarr
known_third_party = dask,numcodecs,numpy,ome_zarr,omero,omero_rois,omero_version,omero_zarr,pytest,setuptools,skimage,zarr
5 changes: 4 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ To export Images or Plates via the OMERO API::
# Plate will be saved in current directory as 2.ome.zarr
$ omero zarr export Plate:2

# Specify the OME-Zarr format, e.g. 0.4. Default is 0.5
$ omero zarr --format 0.4 export Image:1

# Use the Image or Plate 'name' to save e.g. my_image.ome.zarr
$ omero zarr --name_by name export Image:1

Expand All @@ -96,7 +99,7 @@ To export Images or Plates via the OMERO API::
$ omero zarr export Image:1 --tile_width 256 --tile_height 256


NB: If the connection to OMERO is lost and the Image is partially exported,
NB: If the connection to OMERO is lost and the Image or Plate is partially exported,
re-running the command will attempt to complete the export.

To export images via bioformats2raw we use the ```--bf``` flag::
Expand Down
5 changes: 4 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ def get_long_description() -> str:
author="The Open Microscopy Team",
author_email="",
python_requires=">=3",
install_requires=["omero-py>=5.6.0", "ome-zarr>=0.5.0,<0.12.0"],
install_requires=[
"omero-py>=5.6.0",
"ome-zarr>=0.12.0",
],
long_description=long_description,
keywords=["OMERO.CLI", "plugin"],
url="https://github.com/ome/omero-cli-zarr/",
Expand Down
4 changes: 0 additions & 4 deletions src/omero_zarr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from ome_zarr.format import CurrentFormat

from ._version import version as __version__

ngff_version = CurrentFormat().version

__all__ = [
"__version__",
]
18 changes: 15 additions & 3 deletions src/omero_zarr/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
from omero.cli import CLI, BaseControl, Parser, ProxyStringType
from omero.gateway import BlitzGateway, BlitzObjectWrapper
from omero.model import ImageI, PlateI
from zarr.hierarchy import open_group
from zarr.storage import FSStore
from zarr.api.synchronous import open_group
from zarr.storage import LocalStore

from .masks import (
MASK_DTYPE_SIZE,
Expand Down Expand Up @@ -323,6 +323,12 @@ def _configure(self, parser: Parser) -> None:
subcommand.add_argument(
"--output", type=str, default="", help="The output directory"
)
subcommand.add_argument(
"--format",
type=str,
choices=["0.4", "0.5"],
help="OME-Zarr version. Default is '0.5'",
)
for subcommand in (polygons, masks):
subcommand.add_argument(
"--overlaps",
Expand Down Expand Up @@ -399,6 +405,12 @@ def export(self, args: argparse.Namespace) -> None:
if isinstance(args.object, ImageI):
image = self._lookup(self.gateway, "Image", args.object.id)
if args.bf or args.bfpath:
if args.format and args.format != "0.4":
self.ctx.die(
110,
"bioformats2raw does not support OME-Zarr format %s"
% args.format,
)
self._bf_export(image, args)
else:
image_to_zarr(image, args)
Expand Down Expand Up @@ -484,7 +496,7 @@ def _bf_export(self, image: BlitzObjectWrapper, args: argparse.Namespace) -> Non
self.ctx.out(f"Image exported to {image_target.resolve()}")

# Add OMERO metadata
store = FSStore(
store = LocalStore(
str(image_target.resolve()),
auto_mkdir=False,
normalize_keys=False,
Expand Down
35 changes: 15 additions & 20 deletions src/omero_zarr/masks.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,17 @@
from typing import Dict, List, Optional, Set, Tuple

import numpy as np
import omero.clients # noqa
import omero.clients
from ome_zarr.conversions import int_to_rgba_255
from ome_zarr.io import parse_url
from ome_zarr.reader import Multiscales, Node
from ome_zarr.scale import Scaler
from ome_zarr.types import JSONDict
from ome_zarr.writer import write_multiscale_labels
from ome_zarr.writer import get_metadata, write_multiscale_labels
from omero.model import MaskI, PolygonI
from omero.rtypes import unwrap
from skimage.draw import polygon as sk_polygon
from zarr.hierarchy import open_group
from zarr.api.synchronous import open_group

from .util import (
get_zarr_name,
marshal_axes,
marshal_transformations,
open_store,
print_status,
)
from .util import get_zarr_name, marshal_axes, marshal_transformations, print_status

LOGGER = logging.getLogger("omero_zarr.masks")

Expand Down Expand Up @@ -96,6 +88,7 @@ def plate_shapes_to_zarr(
args.overlaps,
args.output,
args.name_by,
args.format,
)

count = 0
Expand Down Expand Up @@ -195,6 +188,7 @@ def image_shapes_to_zarr(
args.overlaps,
args.output,
args.name_by,
args.format,
)

if args.style == "split":
Expand Down Expand Up @@ -231,6 +225,7 @@ def __init__(
overlaps: str = "error",
output: Optional[str] = None,
name_by: str = "id",
ome_zarr_fmt: Optional[str] = None,
) -> None:
self.dtype = dtype
self.path = path
Expand All @@ -241,6 +236,7 @@ def __init__(
self.overlaps = overlaps
self.output = output
self.name_by = name_by
self.format = ome_zarr_fmt
if image:
self.image = image
self.size_t = image.getSizeT()
Expand Down Expand Up @@ -324,14 +320,13 @@ def save(self, masks: List[omero.model.Shape], name: str) -> None:
image_path = source_image
if self.output:
image_path = os.path.join(self.output, source_image)
src = parse_url(image_path)
assert src, f"Source image does not exist at {image_path}"
input_pyramid = Node(src, [])
assert input_pyramid.load(Multiscales), "No multiscales metadata found"
input_pyramid_levels = len(input_pyramid.data)
img_group = open_group(image_path)
img_attrs = get_metadata(img_group)
assert "multiscales" in img_attrs, "No multiscales metadata found"
input_pyramid_levels = len(img_attrs["multiscales"][0]["datasets"])

store = open_store(image_path)
label_group = open_group(store)
# If image is zarr v2, labels will be too
write_group = open_group(image_path, mode="a")

_mask_shape: List[int] = list(self.image_shape)
mask_shape: Tuple[int, ...] = tuple(_mask_shape)
Expand Down Expand Up @@ -385,7 +380,7 @@ def save(self, masks: List[omero.model.Shape], name: str) -> None:

write_multiscale_labels(
label_pyramid,
label_group,
write_group,
name,
axes=axes,
coordinate_transformations=transformations,
Expand Down
Loading
Loading