Skip to content

Commit

Permalink
- bugfix: swap xy.
Browse files Browse the repository at this point in the history
  • Loading branch information
Wim Pomp committed Mar 18, 2024
1 parent 5dafc31 commit 110cb6d
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 48 deletions.
84 changes: 42 additions & 42 deletions ndbioimage/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -122,8 +122,8 @@ def __getitem__(self, n):
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):
Expand Down Expand Up @@ -225,8 +225,8 @@ def unique_yield(a, b):

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
Expand Down Expand Up @@ -266,7 +266,7 @@ def __getitem__(self, n):
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 = []
Expand All @@ -283,7 +283,7 @@ def __getitem__(self, n):
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

Expand All @@ -308,24 +308,24 @@ def __str__(self):

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)
if dtype is not None:
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):
""" frame-wise application of np.argmin and np.argmax """
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]
Expand All @@ -336,7 +336,7 @@ def __array_arg_fun__(self, fun, axis=None, out=None):
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
Expand All @@ -356,19 +356,19 @@ def __array_arg_fun__(self, fun, axis=None, out=None):
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:
Expand Down Expand Up @@ -401,8 +401,8 @@ def cfun(*res):
# 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)]
Expand Down Expand Up @@ -430,23 +430,23 @@ def cfun(*res):
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)])
out[out_idx] = (np.round(res) if out.dtype.kind in 'ui' else res).astype(p.sub('', dtype.name))
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],)
Expand Down Expand Up @@ -512,7 +512,7 @@ def shape(self, value):
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):
Expand Down Expand Up @@ -730,13 +730,13 @@ def astype(self, dtype, *args, **kwargs):
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):
Expand Down Expand Up @@ -906,7 +906,7 @@ def with_transform(self, channels=True, drift=False, file=None, bead_files=()):
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
Expand Down Expand Up @@ -944,7 +944,7 @@ def _can_open(path): # Override this method, and return true when the subclass

@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):
Expand Down Expand Up @@ -989,7 +989,7 @@ def __init__(self, path, dtype=None, axes=None):
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:
Expand Down Expand Up @@ -1053,12 +1053,12 @@ def __init__(self, path, dtype=None, axes=None):
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:
Expand Down
4 changes: 2 additions & 2 deletions ndbioimage/readers/cziread.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ def def_list(item):
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])
Expand All @@ -582,7 +582,7 @@ def __frame__(self, c=0, z=0, t=0):
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

Expand Down
2 changes: 1 addition & 1 deletion ndbioimage/readers/ndread.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def __frame__(self, c, z, t):
# 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
4 changes: 2 additions & 2 deletions ndbioimage/readers/tifread.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ def ome(self):

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
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down

0 comments on commit 110cb6d

Please sign in to comment.