From b975b16b2b27ee742e10456aa65d1a9cfdf8053a Mon Sep 17 00:00:00 2001 From: appleb_m Date: Thu, 26 Feb 2026 17:20:02 +0100 Subject: [PATCH] DAQ: further rework, WIP --- src/aare/daq/daq.py | 206 ++++++++++++++++++-------------------------- 1 file changed, 84 insertions(+), 122 deletions(-) diff --git a/src/aare/daq/daq.py b/src/aare/daq/daq.py index 8a806337..e6752483 100644 --- a/src/aare/daq/daq.py +++ b/src/aare/daq/daq.py @@ -1,6 +1,7 @@ import secrets import time +import traceback from datetime import datetime from math import ceil @@ -46,61 +47,6 @@ from aare.common.exception_handler import ( logger = setup_logger("aareDAQ") -class TransformationInvalidException(Exception): - def __init__(self, message="Transformation is not implemented"): - super().__init__(message) - self.message = message - logger.error(f"{message}", extra={"exception:" : Exception}) - - def __str__(self): - return self.message - - -class LoopCenteringFailed(Exception): - def __init__(self, message="Loop Centering did not detect a sample"): - super().__init__(message) - self.message = message - logger.error(f"{message}", extra={"exception:" : Exception}) - - def __str__(self): - return self.message - -class MountingFailed(Exception): - def __init__(self, message="A sample was not mounted"): - super().__init__(message) - self.message = message - logger.error(f"{message}", extra={"exception:" : Exception}) - - def __str__(self): - return self.message - -class WarningTellException(Exception): - def __init__(self, message="Warning error in TELL"): - super().__init__(message) - self.message = message - logger.error(f"{message}", extra={"exception:": Exception}) - - def __str__(self): - return self.message - -class CriticalTellException(Exception): - def __init__(self, message="Critical error in TELL"): - super().__init__(message) - self.message = message - logger.error(f"{message}", extra={"exception:": Exception}) - - def __str__(self): - return self.message - -class AXCFailed(Exception): - def __init__(self, message="Auto X-ray centering failed"): - super().__init__(message) - self.message = message - logger.error(f"{message}", extra={"exception:": Exception}) - - def __str__(self): - return self.message - class AareDAQ: MIN_SPOTS_LOW_RES_THRESHOLD = 10.0 @@ -109,7 +55,7 @@ class AareDAQ: self.last_time = 0.0 self.__cfg = cfg self.__devs = BeamlineDevices(bl) - self.__mlbox = MlBox() + self.__mlbox = MlBox(bl) self.__jfjoch = JFJochWrapper(bl) self.__bl = bl.value.upper() self.__aare = AareWrapper(bl) @@ -278,9 +224,12 @@ class AareDAQ: @property def sample(self) -> SampleShortInfo | None: + #TODO figure out why this works and what it should be if self.__cfg.current_sample is not None and self.__cfg.current_sample.location is None: return self.__cfg.current_sample - return None + if self.__devs.tell.get_mounted_sample() is None: + return None + return self.__cfg.current_sample @property def samcam_settings(self) -> SampleCameraSettings: @@ -304,18 +253,14 @@ class AareDAQ: def save_abr_meas_pos(self): self.__cfg.set_busy(BeamlineStateEnum.SampleAlignment) - print('Set busy in save_abr_meas_pos') try: - print('Set abr measure pos in save_abr_meas_pos') self.__cfg.abr_meas_pos = self.__devs.aerotech_pos - print('busy should be set to false now') self.__cfg.state_busy = False except: self.__cfg.state_busy = False raise def goto_abr_meas_pos(self): - print('why are we here') self.__cfg.set_busy(BeamlineStateEnum.SampleAlignment) try: self.__devs.aerotech_pos = self.__cfg.abr_meas_pos @@ -350,8 +295,8 @@ class AareDAQ: self.__devs.aerotech_omega = ABR_OMEGA_MOUNT #collimator should be down!!! self.__devs.tell.check_enable_motion() - self.__devs.tell.wait_mount_complete() - #self.__devs.tell.set_in_mount_position(True) + self.__devs.tell.wait_not_busy() + self.__devs.tell.set_in_mount_position(True) if target is None: self.__devs.tell.unmount(wait=True, timeout=60.0) else: @@ -375,13 +320,18 @@ class AareDAQ: logger.debug(target) self.__mount(target) logger.info(f"Sample mounted: {target}") - self.__aare.sample_mounted(target) except Exception as e: self.__cfg.state_busy = False logger.debug(f"Failed to mount sample: {e}") + self.__aare.sample_failed(target, f"Mount failed due to {e}") raise e workflows.rse2sa(devs=self.__devs, cfg=self.__cfg) self.__cfg.state_busy = False + if target is not None: + if target.db_id is not None: + self.__aare.sample_mounted(target) + self.save_screenshot_db(target.db_id, "mounted") + @property def camera_image(self) -> np.ndarray | None: @@ -1011,21 +961,21 @@ class AareDAQ: zoom_settings = self.__cfg.zoom_settings.z for zoom_iter, zoom_value in enumerate(zoom_settings): - exposure = zoom_settings[zoom_value].exposure - gain = zoom_settings[zoom_value].gain + #exposure = zoom_settings[zoom_value].exposure + #gain = zoom_settings[zoom_value].gain max_attempt = 2 attempt = 0 base_angles = (0, 45, 90) if (zoom_iter % 2 == 0) else (90, 45, 0) if sample_id is not None: + logger.info(f"submitting to db loop center sequence for sample {sample_id}, zoom={zoom_value}") self.save_screenshot_db(sample_id, f"pre_alc") while attempt < max_attempt: - self.__devs.samcam_settings = SampleCameraSettings(exposure=exposure, gain=gain) - exp = int(exposure * 1000) - gn = int(gain) - self.__devs.set_zoom(zoom_value, wait=True) - logger.debug(f'zoom={zoom_value},gain={gn}, exp={exp}ms') + #self.__devs.samcam_settings = SampleCameraSettings(exposure=exposure, gain=gain) + #exp = int(exposure * 1000) + #gn = int(gain) + self.zoom = zoom_value found_flag = False found_angle: int | None = None @@ -1037,7 +987,7 @@ class AareDAQ: self.__devs.aerotech_omega = angle logger.info(f"time to move: {time.perf_counter()-time_to_move_aerotech}") - filename = f"{sample_id}_{angle}_{zoom_value:.0f}_{exp}_{gn}" if sample_id is not None else None + filename = f"{sample_id}_{angle}_{zoom_value:.0f}" if sample_id is not None else None try: target, cls, classes = self.__ml_loop_centre_box(sample_id, filename) @@ -1064,6 +1014,8 @@ class AareDAQ: self.__devs.smargon_pos = target self.__devs.smargon_wait(60) logger.info(f"time to move smargon: {time.perf_counter() - time_to_move_smargon}") + if sample_id is not None: + self.save_screenshot_db(sample_id, f"{sample_id}_{angle}_{zoom_value:.0f}") if targets_found_this_attempt == 0: logger.error(f"No targets found in this attempt {attempt}") @@ -1087,6 +1039,7 @@ class AareDAQ: logger.debug("alc success") self.__aare.sample_centered(self.__cfg.current_sample) if sample_id is not None: + logger.info(f"sample {sample_id} centered") self.save_screenshot_db(sample_id, f"{sample_id}_centered") return True @@ -1111,25 +1064,29 @@ class AareDAQ: f"Loop_face: {found_classes_count.get(3,0)}, " f"Loop_all: {found_classes_count.get(0,0)}, " f"Pin: {found_classes_count.get(1,0)}") - logger.info(f"Error in loop centering: {e}") + logger.error(traceback.format_exc()) + + logger.error(f"Error in loop centering: {e}") return False def auto_loop_center(self, sample_id: int | None = None) -> float: start = time.perf_counter() try: self.__cfg.try_set_busy(timeout=360) + if sample_id is None: + sample_id = self.__cfg.current_sample.db_id if not self.__loop_center_sequence(sample_id): raise LoopCenteringFailed self.__cfg.state_busy = False except Exception: self.__cfg.zoom_mode = ZoomModeEnum.User - self.__devs.samcam_settings = self.__cfg.zoom_settings.get_camera_settings(self.zoom) + #self.__devs.samcam_settings = self.__cfg.zoom_settings.get_camera_settings(self.zoom) self.__cfg.state_busy = False raise self.__cfg.zoom_mode = ZoomModeEnum.User - self.__devs.samcam_settings = self.__cfg.zoom_settings.get_camera_settings(self.zoom) + #self.__devs.samcam_settings = self.__cfg.zoom_settings.get_camera_settings(self.zoom) end = time.perf_counter() return end - start @@ -1252,7 +1209,12 @@ class AareDAQ: start_mount=time.perf_counter() logger.info(f"starting mount {sample.db_id} at {time.ctime()}") self.__mount(sample) + if sample.db_id is not None: + self.__aare.sample_mounted(sample) + self.save_screenshot_db(sample.db_id, "mounted") logger.info(f"mounting done at {time.perf_counter() - start_mount}, total time: {time.perf_counter() - start}") + #self.__devs.smargon_pos + #self.__devs.aerotech_pos = alc_time = time.perf_counter() - start logger.info(f"starting alc at {alc_time}") if not self.__loop_center_sequence(sample.db_id): @@ -1265,46 +1227,46 @@ class AareDAQ: logger.info(f"alc done at {time.perf_counter() - start}") self.__face_detection_sequence() logger.info(f"face_detection done at {time.perf_counter() - start}") - self.zoom = 500 + #self.zoom = 500 hex_string = secrets.token_hex(3) # 3 bytes = 6 hex characters print(hex_string.upper()) - raster_params = self.get_auto_raster_params() - if self.__auto_center(RasterGridRequest( - exp_time_s=raster_params.exp_time_s, - file_prefix=sample_prefix + f"_{hex_string}", - smargon_top_left= SmargonCoordinate(), - n_x=1, - n_y=1, - dtz=raster_params.dtz, - grid_size_mm=Coordinate(x=geom.beam_size_mm.x * 0.5, y=geom.beam_size_mm.y * 0.5), - omega_deg=self.omega, - transmission = raster_params.transmission, - )): - logger.info(f"raster scans done at {time.perf_counter() - start}") - params, source = self.get_collection_params(prefer_smart=False) - logger.info(f"Using {source} for data collection: {params}") - - self.__cfg.zoom_mode = ZoomModeEnum.User - self.__devs.samcam_settings = self.__cfg.zoom_settings.get_camera_settings(self.zoom) - self.__devs.dtz = params.dtz - if self.omega + 180 < 720: - start_omega = self.omega - else: - start_omega = params.start_omega_deg - self.__rotation( RotationScanRequest(start_omega_deg=start_omega, - dtz=params.dtz, - file_prefix="data/" + sample_prefix + f"_{hex_string}", - exp_time_s=params.exp_time_s, - incr_omega_deg=params.incr_omega_deg, - steps=params.steps, - transmission=params.transmission, - )) - logger.info(f"rotation done at {time.perf_counter() - start}") - else: - logger.error("auto center failed") - self.__aare.axc_failed(sample) + # raster_params = self.get_auto_raster_params() + # if self.__auto_center(RasterGridRequest( + # exp_time_s=raster_params.exp_time_s, + # file_prefix=sample_prefix + f"_{hex_string}", + # smargon_top_left= SmargonCoordinate(), + # n_x=1, + # n_y=1, + # dtz=raster_params.dtz, + # grid_size_mm=Coordinate(x=geom.beam_size_mm.x * 0.5, y=geom.beam_size_mm.y * 0.5), + # omega_deg=self.omega, + # transmission = raster_params.transmission, + # )): + # logger.info(f"raster scans done at {time.perf_counter() - start}") + # params, source = self.get_collection_params(prefer_smart=False) + # logger.info(f"Using {source} for data collection: {params}") + # + # self.__cfg.zoom_mode = ZoomModeEnum.User + # self.__devs.samcam_settings = self.__cfg.zoom_settings.get_camera_settings(self.zoom) + # self.__devs.dtz = params.dtz + # if self.omega + 180 < 720: + # start_omega = self.omega + # else: + # start_omega = params.start_omega_deg + # # self.__rotation( RotationScanRequest(start_omega_deg=start_omega, + # # dtz=params.dtz, + # # file_prefix="data/" + sample_prefix + f"_{hex_string}", + # # exp_time_s=params.exp_time_s, + # # incr_omega_deg=params.incr_omega_deg, + # # steps=params.steps, + # # transmission=params.transmission, + # # )) + # logger.info(f"rotation done at {time.perf_counter() - start}") + # else: + # logger.error("auto center failed") + # self.__aare.axc_failed(sample) self.zoom = 1 self.__cfg.zoom_mode = ZoomModeEnum.User self.__devs.samcam_settings = self.__cfg.zoom_settings.get_camera_settings(self.zoom) @@ -1324,17 +1286,17 @@ class AareDAQ: return end - start def __set_state(self, target: BeamlineStateEnum): - # __set_state assumes that beamline is already in busy state - # it will apply a proper transformation and change state afterward - # specifically: - # 1. If target state is maintenance, just go there - # 2. If target state is same as current, nothing will happen - # 3. If target state cannot be reached, exception is raised and current state is kept - # 4. If exception is raised during transformation, state is set to maintenance - # 5. If transformation goes OK, target state is set - # - # Busy state will be cleared only, if exception is raised. - # + """__set_state assumes that beamline is already in busy state + it will apply a proper transformation and change state afterward + specifically: + 1. If target state is maintenance, just go there + 2. If target state is same as current, nothing will happen + 3. If target state cannot be reached, exception is raised and current state is kept + 4. If exception is raised during transformation, state is set to maintenance + 5. If transformation goes OK, target state is set + + Busy state will be cleared only, if exception is raised. """ + curr_state = self.__cfg.state if not self.__cfg.state_busy: