Metadata-Version: 2.4
Name: pycontrol-gui
Version: 3.0.0a12
Summary: Qt desktop frontend for pycontrol-core.
Author: Karpova Lab contributors
License: GPL-3.0-or-later
License-File: LICENSE.txt
Requires-Python: >=3.11
Requires-Dist: packaging>=24
Requires-Dist: pycontrol-core<3.1,>=3.0.0a12
Requires-Dist: pyqtgraph>=0.13.7
Requires-Dist: pyside6>=6.8
Provides-Extra: test
Requires-Dist: pytest-qt>=4.4; extra == 'test'
Requires-Dist: pytest>=8; extra == 'test'
Description-Content-Type: text/markdown

# pycontrol-gui

`pycontrol-gui` is the Qt desktop frontend for `pycontrol-core`.

It provides the main pyControl operator workflows:

- Run one task on one setup.
- Edit and run multi-subject experiments.
- Manage setup names, ports, auto-detected MCU cache, and setup variables.
- View live logs and plots.
- Use workspace task extensions, experiment extensions, task plotters, task
  controls, and extension settings.

## Install From PyPI Alpha

pyControl is installed once per machine as a global app. Install its lifecycle
manager, then install and launch the app:

```bash
uv tool install --prerelease if-necessary-or-explicit pycontrol-manager
pycontrol-manager app install
pycontrol-manager app status
pycontrol gui
```

On first launch, the welcome dialog offers to create or open a workspace.

Or install the app directly:

```bash
uv tool install --with-executables-from pycontrol-core pycontrol-gui
# or, in an existing Python environment
pip install --pre pycontrol-gui
```

Upgrade published packages with `pycontrol-manager app update`.

## Switch the Global App to Development Sources

Given a source root containing sibling `pycontrol-core/` and `pycontrol-gui/`
checkouts:

```bash
pycontrol-manager app source local /path/to/source-root
pycontrol gui
```

Both checkouts are editable, so source edits are immediately live in the same
global commands and OS launcher. `pycontrol-manager app update` refuses to
replace editable sources. Switch back to the newest published packages
explicitly:

```bash
pycontrol-manager app source pypi
```

For an isolated development environment instead, `pycontrol-gui/pyproject.toml`
already points uv at the sibling core checkout:

```bash
cd /path/to/source-root/pycontrol-gui
uv sync
uv run pycontrol-gui /path/to/workspace
```

Run tests with Python's module form so stale local script shebangs do not get in
the way:

```bash
uv run python -m pytest
```

See [maintainability.md](docs/maintainability.md) for the standard-GUI
adoption target and the current GUI simplification hotspots.

## Workspaces

Workspaces are plain data folders; the app is installed once and switches
between them. Open a workspace with **Workspace -> Open Workspace...**, create
one with **Workspace -> New Workspace...**, or pass a workspace path with
`pycontrol gui PATH`.

When `pycontrol gui` is launched without a path, it first searches the current
directory and its parents for a valid workspace. If none is found, it opens the
last valid workspace remembered from an earlier session. If there is no
remembered workspace—such as the first launch from outside a workspace—the
welcome dialog offers to create or open one. Opening or creating a workspace
remembers it for subsequent launches. An explicit path always takes precedence.

`pycontrol-gui --set-workspace PATH` records the workspace to open on next
launch without starting the GUI;
`pycontrol-gui --forget-workspace` clears the remembered workspace and recent
list so the next launch shows the welcome dialog again. Use
**Workspace -> Reload workspace** to refresh selectors after external file
changes.

The GUI uses the standard `pycontrol-core` workspace layout:

| Path | GUI use |
| --- | --- |
| `tasks/` | Task selector in Run task and Experiments. |
| `hardware_definitions/` | Hardware-definition selector and setup validation. |
| `devices/` | Workspace-local device drivers for task sharing and setup maintenance. |
| `plugins/task_extensions/` | Host-side task automation. |
| `plugins/experiment_extensions/` | Whole-experiment automation. |
| `plugins/task_plotters/` | Custom live plot widgets. |
| `plugins/task_controls/` | Declarative or Python task-control panels. |
| `experiments/*.json` | Experiment editor and run view. |
| `settings.json` / `setups.json` | Workspace settings and setup registry. |

Workspace `settings.json` includes the default data directory plus GUI settings
such as startup tab, plot update frequency, font sizes, and whether task
controls are mounted by default. Relative data paths are resolved against the
workspace root, and users can still override the data directory for an
individual run. GUI application preferences (`QSettings`) store process-local
state such as the selected workspace root, splitter layouts, and update-check
timestamps.

## Run Task

The Run task tab connects to one setup, uploads an optional hardware definition,
loads a task, starts/stops a session, writes data through core loggers, and
routes board events into logs, controls, and plots.

The live log view supports filtering and autoscroll, and task extensions can
publish status snapshots with `TaskExtension.update_status(...)` for the Run
task and experiment status panels.

Task files can select optional GUI helpers:

```python
v.task_extension = "sequence"
v.task_plotter = "SequencePlotter"
v.task_controls = "reward_panel"
```

If a helper is missing or fails to load, the task can still run with the default
plotter and no custom controls.

## Experiments

The Experiments tab edits experiment JSON files and creates one subject panel
per active subject/setup assignment. Each subject panel owns its own
`SessionRuntime`, `SessionController`, `QThread`, `QtBusAdapter`, logger,
controls, and plot widget so one rig's failure does not directly own another
rig's state.

Experiments can also select an optional hardware-test task. When enabled, the
run view uploads and runs that task for each subject before preparing the main
experiment task.

An active Run task run (`RUNNING`) locks the Experiments and Setups tabs. An
open experiment run view locks Run task and Setups so one workflow owns the
shared application state at a time.

The Qt experiment editor exposes hardware definitions as first-class fields. For
tasks that import `hardware_definition`, the editor shows a hardware-definition
selector (saved to the experiment's `hardware_definition` field) and the
subjects table previews the effective hwdef per subject. The effective hwdef is
the experiment override, else the setup's `hardware_definition` default. Run
task offers the same selector, and Setups store a default hwdef per setup.

## Plugins And Trusted Code

Workspace plugins are trusted Python and execute in the GUI process.

- Task plotters live in `plugins/task_plotters/` and subclass
  `pycontrol_gui.plotting.TaskPlotter`.
- Task controls live in `plugins/task_controls/` and can be declarative JSON or
  custom Python widgets exporting `build_controls(parent, context)`. The GUI
  renders JSON specs with `TaskControlsPanel` and embeds Python widgets directly.
- Task and experiment extensions are loaded through `pycontrol-core`.
- `SETTINGS` declarations for task extensions, experiment extensions, and task
  plotters are edited in the GUI Settings dialog and saved under
  `settings.extensions.*`. Task controls are configured through task variables
  or declarative control defaults instead.
- The Settings dialog shows a configurable-file page for built-in plotting
  defaults and each plugin file with valid `SETTINGS`. Each page has a
  `Use defaults` button that resets only that file's settings before saving.

Secret settings are masked in the GUI but still saved in `settings.json`.

## Task Sharing And Sandboxes

The Run task tab can export a selected task and its workspace-local dependencies
as a protocol bundle ZIP. **Workspace -> Enter sandbox...** opens a sandbox
manager that can create an isolated workspace from a shared ZIP, run it against
local setups, and return to the parent workspace with a visible sandbox banner.
See [task-sharing.md](docs/task-sharing.md).

## Plotting Diagnostics

The workspace `GUI.plot_update_frequency_hz` setting controls live plot redraws;
new workspaces default to `35 Hz`. Plot data ingestion still happens through the
session event stream, so lowering the redraw rate reduces GUI paint work without
dropping incoming events.

For hardware performance checks, launch with plot profiling enabled:

```bash
PYCONTROL_PLOT_PROFILE=1 pycontrol-gui /path/to/workspace
```

Set `PYCONTROL_PLOT_PROFILE_INTERVAL_S` to change the reporting interval. The
GUI logs `[plot-profile]` lines with call counts plus average and maximum
latency for `process_batch()` and `update_plot()` spans.

## Import Stability

The supported import surfaces are:

- `pycontrol_gui.plotting`
- `pycontrol_gui.error_logging`
- `pycontrol_gui.resources`

Widgets, controllers, and workspace models are application internals. Tests may
import them, but downstream code should not treat them as stable.

## Error Logging

`pycontrol-gui` writes host-side diagnostics to a rotating `ErrorLog.txt` file:

1. `<workspace root>/ErrorLog.txt`
2. `~/.pycontrol-gui/logs/ErrorLog.txt`
3. `./ErrorLog.txt`

Open **View -> Error log** (`Ctrl+E`) to inspect or clear the current log.
Run/session `.tsv` files are separate and remain in the experiment data
directory.

## Documentation

New to the project? Start with the repo-level guides:

- [Documentation index](../rewrite-docs/README.md) - map of everything, with a reading order.
- [Architecture tour](../rewrite-docs/ARCHITECTURE-TOUR.md) - learn core and GUI end to end.
- [Data-flow walkthrough](../rewrite-docs/OVERVIEW.html#data-flow) - one packet's journey through the pipeline.

GUI guides:

- [Architecture, threading, and data flow](docs/architecture.md)
- [Task sharing and sandboxes](docs/task-sharing.md)
- [Task plotter plugins](docs/plot-plugins.md)
- [Task controls](docs/task-controls.md)
- [Extensions in the GUI](docs/extensions.md)
- [Maintainability notes](docs/maintainability.md)
- [Shared contributor workflow](../pycontrol-archive/CONTRIBUTING.md)
