From cf7f2b6e1e05c702a028ed008fe997ed8d0d90fb Mon Sep 17 00:00:00 2001 From: Wim Pomp Date: Sat, 19 Aug 2023 12:08:04 +0200 Subject: [PATCH] - remove list of views from base - fix frame_decorator in views - use transforms and frame_decorators as cache keys --- .gitignore | 1 + ndbioimage/__init__.py | 52 +++++++--------------------------- ndbioimage/readers/fijiread.py | 4 +-- ndbioimage/readers/ndread.py | 4 +-- ndbioimage/readers/seqread.py | 2 +- pyproject.toml | 2 +- 6 files changed, 18 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index a903a4f..690a717 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ /ndbioimage/_version.py /ndbioimage/jars /tests/files/* +/poetry.lock diff --git a/ndbioimage/__init__.py b/ndbioimage/__init__.py index a8c3081..d736d2c 100755 --- a/ndbioimage/__init__.py +++ b/ndbioimage/__init__.py @@ -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() - self.isclosed = True - if exception: - raise exception + if not self.isclosed: + self.isclosed = True + 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 diff --git a/ndbioimage/readers/fijiread.py b/ndbioimage/readers/fijiread.py index 1a5d2e5..26083b0 100644 --- a/ndbioimage/readers/fijiread.py +++ b/ndbioimage/readers/fijiread.py @@ -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 diff --git a/ndbioimage/readers/ndread.py b/ndbioimage/readers/ndread.py index 5a826a0..cc2b303 100644 --- a/ndbioimage/readers/ndread.py +++ b/ndbioimage/readers/ndread.py @@ -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 diff --git a/ndbioimage/readers/seqread.py b/ndbioimage/readers/seqread.py index cebdf7e..bd50785 100644 --- a/ndbioimage/readers/seqread.py +++ b/ndbioimage/readers/seqread.py @@ -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 diff --git a/pyproject.toml b/pyproject.toml index d4063e7..884d916 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 "] license = "GPLv3"