Skip to content

Commit

Permalink
Finish off labels for v05
Browse files Browse the repository at this point in the history
  • Loading branch information
dstansby committed Jan 23, 2025
1 parent 663a486 commit f6a8925
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 21 deletions.
14 changes: 13 additions & 1 deletion src/ome_zarr_models/_v05/image_label.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
from pydantic import Field
from pydantic_zarr.v2 import ArraySpec, GroupSpec

from ome_zarr_models._v05.base import BaseGroupv05, BaseOMEAttrs
from ome_zarr_models.v04.image_label import ImageLabelAttrs
from ome_zarr_models._v05.image_label_types import Label
from ome_zarr_models._v05.multiscales import Multiscale
from ome_zarr_models.base import BaseAttrs

__all__ = ["ImageLabel", "ImageLabelAttrs"]


class ImageLabelAttrs(BaseAttrs):
"""
Attributes for an image label object.
"""

image_label: Label = Field(..., alias="image-label")
multiscales: list[Multiscale]


class OMEImageLabelAttrs(BaseOMEAttrs):
ome: ImageLabelAttrs

Expand Down
26 changes: 26 additions & 0 deletions src/ome_zarr_models/_v05/image_label_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from typing import Literal

from ome_zarr_models.v04.image_label_types import (
RGBA,
Color,
LabelBase,
Property,
Source,
Uint8,
)

__all__ = [
"RGBA",
"Color",
"Property",
"Source",
"Uint8",
]


class Label(LabelBase):
"""
Metadata for a single image-label.
"""

version: Literal["0.5"] | None = None
10 changes: 2 additions & 8 deletions src/ome_zarr_models/v04/image_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from __future__ import annotations

from typing import TYPE_CHECKING, Literal, Self
from typing import TYPE_CHECKING, Self

import zarr
from pydantic import Field
Expand All @@ -13,9 +13,7 @@
from ome_zarr_models.base import BaseAttrs
from ome_zarr_models.v04.base import BaseGroupv04
from ome_zarr_models.v04.image import Image
from ome_zarr_models.v04.image_label_types import (
Label as _Label,
)
from ome_zarr_models.v04.image_label_types import Label
from ome_zarr_models.v04.multiscales import Multiscale

if TYPE_CHECKING:
Expand All @@ -27,10 +25,6 @@
]


class Label(_Label):
version: Literal["0.5"]


class ImageLabelAttrs(BaseAttrs):
"""
Attributes for an image label object.
Expand Down
25 changes: 16 additions & 9 deletions src/ome_zarr_models/v04/image_label_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from __future__ import annotations

import warnings
from typing import Annotated, Literal
from typing import Annotated, Literal, Self, TypeVar

from pydantic import AfterValidator, Field, model_validator

Expand Down Expand Up @@ -71,24 +71,31 @@ def _parse_colors(colors: tuple[Color] | None) -> tuple[Color] | None:
return colors


class Label(BaseAttrs):
"""
Metadata for a single image-label.
"""

class LabelBase(BaseAttrs):
# TODO: validate
# "All the values under the label-value (of colors) key MUST be unique."
colors: Annotated[tuple[Color, ...] | None, AfterValidator(_parse_colors)] = None
properties: tuple[Property, ...] | None = None
source: Source | None = None
version: Literal["0.4"] | None
version: str | None = None

@model_validator(mode="after")
def _parse_model(self) -> Label:
def _parse_model(self) -> Self:
return _parse_imagelabel(self)


def _parse_imagelabel(model: Label) -> Label:
class Label(LabelBase):
"""
Metadata for a single image-label.
"""

version: Literal["0.4"] | None = None


_T = TypeVar("_T", bound=LabelBase)


def _parse_imagelabel(model: _T) -> _T:
"""
Check that label_values are consistent across properties and colors
"""
Expand Down
57 changes: 56 additions & 1 deletion tests/v05/data/image_label_example.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,61 @@
"source": {
"image": "../../"
}
}
},
"multiscales": [
{
"name": "example",
"axes": [
{ "name": "t", "type": "time", "unit": "millisecond" },
{ "name": "c", "type": "channel" },
{ "name": "z", "type": "space", "unit": "micrometer" },
{ "name": "y", "type": "space", "unit": "micrometer" },
{ "name": "x", "type": "space", "unit": "micrometer" }
],
"datasets": [
{
"path": "0",
"coordinateTransformations": [
{
"type": "scale",
"scale": [1.0, 1.0, 0.5, 0.5, 0.5]
}
]
},
{
"path": "1",
"coordinateTransformations": [
{
"type": "scale",
"scale": [1.0, 1.0, 1.0, 1.0, 1.0]
}
]
},
{
"path": "2",
"coordinateTransformations": [
{
"type": "scale",
"scale": [1.0, 1.0, 2.0, 2.0, 2.0]
}
]
}
],
"coordinateTransformations": [
{
"type": "scale",
"scale": [0.1, 1.0, 1.0, 1.0, 1.0]
}
],
"type": "gaussian",
"metadata": {
"description": "the fields in metadata depend on the downscaling implementation. Here, the parameters passed to the skimage function are given",
"method": "skimage.transform.pyramid_gaussian",
"version": "0.16.1",
"args": "[true]",
"kwargs": { "multichannel": true }
}
}
]
}
}
79 changes: 77 additions & 2 deletions tests/v05/test_image_label.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,83 @@
from ome_zarr_models._v05.image_label import ImageLabel
from ome_zarr_models._v05.axes import Axis
from ome_zarr_models._v05.coordinate_transformations import VectorScale
from ome_zarr_models._v05.image_label import ImageLabel, ImageLabelAttrs
from ome_zarr_models._v05.image_label_types import Color, Label, Source
from ome_zarr_models._v05.multiscales import Dataset, Multiscale
from tests.v05.conftest import json_to_zarr_group


def test_image_label() -> None:
zarr_group = json_to_zarr_group(json_fname="image_label_example.json")
ome_group = ImageLabel.from_zarr(zarr_group)
assert ome_group.ome_attributes == None
assert ome_group.ome_attributes == ImageLabelAttrs(
image_label=Label(
colors=(
Color(label_value=0, rgba=(0, 0, 128, 128)),
Color(label_value=1, rgba=(0, 128, 0, 128)),
),
properties=[
{
"label_value": 0,
"area (pixels)": 1200,
"class": "intercellular space",
},
{
"label_value": 1,
"area (pixels)": 1650,
"class": "cell",
"cell type": "neuron",
},
],
source=Source(image="../../"),
version=None,
),
multiscales=[
Multiscale(
axes=[
Axis(name="t", type="time", unit="millisecond"),
Axis(name="c", type="channel", unit=None),
Axis(name="z", type="space", unit="micrometer"),
Axis(name="y", type="space", unit="micrometer"),
Axis(name="x", type="space", unit="micrometer"),
],
datasets=(
Dataset(
path="0",
coordinateTransformations=(
VectorScale(type="scale", scale=[1.0, 1.0, 0.5, 0.5, 0.5]),
),
),
Dataset(
path="1",
coordinateTransformations=(
VectorScale(type="scale", scale=[1.0, 1.0, 1.0, 1.0, 1.0]),
),
),
Dataset(
path="2",
coordinateTransformations=(
VectorScale(type="scale", scale=[1.0, 1.0, 2.0, 2.0, 2.0]),
),
),
),
version=None,
coordinateTransformations=(
VectorScale(type="scale", scale=[0.1, 1.0, 1.0, 1.0, 1.0]),
),
metadata={
"description": (
"the fields in metadata depend on the downscaling "
"implementation. Here, the parameters passed to the skimage "
"function are given"
),
"method": "skimage.transform.pyramid_gaussian",
"version": "0.16.1",
"args": "[true]",
"kwargs": {"multichannel": True},
},
name="example",
type="gaussian",
)
],
version="0.5",
)

0 comments on commit f6a8925

Please sign in to comment.