new_gui: ABR->staff align-CoR only, Go-to-Home, 6-level zoom, remove manual run-plan
- ABR extracted to widgets/abr_control.py; shown only in the staff Align-centre- of-rotation procedure (removed from the shared MotorsPanel) - SMARGON: '⌂ Go to Home' button -> move_smargon(0,0,18) (home_requested) - ZOOM: real settings (motor values) 1.0/2.0/3.5/5.8/7.5/12.5x in a 3-col grid; emit the motor value (was the magnification); camera shows the magnification label via zoom_label() - remove the RUN PLAN chip row from the manual cockpit (runner uses default protocol); readable combos/spinboxes already global - input contrast fix + mounted card from prior commit Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
b4a4cb2d61
commit
f688ca5319
@@ -62,9 +62,12 @@ Backend contract is documented in the `new-gui-backend-paths` memory.
|
||||
(switch the beamline state where one exists; CoR uses Sample alignment + omega +
|
||||
smargon + ABR). Centre = camera (beam-centre marker) / XRF spectrum; right =
|
||||
full motors (omega/smargon/ABR/zoom/light).
|
||||
- **Motors panel**: compact SMARGON with **editable Chi/Phi** + **Focus (Z)** jog
|
||||
(new — smargon-z move), staff-only **ABR** (GMX/GMY/GMZ + save/goto) under
|
||||
SMARGON. Energy lives in the staff Tools dialog (not the motors panel).
|
||||
- **Motors panel**: compact SMARGON with **editable Chi/Phi**, a **⌂ Go to Home**
|
||||
button (smargon → 0,0,18), **Focus (Z)** jog, **ZOOM** as a 6-level grid
|
||||
(1.0×/2.0×/3.5×/5.8×/7.5×/12.5×; the button sends the zoom-motor value, the
|
||||
camera shows the magnification label), and LIGHT. **ABR** is NOT here — it lives
|
||||
only in the staff **Align centre of rotation** procedure. Energy lives in the
|
||||
staff Tools dialog.
|
||||
- **Camera exp/gain** are inline in the camera tab strip (Exp/Gain → `samcam_settings`).
|
||||
- **Prediction metrics** dialog (per-class counts, confidence, FPS) and a **live
|
||||
smargon-trace** dialog (ΔX/ΔY/ΔZ + distance from a reference, fed by the status
|
||||
@@ -100,13 +103,12 @@ Backend contract is documented in the `new-gui-backend-paths` memory.
|
||||
- **Preconditions**: data-collection actions are gated by a ring/shutter/hutch
|
||||
warning (1-hour snooze); mounting is hard-blocked by the hutch PSS;
|
||||
`sample_missing` shows a modal (suppressed during automation).
|
||||
- **Pausable pipeline** (mounted): a **RUN PLAN** chip row toggles which stages
|
||||
▶ Play executes (Center/Raster/XRF/Collect). Play runs the lit stages in order,
|
||||
- **Pausable pipeline** (mounted): ▶ Play runs the protocol stages in order,
|
||||
advancing as each completes (`raster_scan_completed`/`standard_scan_completed`,
|
||||
else a `status.busy` True→False edge, else ⏭ Skip) and **pausing before any
|
||||
stage flagged with a ⚑ breakpoint**; ▶ resumes, ❚❚ pauses after the current
|
||||
stage, ⏹ ends. (Automation pauses between samples; per-stage control inside a
|
||||
sample is **GUI-driven** — see below.)
|
||||
stage, ⏹ ends. (The visible run-plan chips were removed from Manual; the runner
|
||||
uses the default protocol. Automation has the GUI-driven per-stage runner below.)
|
||||
- **Automation** (queue page): **GUI-driven per-stage runner** drives each queued
|
||||
sample through mount → its enabled protocol stages → unmount, firing the
|
||||
per-stage backend ops and advancing on completion (raster/standard signals,
|
||||
|
||||
@@ -95,7 +95,7 @@ class DevSeed(QObject):
|
||||
bl=SimpleNamespace(
|
||||
flux_ph_s=4.0e11, ring_current_mA=401.0, cryojet_K=100.1,
|
||||
shutter_open=False, exp_shutter_open=True, transmission=0.1,
|
||||
zoom=2.0, front_light=80, back_light=45,
|
||||
zoom=280.0, front_light=80, back_light=45,
|
||||
sample_camera=SimpleNamespace(gain=1.0, exposure=0.02),
|
||||
pss_prohibited=True, pss_alarm=False),
|
||||
geom=geom,
|
||||
|
||||
@@ -359,6 +359,13 @@ class MainWindow(QWidget):
|
||||
if hasattr(self.daq, "beam_mark_clear"):
|
||||
self.staff.beam_mark_clear.connect(self.daq.beam_mark_clear)
|
||||
self._wire_motors(self.staff.motors)
|
||||
# ABR lives only in the staff Align-centre-of-rotation procedure
|
||||
if hasattr(self.daq, "abr_tweak"):
|
||||
self.staff.abr.abr_tweak.connect(self.daq.abr_tweak)
|
||||
if hasattr(self.daq, "abr_save"):
|
||||
self.staff.abr.abr_save.connect(self.daq.abr_save)
|
||||
if hasattr(self.daq, "abr_goto_meas"):
|
||||
self.staff.abr.abr_goto.connect(self.daq.abr_goto_meas)
|
||||
sp2 = self.staff.spectrum
|
||||
sp2.start_clicked.connect(self.daq.fluorimeter_start)
|
||||
sp2.stop_clicked.connect(self.daq.fluorimeter_stop)
|
||||
@@ -406,12 +413,11 @@ class MainWindow(QWidget):
|
||||
m.back_light_changed.connect(self.daq.back_light)
|
||||
m.smargon_jog.connect(self._on_smargon_jog)
|
||||
m.smargon_angles.connect(self._on_smargon_angles)
|
||||
if hasattr(self.daq, "abr_tweak"):
|
||||
m.abr_tweak.connect(self.daq.abr_tweak)
|
||||
if hasattr(self.daq, "abr_save"):
|
||||
m.abr_save.connect(self.daq.abr_save)
|
||||
if hasattr(self.daq, "abr_goto_meas"):
|
||||
m.abr_goto.connect(self.daq.abr_goto_meas)
|
||||
m.home_requested.connect(self._on_home)
|
||||
|
||||
def _on_home(self) -> None:
|
||||
from aare.common.coordinate import Coordinate, SmargonCoordinate
|
||||
self.daq.move_smargon(SmargonCoordinate(sh_mm=Coordinate(x=0.0, y=0.0, z=18.0)))
|
||||
|
||||
@Slot(str)
|
||||
def _on_mode_changed(self, mode: str) -> None:
|
||||
|
||||
@@ -176,9 +176,6 @@ class ManualView(QWidget):
|
||||
t.end.connect(self._on_end)
|
||||
t.unmount.connect(s.unmount)
|
||||
|
||||
# run plan (which stages the auto-run executes)
|
||||
self.pipeline.run_plan.toggled.connect(s.toggle_protocol)
|
||||
|
||||
# bookmarks
|
||||
bm = self.pipeline.bookmarks
|
||||
bm.bookmark_add.connect(self._on_bookmark_add)
|
||||
@@ -606,7 +603,6 @@ class ManualView(QWidget):
|
||||
|
||||
def _refresh_pipe(self) -> None:
|
||||
self.pipeline.update_from_state(self._state)
|
||||
self.pipeline.run_plan.set_protocol(self._state.protocol)
|
||||
# enable grid-draw affordance only while the raster stage is selected
|
||||
if self._state.stage != "raster":
|
||||
self.pipeline.settings.set_draw_active(False)
|
||||
@@ -638,7 +634,8 @@ class ManualView(QWidget):
|
||||
self._project_bookmarks()
|
||||
bl = getattr(s, "bl", None)
|
||||
if bl is not None and getattr(bl, "zoom", None) is not None:
|
||||
self.camera.set_zoom(bl.zoom)
|
||||
from aare.gui.new_gui.widgets.motors_panel import zoom_label
|
||||
self.camera.set_zoom_text(zoom_label(bl.zoom))
|
||||
if bl is not None:
|
||||
self.camera.set_beam_state(
|
||||
getattr(bl, "shutter_open", False), getattr(s, "busy", False))
|
||||
|
||||
@@ -20,6 +20,7 @@ from PySide6.QtWidgets import (
|
||||
)
|
||||
|
||||
from aare.gui.new_gui.theme import CHANGER_W, Palette
|
||||
from aare.gui.new_gui.widgets.abr_control import AbrControl
|
||||
from aare.gui.new_gui.widgets.camera import CameraViewport
|
||||
from aare.gui.new_gui.widgets.common import micro_label, section_label
|
||||
from aare.gui.new_gui.widgets.motors_panel import MotorsPanel
|
||||
@@ -91,7 +92,7 @@ class StaffView(QWidget):
|
||||
|
||||
# --- right: alignment motors (omega / smargon / ABR / zoom / light) ---
|
||||
self.motors = MotorsPanel(palette)
|
||||
self.motors.set_staff(True) # ABR always available in staff view
|
||||
self.motors.set_staff(True)
|
||||
root.addWidget(self.motors)
|
||||
|
||||
self._select("beam")
|
||||
@@ -125,9 +126,20 @@ class StaffView(QWidget):
|
||||
self.ctx.addWidget(self._note_panel( # 1
|
||||
"Switch to the Beamline camera and adjust the beamstop hardware until "
|
||||
"centred on the beam."))
|
||||
self.ctx.addWidget(self._note_panel( # 2
|
||||
# centre of rotation: guidance note + ABR control (staff-only, here only)
|
||||
cor = QWidget() # 2
|
||||
col = QHBoxLayout(cor)
|
||||
col.setContentsMargins(0, 0, 0, 0)
|
||||
col.setSpacing(18)
|
||||
note = QLabel(
|
||||
"Rotate ω (right panel) and re-centre the sample with the smargon jog "
|
||||
"and ABR focus so it stays on the rotation axis at all angles."))
|
||||
"and ABR so it stays on the rotation axis at all angles.")
|
||||
note.setWordWrap(True)
|
||||
note.setStyleSheet(f"font-size:12px; color:{self._p.text_muted};")
|
||||
col.addWidget(note, 1)
|
||||
self.abr = AbrControl(self._p)
|
||||
col.addWidget(self.abr)
|
||||
self.ctx.addWidget(cor)
|
||||
|
||||
# flux — spectrum controls live in the SpectrumView itself
|
||||
self.ctx.addWidget(self._note_panel( # 3
|
||||
@@ -172,6 +184,7 @@ class StaffView(QWidget):
|
||||
def update_daq_status(self, s) -> None:
|
||||
self._last_status = s
|
||||
self.motors.update_daq_status(s)
|
||||
self.abr.update_daq_status(s)
|
||||
geom = getattr(s, "geom", None)
|
||||
beam = getattr(geom, "beam_location_pxl", None) if geom else None
|
||||
if beam is not None:
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
"""ABR (aerotech beam reference) control — staff Align-centre-of-rotation only.
|
||||
|
||||
Tweak the ABR measurement position (GMX/GMY/GMZ), Save it, or Goto it. Lives in
|
||||
the staff view's centre-of-rotation procedure, not the general motors panel.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtWidgets import (
|
||||
QDoubleSpinBox,
|
||||
QGridLayout,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from aare.common.coordinate import AerotechCoordinate, Coordinate
|
||||
from aare.gui.new_gui.theme import FONT_MONO_FALLBACK, Palette
|
||||
from aare.gui.new_gui.widgets.common import section_label
|
||||
|
||||
|
||||
class AbrControl(QWidget):
|
||||
abr_tweak = Signal(object) # AerotechCoordinate
|
||||
abr_save = Signal()
|
||||
abr_goto = Signal()
|
||||
|
||||
def __init__(self, palette: Palette, parent=None):
|
||||
super().__init__(parent)
|
||||
self._p = palette
|
||||
lay = QVBoxLayout(self)
|
||||
lay.setContentsMargins(0, 0, 0, 0)
|
||||
lay.setSpacing(6)
|
||||
lay.addWidget(section_label("ABR · meas. pos"))
|
||||
|
||||
steprow = QHBoxLayout()
|
||||
steprow.addWidget(self._lbl("Step"))
|
||||
self._step = QDoubleSpinBox()
|
||||
self._step.setRange(1, 1000)
|
||||
self._step.setValue(10)
|
||||
self._step.setSuffix(" µm")
|
||||
self._step.setFixedWidth(90)
|
||||
steprow.addWidget(self._step)
|
||||
steprow.addStretch(1)
|
||||
lay.addLayout(steprow)
|
||||
|
||||
grid = QGridLayout()
|
||||
grid.setSpacing(5)
|
||||
self._labels: dict[str, QLabel] = {}
|
||||
for r, axis in enumerate(("x", "y", "z")):
|
||||
grid.addWidget(self._lbl(f"GM{axis.upper()}"), r, 0)
|
||||
minus, plus = self._btn("−"), self._btn("+")
|
||||
minus.clicked.connect(lambda _=False, a=axis: self._tweak(a, -1))
|
||||
plus.clicked.connect(lambda _=False, a=axis: self._tweak(a, +1))
|
||||
val = QLabel("—")
|
||||
val.setStyleSheet(f"font-family:{FONT_MONO_FALLBACK}; font-size:11px;"
|
||||
f" color:{palette.text_primary};")
|
||||
self._labels[axis] = val
|
||||
grid.addWidget(minus, r, 1)
|
||||
grid.addWidget(plus, r, 2)
|
||||
grid.addWidget(val, r, 3)
|
||||
grid.setColumnStretch(3, 1)
|
||||
lay.addLayout(grid)
|
||||
|
||||
btns = QHBoxLayout()
|
||||
save = self._btn("Save", wide=True)
|
||||
goto = self._btn("Goto", wide=True)
|
||||
save.clicked.connect(self.abr_save)
|
||||
goto.clicked.connect(self.abr_goto)
|
||||
btns.addWidget(save)
|
||||
btns.addWidget(goto)
|
||||
lay.addLayout(btns)
|
||||
|
||||
def _lbl(self, text: str) -> QLabel:
|
||||
lbl = QLabel(text)
|
||||
lbl.setStyleSheet(f"font-size:10.5px; color:{self._p.text_faint};")
|
||||
return lbl
|
||||
|
||||
def _btn(self, text: str, wide: bool = False) -> QPushButton:
|
||||
b = QPushButton(text)
|
||||
b.setCursor(Qt.PointingHandCursor)
|
||||
if not wide:
|
||||
b.setFixedWidth(30)
|
||||
b.setStyleSheet(
|
||||
f"QPushButton {{ background:{self._p.surface};"
|
||||
f" border:1px solid {self._p.border_control}; border-radius:6px;"
|
||||
f" padding:5px 8px; font-size:12px; color:{self._p.text_secondary}; }}"
|
||||
f" QPushButton:hover {{ border-color:{self._p.accent};"
|
||||
f" color:{self._p.accent}; }}")
|
||||
return b
|
||||
|
||||
def _tweak(self, axis: str, sign: int) -> None:
|
||||
step_mm = self._step.value() / 1000.0 * sign
|
||||
kw = {"x": 0.0, "y": 0.0, "z": 0.0}
|
||||
kw[axis] = step_mm
|
||||
self.abr_tweak.emit(AerotechCoordinate(at_mm=Coordinate(**kw), omega_deg=None))
|
||||
|
||||
def update_daq_status(self, s) -> None:
|
||||
geom = getattr(s, "geom", None)
|
||||
meas = getattr(geom, "aerotech_meas", None) if geom else None
|
||||
if meas is None:
|
||||
return
|
||||
for axis in ("x", "y", "z"):
|
||||
v = getattr(meas, axis, None)
|
||||
if v is not None:
|
||||
self._labels[axis].setText(f"{v:.4f}")
|
||||
@@ -52,7 +52,7 @@ class CameraViewport(QWidget):
|
||||
self._p = palette
|
||||
self._pixmap: QPixmap | None = None
|
||||
self._fps: float = 0.0
|
||||
self._zoom: float = 2.0
|
||||
self._zoom_text: str = "—"
|
||||
self._mode = "empty"
|
||||
self._target_point: QPoint | None = None # image-pixel coords
|
||||
self._beam_px: QPoint | None = None # beam centre, image-pixel coords
|
||||
@@ -234,8 +234,8 @@ class CameraViewport(QWidget):
|
||||
self._fps = fps
|
||||
self.update()
|
||||
|
||||
def set_zoom(self, zoom: float) -> None:
|
||||
self._zoom = zoom
|
||||
def set_zoom_text(self, text: str) -> None:
|
||||
self._zoom_text = text or "—"
|
||||
self.update()
|
||||
|
||||
def update_target_point(self, data: dict) -> None:
|
||||
@@ -491,7 +491,7 @@ class CameraViewport(QWidget):
|
||||
f.setPixelSize(11)
|
||||
painter.setFont(f)
|
||||
fps = "-" if self._fps != self._fps else f"{self._fps:.0f}" # NaN-safe
|
||||
text = f"SAMCAM · {fps} fps · {self._zoom:.1f}×"
|
||||
text = f"SAMCAM · {fps} fps · {self._zoom_text}"
|
||||
painter.drawText(QRect(0, 8, r.width() - 14, 16),
|
||||
Qt.AlignRight | Qt.AlignTop, text)
|
||||
|
||||
|
||||
@@ -21,15 +21,24 @@ from PySide6.QtWidgets import (
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from aare.common.coordinate import AerotechCoordinate, Coordinate
|
||||
from aare.gui.new_gui.theme import FONT_MONO_FALLBACK, MOTORS_W, Palette
|
||||
from aare.gui.new_gui.widgets.common import hline, section_label
|
||||
|
||||
OMEGA_STEPS = (-90, -45, -10, 10, 45, 90)
|
||||
ZOOM_LEVELS = (1.0, 2.0, 3.5, 5.8)
|
||||
# (label, zoom-motor value) — the value is a motor position, NOT a magnification.
|
||||
ZOOM_SETTINGS = (("1.0×", 1.0), ("2.0×", 280.0), ("3.5×", 500.0),
|
||||
("5.8×", 700.0), ("7.5×", 800.0), ("12.5×", 1000.0))
|
||||
JOG_STEPS_UM = (10, 50, 100, 500)
|
||||
|
||||
|
||||
def zoom_label(value) -> str:
|
||||
"""Map a zoom-motor value back to its magnification label (for the camera)."""
|
||||
if value is None:
|
||||
return "—"
|
||||
name, _ = min(ZOOM_SETTINGS, key=lambda nv: abs(nv[1] - value))
|
||||
return name
|
||||
|
||||
|
||||
class MotorsPanel(QWidget):
|
||||
omega_rel = Signal(float) # degrees, relative
|
||||
smargon_jog = Signal(float, float, float) # dx_mm, dy_mm, dz_mm (beamline frame)
|
||||
@@ -37,9 +46,7 @@ class MotorsPanel(QWidget):
|
||||
zoom_changed = Signal(float)
|
||||
front_light_changed = Signal(int)
|
||||
back_light_changed = Signal(int)
|
||||
abr_tweak = Signal(object) # AerotechCoordinate (staff)
|
||||
abr_save = Signal()
|
||||
abr_goto = Signal()
|
||||
home_requested = Signal() # move smargon to home (0,0,18)
|
||||
|
||||
def __init__(self, palette: Palette, parent=None):
|
||||
super().__init__(parent)
|
||||
@@ -109,6 +116,19 @@ class MotorsPanel(QWidget):
|
||||
lay.addLayout(ang)
|
||||
lay.addSpacing(8)
|
||||
|
||||
home = QPushButton("⌂ Go to Home")
|
||||
home.setCursor(Qt.PointingHandCursor)
|
||||
home.setToolTip("Move the sample holder to the home position (0, 0, 18 mm)")
|
||||
home.setStyleSheet(
|
||||
f"QPushButton {{ background:{palette.surface};"
|
||||
f" border:1px solid {palette.border_control}; border-radius:8px;"
|
||||
f" padding:7px 12px; font-size:12px; color:{palette.text_secondary}; }}"
|
||||
f" QPushButton:hover {{ border-color:{palette.accent};"
|
||||
f" color:{palette.accent}; }}")
|
||||
home.clicked.connect(self.home_requested)
|
||||
lay.addWidget(home)
|
||||
lay.addSpacing(8)
|
||||
|
||||
# XY jog pad + focus (Z)
|
||||
padrow = QHBoxLayout()
|
||||
pad = QGridLayout()
|
||||
@@ -142,68 +162,29 @@ class MotorsPanel(QWidget):
|
||||
padrow.addLayout(foc)
|
||||
lay.addLayout(padrow)
|
||||
|
||||
# ---- ABR (staff only) ----
|
||||
self._abr_section = QWidget()
|
||||
ab = QVBoxLayout(self._abr_section)
|
||||
ab.setContentsMargins(0, 0, 0, 0)
|
||||
ab.setSpacing(0)
|
||||
ab.addSpacing(14)
|
||||
ab.addWidget(hline(palette))
|
||||
ab.addSpacing(14)
|
||||
ab.addWidget(section_label("ABR · meas. pos"))
|
||||
ab.addSpacing(6)
|
||||
steprow = QHBoxLayout()
|
||||
steprow.addWidget(self._small_label("Step"))
|
||||
self._abr_step = QDoubleSpinBox(); self._abr_step.setRange(1, 1000)
|
||||
self._abr_step.setValue(10); self._abr_step.setSuffix(" µm")
|
||||
steprow.addWidget(self._abr_step); steprow.addStretch(1)
|
||||
ab.addLayout(steprow)
|
||||
abr_grid = QGridLayout(); abr_grid.setSpacing(5)
|
||||
self._abr_labels = {}
|
||||
for r, axis in enumerate(("x", "y", "z")):
|
||||
abr_grid.addWidget(self._small_label(f"GM{axis.upper()}"), r, 0)
|
||||
m = self._jog_btn("−"); p = self._jog_btn("+")
|
||||
m.clicked.connect(lambda _=False, a=axis: self._abr(a, -1))
|
||||
p.clicked.connect(lambda _=False, a=axis: self._abr(a, +1))
|
||||
val = QLabel("—")
|
||||
val.setStyleSheet(f"font-family:{FONT_MONO_FALLBACK}; font-size:11px;")
|
||||
self._abr_labels[axis] = val
|
||||
abr_grid.addWidget(m, r, 1); abr_grid.addWidget(p, r, 2); abr_grid.addWidget(val, r, 3)
|
||||
ab.addLayout(abr_grid)
|
||||
abr_btns = QHBoxLayout()
|
||||
save = QPushButton("Save"); save.clicked.connect(self.abr_save)
|
||||
goto = QPushButton("Goto"); goto.clicked.connect(self.abr_goto)
|
||||
for b in (save, goto):
|
||||
b.setCursor(Qt.PointingHandCursor)
|
||||
abr_btns.addWidget(save); abr_btns.addWidget(goto)
|
||||
ab.addLayout(abr_btns)
|
||||
self._abr_section.setVisible(False)
|
||||
lay.addWidget(self._abr_section)
|
||||
|
||||
lay.addSpacing(14)
|
||||
lay.addWidget(hline(palette))
|
||||
lay.addSpacing(14)
|
||||
|
||||
# ---- ZOOM ----
|
||||
# ---- ZOOM (3-col grid of all magnification presets) ----
|
||||
lay.addWidget(section_label("ZOOM"))
|
||||
lay.addSpacing(8)
|
||||
zoom_row = QHBoxLayout()
|
||||
zoom_row.setSpacing(6)
|
||||
zoom_grid = QGridLayout()
|
||||
zoom_grid.setSpacing(6)
|
||||
self._zoom_group = QButtonGroup(self)
|
||||
self._zoom_group.setExclusive(True)
|
||||
self._zoom_btns: dict[float, QPushButton] = {}
|
||||
for z in ZOOM_LEVELS:
|
||||
b = QPushButton(f"{z:.1f}×")
|
||||
for i, (name, value) in enumerate(ZOOM_SETTINGS):
|
||||
b = QPushButton(name)
|
||||
b.setCheckable(True)
|
||||
b.setCursor(Qt.PointingHandCursor)
|
||||
b.clicked.connect(lambda _=False, zz=z: self.zoom_changed.emit(zz))
|
||||
b.clicked.connect(lambda _=False, v=value: self.zoom_changed.emit(v))
|
||||
b.toggled.connect(lambda _on, bb=b: self._restyle_zoom(bb))
|
||||
self._zoom_group.addButton(b)
|
||||
self._zoom_btns[z] = b
|
||||
zoom_row.addWidget(b)
|
||||
self._zoom_btns[value] = b
|
||||
zoom_grid.addWidget(b, i // 3, i % 3)
|
||||
self._restyle_zoom(b)
|
||||
zoom_row.addStretch(1)
|
||||
lay.addLayout(zoom_row)
|
||||
lay.addLayout(zoom_grid)
|
||||
|
||||
lay.addSpacing(14)
|
||||
lay.addWidget(hline(palette))
|
||||
@@ -218,7 +199,9 @@ class MotorsPanel(QWidget):
|
||||
lay.addStretch(1)
|
||||
|
||||
def set_staff(self, is_staff: bool) -> None:
|
||||
self._abr_section.setVisible(is_staff)
|
||||
# ABR moved to the staff Align-centre-of-rotation procedure; nothing
|
||||
# staff-gated remains in the motors panel.
|
||||
pass
|
||||
|
||||
# -------- helpers --------
|
||||
def _small_label(self, text: str) -> QLabel:
|
||||
@@ -292,12 +275,6 @@ class MotorsPanel(QWidget):
|
||||
step_mm = JOG_STEPS_UM[self._jog_idx] / 1000.0
|
||||
self.smargon_jog.emit(sx * step_mm, sy * step_mm, sz * step_mm)
|
||||
|
||||
def _abr(self, axis: str, sign: int) -> None:
|
||||
step_mm = self._abr_step.value() / 1000.0 * sign
|
||||
kw = {"x": 0.0, "y": 0.0, "z": 0.0}
|
||||
kw[axis] = step_mm
|
||||
self.abr_tweak.emit(AerotechCoordinate(at_mm=Coordinate(**kw), omega_deg=None))
|
||||
|
||||
# -------- live updates --------
|
||||
def update_daq_status(self, s) -> None:
|
||||
geom = getattr(s, "geom", None)
|
||||
@@ -309,12 +286,6 @@ class MotorsPanel(QWidget):
|
||||
if smg is not None:
|
||||
self._sync_spin(self._chi, getattr(smg, "chi_deg", None))
|
||||
self._sync_spin(self._phi, getattr(smg, "phi_deg", None))
|
||||
meas = getattr(geom, "aerotech_meas", None)
|
||||
if meas is not None:
|
||||
for axis in ("x", "y", "z"):
|
||||
v = getattr(meas, axis, None)
|
||||
if v is not None:
|
||||
self._abr_labels[axis].setText(f"{v:.4f}")
|
||||
bl = getattr(s, "bl", None)
|
||||
if bl is not None:
|
||||
zoom = getattr(bl, "zoom", None)
|
||||
@@ -332,7 +303,7 @@ class MotorsPanel(QWidget):
|
||||
spin.blockSignals(False)
|
||||
|
||||
def _sync_zoom(self, zoom: float) -> None:
|
||||
nearest = min(ZOOM_LEVELS, key=lambda z: abs(z - zoom))
|
||||
nearest = min(ZOOM_SETTINGS, key=lambda nv: abs(nv[1] - zoom))[1]
|
||||
btn = self._zoom_btns.get(nearest)
|
||||
if btn and not btn.isChecked():
|
||||
btn.blockSignals(True)
|
||||
|
||||
@@ -28,7 +28,6 @@ from PySide6.QtWidgets import (
|
||||
|
||||
from aare.gui.new_gui.theme import FONT_MONO_FALLBACK, Palette
|
||||
from aare.gui.new_gui.widgets.common import (
|
||||
Chip,
|
||||
micro_label,
|
||||
mono_label,
|
||||
vline,
|
||||
@@ -36,43 +35,6 @@ from aare.gui.new_gui.widgets.common import (
|
||||
from aare.gui.new_gui.widgets.heatmap import METRICS
|
||||
from aare.gui.new_gui.widgets.pipeline import PipelineTracker
|
||||
|
||||
_RUN_PLAN_STAGES = (("center", "Center"), ("raster", "Raster"),
|
||||
("xrf", "XRF"), ("collect", "Collect"))
|
||||
|
||||
|
||||
class RunPlanRow(QWidget):
|
||||
"""Toggle which stages ▶ Play runs. ⚑ on a node pauses before that stage."""
|
||||
|
||||
toggled = Signal(str)
|
||||
|
||||
def __init__(self, palette: Palette, parent=None):
|
||||
super().__init__(parent)
|
||||
lay = QHBoxLayout(self)
|
||||
lay.setContentsMargins(0, 0, 0, 0)
|
||||
lay.setSpacing(6)
|
||||
lay.addWidget(micro_label("RUN PLAN"))
|
||||
self._chips: dict[str, Chip] = {}
|
||||
for key, label in _RUN_PLAN_STAGES:
|
||||
c = Chip(label, palette, checked=False, mono=False)
|
||||
c.clicked.connect(lambda _=False, k=key: self.toggled.emit(k))
|
||||
self._chips[key] = c
|
||||
lay.addWidget(c)
|
||||
hint = QLabel("▶ runs the lit stages · tap a stage's ⚑ to pause before it")
|
||||
hint.setStyleSheet(f"font-size:10.5px; color:{palette.text_faint};")
|
||||
lay.addSpacing(6)
|
||||
lay.addWidget(hint)
|
||||
lay.addStretch(1)
|
||||
|
||||
def set_protocol(self, protocol: dict) -> None:
|
||||
for key, chip in self._chips.items():
|
||||
on = bool(protocol.get(key))
|
||||
if chip.isChecked() != on:
|
||||
chip.blockSignals(True)
|
||||
chip.setChecked(on)
|
||||
chip.blockSignals(False)
|
||||
chip._restyle()
|
||||
|
||||
|
||||
def _primary_button(text: str, palette: Palette) -> QPushButton:
|
||||
b = QPushButton(text)
|
||||
b.setObjectName("Primary")
|
||||
@@ -697,10 +659,6 @@ class PipelinePanel(QWidget):
|
||||
self.settings = ContextualSettings(palette, defaults)
|
||||
lay.addWidget(self.settings)
|
||||
|
||||
# run plan (which stages ▶ Play runs)
|
||||
self.run_plan = RunPlanRow(palette)
|
||||
lay.addWidget(self.run_plan)
|
||||
|
||||
# transport
|
||||
self.transport = TransportRow(palette)
|
||||
lay.addWidget(self.transport)
|
||||
@@ -716,7 +674,6 @@ class PipelinePanel(QWidget):
|
||||
self._mounted = mounted
|
||||
self._badge.setVisible(mounted)
|
||||
self.bookmarks.setVisible(mounted)
|
||||
self.run_plan.setVisible(mounted)
|
||||
self.transport.setVisible(mounted)
|
||||
self.settings.set_run_enabled(mounted)
|
||||
self.tracker.set_preview(not mounted)
|
||||
|
||||
Reference in New Issue
Block a user