auto-trainer-core 2.0.1.dev349__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.
Files changed (73) hide show
  1. auto_trainer_core-2.0.1.dev349.dist-info/METADATA +19 -0
  2. auto_trainer_core-2.0.1.dev349.dist-info/RECORD +73 -0
  3. auto_trainer_core-2.0.1.dev349.dist-info/WHEEL +5 -0
  4. auto_trainer_core-2.0.1.dev349.dist-info/top_level.txt +1 -0
  5. autotrainer/core/__init__.py +319 -0
  6. autotrainer/core/analysis/__init__.py +6 -0
  7. autotrainer/core/analysis/alarm_monitor.py +484 -0
  8. autotrainer/core/analysis/audio_spectrum_data.py +27 -0
  9. autotrainer/core/analysis/audio_spectrum_monitor.py +134 -0
  10. autotrainer/core/analysis/auto_tunnel_fan_monitor.py +92 -0
  11. autotrainer/core/analysis/detector.py +179 -0
  12. autotrainer/core/analysis/external_doors_monitor.py +124 -0
  13. autotrainer/core/analysis/global_animal_presence_monitor.py +69 -0
  14. autotrainer/core/analysis/head_fix_measurement.py +15 -0
  15. autotrainer/core/analysis/headbar_pressure_monitor.py +158 -0
  16. autotrainer/core/analysis/load_cell_monitor.py +377 -0
  17. autotrainer/core/analysis/load_cell_tare_monitor.py +217 -0
  18. autotrainer/core/analysis/measurement_data.py +80 -0
  19. autotrainer/core/analysis/pellet_position_monitor.py +108 -0
  20. autotrainer/core/analysis/sensor_analysis.py +390 -0
  21. autotrainer/core/analysis/system_fault_monitor.py +81 -0
  22. autotrainer/core/analysis/system_maintenance_monitor.py +88 -0
  23. autotrainer/core/animal/__init__.py +1 -0
  24. autotrainer/core/animal/animal_subject.py +208 -0
  25. autotrainer/core/capture.py +25 -0
  26. autotrainer/core/configuration/__init__.py +88 -0
  27. autotrainer/core/configuration/alarm_configuration.py +55 -0
  28. autotrainer/core/configuration/animal_presence_configuration.py +17 -0
  29. autotrainer/core/configuration/behavior_configuration.py +323 -0
  30. autotrainer/core/configuration/camera_configuration.py +108 -0
  31. autotrainer/core/configuration/external_doors_monitor_configuration.py +9 -0
  32. autotrainer/core/configuration/hardware_configuration.py +30 -0
  33. autotrainer/core/configuration/inference_configuration.py +26 -0
  34. autotrainer/core/configuration/load_cell_config.py +61 -0
  35. autotrainer/core/configuration/persistence_configuration.py +29 -0
  36. autotrainer/core/configuration/presence_detection_configuration.py +9 -0
  37. autotrainer/core/configuration/system_configuration.py +211 -0
  38. autotrainer/core/configuration/system_fault_config.py +9 -0
  39. autotrainer/core/configuration/system_maintenance_config.py +17 -0
  40. autotrainer/core/diamond_triangle_config.py +150 -0
  41. autotrainer/core/event/__init__.py +54 -0
  42. autotrainer/core/event/api_event_kind.py +5 -0
  43. autotrainer/core/event/api_event_plugin.py +57 -0
  44. autotrainer/core/event/event_info.py +53 -0
  45. autotrainer/core/event/event_manager.py +296 -0
  46. autotrainer/core/event/event_manager_plugin.py +45 -0
  47. autotrainer/core/event/file_event_plugin.py +91 -0
  48. autotrainer/core/event/logger_event_plugin.py +43 -0
  49. autotrainer/core/fixed_array_multiqueue.py +263 -0
  50. autotrainer/core/fixed_array_queue.py +124 -0
  51. autotrainer/core/frame_index.py +34 -0
  52. autotrainer/core/interfaces.py +347 -0
  53. autotrainer/core/logging.py +714 -0
  54. autotrainer/core/message/__init__.py +26 -0
  55. autotrainer/core/message/audio_spectrum_message.py +21 -0
  56. autotrainer/core/message/measurement_message.py +61 -0
  57. autotrainer/core/message/message_handler.py +158 -0
  58. autotrainer/core/message/motor_configuration_message.py +128 -0
  59. autotrainer/core/message/system_command_kind.py +74 -0
  60. autotrainer/core/message/system_message_handler.py +122 -0
  61. autotrainer/core/message/system_status_message.py +112 -0
  62. autotrainer/core/multiproc.py +50 -0
  63. autotrainer/core/notification/__init__.py +2 -0
  64. autotrainer/core/notification/notification_center.py +80 -0
  65. autotrainer/core/notification/trigger_notification.py +27 -0
  66. autotrainer/core/observable_object.py +105 -0
  67. autotrainer/core/perf_monitor.py +77 -0
  68. autotrainer/core/pose_elements.py +196 -0
  69. autotrainer/core/project/__init__.py +19 -0
  70. autotrainer/core/project/project_info.py +486 -0
  71. autotrainer/core/queue_util.py +60 -0
  72. autotrainer/core/reach_event.py +38 -0
  73. autotrainer/core/video_detection.py +326 -0
@@ -0,0 +1,19 @@
1
+ Metadata-Version: 2.1
2
+ Name: auto-trainer-core
3
+ Version: 2.0.1.dev349
4
+ Summary: Core objects and implementations for autotrainer
5
+ License: MIT
6
+ Requires-Python: >=3.8
7
+ Requires-Dist: auto-trainer-api ==0.9.17
8
+ Requires-Dist: verboselogs <2,>=1.7
9
+ Requires-Dist: coloredlogs <16,>=15
10
+ Requires-Dist: events <1,>=0.5
11
+ Requires-Dist: transitions <1,>=0.9.2
12
+ Requires-Dist: psutil <8,>=7
13
+ Requires-Dist: numpy <2,>=1.23.5
14
+ Requires-Dist: opencv-python <5,>=4.12
15
+ Requires-Dist: pyhumps <4,>=3.8
16
+ Requires-Dist: pyyaml <7,>=6.0.2
17
+ Requires-Dist: importlib-resources ; python_version < "3.10"
18
+ Requires-Dist: importlib-metadata ; python_version < "3.10"
19
+
@@ -0,0 +1,73 @@
1
+ autotrainer/core/__init__.py,sha256=AWfSxjxyl8BsoEh7OohPiK1uaU7W0W5N5QFPDi_xt-A,10817
2
+ autotrainer/core/capture.py,sha256=DQzWCPPpWX6RpukgmRgNZ8RkalupC3XG2BZBonm6c-0,616
3
+ autotrainer/core/diamond_triangle_config.py,sha256=LoodiIunpP3RIGna25QFNgAt83gXwvCpacvMvpg8IN8,6686
4
+ autotrainer/core/fixed_array_multiqueue.py,sha256=I7UX4OarzWiiEJYwSgEjJhZFUkX9GNF87F9Z9uXHFe0,11209
5
+ autotrainer/core/fixed_array_queue.py,sha256=Bdx04A6fKxWMVH64XiDCLoPy7HjzFAKXwWhDF4xHMdU,3750
6
+ autotrainer/core/frame_index.py,sha256=DIVrma1Psn5PvYxMprijpTToycfWty8IyZt2CVd0jQI,1096
7
+ autotrainer/core/interfaces.py,sha256=Xb26yKmo-FM5IkXW0XcS6RKjeLt029-EUR5kcP9qVkU,12304
8
+ autotrainer/core/logging.py,sha256=7sVX4bcnVJwWOWa6AmK2xsIa_gdF2xIV0pnCjLCcr1s,24025
9
+ autotrainer/core/multiproc.py,sha256=u6jGIk-7iMYxKrVCnM4vFaCMfMZ2CC4z66ussvriXyI,1383
10
+ autotrainer/core/observable_object.py,sha256=-IiFL1HjfIl5u8-9vaBgoWSHaOohi82TdTjW7W8eIUc,4376
11
+ autotrainer/core/perf_monitor.py,sha256=mOpUTgT6MPPF76LpqVhZA8W1XAo0Xy6r1uvqicUrOIs,2715
12
+ autotrainer/core/pose_elements.py,sha256=4y-jf1ZOU9ZnYt7ds1QfPjJDWD-X-C07_WMBW5oKa7M,8265
13
+ autotrainer/core/queue_util.py,sha256=8AP4kr8tcYJ_ZFGaKnZ6S0Dj1MTBsBd7q7xnj0FeISs,1787
14
+ autotrainer/core/reach_event.py,sha256=oRGHe6ONMiHA2LNypJpRvaoMQw1g0vOk_fmWxDWsB3M,1070
15
+ autotrainer/core/video_detection.py,sha256=kQyVQMNJN537w_-UAI4tNihiepF9FUqOqQ-5cowMnzk,14741
16
+ autotrainer/core/analysis/__init__.py,sha256=7lRVWu2Myb0gVgnvLfm30NsMn6ihPf6Ze1CSfnm-nug,336
17
+ autotrainer/core/analysis/alarm_monitor.py,sha256=lhZKo5bP0dRBed-9r1KqtTS3MkaUxhiiOpyyZAtrdMc,22742
18
+ autotrainer/core/analysis/audio_spectrum_data.py,sha256=aVxvYR_Aq6n6ojmA7F4D5GtHJ9e8q8e-iThMSlBrKKk,843
19
+ autotrainer/core/analysis/audio_spectrum_monitor.py,sha256=-OSnlC2xaINfP-aV61_JBu7vGLsH724zlX4SdVtc0Vo,5284
20
+ autotrainer/core/analysis/auto_tunnel_fan_monitor.py,sha256=hr6StldI_UsBukvJQYybUqr1ORci9sP1PCxKzqV3fkU,3425
21
+ autotrainer/core/analysis/detector.py,sha256=_lzgFSh5zIv14ZcpEXrnakQifFHTI_oCo4A-yPc7Fig,6987
22
+ autotrainer/core/analysis/external_doors_monitor.py,sha256=2PlLibH7NmKohx_F4hl-SR2IVMCf9YVSfa09f1p9ZXY,3931
23
+ autotrainer/core/analysis/global_animal_presence_monitor.py,sha256=E9AbgpYvcv4KucXRGETtvCz_GYGnXnFC5-rBDD0WZdM,2564
24
+ autotrainer/core/analysis/head_fix_measurement.py,sha256=38tIY5rYnjf5qkWTnChYCU4RY7V39ht1Qwu9K5JE0lU,500
25
+ autotrainer/core/analysis/headbar_pressure_monitor.py,sha256=pl8wc9fV7WyaXSNAsS8B_TKVvuNL1beTuPh4j3ApOgY,5989
26
+ autotrainer/core/analysis/load_cell_monitor.py,sha256=KAHkD7VxRN2JFoAKPt9PM6hoUy7pmp4dbrzcVIOdI8E,16662
27
+ autotrainer/core/analysis/load_cell_tare_monitor.py,sha256=kt6umiwb9r69-qLLyOKznFBPQmxBksjl6xWsP-OcDsQ,7596
28
+ autotrainer/core/analysis/measurement_data.py,sha256=JUJzIGCzWscnM2Zruz8g0-DGdPG2Qgb0kqtv-y6LhEU,2277
29
+ autotrainer/core/analysis/pellet_position_monitor.py,sha256=YAsratf5_cM4oGEQahtNdFbtfXSQ4_8ITNKl8e_zchk,4430
30
+ autotrainer/core/analysis/sensor_analysis.py,sha256=C3XgpEFCAtj2tVApXqk1LcSkI-OF4L5MJ9aHvYkO1C0,15969
31
+ autotrainer/core/analysis/system_fault_monitor.py,sha256=WXEalsxNoYbrDwuNOVl6PKcIMk68gQsMHs4VWsCtlrc,3133
32
+ autotrainer/core/analysis/system_maintenance_monitor.py,sha256=KD2kWcwOyTRGIVyJrtGnAfFca9W9OlRvxklAFybZDOY,3647
33
+ autotrainer/core/animal/__init__.py,sha256=XWXKMmMWwgDHFgU4E7dNscAXLQoIiQVnoNi_F5OJ5P4,43
34
+ autotrainer/core/animal/animal_subject.py,sha256=IHtUwyRX9plrlfL84ssfp-Ah1ovKXgs53Gnwtv6MMe4,8346
35
+ autotrainer/core/configuration/__init__.py,sha256=ZukPVGf_kDHLmjE6ZTElTOMHrHxN0HqO91_lrC28Lrk,2544
36
+ autotrainer/core/configuration/alarm_configuration.py,sha256=Wz80R8VrE90qrF4cfiaFQHxsNCmfWU2I8ik6sSPl63c,1750
37
+ autotrainer/core/configuration/animal_presence_configuration.py,sha256=cPD9dyL8_GOOaSZBjFu4n3W_5h1hEsJh34ls--9lsLI,536
38
+ autotrainer/core/configuration/behavior_configuration.py,sha256=ln_i5IJiWrFNpzx-gDQ1s6y0O0SZ888igJexfPvMM3Q,14398
39
+ autotrainer/core/configuration/camera_configuration.py,sha256=FaOlz4l6eKChTSY7zV3GEHF-QIzlTmWdcp58Y9X19nU,3575
40
+ autotrainer/core/configuration/external_doors_monitor_configuration.py,sha256=UczMCDafoH08O_mnsiAMPVhYuxbGEuboTwE_1jfo4Ao,124
41
+ autotrainer/core/configuration/hardware_configuration.py,sha256=e2ALNU2xsup4WlivQbDJ2DzSiXqBXwg2RpwvikI0lrw,950
42
+ autotrainer/core/configuration/inference_configuration.py,sha256=vuZkHpxO87hPXuw5wmG5f65gH8PsfojQoMmaJ7Rbmvs,903
43
+ autotrainer/core/configuration/load_cell_config.py,sha256=JY-5QeiUJ3B1MqjPQY973UWxn8F4uMNZB59s0wlNFi4,2368
44
+ autotrainer/core/configuration/persistence_configuration.py,sha256=v5ciqmWXpCwqFcvo3seCIJmyMYYjzOgyVVQ6aZniewM,935
45
+ autotrainer/core/configuration/presence_detection_configuration.py,sha256=DZVKYr1NrSjDTsOqezXrdX1u3QMI8FYRZJRQuuN1z50,506
46
+ autotrainer/core/configuration/system_configuration.py,sha256=qU0SslckYc4kndCAs0JFJDhVewy121OfIlBggOYvAZQ,10036
47
+ autotrainer/core/configuration/system_fault_config.py,sha256=unXjKOBpmBBAD5EOpkwR0POkhmJuld_qF6MfoI6upQw,208
48
+ autotrainer/core/configuration/system_maintenance_config.py,sha256=zFmgjqLfn_UL4Uwu63eR-RLMHZKLMv69XImEjwXb8rc,507
49
+ autotrainer/core/event/__init__.py,sha256=fOlq8bo77vFH_fbtook1SSq5dxE4I2hHYIQr-FdycCI,1689
50
+ autotrainer/core/event/api_event_kind.py,sha256=ikc1W05MV3Bwu4rbELSrLEAPQBIMOemqKymLkrPqvlA,91
51
+ autotrainer/core/event/api_event_plugin.py,sha256=0VNUtcGAEwXVcLXl5PN1x-gVvmNVGrYbPNzfn1pB7x8,1677
52
+ autotrainer/core/event/event_info.py,sha256=XmjNVwDh51EdncokkIPBZPnXVeNED-7qYRROIMehVXQ,2609
53
+ autotrainer/core/event/event_manager.py,sha256=tzy5oJPn3PNIh1O0edZQULTsg5Q43qhMfDxQC2EVL2M,12053
54
+ autotrainer/core/event/event_manager_plugin.py,sha256=espUtA57tY7HIk1taRwvqmONBVvHMKI9OzPf0ZNdE0A,1275
55
+ autotrainer/core/event/file_event_plugin.py,sha256=PadLslxWJ2LA0nPjw5gzTnSYYlVrOotfV4VGuOLLfhw,3469
56
+ autotrainer/core/event/logger_event_plugin.py,sha256=FoVReomBC_O4XOgHmb60YTVm6WuY3W2H3eC959176sI,1124
57
+ autotrainer/core/message/__init__.py,sha256=HGQo3bCXygdDOhUGER4TFg46jiPYmh4mGfLB7rdjy6k,914
58
+ autotrainer/core/message/audio_spectrum_message.py,sha256=InEYnJ2PjWPcPO6yuG3o1T0tcBL-3GJaULFEpwHdw1Y,650
59
+ autotrainer/core/message/measurement_message.py,sha256=W6bOpJ_vXqvrKQTbZDUF9f9BG_wodPNIirx7kEoSJZA,1812
60
+ autotrainer/core/message/message_handler.py,sha256=FKUiAy-DW6Cw_2t1EIkhVboxSW8gxPqfVNe_DUjjx3Q,6153
61
+ autotrainer/core/message/motor_configuration_message.py,sha256=GWXGbSE6GekUWmyNpyIfGWVyS5PnTYBuVCWSw2PdB5U,3141
62
+ autotrainer/core/message/system_command_kind.py,sha256=c0cH9OESrgiCiLv7eMdoX-fV7EwFivg9rVGv0glTSWY,2959
63
+ autotrainer/core/message/system_message_handler.py,sha256=esps9BfPoDPsCEfl1Kd88K5V9aSVRJ0pz8nQU7HM-NY,5559
64
+ autotrainer/core/message/system_status_message.py,sha256=-WXY0aJmZNj5avQf0BL03tpjJRsNBfM9c4kPPdsT42Q,3939
65
+ autotrainer/core/notification/__init__.py,sha256=7Kom9ULw_zDTHFzCdR1Pw-XWhuVlq_FlQPN2n2l3Vz8,143
66
+ autotrainer/core/notification/notification_center.py,sha256=OJc3B7Hx13rCfJc6mmd4YSnF1cef0EslOcSnQdHB2Is,2839
67
+ autotrainer/core/notification/trigger_notification.py,sha256=USxBPTkBe0nlhXqOcxn9HsT9ck6mbv-jtPkoiQyn_f8,691
68
+ autotrainer/core/project/__init__.py,sha256=taVWi9lZaiUDgDfE_rDBjGa24Kx2x2hI2UE1noF-84g,490
69
+ autotrainer/core/project/project_info.py,sha256=dvOejVskSWdXztZb7QGkaZorisNXRxR9KuYqHwMp_aQ,19020
70
+ auto_trainer_core-2.0.1.dev349.dist-info/METADATA,sha256=LnZnBL_fdABjvkLhbIZoaTFQIYBvbxNWKtNapxxdePM,651
71
+ auto_trainer_core-2.0.1.dev349.dist-info/WHEEL,sha256=BNRMDyzLkkcmlv0J8ppDQkk2VED33SesJDynr9ED1gc,91
72
+ auto_trainer_core-2.0.1.dev349.dist-info/top_level.txt,sha256=ixgifxjw5vwK1dy4q_onvrKJa8ktriizMqAznqOyILM,12
73
+ auto_trainer_core-2.0.1.dev349.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.3.4)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ autotrainer
@@ -0,0 +1,319 @@
1
+ import dataclasses
2
+ import math
3
+ import time
4
+ from collections import namedtuple
5
+ from typing import Union, List, Tuple, Dict, Any, Iterable, TypeVar, Type, Optional, Callable
6
+ from typing_extensions import Self
7
+
8
+ import humps
9
+ import yaml
10
+ from typing_extensions import Self
11
+
12
+ # NB: import order is very important, put the less specific/most general first, then go in order of dependency.
13
+
14
+ from .logging import get_verbose_logger
15
+
16
+ #
17
+
18
+ logger = get_verbose_logger(__name__)
19
+
20
+ #
21
+
22
+ def mean_method(data):
23
+ return sum(data) / len(data)
24
+
25
+
26
+ def calculate_std_dev_manual(data, reduce_method=mean_method):
27
+ n = len(data)
28
+ if n < 2:
29
+ raise ValueError("Data must contain at least two values to calculate standard deviation.")
30
+ res = reduce_method(data)
31
+ squared_diffs = [(x - res) ** 2 for x in data]
32
+ variance = sum(squared_diffs) / (n - 1) # Sample standard deviation
33
+ std_dev = variance ** 0.5
34
+ return res, std_dev
35
+
36
+ #
37
+
38
+ @dataclasses.dataclass
39
+ class RawValueHolder:
40
+ value: Any
41
+
42
+
43
+ def _no_convert(v):
44
+ return v
45
+
46
+
47
+ class ValueHolderDescriptor:
48
+
49
+ def __init__(
50
+ self,
51
+ *,
52
+ convert_to: Callable[[Any], Any] = _no_convert,
53
+ convert_from: Callable[[Any], Any] = _no_convert,
54
+ ):
55
+ self._convert_to = convert_to
56
+ self._convert_from = convert_from
57
+
58
+ def __set_name__(self, owner, name):
59
+ self.name = name
60
+ self._priv_name = f"_{name}"
61
+
62
+ def __get__(self, instance, owner):
63
+ if instance is None:
64
+ return self
65
+ return self._convert_from(getattr(instance, self._priv_name).value)
66
+
67
+ def __set__(self, instance, value):
68
+ getattr(instance, self._priv_name).value = self._convert_to(value)
69
+
70
+ #
71
+
72
+ def transitions_allow_functions(transitions: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
73
+ """Update the dicts to the functions name"""
74
+ for trans in transitions:
75
+ for k in ('trigger', 'before', 'after', 'conditions'):
76
+ v = trans.get(k)
77
+ if isinstance(v, (list, tuple)):
78
+ trans[k] = tuple(
79
+ sub.__name__ if callable(sub) else sub
80
+ for sub in v
81
+ )
82
+ elif callable(v):
83
+ trans[k] = v.__name__
84
+ return transitions
85
+ #
86
+
87
+ Pairs3dOffsetT = Union[List[Tuple[str, str]], Tuple[Tuple[str, str], ...]]
88
+
89
+ _Offset3DTuple = namedtuple("Offset3DTuple", ('x', 'y', 'z'))
90
+
91
+
92
+ def _get_perf_now():
93
+ # allowed to be patched from test
94
+ return time.perf_counter()
95
+
96
+
97
+ def get_perf_now():
98
+ return _get_perf_now()
99
+
100
+
101
+ class Offset3DTuple(_Offset3DTuple):
102
+ """Named tuple (x, y, z),
103
+ allowing construction with "packed" Offset3DTuple((x, y, z)) or "unpacked" Offset3DTuple(x, y, z) coordinates.
104
+ When "packed": any object having a len() == 3 will be unpacked using python regular:
105
+ x, y, z = args[0]
106
+ Otherwise the construction fails (with anything else in args[0] when len(args) == 1)
107
+ """
108
+ x: float
109
+ y: float
110
+ z: float
111
+
112
+ def __new__(cls, *args, **kwargs):
113
+ if len(args) == 1:
114
+ arg0 = args[0]
115
+ if hasattr(arg0, "__len__") and len(arg0) == 3:
116
+ x, y, z = arg0
117
+ return super().__new__(cls, x, y, z, **kwargs) # noqa
118
+ return super().__new__(cls, *args, **kwargs) # noqa
119
+
120
+ def __repr__(self):
121
+ # to not get "Offset3DTuple(x, y, z)" but instead only "(x, y, z)"
122
+ return str(tuple(self))
123
+
124
+ __str__ = __repr__
125
+
126
+ @staticmethod
127
+ def get_nan() -> Self:
128
+ return _nan_offset3d_tuple
129
+
130
+ @staticmethod
131
+ def get_zero() -> Self:
132
+ return _zero_offset3d_tuple
133
+
134
+ def replace(self, x: Optional[float] = None, y: Optional[float] = None, z: Optional[float] = None) -> Self:
135
+ return self.__class__(
136
+ self.x if x is None else x,
137
+ self.y if y is None else y,
138
+ self.z if z is None else z,
139
+ )
140
+
141
+ def humanize(self, n_digits: int = 2) -> str:
142
+ x, y, z = self
143
+ return f"({x:.0{n_digits}f}, {y:.0{n_digits}f}, {z:.0{n_digits}f})"
144
+
145
+ def round(self, n: int=2) -> Self:
146
+ return self.__class__(*(round(v, n) for v in self))
147
+
148
+ # tried to use with statistics.mean, but at some point with it there is a sorting applied on the list (of offsets),
149
+ # and a smaller-than (<) operator check against a start value of 0 .. and we don't handle that with Offset3DTuple.
150
+ # def as_integer_ratio(self) -> Tuple[Self, Self]:
151
+ # # use float(v) to ensure float, and allow use of as_integer_ration, if integer is in any of x/y/z.
152
+ # xo, yo, zo = map(lambda v: float(v).as_integer_ratio(), self)
153
+ # return self.__class__(xo[0], yo[0], zo[0]), self.__class__(xo[1], yo[1], zo[1])
154
+
155
+ def __pow__(self, other, modulo=None) -> Self:
156
+ if modulo is None:
157
+ return self.__class__(*(v ** other for v in self))
158
+ return self.__class__(
159
+ *(pow(v, other, modulo) for v in self)
160
+ )
161
+
162
+ def __rpow__(self, other, modulo=None) -> Self:
163
+ if modulo is None:
164
+ return self.__class__(*(other ** v for v in self))
165
+ return self.__class__(
166
+ *(pow(other, v, modulo) for v in self)
167
+ )
168
+
169
+
170
+ def __add__(self, other) -> Self:
171
+ if hasattr(other, "__len__") and len(other) == 3:
172
+ return self.__class__(*(v1 + v2 for v1, v2 in zip(self, other)))
173
+ return self.__class__(*(v + other for v in self))
174
+
175
+ __radd__ = __add__
176
+
177
+ def __sub__(self, other) -> Self:
178
+ if hasattr(other, "__len__") and len(other) == 3:
179
+ return self.__class__(*(v1 - v2 for v1, v2 in zip(self, other)))
180
+ return self.__class__(*(v - other for v in self))
181
+
182
+ def __rsub__(self, other) -> Self:
183
+ if hasattr(other, "__len__") and len(other) == 3:
184
+ return self.__class__(*(v2 - v1 for v1, v2 in zip(self, other)))
185
+ return self.__class__(*(other - v for v in self))
186
+
187
+ def __neg__(self) -> Self:
188
+ return self.__class__(-self.x, -self.y, -self.z)
189
+
190
+ def __mul__(self, other) -> Self:
191
+ if hasattr(other, "__len__") and len(other) == 3:
192
+ return self.__class__(*(v1 * v2 for v1, v2 in zip(self, other)))
193
+ return self.__class__(*(v * other for v in self))
194
+
195
+ __rmul__ = __mul__
196
+
197
+ def __truediv__(self, other) -> Self:
198
+ if hasattr(other, "__len__") and len(other) == 3:
199
+ return self.__class__(*(v1 / v2 for v1, v2 in zip(self, other)))
200
+ return self.__class__(*(v / other for v in self))
201
+
202
+ def __abs__(self) -> Self:
203
+ return self.__class__(*(abs(v) for v in self))
204
+
205
+ @property
206
+ def distance(self) -> float:
207
+ return math.sqrt(sum(c**2 for c in self))
208
+
209
+
210
+ _nan_offset3d_tuple = Offset3DTuple(math.nan, math.nan, math.nan)
211
+ _zero_offset3d_tuple = Offset3DTuple(0, 0, 0)
212
+
213
+ #
214
+
215
+
216
+ def build_kwargs_apply_mapping(
217
+ content: Dict[str, Any],
218
+ mapping: Iterable[Union[str, Tuple[str, str]]],
219
+ *,
220
+ skip_remaining: bool = False,
221
+ ) -> Dict[str, Any]:
222
+ kwargs = {}
223
+ content = dict(content) # make copy of 1 level given we'll remove/pop from it
224
+ for cur_map in mapping:
225
+ if isinstance(cur_map, str):
226
+ dest = key = cur_map
227
+ else:
228
+ assert len(cur_map) == 2
229
+ dest, key = cur_map
230
+ if key in content:
231
+ value = content.pop(key)
232
+ if dest not in kwargs: # first one wins
233
+ kwargs[dest] = value
234
+ # insert whatever remains in content, unless skipped:
235
+ if not skip_remaining:
236
+ kwargs.update(content)
237
+ return kwargs
238
+
239
+ #
240
+
241
+
242
+ ConfigItemCls = TypeVar("ConfigItemCls")
243
+
244
+
245
+ def make_camelize_representer(section_name: str):
246
+
247
+ def representer(dumper: yaml.SafeDumper, obj):
248
+ return dumper.represent_mapping(section_name, {
249
+ humps.camelize(field.name): getattr(obj, field.name)
250
+ for field in dataclasses.fields(obj)
251
+ })
252
+
253
+ return representer
254
+
255
+
256
+ def make_decamelize_constructor(cls: Type[ConfigItemCls]):
257
+
258
+ # required delayed import for now,
259
+ # not big deal given this function is to be called once only (per config class).
260
+ from .configuration import SystemConfigurationLoader
261
+
262
+ def constructor(loader: SystemConfigurationLoader, node: yaml.nodes.MappingNode) -> ConfigItemCls:
263
+ content = loader.construct_mapping(node, deep=True)
264
+ content = humps.decamelize(content) # decamelize first,
265
+ # "decamelized" names are here after checked against field names
266
+ if loader.safe_load:
267
+ names = [f.name for f in dataclasses.fields(cls)]
268
+ before_count = len(content)
269
+ before_s = set(content)
270
+ content = {
271
+ k: v
272
+ for k, v in content.items()
273
+ if k in names
274
+ }
275
+ filtered_count = before_count - len(content)
276
+ after_s = set(content)
277
+ if filtered_count != 0:
278
+ logger.verbose("%s: safe load filtered %s unknown properties/attributes: %s",
279
+ cls.__qualname__, filtered_count, sorted(list(before_s - after_s)))
280
+ return cls(**content)
281
+
282
+ return constructor
283
+
284
+
285
+
286
+ # MUST come first (but after above definitions):
287
+ import autotrainer.core.logging
288
+ import autotrainer.core.diamond_triangle_config
289
+ # ..
290
+
291
+
292
+ from .observable_object import ObservableObject, ObservableObjectProtocol
293
+
294
+ from .frame_index import FrameIndexCategory
295
+
296
+ from .fixed_array_multiqueue import FixedArrayMultiQueue
297
+ from .fixed_array_queue import FixedArrayQueue
298
+
299
+ from .project import ProjectInfo, ProjectInterval, video_write_ext
300
+ from .animal import AnimalSubject
301
+
302
+ from .perf_monitor import PerfMonitor
303
+ from .queue_util import clear_queue
304
+ from .notification import NotificationCenter, Notification, TriggerNotification, post_trigger_enable
305
+ from .configuration import HardwareConfiguration, InferenceConfiguration, PersistenceConfiguration
306
+
307
+ from .message import MotorConfigurations, Motor
308
+ from .message import SystemStatusMessageKind, SystemCommandKind, MeasurementMessageProtocol, AudioSpectrumMessage
309
+ from .configuration import SystemConfiguration, BehaviorConfiguration, CameraConfiguration, CameraId, \
310
+ SystemConfigurationLoader
311
+
312
+ from .message import MessageHandler, SystemMessageHandler
313
+ from .analysis import SensorAnalysis, MeasurementData, AudioSpectrumData
314
+ from .analysis import LoadCellMonitor, HeadbarPressureMonitor
315
+
316
+ from .event.api_event_kind import ApiEventKind
317
+ from .event.event_info import EventInfo
318
+ from .event.api_event_plugin import EventManagerPlugin
319
+ from .event.event_manager import EventManager
@@ -0,0 +1,6 @@
1
+ from .audio_spectrum_data import AudioSpectrumData
2
+ from .headbar_pressure_monitor import (HeadbarPressureMonitor, HeadbarPressureConfiguration)
3
+ from .load_cell_monitor import LoadCellMonitor
4
+ from .measurement_data import MeasurementData
5
+ from .alarm_monitor import EmergencyAlarmMonitor
6
+ from .sensor_analysis import SensorAnalysis