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.
- auto_trainer_core-2.0.1.dev349.dist-info/METADATA +19 -0
- auto_trainer_core-2.0.1.dev349.dist-info/RECORD +73 -0
- auto_trainer_core-2.0.1.dev349.dist-info/WHEEL +5 -0
- auto_trainer_core-2.0.1.dev349.dist-info/top_level.txt +1 -0
- autotrainer/core/__init__.py +319 -0
- autotrainer/core/analysis/__init__.py +6 -0
- autotrainer/core/analysis/alarm_monitor.py +484 -0
- autotrainer/core/analysis/audio_spectrum_data.py +27 -0
- autotrainer/core/analysis/audio_spectrum_monitor.py +134 -0
- autotrainer/core/analysis/auto_tunnel_fan_monitor.py +92 -0
- autotrainer/core/analysis/detector.py +179 -0
- autotrainer/core/analysis/external_doors_monitor.py +124 -0
- autotrainer/core/analysis/global_animal_presence_monitor.py +69 -0
- autotrainer/core/analysis/head_fix_measurement.py +15 -0
- autotrainer/core/analysis/headbar_pressure_monitor.py +158 -0
- autotrainer/core/analysis/load_cell_monitor.py +377 -0
- autotrainer/core/analysis/load_cell_tare_monitor.py +217 -0
- autotrainer/core/analysis/measurement_data.py +80 -0
- autotrainer/core/analysis/pellet_position_monitor.py +108 -0
- autotrainer/core/analysis/sensor_analysis.py +390 -0
- autotrainer/core/analysis/system_fault_monitor.py +81 -0
- autotrainer/core/analysis/system_maintenance_monitor.py +88 -0
- autotrainer/core/animal/__init__.py +1 -0
- autotrainer/core/animal/animal_subject.py +208 -0
- autotrainer/core/capture.py +25 -0
- autotrainer/core/configuration/__init__.py +88 -0
- autotrainer/core/configuration/alarm_configuration.py +55 -0
- autotrainer/core/configuration/animal_presence_configuration.py +17 -0
- autotrainer/core/configuration/behavior_configuration.py +323 -0
- autotrainer/core/configuration/camera_configuration.py +108 -0
- autotrainer/core/configuration/external_doors_monitor_configuration.py +9 -0
- autotrainer/core/configuration/hardware_configuration.py +30 -0
- autotrainer/core/configuration/inference_configuration.py +26 -0
- autotrainer/core/configuration/load_cell_config.py +61 -0
- autotrainer/core/configuration/persistence_configuration.py +29 -0
- autotrainer/core/configuration/presence_detection_configuration.py +9 -0
- autotrainer/core/configuration/system_configuration.py +211 -0
- autotrainer/core/configuration/system_fault_config.py +9 -0
- autotrainer/core/configuration/system_maintenance_config.py +17 -0
- autotrainer/core/diamond_triangle_config.py +150 -0
- autotrainer/core/event/__init__.py +54 -0
- autotrainer/core/event/api_event_kind.py +5 -0
- autotrainer/core/event/api_event_plugin.py +57 -0
- autotrainer/core/event/event_info.py +53 -0
- autotrainer/core/event/event_manager.py +296 -0
- autotrainer/core/event/event_manager_plugin.py +45 -0
- autotrainer/core/event/file_event_plugin.py +91 -0
- autotrainer/core/event/logger_event_plugin.py +43 -0
- autotrainer/core/fixed_array_multiqueue.py +263 -0
- autotrainer/core/fixed_array_queue.py +124 -0
- autotrainer/core/frame_index.py +34 -0
- autotrainer/core/interfaces.py +347 -0
- autotrainer/core/logging.py +714 -0
- autotrainer/core/message/__init__.py +26 -0
- autotrainer/core/message/audio_spectrum_message.py +21 -0
- autotrainer/core/message/measurement_message.py +61 -0
- autotrainer/core/message/message_handler.py +158 -0
- autotrainer/core/message/motor_configuration_message.py +128 -0
- autotrainer/core/message/system_command_kind.py +74 -0
- autotrainer/core/message/system_message_handler.py +122 -0
- autotrainer/core/message/system_status_message.py +112 -0
- autotrainer/core/multiproc.py +50 -0
- autotrainer/core/notification/__init__.py +2 -0
- autotrainer/core/notification/notification_center.py +80 -0
- autotrainer/core/notification/trigger_notification.py +27 -0
- autotrainer/core/observable_object.py +105 -0
- autotrainer/core/perf_monitor.py +77 -0
- autotrainer/core/pose_elements.py +196 -0
- autotrainer/core/project/__init__.py +19 -0
- autotrainer/core/project/project_info.py +486 -0
- autotrainer/core/queue_util.py +60 -0
- autotrainer/core/reach_event.py +38 -0
- 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 @@
|
|
|
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
|