1. Reading Microscopy Data in Python#

Choosing the right Python library for microscopy data analysis is crucial for optimizing workflow efficiency and gaining valuable insights. This guide offers a comprehensive overview of available libraries, helping you make informed decisions based on your priorities, whether it’s speed, versatility, or integration with other tools. Empower your microscopy data analysis by exploring the options tailored to meet your specific requirements.

For opening microscopy data files in Python, you have several options, each with its own advantages. Here’s a breakdown of the options and some considerations:

  1. scikit-image (skimage.io.imread and skimage.io.imread_collection):

  • Used for reading standard image formats.

  • Provides simple and efficient functions for reading individual images or collections of images.

  1. tifffile (tifffile.TiffFile and tifffile.TiffSequence):

  • Specialized for working with TIFF files, including multi-dimensional arrays.

  • TiffSequence is useful for handling sequences of TIFF files.

  1. bioformats (bioformats.ImageReader):

  • Supports a variety of microscopy formats, especially those using the OME data model.

  • Handles multi-dimensional data and can read metadata.

Regarding ImageJ hyperstack organization (TZCYXS):

T: Time
Z: Z-stack (slices)
C: Channels
Y: Height
X: Width
S: Series (used for distinguishing multiple acquisitions)

For Holoviews:

  • It’s used for interactive visualization but doesn’t directly handle file reading. Check for memmap support and disk reading capabilities.

Regarding Bioformats standard:

  • Bioformats follows the OME (Open Microscopy Environment) standard, where each channel and time point is stored in a separate TIFF file. An OME.tif typically contains a single plane or a Z-stack.

About tiles and 5D in Bioformats:

  • In the context of Bioformats, 5D typically refers to a dataset with dimensions T-Z-C-Y-X, where T is time, Z is the z-stack, C is the channel, and Y and X are spatial dimensions. Tiles may refer to sub-images or chunks of the larger image, which can be useful for efficiently working with large datasets.

The 6D, 7D, and 8D configurations in Bioformats likely involve additional dimensions or parameters specific to certain types of microscopy data.

To understand the exact definition of 5D in Bioformats, you should refer to the Bioformats documentation or OME data model specifications for detailed information on how these dimensions are interpreted and utilized in the context of microscopy data.

1.1. Data Path Assignment and Imports#

To begin our analysis, we first need to import the necessary libraries and assign the path to our data files. This step ensures that we have access to the tools and resources required for the subsequent tasks.

Let’s get started by executing the following code:

[1]:
%load_ext autoreload
%autoreload 2

from pathlib import Path

import skimage.io
import tifffile

import nima_io.read as ir

tdata = Path("../../tests/data/")
lif = tdata / "2015Aug28_TransHXB2_50min+DMSO.lif"
img_tile = tdata / "t4_1.tif"  # C=3 T=4 S=15
img_void_tile = tdata / "tile6_1.tif"  # C=4 T=3 S=14 scattered
# imgsingle = tdata / "exp2_2.tif"  # C=2 T=81
# mcts = tdata / "multi-channel-time-series.ome.tif"  # C=3 T=7
# bigtiff = tdata / "LC26GFP_1.tf8"  # bigtiff

slif = str(lif)
simg_tile = str(img_tile)
simg_void_tile = str(img_void_tile)
# simgsingle = str(imgsingle)
# smcts = str(mcts)
# sbigtiff = str(bigtiff)

1.2. Skimage and Tifffile#

scikit-image serves as a versatile option for general image reading, encompassing various formats, including TIFF. Meanwhile tifffile stands out for its capabilities in managing sequences, OME metadata, memory mapping, and Zarr arrays specifically for TIFF data files.

  • Memory mapping memmap enables efficient work with large files by mapping portions into memory as needed, without loading the entire file.

  • Zarr storage format, known for its handling of chunked, compressed, and n-dimensional arrays. This provides flexibility in reading and writing Zarr arrays, contributing to the library’s versatility in managing microscopy datasets, especially those with large or complex structures.

[2]:
t1 = skimage.io.imread(img_tile, plugin="tifffile")
t2 = skimage.io.imread(img_void_tile, plugin="tifffile")
t1.shape, t2.shape
/tmp/ipykernel_4307/3133617244.py:1: FutureWarning: The plugin infrastructure in `skimage.io` and the parameter `plugin` are deprecated since version 0.25 and will be removed in 0.27 (or later). To avoid this warning, please do not use the parameter `plugin`. Instead, use `imageio` or other I/O packages directly. See also `imread`.
  t1 = skimage.io.imread(img_tile, plugin="tifffile")
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
/tmp/ipykernel_4307/3133617244.py in ?()
----> 1 t1 = skimage.io.imread(img_tile, plugin="tifffile")
      2 t2 = skimage.io.imread(img_void_tile, plugin="tifffile")
      3 t1.shape, t2.shape

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/skimage/_shared/utils.py in ?(*args, **kwargs)
    324                 elif self.new_name is not None:
    325                     # Assign old value to new one
    326                     kwargs[self.new_name] = deprecated_value
    327
--> 328             return func(*args, **kwargs)

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/skimage/io/_io.py in ?(fname, as_gray, plugin, **plugin_args)
     78         if fname.lower().endswith(('.tiff', '.tif')):
     79             plugin = 'tifffile'
     80
     81     with file_or_url_context(fname) as fname, _hide_plugin_deprecation_warnings():
---> 82         img = call_plugin('imread', fname, plugin=plugin, **plugin_args)
     83
     84     if not hasattr(img, 'ndim'):
     85         return img

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/skimage/_shared/utils.py in ?(*args, **kwargs)
    534         @functools.wraps(func)
    535         def wrapped(*args, **kwargs):
    536             stacklevel = 1 + self.get_stack_length(func) - stack_rank
    537             warnings.warn(message, category=FutureWarning, stacklevel=stacklevel)
--> 538             return func(*args, **kwargs)

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/skimage/io/manage_plugins.py in ?(kind, *args, **kwargs)
    250             func = [f for (p, f) in plugin_funcs if p == plugin][0]
    251         except IndexError:
    252             raise RuntimeError(f'Could not find the plugin "{plugin}" for {kind}.')
    253
--> 254     return func(*args, **kwargs)

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/skimage/io/_plugins/tifffile_plugin.py in ?(fname, **kwargs)
     70     """
     71     if 'img_num' in kwargs:
     72         kwargs['key'] = kwargs.pop('img_num')
     73
---> 74     return tifffile_imread(fname, **kwargs)

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(files, selection, aszarr, key, series, level, squeeze, maxworkers, buffersize, mode, name, offset, size, pattern, axesorder, categories, imread, imreadargs, sort, container, chunkshape, chunkdtype, axestiled, ioworkers, chunkmode, fillvalue, zattrs, multiscales, omexml, out, out_inplace, _multifile, _useframes, **kwargs)
   1203         ):
   1204             files = files[0]
   1205
   1206         if isinstance(files, str) or not isinstance(files, Sequence):
-> 1207             with TiffFile(
   1208                 files,
   1209                 mode=mode,
   1210                 name=name,

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self, file, mode, name, offset, size, omexml, _multifile, _useframes, _parent, **is_flags)
   4278                 raise ValueError('invalid OME-XML')
   4279             self._omexml = omexml
   4280             self.is_ome = True
   4281
-> 4282         fh = FileHandle(file, mode=mode, name=name, offset=offset, size=size)
   4283         self._fh = fh
   4284         self._multifile = True if _multifile is None else bool(_multifile)
   4285         self._files = {fh.name: self}

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self, file, mode, name, offset, size)
  13323         self._offset = -1 if offset is None else offset
  13324         self._size = -1 if size is None else size
  13325         self._close = True
  13326         self._lock = NullContext()
> 13327         self.open()
  13328         assert self._fh is not None

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self)
  13342             if self._mode not in {'rb', 'r+b', 'wb', 'xb'}:
  13343                 raise ValueError(f'invalid mode {self._mode}')
  13344             self._file = os.path.realpath(self._file)
  13345             self._dir, self._name = os.path.split(self._file)
> 13346             self._fh = open(self._file, self._mode, encoding=None)
  13347             self._close = True
  13348             self._offset = max(0, self._offset)
  13349         elif isinstance(self._file, FileHandle):

FileNotFoundError: [Errno 2] No such file or directory: '/home/runner/work/nima_io/nima_io/tests/data/t4_1.tif'
[3]:
tf1 = tifffile.imread(img_tile)
tf2 = tifffile.imread(img_void_tile)
tf1.shape, tf2.shape
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
/tmp/ipykernel_4307/3090132194.py in ?()
----> 1 tf1 = tifffile.imread(img_tile)
      2 tf2 = tifffile.imread(img_void_tile)
      3 tf1.shape, tf2.shape

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(files, selection, aszarr, key, series, level, squeeze, maxworkers, buffersize, mode, name, offset, size, pattern, axesorder, categories, imread, imreadargs, sort, container, chunkshape, chunkdtype, axestiled, ioworkers, chunkmode, fillvalue, zattrs, multiscales, omexml, out, out_inplace, _multifile, _useframes, **kwargs)
   1203         ):
   1204             files = files[0]
   1205
   1206         if isinstance(files, str) or not isinstance(files, Sequence):
-> 1207             with TiffFile(
   1208                 files,
   1209                 mode=mode,
   1210                 name=name,

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self, file, mode, name, offset, size, omexml, _multifile, _useframes, _parent, **is_flags)
   4278                 raise ValueError('invalid OME-XML')
   4279             self._omexml = omexml
   4280             self.is_ome = True
   4281
-> 4282         fh = FileHandle(file, mode=mode, name=name, offset=offset, size=size)
   4283         self._fh = fh
   4284         self._multifile = True if _multifile is None else bool(_multifile)
   4285         self._files = {fh.name: self}

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self, file, mode, name, offset, size)
  13323         self._offset = -1 if offset is None else offset
  13324         self._size = -1 if size is None else size
  13325         self._close = True
  13326         self._lock = NullContext()
> 13327         self.open()
  13328         assert self._fh is not None

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self)
  13342             if self._mode not in {'rb', 'r+b', 'wb', 'xb'}:
  13343                 raise ValueError(f'invalid mode {self._mode}')
  13344             self._file = os.path.realpath(self._file)
  13345             self._dir, self._name = os.path.split(self._file)
> 13346             self._fh = open(self._file, self._mode, encoding=None)
  13347             self._close = True
  13348             self._offset = max(0, self._offset)
  13349         elif isinstance(self._file, FileHandle):

FileNotFoundError: [Errno 2] No such file or directory: '/home/runner/work/nima_io/nima_io/tests/data/t4_1.tif'
[4]:
fp1glob = str(tdata / "im1s1z3c5t_?.ome.tif")

tifs = tifffile.TiffSequence(fp1glob)
d = tifs.asarray()
print(d.shape)
print(tifs.shape)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/tmp/ipykernel_4307/2832391936.py in ?()
      1 fp1glob = str(tdata / "im1s1z3c5t_?.ome.tif")
      2
----> 3 tifs = tifffile.TiffSequence(fp1glob)
      4 d = tifs.asarray()
      5 print(d.shape)
      6 print(tifs.shape)

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self, files, imread, **kwargs)
  13039         *,
  13040         imread: Callable[..., NDArray[Any]] = imread,
  13041         **kwargs: Any,
  13042     ) -> None:
> 13043         super().__init__(imread, '*.tif' if files is None else files, **kwargs)

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self, imread, files, container, sort, parse, **kwargs)
  12757                 files = sort_func(files)
  12758
  12759         files = [os.fspath(f) for f in files]  # type: ignore[union-attr]
  12760         if not files:
> 12761             raise ValueError('no files found')
  12762
  12763         if not callable(imread):
  12764             raise ValueError('invalid imread function')

ValueError: no files found
[5]:
with tifffile.TiffFile(img_tile) as tif:
    tag = tif.pages[0].tags["ImageDescription"]

tag.value[:1000]
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
/tmp/ipykernel_4307/3879889513.py in ?()
----> 1 with tifffile.TiffFile(img_tile) as tif:
      2     tag = tif.pages[0].tags["ImageDescription"]
      3
      4 tag.value[:1000]

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self, file, mode, name, offset, size, omexml, _multifile, _useframes, _parent, **is_flags)
   4278                 raise ValueError('invalid OME-XML')
   4279             self._omexml = omexml
   4280             self.is_ome = True
   4281
-> 4282         fh = FileHandle(file, mode=mode, name=name, offset=offset, size=size)
   4283         self._fh = fh
   4284         self._multifile = True if _multifile is None else bool(_multifile)
   4285         self._files = {fh.name: self}

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self, file, mode, name, offset, size)
  13323         self._offset = -1 if offset is None else offset
  13324         self._size = -1 if size is None else size
  13325         self._close = True
  13326         self._lock = NullContext()
> 13327         self.open()
  13328         assert self._fh is not None

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self)
  13342             if self._mode not in {'rb', 'r+b', 'wb', 'xb'}:
  13343                 raise ValueError(f'invalid mode {self._mode}')
  13344             self._file = os.path.realpath(self._file)
  13345             self._dir, self._name = os.path.split(self._file)
> 13346             self._fh = open(self._file, self._mode, encoding=None)
  13347             self._close = True
  13348             self._offset = max(0, self._offset)
  13349         elif isinstance(self._file, FileHandle):

FileNotFoundError: [Errno 2] No such file or directory: '/home/runner/work/nima_io/nima_io/tests/data/t4_1.tif'

1.3. nima_io#

1.3.1. read#

[6]:
md, wr = ir.read(simg_void_tile)
md.core, wr
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[6], line 1
----> 1 md, wr = ir.read(simg_void_tile)
      2 md.core, wr

File ~/work/nima_io/nima_io/src/nima_io/read.py:428, in read(filepath)
    426 if not Path(filepath).is_file():
    427     msg = f"File not found: {filepath}"
--> 428     raise FileNotFoundError(msg)
    429 ensure_jvm()
    430 channel_separator = jimport("loci.formats.ChannelSeparator")

FileNotFoundError: File not found: ../../tests/data/tile6_1.tif
[7]:
md.core.voxel_size
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[7], line 1
----> 1 md.core.voxel_size

NameError: name 'md' is not defined
[8]:
root = wr.rdr.getMetadataStoreRoot()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[8], line 1
----> 1 root = wr.rdr.getMetadataStoreRoot()

NameError: name 'wr' is not defined
[9]:
ome_store = wr.rdr.getMetadataStore()
ome_store
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[9], line 1
----> 1 ome_store = wr.rdr.getMetadataStore()
      2 ome_store

NameError: name 'wr' is not defined
[10]:
get_power = ome_store.getArcPower(0, 4)
get_power
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[10], line 1
----> 1 get_power = ome_store.getArcPower(0, 4)
      2 get_power

NameError: name 'ome_store' is not defined
[11]:
att = ome_store.getChannelLightSourceSettingsAttenuation(0, 0)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[11], line 1
----> 1 att = ome_store.getChannelLightSourceSettingsAttenuation(0, 0)

NameError: name 'ome_store' is not defined
[12]:
nmax = 7
(
    len([md for md in md.full.items() if len(md[1][0][0]) == nmax]),
    [md for md in md.full.items() if len(md[1][0][0]) == nmax],
)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[12], line 3
      1 nmax = 7
      2 (
----> 3     len([md for md in md.full.items() if len(md[1][0][0]) == nmax]),
      4     [md for md in md.full.items() if len(md[1][0][0]) == nmax],
      5 )

NameError: name 'md' is not defined
[13]:
list(range(4))
[13]:
[0, 1, 2, 3]
[14]:
[(0,) * n for n in range(3 + 1)]
[14]:
[(), (0,), (0, 0), (0, 0, 0)]
[15]:
ir.convert_java_numeric_field(att), ir.convert_java_numeric_field(get_power)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[15], line 1
----> 1 ir.convert_java_numeric_field(att), ir.convert_java_numeric_field(get_power)

AttributeError: module 'nima_io.read' has no attribute 'convert_java_numeric_field'
[16]:
{md.full.get(k)[0][0] for k in md.full}
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[16], line 1
----> 1 {md.full.get(k)[0][0] for k in md.full}

NameError: name 'md' is not defined
[17]:
[(k, md.full.get(k)[0]) for k in md.full if not md.full.get(k)[0][1]]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[17], line 1
----> 1 [(k, md.full.get(k)[0]) for k in md.full if not md.full.get(k)[0][1]]

NameError: name 'md' is not defined
[18]:
ome_store.getRoot() == root
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[18], line 1
----> 1 ome_store.getRoot() == root

NameError: name 'ome_store' is not defined
[19]:
ome_store.getPlaneCount(4), ome_store.getPlaneTheC(4, 11), ome_store.getPixelsSizeZ(4)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[19], line 1
----> 1 ome_store.getPlaneCount(4), ome_store.getPlaneTheC(4, 11), ome_store.getPixelsSizeZ(4)

NameError: name 'ome_store' is not defined
[20]:
wr.rdr.getDimensionOrder(), ir.read(slif)[1].rdr.getDimensionOrder()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[20], line 1
----> 1 wr.rdr.getDimensionOrder(), ir.read(slif)[1].rdr.getDimensionOrder()

NameError: name 'wr' is not defined

Mind the difference between img_void_tile and lif files.

[21]:
md.full["PixelsDimensionOrder"]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[21], line 1
----> 1 md.full["PixelsDimensionOrder"]

NameError: name 'md' is not defined
[22]:
root.getImage(0)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[22], line 1
----> 1 root.getImage(0)

NameError: name 'root' is not defined
[23]:
root.getImage(13).getPixels().getPlane(11).getTheC().getValue()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[23], line 1
----> 1 root.getImage(13).getPixels().getPlane(11).getTheC().getValue()

NameError: name 'root' is not defined
[24]:
(
    root.getImage(13).getName(),
    ir.read(slif)[1].rdr.getMetadataStoreRoot().getImage(2).getName(),
)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[24], line 2
      1 (
----> 2     root.getImage(13).getName(),
      3     ir.read(slif)[1].rdr.getMetadataStoreRoot().getImage(2).getName(),
      4 )

NameError: name 'root' is not defined
[25]:
md.core.__dict__
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[25], line 1
----> 1 md.core.__dict__

NameError: name 'md' is not defined
[26]:
vars(md.core)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[26], line 1
----> 1 vars(md.core)

NameError: name 'md' is not defined

1.3.2. Stitch#

[27]:
f = ir.stitch(md.core, wr, c=2, t=2)
skimage.io.imshow(f)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[27], line 1
----> 1 f = ir.stitch(md.core, wr, c=2, t=2)
      2 skimage.io.imshow(f)

NameError: name 'md' is not defined
[28]:
md.core.stage_position[2]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[28], line 1
----> 1 md.core.stage_position[2]

NameError: name 'md' is not defined

1.4. nima_io.read#

function

time (ms)

note

read

169

read_pims

195

extra pims DIMS

  • Metadata is now uniform across different reading functions.

In the following sections, various bioformats implementations are explored. None of the explored libraries return the numerous metadata linked to individual planes. Consequently, I have developed a small library to handle additional (often neglected) metadata, such as acquisition stage position (essential for reconstructing tiled images) and illumination and emission settings.

1.4.1. PIMS#

Which is currently unable to download loci_tools.jar.

I really like the frame metadata t_s, x_um, y_um and z_um. Every array (2D, 3D, …, n-D) having those metadata in common are contained in the Frame obj: a numpy array with metadata(dict) and frame_no(int).

Are fs.bundle_axes (fs.frame_shape), fs.iter_axes and fs.default_coords overcomplicated?

Anyway: iter=0 == iter=n which is at least unexpected.

[29]:
md_pims, wr_pims = ir.read_pims(img_void_tile)
md_pims.core.__dict__
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
Cell In[29], line 1
----> 1 md_pims, wr_pims = ir.read_pims(img_void_tile)
      2 md_pims.core.__dict__

File ~/work/nima_io/nima_io/src/nima_io/read.py:479, in read_pims(filepath)
    442 def read_pims(filepath: str) -> tuple[Metadata, ImageReaderWrapper]:
    443     """Read metadata and initialize Bioformats reader using the pims library.
    444
    445     Parameters
   (...)    477     (series, plane) where plane combines z, t and c?
    478     """
--> 479     fs = pims.Bioformats(filepath)
    480     core_md = CoreMetadata(fs.rdr)
    481     md = Metadata(core_md, {}, {})

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/pims/bioformats.py:330, in BioformatsReader.__init__(self, filename, meta, java_memory, read_mode, series)
    328 # Make sure that file exists before starting java
    329 if not os.path.isfile(filename):
--> 330     raise IOError('The file "{}" does not exist.'.format(filename))
    332 # Start java VM and initialize logger (globally)
    333 if not jpype.isJVMStarted():

OSError: The file "../../tests/data/tile6_1.tif" does not exist.
[30]:
mdata = wr.rdr.getMetadataStore()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[30], line 1
----> 1 mdata = wr.rdr.getMetadataStore()

NameError: name 'wr' is not defined
[31]:
root = mdata.getRoot()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[31], line 1
----> 1 root = mdata.getRoot()

NameError: name 'mdata' is not defined
[32]:
im0 = root.getImage(0)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[32], line 1
----> 1 im0 = root.getImage(0)

NameError: name 'root' is not defined
[33]:
pixels = im0.getPixels()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[33], line 1
----> 1 pixels = im0.getPixels()

NameError: name 'im0' is not defined
[34]:
for idx in range(pixels.sizeOfTiffDataList()):
    tiffData = pixels.getTiffData(idx)
    c = tiffData.getFirstC().getValue().intValue()
    t = tiffData.getFirstT().getValue().intValue()
    print(f"TiffData: c={c}, t={t}")
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[34], line 1
----> 1 for idx in range(pixels.sizeOfTiffDataList()):
      2     tiffData = pixels.getTiffData(idx)
      3     c = tiffData.getFirstC().getValue().intValue()

NameError: name 'pixels' is not defined

1.5. ImageIO#

[35]:
from imageio.v3 import imread

%timeit imread(img_void_tile, index=13)
i = imread(img_void_tile, index=13)
i.shape
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[35], line 3
      1 from imageio.v3 import imread
----> 3 get_ipython().run_line_magic('timeit', 'imread(img_void_tile, index=13)')
      4 i = imread(img_void_tile, index=13)
      5 i.shape

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/IPython/core/interactiveshell.py:2488, in InteractiveShell.run_line_magic(self, magic_name, line, _stack_depth)
   2486     kwargs['local_ns'] = self.get_local_scope(stack_depth)
   2487 with self.builtin_trap:
-> 2488     result = fn(*args, **kwargs)
   2490 # The code below prevents the output from being displayed
   2491 # when using magics with decorator @output_can_be_silenced
   2492 # when the last Python token in the expression is a ';'.
   2493 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/IPython/core/magics/execution.py:1225, in ExecutionMagics.timeit(self, line, cell, local_ns)
   1223 for index in range(0, 10):
   1224     number = 10 ** index
-> 1225     time_number = timer.timeit(number)
   1226     if time_number >= 0.2:
   1227         break

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/IPython/core/magics/execution.py:183, in Timer.timeit(self, number)
    181 gc.disable()
    182 try:
--> 183     timing = self.inner(it, self.timer)
    184 finally:
    185     if gcold:

File <magic-timeit>:1, in inner(_it, _timer)

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/imageio/v3.py:53, in imread(uri, index, plugin, extension, format_hint, **kwargs)
     50 if index is not None:
     51     call_kwargs["index"] = index
---> 53 with imopen(uri, "r", **plugin_kwargs) as img_file:
     54     return np.asarray(img_file.read(**call_kwargs))

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/imageio/core/imopen.py:113, in imopen(uri, io_mode, plugin, extension, format_hint, legacy_mode, **kwargs)
    111     request.format_hint = format_hint
    112 else:
--> 113     request = Request(uri, io_mode, format_hint=format_hint, extension=extension)
    115 source = "<bytes>" if isinstance(uri, bytes) else uri
    117 # fast-path based on plugin
    118 # (except in legacy mode)

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/imageio/core/request.py:249, in Request.__init__(self, uri, mode, extension, format_hint, **kwargs)
    246     raise ValueError(f"Invalid Request.Mode: {mode}")
    248 # Parse what was given
--> 249 self._parse_uri(uri)
    251 # Set extension
    252 if extension is not None:

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/imageio/core/request.py:409, in Request._parse_uri(self, uri)
    406 if is_read_request:
    407     # Reading: check that the file exists (but is allowed a dir)
    408     if not os.path.exists(fn):
--> 409         raise FileNotFoundError("No such file: '%s'" % fn)
    410 else:
    411     # Writing: check that the directory to write to does exist
    412     dn = os.path.dirname(fn)

FileNotFoundError: No such file: '/home/runner/work/nima_io/nima_io/tests/data/tile6_1.tif'
[36]:
i.nbytes, 512**2 * 3 * 4 * 2
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[36], line 1
----> 1 i.nbytes, 512**2 * 3 * 4 * 2

NameError: name 'i' is not defined

It can read tif (tf8) files. Series might be passed using index (you need to know in advance).

1.6. AICSImageIO#

[37]:
from aicsimageio import AICSImage

i = AICSImage(img_void_tile)
# i = AICSImage(img_void_tile, reconstruct_mosaic=True)
# i_lif = AICSImage(lif)
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[37], line 1
----> 1 from aicsimageio import AICSImage
      3 i = AICSImage(img_void_tile)
      4 # i = AICSImage(img_void_tile, reconstruct_mosaic=True)
      5 # i_lif = AICSImage(lif)

ModuleNotFoundError: No module named 'aicsimageio'
[38]:
i.ome_metadata.instruments[0].arcs[0]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[38], line 1
----> 1 i.ome_metadata.instruments[0].arcs[0]

NameError: name 'i' is not defined
[39]:
lif_aics = AICSImage(slif)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[39], line 1
----> 1 lif_aics = AICSImage(slif)

NameError: name 'AICSImage' is not defined
[40]:
lif_aics.metadata
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[40], line 1
----> 1 lif_aics.metadata

NameError: name 'lif_aics' is not defined
[41]:
i.ome_metadata
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[41], line 1
----> 1 i.ome_metadata

NameError: name 'i' is not defined
[42]:
i.metadata.images[0].pixels.channels[0].light_source_settings.attenuation
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[42], line 1
----> 1 i.metadata.images[0].pixels.channels[0].light_source_settings.attenuation

NameError: name 'i' is not defined
[43]:
i.scenes
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[43], line 1
----> 1 i.scenes

NameError: name 'i' is not defined
[44]:
i.get_dask_stack()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[44], line 1
----> 1 i.get_dask_stack()

NameError: name 'i' is not defined

Mosaic stitch is not supported on tif files; so I will use my function relying on the PositionXYZ metadata.

1.7. dask_image#

[45]:
from dask_image.imread import imread

i = imread(img_void_tile)
---------------------------------------------------------------------------
UnknownFormatError                        Traceback (most recent call last)
Cell In[45], line 3
      1 from dask_image.imread import imread
----> 3 i = imread(img_void_tile)

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/dask_image/imread/__init__.py:48, in imread(fname, nframes, arraytype)
     45     import cupy
     46     arrayfunc = cupy.asanyarray
---> 48 with pims.open(sfname) as imgs:
     49     shape = (len(imgs),) + imgs.frame_shape
     50     dtype = np.dtype(imgs.pixel_type)

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/pims/api.py:199, in open(sequence, **kwargs)
    197     except Exception as e:
    198         messages.append('{} errored: {}'.format(str(handler), str(e)))
--> 199 raise UnknownFormatError(
    200     "All handlers returned exceptions:\n" + "\n".join(messages))

UnknownFormatError: All handlers returned exceptions:
<class 'pims.tiff_stack.TiffStack_tifffile'> errored: [Errno 2] No such file or directory: '/home/runner/work/nima_io/nima_io/tests/data/tile6_1.tif'
<class 'pims.imageio_reader.ImageIOReader'> errored: No such file: '/home/runner/work/nima_io/nima_io/tests/data/tile6_1.tif'
<class 'pims.bioformats.BioformatsReader'> errored: The file "../../tests/data/tile6_1.tif" does not exist.
[46]:
i
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[46], line 1
----> 1 i

NameError: name 'i' is not defined

Somehow it uses bioformats and can handle lif. No mosaic, no metadata though.

Pycroscopy https://pypi.org/project/pycroscopy/ is not reading lif nor ome-tif at the moment.

large-image[all] failed to install.

pyimagej need conda?

1.8. bioio-bioformats#

import bioio_ome_tiled_tiff

bioio_ome_tiled_tiff.Reader(str(img_void_tile))

TypeError: tile6_1.tif is not a tiled tiff. The python backend of the BioReader only supports OME tiled tiffs.

[47]:
import bioio_bioformats

im = bioio_bioformats.Reader(img_void_tile)
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[47], line 3
      1 import bioio_bioformats
----> 3 im = bioio_bioformats.Reader(img_void_tile)

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bioio_bioformats/reader.py:110, in Reader.__init__(self, image, original_meta, memoize, options, dask_tiles, tile_size, fs_kwargs)
     99 def __init__(
    100     self,
    101     image: types.PathLike,
   (...)    108     fs_kwargs: Dict[str, Any] = {},
    109 ):
--> 110     self._fs, self._path = io.pathlike_to_fs(
    111         image,
    112         enforce_exists=True,
    113         fs_kwargs=fs_kwargs,
    114     )
    115     # Catch non-local file system
    116     if not isinstance(self._fs, LocalFileSystem):

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bioio_base/io.py:58, in pathlike_to_fs(uri, enforce_exists, fs_kwargs)
     56 if enforce_exists:
     57     if not fs.exists(path):
---> 58         raise FileNotFoundError(f"{fs.protocol}://{path}")
     60 # Get and store details
     61 # We do not return an AbstractBufferedFile (i.e. fs.open) as we do not want to have
     62 # any open file buffers _after_ any API call. API calls must themselves call
     63 # fs.open and complete their function during the context of the opened buffer.
     64 return fs, path

FileNotFoundError: ('file', 'local'):///home/runner/work/nima_io/nima_io/docs/tutorials/../../tests/data/tile6_1.tif
[48]:
im.ome_metadata.images[0].pixels.channels[2].light_source_settings
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[48], line 1
----> 1 im.ome_metadata.images[0].pixels.channels[2].light_source_settings

NameError: name 'im' is not defined
[49]:
lif_bioio = bioio_bioformats.Reader(lif)
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[49], line 1
----> 1 lif_bioio = bioio_bioformats.Reader(lif)

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bioio_bioformats/reader.py:110, in Reader.__init__(self, image, original_meta, memoize, options, dask_tiles, tile_size, fs_kwargs)
     99 def __init__(
    100     self,
    101     image: types.PathLike,
   (...)    108     fs_kwargs: Dict[str, Any] = {},
    109 ):
--> 110     self._fs, self._path = io.pathlike_to_fs(
    111         image,
    112         enforce_exists=True,
    113         fs_kwargs=fs_kwargs,
    114     )
    115     # Catch non-local file system
    116     if not isinstance(self._fs, LocalFileSystem):

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bioio_base/io.py:58, in pathlike_to_fs(uri, enforce_exists, fs_kwargs)
     56 if enforce_exists:
     57     if not fs.exists(path):
---> 58         raise FileNotFoundError(f"{fs.protocol}://{path}")
     60 # Get and store details
     61 # We do not return an AbstractBufferedFile (i.e. fs.open) as we do not want to have
     62 # any open file buffers _after_ any API call. API calls must themselves call
     63 # fs.open and complete their function during the context of the opened buffer.
     64 return fs, path

FileNotFoundError: ('file', 'local'):///home/runner/work/nima_io/nima_io/docs/tutorials/../../tests/data/2015Aug28_TransHXB2_50min+DMSO.lif
[50]:
lif_bioio.physical_pixel_sizes
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[50], line 1
----> 1 lif_bioio.physical_pixel_sizes

NameError: name 'lif_bioio' is not defined
[51]:
im.get_dask_stack()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[51], line 1
----> 1 im.get_dask_stack()

NameError: name 'im' is not defined
[52]:
im.ome_metadata.plates[0].wells[0]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[52], line 1
----> 1 im.ome_metadata.plates[0].wells[0]

NameError: name 'im' is not defined
[53]:
i = bioio_bioformats.Reader(img_tile)
i.data.shape, i.dims
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[53], line 1
----> 1 i = bioio_bioformats.Reader(img_tile)
      2 i.data.shape, i.dims

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bioio_bioformats/reader.py:110, in Reader.__init__(self, image, original_meta, memoize, options, dask_tiles, tile_size, fs_kwargs)
     99 def __init__(
    100     self,
    101     image: types.PathLike,
   (...)    108     fs_kwargs: Dict[str, Any] = {},
    109 ):
--> 110     self._fs, self._path = io.pathlike_to_fs(
    111         image,
    112         enforce_exists=True,
    113         fs_kwargs=fs_kwargs,
    114     )
    115     # Catch non-local file system
    116     if not isinstance(self._fs, LocalFileSystem):

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bioio_base/io.py:58, in pathlike_to_fs(uri, enforce_exists, fs_kwargs)
     56 if enforce_exists:
     57     if not fs.exists(path):
---> 58         raise FileNotFoundError(f"{fs.protocol}://{path}")
     60 # Get and store details
     61 # We do not return an AbstractBufferedFile (i.e. fs.open) as we do not want to have
     62 # any open file buffers _after_ any API call. API calls must themselves call
     63 # fs.open and complete their function during the context of the opened buffer.
     64 return fs, path

FileNotFoundError: ('file', 'local'):///home/runner/work/nima_io/nima_io/docs/tutorials/../../tests/data/t4_1.tif
[54]:
i.xarray_dask_data.attrs["processed"]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[54], line 1
----> 1 i.xarray_dask_data.attrs["processed"]

NameError: name 'i' is not defined
[55]:
unp = i.xarray_dask_data.attrs["unprocessed"]
unp[:1000]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[55], line 1
----> 1 unp = i.xarray_dask_data.attrs["unprocessed"]
      2 unp[:1000]

NameError: name 'i' is not defined
[56]:
stk = i.get_dask_stack()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[56], line 1
----> 1 stk = i.get_dask_stack()

NameError: name 'i' is not defined
[57]:
stk.A
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[57], line 1
----> 1 stk.A

NameError: name 'stk' is not defined

1.9. bfio#

[58]:
import bfio

bfio.BioReader(img_void_tile)
18-Jun-25 07:21:10 - jgo      - ERROR    - Failed to bootstrap the artifact.
18-Jun-25 07:21:10 - jgo      - ERROR    -
18-Jun-25 07:21:10 - jgo      - ERROR    - Possible solutions:
18-Jun-25 07:21:10 - jgo      - ERROR    - * Double check the endpoint for correctness (https://search.maven.org/).
18-Jun-25 07:21:10 - jgo      - ERROR    - * Add needed repositories to ~/.jgorc [repositories] block (see README).
18-Jun-25 07:21:10 - jgo      - ERROR    - * Try with an explicit version number (release metadata might be wrong).
18-Jun-25 07:21:10 - jgo      - ERROR    -
18-Jun-25 07:21:10 - jgo      - ERROR    - Full Maven error output:
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR] [ERROR] Some problems were encountered while processing the POMs:
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR] Non-resolvable import POM: The following artifacts could not be resolved: ome:formats-gpl:pom:8.0.1 (absent): Could not transfer artifact ome:formats-gpl:pom:8.0.1 from/to scijava.public (https://maven.scijava.org/content/groups/public): status code: 503, reason phrase: Service Unavailable (503) @ line 8, column 29
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR] The build could not read 1 project -> [Help 1]
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR]
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR]   The project ome-BOOTSTRAPPER:formats-gpl-BOOTSTRAPPER:0 (/home/runner/.jgo/ome/formats-gpl/8.0.1/344539b25396a9fec73bbca83cd544ca093643095ca71d7225ef568cd60ef13a/pom.xml) has 1 error
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR]     Non-resolvable import POM: The following artifacts could not be resolved: ome:formats-gpl:pom:8.0.1 (absent): Could not transfer artifact ome:formats-gpl:pom:8.0.1 from/to scijava.public (https://maven.scijava.org/content/groups/public): status code: 503, reason phrase: Service Unavailable (503) @ line 8, column 29 -> [Help 2]
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR]
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR] Re-run Maven using the -X switch to enable full debug logging.
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR]
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR] For more information about the errors and possible solutions, please read the following articles:
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
18-Jun-25 07:21:10 - jgo      - ERROR    -      [ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException
18-Jun-25 07:21:10 - jgo      - ERROR    -
---------------------------------------------------------------------------
CalledProcessError                        Traceback (most recent call last)
Cell In[58], line 3
      1 import bfio
----> 3 bfio.BioReader(img_void_tile)

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bfio/bfio.py:98, in BioReader.__init__(self, file_path, max_workers, backend, clean_metadata, level)
     96 elif self._backend_name == "bioformats":
     97     try:
---> 98         self._backend = backends.JavaReader(self)
     99         if max_workers is not None:
    100             self.logger.warning(
    101                 "The max_workers keyword was present, but bioformats backend "
    102                 + "only operates with a single worker. Setting max_workers=1."
    103             )

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bfio/backends.py:951, in JavaReader.__init__(self, frontend)
    949 def __init__(self, frontend):
    950     if not JavaReader._classes_loaded:
--> 951         self._load_java_classes()
    953     super().__init__(frontend)
    955     factory = ServiceFactory()

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bfio/backends.py:933, in JavaReader._load_java_classes(self)
    931 def _load_java_classes(self):
    932     if not jpype.isJVMStarted():
--> 933         start()
    935     global ImageReader
    936     from loci.formats import ImageReader

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bfio/utils.py:43, in start()
     41 global JAR_VERSION
     42 scyjava.config.endpoints.append("ome:formats-gpl:8.0.1")
---> 43 scyjava.start_jvm()
     44 import loci
     46 loci.common.DebugTools.setRootLevel("ERROR")

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/scyjava/_jvm.py:146, in start_jvm(options)
    144     endpoints = endpoints[:1] + sorted(endpoints[1:])
    145     _logger.debug("Using endpoints %s", endpoints)
--> 146     _, workspace = jgo.resolve_dependencies(
    147         "+".join(endpoints),
    148         m2_repo=scyjava.config.get_m2_repo(),
    149         cache_dir=scyjava.config.get_cache_dir(),
    150         manage_dependencies=scyjava.config.get_manage_deps(),
    151         repositories=repositories,
    152         verbose=scyjava.config.get_verbose(),
    153         shortcuts=scyjava.config.get_shortcuts(),
    154     )
    155     jpype.addClassPath(os.path.join(workspace, "*"))
    157 # HACK: Try to set JAVA_HOME if it isn't already.

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/jgo/jgo.py:667, in resolve_dependencies(endpoint_string, cache_dir, m2_repo, link_type, update_cache, force_update, manage_dependencies, repositories, shortcuts, verbose)
    664             _logger.debug("\t%s", line)
    665     _logger.error("")
--> 667     raise e
    669 info_regex = re.compile("^.*\\[[A-Z]+\\] *")
    670 relevant_jars = []

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/jgo/jgo.py:638, in resolve_dependencies(endpoint_string, cache_dir, m2_repo, link_type, update_cache, force_update, manage_dependencies, repositories, shortcuts, verbose)
    636 try:
    637     mvn = executable_path_or_raise("mvn")
--> 638     mvn_out = run_and_combine_outputs(mvn, *mvn_args)
    639 except subprocess.CalledProcessError as e:
    640     _logger.error("Failed to bootstrap the artifact.")

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/jgo/jgo.py:269, in run_and_combine_outputs(command, *args)
    267 command_string = (command,) + args
    268 _logger.debug(f"Executing: {command_string}")
--> 269 return subprocess.check_output(command_string, stderr=subprocess.STDOUT)

File /opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/subprocess.py:466, in check_output(timeout, *popenargs, **kwargs)
    463         empty = b''
    464     kwargs['input'] = empty
--> 466 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    467            **kwargs).stdout

File /opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/subprocess.py:571, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    569     retcode = process.poll()
    570     if check and retcode:
--> 571         raise CalledProcessError(retcode, process.args,
    572                                  output=stdout, stderr=stderr)
    573 return CompletedProcess(process.args, retcode, stdout, stderr)

CalledProcessError: Command '('/usr/bin/mvn', '-B', '-f', '/home/runner/.jgo/ome/formats-gpl/8.0.1/344539b25396a9fec73bbca83cd544ca093643095ca71d7225ef568cd60ef13a/pom.xml', 'dependency:resolve')' returned non-zero exit status 1.
[59]:
rdr = bfio.BioReader(img_void_tile)
%timeit i = rdr.read()
i = rdr.read()
i.shape
18-Jun-25 07:21:43 - jgo      - ERROR    - Failed to bootstrap the artifact.
18-Jun-25 07:21:43 - jgo      - ERROR    -
18-Jun-25 07:21:43 - jgo      - ERROR    - Possible solutions:
18-Jun-25 07:21:43 - jgo      - ERROR    - * Double check the endpoint for correctness (https://search.maven.org/).
18-Jun-25 07:21:43 - jgo      - ERROR    - * Add needed repositories to ~/.jgorc [repositories] block (see README).
18-Jun-25 07:21:43 - jgo      - ERROR    - * Try with an explicit version number (release metadata might be wrong).
18-Jun-25 07:21:43 - jgo      - ERROR    -
18-Jun-25 07:21:43 - jgo      - ERROR    - Full Maven error output:
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR] [ERROR] Some problems were encountered while processing the POMs:
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR] Non-resolvable import POM: The following artifacts could not be resolved: ome:formats-gpl:pom:8.0.1 (absent): Could not transfer artifact ome:formats-gpl:pom:8.0.1 from/to scijava.public (https://maven.scijava.org/content/groups/public): status code: 503, reason phrase: Service Unavailable (503) @ line 8, column 29
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR] The build could not read 1 project -> [Help 1]
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR]
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR]   The project ome-BOOTSTRAPPER:formats-gpl-BOOTSTRAPPER:0 (/home/runner/.jgo/ome/formats-gpl/8.0.1/a15c5e3bb47cd22481cf59c89685740cd2f7b08fa54309173309300e97d04535/pom.xml) has 1 error
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR]     Non-resolvable import POM: The following artifacts could not be resolved: ome:formats-gpl:pom:8.0.1 (absent): Could not transfer artifact ome:formats-gpl:pom:8.0.1 from/to scijava.public (https://maven.scijava.org/content/groups/public): status code: 503, reason phrase: Service Unavailable (503) @ line 8, column 29 -> [Help 2]
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR]
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR] Re-run Maven using the -X switch to enable full debug logging.
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR]
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR] For more information about the errors and possible solutions, please read the following articles:
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
18-Jun-25 07:21:43 - jgo      - ERROR    -      [ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException
18-Jun-25 07:21:43 - jgo      - ERROR    -
---------------------------------------------------------------------------
CalledProcessError                        Traceback (most recent call last)
Cell In[59], line 1
----> 1 rdr = bfio.BioReader(img_void_tile)
      2 get_ipython().run_line_magic('timeit', 'i = rdr.read()')
      3 i = rdr.read()

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bfio/bfio.py:98, in BioReader.__init__(self, file_path, max_workers, backend, clean_metadata, level)
     96 elif self._backend_name == "bioformats":
     97     try:
---> 98         self._backend = backends.JavaReader(self)
     99         if max_workers is not None:
    100             self.logger.warning(
    101                 "The max_workers keyword was present, but bioformats backend "
    102                 + "only operates with a single worker. Setting max_workers=1."
    103             )

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bfio/backends.py:951, in JavaReader.__init__(self, frontend)
    949 def __init__(self, frontend):
    950     if not JavaReader._classes_loaded:
--> 951         self._load_java_classes()
    953     super().__init__(frontend)
    955     factory = ServiceFactory()

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bfio/backends.py:933, in JavaReader._load_java_classes(self)
    931 def _load_java_classes(self):
    932     if not jpype.isJVMStarted():
--> 933         start()
    935     global ImageReader
    936     from loci.formats import ImageReader

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/bfio/utils.py:43, in start()
     41 global JAR_VERSION
     42 scyjava.config.endpoints.append("ome:formats-gpl:8.0.1")
---> 43 scyjava.start_jvm()
     44 import loci
     46 loci.common.DebugTools.setRootLevel("ERROR")

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/scyjava/_jvm.py:146, in start_jvm(options)
    144     endpoints = endpoints[:1] + sorted(endpoints[1:])
    145     _logger.debug("Using endpoints %s", endpoints)
--> 146     _, workspace = jgo.resolve_dependencies(
    147         "+".join(endpoints),
    148         m2_repo=scyjava.config.get_m2_repo(),
    149         cache_dir=scyjava.config.get_cache_dir(),
    150         manage_dependencies=scyjava.config.get_manage_deps(),
    151         repositories=repositories,
    152         verbose=scyjava.config.get_verbose(),
    153         shortcuts=scyjava.config.get_shortcuts(),
    154     )
    155     jpype.addClassPath(os.path.join(workspace, "*"))
    157 # HACK: Try to set JAVA_HOME if it isn't already.

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/jgo/jgo.py:667, in resolve_dependencies(endpoint_string, cache_dir, m2_repo, link_type, update_cache, force_update, manage_dependencies, repositories, shortcuts, verbose)
    664             _logger.debug("\t%s", line)
    665     _logger.error("")
--> 667     raise e
    669 info_regex = re.compile("^.*\\[[A-Z]+\\] *")
    670 relevant_jars = []

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/jgo/jgo.py:638, in resolve_dependencies(endpoint_string, cache_dir, m2_repo, link_type, update_cache, force_update, manage_dependencies, repositories, shortcuts, verbose)
    636 try:
    637     mvn = executable_path_or_raise("mvn")
--> 638     mvn_out = run_and_combine_outputs(mvn, *mvn_args)
    639 except subprocess.CalledProcessError as e:
    640     _logger.error("Failed to bootstrap the artifact.")

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/jgo/jgo.py:269, in run_and_combine_outputs(command, *args)
    267 command_string = (command,) + args
    268 _logger.debug(f"Executing: {command_string}")
--> 269 return subprocess.check_output(command_string, stderr=subprocess.STDOUT)

File /opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/subprocess.py:466, in check_output(timeout, *popenargs, **kwargs)
    463         empty = b''
    464     kwargs['input'] = empty
--> 466 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    467            **kwargs).stdout

File /opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/subprocess.py:571, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    569     retcode = process.poll()
    570     if check and retcode:
--> 571         raise CalledProcessError(retcode, process.args,
    572                                  output=stdout, stderr=stderr)
    573 return CompletedProcess(process.args, retcode, stdout, stderr)

CalledProcessError: Command '('/usr/bin/mvn', '-B', '-f', '/home/runner/.jgo/ome/formats-gpl/8.0.1/a15c5e3bb47cd22481cf59c89685740cd2f7b08fa54309173309300e97d04535/pom.xml', 'dependency:resolve')' returned non-zero exit status 1.
[60]:
rdr.metadata
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[60], line 1
----> 1 rdr.metadata

NameError: name 'rdr' is not defined
[61]:
rdr.ps_x
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[61], line 1
----> 1 rdr.ps_x

NameError: name 'rdr' is not defined
[62]:
rdr.close()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[62], line 1
----> 1 rdr.close()

NameError: name 'rdr' is not defined

1.10. PIMS#

[63]:
import pims

# %timeit fs = pims.Bioformats(img_void_tile)
fs = pims.Bioformats(img_void_tile)
fs.sizes
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
Cell In[63], line 4
      1 import pims
      3 # %timeit fs = pims.Bioformats(img_void_tile)
----> 4 fs = pims.Bioformats(img_void_tile)
      5 fs.sizes

File ~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/pims/bioformats.py:330, in BioformatsReader.__init__(self, filename, meta, java_memory, read_mode, series)
    328 # Make sure that file exists before starting java
    329 if not os.path.isfile(filename):
--> 330     raise IOError('The file "{}" does not exist.'.format(filename))
    332 # Start java VM and initialize logger (globally)
    333 if not jpype.isJVMStarted():

OSError: The file "../../tests/data/tile6_1.tif" does not exist.

1.11. PyOMETiff#

[64]:
import pyometiff

%timeit rdr = pyometiff.OMETIFFReader(fpath=img_void_tile)
rdr = pyometiff.OMETIFFReader(fpath=img_void_tile)
1.32 μs ± 4.39 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
[65]:
%timeit r = rdr.read()
res = rdr.read()
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
/tmp/ipykernel_4307/1732195015.py in ?()
----> 1 get_ipython().run_line_magic('timeit', 'r = rdr.read()')
      2 res = rdr.read()

<magic-timeit> in ?(_it, _timer)
----> 1 'Could not get source, probably due dynamically evaluated source code.'

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/pyometiff/omereader.py in ?(self)
     38     def read(self) -> tuple[np.ndarray, dict, str]:
---> 39         self.array, self.omexml_string = self._open_tiff(self.fpath)
     40         self.metadata = self.parse_metadata(self.omexml_string)
     41         return self.array, self.metadata, self.omexml_string

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/pyometiff/omereader.py in ?(cls, fpath)
    221     @classmethod
    222     def _open_tiff(cls, fpath: pathlib.Path) -> tuple[np.ndarray, str]:
--> 223         with tifffile.TiffFile(str(fpath)) as tif:
    224             omexml_string = tif.ome_metadata
    225             array = tif.asarray()
    226

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self, file, mode, name, offset, size, omexml, _multifile, _useframes, _parent, **is_flags)
   4278                 raise ValueError('invalid OME-XML')
   4279             self._omexml = omexml
   4280             self.is_ome = True
   4281
-> 4282         fh = FileHandle(file, mode=mode, name=name, offset=offset, size=size)
   4283         self._fh = fh
   4284         self._multifile = True if _multifile is None else bool(_multifile)
   4285         self._files = {fh.name: self}

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self, file, mode, name, offset, size)
  13323         self._offset = -1 if offset is None else offset
  13324         self._size = -1 if size is None else size
  13325         self._close = True
  13326         self._lock = NullContext()
> 13327         self.open()
  13328         assert self._fh is not None

~/.local/share/hatch/env/virtual/nima-io/FLi94gtt/nima-io/lib/python3.12/site-packages/tifffile/tifffile.py in ?(self)
  13342             if self._mode not in {'rb', 'r+b', 'wb', 'xb'}:
  13343                 raise ValueError(f'invalid mode {self._mode}')
  13344             self._file = os.path.realpath(self._file)
  13345             self._dir, self._name = os.path.split(self._file)
> 13346             self._fh = open(self._file, self._mode, encoding=None)
  13347             self._close = True
  13348             self._offset = max(0, self._offset)
  13349         elif isinstance(self._file, FileHandle):

FileNotFoundError: [Errno 2] No such file or directory: '/home/runner/work/nima_io/nima_io/tests/data/tile6_1.tif'
[66]:
res[1]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[66], line 1
----> 1 res[1]

NameError: name 'res' is not defined
[67]:
pyometiff.OMETIFFReader._get_metadata_template()
[67]:
{'Directory': None,
 'Filename': None,
 'Extension': None,
 'ImageType': None,
 'AcqDate': None,
 'TotalSeries': None,
 'SizeX': None,
 'SizeY': None,
 'SizeZ': 1,
 'SizeC': 1,
 'SizeT': 1,
 'SizeS': 1,
 'SizeB': 1,
 'SizeM': 1,
 'PhysicalSizeX': None,
 'PhysicalSizeXUnit': None,
 'PhysicalSizeY': None,
 'PhysicalSizeYUnit': None,
 'PhysicalSizeZ': None,
 'PhysicalSizeZUnit': None,
 'Sizes BF': None,
 'DimOrder BF': None,
 'DimOrder BF Array': None,
 'ObjNA': [],
 'ObjMag': [],
 'ObjID': [],
 'ObjName': [],
 'ObjImmersion': [],
 'TubelensMag': [],
 'ObjNominalMag': [],
 'DetectorModel': [],
 'DetectorName': [],
 'DetectorID': [],
 'DetectorType': [],
 'InstrumentID': [],
 'MicroscopeType': [],
 'Channels': [],
 'ImageIDs': []}

1.12. Final Note#

I will keep

  1. Read

  2. stitch

  3. md_grouping

  • impy

  • napari.read

  • pycromanager

  • microscope

  • python-microscopy