From 33b242eca6052a77533d6292e49eb7598de5211a Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Wed, 25 Jun 2025 12:25:06 +0200 Subject: [PATCH] DAQ: Add beam location --- common/src/aaredaqlib/models.py | 6 ++ daq/src/aaredaq/daq.py | 2 +- daq/src/aaredaq/devices.py | 81 +++++++++++++++++++++++---- daq/src/aaredaq/server.py | 6 +- daq/src/aaredaq/workflows.py | 30 ++++++++-- gui/src/aaregui/main_window.py | 2 + gui/src/aaregui/threads/daq_worker.py | 4 ++ gui/src/aaregui/widgets/status_bar.py | 5 ++ 8 files changed, 118 insertions(+), 18 deletions(-) diff --git a/common/src/aaredaqlib/models.py b/common/src/aaredaqlib/models.py index 685b5c92..45f2f907 100644 --- a/common/src/aaredaqlib/models.py +++ b/common/src/aaredaqlib/models.py @@ -8,6 +8,12 @@ from aaredaqlib.coordinate import Coordinate from aaredaqlib.diffraction_geometry import DiffractionGeometry from aaredaqlib.sample_geometry import SampleGeometryModel +class StagePositionEnum(Enum): + MEASURE = 0 + PARK = 1 + DOWN = 2 + UNKNOWN = 3 + class TokenData(BaseModel): sub: str # Username pgroups: List[str] diff --git a/daq/src/aaredaq/daq.py b/daq/src/aaredaq/daq.py index e2869127..2638e53d 100644 --- a/daq/src/aaredaq/daq.py +++ b/daq/src/aaredaq/daq.py @@ -732,7 +732,7 @@ class AareDAQ: case BeamlineStateEnum.BeamLocation: if target == BeamlineStateEnum.SampleAlignment: workflows.bl2sa(self.__devs, self.__cfg) - if target == BeamlineStateEnum.SampleExchange: + elif target == BeamlineStateEnum.SampleExchange: workflows.bl2sa(self.__devs, self.__cfg) workflows.sa2se(self.__devs, self.__cfg) else: diff --git a/daq/src/aaredaq/devices.py b/daq/src/aaredaq/devices.py index a2672273..b4e868b3 100644 --- a/daq/src/aaredaq/devices.py +++ b/daq/src/aaredaq/devices.py @@ -2,7 +2,7 @@ from epics import PV from aaredaqlib.beamline import MXBeamline from aaredaqlib.coordinate import Coordinate -from aaredaqlib.models import SampleCameraSettings +from aaredaqlib.models import SampleCameraSettings, StagePositionEnum from mxlibs3 import aerotech, smargon from mxlibs3.area_detector import epicsAD from mxlibs3.enum_pv import EnumPv @@ -46,8 +46,6 @@ class BeamlineDevices: self.bsx = MyMotor(f"{BEAMLINE}-ES-BS:TRX1") self.bsy = MyMotor(f"{BEAMLINE}-ES-BS:TRY1") - self.__collimator = PV(f"{BEAMLINE}-ES-COL:TRY1") - self.__bpm = PV(f"{BEAMLINE}-OP-XBPM1:SumAll:MeanValue_RBV") self.aerotech = aerotech.Abr(beamline) @@ -161,6 +159,32 @@ class BeamlineDevices: } ) + self.__collimator = EnumPv( + { + "name": "Collimator", + "pv": f"{BEAMLINE}-ES-COL:SET-POS", + "readback": f"{BEAMLINE}-ES-COL:GET-POS", + "states": { + "parking": "parking", + "measure": "measure", + "down": "down", + }, + } + ) + + self.__scinti = EnumPv( + { + "name": "Scintillator", + "pv": f"{BEAMLINE}-ES-SCL:SET-POS", + "readback": f"{BEAMLINE}-ES-SCL:GET-POS", + "states": { + "parking": "parking", + "measure": "measure", + "down": "down", + }, + } + ) + self.sample_cam = epicsAD(f"{BEAMLINE}-SAMCAM:") @property @@ -177,15 +201,50 @@ class BeamlineDevices: self.__zoom.move(value, wait=True) @property - def collimator_up(self) -> bool: - return bool(abs(self.__collimator.value - 92.979) < 0.01) - - @collimator_up.setter - def collimator_up(self, value: bool): - if value: - self.__collimator.put(92.979, wait=True) + def collimator(self) -> StagePositionEnum: + if self.__collimator.position_is("down"): + return StagePositionEnum.DOWN + elif self.__collimator.position_is("measure"): + return StagePositionEnum.MEASURE + elif self.__collimator.position_is("parking"): + return StagePositionEnum.PARK else: - self.__collimator.put(52.979, wait=True) + return StagePositionEnum.UNKNOWN + + @collimator.setter + def collimator(self, value: StagePositionEnum): + self.set_collimator(value, wait=True) + + def set_collimator(self, value: StagePositionEnum, /, wait: bool = True): + if value == StagePositionEnum.DOWN: + self.__collimator.move("down", wait=wait) + elif value == StagePositionEnum.MEASURE: + self.__collimator.move("measure", wait=wait) + elif value == StagePositionEnum.PARK: + self.__collimator.move("parking", wait=wait) + + @property + def scintillator(self) -> StagePositionEnum: + if self.__scinti.position_is("down"): + return StagePositionEnum.DOWN + elif self.__scinti.position_is("measure"): + return StagePositionEnum.MEASURE + elif self.__scinti.position_is("parking"): + return StagePositionEnum.PARK + else: + return StagePositionEnum.UNKNOWN + + @scintillator.setter + def scintillator(self, value: StagePositionEnum): + self.set_scintillator(value, wait=True) + + def set_scintillator(self, value: StagePositionEnum, /, wait: bool = True): + if value == StagePositionEnum.DOWN: + self.__scinti.move("down", wait=wait) + elif value == StagePositionEnum.MEASURE: + self.__scinti.move("measure", wait=wait) + elif value == StagePositionEnum.PARK: + self.__scinti.move("parking", wait=wait) @property def reflector_up(self) -> bool: diff --git a/daq/src/aaredaq/server.py b/daq/src/aaredaq/server.py index 6e9eeb9c..c9d4f1b1 100644 --- a/daq/src/aaredaq/server.py +++ b/daq/src/aaredaq/server.py @@ -6,7 +6,7 @@ import urllib3 import uvicorn from aaredaqlib.coordinate import SmargonCoordinate, Coordinate from aaredaqlib.models import SampleShortInfo, DAQStatusModel, BeamlineStateEnum, BeamlineSettingsModel, \ - SampleShortInfoList, SessionStatus, SampleCameraSettings, AutofocusSettings + SampleShortInfoList, SessionStatus, SampleCameraSettings, AutofocusSettings, TokenData from aaredaqlib.raster_grid import RasterGridRequest, CompletedRasterGrid from aaredaqlib.rotation_scan import RotationScanRequest from aaredaqlib.sample_geometry import SampleGeometryModel @@ -239,6 +239,10 @@ async def sample_alignment(token: str = Depends(oauth2_scheme)): auth.check_jwt_rw(cfg, auth.parse_token(token)) daq.state = BeamlineStateEnum.SampleAlignment +@app.post("/state/beam_location") +async def beam_location(token: str = Depends(oauth2_scheme)): + auth.check_jwt_staff(auth.parse_token(token)) + daq.state = BeamlineStateEnum.BeamLocation # Scans @app.post("/scan/raster") diff --git a/daq/src/aaredaq/workflows.py b/daq/src/aaredaq/workflows.py index f614e884..de3b6d6f 100644 --- a/daq/src/aaredaq/workflows.py +++ b/daq/src/aaredaq/workflows.py @@ -6,6 +6,7 @@ from aaredaq.config import ABR_POS_MOUNT, ABR_OMEGA_MOUNT from aaredaq.devices import BeamlineDevices from aaredaq.config import BeamlineConfig from aaredaqlib.coordinate import Coordinate +from aaredaqlib.models import StagePositionEnum, SampleCameraSettings from mxlibs3.mx_lib import pv_wait @@ -61,6 +62,9 @@ def m2se(devs: BeamlineDevices, cfg: BeamlineConfig): print("executing MAINTENANCE -> sample exchange") hub = cfg.settings + devs.collimator = StagePositionEnum.PARK + devs.scintillator = StagePositionEnum.DOWN + _dtzpark = hub.dtz_park _cryopark = hub.cryojet_park_position _cryo = hub.cryojet_in_use @@ -251,16 +255,32 @@ def ba2sa(devs: BeamlineDevices, cfg: BeamlineConfig): def sa2bl(devs: BeamlineDevices, cfg: BeamlineConfig): - devs.cryo.move(20) - devs.abr_pos = cfg.abr_meas_pos + Coordinate(x=1) - devs.beamstop_stage_up = True - devs.reflector_up = True + devs.zoom = 1000 + devs.samcam_settings = SampleCameraSettings(exposure=0.02, gain=100) + devs.lamp_light = 2.5 + devs.abr_pos = cfg.abr_meas_pos + Coordinate(x=-10) + devs.cryo.move(20) + devs.set_scintillator(StagePositionEnum.MEASURE, wait=False) + devs.set_collimator(StagePositionEnum.MEASURE, wait=False) + devs.beamstop_stage_up = True + devs.reflector_up = False + devs.scintillator = StagePositionEnum.MEASURE + devs.collimator = StagePositionEnum.MEASURE def bl2sa(devs: BeamlineDevices, cfg: BeamlineConfig): hub = cfg.settings - move_bsz(devs, hub.bsz) + + devs.set_scintillator(StagePositionEnum.DOWN, wait=False) + devs.set_collimator(StagePositionEnum.PARK, wait=False) + devs.reflector_up = True + devs.scintillator = StagePositionEnum.DOWN + devs.collimator = StagePositionEnum.PARK + + if hub.cryojet_in_use: + devs.cryo.move(hub.cryojet_measurement_position) + devs.abr_pos = cfg.abr_meas_pos diff --git a/gui/src/aaregui/main_window.py b/gui/src/aaregui/main_window.py index 8ec90c2b..1cdcb1d0 100644 --- a/gui/src/aaregui/main_window.py +++ b/gui/src/aaregui/main_window.py @@ -203,6 +203,8 @@ class MainWindow(QMainWindow): self.status_bar.dewar_exchange.connect(self.daq.dewar_exchange) self.status_bar.sample_exchange.connect(self.daq.sample_exchange) self.status_bar.sample_alignment.connect(self.daq.sample_alignment) + self.status_bar.beam_location.connect(self.daq.beam_location) + self.status_bar.close_shutter.connect(self.daq.close_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 b0f0ab9d..ec39a56c 100644 --- a/gui/src/aaregui/threads/daq_worker.py +++ b/gui/src/aaregui/threads/daq_worker.py @@ -168,6 +168,10 @@ class DAQWorker(QObject): def sample_alignment(self): self.generic_post("state/sample_alignment") + @Slot() + def beam_location(self): + self.generic_post("state/beam_location") + @Slot(str) def set_pgroup(self, val: str): if val == "": diff --git a/gui/src/aaregui/widgets/status_bar.py b/gui/src/aaregui/widgets/status_bar.py index 8776b9b6..f155dab8 100644 --- a/gui/src/aaregui/widgets/status_bar.py +++ b/gui/src/aaregui/widgets/status_bar.py @@ -12,6 +12,7 @@ class StatusBar(QStatusBar): dewar_exchange = Signal() sample_alignment = Signal() sample_exchange = Signal() + beam_location = Signal() force_session = Signal() end_session = Signal() @@ -104,6 +105,8 @@ class StatusBar(QStatusBar): state = "Maintenance" elif state == BeamlineStateEnum.Moving: state = "Moving" + elif state == BeamlineStateEnum.BeamLocation: + state = "Beam location" elif state == BeamlineStateEnum.RobotSampleExchange: state = "Robot sample exchange" else: @@ -179,6 +182,8 @@ class StatusBar(QStatusBar): action_1.triggered.connect(self.sa) action_3 = menu.addAction("Dewar load/unload") action_3.triggered.connect(self.dl) + action_4 = menu.addAction("Beam location") + action_4.triggered.connect(self.beam_location) label_geometry = self.state_label.geometry() menu.move(self.mapToGlobal(label_geometry.topLeft()) - QPoint(0, menu.sizeHint().height()))