Skip to content

Commit

Permalink
Merge pull request #12 from fractal-analytics-platform/expand_testing
Browse files Browse the repository at this point in the history
Expand testing
  • Loading branch information
lorenzocerrone authored Nov 7, 2024
2 parents 40f2440 + 6be8f07 commit 46ab28a
Show file tree
Hide file tree
Showing 28 changed files with 793 additions and 434 deletions.
2 changes: 1 addition & 1 deletion docs/notebooks/basic_usage.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "dev2",
"display_name": "ngio",
"language": "python",
"name": "python3"
},
Expand Down
4 changes: 2 additions & 2 deletions docs/notebooks/image.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -301,15 +301,15 @@
"\n",
"print(f\"New list of feature table: {ngff_image.table.list(table_type='feature_table')}\")\n",
"feat_table.set_table(feat_df)\n",
"feat_table.write()\n",
"feat_table.consolidate()\n",
"\n",
"feat_table.table"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "dev2",
"display_name": "ngio",
"language": "python",
"name": "python3"
},
Expand Down
4 changes: 2 additions & 2 deletions docs/notebooks/processing.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
" roi_list.append(roi)\n",
"\n",
"mip_roi_table.set_rois(roi_list, overwrite=True)\n",
"mip_roi_table.write()\n",
"mip_roi_table.consolidate()\n",
"\n",
"mip_roi_table.table"
]
Expand Down Expand Up @@ -303,7 +303,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.7"
"version": "3.10.15"
}
},
"nbformat": 4,
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,12 @@ core = ["zarr<3", "dask[distributed]", "dask-image"]

test = ["zarr<3", "pytest", "pytest-cov"]

# add anything else you like to have in your dev environment here
dev2 = [
"zarr<3",
"dask[distributed]",
"dask-image",
"napari",
"pyqt5",
"scikit-image",
"matplotlib",
"ipython",
Expand All @@ -66,7 +67,7 @@ dev2 = [
"pre-commit",
"rich", # https://github.com/Textualize/rich
"ruff",
]
] # add anything else you like to have in your dev environment here

dev3 = [
"zarr==v3.0.0-alpha.4",
Expand Down
51 changes: 17 additions & 34 deletions src/ngio/core/dimensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
but it is based on the actual metadata of the image data.
"""

from collections import OrderedDict


class Dimensions:
"""Dimension metadata."""
Expand Down Expand Up @@ -37,7 +39,7 @@ def __init__(
self._axes_order = axes_order

self._shape = [self._on_disk_shape[i] for i in axes_order]
self._shape_dict = dict(zip(axes_names, self._shape, strict=True))
self._shape_dict = OrderedDict(zip(axes_names, self._shape, strict=True))

def __str__(self) -> str:
"""Return the string representation of the object."""
Expand All @@ -64,33 +66,6 @@ def ad_dict(self) -> dict[str, int]:
"""Return the shape as a dictionary."""
return self._shape_dict

@property
def t(self) -> int | None:
"""Return the time dimension."""
return self._shape_dict.get("t", None)

@property
def c(self) -> int | None:
"""Return the channel dimension."""
return self._shape_dict.get("c", None)

@property
def z(self) -> int | None:
"""Return the z dimension."""
return self._shape_dict.get("z", None)

@property
def y(self) -> int:
"""Return the y dimension."""
assert "y" in self._shape_dict
return self._shape_dict["y"]

@property
def x(self) -> int:
"""Return the x dimension."""
assert "x" in self._shape_dict
return self._shape_dict["x"]

def get(self, ax_name: str, default: int = 1) -> int:
"""Return the dimension of the given axis name."""
return self._shape_dict.get(ax_name, default)
Expand All @@ -103,14 +78,16 @@ def on_disk_ndim(self) -> int:
@property
def is_time_series(self) -> bool:
"""Return whether the data is a time series."""
if (self.t is None) or (self.t == 1):
t = self._shape_dict.get("t", 1)
if t == 1:
return False
return True

@property
def is_2d(self) -> bool:
"""Return whether the data is 2D."""
if (self.z is not None) and (self.z > 1):
z = self._shape_dict.get("z", 1)
if z != 1:
return False
return True

Expand All @@ -122,9 +99,7 @@ def is_2d_time_series(self) -> bool:
@property
def is_3d(self) -> bool:
"""Return whether the data is 3D."""
if (self.z is None) or (self.z == 1):
return False
return True
return not self.is_2d

@property
def is_3d_time_series(self) -> bool:
Expand All @@ -134,6 +109,14 @@ def is_3d_time_series(self) -> bool:
@property
def is_multi_channels(self) -> bool:
"""Return whether the data has multiple channels."""
if (self.c is None) or (self.c == 1):
c = self._shape_dict.get("c", 1)
if c == 1:
return False
return True

def find_axis(self, ax_name: str) -> int | None:
"""Return the index of the axis name."""
for i, ax in enumerate(self._axes_names):
if ax == ax_name:
return i
return None
8 changes: 6 additions & 2 deletions src/ngio/core/image_like_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from pathlib import Path
from typing import Any, Literal
from warnings import warn

import dask.array as da
import numpy as np
Expand All @@ -21,6 +20,7 @@
get_ngff_image_meta_handler,
)
from ngio.pipes import DataTransformPipe, NaiveSlicer, RoiSlicer, on_disk_zoom
from ngio.utils import ngio_logger
from ngio.utils._common_types import ArrayLike


Expand Down Expand Up @@ -62,7 +62,7 @@ def __init__(
_label_group (LabelGroup): The group containing the label data (internal use).
"""
if not strict:
warn("Strict mode is not fully supported yet.", UserWarning, stacklevel=2)
ngio_logger.warning("Strict mode is not fully supported yet.")

self._mode = mode
if not isinstance(store, zarr.Group):
Expand Down Expand Up @@ -227,6 +227,10 @@ def on_disk_shape(self) -> tuple[int, ...]:
"""Return the shape of the image."""
return self.dimensions.on_disk_shape

def find_axis(self, axis_name: str) -> int | None:
"""Return the index of the given axis name."""
return self.dimensions.find_axis(axis_name)

# Methods to get the image data in the canonical order
def init_lock(self, lock_id: str | None = None) -> None:
"""Set the lock for the Dask array."""
Expand Down
73 changes: 47 additions & 26 deletions src/ngio/core/label_handler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""A module to handle OME-NGFF images stored in Zarr format."""

import builtins
from typing import Any, Literal

import zarr
Expand Down Expand Up @@ -285,13 +286,18 @@ def get_label(
def derive(
self,
name: str,
reference: ImageLike | None = None,
levels: int | builtins.list[str] = 5,
overwrite: bool = False,
**kwargs: dict,
) -> Label:
"""Derive a new label from an existing label.
Args:
name (str): The name of the new label.
reference (ImageLike | None): The reference image to use for the new label.
levels (int | list[str]): The number of levels to create or
a list of paths names.
overwrite (bool): If True, the label will be overwritten if it exists.
Default is False.
**kwargs: Additional keyword arguments to pass to the new label.
Expand All @@ -311,44 +317,46 @@ def derive(
# create the new label
new_label_group = self._label_group.create_group(name, overwrite=overwrite)

if self._image_ref is None:
label_0 = self.get_label(list_of_labels[0])
metadata = label_0.metadata
on_disk_shape = label_0.on_disk_shape
chunks = label_0.on_disk_array.chunks
dataset = label_0.dataset
else:
label_0 = self._image_ref
metadata = label_0.metadata
channel_index = metadata.index_mapping.get("c", None)
if channel_index is not None:
on_disk_shape = (
label_0.on_disk_shape[:channel_index]
+ label_0.on_disk_shape[channel_index + 1 :]
)
chunks = (
label_0.on_disk_array.chunks[:channel_index]
+ label_0.on_disk_array.chunks[channel_index + 1 :]
)
else:
on_disk_shape = label_0.on_disk_shape
chunks = label_0.on_disk_array.chunks
ref_0 = self._image_ref if reference is None else reference
assert isinstance(ref_0, ImageLike)

if isinstance(levels, int):
paths = [str(i) for i in range(levels)]
elif isinstance(levels, list):
if not all(isinstance(level, str) for level in levels):
raise ValueError(f"All levels must be strings. Got: {levels}")
paths = levels

on_disk_ch_index = ref_0.find_axis("c")
metadata = ref_0.metadata

if on_disk_ch_index is None:
on_disk_shape = ref_0.on_disk_shape
chunks = ref_0.on_disk_array.chunks
else:
metadata = metadata.remove_axis("c")
dataset = metadata.get_highest_resolution_dataset()
on_disk_shape = (
ref_0.on_disk_shape[:on_disk_ch_index]
+ ref_0.on_disk_shape[on_disk_ch_index + 1 :]
)
chunks = (
ref_0.on_disk_array.chunks[:on_disk_ch_index]
+ ref_0.on_disk_array.chunks[on_disk_ch_index + 1 :]
)
dataset = metadata.get_dataset(path=paths[0])

default_kwargs = {
"store": new_label_group,
"shape": on_disk_shape,
"chunks": chunks,
"dtype": label_0.on_disk_array.dtype,
"dtype": ref_0.on_disk_array.dtype,
"on_disk_axis": dataset.on_disk_axes_names,
"pixel_sizes": dataset.pixel_size,
"xy_scaling_factor": metadata.xy_scaling_factor,
"z_scaling_factor": metadata.z_scaling_factor,
"time_spacing": dataset.time_spacing,
"time_units": dataset.time_axis_unit,
"num_levels": metadata.num_levels,
"levels": paths,
"name": name,
"overwrite": overwrite,
"version": metadata.version,
Expand All @@ -357,7 +365,20 @@ def derive(
default_kwargs.update(kwargs)

create_empty_ome_zarr_label(
**default_kwargs,
store=new_label_group,
on_disk_shape=on_disk_shape,
chunks=chunks,
dtype=ref_0.on_disk_array.dtype,
on_disk_axis=dataset.on_disk_axes_names,
pixel_sizes=dataset.pixel_size,
xy_scaling_factor=metadata.xy_scaling_factor,
z_scaling_factor=metadata.z_scaling_factor,
time_spacing=dataset.time_spacing,
time_units=dataset.time_axis_unit,
levels=paths,
name=name,
overwrite=overwrite,
version=metadata.version,
)

if name not in self.list():
Expand Down
4 changes: 2 additions & 2 deletions src/ngio/core/ngff_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def derive_new_image(

default_kwargs = {
"store": store,
"shape": image_0.on_disk_shape,
"on_disk_shape": image_0.on_disk_shape,
"chunks": image_0.on_disk_array.chunks,
"dtype": image_0.on_disk_array.dtype,
"on_disk_axis": image_0.dataset.on_disk_axes_names,
Expand All @@ -187,7 +187,7 @@ def derive_new_image(
"z_scaling_factor": self.image_meta.z_scaling_factor,
"time_spacing": image_0.dataset.time_spacing,
"time_units": image_0.dataset.time_axis_unit,
"num_levels": self.num_levels,
"levels": self.num_levels,
"name": name,
"channel_labels": image_0.channel_labels,
"channel_wavelengths": [ch.wavelength_id for ch in channels],
Expand Down
Loading

0 comments on commit 46ab28a

Please sign in to comment.