From 59539f80d473daee69a206607d259d85ba91da18 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Wed, 25 Jun 2025 15:12:29 +0200 Subject: [PATCH] DAQ: Beam location, work in progress --- daq/src/aaredaq/daq.py | 9 +++- daq/src/aaredaq/server.py | 6 +-- daq/src/aaredaq/workflows.py | 3 ++ gui/src/aaregui/main_window.py | 1 + gui/src/aaregui/threads/daq_worker.py | 6 ++- gui/src/aaregui/widgets/camera_image.py | 70 +++++++++++++++++-------- gui/src/aaregui/widgets/status_bar.py | 7 +++ 7 files changed, 74 insertions(+), 28 deletions(-) diff --git a/daq/src/aaredaq/daq.py b/daq/src/aaredaq/daq.py index 1f4abe9c..bb1b216d 100644 --- a/daq/src/aaredaq/daq.py +++ b/daq/src/aaredaq/daq.py @@ -772,8 +772,13 @@ class AareDAQ: self.__cfg.state_busy = False raise e - def close_shutter(self): - self.__devs.shutter = False + @property + def shutter(self) -> bool: + return self.__devs.shutter + + @shutter.setter + def shutter(self, v: bool): + self.__devs.shutter = v @property def diffraction_geometry(self) -> DiffractionGeometry: diff --git a/daq/src/aaredaq/server.py b/daq/src/aaredaq/server.py index 97097d88..74c8bf53 100644 --- a/daq/src/aaredaq/server.py +++ b/daq/src/aaredaq/server.py @@ -141,10 +141,10 @@ async def samcam_autofocus(s: AutofocusSettings, token: str = Depends(oauth2_sch daq.autofocus(s) return "OK" -@app.post("/shutter/close") -async def close_shutter(token: str = Depends(oauth2_scheme)): +@app.post("/beamline/shutter") +async def shutter(val: bool, token: str = Depends(oauth2_scheme)): auth.check_jwt_rw(cfg, auth.parse_token(token)) - daq.close_shutter() + daq.shutter = val return "OK" diff --git a/daq/src/aaredaq/workflows.py b/daq/src/aaredaq/workflows.py index de3b6d6f..1f0f61cb 100644 --- a/daq/src/aaredaq/workflows.py +++ b/daq/src/aaredaq/workflows.py @@ -267,10 +267,13 @@ def sa2bl(devs: BeamlineDevices, cfg: BeamlineConfig): devs.reflector_up = False devs.scintillator = StagePositionEnum.MEASURE devs.collimator = StagePositionEnum.MEASURE + devs.shutter = True def bl2sa(devs: BeamlineDevices, cfg: BeamlineConfig): hub = cfg.settings + devs.shutter = False + devs.set_scintillator(StagePositionEnum.DOWN, wait=False) devs.set_collimator(StagePositionEnum.PARK, wait=False) diff --git a/gui/src/aaregui/main_window.py b/gui/src/aaregui/main_window.py index 1cdcb1d0..9910bb4e 100644 --- a/gui/src/aaregui/main_window.py +++ b/gui/src/aaregui/main_window.py @@ -206,6 +206,7 @@ class MainWindow(QMainWindow): self.status_bar.beam_location.connect(self.daq.beam_location) self.status_bar.close_shutter.connect(self.daq.close_shutter) + self.status_bar.open_shutter.connect(self.daq.open_shutter) self.raster.file_ready.connect(self.viewer.load_file) self.raster.image_selected.connect(self.viewer.load_image) diff --git a/gui/src/aaregui/threads/daq_worker.py b/gui/src/aaregui/threads/daq_worker.py index ec39a56c..78d1454a 100644 --- a/gui/src/aaregui/threads/daq_worker.py +++ b/gui/src/aaregui/threads/daq_worker.py @@ -138,7 +138,11 @@ class DAQWorker(QObject): @Slot() def close_shutter(self): - self.generic_post("shutter/close") + self.generic_post(f"beamline/shutter?val=false") + + @Slot() + def open_shutter(self): + self.generic_post(f"beamline/shutter?val=true") @Slot() def alc_background(self): diff --git a/gui/src/aaregui/widgets/camera_image.py b/gui/src/aaregui/widgets/camera_image.py index 50a46137..8aa3d60d 100644 --- a/gui/src/aaregui/widgets/camera_image.py +++ b/gui/src/aaregui/widgets/camera_image.py @@ -22,7 +22,7 @@ from PySide6.QtWidgets import ( QFrame, ) -from aaredaqlib.models import DAQStatusModel, AutofocusSettings, SampleCameraSettings +from aaredaqlib.models import DAQStatusModel, AutofocusSettings, SampleCameraSettings, BeamlineStateEnum from aaregui.models.bookmark import SmargonBookmarkList from aaredaqlib.coordinate import Coordinate, SmargonCoordinate from aaredaqlib.raster_grid import RasterGridRequest @@ -118,9 +118,6 @@ class SampleCameraImageLabel(QGraphicsView): self.start_point = self.mapToScene(event.pos()) match self.__state: - case SampleCameraImageState.BEAM_MARKING: - if event.button() == Qt.MouseButton.LeftButton: - self.update_beam_mark.emit(self.start_point.x(), self.start_point.y()) case SampleCameraImageState.IDLE: self.click_timer.start(self.right_click_hold_threshold) if event.button() == Qt.MouseButton.RightButton: @@ -310,9 +307,17 @@ class SampleCameraImageLabel(QGraphicsView): def update_daq_status(self, s: DAQStatusModel): self.__geom = s.geom self.__sam_cam = s.bl.sample_camera + if s.state == BeamlineStateEnum.BeamLocation: + self.__state = SampleCameraImageState.BEAM_MARKING + elif self.__state == SampleCameraImageState.BEAM_MARKING: + self.__state = SampleCameraImageState.IDLE def __left_single_click(self, event): match self.__state: + case SampleCameraImageState.BEAM_MARKING: + if event.button() == Qt.MouseButton.LeftButton and event.modifiers() & Qt.KeyboardModifier.ShiftModifier: + point = self.mapToScene(event.pos()) + self.update_beam_mark.emit(point.x(), point.y()) case SampleCameraImageState.IDLE: point = self.mapToScene(event.pos()) if event.modifiers() & Qt.KeyboardModifier.ShiftModifier: @@ -328,8 +333,12 @@ class SampleCameraImageLabel(QGraphicsView): def __draw_beam_center(self, painter: QPainter): beam_size_pxl = self.__geom.beam_size_pxl + if self.__state == SampleCameraImageState.BEAM_MARKING: + painter.setPen(QPen(QColor(102, 51, 153), 3, Qt.PenStyle.SolidLine)) + else: + painter.setPen(QPen(QColor(245, 121, 0), 3, Qt.PenStyle.SolidLine)) + painter.setBrush(Qt.BrushStyle.NoBrush) - painter.setPen(QPen(QColor(245, 121, 0), 3, Qt.PenStyle.SolidLine)) painter.drawRect( QRect( int(self.__geom.beam_location_pxl.x - beam_size_pxl.x / 2), @@ -411,22 +420,39 @@ class SampleCameraImageLabel(QGraphicsView): super().keyPressEvent(event) def wheelEvent(self, event: QWheelEvent): - # Only process the wheel event if the timer is not active or enough time has passed - if not self.wheel_event_timer.isActive(): - delta_y = event.angleDelta().y() + match self.__state: + case SampleCameraImageState.BEAM_MARKING: + if not self.wheel_event_timer.isActive(): + delta_y = event.angleDelta().y() - if event.modifiers() & Qt.KeyboardModifier.AltModifier: - new_exp_time = self.__sam_cam.exposure * (1.0 + math.copysign(0.1, delta_y)) - new_settings = SampleCameraSettings(exposure=new_exp_time, gain=self.__sam_cam.gain) - self.samcam_updated.emit(new_settings) - elif event.modifiers() & Qt.KeyboardModifier.ControlModifier: - new_exp_time = self.__sam_cam.exposure * (1.0 + math.copysign(0.5, delta_y)) - new_settings = SampleCameraSettings(exposure=new_exp_time, gain=self.__sam_cam.gain) - self.samcam_updated.emit(new_settings) - elif event.modifiers() & Qt.KeyboardModifier.ShiftModifier: - self.set_omega.emit(self.__geom.omega_deg + math.copysign(10.0, delta_y)) - else: - self.set_omega.emit(self.__geom.omega_deg + math.copysign(90.0, delta_y)) + if event.modifiers() & Qt.KeyboardModifier.AltModifier: + new_exp_time = self.__sam_cam.exposure * (1.0 + math.copysign(0.1, delta_y)) + new_settings = SampleCameraSettings(exposure=new_exp_time, gain=self.__sam_cam.gain) + self.samcam_updated.emit(new_settings) + else: + new_exp_time = self.__sam_cam.exposure * (1.0 + math.copysign(0.5, delta_y)) + new_settings = SampleCameraSettings(exposure=new_exp_time, gain=self.__sam_cam.gain) + self.samcam_updated.emit(new_settings) - # Start the timer to throttle further events - self.wheel_event_timer.start(self.wheel_event_threshold) + # Start the timer to throttle further events + self.wheel_event_timer.start(self.wheel_event_threshold) + case SampleCameraImageState.IDLE: + # Only process the wheel event if the timer is not active or enough time has passed + if not self.wheel_event_timer.isActive(): + delta_y = event.angleDelta().y() + + if event.modifiers() & Qt.KeyboardModifier.AltModifier: + new_exp_time = self.__sam_cam.exposure * (1.0 + math.copysign(0.1, delta_y)) + new_settings = SampleCameraSettings(exposure=new_exp_time, gain=self.__sam_cam.gain) + self.samcam_updated.emit(new_settings) + elif event.modifiers() & Qt.KeyboardModifier.ControlModifier: + new_exp_time = self.__sam_cam.exposure * (1.0 + math.copysign(0.5, delta_y)) + new_settings = SampleCameraSettings(exposure=new_exp_time, gain=self.__sam_cam.gain) + self.samcam_updated.emit(new_settings) + elif event.modifiers() & Qt.KeyboardModifier.ShiftModifier: + self.set_omega.emit(self.__geom.omega_deg + math.copysign(10.0, delta_y)) + else: + self.set_omega.emit(self.__geom.omega_deg + math.copysign(90.0, delta_y)) + + # Start the timer to throttle further events + self.wheel_event_timer.start(self.wheel_event_threshold) diff --git a/gui/src/aaregui/widgets/status_bar.py b/gui/src/aaregui/widgets/status_bar.py index f155dab8..e6f8b41b 100644 --- a/gui/src/aaregui/widgets/status_bar.py +++ b/gui/src/aaregui/widgets/status_bar.py @@ -17,6 +17,7 @@ class StatusBar(QStatusBar): force_session = Signal() end_session = Signal() close_shutter = Signal() + open_shutter = Signal() def __init__(self, token: TokenData, parent=None): super().__init__(parent) @@ -167,6 +168,9 @@ class StatusBar(QStatusBar): action_1 = menu.addAction("Close shutter") action_1.triggered.connect(self.close_shutter_clicked) + action_2 = menu.addAction("Open shutter") + action_2.triggered.connect(self.open_shutter_clicked) + label_geometry = self.shutter_label.geometry() menu.move(self.mapToGlobal(label_geometry.topLeft()) - QPoint(0, menu.sizeHint().height())) menu.setFixedWidth(label_geometry.width()) @@ -209,6 +213,9 @@ class StatusBar(QStatusBar): def close_shutter_clicked(self): self.close_shutter.emit() + def open_shutter_clicked(self): + self.open_shutter.emit() + def show_change_dialog(self): dialog = PGroupDialog() if dialog.exec() == QDialog.DialogCode.Accepted: