DAQ: changed routing so that there is a mid layer between automation and manual alls of private functions such as mount, loop_center, rotation and raster. Needs some checking and testing.
This commit is contained in:
1 parent
2f0f9623a7
commit
2044313864
1 file changed
+190
-73
+190
-73
@@ -83,6 +83,116 @@ class AareDAQ:
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to emit face detection progress: {e}")
|
||||
|
||||
def _handle_operation_error(self, operation_name: str, sample: SampleShortInfo | None, error: Exception,
|
||||
error_type: str = "generic") -> None:
|
||||
"""
|
||||
Centralized error handling for all operations.
|
||||
|
||||
Args:
|
||||
operation_name: Name of the operation that failed (e.g., "mount", "alc", "raster")
|
||||
sample: The sample being processed
|
||||
error: The exception that occurred
|
||||
error_type: Type of error - "mount", "alc", "axc", or "generic"
|
||||
"""
|
||||
if sample is None:
|
||||
logger.error(f"Error in {operation_name}: {error}")
|
||||
return
|
||||
|
||||
try:
|
||||
if error_type == "mount":
|
||||
self.__aare.sample_failed(sample, failed_comment=f"Mount failed: {error}")
|
||||
elif error_type == "alc":
|
||||
self.__aare.alc_failed(sample, alc_comment=f"Loop centering failed: {error}")
|
||||
elif error_type == "axc":
|
||||
self.__aare.axc_failed(sample)
|
||||
else:
|
||||
self.__aare.sample_failed(sample, failed_comment=f"Error in {operation_name}: {error}")
|
||||
except Exception as db_error:
|
||||
logger.error(f"Failed to report {operation_name} error to database: {db_error}")
|
||||
|
||||
def _execute_mount_and_prepare(self, sample: SampleShortInfo) -> bool:
|
||||
"""
|
||||
Execute mounting and take screenshot.
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
self.__mount(sample)
|
||||
if sample.db_id is not None:
|
||||
self.__aare.sample_mounted(sample)
|
||||
self.save_screenshot_db(sample.db_id, f"{sample.db_id}_mounted")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Mount failed: {e}")
|
||||
self._handle_operation_error("mount", sample, e, error_type="mount")
|
||||
return False
|
||||
|
||||
def _execute_loop_centering(self, sample_id: int | None) -> bool:
|
||||
"""
|
||||
Execute loop centering sequence.
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
if not self.__loop_center_sequence(sample_id):
|
||||
self._handle_operation_error("loop_centering", self.sample, LoopCenteringFailed(), error_type="alc")
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Loop centering failed: {e}")
|
||||
self._handle_operation_error("loop_centering", self.sample, e, error_type="alc")
|
||||
return False
|
||||
|
||||
def _execute_raster_sequence(self, grid_request: RasterGridRequest,
|
||||
auto_center: bool = False) -> CompletedRasterGrid | None:
|
||||
"""
|
||||
Execute raster scan with optional auto-centering.
|
||||
|
||||
Args:
|
||||
grid_request: Raster grid parameters
|
||||
auto_center: If True, use auto-centering; if False, use direct raster
|
||||
|
||||
Returns:
|
||||
CompletedRasterGrid result or None if failed
|
||||
"""
|
||||
try:
|
||||
if auto_center:
|
||||
result = self.__auto_center(grid_request)
|
||||
else:
|
||||
raster_result = self.__raster(grid_request)
|
||||
result = CompletedRasterGrid(r=[raster_result])
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Raster sequence failed: {e}")
|
||||
self._handle_operation_error("raster", self.sample, e, error_type="axc")
|
||||
return None
|
||||
|
||||
def _execute_rotation_sequence(self, rotation_request: RotationScanRequest) -> CompletedRotationScan | None:
|
||||
"""
|
||||
Execute rotation scan.
|
||||
|
||||
Args:
|
||||
rotation_request: Rotation scan parameters
|
||||
|
||||
Returns:
|
||||
CompletedRotationScan result or None if failed
|
||||
"""
|
||||
try:
|
||||
result = self.__rotation(rotation_request)
|
||||
self.__set_state(BeamlineStateEnum.SampleAlignment)
|
||||
if self.sample is not None and self.sample.db_id is not None:
|
||||
self.save_screenshot_db(self.sample.db_id, "scan_preview")
|
||||
self.__aare.sample_collected(self.sample)
|
||||
self.__aare.ingest_scan(sample=self.sample, result=result.result,
|
||||
geom=self.sample_geometry, beam_mark_pxl=self.__cfg.get_beam_mark(self.zoom))
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"Rotation sequence failed: {e}")
|
||||
self._handle_operation_error("rotation", self.sample, e, error_type="generic")
|
||||
return None
|
||||
|
||||
def _append_smargon_trace(self, *, sample_id: int | None, event: str) -> None:
|
||||
try:
|
||||
path = self._smargon_trace_path
|
||||
@@ -865,24 +975,15 @@ class AareDAQ:
|
||||
"""
|
||||
self.__cfg.try_set_busy(timeout=ceil(360))
|
||||
try:
|
||||
if auto:
|
||||
result = self.__auto_center(r)
|
||||
else:
|
||||
raster_result = self.__raster(r)
|
||||
result = CompletedRasterGrid(r=[raster_result])
|
||||
self.__set_state(BeamlineStateEnum.SampleAlignment)
|
||||
result = self._execute_raster_sequence(r, auto_center=auto)
|
||||
|
||||
if result is None:
|
||||
raise Exception("Raster scan failed")
|
||||
|
||||
self.__cfg.state_busy = False
|
||||
#return CompletedRasterGrid(r=[])
|
||||
return result
|
||||
except Exception as e:
|
||||
try:
|
||||
self.__aare.axc_failed(self.sample)
|
||||
except Exception as axc_e:
|
||||
logger.error(f"Exception while reporting AXC failure: {axc_e}")
|
||||
if not self.busy:
|
||||
self.__cfg.try_set_busy(timeout=ceil(360))
|
||||
if self.status.state != BeamlineStateEnum.SampleAlignment:
|
||||
self.__set_state(BeamlineStateEnum.SampleAlignment)
|
||||
self.__set_state(BeamlineStateEnum.SampleAlignment)
|
||||
self.__cfg.state_busy = False
|
||||
raise e
|
||||
|
||||
@@ -973,8 +1074,10 @@ class AareDAQ:
|
||||
self.__cfg.try_set_busy(timeout=ceil(total_time + 360))
|
||||
|
||||
try:
|
||||
result = self.__rotation(request)
|
||||
self.__set_state(BeamlineStateEnum.SampleAlignment)
|
||||
result = self._execute_rotation_sequence(request)
|
||||
|
||||
if result is None:
|
||||
raise Exception("Rotation scan failed")
|
||||
self.__cfg.state_busy = False
|
||||
return result
|
||||
except Exception as e:
|
||||
@@ -1516,18 +1619,19 @@ class AareDAQ:
|
||||
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):
|
||||
|
||||
if not self._execute_loop_centering(sample_id):
|
||||
raise LoopCenteringFailed
|
||||
|
||||
self.__cfg.state_busy = False
|
||||
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
self.__cfg.zoom_mode = ZoomModeEnum.User
|
||||
#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)
|
||||
finally:
|
||||
self.__cfg.zoom_mode = ZoomModeEnum.User
|
||||
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
@@ -1676,6 +1780,17 @@ class AareDAQ:
|
||||
|
||||
return default_params, "defaults"
|
||||
|
||||
def _end_operation(self, start) -> float:
|
||||
"""
|
||||
End an operation and return elapsed time.
|
||||
|
||||
Returns:
|
||||
(elapsed_seconds, end_time_perf_counter)
|
||||
"""
|
||||
self.__cfg.state_busy = False
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
|
||||
def measure(self, sample: SampleShortInfo) -> float:
|
||||
"""
|
||||
Main measurement sequence for a given sample.
|
||||
@@ -1700,79 +1815,81 @@ class AareDAQ:
|
||||
logger.info(f"setting busy at {time.perf_counter() - start}")
|
||||
self.__cfg.try_set_busy(timeout=360)
|
||||
logger.info(f"set busy at {time.perf_counter() - start}")
|
||||
geom = self.sample_geometry
|
||||
start_mount=time.perf_counter()
|
||||
logger.info(f"starting mount {sample.db_id} at {time.ctime()}")
|
||||
self.__mount(sample)
|
||||
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):
|
||||
self.__aare.alc_failed(sample)
|
||||
print("alc failed")
|
||||
self.__cfg.state_busy = False
|
||||
end = time.perf_counter()
|
||||
|
||||
return end - start
|
||||
if not self._execute_mount_and_prepare(sample):
|
||||
logger.error("Failed to mount sample")
|
||||
return self._end_operation(start)
|
||||
|
||||
logger.info(f"mounting done at {time.perf_counter() - start}")
|
||||
|
||||
# Step 2: Loop centering
|
||||
if not self._execute_loop_centering(sample.db_id):
|
||||
logger.error("Loop Centering did not succeed")
|
||||
return self._end_operation(start)
|
||||
|
||||
logger.info(f"alc done at {time.perf_counter() - start}")
|
||||
|
||||
# Step 3: Face detection
|
||||
result = self.__face_detection_sequence(steps=7, step_size=30)
|
||||
self._emit_face_detection_progress(result)
|
||||
logger.info(f"face_detection done at {time.perf_counter() - start}")
|
||||
#self.zoom = 500
|
||||
|
||||
hex_string = secrets.token_hex(3) # 3 bytes = 6 hex characters
|
||||
print(hex_string.upper())
|
||||
|
||||
hex_string = secrets.token_hex(3)
|
||||
raster_params = self.get_auto_raster_params()
|
||||
if self.__auto_center(RasterGridRequest(
|
||||
geom = self.sample_geometry
|
||||
|
||||
raster_grid = RasterGridRequest(
|
||||
exp_time_s=raster_params.exp_time_s,
|
||||
file_prefix=sample_prefix + f"_{hex_string}",
|
||||
smargon_top_left= SmargonCoordinate(),
|
||||
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}")
|
||||
transmission=raster_params.transmission,
|
||||
)
|
||||
|
||||
raster_result = self._execute_raster_sequence(raster_grid, auto_center=True)
|
||||
if raster_result is None:
|
||||
logger.error("Raster result was None")
|
||||
return self._end_operation(start)
|
||||
|
||||
logger.info(f"raster scans done at {time.perf_counter() - start}")
|
||||
|
||||
# Step 5: Data collection (rotation)
|
||||
params, source = self.get_collection_params(prefer_smart=False)
|
||||
logger.info(f"Using {source} for data collection: {params}")
|
||||
|
||||
self.__devs.dtz = params.dtz
|
||||
start_omega = self.omega
|
||||
|
||||
rotation_request = 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,
|
||||
)
|
||||
|
||||
rotation_result = self._execute_rotation_sequence(rotation_request)
|
||||
if rotation_result is None:
|
||||
logger.error("Rotation result was None")
|
||||
return self._end_operation(start)
|
||||
|
||||
logger.info(f"rotation done at {time.perf_counter() - start}")
|
||||
|
||||
self.__devs.dtz = params.dtz
|
||||
start_omega = self.omega
|
||||
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}")
|
||||
self.__cfg.state_busy = False
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
else:
|
||||
logger.error("auto center failed")
|
||||
self.__aare.axc_failed(sample)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in measure: {e}")
|
||||
if isinstance(e, AXCFailed):
|
||||
logger.debug(f"error is instance AXCFailed")
|
||||
self.__aare.axc_failed(sample)
|
||||
else:
|
||||
self.__aare.sample_failed(sample, f"Error in automation: {e}")
|
||||
self.__cfg.state_busy = False
|
||||
end = time.perf_counter()
|
||||
raise e
|
||||
self.__cfg.state_busy = False
|
||||
end = time.perf_counter()
|
||||
return end - start
|
||||
self._handle_operation_error("measure", sample, e, error_type="generic")
|
||||
|
||||
finally:
|
||||
return self._end_operation(start)
|
||||
|
||||
def __set_state(self, target: BeamlineStateEnum):
|
||||
"""__set_state assumes that beamline is already in busy state
|
||||
|
||||
Reference in new issue
Block a user