Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Name option #147

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
30 changes: 18 additions & 12 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@ from OMERO as zarr files, according to the spec at
https://github.com/ome/omero-ms-zarr/blob/master/spec.md
as well as Masks associated with Images.

Images are 5D arrays of shape `(t, c, z, y, x)`.
Images are nD arrays of shape, up to `(t, c, z, y, x)`.
Plates are a hierarchy of `plate/row/column/field(image)`.
Masks are 2D bitmasks which can exist on muliplte planes of an Image.
In `ome-zarr` sets of Masks are collected together into "labels".

It supports export using 2 alternative methods:

- By default the OMERO API is used to load planes as numpy arrays
and the zarr file is created from this data. NB: currently, large
tiled images are not supported by this method.
and the zarr file is created from this data.

- Alternatively, if you can read directly from the OMERO binary
repository and have installed https://github.com/glencoesoftware/bioformats2raw
Expand All @@ -37,16 +36,19 @@ Images and Plates
To export Images or Plates via the OMERO API::


# Image will be saved in current directory as 1.zarr
# Image will be saved in current directory as 1.ome.zarr
$ omero zarr export Image:1

# Plate will be saved in current directory as 2.zarr
# Plate will be saved in current directory as 2.ome.zarr
$ omero zarr export Plate:2

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

# Specify an output directory
$ omero zarr --output /home/user/zarr_files export Image:1

# By default, a tile size of 1024 is used. Specify values with
# By default, a tile (chunk) size of 1024 is used. Specify values with
$ omero zarr export Image:1 --tile_width 256 --tile_height 256


Expand All @@ -66,24 +68,28 @@ Masks and Polygons

To export Masks or Polygons for an Image or Plate, use the `masks` or `polygons` command::

# Saved under 1.zarr/labels/0 - 1.zarr/ must already exist
# Saved under 1.ome.zarr/labels/0
# 1.ome.zarr/ should already exist...
$ omero zarr masks Image:1

# Labels saved under each image. e.g 2.zarr/A/1/0/labels/0
# Plate should already be exported
# ...or specify path with --source-image
$ omero zarr masks Image:1 --source-image my_image.ome.zarr

# Labels saved under each image. e.g 2.ome.zarr/A/1/0/labels/0
# 2.ome.zarr should already be exported or specify path with --source-image
$ omero zarr masks Plate:2

# Saved under zarr_files/1.zarr/labels/0
# Saved under zarr_files/1.ome.zarr/labels/0
$ omero zarr --output /home/user/zarr_files masks Image:1

# Specify the label-name. (default is '0')
# e.g. Export to 1.zarr/labels/A
# e.g. Export to 1.ome.zarr/labels/A
$ omero zarr masks Image:1 --label-name=A

# Allow overlapping masks or polygons (overlap will be maximum value of the dtype)
$ omero zarr polygons Image:1 --overlaps=dtype_max

The default behaviour is to export all masks or polygons on the Image to a single 5D
The default behaviour is to export all masks or polygons on the Image to a single nD
"labeled" zarr array, with a different value for each Shape.
An exception will be thrown if any of the masks overlap, unless the `--overlaps`
option is used as above.
Expand Down
9 changes: 9 additions & 0 deletions src/omero_zarr/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,15 @@ def _configure(self, parser: Parser) -> None:
default=None,
help="Maximum number of workers (only for use with bioformats2raw)",
)
export.add_argument(
"--name_by",
default="id",
choices=["id", "name"],
help=(
"How to name the Image or Plate zarr. Default 'id' is [ID].ome.zarr. "
"'name' is [NAME].ome.zarr"
),
)
export.add_argument(
"object",
type=ProxyStringType("Image"),
Expand Down
4 changes: 2 additions & 2 deletions src/omero_zarr/masks.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,9 @@ def save(self, masks: List[omero.model.Shape], name: str) -> None:
ignored_dimensions.add(d)

if self.plate:
filename = f"{self.plate.id}.zarr"
filename = f"{self.plate.id}.ome.zarr"
else:
filename = f"{self.image.id}.zarr"
filename = f"{self.image.id}.ome.zarr"

# Verify that we are linking this mask to a real ome-zarr
source_image = self.source_image
Expand Down
28 changes: 23 additions & 5 deletions src/omero_zarr/raw_pixels.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,29 @@
from .util import marshal_axes, marshal_transformations, open_store, print_status


def image_to_zarr(image: omero.gateway.ImageWrapper, args: argparse.Namespace) -> None:
def sanitize_name(zarr_name: str) -> str:
# Avoids re.compile errors when writing Zarr data with the named root
# https://github.com/ome/omero-cli-zarr/pull/147#issuecomment-1669075660
return zarr_name.replace("[", "(").replace("]", ")")


def get_zarr_name(
obj: omero.gateway.BlitzObjectWrapper, args: argparse.Namespace
) -> str:
target_dir = args.output
name_by = args.name_by
if name_by == "name":
obj_name = sanitize_name(obj.name)
name = os.path.join(target_dir, "%s.ome.zarr" % obj_name)
else:
name = os.path.join(target_dir, "%s.ome.zarr" % obj.id)
return name


def image_to_zarr(image: omero.gateway.ImageWrapper, args: argparse.Namespace) -> None:
tile_width = args.tile_width
tile_height = args.tile_height

name = os.path.join(target_dir, "%s.zarr" % image.id)
name = get_zarr_name(image, args)
print(f"Exporting to {name} ({VERSION})")
store = open_store(name)
root = open_group(store)
Expand Down Expand Up @@ -243,9 +260,8 @@ def plate_to_zarr(plate: omero.gateway._PlateWrapper, args: argparse.Namespace)
n_cols = gs["columns"]
n_fields = plate.getNumberOfFields()
total = n_rows * n_cols * (n_fields[1] - n_fields[0] + 1)
name = get_zarr_name(plate, args)

target_dir = args.output
name = os.path.join(target_dir, "%s.zarr" % plate.id)
store = open_store(name)
print(f"Exporting to {name} ({VERSION})")
root = open_group(store)
Expand Down Expand Up @@ -296,6 +312,8 @@ def plate_to_zarr(plate: omero.gateway._PlateWrapper, args: argparse.Namespace)
print_status(int(t0), int(time.time()), count, total)

# Update plate_metadata after each Well
if len(well_paths) == 0:
continue
write_plate_metadata(
root,
row_names,
Expand Down
2 changes: 1 addition & 1 deletion src/omero_zarr/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def print_status(t0: int, t: int, count: int, total: int) -> None:
"""
percent_done = float(count) * 100 / total
dt = t - t0
if dt > 0:
if dt > 0 and count > 0:
rate = float(count) / (t - t0)
eta_f = float(total - count) / rate
eta = time.strftime("%H:%M:%S", time.gmtime(eta_f))
Expand Down
Loading