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

Universal API implementations for Micro-Manager OME-TIFF and NDTiff #185

Merged
merged 79 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
89f609b
wip: draft mmstack ome-tiff fov
ziw-liu Jun 29, 2023
ce80f9c
MM FOV base class
ziw-liu Jul 27, 2023
5e7c8bc
tests
ziw-liu Jul 27, 2023
e0f54c6
bump tifffile
ziw-liu Jul 27, 2023
33d69df
comment
ziw-liu Sep 1, 2023
bff9c84
fix indent after rebase
ziw-liu Sep 1, 2023
7df30be
use get default
ziw-liu Sep 2, 2023
8053fde
test pixel indexing
ziw-liu Sep 2, 2023
9d95517
set MM metadata
ziw-liu Sep 2, 2023
31c5897
style
ziw-liu Sep 2, 2023
41772c3
update dependencies
ziw-liu Feb 2, 2024
82747d8
Merge branch 'unified-api' into ometiff-uapi
ziw-liu Feb 2, 2024
049d945
add xarray
ziw-liu Feb 2, 2024
e086b4b
move old readers to the `_deprecated` namespace
ziw-liu Feb 6, 2024
723ab9d
uapi for ndtiff
ziw-liu Feb 6, 2024
6efbb34
refactor test setup to parametrize by dataset
ziw-liu Feb 6, 2024
d698609
convert mmstack
ziw-liu Feb 6, 2024
a4fbd76
fix and test chunking
ziw-liu Feb 6, 2024
3cace84
fix metadata conversion and test ndtiff
ziw-liu Feb 7, 2024
d57008b
update cli
ziw-liu Feb 8, 2024
5ae6333
fix scaling
ziw-liu Feb 8, 2024
aacd964
test 1.4 and incomplete ome-tiffs
ziw-liu Feb 8, 2024
8d4265d
move reader tests
ziw-liu Feb 8, 2024
6dc5711
deprecate reader tests
ziw-liu Feb 8, 2024
e82fbe0
update deprecated tests
ziw-liu Feb 8, 2024
37c2fbc
update ngff tests
ziw-liu Feb 8, 2024
6a8d38c
isort
ziw-liu Feb 8, 2024
2ec73ab
update black target to 3.10
ziw-liu Feb 8, 2024
a96135f
lint
ziw-liu Feb 8, 2024
b10f333
fix download paths
ziw-liu Feb 8, 2024
07f24a5
update docs references and theme
ziw-liu Feb 8, 2024
f636310
untrack autogenerated file
ziw-liu Feb 8, 2024
0e17863
ignore execution time file
ziw-liu Feb 8, 2024
7497f04
add github icon
ziw-liu Feb 8, 2024
02103a4
update docstring
ziw-liu Feb 8, 2024
16ad699
update docstring
ziw-liu Feb 8, 2024
ef04a64
show channel names and chunk size in info
ziw-liu Feb 9, 2024
fc4a0cc
print plate chunk size if verbose
ziw-liu Feb 9, 2024
7e960dc
fallback for pixel size
ziw-liu Feb 9, 2024
0d29dae
remove log level setting
ziw-liu Feb 9, 2024
8799d84
do not filter logs and warnings in reader
ziw-liu Feb 9, 2024
fab9d93
avoid root logger
ziw-liu Feb 9, 2024
f63ccd2
isort
ziw-liu Feb 9, 2024
b4ac082
set default logging level to INFO
ziw-liu Feb 9, 2024
9c261c3
format docstring
ziw-liu Feb 9, 2024
fb32fb4
improve conversion messages
ziw-liu Feb 9, 2024
83538cf
black
ziw-liu Feb 9, 2024
baf3e93
fix ome-tiff channel name indexing
ziw-liu Feb 9, 2024
840b819
fix ndtiff channel name indexing
ziw-liu Feb 9, 2024
978f893
update converter test
ziw-liu Feb 9, 2024
6336c1d
remove use of os.path in `reader`
ieivanov Feb 12, 2024
6ec5f0a
expand _check_ndtiff checks
ieivanov Feb 13, 2024
e71ee62
fix iteration
ziw-liu Feb 15, 2024
18c725f
fix python 3.10
ziw-liu Feb 15, 2024
f6a5bd7
bump zarr version to include resizing fix
ziw-liu Feb 15, 2024
1535833
fix cli default
ziw-liu Feb 15, 2024
f93f0f9
set log level with an environment variable
ziw-liu Feb 15, 2024
232ef1c
fix unset
ziw-liu Feb 15, 2024
d9e4380
catch non-existent page
ziw-liu Feb 16, 2024
2698317
implement fallback for incomplete channel names
ziw-liu Feb 16, 2024
7001352
add debug logs
ziw-liu Feb 16, 2024
ff6a038
handle virtual frames
ziw-liu Feb 16, 2024
44c3080
try reading pages from TiffFile directly
ziw-liu Feb 16, 2024
dab5857
filter error logs about ImageJ metadata being broken
ziw-liu Feb 16, 2024
fa8fbc3
fix regex
ziw-liu Feb 17, 2024
692e2a7
remove use of os.path in `convert.py`
ieivanov Feb 21, 2024
a2e9b53
better channel indexing in `_get_summary_metadata`
ieivanov Feb 21, 2024
e59e403
style
ieivanov Feb 21, 2024
406012b
safer NoneType check
ziw-liu Feb 22, 2024
a6e13a8
private default axis names for NDTiff
ziw-liu Feb 22, 2024
0da400c
update documentation to reflect new entry point
ziw-liu Feb 22, 2024
ebed5ee
add repr to MM FOV and dataset types
ziw-liu Feb 22, 2024
d7c2b70
rename mm_meta and expose summary metadata
ziw-liu Feb 22, 2024
a916373
add MicroManagerFOVMapping.root
ziw-liu Feb 28, 2024
29131f9
add MicroManagerFOVMapping.zyx_scale
ziw-liu Feb 28, 2024
b1c1e1d
add warning log for failed position grid
ziw-liu Feb 28, 2024
e8fe720
fix grid layout
ziw-liu Feb 28, 2024
ee109d7
suppress hypothesis flakiness
ziw-liu Feb 28, 2024
efc406c
different health check suppression
ziw-liu Feb 28, 2024
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
4 changes: 2 additions & 2 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ jobs:
pip install black
- name: Check code styling with Black
run: |
black --diff -S -t py39 iohub
black --check -S -t py39 iohub
black --diff -S -t py310 iohub
black --check -S -t py310 iohub

lint:
name: Lint Check
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ instance/
# Sphinx documentation
docs/_build/
docs/source/auto_examples/
docs/source/sg_execution_times.rst

# PyBuilder
target/
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ and the [example scripts](https://github.com/czbiohub-sf/iohub/tree/main/example
Read a directory containing a TIFF dataset:

```py
from iohub import read_micromanager
from iohub import read_images

reader = read_micromanager("/path/to/data/")
reader = read_images("/path/to/data/")
print(reader.shape)
```

Expand Down
1 change: 1 addition & 0 deletions docs/source/api/mm_converter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ Convert TIFF to OME-Zarr

.. autoclass:: TIFFConverter
:members:
:special-members: __call__
8 changes: 6 additions & 2 deletions docs/source/api/mm_ometiff_reader.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
Read MMStack OME-TIFF
=====================

.. currentmodule:: iohub.multipagetiff
.. currentmodule:: iohub.mmstack

.. autoclass:: MicromanagerOmeTiffReader
.. autoclass:: MMStack
:members:
:inherited-members:

.. autoclass:: MMOmeTiffFOV
:members:
:inherited-members:
6 changes: 3 additions & 3 deletions docs/source/api/mm_reader.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Read Micro-Manager datasets
===========================
Read multi-FOV datasets
=======================

.. currentmodule:: iohub

.. autofunction:: read_micromanager
.. autofunction:: read_images
2 changes: 1 addition & 1 deletion docs/source/api/mm_sequence_reader.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Read MM TIFF sequence
=====================

.. currentmodule:: iohub.singlepagetiff
.. currentmodule:: iohub._deprecated.singlepagetiff

.. autoclass:: MicromanagerSequenceReader
:members:
Expand Down
6 changes: 5 additions & 1 deletion docs/source/api/ndtiff.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ Read NDTiff

.. currentmodule:: iohub.ndtiff

.. autoclass:: NDTiffReader
.. autoclass:: NDTiffDataset
:members:
:inherited-members:

.. autoclass:: NDTiffFOV
:members:
:inherited-members:
13 changes: 0 additions & 13 deletions docs/source/api/ngff.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ OME-NGFF (OME-Zarr)
Convenience
-----------

`open_ome_zarr`
^^^^^^^^^^^^^^^
.. autofunction:: open_ome_zarr


Expand All @@ -16,25 +14,14 @@ NGFF Nodes

.. currentmodule:: iohub.ngff


`NGFFNode`
^^^^^^^^^^

.. autoclass:: NGFFNode
:members:

`Position`
^^^^^^^^^^
.. autoclass:: Position
:members:


`TiledPosition`
^^^^^^^^^^^^^^^
.. autoclass:: TiledPosition
:members:

`Plate`
^^^^^^^
.. autoclass:: Plate
:members:
2 changes: 1 addition & 1 deletion docs/source/api/upti.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Read PTI TIFF
=============

.. currentmodule:: iohub.upti
.. currentmodule:: iohub._deprecated.upti

.. autoclass:: UPTIReader
:members:
Expand Down
10 changes: 9 additions & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,15 @@
"json_url": json_url,
"version_match": version_match,
},
"navbar_end": ["theme-switcher", "version-switcher", "navbar-icon-links"],
"icon_links": [
{
"name": "GitHub",
"url": "https://github.com/czbiohub-sf/iohub",
"icon": "fa-brands fa-square-github",
"type": "fontawesome",
}
],
"navbar_end": ["theme-switcher", "navbar-icon-links", "version-switcher"],
}

# Add any paths that contain custom themes here, relative to this directory.
Expand Down
20 changes: 15 additions & 5 deletions iohub/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
iohub
=====

"""iohub
N-dimensional bioimaging data I/O with OME metadata in Python
"""

import logging
import os

from iohub.ngff import open_ome_zarr
from iohub.reader import read_micromanager
from iohub.reader import read_images

__all__ = ["open_ome_zarr", "read_images"]


_level = os.environ.get("IOHUB_LOG_LEVEL", logging.INFO)
if str(_level).isdigit():
_level = int(_level)

__all__ = ["open_ome_zarr", "read_micromanager"]
logging.basicConfig()
logging.getLogger(__name__).setLevel(_level)
1 change: 1 addition & 0 deletions iohub/_deprecated/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Deprecated modules"""
10 changes: 7 additions & 3 deletions iohub/reader_base.py → iohub/_deprecated/reader_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,21 @@ def shape(self):
return self.frames, self.channels, self.slices, self.height, self.width

@property
def mm_meta(self):
def micromanager_metadata(self) -> dict | None:
return self._mm_meta

@mm_meta.setter
def mm_meta(self, value):
@micromanager_metadata.setter
def micromanager_metadata(self, value):
if not isinstance(value, dict):
raise TypeError(
f"Type of `mm_meta` should be `dict`, got `{type(value)}`."
)
self._mm_meta = value

@property
def micromanager_summary(self) -> dict | None:
return self._mm_meta.get("Summary", None)

@property
def stage_positions(self):
return self._stage_positions
Expand Down
42 changes: 21 additions & 21 deletions iohub/singlepagetiff.py → iohub/_deprecated/singlepagetiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import tifffile as tiff
import zarr

from iohub.reader_base import ReaderBase
from iohub._deprecated.reader_base import ReaderBase


class MicromanagerSequenceReader(ReaderBase):
Expand Down Expand Up @@ -91,9 +91,9 @@ def _set_mm_meta(self, one_pos):
# pull one metadata sample and extract experiment dimensions
metadata_path = os.path.join(one_pos, "metadata.txt")
with open(metadata_path, "r") as f:
self.mm_meta = json.load(f)
self._mm_meta = json.load(f)

mm_version = self.mm_meta["Summary"]["MicroManagerVersion"]
mm_version = self._mm_meta["Summary"]["MicroManagerVersion"]
if mm_version == "1.4.22":
self._mm1_meta_parser()
elif "beta" in mm_version:
Expand Down Expand Up @@ -402,12 +402,12 @@ def _mm1_meta_parser(self):
-------

"""
self.z_step_size = self.mm_meta["Summary"]["z-step_um"]
self.width = self.mm_meta["Summary"]["Width"]
self.height = self.mm_meta["Summary"]["Height"]
self.frames = self.mm_meta["Summary"]["Frames"]
self.slices = self.mm_meta["Summary"]["Slices"]
self.channels = self.mm_meta["Summary"]["Channels"]
self.z_step_size = self._mm_meta["Summary"]["z-step_um"]
self.width = self._mm_meta["Summary"]["Width"]
self.height = self._mm_meta["Summary"]["Height"]
self.frames = self._mm_meta["Summary"]["Frames"]
self.slices = self._mm_meta["Summary"]["Slices"]
self.channels = self._mm_meta["Summary"]["Channels"]

def _mm2beta_meta_parser(self):
"""
Expand All @@ -418,14 +418,14 @@ def _mm2beta_meta_parser(self):
-------

"""
self.z_step_size = self.mm_meta["Summary"]["z-step_um"]
self.z_step_size = self._mm_meta["Summary"]["z-step_um"]
self.width = int(
self.mm_meta["Summary"]["UserData"]["Width"]["PropVal"]
self._mm_meta["Summary"]["UserData"]["Width"]["PropVal"]
)
self.height = int(
self.mm_meta["Summary"]["UserData"]["Height"]["PropVal"]
self._mm_meta["Summary"]["UserData"]["Height"]["PropVal"]
)
self.time_stamp = self.mm_meta["Summary"]["StartTime"]
self.time_stamp = self._mm_meta["Summary"]["StartTime"]

def _mm2gamma_meta_parser(self):
"""
Expand All @@ -436,18 +436,18 @@ def _mm2gamma_meta_parser(self):
-------

"""
keys_list = list(self.mm_meta.keys())
keys_list = list(self._mm_meta.keys())
if "FrameKey-0-0-0" in keys_list[1]:
roi_string = self.mm_meta[keys_list[1]]["ROI"]
roi_string = self._mm_meta[keys_list[1]]["ROI"]
self.width = int(roi_string.split("-")[2])
self.height = int(roi_string.split("-")[3])
elif "Metadata-" in keys_list[2]:
self.width = self.mm_meta[keys_list[2]]["Width"]
self.height = self.mm_meta[keys_list[2]]["Height"]
self.width = self._mm_meta[keys_list[2]]["Width"]
self.height = self._mm_meta[keys_list[2]]["Height"]
else:
raise ValueError("Metadata file incompatible with metadata reader")

self.z_step_size = self.mm_meta["Summary"]["z-step_um"]
self.frames = self.mm_meta["Summary"]["Frames"]
self.slices = self.mm_meta["Summary"]["Slices"]
self.channels = self.mm_meta["Summary"]["Channels"]
self.z_step_size = self._mm_meta["Summary"]["z-step_um"]
self.frames = self._mm_meta["Summary"]["Frames"]
self.slices = self._mm_meta["Summary"]["Slices"]
self.channels = self._mm_meta["Summary"]["Channels"]
3 changes: 1 addition & 2 deletions iohub/upti.py → iohub/_deprecated/upti.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
import tifffile as tiff
import zarr

from iohub.reader_base import ReaderBase
from iohub._deprecated.reader_base import ReaderBase


class UPTIReader(ReaderBase):

"""
Reader for UPTI raw data.
Accepts both new live UPTI and older UPTI format.
Expand Down
31 changes: 16 additions & 15 deletions iohub/zarrfile.py → iohub/_deprecated/zarrfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
import numpy as np
import zarr

from iohub.reader_base import ReaderBase
from iohub._deprecated.reader_base import ReaderBase

_logger = logging.getLogger(__name__)

class ZarrReader(ReaderBase):

class ZarrReader(ReaderBase):
"""
.. deprecated:: 0.0.1
`ZarrReader` will be removed in future iohub releases,
Expand All @@ -30,7 +31,7 @@ def __init__(
):
super().__init__()

logging.warning(
_logger.warning(
DeprecationWarning(
"`iohub.zarrfile.ZarrReader` is deprecated "
"and will be removed in the future. "
Expand Down Expand Up @@ -94,7 +95,7 @@ def __init__(
try:
self._set_mm_meta()
except TypeError:
self.mm_meta = dict()
self.micromanager_metadata = {}

self._generate_hcs_meta()

Expand Down Expand Up @@ -187,37 +188,37 @@ def _set_mm_meta(self):
-------

"""
self.mm_meta = self.root.attrs.get("Summary")
mm_version = self.mm_meta["MicroManagerVersion"]
self._mm_meta = self.root.attrs.get("Summary")
mm_version = self._mm_meta["MicroManagerVersion"]

if mm_version != "pycromanager":
if "beta" in mm_version:
if self.mm_meta["Positions"] > 1:
if self._mm_meta["Positions"] > 1:
self.stage_positions = []

for p in range(len(self.mm_meta["StagePositions"])):
for p in range(len(self._mm_meta["StagePositions"])):
pos = self._simplify_stage_position_beta(
self.mm_meta["StagePositions"][p]
self._mm_meta["StagePositions"][p]
)
self.stage_positions.append(pos)

# elif mm_version == '1.4.22':
# for ch in self.mm_meta['ChNames']:
# for ch in self._mm_meta['ChNames']:
# self.channel_names.append(ch)
else:
if self.mm_meta["Positions"] > 1:
if self._mm_meta["Positions"] > 1:
self.stage_positions = []

for p in range(self.mm_meta["Positions"]):
for p in range(self._mm_meta["Positions"]):
pos = self._simplify_stage_position(
self.mm_meta["StagePositions"][p]
self._mm_meta["StagePositions"][p]
)
self.stage_positions.append(pos)

# for ch in self.mm_meta['ChNames']:
# for ch in self._mm_meta['ChNames']:
# self.channel_names.append(ch)

self.z_step_size = self.mm_meta["z-step_um"]
self.z_step_size = self._mm_meta["z-step_um"]

def _get_channel_names(self):
well = self.hcs_meta["plate"]["wells"][0]["path"]
Expand Down
Loading
Loading