Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies = [
"multiscale_spatial_image==0.11.2",
"networkx",
"numpy",
"ome_zarr>=0.7.0",
"ome_zarr>=0.8.4",
"pandas",
"pooch",
"pyarrow",
Expand Down
26 changes: 0 additions & 26 deletions src/spatialdata/_io/format.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
from typing import Any, Optional, Union

from anndata import AnnData
from multiscale_spatial_image.multiscale_spatial_image import MultiscaleSpatialImage
from ome_zarr.format import CurrentFormat
from pandas.api.types import CategoricalDtype
from shapely import GeometryType
from spatial_image import SpatialImage

from spatialdata.models import PointsModel, ShapesModel
from spatialdata.models._utils import get_channels

CoordinateTransform_t = list[dict[str, Any]]

Expand Down Expand Up @@ -72,29 +69,6 @@ def validate_coordinate_transformations(

assert np.all([j0 == j1 for j0, j1 in zip(json0, json1)])

def channels_to_metadata(
self,
data: Union[SpatialImage, MultiscaleSpatialImage],
channels_metadata: Optional[dict[str, Any]] = None,
) -> dict[str, Union[int, str]]:
"""Convert channels to omero metadata."""
channels = get_channels(data)
metadata: dict[str, Any] = {"channels": []}
if channels_metadata is not None:
if set(channels_metadata.keys()).symmetric_difference(set(channels)):
for c in channels:
metadata["channels"].append({"label": c} | channels_metadata[c])
else:
raise ValueError("Channels metadata must contain all channels.")
else:
for c in channels:
metadata["channels"].append({"label": c})
return metadata

def channels_from_metadata(self, omero_metadata: dict[str, Any]) -> list[Any]:
"""Convert channels from omero metadata."""
return [d["label"] for d in omero_metadata["channels"]]


class ShapesFormatV01(SpatialDataFormatV01):
"""Formatter for shapes."""
Expand Down
19 changes: 13 additions & 6 deletions src/spatialdata/_io/io_raster.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
overwrite_coordinate_transformations_raster,
)
from spatialdata._io.format import CurrentRasterFormat
from spatialdata.models._utils import get_channels
from spatialdata.transformations._utils import (
_get_transformations,
_get_transformations_xarray,
Expand Down Expand Up @@ -58,7 +59,8 @@ def _read_multiscale(
node = nodes[0]
datasets = node.load(Multiscales).datasets
multiscales = node.load(Multiscales).zarr.root_attrs["multiscales"]
channels_metadata = node.load(Multiscales).zarr.root_attrs.get("channels_metadata", None)
omero_metadata = node.load(Multiscales).zarr.root_attrs.get("omero", None)
legacy_channels_metadata = node.load(Multiscales).zarr.root_attrs.get("channels_metadata", None) # legacy v0.1
assert len(multiscales) == 1
# checking for multiscales[0]["coordinateTransformations"] would make fail
# something that doesn't have coordinateTransformations in top level
Expand All @@ -70,8 +72,11 @@ def _read_multiscale(
# name = os.path.basename(node.metadata["name"])
# if image, read channels metadata
channels: Optional[list[Any]] = None
if raster_type == "image" and channels_metadata is not None:
channels = fmt.channels_from_metadata(channels_metadata)
if raster_type == "image":
if legacy_channels_metadata is not None:
channels = [d["label"] for d in legacy_channels_metadata["channels"]]
if omero_metadata is not None:
channels = [d["label"] for d in omero_metadata["channels"]]
axes = [i["name"] for i in node.metadata["axes"]]
if len(datasets) > 1:
multiscale_image = {}
Expand Down Expand Up @@ -105,7 +110,6 @@ def _write_raster(
fmt: Format = CurrentRasterFormat(),
storage_options: Optional[Union[JSONDict, list[JSONDict]]] = None,
label_metadata: Optional[JSONDict] = None,
channels_metadata: Optional[JSONDict] = None,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed cause it's unused

**metadata: Union[str, JSONDict, list[JSONDict]],
) -> None:
assert raster_type in ["image", "labels"]
Expand All @@ -130,9 +134,12 @@ def _get_group_for_writing_transformations() -> zarr.Group:
return group.require_group(name)
return group["labels"][name]

# convert channel names to channel metadata
# convert channel names to channel metadata in omero
if raster_type == "image":
group_data.attrs["channels_metadata"] = fmt.channels_to_metadata(raster_data, channels_metadata)
metadata["metadata"] = {"omero": {"channels": []}}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so "technically" here I should be checking that metadata doesn't already have this key, and also with respect to the omero dict, yet the only time that the _write_raster is exposed, via _write_image, it is not allowed for the metadata to be passed. What would you suggest? I don't really see a real use case, so I would suggest to keep it as is and use them effectively as kwargs as it is now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I also would keep this as it is.

channels = get_channels(raster_data)
for c in channels:
metadata["metadata"]["omero"]["channels"].append({"label": c}) # type: ignore[union-attr, index, call-overload]

if isinstance(raster_data, SpatialImage):
data = raster_data.data
Expand Down