diff --git a/common/src/aaredaqlib/models.py b/common/src/aaredaqlib/models.py index b31b6f7f..acbe2ec2 100644 --- a/common/src/aaredaqlib/models.py +++ b/common/src/aaredaqlib/models.py @@ -108,8 +108,7 @@ class LoopCenteringZoomModelElem(BaseModel): class LoopCenteringZoomModel(BaseModel): - z: List[LoopCenteringZoomModelElem] - + z: List[LoopCenteringZoomModelElem] # zoom gain exp (X06DA) # 1 50 0.05 @@ -124,7 +123,7 @@ def def_loop_centering_zoom() -> LoopCenteringZoomModel: return LoopCenteringZoomModel( z=[ LoopCenteringZoomModelElem( - zoom_value=280, sam_cam_gain=50.0, sam_cam_exp=0.10 + zoom_value=280, sam_cam_gain=100.0, sam_cam_exp=0.05 ) ] ) @@ -152,6 +151,60 @@ class SampleCameraSettings(BaseModel): gain: float exposure: float + +class ZoomModel(BaseModel): + z:dict[float, SampleCameraSettings] + + def get_camera_settings(self, zoom_value: float) -> SampleCameraSettings | tuple[float, float]: + if not self.z: + raise ValueError("No zoom data available") + + if zoom_value in self.z: + elem = self.z[zoom_value] + return SampleCameraSettings(gain=elem.gain, exposure=elem.exposure) + + sorted_zooms = sorted(self.z.keys()) + + if zoom_value <= sorted_zooms[0]: + elem = self.z[sorted_zooms[0]] + return SampleCameraSettings(gain=elem.gain, exposure=elem.exposure) + + if zoom_value >= sorted_zooms[-1]: + elem = self.z[sorted_zooms[-1]] + return SampleCameraSettings(gain=elem.gain, exposure=elem.exposure) + + for i in range(len(sorted_zooms) - 1): + if sorted_zooms[i] <= zoom_value <= sorted_zooms[i + 1]: + lower_zoom = sorted_zooms[i] + upper_zoom = sorted_zooms[i + 1] + + lower_elem = self.z[lower_zoom] + upper_elem = self.z[upper_zoom] + + t = (zoom_value - lower_zoom) / (upper_zoom - lower_zoom) + + interpolated_gain = lower_elem.gain + t * (upper_elem.gain - lower_elem.gain) + interpolated_exp = lower_elem.exposure + t * (upper_elem.exposure - lower_elem.exposure) + + return SampleCameraSettings(gain=interpolated_gain, exposure=interpolated_exp) + + closest = min(self.z.keys(), key=lambda x: abs(x - zoom_value)) + elem = self.z[closest] + return SampleCameraSettings(gain=elem.gain, exposure=elem.exposure) + +def def_zoom() -> ZoomModel: + return ZoomModel( + z={ + 1: SampleCameraSettings(gain=50.0, exposure=0.05), + 280: SampleCameraSettings(gain=100.0, exposure=0.05), + 500: SampleCameraSettings(gain=100.0, exposure=0.05), + 700: SampleCameraSettings(gain=150.0, exposure=0.05), + 800: SampleCameraSettings(gain=100.0, exposure=0.10), + 1000: SampleCameraSettings(gain=200.0, exposure=0.10) + } + ) + + class AutofocusSettings(BaseModel): center_x_pxl: float center_y_pxl: float diff --git a/daq/src/aaredaq/config.py b/daq/src/aaredaq/config.py index 5388a4ba..81c7ca2b 100644 --- a/daq/src/aaredaq/config.py +++ b/daq/src/aaredaq/config.py @@ -14,7 +14,7 @@ from aaredaqlib.models import ( def_loop_centering_zoom, SampleShortInfo, SessionStatus, - BeamlineStateEnum, SessionsStateEnum, SampleShortInfoList, CryojetSettingsModel, + BeamlineStateEnum, SessionsStateEnum, SampleShortInfoList, CryojetSettingsModel, ZoomModel, def_zoom, ) from aaredaqlib.beamline import MXBeamline @@ -352,6 +352,18 @@ class BeamlineConfig: def alc_zoom_settings(self, data: LoopCenteringZoomModel): self.__client.set(f"{self.__bl}:alc_zoom_settings", data.model_dump_json()) + @property + def zoom_settings(self) -> ZoomModel: + tmp = self.__client.get(f"{self.__bl}:zoom_settings") + if tmp is None: + return def_zoom() + data_dict = json.loads(tmp) + return ZoomModel(**data_dict) + + @zoom_settings.setter + def zoom_settings(self, data: ZoomModel): + self.__client.set(f"{self.__bl}:zoom_settings", data.model_dump_json()) + @property def abr_meas_pos(self) -> Coordinate: tmp = self.__client.get(f"{self.__bl}:abr_meas_pos") diff --git a/daq/src/aaredaq/daq.py b/daq/src/aaredaq/daq.py index 8a87bbbd..e2e16fe7 100644 --- a/daq/src/aaredaq/daq.py +++ b/daq/src/aaredaq/daq.py @@ -97,6 +97,8 @@ class AareDAQ: def zoom(self, val: float): self.__saved_box = None self.__devs.zoom = val + self.samcam_settings = self.__cfg.zoom_settings.get_camera_settings(val) + #elf.__cfg.state_busy = False @property def light(self) -> float: @@ -226,7 +228,7 @@ class AareDAQ: self.__cfg.current_sample = None else: # reset zoom - self.__devs.zoom = 280 + self.zoom = 280 # mount sample self.__aare.sample_unmounted(curr_sample) self.__devs.tell.mount( @@ -414,7 +416,7 @@ class AareDAQ: for s in self.__cfg.alc_zoom_settings.z: self.__devs.samcam_settings = SampleCameraSettings(exposure=s.sam_cam_exp, gain=s.sam_cam_gain) - self.__devs.zoom = s.zoom_value + self.zoom = s.zoom_value time.sleep(5.0) # Wait for settings to stabilize image = self.__devs.sample_cam.get_image(gray=False)