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
5 changes: 2 additions & 3 deletions src/spatialdata/_core/spatialdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -1698,15 +1698,14 @@ def write_metadata(
check_valid_name(element_name)
if element_name not in self:
raise ValueError(f"Element with name {element_name} not found in SpatialData object.")
if write_attrs:
self.write_attrs(sdata_format=sdata_format)

self.write_transformations(element_name)
self.write_channel_names(element_name)
# TODO: write .uns['spatialdata_attrs'] metadata for AnnData.
# TODO: write .attrs['spatialdata_attrs'] metadata for DaskDataFrame.

if write_attrs:
self.write_attrs(sdata_format=sdata_format)

if self.has_consolidated_metadata():
consolidate_metadata = True
if consolidate_metadata:
Expand Down
5 changes: 5 additions & 0 deletions src/spatialdata/_io/io_points.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ def _read_points(
return points


class PointsReader:
def __call__(self, store: str | Path | MutableMapping[str, object] | zarr.Group) -> DaskDataFrame:
return _read_points(store)


def write_points(
points: DaskDataFrame,
group: zarr.Group,
Expand Down
62 changes: 35 additions & 27 deletions src/spatialdata/_io/io_raster.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,33 +35,6 @@
)


def _get_multiscale_nodes(image_nodes: list[Node], nodes: list[Node]) -> list[Node]:
"""Get nodes with Multiscales spec from a list of nodes.

The nodes with the Multiscales spec are the nodes used for reading in image and label data. We only have to check
the multiscales now, while before we also had to check the label spec. In the new ome-zarr-py though labels can have
the Label spec, these do not contain the multiscales anymore used to read the data. They can contain label specific
metadata though.

Parameters
----------
image_nodes
List of nodes returned from the ome-zarr-py Reader.
nodes
List to append the nodes with the multiscales spec to.

Returns
-------
List of nodes with the multiscales spec.
"""
if len(image_nodes):
for node in image_nodes:
# Labels are now also Multiscales in newer version of ome-zarr-py
if np.any([isinstance(spec, Multiscales) for spec in node.specs]):
nodes.append(node)
return nodes


def _read_multiscale(
store: str | Path, raster_type: Literal["image", "labels"], reader_format: Format
) -> DataArray | DataTree:
Expand Down Expand Up @@ -134,6 +107,7 @@ def _read_multiscale(
msi = DataTree.from_dict(multiscale_image)
_set_transformations(msi, transformations)
return compute_coordinates(msi)

data = node.load(Multiscales).array(resolution=datasets[0])
si = DataArray(
data,
Expand All @@ -145,6 +119,40 @@ def _read_multiscale(
return compute_coordinates(si)


def _get_multiscale_nodes(image_nodes: list[Node], nodes: list[Node]) -> list[Node]:
"""Get nodes with Multiscales spec from a list of nodes.

The nodes with the Multiscales spec are the nodes used for reading in image and label data. We only have to check
the multiscales now, while before we also had to check the label spec. In the new ome-zarr-py though labels can have
the Label spec, these do not contain the multiscales anymore used to read the data. They can contain label specific
metadata though.

Parameters
----------
image_nodes
List of nodes returned from the ome-zarr-py Reader.
nodes
List to append the nodes with the multiscales spec to.

Returns
-------
List of nodes with the multiscales spec.
"""
if len(image_nodes):
for node in image_nodes:
# Labels are now also Multiscales in newer version of ome-zarr-py
if np.any([isinstance(spec, Multiscales) for spec in node.specs]):
nodes.append(node)
return nodes


class MultiscaleReader:
def __call__(
self, path: str | Path, raster_type: Literal["image", "labels"], reader_format: Format
) -> DataArray | DataTree:
return _read_multiscale(path, raster_type, reader_format)


def _write_raster(
raster_type: Literal["image", "labels"],
raster_data: DataArray | DataTree,
Expand Down
7 changes: 6 additions & 1 deletion src/spatialdata/_io/io_shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@


def _read_shapes(
store: str | Path | MutableMapping | zarr.Group, # type: ignore[type-arg]
store: str | Path | MutableMapping[str, object] | zarr.Group,
) -> GeoDataFrame:
"""Read shapes from a zarr store."""
assert isinstance(store, str | Path)
Expand Down Expand Up @@ -67,6 +67,11 @@ def _read_shapes(
return geo_df


class ShapesReader:
def __call__(self, store: str | Path | MutableMapping[str, object] | zarr.Group) -> GeoDataFrame:
return _read_shapes(store)


def write_shapes(
shapes: GeoDataFrame,
group: zarr.Group,
Expand Down
14 changes: 12 additions & 2 deletions src/spatialdata/_io/io_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def _read_table(
group: zarr.Group,
tables: dict[str, AnnData],
on_bad_files: Literal[BadFileHandleMethod.ERROR, BadFileHandleMethod.WARN] = BadFileHandleMethod.ERROR,
) -> dict[str, AnnData]:
) -> None:
"""
Read in tables in the tables Zarr.group of a SpatialData Zarr store.

Expand Down Expand Up @@ -85,7 +85,17 @@ def _read_table(
count += 1

logger.debug(f"Found {count} elements in {group}")
return tables


class TablesReader:
def __call__(
self,
path: str,
group: zarr.Group,
container: dict[str, AnnData],
on_bad_files: Literal[BadFileHandleMethod.ERROR, BadFileHandleMethod.WARN],
) -> None:
return _read_table(path, group, container, on_bad_files)


def write_table(
Expand Down
Loading
Loading