impy-array 2.4.5__tar.gz → 2.4.7__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.5 → impy_array-2.4.7}/PKG-INFO +3 -2
- impy_array-2.4.7/impy/__init__.py +63 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_corr.py +3 -1
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_misc.py +3 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_skimage.py +14 -3
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/big.py +0 -1
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/imgarray.py +66 -9
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/labeledarray.py +58 -9
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/lazy.py +241 -52
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/tiled.py +67 -20
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/axes/_axis.py +40 -40
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/core.py +21 -6
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/io/_mrc.py +2 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/viewer/__init__.py +1 -1
- {impy_array-2.4.5 → impy_array-2.4.7}/pyproject.toml +2 -1
- impy_array-2.4.5/impy/__init__.py +0 -43
- {impy_array-2.4.5 → impy_array-2.4.7}/.gitignore +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/LICENSE +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/README.md +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/__main__.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/_const.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/_types.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/array_api.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/__init__.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_imshow.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/__init__.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_deconv.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_docs.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_filters.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_glcm.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_linalg.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_plot.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_process_numba.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_structures.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/_utils/_transform.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/axesmixin.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/bases/__init__.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/bases/metaarray.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/bases/overload.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/label.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/phasearray.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/arrays/specials.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/axes/__init__.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/axes/_axes.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/axes/_axes_tuple.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/axes/_slicer.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/binder.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/collections.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/correlation.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/frame/__init__.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/frame/frames.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/io/__init__.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/io/_nd2.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/io/_npy.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/io/_registry.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/io/_tiff.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/io/_utils.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/io/_zarr.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/lazy/__init__.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/lazy/core.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/lazy/random.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/random.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/roi.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/utils/__init__.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/utils/axesop.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/utils/deco.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/utils/gauss.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/utils/misc.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/utils/slicer.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/utils/utilcls.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/viewer/utils.py +0 -0
- {impy_array-2.4.5 → impy_array-2.4.7}/impy/viewer/viewer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: impy-array
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.7
|
|
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>
|
|
@@ -39,6 +39,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
39
39
|
Classifier: Programming Language :: Python :: 3.10
|
|
40
40
|
Classifier: Programming Language :: Python :: 3.11
|
|
41
41
|
Classifier: Programming Language :: Python :: 3.12
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
42
43
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
43
44
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
44
45
|
Requires-Python: >=3.9
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
__version__ = "2.4.7"
|
|
2
|
+
__author__ = "Hanjin Liu"
|
|
3
|
+
__email__ = "liuhanjin-sc@g.ecc.u-tokyo.ac.jp"
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from impy._const import Const, SetConst, use # noqa
|
|
9
|
+
|
|
10
|
+
from impy.collections import DataList, DataDict # noqa
|
|
11
|
+
from impy.core import * # noqa
|
|
12
|
+
from impy.binder import bind # noqa
|
|
13
|
+
from impy.correlation import * # noqa
|
|
14
|
+
from impy.arrays import ImgArray, LazyImgArray, BigImgArray, Label # noqa
|
|
15
|
+
from impy import random, io, lazy # noqa
|
|
16
|
+
from impy.axes import slicer # noqa
|
|
17
|
+
|
|
18
|
+
# Inheritance
|
|
19
|
+
# -----------
|
|
20
|
+
#
|
|
21
|
+
# AxesMixin -----> LazyImgArray ------> BigImgArray
|
|
22
|
+
# |
|
|
23
|
+
# +-----> MetaArray --+--> LabeledArray --+--> ImgArray
|
|
24
|
+
# | | |
|
|
25
|
+
# np.ndarray +--> Label +--> PhaseArray
|
|
26
|
+
# |
|
|
27
|
+
# +--> PropArray
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
logging.getLogger("skimage").setLevel(logging.ERROR)
|
|
31
|
+
logging.getLogger("tifffile").setLevel(logging.ERROR)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
del logging
|
|
35
|
+
|
|
36
|
+
# dtypes
|
|
37
|
+
from numpy import ( # noqa
|
|
38
|
+
uint8, uint16, uint32, uint64,
|
|
39
|
+
int8, int16, int32, int64,
|
|
40
|
+
float16, float32, float64,
|
|
41
|
+
complex64, complex128,
|
|
42
|
+
bool_,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# lazy loading
|
|
46
|
+
|
|
47
|
+
_VIEWER_CACHE = None
|
|
48
|
+
if TYPE_CHECKING:
|
|
49
|
+
from impy.viewer import napariViewers
|
|
50
|
+
|
|
51
|
+
gui: "napariViewers"
|
|
52
|
+
|
|
53
|
+
def __getattr__(key):
|
|
54
|
+
global _VIEWER_CACHE
|
|
55
|
+
|
|
56
|
+
if key == "gui":
|
|
57
|
+
from impy.viewer import napariViewers
|
|
58
|
+
|
|
59
|
+
if _VIEWER_CACHE is None:
|
|
60
|
+
_VIEWER_CACHE = napariViewers()
|
|
61
|
+
return _VIEWER_CACHE
|
|
62
|
+
else:
|
|
63
|
+
raise AttributeError(f"module 'impy' has no attribute '{key}'")
|
|
@@ -34,7 +34,7 @@ def subpixel_pcc(
|
|
|
34
34
|
f0: np.ndarray,
|
|
35
35
|
f1: np.ndarray,
|
|
36
36
|
upsample_factor: int,
|
|
37
|
-
max_shifts: tuple[float, ...] | None = None,
|
|
37
|
+
max_shifts: float | tuple[float, ...] | None = None,
|
|
38
38
|
):
|
|
39
39
|
power, product = _pcc_and_power_spec(f0, f1, max_shifts)
|
|
40
40
|
maxima = xp.unravel_index(xp.argmax(power), power.shape)
|
|
@@ -60,6 +60,8 @@ def subpixel_pcc(
|
|
|
60
60
|
power = abs2(cross_correlation)
|
|
61
61
|
|
|
62
62
|
if max_shifts is not None:
|
|
63
|
+
if np.isscalar(max_shifts):
|
|
64
|
+
max_shifts = (max_shifts,) * f0.ndim
|
|
63
65
|
max_shifts = xp.asarray(max_shifts)
|
|
64
66
|
_upsampled_left_shifts = (shifts + max_shifts) * upsample_factor
|
|
65
67
|
_upsampled_right_shifts = (max_shifts - shifts) * upsample_factor
|
|
@@ -41,6 +41,9 @@ def make_rotated_axis(src, dst):
|
|
|
41
41
|
n = int(round(d))
|
|
42
42
|
return np.linspace(src, src + dr / d * (n - 1), n)
|
|
43
43
|
|
|
44
|
+
def make_rotated_axis_by_vec(src, unit_vec, n: int):
|
|
45
|
+
return np.linspace(src, src + unit_vec * (n - 1), n)
|
|
46
|
+
|
|
44
47
|
def make_pad(pad_width, dims, all_axes, **kwargs):
|
|
45
48
|
"""More flexible padding than `np.pad`."""
|
|
46
49
|
pad_width_ = []
|
|
@@ -6,8 +6,19 @@ from functools import reduce, lru_cache
|
|
|
6
6
|
|
|
7
7
|
# same as the function in skimage.filters._fft_based (available in scikit-image >= 0.19)
|
|
8
8
|
@lru_cache(maxsize=4)
|
|
9
|
-
def _get_ND_butterworth_filter(
|
|
10
|
-
|
|
9
|
+
def _get_ND_butterworth_filter(
|
|
10
|
+
shape: tuple[int, ...],
|
|
11
|
+
cutoff: float,
|
|
12
|
+
order: int,
|
|
13
|
+
high_pass: bool,
|
|
14
|
+
real: bool,
|
|
15
|
+
):
|
|
16
|
+
if cutoff == 0:
|
|
17
|
+
if high_pass:
|
|
18
|
+
wfilt = np.ones(shape, dtype=np.float32)
|
|
19
|
+
else:
|
|
20
|
+
wfilt = np.zeros(shape, dtype=np.float32)
|
|
21
|
+
return wfilt
|
|
11
22
|
ranges = []
|
|
12
23
|
for d, fc in zip(shape, cutoff):
|
|
13
24
|
axis = np.arange(-(d - 1) // 2, (d - 1) // 2 + 1, dtype=np.float32) / (d*fc)
|
|
@@ -19,4 +30,4 @@ def _get_ND_butterworth_filter(shape: tuple[int, ...], cutoff: float, order: int
|
|
|
19
30
|
wfilt = 1 / (1 + q2**order)
|
|
20
31
|
if high_pass:
|
|
21
32
|
wfilt = 1 - wfilt
|
|
22
|
-
return wfilt
|
|
33
|
+
return wfilt
|
|
@@ -31,7 +31,6 @@ class BigImgArray(LazyImgArray):
|
|
|
31
31
|
fft = wrap_method(LazyImgArray.fft)
|
|
32
32
|
ifft = wrap_method(LazyImgArray.ifft)
|
|
33
33
|
power_spectra = wrap_method(LazyImgArray.power_spectra)
|
|
34
|
-
tiled_lowpass_filter = wrap_method(LazyImgArray.tiled_lowpass_filter)
|
|
35
34
|
proj = wrap_method(LazyImgArray.proj)
|
|
36
35
|
binning = wrap_method(LazyImgArray.binning)
|
|
37
36
|
track_drift = wrap_method(LazyImgArray.track_drift)
|
|
@@ -217,13 +217,13 @@ class ImgArray(LabeledArray):
|
|
|
217
217
|
c_axes=complement_axes(dims, self.axes),
|
|
218
218
|
kwargs=dict(matrix=mx, order=order, mode=mode, cval=cval),
|
|
219
219
|
)
|
|
220
|
-
|
|
220
|
+
|
|
221
221
|
@_docs.write_docs
|
|
222
222
|
@dims_to_spatial_axes
|
|
223
223
|
@same_dtype(asfloat=True)
|
|
224
224
|
@check_input_and_output
|
|
225
225
|
def shift(
|
|
226
|
-
self, translation, order: int = 3, mode: PaddingMode = "constant",
|
|
226
|
+
self, translation, order: int = 3, mode: PaddingMode = "constant",
|
|
227
227
|
cval: float = 0, prefilter: bool | None = None, dims: Dims = None,
|
|
228
228
|
update: bool = False,
|
|
229
229
|
) -> ImgArray:
|
|
@@ -247,12 +247,11 @@ class ImgArray(LabeledArray):
|
|
|
247
247
|
cval = cval(self.value)
|
|
248
248
|
|
|
249
249
|
prefilter = prefilter or order > 1
|
|
250
|
-
mtx = _transform.compose_affine_matrix(translation=translation)
|
|
251
250
|
|
|
252
251
|
return self._apply_dask(
|
|
253
|
-
_transform.
|
|
252
|
+
_transform.shift,
|
|
254
253
|
c_axes=complement_axes(dims, self.axes),
|
|
255
|
-
kwargs=dict(
|
|
254
|
+
kwargs=dict(shift=translation, order=order, mode=mode, cval=cval,
|
|
256
255
|
prefilter=prefilter)
|
|
257
256
|
)
|
|
258
257
|
|
|
@@ -329,7 +328,9 @@ class ImgArray(LabeledArray):
|
|
|
329
328
|
out.set_scale({a: self.scale[a]/scale for a, scale in zip(self.axes, zoom_)})
|
|
330
329
|
return out
|
|
331
330
|
|
|
332
|
-
|
|
331
|
+
def log(self, eps: float = 1e-8) -> ImgArray:
|
|
332
|
+
"""Calculate natural logarithm of the image, with a small epsilon."""
|
|
333
|
+
return np.log(self.as_float() + eps)
|
|
333
334
|
|
|
334
335
|
@_docs.write_docs
|
|
335
336
|
@dims_to_spatial_axes
|
|
@@ -902,6 +903,51 @@ class ImgArray(LabeledArray):
|
|
|
902
903
|
return xp.asnumpy(out)
|
|
903
904
|
|
|
904
905
|
|
|
906
|
+
@_docs.write_docs
|
|
907
|
+
@dims_to_spatial_axes
|
|
908
|
+
@same_dtype(asfloat=True)
|
|
909
|
+
@check_input_and_output
|
|
910
|
+
def bandpass_filter(
|
|
911
|
+
self,
|
|
912
|
+
cuton: nDFloat = 0.02,
|
|
913
|
+
cutoff: nDFloat = 0.2,
|
|
914
|
+
order: float = 2,
|
|
915
|
+
*,
|
|
916
|
+
dims: Dims = None,
|
|
917
|
+
update: bool = False
|
|
918
|
+
):
|
|
919
|
+
"""
|
|
920
|
+
Butterworth band-pass filter.
|
|
921
|
+
|
|
922
|
+
Parameters
|
|
923
|
+
----------
|
|
924
|
+
cuton, cutoff : float or array-like
|
|
925
|
+
Cuton and Cutoff frequency. Fequency domain between these two values will be
|
|
926
|
+
passed.
|
|
927
|
+
order : float, default is 2
|
|
928
|
+
Steepness of cutoff.
|
|
929
|
+
{dims}{update}
|
|
930
|
+
|
|
931
|
+
Returns
|
|
932
|
+
-------
|
|
933
|
+
ImgArray
|
|
934
|
+
Filtered image
|
|
935
|
+
"""
|
|
936
|
+
from ._utils._skimage import _get_ND_butterworth_filter
|
|
937
|
+
cuton = check_nd(cuton, len(dims))
|
|
938
|
+
cutoff = check_nd(cutoff, len(dims))
|
|
939
|
+
spatial_shape = self.sizesof(dims)
|
|
940
|
+
spatial_axes = [self.axisof(a) for a in dims]
|
|
941
|
+
weight_on = _get_ND_butterworth_filter(spatial_shape, cuton, order, True, True)
|
|
942
|
+
weight_off = _get_ND_butterworth_filter(spatial_shape, cutoff, order, False, True)
|
|
943
|
+
weight = weight_off * weight_on
|
|
944
|
+
input = xp.asarray(self.value)
|
|
945
|
+
if len(dims) < self.ndim:
|
|
946
|
+
weight = add_axes(self.axes, self.shape, weight, dims)
|
|
947
|
+
out = xp.fft.irfftn(xp.asarray(weight)*xp.fft.rfftn(input, axes=spatial_axes),
|
|
948
|
+
s=spatial_shape, axes=spatial_axes)
|
|
949
|
+
return xp.asnumpy(out)
|
|
950
|
+
|
|
905
951
|
@_docs.write_docs
|
|
906
952
|
@dims_to_spatial_axes
|
|
907
953
|
@same_dtype(asfloat=True)
|
|
@@ -3939,6 +3985,7 @@ class ImgArray(LabeledArray):
|
|
|
3939
3985
|
along: AxisLike | None = None,
|
|
3940
3986
|
show_drift: bool = False,
|
|
3941
3987
|
upsample_factor: int = 10,
|
|
3988
|
+
max_shift: nDFloat | None = None,
|
|
3942
3989
|
) -> MarkerFrame:
|
|
3943
3990
|
"""
|
|
3944
3991
|
Calculate yx-directional drift using the method equivalent to
|
|
@@ -3952,6 +3999,8 @@ class ImgArray(LabeledArray):
|
|
|
3952
3999
|
If True, plot the result.
|
|
3953
4000
|
upsample_factor : int, default is 10
|
|
3954
4001
|
Up-sampling factor when calculating phase cross correlation.
|
|
4002
|
+
max_shift : tuple of float, optional
|
|
4003
|
+
Maximum shift in spatial directions.
|
|
3955
4004
|
|
|
3956
4005
|
Returns
|
|
3957
4006
|
-------
|
|
@@ -3966,7 +4015,9 @@ class ImgArray(LabeledArray):
|
|
|
3966
4015
|
raise ValueError("`along` must be single character.")
|
|
3967
4016
|
if not isinstance(upsample_factor, int):
|
|
3968
4017
|
raise TypeError(f"upsample-factor must be integer but got {type(upsample_factor)}")
|
|
3969
|
-
|
|
4018
|
+
if max_shift is not None:
|
|
4019
|
+
if np.isscalar(max_shift):
|
|
4020
|
+
max_shift = np.full(self.ndim - 1, max_shift)
|
|
3970
4021
|
result = np.zeros((self.sizeof(along), self.ndim-1), dtype=np.float32)
|
|
3971
4022
|
c_axes = complement_axes(along, self.axes)
|
|
3972
4023
|
last_img = None
|
|
@@ -3975,7 +4026,12 @@ class ImgArray(LabeledArray):
|
|
|
3975
4026
|
img = xp.asarray(img)
|
|
3976
4027
|
if last_img is not None:
|
|
3977
4028
|
result[i] = xp.asnumpy(
|
|
3978
|
-
_corr.subpixel_pcc(
|
|
4029
|
+
_corr.subpixel_pcc(
|
|
4030
|
+
last_img,
|
|
4031
|
+
img,
|
|
4032
|
+
max_shifts=max_shift,
|
|
4033
|
+
upsample_factor=upsample_factor,
|
|
4034
|
+
)[0]
|
|
3979
4035
|
)
|
|
3980
4036
|
last_img = img
|
|
3981
4037
|
else:
|
|
@@ -4000,6 +4056,7 @@ class ImgArray(LabeledArray):
|
|
|
4000
4056
|
*,
|
|
4001
4057
|
zero_ave: bool = True,
|
|
4002
4058
|
along: AxisLike | None = None,
|
|
4059
|
+
max_shift: nDFloat | None = None,
|
|
4003
4060
|
order: int = 1,
|
|
4004
4061
|
mode: str = "constant",
|
|
4005
4062
|
cval: float = 0,
|
|
@@ -4062,7 +4119,7 @@ class ImgArray(LabeledArray):
|
|
|
4062
4119
|
)
|
|
4063
4120
|
return out
|
|
4064
4121
|
|
|
4065
|
-
shift = ref.track_drift(along=along).values
|
|
4122
|
+
shift = ref.track_drift(along=along, max_shift=max_shift).values
|
|
4066
4123
|
|
|
4067
4124
|
else:
|
|
4068
4125
|
shift = np.asarray(shift, dtype=np.float32)
|
|
@@ -848,8 +848,8 @@ class LabeledArray(MetaArray):
|
|
|
848
848
|
Parameters
|
|
849
849
|
----------
|
|
850
850
|
pixel : int or array-like, default is 1
|
|
851
|
-
Number of pixels to remove. If an array is given, each axis will be cropped
|
|
852
|
-
using each value respectively.
|
|
851
|
+
Number of pixels to remove. If an array is given, each axis will be cropped
|
|
852
|
+
with different pixels, using each value respectively.
|
|
853
853
|
{dims}
|
|
854
854
|
|
|
855
855
|
Returns
|
|
@@ -869,16 +869,65 @@ class LabeledArray(MetaArray):
|
|
|
869
869
|
out = self[fmt[sl]]
|
|
870
870
|
return out
|
|
871
871
|
|
|
872
|
+
def crop_subregion(
|
|
873
|
+
self,
|
|
874
|
+
centers: Coords,
|
|
875
|
+
shape: tuple[int, int],
|
|
876
|
+
angles: float | Sequence[float] = 0,
|
|
877
|
+
*,
|
|
878
|
+
order=3,
|
|
879
|
+
) -> Self:
|
|
880
|
+
"""
|
|
881
|
+
Crop a subragion of an image.
|
|
882
|
+
|
|
883
|
+
Parameters
|
|
884
|
+
----------
|
|
885
|
+
centers : sequence of (float, float)
|
|
886
|
+
Center coordinates in pixels.
|
|
887
|
+
shape : (int, int)
|
|
888
|
+
Shape of the subregion.
|
|
889
|
+
angles : float or sequence of float, default is 0
|
|
890
|
+
Clockwise angle of the subregion.
|
|
891
|
+
{dims}
|
|
892
|
+
"""
|
|
893
|
+
if order > 1:
|
|
894
|
+
self_filt = self.spline_filter(order).value
|
|
895
|
+
else:
|
|
896
|
+
self_filt = self.value
|
|
897
|
+
centers = np.asarray(centers)
|
|
898
|
+
if np.isscalar(angles):
|
|
899
|
+
angles = [angles] * len(centers)
|
|
900
|
+
else:
|
|
901
|
+
if len(centers) != len(angles):
|
|
902
|
+
raise ValueError("Length of centers and angles must be the same.")
|
|
903
|
+
cropped_imgs = []
|
|
904
|
+
for center, angle in zip(centers, angles, strict=True):
|
|
905
|
+
center = np.asarray(center)
|
|
906
|
+
rad = np.deg2rad(angle)
|
|
907
|
+
ey = np.array([np.sin(rad), np.cos(rad)])
|
|
908
|
+
ex = np.array([np.cos(rad), -np.sin(rad)])
|
|
909
|
+
ny, nx = shape
|
|
910
|
+
origin = center - ey * (nx - 1) / 2 - ex * (ny - 1) / 2
|
|
911
|
+
ax0 = _misc.make_rotated_axis_by_vec(origin, ex, nx)
|
|
912
|
+
ax1 = _misc.make_rotated_axis_by_vec(origin, ey, ny)
|
|
913
|
+
all_coords = ax0[:, np.newaxis] + ax1[np.newaxis] - origin
|
|
914
|
+
all_coords = np.moveaxis(all_coords, -1, 0)
|
|
915
|
+
cropped_img = ndi.map_coordinates(self_filt, all_coords, prefilter=False, order=order)
|
|
916
|
+
cropped_imgs.append(cropped_img)
|
|
917
|
+
cropped_imgs = np.stack(cropped_imgs, axis=0).view(self.__class__)
|
|
918
|
+
return cropped_imgs._set_info(self, new_axes="p" + self.axes)
|
|
919
|
+
|
|
872
920
|
@_docs.write_docs
|
|
873
921
|
@check_input_and_output
|
|
874
922
|
@dims_to_spatial_axes
|
|
875
|
-
def rotated_crop(self, origin, dst1, dst2, dims=2) -> Self:
|
|
923
|
+
def rotated_crop(self, origin, dst1, dst2, *, crop_labels: bool = True, dims=2) -> Self:
|
|
876
924
|
"""
|
|
877
|
-
Crop the image at four courners of an rotated rectangle. Currently only supports
|
|
878
|
-
yx-plane. An rotated rectangle is specified with positions of a
|
|
879
|
-
and `dst2`, i.e., vectors (dst1-origin) and
|
|
880
|
-
origin
|
|
881
|
-
|
|
925
|
+
Crop the image at four courners of an rotated rectangle. Currently only supports
|
|
926
|
+
rotation within yx-plane. An rotated rectangle is specified with positions of a
|
|
927
|
+
origin and two destinations `dst1` and `dst2`, i.e., vectors (dst1-origin) and
|
|
928
|
+
(dst2-origin) represent a rotated rectangle. Let origin be the origin of a
|
|
929
|
+
xy-plane, the rotation direction from dst1 to dst2 must be counter-clockwise,
|
|
930
|
+
or the cropped image will be reversed.
|
|
882
931
|
|
|
883
932
|
Parameters
|
|
884
933
|
----------
|
|
@@ -907,7 +956,7 @@ class LabeledArray(MetaArray):
|
|
|
907
956
|
)
|
|
908
957
|
cropped_img = cropped_img.view(self.__class__)
|
|
909
958
|
cropped_img.axes = self.axes
|
|
910
|
-
if self.labels is not None:
|
|
959
|
+
if crop_labels and self.labels is not None:
|
|
911
960
|
try:
|
|
912
961
|
lbl = self.labels
|
|
913
962
|
cropped_labels = np.empty(lbl.shape[:-2] + all_coords.shape[1:], dtype=lbl.dtype)
|