pycontrol-gui 3.0.0a1__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.
- pycontrol_gui-3.0.0a1/.gitignore +29 -0
- pycontrol_gui-3.0.0a1/PKG-INFO +228 -0
- pycontrol_gui-3.0.0a1/README.md +213 -0
- pycontrol_gui-3.0.0a1/docs/architecture.md +338 -0
- pycontrol_gui-3.0.0a1/docs/code-review.md +179 -0
- pycontrol_gui-3.0.0a1/docs/extensions.md +180 -0
- pycontrol_gui-3.0.0a1/docs/plot-plugins.md +297 -0
- pycontrol_gui-3.0.0a1/docs/task-controls.md +208 -0
- pycontrol_gui-3.0.0a1/docs/task-sharing.md +119 -0
- pycontrol_gui-3.0.0a1/pyproject.toml +59 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/__init__.py +15 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/__main__.py +5 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/app.py +102 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/bus_adapter.py +54 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/error_logging.py +134 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/experiment_extensions.py +39 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/main_window.py +894 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/persistent_variables.py +55 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/__init__.py +17 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/base.py +38 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/default_plotter.py +123 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/host.py +364 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/loader.py +48 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/profiling.py +81 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/widgets/__init__.py +7 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/widgets/analog_plot.py +167 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/widgets/events_plot.py +164 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/widgets/states_plot.py +132 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/__init__.py +38 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/add.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/bar-graph.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/book.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/circle-arrow-up.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/circle-arrow-up_white.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/close.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/close_white.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/collapse.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/comment.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/connect.svg +12 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/copy.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/copy_evil.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/delete.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/detach.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/disable.svg +5 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/disconnect.svg +13 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/down.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/edit.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/enable.svg +4 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/expand.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/filter.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/folder.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/funnel.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/github.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/help.svg +8 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/info.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/keyboard.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/left.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/logo.svg +68 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/mount.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/notion.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/pause.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/play.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/play_white.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/record.svg +10 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/record_white.svg +8 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/refresh.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/remove.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/right.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/run.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/run_white.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/save.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/save_as.svg +6 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/settings.svg +4 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/share.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/stop.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/stop_white.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/telegram.svg +1 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/trash.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/up.svg +3 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/upload.svg +6 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/wrench.svg +4 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/sandbox_session.py +83 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/session_controller.py +605 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/session_helpers.py +183 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/session_runtime.py +194 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/setup_maintenance.py +139 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/task_variables.py +121 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/update_check.py +283 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/__init__.py +34 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/about_dialog.py +103 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/controls_dialog.py +828 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/controls_dialog_editor.py +885 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/controls_spec_io.py +36 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/error_log_dialog.py +115 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_editor_rows.py +70 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_editor_table.py +137 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_run_control.py +144 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_run_models.py +48 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_run_plots.py +306 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_run_summary.py +113 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_run_view.py +1288 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiments_tab.py +1859 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/file_tree.py +46 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/hardware_variables_dialog.py +206 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/keyboard_shortcuts_dialog.py +68 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/log_filter_controller.py +218 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/log_view.py +221 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/run_task_tab.py +1598 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/sandbox_dialog.py +422 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/session_controls_shell.py +42 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/session_event_ui.py +177 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/session_panel.py +218 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/session_shutdown_ui.py +42 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/settings_dialog.py +728 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/setups_tab.py +837 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/share_dialog.py +162 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/style.py +177 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/subject_run_panel.py +1282 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/task_controls_host.py +144 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/task_selector_widgets.py +161 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/task_status.py +177 -0
- pycontrol_gui-3.0.0a1/src/pycontrol_gui/workspace_model.py +699 -0
- pycontrol_gui-3.0.0a1/tests/CLASSIFICATION.md +11 -0
- pycontrol_gui-3.0.0a1/tests/__init__.py +1 -0
- pycontrol_gui-3.0.0a1/tests/conftest.py +5 -0
- pycontrol_gui-3.0.0a1/tests/support/__init__.py +1 -0
- pycontrol_gui-3.0.0a1/tests/support/fake_board.py +352 -0
- pycontrol_gui-3.0.0a1/tests/test_app.py +81 -0
- pycontrol_gui-3.0.0a1/tests/test_bus_adapter.py +48 -0
- pycontrol_gui-3.0.0a1/tests/test_controls_dialog.py +53 -0
- pycontrol_gui-3.0.0a1/tests/test_error_log_dialog.py +22 -0
- pycontrol_gui-3.0.0a1/tests/test_error_logging.py +61 -0
- pycontrol_gui-3.0.0a1/tests/test_experiment_run_plots.py +49 -0
- pycontrol_gui-3.0.0a1/tests/test_experiment_run_view.py +1079 -0
- pycontrol_gui-3.0.0a1/tests/test_log_view.py +260 -0
- pycontrol_gui-3.0.0a1/tests/test_model_view_widgets.py +86 -0
- pycontrol_gui-3.0.0a1/tests/test_persistent_variables.py +36 -0
- pycontrol_gui-3.0.0a1/tests/test_plotting_loader.py +57 -0
- pycontrol_gui-3.0.0a1/tests/test_plotting_widgets.py +156 -0
- pycontrol_gui-3.0.0a1/tests/test_session_controller.py +819 -0
- pycontrol_gui-3.0.0a1/tests/test_session_event_ui.py +48 -0
- pycontrol_gui-3.0.0a1/tests/test_session_runtime.py +62 -0
- pycontrol_gui-3.0.0a1/tests/test_settings_dialog.py +47 -0
- pycontrol_gui-3.0.0a1/tests/test_setups_tab.py +49 -0
- pycontrol_gui-3.0.0a1/tests/test_share_dialog.py +172 -0
- pycontrol_gui-3.0.0a1/tests/test_smoke.py +207 -0
- pycontrol_gui-3.0.0a1/tests/test_task_variables.py +32 -0
- pycontrol_gui-3.0.0a1/tests/test_update_check.py +33 -0
- pycontrol_gui-3.0.0a1/tests/test_workspace_model.py +484 -0
- pycontrol_gui-3.0.0a1/uv.lock +472 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
### macOS
|
|
2
|
+
# Finder metadata
|
|
3
|
+
.DS_Store
|
|
4
|
+
|
|
5
|
+
# Thumbnails
|
|
6
|
+
._*
|
|
7
|
+
|
|
8
|
+
# Custom folder icons
|
|
9
|
+
Icon
|
|
10
|
+
|
|
11
|
+
# Volume root files
|
|
12
|
+
.DocumentRevisions-V100
|
|
13
|
+
.fseventsd
|
|
14
|
+
.Spotlight-V100
|
|
15
|
+
.TemporaryItems
|
|
16
|
+
.Trashes
|
|
17
|
+
.VolumeIcon.icns
|
|
18
|
+
.com.apple.timemachine.donotpresent
|
|
19
|
+
|
|
20
|
+
### Python / uv
|
|
21
|
+
__pycache__/
|
|
22
|
+
*.py[cod]
|
|
23
|
+
.mypy_cache/
|
|
24
|
+
.pytest_cache/
|
|
25
|
+
.ruff_cache/
|
|
26
|
+
.venv/
|
|
27
|
+
dist/
|
|
28
|
+
build/
|
|
29
|
+
*.egg-info/
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pycontrol-gui
|
|
3
|
+
Version: 3.0.0a1
|
|
4
|
+
Summary: Qt desktop frontend for pycontrol-core.
|
|
5
|
+
Author: Karpova Lab contributors
|
|
6
|
+
License: GPL-3.0-or-later
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Requires-Dist: pycontrol-core<3.1,>=3.0.0a1
|
|
9
|
+
Requires-Dist: pyqtgraph>=0.13.7
|
|
10
|
+
Requires-Dist: pyside6>=6.8
|
|
11
|
+
Provides-Extra: test
|
|
12
|
+
Requires-Dist: pytest-qt>=4.4; extra == 'test'
|
|
13
|
+
Requires-Dist: pytest>=8; extra == 'test'
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# pycontrol-gui
|
|
17
|
+
|
|
18
|
+
`pycontrol-gui` is the Qt desktop frontend for `pycontrol-core`.
|
|
19
|
+
|
|
20
|
+
It provides the main pyControl operator workflows:
|
|
21
|
+
|
|
22
|
+
- Run one task on one setup.
|
|
23
|
+
- Edit and run multi-subject experiments.
|
|
24
|
+
- Manage setup names, ports, auto-detected MCU cache, and setup variables.
|
|
25
|
+
- View live logs and plots.
|
|
26
|
+
- Use workspace task extensions, experiment extensions, task plotters, task
|
|
27
|
+
controls, and extension settings.
|
|
28
|
+
|
|
29
|
+
## Install From PyPI Alpha
|
|
30
|
+
|
|
31
|
+
For the `3.0.0a1` alpha, pin the prerelease:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv add "pycontrol-gui==3.0.0a1"
|
|
35
|
+
# or
|
|
36
|
+
pip install --pre "pycontrol-gui==3.0.0a1"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
To accept the newest available alpha with uv, use:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
uv add pycontrol-gui --prerelease allow
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Install For Development
|
|
46
|
+
|
|
47
|
+
Install the sibling core package first:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cd ../pycontrol-core
|
|
51
|
+
pip install -e ".[test,lint]"
|
|
52
|
+
|
|
53
|
+
cd ../pycontrol-gui
|
|
54
|
+
pip install -e ".[test]"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
With `uv`, `pycontrol-gui/pyproject.toml` points `pycontrol-core` at the
|
|
58
|
+
sibling `../pycontrol-core` path.
|
|
59
|
+
|
|
60
|
+
Run the app:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pycontrol-gui
|
|
64
|
+
pycontrol-gui /path/to/workspace
|
|
65
|
+
# or
|
|
66
|
+
python -m pycontrol_gui
|
|
67
|
+
python -m pycontrol_gui /path/to/workspace
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Run tests with Python's module form so stale local script shebangs do not get in
|
|
71
|
+
the way:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv run python -m pytest
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Workspaces
|
|
78
|
+
|
|
79
|
+
Open a workspace with **Workspace -> Open Workspace...**, create one with
|
|
80
|
+
**Workspace -> New Workspace...**, or pass a workspace path on the command line.
|
|
81
|
+
If no path is supplied, the GUI uses the last-opened workspace from application
|
|
82
|
+
preferences, then falls back to discovering a workspace from the current working
|
|
83
|
+
directory. Use **Workspace -> Reload workspace** to refresh selectors after
|
|
84
|
+
external file changes.
|
|
85
|
+
|
|
86
|
+
The GUI uses the standard `pycontrol-core` workspace layout:
|
|
87
|
+
|
|
88
|
+
| Path | GUI use |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| `tasks/` | Task selector in Run task and Experiments. |
|
|
91
|
+
| `hardware_definitions/` | Hardware-definition selector and setup validation. |
|
|
92
|
+
| `devices/` | Workspace-local device drivers for task sharing and setup maintenance. |
|
|
93
|
+
| `plugins/task_extensions/` | Host-side task automation. |
|
|
94
|
+
| `plugins/experiment_extensions/` | Whole-experiment automation. |
|
|
95
|
+
| `plugins/task_plotters/` | Custom live plot widgets. |
|
|
96
|
+
| `plugins/task_controls/` | Declarative or Python task-control panels. |
|
|
97
|
+
| `experiments/*.json` | Experiment editor and run view. |
|
|
98
|
+
| `settings.json` / `setups.json` | Workspace settings and setup registry. |
|
|
99
|
+
|
|
100
|
+
Workspace `settings.json` includes the default data directory plus GUI settings
|
|
101
|
+
such as startup tab, plot update frequency, font sizes, and whether task
|
|
102
|
+
controls are mounted by default. Relative data paths are resolved against the
|
|
103
|
+
workspace root, and users can still override the data directory for an
|
|
104
|
+
individual run. GUI application preferences (`QSettings`) store process-local
|
|
105
|
+
state such as the selected workspace root, splitter layouts, and update-check
|
|
106
|
+
timestamps.
|
|
107
|
+
|
|
108
|
+
## Run Task
|
|
109
|
+
|
|
110
|
+
The Run task tab connects to one setup, uploads an optional hardware definition,
|
|
111
|
+
loads a task, starts/stops a session, writes data through core loggers, and
|
|
112
|
+
routes board events into logs, controls, and plots.
|
|
113
|
+
|
|
114
|
+
The live log view supports filtering and autoscroll, and task extensions can
|
|
115
|
+
publish status snapshots with `TaskExtension.update_status(...)` for the Run
|
|
116
|
+
task and experiment status panels.
|
|
117
|
+
|
|
118
|
+
Task files can select optional GUI helpers:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
v.task_extension = "sequence"
|
|
122
|
+
v.task_plotter = "SequencePlotter"
|
|
123
|
+
v.task_controls = "reward_panel"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
If a helper is missing or fails to load, the task can still run with the default
|
|
127
|
+
plotter and no custom controls.
|
|
128
|
+
|
|
129
|
+
## Experiments
|
|
130
|
+
|
|
131
|
+
The Experiments tab edits experiment JSON files and creates one subject panel
|
|
132
|
+
per active subject/setup assignment. Each subject panel owns its own
|
|
133
|
+
`SessionRuntime`, `SessionController`, `QThread`, `QtBusAdapter`, logger,
|
|
134
|
+
controls, and plot widget so one rig's failure does not directly own another
|
|
135
|
+
rig's state.
|
|
136
|
+
|
|
137
|
+
Experiments can also select an optional hardware-test task. When enabled, the
|
|
138
|
+
run view uploads and runs that task for each subject before preparing the main
|
|
139
|
+
experiment task.
|
|
140
|
+
|
|
141
|
+
Active Run task sessions lock the Experiments and Setups tabs; active
|
|
142
|
+
experiment runs lock Run task and Setups so one workflow owns the shared
|
|
143
|
+
application runtime at a time.
|
|
144
|
+
|
|
145
|
+
The Qt experiment editor exposes hardware definitions as first-class fields. For
|
|
146
|
+
tasks that import `hardware_definition`, the editor shows a hardware-definition
|
|
147
|
+
selector (saved to the experiment's `hardware_definition` field) and the
|
|
148
|
+
subjects table previews the effective hwdef per subject. The effective hwdef is
|
|
149
|
+
the experiment override, else the setup's `hardware_definition` default. Run
|
|
150
|
+
task offers the same selector, and Setups store a default hwdef per setup.
|
|
151
|
+
|
|
152
|
+
## Plugins And Trusted Code
|
|
153
|
+
|
|
154
|
+
Workspace plugins are trusted Python and execute in the GUI process.
|
|
155
|
+
|
|
156
|
+
- Task plotters live in `plugins/task_plotters/` and subclass
|
|
157
|
+
`pycontrol_gui.plotting.TaskPlotter`.
|
|
158
|
+
- Task controls live in `plugins/task_controls/` and can be declarative JSON or
|
|
159
|
+
custom Python widgets exporting `build_controls(parent, context)`. The GUI
|
|
160
|
+
renders JSON specs with `TaskControlsPanel` and embeds Python widgets directly.
|
|
161
|
+
- Task and experiment extensions are loaded through `pycontrol-core`.
|
|
162
|
+
- `SETTINGS` declarations for task extensions, experiment extensions, and task
|
|
163
|
+
plotters are edited in the GUI Settings dialog and saved under
|
|
164
|
+
`settings.extensions.*`. Task controls are configured through task variables
|
|
165
|
+
or declarative control defaults instead.
|
|
166
|
+
- The Settings dialog shows a configurable-file page for built-in plotting
|
|
167
|
+
defaults and each plugin file with valid `SETTINGS`. Each page has a
|
|
168
|
+
`Use defaults` button that resets only that file's settings before saving.
|
|
169
|
+
|
|
170
|
+
Secret settings are masked in the GUI but still saved in `settings.json`.
|
|
171
|
+
|
|
172
|
+
## Plotting Diagnostics
|
|
173
|
+
|
|
174
|
+
The workspace `GUI.plot_update_frequency_hz` setting controls live plot redraws;
|
|
175
|
+
new workspaces default to `35 Hz`. Plot data ingestion still happens through the
|
|
176
|
+
session event stream, so lowering the redraw rate reduces GUI paint work without
|
|
177
|
+
dropping incoming events.
|
|
178
|
+
|
|
179
|
+
For hardware performance checks, launch with plot profiling enabled:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
PYCONTROL_PLOT_PROFILE=1 pycontrol-gui /path/to/workspace
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Set `PYCONTROL_PLOT_PROFILE_INTERVAL_S` to change the reporting interval. The
|
|
186
|
+
GUI logs `[plot-profile]` lines with call counts plus average and maximum
|
|
187
|
+
latency for `process_batch()` and `update_plot()` spans.
|
|
188
|
+
|
|
189
|
+
## Import Stability
|
|
190
|
+
|
|
191
|
+
The supported import surfaces are:
|
|
192
|
+
|
|
193
|
+
- `pycontrol_gui.plotting`
|
|
194
|
+
- `pycontrol_gui.error_logging`
|
|
195
|
+
- `pycontrol_gui.resources`
|
|
196
|
+
|
|
197
|
+
Widgets, controllers, and workspace models are application internals. Tests may
|
|
198
|
+
import them, but downstream code should not treat them as stable.
|
|
199
|
+
|
|
200
|
+
## Error Logging
|
|
201
|
+
|
|
202
|
+
`pycontrol-gui` writes host-side diagnostics to a rotating `ErrorLog.txt` file:
|
|
203
|
+
|
|
204
|
+
1. `<workspace root>/ErrorLog.txt`
|
|
205
|
+
2. `~/.pycontrol-gui/logs/ErrorLog.txt`
|
|
206
|
+
3. `./ErrorLog.txt`
|
|
207
|
+
|
|
208
|
+
Open **View -> Error log** (`Ctrl+E`) to inspect or clear the current log.
|
|
209
|
+
Run/session `.tsv` files are separate and remain in the experiment data
|
|
210
|
+
directory.
|
|
211
|
+
|
|
212
|
+
## Documentation
|
|
213
|
+
|
|
214
|
+
New to the project? Start with the repo-level guides:
|
|
215
|
+
|
|
216
|
+
- [Documentation index](../rewrite-docs/README.md) - map of everything, with a reading order.
|
|
217
|
+
- [Architecture tour](../rewrite-docs/md-viewer.html?doc=ARCHITECTURE-TOUR.md) - learn core and GUI end to end.
|
|
218
|
+
- [Why the rewrite](../rewrite-docs/md-viewer.html?doc=WHY-REWRITE.md) - what changed versus pyControl v2 and why.
|
|
219
|
+
|
|
220
|
+
GUI guides:
|
|
221
|
+
|
|
222
|
+
- [Architecture, threading, and data flow](docs/architecture.md)
|
|
223
|
+
- [Task sharing and sandboxes](docs/task-sharing.md)
|
|
224
|
+
- [Task plotter plugins](docs/plot-plugins.md)
|
|
225
|
+
- [Task controls](docs/task-controls.md)
|
|
226
|
+
- [Extensions in the GUI](docs/extensions.md)
|
|
227
|
+
- [Current code review backlog](docs/code-review.md)
|
|
228
|
+
- [Shared contributor workflow](../CONTRIBUTING.md)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# pycontrol-gui
|
|
2
|
+
|
|
3
|
+
`pycontrol-gui` is the Qt desktop frontend for `pycontrol-core`.
|
|
4
|
+
|
|
5
|
+
It provides the main pyControl operator workflows:
|
|
6
|
+
|
|
7
|
+
- Run one task on one setup.
|
|
8
|
+
- Edit and run multi-subject experiments.
|
|
9
|
+
- Manage setup names, ports, auto-detected MCU cache, and setup variables.
|
|
10
|
+
- View live logs and plots.
|
|
11
|
+
- Use workspace task extensions, experiment extensions, task plotters, task
|
|
12
|
+
controls, and extension settings.
|
|
13
|
+
|
|
14
|
+
## Install From PyPI Alpha
|
|
15
|
+
|
|
16
|
+
For the `3.0.0a1` alpha, pin the prerelease:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
uv add "pycontrol-gui==3.0.0a1"
|
|
20
|
+
# or
|
|
21
|
+
pip install --pre "pycontrol-gui==3.0.0a1"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
To accept the newest available alpha with uv, use:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv add pycontrol-gui --prerelease allow
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Install For Development
|
|
31
|
+
|
|
32
|
+
Install the sibling core package first:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cd ../pycontrol-core
|
|
36
|
+
pip install -e ".[test,lint]"
|
|
37
|
+
|
|
38
|
+
cd ../pycontrol-gui
|
|
39
|
+
pip install -e ".[test]"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
With `uv`, `pycontrol-gui/pyproject.toml` points `pycontrol-core` at the
|
|
43
|
+
sibling `../pycontrol-core` path.
|
|
44
|
+
|
|
45
|
+
Run the app:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pycontrol-gui
|
|
49
|
+
pycontrol-gui /path/to/workspace
|
|
50
|
+
# or
|
|
51
|
+
python -m pycontrol_gui
|
|
52
|
+
python -m pycontrol_gui /path/to/workspace
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Run tests with Python's module form so stale local script shebangs do not get in
|
|
56
|
+
the way:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uv run python -m pytest
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Workspaces
|
|
63
|
+
|
|
64
|
+
Open a workspace with **Workspace -> Open Workspace...**, create one with
|
|
65
|
+
**Workspace -> New Workspace...**, or pass a workspace path on the command line.
|
|
66
|
+
If no path is supplied, the GUI uses the last-opened workspace from application
|
|
67
|
+
preferences, then falls back to discovering a workspace from the current working
|
|
68
|
+
directory. Use **Workspace -> Reload workspace** to refresh selectors after
|
|
69
|
+
external file changes.
|
|
70
|
+
|
|
71
|
+
The GUI uses the standard `pycontrol-core` workspace layout:
|
|
72
|
+
|
|
73
|
+
| Path | GUI use |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `tasks/` | Task selector in Run task and Experiments. |
|
|
76
|
+
| `hardware_definitions/` | Hardware-definition selector and setup validation. |
|
|
77
|
+
| `devices/` | Workspace-local device drivers for task sharing and setup maintenance. |
|
|
78
|
+
| `plugins/task_extensions/` | Host-side task automation. |
|
|
79
|
+
| `plugins/experiment_extensions/` | Whole-experiment automation. |
|
|
80
|
+
| `plugins/task_plotters/` | Custom live plot widgets. |
|
|
81
|
+
| `plugins/task_controls/` | Declarative or Python task-control panels. |
|
|
82
|
+
| `experiments/*.json` | Experiment editor and run view. |
|
|
83
|
+
| `settings.json` / `setups.json` | Workspace settings and setup registry. |
|
|
84
|
+
|
|
85
|
+
Workspace `settings.json` includes the default data directory plus GUI settings
|
|
86
|
+
such as startup tab, plot update frequency, font sizes, and whether task
|
|
87
|
+
controls are mounted by default. Relative data paths are resolved against the
|
|
88
|
+
workspace root, and users can still override the data directory for an
|
|
89
|
+
individual run. GUI application preferences (`QSettings`) store process-local
|
|
90
|
+
state such as the selected workspace root, splitter layouts, and update-check
|
|
91
|
+
timestamps.
|
|
92
|
+
|
|
93
|
+
## Run Task
|
|
94
|
+
|
|
95
|
+
The Run task tab connects to one setup, uploads an optional hardware definition,
|
|
96
|
+
loads a task, starts/stops a session, writes data through core loggers, and
|
|
97
|
+
routes board events into logs, controls, and plots.
|
|
98
|
+
|
|
99
|
+
The live log view supports filtering and autoscroll, and task extensions can
|
|
100
|
+
publish status snapshots with `TaskExtension.update_status(...)` for the Run
|
|
101
|
+
task and experiment status panels.
|
|
102
|
+
|
|
103
|
+
Task files can select optional GUI helpers:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
v.task_extension = "sequence"
|
|
107
|
+
v.task_plotter = "SequencePlotter"
|
|
108
|
+
v.task_controls = "reward_panel"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
If a helper is missing or fails to load, the task can still run with the default
|
|
112
|
+
plotter and no custom controls.
|
|
113
|
+
|
|
114
|
+
## Experiments
|
|
115
|
+
|
|
116
|
+
The Experiments tab edits experiment JSON files and creates one subject panel
|
|
117
|
+
per active subject/setup assignment. Each subject panel owns its own
|
|
118
|
+
`SessionRuntime`, `SessionController`, `QThread`, `QtBusAdapter`, logger,
|
|
119
|
+
controls, and plot widget so one rig's failure does not directly own another
|
|
120
|
+
rig's state.
|
|
121
|
+
|
|
122
|
+
Experiments can also select an optional hardware-test task. When enabled, the
|
|
123
|
+
run view uploads and runs that task for each subject before preparing the main
|
|
124
|
+
experiment task.
|
|
125
|
+
|
|
126
|
+
Active Run task sessions lock the Experiments and Setups tabs; active
|
|
127
|
+
experiment runs lock Run task and Setups so one workflow owns the shared
|
|
128
|
+
application runtime at a time.
|
|
129
|
+
|
|
130
|
+
The Qt experiment editor exposes hardware definitions as first-class fields. For
|
|
131
|
+
tasks that import `hardware_definition`, the editor shows a hardware-definition
|
|
132
|
+
selector (saved to the experiment's `hardware_definition` field) and the
|
|
133
|
+
subjects table previews the effective hwdef per subject. The effective hwdef is
|
|
134
|
+
the experiment override, else the setup's `hardware_definition` default. Run
|
|
135
|
+
task offers the same selector, and Setups store a default hwdef per setup.
|
|
136
|
+
|
|
137
|
+
## Plugins And Trusted Code
|
|
138
|
+
|
|
139
|
+
Workspace plugins are trusted Python and execute in the GUI process.
|
|
140
|
+
|
|
141
|
+
- Task plotters live in `plugins/task_plotters/` and subclass
|
|
142
|
+
`pycontrol_gui.plotting.TaskPlotter`.
|
|
143
|
+
- Task controls live in `plugins/task_controls/` and can be declarative JSON or
|
|
144
|
+
custom Python widgets exporting `build_controls(parent, context)`. The GUI
|
|
145
|
+
renders JSON specs with `TaskControlsPanel` and embeds Python widgets directly.
|
|
146
|
+
- Task and experiment extensions are loaded through `pycontrol-core`.
|
|
147
|
+
- `SETTINGS` declarations for task extensions, experiment extensions, and task
|
|
148
|
+
plotters are edited in the GUI Settings dialog and saved under
|
|
149
|
+
`settings.extensions.*`. Task controls are configured through task variables
|
|
150
|
+
or declarative control defaults instead.
|
|
151
|
+
- The Settings dialog shows a configurable-file page for built-in plotting
|
|
152
|
+
defaults and each plugin file with valid `SETTINGS`. Each page has a
|
|
153
|
+
`Use defaults` button that resets only that file's settings before saving.
|
|
154
|
+
|
|
155
|
+
Secret settings are masked in the GUI but still saved in `settings.json`.
|
|
156
|
+
|
|
157
|
+
## Plotting Diagnostics
|
|
158
|
+
|
|
159
|
+
The workspace `GUI.plot_update_frequency_hz` setting controls live plot redraws;
|
|
160
|
+
new workspaces default to `35 Hz`. Plot data ingestion still happens through the
|
|
161
|
+
session event stream, so lowering the redraw rate reduces GUI paint work without
|
|
162
|
+
dropping incoming events.
|
|
163
|
+
|
|
164
|
+
For hardware performance checks, launch with plot profiling enabled:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
PYCONTROL_PLOT_PROFILE=1 pycontrol-gui /path/to/workspace
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Set `PYCONTROL_PLOT_PROFILE_INTERVAL_S` to change the reporting interval. The
|
|
171
|
+
GUI logs `[plot-profile]` lines with call counts plus average and maximum
|
|
172
|
+
latency for `process_batch()` and `update_plot()` spans.
|
|
173
|
+
|
|
174
|
+
## Import Stability
|
|
175
|
+
|
|
176
|
+
The supported import surfaces are:
|
|
177
|
+
|
|
178
|
+
- `pycontrol_gui.plotting`
|
|
179
|
+
- `pycontrol_gui.error_logging`
|
|
180
|
+
- `pycontrol_gui.resources`
|
|
181
|
+
|
|
182
|
+
Widgets, controllers, and workspace models are application internals. Tests may
|
|
183
|
+
import them, but downstream code should not treat them as stable.
|
|
184
|
+
|
|
185
|
+
## Error Logging
|
|
186
|
+
|
|
187
|
+
`pycontrol-gui` writes host-side diagnostics to a rotating `ErrorLog.txt` file:
|
|
188
|
+
|
|
189
|
+
1. `<workspace root>/ErrorLog.txt`
|
|
190
|
+
2. `~/.pycontrol-gui/logs/ErrorLog.txt`
|
|
191
|
+
3. `./ErrorLog.txt`
|
|
192
|
+
|
|
193
|
+
Open **View -> Error log** (`Ctrl+E`) to inspect or clear the current log.
|
|
194
|
+
Run/session `.tsv` files are separate and remain in the experiment data
|
|
195
|
+
directory.
|
|
196
|
+
|
|
197
|
+
## Documentation
|
|
198
|
+
|
|
199
|
+
New to the project? Start with the repo-level guides:
|
|
200
|
+
|
|
201
|
+
- [Documentation index](../rewrite-docs/README.md) - map of everything, with a reading order.
|
|
202
|
+
- [Architecture tour](../rewrite-docs/md-viewer.html?doc=ARCHITECTURE-TOUR.md) - learn core and GUI end to end.
|
|
203
|
+
- [Why the rewrite](../rewrite-docs/md-viewer.html?doc=WHY-REWRITE.md) - what changed versus pyControl v2 and why.
|
|
204
|
+
|
|
205
|
+
GUI guides:
|
|
206
|
+
|
|
207
|
+
- [Architecture, threading, and data flow](docs/architecture.md)
|
|
208
|
+
- [Task sharing and sandboxes](docs/task-sharing.md)
|
|
209
|
+
- [Task plotter plugins](docs/plot-plugins.md)
|
|
210
|
+
- [Task controls](docs/task-controls.md)
|
|
211
|
+
- [Extensions in the GUI](docs/extensions.md)
|
|
212
|
+
- [Current code review backlog](docs/code-review.md)
|
|
213
|
+
- [Shared contributor workflow](../CONTRIBUTING.md)
|