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.
Files changed (150) hide show
  1. pycontrol_gui-3.0.0a1/.gitignore +29 -0
  2. pycontrol_gui-3.0.0a1/PKG-INFO +228 -0
  3. pycontrol_gui-3.0.0a1/README.md +213 -0
  4. pycontrol_gui-3.0.0a1/docs/architecture.md +338 -0
  5. pycontrol_gui-3.0.0a1/docs/code-review.md +179 -0
  6. pycontrol_gui-3.0.0a1/docs/extensions.md +180 -0
  7. pycontrol_gui-3.0.0a1/docs/plot-plugins.md +297 -0
  8. pycontrol_gui-3.0.0a1/docs/task-controls.md +208 -0
  9. pycontrol_gui-3.0.0a1/docs/task-sharing.md +119 -0
  10. pycontrol_gui-3.0.0a1/pyproject.toml +59 -0
  11. pycontrol_gui-3.0.0a1/src/pycontrol_gui/__init__.py +15 -0
  12. pycontrol_gui-3.0.0a1/src/pycontrol_gui/__main__.py +5 -0
  13. pycontrol_gui-3.0.0a1/src/pycontrol_gui/app.py +102 -0
  14. pycontrol_gui-3.0.0a1/src/pycontrol_gui/bus_adapter.py +54 -0
  15. pycontrol_gui-3.0.0a1/src/pycontrol_gui/error_logging.py +134 -0
  16. pycontrol_gui-3.0.0a1/src/pycontrol_gui/experiment_extensions.py +39 -0
  17. pycontrol_gui-3.0.0a1/src/pycontrol_gui/main_window.py +894 -0
  18. pycontrol_gui-3.0.0a1/src/pycontrol_gui/persistent_variables.py +55 -0
  19. pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/__init__.py +17 -0
  20. pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/base.py +38 -0
  21. pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/default_plotter.py +123 -0
  22. pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/host.py +364 -0
  23. pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/loader.py +48 -0
  24. pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/profiling.py +81 -0
  25. pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/widgets/__init__.py +7 -0
  26. pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/widgets/analog_plot.py +167 -0
  27. pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/widgets/events_plot.py +164 -0
  28. pycontrol_gui-3.0.0a1/src/pycontrol_gui/plotting/widgets/states_plot.py +132 -0
  29. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/__init__.py +38 -0
  30. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/add.svg +3 -0
  31. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/bar-graph.svg +1 -0
  32. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/book.svg +3 -0
  33. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/circle-arrow-up.svg +3 -0
  34. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/circle-arrow-up_white.svg +3 -0
  35. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/close.svg +3 -0
  36. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/close_white.svg +3 -0
  37. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/collapse.svg +1 -0
  38. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/comment.svg +3 -0
  39. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/connect.svg +12 -0
  40. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/copy.svg +1 -0
  41. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/copy_evil.svg +1 -0
  42. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/delete.svg +3 -0
  43. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/detach.svg +1 -0
  44. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/disable.svg +5 -0
  45. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/disconnect.svg +13 -0
  46. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/down.svg +3 -0
  47. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/edit.svg +3 -0
  48. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/enable.svg +4 -0
  49. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/expand.svg +1 -0
  50. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/filter.svg +3 -0
  51. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/folder.svg +3 -0
  52. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/funnel.svg +1 -0
  53. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/github.svg +1 -0
  54. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/help.svg +8 -0
  55. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/info.svg +1 -0
  56. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/keyboard.svg +1 -0
  57. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/left.svg +3 -0
  58. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/logo.svg +68 -0
  59. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/mount.svg +1 -0
  60. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/notion.svg +1 -0
  61. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/pause.svg +3 -0
  62. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/play.svg +3 -0
  63. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/play_white.svg +3 -0
  64. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/record.svg +10 -0
  65. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/record_white.svg +8 -0
  66. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/refresh.svg +3 -0
  67. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/remove.svg +3 -0
  68. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/right.svg +3 -0
  69. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/run.svg +3 -0
  70. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/run_white.svg +3 -0
  71. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/save.svg +3 -0
  72. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/save_as.svg +6 -0
  73. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/settings.svg +4 -0
  74. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/share.svg +1 -0
  75. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/stop.svg +3 -0
  76. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/stop_white.svg +3 -0
  77. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/telegram.svg +1 -0
  78. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/trash.svg +3 -0
  79. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/up.svg +3 -0
  80. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/upload.svg +6 -0
  81. pycontrol_gui-3.0.0a1/src/pycontrol_gui/resources/icons/wrench.svg +4 -0
  82. pycontrol_gui-3.0.0a1/src/pycontrol_gui/sandbox_session.py +83 -0
  83. pycontrol_gui-3.0.0a1/src/pycontrol_gui/session_controller.py +605 -0
  84. pycontrol_gui-3.0.0a1/src/pycontrol_gui/session_helpers.py +183 -0
  85. pycontrol_gui-3.0.0a1/src/pycontrol_gui/session_runtime.py +194 -0
  86. pycontrol_gui-3.0.0a1/src/pycontrol_gui/setup_maintenance.py +139 -0
  87. pycontrol_gui-3.0.0a1/src/pycontrol_gui/task_variables.py +121 -0
  88. pycontrol_gui-3.0.0a1/src/pycontrol_gui/update_check.py +283 -0
  89. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/__init__.py +34 -0
  90. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/about_dialog.py +103 -0
  91. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/controls_dialog.py +828 -0
  92. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/controls_dialog_editor.py +885 -0
  93. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/controls_spec_io.py +36 -0
  94. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/error_log_dialog.py +115 -0
  95. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_editor_rows.py +70 -0
  96. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_editor_table.py +137 -0
  97. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_run_control.py +144 -0
  98. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_run_models.py +48 -0
  99. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_run_plots.py +306 -0
  100. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_run_summary.py +113 -0
  101. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiment_run_view.py +1288 -0
  102. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/experiments_tab.py +1859 -0
  103. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/file_tree.py +46 -0
  104. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/hardware_variables_dialog.py +206 -0
  105. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/keyboard_shortcuts_dialog.py +68 -0
  106. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/log_filter_controller.py +218 -0
  107. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/log_view.py +221 -0
  108. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/run_task_tab.py +1598 -0
  109. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/sandbox_dialog.py +422 -0
  110. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/session_controls_shell.py +42 -0
  111. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/session_event_ui.py +177 -0
  112. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/session_panel.py +218 -0
  113. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/session_shutdown_ui.py +42 -0
  114. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/settings_dialog.py +728 -0
  115. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/setups_tab.py +837 -0
  116. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/share_dialog.py +162 -0
  117. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/style.py +177 -0
  118. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/subject_run_panel.py +1282 -0
  119. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/task_controls_host.py +144 -0
  120. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/task_selector_widgets.py +161 -0
  121. pycontrol_gui-3.0.0a1/src/pycontrol_gui/widgets/task_status.py +177 -0
  122. pycontrol_gui-3.0.0a1/src/pycontrol_gui/workspace_model.py +699 -0
  123. pycontrol_gui-3.0.0a1/tests/CLASSIFICATION.md +11 -0
  124. pycontrol_gui-3.0.0a1/tests/__init__.py +1 -0
  125. pycontrol_gui-3.0.0a1/tests/conftest.py +5 -0
  126. pycontrol_gui-3.0.0a1/tests/support/__init__.py +1 -0
  127. pycontrol_gui-3.0.0a1/tests/support/fake_board.py +352 -0
  128. pycontrol_gui-3.0.0a1/tests/test_app.py +81 -0
  129. pycontrol_gui-3.0.0a1/tests/test_bus_adapter.py +48 -0
  130. pycontrol_gui-3.0.0a1/tests/test_controls_dialog.py +53 -0
  131. pycontrol_gui-3.0.0a1/tests/test_error_log_dialog.py +22 -0
  132. pycontrol_gui-3.0.0a1/tests/test_error_logging.py +61 -0
  133. pycontrol_gui-3.0.0a1/tests/test_experiment_run_plots.py +49 -0
  134. pycontrol_gui-3.0.0a1/tests/test_experiment_run_view.py +1079 -0
  135. pycontrol_gui-3.0.0a1/tests/test_log_view.py +260 -0
  136. pycontrol_gui-3.0.0a1/tests/test_model_view_widgets.py +86 -0
  137. pycontrol_gui-3.0.0a1/tests/test_persistent_variables.py +36 -0
  138. pycontrol_gui-3.0.0a1/tests/test_plotting_loader.py +57 -0
  139. pycontrol_gui-3.0.0a1/tests/test_plotting_widgets.py +156 -0
  140. pycontrol_gui-3.0.0a1/tests/test_session_controller.py +819 -0
  141. pycontrol_gui-3.0.0a1/tests/test_session_event_ui.py +48 -0
  142. pycontrol_gui-3.0.0a1/tests/test_session_runtime.py +62 -0
  143. pycontrol_gui-3.0.0a1/tests/test_settings_dialog.py +47 -0
  144. pycontrol_gui-3.0.0a1/tests/test_setups_tab.py +49 -0
  145. pycontrol_gui-3.0.0a1/tests/test_share_dialog.py +172 -0
  146. pycontrol_gui-3.0.0a1/tests/test_smoke.py +207 -0
  147. pycontrol_gui-3.0.0a1/tests/test_task_variables.py +32 -0
  148. pycontrol_gui-3.0.0a1/tests/test_update_check.py +33 -0
  149. pycontrol_gui-3.0.0a1/tests/test_workspace_model.py +484 -0
  150. 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)