- seqread: lazily read delta_t
- calculate timeinterval more efficiently - remove timeval field - bugfix in retrieving laser wavelenghts and powers - add series/pos to summary - cziread: better assign lightsources to channels
This commit is contained in:
@@ -17,12 +17,12 @@ from parfor import parfor
|
||||
from tiffwrite import IJTiffFile
|
||||
from numbers import Number
|
||||
from argparse import ArgumentParser
|
||||
from ndbioimage.transforms import Transform, Transforms
|
||||
from ndbioimage.jvm import JVM
|
||||
from typing import List
|
||||
from pathlib import Path
|
||||
from importlib.metadata import version
|
||||
from traceback import print_exc
|
||||
from ndbioimage.transforms import Transform, Transforms
|
||||
from ndbioimage.jvm import JVM
|
||||
|
||||
|
||||
try:
|
||||
@@ -535,8 +535,9 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, metaclass=ABCMeta):
|
||||
self.objective = find(instrument.objectives, id=self.ome.images[0].objective_settings.id)
|
||||
else:
|
||||
self.objective = None
|
||||
self.timeval = [find(image.pixels.planes, the_c=0, the_t=t, the_z=0).delta_t for t in range(self.shape['t'])]
|
||||
self.timeinterval = np.diff(self.timeval).mean() if len(self.timeval) > 1 else 0
|
||||
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
|
||||
self.timeinterval = (t1 - t0) / (self.shape['t'] - 1) if self.shape['t'] > 1 else None
|
||||
try:
|
||||
self.binning = [int(i) for i in image.pixels.channels[0].detector_settings.binning.value.split('x')]
|
||||
self.pxsize *= self.binning[0]
|
||||
@@ -562,9 +563,9 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, metaclass=ABCMeta):
|
||||
for channel in image.pixels.channels
|
||||
if channel.detector_settings
|
||||
and find(instrument.detectors, id=channel.detector_settings.id).amplification_gain]
|
||||
self.laserwavelengths = [(channel.emission_wavelength_quantity.to(self.ureg.nm).m,)
|
||||
for channel in pixels.channels if channel.emission_wavelength_quantity]
|
||||
self.laserpowers = try_default(lambda channel: [(1 - channel.light_source_settings.attenuation,)
|
||||
self.laserwavelengths = [(channel.excitation_wavelength_quantity.to(self.ureg.nm).m,)
|
||||
for channel in pixels.channels if channel.excitation_wavelength_quantity]
|
||||
self.laserpowers = try_default(lambda: [(1 - channel.light_source_settings.attenuation,)
|
||||
for channel in pixels.channels], [])
|
||||
self.filter = try_default(lambda: [find(instrument.filter_sets, id=channel.filter_set_ref.id).model
|
||||
for channel in image.pixels.channels], None)
|
||||
@@ -697,6 +698,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, metaclass=ABCMeta):
|
||||
def summary(self):
|
||||
""" gives a helpful summary of the recorded experiment """
|
||||
s = [f"path/filename: {self.path}",
|
||||
f"series/pos: {self.series}",
|
||||
f"reader: {self.__class__.__module__.split('.')[-1]}",
|
||||
f"shape ({self.axes}):".ljust(15) + f"{' x '.join(str(i) for i in self.shape)}"]
|
||||
if self.pxsize_um:
|
||||
|
||||
@@ -360,10 +360,12 @@ class Reader(Imread, ABC):
|
||||
|
||||
light_sources_settings = channel.find("LightSourcesSettings")
|
||||
# no space in ome for multiple lightsources simultaneously
|
||||
if len(light_sources_settings) > idx:
|
||||
light_source_settings = light_sources_settings[idx]
|
||||
else:
|
||||
light_source_settings = light_sources_settings[0]
|
||||
light_source_settings = model.LightSourceSettings(
|
||||
id="_".join([light_source_settings.find("LightSource").attrib["Id"]
|
||||
for light_source_settings in light_sources_settings]),
|
||||
id=light_source_settings.find("LightSource").attrib["Id"],
|
||||
attenuation=float(text(light_source_settings.find("Attenuation"))),
|
||||
wavelength=float(text(light_source_settings.find("Wavelength"))),
|
||||
wavelength_unit=nm)
|
||||
@@ -376,7 +378,7 @@ class Reader(Imread, ABC):
|
||||
color=model.simple_types.Color(text(channels_ds[channel.attrib["Id"]].find("Color"))),
|
||||
detector_settings=model.DetectorSettings(id=detector.attrib["Id"], binning=binning),
|
||||
emission_wavelength=text(channel.find("EmissionWavelength")),
|
||||
excitation_wavelength=text(channel.find("ExcitationWavelength")),
|
||||
excitation_wavelength=light_source_settings.wavelength,
|
||||
filter_set_ref=model.FilterSetRef(id=ome.instruments[0].filter_sets[filterset_idx].id),
|
||||
illumination_type=text(channel.find("IlluminationType")),
|
||||
light_source_settings=light_source_settings,
|
||||
|
||||
@@ -5,10 +5,35 @@ from ndbioimage import Imread
|
||||
from pathlib import Path
|
||||
from functools import cached_property
|
||||
from ome_types import model
|
||||
from ome_types._base_type import quantity_property
|
||||
from itertools import product
|
||||
from datetime import datetime
|
||||
from abc import ABC
|
||||
from parfor import pmap
|
||||
|
||||
|
||||
def lazy_property(function, field, *arg_fields):
|
||||
def lazy(self):
|
||||
if self.__dict__.get(field) is None:
|
||||
self.__dict__[field] = function(*[getattr(self, arg_field) for arg_field in arg_fields])
|
||||
self.__fields_set__.add(field)
|
||||
return self.__dict__[field]
|
||||
return property(lazy)
|
||||
|
||||
|
||||
class Plane(model.Plane):
|
||||
""" Lazily retrieve delta_t from metadata """
|
||||
def __init__(self, t0, file, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
setattr(self.__class__, 'delta_t', lazy_property(self.get_delta_t, 'delta_t', 't0', 'file'))
|
||||
setattr(self.__class__, 'delta_t_quantity', quantity_property('delta_t'))
|
||||
self.__dict__['t0'] = t0
|
||||
self.__dict__['file'] = file
|
||||
|
||||
@staticmethod
|
||||
def get_delta_t(t0, file):
|
||||
with tifffile.TiffFile(file) as tif:
|
||||
info = yaml.safe_load(tif.pages[0].tags[50839].value['Info'])
|
||||
return float((datetime.strptime(info["Time"], "%Y-%m-%d %H:%M:%S %z") - t0).seconds)
|
||||
|
||||
|
||||
class Reader(Imread, ABC):
|
||||
@@ -65,19 +90,10 @@ class Reader(Imread, ABC):
|
||||
physical_size_z=metadata["Info"]["Summary"]["z-step_um"]),
|
||||
objective_settings=model.ObjectiveSettings(id="Objective:0")))
|
||||
|
||||
def timeval_fun(i):
|
||||
with tifffile.TiffFile(self.filedict[i]) as tif:
|
||||
info = yaml.safe_load(tif.pages[0].tags[50839].value['Info'])
|
||||
return (datetime.strptime(info["Time"], "%Y-%m-%d %H:%M:%S %z") - t0).seconds
|
||||
|
||||
length = size_c * size_z * size_t
|
||||
timeval = pmap(timeval_fun, product(range(size_c), range(size_z), range(size_t)), length=length,
|
||||
serial=length <= 24, desc='Reading metadata')
|
||||
|
||||
for (c, z, t), time in zip(product(range(size_c), range(size_z), range(size_t)), timeval):
|
||||
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, exposure_time=metadata["Info"]["Exposure-ms"] / 1000, delta_t=time))
|
||||
Plane(t0, self.filedict[c, z, t],
|
||||
the_c=c, the_z=z, the_t=t, exposure_time=metadata["Info"]["Exposure-ms"] / 1000))
|
||||
|
||||
# compare channel names from metadata with filenames
|
||||
pattern_c = re.compile(r"img_\d{3,}_(.*)_\d{3,}$")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "ndbioimage"
|
||||
version = "2023.7.0"
|
||||
version = "2023.7.1"
|
||||
description = "Bio image reading, metadata and some affine registration."
|
||||
authors = ["W. Pomp <w.pomp@nki.nl>"]
|
||||
license = "GPLv3"
|
||||
|
||||
Reference in New Issue
Block a user