- make cache size configurable
This commit is contained in:
@@ -68,8 +68,8 @@ with Imread('image_file.tif', axes='cztyx') as im:
|
|||||||
### Command line
|
### Command line
|
||||||
```ndbioimage --help```: show help
|
```ndbioimage --help```: show help
|
||||||
```ndbioimage image```: show metadata about image
|
```ndbioimage image```: show metadata about image
|
||||||
```ndbioimage image {name}.tif -r```: copy image into image.tif (replacing {name} with image), while registering channels
|
```ndbioimage image -w {name}.tif -r```: copy image into image.tif (replacing {name} with image), while registering channels
|
||||||
```ndbioimage image image.mp4 -C cyan lime red``` copy image into image.mp4 (z will be max projected), make channel colors cyan lime and red
|
```ndbioimage image -w image.mp4 -C cyan lime red``` copy image into image.mp4 (z will be max projected), make channel colors cyan lime and red
|
||||||
|
|
||||||
## Adding more formats
|
## Adding more formats
|
||||||
Readers for image formats subclass AbstractReader. When an image reader is imported, Imread will
|
Readers for image formats subclass AbstractReader. When an image reader is imported, Imread will
|
||||||
|
|||||||
@@ -65,18 +65,18 @@ class DequeDict(OrderedDict):
|
|||||||
self.maxlen = maxlen
|
self.maxlen = maxlen
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def __truncate__(self) -> None:
|
def __setitem__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
|
super().__setitem__(*args, **kwargs)
|
||||||
|
self.truncate()
|
||||||
|
|
||||||
|
def truncate(self) -> None:
|
||||||
if self.maxlen is not None:
|
if self.maxlen is not None:
|
||||||
while len(self) > self.maxlen:
|
while len(self) > self.maxlen:
|
||||||
self.popitem(False)
|
self.popitem(False)
|
||||||
|
|
||||||
def __setitem__(self, *args: Any, **kwargs: Any) -> None:
|
|
||||||
super().__setitem__(*args, **kwargs)
|
|
||||||
self.__truncate__()
|
|
||||||
|
|
||||||
def update(self, *args: Any, **kwargs: Any) -> None:
|
def update(self, *args: Any, **kwargs: Any) -> None:
|
||||||
super().update(*args, **kwargs)
|
super().update(*args, **kwargs) # type: ignore
|
||||||
self.__truncate__()
|
self.truncate()
|
||||||
|
|
||||||
|
|
||||||
def find(obj: Sequence[Any], **kwargs: Any) -> Any:
|
def find(obj: Sequence[Any], **kwargs: Any) -> Any:
|
||||||
@@ -249,6 +249,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
tirfangle: Optional[list[float]]
|
tirfangle: Optional[list[float]]
|
||||||
gain: Optional[list[float]]
|
gain: Optional[list[float]]
|
||||||
pcf: Optional[list[float]]
|
pcf: Optional[list[float]]
|
||||||
|
path: Path
|
||||||
__frame__: Callable[[int, int, int], np.ndarray]
|
__frame__: Callable[[int, int, int], np.ndarray]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -331,8 +332,9 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
if hasattr(self, 'close'):
|
if hasattr(self, 'close'):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def __getitem__(self, n: int | Sequence[int] | slice | type(Ellipsis) |
|
def __getitem__(self, n: int | Sequence[int] | Sequence[slice] | slice | type(Ellipsis) |
|
||||||
dict[str, int | Sequence[int] | slice | type(Ellipsis)]) -> Number | Imread | np.ndarray:
|
dict[str, int | Sequence[int] | Sequence[slice] | slice | type(Ellipsis)]
|
||||||
|
) -> Number | Imread | np.ndarray:
|
||||||
""" slice like a numpy array but return an Imread instance """
|
""" slice like a numpy array but return an Imread instance """
|
||||||
if self.isclosed:
|
if self.isclosed:
|
||||||
raise OSError('file is closed')
|
raise OSError('file is closed')
|
||||||
@@ -380,7 +382,8 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
return new
|
return new
|
||||||
|
|
||||||
def __getstate__(self) -> dict[str: Any]:
|
def __getstate__(self) -> dict[str: Any]:
|
||||||
return {key: value for key, value in self.__dict__.items() if key not in self.do_not_pickle}
|
return ({key: value for key, value in self.__dict__.items() if key not in self.do_not_pickle} |
|
||||||
|
{'cache_size': self.cache.maxlen})
|
||||||
|
|
||||||
def __len__(self) -> int:
|
def __len__(self) -> int:
|
||||||
return self.shape[0]
|
return self.shape[0]
|
||||||
@@ -390,10 +393,10 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
|
|
||||||
def __setstate__(self, state: dict[str, Any]) -> None:
|
def __setstate__(self, state: dict[str, Any]) -> None:
|
||||||
""" What happens during unpickling """
|
""" What happens during unpickling """
|
||||||
self.__dict__.update(state)
|
self.__dict__.update({key: value for key, value in state.items() if key != 'cache_size'})
|
||||||
if isinstance(self, AbstractReader):
|
if isinstance(self, AbstractReader):
|
||||||
self.open()
|
self.open()
|
||||||
self.cache = DequeDict(16)
|
self.cache = DequeDict(state.get('cache_size', 16))
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return str(self.path)
|
return str(self.path)
|
||||||
@@ -509,7 +512,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
yxczt = (slice(None), slice(None)) + idx
|
yxczt = (slice(None), slice(None)) + idx
|
||||||
in_idx = tuple(yxczt['yxczt'.find(i)] for i in self.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]
|
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)
|
initials = [fun(np.asarray(ffun(self[in_idx])), initial=initial, where=w) # type: ignore
|
||||||
for fun, ffun, initial in zip(funs, ffuns, initials)]
|
for fun, ffun, initial in zip(funs, ffuns, initials)]
|
||||||
res = cfun(*initials)
|
res = cfun(*initials)
|
||||||
res = (np.round(res) if dtype.kind in 'ui' else res).astype(p.sub('', dtype.name))
|
res = (np.round(res) if dtype.kind in 'ui' else res).astype(p.sub('', dtype.name))
|
||||||
@@ -543,7 +546,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
out_idx = tuple(yxczt['yxczt'.find(i)] for i in out_axes)
|
out_idx = tuple(yxczt['yxczt'.find(i)] for i in out_axes)
|
||||||
in_idx = tuple(yxczt['yxczt'.find(i)] for i in self.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]
|
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)
|
res = cfun(*[fun(ffun(self[in_idx]), frame_ax, initial=initial, where=w) # type: ignore
|
||||||
for fun, ffun, initial in zip(funs, ffuns, initials)])
|
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))
|
out[out_idx] = (np.round(res) if out.dtype.kind in 'ui' else res).astype(p.sub('', dtype.name))
|
||||||
else:
|
else:
|
||||||
@@ -556,12 +559,12 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
if idx['czt'.find(axis_str)] == 0:
|
if idx['czt'.find(axis_str)] == 0:
|
||||||
w = where if where is None or isinstance(where, bool) else (where[in_idx],)
|
w = where if where is None or isinstance(where, bool) else (where[in_idx],)
|
||||||
for tmp, fun, ffun, initial in zip(tmps, funs, ffuns, initials):
|
for tmp, fun, ffun, initial in zip(tmps, funs, ffuns, initials):
|
||||||
tmp[out_idx] = fun((ffun(self[in_idx]),), 0, initial=initial, where=w)
|
tmp[out_idx] = fun((ffun(self[in_idx]),), 0, initial=initial, where=w) # type: ignore
|
||||||
else:
|
else:
|
||||||
w = where if where is None or isinstance(where, bool) else \
|
w = where if where is None or isinstance(where, bool) else \
|
||||||
(np.ones_like(where[in_idx]), where[in_idx])
|
(np.ones_like(where[in_idx]), where[in_idx])
|
||||||
for tmp, fun, ffun in zip(tmps, funs, ffuns):
|
for tmp, fun, ffun in zip(tmps, funs, ffuns):
|
||||||
tmp[out_idx] = fun((tmp[out_idx], ffun(self[in_idx])), 0, where=w)
|
tmp[out_idx] = fun((tmp[out_idx], ffun(self[in_idx])), 0, where=w) # type: ignore
|
||||||
out[...] = (np.round(cfun(*tmps)) if out.dtype.kind in 'ui' else
|
out[...] = (np.round(cfun(*tmps)) if out.dtype.kind in 'ui' else
|
||||||
cfun(*tmps)).astype(p.sub('', dtype.name))
|
cfun(*tmps)).astype(p.sub('', dtype.name))
|
||||||
return out
|
return out
|
||||||
@@ -606,7 +609,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self) -> int:
|
def size(self) -> int:
|
||||||
return np.prod(self.shape)
|
return np.prod(self.shape) # type: ignore
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def shape(self) -> Shape:
|
def shape(self) -> Shape:
|
||||||
@@ -665,7 +668,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def T(self) -> Imread: # noqa
|
def T(self) -> Imread: # noqa
|
||||||
return self.transpose()
|
return self.transpose() # type: ignore
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def timeseries(self) -> bool:
|
def timeseries(self) -> bool:
|
||||||
@@ -782,7 +785,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
|
|
||||||
@wraps(np.ndarray.std)
|
@wraps(np.ndarray.std)
|
||||||
def std(self, axis=None, dtype=None, out=None, ddof=0, keepdims=None, *, where=True):
|
def std(self, axis=None, dtype=None, out=None, ddof=0, keepdims=None, *, where=True):
|
||||||
return self.var(axis, dtype, out, ddof, keepdims, where=where, std=True)
|
return self.var(axis, dtype, out, ddof, keepdims, where=where, std=True) # type: ignore
|
||||||
|
|
||||||
@wraps(np.ndarray.sum)
|
@wraps(np.ndarray.sum)
|
||||||
def sum(self, axis=None, dtype=None, out=None, keepdims=False, initial=None, where=True, **_):
|
def sum(self, axis=None, dtype=None, out=None, keepdims=False, initial=None, where=True, **_):
|
||||||
@@ -845,7 +848,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
for i, e in zip('yxczt', (y, x, c, z, t)))
|
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)
|
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)):
|
for (ci, cj), (zi, zj), (ti, tj) in product(enumerate(c), enumerate(z), enumerate(t)):
|
||||||
d[:, :, ci, zi, ti] = self.frame(cj, zj, tj)[y][:, x]
|
d[:, :, ci, zi, ti] = self.frame(cj, zj, tj)[y][:, x] # type: ignore
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def copy(self) -> View:
|
def copy(self) -> View:
|
||||||
@@ -865,14 +868,15 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
|
|
||||||
# cache last n (default 16) frames in memory for speed (~250x faster)
|
# cache last n (default 16) frames in memory for speed (~250x faster)
|
||||||
key = (c, z, t, self.transform, self.frame_decorator)
|
key = (c, z, t, self.transform, self.frame_decorator)
|
||||||
if key in self.cache:
|
if self.cache.maxlen and key in self.cache:
|
||||||
self.cache.move_to_end(key)
|
self.cache.move_to_end(key)
|
||||||
f = self.cache[key]
|
f = self.cache[key]
|
||||||
else:
|
else:
|
||||||
f = self.transform[self.channel_names[c], t].frame(self.__frame__(c, z, t))
|
f = self.transform[self.channel_names[c], t].frame(self.__frame__(c, z, t))
|
||||||
if self.frame_decorator is not None:
|
if self.frame_decorator is not None:
|
||||||
f = self.frame_decorator(self, f, c, z, t)
|
f = self.frame_decorator(self, f, c, z, t)
|
||||||
self.cache[key] = f
|
if self.cache.maxlen:
|
||||||
|
self.cache[key] = f
|
||||||
if self.dtype is not None:
|
if self.dtype is not None:
|
||||||
return f.copy().astype(self.dtype)
|
return f.copy().astype(self.dtype)
|
||||||
else:
|
else:
|
||||||
@@ -942,7 +946,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
for plane in image.pixels.planes if plane.the_c == 0 and plane.the_t == 0])
|
for plane in image.pixels.planes if plane.the_c == 0 and plane.the_t == 0])
|
||||||
i = np.argsort(z[:, 1])
|
i = np.argsort(z[:, 1])
|
||||||
image.pixels.physical_size_z = np.nanmean(np.true_divide(*np.diff(z[i], axis=0).T)) * 1e6
|
image.pixels.physical_size_z = np.nanmean(np.true_divide(*np.diff(z[i], axis=0).T)) * 1e6
|
||||||
image.pixels.physical_size_z_unit = 'µm'
|
image.pixels.physical_size_z_unit = 'µm' # type: ignore
|
||||||
except Exception: # noqa
|
except Exception: # noqa
|
||||||
pass
|
pass
|
||||||
return ome
|
return ome
|
||||||
@@ -1015,7 +1019,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
frame = np.dstack([255 * frame * i for i in color])
|
frame = np.dstack([255 * frame * i for i in color])
|
||||||
return np.clip(np.round(frame), 0, 255).astype('uint8')
|
return np.clip(np.round(frame), 0, 255).astype('uint8')
|
||||||
|
|
||||||
ab = list(zip(*[get_ab(i) for i in self.transpose('cztyx')]))
|
ab = list(zip(*[get_ab(i) for i in self.transpose('cztyx')])) # type: ignore
|
||||||
colors = colors or ('r', 'g', 'b')[:self.shape['c']] + max(0, self.shape['c'] - 3) * ('w',)
|
colors = colors or ('r', 'g', 'b')[:self.shape['c']] + max(0, self.shape['c'] - 3) * ('w',)
|
||||||
brightnesses = brightnesses or (1,) * self.shape['c']
|
brightnesses = brightnesses or (1,) * self.shape['c']
|
||||||
scale = scale or 1
|
scale = scale or 1
|
||||||
@@ -1027,7 +1031,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
outputdict={'-vcodec': 'libx264', '-preset': 'veryslow', '-pix_fmt': 'yuv420p', '-r': '7',
|
outputdict={'-vcodec': 'libx264', '-preset': 'veryslow', '-pix_fmt': 'yuv420p', '-r': '7',
|
||||||
'-vf': f'setpts={25 / 7}*PTS,scale={shape_x}:{shape_y}:flags=neighbor'}
|
'-vf': f'setpts={25 / 7}*PTS,scale={shape_x}:{shape_y}:flags=neighbor'}
|
||||||
) as movie:
|
) as movie:
|
||||||
im = self.transpose('tzcyx')
|
im = self.transpose('tzcyx') # type: ignore
|
||||||
for ti in tqdm(t, desc='Saving movie', disable=not bar):
|
for ti in tqdm(t, desc='Saving movie', disable=not bar):
|
||||||
movie.writeFrame(np.max([cframe(yx, c, a, b / s, scale)
|
movie.writeFrame(np.max([cframe(yx, c, a, b / s, scale)
|
||||||
for yx, a, b, c, s in zip(im[ti].max('z'), *ab, colors, brightnesses)], 0))
|
for yx, a, b, c, s in zip(im[ti].max('z'), *ab, colors, brightnesses)], 0))
|
||||||
@@ -1061,7 +1065,7 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
n[i] = (n[i],)
|
n[i] = (n[i],)
|
||||||
|
|
||||||
shape = [len(i) for i in n]
|
shape = [len(i) for i in n]
|
||||||
with TransformTiff(self, fname.with_suffix('.tif'), pixel_type,
|
with TransformTiff(self, fname.with_suffix('.tif'), dtype=pixel_type,
|
||||||
pxsize=self.pxsize_um, deltaz=self.deltaz_um, **kwargs) as tif:
|
pxsize=self.pxsize_um, deltaz=self.deltaz_um, **kwargs) as tif:
|
||||||
for i, m in tqdm(zip(product(*[range(s) for s in shape]), product(*n)), # noqa
|
for i, m in tqdm(zip(product(*[range(s) for s in shape]), product(*n)), # noqa
|
||||||
total=np.prod(shape), desc='Saving tiff', disable=not bar):
|
total=np.prod(shape), desc='Saving tiff', disable=not bar):
|
||||||
@@ -1106,6 +1110,11 @@ class Imread(np.lib.mixins.NDArrayOperatorsMixin, ABC):
|
|||||||
view.transform.adapt(view.frameoffset, view.shape.yxczt, view.channel_names)
|
view.transform.adapt(view.frameoffset, view.shape.yxczt, view.channel_names)
|
||||||
return view
|
return view
|
||||||
|
|
||||||
|
def set_cache_size(self, cache_size: int) -> None:
|
||||||
|
assert isinstance(cache_size, int) and cache_size >= 0
|
||||||
|
self.cache.maxlen = cache_size
|
||||||
|
self.cache.truncate()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def split_path_series(path: Path | str) -> tuple[Path, int]:
|
def split_path_series(path: Path | str) -> tuple[Path, int]:
|
||||||
if isinstance(path, str):
|
if isinstance(path, str):
|
||||||
@@ -1320,12 +1329,13 @@ def main() -> None:
|
|||||||
parser = ArgumentParser(description='Display info and save as tif')
|
parser = ArgumentParser(description='Display info and save as tif')
|
||||||
parser.add_argument('-v', '--version', action='version', version=__version__)
|
parser.add_argument('-v', '--version', action='version', version=__version__)
|
||||||
parser.add_argument('file', help='image_file', type=str, nargs='*')
|
parser.add_argument('file', help='image_file', type=str, nargs='*')
|
||||||
parser.add_argument('-w', '--write', help='path to tif/movie out, {folder}, {name} and {ext} take this from file in', type=str, default=None)
|
parser.add_argument('-w', '--write', help='path to tif/movie out, {folder}, {name} and {ext} take this from file in',
|
||||||
|
type=str, default=None)
|
||||||
parser.add_argument('-o', '--extract_ome', help='extract ome to xml file', action='store_true')
|
parser.add_argument('-o', '--extract_ome', help='extract ome to xml file', action='store_true')
|
||||||
parser.add_argument('-r', '--register', help='register channels', action='store_true')
|
parser.add_argument('-r', '--register', help='register channels', action='store_true')
|
||||||
parser.add_argument('-c', '--channel', help='channel', type=int, default=None)
|
parser.add_argument('-c', '--channel', help='channel', type=int, default=None)
|
||||||
parser.add_argument('-z', '--zslice', help='z-slice', type=int, default=None)
|
parser.add_argument('-z', '--zslice', help='z-slice', type=int, default=None)
|
||||||
parser.add_argument('-t', '--time', help='time', type=str, default=None)
|
parser.add_argument('-t', '--time', help='time (frames) in python slicing notation', type=str, default=None)
|
||||||
parser.add_argument('-s', '--split', help='split channels', action='store_true')
|
parser.add_argument('-s', '--split', help='split channels', action='store_true')
|
||||||
parser.add_argument('-f', '--force', help='force overwrite', action='store_true')
|
parser.add_argument('-f', '--force', help='force overwrite', action='store_true')
|
||||||
parser.add_argument('-C', '--movie-colors', help='colors for channels in movie', type=str, nargs='*')
|
parser.add_argument('-C', '--movie-colors', help='colors for channels in movie', type=str, nargs='*')
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ class OmeParse:
|
|||||||
model.Objective(
|
model.Objective(
|
||||||
id=objective.attrib['Id'],
|
id=objective.attrib['Id'],
|
||||||
model=self.text(objective.find('Manufacturer').find('Model')),
|
model=self.text(objective.find('Manufacturer').find('Model')),
|
||||||
immersion=self.text(objective.find('Immersion')),
|
immersion=self.text(objective.find('Immersion')), # type: ignore
|
||||||
lens_na=float(self.text(objective.find('LensNA'))),
|
lens_na=float(self.text(objective.find('LensNA'))),
|
||||||
nominal_magnification=float(self.text(objective.find('NominalMagnification')))))
|
nominal_magnification=float(self.text(objective.find('NominalMagnification')))))
|
||||||
|
|
||||||
@@ -410,14 +410,14 @@ class OmeParse:
|
|||||||
pixels=model.Pixels(
|
pixels=model.Pixels(
|
||||||
id='Pixels:0', size_x=self.size_x, size_y=self.size_y,
|
id='Pixels:0', size_x=self.size_x, size_y=self.size_y,
|
||||||
size_c=self.size_c, size_z=self.size_z, size_t=self.size_t,
|
size_c=self.size_c, size_z=self.size_z, size_t=self.size_t,
|
||||||
dimension_order='XYCZT', type=pixel_type,
|
dimension_order='XYCZT', type=pixel_type, # type: ignore
|
||||||
significant_bits=int(self.text(image.find('ComponentBitCount'))),
|
significant_bits=int(self.text(image.find('ComponentBitCount'))),
|
||||||
big_endian=False, interleaved=False, metadata_only=True),
|
big_endian=False, interleaved=False, metadata_only=True), # type: ignore
|
||||||
experimenter_ref=model.ExperimenterRef(id='Experimenter:0'),
|
experimenter_ref=model.ExperimenterRef(id='Experimenter:0'),
|
||||||
instrument_ref=model.InstrumentRef(id='Instrument:0'),
|
instrument_ref=model.InstrumentRef(id='Instrument:0'),
|
||||||
objective_settings=model.ObjectiveSettings(
|
objective_settings=model.ObjectiveSettings(
|
||||||
id=objective_settings.find('ObjectiveRef').attrib['Id'],
|
id=objective_settings.find('ObjectiveRef').attrib['Id'],
|
||||||
medium=self.text(objective_settings.find('Medium')),
|
medium=self.text(objective_settings.find('Medium')), # type: ignore
|
||||||
refractive_index=float(self.text(objective_settings.find('RefractiveIndex')))),
|
refractive_index=float(self.text(objective_settings.find('RefractiveIndex')))),
|
||||||
stage_label=model.StageLabel(
|
stage_label=model.StageLabel(
|
||||||
name=f'Scene position #0',
|
name=f'Scene position #0',
|
||||||
@@ -492,13 +492,13 @@ class OmeParse:
|
|||||||
model.Channel(
|
model.Channel(
|
||||||
id=f'Channel:{idx}',
|
id=f'Channel:{idx}',
|
||||||
name=channel.attrib['Name'],
|
name=channel.attrib['Name'],
|
||||||
acquisition_mode=self.text(channel.find('AcquisitionMode')),
|
acquisition_mode=self.text(channel.find('AcquisitionMode')), # type: ignore
|
||||||
color=model.Color(self.text(self.channels_ds[channel.attrib['Id']].find('Color'), 'white')),
|
color=model.Color(self.text(self.channels_ds[channel.attrib['Id']].find('Color'), 'white')),
|
||||||
detector_settings=model.DetectorSettings(id=detector.attrib['Id'], binning=binning),
|
detector_settings=model.DetectorSettings(id=detector.attrib['Id'], binning=binning),
|
||||||
# emission_wavelength=text(channel.find('EmissionWavelength')), # TODO: fix
|
# emission_wavelength=text(channel.find('EmissionWavelength')), # TODO: fix
|
||||||
excitation_wavelength=light_source_settings.wavelength,
|
excitation_wavelength=light_source_settings.wavelength,
|
||||||
filter_set_ref=model.FilterSetRef(id=self.ome.instruments[0].filter_sets[filterset_idx].id),
|
filter_set_ref=model.FilterSetRef(id=self.ome.instruments[0].filter_sets[filterset_idx].id),
|
||||||
illumination_type=self.text(channel.find('IlluminationType')),
|
illumination_type=self.text(channel.find('IlluminationType')), # type: ignore
|
||||||
light_source_settings=light_source_settings,
|
light_source_settings=light_source_settings,
|
||||||
samples_per_pixel=int(self.text(laser_scan_info.find('Averaging')))))
|
samples_per_pixel=int(self.text(laser_scan_info.find('Averaging')))))
|
||||||
elif self.version in ('1.1', '1.2'):
|
elif self.version in ('1.1', '1.2'):
|
||||||
@@ -543,7 +543,7 @@ class OmeParse:
|
|||||||
model.Channel(
|
model.Channel(
|
||||||
id=f'Channel:{idx}',
|
id=f'Channel:{idx}',
|
||||||
name=channel.attrib['Name'],
|
name=channel.attrib['Name'],
|
||||||
acquisition_mode=self.text(channel.find('AcquisitionMode')).replace(
|
acquisition_mode=self.text(channel.find('AcquisitionMode')).replace( # type: ignore
|
||||||
'SingleMoleculeLocalisation', 'SingleMoleculeImaging'),
|
'SingleMoleculeLocalisation', 'SingleMoleculeImaging'),
|
||||||
color=color,
|
color=color,
|
||||||
detector_settings=model.DetectorSettings(
|
detector_settings=model.DetectorSettings(
|
||||||
@@ -553,7 +553,7 @@ class OmeParse:
|
|||||||
excitation_wavelength=self.try_default(float, None,
|
excitation_wavelength=self.try_default(float, None,
|
||||||
self.text(channel.find('ExcitationWavelength'))),
|
self.text(channel.find('ExcitationWavelength'))),
|
||||||
# filter_set_ref=model.FilterSetRef(id=ome.instruments[0].filter_sets[filterset_idx].id),
|
# filter_set_ref=model.FilterSetRef(id=ome.instruments[0].filter_sets[filterset_idx].id),
|
||||||
illumination_type=self.text(channel.find('IlluminationType')),
|
illumination_type=self.text(channel.find('IlluminationType')), # type: ignore
|
||||||
light_source_settings=light_source_settings,
|
light_source_settings=light_source_settings,
|
||||||
samples_per_pixel=samples_per_pixel))
|
samples_per_pixel=samples_per_pixel))
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,8 @@ class Reader(AbstractReader, ABC):
|
|||||||
pixels=model.Pixels(
|
pixels=model.Pixels(
|
||||||
size_c=size_c, size_z=size_z, size_t=size_t,
|
size_c=size_c, size_z=size_z, size_t=size_t,
|
||||||
size_x=metadata['Info']['Width'], size_y=metadata['Info']['Height'],
|
size_x=metadata['Info']['Width'], size_y=metadata['Info']['Height'],
|
||||||
dimension_order='XYCZT', type=pixel_type, physical_size_x=pxsize, physical_size_y=pxsize,
|
dimension_order='XYCZT', # type: ignore
|
||||||
|
type=pixel_type, physical_size_x=pxsize, physical_size_y=pxsize,
|
||||||
physical_size_z=metadata['Info']['Summary']['z-step_um']),
|
physical_size_z=metadata['Info']['Summary']['z-step_um']),
|
||||||
objective_settings=model.ObjectiveSettings(id='Objective:0')))
|
objective_settings=model.ObjectiveSettings(id='Objective:0')))
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ class Reader(AbstractReader, ABC):
|
|||||||
pixels=model.Pixels(
|
pixels=model.Pixels(
|
||||||
id='Pixels:0',
|
id='Pixels:0',
|
||||||
size_c=size_c, size_z=size_z, size_t=size_t, size_x=size_x, size_y=size_y,
|
size_c=size_c, size_z=size_z, size_t=size_t, size_x=size_x, size_y=size_y,
|
||||||
dimension_order='XYCZT', type=dtype, physical_size_x=pxsize, physical_size_y=pxsize),
|
dimension_order='XYCZT', type=dtype, # type: ignore
|
||||||
|
physical_size_x=pxsize, physical_size_y=pxsize),
|
||||||
objective_settings=model.ObjectiveSettings(id='Objective:0')))
|
objective_settings=model.ObjectiveSettings(id='Objective:0')))
|
||||||
for c, z, t in product(range(size_c), range(size_z), range(size_t)):
|
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=interval_t * t))
|
ome.images[0].pixels.planes.append(model.Plane(the_c=c, the_z=z, the_t=t, delta_t=interval_t * t))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "ndbioimage"
|
name = "ndbioimage"
|
||||||
version = "2024.10.0"
|
version = "2025.1.0"
|
||||||
description = "Bio image reading, metadata and some affine registration."
|
description = "Bio image reading, metadata and some affine registration."
|
||||||
authors = ["W. Pomp <w.pomp@nki.nl>"]
|
authors = ["W. Pomp <w.pomp@nki.nl>"]
|
||||||
license = "GPLv3"
|
license = "GPLv3"
|
||||||
@@ -16,13 +16,13 @@ numpy = ">=1.20.0"
|
|||||||
pandas = "*"
|
pandas = "*"
|
||||||
tifffile = "*"
|
tifffile = "*"
|
||||||
czifile = "2019.7.2"
|
czifile = "2019.7.2"
|
||||||
tiffwrite = ">=2024.10.4"
|
tiffwrite = ">=2024.12.1"
|
||||||
ome-types = ">=0.4.0"
|
ome-types = ">=0.4.0"
|
||||||
pint = "*"
|
pint = "*"
|
||||||
tqdm = "*"
|
tqdm = "*"
|
||||||
lxml = "*"
|
lxml = "*"
|
||||||
pyyaml = "*"
|
pyyaml = "*"
|
||||||
parfor = ">=2024.9.2"
|
parfor = ">=2025.1.0"
|
||||||
JPype1 = "*"
|
JPype1 = "*"
|
||||||
SimpleITK-SimpleElastix = [
|
SimpleITK-SimpleElastix = [
|
||||||
{ version = "*", python = "<3.12" },
|
{ version = "*", python = "<3.12" },
|
||||||
|
|||||||
Reference in New Issue
Block a user