Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bioformats2raw metadata support #174

Draft
wants to merge 22 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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 .isort.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[settings]
known_third_party = dask,numcodecs,numpy,pytest,scipy,setuptools,skimage,zarr
known_third_party = dask,entrypoints,numcodecs,numpy,pytest,scipy,setuptools,skimage,zarr
multi_line_output = 3
include_trailing_comma = True
force_grid_wrap = 0
Expand Down
93 changes: 86 additions & 7 deletions ome_zarr/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
from typing import Any, Dict, Iterator, List, Optional, Type, Union, cast, overload

import dask.array as da
import entrypoints
import numpy as np
import zarr
from dask import delayed

from .axes import Axes
Expand Down Expand Up @@ -45,21 +47,44 @@ def __init__(
self.post_nodes: List[Node] = []

# TODO: this should be some form of plugin infra over subclasses
found: List[Spec] = []
if Labels.matches(zarr):
self.specs.append(Labels(self))
found.append(Labels(self))
self.specs.append(found[-1])
if Label.matches(zarr):
self.specs.append(Label(self))
found.append(Label(self))
self.specs.append(found[-1])
if Multiscales.matches(zarr):
self.specs.append(Multiscales(self))
found.append(Multiscales(self))
self.specs.append(found[-1])
if OMERO.matches(zarr):
self.specs.append(OMERO(self))
found.append(OMERO(self))
self.specs.append(found[-1])
if plate_labels:
self.specs.append(PlateLabels(self))
found.append(PlateLabels(self))
self.specs.append(found[-1])
elif Plate.matches(zarr):
self.specs.append(Plate(self))
found.append(Plate(self))
self.specs.append(found[-1])
# self.add(zarr, plate_labels=True)
if Well.matches(zarr):
self.specs.append(Well(self))
found.append(Well(self))
self.specs.append(found[-1])

for key, value in entrypoints.get_group_named("ome_zarr.spec").items():
Copy link
Member

Choose a reason for hiding this comment

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

What does this do? I see no file named "ome_zarr.spec" and I've not used entrypoints before. I don't get much idea from https://github.com/takluyver/entrypoints as to what it does, only that "This package is in maintenance-only mode. New code should use the importlib.metadata module".

Copy link
Member Author

Choose a reason for hiding this comment

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

What does this do?

It's essentially a namespace for the particular entrypoint. It's used at
https://github.com/ome/ome-zarr-metadata/blob/main/setup.cfg#L81

cls = value.load()
if cls.matches(zarr):
found.append(cls(self))
self.specs.append(found[-1])

if not found:
self.specs.append(Implicit(self))

# Load up the hierarchy
if Leaf.matches(zarr):
self.specs.append(Leaf(self))
else:
self.specs.append(Root(self))

@overload
def first(self, spectype: Type["Well"]) -> Optional["Well"]:
Expand Down Expand Up @@ -178,6 +203,60 @@ def lookup(self, key: str, default: Any) -> Any:
return self.zarr.root_attrs.get(key, default)


class Implicit(Spec):
"""
A spec-type which simply iterates over available zgroups.
"""

@staticmethod
def matches(zarr: ZarrLocation) -> bool:
"""Always return true"""
return True

def __init__(self, node: Node) -> None:
super().__init__(node)

for name in zarr.group(self.zarr.store).group_keys():
child_zarr = self.zarr.create(name)
if child_zarr.exists():
node.add(child_zarr)


class Leaf(Spec):
"""
A non-root level of the Zarr hierarchy
"""

@staticmethod
def matches(zarr: ZarrLocation) -> bool:
"""Return if the parent directory is within the zarr fileset"""

parent_zarr = zarr.create("..")
return bool(parent_zarr.exists() and (parent_zarr.zgroup or parent_zarr.zarray))

def __init__(self, node: Node) -> None:
super().__init__(node)
parent_zarr = node.zarr.create("..")
if parent_zarr.exists() and (parent_zarr.zgroup or parent_zarr.zarray):
node.add(parent_zarr)


class Root(Spec):
"""
Root of the Zarr fileset
"""

@staticmethod
def matches(zarr: ZarrLocation) -> bool:
"""Return if the parent directory is not within the zarr fileset"""

parent_zarr = zarr.create("..")
return parent_zarr.exists() and not (parent_zarr.zgroup or parent_zarr.zarray)

def __init__(self, node: Node) -> None:
super().__init__(node)


class Labels(Spec):
"""Relatively small specification for the well-known "labels" group which only
contains the name of subgroups which should be loaded as labeled images."""
Expand Down
1 change: 1 addition & 0 deletions requirements/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
black
cython >= 0.29.16
numpy >= 1.16.0
entrypoints
pre-commit
tox
wheel
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def read(fname):
install_requires += (["requests"],)
install_requires += (["scikit-image"],)
install_requires += (["toolz"],)
install_requires += (["entrypoints"],)


setup(
Expand Down