-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from bioio-devs/bioio-nd2
feature/nd2-reader
- Loading branch information
Showing
17 changed files
with
574 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,3 +29,4 @@ repos: | |
rev: v1.4.1 | ||
hooks: | ||
- id: mypy | ||
additional_dependencies: [types-PyYAML>=6.0.12.9] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,7 @@ | |
__author__ = "bioio-devs" | ||
__email__ = "[email protected]" | ||
|
||
from .reader_metadata import Reader | ||
from .reader import Reader | ||
from .reader_metadata import ReaderMetadata | ||
|
||
__all__ = ["Reader", "ReaderMetadata"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,109 +1,94 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
from typing import Any, Optional, Tuple | ||
|
||
from bioio_base.dimensions import Dimensions | ||
from bioio_base.reader import Reader as BaseReader | ||
from typing import Any, Dict, Tuple | ||
|
||
import nd2 | ||
import xarray as xr | ||
from bioio_base import constants, exceptions, io, reader, types | ||
from fsspec.implementations.local import LocalFileSystem | ||
from fsspec.spec import AbstractFileSystem | ||
|
||
############################################################################### | ||
|
||
|
||
class Reader(BaseReader): | ||
""" | ||
The main class of each reader plugin. This class is subclass | ||
of the abstract class reader (BaseReader) in bioio-base. | ||
class Reader(reader.Reader): | ||
"""Read NIS-Elements files using the Nikon nd2 SDK. | ||
This reader requires `nd2` to be installed in the environment. | ||
Parameters | ||
---------- | ||
image: Any | ||
Some type of object to read and follow the Reader specification. | ||
image : Path or str | ||
path to file | ||
fs_kwargs: Dict[str, Any] | ||
Any specific keyword arguments to pass down to the fsspec created filesystem. | ||
Default: {} | ||
Notes | ||
----- | ||
It is up to the implementer of the Reader to decide which types they would like to | ||
accept (certain readers may not support buffers for example). | ||
Raises | ||
------ | ||
exceptions.UnsupportedFileFormatError | ||
If the file is not supported by ND2. | ||
""" | ||
_xarray_dask_data: Optional["xr.DataArray"] = None | ||
_xarray_data: Optional["xr.DataArray"] = None | ||
_mosaic_xarray_dask_data: Optional["xr.DataArray"] = None | ||
_mosaic_xarray_data: Optional["xr.DataArray"] = None | ||
_dims: Optional[Dimensions] = None | ||
_metadata: Optional[Any] = None | ||
_scenes: Optional[Tuple[str, ...]] = None | ||
_current_scene_index: int = 0 | ||
# Do not provide default value because | ||
# they may not need to be used by your reader (i.e. input param is an array) | ||
_fs: "AbstractFileSystem" | ||
_path: str | ||
|
||
# Required Methods | ||
|
||
def __init__(image: Any, **kwargs: Any): | ||
""" | ||
Store / cache certain parameters required for later reading. | ||
Try not to read the image into memory here. | ||
""" | ||
raise NotImplementedError() | ||
|
||
@staticmethod | ||
def _is_supported_image(fs: "AbstractFileSystem", path: str, **kwargs: Any) -> bool: | ||
""" | ||
Perform a check to determine if the object(s) or path(s) provided as | ||
parameters are supported by this reader. | ||
""" | ||
raise NotImplementedError() | ||
def _is_supported_image(fs: AbstractFileSystem, path: str, **kwargs: Any) -> bool: | ||
return nd2.is_supported_file(path, fs.open) | ||
|
||
def __init__(self, image: types.PathLike, fs_kwargs: Dict[str, Any] = {}): | ||
self._fs, self._path = io.pathlike_to_fs( | ||
image, | ||
enforce_exists=True, | ||
fs_kwargs=fs_kwargs, | ||
) | ||
# Catch non-local file system | ||
if not isinstance(self._fs, LocalFileSystem): | ||
raise ValueError( | ||
f"Cannot read ND2 from non-local file system. " | ||
f"Received URI: {self._path}, which points to {type(self._fs)}." | ||
) | ||
|
||
if not self._is_supported_image(self._fs, self._path): | ||
raise exceptions.UnsupportedFileFormatError( | ||
self.__class__.__name__, self._path | ||
) | ||
|
||
@property | ||
def scenes(self) -> Tuple[str, ...]: | ||
""" | ||
Return the list of available scenes for the file using the | ||
cached parameters stored to the object in the __init__. | ||
""" | ||
raise NotImplementedError() | ||
|
||
def _read_delayed(self) -> "xr.DataArray": | ||
""" | ||
Return an xarray DataArray filled with a delayed dask array, coordinate planes, | ||
and any metadata stored in the attrs. | ||
Metadata should be labelled with one of the bioio-base constants. | ||
""" | ||
raise NotImplementedError() | ||
|
||
def _read_immediate(self) -> "xr.DataArray": | ||
""" | ||
Return an xarray DataArray filled with an in-memory numpy ndarray, | ||
coordinate planes, and any metadata stored in the attrs. | ||
Metadata should be labelled with one of the bioio-base constants. | ||
""" | ||
raise NotImplementedError() | ||
|
||
# Optional Methods | ||
|
||
def _get_stitched_dask_mosaic(self) -> "xr.DataArray": | ||
""" | ||
If your file returns an `M` dimension for "Mosiac Tile", | ||
this function should stitch and return the stitched data as | ||
an xarray DataArray both operating against the original delayed array | ||
and returning a delayed array. | ||
""" | ||
return super()._get_stitched_dask_mosaic() | ||
with nd2.ND2File(self._path) as rdr: | ||
return tuple(rdr._position_names()) | ||
|
||
def _read_delayed(self) -> xr.DataArray: | ||
return self._xarr_reformat(delayed=True) | ||
|
||
def _read_immediate(self) -> xr.DataArray: | ||
return self._xarr_reformat(delayed=False) | ||
|
||
def _xarr_reformat(self, delayed: bool) -> xr.DataArray: | ||
with nd2.ND2File(self._path) as rdr: | ||
xarr = rdr.to_xarray( | ||
delayed=delayed, squeeze=False, position=self.current_scene_index | ||
) | ||
xarr.attrs[constants.METADATA_UNPROCESSED] = xarr.attrs.pop("metadata") | ||
if self.current_scene_index is not None: | ||
xarr.attrs[constants.METADATA_UNPROCESSED][ | ||
"frame" | ||
] = rdr.frame_metadata(self.current_scene_index) | ||
return xarr.isel({nd2.AXIS.POSITION: 0}, missing_dims="ignore") | ||
|
||
def _get_stitched_mosaic(self) -> "xr.DataArray": | ||
@property | ||
def physical_pixel_sizes(self) -> types.PhysicalPixelSizes: | ||
""" | ||
If your file returns an `M` dimension for "Mosiac Tile", | ||
this function should stitch and return the stitched data as | ||
an xarray DataArray both operating against the original in-memory array | ||
and returning a in-memory array. | ||
Returns | ||
------- | ||
sizes: PhysicalPixelSizes | ||
Using available metadata, the floats representing physical pixel sizes for | ||
dimensions Z, Y, and X. | ||
Notes | ||
----- | ||
We currently do not handle unit attachment to these values. Please see the file | ||
metadata for unit information. | ||
""" | ||
return super()._get_stitched_mosaic() | ||
with nd2.ND2File(self._path) as rdr: | ||
return types.PhysicalPixelSizes(*rdr.voxel_size()[::-1]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# -*- coding: utf-8 -*- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
import pathlib | ||
|
||
LOCAL_RESOURCES_DIR = pathlib.Path(__file__).parent / "resources" |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.