pymodaq_utils 5.2.7__tar.gz → 5.3.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.
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/PKG-INFO +13 -13
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/README.rst +11 -11
- pymodaq_utils-5.3.0/src/pymodaq_utils/categorizing.py +61 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/factory.py +6 -4
- pymodaq_utils-5.3.0/src/pymodaq_utils/help.py +47 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/math_utils.py +89 -47
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/serialize/serializer_legacy.py +3 -4
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/utils.py +18 -3
- pymodaq_utils-5.3.0/src/pymodaq_utils/warnings.py +13 -0
- pymodaq_utils-5.2.7/src/pymodaq_utils/warnings.py +0 -10
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/.gitignore +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/LICENSE +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/pyproject.toml +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/__init__.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/abstract.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/array_manipulation.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/config.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/enums.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/environment.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/icon.ico +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/logger.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/mysocket.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/packages.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/resources/__init__.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/resources/config_template.toml +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/resources/hatch_build_plugins.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/serialize/__init__.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/serialize/factory.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/serialize/mysocket.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/serialize/serializer.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/serialize/utils.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/singleton.py +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/splash.png +0 -0
- {pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/units.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: pymodaq_utils
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.3.0
|
|
4
4
|
Summary: Modular Data Acquisition with Python
|
|
5
5
|
Project-URL: Homepage, http://pymodaq.cnrs.fr
|
|
6
6
|
Project-URL: Source, https://github.com/PyMoDAQ/PyMoDAQ
|
|
@@ -76,11 +76,11 @@ PyMoDAQ Utils
|
|
|
76
76
|
:target: https://pypi.org/project/pymodaq_utils/
|
|
77
77
|
:alt: Latest Version
|
|
78
78
|
|
|
79
|
-
.. image:: https://readthedocs.org/projects/pymodaq/badge/?version=
|
|
80
|
-
:target: https://pymodaq.readthedocs.io/en/stable/?badge=
|
|
79
|
+
.. image:: https://readthedocs.org/projects/pymodaq/badge/?version=patch-3
|
|
80
|
+
:target: https://pymodaq.readthedocs.io/en/stable/?badge=patch-3
|
|
81
81
|
:alt: Documentation Status
|
|
82
82
|
|
|
83
|
-
.. image:: https://codecov.io/gh/PyMoDAQ/PyMoDAQ/branch/
|
|
83
|
+
.. image:: https://codecov.io/gh/PyMoDAQ/PyMoDAQ/branch/patch-3/graph/badge.svg?token=IQNJRCQDM2
|
|
84
84
|
:target: https://codecov.io/gh/PyMoDAQ/PyMoDAQ
|
|
85
85
|
|
|
86
86
|
+-------------+-------------+---------------+
|
|
@@ -99,28 +99,28 @@ PyMoDAQ Utils
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
|
|
102
|
-
.. |310-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
102
|
+
.. |310-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Linux_3.10.svg
|
|
103
103
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
104
104
|
|
|
105
|
-
.. |311-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
105
|
+
.. |311-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Linux_3.11.svg
|
|
106
106
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
107
107
|
|
|
108
|
-
.. |312-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
108
|
+
.. |312-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Linux_3.12.svg
|
|
109
109
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
110
110
|
|
|
111
|
-
.. |313-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
111
|
+
.. |313-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Linux_3.13.svg
|
|
112
112
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
113
113
|
|
|
114
|
-
.. |310-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
114
|
+
.. |310-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Windows_3.10.svg
|
|
115
115
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
116
116
|
|
|
117
|
-
.. |311-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
117
|
+
.. |311-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Windows_3.11.svg
|
|
118
118
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
119
119
|
|
|
120
|
-
.. |312-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
120
|
+
.. |312-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Windows_3.12.svg
|
|
121
121
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
122
122
|
|
|
123
|
-
.. |313-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
123
|
+
.. |313-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Windows_3.13.svg
|
|
124
124
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
125
125
|
|
|
126
126
|
|
|
@@ -11,11 +11,11 @@ PyMoDAQ Utils
|
|
|
11
11
|
:target: https://pypi.org/project/pymodaq_utils/
|
|
12
12
|
:alt: Latest Version
|
|
13
13
|
|
|
14
|
-
.. image:: https://readthedocs.org/projects/pymodaq/badge/?version=
|
|
15
|
-
:target: https://pymodaq.readthedocs.io/en/stable/?badge=
|
|
14
|
+
.. image:: https://readthedocs.org/projects/pymodaq/badge/?version=patch-3
|
|
15
|
+
:target: https://pymodaq.readthedocs.io/en/stable/?badge=patch-3
|
|
16
16
|
:alt: Documentation Status
|
|
17
17
|
|
|
18
|
-
.. image:: https://codecov.io/gh/PyMoDAQ/PyMoDAQ/branch/
|
|
18
|
+
.. image:: https://codecov.io/gh/PyMoDAQ/PyMoDAQ/branch/patch-3/graph/badge.svg?token=IQNJRCQDM2
|
|
19
19
|
:target: https://codecov.io/gh/PyMoDAQ/PyMoDAQ
|
|
20
20
|
|
|
21
21
|
+-------------+-------------+---------------+
|
|
@@ -34,28 +34,28 @@ PyMoDAQ Utils
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
.. |310-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
37
|
+
.. |310-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Linux_3.10.svg
|
|
38
38
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
39
39
|
|
|
40
|
-
.. |311-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
40
|
+
.. |311-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Linux_3.11.svg
|
|
41
41
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
42
42
|
|
|
43
|
-
.. |312-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
43
|
+
.. |312-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Linux_3.12.svg
|
|
44
44
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
45
45
|
|
|
46
|
-
.. |313-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
46
|
+
.. |313-linux| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Linux_3.13.svg
|
|
47
47
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
48
48
|
|
|
49
|
-
.. |310-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
49
|
+
.. |310-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Windows_3.10.svg
|
|
50
50
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
51
51
|
|
|
52
|
-
.. |311-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
52
|
+
.. |311-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Windows_3.11.svg
|
|
53
53
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
54
54
|
|
|
55
|
-
.. |312-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
55
|
+
.. |312-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Windows_3.12.svg
|
|
56
56
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
57
57
|
|
|
58
|
-
.. |313-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/
|
|
58
|
+
.. |313-windows| image:: https://raw.githubusercontent.com/PyMoDAQ/PyMoDAQ/badges/pymodaq_utils/patch-3/tests_Windows_3.13.svg
|
|
59
59
|
:target: https://github.com/PyMoDAQ/PyMoDAQ/actions/workflows/tests-utils.yml
|
|
60
60
|
|
|
61
61
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
def categorize_items(item_list, remote_items=None, mock_items=None):
|
|
2
|
+
"""
|
|
3
|
+
Core function: categorize any list of items into Mock/Plugin/Remote.
|
|
4
|
+
|
|
5
|
+
Args:
|
|
6
|
+
item_list: List of items to categorize
|
|
7
|
+
remote_items: Custom set of remote items (optional)
|
|
8
|
+
mock_items: Custom set of mock items (optional)
|
|
9
|
+
|
|
10
|
+
Returns: dict {category: [items]} with only non-empty categories
|
|
11
|
+
"""
|
|
12
|
+
remote_items = remote_items or REMOTE_ITEMS
|
|
13
|
+
mock_items = mock_items or MOCK_ITEMS
|
|
14
|
+
|
|
15
|
+
categorized = {'Remote': [], 'Mock': [], 'Plugin': []}
|
|
16
|
+
|
|
17
|
+
for item in item_list:
|
|
18
|
+
if item in remote_items:
|
|
19
|
+
categorized['Remote'].append(item)
|
|
20
|
+
elif item in mock_items or 'mock' in item.lower():
|
|
21
|
+
categorized['Mock'].append(item)
|
|
22
|
+
else:
|
|
23
|
+
categorized['Plugin'].append(item)
|
|
24
|
+
|
|
25
|
+
# Return only non-empty categories
|
|
26
|
+
return {k: v for k, v in categorized.items() if v}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def add_category_layers(dimension_dict, remote_items=None, mock_items=None):
|
|
30
|
+
"""
|
|
31
|
+
Add category layers to a dimension dictionary.
|
|
32
|
+
Uses categorize_items for each dimension.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
dimension_dict: {dimension: [items]}
|
|
36
|
+
|
|
37
|
+
Returns: {dimension: {category: [items]}}
|
|
38
|
+
"""
|
|
39
|
+
result = {}
|
|
40
|
+
|
|
41
|
+
for dimension, items in dimension_dict.items():
|
|
42
|
+
# Reuse the core categorization function
|
|
43
|
+
result[dimension] = categorize_items(items, remote_items, mock_items)
|
|
44
|
+
|
|
45
|
+
return result
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
REMOTE_ITEMS = {'LECODirector', 'TCPServer'}
|
|
49
|
+
MOCK_ITEMS = {}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def find_last_index(list_children: list = None, name_prefix='', format_string='02.0f'):
|
|
53
|
+
if list_children is None:
|
|
54
|
+
list_children = []
|
|
55
|
+
# Custom function to find last available index
|
|
56
|
+
child_indexes = ([int(par.name()[len(name_prefix):]) for par in list_children if name_prefix in par.name()])
|
|
57
|
+
if len(child_indexes) == 0:
|
|
58
|
+
newindex = 0
|
|
59
|
+
else:
|
|
60
|
+
newindex = max(child_indexes) + 1
|
|
61
|
+
return f'{newindex:{format_string}}'
|
|
@@ -34,13 +34,15 @@ class ObjectFactory(metaclass=ABCMeta):
|
|
|
34
34
|
|
|
35
35
|
Examples
|
|
36
36
|
--------
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
::
|
|
38
|
+
|
|
39
|
+
@ObjectFactory.register('custom')
|
|
40
|
+
def my_custom_builder():
|
|
41
|
+
pass
|
|
40
42
|
|
|
41
43
|
See Also
|
|
42
44
|
--------
|
|
43
|
-
|
|
45
|
+
pymodaq_data.post_treatment.process_to_scalar.DataProcessorFactory
|
|
44
46
|
"""
|
|
45
47
|
_builders = {}
|
|
46
48
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Contextual help of the PyMoDAQ modules.
|
|
2
|
+
|
|
3
|
+
By convention, the help of a module (control module, manager, extension...) is a short markdown text stored in a file
|
|
4
|
+
named ``help.md`` in the same folder as the python file defining the module. The same text is used as the introduction
|
|
5
|
+
of the module documentation.
|
|
6
|
+
"""
|
|
7
|
+
import inspect
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from types import ModuleType
|
|
10
|
+
from typing import Optional, Union
|
|
11
|
+
|
|
12
|
+
from pymodaq_utils.logger import set_logger, get_module_name
|
|
13
|
+
|
|
14
|
+
logger = set_logger(get_module_name(__file__))
|
|
15
|
+
|
|
16
|
+
HELP_FILE_NAME = 'help.md'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_help_text(obj: Union[type, object, ModuleType, str, Path]) -> Optional[str]:
|
|
20
|
+
"""Get the markdown help text associated with a module, a class or an object
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
obj: type, object, ModuleType, str or Path
|
|
25
|
+
A class, an instance, a python module, or the path of a file (or a folder) from which the help is looked for.
|
|
26
|
+
The help file is ``help.md`` in the folder of the file defining the object.
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
str or None
|
|
31
|
+
The markdown text, None if no help file is found.
|
|
32
|
+
"""
|
|
33
|
+
if isinstance(obj, (str, Path)):
|
|
34
|
+
path = Path(obj)
|
|
35
|
+
else:
|
|
36
|
+
if not isinstance(obj, (type, ModuleType)):
|
|
37
|
+
obj = type(obj)
|
|
38
|
+
try:
|
|
39
|
+
path = Path(inspect.getfile(obj))
|
|
40
|
+
except (TypeError, OSError):
|
|
41
|
+
logger.warning(f'Could not find the source file of {obj}')
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
help_path = (path if path.is_dir() else path.parent) / HELP_FILE_NAME
|
|
45
|
+
if not help_path.is_file():
|
|
46
|
+
return None
|
|
47
|
+
return help_path.read_text(encoding='utf-8')
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import numbers
|
|
2
2
|
from typing import Union
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
import numpy as np
|
|
6
6
|
from numbers import Number
|
|
7
7
|
from typing import List, Union, Tuple
|
|
@@ -12,6 +12,31 @@ from pint import Quantity
|
|
|
12
12
|
logger = set_logger(get_module_name(__file__))
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
|
|
16
|
+
def get_si_prefix(number) -> tuple[Number, str]:
|
|
17
|
+
if number == 0:
|
|
18
|
+
return 0, ""
|
|
19
|
+
|
|
20
|
+
# Standard SI prefixes organized by their 10^(3*tier) powers
|
|
21
|
+
prefixes = {
|
|
22
|
+
24: 'Y', 21: 'Z', 18: 'E', 15: 'P', 12: 'T', 9: 'G', 6: 'M', 3: 'k',
|
|
23
|
+
0: '',
|
|
24
|
+
-3: 'm', -6: 'µ', -9: 'n', -12: 'p', -15: 'f', -18: 'a', -21: 'z', -24: 'y'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# Calculate the exponent tier (multiples of 3)
|
|
28
|
+
exponent = np.floor(np.log10(abs(number)) / 3) * 3
|
|
29
|
+
|
|
30
|
+
# Clip to maximum/minimum available prefixes
|
|
31
|
+
exponent = max(-24, min(24, exponent))
|
|
32
|
+
|
|
33
|
+
# Calculate the scaled number component
|
|
34
|
+
scaled_value = number / (10 ** exponent)
|
|
35
|
+
prefix_symbol = prefixes[exponent]
|
|
36
|
+
|
|
37
|
+
return scaled_value, prefix_symbol
|
|
38
|
+
|
|
39
|
+
|
|
15
40
|
def my_moment(x, y):
|
|
16
41
|
"""Returns the moments of a distribution y over an axe x
|
|
17
42
|
|
|
@@ -165,7 +190,14 @@ def find_index(x, threshold: Union[Number, List[Number]]) -> List[tuple]:
|
|
|
165
190
|
threshold = [threshold]
|
|
166
191
|
out = []
|
|
167
192
|
for value in threshold:
|
|
168
|
-
|
|
193
|
+
if np.any(np.isnan(x)):
|
|
194
|
+
try:
|
|
195
|
+
ix = int(np.nanargmin(np.abs(x - value)))
|
|
196
|
+
except ValueError:
|
|
197
|
+
x = np.nan_to_num(x, nan=np.max(x))
|
|
198
|
+
ix = int(np.argmin(np.abs(x - value)))
|
|
199
|
+
else:
|
|
200
|
+
ix = int(np.argmin(np.abs(x - value)))
|
|
169
201
|
out.append((ix, x[ix]))
|
|
170
202
|
return out
|
|
171
203
|
|
|
@@ -455,28 +487,29 @@ def flatten(xs):
|
|
|
455
487
|
class LSqEllipse:
|
|
456
488
|
|
|
457
489
|
def fit(self, data):
|
|
458
|
-
"""
|
|
490
|
+
"""Least Squares fitting algorithm
|
|
459
491
|
|
|
460
492
|
Theory taken from (*)
|
|
461
|
-
Solving equation Sa=lCa
|
|
462
|
-
a2 = |d f g>
|
|
493
|
+
Solving equation ``Sa=lCa``, with ``a = |a b c d f g>``, ``a1 = |a b c>`` and ``a2 = |d f g>``
|
|
463
494
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
data
|
|
467
|
-
|
|
495
|
+
Parameters
|
|
496
|
+
----------
|
|
497
|
+
data: list of list of float
|
|
498
|
+
list of two lists containing the x and y data of the ellipse, of the form
|
|
499
|
+
``[[x1, x2, ..., xi],[y1, y2, ..., yi]]``
|
|
468
500
|
|
|
469
501
|
Returns
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
502
|
+
-------
|
|
503
|
+
list
|
|
504
|
+
the coefficients ``[a,b,c,d,f,g]`` describing an ellipse corresponding to
|
|
505
|
+
``ax**2+2bxy+cy**2+2dx+2fy+g``
|
|
473
506
|
"""
|
|
474
|
-
x, y =
|
|
507
|
+
x, y = np.asarray(data, dtype=float)
|
|
475
508
|
|
|
476
509
|
# Quadratic part of design matrix [eqn. 15] from (*)
|
|
477
|
-
D1 =
|
|
510
|
+
D1 = np.mat(np.vstack([x ** 2, x * y, y ** 2])).T
|
|
478
511
|
# Linear part of design matrix [eqn. 16] from (*)
|
|
479
|
-
D2 =
|
|
512
|
+
D2 = np.mat(np.vstack([x, y, np.ones(len(x))])).T
|
|
480
513
|
|
|
481
514
|
# forming scatter matrix [eqn. 17] from (*)
|
|
482
515
|
S1 = D1.T * D1
|
|
@@ -484,23 +517,23 @@ class LSqEllipse:
|
|
|
484
517
|
S3 = D2.T * D2
|
|
485
518
|
|
|
486
519
|
# Constraint matrix [eqn. 18]
|
|
487
|
-
C1 =
|
|
520
|
+
C1 = np.mat('0. 0. 2.; 0. -1. 0.; 2. 0. 0.')
|
|
488
521
|
|
|
489
522
|
# Reduced scatter matrix [eqn. 29]
|
|
490
523
|
M = C1.I * (S1 - S2 * S3.I * S2.T)
|
|
491
524
|
|
|
492
525
|
# M*|a b c >=l|a b c >. Find eigenvalues and eigenvectors from this equation [eqn. 28]
|
|
493
|
-
eval, evec =
|
|
526
|
+
eval, evec = np.linalg.eig(M)
|
|
494
527
|
|
|
495
528
|
# eigenvector must meet constraint 4ac - b^2 to be valid.
|
|
496
|
-
cond = 4 *
|
|
497
|
-
a1 = evec[:,
|
|
529
|
+
cond = 4 * np.multiply(evec[0, :], evec[2, :]) - np.power(evec[1, :], 2)
|
|
530
|
+
a1 = evec[:, np.nonzero(cond.A > 0)[1]]
|
|
498
531
|
|
|
499
532
|
# |d f g> = -S3^(-1)*S2^(T)*|a b c> [eqn. 24]
|
|
500
533
|
a2 = -S3.I * S2.T * a1
|
|
501
534
|
|
|
502
535
|
# eigenvectors |a b c d f g>
|
|
503
|
-
self.coef =
|
|
536
|
+
self.coef = np.vstack([a1, a2])
|
|
504
537
|
self._save_parameters()
|
|
505
538
|
|
|
506
539
|
def _save_parameters(self):
|
|
@@ -508,17 +541,22 @@ class LSqEllipse:
|
|
|
508
541
|
|
|
509
542
|
Theory taken form http://mathworld.wolfram
|
|
510
543
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
coef
|
|
514
|
-
|
|
544
|
+
Parameters
|
|
545
|
+
----------
|
|
546
|
+
coef: list
|
|
547
|
+
list of the coefficients describing an ellipse ``[a,b,c,d,f,g]`` corresponding to
|
|
548
|
+
``ax**2+2bxy+cy**2+2dx+2fy+g``
|
|
515
549
|
|
|
516
550
|
Returns
|
|
517
|
-
|
|
518
|
-
center
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
551
|
+
-------
|
|
552
|
+
center: list
|
|
553
|
+
of the form [x0, y0]
|
|
554
|
+
width: float
|
|
555
|
+
major axis
|
|
556
|
+
height: float
|
|
557
|
+
minor axis
|
|
558
|
+
phi: float
|
|
559
|
+
rotation of major axis form the x-axis in radians
|
|
522
560
|
"""
|
|
523
561
|
|
|
524
562
|
# eigenvectors are the coefficients of an ellipse in general form
|
|
@@ -536,14 +574,14 @@ class LSqEllipse:
|
|
|
536
574
|
|
|
537
575
|
# Find the semi-axes lengths [eqn. 21 and 22] from (**)
|
|
538
576
|
numerator = 2 * (a * f * f + c * d * d + g * b * b - 2 * b * d * f - a * c * g)
|
|
539
|
-
denominator1 = (b * b - a * c) * ((c - a) *
|
|
540
|
-
denominator2 = (b * b - a * c) * ((a - c) *
|
|
541
|
-
width =
|
|
542
|
-
height =
|
|
577
|
+
denominator1 = (b * b - a * c) * ((c - a) * np.sqrt(1 + 4 * b * b / ((a - c) * (a - c))) - (c + a))
|
|
578
|
+
denominator2 = (b * b - a * c) * ((a - c) * np.sqrt(1 + 4 * b * b / ((a - c) * (a - c))) - (c + a))
|
|
579
|
+
width = np.sqrt(numerator / denominator1)
|
|
580
|
+
height = np.sqrt(numerator / denominator2)
|
|
543
581
|
|
|
544
582
|
# angle of counterclockwise rotation of major-axis of ellipse to x-axis [eqn. 23] from (**)
|
|
545
583
|
# or [eqn. 26] from (***).
|
|
546
|
-
phi = .5 *
|
|
584
|
+
phi = .5 * np.arctan((2. * b) / (a - c))
|
|
547
585
|
|
|
548
586
|
self._center = [x0, y0]
|
|
549
587
|
self._width = width
|
|
@@ -576,25 +614,29 @@ class LSqEllipse:
|
|
|
576
614
|
def make_test_ellipse(center=[1, 1], width=1, height=.6, phi=3.14 / 5):
|
|
577
615
|
"""Generate Elliptical data with noise
|
|
578
616
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
center
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
617
|
+
Parameters
|
|
618
|
+
----------
|
|
619
|
+
center: list of float
|
|
620
|
+
(<x_location>, <y_location>)
|
|
621
|
+
width: float
|
|
622
|
+
semimajor axis. Horizontal dimension of the ellipse
|
|
623
|
+
height: float
|
|
624
|
+
semiminor axis. Vertical dimension of the ellipse
|
|
625
|
+
phi: float
|
|
626
|
+
tilt of the ellipse in radians, the angle the semimajor axis makes with the x-axis
|
|
586
627
|
|
|
587
628
|
Returns
|
|
588
629
|
-------
|
|
589
|
-
|
|
590
|
-
|
|
630
|
+
list of list of float
|
|
631
|
+
list of two lists containing the x and y data of the ellipse, of the form
|
|
632
|
+
``[[x1, x2, ..., xi],[y1, y2, ..., yi]]``
|
|
591
633
|
"""
|
|
592
|
-
t =
|
|
593
|
-
x_noise, y_noise =
|
|
634
|
+
t = np.linspace(0, 2 * np.pi, 1000)
|
|
635
|
+
x_noise, y_noise = np.random.rand(2, len(t))
|
|
594
636
|
|
|
595
|
-
ellipse_x = center[0] + width *
|
|
637
|
+
ellipse_x = center[0] + width * np.cos(t) * np.cos(phi) - height * np.sin(t) * np.sin(
|
|
596
638
|
phi) + x_noise / 2.
|
|
597
|
-
ellipse_y = center[1] + width *
|
|
639
|
+
ellipse_y = center[1] + width * np.cos(t) * np.sin(phi) + height * np.sin(t) * np.cos(
|
|
598
640
|
phi) + y_noise / 2.
|
|
599
641
|
|
|
600
642
|
return [ellipse_x, ellipse_y]
|
{pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/serialize/serializer_legacy.py
RENAMED
|
@@ -229,8 +229,7 @@ class Serializer:
|
|
|
229
229
|
|
|
230
230
|
class DeSerializer:
|
|
231
231
|
"""Used to DeSerialize bytes to python objects, numpy arrays and PyMoDAQ Axis,
|
|
232
|
-
|
|
233
|
-
objects
|
|
232
|
+
DataWithAxes and DataToExport objects
|
|
234
233
|
|
|
235
234
|
Parameters
|
|
236
235
|
----------
|
|
@@ -240,8 +239,8 @@ class DeSerializer:
|
|
|
240
239
|
|
|
241
240
|
See Also
|
|
242
241
|
--------
|
|
243
|
-
|
|
244
|
-
|
|
242
|
+
pymodaq_utils.serialize.mysocket.SocketString
|
|
243
|
+
pymodaq_utils.serialize.mysocket.Socket
|
|
245
244
|
"""
|
|
246
245
|
|
|
247
246
|
def __init__(self, bytes_string: Union[bytes, Socket] = None) -> None:
|
|
@@ -31,7 +31,7 @@ else:
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
logger = logger_module.set_logger(logger_module.get_module_name(__file__))
|
|
34
|
-
|
|
34
|
+
ser_factory = SerializableFactory()
|
|
35
35
|
config = Config()
|
|
36
36
|
|
|
37
37
|
|
|
@@ -359,7 +359,7 @@ def elt_as_first_element_dicts(elt_list, match_word='Mock', key='name'):
|
|
|
359
359
|
return plugins
|
|
360
360
|
|
|
361
361
|
|
|
362
|
-
def find_keys_from_val(dict_tmp: dict, val: object):
|
|
362
|
+
def find_keys_from_val(dict_tmp: dict, val: object) -> list:
|
|
363
363
|
"""Returns the keys from a dict if its value is matching val"""
|
|
364
364
|
return [k for k, v in dict_tmp.items() if v == val]
|
|
365
365
|
|
|
@@ -623,12 +623,27 @@ def format_dir_path(path: Path) -> str:
|
|
|
623
623
|
return f'{path}{dir_trailing_symbol if path.is_dir() else ""}'
|
|
624
624
|
|
|
625
625
|
|
|
626
|
+
def read_binary_and_deserialize(fname: Path) -> list[SerializableBase]:
|
|
627
|
+
if not fname.exists():
|
|
628
|
+
return []
|
|
629
|
+
with open(fname, 'rb') as file:
|
|
630
|
+
lines = file.readlines()
|
|
631
|
+
all_lines = b''
|
|
632
|
+
for line in lines:
|
|
633
|
+
all_lines += line
|
|
634
|
+
data = []
|
|
635
|
+
while len(all_lines) > 0:
|
|
636
|
+
entry, all_lines = ser_factory.get_apply_deserializer(all_lines, only_object=False)
|
|
637
|
+
data.append(entry)
|
|
638
|
+
return data
|
|
639
|
+
|
|
640
|
+
|
|
626
641
|
if __name__ == '__main__':
|
|
627
642
|
|
|
628
643
|
#plugins = get_plugins() # pragma: no cover
|
|
629
644
|
#extensions = get_extension()
|
|
630
645
|
#models = get_models()
|
|
631
|
-
#count = count_lines('C:\\Users\\weber\\Labo\\Programmes Python\\PyMoDAQ_Git\\pymodaq\src')
|
|
646
|
+
#count = count_lines(r'C:\\Users\\weber\\Labo\\Programmes Python\\PyMoDAQ_Git\\pymodaq\src')
|
|
632
647
|
|
|
633
648
|
|
|
634
649
|
# import license
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
warnings.filterwarnings("ignore", message=".*libpyside.*", category=RuntimeWarning)
|
|
3
|
+
# deactivate messages when disconnect fails (catched by TypeError for pyqt6 and pyqt5
|
|
4
|
+
# but pyside6 do not do errors but throw this Runtimewarning)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def deprecation_msg(message, stacklevel=3):
|
|
8
|
+
warnings.warn(message, DeprecationWarning, stacklevel=stacklevel)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def user_warning(message, stacklevel=3):
|
|
12
|
+
warnings.warn(message, UserWarning, stacklevel=stacklevel)
|
|
13
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/resources/config_template.toml
RENAMED
|
File without changes
|
{pymodaq_utils-5.2.7 → pymodaq_utils-5.3.0}/src/pymodaq_utils/resources/hatch_build_plugins.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|