- bugfix in czi metadata reader

- cziread now gives empty frame if the frame wasn't saved in the file
- astype accepts extra arguments, but does not use them
- improved jvm handling
- tifread dtype fix
This commit is contained in:
Wim Pomp
2023-09-04 10:26:10 +02:00
parent ef6116c6bc
commit 96ab3174d7
5 changed files with 62 additions and 41 deletions

View File

@@ -346,7 +346,6 @@ class Shape(tuple):
class Imread(np.lib.mixins.NDArrayOperatorsMixin): class Imread(np.lib.mixins.NDArrayOperatorsMixin):
def __new__(cls, path=None, *args, **kwargs): def __new__(cls, path=None, *args, **kwargs):
if cls is not Imread: if cls is not Imread:
return super().__new__(cls) return super().__new__(cls)
@@ -955,7 +954,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin):
def asarray(self): def asarray(self):
return self.__array__() return self.__array__()
def astype(self, dtype): def astype(self, dtype, *args, **kwargs):
new = self.copy() new = self.copy()
new.dtype = dtype new.dtype = dtype
return new return new

View File

@@ -18,29 +18,37 @@ try:
def __init__(self, jars=None): def __init__(self, jars=None):
if not self.vm_started and not self.vm_killed: if not self.vm_started and not self.vm_killed:
jarpath = Path(__file__).parent / 'jars' try:
if jars is None: jarpath = Path(__file__).parent / 'jars'
jars = {} if jars is None:
for jar, src in jars.items(): jars = {}
if not (jarpath / jar).exists(): for jar, src in jars.items():
JVM.download(src, jarpath / jar) if not (jarpath / jar).exists():
classpath = [str(jarpath / jar) for jar in jars.keys()] JVM.download(src, jarpath / jar)
classpath = [str(jarpath / jar) for jar in jars.keys()]
import jpype import jpype
jpype.startJVM(classpath=classpath) jpype.startJVM(classpath=classpath)
import jpype.imports except Exception:
from loci.common import DebugTools self.vm_started = False
from loci.formats import ImageReader else:
from loci.formats import ChannelSeparator self.vm_started = True
from loci.formats import FormatTools try:
from loci.formats import MetadataTools import jpype.imports
from loci.common import DebugTools
from loci.formats import ImageReader
from loci.formats import ChannelSeparator
from loci.formats import FormatTools
from loci.formats import MetadataTools
DebugTools.setRootLevel("ERROR") DebugTools.setRootLevel("ERROR")
self.vm_started = True
self.image_reader = ImageReader self.image_reader = ImageReader
self.channel_separator = ChannelSeparator self.channel_separator = ChannelSeparator
self.format_tools = FormatTools self.format_tools = FormatTools
self.metadata_tools = MetadataTools self.metadata_tools = MetadataTools
except Exception:
pass
if self.vm_killed: if self.vm_killed:
raise Exception('The JVM was killed before, and cannot be restarted in this Python process.') raise Exception('The JVM was killed before, and cannot be restarted in this Python process.')
@@ -51,8 +59,10 @@ try:
dest.parent.mkdir(exist_ok=True) dest.parent.mkdir(exist_ok=True)
dest.write_bytes(request.urlopen(src).read()) dest.write_bytes(request.urlopen(src).read())
def kill_vm(self): @classmethod
if self.vm_started and not self.vm_killed: def kill_vm(cls):
self = cls._instance
if self is not None and self.vm_started and not self.vm_killed:
import jpype import jpype
jpype.shutdownJVM() jpype.shutdownJVM()
self.vm_started = False self.vm_started = False

View File

@@ -58,6 +58,9 @@ class Reader(AbstractReader, ABC):
def text(item, default=""): def text(item, default=""):
return default if item is None else item.text return default if item is None else item.text
def def_list(item):
return [] if item is None else item
ome = model.OME() ome = model.OME()
metadata = tree.find("Metadata") metadata = tree.find("Metadata")
@@ -99,7 +102,7 @@ class Reader(AbstractReader, ABC):
model=tubelens.attrib["Name"], model=tubelens.attrib["Name"],
nominal_magnification=1.0)) # TODO: nominal_magnification nominal_magnification=1.0)) # TODO: nominal_magnification
for light_source in instrument.find("LightSources"): for light_source in def_list(instrument.find("LightSources")):
if light_source.find("LightSourceType").find("Laser") is not None: if light_source.find("LightSourceType").find("Laser") is not None:
ome.instruments[0].lasers.append( ome.instruments[0].lasers.append(
model.Laser( model.Laser(
@@ -222,6 +225,9 @@ class Reader(AbstractReader, ABC):
def text(item, default=""): def text(item, default=""):
return default if item is None else item.text return default if item is None else item.text
def def_list(item):
return [] if item is None else item
ome = model.OME() ome = model.OME()
metadata = tree.find("Metadata") metadata = tree.find("Metadata")
@@ -260,7 +266,7 @@ class Reader(AbstractReader, ABC):
lens_na=float(text(objective.find("LensNA"))), lens_na=float(text(objective.find("LensNA"))),
nominal_magnification=float(text(objective.find("NominalMagnification"))))) nominal_magnification=float(text(objective.find("NominalMagnification")))))
for light_source in instrument.find("LightSources"): for light_source in def_list(instrument.find("LightSources")):
if light_source.find("LightSourceType").find("Laser") is not None: if light_source.find("LightSourceType").find("Laser") is not None:
ome.instruments[0].lasers.append( ome.instruments[0].lasers.append(
model.Laser( model.Laser(
@@ -415,18 +421,19 @@ class Reader(AbstractReader, ABC):
def __frame__(self, c=0, z=0, t=0): def __frame__(self, c=0, z=0, t=0):
f = np.zeros(self.base.shape['xy'], self.dtype) f = np.zeros(self.base.shape['xy'], self.dtype)
directory_entries = self.filedict[c, z, t] if (c, z, t) in self.filedict:
x_min = min([f.start[f.axes.index('X')] for f in directory_entries]) directory_entries = self.filedict[c, z, t]
y_min = min([f.start[f.axes.index('Y')] for f in directory_entries]) x_min = min([f.start[f.axes.index('X')] for f in directory_entries])
xy_min = {'X': x_min, 'Y': y_min} y_min = min([f.start[f.axes.index('Y')] for f in directory_entries])
for directory_entry in directory_entries: xy_min = {'X': x_min, 'Y': y_min}
subblock = directory_entry.data_segment() for directory_entry in directory_entries:
tile = subblock.data(resize=True, order=0) subblock = directory_entry.data_segment()
axes_min = [xy_min.get(ax, 0) for ax in directory_entry.axes] tile = subblock.data(resize=True, order=0)
index = [slice(i - j - m, i - j + k) axes_min = [xy_min.get(ax, 0) for ax in directory_entry.axes]
for i, j, k, m in zip(directory_entry.start, self.reader.start, tile.shape, axes_min)] index = [slice(i - j - m, i - j + k)
index = tuple(index[self.reader.axes.index(i)] for i in 'XY') for i, j, k, m in zip(directory_entry.start, self.reader.start, tile.shape, axes_min)]
f[index] = tile.squeeze() index = tuple(index[self.reader.axes.index(i)] for i in 'XY')
f[index] = tile.squeeze()
return f return f
@staticmethod @staticmethod

View File

@@ -44,6 +44,11 @@ class Reader(AbstractReader, ABC):
else: else:
pxsize = None pxsize = None
dtype = page.dtype.name
if dtype not in ('int8', 'int16', 'int32', 'uint8', 'uint16', 'uint32',
'float', 'double', 'complex', 'double-complex', 'bit'):
dtype = 'float'
ome = model.OME() ome = model.OME()
ome.instruments.append(model.Instrument(id='Instrument:0')) ome.instruments.append(model.Instrument(id='Instrument:0'))
ome.instruments[0].objectives.append(model.Objective(id='Objective:0')) ome.instruments[0].objectives.append(model.Objective(id='Objective:0'))
@@ -53,7 +58,7 @@ class Reader(AbstractReader, ABC):
pixels=model.Pixels( pixels=model.Pixels(
id='Pixels:0', id='Pixels:0',
size_c=size_c, size_z=size_z, size_t=size_t, size_x=size_x, size_y=size_y, size_c=size_c, size_z=size_z, size_t=size_t, size_x=size_x, size_y=size_y,
dimension_order="XYCZT", type=page.dtype.name, physical_size_x=pxsize, physical_size_y=pxsize), dimension_order="XYCZT", type=dtype, physical_size_x=pxsize, physical_size_y=pxsize),
objective_settings=model.ObjectiveSettings(id="Objective:0"))) objective_settings=model.ObjectiveSettings(id="Objective:0")))
for c, z, t in product(range(size_c), range(size_z), range(size_t)): for c, z, t in product(range(size_c), range(size_z), range(size_t)):
ome.images[0].pixels.planes.append(model.Plane(the_c=c, the_z=z, the_t=t, delta_t=0)) ome.images[0].pixels.planes.append(model.Plane(the_c=c, the_z=z, the_t=t, delta_t=0))

View File

@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "ndbioimage" name = "ndbioimage"
version = "2023.8.2" version = "2023.9.0"
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"