arrlp 0.1.7__py3-none-any.whl
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.
- arrlp/__init__.py +23 -0
- arrlp/modules/__init__.py +0 -0
- arrlp/modules/compress_LP/__init__.py +0 -0
- arrlp/modules/compress_LP/compress.py +114 -0
- arrlp/modules/compress_LP/test_compress.py +79 -0
- arrlp/modules/convolve_LP/__init__.py +0 -0
- arrlp/modules/convolve_LP/convolve.py +67 -0
- arrlp/modules/convolve_LP/test_convolve.py +59 -0
- arrlp/modules/coordinates_LP/__init__.py +0 -0
- arrlp/modules/coordinates_LP/coordinates.py +125 -0
- arrlp/modules/coordinates_LP/test_coordinates.py +43 -0
- arrlp/modules/correlate_LP/__init__.py +0 -0
- arrlp/modules/correlate_LP/correlate.py +194 -0
- arrlp/modules/correlate_LP/test_correlate.py +58 -0
- arrlp/modules/kernel_LP/__init__.py +0 -0
- arrlp/modules/kernel_LP/kernel.py +187 -0
- arrlp/modules/kernel_LP/test_kernel.py +50 -0
- arrlp/modules/relabel_LP/__init__.py +0 -0
- arrlp/modules/relabel_LP/relabel.py +60 -0
- arrlp/modules/relabel_LP/test_relabel.py +37 -0
- arrlp/modules.json +38 -0
- arrlp/py.typed +0 -0
- arrlp/scripts/__init__.py +0 -0
- arrlp/scripts.json +1 -0
- arrlp-0.1.7.dist-info/METADATA +49 -0
- arrlp-0.1.7.dist-info/RECORD +27 -0
- arrlp-0.1.7.dist-info/WHEEL +4 -0
arrlp/__init__.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-28
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
A library providing custom functions for arrays.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# %% Lazy imports
|
|
15
|
+
from corelp import getmodule
|
|
16
|
+
__getattr__, __all__ = getmodule(__file__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# %% Test function run
|
|
21
|
+
if __name__ == "__main__":
|
|
22
|
+
from corelp import test
|
|
23
|
+
test(__file__)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-11-30
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : compress
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
Compresses an array between values by normalizing, with possibility to saturate extrema.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# %% Libraries
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# %% Function
|
|
21
|
+
def compress(array, /, max=1, min=0, *, dtype=None, white=None, black=None, white_percent=None, black_percent=None, saturate=None) :
|
|
22
|
+
'''
|
|
23
|
+
Compresses an array between values by normalizing, with possibility to saturate extrema.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
array : np.ndarray
|
|
28
|
+
Array to normalize.
|
|
29
|
+
max : int or float or None
|
|
30
|
+
white value in output. None for no changing of white
|
|
31
|
+
min : int or float or None
|
|
32
|
+
black value in output. None for no changing of black
|
|
33
|
+
dtype : np.dtype or str or None
|
|
34
|
+
dtype of output, None for same as input
|
|
35
|
+
white : int or float or None
|
|
36
|
+
white value in input. None for maximum
|
|
37
|
+
black : int or float or None
|
|
38
|
+
black value in input. None for minimum
|
|
39
|
+
white_percent : int or None
|
|
40
|
+
white percentage distribution in input if white is None.
|
|
41
|
+
black_percent : int or None
|
|
42
|
+
black percentage distribution in input if black is None.
|
|
43
|
+
saturate : Any or bool or None
|
|
44
|
+
If True, will saturate values above white and black. If Any, will replace by this value. If None no saturation.
|
|
45
|
+
|
|
46
|
+
Returns
|
|
47
|
+
-------
|
|
48
|
+
array : np.ndarray
|
|
49
|
+
Normalized and saturated copy of array.
|
|
50
|
+
|
|
51
|
+
Examples
|
|
52
|
+
--------
|
|
53
|
+
>>> from arrlp import compress
|
|
54
|
+
>>> array = np.arange(100, dtype=np.float32)
|
|
55
|
+
...
|
|
56
|
+
>>> compress(array, 10, 5) # compresses array between 10 and 5
|
|
57
|
+
>>> compress(array, white=50, black=40) # compresses array linearly so that 50 value is at 1 and 40 is at 0
|
|
58
|
+
>>> compress(array, white=50, black=40, saturate=np.nan) # compresses array linearly so that 50 value is at 1 and 40 is at 0, replace outside values by np.nan
|
|
59
|
+
>>> compress(array, white_percent=10, black=1) # compresses array linearly so that 10% of array will be white, and 1% black (without saturation)
|
|
60
|
+
>>> compress(array, white_percent=10, black=1, saturate=True) # compresses array linearly so that 10% of array will be white, and 1% black (with saturation)
|
|
61
|
+
'''
|
|
62
|
+
|
|
63
|
+
# init
|
|
64
|
+
array = np.asarray(array)
|
|
65
|
+
if dtype is None :
|
|
66
|
+
dtype = array.dtype
|
|
67
|
+
|
|
68
|
+
# Get white/black
|
|
69
|
+
if white is None :
|
|
70
|
+
white = np.nanmax(array) if white_percent is None else np.nanpercentile(array, 100-white_percent)
|
|
71
|
+
if black is None :
|
|
72
|
+
black = np.nanmin(array) if black_percent is None else np.nanpercentile(array, black_percent)
|
|
73
|
+
if white >= black :
|
|
74
|
+
raise ValueError('white >= black is not possible while compressing')
|
|
75
|
+
|
|
76
|
+
# Normalization
|
|
77
|
+
if max is not None and min is not None and min >= max :
|
|
78
|
+
raise ValueError('min >= max is not possible while compressing')
|
|
79
|
+
if max is not None :
|
|
80
|
+
array = normalization(array, value=max, norm=white, fix=black)
|
|
81
|
+
white = max
|
|
82
|
+
if min is not None :
|
|
83
|
+
array = normalization(array, value=min, norm=black, fix=white)
|
|
84
|
+
black = min
|
|
85
|
+
if max is None and min is None :
|
|
86
|
+
array = np.copy(array)
|
|
87
|
+
|
|
88
|
+
# Saturation
|
|
89
|
+
if saturate is not None :
|
|
90
|
+
if saturate is True :
|
|
91
|
+
sat_min, sat_max = min, max
|
|
92
|
+
else :
|
|
93
|
+
sat_min, sat_max = saturate, saturate
|
|
94
|
+
array[array>max] = sat_max
|
|
95
|
+
array[array<min] = sat_min
|
|
96
|
+
|
|
97
|
+
return array.astype(dtype)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def normalization(array, /, value:float=None, norm:float=None, fix:float=None):
|
|
102
|
+
'''Basic normalization process of array copy while keeping a fixed point'''
|
|
103
|
+
|
|
104
|
+
if fix is None : fix = 0
|
|
105
|
+
if norm is None : norm = max(np.nanmax(array),-np.nanmin(array))
|
|
106
|
+
if value is None : value = 1*np.sign(norm)
|
|
107
|
+
return (array-fix)/(norm-fix)*(value-fix) + fix
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# %% Test function run
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
from corelp import test
|
|
114
|
+
test(__file__)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-11-30
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : compress
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This file allows to test compress
|
|
11
|
+
|
|
12
|
+
compress : Compresses an array between values by normalizing, with possibility to saturate extrema.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# %% Libraries
|
|
18
|
+
from corelp import print, debug
|
|
19
|
+
import pytest
|
|
20
|
+
from arrlp import compress
|
|
21
|
+
debug_folder = debug(__file__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# %% Function test
|
|
26
|
+
def test_function() :
|
|
27
|
+
'''
|
|
28
|
+
Test compress function
|
|
29
|
+
'''
|
|
30
|
+
print('Hello world!')
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# %% Instance fixture
|
|
35
|
+
@pytest.fixture()
|
|
36
|
+
def instance() :
|
|
37
|
+
'''
|
|
38
|
+
Create a new instance at each test function
|
|
39
|
+
'''
|
|
40
|
+
return compress()
|
|
41
|
+
|
|
42
|
+
def test_instance(instance) :
|
|
43
|
+
'''
|
|
44
|
+
Test on fixture
|
|
45
|
+
'''
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# %% Returns test
|
|
50
|
+
@pytest.mark.parametrize("args, kwargs, expected, message", [
|
|
51
|
+
#([], {}, None, ""),
|
|
52
|
+
([], {}, None, ""),
|
|
53
|
+
])
|
|
54
|
+
def test_returns(args, kwargs, expected, message) :
|
|
55
|
+
'''
|
|
56
|
+
Test compress return values
|
|
57
|
+
'''
|
|
58
|
+
assert compress(*args, **kwargs) == expected, message
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# %% Error test
|
|
63
|
+
@pytest.mark.parametrize("args, kwargs, error, error_message", [
|
|
64
|
+
#([], {}, None, ""),
|
|
65
|
+
([], {}, None, ""),
|
|
66
|
+
])
|
|
67
|
+
def test_errors(args, kwargs, error, error_message) :
|
|
68
|
+
'''
|
|
69
|
+
Test compress error values
|
|
70
|
+
'''
|
|
71
|
+
with pytest.raises(error, match=error_message) :
|
|
72
|
+
compress(*args, **kwargs)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# %% Test function run
|
|
77
|
+
if __name__ == "__main__":
|
|
78
|
+
from corelp import test
|
|
79
|
+
test(__file__)
|
|
File without changes
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-30
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : convolve
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This function convolves two numpy arrays (1D, 2D, 3D).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# %% Libraries
|
|
16
|
+
from arrlp import correlate
|
|
17
|
+
import numpy as np
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# %% Function
|
|
22
|
+
def convolve(arr, k=None, /, out=None, **kwargs) :
|
|
23
|
+
'''
|
|
24
|
+
This function convolves two numpy arrays (1D, 2D, 3D).
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
arr : numpy.ndarray
|
|
29
|
+
first array to correlate.
|
|
30
|
+
k : numpy.ndarray
|
|
31
|
+
second array to correlate, if is None is auto created.
|
|
32
|
+
out : numpy.ndarray
|
|
33
|
+
array where to put correlation, same shape as arr, if None is auto initialized.
|
|
34
|
+
kwargs : dict
|
|
35
|
+
Parameters to pass to arrlp.correlate function.
|
|
36
|
+
|
|
37
|
+
Returns
|
|
38
|
+
-------
|
|
39
|
+
out : numpy.ndarray
|
|
40
|
+
Correlated array.
|
|
41
|
+
|
|
42
|
+
Raises
|
|
43
|
+
------
|
|
44
|
+
TypeError
|
|
45
|
+
if output shape does not match array shape.
|
|
46
|
+
|
|
47
|
+
Examples
|
|
48
|
+
--------
|
|
49
|
+
>>> from arrlp import correlate
|
|
50
|
+
...
|
|
51
|
+
>>> convolve(img, sigma=5) # Gaussian convolve
|
|
52
|
+
>>> convolve(img, window=10) # Mask convolve
|
|
53
|
+
>>> convolve(img, wl=640, NA=1.5) # Airy convolve
|
|
54
|
+
'''
|
|
55
|
+
|
|
56
|
+
if k is not None :
|
|
57
|
+
for dim in range(np.ndim(k)) :
|
|
58
|
+
k = np.flip(k, axis=dim)
|
|
59
|
+
return correlate(arr, k, out, **kwargs)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# %% Test function run
|
|
65
|
+
if __name__ == "__main__":
|
|
66
|
+
from corelp import test
|
|
67
|
+
test(__file__)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-30
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : convolve
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This file allows to test convolve
|
|
11
|
+
|
|
12
|
+
convolve : This function convolves two numpy arrays (1D, 2D, 3D).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# %% Libraries
|
|
18
|
+
from corelp import debug
|
|
19
|
+
import pytest
|
|
20
|
+
from matplotlib import pyplot as plt
|
|
21
|
+
from arrlp import kernel, convolve
|
|
22
|
+
debug_folder = debug(__file__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# %% Function test
|
|
27
|
+
@pytest.mark.parametrize("kwargs, title", [
|
|
28
|
+
({"window":10}, "Mask"),
|
|
29
|
+
({"sigma":5}, "Gaussian"),
|
|
30
|
+
({"wl":640, "NA":1.5}, "Airy"),
|
|
31
|
+
])
|
|
32
|
+
def test_function(kwargs, title) :
|
|
33
|
+
'''
|
|
34
|
+
Test correlate values
|
|
35
|
+
'''
|
|
36
|
+
|
|
37
|
+
img = kernel(pixel=5, window=1000)
|
|
38
|
+
|
|
39
|
+
plt.figure()
|
|
40
|
+
plt.imshow(img, cmap="hot")
|
|
41
|
+
plt.tight_layout()
|
|
42
|
+
plt.colorbar()
|
|
43
|
+
plt.savefig(debug_folder / f"{title}_before.png")
|
|
44
|
+
|
|
45
|
+
out = convolve(img, pixel=5, **kwargs)
|
|
46
|
+
|
|
47
|
+
plt.figure()
|
|
48
|
+
plt.imshow(out, cmap="hot")
|
|
49
|
+
plt.tight_layout()
|
|
50
|
+
plt.colorbar()
|
|
51
|
+
plt.savefig(debug_folder / f"{title}.png")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# %% Test function run
|
|
57
|
+
if __name__ == "__main__":
|
|
58
|
+
from corelp import test
|
|
59
|
+
test(__file__)
|
|
File without changes
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-30
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : coordinates
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This function will return a ndarray corresponding to the coordinates array of the input.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# %% Libraries
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# %% Function
|
|
21
|
+
def coordinates(shape, pixel=1., *, ndims=1, center=True, grid=False, origin=0.) :
|
|
22
|
+
'''
|
|
23
|
+
This function will return a ndarray corresponding to the coordinates array of the input.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
shape : int or tuple or np.ndarray
|
|
28
|
+
Describes the shape of the coordinates.
|
|
29
|
+
If int, all dimensions will have this value.
|
|
30
|
+
If tuple, corresponds to the shape.
|
|
31
|
+
If array, will take the shape attribute of the array
|
|
32
|
+
pixel : float, tuple(float)
|
|
33
|
+
Says what is the size of one bin, default is 1.
|
|
34
|
+
If tuple, corresponds to the pixel for each dimension.
|
|
35
|
+
ndims : int
|
|
36
|
+
Number of dimensions if input shape is int.
|
|
37
|
+
Will be overriden by any other input dimension.
|
|
38
|
+
center : bool or tuple(bool)
|
|
39
|
+
True to center origin, False to start by origin.
|
|
40
|
+
If tuple, defines how to place origin for each dimension.
|
|
41
|
+
grid : bool
|
|
42
|
+
True to return full meshgrid for each dimensions, False for broadcastable arrays.
|
|
43
|
+
origin : float or tuple(float)
|
|
44
|
+
Value of origin (default 0).
|
|
45
|
+
If tuple, value for each dimension.
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
coords : np.ndarray or tuple(np.ndarray)
|
|
50
|
+
for 1 dimensional shape, returns coordinates array.
|
|
51
|
+
else, return a tuple of arrays for each dimensions.
|
|
52
|
+
|
|
53
|
+
Raises
|
|
54
|
+
------
|
|
55
|
+
ValueError
|
|
56
|
+
if input or passed as tuples that do not have the good number of dimensions.
|
|
57
|
+
|
|
58
|
+
Examples
|
|
59
|
+
--------
|
|
60
|
+
>>> from arrlp import coordinates
|
|
61
|
+
...
|
|
62
|
+
>>> array = np.ones((5,4))
|
|
63
|
+
>>> coordinates = coordinates(array, pixel=10, center=(True, False), grid=False, origin=(0,3))
|
|
64
|
+
... array([[-20.], [-10.], [0.], [10.], [20.]]), array([[3., 13., 23., 33.]])
|
|
65
|
+
'''
|
|
66
|
+
|
|
67
|
+
# Manage shape argument
|
|
68
|
+
if isinstance(shape, int) :
|
|
69
|
+
shape = (shape,) * ndims
|
|
70
|
+
elif isinstance(shape, tuple) :
|
|
71
|
+
pass
|
|
72
|
+
else :
|
|
73
|
+
shape = np.shape(shape)
|
|
74
|
+
|
|
75
|
+
# Correct ndims
|
|
76
|
+
ndims = len(shape)
|
|
77
|
+
|
|
78
|
+
# Correct input dimensions
|
|
79
|
+
pixel = iterable(pixel, ndims)
|
|
80
|
+
center = iterable(center, ndims)
|
|
81
|
+
origin = iterable(origin, ndims)
|
|
82
|
+
|
|
83
|
+
#looping on shape
|
|
84
|
+
coords = []
|
|
85
|
+
for dim, (n, pix, cent, orig) in enumerate(zip(shape, pixel, center, origin)) :
|
|
86
|
+
coord = n2coord(n, pixel=pix, center=cent, origin=orig)
|
|
87
|
+
reshape = np.ones(ndims, dtype=int)
|
|
88
|
+
reshape[dim] = len(coord)
|
|
89
|
+
coord = coord.reshape(tuple(reshape))
|
|
90
|
+
coords.append(coord)
|
|
91
|
+
|
|
92
|
+
#Meshgrid
|
|
93
|
+
if ndims == 1 :
|
|
94
|
+
return coords[0]
|
|
95
|
+
elif grid :
|
|
96
|
+
return np.meshgrid(*coords, indexing='ij')
|
|
97
|
+
else :
|
|
98
|
+
return coords
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def iterable(arg, ndims) :
|
|
103
|
+
try :
|
|
104
|
+
if len(arg) != ndims :
|
|
105
|
+
raise ValueError('Argument does not have good number of dimensions')
|
|
106
|
+
else :
|
|
107
|
+
return arg
|
|
108
|
+
except TypeError :
|
|
109
|
+
return (arg,) * ndims
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def n2coord(n, pixel=1., center=False, origin=0.) :
|
|
114
|
+
if center :
|
|
115
|
+
start, stop = -(n - 1) / 2,(n - 1) / 2
|
|
116
|
+
else :
|
|
117
|
+
start,stop = 0, n - 1
|
|
118
|
+
return np.linspace(start, stop, n) * pixel + origin
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# %% Test function run
|
|
123
|
+
if __name__ == "__main__":
|
|
124
|
+
from corelp import test
|
|
125
|
+
test(__file__)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-30
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : coordinates
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This file allows to test coordinates
|
|
11
|
+
|
|
12
|
+
coordinates : This function will return a ndarray corresponding to the coordinates array of the input.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# %% Libraries
|
|
18
|
+
from corelp import debug
|
|
19
|
+
import pytest
|
|
20
|
+
import numpy as np
|
|
21
|
+
from arrlp import coordinates
|
|
22
|
+
debug_folder = debug(__file__)
|
|
23
|
+
|
|
24
|
+
print(coordinates())
|
|
25
|
+
|
|
26
|
+
# %% Returns test
|
|
27
|
+
@pytest.mark.parametrize("args, kwargs, expected, message", [
|
|
28
|
+
#([], {}, None, ""),
|
|
29
|
+
([np.ones((5,4))], {"pixel":10, "center":(True, False), "grid":False, "origin":(0,3)}, (np.array([[-20.], [-10.], [0.], [10.], [20.]]), np.array([[3., 13., 23., 33.]])), ""),
|
|
30
|
+
])
|
|
31
|
+
def test_returns(args, kwargs, expected, message) :
|
|
32
|
+
'''
|
|
33
|
+
Test coordinates return values
|
|
34
|
+
'''
|
|
35
|
+
assert (coordinates(*args, **kwargs)[0] == expected[0]).all(), message
|
|
36
|
+
assert (coordinates(*args, **kwargs)[1] == expected[1]).all(), message
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# %% Test function run
|
|
41
|
+
if __name__ == "__main__":
|
|
42
|
+
from corelp import test
|
|
43
|
+
test(__file__)
|
|
File without changes
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-30
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : correlate
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This function correlates two numpy arrays (1D, 2D, 3D).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# %% Libraries
|
|
16
|
+
from arrlp import kernel
|
|
17
|
+
from numba import njit, prange
|
|
18
|
+
import numpy as np
|
|
19
|
+
import astropy
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# %% Function
|
|
24
|
+
def correlate(arr, k=None, /, out=None, *, method="mean", **kernel_kwargs) :
|
|
25
|
+
'''
|
|
26
|
+
This function correlates two numpy arrays (1D, 2D, 3D).
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
arr : numpy.ndarray
|
|
31
|
+
first array to correlate.
|
|
32
|
+
k : numpy.ndarray
|
|
33
|
+
second array to correlate, if is None is auto created.
|
|
34
|
+
out : numpy.ndarray
|
|
35
|
+
array where to put correlation, same shape as arr, if None is auto initialized.
|
|
36
|
+
method : str
|
|
37
|
+
define function to use for correlation. Should be in ["astro", "mean", "std", "min", "max", "sum", "prod"].
|
|
38
|
+
kernel_kwargs : dict
|
|
39
|
+
Parameters passed to kernel function for auto-creation.
|
|
40
|
+
|
|
41
|
+
Returns
|
|
42
|
+
-------
|
|
43
|
+
out : numpy.ndarray
|
|
44
|
+
Correlated array.
|
|
45
|
+
|
|
46
|
+
Raises
|
|
47
|
+
------
|
|
48
|
+
TypeError
|
|
49
|
+
if output shape does not match array shape.
|
|
50
|
+
|
|
51
|
+
Examples
|
|
52
|
+
--------
|
|
53
|
+
>>> from arrlp import correlate
|
|
54
|
+
...
|
|
55
|
+
>>> correlate(img, sigma=5) # Gaussian correlation
|
|
56
|
+
>>> correlate(img, window=10) # Mask correlation
|
|
57
|
+
>>> correlate(img, wl=640, NA=1.5) # Airy correlation
|
|
58
|
+
'''
|
|
59
|
+
|
|
60
|
+
# Method
|
|
61
|
+
ndims = len(np.shape(arr))
|
|
62
|
+
method = f"{method}{ndims}"
|
|
63
|
+
|
|
64
|
+
# Kernel
|
|
65
|
+
if k is None :
|
|
66
|
+
k = kernel(ndims, **kernel_kwargs)
|
|
67
|
+
|
|
68
|
+
# Output
|
|
69
|
+
if out is None :
|
|
70
|
+
out = np.empty_like(arr)
|
|
71
|
+
if np.shape(out) != np.shape(arr) :
|
|
72
|
+
raise TypeError('Output shape does not match array shape')
|
|
73
|
+
|
|
74
|
+
# Function
|
|
75
|
+
function = function_factory(method)
|
|
76
|
+
function(arr, k, out)
|
|
77
|
+
|
|
78
|
+
return out
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
_cached = {}
|
|
83
|
+
funcs = {
|
|
84
|
+
'mean' : np.nanmean,
|
|
85
|
+
'std' : np.nanstd,
|
|
86
|
+
'min' : np.nanmin,
|
|
87
|
+
'max' : np.nanmax,
|
|
88
|
+
'sum' : np.nansum,
|
|
89
|
+
'prod' : np.nanprod,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
def function_factory(method) :
|
|
93
|
+
function = _cached.get(method, None)
|
|
94
|
+
if function is not None :
|
|
95
|
+
return function
|
|
96
|
+
|
|
97
|
+
if method.startswith("astro") :
|
|
98
|
+
if method.endswith("1") :
|
|
99
|
+
def invert(k) :
|
|
100
|
+
return k[::-1]
|
|
101
|
+
elif method.endswith("2") :
|
|
102
|
+
def invert(k) :
|
|
103
|
+
return k[::-1, ::-1]
|
|
104
|
+
elif method.endswith("3") :
|
|
105
|
+
def invert(k) :
|
|
106
|
+
return k[::-1, ::-1, ::-1]
|
|
107
|
+
else :
|
|
108
|
+
raise SyntaxError(f'Correlation error cannot be {method}')
|
|
109
|
+
|
|
110
|
+
def function(arr, k, out, *, kernel_limit=2**12) :
|
|
111
|
+
k = invert(k)
|
|
112
|
+
if k.size > kernel_limit :
|
|
113
|
+
out[:] = astropy.convolution.convolve_fft(arr, k, normalize_kernel=False)
|
|
114
|
+
else :
|
|
115
|
+
out[:] = astropy.convolution.convolve(arr, k, boundary='extend', normalize_kernel=False)
|
|
116
|
+
_cached[method] = function
|
|
117
|
+
return function
|
|
118
|
+
|
|
119
|
+
func = funcs[method[:-1]]
|
|
120
|
+
|
|
121
|
+
if method.endswith("1") :
|
|
122
|
+
@njit(parallel=True)
|
|
123
|
+
def function(arr, k, out):
|
|
124
|
+
xlim, = np.shape(arr)
|
|
125
|
+
xp, = np.shape(k)
|
|
126
|
+
xp = int(xp / 2)
|
|
127
|
+
sum = np.sum(k)
|
|
128
|
+
sizep = k.size
|
|
129
|
+
for i in prange(xlim):
|
|
130
|
+
x = i
|
|
131
|
+
xmin, xmax = max(0, x - xp), min(xlim, x + xp + 1)
|
|
132
|
+
n = (xmax - xmin)
|
|
133
|
+
if n != sizep :
|
|
134
|
+
ksum = np.sum(k[xmin - x + xp: xmax - x + xp])
|
|
135
|
+
if ksum != 0 :
|
|
136
|
+
n = n * sum / ksum
|
|
137
|
+
crop = arr[xmin:xmax] * k[xmin - x + xp: xmax - x + xp] * n
|
|
138
|
+
out[x] = func(crop)
|
|
139
|
+
|
|
140
|
+
elif method.endswith("2") :
|
|
141
|
+
|
|
142
|
+
@njit(parallel=True)
|
|
143
|
+
def function(arr, k, out):
|
|
144
|
+
ylim, xlim = np.shape(arr)
|
|
145
|
+
yp, xp = np.shape(k)
|
|
146
|
+
yp, xp = int(yp / 2),int(xp / 2)
|
|
147
|
+
sum = np.sum(k)
|
|
148
|
+
sizep = k.size
|
|
149
|
+
for y in prange(ylim):
|
|
150
|
+
for x in range(xlim) :
|
|
151
|
+
ymin, ymax = max(0, y - yp), min(ylim,y + yp + 1)
|
|
152
|
+
xmin, xmax = max(0, x - xp), min(xlim,x + xp + 1)
|
|
153
|
+
n = (ymax - ymin) * (xmax - xmin)
|
|
154
|
+
if n != sizep :
|
|
155
|
+
ksum = np.sum(k[ymin - y + yp: ymax - y + yp, xmin - x + xp: xmax - x + xp])
|
|
156
|
+
if ksum != 0 :
|
|
157
|
+
n = n * sum / ksum
|
|
158
|
+
crop = arr[ymin:ymax, xmin:xmax] * k[ymin - y + yp: ymax - y + yp, xmin - x + xp: xmax - x + xp] * n
|
|
159
|
+
out[y, x] = func(crop)
|
|
160
|
+
|
|
161
|
+
elif method.endswith("3") :
|
|
162
|
+
|
|
163
|
+
@njit(parallel=True)
|
|
164
|
+
def function(arr, k, out):
|
|
165
|
+
zlim, ylim, xlim = np.shape(arr)
|
|
166
|
+
zp, yp, xp = np.shape(k)
|
|
167
|
+
zp, yp, xp = int(zp / 2), int(yp / 2), int(xp / 2)
|
|
168
|
+
sum = np.sum(k)
|
|
169
|
+
sizep = k.size
|
|
170
|
+
for z in prange(zlim) :
|
|
171
|
+
for y in range(ylim) :
|
|
172
|
+
for x in range(xlim) :
|
|
173
|
+
zmin, zmax = max(0, z - zp), min(zlim, z + zp + 1)
|
|
174
|
+
ymin, ymax = max(0, y - yp), min(ylim, y + yp + 1)
|
|
175
|
+
xmin, xmax = max(0, x - xp), min(xlim, x + xp + 1)
|
|
176
|
+
n = (zmax - zmin) * (ymax - ymin) * (xmax - xmin)
|
|
177
|
+
if n != sizep :
|
|
178
|
+
ksum = np.sum(k[zmin - z + zp: zmax - z + zp, ymin - y + yp: ymax - y + yp, xmin - x + xp: xmax - x + xp])
|
|
179
|
+
if ksum != 0 :
|
|
180
|
+
n = n * sum / ksum
|
|
181
|
+
crop = arr[zmin: zmax, ymin: ymax, xmin: xmax] * k[zmin - z + zp: zmax - z + zp, ymin - y + yp: ymax - y + yp, xmin - x + xp: xmax - x + xp] * n
|
|
182
|
+
out[z, y, x] = func(crop)
|
|
183
|
+
|
|
184
|
+
else :
|
|
185
|
+
raise SyntaxError(f'Correlation error cannot be {method}')
|
|
186
|
+
_cached[method] = function
|
|
187
|
+
return function
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
# %% Test function run
|
|
192
|
+
if __name__ == "__main__":
|
|
193
|
+
from corelp import test
|
|
194
|
+
test(__file__)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-30
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : correlate
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This file allows to test correlate
|
|
11
|
+
|
|
12
|
+
correlate : This function correlates two numpy arrays (1D, 2D, 3D).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# %% Libraries
|
|
18
|
+
from corelp import debug
|
|
19
|
+
import pytest
|
|
20
|
+
from matplotlib import pyplot as plt
|
|
21
|
+
from arrlp import kernel, correlate
|
|
22
|
+
debug_folder = debug(__file__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# %% Function test
|
|
27
|
+
@pytest.mark.parametrize("kwargs, title", [
|
|
28
|
+
({"window":10}, "Mask"),
|
|
29
|
+
({"sigma":5}, "Gaussian"),
|
|
30
|
+
({"wl":640, "NA":1.5}, "Airy"),
|
|
31
|
+
])
|
|
32
|
+
def test_function(kwargs, title) :
|
|
33
|
+
'''
|
|
34
|
+
Test correlate values
|
|
35
|
+
'''
|
|
36
|
+
|
|
37
|
+
img = kernel(pixel=5, window=1000)
|
|
38
|
+
|
|
39
|
+
plt.figure()
|
|
40
|
+
plt.imshow(img, cmap="hot")
|
|
41
|
+
plt.tight_layout()
|
|
42
|
+
plt.colorbar()
|
|
43
|
+
plt.savefig(debug_folder / f"{title}_before.png")
|
|
44
|
+
|
|
45
|
+
out = correlate(img, pixel=5, **kwargs)
|
|
46
|
+
|
|
47
|
+
plt.figure()
|
|
48
|
+
plt.imshow(out, cmap="hot")
|
|
49
|
+
plt.tight_layout()
|
|
50
|
+
plt.colorbar()
|
|
51
|
+
plt.savefig(debug_folder / f"{title}.png")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# %% Test function run
|
|
56
|
+
if __name__ == "__main__":
|
|
57
|
+
from corelp import test
|
|
58
|
+
test(__file__)
|
|
File without changes
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-30
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : kernel
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This funtion creates kernels small arrays, mainly for convolutions.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# %% Libraries
|
|
16
|
+
from arrlp import coordinates
|
|
17
|
+
import numpy as np
|
|
18
|
+
from scipy.special import erf, erfinv, j1
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# %% Function
|
|
23
|
+
def kernel(ndims=2, pixel=1, *, dtype=np.float32, atrou=0, window=None, sigma=None, wl=None, NA=None) :
|
|
24
|
+
'''
|
|
25
|
+
This funtion creates kernels small arrays, mainly for convolutions.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
ndims : int
|
|
30
|
+
Number of dimensions.
|
|
31
|
+
pixel : int
|
|
32
|
+
Size of pixel for each dimension.
|
|
33
|
+
dtype : np.dtype
|
|
34
|
+
data type of kernel.
|
|
35
|
+
atrou : int
|
|
36
|
+
Number of trou to put for atrou algorithm, None for normal kernel.
|
|
37
|
+
window : float
|
|
38
|
+
Size of window for mask kernel.
|
|
39
|
+
sigma : float
|
|
40
|
+
Size of sigma for gaussian kernel.
|
|
41
|
+
wl : float
|
|
42
|
+
wavelength for Airy kernel.
|
|
43
|
+
NA : float
|
|
44
|
+
Numerical Aperture for Airy kernel.
|
|
45
|
+
|
|
46
|
+
Returns
|
|
47
|
+
-------
|
|
48
|
+
k : np.array
|
|
49
|
+
kernel generated.
|
|
50
|
+
|
|
51
|
+
Raises
|
|
52
|
+
------
|
|
53
|
+
SyntaxError
|
|
54
|
+
One keyword input must be put that defines type of kernel, if not will raise Error.
|
|
55
|
+
|
|
56
|
+
Examples
|
|
57
|
+
--------
|
|
58
|
+
>>> from arrlp import kernel
|
|
59
|
+
...
|
|
60
|
+
>>> kernel(window=10) # Mask
|
|
61
|
+
>>> kernel(sigma=5) # Gaussian
|
|
62
|
+
>>> kernel(wl=640, NA=1.5) # Airy
|
|
63
|
+
'''
|
|
64
|
+
|
|
65
|
+
#kernel
|
|
66
|
+
if sigma is not None :
|
|
67
|
+
k = kernel_gaus(sigma, pixel, ndims)
|
|
68
|
+
elif window is not None :
|
|
69
|
+
k = kernel_mask(window, pixel, ndims)
|
|
70
|
+
elif wl is not None and NA is not None :
|
|
71
|
+
k = kernel_airy(wl, NA, pixel, ndims)
|
|
72
|
+
else :
|
|
73
|
+
raise SyntaxError('Kernel was not recognized')
|
|
74
|
+
|
|
75
|
+
#"à trou" kernel
|
|
76
|
+
if atrou is not None and atrou != 0 :
|
|
77
|
+
k = kernel_atrou(k, atrou)
|
|
78
|
+
|
|
79
|
+
k = k.astype(dtype)
|
|
80
|
+
k /= k.sum()
|
|
81
|
+
return k
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def kernel_gaus(sigma, pixel=1, ndims=1, tol_zero=1/100) :
|
|
86
|
+
'''gets a n dimensions gaussian kernel'''
|
|
87
|
+
|
|
88
|
+
# Coordinates
|
|
89
|
+
sigma = np.asarray(iterable(sigma, ndims))
|
|
90
|
+
pixel = np.asarray(iterable(pixel, ndims))
|
|
91
|
+
shape = np.ceil(sigma * 6 / pixel)
|
|
92
|
+
shape = tuple((shape + 1 - shape % 2).astype(int)) #odd number shape
|
|
93
|
+
coords = coordinates(shape, center=True, pixel=pixel)
|
|
94
|
+
|
|
95
|
+
# Apply Gaussian on each dimension and calculates distance from origin in sigmas
|
|
96
|
+
k = 1
|
|
97
|
+
r2 = 0 # (r/sigma)²
|
|
98
|
+
for coord, sig, pix in zip(coords, sigma, pixel) :
|
|
99
|
+
mini = (coord - pix/2) / np.sqrt(2) / sig
|
|
100
|
+
maxi = (coord + pix/2) / np.sqrt(2) / sig
|
|
101
|
+
k = k * ((erf(mini) - erf(maxi)) / 2)
|
|
102
|
+
r2 = r2 + (coord / sig)**2
|
|
103
|
+
|
|
104
|
+
# Apply mask
|
|
105
|
+
mask = r2 > 2 * erfinv((1 - tol_zero)**(1/ndims))**2 # r² > (n**(1/ndims)*sqrt(2))**2
|
|
106
|
+
k[mask] = 0
|
|
107
|
+
return k
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def kernel_mask(window, pixel=1, ndims=1) :
|
|
112
|
+
'''gets a n dimensions mask kernel'''
|
|
113
|
+
|
|
114
|
+
# Coordinates
|
|
115
|
+
window = np.asarray(iterable(window, ndims))
|
|
116
|
+
pixel = np.asarray(iterable(pixel, ndims))
|
|
117
|
+
shape = np.ceil(window / pixel)
|
|
118
|
+
shape = tuple((shape + 1 - shape % 2).astype(int)) #odd number shape
|
|
119
|
+
coords = coordinates(shape, center=True, pixel=pixel)
|
|
120
|
+
|
|
121
|
+
# Calculates distance from origin in windows
|
|
122
|
+
k = np.ones(shape)
|
|
123
|
+
r2 = 0 # (r/window)²
|
|
124
|
+
for coord, win, pix in zip(coords, window, pixel) :
|
|
125
|
+
r2 = r2 + (coord / win)**2
|
|
126
|
+
|
|
127
|
+
# Apply mask
|
|
128
|
+
mask = r2 > 1/4 #r² > (1/2)**2
|
|
129
|
+
k[mask] = 0
|
|
130
|
+
return k
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def kernel_airy(wl, NA, pixel=1, ndims=1) :
|
|
135
|
+
'''gets a n dimensions mask kernel'''
|
|
136
|
+
|
|
137
|
+
# Coordinates
|
|
138
|
+
pixel = np.asarray(iterable(pixel, ndims))
|
|
139
|
+
shape = np.ceil((2.44 * wl / NA) / pixel)
|
|
140
|
+
shape = tuple((shape + 1 - shape % 2).astype(int)) #odd number shape
|
|
141
|
+
coords = coordinates(shape, center=True, pixel=pixel)
|
|
142
|
+
|
|
143
|
+
# Calculates distance from origin in nm and pixel apply Airy function
|
|
144
|
+
r2 = 0 # r²
|
|
145
|
+
for coord in coords :
|
|
146
|
+
r2 = r2 + coord**2
|
|
147
|
+
r = np.sqrt(r2)
|
|
148
|
+
z = 2 * np.pi * r * NA / wl
|
|
149
|
+
ma = r < 1 # < 1 nm
|
|
150
|
+
k = np.empty(shape, dtype=np.float32)
|
|
151
|
+
k[~ma] = (2 * j1(z[~ma]) / z[~ma])**2
|
|
152
|
+
k[ma] = 1
|
|
153
|
+
|
|
154
|
+
# Apply mask
|
|
155
|
+
mask = r2 > (1.22 * wl / NA)**2 #r² > (1.22 * wl/NA)**2
|
|
156
|
+
k[mask] = 0
|
|
157
|
+
return k
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def kernel_atrou(k, order) :
|
|
162
|
+
if order == 0 :
|
|
163
|
+
return k
|
|
164
|
+
shape = k.shape
|
|
165
|
+
newshape = tuple([s + (s - 1) * order for s in shape])
|
|
166
|
+
newkernel = np.zeros(newshape)
|
|
167
|
+
slices = [slice(None,None,order+1) for _ in range(k.ndim)]
|
|
168
|
+
newkernel[*slices] = k
|
|
169
|
+
return newkernel
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def iterable(arg, ndims) :
|
|
174
|
+
try :
|
|
175
|
+
if len(arg) != ndims :
|
|
176
|
+
raise ValueError('Argument does not have good number of dimensions')
|
|
177
|
+
else :
|
|
178
|
+
return arg
|
|
179
|
+
except TypeError :
|
|
180
|
+
return (arg,) * ndims
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
# %% Test function run
|
|
185
|
+
if __name__ == "__main__":
|
|
186
|
+
from corelp import test
|
|
187
|
+
test(__file__)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-30
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : kernel
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This file allows to test kernel
|
|
11
|
+
|
|
12
|
+
kernel : This funtion creates kernels small arrays, mainly for convolutions.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# %% Libraries
|
|
18
|
+
from corelp import debug
|
|
19
|
+
import pytest
|
|
20
|
+
from matplotlib import pyplot as plt
|
|
21
|
+
import numpy as np
|
|
22
|
+
from arrlp import kernel
|
|
23
|
+
debug_folder = debug(__file__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# %% Function test
|
|
28
|
+
@pytest.mark.parametrize("kwargs, title", [
|
|
29
|
+
({"window":500}, "Mask"),
|
|
30
|
+
({"sigma":250}, "Gaussian"),
|
|
31
|
+
({"wl":640, "NA":1.5}, "Airy"),
|
|
32
|
+
])
|
|
33
|
+
def test_function(kwargs, title) :
|
|
34
|
+
'''
|
|
35
|
+
Test kernel values
|
|
36
|
+
'''
|
|
37
|
+
k = kernel(pixel=10, **kwargs)
|
|
38
|
+
assert np.isclose(k.sum(), np.float32(1.))
|
|
39
|
+
plt.figure()
|
|
40
|
+
plt.imshow(k, cmap="hot")
|
|
41
|
+
plt.tight_layout()
|
|
42
|
+
plt.colorbar()
|
|
43
|
+
plt.savefig(debug_folder / f"{title}.png")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# %% Test function run
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
from corelp import test
|
|
50
|
+
test(__file__)
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-31
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : relabel
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This function redefines a label array to fill potential holes inside.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# %% Libraries
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
from numba import njit
|
|
19
|
+
|
|
20
|
+
@njit()
|
|
21
|
+
def relabel(array):
|
|
22
|
+
'''
|
|
23
|
+
This function redefines a label array to fill potential holes inside.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
labels : np.ndarray
|
|
28
|
+
array of labels (ints where each number > 0 corresponds to one object).
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
labels : np.ndarray
|
|
33
|
+
1D version of the corrected labels array.
|
|
34
|
+
|
|
35
|
+
Examples
|
|
36
|
+
--------
|
|
37
|
+
>>> from arrlp import relabel
|
|
38
|
+
...
|
|
39
|
+
>>> relabel(labels)
|
|
40
|
+
'''
|
|
41
|
+
|
|
42
|
+
array = array.ravel() # Flatten array
|
|
43
|
+
unique_values = np.unique(array) # Get sorted unique values
|
|
44
|
+
mapping = np.zeros(unique_values[-1] + 1, dtype=np.uint32) # Create mapping array
|
|
45
|
+
|
|
46
|
+
# Assign new sequential labels
|
|
47
|
+
for new_label, old_value in enumerate(unique_values):
|
|
48
|
+
mapping[old_value] = new_label # Map old value to new one
|
|
49
|
+
|
|
50
|
+
# Apply relabeling
|
|
51
|
+
for i in range(len(array)):
|
|
52
|
+
array[i] = mapping[array[i]]
|
|
53
|
+
|
|
54
|
+
return array.reshape((-1,)) # Return as 1D array
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# %% Test function run
|
|
58
|
+
if __name__ == "__main__":
|
|
59
|
+
from corelp import test
|
|
60
|
+
test(__file__)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Date : 2025-08-31
|
|
4
|
+
# Author : Lancelot PINCET
|
|
5
|
+
# GitHub : https://github.com/LancelotPincet
|
|
6
|
+
# Library : arrLP
|
|
7
|
+
# Module : relabel
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
This file allows to test relabel
|
|
11
|
+
|
|
12
|
+
relabel : This function redefines a label array to fill potential holes inside.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# %% Libraries
|
|
18
|
+
from corelp import print, debug
|
|
19
|
+
import pytest
|
|
20
|
+
from arrlp import relabel
|
|
21
|
+
debug_folder = debug(__file__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# %% Function test
|
|
26
|
+
def test_function() :
|
|
27
|
+
'''
|
|
28
|
+
Test relabel function
|
|
29
|
+
'''
|
|
30
|
+
print('Hello world!')
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# %% Test function run
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
from corelp import test
|
|
37
|
+
test(__file__)
|
arrlp/modules.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compress": {
|
|
3
|
+
"date": "2025-11-30",
|
|
4
|
+
"description": "Compresses an array between values by normalizing, with possibility to saturate extrema.",
|
|
5
|
+
"module": "modules/compress_LP/compress",
|
|
6
|
+
"object": "compress"
|
|
7
|
+
},
|
|
8
|
+
"convolve": {
|
|
9
|
+
"date": "2025-08-30",
|
|
10
|
+
"description": "This function convolves two numpy arrays (1D, 2D, 3D).",
|
|
11
|
+
"module": "modules/convolve_LP/convolve",
|
|
12
|
+
"object": "convolve"
|
|
13
|
+
},
|
|
14
|
+
"coordinates": {
|
|
15
|
+
"date": "2025-08-30",
|
|
16
|
+
"description": "This function will return a ndarray corresponding to the coordinates array of the input.",
|
|
17
|
+
"module": "modules/coordinates_LP/coordinates",
|
|
18
|
+
"object": "coordinates"
|
|
19
|
+
},
|
|
20
|
+
"correlate": {
|
|
21
|
+
"date": "2025-08-30",
|
|
22
|
+
"description": "This function correlates two numpy arrays (1D, 2D, 3D).",
|
|
23
|
+
"module": "modules/correlate_LP/correlate",
|
|
24
|
+
"object": "correlate"
|
|
25
|
+
},
|
|
26
|
+
"kernel": {
|
|
27
|
+
"date": "2025-08-30",
|
|
28
|
+
"description": "This funtion creates kernels small arrays, mainly for convolutions.",
|
|
29
|
+
"module": "modules/kernel_LP/kernel",
|
|
30
|
+
"object": "kernel"
|
|
31
|
+
},
|
|
32
|
+
"relabel": {
|
|
33
|
+
"date": "2025-08-31",
|
|
34
|
+
"description": "This function redefines a label array to fill potential holes inside.",
|
|
35
|
+
"module": "modules/relabel_LP/relabel",
|
|
36
|
+
"object": "relabel"
|
|
37
|
+
}
|
|
38
|
+
}
|
arrlp/py.typed
ADDED
|
File without changes
|
|
File without changes
|
arrlp/scripts.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: arrlp
|
|
3
|
+
Version: 0.1.7
|
|
4
|
+
Summary: A library providing custom functions for arrays.
|
|
5
|
+
Requires-Dist: astropy
|
|
6
|
+
Requires-Dist: corelp
|
|
7
|
+
Requires-Dist: ipykernel
|
|
8
|
+
Requires-Dist: numba
|
|
9
|
+
Requires-Dist: numpy
|
|
10
|
+
Requires-Dist: pytest
|
|
11
|
+
Requires-Dist: scipy
|
|
12
|
+
Requires-Dist: sphinx
|
|
13
|
+
Requires-Dist: sphinx-design
|
|
14
|
+
Requires-Dist: sphinx-rtd-theme
|
|
15
|
+
Requires-Dist: spyder-kernels
|
|
16
|
+
Requires-Dist: toml
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# arrLP
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
Author : Lancelot PINCET
|
|
24
|
+
GitHub : https://github.com/LancelotPincet/arrLP
|
|
25
|
+
HTTPS : https://github.com/LancelotPincet/arrLP.git
|
|
26
|
+
SSH : git@github.com:LancelotPincet/arrLP.git
|
|
27
|
+
PyPI : https://pypi.org/project/arrLP
|
|
28
|
+
Docs : https://arrLP.readthedocs.io
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**A library providing custom functions for arrays.**
|
|
32
|
+
|
|
33
|
+
arrLP is available on [PyPI](https://pypi.org/project/arrLP) for pip installs.
|
|
34
|
+
For more information, do not hesitate to consult the [Documentation](https://arrLP.readthedocs.io).
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## MIT License
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary>details</summary>
|
|
42
|
+
|
|
43
|
+
Intellectual property behind this Library is protected via an [MIT license](LICENSE). This means everyone can *freely* use it in a personnal, academic or commercial manner, if they **keep the copyright name** at the top of the codes.
|
|
44
|
+
|
|
45
|
+
The library can be redistributed, *with or without modifications*, in open or closed projects. However the **MIT license must be conserved**. For example in a commercial closed project, this means the **copyright and license must be visible somewhere**, like in the documentation or credits.
|
|
46
|
+
|
|
47
|
+
The license also explains that the **code performances are not warrantied**, and you are responsible for how you are using it. For more information on your rights and obligations please refer to [descriptive websites](https://en.wikipedia.org/wiki/MIT_License), or contact author for approvales.
|
|
48
|
+
|
|
49
|
+
</details>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
arrlp/__init__.py,sha256=EOH7t03_YW3YBcmw4MetXAWQzP8TJcJm-tYxhGIg7Sk,436
|
|
2
|
+
arrlp/modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
arrlp/modules/compress_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
arrlp/modules/compress_LP/compress.py,sha256=NGTqGjz-ZTtYy2M9XW-kimwGAeML4E1r58Urz06jgis,4011
|
|
5
|
+
arrlp/modules/compress_LP/test_compress.py,sha256=V6YwrWhNN8-89XsHwL4IPCDq4JsR3BZe7z5JzEjmnSY,1529
|
|
6
|
+
arrlp/modules/convolve_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
arrlp/modules/convolve_LP/convolve.py,sha256=Y6-aI-5k5XnRQ06ChHXRis3By7o7hWh4a5P0oDohP-8,1486
|
|
8
|
+
arrlp/modules/convolve_LP/test_convolve.py,sha256=hws1boa0xXvFLIOSKdwvgAXMU9vDcSnkZm44xS5nCP0,1198
|
|
9
|
+
arrlp/modules/coordinates_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
arrlp/modules/coordinates_LP/coordinates.py,sha256=SFxtD2iBYQjX1Eg1KBymB5Dcn2d6g7_3_XFkXcRmY04,3519
|
|
11
|
+
arrlp/modules/coordinates_LP/test_coordinates.py,sha256=Z1XQzUy6zPbcBKK4epgfUConioVwJiogUo57Y79lqdM,1165
|
|
12
|
+
arrlp/modules/correlate_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
arrlp/modules/correlate_LP/correlate.py,sha256=U0CncMqAuvccGDlLVmNRUMZLk89xwYEzMyRqoLpKNfo,6133
|
|
14
|
+
arrlp/modules/correlate_LP/test_correlate.py,sha256=KrVm2ncdxXs_yH0CFpP4t9Vlwwc6HApRXyxZjLNxdfQ,1203
|
|
15
|
+
arrlp/modules/kernel_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
+
arrlp/modules/kernel_LP/kernel.py,sha256=qhO6dOHu2WrfzTJznlsndupxh2Y52rO_KZ3DrsW-YbE,4887
|
|
17
|
+
arrlp/modules/kernel_LP/test_kernel.py,sha256=n8Jt9aebOcwPPNUFYCKLpxwivgduCgSy67uRGDCsgu8,1058
|
|
18
|
+
arrlp/modules/relabel_LP/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
arrlp/modules/relabel_LP/relabel.py,sha256=w3iNR4iyQQfaqjDIH6URX62lUllyQBxOYzLCDkDxJsg,1405
|
|
20
|
+
arrlp/modules/relabel_LP/test_relabel.py,sha256=pue00n5MVP4sog8bZFqgtu7GYf_2JtevrwHzJIIZFqk,667
|
|
21
|
+
arrlp/modules.json,sha256=ZKh2T--LLx4IuihvINbUezLGDtOG6cf64nFX6dSkIaw,1393
|
|
22
|
+
arrlp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
+
arrlp/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
+
arrlp/scripts.json,sha256=RBNvo1WzZ4oRRq0W9-hknpT7T8If536DEMBg9hyq_4o,2
|
|
25
|
+
arrlp-0.1.7.dist-info/WHEEL,sha256=NHRAbdxxzyL9K3IO2LjmlNqKSyPZnKv2BD16YYVKo18,79
|
|
26
|
+
arrlp-0.1.7.dist-info/METADATA,sha256=7Ic400MWqSTFKV1YFZWOdMbrsjtUkwXrP34ls85v7ns,1907
|
|
27
|
+
arrlp-0.1.7.dist-info/RECORD,,
|