Skip to content

Commit f48eccd

Browse files
committed
refactor: Adjusted cli based on feedback
Signed-off-by: Sricharan Reddy Varra <sricharan.varra@biohub.org>
1 parent 53b10ac commit f48eccd

7 files changed

Lines changed: 440 additions & 196 deletions

File tree

src/iohub/cli/cli.py

Lines changed: 33 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from iohub import __version__, open_ome_zarr
66
from iohub.cli.parsing import input_position_dirpaths
77
from iohub.convert import TIFFConverter
8-
from iohub.core.ozx import pack_ozx, summarize_ozx
8+
from iohub.core.ozx import is_ozx_path, pack_ozx, unpack_ozx
99
from iohub.reader import print_info
1010
from iohub.rename_wells import rename_wells
1111

@@ -55,49 +55,65 @@ def info(files, verbose):
5555
"--input",
5656
"-i",
5757
required=True,
58-
type=_DATASET_PATH,
59-
help="Input Micro-Manager TIFF dataset directory",
58+
type=_OME_ZARR_PATH,
59+
help="Input dataset: Micro-Manager TIFF dir, OME-Zarr dir, or RFC-9 .ozx archive.",
6060
)
6161
@click.option(
6262
"--output",
6363
"-o",
6464
required=True,
65-
type=click.Path(exists=False, resolve_path=True),
66-
help="Output zarr store (/**/converted.zarr)",
65+
type=click.Path(exists=False, resolve_path=True, path_type=pathlib.Path),
66+
help="Output path. Suffix selects the operation: .zarr (Zarr dir) or .ozx (zipped).",
6767
)
6868
@click.option(
6969
"--grid-layout",
7070
"-g",
7171
required=False,
7272
is_flag=True,
73-
help="Arrange FOVs in a row/column grid layout for tiled acquisition",
73+
help="(TIFF → Zarr only) Arrange FOVs in a row/column grid layout.",
7474
)
7575
@click.option(
7676
"--chunks",
7777
"-c",
7878
required=False,
7979
default="XYZ",
80-
help="Zarr chunk size given as 'XY', 'XYZ', or a tuple of chunk "
81-
"dimensions. If 'XYZ', chunk size will be limited to 500 MB.",
80+
help="(TIFF → Zarr only) Zarr chunk size: 'XY', 'XYZ', or a tuple. 'XYZ' caps at 500 MB.",
8281
)
8382
@click.option(
8483
"--ome-zarr-version",
8584
"-v",
8685
required=False,
87-
default="0.4",
86+
default=None,
8887
type=click.Choice(["0.4", "0.5"]),
89-
help="OME-NGFF version for the output Zarr store. '0.4' uses Zarr v2 format; '0.5' uses Zarr v3 format.",
88+
help="OME-NGFF version. TIFF default: 0.4. Pack: sniffed from source if omitted.",
9089
)
9190
def convert(input, output, grid_layout, chunks, ome_zarr_version):
92-
"""Converts Micro-Manager TIFF datasets to OME-Zarr"""
93-
converter = TIFFConverter(
94-
input_dir=input,
95-
output_dir=output,
91+
"""Convert datasets between supported formats.
92+
93+
Routes by suffix: a TIFF directory plus a ``.zarr`` output runs the
94+
Micro-Manager TIFF → OME-Zarr converter; a ``.zarr`` source plus a
95+
``.ozx`` output packs an RFC-9 zip archive; a ``.ozx`` source plus
96+
a ``.zarr`` output unpacks back to a directory store.
97+
"""
98+
src = pathlib.Path(input)
99+
dst = pathlib.Path(output)
100+
101+
if is_ozx_path(dst):
102+
out = pack_ozx(src, dst, version=ome_zarr_version)
103+
click.echo(f"packed: {out}")
104+
return
105+
if is_ozx_path(src):
106+
out = unpack_ozx(src, dst)
107+
click.echo(f"unpacked: {out}")
108+
return
109+
# Default: TIFF → OME-Zarr (TIFFConverter sniffs the input format).
110+
TIFFConverter(
111+
input_dir=src,
112+
output_dir=dst,
96113
grid_layout=grid_layout,
97114
chunks=chunks,
98-
version=ome_zarr_version,
99-
)
100-
converter()
115+
version=ome_zarr_version or "0.4",
116+
)()
101117

102118

103119
@cli.command()
@@ -198,91 +214,3 @@ def rename_wells_command(zarrfile, csvfile):
198214
```
199215
"""
200216
rename_wells(zarrfile, csvfile)
201-
202-
203-
def _echo_ozx_summary(verb: str, path: pathlib.Path) -> None:
204-
"""Print the one-liner ``ozx pack`` shows on success."""
205-
s = summarize_ozx(path)
206-
click.echo(f"{verb}: {path} (ome version={s.version}, jsonFirst={s.json_first})")
207-
208-
209-
@cli.group(name="ozx")
210-
@click.help_option("-h", "--help")
211-
def ozx_group():
212-
"""RFC-9 zipped OME-Zarr (``.ozx``) operations.
213-
214-
A ``.ozx`` is a single-file OME-Zarr archive (ZIP_STORED + ZIP64)
215-
designed for distribution - S3, AWS Open Data, HPC↔compute-cluster
216-
transfers - not as a live mutable store. One file to upload,
217-
download, and serve.
218-
219-
Use ``ozx pack`` to bundle a directory store for export and
220-
``ozx info`` to inspect an archive's RFC-9 properties. ``iohub
221-
info`` works on ``.ozx`` paths directly for the usual FOV summary.
222-
"""
223-
224-
225-
@ozx_group.command(name="pack")
226-
@click.help_option("-h", "--help")
227-
@click.option(
228-
"-i",
229-
"--input",
230-
"src",
231-
required=True,
232-
type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True, path_type=pathlib.Path),
233-
help="Input OME-Zarr directory store.",
234-
)
235-
@click.option(
236-
"-o",
237-
"--output",
238-
"dst",
239-
required=True,
240-
type=click.Path(exists=False, resolve_path=True, path_type=pathlib.Path),
241-
help="Output .ozx path (must not exist).",
242-
)
243-
@click.option(
244-
"--version",
245-
"ome_version",
246-
default=None,
247-
help="OME-NGFF version to record. Sniffed from source if omitted.",
248-
)
249-
def ozx_pack(src, dst, ome_version):
250-
"""Pack an OME-Zarr directory into an RFC-9 ``.ozx`` archive.
251-
252-
Writes a ZIP_STORED + ZIP64 archive in one pass with entries in BFS
253-
order - root ``zarr.json`` first, other ``zarr.json`` next, chunks
254-
last - and ``jsonFirst:true`` in the archive comment. HTTP-range
255-
readers can then fetch all metadata in one contiguous Range request
256-
on cold opens, the win that matters for S3 and AWS Open Data.
257-
"""
258-
out = pack_ozx(src, dst, version=ome_version)
259-
_echo_ozx_summary("packed", out)
260-
261-
262-
@ozx_group.command(name="info")
263-
@click.help_option("-h", "--help")
264-
@click.argument(
265-
"path",
266-
type=click.Path(exists=True, dir_okay=False, resolve_path=True, path_type=pathlib.Path),
267-
)
268-
def ozx_info(path):
269-
"""Print RFC-9 archive metadata: version, ``jsonFirst``, entry count, size.
270-
271-
Use it to sanity-check an archive before publishing (``jsonFirst``
272-
should be ``True`` after ``iohub ozx pack``) or to inspect archives
273-
received from collaborators or downloaded from public datasets.
274-
"""
275-
import zipfile
276-
277-
# One zip open for the namelist, one for the comment.
278-
with zipfile.ZipFile(path) as zf:
279-
names = zf.namelist()
280-
summary = summarize_ozx(path)
281-
n_entries = len(names)
282-
n_meta = sum(1 for n in names if n.rsplit("/", 1)[-1] == "zarr.json")
283-
n_dupes = n_entries - len(set(names))
284-
click.echo(f"path: {path}")
285-
click.echo(f"size: {path.stat().st_size:,} bytes")
286-
click.echo(f"entries: {n_entries:,} ({n_meta} zarr.json, {n_dupes} duplicate names)")
287-
click.echo(f"ome version: {summary.version}")
288-
click.echo(f"jsonFirst: {summary.json_first}")

src/iohub/core/__init__.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,9 @@
2121
OzxSummary,
2222
is_ozx_path,
2323
pack_ozx,
24-
read_ozx_comment,
25-
read_ozx_json_first,
2624
read_ozx_version,
2725
summarize_ozx,
28-
write_ozx_comment,
26+
unpack_ozx,
2927
)
3028
from iohub.core.protocol import (
3129
ArrayBackend,
@@ -87,13 +85,11 @@
8785
"normalize_path",
8886
"pack_ozx",
8987
"pad_shape",
90-
"read_ozx_comment",
91-
"read_ozx_json_first",
9288
"read_ozx_version",
9389
"register_implementation",
9490
"set_default_implementation",
9591
"summarize_ozx",
96-
"write_ozx_comment",
92+
"unpack_ozx",
9793
# Compat
9894
"zarr_format_for_version",
9995
]

0 commit comments

Comments
 (0)