Skip to content

Commit c1a603e

Browse files
committed
Refactor drop t dimension task to ngio 0.2.2
1 parent 0f5db0d commit c1a603e

File tree

2 files changed

+72
-65
lines changed

2 files changed

+72
-65
lines changed

src/fractal_helper_tasks/drop_t_dimension.py

Lines changed: 34 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,17 @@
88
"""Task to remove singleton T dimension from an OME-Zarr."""
99

1010
import logging
11+
import os
12+
import shutil
1113
from typing import Any
1214

1315
import dask.array as da
14-
import zarr
15-
from fractal_tasks_core.ngff import load_NgffImageMeta
16-
from fractal_tasks_core.pyramids import build_pyramid
16+
import ngio
1717
from pydantic import validate_call
1818

1919
logger = logging.getLogger(__name__)
2020

2121

22-
def get_attrs_without_t(zarr_url: str):
23-
"""Generate zattrs without the t dimension.
24-
25-
Args:
26-
zarr_url: Path to the zarr image
27-
"""
28-
image_group = zarr.open_group(zarr_url)
29-
zattrs = image_group.attrs.asdict()
30-
# print(zattrs)
31-
for multiscale in zattrs["multiscales"]:
32-
# Update axes
33-
multiscale["axes"] = multiscale["axes"][1:]
34-
# Update coordinate Transforms
35-
for dataset in multiscale["datasets"]:
36-
for transform in dataset["coordinateTransformations"]:
37-
if transform["type"] == "scale":
38-
transform["scale"] = transform["scale"][1:]
39-
return zattrs
40-
41-
4222
@validate_call
4323
def drop_t_dimension(
4424
*,
@@ -58,60 +38,49 @@ def drop_t_dimension(
5838
"""
5939
# Normalize zarr_url
6040
zarr_url_old = zarr_url.rstrip("/")
61-
if overwrite_input:
62-
zarr_url_new = zarr_url_old
63-
else:
64-
zarr_url_new = f"{zarr_url_old}_{suffix}"
41+
zarr_url_new = f"{zarr_url_old}_{suffix}"
6542

6643
logger.info(f"{zarr_url_old=}")
6744
logger.info(f"{zarr_url_new=}")
6845

69-
# Read some parameters from metadata
70-
ngff_image = load_NgffImageMeta(zarr_url_old)
71-
72-
# Check that T axis is the first axis:
73-
if not ngff_image.multiscale.axes[0].name == "t":
74-
logger.warning(
75-
f"The Zarr image {zarr_url_old} did not contain a T axis as its "
76-
f"first axis. The axes were: {ngff_image.multiscale.axes} \n"
77-
"The Drop T axis task is skipped"
46+
old_ome_zarr = ngio.open_ome_zarr_container(zarr_url_old)
47+
old_ome_zarr_img = old_ome_zarr.get_image()
48+
if not old_ome_zarr_img.has_axis("t"):
49+
raise ValueError(
50+
f"The Zarr image {zarr_url_old} does not contain a T axis. "
51+
"Thus, the drop T dimension task can't be applied to it."
7852
)
79-
return {}
80-
81-
# Load 0-th level
82-
data_tczyx = da.from_zarr(zarr_url_old + "/0")
83-
# TODO: Check that T dimension is actually a singleton.
84-
new_data = data_tczyx[0, ...]
53+
# TODO: Check if T dimension not singleton
54+
image = old_ome_zarr_img.get_array(mode="dask")
55+
t_index = old_ome_zarr_img.meta.axes_mapper.get_index("t")
56+
new_img = da.squeeze(image, axis=t_index)
57+
pixel_size = old_ome_zarr_img.pixel_size
58+
new_pixel_size = ngio.PixelSize(x=pixel_size.x, y=pixel_size.y, z=pixel_size.z)
59+
axes_names = old_ome_zarr_img.meta.axes_mapper.on_disk_axes_names
60+
del axes_names[t_index]
61+
chunk_sizes = old_ome_zarr_img.chunks
62+
new_chunk_sizes = chunk_sizes[:t_index] + chunk_sizes[t_index + 1 :]
63+
new_ome_zarr_container = old_ome_zarr.derive_image(
64+
store=zarr_url_new,
65+
shape=new_img.shape,
66+
chunks=new_chunk_sizes,
67+
dtype=old_ome_zarr_img.dtype,
68+
pixel_size=new_pixel_size,
69+
axes_names=axes_names,
70+
)
71+
new_image_container = new_ome_zarr_container.get_image()
72+
new_image_container.set_array(new_img)
73+
new_image_container.consolidate()
8574

8675
if overwrite_input:
8776
image_list_update = dict(zarr_url=zarr_url_old, types=dict(has_t=False))
77+
os.rename(zarr_url_old, f"{zarr_url_old}_tmp")
78+
os.rename(zarr_url_new, zarr_url_old)
79+
shutil.rmtree(f"{zarr_url}_tmp")
8880
else:
89-
# Generate attrs without the T dimension
90-
new_attrs = get_attrs_without_t(zarr_url_old)
91-
new_image_group = zarr.group(zarr_url_new)
92-
new_image_group.attrs.put(new_attrs)
9381
image_list_update = dict(
9482
zarr_url=zarr_url_new, origin=zarr_url_old, types=dict(has_t=False)
9583
)
96-
# TODO: Check if image contains labels & raise error (or even copy them)
97-
# FIXME: Check if image contains ROI tables & copy them
98-
99-
# Write to disk (triggering execution)
100-
logger.debug(f"Writing Zarr without T dimension to {zarr_url_new}")
101-
new_data.to_zarr(
102-
f"{zarr_url_new}/0",
103-
overwrite=True,
104-
dimension_separator="/",
105-
write_empty_chunks=False,
106-
)
107-
logger.debug(f"Finished writing Zarr without T dimension to {zarr_url_new}")
108-
build_pyramid(
109-
zarrurl=zarr_url_new,
110-
overwrite=True,
111-
num_levels=ngff_image.num_levels,
112-
coarsening_xy=ngff_image.coarsening_xy,
113-
chunksize=new_data.chunksize,
114-
)
11584

11685
return {"image_list_updates": [image_list_update]}
11786

tests/test_drop_t_dimension.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""Test drop t dimension task."""
2+
3+
from pathlib import Path
4+
5+
import ngio
6+
import numpy as np
7+
8+
from fractal_helper_tasks.drop_t_dimension import (
9+
drop_t_dimension,
10+
)
11+
12+
13+
def test_drop_t_dimension(
14+
tmp_path: Path,
15+
):
16+
zarr_url = str(tmp_path / "my_zarr.zarr")
17+
18+
ngio.create_ome_zarr_from_array(
19+
store=zarr_url,
20+
array=np.zeros((1, 1, 1, 100, 100)),
21+
xy_pixelsize=0.5,
22+
z_spacing=1.0,
23+
axes_names="tczyx",
24+
overwrite=True,
25+
)
26+
27+
drop_t_dimension(
28+
zarr_url=zarr_url,
29+
overwrite_input=False,
30+
)
31+
new_zarr_url = f"{zarr_url}_no_T"
32+
new_ome_zarr_container = ngio.open_ome_zarr_container(new_zarr_url)
33+
assert new_ome_zarr_container.image_meta.axes_mapper.on_disk_axes_names == [
34+
"c",
35+
"z",
36+
"y",
37+
"x",
38+
]

0 commit comments

Comments
 (0)