impy-array 2.4.0__tar.gz → 2.4.2__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.0 → impy_array-2.4.2}/PKG-INFO +14 -9
- {impy_array-2.4.0 → impy_array-2.4.2}/README.md +12 -7
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/__init__.py +1 -1
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_glcm.py +1 -1
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_structures.py +1 -1
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_transform.py +37 -35
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/imgarray.py +79 -47
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/lazy.py +8 -2
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/tiled.py +5 -1
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/core.py +5 -2
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/io.py +2 -3
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/utils/gauss.py +27 -22
- {impy_array-2.4.0 → impy_array-2.4.2}/.gitignore +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/LICENSE +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/__main__.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/_const.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/_types.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/array_api.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/__init__.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_imshow.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/__init__.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_corr.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_deconv.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_docs.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_filters.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_linalg.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_misc.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_plot.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_process_numba.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/_utils/_skimage.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/axesmixin.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/bases/__init__.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/bases/metaarray.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/bases/overload.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/big.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/label.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/labeledarray.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/phasearray.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/arrays/specials.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/axes/__init__.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/axes/_axes.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/axes/_axes_tuple.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/axes/_axis.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/axes/_slicer.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/binder.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/collections.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/correlation.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/frame/__init__.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/frame/frames.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/lazy/__init__.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/lazy/core.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/lazy/random.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/random.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/roi.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/utils/__init__.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/utils/axesop.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/utils/deco.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/utils/misc.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/utils/slicer.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/utils/utilcls.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/viewer/__init__.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/viewer/utils.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/impy/viewer/viewer.py +0 -0
- {impy_array-2.4.0 → impy_array-2.4.2}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: impy-array
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.2
|
|
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>
|
|
@@ -76,9 +76,11 @@ Description-Content-Type: text/markdown
|
|
|
76
76
|
|
|
77
77
|
# A numpy extension for efficient and powerful image analysis workflow
|
|
78
78
|
|
|
79
|
-
`impy` is an all-in-one image analysis library, equipped with parallel processing, GPU
|
|
79
|
+
`impy` is an all-in-one image analysis library, equipped with parallel processing, GPU
|
|
80
|
+
support, GUI-based tools and so on.
|
|
80
81
|
|
|
81
|
-
The core array, `ImgArray`, is a subclass of `numpy.ndarray`, tagged with information
|
|
82
|
+
The core array, `ImgArray`, is a subclass of `numpy.ndarray`, tagged with information
|
|
83
|
+
such as:
|
|
82
84
|
|
|
83
85
|
- image axes
|
|
84
86
|
- scale of each axis
|
|
@@ -109,7 +111,10 @@ git clone https://github.com/hanjinliu/impy
|
|
|
109
111
|
|
|
110
112
|
### Code as fast as you speak
|
|
111
113
|
|
|
112
|
-
Almost all the functions, such as filtering, deconvolution, labeling, single molecule
|
|
114
|
+
Almost all the functions, such as filtering, deconvolution, labeling, single molecule
|
|
115
|
+
detection, and even those pure `numpy` functions, are aware of image metadata. They
|
|
116
|
+
"know" which dimension corresponds to `"z"` axis, which axes they should iterate along
|
|
117
|
+
or where to save the image. As a result, **your code will be very concise**:
|
|
113
118
|
|
|
114
119
|
```python
|
|
115
120
|
import impy as ip
|
|
@@ -124,7 +129,7 @@ img_prj.imsave(f"Max-{img.name}") # Save in the same place. Don't spend tim
|
|
|
124
129
|
|
|
125
130
|
### Supports many file formats
|
|
126
131
|
|
|
127
|
-
`impy` automatically chooses proper reader/writer according to the extension.
|
|
132
|
+
`impy` automatically chooses the proper reader/writer according to the extension.
|
|
128
133
|
|
|
129
134
|
- Tiff file (".tif", ".tiff")
|
|
130
135
|
- MRC file (".mrc", ".rec", ".st", ".map", ".map.gz")
|
|
@@ -183,8 +188,8 @@ img.imfilter(param=1.0)
|
|
|
183
188
|
|
|
184
189
|
### Command line usage
|
|
185
190
|
|
|
186
|
-
`impy` also supports command
|
|
187
|
-
from
|
|
191
|
+
`impy` also supports command-line-based image analysis. All methods of `ImgArray` are
|
|
192
|
+
available from the command line, such as
|
|
188
193
|
|
|
189
194
|
```shell
|
|
190
195
|
impy path/to/image.tif ./output.tif --method gaussian_filter --sigma 2.0
|
|
@@ -199,7 +204,7 @@ out = img.gaussian_filter(sigma=2.0)
|
|
|
199
204
|
out.imsave("./output.tif")
|
|
200
205
|
```
|
|
201
206
|
|
|
202
|
-
For more complex
|
|
207
|
+
For more complex procedures, it is possible to send images directly to `IPython`
|
|
203
208
|
|
|
204
209
|
```
|
|
205
210
|
impy path/to/image.tif -i
|
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
# A numpy extension for efficient and powerful image analysis workflow
|
|
6
6
|
|
|
7
|
-
`impy` is an all-in-one image analysis library, equipped with parallel processing, GPU
|
|
7
|
+
`impy` is an all-in-one image analysis library, equipped with parallel processing, GPU
|
|
8
|
+
support, GUI-based tools and so on.
|
|
8
9
|
|
|
9
|
-
The core array, `ImgArray`, is a subclass of `numpy.ndarray`, tagged with information
|
|
10
|
+
The core array, `ImgArray`, is a subclass of `numpy.ndarray`, tagged with information
|
|
11
|
+
such as:
|
|
10
12
|
|
|
11
13
|
- image axes
|
|
12
14
|
- scale of each axis
|
|
@@ -37,7 +39,10 @@ git clone https://github.com/hanjinliu/impy
|
|
|
37
39
|
|
|
38
40
|
### Code as fast as you speak
|
|
39
41
|
|
|
40
|
-
Almost all the functions, such as filtering, deconvolution, labeling, single molecule
|
|
42
|
+
Almost all the functions, such as filtering, deconvolution, labeling, single molecule
|
|
43
|
+
detection, and even those pure `numpy` functions, are aware of image metadata. They
|
|
44
|
+
"know" which dimension corresponds to `"z"` axis, which axes they should iterate along
|
|
45
|
+
or where to save the image. As a result, **your code will be very concise**:
|
|
41
46
|
|
|
42
47
|
```python
|
|
43
48
|
import impy as ip
|
|
@@ -52,7 +57,7 @@ img_prj.imsave(f"Max-{img.name}") # Save in the same place. Don't spend tim
|
|
|
52
57
|
|
|
53
58
|
### Supports many file formats
|
|
54
59
|
|
|
55
|
-
`impy` automatically chooses proper reader/writer according to the extension.
|
|
60
|
+
`impy` automatically chooses the proper reader/writer according to the extension.
|
|
56
61
|
|
|
57
62
|
- Tiff file (".tif", ".tiff")
|
|
58
63
|
- MRC file (".mrc", ".rec", ".st", ".map", ".map.gz")
|
|
@@ -111,8 +116,8 @@ img.imfilter(param=1.0)
|
|
|
111
116
|
|
|
112
117
|
### Command line usage
|
|
113
118
|
|
|
114
|
-
`impy` also supports command
|
|
115
|
-
from
|
|
119
|
+
`impy` also supports command-line-based image analysis. All methods of `ImgArray` are
|
|
120
|
+
available from the command line, such as
|
|
116
121
|
|
|
117
122
|
```shell
|
|
118
123
|
impy path/to/image.tif ./output.tif --method gaussian_filter --sigma 2.0
|
|
@@ -127,7 +132,7 @@ out = img.gaussian_filter(sigma=2.0)
|
|
|
127
132
|
out.imsave("./output.tif")
|
|
128
133
|
```
|
|
129
134
|
|
|
130
|
-
For more complex
|
|
135
|
+
For more complex procedures, it is possible to send images directly to `IPython`
|
|
131
136
|
|
|
132
137
|
```
|
|
133
138
|
impy path/to/image.tif -i
|
|
@@ -10,9 +10,9 @@ if TYPE_CHECKING:
|
|
|
10
10
|
from impy import ImgArray
|
|
11
11
|
|
|
12
12
|
__all__ = [
|
|
13
|
-
"compose_affine_matrix",
|
|
13
|
+
"compose_affine_matrix",
|
|
14
14
|
"decompose_affine_matrix",
|
|
15
|
-
"affinefit",
|
|
15
|
+
"affinefit",
|
|
16
16
|
"check_matrix",
|
|
17
17
|
"warp",
|
|
18
18
|
]
|
|
@@ -24,8 +24,8 @@ class AffineTransformationParameters(NamedTuple):
|
|
|
24
24
|
shear: np.ndarray
|
|
25
25
|
|
|
26
26
|
def warp(
|
|
27
|
-
img:
|
|
28
|
-
matrix:
|
|
27
|
+
img: np.ndarray,
|
|
28
|
+
matrix: np.ndarray,
|
|
29
29
|
mode="constant",
|
|
30
30
|
cval=0,
|
|
31
31
|
output_shape=None,
|
|
@@ -35,13 +35,13 @@ def warp(
|
|
|
35
35
|
):
|
|
36
36
|
img = xp.asarray(img, dtype=img.dtype)
|
|
37
37
|
matrix = xp.asarray(matrix)
|
|
38
|
-
out = xp.ndi.affine_transform(img, matrix, cval=cval, mode=mode, output_shape=output_shape,
|
|
38
|
+
out = xp.ndi.affine_transform(img, matrix, cval=cval, mode=mode, output_shape=output_shape,
|
|
39
39
|
offset=offset, order=order, prefilter=prefilter)
|
|
40
40
|
return out
|
|
41
41
|
|
|
42
|
-
def shift(img:
|
|
42
|
+
def shift(img: np.ndarray, shift: np.ndarray, cval=0, mode="constant", order=1, prefilter=False):
|
|
43
43
|
img = xp.asarray(img, dtype=img.dtype)
|
|
44
|
-
out = xp.ndi.shift(img, shift, cval=cval, mode=mode,
|
|
44
|
+
out = xp.ndi.shift(img, shift, cval=cval, mode=mode,
|
|
45
45
|
order=order, prefilter=prefilter)
|
|
46
46
|
return out
|
|
47
47
|
|
|
@@ -71,10 +71,10 @@ def compose_affine_matrix(
|
|
|
71
71
|
translation = [translation] * ndim
|
|
72
72
|
if rotation is not None:
|
|
73
73
|
rotation = np.rad2deg(rotation)
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
af = Affine(scale=scale, translate=translation, rotate=rotation, shear=shear)
|
|
76
76
|
mx = af.affine_matrix
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
return mx
|
|
79
79
|
|
|
80
80
|
|
|
@@ -83,12 +83,12 @@ def decompose_affine_matrix(matrix: np.ndarray):
|
|
|
83
83
|
if ndim == 2:
|
|
84
84
|
from skimage.transform import AffineTransform
|
|
85
85
|
af = AffineTransform(matrix=matrix)
|
|
86
|
-
out = AffineTransformationParameters(translation=af.translation, rotation=af.rotation,
|
|
86
|
+
out = AffineTransformationParameters(translation=af.translation, rotation=af.rotation,
|
|
87
87
|
scale=af.scale, shear=af.shear)
|
|
88
88
|
else:
|
|
89
89
|
from napari.utils.transforms import Affine
|
|
90
90
|
af = Affine(affine_matrix=matrix)
|
|
91
|
-
out = AffineTransformationParameters(translation=af.translate, rotation=af.rotate,
|
|
91
|
+
out = AffineTransformationParameters(translation=af.translate, rotation=af.rotate,
|
|
92
92
|
scale=af.scale, shear=af.shear)
|
|
93
93
|
return out
|
|
94
94
|
|
|
@@ -104,8 +104,10 @@ def affinefit(img, imgref, bins=256, order=1):
|
|
|
104
104
|
from scipy.stats import entropy
|
|
105
105
|
from scipy.optimize import minimize
|
|
106
106
|
from skimage.transform import warp
|
|
107
|
-
|
|
108
|
-
as_3x3_matrix
|
|
107
|
+
|
|
108
|
+
def as_3x3_matrix(mtx: np.ndarray):
|
|
109
|
+
return np.vstack((mtx.reshape(2,3), [0., 0., 1.]))
|
|
110
|
+
|
|
109
111
|
def normalized_mutual_information(img, imgref):
|
|
110
112
|
"""
|
|
111
113
|
Y(A,B) = (H(A)+H(B))/H(A,B)
|
|
@@ -117,15 +119,15 @@ def affinefit(img, imgref, bins=256, order=1):
|
|
|
117
119
|
e2 = entropy(np.sum(hist, axis=1))
|
|
118
120
|
e12 = entropy(np.ravel(hist)) # mutual entropy
|
|
119
121
|
return (e1 + e2)/e12
|
|
120
|
-
|
|
122
|
+
|
|
121
123
|
def cost_nmi(mtx, img, imgref):
|
|
122
124
|
mtx = as_3x3_matrix(mtx)
|
|
123
125
|
img_transformed = warp(img, mtx, order=order)
|
|
124
126
|
return -normalized_mutual_information(img_transformed, imgref)
|
|
125
|
-
|
|
127
|
+
|
|
126
128
|
mtx0 = np.array([[1., 0., 0.],
|
|
127
129
|
[0., 1., 0.]]) # aberration makes little difference
|
|
128
|
-
|
|
130
|
+
|
|
129
131
|
result = minimize(
|
|
130
132
|
cost_nmi, mtx0, args=(np.asarray(img), np.asarray(imgref)), method="Powell"
|
|
131
133
|
)
|
|
@@ -134,24 +136,24 @@ def affinefit(img, imgref, bins=256, order=1):
|
|
|
134
136
|
|
|
135
137
|
|
|
136
138
|
def check_matrix(matrices: list[np.ndarray | float]):
|
|
137
|
-
"""Check Affine transformation matrix."""
|
|
139
|
+
"""Check Affine transformation matrix."""
|
|
138
140
|
mtx = []
|
|
139
141
|
for m in matrices:
|
|
140
|
-
if np.isscalar(m):
|
|
142
|
+
if np.isscalar(m):
|
|
141
143
|
if m == 1:
|
|
142
144
|
mtx.append(m)
|
|
143
145
|
else:
|
|
144
146
|
raise ValueError(f"Only `1` is ok, but got {m}")
|
|
145
|
-
|
|
147
|
+
|
|
146
148
|
elif m.shape != (3, 3) or not np.allclose(m[2,:2], 0):
|
|
147
149
|
raise ValueError(f"Wrong Affine transformation matrix:\n{m}")
|
|
148
|
-
|
|
150
|
+
|
|
149
151
|
else:
|
|
150
152
|
mtx.append(m)
|
|
151
153
|
return mtx
|
|
152
154
|
|
|
153
155
|
def polar2d(
|
|
154
|
-
img:
|
|
156
|
+
img: np.ndarray,
|
|
155
157
|
rmax: int,
|
|
156
158
|
dtheta: float = 0.1, # radian
|
|
157
159
|
order: int = 1,
|
|
@@ -170,14 +172,14 @@ def polar2d(
|
|
|
170
172
|
return out
|
|
171
173
|
|
|
172
174
|
def normalize_radon_input(
|
|
173
|
-
self: ImgArray,
|
|
174
|
-
dims: Axes,
|
|
175
|
-
central_axis: AxisLike,
|
|
175
|
+
self: ImgArray,
|
|
176
|
+
dims: Axes,
|
|
177
|
+
central_axis: AxisLike,
|
|
176
178
|
degrees: Sequence[float] | float,
|
|
177
|
-
):
|
|
179
|
+
):
|
|
178
180
|
ndim = len(dims)
|
|
179
181
|
squeeze = not hasattr(degrees, "__iter__")
|
|
180
|
-
|
|
182
|
+
|
|
181
183
|
if squeeze:
|
|
182
184
|
degrees = [degrees]
|
|
183
185
|
if ndim != self.ndim:
|
|
@@ -213,7 +215,7 @@ def normalize_radon_input(
|
|
|
213
215
|
central_axis: np.ndarray
|
|
214
216
|
if central_axis.shape != (ndim,):
|
|
215
217
|
raise ValueError(f"Image is {ndim}D but central_axis is {central_axis.ndim}D.")
|
|
216
|
-
|
|
218
|
+
|
|
217
219
|
# construct Affine transform matrices
|
|
218
220
|
height = int(np.ceil(np.linalg.norm(self.shape)))
|
|
219
221
|
output_shape = (height, self.shape[1], self.shape[2])
|
|
@@ -222,11 +224,11 @@ def normalize_radon_input(
|
|
|
222
224
|
)
|
|
223
225
|
else:
|
|
224
226
|
raise ValueError("Only 2D or 3D input is supported.")
|
|
225
|
-
|
|
227
|
+
|
|
226
228
|
return params, output_shape, squeeze
|
|
227
229
|
|
|
228
230
|
def normalize_iradon_input(
|
|
229
|
-
self: ImgArray,
|
|
231
|
+
self: ImgArray,
|
|
230
232
|
central_axis: AxisLike,
|
|
231
233
|
height_axis: AxisLike,
|
|
232
234
|
degree_axis: AxisLike,
|
|
@@ -250,7 +252,7 @@ def normalize_iradon_input(
|
|
|
250
252
|
output_shape = (height, self.shape[-1])
|
|
251
253
|
return central_axis, degree_axis, output_shape, new_axes
|
|
252
254
|
|
|
253
|
-
def radon_single(img:
|
|
255
|
+
def radon_single(img: np.ndarray, mtx: np.ndarray, order: int = 3, output_shape=None):
|
|
254
256
|
"""Radon transform of 2D image."""
|
|
255
257
|
img_rot = warp(img, mtx, order=order, output_shape=output_shape, prefilter=False)
|
|
256
258
|
return xp.sum(img_rot, axis=0)
|
|
@@ -290,13 +292,13 @@ def _get_rotation_matrices_for_radon_3d(
|
|
|
290
292
|
return np.einsum("ij,njk,kl->nil", tr_0, rotation, tr_1)
|
|
291
293
|
|
|
292
294
|
# This function is mostly ported from `skimage.transform`.
|
|
293
|
-
# The most important difference is that this implementation support arbitrary
|
|
295
|
+
# The most important difference is that this implementation support arbitrary
|
|
294
296
|
# output shape.
|
|
295
297
|
def iradon(
|
|
296
|
-
img:
|
|
297
|
-
degrees:
|
|
298
|
+
img: np.ndarray,
|
|
299
|
+
degrees: np.ndarray,
|
|
298
300
|
output_shape: tuple[int, int],
|
|
299
|
-
filter_func:
|
|
301
|
+
filter_func: np.ndarray,
|
|
300
302
|
interp: Callable[[np.ndarray, np.ndarray], np.ndarray],
|
|
301
303
|
):
|
|
302
304
|
angles_count = len(degrees)
|
|
@@ -322,7 +324,7 @@ def iradon(
|
|
|
322
324
|
|
|
323
325
|
return reconstructed * np.pi / (2 * angles_count)
|
|
324
326
|
|
|
325
|
-
# This function is almost ported from `skimage.transform`, but create a ramp
|
|
327
|
+
# This function is almost ported from `skimage.transform`, but create a ramp
|
|
326
328
|
# filter in a simpler way.
|
|
327
329
|
def get_fourier_filter(size: int, filter_name: str):
|
|
328
330
|
# ramp filter
|
|
@@ -221,60 +221,78 @@ class ImgArray(LabeledArray):
|
|
|
221
221
|
@_docs.write_docs
|
|
222
222
|
@dims_to_spatial_axes
|
|
223
223
|
@same_dtype(asfloat=True)
|
|
224
|
-
def
|
|
224
|
+
def zoom(
|
|
225
225
|
self,
|
|
226
|
-
|
|
226
|
+
zoom: nDFloat,
|
|
227
227
|
*,
|
|
228
|
-
order: int =
|
|
229
|
-
mode: PaddingMode = "
|
|
228
|
+
order: int = 3,
|
|
229
|
+
mode: PaddingMode = "constant",
|
|
230
230
|
cval: float = 0.0,
|
|
231
|
+
same_shape: bool = False,
|
|
231
232
|
dims: Dims = None,
|
|
232
233
|
) -> ImgArray:
|
|
233
234
|
"""
|
|
234
|
-
|
|
235
|
+
Zoom image by applying the diagonal component of Affine matrix.
|
|
235
236
|
|
|
236
237
|
Parameters
|
|
237
238
|
----------
|
|
238
|
-
scale : float
|
|
239
|
+
scale : float
|
|
239
240
|
Relative scale of the new image. scale 1/2 means that the shape of
|
|
240
241
|
the output image will be (N/2, ...).
|
|
241
242
|
{order}{mode}{cval}{dims}
|
|
243
|
+
same_shape : bool, default is False
|
|
244
|
+
If True, the output image will have the same shape as the input image.
|
|
242
245
|
|
|
243
246
|
Returns
|
|
244
247
|
-------
|
|
245
248
|
ImgArray
|
|
246
249
|
Rescaled image.
|
|
247
250
|
"""
|
|
248
|
-
|
|
249
|
-
scale_is_seq = hasattr(scale, "__iter__")
|
|
251
|
+
zoom_is_seq = hasattr(zoom, "__iter__")
|
|
250
252
|
|
|
251
253
|
# Check if output is too large.
|
|
252
254
|
gb = -1
|
|
253
|
-
if not
|
|
254
|
-
gb = np.prod(self.shape) * (
|
|
255
|
-
elif
|
|
256
|
-
gb = np.prod(self.shape) * np.prod(list(
|
|
255
|
+
if not zoom_is_seq and zoom > 1:
|
|
256
|
+
gb = np.prod(self.shape) * (zoom ** len(dims)) / 2**30 * self.itemsize
|
|
257
|
+
elif zoom_is_seq and np.prod(list(zoom)) > 1:
|
|
258
|
+
gb = np.prod(self.shape) * np.prod(list(zoom)) / 2**30 * self.itemsize
|
|
257
259
|
if gb > Const["MAX_GB"]:
|
|
258
260
|
raise MemoryError(f"Output image is too large: {gb} GB")
|
|
259
261
|
|
|
260
|
-
if
|
|
261
|
-
|
|
262
|
-
if len(
|
|
262
|
+
if zoom_is_seq:
|
|
263
|
+
zoom = list(zoom)
|
|
264
|
+
if len(zoom) != len(dims):
|
|
263
265
|
raise ValueError(
|
|
264
266
|
"scale must have the same length as the spatial dimensions."
|
|
265
267
|
)
|
|
266
|
-
it = iter(
|
|
267
|
-
|
|
268
|
+
it = iter(zoom)
|
|
269
|
+
zoom_ = [next(it) if a in dims else 1 for a in self.axes]
|
|
268
270
|
else:
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
271
|
+
zoom_ = [zoom if a in dims else 1 for a in self.axes]
|
|
272
|
+
|
|
273
|
+
if not same_shape:
|
|
274
|
+
if mode == "constant":
|
|
275
|
+
mode = "grid-constant"
|
|
276
|
+
out = ndi.zoom(
|
|
277
|
+
self.value, zoom_, order=order, mode=mode, cval=cval,
|
|
278
|
+
prefilter=order > 1, grid_mode=True,
|
|
279
|
+
).view(self.__class__)._set_info(self)
|
|
280
|
+
else:
|
|
281
|
+
center = [(s - 1) / 2 for s in self.sizesof(dims)]
|
|
282
|
+
mesh = np.meshgrid(
|
|
283
|
+
*[
|
|
284
|
+
(np.arange(_s) - _c) / _z + _c
|
|
285
|
+
for _s, _z, _c in zip(self.sizesof(dims), zoom_, center)
|
|
286
|
+
],
|
|
287
|
+
indexing="ij",
|
|
288
|
+
)
|
|
289
|
+
out = self.map_coordinates(mesh, order=order, mode=mode, cval=cval, dims=dims)
|
|
274
290
|
out.axes = self.axes.copy()
|
|
275
|
-
out.set_scale({a: self.scale[a]/scale for a, scale in zip(self.axes,
|
|
291
|
+
out.set_scale({a: self.scale[a]/scale for a, scale in zip(self.axes, zoom_)})
|
|
276
292
|
return out
|
|
277
293
|
|
|
294
|
+
rescale = zoom # backward compatibility
|
|
295
|
+
|
|
278
296
|
@_docs.write_docs
|
|
279
297
|
@dims_to_spatial_axes
|
|
280
298
|
@same_dtype
|
|
@@ -465,10 +483,10 @@ class ImgArray(LabeledArray):
|
|
|
465
483
|
out.metadata["GaussianParameters"] = params
|
|
466
484
|
return out
|
|
467
485
|
|
|
468
|
-
rough = self.
|
|
486
|
+
rough = self.zoom(scale, mode="reflect", order=1).value.astype(np.float32)
|
|
469
487
|
if mask is not None:
|
|
470
|
-
from
|
|
471
|
-
mask = ip_asarray(mask).
|
|
488
|
+
from impy.core import asarray as ip_asarray
|
|
489
|
+
mask = ip_asarray(mask).zoom(scale, mode="reflect", order=1) > 0
|
|
472
490
|
gaussian = GaussianBackground(p0)
|
|
473
491
|
gaussian.fit(rough, method=method, mask=mask)
|
|
474
492
|
gaussian.rescale(1/scale)
|
|
@@ -480,12 +498,18 @@ class ImgArray(LabeledArray):
|
|
|
480
498
|
|
|
481
499
|
@same_dtype(asfloat=True)
|
|
482
500
|
@check_input_and_output
|
|
483
|
-
def gauss_correction(
|
|
501
|
+
def gauss_correction(
|
|
502
|
+
self,
|
|
503
|
+
ref: ImgArray | None = None,
|
|
504
|
+
scale: float = 1/16,
|
|
505
|
+
median_radius: float = 15,
|
|
506
|
+
):
|
|
484
507
|
"""
|
|
485
|
-
Correct unevenly distributed excitation light using Gaussian fitting.
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
508
|
+
Correct unevenly distributed excitation light using Gaussian fitting.
|
|
509
|
+
|
|
510
|
+
This method subtracts background intensity at the same time. If input image is
|
|
511
|
+
uint, then output value under 0 will replaced with 0. If you want to quantify
|
|
512
|
+
background, it is necessary to first convert input image to float image.
|
|
489
513
|
|
|
490
514
|
Parameters
|
|
491
515
|
----------
|
|
@@ -1069,7 +1093,6 @@ class ImgArray(LabeledArray):
|
|
|
1069
1093
|
kwargs=dict(footprint=disk, mode=mode, cval=cval)
|
|
1070
1094
|
)
|
|
1071
1095
|
|
|
1072
|
-
|
|
1073
1096
|
@_docs.write_docs
|
|
1074
1097
|
@dims_to_spatial_axes
|
|
1075
1098
|
@check_input_and_output(only_binary=True)
|
|
@@ -1321,7 +1344,9 @@ class ImgArray(LabeledArray):
|
|
|
1321
1344
|
@check_input_and_output
|
|
1322
1345
|
def entropy_filter(self, radius: nDFloat = 5, *, dims: Dims = None) -> ImgArray:
|
|
1323
1346
|
"""
|
|
1324
|
-
Running entropy filter.
|
|
1347
|
+
Running entropy filter.
|
|
1348
|
+
|
|
1349
|
+
This filter is useful for detecting change in background distribution.
|
|
1325
1350
|
|
|
1326
1351
|
Parameters
|
|
1327
1352
|
----------
|
|
@@ -1413,8 +1438,10 @@ class ImgArray(LabeledArray):
|
|
|
1413
1438
|
def kalman_filter(self, gain: float = 0.8, noise_var: float = 0.05, *, along: str = "t",
|
|
1414
1439
|
dims: Dims = None, update: bool = False) -> ImgArray:
|
|
1415
1440
|
"""
|
|
1416
|
-
Kalman filter for image smoothing.
|
|
1417
|
-
|
|
1441
|
+
Kalman filter for image smoothing.
|
|
1442
|
+
|
|
1443
|
+
This function is same as "Kalman Stack Filter" in ImageJ but support batch
|
|
1444
|
+
processing. This filter is useful for preprocessing of particle tracking.
|
|
1418
1445
|
|
|
1419
1446
|
Parameters
|
|
1420
1447
|
----------
|
|
@@ -1450,8 +1477,10 @@ class ImgArray(LabeledArray):
|
|
|
1450
1477
|
@check_input_and_output
|
|
1451
1478
|
def focus_map(self, radius: int = 1, *, dims: Dims = 2) -> PropArray:
|
|
1452
1479
|
"""
|
|
1453
|
-
Compute focus map using variance of Laplacian method.
|
|
1454
|
-
|
|
1480
|
+
Compute focus map using variance of Laplacian method.
|
|
1481
|
+
|
|
1482
|
+
yx-plane with higher variance is likely a focal plane because sharper image
|
|
1483
|
+
causes higher value of Laplacian on the edges.
|
|
1455
1484
|
|
|
1456
1485
|
Parameters
|
|
1457
1486
|
----------
|
|
@@ -1626,8 +1655,10 @@ class ImgArray(LabeledArray):
|
|
|
1626
1655
|
dims: Dims = None,
|
|
1627
1656
|
) -> ImgArray:
|
|
1628
1657
|
"""
|
|
1629
|
-
Run Difference of Gaussian filter.
|
|
1630
|
-
|
|
1658
|
+
Run Difference of Gaussian filter.
|
|
1659
|
+
|
|
1660
|
+
This function does not support `update` argument because intensity can be
|
|
1661
|
+
negative.
|
|
1631
1662
|
|
|
1632
1663
|
Parameters
|
|
1633
1664
|
----------
|
|
@@ -2809,11 +2840,12 @@ class ImgArray(LabeledArray):
|
|
|
2809
2840
|
dtype = np.complex128 if double_precision else np.complex64
|
|
2810
2841
|
|
|
2811
2842
|
# Calculate exp(-ikx)
|
|
2812
|
-
# To minimize floating error, the A term in exp(-2*pi*i*A) should be in the
|
|
2813
|
-
# 0 <= A < 1.
|
|
2814
|
-
exps: list[
|
|
2815
|
-
|
|
2816
|
-
|
|
2843
|
+
# To minimize floating error, the A term in exp(-2*pi*i*A) should be in the
|
|
2844
|
+
# range of 0 <= A < 1.
|
|
2845
|
+
exps: list[np.ndarray] = [
|
|
2846
|
+
xp.exp(-2j * np.pi * xp.mod(wave_num(sl, s, uf) * xp.arange(s)/s, 1.), dtype=dtype)
|
|
2847
|
+
for sl, s, uf in zip(slices, self.sizesof(dims), upsample_factor)
|
|
2848
|
+
]
|
|
2817
2849
|
|
|
2818
2850
|
# Calculate chunk size for proper output shapes
|
|
2819
2851
|
out_chunks = np.ones(self.ndim, dtype=np.int64)
|
|
@@ -3859,7 +3891,7 @@ class ImgArray(LabeledArray):
|
|
|
3859
3891
|
|
|
3860
3892
|
out = self.view(np.ndarray).astype(np.float32)
|
|
3861
3893
|
lowerlim, upperlim = _check_clip_range(in_range, self.value)
|
|
3862
|
-
out = rescale_intensity(out, in_range=(lowerlim, upperlim), out_range=
|
|
3894
|
+
out = rescale_intensity(out, in_range=(lowerlim, upperlim), out_range=dtype)
|
|
3863
3895
|
out = out.view(self.__class__)
|
|
3864
3896
|
return out
|
|
3865
3897
|
|
|
@@ -4538,13 +4570,13 @@ def _specify_one(center, radius, shape:tuple) -> tuple[slice]:
|
|
|
4538
4570
|
|
|
4539
4571
|
def check_filter_func(f):
|
|
4540
4572
|
if f is None:
|
|
4541
|
-
|
|
4573
|
+
return lambda x: True
|
|
4542
4574
|
elif not callable(f):
|
|
4543
4575
|
raise TypeError("`filt` must be callable.")
|
|
4544
4576
|
return f
|
|
4545
4577
|
|
|
4546
4578
|
|
|
4547
|
-
def wave_num(sl: slice, s: int, uf: int) ->
|
|
4579
|
+
def wave_num(sl: slice, s: int, uf: int) -> np.ndarray:
|
|
4548
4580
|
"""
|
|
4549
4581
|
A function that makes wave number vertical vector. Returned vector will
|
|
4550
4582
|
be [k/s, (k + 1/uf)/s, (k + 2/uf)/s, ...] (where k = sl.start)
|
|
@@ -281,6 +281,12 @@ class LazyImgArray(AxesMixin):
|
|
|
281
281
|
chunk_info = ", ".join([f"{s}({o})" for s, o in zip(self.chunksize, self.axes)])
|
|
282
282
|
return chunk_info
|
|
283
283
|
|
|
284
|
+
def astype(self, dtype: DTypeLike, copy: bool = True) -> LazyImgArray:
|
|
285
|
+
"""Convert the array to the specified data type."""
|
|
286
|
+
out = self.__class__(self.value.astype(dtype, copy=copy))
|
|
287
|
+
out._set_info(self)
|
|
288
|
+
return out
|
|
289
|
+
|
|
284
290
|
def _repr_dict_(self):
|
|
285
291
|
return {
|
|
286
292
|
"name": self.name,
|
|
@@ -555,9 +561,9 @@ class LazyImgArray(AxesMixin):
|
|
|
555
561
|
dtype = self.dtype
|
|
556
562
|
all_axes = str(self.axes)
|
|
557
563
|
def _func(input: xp.ndarray, *args, **kwargs):
|
|
558
|
-
out = xp.empty(input.shape,
|
|
564
|
+
out = xp.empty(input.shape, dtype=dtype)
|
|
559
565
|
for sl in iter_slice(input.shape, c_axes, all_axes):
|
|
560
|
-
out[sl] = func(input[sl], *args, **kwargs)
|
|
566
|
+
out[sl] = func(input[sl], *args, **kwargs).astype(dtype, copy=False)
|
|
561
567
|
return out
|
|
562
568
|
depth = switch_slice(c_axes, self.axes, 0, depth)
|
|
563
569
|
return da.map_overlap(
|
|
@@ -94,9 +94,12 @@ class TiledImage(Generic[_T]):
|
|
|
94
94
|
from dask import array as da
|
|
95
95
|
|
|
96
96
|
input = da.from_array(img.value, chunks=self._chunks)
|
|
97
|
+
|
|
98
|
+
def _func(arr: np.ndarray, *args, **kwargs) -> np.ndarray:
|
|
99
|
+
return func(arr, *args, **kwargs).astype(arr.dtype, copy=False)
|
|
97
100
|
out: np.ndarray = xp.asnumpy(
|
|
98
101
|
da.map_overlap(
|
|
99
|
-
|
|
102
|
+
_func,
|
|
100
103
|
input,
|
|
101
104
|
*args,
|
|
102
105
|
depth=self.depth,
|
|
@@ -114,6 +117,7 @@ class TiledImage(Generic[_T]):
|
|
|
114
117
|
c_axes="",
|
|
115
118
|
depth=self.depth,
|
|
116
119
|
boundary=self.boundary,
|
|
120
|
+
dtype=img.dtype,
|
|
117
121
|
args=args,
|
|
118
122
|
kwargs=kwargs,
|
|
119
123
|
)
|
|
@@ -121,8 +121,11 @@ def array(
|
|
|
121
121
|
dtype = arr.dtype
|
|
122
122
|
|
|
123
123
|
axes, name = _normalize_params(axes, name, like)
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
|
|
125
|
+
if copy:
|
|
126
|
+
_arr = np.array(arr, dtype=dtype)
|
|
127
|
+
else:
|
|
128
|
+
_arr = np.asarray(arr, dtype=dtype)
|
|
126
129
|
|
|
127
130
|
# Automatically determine axes
|
|
128
131
|
if axes is None:
|
|
@@ -373,7 +373,6 @@ def _(path: str, img: ImpyArray, lazy: bool = False):
|
|
|
373
373
|
img_dask = _rechunk_to_ones(img.value)
|
|
374
374
|
writer = _MemmapArrayWriter(path, mmap.offset, img.shape, img_dask.chunksize)
|
|
375
375
|
da.store(img_dask, writer)
|
|
376
|
-
mmap.flush()
|
|
377
376
|
return
|
|
378
377
|
|
|
379
378
|
from tifffile import imwrite
|
|
@@ -471,7 +470,6 @@ def _(path: str, img: ImpyArray, lazy: bool = False):
|
|
|
471
470
|
img_dask = _rechunk_to_ones(img.value)
|
|
472
471
|
writer = _MemmapArrayWriter(path, mrc_mmap.data.offset, img.shape, img_dask.chunksize)
|
|
473
472
|
da.store(img_dask, writer)
|
|
474
|
-
mrc_mmap.flush()
|
|
475
473
|
return None
|
|
476
474
|
|
|
477
475
|
# get voxel_size
|
|
@@ -739,12 +737,13 @@ class _MemmapArrayWriter:
|
|
|
739
737
|
# sl = (0:1, 16:32, 0:1000, 0:1000)
|
|
740
738
|
|
|
741
739
|
offset = np.sum([sl[i].start * arr.strides[i] for i in range(self._border + 1)])
|
|
740
|
+
arr_ravel = arr.ravel()
|
|
742
741
|
mmap = np.memmap(
|
|
743
742
|
self._path,
|
|
744
743
|
mode="r+",
|
|
745
744
|
offset=self._offset + offset,
|
|
745
|
+
shape=arr_ravel.shape,
|
|
746
746
|
dtype=arr.dtype,
|
|
747
747
|
)
|
|
748
|
-
arr_ravel = arr.ravel()
|
|
749
748
|
mmap[:arr_ravel.size] = arr_ravel
|
|
750
749
|
mmap.flush()
|
|
@@ -21,11 +21,11 @@ def diagonal_gaussian(r, *params):
|
|
|
21
21
|
sg = params[ndim:-2]
|
|
22
22
|
z_value = np.array([(x0 - mu0)/sg0 for x0, mu0, sg0 in zip(r, mu, sg)])
|
|
23
23
|
return a * np.exp(-np.sum(z_value**2, axis=0) / 2) + b
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
class Gaussian:
|
|
26
26
|
def mu_inrange(self, low, high):
|
|
27
27
|
return np.logical_and(low<=self.mu, self.mu<=high).all()
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
def sg_inrange(self, low, high):
|
|
30
30
|
sg_ = np.abs(self.sg)
|
|
31
31
|
return np.logical_and(low<=sg_, sg_<=high).all()
|
|
@@ -36,40 +36,40 @@ class DiagonalGaussian(Gaussian):
|
|
|
36
36
|
self.mu = self.sg = self.a = self.b = None
|
|
37
37
|
else:
|
|
38
38
|
self.mu, self.sg, self.a, self.b = params
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
@property
|
|
41
41
|
def mu(self):
|
|
42
42
|
return self._mu
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
@mu.setter
|
|
45
45
|
def mu(self, value):
|
|
46
46
|
if value is None:
|
|
47
47
|
self._mu = None
|
|
48
48
|
else:
|
|
49
49
|
self._mu = np.asarray(value)
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
@property
|
|
52
52
|
def sg(self):
|
|
53
53
|
return self._sg
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
@sg.setter
|
|
56
56
|
def sg(self, value):
|
|
57
57
|
if value is None:
|
|
58
58
|
self._sg = None
|
|
59
59
|
else:
|
|
60
60
|
self._sg = np.asarray(value)
|
|
61
|
-
|
|
62
|
-
@property
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
63
|
def params(self):
|
|
64
64
|
"""Get flattened parameters."""
|
|
65
65
|
return tuple(self.mu) + tuple(self.sg) + (self.a, self.b)
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
@params.setter
|
|
68
68
|
def params(self, params:tuple):
|
|
69
69
|
self.a, self.b = params[-2:]
|
|
70
70
|
self.mu = params[:self.ndim]
|
|
71
71
|
self.sg = params[self.ndim:-2]
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
def asdict(self) -> dict[str, Any]:
|
|
74
74
|
return {
|
|
75
75
|
"mu": self.mu.tolist(),
|
|
@@ -77,12 +77,17 @@ class DiagonalGaussian(Gaussian):
|
|
|
77
77
|
"A": self.a,
|
|
78
78
|
"B": self.b,
|
|
79
79
|
}
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
@property
|
|
82
82
|
def ndim(self):
|
|
83
83
|
return self.mu.size
|
|
84
|
-
|
|
85
|
-
def fit(
|
|
84
|
+
|
|
85
|
+
def fit(
|
|
86
|
+
self,
|
|
87
|
+
data: np.ndarray,
|
|
88
|
+
method: str = "Powell",
|
|
89
|
+
mask: np.ndarray | None = None,
|
|
90
|
+
):
|
|
86
91
|
from scipy.optimize import minimize
|
|
87
92
|
if self.mu is None or self.sg is None or self.a is None or self.b is None:
|
|
88
93
|
if mask is not None:
|
|
@@ -92,7 +97,7 @@ class DiagonalGaussian(Gaussian):
|
|
|
92
97
|
else:
|
|
93
98
|
self._estimate_params(data)
|
|
94
99
|
r = np.indices(data.shape)
|
|
95
|
-
|
|
100
|
+
|
|
96
101
|
if mask is None:
|
|
97
102
|
result = minimize(
|
|
98
103
|
square,
|
|
@@ -112,30 +117,30 @@ class DiagonalGaussian(Gaussian):
|
|
|
112
117
|
method=method
|
|
113
118
|
)
|
|
114
119
|
self.params = result.x
|
|
115
|
-
|
|
120
|
+
|
|
116
121
|
return result
|
|
117
|
-
|
|
122
|
+
|
|
118
123
|
def rescale(self, scale: float):
|
|
119
124
|
self.mu *= scale
|
|
120
125
|
self.sg *= scale
|
|
121
126
|
return None
|
|
122
|
-
|
|
127
|
+
|
|
123
128
|
def shift(self, dxdy):
|
|
124
129
|
self.mu += np.array(dxdy)
|
|
125
130
|
return None
|
|
126
|
-
|
|
131
|
+
|
|
127
132
|
def generate(self, shape:tuple) -> np.ndarray:
|
|
128
133
|
r = np.indices(shape, dtype=np.float32)
|
|
129
134
|
return diagonal_gaussian(r, *self.params)
|
|
130
|
-
|
|
131
|
-
def _estimate_params(self, data:np.ndarray):
|
|
135
|
+
|
|
136
|
+
def _estimate_params(self, data: np.ndarray):
|
|
132
137
|
pass
|
|
133
138
|
|
|
134
139
|
class GaussianParticle(DiagonalGaussian):
|
|
135
140
|
def __init__(self, params=None, initial_sg=1):
|
|
136
141
|
super().__init__(params)
|
|
137
142
|
self.initial_sg = initial_sg
|
|
138
|
-
|
|
143
|
+
|
|
139
144
|
def _estimate_params(self, data:np.ndarray):
|
|
140
145
|
# n-dim argmax
|
|
141
146
|
self.mu = np.array(np.unravel_index(np.argmax(data), data.shape), dtype="float32")
|
|
@@ -151,4 +156,4 @@ class GaussianBackground(DiagonalGaussian):
|
|
|
151
156
|
self.sg = np.array(data.shape, dtype="float32")
|
|
152
157
|
self.b, p95 = np.percentile(data, [5, 95])
|
|
153
158
|
self.a = p95 - self.b
|
|
154
|
-
return None
|
|
159
|
+
return None
|
|
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
|