- catch 0 timeinterval
- better error handling in JVM
This commit is contained in:
@@ -24,7 +24,7 @@ from pint import set_application_registry
|
|||||||
from tiffwrite import IFD, IJTiffFile # noqa
|
from tiffwrite import IFD, IJTiffFile # noqa
|
||||||
from tqdm.auto import tqdm
|
from tqdm.auto import tqdm
|
||||||
|
|
||||||
from .jvm import JVM
|
from .jvm import JVM, JVMException
|
||||||
from .transforms import Transform, Transforms
|
from .transforms import Transform, Transforms
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -1134,12 +1134,13 @@ class AbstractReader(Imread, metaclass=ABCMeta):
|
|||||||
try:
|
try:
|
||||||
t0 = find(image.pixels.planes, the_c=0, the_t=0, the_z=0).delta_t
|
t0 = find(image.pixels.planes, the_c=0, the_t=0, the_z=0).delta_t
|
||||||
t1 = find(image.pixels.planes, the_c=0, the_t=self.shape['t'] - 1, the_z=0).delta_t
|
t1 = find(image.pixels.planes, the_c=0, the_t=self.shape['t'] - 1, the_z=0).delta_t
|
||||||
self.timeinterval = (t1 - t0) / (self.shape['t'] - 1) if self.shape['t'] > 1 else None
|
self.timeinterval = (t1 - t0) / (self.shape['t'] - 1) if self.shape['t'] > 1 and t1 > t0 else None
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.timeinterval = None
|
self.timeinterval = None
|
||||||
try:
|
try:
|
||||||
self.binning = [int(i) for i in image.pixels.channels[0].detector_settings.binning.value.split('x')]
|
self.binning = [int(i) for i in image.pixels.channels[0].detector_settings.binning.value.split('x')]
|
||||||
self.pxsize *= self.binning[0]
|
if self.pxsize is not None:
|
||||||
|
self.pxsize *= self.binning[0]
|
||||||
except (AttributeError, IndexError, ValueError):
|
except (AttributeError, IndexError, ValueError):
|
||||||
self.binning = None
|
self.binning = None
|
||||||
self.channel_names = [channel.name for channel in image.pixels.channels]
|
self.channel_names = [channel.name for channel in image.pixels.channels]
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib import request
|
from urllib import request
|
||||||
|
|
||||||
|
|
||||||
|
class JVMException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
class JVM:
|
class JVM:
|
||||||
""" There can be only one java virtual machine per python process,
|
""" There can be only one java virtual machine per python process,
|
||||||
|
|||||||
@@ -1,30 +1,34 @@
|
|||||||
import multiprocessing
|
import multiprocessing
|
||||||
from abc import ABC
|
from abc import ABC
|
||||||
from multiprocessing import queues
|
from multiprocessing import queues
|
||||||
from traceback import print_exc
|
from traceback import format_exc
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from .. import JVM, AbstractReader
|
from .. import AbstractReader, JVM, JVMException
|
||||||
|
|
||||||
jars = {'bioformats_package.jar':
|
jars = {'bioformats_package.jar': 'https://downloads.openmicroscopy.org/bio-formats/latest/artifacts/'
|
||||||
'https://downloads.openmicroscopy.org/bio-formats/latest/artifacts/bioformats_package.jar'}
|
'bioformats_package.jar'}
|
||||||
|
|
||||||
|
|
||||||
class JVMReader:
|
class JVMReader:
|
||||||
def __init__(self, path, series):
|
def __init__(self, path: Path, series: int) -> None:
|
||||||
mp = multiprocessing.get_context('spawn')
|
mp = multiprocessing.get_context('spawn')
|
||||||
self.path = path
|
self.path = path
|
||||||
self.series = series
|
self.series = series
|
||||||
self.queue_in = mp.Queue()
|
self.queue_in = mp.Queue()
|
||||||
self.queue_out = mp.Queue()
|
self.queue_out = mp.Queue()
|
||||||
self.queue_error = mp.Queue()
|
|
||||||
self.done = mp.Event()
|
self.done = mp.Event()
|
||||||
self.process = mp.Process(target=self.run)
|
self.process = mp.Process(target=self.run)
|
||||||
self.process.start()
|
self.process.start()
|
||||||
self.is_alive = True
|
status, message = self.queue_out.get()
|
||||||
|
if status == 'status' and message == 'started':
|
||||||
|
self.is_alive = True
|
||||||
|
else:
|
||||||
|
raise JVMException(message)
|
||||||
|
|
||||||
def close(self):
|
def close(self) -> None:
|
||||||
if self.is_alive:
|
if self.is_alive:
|
||||||
self.done.set()
|
self.done.set()
|
||||||
while not self.queue_in.empty():
|
while not self.queue_in.empty():
|
||||||
@@ -38,47 +42,53 @@ class JVMReader:
|
|||||||
self.process.close()
|
self.process.close()
|
||||||
self.is_alive = False
|
self.is_alive = False
|
||||||
|
|
||||||
def frame(self, c, z, t):
|
def frame(self, c: int, z: int, t: int) -> np.ndarray:
|
||||||
self.queue_in.put((c, z, t))
|
self.queue_in.put((c, z, t))
|
||||||
return self.queue_out.get()
|
status, message = self.queue_out.get()
|
||||||
|
if status == 'frame':
|
||||||
|
return message
|
||||||
|
else:
|
||||||
|
raise JVMException(message)
|
||||||
|
|
||||||
def run(self):
|
def run(self) -> None:
|
||||||
""" Read planes from the image reader file.
|
""" Read planes from the image reader file.
|
||||||
adapted from python-bioformats/bioformats/formatreader.py
|
adapted from python-bioformats/bioformats/formatreader.py
|
||||||
"""
|
"""
|
||||||
jvm = JVM(jars)
|
jvm = None
|
||||||
reader = jvm.image_reader()
|
|
||||||
ome_meta = jvm.metadata_tools.createOMEXMLMetadata()
|
|
||||||
reader.setMetadataStore(ome_meta)
|
|
||||||
reader.setId(str(self.path))
|
|
||||||
reader.setSeries(self.series)
|
|
||||||
|
|
||||||
open_bytes_func = reader.openBytes
|
|
||||||
width, height = int(reader.getSizeX()), int(reader.getSizeY())
|
|
||||||
|
|
||||||
pixel_type = reader.getPixelType()
|
|
||||||
little_endian = reader.isLittleEndian()
|
|
||||||
|
|
||||||
if pixel_type == jvm.format_tools.INT8:
|
|
||||||
dtype = np.int8
|
|
||||||
elif pixel_type == jvm.format_tools.UINT8:
|
|
||||||
dtype = np.uint8
|
|
||||||
elif pixel_type == jvm.format_tools.UINT16:
|
|
||||||
dtype = '<u2' if little_endian else '>u2'
|
|
||||||
elif pixel_type == jvm.format_tools.INT16:
|
|
||||||
dtype = '<i2' if little_endian else '>i2'
|
|
||||||
elif pixel_type == jvm.format_tools.UINT32:
|
|
||||||
dtype = '<u4' if little_endian else '>u4'
|
|
||||||
elif pixel_type == jvm.format_tools.INT32:
|
|
||||||
dtype = '<i4' if little_endian else '>i4'
|
|
||||||
elif pixel_type == jvm.format_tools.FLOAT:
|
|
||||||
dtype = '<f4' if little_endian else '>f4'
|
|
||||||
elif pixel_type == jvm.format_tools.DOUBLE:
|
|
||||||
dtype = '<f8' if little_endian else '>f8'
|
|
||||||
else:
|
|
||||||
dtype = None
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
jvm = JVM(jars)
|
||||||
|
reader = jvm.image_reader()
|
||||||
|
ome_meta = jvm.metadata_tools.createOMEXMLMetadata()
|
||||||
|
reader.setMetadataStore(ome_meta)
|
||||||
|
reader.setId(str(self.path))
|
||||||
|
reader.setSeries(self.series)
|
||||||
|
|
||||||
|
open_bytes_func = reader.openBytes
|
||||||
|
width, height = int(reader.getSizeX()), int(reader.getSizeY())
|
||||||
|
|
||||||
|
pixel_type = reader.getPixelType()
|
||||||
|
little_endian = reader.isLittleEndian()
|
||||||
|
|
||||||
|
if pixel_type == jvm.format_tools.INT8:
|
||||||
|
dtype = np.int8
|
||||||
|
elif pixel_type == jvm.format_tools.UINT8:
|
||||||
|
dtype = np.uint8
|
||||||
|
elif pixel_type == jvm.format_tools.UINT16:
|
||||||
|
dtype = '<u2' if little_endian else '>u2'
|
||||||
|
elif pixel_type == jvm.format_tools.INT16:
|
||||||
|
dtype = '<i2' if little_endian else '>i2'
|
||||||
|
elif pixel_type == jvm.format_tools.UINT32:
|
||||||
|
dtype = '<u4' if little_endian else '>u4'
|
||||||
|
elif pixel_type == jvm.format_tools.INT32:
|
||||||
|
dtype = '<i4' if little_endian else '>i4'
|
||||||
|
elif pixel_type == jvm.format_tools.FLOAT:
|
||||||
|
dtype = '<f4' if little_endian else '>f4'
|
||||||
|
elif pixel_type == jvm.format_tools.DOUBLE:
|
||||||
|
dtype = '<f8' if little_endian else '>f8'
|
||||||
|
else:
|
||||||
|
dtype = None
|
||||||
|
self.queue_out.put(('status', 'started'))
|
||||||
|
|
||||||
while not self.done.is_set():
|
while not self.done.is_set():
|
||||||
try:
|
try:
|
||||||
c, z, t = self.queue_in.get(True, 0.02)
|
c, z, t = self.queue_in.get(True, 0.02)
|
||||||
@@ -151,19 +161,19 @@ class JVMReader:
|
|||||||
image.shape = (height, width)
|
image.shape = (height, width)
|
||||||
|
|
||||||
if image.ndim == 3:
|
if image.ndim == 3:
|
||||||
self.queue_out.put(image[..., c])
|
self.queue_out.put(('frame', image[..., c]))
|
||||||
else:
|
else:
|
||||||
self.queue_out.put(image)
|
self.queue_out.put(('frame', image))
|
||||||
except queues.Empty: # noqa
|
except queues.Empty: # noqa
|
||||||
continue
|
continue
|
||||||
except (Exception,):
|
except (Exception,):
|
||||||
print_exc()
|
self.queue_out.put(('error', format_exc()))
|
||||||
self.queue_out.put(np.zeros((32, 32)))
|
|
||||||
finally:
|
finally:
|
||||||
jvm.kill_vm()
|
if jvm is not None:
|
||||||
|
jvm.kill_vm()
|
||||||
|
|
||||||
|
|
||||||
def can_open(path):
|
def can_open(path: Path) -> bool:
|
||||||
try:
|
try:
|
||||||
jvm = JVM(jars)
|
jvm = JVM(jars)
|
||||||
reader = jvm.image_reader()
|
reader = jvm.image_reader()
|
||||||
@@ -183,17 +193,16 @@ class Reader(AbstractReader, ABC):
|
|||||||
do_not_pickle = 'reader', 'key', 'jvm'
|
do_not_pickle = 'reader', 'key', 'jvm'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _can_open(path):
|
def _can_open(path: Path) -> bool:
|
||||||
""" Use java BioFormats to make an ome metadata structure. """
|
""" Use java BioFormats to make an ome metadata structure. """
|
||||||
with multiprocessing.get_context('spawn').Pool(1) as pool:
|
with multiprocessing.get_context('spawn').Pool(1) as pool:
|
||||||
ome = pool.map(can_open, (path,))[0]
|
return pool.map(can_open, (path,))[0]
|
||||||
return ome
|
|
||||||
|
|
||||||
def open(self):
|
def open(self) -> None:
|
||||||
self.reader = JVMReader(self.path, self.series)
|
self.reader = JVMReader(self.path, self.series)
|
||||||
|
|
||||||
def __frame__(self, c, z, t):
|
def __frame__(self, c: int, z: int, t: int) -> np.ndarray:
|
||||||
return self.reader.frame(c, z, t)
|
return self.reader.frame(c, z, t)
|
||||||
|
|
||||||
def close(self):
|
def close(self) -> None:
|
||||||
self.reader.close()
|
self.reader.close()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "ndbioimage"
|
name = "ndbioimage"
|
||||||
version = "2024.5.0"
|
version = "2024.5.1"
|
||||||
description = "Bio image reading, metadata and some affine registration."
|
description = "Bio image reading, metadata and some affine registration."
|
||||||
authors = ["W. Pomp <w.pomp@nki.nl>"]
|
authors = ["W. Pomp <w.pomp@nki.nl>"]
|
||||||
license = "GPLv3"
|
license = "GPLv3"
|
||||||
|
|||||||
Reference in New Issue
Block a user