mxbiflow 0.1.1__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 (93) hide show
  1. mxbiflow/__init__.py +3 -0
  2. mxbiflow/assets/__init__.py +5 -0
  3. mxbiflow/assets/clicker.wav +0 -0
  4. mxbiflow/config_store.py +68 -0
  5. mxbiflow/data_logger.py +114 -0
  6. mxbiflow/default/__init__.py +4 -0
  7. mxbiflow/default/idle/assets/apple_v1.png +0 -0
  8. mxbiflow/default/idle/idle.py +57 -0
  9. mxbiflow/detector_bridge.py +87 -0
  10. mxbiflow/game.py +84 -0
  11. mxbiflow/infra/eventbus.py +31 -0
  12. mxbiflow/main.py +106 -0
  13. mxbiflow/models/animal.py +130 -0
  14. mxbiflow/models/reward.py +7 -0
  15. mxbiflow/models/session.py +145 -0
  16. mxbiflow/mxbiflow.py +43 -0
  17. mxbiflow/path.py +41 -0
  18. mxbiflow/scene/__init__.py +8 -0
  19. mxbiflow/scene/scene_manager.py +64 -0
  20. mxbiflow/scene/scene_protocol.py +22 -0
  21. mxbiflow/scheduler.py +90 -0
  22. mxbiflow/tasks/GNGSiD/models.py +70 -0
  23. mxbiflow/tasks/GNGSiD/stages/detect_stage/config.json +116 -0
  24. mxbiflow/tasks/GNGSiD/stages/detect_stage/detect_stage.py +161 -0
  25. mxbiflow/tasks/GNGSiD/stages/detect_stage/detect_stage_models.py +65 -0
  26. mxbiflow/tasks/GNGSiD/stages/discriminate_stage/config.json +70 -0
  27. mxbiflow/tasks/GNGSiD/stages/discriminate_stage/discriminate_stage.py +173 -0
  28. mxbiflow/tasks/GNGSiD/stages/discriminate_stage/discriminate_stage_models.py +80 -0
  29. mxbiflow/tasks/GNGSiD/stages/size_reduction_stage/config.json +83 -0
  30. mxbiflow/tasks/GNGSiD/stages/size_reduction_stage/size_reduction_models.py +58 -0
  31. mxbiflow/tasks/GNGSiD/stages/size_reduction_stage/size_reduction_stage.py +149 -0
  32. mxbiflow/tasks/GNGSiD/tasks/artifacts.py +13 -0
  33. mxbiflow/tasks/GNGSiD/tasks/detect/models.py +21 -0
  34. mxbiflow/tasks/GNGSiD/tasks/detect/scene.py +271 -0
  35. mxbiflow/tasks/GNGSiD/tasks/discriminate/discriminate_models.py +31 -0
  36. mxbiflow/tasks/GNGSiD/tasks/discriminate/discriminate_scene.py +336 -0
  37. mxbiflow/tasks/GNGSiD/tasks/touch/touch_models.py +17 -0
  38. mxbiflow/tasks/GNGSiD/tasks/touch/touch_scene.py +256 -0
  39. mxbiflow/tasks/GNGSiD/tasks/utils/targets.py +57 -0
  40. mxbiflow/tasks/cross_modal/bundle_dir.py +553 -0
  41. mxbiflow/tasks/cross_modal/config.py +41 -0
  42. mxbiflow/tasks/cross_modal/media.py +61 -0
  43. mxbiflow/tasks/cross_modal/models.py +57 -0
  44. mxbiflow/tasks/cross_modal/scene.py +252 -0
  45. mxbiflow/tasks/cross_modal/stage.py +218 -0
  46. mxbiflow/tasks/cross_modal/trial_io.py +23 -0
  47. mxbiflow/tasks/cross_modal/trial_schema.py +113 -0
  48. mxbiflow/tasks/default/error_task/error_scene.py +53 -0
  49. mxbiflow/tasks/default/idle_task/assets/apple_v1.png +0 -0
  50. mxbiflow/tasks/default/idle_task/idle_scene.py +85 -0
  51. mxbiflow/tasks/default/initial_habituation_training/README.md +188 -0
  52. mxbiflow/tasks/default/initial_habituation_training/stages/config.csv +7 -0
  53. mxbiflow/tasks/default/initial_habituation_training/stages/config.json +67 -0
  54. mxbiflow/tasks/default/initial_habituation_training/stages/initial_habituation_training_stage.py +172 -0
  55. mxbiflow/tasks/default/initial_habituation_training/stages/models.py +56 -0
  56. mxbiflow/tasks/default/initial_habituation_training/tasks/stay_to_reward/stay_to_reward.py +244 -0
  57. mxbiflow/tasks/default/initial_habituation_training/tasks/stay_to_reward/stay_to_reward_models.py +50 -0
  58. mxbiflow/tasks/task_protocol.py +26 -0
  59. mxbiflow/tasks/task_table.py +29 -0
  60. mxbiflow/tasks/two_alternative_choice/assets/starter.py +27 -0
  61. mxbiflow/tasks/two_alternative_choice/models.py +68 -0
  62. mxbiflow/tasks/two_alternative_choice/stages/size_reduction_stage/config.json +118 -0
  63. mxbiflow/tasks/two_alternative_choice/stages/size_reduction_stage/size_reduction_models.py +41 -0
  64. mxbiflow/tasks/two_alternative_choice/stages/size_reduction_stage/size_reduction_stage.py +122 -0
  65. mxbiflow/tasks/two_alternative_choice/tasks/touch/touch_models.py +19 -0
  66. mxbiflow/tasks/two_alternative_choice/tasks/touch/touch_scene.py +249 -0
  67. mxbiflow/timer/__init__.py +3 -0
  68. mxbiflow/timer/frame_timer.py +47 -0
  69. mxbiflow/timer/realtime_timer.py +0 -0
  70. mxbiflow/tmp_email.py +13 -0
  71. mxbiflow/ui/components/animal.py +87 -0
  72. mxbiflow/ui/components/baseconfig.py +68 -0
  73. mxbiflow/ui/components/card.py +18 -0
  74. mxbiflow/ui/components/device_card/__init__.py +17 -0
  75. mxbiflow/ui/components/device_card/detector/beambreak_detector_card.py +29 -0
  76. mxbiflow/ui/components/device_card/detector/fusion_detector.py +45 -0
  77. mxbiflow/ui/components/device_card/detector/mock_detector_card.py +20 -0
  78. mxbiflow/ui/components/device_card/detector/rfid_detector.py +40 -0
  79. mxbiflow/ui/components/device_card/device_card.py +67 -0
  80. mxbiflow/ui/components/device_card/rewarder/mock_rewarder_card.py +20 -0
  81. mxbiflow/ui/components/device_card/rewarder/rpi_gpio_rewarder.py +33 -0
  82. mxbiflow/ui/components/devices.py +183 -0
  83. mxbiflow/ui/components/dialog/__init__.py +3 -0
  84. mxbiflow/ui/components/dialog/add_devices_dialog.py +64 -0
  85. mxbiflow/ui/components/experiment_groups.py +122 -0
  86. mxbiflow/ui/experiment_panel.py +91 -0
  87. mxbiflow/ui/mxbi_panel.py +152 -0
  88. mxbiflow/utils/logger.py +19 -0
  89. mxbiflow/utils/serial.py +10 -0
  90. mxbiflow-0.1.1.dist-info/METADATA +168 -0
  91. mxbiflow-0.1.1.dist-info/RECORD +93 -0
  92. mxbiflow-0.1.1.dist-info/WHEEL +4 -0
  93. mxbiflow-0.1.1.dist-info/entry_points.txt +4 -0
@@ -0,0 +1,152 @@
1
+ from pymxbi import MXBIModel
2
+ from pymxbi.detector import DetectorEnum, DetectorModel
3
+ from pymxbi.rewarder import RewarderEnum, RewarderModel
4
+ from PySide6.QtCore import Signal
5
+ from PySide6.QtWidgets import (
6
+ QApplication,
7
+ QHBoxLayout,
8
+ QMainWindow,
9
+ QPushButton,
10
+ QVBoxLayout,
11
+ QWidget,
12
+ )
13
+
14
+ from ..config_store import ConfigStore
15
+ from ..models.session import Options
16
+ from ..path import MXBI_CONFIG_PATH, OPTIONS_PATH
17
+ from .components.baseconfig import BaseConfig
18
+ from .components.device_card import (
19
+ BeambreakDetectorCard,
20
+ FusionDetectorCard,
21
+ MockDetectorCard,
22
+ MockRewarderCard,
23
+ RFIDDetectorCard,
24
+ RPIGpioPumpCard,
25
+ )
26
+ from .components.devices import Devices
27
+
28
+
29
+ class MXBIPanel(QMainWindow):
30
+ accepted = Signal()
31
+
32
+ _REWARDER_CARD_FACTORIES: dict[str, type[QWidget]] = {
33
+ RewarderEnum.RPI_GPIO: RPIGpioPumpCard,
34
+ RewarderEnum.MOCK: MockRewarderCard,
35
+ }
36
+ _DETECTOR_CARD_FACTORIES: dict[str, type[QWidget]] = {
37
+ DetectorEnum.RFID_CONTINUOUS: RFIDDetectorCard,
38
+ DetectorEnum.BEAMBREAK_CONTINUOUS: BeambreakDetectorCard,
39
+ DetectorEnum.FUSION_CONTINUOUS: FusionDetectorCard,
40
+ DetectorEnum.MOCK: MockDetectorCard,
41
+ }
42
+
43
+ # -----------------------------
44
+ # Lifecycle / Init
45
+ # -----------------------------
46
+
47
+ def __init__(self):
48
+ super().__init__()
49
+ self._config = ConfigStore(MXBI_CONFIG_PATH, MXBIModel)
50
+ self._options = ConfigStore(OPTIONS_PATH, Options)
51
+
52
+ self._build_ui()
53
+ self._load_from_config()
54
+ self._bind_events()
55
+
56
+ # -----------------------------
57
+ # UI Construction
58
+ # -----------------------------
59
+
60
+ def _build_ui(self) -> None:
61
+ self.setWindowTitle("MXBI Configuration Panel")
62
+
63
+ self._widget_main = QWidget()
64
+ self._layout_main = QVBoxLayout()
65
+ self._widget_main.setLayout(self._layout_main)
66
+ self.setCentralWidget(self._widget_main)
67
+
68
+ self.base_config = BaseConfig(self, self._options.value.mxbis)
69
+ self._layout_main.addWidget(self.base_config)
70
+ self._build_device_groups()
71
+ self._layout_main.addLayout(self._build_buttons_row())
72
+
73
+ def _build_device_groups(self) -> None:
74
+ self.rewarders_group = Devices[RewarderModel](
75
+ self,
76
+ "Rewarders",
77
+ action_label="Add Rewarder",
78
+ device_types=list(RewarderEnum),
79
+ dialog_title="Add rewarder",
80
+ label="rewarder type:",
81
+ card_factories=self._REWARDER_CARD_FACTORIES,
82
+ )
83
+ self._layout_main.addWidget(self.rewarders_group)
84
+
85
+ self.detectors_group = Devices[DetectorModel](
86
+ self,
87
+ "Detectors",
88
+ action_label="Add Detector",
89
+ device_types=list(DetectorEnum),
90
+ dialog_title="Add detector",
91
+ label="detector type:",
92
+ card_factories=self._DETECTOR_CARD_FACTORIES,
93
+ )
94
+ self._layout_main.addWidget(self.detectors_group)
95
+
96
+ def _build_buttons_row(self) -> QHBoxLayout:
97
+ layout_buttons = QHBoxLayout()
98
+ self.save_button = QPushButton("Save")
99
+ self.cancel_button = QPushButton("Cancel")
100
+ self.continue_button = QPushButton("Continue")
101
+ layout_buttons.addWidget(self.cancel_button)
102
+ layout_buttons.addWidget(self.save_button)
103
+ layout_buttons.addWidget(self.continue_button)
104
+ return layout_buttons
105
+
106
+ # -----------------------------
107
+ # Load / Save
108
+ # -----------------------------
109
+
110
+ def _load_from_config(self) -> None:
111
+ self.base_config.load_from_model(self._config.value)
112
+
113
+ self.rewarders_group.load_models(self._config.value.rewarders)
114
+ self.detectors_group.load_models(self._config.value.detectors)
115
+
116
+ def _collect_result(self) -> None:
117
+ self.base_config.apply_to_model(self._config.value)
118
+
119
+ # Replace instead of append so repeated Save/Continue doesn't duplicate entries.
120
+ self._config.value.rewarders = self.rewarders_group.results()
121
+ self._config.value.detectors = self.detectors_group.results()
122
+
123
+ def _on_save(self) -> None:
124
+ self._collect_result()
125
+ self._config.save()
126
+
127
+ def _on_continue(self) -> None:
128
+ self._collect_result()
129
+ self._config.save()
130
+ self.close()
131
+ self.accepted.emit()
132
+
133
+ # -----------------------------
134
+ # Events / Menus
135
+ # -----------------------------
136
+
137
+ def _bind_events(self) -> None:
138
+ self.cancel_button.clicked.connect(self._on_cancel)
139
+ self.save_button.clicked.connect(self._on_save)
140
+ self.continue_button.clicked.connect(self._on_continue)
141
+
142
+ def _on_cancel(self) -> None:
143
+ self.close()
144
+
145
+
146
+ if __name__ == "__main__":
147
+ import sys
148
+
149
+ app = QApplication(sys.argv)
150
+ window = MXBIPanel()
151
+ window.show()
152
+ sys.exit(app.exec())
@@ -0,0 +1,19 @@
1
+ import sys
2
+
3
+ from loguru import logger
4
+
5
+ from ..path import LOG_PATH
6
+
7
+ logger.remove()
8
+
9
+ logger.add(sys.stderr, level="DEBUG")
10
+
11
+ logger.add(
12
+ f"{LOG_PATH}/mxbi.log",
13
+ rotation="10 MB",
14
+ retention="7 days",
15
+ compression="zip",
16
+ encoding="utf-8",
17
+ level="DEBUG",
18
+ serialize=True,
19
+ )
@@ -0,0 +1,10 @@
1
+ from serial import SerialBase
2
+ from serial.tools import list_ports
3
+
4
+
5
+ def get_baudrates():
6
+ return [(str(baudrate), baudrate) for baudrate in SerialBase.BAUDRATES]
7
+
8
+
9
+ def get_all_ports():
10
+ return [port.device for port in list_ports.comports() if port.device is not None]
@@ -0,0 +1,168 @@
1
+ Metadata-Version: 2.3
2
+ Name: mxbiflow
3
+ Version: 0.1.1
4
+ Summary: mxbiflow is a toolkit based on pygame and pymxbi
5
+ Author: HuYang
6
+ Author-email: HuYang <huyangcommit@gmail.com>
7
+ Requires-Dist: gpiozero>=2.0.1
8
+ Requires-Dist: inflection>=0.5.1
9
+ Requires-Dist: keyring>=25.6.0
10
+ Requires-Dist: loguru>=0.7.3
11
+ Requires-Dist: matplotlib>=3.10.6
12
+ Requires-Dist: mss>=10.1.0
13
+ Requires-Dist: numpy>=2.3.3
14
+ Requires-Dist: pandas>=2.3.2
15
+ Requires-Dist: pillow>=11.3.0
16
+ Requires-Dist: pyaudio>=0.2.14
17
+ Requires-Dist: pydantic>=2.11.7
18
+ Requires-Dist: pygame-ce>=2.5.6
19
+ Requires-Dist: pymotego>=0.1.3
20
+ Requires-Dist: pymxbi>=0.1.2
21
+ Requires-Dist: pyserial>=3.5
22
+ Requires-Dist: pyside6>=6.10.1
23
+ Requires-Dist: qtawesome>=1.4.1
24
+ Requires-Dist: rich>=14.1.0
25
+ Requires-Dist: typer>=0.20.0
26
+ Requires-Dist: varname>=0.15.0
27
+ Requires-Python: >=3.14
28
+ Description-Content-Type: text/markdown
29
+
30
+ ## TODO
31
+
32
+ - [ ] session should be managed automatically
33
+
34
+ ## Table of Contents
35
+ - [Task](https://github.com/Ccccraz/mxbi/blob/main/docs/task.md)
36
+
37
+ ## Get Started 🚀
38
+
39
+ I typically use `uv` to manage a Python project, and I **highly recommend** you use `uv` to start the mxbi code as well.
40
+
41
+ ```shell
42
+ cd # Go back to home
43
+
44
+ cd /path/your_favorite # Choose your favorite directory
45
+
46
+ git clone https://github.com/Ccccraz/mxbi.git # Clone the mxbi repository
47
+
48
+ cd mxbi # Enter the mxbi directory
49
+
50
+ uv sync # Install required dependencies
51
+
52
+ uv run mxbi # Start mxbi
53
+ ```
54
+
55
+ ## Current architecture
56
+
57
+ Currently, the entire code structure is divided into five main parts:
58
+
59
+
60
+ - **User GUI**: used for manually adjusting experiment settings
61
+ - **Task scheduler**: used for adjusting task difficulty and switching between tasks
62
+ - **Task**: used for executing specific tasks
63
+ - **Theater**: serves as the environment for task execution
64
+ - **Detector**: Detector, used to detect RFID tags
65
+
66
+ ```mermaid
67
+ flowchart LR
68
+ user_gui -->|create theater| theater
69
+ theater -->|create scheduler| scheduler
70
+ scheduler -->|create task| task
71
+ task -->|adjust level| scheduler
72
+ scheduler -->|check rfid| detector
73
+ detector -->|control| scheduler
74
+ ```
75
+
76
+ ## Task Scheduler
77
+
78
+ There were too many different **states** in the original code, which made the code branch paths overly complex. Therefore, I decided to separate the task `scheduler`, ensuring that the tasks themselves are stateless and that their inputs and outputs are deterministic. The task scheduler will ensure that its initial state is correct.
79
+
80
+ Moreover, the `Protocol` is used to define the interface of Task, which enables the scheduler not only to adjust the difficulty but also to switch between tasks.
81
+
82
+ ## Detector
83
+
84
+ ### Overview
85
+
86
+ The RFID module should run in an independent thread, performing detection every **100 ms** and triggering corresponding callbacks based on the detection results.
87
+
88
+ ### Detector States
89
+
90
+ - **NO_ANIMAL**: No animal detected
91
+ - **ANIMAL_PRESENT**: One animal detected
92
+ - **MORE_THAN_ONE_ANIMAL**: Multiple animals detected (defined as error behavior)
93
+
94
+ ### Data Maintenance
95
+
96
+ - **current_animal**: Currently detected animal
97
+ - **history_animal**: Historical animal record
98
+
99
+ ### State Transition Events
100
+
101
+ - **NO_ANIMAL → ANIMAL_PRESENT** and current_animal != history_animal: New animal appears
102
+ - **NO_ANIMAL → ANIMAL_PRESENT** and current_animal == history_animal: Animal returns
103
+ - **ANIMAL_PRESENT → NO_ANIMAL**: Animal leaves
104
+ - **ANIMAL_PRESENT → ANIMAL_PRESENT** and current_animal != history_animal: New animal appears
105
+ - **ANIMAL_PRESENT → MORE_THAN_ONE_ANIMAL**: Multiple animals detected (error behavior)
106
+ - **MORE_THAN_ONE_ANIMAL → ANIMAL_PRESENT**: Recovery
107
+ - **MORE_THAN_ONE_ANIMAL → NO_ANIMAL**: Recovery
108
+
109
+ ### Scheduler State Regulation
110
+
111
+ - **ANIMAL_ENTERED** → Scheduler in SCHEDULE
112
+ - **ANIMAL_RETURNED** → Scheduler in SCHEDULE
113
+ - **ANIMAL_CHANGED** → Scheduler in SCHEDULE
114
+ - **ANIMAL_LEFT** → Scheduler in IDLE
115
+ - **ERROR_DETECTED** → Scheduler in ERROR
116
+
117
+ ```mermaid
118
+ sequenceDiagram
119
+ participant RFID_Thread
120
+ participant Detector
121
+ participant Scheduler
122
+
123
+ loop Every 100 ms
124
+ RFID_Thread->>Detector: Perform detection
125
+ activate Detector
126
+
127
+ alt NO_ANIMAL → ANIMAL_PRESENT (current ≠ history)
128
+ Detector->>Detector: State transition
129
+ Detector->>Scheduler: ANIMAL_ENTERED
130
+ Scheduler->>Scheduler: Set to SCHEDULE
131
+ else NO_ANIMAL → ANIMAL_PRESENT (current = history)
132
+ Detector->>Detector: State transition
133
+ Detector->>Scheduler: ANIMAL_RETURNED
134
+ Scheduler->>Scheduler: Set to SCHEDULE
135
+ else ANIMAL_PRESENT → NO_ANIMAL
136
+ Detector->>Detector: State transition
137
+ Detector->>Scheduler: ANIMAL_LEFT
138
+ Scheduler->>Scheduler: Set to IDLE
139
+ else ANIMAL_PRESENT → ANIMAL_PRESENT (current ≠ history)
140
+ Detector->>Detector: State transition
141
+ Detector->>Scheduler: ANIMAL_CHANGED
142
+ Scheduler->>Scheduler: Set to SCHEDULE
143
+ else ANIMAL_PRESENT → MORE_THAN_ONE_ANIMAL
144
+ Detector->>Detector: State transition
145
+ Detector->>Scheduler: ERROR_DETECTED
146
+ Scheduler->>Scheduler: Set to ERROR
147
+ else MORE_THAN_ONE_ANIMAL → ANIMAL_PRESENT
148
+ Detector->>Detector: State transition
149
+ Detector->>Scheduler: Recovery event
150
+ Scheduler->>Scheduler: Set to SCHEDULE
151
+ else MORE_THAN_ONE_ANIMAL → NO_ANIMAL
152
+ Detector->>Detector: State transition
153
+ Detector->>Scheduler: Recovery event
154
+ Scheduler->>Scheduler: Set to IDLE
155
+ end
156
+
157
+ deactivate Detector
158
+ end
159
+ ```
160
+
161
+ ## Extract data model
162
+
163
+ The states in the original code were scattered across a large number of variables, so I tried to extract all the data models for unified management. You can find most of the data models under `src/mxbi/models`.
164
+
165
+ ## TODO:
166
+
167
+ - More tasks
168
+ - More detailed instruction documents
@@ -0,0 +1,93 @@
1
+ mxbiflow/__init__.py,sha256=ozmSVFtsr5ddD7pThZNi_guF59SjTpumU1AuvAWbJK0,85
2
+ mxbiflow/assets/__init__.py,sha256=q4EMjlEE0iRc5LGRC-ecFfHcZVgDZTpcHFvpEv5LpSg,98
3
+ mxbiflow/assets/clicker.wav,sha256=EigwY1fa3iwx4JEsnur1PUIZBndrwaLCUv7C5FlSOD8,176582
4
+ mxbiflow/config_store.py,sha256=vVQI4Jv_DTwXL5wg2dvdmzaLuC1OcGDEZjC-GyQ5PW0,2134
5
+ mxbiflow/data_logger.py,sha256=01LtrBMYcm2zqASXdQJzmwRs6HNUCvtHK6S7TspgFOE,3619
6
+ mxbiflow/default/__init__.py,sha256=m4mByPSQBoqPot0ynQcUgK6PiPaCNuWEYQOdnWmkq4U,112
7
+ mxbiflow/default/idle/assets/apple_v1.png,sha256=bKrntrgfA82A2vgS5XLL3DEpC7NtY4kYCDoriG9q5Ko,2185277
8
+ mxbiflow/default/idle/idle.py,sha256=ZhDzXqmExsTXNuE7GncbNXmj8_VF0XdXsvYvXqJa_Nw,1470
9
+ mxbiflow/detector_bridge.py,sha256=D5hOCt7CgeZ5oReJql588nR-Va2wDMqnFxWieC_EvgU,2840
10
+ mxbiflow/game.py,sha256=pvsvSt_mfiGloJk-nQB7fDNzS48yOxz6_Ww8hTBcCwk,2439
11
+ mxbiflow/infra/eventbus.py,sha256=DnAHmRW13Emp6zfeZDJUwbiypHAzPKK62IpuUFOZguo,751
12
+ mxbiflow/main.py,sha256=aYvknPr68ZDc-Y-eJi-OfEkA-D9TQPCP5yK80aR1DAw,2935
13
+ mxbiflow/models/animal.py,sha256=3alb7ZUT-cmGFYE23oVVIAlTV6ye7Es1pRmE62VfH_E,3881
14
+ mxbiflow/models/reward.py,sha256=gmy6Cb-BPCpYvFmSPBJXUCJKIJQPp5BCJsWv-q0pt2A,138
15
+ mxbiflow/models/session.py,sha256=LKTTZ9bpONbsY4oG9MvlvMO2JOjY3-Klc0_KybWvN8Q,4188
16
+ mxbiflow/mxbiflow.py,sha256=zhkdhlFcpy-1lqH-gHU3QajW5bazf6BeLJtwbqSxKFs,980
17
+ mxbiflow/path.py,sha256=UD4FEew3QK6ni6PBiuZ67kyY1wUF2SQyAo_7lMhAGFA,1455
18
+ mxbiflow/scene/__init__.py,sha256=PpsHr3KKReFsc-MN3Gj1OmqvCCCQornT0mfdkxRqJtA,160
19
+ mxbiflow/scene/scene_manager.py,sha256=D1TN9T-SSeUu33fulTexx6hy0OS4zFuxu8SAUX41blg,1708
20
+ mxbiflow/scene/scene_protocol.py,sha256=U3SXoAAues5H8qIeQwY29PRRYAoUhPZMgoC6KDQtK2I,455
21
+ mxbiflow/scheduler.py,sha256=58lOoqiqpjhciIAyhcC9mTR_LtxwAdBuVUl7Dci3pCk,2536
22
+ mxbiflow/tasks/GNGSiD/models.py,sha256=cUZMIHRy-fIlA0vxkTObMRfDKsQtsQz2JL54Z9rXcl0,1209
23
+ mxbiflow/tasks/GNGSiD/stages/detect_stage/config.json,sha256=LRkH-tcQDku-NJbkBtEJMXhND4RLX7A2441VVSNPZz8,3718
24
+ mxbiflow/tasks/GNGSiD/stages/detect_stage/detect_stage.py,sha256=KDHFjSk1jnw2Uhve2pIu89nUlABPU8Abyrrj1EPNios,5530
25
+ mxbiflow/tasks/GNGSiD/stages/detect_stage/detect_stage_models.py,sha256=_AL0hotrxOZT2GFUXQ5l6a6kJ30pdilf2UAnymgMahQ,1502
26
+ mxbiflow/tasks/GNGSiD/stages/discriminate_stage/config.json,sha256=prV8qahUHfoLIXxKpBHH6AhliqpLxim0GVPMznFXh3k,2271
27
+ mxbiflow/tasks/GNGSiD/stages/discriminate_stage/discriminate_stage.py,sha256=8eBGdT0Zf2wbJLXQ7x7niVBTeP6MESgtGTt_U6TUqek,6419
28
+ mxbiflow/tasks/GNGSiD/stages/discriminate_stage/discriminate_stage_models.py,sha256=UvAbt18krt9sa73wjtYpN1PnzcWQkdLYR5ZO_OtLOq0,1938
29
+ mxbiflow/tasks/GNGSiD/stages/size_reduction_stage/config.json,sha256=ZcfVVnOc_RZ5cqUVH-LO1z9EPLL6-wxsCA7UHSwgAXw,2300
30
+ mxbiflow/tasks/GNGSiD/stages/size_reduction_stage/size_reduction_models.py,sha256=FFp9PB27forrphIn4oM2njnwi7SRq0DNhvdyiflWB10,1431
31
+ mxbiflow/tasks/GNGSiD/stages/size_reduction_stage/size_reduction_stage.py,sha256=SBneX5BN9tdgQVqF8UbbVNte6ue8ghbrOZvIugHN2ug,5172
32
+ mxbiflow/tasks/GNGSiD/tasks/artifacts.py,sha256=8f_pNYr6YrRBTF3VZrN5VHglJ0rugRqDU3vqc91pFNY,352
33
+ mxbiflow/tasks/GNGSiD/tasks/detect/models.py,sha256=SBrEC3ve8XpYAa9dm8pZsZr3MIhzpho_2zx0_MwqjhI,438
34
+ mxbiflow/tasks/GNGSiD/tasks/detect/scene.py,sha256=qiT8FpX3C8-t6MTcSejfwoiMrQ21RebHXVeqrfvKK2I,9206
35
+ mxbiflow/tasks/GNGSiD/tasks/discriminate/discriminate_models.py,sha256=wkxv1B5DD2V6wTSUy4nEjI1PGP7WjbG3TGcWDFPn8Hs,765
36
+ mxbiflow/tasks/GNGSiD/tasks/discriminate/discriminate_scene.py,sha256=5fhheLA6PzbzSf9HwVqr6_trl0X8L7YQxQfHuqA8bqc,11769
37
+ mxbiflow/tasks/GNGSiD/tasks/touch/touch_models.py,sha256=nh_Oyh6dCbHTjwaXGzuH-Pch_xe4dNBeTF-ZPQlzmyc,378
38
+ mxbiflow/tasks/GNGSiD/tasks/touch/touch_scene.py,sha256=LUthSquO14UuzhWy1vDdMb8f1dlNqfGQtwbcskBmMm4,8571
39
+ mxbiflow/tasks/GNGSiD/tasks/utils/targets.py,sha256=JLoE0r5wmctsKrkPFY402L764-4lHfPHlH-IOK4TcHE,1588
40
+ mxbiflow/tasks/cross_modal/bundle_dir.py,sha256=tDYCIlVl2yxgijDFh8uLfybF2EiTxJrPeK6emmgGPJY,19249
41
+ mxbiflow/tasks/cross_modal/config.py,sha256=2ySh_tETMfBqwMl6ano2luOpLOq4a1SalwILDuml2bM,1493
42
+ mxbiflow/tasks/cross_modal/media.py,sha256=Btz_ClXcK3Xwdl84K_lsh799bl6j9ZXE4JoYSuyzjho,1954
43
+ mxbiflow/tasks/cross_modal/models.py,sha256=hmfbB-niENbmM5Mmifk3lx6LOpd-kg9Y83Rh-pTUYUU,1050
44
+ mxbiflow/tasks/cross_modal/scene.py,sha256=ldSnvkOil4rBmk4r-IVsbjQg_t5fb2SWrFcKeEV5v5E,8282
45
+ mxbiflow/tasks/cross_modal/stage.py,sha256=ckB5p9jYbXqVocO7OV7XjS6uj6HlX4hOCPtZYmTc83k,8060
46
+ mxbiflow/tasks/cross_modal/trial_io.py,sha256=KUfixonadRVDZK4XROkY93V5DyhGIuSsIHkfaZxCJx4,669
47
+ mxbiflow/tasks/cross_modal/trial_schema.py,sha256=L_F2BIhyjrluErh0qVjV90f8fw9ybYITbD0N9VcKGSg,3804
48
+ mxbiflow/tasks/default/error_task/error_scene.py,sha256=2hcU6nTWTDm62wJGTgSSkOuvmKtyYB5Zur8TaSPWJqE,1396
49
+ mxbiflow/tasks/default/idle_task/assets/apple_v1.png,sha256=bKrntrgfA82A2vgS5XLL3DEpC7NtY4kYCDoriG9q5Ko,2185277
50
+ mxbiflow/tasks/default/idle_task/idle_scene.py,sha256=v5rK5mvkHizh6HuJlVUdLkKWmeKjPNBp9Dhx33HGRHM,2583
51
+ mxbiflow/tasks/default/initial_habituation_training/README.md,sha256=E0S5Bnf69-iHSgm9NVpzw41yAg41hlHC1tdbD4J5RKk,6517
52
+ mxbiflow/tasks/default/initial_habituation_training/stages/config.csv,sha256=gBWxw6l2kV0YzxdgwcmKzSR7io5UAzXZBuAixOQVLzk,243
53
+ mxbiflow/tasks/default/initial_habituation_training/stages/config.json,sha256=UG8tOmCwtQHKb45wX3kdH3NuLchZF3E_H08nJWf8abQ,2065
54
+ mxbiflow/tasks/default/initial_habituation_training/stages/initial_habituation_training_stage.py,sha256=1nk7Sj-zxgp_3NgG1FKfjmbbmFm2lLqOARZpEhm8YtQ,5658
55
+ mxbiflow/tasks/default/initial_habituation_training/stages/models.py,sha256=X3NWmL9ZCdhOZyCOZT7cOpOaKDBMEIv7UeTPCiLkxFg,1412
56
+ mxbiflow/tasks/default/initial_habituation_training/tasks/stay_to_reward/stay_to_reward.py,sha256=rDDb0KgmRJTjyKJIJ44n7ZF25YNrH5uEmxillWceS_8,8168
57
+ mxbiflow/tasks/default/initial_habituation_training/tasks/stay_to_reward/stay_to_reward_models.py,sha256=b1IpQP86F_aWUgFKTnvH3dOLNqjyGjp-BxBI9w5GzkE,947
58
+ mxbiflow/tasks/task_protocol.py,sha256=4Ard1waHI77ZpbgoB9v6u3Wka13hpLP4mgpArun4Wq4,655
59
+ mxbiflow/tasks/task_table.py,sha256=hXV1GYtgfRDpIBDpwraRDiWmYXFhEEQ32Le1ItBkFFg,1285
60
+ mxbiflow/tasks/two_alternative_choice/assets/starter.py,sha256=AMm7_yQOwXg0OuSKXHc-WSmu4tp87-ELPYwPe_cv75g,572
61
+ mxbiflow/tasks/two_alternative_choice/models.py,sha256=N7B3jn8sM02k7mv9pu5k26lqcREHuTEatiVwz2iZN5s,1181
62
+ mxbiflow/tasks/two_alternative_choice/stages/size_reduction_stage/config.json,sha256=S64uPhM7XwoYQ46g2R7Z2msru5ohT7kBP3WlHzUweM4,3179
63
+ mxbiflow/tasks/two_alternative_choice/stages/size_reduction_stage/size_reduction_models.py,sha256=1FGhsIHBZnZ52YPIo8tpAeNsto3ydqlSy7fuuEsl45o,1147
64
+ mxbiflow/tasks/two_alternative_choice/stages/size_reduction_stage/size_reduction_stage.py,sha256=vMu0XrrpnPr7rNZCA8USFYDCODgLd6rfNcxfoPV7VUs,4055
65
+ mxbiflow/tasks/two_alternative_choice/tasks/touch/touch_models.py,sha256=L8wEX7Nv4JVKTQX7zR0KcCNULx4FmiY3qI_ojWKwOk0,342
66
+ mxbiflow/tasks/two_alternative_choice/tasks/touch/touch_scene.py,sha256=OQZGa_nler82HKvDhuplxrtMD8nm06nx7p0vjFZdRGg,8395
67
+ mxbiflow/timer/__init__.py,sha256=lABOmME2FSR0EHGe-lz4p-d_PCBamZCjPQx0Mr1jwmE,62
68
+ mxbiflow/timer/frame_timer.py,sha256=Yfx-u_-Qe-HxODVIQYNtA-iwGd0dWckTx_lhaShdZY8,1331
69
+ mxbiflow/timer/realtime_timer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
+ mxbiflow/tmp_email.py,sha256=A7GpHoMIi9JjoKD10z4ohD6Mz-2D9lMLQvuP08H9zys,448
71
+ mxbiflow/ui/components/animal.py,sha256=4YQ6VF5ts1u96wmux_Kn3JLAhjJ9_s7nMtgtqXOy6LY,3269
72
+ mxbiflow/ui/components/baseconfig.py,sha256=rjsErRi7NZAO3Yb_5l8YCd1g7bPDyb0R85FaJoXvi-c,2297
73
+ mxbiflow/ui/components/card.py,sha256=LdI99dL3S21y72KOkbFD0ByiDuMk4ptuST3m5q2OOcc,484
74
+ mxbiflow/ui/components/device_card/__init__.py,sha256=m6cwCdcppCEXTBRa0VQXG1HtgkYNrusQKoUgO1_IkI4,569
75
+ mxbiflow/ui/components/device_card/detector/beambreak_detector_card.py,sha256=X0BuACjZZZpKCjqrOGySEn8KiUlCHCyCSt_HwR5iFXI,998
76
+ mxbiflow/ui/components/device_card/detector/fusion_detector.py,sha256=RvEpKTspIjPqLH3eKJkO-rkQOWlB22NECyjOkllV5Go,1757
77
+ mxbiflow/ui/components/device_card/detector/mock_detector_card.py,sha256=OZcl5nSgGWsVminqtOzjLYiWwIJxle9S7Luh018h2MM,606
78
+ mxbiflow/ui/components/device_card/detector/rfid_detector.py,sha256=2U28nlShCQs0udB-bIP1Kl1A5VCXy_lxKtGYZr_tack,1452
79
+ mxbiflow/ui/components/device_card/device_card.py,sha256=mP6S74fOciDW1tvZS2vDTKU8iUjVgXA9iiNYA6vqDRE,2030
80
+ mxbiflow/ui/components/device_card/rewarder/mock_rewarder_card.py,sha256=SxlMgu_QKJYfVnCngzr5rqmTLHF0f-bVw4c3CT30M1k,606
81
+ mxbiflow/ui/components/device_card/rewarder/rpi_gpio_rewarder.py,sha256=lf18Oqx7eI1lWBVyuH-RgfqYb9zJU7-HiX_6CiqG8C4,1067
82
+ mxbiflow/ui/components/devices.py,sha256=1r8D0OBBdyXEBkkmd96Ir6OqarRSxzWiq8ZJgdGMOfY,5351
83
+ mxbiflow/ui/components/dialog/__init__.py,sha256=N_P4NFqf7H10XbWV6tkc5PJR-aT-huXFfD9D2eUCpv0,79
84
+ mxbiflow/ui/components/dialog/add_devices_dialog.py,sha256=DrcDfBOQZzjARlj-K9kSFQGriOdo6Q7oIf2Zr1SNX-s,1737
85
+ mxbiflow/ui/components/experiment_groups.py,sha256=9CwJ4g4cfhKv3-JO5y9Qv-HlJfGB_gcBQEtNola2zdM,4258
86
+ mxbiflow/ui/experiment_panel.py,sha256=LOsOsYT7GwOEl0p6XXWvYoF-ugua6QySB8maXTnjNRw,2824
87
+ mxbiflow/ui/mxbi_panel.py,sha256=jLET_x2KGTo4Fr4XN0qo2mV7052QlD5M3Tzt1CKlNLk,4828
88
+ mxbiflow/utils/logger.py,sha256=6pMngPkcs-TWfHbI3I75mNqvTXQCFEFjXL8t2DNhoNE,296
89
+ mxbiflow/utils/serial.py,sha256=xAOymmyoU6JvOTC0HFL3DK1tVkTiXPLsC0plLZYMLKA,274
90
+ mxbiflow-0.1.1.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
91
+ mxbiflow-0.1.1.dist-info/entry_points.txt,sha256=cGSAdRH0zM2dvODbfV1or4Hdhxpq7j6eyEjnV2dYaeE,62
92
+ mxbiflow-0.1.1.dist-info/METADATA,sha256=Ag6-jZjo4rVZmdzHcHMPziFtZ0NPrtwszbBPqu9er14,5869
93
+ mxbiflow-0.1.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.8.24
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ main = mxbiflow.main:main
3
+ mxbi = mxbi:main
4
+