- bugfix: swap xy.

This commit is contained in:
Wim Pomp
2024-03-18 14:45:33 +01:00
parent 5dafc31559
commit 110cb6d9c1
5 changed files with 48 additions and 48 deletions

View File

@@ -106,7 +106,7 @@ def get_ome(path):
class Shape(tuple):
def __new__(cls, shape, axes='xyczt'):
def __new__(cls, shape, axes='yxczt'):
if isinstance(shape, Shape):
axes = shape.axes
instance = super().__new__(cls, shape)
@@ -122,8 +122,8 @@ class Shape(tuple):
return super().__getitem__(n)
@cached_property
def xyczt(self):
return tuple(self[i] for i in 'xyczt')
def yxczt(self):
return tuple(self[i] for i in 'yxczt')
class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
@@ -225,8 +225,8 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
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)
yxczt = (slice(None), slice(None)) + idx
in_idx = tuple(yxczt['yxczt'.find(i)] for i in self.axes)
if item in np.asarray(self[in_idx]):
return True
return False
@@ -266,7 +266,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
while len(n) < self.ndim:
n.append(None)
axes_idx = [self.shape.axes.find(i) for i in 'xyczt']
axes_idx = [self.shape.axes.find(i) for i in 'yxczt']
n = [n[j] if 0 <= j < len(n) else None for j in axes_idx] # reorder n
new_slice = []
@@ -283,7 +283,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
new = View(self)
new.slice = new_slice
new._shape = Shape([1 if isinstance(s, Number) else len(s) for s in new_slice])
new.axes = ''.join(j for j in self.axes if j in [i for i, s in zip('xyczt', new_slice)
new.axes = ''.join(j for j in self.axes if j in [i for i, s in zip('yxczt', new_slice)
if not isinstance(s, Number)])
return new
@@ -308,7 +308,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
def __array__(self, dtype=None):
block = self.block(*self.slice)
axes_idx = [self.shape.axes.find(i) for i in 'xyczt']
axes_idx = [self.shape.axes.find(i) for i in 'yxczt']
axes_squeeze = tuple({i for i, j in enumerate(axes_idx) if j == -1}.union(
{i for i, j in enumerate(self.slice) if isinstance(j, Number)}))
block = block.squeeze(axes_squeeze)
@@ -316,7 +316,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
block = block.astype(dtype)
if block.ndim == 0:
return block.item()
axes = ''.join(j for i, j in enumerate('xyczt') if i not in axes_squeeze)
axes = ''.join(j for i, j in enumerate('yxczt') if i not in axes_squeeze)
return block.transpose([axes.find(i) for i in self.shape.axes if i in axes])
def __array_arg_fun__(self, fun, axis=None, out=None):
@@ -324,8 +324,8 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
if axis is None:
value = arg = None
for idx in 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)
yxczt = (slice(None), slice(None)) + idx
in_idx = tuple(yxczt['yxczt'.find(i)] for i in self.axes)
new = np.asarray(self[in_idx])
new_arg = np.unravel_index(fun(new), new.shape)
new_value = new[new_arg]
@@ -336,7 +336,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
i = fun((value, new_value))
arg = (arg, new_arg + idx)[i]
value = (value, new_value)[i]
axes = ''.join(i for i in self.axes if i in 'xy') + 'czt'
axes = ''.join(i for i in self.axes if i in 'yx') + 'czt'
arg = np.ravel_multi_index([arg[axes.find(i)] for i in self.axes], self.shape)
if out is None:
return arg
@@ -356,19 +356,19 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
out_axes.pop(axis_idx)
if out is None:
out = np.zeros(out_shape, int)
if axis_str in 'xy':
if axis_str in 'yx':
for idx in product(range(self.shape['c']), range(self.shape['z']), range(self.shape['t'])):
xyczt = (slice(None), slice(None)) + idx
out_idx = tuple(xyczt['xyczt'.find(i)] for i in out_axes)
in_idx = tuple(xyczt['xyczt'.find(i)] for i in self.axes)
yxczt = (slice(None), slice(None)) + idx
out_idx = tuple(yxczt['yxczt'.find(i)] for i in out_axes)
in_idx = tuple(yxczt['yxczt'.find(i)] for i in self.axes)
new = self[in_idx]
out[out_idx] = fun(np.asarray(new), new.axes.find(axis_str))
else:
value = np.zeros(out.shape, self.dtype)
for idx in product(range(self.shape['c']), range(self.shape['z']), range(self.shape['t'])):
xyczt = (slice(None), slice(None)) + idx
out_idx = tuple(xyczt['xyczt'.find(i)] for i in out_axes)
in_idx = tuple(xyczt['xyczt'.find(i)] for i in self.axes)
yxczt = (slice(None), slice(None)) + idx
out_idx = tuple(yxczt['yxczt'.find(i)] for i in out_axes)
in_idx = tuple(yxczt['yxczt'.find(i)] for i in self.axes)
new_value = self[in_idx]
new_arg = np.full_like(new_value, idx['czt'.find(axis_str)])
if idx['czt'.find(axis_str)] == 0:
@@ -401,8 +401,8 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
# TODO: smarter transforms
if axis is None:
for idx in 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)
yxczt = (slice(None), slice(None)) + idx
in_idx = tuple(yxczt['yxczt'.find(i)] for i in self.axes)
w = where if where is None or isinstance(where, bool) else where[in_idx]
initials = [fun(np.asarray(ffun(self[in_idx])), initial=initial, where=w)
for fun, ffun, initial in zip(funs, ffuns, initials)]
@@ -430,13 +430,13 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
out_axes.pop(axis_idx)
if out is None:
out = np.zeros(out_shape, dtype)
if axis_str in 'xy':
xy = 'xy' if self.axes.find('x') < self.axes.find('y') else 'yx'
frame_ax = xy.find(axis_str)
if axis_str in 'yx':
yx = 'yx' if self.axes.find('x') > self.axes.find('y') else 'yx'
frame_ax = yx.find(axis_str)
for idx in product(range(self.shape['c']), range(self.shape['z']), range(self.shape['t'])):
xyczt = (slice(None), slice(None)) + idx
out_idx = tuple(xyczt['xyczt'.find(i)] for i in out_axes)
in_idx = tuple(xyczt['xyczt'.find(i)] for i in self.axes)
yxczt = (slice(None), slice(None)) + idx
out_idx = tuple(yxczt['yxczt'.find(i)] for i in out_axes)
in_idx = tuple(yxczt['yxczt'.find(i)] for i in self.axes)
w = where if where is None or isinstance(where, bool) else where[in_idx]
res = cfun(*[fun(ffun(self[in_idx]), frame_ax, initial=initial, where=w)
for fun, ffun, initial in zip(funs, ffuns, initials)])
@@ -444,9 +444,9 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
else:
tmps = [np.zeros(out_shape) for _ in ffuns]
for idx in product(range(self.shape['c']), range(self.shape['z']), range(self.shape['t'])):
xyczt = (slice(None), slice(None)) + idx
out_idx = tuple(xyczt['xyczt'.find(i)] for i in out_axes)
in_idx = tuple(xyczt['xyczt'.find(i)] for i in self.axes)
yxczt = (slice(None), slice(None)) + idx
out_idx = tuple(yxczt['yxczt'.find(i)] for i in out_axes)
in_idx = tuple(yxczt['yxczt'.find(i)] for i in self.axes)
if idx['czt'.find(axis_str)] == 0:
w = where if where is None or isinstance(where, bool) else (where[in_idx],)
@@ -512,7 +512,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
if isinstance(value, Shape):
self._shape = value
else:
self._shape = Shape((value['xyczt'.find(i.lower())] for i in self.axes), self.axes)
self._shape = Shape((value['yxczt'.find(i.lower())] for i in self.axes), self.axes)
@property
def summary(self):
@@ -730,13 +730,13 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
new.dtype = dtype
return new
def block(self, x=None, y=None, c=None, z=None, t=None):
def block(self, y=None, x=None, c=None, z=None, t=None):
""" 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.empty((len(x), len(y), len(c), len(z), len(t)), self.dtype)
y, x, c, z, t = (np.arange(self.shape[i]) if e is None else np.array(e, ndmin=1)
for i, e in zip('yxczt', (y, x, c, z, t)))
d = np.empty((len(y), len(x), 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]
d[:, :, ci, zi, ti] = self.frame(cj, zj, tj)[y][:, x]
return d
def copy(self):
@@ -906,7 +906,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
view.transform = Transforms.from_file(file, C=False)
except Exception: # noqa
view.transform = Transforms().with_drift(self)
view.transform.adapt(view.frameoffset, view.shape.xyczt, view.channel_names)
view.transform.adapt(view.frameoffset, view.shape.yxczt, view.channel_names)
return view
@staticmethod
@@ -944,7 +944,7 @@ class AbstractReader(Imread, metaclass=ABCMeta):
@abstractmethod
def __frame__(self, c, z, t): # Override this, return the frame at c, z, t
return np.random.randint(0, 255, self.shape['xy'])
return np.random.randint(0, 255, self.shape['yx'])
@cached_property
def ome(self):
@@ -989,7 +989,7 @@ class AbstractReader(Imread, metaclass=ABCMeta):
instrument = self.ome.instruments[0] if self.ome.instruments else None
image = self.ome.images[0]
pixels = image.pixels
self.shape = pixels.size_x, pixels.size_y, pixels.size_c, pixels.size_z, pixels.size_t
self.shape = pixels.size_y, pixels.size_x, pixels.size_c, pixels.size_z, pixels.size_t
self.dtype = pixels.type.value if dtype is None else dtype
self.pxsize = pixels.physical_size_x_quantity
try:
@@ -1053,12 +1053,12 @@ class AbstractReader(Imread, metaclass=ABCMeta):
self.exposuretime_s = [None if i is None else i.to(self.ureg.s).m for i in self.exposuretime]
if axes is None:
self.axes = ''.join(i for i in 'cztxy' if self.shape[i] > 1)
self.axes = ''.join(i for i in 'cztyx' if self.shape[i] > 1)
elif axes.lower() == 'full':
self.axes = 'cztxy'
self.axes = 'cztyx'
else:
self.axes = axes
self.slice = [np.arange(s, dtype=int) for s in self.shape.xyczt]
self.slice = [np.arange(s, dtype=int) for s in self.shape.yxczt]
m = self.extrametadata
if m is not None:

View File

@@ -570,7 +570,7 @@ class Reader(AbstractReader, ABC):
return ome
def __frame__(self, c=0, z=0, t=0):
f = np.zeros(self.base.shape['xy'], self.dtype)
f = np.zeros(self.base.shape['yx'], self.dtype)
if (c, z, t) in self.filedict:
directory_entries = self.filedict[c, z, t]
x_min = min([f.start[f.axes.index('X')] for f in directory_entries])
@@ -582,7 +582,7 @@ class Reader(AbstractReader, ABC):
axes_min = [xy_min.get(ax, 0) for ax in directory_entry.axes]
index = [slice(i - j - m, i - j + k)
for i, j, k, m in zip(directory_entry.start, self.reader.start, tile.shape, axes_min)]
index = tuple(index[self.reader.axes.index(i)] for i in 'XY')
index = tuple(index[self.reader.axes.index(i)] for i in 'YX')
f[index] = tile.squeeze()
return f

View File

@@ -52,7 +52,7 @@ class Reader(AbstractReader, ABC):
# in_idx = tuple(xyczt['xyczt'.find(i)] for i in self.axes)
# print(f'{in_idx = }')
frame = self.array[:, :, c, z, t]
if self.axes.find('y') < self.axes.find('x'):
if self.axes.find('y') > self.axes.find('x'):
return frame.T
else:
return frame

View File

@@ -30,8 +30,8 @@ class Reader(AbstractReader, ABC):
page = self.reader.pages[0]
self.p_ndim = page.ndim # noqa
size_x = page.imagelength
size_y = page.imagewidth
size_y = page.imagelength
size_x = page.imagewidth
if self.p_ndim == 3:
size_c = page.samplesperpixel
self.p_transpose = [i for i in [page.axes.find(j) for j in 'SYX'] if i >= 0] # noqa

View File

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