impy-array 2.4.7__tar.gz → 2.4.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {impy_array-2.4.7 → impy_array-2.4.8}/PKG-INFO +2 -1
- {impy_array-2.4.7 → impy_array-2.4.8}/README.md +1 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/__init__.py +1 -1
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/_const.py +10 -10
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/imgarray.py +10 -9
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/labeledarray.py +72 -15
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/lazy.py +15 -7
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/core.py +8 -16
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/io/_mrc.py +16 -9
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/io/_tiff.py +15 -7
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/lazy/core.py +3 -10
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/random.py +4 -4
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/utils/gauss.py +4 -1
- {impy_array-2.4.7 → impy_array-2.4.8}/.gitignore +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/LICENSE +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/__main__.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/_types.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/array_api.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/__init__.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_imshow.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/__init__.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_corr.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_deconv.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_docs.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_filters.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_glcm.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_linalg.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_misc.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_plot.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_process_numba.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_skimage.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_structures.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/_utils/_transform.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/axesmixin.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/bases/__init__.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/bases/metaarray.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/bases/overload.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/big.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/label.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/phasearray.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/specials.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/arrays/tiled.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/axes/__init__.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/axes/_axes.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/axes/_axes_tuple.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/axes/_axis.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/axes/_slicer.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/binder.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/collections.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/correlation.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/frame/__init__.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/frame/frames.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/io/__init__.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/io/_nd2.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/io/_npy.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/io/_registry.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/io/_utils.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/io/_zarr.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/lazy/__init__.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/lazy/random.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/roi.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/utils/__init__.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/utils/axesop.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/utils/deco.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/utils/misc.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/utils/slicer.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/utils/utilcls.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/viewer/__init__.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/viewer/utils.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/impy/viewer/viewer.py +0 -0
- {impy_array-2.4.7 → impy_array-2.4.8}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: impy-array
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.8
|
|
4
4
|
Summary: Speed up coding/extending image analysis in Python.
|
|
5
5
|
Project-URL: Download, https://github.com/hanjinliu/impy
|
|
6
6
|
Author-email: Hanjin Liu <liuhanjin-sc@g.ecc.u-tokyo.ac.jp>
|
|
@@ -131,6 +131,7 @@ img_prj.imsave("image_max.tif") # Save in the same place. Don't spend tim
|
|
|
131
131
|
`impy` automatically chooses the proper reader/writer according to the extension.
|
|
132
132
|
|
|
133
133
|
- Tiff file (".tif", ".tiff")
|
|
134
|
+
- LSM file (".lsm")
|
|
134
135
|
- MRC file (".mrc", ".rec", ".st", ".map", ".map.gz")
|
|
135
136
|
- Zarr file (".zarr")
|
|
136
137
|
- ND2 file (".nd2")
|
|
@@ -58,6 +58,7 @@ img_prj.imsave("image_max.tif") # Save in the same place. Don't spend tim
|
|
|
58
58
|
`impy` automatically chooses the proper reader/writer according to the extension.
|
|
59
59
|
|
|
60
60
|
- Tiff file (".tif", ".tiff")
|
|
61
|
+
- LSM file (".lsm")
|
|
61
62
|
- MRC file (".mrc", ".rec", ".st", ".map", ".map.gz")
|
|
62
63
|
- Zarr file (".zarr")
|
|
63
64
|
- ND2 file (".nd2")
|
|
@@ -8,13 +8,13 @@ MAX_GB_LIMIT = memory.total / 2 * 1e-9
|
|
|
8
8
|
|
|
9
9
|
class GlobalConstant(MutableMapping[str, Any]):
|
|
10
10
|
_const: dict[str, Any]
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
def __init__(self, **kwargs):
|
|
13
13
|
object.__setattr__(self, "_const", dict(**kwargs))
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
def __len__(self) -> int:
|
|
16
16
|
return len(self._const)
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
def __iter__(self):
|
|
19
19
|
raise StopIteration
|
|
20
20
|
|
|
@@ -47,15 +47,15 @@ class GlobalConstant(MutableMapping[str, Any]):
|
|
|
47
47
|
dask.config.set(scheduler=v)
|
|
48
48
|
else:
|
|
49
49
|
raise RuntimeError("Cannot set new keys.")
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
self._const[k] = v
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
__getattr__ = __getitem__
|
|
54
54
|
__setattr__ = __setitem__
|
|
55
55
|
|
|
56
56
|
def __delitem__(self, v):
|
|
57
57
|
raise RuntimeError("Cannot delete any items.")
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
def __repr__(self):
|
|
60
60
|
return (
|
|
61
61
|
f"""
|
|
@@ -65,12 +65,12 @@ class GlobalConstant(MutableMapping[str, Any]):
|
|
|
65
65
|
SCHEDULER : {self['SCHEDULER']}
|
|
66
66
|
"""
|
|
67
67
|
)
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
def asdict(self) -> dict[str, Any]:
|
|
70
70
|
return self._const.copy()
|
|
71
71
|
|
|
72
72
|
Const = GlobalConstant(
|
|
73
|
-
MAX_GB = MAX_GB_LIMIT
|
|
73
|
+
MAX_GB = MAX_GB_LIMIT * 0.8,
|
|
74
74
|
ID_AXIS = "N",
|
|
75
75
|
RESOURCE = "numpy",
|
|
76
76
|
SCHEDULER = "threads",
|
|
@@ -80,12 +80,12 @@ class SetConst:
|
|
|
80
80
|
n_ongoing = 0
|
|
81
81
|
_locked_keys: set[str] = set()
|
|
82
82
|
_old_dict: dict[str, Any] = dict()
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
def __init__(self, dict_: dict[str, Any] | None =None, **kwargs):
|
|
85
85
|
dict_ = dict_ or {}
|
|
86
86
|
dict_.update(kwargs)
|
|
87
87
|
self._kwargs = dict_
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
def __enter__(self):
|
|
90
90
|
self.__class__.n_ongoing += 1
|
|
91
91
|
if self.__class__.n_ongoing == 1:
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
import warnings
|
|
3
|
+
from functools import partial
|
|
4
|
+
from itertools import product
|
|
5
|
+
from typing import TYPE_CHECKING, Literal, Sequence, Iterable, Callable, overload, Any
|
|
6
|
+
|
|
3
7
|
import numpy as np
|
|
4
8
|
from numpy.typing import DTypeLike
|
|
5
|
-
from functools import partial
|
|
6
9
|
from scipy import ndimage as ndi
|
|
7
|
-
from typing import TYPE_CHECKING, Literal, Sequence, Iterable, Callable, overload, Any
|
|
8
10
|
|
|
9
11
|
from impy.arrays.labeledarray import LabeledArray
|
|
10
12
|
from impy.arrays.label import Label
|
|
@@ -3987,8 +3989,7 @@ class ImgArray(LabeledArray):
|
|
|
3987
3989
|
upsample_factor: int = 10,
|
|
3988
3990
|
max_shift: nDFloat | None = None,
|
|
3989
3991
|
) -> MarkerFrame:
|
|
3990
|
-
"""
|
|
3991
|
-
Calculate yx-directional drift using the method equivalent to
|
|
3992
|
+
"""Calculate yx-directional drift using the method equivalent to
|
|
3992
3993
|
``skimage.registration.phase_cross_correlation``.
|
|
3993
3994
|
|
|
3994
3995
|
Parameters
|
|
@@ -4063,9 +4064,10 @@ class ImgArray(LabeledArray):
|
|
|
4063
4064
|
dims: Dims = 2,
|
|
4064
4065
|
update: bool = False,
|
|
4065
4066
|
) -> ImgArray:
|
|
4066
|
-
"""
|
|
4067
|
-
|
|
4068
|
-
is not given, then it will be determined using
|
|
4067
|
+
"""Drift correction using iterative Affine translation.
|
|
4068
|
+
|
|
4069
|
+
If translation vectors ``shift`` is not given, then it will be determined using
|
|
4070
|
+
``track_drift`` method of ImgArray.
|
|
4069
4071
|
|
|
4070
4072
|
Parameters
|
|
4071
4073
|
----------
|
|
@@ -4092,7 +4094,7 @@ class ImgArray(LabeledArray):
|
|
|
4092
4094
|
Examples
|
|
4093
4095
|
--------
|
|
4094
4096
|
Drift correction of multichannel image using the first channel as the reference.
|
|
4095
|
-
|
|
4097
|
+
>>> img.drift_correction(ref=img["c=0"])
|
|
4096
4098
|
"""
|
|
4097
4099
|
|
|
4098
4100
|
if along is None:
|
|
@@ -4107,7 +4109,6 @@ class ImgArray(LabeledArray):
|
|
|
4107
4109
|
elif not isinstance(ref, ImgArray):
|
|
4108
4110
|
ref = self[ref]
|
|
4109
4111
|
if ref.axes != [along] + dims:
|
|
4110
|
-
from itertools import product
|
|
4111
4112
|
_c_axes = complement_axes([along] + dims, str(ref.axes))
|
|
4112
4113
|
fmt = slicer.get_formatter(_c_axes)
|
|
4113
4114
|
out = np.empty_like(self)
|
|
@@ -3,7 +3,7 @@ import numpy as np
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
import itertools
|
|
5
5
|
from functools import partial
|
|
6
|
-
from typing import TYPE_CHECKING, Any, Sequence, MutableMapping, Protocol
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal, Sequence, MutableMapping, Protocol
|
|
7
7
|
from warnings import warn
|
|
8
8
|
from scipy import ndimage as ndi
|
|
9
9
|
|
|
@@ -23,7 +23,7 @@ from impy.array_api import xp
|
|
|
23
23
|
|
|
24
24
|
if TYPE_CHECKING:
|
|
25
25
|
from typing_extensions import Self
|
|
26
|
-
from numpy.typing import ArrayLike, DTypeLike
|
|
26
|
+
from numpy.typing import ArrayLike, DTypeLike, NDArray
|
|
27
27
|
from impy.frame import PathFrame
|
|
28
28
|
from impy.roi import RoiList
|
|
29
29
|
|
|
@@ -401,10 +401,18 @@ class LabeledArray(MetaArray):
|
|
|
401
401
|
out._set_info(self)
|
|
402
402
|
return out
|
|
403
403
|
|
|
404
|
-
def as_float(self) -> Self:
|
|
405
|
-
if
|
|
404
|
+
def as_float(self, *, depth: int = 32) -> Self:
|
|
405
|
+
if depth == 16:
|
|
406
|
+
dtype = np.float16
|
|
407
|
+
elif depth == 32:
|
|
408
|
+
dtype = np.float32
|
|
409
|
+
elif depth == 64:
|
|
410
|
+
dtype = np.float64
|
|
411
|
+
else:
|
|
412
|
+
raise ValueError(f"depth must be 16, 32, or 64, but got {depth}")
|
|
413
|
+
if self.dtype == dtype:
|
|
406
414
|
return self
|
|
407
|
-
out = self.value.astype(
|
|
415
|
+
out = self.value.astype(dtype).view(self.__class__)
|
|
408
416
|
out._set_info(self)
|
|
409
417
|
return out
|
|
410
418
|
|
|
@@ -417,8 +425,12 @@ class LabeledArray(MetaArray):
|
|
|
417
425
|
return self.as_uint16()
|
|
418
426
|
elif dtype == "uint8":
|
|
419
427
|
return self.as_uint8()
|
|
428
|
+
elif dtype == "float16":
|
|
429
|
+
return self.as_float(depth=16)
|
|
420
430
|
elif dtype == "float32":
|
|
421
|
-
return self.as_float()
|
|
431
|
+
return self.as_float(depth=32)
|
|
432
|
+
elif dtype == "float64":
|
|
433
|
+
return self.as_float(depth=64)
|
|
422
434
|
elif dtype == "bool":
|
|
423
435
|
return self.astype("bool")
|
|
424
436
|
elif dtype == "float64":
|
|
@@ -576,6 +588,7 @@ class LabeledArray(MetaArray):
|
|
|
576
588
|
*,
|
|
577
589
|
order: int = 3,
|
|
578
590
|
prefilter: bool | None = None,
|
|
591
|
+
how: Literal["pack", "equal"] = "pack",
|
|
579
592
|
) -> PropArray:
|
|
580
593
|
"""
|
|
581
594
|
Measure line profile (kymograph) iteratively for every slice of image. This
|
|
@@ -590,7 +603,12 @@ class LabeledArray(MetaArray):
|
|
|
590
603
|
`a = [[y0, x0], [y1, x1], ..., [yn, xn]]`
|
|
591
604
|
b : array-like, optional
|
|
592
605
|
Destination coordinate. If specified, `a` must be the source coordinate.
|
|
593
|
-
{order}
|
|
606
|
+
{order}{prefilter}
|
|
607
|
+
how : "pack" or "equal", default "pack"
|
|
608
|
+
How to sample points on the line. "pack" means that the points are sampled
|
|
609
|
+
at 1-px interval from the start point. "equal" means that the points are
|
|
610
|
+
sampled equally at the interval larger but neareset to 1-px so that the
|
|
611
|
+
points covers the entire line.
|
|
594
612
|
|
|
595
613
|
Returns
|
|
596
614
|
-------
|
|
@@ -616,7 +634,12 @@ class LabeledArray(MetaArray):
|
|
|
616
634
|
a = np.asarray(a, dtype=np.float32)
|
|
617
635
|
_, ndim = a.shape
|
|
618
636
|
seg = SegmentedLine(a)
|
|
619
|
-
|
|
637
|
+
if how == "pack":
|
|
638
|
+
coords = np.stack(seg.arange(), axis=0)
|
|
639
|
+
elif how == "equal":
|
|
640
|
+
coords = np.stack(seg.linspace(int(seg.length())), axis=0)
|
|
641
|
+
else:
|
|
642
|
+
raise ValueError(f"No option matches how={how}")
|
|
620
643
|
|
|
621
644
|
if ndim == self.ndim:
|
|
622
645
|
dims = self.axes
|
|
@@ -632,7 +655,11 @@ class LabeledArray(MetaArray):
|
|
|
632
655
|
axes=c_axes+[new_axis], propname="reslice")
|
|
633
656
|
|
|
634
657
|
out.set_scale(self)
|
|
635
|
-
|
|
658
|
+
axis = self.axes[dims[-1]]
|
|
659
|
+
if how == "equal":
|
|
660
|
+
out.set_scale({new_axis: axis.scale * seg.interv}, unit=axis.unit)
|
|
661
|
+
else:
|
|
662
|
+
out.set_scale({new_axis: axis.scale}, unit=axis.unit)
|
|
636
663
|
return out
|
|
637
664
|
|
|
638
665
|
@_docs.write_docs
|
|
@@ -1576,31 +1603,61 @@ class SegmentedLine:
|
|
|
1576
1603
|
dist = np.sqrt(np.sum(vec**2, axis=1))
|
|
1577
1604
|
dist_sum = np.sum(dist)
|
|
1578
1605
|
npoints = int(dist_sum)
|
|
1579
|
-
interv = dist_sum / npoints
|
|
1606
|
+
self.interv = dist_sum / npoints
|
|
1580
1607
|
|
|
1581
|
-
self.length = dist_sum
|
|
1582
1608
|
self.vec = vec
|
|
1583
1609
|
self.dist = dist
|
|
1584
1610
|
self.nodes = nodes
|
|
1585
|
-
self.interv = interv
|
|
1586
1611
|
|
|
1587
1612
|
def sample_points(self) -> np.ndarray:
|
|
1588
1613
|
res = 0
|
|
1589
1614
|
out = [self.nodes[0:1]]
|
|
1590
1615
|
npoints = 1
|
|
1616
|
+
interv = self.length() / int(self.length())
|
|
1591
1617
|
for v, d, p in zip(self.vec, self.dist, self.nodes[:-1]):
|
|
1592
1618
|
res0 = res
|
|
1593
|
-
d_int, res = divmod(d + res,
|
|
1594
|
-
idx =
|
|
1619
|
+
d_int, res = divmod(d + res, interv)
|
|
1620
|
+
idx = interv * (np.arange(d_int) + 1) - res0
|
|
1595
1621
|
xs = idx[:, np.newaxis] * v[np.newaxis]/d + p
|
|
1596
1622
|
out.append(xs)
|
|
1597
1623
|
npoints += xs.shape[0]
|
|
1598
1624
|
|
|
1599
|
-
if npoints <= int(self.length):
|
|
1625
|
+
if npoints <= int(self.length()):
|
|
1600
1626
|
out.append(self.nodes[-1:])
|
|
1601
1627
|
|
|
1602
1628
|
return np.concatenate(out, axis=0)
|
|
1603
1629
|
|
|
1630
|
+
def length(self) -> np.float64:
|
|
1631
|
+
return np.sum(self.lengths())
|
|
1632
|
+
|
|
1633
|
+
def lengths(self) -> NDArray[np.float64]:
|
|
1634
|
+
return np.sqrt(np.sum(np.diff(self.nodes, axis=0) ** 2, axis=1))
|
|
1635
|
+
|
|
1636
|
+
def linspace(self, num: int) -> tuple[NDArray[np.float64], ...]:
|
|
1637
|
+
"""Return a tuple of x and y coordinates of np.linspace along the line."""
|
|
1638
|
+
tnots = np.cumsum(
|
|
1639
|
+
np.concatenate([[0], self.lengths()], dtype=np.float64)
|
|
1640
|
+
)
|
|
1641
|
+
teval = np.linspace(0, tnots[-1], num)
|
|
1642
|
+
return tuple(
|
|
1643
|
+
np.interp(teval, tnots, self.nodes[:, i])
|
|
1644
|
+
for i in range(self.nodes.shape[1])
|
|
1645
|
+
)
|
|
1646
|
+
|
|
1647
|
+
def arange(
|
|
1648
|
+
self, step: float = 1.0
|
|
1649
|
+
) -> tuple[NDArray[np.float64], NDArray[np.float64]]:
|
|
1650
|
+
tnots = np.cumsum(
|
|
1651
|
+
np.concatenate([[0], self.lengths()], dtype=np.float64)
|
|
1652
|
+
)
|
|
1653
|
+
length = tnots[-1]
|
|
1654
|
+
num, rem = divmod(length, step)
|
|
1655
|
+
teval = np.linspace(0, length - rem, int(num + 1))
|
|
1656
|
+
return tuple(
|
|
1657
|
+
np.interp(teval, tnots, self.nodes[:, i])
|
|
1658
|
+
for i in range(self.nodes.shape[1])
|
|
1659
|
+
)
|
|
1660
|
+
|
|
1604
1661
|
def _count_list_depth(x) -> int:
|
|
1605
1662
|
n = 0
|
|
1606
1663
|
out = x
|
|
@@ -1612,10 +1612,18 @@ class LazyImgArray(AxesMixin):
|
|
|
1612
1612
|
out._set_info(self)
|
|
1613
1613
|
return out
|
|
1614
1614
|
|
|
1615
|
-
def as_float(self) -> LazyImgArray:
|
|
1616
|
-
if
|
|
1615
|
+
def as_float(self, *, depth: int = 32) -> LazyImgArray:
|
|
1616
|
+
if depth == 16:
|
|
1617
|
+
dtype = np.float16
|
|
1618
|
+
elif depth == 32:
|
|
1619
|
+
dtype = np.float32
|
|
1620
|
+
elif depth == 64:
|
|
1621
|
+
dtype = np.float64
|
|
1622
|
+
else:
|
|
1623
|
+
raise ValueError(f"depth must be 16, 32, or 64, but got {depth}")
|
|
1624
|
+
if self.dtype == dtype:
|
|
1617
1625
|
return self
|
|
1618
|
-
out = self.value.astype(
|
|
1626
|
+
out = self.value.astype(dtype)
|
|
1619
1627
|
out = self.__class__(out)
|
|
1620
1628
|
out._set_info(self)
|
|
1621
1629
|
return out
|
|
@@ -1628,12 +1636,12 @@ class LazyImgArray(AxesMixin):
|
|
|
1628
1636
|
return self.as_uint16()
|
|
1629
1637
|
elif dtype == "uint8":
|
|
1630
1638
|
return self.as_uint8()
|
|
1639
|
+
elif dtype == "float16":
|
|
1640
|
+
return self.as_float(depth=16)
|
|
1631
1641
|
elif dtype == "float32":
|
|
1632
|
-
return self.as_float()
|
|
1642
|
+
return self.as_float(depth=32)
|
|
1633
1643
|
elif dtype == "float64":
|
|
1634
|
-
|
|
1635
|
-
UserWarning)
|
|
1636
|
-
return self.as_float()
|
|
1644
|
+
return self.as_float(depth=64)
|
|
1637
1645
|
elif dtype == "complex64":
|
|
1638
1646
|
out = self.value.astype(np.complex64)
|
|
1639
1647
|
out = self.__class__(out)
|
|
@@ -99,8 +99,7 @@ def array(
|
|
|
99
99
|
axes: str = None,
|
|
100
100
|
like: MetaArray | None = None,
|
|
101
101
|
) -> ImgArray:
|
|
102
|
-
"""
|
|
103
|
-
make an ImgArray object, like ``np.array(x)``
|
|
102
|
+
"""Make an ImgArray object, like ``np.array(x)``
|
|
104
103
|
|
|
105
104
|
Parameters
|
|
106
105
|
----------
|
|
@@ -116,12 +115,7 @@ def array(
|
|
|
116
115
|
|
|
117
116
|
"""
|
|
118
117
|
if isinstance(arr, np.ndarray) and dtype is None:
|
|
119
|
-
|
|
120
|
-
dtype = arr.dtype
|
|
121
|
-
elif arr.dtype.kind == "f":
|
|
122
|
-
dtype = np.float32
|
|
123
|
-
else:
|
|
124
|
-
dtype = arr.dtype
|
|
118
|
+
dtype = arr.dtype
|
|
125
119
|
|
|
126
120
|
axes, name = _normalize_params(axes, name, like)
|
|
127
121
|
|
|
@@ -150,8 +144,7 @@ def asarray(
|
|
|
150
144
|
axes: str | None = None,
|
|
151
145
|
like: MetaArray | None = None,
|
|
152
146
|
) -> ImgArray:
|
|
153
|
-
"""
|
|
154
|
-
make an ImgArray object, like ``np.asarray(x)``
|
|
147
|
+
"""Make an ImgArray object, like ``np.asarray(x)``
|
|
155
148
|
|
|
156
149
|
Parameters
|
|
157
150
|
----------
|
|
@@ -296,9 +289,8 @@ def _inject_numpy_function(func: Callable[_P, Any | None]) -> Callable[_P, ImgAr
|
|
|
296
289
|
return asarray(npfunc(*args, **kwargs), name=name, axes=axes, like=like)
|
|
297
290
|
|
|
298
291
|
_func.__doc__ = (
|
|
299
|
-
f"""
|
|
300
|
-
|
|
301
|
-
and ``name``. Original docstring follows.
|
|
292
|
+
f"""impy version of numpy.{func.__name__}. This function has additional
|
|
293
|
+
parameters ``axes`` and ``name``. Original docstring follows.
|
|
302
294
|
|
|
303
295
|
Additional Parameters
|
|
304
296
|
---------------------
|
|
@@ -396,7 +388,7 @@ def gaussian_kernel(
|
|
|
396
388
|
"""
|
|
397
389
|
if np.isscalar(sigma):
|
|
398
390
|
sigma = (sigma,)*len(shape)
|
|
399
|
-
g = gauss.GaussianParticle([(np.array(shape)-1)/2, sigma, peak, 0])
|
|
391
|
+
g = gauss.GaussianParticle([(np.array(shape) - 1) / 2, sigma, peak, 0])
|
|
400
392
|
ker = g.generate(shape)
|
|
401
393
|
ker = array(ker, name=name or "Gaussian-Kernel", axes=axes)
|
|
402
394
|
if axes is None and ker.ndim == 3:
|
|
@@ -551,12 +543,12 @@ def imread(
|
|
|
551
543
|
return _imread_stack(path, dtype=dtype, key=key, squeeze=squeeze)
|
|
552
544
|
elif "*" in path:
|
|
553
545
|
return _imread_glob(path, dtype=dtype, key=key, squeeze=squeeze)
|
|
554
|
-
elif not
|
|
546
|
+
elif not Path(path).exists():
|
|
555
547
|
raise FileNotFoundError(f"No such file or directory: {path}")
|
|
556
548
|
|
|
557
549
|
# read tif metadata
|
|
558
550
|
if not is_memmap:
|
|
559
|
-
size =
|
|
551
|
+
size = Path(path).stat().st_size / 2**30
|
|
560
552
|
if size > Const["MAX_GB"]:
|
|
561
553
|
raise MemoryError(f"Too large {size:.2f} GB")
|
|
562
554
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
from typing import TYPE_CHECKING
|
|
4
5
|
import warnings
|
|
5
6
|
import os
|
|
@@ -59,7 +60,13 @@ def _(path: str, img: ImpyArray, lazy: bool = False):
|
|
|
59
60
|
|
|
60
61
|
if img.dtype == "bool":
|
|
61
62
|
img = img.astype(np.int8)
|
|
62
|
-
|
|
63
|
+
elif img.dtype == "float64":
|
|
64
|
+
warnings.warn(
|
|
65
|
+
"MRC format does not support float64. Converting to float32.",
|
|
66
|
+
UserWarning,
|
|
67
|
+
stacklevel=2,
|
|
68
|
+
)
|
|
69
|
+
img = img.astype(np.float32)
|
|
63
70
|
if lazy:
|
|
64
71
|
from dask import array as da
|
|
65
72
|
|
|
@@ -75,9 +82,10 @@ def _(path: str, img: ImpyArray, lazy: bool = False):
|
|
|
75
82
|
# get voxel_size
|
|
76
83
|
if img.axes not in ("zyx", "yx"):
|
|
77
84
|
raise ImageAxesError(
|
|
78
|
-
f"Can only save zyx- or yx- image as a mrc file, but image has {img.axes}
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
f"Can only save zyx- or yx- image as a mrc file, but image has {img.axes} "
|
|
86
|
+
"axes."
|
|
87
|
+
)
|
|
88
|
+
if Path(path).exists():
|
|
81
89
|
with mrcfile.open(path, mode="r+") as mrc:
|
|
82
90
|
mrc.set_data(img.value)
|
|
83
91
|
mrc.voxel_size = voxel_size
|
|
@@ -98,13 +106,12 @@ _MRC_MODE = {
|
|
|
98
106
|
}
|
|
99
107
|
|
|
100
108
|
def _parse_mrcfile(mrc: MrcObject) -> ImageMetadata:
|
|
101
|
-
|
|
102
|
-
if ndim == 3:
|
|
103
|
-
axes = "zyx"
|
|
104
|
-
elif ndim == 2:
|
|
109
|
+
if mrc.is_single_image():
|
|
105
110
|
axes = "yx"
|
|
111
|
+
elif mrc.is_volume_stack():
|
|
112
|
+
axes = "tzyx"
|
|
106
113
|
else:
|
|
107
|
-
|
|
114
|
+
axes = "zyx"
|
|
108
115
|
|
|
109
116
|
scale = dict.fromkeys(axes, 1.0)
|
|
110
117
|
for a in axes:
|
|
@@ -14,7 +14,7 @@ from impy.utils.axesop import complement_axes
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from tifffile import TiffFile
|
|
16
16
|
|
|
17
|
-
@IO.mark_reader(".tif", ".tiff")
|
|
17
|
+
@IO.mark_reader(".tif", ".tiff", ".lsm")
|
|
18
18
|
def _(path: str, memmap: bool = False) -> ImageData:
|
|
19
19
|
"""The tif file reader."""
|
|
20
20
|
from tifffile import TiffFile
|
|
@@ -28,7 +28,7 @@ def _(path: str, memmap: bool = False) -> ImageData:
|
|
|
28
28
|
|
|
29
29
|
return ImageData.from_metadata(image, meta)
|
|
30
30
|
|
|
31
|
-
@IO.mark_header_reader(".tif", ".tiff")
|
|
31
|
+
@IO.mark_header_reader(".tif", ".tiff", ".lsm")
|
|
32
32
|
def _(path: str) -> ImageMetadata:
|
|
33
33
|
"""The tif header reader."""
|
|
34
34
|
from tifffile import TiffFile
|
|
@@ -39,7 +39,7 @@ def _(path: str) -> ImageMetadata:
|
|
|
39
39
|
return meta
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
@IO.mark_writer(".tif", ".tiff")
|
|
42
|
+
@IO.mark_writer(".tif", ".tiff", ".lsm")
|
|
43
43
|
def _(path: str, img: ImpyArray, lazy: bool = False):
|
|
44
44
|
"""The TIFF writer."""
|
|
45
45
|
from tifffile import imwrite, memmap
|
|
@@ -103,7 +103,7 @@ def _parse_tifffile(tif: TiffFile) -> ImageMetadata:
|
|
|
103
103
|
tags = {v.name: v.value for v in pagetag.values()}
|
|
104
104
|
|
|
105
105
|
labels = ijmeta.get("Labels")
|
|
106
|
-
scale =
|
|
106
|
+
scale: dict[str, float] = {}
|
|
107
107
|
dz = ijmeta.get("spacing", 1.0)
|
|
108
108
|
scale_unit: dict[str, float] = {}
|
|
109
109
|
try:
|
|
@@ -133,9 +133,9 @@ def _parse_tifffile(tif: TiffFile) -> ImageMetadata:
|
|
|
133
133
|
_unit = ijmeta.pop("unit", None)
|
|
134
134
|
for k in scale.keys():
|
|
135
135
|
scale_unit[k] = _unit
|
|
136
|
-
if tif.
|
|
136
|
+
if ome_meta := tif.ome_metadata:
|
|
137
137
|
try:
|
|
138
|
-
xml = xml2dict(
|
|
138
|
+
xml = xml2dict(ome_meta)
|
|
139
139
|
meta_data: dict[str, Any] = xml["OME"]["Image"]
|
|
140
140
|
if isinstance(meta_data, list):
|
|
141
141
|
meta_data = meta_data[0]
|
|
@@ -156,6 +156,14 @@ def _parse_tifffile(tif: TiffFile) -> ImageMetadata:
|
|
|
156
156
|
|
|
157
157
|
except Exception:
|
|
158
158
|
pass
|
|
159
|
+
if lsm_meta := tif.lsm_metadata:
|
|
160
|
+
scale_unit = "μm"
|
|
161
|
+
if voxel_size_x := lsm_meta.get("VoxelSizeX"):
|
|
162
|
+
scale["x"] = voxel_size_x * 1e6
|
|
163
|
+
if voxel_size_y := lsm_meta.get("VoxelSizeY"):
|
|
164
|
+
scale["y"] = voxel_size_y * 1e6
|
|
165
|
+
if voxel_size_z := lsm_meta.get("VoxelSizeZ"):
|
|
166
|
+
scale["z"] = voxel_size_z * 1e6
|
|
159
167
|
|
|
160
168
|
return ImageMetadata(
|
|
161
169
|
axes=axes,
|
|
@@ -188,7 +196,7 @@ def _get_ijmeta_from_img(img: ImpyArray, update_lut=True):
|
|
|
188
196
|
info = {}
|
|
189
197
|
metadata["Info"] = str(info)
|
|
190
198
|
scale_unit = img.scale_unit
|
|
191
|
-
if scale_unit[0] in ("μ", "\xb5", "\xc2"):
|
|
199
|
+
if scale_unit and scale_unit[0] in ("μ", "\xb5", "\xc2"):
|
|
192
200
|
scale_unit = "\\u00B5" + scale_unit[1:]
|
|
193
201
|
metadata["unit"] = scale_unit
|
|
194
202
|
|
|
@@ -108,8 +108,7 @@ def array(
|
|
|
108
108
|
axes: str = None,
|
|
109
109
|
like: MetaArray | None = None,
|
|
110
110
|
) -> LazyImgArray:
|
|
111
|
-
"""
|
|
112
|
-
make an LazyImgArray object, like ``np.array(x)``
|
|
111
|
+
"""Make an LazyImgArray object, like ``np.array(x)``
|
|
113
112
|
|
|
114
113
|
Parameters
|
|
115
114
|
----------
|
|
@@ -144,12 +143,7 @@ def array(
|
|
|
144
143
|
arr = da.asarray(arr)
|
|
145
144
|
|
|
146
145
|
if isinstance(arr, np.ndarray) and dtype is None:
|
|
147
|
-
|
|
148
|
-
dtype = arr.dtype
|
|
149
|
-
elif arr.dtype.kind == "f":
|
|
150
|
-
dtype = np.float32
|
|
151
|
-
else:
|
|
152
|
-
dtype = arr.dtype
|
|
146
|
+
dtype = arr.dtype
|
|
153
147
|
|
|
154
148
|
axes, name = _normalize_params(axes, name, like)
|
|
155
149
|
|
|
@@ -172,8 +166,7 @@ def asarray(
|
|
|
172
166
|
like: MetaArray | None = None,
|
|
173
167
|
chunks="auto",
|
|
174
168
|
) -> LazyImgArray:
|
|
175
|
-
"""
|
|
176
|
-
make an LazyImgArray object, like ``np.asarray(x)``
|
|
169
|
+
"""Make an LazyImgArray object, like ``np.asarray(x)``
|
|
177
170
|
|
|
178
171
|
Parameters
|
|
179
172
|
----------
|
|
@@ -127,7 +127,7 @@ class ImageGenerator:
|
|
|
127
127
|
def standard_normal(
|
|
128
128
|
self,
|
|
129
129
|
size: int | tuple[int, ...] | None = None,
|
|
130
|
-
dtype
|
|
130
|
+
dtype=np.float32,
|
|
131
131
|
*,
|
|
132
132
|
axes: AxesLike | None = None,
|
|
133
133
|
name: str | None = None,
|
|
@@ -142,7 +142,7 @@ class ImageGenerator:
|
|
|
142
142
|
def standard_exponential(
|
|
143
143
|
self,
|
|
144
144
|
size: int | tuple[int, ...] | None = None,
|
|
145
|
-
dtype
|
|
145
|
+
dtype=np.float32,
|
|
146
146
|
method: Literal["zig", "inv"] = None,
|
|
147
147
|
*,
|
|
148
148
|
axes: AxesLike | None = None,
|
|
@@ -159,7 +159,7 @@ class ImageGenerator:
|
|
|
159
159
|
def random(
|
|
160
160
|
self,
|
|
161
161
|
size: int | tuple[int, ...] | None = None,
|
|
162
|
-
dtype
|
|
162
|
+
dtype=np.float32,
|
|
163
163
|
*,
|
|
164
164
|
axes: AxesLike | None = None,
|
|
165
165
|
name: str | None = None,
|
|
@@ -184,7 +184,7 @@ class ImageGenerator:
|
|
|
184
184
|
) -> ImgArray:
|
|
185
185
|
size, name, axes = _normalize_like(size, name, axes, like)
|
|
186
186
|
|
|
187
|
-
arr = self._rng.normal(loc=loc, scale=scale, size=size)
|
|
187
|
+
arr = self._rng.normal(loc=loc, scale=scale, size=size).astype(np.float32)
|
|
188
188
|
if np.isscalar(arr):
|
|
189
189
|
return arr
|
|
190
190
|
return asarray(xp.asnumpy(arr), axes=axes, name=name)
|
|
@@ -19,7 +19,10 @@ def diagonal_gaussian(r, *params):
|
|
|
19
19
|
ndim = len(params[:-2])//2
|
|
20
20
|
mu = params[:ndim]
|
|
21
21
|
sg = params[ndim:-2]
|
|
22
|
-
z_value = np.array(
|
|
22
|
+
z_value = np.array(
|
|
23
|
+
[(x0 - mu0) / sg0 for x0, mu0, sg0 in zip(r, mu, sg)],
|
|
24
|
+
dtype=np.float32
|
|
25
|
+
)
|
|
23
26
|
return a * np.exp(-np.sum(z_value**2, axis=0) / 2) + b
|
|
24
27
|
|
|
25
28
|
class Gaussian:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|