Sample camera handling through DAQ and GUI

This commit is contained in:
leonarski_f committed 2025-05-30 12:03:30 +02:00
1 parent 1f0b4b5517
commit b871124f8f
8 files changed
+110 -6

No files matched your search

+5
View File
@@ -133,6 +133,10 @@ class SessionsStateEnum(Enum):
OwnedByElse = 2
Vacant = 3
class SampleCameraSettings(BaseModel):
gain: float
exposure: float
class BeamlineStatus(BaseModel):
energy_keV: float
dtz_mm: float
@@ -141,6 +145,7 @@ class BeamlineStatus(BaseModel):
cryojet_K: float
shutter_open: bool
flux_ph_s: float
sample_camera: SampleCameraSettings
class SessionStatus(BaseModel):
session: SessionsStateEnum = SessionsStateEnum.Vacant
+13 -4
View File
@@ -10,7 +10,7 @@ from aaredaqlib.models import (
SampleShortInfo,
PuckLoadedInfo,
SampleShortInfoList,
DAQStatusModel, BeamlineStatus, SessionStatus, )
DAQStatusModel, BeamlineStatus, SessionStatus, SampleCameraSettings, )
from aaredaqlib.raster_grid import RasterGridRequest
from aaredaqlib.rotation_scan import RotationScanRequest
from aaredaqlib.sample_geometry import SampleGeometryModel
@@ -109,6 +109,14 @@ class AareDAQ:
return None
return self.__cfg.current_sample
@property
def samcam_settings(self) -> SampleCameraSettings:
return self.__devs.samcam_settings
@samcam_settings.setter
def samcam_settings(self, s: SampleCameraSettings):
self.__devs.samcam_settings = s
def tweak_abr_meas_pos(self, c: Coordinate):
self.__cfg.set_busy(BeamlineStateEnum.SampleAlignment)
try:
@@ -287,7 +295,7 @@ class AareDAQ:
self.__devs.lamp_light.move("on", wait=True)
for s in self.__cfg.alc_zoom_settings.z:
self.__devs.sample_cam.setup(expo=s.sam_cam_exp, gain=s.sam_cam_gain)
self.__devs.samcam_settings = SampleCameraSettings(exposure=s.sam_cam_exp, gain=s.sam_cam_gain)
self.__devs.zoom = s.zoom_value
time.sleep(5.0) # Wait for settings to stabilize
@@ -462,7 +470,7 @@ class AareDAQ:
try:
i = 0
for s in self.__cfg.alc_zoom_settings.z:
self.__devs.sample_cam.setup(expo=s.sam_cam_exp, gain=s.sam_cam_gain)
self.__devs.samcam_settings = SampleCameraSettings(exposure=s.sam_cam_exp, gain=s.sam_cam_gain)
self.__devs.zoom_sync(s.zoom_value)
if i % 2 == 0:
angles = (0, 90)
@@ -686,7 +694,8 @@ class AareDAQ:
light=self.light,
cryojet_K=self.__devs.cryojet_temp,
shutter_open=self.__devs.shutter,
flux_ph_s=3.0e12
flux_ph_s=3.0e12,
sample_camera=self.__devs.samcam_settings
)
@property
+13
View File
@@ -2,6 +2,7 @@ from aaredaqlib.coordinate import Coordinate
from epics import PV
from aaredaqlib.beamline import MXBeamline
from aaredaqlib.models import SampleCameraSettings
from mxlibs3 import aerotech, smargon
from mxlibs3.area_detector import epicsAD
from mxlibs3.enum_pv import EnumPv
@@ -236,3 +237,15 @@ class BeamlineDevices:
self.__shutter.put(1)
else:
self.__shutter.put(0)
@property
def samcam_settings(self) -> SampleCameraSettings:
return SampleCameraSettings(
gain=self.sample_cam.gain.value,
exposure=self.sample_cam.expo.value
)
@samcam_settings.setter
def samcam_settings(self, settings: SampleCameraSettings):
print(settings)
self.sample_cam.setup(settings.gain, settings.exposure)
+6 -1
View File
@@ -6,7 +6,7 @@ import urllib3
import uvicorn
from aaredaqlib.coordinate import SmargonCoordinate, Coordinate
from aaredaqlib.models import SampleShortInfo, DAQStatusModel, BeamlineStateEnum, BeamlineSettingsModel, \
SampleShortInfoList, SessionStatus
SampleShortInfoList, SessionStatus, SampleCameraSettings
from aaredaqlib.raster_grid import RasterGridRequest
from aaredaqlib.rotation_scan import RotationScanRequest
from aaredaqlib.sample_geometry import SampleGeometryModel
@@ -111,6 +111,11 @@ async def clear_beam_center(token: str = Depends(oauth2_scheme)):
daq.clear_mark_beam()
return "OK"
@app.put("/beamline/samcam")
async def samcam_settings(s: SampleCameraSettings, token: str = Depends(oauth2_scheme)):
auth.check_jwt_staff(auth.parse_token(token))
daq.samcam_settings = s
return "OK"
@app.post("/shutter/close")
async def close_shutter(token: str = Depends(oauth2_scheme)):
+2
View File
@@ -113,6 +113,8 @@ class MainWindow(QMainWindow):
self.daq.update.connect(self.tell_samples.update_daq_status)
self.daq.update.connect(self.beamline.abr_tweak.update_daq_status)
self.daq.update.connect(self.status_bar.update_daq_status)
self.daq.update.connect(self.beamline.samcam.update_daq_status)
self.beamline.samcam.changed.connect(self.daq.samcam_settings)
self.beamline.state_panel.sample_exchange.clicked.connect(self.daq.sample_exchange)
self.beamline.state_panel.sample_alignment.clicked.connect(self.daq.sample_alignment)
self.beamline.state_panel.dewar_exchange.clicked.connect(self.daq.dewar_exchange)
@@ -6,6 +6,7 @@ from aaregui.panels.beamline_state_panel import BeamlineStatePanel
from aaregui.panels.illumination_panel import IlluminationPanel
from aaregui.panels.loop_centering_panel import LoopCenteringPanel
from aaregui.panels.omega_panel import OmegaPanel
from aaregui.panels.samcam_panel import SamcamPanel
from aaregui.panels.smargon_panel import SmargonPanel
from aaregui.panels.zoom_panel import ZoomPanel
@@ -38,6 +39,9 @@ class BeamlineControls(QFrame):
self.state_panel = BeamlineStatePanel(self)
self.v_layout.addWidget(self.state_panel)
self.samcam = SamcamPanel(self)
self.v_layout.addWidget(self.samcam)
self.abr_tweak = AbrTweakWidget(self)
self.beam_center = BeamCenterWidget(self)
@@ -47,3 +51,4 @@ class BeamlineControls(QFrame):
self.v_layout.addStretch()
self.setLayout(self.v_layout)
+61
View File
@@ -0,0 +1,61 @@
from PySide6.QtWidgets import QWidget, QSpinBox, QVBoxLayout, QHBoxLayout, QLabel, QDoubleSpinBox
from PySide6.QtCore import Signal, Slot
from aaredaqlib.models import SampleCameraSettings, DAQStatusModel
from aaregui.widgets.title_label import TitleLabel
class SamcamPanel(QWidget):
# Signals for when exposure or gain values change
changed = Signal(SampleCameraSettings)
old_settings = SampleCameraSettings(gain=100, exposure=0.001)
def __init__(self, parent=None):
super().__init__(parent)
# Create layout
layout = QVBoxLayout()
layout.addWidget(TitleLabel("Sample camera", self))
# Exposure control
exposure_layout = QHBoxLayout()
exposure_label = QLabel("Exposure (s):")
self.exposure_spinbox = QDoubleSpinBox()
self.exposure_spinbox.setRange(0, 1.0) # Adjust range as needed
self.exposure_spinbox.setSingleStep(0.001)
self.exposure_spinbox.setStyleSheet("QDoubleSpinBox { background-color: white; }")
self.exposure_spinbox.setDecimals(3)
self.exposure_spinbox.editingFinished.connect(self.__changed)
exposure_layout.addWidget(exposure_label)
exposure_layout.addWidget(self.exposure_spinbox)
# Gain control
gain_layout = QHBoxLayout()
gain_label = QLabel("Gain:")
self.gain_spinbox = QDoubleSpinBox()
self.gain_spinbox.setRange(0, 1000) # Adjust range as needed
self.gain_spinbox.setSingleStep(1)
self.gain_spinbox.setDecimals(1)
self.gain_spinbox.setStyleSheet("QDoubleSpinBox { background-color: white; }")
self.gain_spinbox.editingFinished.connect(self.__changed)
gain_layout.addWidget(gain_label)
gain_layout.addWidget(self.gain_spinbox)
# Add controls to main layout
layout.addLayout(exposure_layout)
layout.addLayout(gain_layout)
self.setLayout(layout)
def __changed(self):
self.changed.emit(SampleCameraSettings(gain=self.gain_spinbox.value(),
exposure=self.exposure_spinbox.value()))
@Slot(DAQStatusModel)
def update_daq_status(self, s: DAQStatusModel):
pass
if self.old_settings != s.bl.sample_camera:
self.gain_spinbox.setValue(s.bl.sample_camera.gain)
self.exposure_spinbox.setValue(s.bl.sample_camera.exposure)
self.old_settings = s.bl.sample_camera
+5 -1
View File
@@ -1,7 +1,7 @@
from PySide6.QtCore import Signal, QUrl, Slot, QTimer, QObject, QByteArray
from PySide6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
from aaredaqlib.models import DAQStatusModel, SampleShortInfoList, SampleShortInfo
from aaredaqlib.models import DAQStatusModel, SampleShortInfoList, SampleShortInfo, SampleCameraSettings
from aaredaqlib.coordinate import SmargonCoordinate, Coordinate
from aaredaqlib.raster_grid import RasterGridRequest
from aaredaqlib.rotation_scan import RotationScanRequest
@@ -153,6 +153,10 @@ class DAQWorker(QObject):
else:
self.generic_put(f"access/pgroup?val={val}")
@Slot(SampleCameraSettings)
def samcam_settings(self, s: SampleCameraSettings):
self.generic_put("beamline/samcam", s.model_dump_json())
@Slot(SmargonCoordinate)
def move_smargon(self, coord: SmargonCoordinate):
self.generic_put("beamline/smargon", coord.model_dump_json())