- remove list of views from base

- fix frame_decorator in views
- use transforms and frame_decorators as cache keys
This commit is contained in:
Wim Pomp
2023-08-19 12:08:04 +02:00
parent 3dbed27078
commit cf7f2b6e1e
6 changed files with 18 additions and 47 deletions

1
.gitignore vendored
View File

@@ -8,3 +8,4 @@
/ndbioimage/_version.py
/ndbioimage/jars
/tests/files/*
/poetry.lock

View File

@@ -367,13 +367,12 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin):
raise ReaderNotFoundError(f'No reader found for {path}.')
def __init__(self, base=None, slice=None, shape=(0, 0, 0, 0, 0), dtype=None,
transform=False, drift=False, beadfile=None):
transform=False, drift=False, beadfile=None, frame_decorator=None):
self.base = base
self.slice = slice
self._shape = Shape(shape)
self.dtype = dtype
self.views = []
self._frame_decorator = None
self.frame_decorator = frame_decorator
self.transform = transform
self.drift = drift
@@ -397,7 +396,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin):
if k not in a:
yield k
for idx in unique_yield(list(self.cache.keys()),
for idx in unique_yield([key[:3] for key in self.cache.keys()],
product(range(self.shape['c']), range(self.shape['z']), range(self.shape['t']))):
xyczt = (slice(None), slice(None)) + idx
in_idx = tuple(xyczt['xyczt'.find(i)] for i in self.axes)
@@ -409,18 +408,10 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin):
return self
def __exit__(self, *args, **kwargs):
exception = None
for view in self.views:
try:
view.__exit__()
except Exception as e:
exception = e
self.views = []
if hasattr(self, 'close') and not self.isclosed:
self.close()
if not self.isclosed:
self.isclosed = True
if exception:
raise exception
if hasattr(self, 'close'):
self.close()
def __getitem__(self, n):
""" slice like a numpy array but return an Imread instance """
@@ -483,22 +474,11 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin):
self.__dict__.update(state)
if isinstance(self, AbstractReader):
self.open()
self.views = []
self.cache = DequeDict(16)
def __str__(self):
return str(self.path)
# TODO: this is causing problems when multiprocessing and doesn't work anyway
# def __del__(self):
# if not self.copies:
# if self.base is None:
# self.__exit__()
# else:
# self.base.views.remove(self)
def __array__(self, dtype=None):
block = self.block(*self.slice)
axes_idx = [self.shape.axes.find(i) for i in 'xyczt']
@@ -691,15 +671,6 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin):
return
return
@property
def frame_decorator(self):
return self._frame_decorator
@frame_decorator.setter
def frame_decorator(self, decorator):
self._frame_decorator = decorator
self.cache = DequeDict(self.cache.maxlen)
@property
def ndim(self):
return len(self.shape)
@@ -940,6 +911,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin):
@wraps(np.sum)
def sum(self, axis=None, dtype=None, out=None, keepdims=False, initial=None, where=True, **kwargs):
return self.__array_fun__([np.sum], axis, dtype, out, keepdims, [initial], where)
@wraps(np.swapaxes)
def swapaxes(self, axis1, axis2):
new = self.copy()
@@ -992,7 +964,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin):
""" returns 5D block of frames """
x, y, c, z, t = [np.arange(self.shape[i]) if e is None else np.array(e, ndmin=1)
for i, e in zip('xyczt', (x, y, c, z, t))]
d = np.full((len(x), len(y), len(c), len(z), len(t)), np.nan, self.dtype)
d = np.empty((len(x), len(y), len(c), len(z), len(t)), self.dtype)
for (ci, cj), (zi, zj), (ti, tj) in product(enumerate(c), enumerate(z), enumerate(t)):
d[:, :, ci, zi, ti] = self.frame(cj, zj, tj)[x][:, y]
return d
@@ -1013,7 +985,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin):
t %= self.base.shape['t']
# cache last n (default 16) frames in memory for speed (~250x faster)
key = (c, z, t, self.transform is None, self.frame_decorator is None)
key = (c, z, t, self.transform, self.frame_decorator)
if key in self.cache:
self.cache.move_to_end(key)
f = self.cache[key]
@@ -1170,8 +1142,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin):
class View(Imread):
def __init__(self, base, dtype=None, transform=None, drift=None, beadfile=None):
super().__init__(base.base, base.slice, base.shape, dtype or base.dtype, transform or base.transform,
drift or base.drift, beadfile or base.beadfile)
base.views.append(self)
drift or base.drift, beadfile or base.beadfile, base.frame_decorator)
self.set_transform()
def __getattr__(self, item):
@@ -1180,7 +1151,6 @@ class View(Imread):
return self.base.__getattribute__(item)
class AbstractReader(Imread, metaclass=ABCMeta):
""" class to read image files, while taking good care of important metadata,
currently optimized for .czi files, but can open anything that bioformats can handle

View File

@@ -52,8 +52,8 @@ class Reader(AbstractReader, ABC):
model.Image(
pixels=model.Pixels(
size_c=size_c, size_z=size_z, size_t=size_t, size_x=size_x, size_y=size_y,
dimension_order="XYCZT", type=pixel_type,
objective_settings=model.ObjectiveSettings(id="Objective:0"))))
dimension_order="XYCZT", type=pixel_type),
objective_settings=model.ObjectiveSettings(id="Objective:0")))
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))
return ome

View File

@@ -32,8 +32,8 @@ class Reader(AbstractReader, ABC):
model.Image(
pixels=model.Pixels(
size_c=size_c, size_z=size_z, size_t=size_t, size_x=size_x, size_y=size_y,
dimension_order="XYCZT", type=pixel_type,
objective_settings=model.ObjectiveSettings(id="Objective:0"))))
dimension_order="XYCZT", type=pixel_type),
objective_settings=model.ObjectiveSettings(id="Objective:0")))
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))
return ome

View File

@@ -107,7 +107,7 @@ class Reader(AbstractReader, ABC):
return ome
def open(self):
if re.match(r'(?:\d+\-)?Pos.*', self.path.name) is None:
if re.match(r'(?:\d+-)?Pos.*', self.path.name) is None:
path = self.path / f"Pos{self.series}"
else:
path = self.path

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "ndbioimage"
version = "2023.8.0"
version = "2023.8.1"
description = "Bio image reading, metadata and some affine registration."
authors = ["W. Pomp <w.pomp@nki.nl>"]
license = "GPLv3"