wip bugfixes
This commit is contained in:
@@ -12,7 +12,6 @@ import os
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
from functools import partial
|
||||
from typing import TYPE_CHECKING, Any, Literal
|
||||
|
||||
import numpy as np
|
||||
@@ -20,12 +19,13 @@ from bec_lib.file_utils import get_full_path
|
||||
from bec_lib.logger import bec_logger
|
||||
from ophyd import ADBase
|
||||
from ophyd import Component as Cpt
|
||||
from ophyd import EpicsSignalRO, EpicsSignalWithRBV
|
||||
from ophyd import Signal
|
||||
from ophyd_devices import (
|
||||
AndStatus,
|
||||
AsyncSignal,
|
||||
CompareStatus,
|
||||
DeviceStatus,
|
||||
EpicsSignalRO,
|
||||
EpicsSignalWithRBV,
|
||||
ExceptionStatus,
|
||||
FileEventSignal,
|
||||
PreviewSignal,
|
||||
@@ -201,6 +201,7 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
"set_pixel_map",
|
||||
"set_pixel_map_from_json_file",
|
||||
"set_enable_xes",
|
||||
"set_enable_image_writing",
|
||||
]
|
||||
|
||||
xes_data = Cpt(
|
||||
@@ -514,6 +515,15 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
"""
|
||||
self.enable_xes = enable
|
||||
|
||||
def set_enable_image_writing(self, enable: bool) -> None:
|
||||
"""
|
||||
Enable or disable image writing to file through the HDF5 plugin.
|
||||
|
||||
Args:
|
||||
enable (bool): Whether to enable image writing.
|
||||
"""
|
||||
self.hdf.enable.set(1 if enable else 0).wait(timeout=self._pv_timeout)
|
||||
|
||||
@property
|
||||
def enable_xes(self) -> bool:
|
||||
"""Get whether XES data acquisition is enabled."""
|
||||
@@ -701,18 +711,18 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
file_path = "/".join(self._full_path.split("/")[:-1])
|
||||
file_name = self._full_path.split("/")[-1]
|
||||
self.cam.array_callbacks.set(1).wait(5) # Enable array callbacks
|
||||
# self.hdf.enable.set(1).wait(5) # Enable HDF5 plugin
|
||||
self.hdf.file_path.set(file_path).wait(5)
|
||||
self.hdf.file_name.set(file_name).wait(5)
|
||||
# Setup file writing for the total expected number of images
|
||||
self.hdf.num_capture.set(self._n_images).wait(5)
|
||||
self.hdf.capture.put(1)
|
||||
self.file_event.put(
|
||||
file_path=self._full_path,
|
||||
done=False,
|
||||
successful=False,
|
||||
hinted_h5_entries={"data": "/entry/data/data"},
|
||||
)
|
||||
if self.hdf.enable.get() == 1:
|
||||
self.hdf.capture.put(1)
|
||||
self.file_event.put(
|
||||
file_path=self._full_path,
|
||||
done=False,
|
||||
successful=False,
|
||||
hinted_h5_entries={"data": "/entry/data/data"},
|
||||
)
|
||||
|
||||
# -------------------------
|
||||
# XES specific staging
|
||||
@@ -807,13 +817,15 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
def on_complete(self) -> DeviceStatus | StatusBase | None:
|
||||
"""Called to inquire if a device has completed a scans."""
|
||||
# Status Camera
|
||||
status_camera = CompareStatus(self.cam.acquire_busy, ACQUIRESTATUS.DONE)
|
||||
return_status = CompareStatus(self.cam.acquire_busy, ACQUIRESTATUS.DONE)
|
||||
# Status Writer
|
||||
st1 = CompareStatus(self.hdf.capture, ACQUIRESTATUS.DONE)
|
||||
st2 = CompareStatus(self.hdf.write_file, ACQUIRESTATUS.DONE)
|
||||
st3 = ExceptionStatus(self.hdf.write_status, 0, operation="!=")
|
||||
status_written_images = CompareStatus(self.hdf.num_captured, self._n_images)
|
||||
status_writer = st1 & st2 & status_written_images
|
||||
status_writer = None
|
||||
if self.hdf.enable.get() == 1:
|
||||
st2 = CompareStatus(self.hdf.write_file, ACQUIRESTATUS.DONE)
|
||||
st3 = ExceptionStatus(self.hdf.write_status, 0, operation="!=")
|
||||
status_written_images = CompareStatus(self.hdf.num_captured, self._n_images)
|
||||
status_writer = st1 & st2 & status_written_images & st3
|
||||
|
||||
# Status Backend
|
||||
status_backend = None
|
||||
@@ -822,25 +834,18 @@ class Timepix(PSIDeviceBase, TimePixControl):
|
||||
status_backend = self.backend.on_complete(status=status_backend)
|
||||
# Combine the statuses
|
||||
if status_backend is not None:
|
||||
return_status = status_backend & status_camera & status_writer & st3
|
||||
else:
|
||||
return_status = status_camera & status_writer & st3
|
||||
# We check the write_status if it goes to write error
|
||||
# st3 = ExceptionStatus(self.hdf.write_status, 0, operation="!=")
|
||||
return_status = status_backend & return_status
|
||||
if status_writer is not None:
|
||||
return_status = return_status & status_writer
|
||||
|
||||
# def _failed_to_write_callback(status, ret_status: AndStatus):
|
||||
# if status.done and status.success:
|
||||
# if not ret_status.done:
|
||||
# ret_status.set_exception(f"Error while writing on {self.name}")
|
||||
|
||||
self.cancel_on_stop(st3)
|
||||
# st3.add_callback(partial(_failed_to_write_callback, ret_status=return_status))
|
||||
return_status.add_callback(self._complete_callback)
|
||||
self.cancel_on_stop(return_status)
|
||||
return return_status
|
||||
|
||||
def _complete_callback(self, status: CompareStatus) -> None:
|
||||
"""Callback for when the device completes a scan."""
|
||||
if self.hdf.enable.get() != 1: # TODO: Not sure if we should support disabled file writing.
|
||||
return
|
||||
if status.success:
|
||||
self.file_event.put(
|
||||
file_path=self._full_path, # pylint: disable:protected-access
|
||||
|
||||
@@ -12,7 +12,6 @@ hooks for all the relevant ophyd interface, 'on_stage',
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import signal
|
||||
import socket
|
||||
import threading
|
||||
import time
|
||||
@@ -239,6 +238,7 @@ class TimepixFlyBackend:
|
||||
|
||||
def on_destroy(self):
|
||||
"""Hook for on_destroy logic."""
|
||||
time_started = time.time()
|
||||
self.timepix_fly_client.shutdown()
|
||||
self._data_thread_shutdown_event.set()
|
||||
if self._data_thread is not None and self._data_thread.is_alive():
|
||||
@@ -255,6 +255,9 @@ class TimepixFlyBackend:
|
||||
except Exception:
|
||||
content = traceback.format_exc()
|
||||
logger.error(f"Error closing socket server: {content}")
|
||||
logger.info(
|
||||
f"Timepix Fly backend destroyed and resources cleaned up after {time.time() - time_started:.3f} seconds."
|
||||
)
|
||||
|
||||
def on_stop(self):
|
||||
"""Hook for on_stop logic."""
|
||||
|
||||
@@ -270,16 +270,18 @@ class TimepixFlyClient:
|
||||
continue
|
||||
if status in success:
|
||||
dev_status.set_finished()
|
||||
logger.debug(f"Status callback finished in succes: {status.value}")
|
||||
logger.debug(f"Status callback finished in success: {status.value}")
|
||||
self._status_callbacks.pop(cb_id)
|
||||
elif status in error:
|
||||
try:
|
||||
last_error = self.last_error()
|
||||
raise TimePixStatusError(
|
||||
f"TimePixFly Backend state '{status.value}' is in list of specified errors {error}. Last error message: {last_error.message}"
|
||||
f"TimePixFly state '{status.value}': {last_error.message}"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in status callback from TimepixFly Backend: {e}")
|
||||
logger.error(
|
||||
f"Error in status callback for '{status.value}' from TimepixFly backend: {e}"
|
||||
)
|
||||
dev_status.set_exception(e)
|
||||
self._status_callbacks.pop(cb_id)
|
||||
# Reset the _started flag if the status is in CONFIG.
|
||||
|
||||
Reference in New Issue
Block a user