impy-array 2.3.2__tar.gz → 2.4.0__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.3.2 → impy_array-2.4.0}/PKG-INFO +39 -9
- {impy_array-2.3.2 → impy_array-2.4.0}/README.md +24 -7
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/__init__.py +11 -11
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_deconv.py +10 -14
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_filters.py +12 -12
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_glcm.py +15 -15
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_misc.py +5 -5
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_structures.py +4 -4
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/imgarray.py +708 -681
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/io.py +160 -65
- impy_array-2.4.0/impy/lazy/__init__.py +2 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/lazy/core.py +42 -34
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/random.py +26 -27
- {impy_array-2.3.2 → impy_array-2.4.0}/pyproject.toml +21 -1
- impy_array-2.3.2/impy/lazy/__init__.py +0 -2
- {impy_array-2.3.2 → impy_array-2.4.0}/.gitignore +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/LICENSE +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/__main__.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/_const.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/_types.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/array_api.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/__init__.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_imshow.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/__init__.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_corr.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_docs.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_linalg.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_plot.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_process_numba.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_skimage.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/_utils/_transform.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/axesmixin.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/bases/__init__.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/bases/metaarray.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/bases/overload.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/big.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/label.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/labeledarray.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/lazy.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/phasearray.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/specials.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/arrays/tiled.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/axes/__init__.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/axes/_axes.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/axes/_axes_tuple.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/axes/_axis.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/axes/_slicer.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/binder.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/collections.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/core.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/correlation.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/frame/__init__.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/frame/frames.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/lazy/random.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/roi.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/utils/__init__.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/utils/axesop.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/utils/deco.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/utils/gauss.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/utils/misc.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/utils/slicer.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/utils/utilcls.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/viewer/__init__.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/viewer/utils.py +0 -0
- {impy_array-2.3.2 → impy_array-2.4.0}/impy/viewer/viewer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: impy-array
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
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>
|
|
@@ -43,28 +43,42 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
43
43
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
44
44
|
Requires-Python: >=3.9
|
|
45
45
|
Requires-Dist: dask>=2021.6.0
|
|
46
|
-
Requires-Dist: napari>=0.4.17
|
|
47
46
|
Requires-Dist: numpy>=1.22
|
|
48
47
|
Requires-Dist: pandas>=1.3
|
|
49
48
|
Requires-Dist: scikit-image>=0.20.0
|
|
50
49
|
Requires-Dist: scipy>=1.7
|
|
51
50
|
Provides-Extra: all
|
|
52
51
|
Requires-Dist: mrcfile; extra == 'all'
|
|
52
|
+
Requires-Dist: napari>=0.4.17; extra == 'all'
|
|
53
|
+
Requires-Dist: roifile; extra == 'all'
|
|
54
|
+
Requires-Dist: tifffile; extra == 'all'
|
|
53
55
|
Requires-Dist: zarr; extra == 'all'
|
|
54
56
|
Provides-Extra: mrc
|
|
55
57
|
Requires-Dist: mrcfile; extra == 'mrc'
|
|
58
|
+
Provides-Extra: napari
|
|
59
|
+
Requires-Dist: napari>=0.4.17; extra == 'napari'
|
|
60
|
+
Provides-Extra: testing
|
|
61
|
+
Requires-Dist: dask-image; extra == 'testing'
|
|
62
|
+
Requires-Dist: mrcfile; extra == 'testing'
|
|
63
|
+
Requires-Dist: pytest; extra == 'testing'
|
|
64
|
+
Requires-Dist: roifile; extra == 'testing'
|
|
65
|
+
Requires-Dist: tifffile; extra == 'testing'
|
|
66
|
+
Requires-Dist: zarr; extra == 'testing'
|
|
67
|
+
Provides-Extra: tiff
|
|
68
|
+
Requires-Dist: tifffile; extra == 'tiff'
|
|
56
69
|
Provides-Extra: zarr
|
|
57
70
|
Requires-Dist: zarr; extra == 'zarr'
|
|
58
71
|
Description-Content-Type: text/markdown
|
|
59
72
|
|
|
60
|
-
[](https://github.com/hanjinliu/impy/blob/main/LICENSE)
|
|
74
|
+
[](https://pypistats.org/packages/impy-array)
|
|
61
75
|
[](https://badge.fury.io/py/impy-array)
|
|
62
76
|
|
|
63
77
|
# A numpy extension for efficient and powerful image analysis workflow
|
|
64
78
|
|
|
65
79
|
`impy` is an all-in-one image analysis library, equipped with parallel processing, GPU support, GUI based tools and so on.
|
|
66
80
|
|
|
67
|
-
The core array, `ImgArray`, is a subclass of `numpy.ndarray`, tagged with information such as
|
|
81
|
+
The core array, `ImgArray`, is a subclass of `numpy.ndarray`, tagged with information such as
|
|
68
82
|
|
|
69
83
|
- image axes
|
|
70
84
|
- scale of each axis
|
|
@@ -79,8 +93,12 @@ Documentation is available [here](https://hanjinliu.github.io/impy/).
|
|
|
79
93
|
|
|
80
94
|
- use pip
|
|
81
95
|
|
|
82
|
-
```
|
|
96
|
+
``` sh
|
|
83
97
|
pip install impy-array
|
|
98
|
+
pip install impy-array[tiff] # with supports for reading/writing .tif files
|
|
99
|
+
pip install impy-array[mrc] # with supports for reading/writing .mrc files
|
|
100
|
+
pip install impy-array[napari] # viewer support
|
|
101
|
+
pip install impy-array[all] # install everything
|
|
84
102
|
```
|
|
85
103
|
|
|
86
104
|
- from source
|
|
@@ -104,7 +122,7 @@ img_prj = np.max(img_fil, axis="z") # Z-projection (numpy is aware of image a
|
|
|
104
122
|
img_prj.imsave(f"Max-{img.name}") # Save in the same place. Don't spend time on searching for the directory!
|
|
105
123
|
```
|
|
106
124
|
|
|
107
|
-
###
|
|
125
|
+
### Supports many file formats
|
|
108
126
|
|
|
109
127
|
`impy` automatically chooses proper reader/writer according to the extension.
|
|
110
128
|
|
|
@@ -113,10 +131,22 @@ img_prj.imsave(f"Max-{img.name}") # Save in the same place. Don't spend tim
|
|
|
113
131
|
- Zarr file (".zarr")
|
|
114
132
|
- Other image file (".png", ".jpg")
|
|
115
133
|
|
|
134
|
+
### Lazy loading
|
|
135
|
+
|
|
136
|
+
With the `lazy` submodule, you can easily make image processing workflows for large
|
|
137
|
+
images.
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
import impy as ip
|
|
141
|
+
|
|
142
|
+
img = ip.lazy.imread("path/to/very-large-image.tif")
|
|
143
|
+
out = img.gaussian_filter()
|
|
144
|
+
out.imsave("image_filtered.tif")
|
|
145
|
+
```
|
|
146
|
+
|
|
116
147
|
### Switch between CPU and GPU
|
|
117
148
|
|
|
118
149
|
`impy` can internally switches the functions between `numpy` and `cupy`.
|
|
119
|
-
You can use GPU for calculation very easily.
|
|
120
150
|
|
|
121
151
|
```python
|
|
122
152
|
img.gaussian_filter() # <- CPU
|
|
@@ -127,7 +157,7 @@ ip.Const["RESOURCE"] = "cupy" # <- globally use GPU
|
|
|
127
157
|
|
|
128
158
|
### Seamless interface between `napari`
|
|
129
159
|
|
|
130
|
-
[napari](https://github.com/napari/napari) is an interactive viewer for multi-dimensional images. `impy` has a **simple and efficient interface** with it, via the object `ip.gui`. Since `ImgArray` is tagged with image metadata, you don't have to care about axes or scales. Just run
|
|
160
|
+
[napari](https://github.com/napari/napari) is an interactive viewer for multi-dimensional images. `impy` has a **simple and efficient interface** with it, via the object `ip.gui`. Since `ImgArray` is tagged with image metadata, you don't have to care about axes or scales. Just run
|
|
131
161
|
|
|
132
162
|
```python
|
|
133
163
|
ip.gui.add(img)
|
|
@@ -156,7 +186,7 @@ img.imfilter(param=1.0)
|
|
|
156
186
|
`impy` also supports command line based image analysis. All method of `ImgArray` is available
|
|
157
187
|
from commad line, such as
|
|
158
188
|
|
|
159
|
-
```
|
|
189
|
+
```shell
|
|
160
190
|
impy path/to/image.tif ./output.tif --method gaussian_filter --sigma 2.0
|
|
161
191
|
```
|
|
162
192
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
[](https://github.com/hanjinliu/impy/blob/main/LICENSE)
|
|
2
|
+
[](https://pypistats.org/packages/impy-array)
|
|
2
3
|
[](https://badge.fury.io/py/impy-array)
|
|
3
4
|
|
|
4
5
|
# A numpy extension for efficient and powerful image analysis workflow
|
|
5
6
|
|
|
6
7
|
`impy` is an all-in-one image analysis library, equipped with parallel processing, GPU support, GUI based tools and so on.
|
|
7
8
|
|
|
8
|
-
The core array, `ImgArray`, is a subclass of `numpy.ndarray`, tagged with information such as
|
|
9
|
+
The core array, `ImgArray`, is a subclass of `numpy.ndarray`, tagged with information such as
|
|
9
10
|
|
|
10
11
|
- image axes
|
|
11
12
|
- scale of each axis
|
|
@@ -20,8 +21,12 @@ Documentation is available [here](https://hanjinliu.github.io/impy/).
|
|
|
20
21
|
|
|
21
22
|
- use pip
|
|
22
23
|
|
|
23
|
-
```
|
|
24
|
+
``` sh
|
|
24
25
|
pip install impy-array
|
|
26
|
+
pip install impy-array[tiff] # with supports for reading/writing .tif files
|
|
27
|
+
pip install impy-array[mrc] # with supports for reading/writing .mrc files
|
|
28
|
+
pip install impy-array[napari] # viewer support
|
|
29
|
+
pip install impy-array[all] # install everything
|
|
25
30
|
```
|
|
26
31
|
|
|
27
32
|
- from source
|
|
@@ -45,7 +50,7 @@ img_prj = np.max(img_fil, axis="z") # Z-projection (numpy is aware of image a
|
|
|
45
50
|
img_prj.imsave(f"Max-{img.name}") # Save in the same place. Don't spend time on searching for the directory!
|
|
46
51
|
```
|
|
47
52
|
|
|
48
|
-
###
|
|
53
|
+
### Supports many file formats
|
|
49
54
|
|
|
50
55
|
`impy` automatically chooses proper reader/writer according to the extension.
|
|
51
56
|
|
|
@@ -54,10 +59,22 @@ img_prj.imsave(f"Max-{img.name}") # Save in the same place. Don't spend tim
|
|
|
54
59
|
- Zarr file (".zarr")
|
|
55
60
|
- Other image file (".png", ".jpg")
|
|
56
61
|
|
|
62
|
+
### Lazy loading
|
|
63
|
+
|
|
64
|
+
With the `lazy` submodule, you can easily make image processing workflows for large
|
|
65
|
+
images.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import impy as ip
|
|
69
|
+
|
|
70
|
+
img = ip.lazy.imread("path/to/very-large-image.tif")
|
|
71
|
+
out = img.gaussian_filter()
|
|
72
|
+
out.imsave("image_filtered.tif")
|
|
73
|
+
```
|
|
74
|
+
|
|
57
75
|
### Switch between CPU and GPU
|
|
58
76
|
|
|
59
77
|
`impy` can internally switches the functions between `numpy` and `cupy`.
|
|
60
|
-
You can use GPU for calculation very easily.
|
|
61
78
|
|
|
62
79
|
```python
|
|
63
80
|
img.gaussian_filter() # <- CPU
|
|
@@ -68,7 +85,7 @@ ip.Const["RESOURCE"] = "cupy" # <- globally use GPU
|
|
|
68
85
|
|
|
69
86
|
### Seamless interface between `napari`
|
|
70
87
|
|
|
71
|
-
[napari](https://github.com/napari/napari) is an interactive viewer for multi-dimensional images. `impy` has a **simple and efficient interface** with it, via the object `ip.gui`. Since `ImgArray` is tagged with image metadata, you don't have to care about axes or scales. Just run
|
|
88
|
+
[napari](https://github.com/napari/napari) is an interactive viewer for multi-dimensional images. `impy` has a **simple and efficient interface** with it, via the object `ip.gui`. Since `ImgArray` is tagged with image metadata, you don't have to care about axes or scales. Just run
|
|
72
89
|
|
|
73
90
|
```python
|
|
74
91
|
ip.gui.add(img)
|
|
@@ -97,7 +114,7 @@ img.imfilter(param=1.0)
|
|
|
97
114
|
`impy` also supports command line based image analysis. All method of `ImgArray` is available
|
|
98
115
|
from commad line, such as
|
|
99
116
|
|
|
100
|
-
```
|
|
117
|
+
```shell
|
|
101
118
|
impy path/to/image.tif ./output.tif --method gaussian_filter --sigma 2.0
|
|
102
119
|
```
|
|
103
120
|
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
__version__ = "2.
|
|
1
|
+
__version__ = "2.4.0"
|
|
2
2
|
__author__ = "Hanjin Liu"
|
|
3
3
|
__email__ = "liuhanjin-sc@g.ecc.u-tokyo.ac.jp"
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
6
|
|
|
7
|
-
from ._const import Const, SetConst, use
|
|
7
|
+
from ._const import Const, SetConst, use # noqa
|
|
8
8
|
|
|
9
|
-
from .collections import DataList, DataDict
|
|
10
|
-
from .core import *
|
|
11
|
-
from .binder import bind
|
|
12
|
-
from .viewer import gui
|
|
13
|
-
from .correlation import *
|
|
14
|
-
from .arrays import ImgArray, LazyImgArray, BigImgArray, Label #
|
|
15
|
-
from . import random, io, lazy
|
|
16
|
-
from .axes import slicer
|
|
9
|
+
from .collections import DataList, DataDict # noqa
|
|
10
|
+
from .core import * # noqa
|
|
11
|
+
from .binder import bind # noqa
|
|
12
|
+
from .viewer import gui # noqa
|
|
13
|
+
from .correlation import * # noqa
|
|
14
|
+
from .arrays import ImgArray, LazyImgArray, BigImgArray, Label # noqa
|
|
15
|
+
from . import random, io, lazy # noqa
|
|
16
|
+
from .axes import slicer # noqa
|
|
17
17
|
|
|
18
18
|
# Inheritance
|
|
19
19
|
# -----------
|
|
@@ -34,7 +34,7 @@ logging.getLogger("tifffile").setLevel(logging.ERROR)
|
|
|
34
34
|
del logging
|
|
35
35
|
|
|
36
36
|
# dtypes
|
|
37
|
-
from numpy import (
|
|
37
|
+
from numpy import ( # noqa
|
|
38
38
|
uint8, uint16, uint32, uint64,
|
|
39
39
|
int8, int16, int32, int64,
|
|
40
40
|
float16, float32, float64,
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
3
|
from functools import partial
|
|
5
4
|
import numpy as np
|
|
6
5
|
from impy.array_api import xp
|
|
7
6
|
|
|
8
|
-
if TYPE_CHECKING:
|
|
9
|
-
from impy.arrays import ImgArray
|
|
10
|
-
|
|
11
7
|
try:
|
|
12
8
|
gradient = xp.gradient
|
|
13
9
|
except AttributeError:
|
|
@@ -17,18 +13,18 @@ except AttributeError:
|
|
|
17
13
|
out = numpy.gradient(a.get(), axis=axis)
|
|
18
14
|
return xp.asarray(out)
|
|
19
15
|
|
|
20
|
-
__all__ = ["wiener", "
|
|
16
|
+
__all__ = ["wiener", "richardson_lucy", "richardson_lucy_tv", "check_psf"]
|
|
21
17
|
|
|
22
18
|
def wiener(obs, psf_ft, psf_ft_conj, lmd):
|
|
23
19
|
obs = xp.asarray(obs)
|
|
24
20
|
fft = xp.fft.rfftn
|
|
25
21
|
ifft = partial(xp.fft.irfftn, s=obs.shape)
|
|
26
|
-
|
|
22
|
+
|
|
27
23
|
img_ft = fft(obs)
|
|
28
|
-
|
|
24
|
+
|
|
29
25
|
estimated = xp.real(ifft(img_ft*psf_ft_conj / (psf_ft*psf_ft_conj + lmd)))
|
|
30
26
|
return xp.fft.fftshift(estimated)
|
|
31
|
-
|
|
27
|
+
|
|
32
28
|
def richardson_lucy(obs, psf_ft, psf_ft_conj, niter, eps):
|
|
33
29
|
# Identical to the algorithm in Deconvolution.jl of Julia.
|
|
34
30
|
obs = xp.asarray(obs)
|
|
@@ -36,12 +32,12 @@ def richardson_lucy(obs, psf_ft, psf_ft_conj, niter, eps):
|
|
|
36
32
|
ifft = partial(xp.fft.irfftn, s=obs.shape)
|
|
37
33
|
conv = factor = xp.empty(obs.shape, dtype=xp.float32) # placeholder
|
|
38
34
|
estimated = xp.real(ifft(fft(obs) * psf_ft)) # initialization
|
|
39
|
-
|
|
35
|
+
|
|
40
36
|
for _ in range(niter):
|
|
41
37
|
conv[:] = ifft(fft(estimated) * psf_ft).real
|
|
42
38
|
factor[:] = ifft(fft(_safe_div(obs, conv, eps=eps)) * psf_ft_conj).real
|
|
43
39
|
estimated *= factor
|
|
44
|
-
|
|
40
|
+
|
|
45
41
|
return xp.fft.fftshift(estimated)
|
|
46
42
|
|
|
47
43
|
def richardson_lucy_tv(obs, psf_ft, psf_ft_conj, max_iter, lmd, tol, eps):
|
|
@@ -51,21 +47,21 @@ def richardson_lucy_tv(obs, psf_ft, psf_ft_conj, max_iter, lmd, tol, eps):
|
|
|
51
47
|
est_old = ifft(fft(obs) * psf_ft).real
|
|
52
48
|
est_new = xp.empty(obs.shape, dtype=xp.float32)
|
|
53
49
|
conv = factor = norm = gg = xp.empty(obs.shape, dtype=np.float32) # placeholder
|
|
54
|
-
|
|
50
|
+
|
|
55
51
|
for _ in range(max_iter):
|
|
56
52
|
conv[:] = ifft(fft(est_old) * psf_ft).real
|
|
57
53
|
factor[:] = ifft(fft(_safe_div(obs, conv, eps=eps)) * psf_ft_conj).real
|
|
58
54
|
est_new[:] = est_old * factor
|
|
59
55
|
grad = gradient(est_old)
|
|
60
56
|
norm[:] = xp.sqrt(sum(g**2 for g in grad))
|
|
61
|
-
gg[:] = sum(gradient(_safe_div(grad[i], norm, eps=1e-8), axis=i)
|
|
57
|
+
gg[:] = sum(gradient(_safe_div(grad[i], norm, eps=1e-8), axis=i)
|
|
62
58
|
for i in range(obs.ndim))
|
|
63
59
|
est_new /= (1 - lmd * gg)
|
|
64
60
|
gain = xp.sum(xp.abs(est_new - est_old))/xp.sum(xp.abs(est_old))
|
|
65
61
|
if gain < tol:
|
|
66
62
|
break
|
|
67
63
|
est_old[:] = est_new
|
|
68
|
-
|
|
64
|
+
|
|
69
65
|
return xp.fft.fftshift(est_new)
|
|
70
66
|
|
|
71
67
|
|
|
@@ -81,7 +77,7 @@ def check_psf(img_shape: tuple[int, ...], img_scale: tuple[float, ...], psf):
|
|
|
81
77
|
psf = psf(img_shape, img_scale)
|
|
82
78
|
psf = xp.asarray(psf, dtype=np.float32)
|
|
83
79
|
psf /= xp.sum(psf)
|
|
84
|
-
|
|
80
|
+
|
|
85
81
|
if img_shape != psf.shape:
|
|
86
82
|
raise ValueError(
|
|
87
83
|
f"observation and PSF have different shape: {img_shape} and {psf.shape}"
|
|
@@ -4,16 +4,16 @@ from ._linalg import hessian_eigval
|
|
|
4
4
|
from impy.array_api import xp, cupy_dispatcher
|
|
5
5
|
from scipy import ndimage as scipy_ndi
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
__all__ = ["binary_erosion",
|
|
9
|
-
"erosion"
|
|
9
|
+
"erosion",
|
|
10
10
|
"binary_dilation",
|
|
11
11
|
"dilation",
|
|
12
12
|
"binary_opening",
|
|
13
13
|
"opening",
|
|
14
14
|
"binary_closing",
|
|
15
15
|
"closing",
|
|
16
|
-
"gaussian_filter",
|
|
16
|
+
"gaussian_filter",
|
|
17
17
|
"gaussian_filter_fourier",
|
|
18
18
|
"median_filter",
|
|
19
19
|
"convolve",
|
|
@@ -124,7 +124,7 @@ def coef_filter(data, selem, mode="reflect", cval=0.0):
|
|
|
124
124
|
x2 = convolve(data**2, selem, mode=mode, cval=cval)
|
|
125
125
|
out = _safe_sqrt(xp.asnumpy(x2 - x1**2), fill=0)/xp.asnumpy(x1)
|
|
126
126
|
return out
|
|
127
|
-
|
|
127
|
+
|
|
128
128
|
def dog_filter(img, low_sigma, high_sigma, mode="reflect", cval=0.0):
|
|
129
129
|
filt_l = gaussian_filter(img, low_sigma, mode=mode, cval=cval)
|
|
130
130
|
filt_h = gaussian_filter(img, high_sigma, mode=mode, cval=cval)
|
|
@@ -164,23 +164,23 @@ def population(img, selem):
|
|
|
164
164
|
# See skimage/feature/template.py
|
|
165
165
|
def ncc_filter(img: np.ndarray, template: np.ndarray, bg=0, mode="constant"):
|
|
166
166
|
from scipy.signal import fftconvolve
|
|
167
|
-
from skimage import
|
|
167
|
+
from skimage.feature import template as skimage_template
|
|
168
168
|
ndim = template.ndim
|
|
169
|
-
_win_sum =
|
|
169
|
+
_win_sum = skimage_template._window_sum_2d if ndim == 2 else skimage_template._window_sum_3d
|
|
170
170
|
pad_width = [(w, w) for w in template.shape]
|
|
171
171
|
padimg = np.pad(img, pad_width=pad_width, mode=mode, constant_values=bg)
|
|
172
|
-
|
|
172
|
+
|
|
173
173
|
corr = fftconvolve(padimg, template[(slice(None,None,-1),)*ndim], mode="valid")[(slice(1,-1,None),)*ndim]
|
|
174
|
-
|
|
174
|
+
|
|
175
175
|
win_sum1 = _win_sum(padimg, template.shape)
|
|
176
176
|
win_sum2 = _win_sum(padimg**2, template.shape)
|
|
177
|
-
|
|
177
|
+
|
|
178
178
|
template_mean = np.mean(template)
|
|
179
179
|
template_volume = np.prod(template.shape)
|
|
180
180
|
template_ssd = np.sum((template - template_mean)**2)
|
|
181
|
-
|
|
181
|
+
|
|
182
182
|
var = (win_sum2 - win_sum1**2/template_volume) * template_ssd
|
|
183
|
-
|
|
183
|
+
|
|
184
184
|
# zero division happens when perfectly matched
|
|
185
185
|
response = np.ones_like(corr)
|
|
186
186
|
mask = var > np.finfo(np.float32).eps
|
|
@@ -192,7 +192,7 @@ def ncc_filter(img: np.ndarray, template: np.ndarray, bg=0, mode="constant"):
|
|
|
192
192
|
slices.append(slice(d0, d1))
|
|
193
193
|
out = response[tuple(slices)]
|
|
194
194
|
return out
|
|
195
|
-
|
|
195
|
+
|
|
196
196
|
def _safe_sqrt(a: np.ndarray, fill=0):
|
|
197
197
|
out = np.full(a.shape, fill, dtype=np.float32)
|
|
198
198
|
out = np.zeros_like(a)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
-
from ...collections import DataDict
|
|
3
2
|
import scipy
|
|
3
|
+
from impy.collections import DataDict
|
|
4
4
|
|
|
5
5
|
__all__ = ["glcm_props_", "check_glcm"]
|
|
6
6
|
|
|
@@ -15,7 +15,7 @@ def asm_(glcm, ref, nei):
|
|
|
15
15
|
|
|
16
16
|
def idm_(glcm, ref, nei):
|
|
17
17
|
return np.sum(glcm/(1+(ref-nei)**2), axis=(0,1))
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
def energy_(glcm, ref, nei):
|
|
20
20
|
return np.sqrt(np.sum(glcm**2, axis=(0,1)))
|
|
21
21
|
|
|
@@ -29,11 +29,11 @@ def entropy_(glcm, ref, nei):
|
|
|
29
29
|
def correlation_(glcm, ref, nei):
|
|
30
30
|
diffy = ref - np.sum(glcm * ref, axis=(0,1))
|
|
31
31
|
diffx = nei - np.sum(glcm * nei, axis=(0,1))
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
stdy = np.sqrt(np.sum(glcm*diffy**2, axis=(0,1)))
|
|
34
34
|
stdx = np.sqrt(np.sum(glcm*diffx**2, axis=(0,1)))
|
|
35
35
|
cov = np.sum(glcm*diffx*diffy, axis=(0,1))
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
out = np.empty(glcm.shape[2:], dtype=np.float32)
|
|
38
38
|
mask_0 = np.logical_or(stdx<1e-15, stdy<1e-15)
|
|
39
39
|
mask_1 = ~mask_0
|
|
@@ -73,7 +73,7 @@ propdict = {"contrast": contrast_,
|
|
|
73
73
|
def glcm_props_(data, distances, angles, levels, radius, properties):
|
|
74
74
|
outshape = (len(distances), len(angles)) + \
|
|
75
75
|
(data.shape[0]-2*radius, data.shape[1]-2*radius)
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
propout = DataDict()
|
|
78
78
|
for prop in properties:
|
|
79
79
|
if isinstance(prop, str):
|
|
@@ -82,13 +82,13 @@ def glcm_props_(data, distances, angles, levels, radius, properties):
|
|
|
82
82
|
propout[prop.__name__] = np.empty(outshape, dtype=np.float32)
|
|
83
83
|
# placeholder
|
|
84
84
|
glcm = np.empty((levels, levels, len(distances), len(angles)), dtype=np.float32)
|
|
85
|
-
|
|
85
|
+
|
|
86
86
|
ref, nei = np.indices((levels, levels), dtype=np.float32)
|
|
87
87
|
ref = ref[:, :, np.newaxis, np.newaxis]
|
|
88
88
|
nei = nei[:, :, np.newaxis, np.newaxis]
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
from ._process_numba import _calc_glcm
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
for x in range(outshape[3]):
|
|
93
93
|
for y in range(outshape[2]):
|
|
94
94
|
# calc glcm
|
|
@@ -101,7 +101,7 @@ def glcm_props_(data, distances, angles, levels, radius, properties):
|
|
|
101
101
|
else:
|
|
102
102
|
# only callable
|
|
103
103
|
propout[prop.__name__][:,:,y,x] = prop(glcm, ref, nei)
|
|
104
|
-
|
|
104
|
+
|
|
105
105
|
return propout
|
|
106
106
|
|
|
107
107
|
def check_glcm(self, bins, rescale_max):
|
|
@@ -112,22 +112,22 @@ def check_glcm(self, bins, rescale_max):
|
|
|
112
112
|
bins = 256
|
|
113
113
|
elif bins > 256:
|
|
114
114
|
raise ValueError("`bins` must be smaller than 256.")
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
if self.dtype == np.uint16:
|
|
117
117
|
self = self.as_uint8()
|
|
118
118
|
elif self.dtype == np.uint8:
|
|
119
119
|
pass
|
|
120
120
|
else:
|
|
121
121
|
raise TypeError(f"Cannot calculate comatrix of {self.dtype} image.")
|
|
122
|
-
|
|
122
|
+
|
|
123
123
|
imax = np.iinfo(self.dtype).max
|
|
124
|
-
|
|
124
|
+
|
|
125
125
|
if rescale_max:
|
|
126
126
|
scale = int(imax/self.max())
|
|
127
127
|
self *= scale
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
if (imax+1) % bins != 0 or bins > imax+1:
|
|
130
130
|
raise ValueError(f"`bins` must be a divisor of {imax+1} (max value of {self.dtype}).")
|
|
131
131
|
self = self // ((imax+1) // bins)
|
|
132
|
-
|
|
133
|
-
return self, bins, rescale_max
|
|
132
|
+
|
|
133
|
+
return self, bins, rescale_max
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
import numpy as np
|
|
3
|
-
from
|
|
3
|
+
from impy.array_api import xp
|
|
4
4
|
|
|
5
5
|
def adjust_bin(
|
|
6
6
|
img: np.ndarray,
|
|
@@ -44,12 +44,12 @@ def make_rotated_axis(src, dst):
|
|
|
44
44
|
def make_pad(pad_width, dims, all_axes, **kwargs):
|
|
45
45
|
"""More flexible padding than `np.pad`."""
|
|
46
46
|
pad_width_ = []
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
# for consistency with scipy-format
|
|
49
49
|
if "cval" in kwargs.keys():
|
|
50
50
|
kwargs["constant_values"] = kwargs["cval"]
|
|
51
51
|
kwargs.pop("cval")
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
if hasattr(pad_width, "__iter__") and len(pad_width) == len(dims):
|
|
54
54
|
pad_iter = iter(pad_width)
|
|
55
55
|
for a in all_axes:
|
|
@@ -57,7 +57,7 @@ def make_pad(pad_width, dims, all_axes, **kwargs):
|
|
|
57
57
|
pad_width_.append(next(pad_iter))
|
|
58
58
|
else:
|
|
59
59
|
pad_width_.append((0, 0))
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
elif isinstance(pad_width, int):
|
|
62
62
|
for a in all_axes:
|
|
63
63
|
if a in dims:
|
|
@@ -66,7 +66,7 @@ def make_pad(pad_width, dims, all_axes, **kwargs):
|
|
|
66
66
|
pad_width_.append((0, 0))
|
|
67
67
|
else:
|
|
68
68
|
raise TypeError(f"pad_width must be iterable or int, but got {type(pad_width)}")
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
return pad_width_
|
|
71
71
|
|
|
72
72
|
def dft(img: xp.ndarray, exps: list[xp.ndarray] = None):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import numpy as np
|
|
2
|
-
from
|
|
2
|
+
from impy.array_api import xp
|
|
3
3
|
|
|
4
4
|
def circle(radius, shape, dtype="bool"):
|
|
5
5
|
x = xp.arange(-(shape[0] - 1) / 2, (shape[0] - 1) / 2 + 1)
|
|
@@ -10,7 +10,7 @@ def circle(radius, shape, dtype="bool"):
|
|
|
10
10
|
def ball_like(radius, ndim:int):
|
|
11
11
|
half_int = int(2*radius)/2
|
|
12
12
|
L = xp.arange(-half_int, half_int + 1)
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
if ndim == 1:
|
|
15
15
|
return xp.ones(int(radius)*2+1, dtype=np.uint8)
|
|
16
16
|
elif ndim == 2:
|
|
@@ -32,9 +32,9 @@ def ball_like_odd(radius, ndim):
|
|
|
32
32
|
[1, 1, 1, 1],
|
|
33
33
|
[0, 1, 1, 0]]
|
|
34
34
|
This is not suitable for specify().
|
|
35
|
-
"""
|
|
35
|
+
"""
|
|
36
36
|
xc = int(radius)
|
|
37
37
|
l = xc*2 + 1
|
|
38
38
|
coords = xp.indices((l,)*ndim)
|
|
39
39
|
s = xp.sum((a-xc)**2 for a in coords)
|
|
40
|
-
return xp.array(s <= radius*radius, dtype=bool)
|
|
40
|
+
return xp.array(s <= radius*radius, dtype=bool)
|