diff --git a/src/aare/daq/daq.py b/src/aare/daq/daq.py index a109c82f..a5c76498 100644 --- a/src/aare/daq/daq.py +++ b/src/aare/daq/daq.py @@ -1,34 +1,32 @@ -import copy + import secrets import time -from copy import deepcopy + from datetime import datetime from math import ceil from typing import List, Tuple, Optional import cv2 import numpy as np -import redis + import aare.common.face_detection as fd from aare.daq import workflows from aare.daq.aaredb import AareWrapper -from aare.daq.autofocus import calculate_focus_measure -from aare.daq.config import BeamlineConfig, aerotech_pos_MOUNT + +from aare.daq.config import BeamlineConfig from aare.daq.config import BeamlineStateEnum from aare.daq.devices import BeamlineDevices from aare.daq.mlbox import MlBox from aare.common.beamline import MXBeamline from aare.common.coordinate import Coordinate, SmargonCoordinate from aare.common.diffraction_geometry import DiffractionGeometry -from aare.common.find_xtal import raster_centre_of_mass, create_quality_filtered_array, identify_crystal_raster, \ - get_result_list_from_com, get_best_b_factor, get_best_res, get_xtal_size from aare.common.logger_config import setup_logger from aare.common.models import ( SampleShortInfo, PuckLoadedInfo, SampleShortInfoList, - DAQStatusModel, BeamlineStatus, SessionStatus, SampleCameraSettings, AutofocusSettings, ZoomModeEnum, CrystalSize, + DAQStatusModel, BeamlineStatus, SessionStatus, SampleCameraSettings, ZoomModeEnum, SimpleScanParameters, MLBoxModel, FluorescenceSpectrumParameterModel, FluorescenceSpectrumOutputModel) from aare.common.raster_grid import RasterGridRequest, CompletedRasterGrid, CompletedRasterGridElem @@ -318,83 +316,14 @@ class AareDAQ: raise def __mount_failure_handler(self, mount_error): - failed = self.__cfg.increment_failed_mount_count() - if failed >=4: - #TODO move park does not dry, need to change this!!! - self.__devs.tell.dry(wait=False, wait_cold=-1) - raise CriticalTellException(f"Repeated drying failure, moved to park" - f"\nThere either really is no sample or " - f"a critical failure.\nPlease check the dewar and if a sample, " - f"please contact the MX team") - elif failed >=3: - self.__devs.tell.dry(wait=False, wait_cold=-1) - raise WarningTellException(f"Continued to not find a sample, drying robot in park for 10 minutes. " - f"\n Please get a cup of coffee.\nAfter the robot has dried, " - f"check the sample positions that have been missed, if no samples continue!" - f"\nOtherwise there may be a critical error so please let your local " - f"contact for support") - elif failed == 2: - self.__devs.tell.dry(wait=False) - raise MountingFailed(f"Drying gripper: repeated error: {mount_error}") - else: - raise MountingFailed(f"{mount_error}") + pass def __mount(self, target: SampleShortInfo | None): pass @sample.setter def sample(self, target: SampleShortInfo | None): - # This will set internally state to SampleExchange, but will return to SampleAlignment - # before exiting - - self.__cfg.try_set_busy(timeout=360) - - try: - curr_sample = self.__cfg.current_sample - curr_sample_is_manual = False - logger.info(f"current sample: {curr_sample}") - logger.info(f"new target is: {target}") - self.__cfg.crystal_size = CrystalSize(x=0, y=0, z=0) - self.__cfg.last_best_b_factor = None - self.__cfg.last_best_res = None - self.__cfg.xrf = None - - if curr_sample is not None and curr_sample.location is None: - self.__cfg.current_sample = None - curr_sample_is_manual = True - - if target is not None or not curr_sample_is_manual: - self.__mount(target) - if target is not None and target.db_id is not None: - #self.__aare.sample_mounted(self.__cfg.current_sample) - logger.info(f"post_mount_{target.db_id}_{self.__devs.zoom}") - self.save_screenshot_db(target.db_id , f"post_mount_{target.db_id }_{self.__devs.zoom}") - except Exception as e: - self.__cfg.state_busy = False - # If unmount succeeded, but mount failed - mounted_sample = self.__devs.tell.get_mounted_sample() - #TODO check the following error logic - # if target is not None: - # print(f"TELL: Error mounting, TELL believes current sample is {mounted_sample}, while expected {target.location}") - if mounted_sample is None: - logger.error("TELL: After mounting there is no sample on gonio according to TELL") - self.__cfg.current_sample = None - if target is not None: - raise e - elif target is not None and (target.location is not None - and mounted_sample.puck.pos == target.location.pos - and mounted_sample.puck.segment == target.location.segment - and mounted_sample.pin == target.pin): - logger.info("TELL: Actually mounting was correct according to TELL, so setting current sample to target") - self.__cfg.current_sample = target - else: - raise e - - self.__set_state(BeamlineStateEnum.SampleAlignment) - self.__cfg.state_busy = False - - #if target is not None and target.location is not None: - # self.__loop_center_sequence(target.db_id) + pass @property def camera_image(self) -> np.ndarray | None: @@ -514,7 +443,6 @@ class AareDAQ: bgr_array = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) cv2.imwrite(f"bkg{zoom_value:.0f}_{exposure*1000:.0f}_{gain:.0f}.jpg", bgr_array) self.__cfg.state_busy = False - self.__devs.sample_cam.set_auto() except Exception as e: self.__cfg.state_busy = False raise e @@ -754,8 +682,8 @@ class AareDAQ: if beam_y !=0 and abs(centre_y-beam_y)/abs(beam_y) > tolerance: coord = geom.picture_to_smargon(Coordinate(x=beam_x, y=centre_y)) - self.__devs.smargon.target = SmargonCoordinate(sh_mm=coord) - self.__devs.smargon.wait(60) + self.__devs.smargon = SmargonCoordinate(sh_mm=coord) + self.__devs.smargon_wait(60) return @@ -771,10 +699,10 @@ class AareDAQ: self.__devs.samcam_settings = SampleCameraSettings( exposure=zoom_settings[zoom_value].exposure, gain=zoom_settings[zoom_value].gain) - self.__devs.zoom_sync(zoom_value) + self.__devs.set_zoom(zoom_value, wait=True) boxes: dict[int, tuple[float, float, float, float]] = {} - curr_angle = int(self.__devs.aerotech.omega) + curr_angle = int(self.__devs.aerotech_omega) total_range = steps * step_size + 1 start_angle = curr_angle if curr_angle + total_range < 720 else 0 end_angle = curr_angle + total_range @@ -782,7 +710,7 @@ class AareDAQ: for angle in range(start_angle, end_angle, step_size): logger.debug(f'moving to angle: {angle}') rotate_time = time.perf_counter() - self.__devs.aerotech.move(angle, wait=True) + self.__devs.aerotech_omega = angle logger.info(f"time to rotate 15 degrees: {time.perf_counter() - rotate_time}") curr_image = cv2.cvtColor(self.camera_image, cv2.COLOR_RGB2BGR) @@ -818,7 +746,7 @@ class AareDAQ: logger.info(f"best params: {best_params}") logger.info(f"chosen fit: {best_name}") logger.info(f"best angle: {flat_face_angle}") - self.__devs.aerotech.move(flat_face_angle, wait=True) + self.__devs.aerotech_omega = flat_face_angle samples_out = fd.get_samples_out(boxes) logger.info(f"face detection sequence done, samples: {samples_out}") @@ -864,7 +792,7 @@ class AareDAQ: self.__devs.samcam_settings = SampleCameraSettings(exposure=exposure, gain=gain) exp = int(exposure * 1000) gn = int(gain) - self.__devs.zoom_sync(zoom_value) + self.__devs.set_zoom(zoom_value, wait=True) logger.debug(f'zoom={zoom_value},gain={gn}, exp={exp}ms') found_flag = False @@ -874,7 +802,7 @@ class AareDAQ: for angle in base_angles: logger.debug(f"Moving to new omega: {angle}") time_to_move_aerotech= time.perf_counter() - self.__devs.aerotech.move(angle, wait=True) + 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 @@ -901,8 +829,8 @@ class AareDAQ: found_angle = angle time_to_move_smargon = time.perf_counter() - self.__devs.smargon.target = target - self.__devs.smargon.wait(60) + 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 targets_found_this_attempt == 0: @@ -1128,7 +1056,7 @@ class AareDAQ: self.__cfg.zoom_mode = ZoomModeEnum.User self.__devs.samcam_settings = self.__cfg.zoom_settings.get_camera_settings(self.zoom) - self.__devs.dtz.move(params.dtz, wait=True) + self.__devs.dtz = params.dtz if self.omega + 180 < 720: start_omega = self.omega else: @@ -1288,7 +1216,7 @@ class AareDAQ: flux_ph_s=self.__devs.full_flux, sample_camera=self.__devs.samcam_settings, name=self.__bl, - transmission=self.__devs.transmission.get(), + transmission=self.__devs.transmission, zoom=self.__devs.zoom, commissioning_mode=self.__cfg.commissioning_mode, dtz_min=self.__devs.dtz_low, @@ -1314,7 +1242,7 @@ class AareDAQ: def cancel(self): if self.__cfg.state == BeamlineStateEnum.DataCollection: - self.__devs.aerotech.stop() + self.__devs.aerotech_stop() self.__jfjoch.cancel() def anneal(self, time_s: float): @@ -1331,12 +1259,12 @@ class AareDAQ: self.__set_state(BeamlineStateEnum.XrayFluorescence) if fm.transmission is not None: - self.__devs.transmission.set(fm.transmission, wait=True) + self.__devs.transmission = fm.transmission self.__devs.fluorimeter.start_acquisition(erase=fm.erase) - self.__devs.aerotech.set_shutter(1) + self.__devs.shutter = True time.sleep(fm.acq_time_s) - self.__devs.aerotech.set_shutter(0) + self.__devs.shutter = False self.__devs.fluorimeter.stop_acquisition() time.sleep(0.2) spectrum = self.__devs.fluorimeter.get_current_data() @@ -1358,20 +1286,3 @@ class AareDAQ: self.__set_state(BeamlineStateEnum.SampleAlignment) self.__cfg.state_busy = False raise e - - def fluorimeter_start(self, erase: bool = False): - self.__devs.aerotech.set_shutter(1) - self.__devs.fluorimeter.start_acquisition(erase=erase) - - def fluorimeter_stop(self): - self.__devs.fluorimeter.stop_acquisition() - self.__devs.aerotech.set_shutter(0) - - def fluorimeter_status(self) -> int | None: - return self.__devs.fluorimeter.check_status() - - def fluorimeter_data(self): - return self.__devs.fluorimeter.get_current_data() - - def fluorimeter_background(self): - return self.__devs.fluorimeter.get_current_background() \ No newline at end of file diff --git a/src/aare/daq/devices.py b/src/aare/daq/devices.py index ad6ca291..0d681a1a 100644 --- a/src/aare/daq/devices.py +++ b/src/aare/daq/devices.py @@ -206,6 +206,9 @@ class BeamlineDevices: def aerotech_lock(self, val: bool): pass + def aerotech_stop(self): + pass + # Smargon goniometer @property def smargon_pos(self) -> SmargonCoordinate: @@ -218,8 +221,8 @@ class BeamlineDevices: def smargon_pos(self, pos: SmargonCoordinate): self.set_smargon_pos(pos, wait=True) - def smargon_wait(self): - self.__smargon.wait() + def smargon_wait(self, timeout: float = 10.0): + self.__smargon.wait(timeout=timeout) def smargon_move_home(self): self.__smargon.move_home(wait=True)