impy-array 2.3.3__tar.gz → 2.4.1__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.3 → impy_array-2.4.1}/PKG-INFO +30 -12
- {impy_array-2.3.3 → impy_array-2.4.1}/README.md +29 -11
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/__init__.py +11 -11
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_deconv.py +10 -14
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_filters.py +1 -1
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_glcm.py +15 -15
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_misc.py +5 -5
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_structures.py +4 -4
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_transform.py +37 -35
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/imgarray.py +785 -726
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/io.py +107 -16
- impy_array-2.4.1/impy/lazy/__init__.py +2 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/lazy/core.py +42 -34
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/random.py +26 -27
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/utils/gauss.py +27 -22
- impy_array-2.3.3/impy/lazy/__init__.py +0 -2
- {impy_array-2.3.3 → impy_array-2.4.1}/.gitignore +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/LICENSE +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/__main__.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/_const.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/_types.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/array_api.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/__init__.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_imshow.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/__init__.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_corr.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_docs.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_linalg.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_plot.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_process_numba.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/_utils/_skimage.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/axesmixin.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/bases/__init__.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/bases/metaarray.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/bases/overload.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/big.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/label.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/labeledarray.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/lazy.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/phasearray.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/specials.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/arrays/tiled.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/axes/__init__.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/axes/_axes.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/axes/_axes_tuple.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/axes/_axis.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/axes/_slicer.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/binder.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/collections.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/core.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/correlation.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/frame/__init__.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/frame/frames.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/lazy/random.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/roi.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/utils/__init__.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/utils/axesop.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/utils/deco.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/utils/misc.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/utils/slicer.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/utils/utilcls.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/viewer/__init__.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/viewer/utils.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/impy/viewer/viewer.py +0 -0
- {impy_array-2.3.3 → impy_array-2.4.1}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: impy-array
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.1
|
|
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>
|
|
@@ -70,14 +70,17 @@ Provides-Extra: zarr
|
|
|
70
70
|
Requires-Dist: zarr; extra == 'zarr'
|
|
71
71
|
Description-Content-Type: text/markdown
|
|
72
72
|
|
|
73
|
-
[](https://github.com/hanjinliu/impy/blob/main/LICENSE)
|
|
74
|
+
[](https://pypistats.org/packages/impy-array)
|
|
74
75
|
[](https://badge.fury.io/py/impy-array)
|
|
75
76
|
|
|
76
77
|
# A numpy extension for efficient and powerful image analysis workflow
|
|
77
78
|
|
|
78
|
-
`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.
|
|
79
81
|
|
|
80
|
-
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:
|
|
81
84
|
|
|
82
85
|
- image axes
|
|
83
86
|
- scale of each axis
|
|
@@ -108,7 +111,10 @@ git clone https://github.com/hanjinliu/impy
|
|
|
108
111
|
|
|
109
112
|
### Code as fast as you speak
|
|
110
113
|
|
|
111
|
-
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**:
|
|
112
118
|
|
|
113
119
|
```python
|
|
114
120
|
import impy as ip
|
|
@@ -121,19 +127,31 @@ img_prj = np.max(img_fil, axis="z") # Z-projection (numpy is aware of image a
|
|
|
121
127
|
img_prj.imsave(f"Max-{img.name}") # Save in the same place. Don't spend time on searching for the directory!
|
|
122
128
|
```
|
|
123
129
|
|
|
124
|
-
###
|
|
130
|
+
### Supports many file formats
|
|
125
131
|
|
|
126
|
-
`impy` automatically chooses proper reader/writer according to the extension.
|
|
132
|
+
`impy` automatically chooses the proper reader/writer according to the extension.
|
|
127
133
|
|
|
128
134
|
- Tiff file (".tif", ".tiff")
|
|
129
135
|
- MRC file (".mrc", ".rec", ".st", ".map", ".map.gz")
|
|
130
136
|
- Zarr file (".zarr")
|
|
131
137
|
- Other image file (".png", ".jpg")
|
|
132
138
|
|
|
139
|
+
### Lazy loading
|
|
140
|
+
|
|
141
|
+
With the `lazy` submodule, you can easily make image processing workflows for large
|
|
142
|
+
images.
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
import impy as ip
|
|
146
|
+
|
|
147
|
+
img = ip.lazy.imread("path/to/very-large-image.tif")
|
|
148
|
+
out = img.gaussian_filter()
|
|
149
|
+
out.imsave("image_filtered.tif")
|
|
150
|
+
```
|
|
151
|
+
|
|
133
152
|
### Switch between CPU and GPU
|
|
134
153
|
|
|
135
154
|
`impy` can internally switches the functions between `numpy` and `cupy`.
|
|
136
|
-
You can use GPU for calculation very easily.
|
|
137
155
|
|
|
138
156
|
```python
|
|
139
157
|
img.gaussian_filter() # <- CPU
|
|
@@ -170,10 +188,10 @@ img.imfilter(param=1.0)
|
|
|
170
188
|
|
|
171
189
|
### Command line usage
|
|
172
190
|
|
|
173
|
-
`impy` also supports command
|
|
174
|
-
from
|
|
191
|
+
`impy` also supports command-line-based image analysis. All methods of `ImgArray` are
|
|
192
|
+
available from the command line, such as
|
|
175
193
|
|
|
176
|
-
```
|
|
194
|
+
```shell
|
|
177
195
|
impy path/to/image.tif ./output.tif --method gaussian_filter --sigma 2.0
|
|
178
196
|
```
|
|
179
197
|
|
|
@@ -186,7 +204,7 @@ out = img.gaussian_filter(sigma=2.0)
|
|
|
186
204
|
out.imsave("./output.tif")
|
|
187
205
|
```
|
|
188
206
|
|
|
189
|
-
For more complex
|
|
207
|
+
For more complex procedures, it is possible to send images directly to `IPython`
|
|
190
208
|
|
|
191
209
|
```
|
|
192
210
|
impy path/to/image.tif -i
|
|
@@ -1,11 +1,14 @@
|
|
|
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
|
-
`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.
|
|
7
9
|
|
|
8
|
-
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:
|
|
9
12
|
|
|
10
13
|
- image axes
|
|
11
14
|
- scale of each axis
|
|
@@ -36,7 +39,10 @@ git clone https://github.com/hanjinliu/impy
|
|
|
36
39
|
|
|
37
40
|
### Code as fast as you speak
|
|
38
41
|
|
|
39
|
-
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**:
|
|
40
46
|
|
|
41
47
|
```python
|
|
42
48
|
import impy as ip
|
|
@@ -49,19 +55,31 @@ img_prj = np.max(img_fil, axis="z") # Z-projection (numpy is aware of image a
|
|
|
49
55
|
img_prj.imsave(f"Max-{img.name}") # Save in the same place. Don't spend time on searching for the directory!
|
|
50
56
|
```
|
|
51
57
|
|
|
52
|
-
###
|
|
58
|
+
### Supports many file formats
|
|
53
59
|
|
|
54
|
-
`impy` automatically chooses proper reader/writer according to the extension.
|
|
60
|
+
`impy` automatically chooses the proper reader/writer according to the extension.
|
|
55
61
|
|
|
56
62
|
- Tiff file (".tif", ".tiff")
|
|
57
63
|
- MRC file (".mrc", ".rec", ".st", ".map", ".map.gz")
|
|
58
64
|
- Zarr file (".zarr")
|
|
59
65
|
- Other image file (".png", ".jpg")
|
|
60
66
|
|
|
67
|
+
### Lazy loading
|
|
68
|
+
|
|
69
|
+
With the `lazy` submodule, you can easily make image processing workflows for large
|
|
70
|
+
images.
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
import impy as ip
|
|
74
|
+
|
|
75
|
+
img = ip.lazy.imread("path/to/very-large-image.tif")
|
|
76
|
+
out = img.gaussian_filter()
|
|
77
|
+
out.imsave("image_filtered.tif")
|
|
78
|
+
```
|
|
79
|
+
|
|
61
80
|
### Switch between CPU and GPU
|
|
62
81
|
|
|
63
82
|
`impy` can internally switches the functions between `numpy` and `cupy`.
|
|
64
|
-
You can use GPU for calculation very easily.
|
|
65
83
|
|
|
66
84
|
```python
|
|
67
85
|
img.gaussian_filter() # <- CPU
|
|
@@ -98,10 +116,10 @@ img.imfilter(param=1.0)
|
|
|
98
116
|
|
|
99
117
|
### Command line usage
|
|
100
118
|
|
|
101
|
-
`impy` also supports command
|
|
102
|
-
from
|
|
119
|
+
`impy` also supports command-line-based image analysis. All methods of `ImgArray` are
|
|
120
|
+
available from the command line, such as
|
|
103
121
|
|
|
104
|
-
```
|
|
122
|
+
```shell
|
|
105
123
|
impy path/to/image.tif ./output.tif --method gaussian_filter --sigma 2.0
|
|
106
124
|
```
|
|
107
125
|
|
|
@@ -114,7 +132,7 @@ out = img.gaussian_filter(sigma=2.0)
|
|
|
114
132
|
out.imsave("./output.tif")
|
|
115
133
|
```
|
|
116
134
|
|
|
117
|
-
For more complex
|
|
135
|
+
For more complex procedures, it is possible to send images directly to `IPython`
|
|
118
136
|
|
|
119
137
|
```
|
|
120
138
|
impy path/to/image.tif -i
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
__version__ = "2.
|
|
1
|
+
__version__ = "2.4.1"
|
|
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}"
|
|
@@ -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)
|