GUI: added controls for mono_picth_scan and change_energy
This commit is contained in:
@@ -3608,6 +3608,20 @@ class AareDAQ:
|
||||
finally:
|
||||
self.__cfg.state_busy = False
|
||||
|
||||
def mono_pitch_scan(self, plot: bool = False) -> None:
|
||||
self.__cfg.try_set_busy(timeout=360)
|
||||
try:
|
||||
self.__devs.bec_worker.mono_pitch_scan_runner(plot=plot)
|
||||
finally:
|
||||
self.__cfg.state_busy = False
|
||||
|
||||
def change_energy(self, value: float, plot: bool = False) -> None:
|
||||
self.__cfg.try_set_busy(timeout=360)
|
||||
try:
|
||||
self.__devs.bec_worker.change_energy(value=value, plot=plot)
|
||||
finally:
|
||||
self.__cfg.state_busy = False
|
||||
|
||||
def fluorimeter_take_spectrum(self, fm: FluorescenceSpectrumParameterModel) -> FluorescenceSpectrumOutputModel:
|
||||
self.__cfg.try_set_busy(timeout=360)
|
||||
|
||||
|
||||
@@ -424,6 +424,43 @@ async def zoom(val: float, token: str = Depends(oauth2_scheme)):
|
||||
return "OK"
|
||||
|
||||
|
||||
@app.post("/beamline/mono_pitch_scan")
|
||||
async def mono_pitch_scan(plot: bool = False, token: str = Depends(oauth2_scheme)):
|
||||
"""
|
||||
Run a monochromator pitch scan. Staff only.
|
||||
|
||||
Args:
|
||||
plot: Whether to enable plotting in the BEC worker.
|
||||
token: OAuth2 access token.
|
||||
|
||||
Returns:
|
||||
"OK" on success.
|
||||
"""
|
||||
logger.debug(f"Running mono pitch scan (plot={plot})")
|
||||
auth.check_jwt_staff(cfg, auth.parse_token(token))
|
||||
daq.mono_pitch_scan(plot=plot)
|
||||
return "OK"
|
||||
|
||||
|
||||
@app.put("/beamline/change_energy")
|
||||
async def change_energy(value: float, plot: bool = False, token: str = Depends(oauth2_scheme)):
|
||||
"""
|
||||
Change monochromator energy. Staff only.
|
||||
|
||||
Args:
|
||||
value: Target energy.
|
||||
plot: Whether to enable plotting in the BEC worker.
|
||||
token: OAuth2 access token.
|
||||
|
||||
Returns:
|
||||
"OK" on success.
|
||||
"""
|
||||
logger.debug(f"Changing energy to {value} (plot={plot})")
|
||||
auth.check_jwt_staff(cfg, auth.parse_token(token))
|
||||
daq.change_energy(value=value, plot=plot)
|
||||
return "OK"
|
||||
|
||||
|
||||
@app.put("/beamline/smargon")
|
||||
async def smargon(val: SmargonCoordinate, token: str = Depends(oauth2_scheme)):
|
||||
"""
|
||||
|
||||
@@ -92,6 +92,8 @@ class MainWindow(QMainWindow):
|
||||
self._cleanup_done = False
|
||||
self._default_window_state = None
|
||||
|
||||
self._show_beamline_state_panel_for_users = True
|
||||
|
||||
self._waiting_for_baton_response: bool = False
|
||||
self._baton_request_dialog: BatonRequestDialog | None = None
|
||||
self._baton_pending_dialog: BatonPendingDialog | None = None
|
||||
@@ -187,10 +189,16 @@ class MainWindow(QMainWindow):
|
||||
self.loop_centering = LoopCenteringPanel(parent=self.left_column)
|
||||
|
||||
self.beamline_state_panel = BeamlineStatePanel(parent=self.left_column)
|
||||
self._beamline_state_panel_enabled = bool(
|
||||
self.__decoded_token.staff or self._show_beamline_state_panel_for_users
|
||||
)
|
||||
|
||||
self.left_column_layout.addWidget(self.data_collection)
|
||||
self.left_column_layout.addWidget(self.loop_centering)
|
||||
self.left_column_layout.addWidget(self.beamline_state_panel)
|
||||
if self._beamline_state_panel_enabled:
|
||||
self.left_column_layout.addWidget(self.beamline_state_panel)
|
||||
else:
|
||||
self.beamline_state_panel.hide()
|
||||
self.left_column_layout.addStretch()
|
||||
|
||||
top_widget_layout.addWidget(collection_controls_scroll)
|
||||
@@ -456,6 +464,8 @@ class MainWindow(QMainWindow):
|
||||
self.beamline.illumination_panel.back_light.connect(self.daq.back_light)
|
||||
|
||||
if self.__decoded_token.staff:
|
||||
self.beamline.monochromator_panel.mono_pitch_scan.connect(self.daq.mono_pitch_scan)
|
||||
self.beamline.monochromator_panel.change_energy.connect(self.daq.change_energy)
|
||||
self.beamline.abr_tweak.abr_tweak.connect(self.daq.abr_tweak)
|
||||
self.beamline.abr_tweak.abr_save.connect(self.daq.abr_save)
|
||||
self.beamline.abr_tweak.abr_goto_meas.connect(self.daq.abr_goto_meas)
|
||||
@@ -613,6 +623,7 @@ class MainWindow(QMainWindow):
|
||||
self.daq.update.connect(self.camera_thread.update_daq_status)
|
||||
|
||||
if self.__decoded_token.staff:
|
||||
self.daq.update.connect(self.beamline.monochromator_panel.update_daq_status)
|
||||
self.daq.update.connect(self.beamline.beam_size.update_daq_status)
|
||||
self.daq.update.connect(self.beamline.beam_center.update_daq_status)
|
||||
self.daq.update.connect(self.beamline.abr_tweak.update_daq_status)
|
||||
@@ -823,6 +834,15 @@ class MainWindow(QMainWindow):
|
||||
|
||||
view_menu = menu_bar.addMenu("View")
|
||||
|
||||
if self._beamline_state_panel_enabled:
|
||||
self._show_beamline_state_action = QAction("Show Beamline State Panel", self)
|
||||
self._show_beamline_state_action.setCheckable(True)
|
||||
self._show_beamline_state_action.setChecked(self.beamline_state_panel.isVisible())
|
||||
self._show_beamline_state_action.triggered.connect(
|
||||
lambda checked: self.beamline_state_panel.setVisible(checked)
|
||||
)
|
||||
view_menu.addAction(self._show_beamline_state_action)
|
||||
|
||||
show_samples_action = QAction("Show Sample List", self)
|
||||
show_samples_action.setCheckable(True)
|
||||
show_samples_action.setChecked(True)
|
||||
@@ -973,6 +993,12 @@ class MainWindow(QMainWindow):
|
||||
self.job_list_dock.setVisible(True)
|
||||
self.manual_sample_dock.setVisible(True)
|
||||
|
||||
if self._beamline_state_panel_enabled:
|
||||
self.beamline_state_panel.setVisible(True)
|
||||
self.beamline_state_panel.set_collapsed(False)
|
||||
if hasattr(self, "_show_beamline_state_action"):
|
||||
self._show_beamline_state_action.setChecked(True)
|
||||
|
||||
self.face_panel_dock.setVisible(False)
|
||||
self.fluor_panel_dock.setVisible(False)
|
||||
self.smargon_trace_dock.setVisible(False)
|
||||
|
||||
@@ -5,6 +5,7 @@ from aare.gui.panels.beam_center_panel import BeamCenterWidget
|
||||
from aare.gui.panels.beam_mark_panel import BeamMarkWidget
|
||||
from aare.gui.panels.beam_size_panel import BeamSizeWidget
|
||||
from aare.gui.panels.illumination_panel import IlluminationPanel
|
||||
from aare.gui.panels.monochromator_panel import MonochromatorPanel
|
||||
from aare.gui.panels.omega_panel import OmegaPanel
|
||||
from aare.gui.panels.samcam_panel import SamcamPanel
|
||||
from aare.gui.panels.smargon_panel import SmargonPanel
|
||||
@@ -37,11 +38,13 @@ class BeamlineControls(QFrame):
|
||||
self.v_layout.addWidget(self.samcam)
|
||||
|
||||
if staff:
|
||||
self.monochromator_panel = MonochromatorPanel(self)
|
||||
self.abr_tweak = AbrTweakWidget(self)
|
||||
self.beam_mark = BeamMarkWidget(self)
|
||||
self.beam_center = BeamCenterWidget(self)
|
||||
self.beam_size = BeamSizeWidget(self)
|
||||
|
||||
self.v_layout.addWidget(self.monochromator_panel)
|
||||
self.v_layout.addWidget(self.abr_tweak)
|
||||
self.v_layout.addWidget(self.beam_mark)
|
||||
self.v_layout.addWidget(self.beam_center)
|
||||
@@ -49,4 +52,3 @@ class BeamlineControls(QFrame):
|
||||
|
||||
self.v_layout.addStretch()
|
||||
self.setLayout(self.v_layout)
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ class BeamlineStatePanel(QFrame):
|
||||
|
||||
set_width = 400
|
||||
map_height = 470
|
||||
title_height = 50
|
||||
collapsed_height = 50
|
||||
station_radius = 8
|
||||
|
||||
def __init__(self, parent=None):
|
||||
@@ -63,7 +65,9 @@ class BeamlineStatePanel(QFrame):
|
||||
self.setFrameShape(QFrame.Shape.StyledPanel)
|
||||
self.setFrameShadow(QFrame.Shadow.Raised)
|
||||
self.setFixedWidth(self.set_width)
|
||||
self._is_collapsed = False
|
||||
self.setMinimumHeight(self.map_height)
|
||||
self.setMaximumHeight(self.map_height)
|
||||
|
||||
self._current_state: BeamlineStateEnum | None = None
|
||||
self._hovered_state: BeamlineStateEnum | None = None
|
||||
@@ -134,8 +138,27 @@ class BeamlineStatePanel(QFrame):
|
||||
self.title.setText("<H3>Beamline state</H3>")
|
||||
self.title.setStyleSheet("background-color: #4B0082; color: #ffffff;")
|
||||
self.title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.title.setFixedHeight(50)
|
||||
self.title.setGeometry(0, 0, self.set_width, 50)
|
||||
self.title.setFixedHeight(self.title_height)
|
||||
self.title.setGeometry(0, 0, self.set_width, self.title_height)
|
||||
|
||||
self.toggle_button = QPushButton("−", self)
|
||||
self.toggle_button.setToolTip("Minimise beamline state panel")
|
||||
self.toggle_button.setFixedSize(28, 28)
|
||||
self.toggle_button.move(self.set_width - 36, 11)
|
||||
self.toggle_button.clicked.connect(self.toggle_collapsed)
|
||||
self.toggle_button.setStyleSheet("""
|
||||
QPushButton {
|
||||
border: none;
|
||||
border-radius: 14px;
|
||||
background-color: rgba(255, 255, 255, 0.20);
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: rgba(255, 255, 255, 0.32);
|
||||
}
|
||||
""")
|
||||
|
||||
self.current_label = QLabel("Current: —", self)
|
||||
self.current_label.setStyleSheet("""
|
||||
@@ -165,6 +188,7 @@ class BeamlineStatePanel(QFrame):
|
||||
|
||||
self._build_station_widgets()
|
||||
self._position_station_widgets()
|
||||
self._update_collapsed_state()
|
||||
|
||||
@staticmethod
|
||||
def _canon_segment(a: BeamlineStateEnum, b: BeamlineStateEnum) -> tuple[BeamlineStateEnum, BeamlineStateEnum]:
|
||||
@@ -267,6 +291,39 @@ class BeamlineStatePanel(QFrame):
|
||||
|
||||
self._apply_station_highlight()
|
||||
|
||||
def toggle_collapsed(self) -> None:
|
||||
self._is_collapsed = not self._is_collapsed
|
||||
self._update_collapsed_state()
|
||||
|
||||
def set_collapsed(self, collapsed: bool) -> None:
|
||||
if self._is_collapsed == collapsed:
|
||||
return
|
||||
self._is_collapsed = collapsed
|
||||
self._update_collapsed_state()
|
||||
|
||||
def _update_collapsed_state(self) -> None:
|
||||
show_content = not self._is_collapsed
|
||||
|
||||
self.current_label.setVisible(show_content)
|
||||
self.tell_label.setVisible(show_content)
|
||||
|
||||
for widget in self._station_widgets.values():
|
||||
widget.setVisible(show_content)
|
||||
|
||||
if self._is_collapsed:
|
||||
self.setMinimumHeight(self.collapsed_height)
|
||||
self.setMaximumHeight(self.collapsed_height)
|
||||
self.toggle_button.setText("+")
|
||||
self.toggle_button.setToolTip("Restore beamline state panel")
|
||||
else:
|
||||
self.setMinimumHeight(self.map_height)
|
||||
self.setMaximumHeight(self.map_height)
|
||||
self.toggle_button.setText("−")
|
||||
self.toggle_button.setToolTip("Minimise beamline state panel")
|
||||
|
||||
self.updateGeometry()
|
||||
self.update()
|
||||
|
||||
def _emit_for_state(self, state: BeamlineStateEnum) -> None:
|
||||
self._pending_target_state = state
|
||||
self._hovered_state = None
|
||||
@@ -460,6 +517,9 @@ class BeamlineStatePanel(QFrame):
|
||||
def paintEvent(self, event) -> None:
|
||||
super().paintEvent(event)
|
||||
|
||||
if self._is_collapsed:
|
||||
return
|
||||
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
from PySide6.QtCore import Signal, Slot
|
||||
from PySide6.QtWidgets import QWidget, QGridLayout, QLabel, QDoubleSpinBox, QPushButton
|
||||
|
||||
from aare.common.models import DAQStatusModel
|
||||
from aare.gui.widgets.title_label import TitleLabel
|
||||
|
||||
|
||||
class MonochromatorPanel(QWidget):
|
||||
mono_pitch_scan = Signal()
|
||||
change_energy = Signal(float)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
grid_layout = QGridLayout(self)
|
||||
grid_layout.addWidget(TitleLabel("Monochromator", self), 0, 0, 1, 2)
|
||||
|
||||
self.mono_pitch_scan_button = QPushButton("Mono Pitch Scan", parent=self)
|
||||
self.mono_pitch_scan_button.clicked.connect(self.mono_pitch_scan.emit)
|
||||
grid_layout.addWidget(self.mono_pitch_scan_button, 1, 0, 1, 2)
|
||||
|
||||
grid_layout.addWidget(QLabel("Energy", parent=self), 2, 0)
|
||||
|
||||
self.energy_spin = QDoubleSpinBox(parent=self)
|
||||
self.energy_spin.setDecimals(3)
|
||||
self.energy_spin.setRange(1000.0, 30000.0)
|
||||
self.energy_spin.setSingleStep(100.0)
|
||||
self.energy_spin.setSuffix(" eV")
|
||||
self.energy_spin.setValue(12000.0)
|
||||
grid_layout.addWidget(self.energy_spin, 3, 0)
|
||||
|
||||
self.change_energy_button = QPushButton("Change Energy", parent=self)
|
||||
self.change_energy_button.clicked.connect(self._emit_change_energy)
|
||||
grid_layout.addWidget(self.change_energy_button, 3, 1)
|
||||
|
||||
@Slot()
|
||||
def _emit_change_energy(self):
|
||||
self.change_energy.emit(float(self.energy_spin.value()))
|
||||
|
||||
@Slot(DAQStatusModel)
|
||||
def update_daq_status(self, _status: DAQStatusModel):
|
||||
pass
|
||||
@@ -661,6 +661,14 @@ class DAQWorker(QObject):
|
||||
def zoom(self, f: float):
|
||||
self.generic_put(f"beamline/zoom?val={f:.3f}")
|
||||
|
||||
@Slot()
|
||||
def mono_pitch_scan(self):
|
||||
self.generic_post("beamline/mono_pitch_scan")
|
||||
|
||||
@Slot(float)
|
||||
def change_energy(self, value: float):
|
||||
self.generic_put(f"beamline/change_energy?value={value:.3f}")
|
||||
|
||||
@Slot(int)
|
||||
def front_light(self, v: int):
|
||||
self.generic_put(f"beamline/front_light?val={v:d}")
|
||||
|
||||
Reference in New Issue
Block a user