Repository navigation
Add generic widgets for watching signal values, tweaking movables, device status and beamline status. - #148
Jakub Wlodek (jwlodek) wants to merge 18 commits into
Conversation
Jakub Wlodek (jwlodek)
commented
Nov 10, 2026
- Add theming for status section
- Add widget for watching live value of scalar/string signals
- Add widget that given a device will generate a status view displaying hinted signal statuses
- Add unit tests for device status widget
- Add widget that extends signal status to also offer setpoint and tweak controls for movable signals
- Add widget that groups move controls to allow for batch moves
- Create slits control widget out of movable groups
- Some refactoring of shutter widget to extend from signal status widget
- Add HEX specific components using new features
…le longer timeouts on set and correctly forward progress bars
… hinted signal statuses
…k controls for movable signals
…ek/hextools into beamline-status
There was a problem hiding this comment.
🟡 Changes recommended
Unvalidated execution-namespace mismatches can cause the controls to move a different device from the one displayed or check the wrong RunEngine.
5 open issues
Validate device and engine against the execution namespace · New Match namespace alias selection to device-name preference · New Recheck engine readiness before submitting queued moves · New Preserve staged targets when a move fails or pauses · New Unsubscribe safely when QtSignalStatus is destroyed · New
What changed in this PR
Adds reusable monitoring and motion-control widgets to the hextools Qt GUI, with HEX-specific slit, filter, and beamline views.
Changes:
- Add themed live signal, device, and beamline status displays, including shared support for shutter indicators.
- Add typed setpoints, tweaks, and batch moves for local controls while retaining Queue Server plan widgets.
- Extend slit and filter subscription interfaces, expose
move_filters, and add GUI and device regression tests.
| File | Description |
|---|---|
tests/photon_delivery_system/test_slits.py |
Tests slit-axis readbacks, subscriptions, and progress. |
tests/photon_delivery_system/test_filters.py |
Tests filter labels, subscriptions, and paired moves. |
tests/gui/test_window_close.py |
Tests status-window integration and slit selection. |
tests/gui/test_signal_status.py |
Tests value formatting, alarms, units, and cleanup. |
tests/gui/test_signal_status_group.py |
Tests hinted fields and status layouts. |
tests/gui/test_shutter_status.py |
Updates indicator tests and covers invalid alarms. |
tests/gui/test_movable_control.py |
Tests typed inputs, tweaks, batching, and slit controls. |
tests/gui/test_hex_status_sections.py |
Tests HEX status sections and filter controls. |
src/hextools/profiles/collection.py |
Exposes mv and mvr in the operator namespace. |
src/hextools/photon_delivery_system/slits.py |
Introduces subscribable gap and center motion devices. |
src/hextools/photon_delivery_system/filters.py |
Adds subscriptions, label lookup, and move_filters. |
src/hextools/photon_delivery_system/__init__.py |
Exports move_filters. |
src/hextools/gui/slits_control.py |
Adds grouped slit controls and a slit selector. |
src/hextools/gui/signal_status.py |
Adds live scalar displays and subscription handling. |
src/hextools/gui/signal_status_group.py |
Builds device and beamline status layouts. |
src/hextools/gui/shutter_status.py |
Reuses signal-status widgets for shutter indicators. |
src/hextools/gui/movable_group.py |
Adds staged batch-move controls. |
src/hextools/gui/movable_control.py |
Adds typed setpoint and relative-tweak controls. |
src/hextools/gui/hex_config.py |
Defines HEX device discovery and status sections. |
src/hextools/gui/_theme.py |
Styles status headers and field labels. |
src/hextools/gui/__main__.py |
Integrates local controls and the beamline status window. |
Review effort: Balanced
| self.reading_changed.connect(on_reading) | ||
| # ophyd-async subscriptions must be made on the bluesky event loop, and | ||
| # callbacks arrive on that thread; the queued Qt signal hops back. | ||
| loop.call_soon_threadsafe(obj.subscribe_reading, self._on_reading) |
There was a problem hiding this comment.
🟡 Changes recommended
Deferred moves can be submitted to a non-idle RunEngine, and inconsistent device alias selection can prevent the acquisition window from opening.
6 open issues
Recheck RunEngine state before submitting the staged batch · New Resolve indexed device paths through NamespaceDeviceSource · New Unsubscribe safely when QtSignalStatus is destroyed Preserve staged targets when a move fails or pauses Recheck engine readiness before submitting queued moves Match namespace alias selection to device-name preference
1 resolved since last review
Review effort: Balanced
| try: | ||
| error = run_in_ipython(code) |
| parts = name.split(".") | ||
| # Attribute access only, so no code in ``name`` is ever evaluated. | ||
| if not all(p.isidentifier() and not p.startswith("_") for p in parts): | ||
| raise KeyError(name) |
Anthony Sligar (sligara7)
left a comment
There was a problem hiding this comment.
Pending the merge conflict (probably from me merging PR 145), this PR looks good to merge.
There was a problem hiding this comment.
🟡 Changes recommended
Failed or paused batches discard pending targets and prevent straightforward retries, while indexed-path and alias mismatches can cause control and window construction to fail.
4 open issues
3 resolved since last review
Review effort: Balanced
| """``(variable name, object)`` for each distinct instance of ``types``.""" | ||
| seen: set[int] = set() | ||
| found = [] | ||
| for name, obj in sorted(namespace.items()): |

