Repository navigation
Separate reusable GUI from HEX configuration - #128
Anthony Sligar (sligara7) wants to merge 27 commits into
Conversation
…eamline constants
Load selected slit readbacks asynchronously, prepare GeRM statistics, restore initial scan positions, and serialize manual shutter actions without changing settling delays. Label the tilt parameter Two theta while retaining theta. Add full-plan failure/abort/pause regressions and document the removed gui environment and deployment-side exporter launcher diagnostics. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep zero delay for manual shutter buttons as confirmed by AJ, alongside mutual exclusion. Acquisition-plan timing remains unchanged. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep Python plan defaults unchanged; narrow slit input types for Pyright and verify manual shutter zero-delay exclusion. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Retain approved manual shutter mutual exclusion and zero manual delay. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move GeRM statistics setup into data logic, use grid reset decorator, remove deferred GUI special cases and clean up PR125 configuration/docs without restoring removed features. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Preserve Jakub’s merged set_fe_aperture API unchanged. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Explicit save_as_tiff=False retains HDF5. Verify emitted resource formats and generic checkbox defaults. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore merged PR125 implementation, profile construction and coupled tests; keep agreed operator fixes. Restructuring remains in history for a separate later proposal. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reproduced collection failures with qtpy absent; verify both modules skip with qtpy or bluesky_widgets unavailable and still execute with GUI extras. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract spec-driven GUI builders and reusable widgets while keeping HEX composition, device adapters, and configuration ownership in hextools.gui_config. Add synthetic-spec and import-boundary regression coverage, preserve existing plan tabs and compatibility paths, and include localhost-only GUI screenshots. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Read expected devices from the HEX GuiSpec instead of the generic launcher, and apply the formatter required by CI. The extracted list matches all 20 PR126 device entries. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Capture the complete HEX GUI after launching the real locked mock profile with isolated local storage and localhost-only EPICS address lists. The screenshot shows the Beamline technique, Filters plan, and full window; the live validation asserted all technique tabs and the Frontend Aperture and Filters plan widgets. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Environment precedence can cause --mock to launch in live mode or override --history-file, and opening the browser without configured specs leaves Search vulnerable to an IndexError.
2 open issues
What changed in this PR
This PR separates reusable GUI components from HEX-specific configuration through a new GuiSpec interface. It retains the HEX launcher and includes the operator fixes from prerequisite PR #126.
Changes:
- Extracts configurable windows, widgets, and shared helpers into
hextools.gui, with HEX composition ingui_config.py. - Adds import-boundary, configuration, and operator-behavior regressions.
- Updates developer guidance, launcher documentation, and screenshot tooling.
| File | Description |
|---|---|
tests/test_review_followup.py |
Checks GeRM statistics activation for both formats. |
tests/test_gui_expected_devices.py |
Reads expected devices from HEX configuration. |
tests/test_edxd.py |
Tests omitted TIFF arguments and updates recovery commentary. |
tests/test_edxd_operator_recovery.py |
Covers recovery, interruptions, and reset opt-outs. |
tests/gui/test_window_close.py |
Adapts lifecycle tests to spec-based windows. |
tests/gui/test_shutter_status.py |
Tests shutter exclusion and busy-state guards. |
tests/gui/test_gui_is_generic.py |
Checks generic boundaries and HEX composition. |
tests/gui/test_generic_widget_boundary.py |
Checks widget imports and embedded HEX policy. |
tests/gui/test_edxd_plan_defaults.py |
Verifies signature-driven TIFF checkboxes. |
src/hextools/utils/nl_msg_hook.py |
Preserves narrator compatibility exports and logger defaults. |
src/hextools/log.py |
Uses the extracted error helper. |
src/hextools/gui/window.py |
Builds and launches spec-configured acquisition windows. |
src/hextools/gui/spec.py |
Defines configuration types and spec loading. |
src/hextools/gui/shutter_status.py |
Injects shutter policy and guards submissions. |
src/hextools/gui/plan_widget.py |
Uses the GUI-local error helper. |
src/hextools/gui/plan_status.py |
Uses the extracted narrator. |
src/hextools/gui/narrator.py |
Houses reusable RunEngine message narration. |
src/hextools/gui/misc/weather.py |
Accepts configurable site coordinates and timezone. |
src/hextools/gui/misc/__init__.py |
Removes HEX-specific wording from the docstring. |
src/hextools/gui/live_re_md_viewer.py |
Injects proposal-system operations. |
src/hextools/gui/errors.py |
Provides shared failed-status unwrapping. |
src/hextools/gui/device_sources.py |
Adds local device-path resolution. |
src/hextools/gui/auto_exporter_view.py |
Accepts the exporter module explicitly. |
src/hextools/gui/_theme.py |
Makes preference storage scope configurable. |
src/hextools/gui/_ipython.py |
Uses the extracted error helper. |
src/hextools/gui/__main__.py |
Retains the HEX launcher and compatibility helpers. |
src/hextools/gui/__init__.py |
Exposes reusable specs and a lazy launcher. |
src/hextools/gui_config.py |
Owns HEX composition, adapters, and defaults. |
src/hextools/exporters/tomography.py |
Replaces redundant conversion with a type cast. |
src/hextools/edxd.py |
Updates TIFF defaults and scan-position recovery. |
src/hextools/detectors/germ.py |
Enables statistics during acquisition preparation. |
src/hextools/bl_constants.py |
Removes an unnecessary type-ignore comment. |
schemas/filters.yml |
Removes the obsolete filter schema. |
pixi.toml |
Constrains the Pyright version range. |
docs/profile.md |
Corrects imports and filter-construction guidance. |
docs/gui.md |
Documents shutter guards, TIFF defaults, and recovery. |
docs/getting_started.md |
Documents exporter launchers and workstation diagnostics. |
docs/developer.md |
Explains spec-based composition and extension boundaries. |
docs/cli.md |
Corrects filter configuration guidance and example casing. |
docs/_scripts/capture_screenshots.py |
Launches screenshots with the explicit HEX spec. |
Review effort: Balanced
Preserve NSLS2#126 operator behavior and NSLS2#127 DCLMConstants/.constants without restructuring. Keep the extracted HEX shutter adapter outside the generic GUI; boundary tests failed on the duplicate merge-added adapter before removal. Validate the actual locked mock launcher, technique tabs, aperture/filters, TIFF defaults and shutter actions; record screenshots and full GUI, operator, lint and type-check results. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Active defects can crash searches when run specs are empty, duplicate narration when a hook is already installed, and silently lose remote proposal updates under the default metadata-sharing setting.
4 open issues
Review effort: Balanced
Apply base environment before mock and explicit history overrides. Only offer the scan browser when run specs are configured; cover both optional and configured paths with synthetic specs. Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: copilot:gpt-6.1-sol Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Creating a fresh narrator bypasses PlanMonitor’s identity check when the utility narrator is already attached, causing each narration line to be logged twice.
No open issues 🎉
4 resolved since last review
Review effort: Balanced
Removes the validation screenshots and restores docs/developer.md and docs/gui.md to main; documentation follows separately. Assisted-by: copilot:claude-opus-5-5
| self._plan_monitor = ( | ||
| PlanMonitor( | ||
| re_client, | ||
| narrator=MsgHookNarrator(logger=spec.logger_name), |


Scope
Code changes only; documentation updates follow in a separate PR.
hextools.gui.hextools.gui_config; no HEX imports or identity branches in generic GUI modules.python -m hextools.guiand compatibility wrappers where feasible.Updated base and history
PRs #126 and #127 are merged into canonical
main:d8efa5c61a982cf83bddcd843e327fa128c84c7dmain:1bcaa5bb0f33511adef446db86f0983847fc2acd7916ac29ae58affa813241818c4ca8eebf4de7b3(parents7a075e6717d33499f0c8137c2f2b0701effbac7aand1bcaa5bb0f33511adef446db86f0983847fc2acd).No rebase, flattening or force-push. Jakub's
DCLMConstants/.constants, profile and photon-delivery implementation/tests match canonicalmainexactly. The merge-addedgui/hex_config.pyduplicated the already extracted HEX shutter adapter: generic import/identity tests failed on it before its removal. The same discovery and manualallow_actuation=True, sleep_time=0.0shutter policy remains ingui_config.py, outside the reusable GUI.Local verification — merged tree, 2026-10-29
All commands used this branch's own locked Pixi
devenvironment, Python 3.13.18, without borrowing another checkout's environment orPYTHONPATH.pixi run --locked -e dev pytest -o addopts='' -q tests/gui tests/test_gui_expected_devices.py tests/photon_delivery_system/test_dclm.py— 129 passed. Includes theme, plan-history, window-close and temporary-file tests; no GUI files excluded.pixi run --locked -e dev pytest -o addopts='' -q tests/photon_delivery_system tests/test_nl_msg_hook.py tests/test_edxd*— 195 passed.pixi run --locked -e dev lint— all configured pre-commit hooks passed, including Ruff lint/format and import contracts; repeated on the final committed tree.pixi run --locked -e dev type-check— 0 errors, 0 warnings.Actual mock GUI, not standalone widgets
Launched
pixi run --locked -e dev python -m hextools.gui --mock --profile <isolated-copy-of-collection> --history-file <isolated-history>and drove its actual IPython/main-window session:Isolation and measured limits: CA/PVA automatic discovery disabled, loopback-only address lists. An additional Python socket audit hook denied non-loopback networking; the only blocked lookup was optional Open-Meteo weather. No Redis or beamline-host lookup/connection was attempted. The active mock path uses in-memory RunEngine metadata, mock devices and local Tiled
simple; the profile's unused Redis hostname is not a mock-launch blocker. Earlier verification omitted this launch and temporary-file tests; the results above supersede those omissions.Camera panes had no live image source. No detector acquisition plan, TST/real beamline or QueueServer service was exercised. This is actual mock GUI/control verification, not detector-stream or live-beamline certification. Draft retained pending review and refreshed CI; this PR has not been merged.
Future client/API limits
The generic entry point is
hextools.gui; specs are defined withhextools.gui.spec.GuiSpec. HEX composition lives inhextools.gui_config.bluesky_widgetsis not modified, andfrom bluesky_widgets import guiis illustrative only—not an existing API. Moving the generic layer there remains future work.