diff --git a/ophyd_devices/epics/devices/eiger9m_csaxs.py b/ophyd_devices/epics/devices/eiger9m_csaxs.py index 3f2ccbd..dc304ff 100644 --- a/ophyd_devices/epics/devices/eiger9m_csaxs.py +++ b/ophyd_devices/epics/devices/eiger9m_csaxs.py @@ -105,7 +105,8 @@ class Eiger9MSetup(CustomDetectorMixin): ) if not isinstance(value, type(old_value)): raise EigerError( - f"Type of new value {type(value)}:{value} does not match old value {type(old_value)}:{old_value}" + f"Type of new value {type(value)}:{value} does not match old value" + f" {type(old_value)}:{old_value}" ) # Update config with new value and send back to client @@ -225,7 +226,7 @@ class Eiger9MSetup(CustomDetectorMixin): except Exception as exc: time.sleep(5) if self.std_client.get_status()["state"] == "READY": - raise EigerTimeoutError(f"Timeout of start_writer_async with {exc}") + raise EigerTimeoutError(f"Timeout of start_writer_async with {exc}") from exc # Check status of std_daq signal_conditions = [ @@ -238,7 +239,8 @@ class Eiger9MSetup(CustomDetectorMixin): all_signals=True, ): raise EigerTimeoutError( - f"Timeout of 5s reached for std_daq start_writer_async with std_daq client status {self.std_client.get_status()}" + "Timeout of 5s reached for std_daq start_writer_async with std_daq client status" + f" {self.std_client.get_status()}" ) def filepath_exists(self, filepath: str) -> None: @@ -279,7 +281,7 @@ class Eiger9MSetup(CustomDetectorMixin): old_scanID = self.parent.scaninfo.scanID self.parent.scaninfo.load_scan_metadata() if self.parent.scaninfo.scanID != old_scanID: - self.parent.stopped is True + self.parent.stopped = True def publish_file_location(self, done: bool = False, successful: bool = None) -> None: """ @@ -333,7 +335,9 @@ class Eiger9MSetup(CustomDetectorMixin): self.stop_detector() self.stop_detector_backend() raise EigerTimeoutError( - f"Reached timeout with detector state {signal_conditions[0][0]}, std_daq state {signal_conditions[1][0]} and received frames of {signal_conditions[2][0]} for the file writer" + f"Reached timeout with detector state {signal_conditions[0][0]}, std_daq state" + f" {signal_conditions[1][0]} and received frames of {signal_conditions[2][0]} for" + " the file writer" ) self.stop_detector() self.stop_detector_backend() diff --git a/ophyd_devices/epics/devices/falcon_csaxs.py b/ophyd_devices/epics/devices/falcon_csaxs.py index aa5ab54..0c29fa5 100644 --- a/ophyd_devices/epics/devices/falcon_csaxs.py +++ b/ophyd_devices/epics/devices/falcon_csaxs.py @@ -110,18 +110,16 @@ class FalconSetup(CustomDetectorMixin): """ - def __init__(self, *args, parent: Device = None, **kwargs) -> None: - super().__init__(*args, parent=parent, **kwargs) - def initialize_default_parameter(self) -> None: """ Set default parameters for Falcon - readout (float): readout time in seconds - _value_pixel_per_buffer (int): number of spectra in buffer of Falcon Sitoro + This will set: + - readout (float): readout time in seconds + - value_pixel_per_buffer (int): number of spectra in buffer of Falcon Sitoro """ - self.parent._value_pixel_per_buffer = 20 + self.parent.value_pixel_per_buffer = 20 self.update_readout_time() def update_readout_time(self) -> None: @@ -134,24 +132,20 @@ class FalconSetup(CustomDetectorMixin): self.parent.readout_time = max(readout_time, self.parent.MIN_READOUT) def initialize_detector(self) -> None: - """ - Initialize Falcon detector. - - The detector is operated in MCA mapping mode. - - Parameters here affect the triggering, gating etc. - - This includes also the readout chunk size and whether data is segmented into spectra in EPICS. - """ + """Initialize Falcon detector""" self.stop_detector() self.stop_detector_backend() self.parent.set_trigger( mapping_mode=MappingSource.MAPPING, trigger_source=TriggerSource.GATE, ignore_gate=0 ) - self.parent.preset_mode.put(1) # 1 Realtime - self.parent.input_logic_polarity.put(0) # 0 Normal, 1 Inverted - self.parent.auto_pixels_per_buffer.put(0) # 0 Manual 1 Auto - self.parent.pixels_per_buffer.put(self.parent._value_pixel_per_buffer) + # 1 Realtime + self.parent.preset_mode.put(1) + # 0 Normal, 1 Inverted + self.parent.input_logic_polarity.put(0) + # 0 Manual 1 Auto + self.parent.auto_pixels_per_buffer.put(0) + # Sets the number of pixels/spectra in the buffer + self.parent.pixels_per_buffer.put(self.parent.value_pixel_per_buffer) def stop_detector(self) -> None: """Stops detector""" @@ -211,7 +205,7 @@ class FalconSetup(CustomDetectorMixin): file_path, file_name = os.path.split(self.parent.filepath) self.parent.hdf5.file_path.put(file_path) self.parent.hdf5.file_name.put(file_name) - self.parent.hdf5.file_template.put(f"%s%s") + self.parent.hdf5.file_template.put("%s%s") self.parent.hdf5.num_capture.put( int(self.parent.scaninfo.num_points * self.parent.scaninfo.frames_per_trigger) ) @@ -246,7 +240,7 @@ class FalconSetup(CustomDetectorMixin): old_scanID = self.parent.scaninfo.scanID self.parent.scaninfo.load_scan_metadata() if self.parent.scaninfo.scanID != old_scanID: - self.parent._stopped = True + self.parent.stopped = True def publish_file_location(self, done: bool = False, successful: bool = None) -> None: """ @@ -288,14 +282,17 @@ class FalconSetup(CustomDetectorMixin): However, this decision could be revoked and handled differently. """ + total_frames = int( + self.parent.scaninfo.num_points * self.parent.scaninfo.frames_per_trigger + ) signal_conditions = [ ( - lambda: self.parent.dxp.current_pixel.get(), - int(self.parent.scaninfo.num_points * self.parent.scaninfo.frames_per_trigger), + self.parent.dxp.current_pixel.get, + total_frames, ), ( - lambda: self.parent.hdf5.array_counter.get(), - int(self.parent.scaninfo.num_points * self.parent.scaninfo.frames_per_trigger), + self.parent.hdf5.array_counter.get, + total_frames, ), ] if not self.wait_for_signals( @@ -305,7 +302,9 @@ class FalconSetup(CustomDetectorMixin): all_signals=True, ): logger.debug( - f"Falcon missed a trigger: received trigger {received_frames}, send data {written_frames} from total_frames {total_frames}" + f"Falcon missed a trigger: received trigger {self.parent.dxp.current_pixel.get()}," + f" send data {self.parent.hdf5.array_counter.get()} from total_frames" + f" {total_frames}" ) self.stop_detector() self.stop_detector_backend() diff --git a/ophyd_devices/epics/devices/pilatus_csaxs.py b/ophyd_devices/epics/devices/pilatus_csaxs.py index d7e1901..5781d0d 100644 --- a/ophyd_devices/epics/devices/pilatus_csaxs.py +++ b/ophyd_devices/epics/devices/pilatus_csaxs.py @@ -11,8 +11,6 @@ from ophyd import ADComponent as ADCpt from bec_lib import messages, MessageEndpoints, bec_logger -from ophyd_devices.utils import bec_utils as bec_utils - from ophyd_devices.epics.devices.psi_detector_base import PSIDetectorBase, CustomDetectorMixin logger = bec_logger.logger @@ -23,14 +21,10 @@ MIN_READOUT = 3e-3 class PilatusError(Exception): """Base class for exceptions in this module.""" - pass - class PilatusTimeoutError(PilatusError): """Raised when the Pilatus does not respond in time during unstage.""" - pass - class TriggerSource(enum.IntEnum): """Trigger source options for the detector""" @@ -123,7 +117,7 @@ class PilatusSetup(CustomDetectorMixin): # Check if energies are eV or keV, assume keV as the default unit = getattr(self.parent.cam.threshold_energy, "units", None) - if unit != None and unit == "eV": + if unit is not None and unit == "eV": factor = 1000 # set energy on detector @@ -148,7 +142,7 @@ class PilatusSetup(CustomDetectorMixin): # Update the readout time of the detector self.update_readout_time() - def create_directory(filepath: str) -> None: + def create_directory(self, filepath: str) -> None: """Create directory if it does not exist""" os.makedirs(filepath, exist_ok=True) @@ -199,7 +193,7 @@ class PilatusSetup(CustomDetectorMixin): self.parent.filepath = self.parent.filewriter.compile_full_filename( self.parent.scaninfo.scan_number, "pilatus_2.h5", 1000, 5, True ) - self.parent.cam.file_path.put(f"/dev/shm/zmq/") + self.parent.cam.file_path.put("/dev/shm/zmq/") self.parent.cam.file_name.put( f"{self.parent.scaninfo.username}_2_{self.parent.scaninfo.scan_number:05d}" ) @@ -282,7 +276,7 @@ class PilatusSetup(CustomDetectorMixin): except Exception as exc: logger.info(f"Pilatus2 wait threw Exception: {exc}") - def send_requests_put(self, url: str, data_msg: list = None, headers: dict = None) -> object: + def send_requests_put(self, url: str, data: list = None, headers: dict = None) -> object: """ Send a put request to the given url @@ -294,7 +288,7 @@ class PilatusSetup(CustomDetectorMixin): Returns: status code of the request """ - return requests.put(url=url, data=json.dumps(data_msg), headers=headers) + return requests.put(url=url, data=json.dumps(data), headers=headers, timeout=5) def send_requests_delete(self, url: str, headers: dict = None) -> object: """ @@ -307,7 +301,7 @@ class PilatusSetup(CustomDetectorMixin): Returns: status code of the request """ - return requests.delete(url=url, headers=headers) + return requests.delete(url=url, headers=headers, timeout=5) def pre_scan(self) -> None: """Pre_scan is an (optional) function that is executed by BEC just before the scan core @@ -369,6 +363,7 @@ class PilatusSetup(CustomDetectorMixin): #TODO remove dependency from the mcs card """ + # pylint: disable=protected-access signal_conditions = [ ( lambda: self.parent.device_manager.devices.mcs.obj._staged, @@ -384,7 +379,9 @@ class PilatusSetup(CustomDetectorMixin): self.stop_detector() self.stop_detector_backend() raise PilatusTimeoutError( - f"Reached timeout with detector state {signal_conditions[0][0]}, std_daq state {signal_conditions[1][0]} and received frames of {signal_conditions[2][0]} for the file writer" + f"Reached timeout with detector state {signal_conditions[0][0]}, std_daq state" + f" {signal_conditions[1][0]} and received frames of {signal_conditions[2][0]} for" + " the file writer" ) self.stop_detector() self.stop_detector_backend() @@ -398,7 +395,7 @@ class PilatusSetup(CustomDetectorMixin): old_scanID = self.parent.scaninfo.scanID self.parent.scaninfo.load_scan_metadata() if self.parent.scaninfo.scanID != old_scanID: - self.parent._stopped = True + self.parent.stopped = True class PilatuscSAXS(PSIDetectorBase): diff --git a/ophyd_devices/epics/devices/psi_detector_base.py b/ophyd_devices/epics/devices/psi_detector_base.py index 7ccb273..4b59185 100644 --- a/ophyd_devices/epics/devices/psi_detector_base.py +++ b/ophyd_devices/epics/devices/psi_detector_base.py @@ -1,5 +1,4 @@ import time -from bec_lib.devicemanager import DeviceStatus import os from typing import List @@ -9,6 +8,7 @@ from ophyd.device import Staged from bec_lib.file_utils import FileWriterMixin from bec_lib.bec_service import SERVICE_CONFIG +from bec_lib.devicemanager import DeviceStatus from ophyd_devices.epics.devices.bec_scaninfo_mixin import BecScaninfoMixin from ophyd_devices.utils import bec_utils @@ -18,11 +18,6 @@ class DetectorInitError(Exception): """Raised when initiation of the device class fails, due to missing device manager or not started in sim_mode.""" - pass - - -# MIN_READOUT = 3e-3 - class CustomDetectorMixin: """ @@ -38,7 +33,7 @@ class CustomDetectorMixin: stage, unstage, trigger, stop and _init. """ - def __init__(self, parent: Device = None, *args, **kwargs) -> None: + def __init__(self, *_args, parent: Device = None, **_kwargs) -> None: self.parent = parent def initialize_default_parameter(self) -> None: @@ -48,7 +43,6 @@ class CustomDetectorMixin: Raises (optional): DetectorTimeoutError: if detector cannot be initialized """ - pass def initialize_detector(self) -> None: """ @@ -57,7 +51,6 @@ class CustomDetectorMixin: Raises (optional): DetectorTimeoutError: if detector cannot be initialized """ - pass def initialize_detector_backend(self) -> None: """ @@ -66,37 +59,31 @@ class CustomDetectorMixin: Raises (optional): DetectorTimeoutError: if filewriter cannot be initialized """ - pass def prepare_detector(self) -> None: """ Prepare detector for the scan """ - pass def prepare_data_backend(self) -> None: """ Prepare detector backend for the scan """ - pass def stop_detector(self) -> None: """ Stop the detector """ - pass def stop_detector_backend(self) -> None: """ Stop the detector backend """ - pass def on_trigger(self) -> None: """ Specify actions to be executed upon receiving trigger signal """ - pass def pre_scan(self) -> None: """ @@ -106,7 +93,6 @@ class CustomDetectorMixin: It is convenient to execute time critical features of the detector, e.g. arming it, but it is recommended to keep this function as short/fast as possible. """ - pass def finished(self) -> None: """ @@ -117,13 +103,11 @@ class CustomDetectorMixin: Raises (optional): DetectorTimeoutError: if detector cannot be stopped """ - pass def check_scanID(self) -> None: """ Check if BEC is running on a new scanID """ - pass def publish_file_location(self, done: bool = False, successful: bool = None) -> None: """ @@ -134,7 +118,6 @@ class CustomDetectorMixin: - file_event: event for the filewriter - public_file: event for any secondary service (e.g. radial integ code) """ - pass def wait_for_signals( self, @@ -162,7 +145,7 @@ class CustomDetectorMixin: ] if (all_signals and all(checks)) or (not all_signals and any(checks)): return True - if check_stopped == True and self.parent.stopped == True: + if check_stopped is True and self.parent.stopped is True: return False if timer > timeout: return False @@ -200,14 +183,6 @@ class PSIDetectorBase(Device): MIN_READOUT = 1e-3 - # @classmethod - # def get_min_readout(cls): - # return cls._MIN_READOUT - - # @classmethod - # def set_min_readout(cls, value): - # cls._MIN_READOUT = value - # Specify which functions are revealed to the user in BEC client USER_ACCESS = [ "describe", @@ -237,9 +212,9 @@ class PSIDetectorBase(Device): ) if device_manager is None and not sim_mode: raise DetectorInitError( - f"No device manager for device: {name}, and not started sim_mode: {sim_mode}. Add DeviceManager to initialization or init with sim_mode=True" + f"No device manager for device: {name}, and not started sim_mode: {sim_mode}. Add" + " DeviceManager to initialization or init with sim_mode=True" ) - # sim_mode True allows the class to be started without BEC running # Init variables self.sim_mode = sim_mode self.stopped = False @@ -339,7 +314,7 @@ class PSIDetectorBase(Device): List(object): list of objects that were unstaged """ self.custom_prepare.check_scanID() - if self.stopped == True: + if self.stopped is True: return super().unstage() self.custom_prepare.finished() state = True diff --git a/tests/test_falcon_csaxs.py b/tests/test_falcon_csaxs.py index 06bee95..73ac9b8 100644 --- a/tests/test_falcon_csaxs.py +++ b/tests/test_falcon_csaxs.py @@ -45,7 +45,8 @@ def mock_det(): @pytest.mark.parametrize( - "trigger_source, mapping_source, ignore_gate, pixels_per_buffer, detector_state, expected_exception", + "trigger_source, mapping_source, ignore_gate, pixels_per_buffer, detector_state," + " expected_exception", [ (1, 1, 0, 20, 0, False), (1, 1, 0, 20, 1, True), @@ -72,7 +73,7 @@ def test_init_detector( Validation upon setting the correct PVs """ - mock_det._value_pixel_per_buffer = pixels_per_buffer + mock_det.value_pixel_per_buffer = pixels_per_buffer mock_det.state._read_pv.mock_data = detector_state if expected_exception: with pytest.raises(FalconTimeoutError): @@ -117,7 +118,7 @@ def test_initialize_default_parameter(mock_det): mock_det.custom_prepare, "update_readout_time" ) as mock_update_readout_time: mock_det.custom_prepare.initialize_default_parameter() - assert mock_det._value_pixel_per_buffer == 20 + assert mock_det.value_pixel_per_buffer == 20 mock_update_readout_time.assert_called_once()