diff --git a/ophyd_devices/epics/devices/eiger9m_csaxs.py b/ophyd_devices/epics/devices/eiger9m_csaxs.py index 64fb266..3f2ccbd 100644 --- a/ophyd_devices/epics/devices/eiger9m_csaxs.py +++ b/ophyd_devices/epics/devices/eiger9m_csaxs.py @@ -1,4 +1,5 @@ import enum +import threading import time import numpy as np import os @@ -24,14 +25,10 @@ logger = bec_logger.logger class EigerError(Exception): """Base class for exceptions in this module.""" - pass - class EigerTimeoutError(EigerError): """Raised when the Eiger does not respond in time.""" - pass - class Eiger9MSetup(CustomDetectorMixin): """Eiger setup class @@ -40,13 +37,13 @@ class Eiger9MSetup(CustomDetectorMixin): """ - def __init__(self, parent: Device = None, *args, **kwargs) -> None: - super().__init__(parent=parent, *args, **kwargs) + def __init__(self, *args, parent: Device = None, **kwargs) -> None: + super().__init__(*args, parent=parent, **kwargs) self.std_rest_server_url = ( kwargs["file_writer_url"] if "file_writer_url" in kwargs else "http://xbl-daq-29:5000" ) self.std_client = None - self._lock = self.parent._lock + self._lock = threading.RLock() def initialize_default_parameter(self) -> None: """Set default parameters for Eiger9M detector""" @@ -57,9 +54,9 @@ class Eiger9MSetup(CustomDetectorMixin): readout_time = ( self.parent.scaninfo.readout_time if hasattr(self.parent.scaninfo, "readout_time") - else self.parent.get_min_readout() + else self.parent.MIN_READOUT ) - self.parent.readout_time = max(readout_time, self.parent.get_min_readout()) + self.parent.readout_time = max(readout_time, self.parent.MIN_READOUT) def initialize_detector(self) -> None: """Initialize detector""" @@ -181,7 +178,7 @@ class Eiger9MSetup(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 @@ -246,14 +243,14 @@ class Eiger9MSetup(CustomDetectorMixin): def filepath_exists(self, filepath: str) -> None: """Check if filepath exists""" - signal_conditions = [(lambda: os.path.exists(os.path.dirname(self.parent.filepath)), True)] + signal_conditions = [(lambda: os.path.exists(os.path.dirname(filepath)), True)] if not self.wait_for_signals( signal_conditions=signal_conditions, timeout=self.parent.timeout, check_stopped=False, all_signals=True, ): - raise EigerError(f"Timeout of 3s reached for filepath {self.parent.filepath}") + raise EigerError(f"Timeout of 3s reached for filepath {filepath}") def arm_acquisition(self) -> None: """Arm Eiger detector for acquisition""" @@ -282,7 +279,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 = True + self.parent.stopped is True def publish_file_location(self, done: bool = False, successful: bool = None) -> None: """ @@ -296,19 +293,19 @@ class Eiger9MSetup(CustomDetectorMixin): done (bool): True if scan is finished successful (bool): True if scan was successful """ - pipe = self.parent._producer.pipeline() + pipe = self.parent.producer.pipeline() if successful is None: msg = messages.FileMessage(file_path=self.parent.filepath, done=done) else: msg = messages.FileMessage( file_path=self.parent.filepath, done=done, successful=successful ) - self.parent._producer.set_and_publish( + self.parent.producer.set_and_publish( MessageEndpoints.public_file(self.parent.scaninfo.scanID, self.parent.name), msg.dumps(), pipe=pipe, ) - self.parent._producer.set_and_publish( + self.parent.producer.set_and_publish( MessageEndpoints.file_event(self.parent.name), msg.dumps(), pipe=pipe ) pipe.execute() @@ -406,7 +403,7 @@ class Eiger9McSAXS(PSIDetectorBase): # specify Setup class custom_prepare_cls = Eiger9MSetup # specify minimum readout time for detector - PSIDetectorBase.set_min_readout(3e-3) + MIN_READOUT = 3e-3 # specify class attributes cam = ADCpt(SLSDetectorCam, "cam1:") diff --git a/ophyd_devices/epics/devices/falcon_csaxs.py b/ophyd_devices/epics/devices/falcon_csaxs.py index b81faf3..aa5ab54 100644 --- a/ophyd_devices/epics/devices/falcon_csaxs.py +++ b/ophyd_devices/epics/devices/falcon_csaxs.py @@ -21,14 +21,10 @@ logger = bec_logger.logger class FalconError(Exception): """Base class for exceptions in this module.""" - pass - class FalconTimeoutError(FalconError): """Raised when the Falcon does not respond in time.""" - pass - class DetectorState(enum.IntEnum): """Detector states for Falcon detector""" @@ -114,8 +110,8 @@ class FalconSetup(CustomDetectorMixin): """ - def __init__(self, parent: Device = None, *args, **kwargs) -> None: - super().__init__(parent=parent, *args, **kwargs) + def __init__(self, *args, parent: Device = None, **kwargs) -> None: + super().__init__(*args, parent=parent, **kwargs) def initialize_default_parameter(self) -> None: """ @@ -133,9 +129,9 @@ class FalconSetup(CustomDetectorMixin): readout_time = ( self.parent.scaninfo.readout_time if hasattr(self.parent.scaninfo, "readout_time") - else self.parent.get_min_readout() + else self.parent.MIN_READOUT ) - self.parent.readout_time = max(readout_time, self.parent.get_min_readout()) + self.parent.readout_time = max(readout_time, self.parent.MIN_READOUT) def initialize_detector(self) -> None: """ @@ -264,19 +260,19 @@ class FalconSetup(CustomDetectorMixin): done (bool): True if scan is finished successful (bool): True if scan was successful """ - pipe = self.parent._producer.pipeline() + pipe = self.parent.producer.pipeline() if successful is None: msg = messages.FileMessage(file_path=self.parent.filepath, done=done) else: msg = messages.FileMessage( file_path=self.parent.filepath, done=done, successful=successful ) - self.parent._producer.set_and_publish( + self.parent.producer.set_and_publish( MessageEndpoints.public_file(self.parent.scaninfo.scanID, self.parent.name), msg.dumps(), pipe=pipe, ) - self.parent._producer.set_and_publish( + self.parent.producer.set_and_publish( MessageEndpoints.file_event(self.parent.name), msg.dumps(), pipe=pipe ) pipe.execute() @@ -339,7 +335,7 @@ class FalconcSAXS(PSIDetectorBase): # specify Setup class custom_prepare_cls = FalconSetup # specify minimum readout time for detector - PSIDetectorBase.set_min_readout(3e-3) + MIN_READOUT = 3e-3 # specify class attributes dxp = Cpt(EpicsDXPFalcon, "dxp1:") diff --git a/ophyd_devices/epics/devices/pilatus_csaxs.py b/ophyd_devices/epics/devices/pilatus_csaxs.py index db64898..d7e1901 100644 --- a/ophyd_devices/epics/devices/pilatus_csaxs.py +++ b/ophyd_devices/epics/devices/pilatus_csaxs.py @@ -86,9 +86,9 @@ class PilatusSetup(CustomDetectorMixin): readout_time = ( self.parent.scaninfo.readout_time if hasattr(self.parent.scaninfo, "readout_time") - else self.parent.get_min_readout() + else self.parent.MIN_READOUT ) - self.parent.readout_time = max(readout_time, self.parent.get_min_readout()) + self.parent.readout_time = max(readout_time, self.parent.MIN_READOUT) def initialize_detector(self) -> None: """Initialize detector""" @@ -336,7 +336,7 @@ class PilatusSetup(CustomDetectorMixin): done (bool): True if scan is finished successful (bool): True if scan was successful """ - pipe = self.parent._producer.pipeline() + pipe = self.parent.producer.pipeline() if successful is None: msg = messages.FileMessage( file_path=self.parent.filepath, @@ -350,12 +350,12 @@ class PilatusSetup(CustomDetectorMixin): successful=successful, metadata={"input_path": self.parent.filepath_raw}, ) - self.parent._producer.set_and_publish( + self.parent.producer.set_and_publish( MessageEndpoints.public_file(self.parent.scaninfo.scanID, self.parent.name), msg.dumps(), pipe=pipe, ) - self.parent._producer.set_and_publish( + self.parent.producer.set_and_publish( MessageEndpoints.file_event(self.parent.name), msg.dumps(), pipe=pipe ) pipe.execute() @@ -422,7 +422,7 @@ class PilatuscSAXS(PSIDetectorBase): # specify Setup class custom_prepare_cls = PilatusSetup # specify minimum readout time for detector - PSIDetectorBase.set_min_readout(3e-3) + MIN_READOUT = 3e-3 # specify class attributes cam = ADCpt(SLSDetectorCam, "cam1:") diff --git a/ophyd_devices/epics/devices/psi_detector_base.py b/ophyd_devices/epics/devices/psi_detector_base.py index a4cfe89..7ccb273 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 -import threading from bec_lib.devicemanager import DeviceStatus import os @@ -163,7 +162,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 == True and self.parent.stopped == True: return False if timer > timeout: return False @@ -199,15 +198,15 @@ class PSIDetectorBase(Device): custom_prepare_cls = CustomDetectorMixin - _MIN_READOUT = 1e-3 + MIN_READOUT = 1e-3 - @classmethod - def get_min_readout(cls): - return cls._MIN_READOUT + # @classmethod + # def get_min_readout(cls): + # return cls._MIN_READOUT - @classmethod - def set_min_readout(cls, value): - cls._MIN_READOUT = value + # @classmethod + # def set_min_readout(cls, value): + # cls._MIN_READOUT = value # Specify which functions are revealed to the user in BEC client USER_ACCESS = [ @@ -243,8 +242,7 @@ class PSIDetectorBase(Device): # sim_mode True allows the class to be started without BEC running # Init variables self.sim_mode = sim_mode - self._lock = threading.RLock() - self._stopped = False + self.stopped = False self.name = name self.service_cfg = None self.std_client = None @@ -264,7 +262,7 @@ class PSIDetectorBase(Device): self.device_manager = bec_utils.DMMock() base_path = kwargs["basepath"] if "basepath" in kwargs else "~/Data10/" self.service_cfg = {"base_path": os.path.expanduser(base_path)} - self._producer = self.device_manager.producer + self.producer = self.device_manager.producer self._update_scaninfo() self._update_filewriter() self._init() @@ -307,7 +305,7 @@ class PSIDetectorBase(Device): return super().stage() # Reset flag for detector stopped - self._stopped = False + self.stopped = False # Load metadata of the scan self.scaninfo.load_scan_metadata() # Prepare detector and file writer @@ -328,7 +326,7 @@ class PSIDetectorBase(Device): """ Unstage device in preparation for a scan - Returns directly if self._stopped, + Returns directly if self.stopped, otherwise checks with self._finished if data acquisition on device finished (an was successful) @@ -341,12 +339,12 @@ class PSIDetectorBase(Device): List(object): list of objects that were unstaged """ self.custom_prepare.check_scanID() - if self._stopped == True: + if self.stopped == True: return super().unstage() self.custom_prepare.finished() state = True self.custom_prepare.publish_file_location(done=state, successful=state) - self._stopped = False + self.stopped = False return super().unstage() def stop(self, *, success=False) -> None: @@ -360,4 +358,4 @@ class PSIDetectorBase(Device): self.custom_prepare.stop_detector() self.custom_prepare.stop_detector_backend() super().stop(success=success) - self._stopped = True + self.stopped = True diff --git a/tests/test_eiger9m_csaxs.py b/tests/test_eiger9m_csaxs.py index a461582..cea1c0d 100644 --- a/tests/test_eiger9m_csaxs.py +++ b/tests/test_eiger9m_csaxs.py @@ -278,7 +278,7 @@ def test_stage( # TODO consider putting energy as variable in scaninfo mock_det.device_manager.add_device("mokev", value=12.4) mock_det.cam.beam_energy.put(scaninfo["mokev"]) - mock_det._stopped = stopped + mock_det.stopped = stopped mock_det.cam.detector_state._read_pv.mock_data = detector_state with mock.patch.object(mock_det.custom_prepare, "prepare_data_backend") as mock_prep_fw: mock_det.filepath = scaninfo["filepath"] @@ -393,15 +393,15 @@ def test_unstage( with mock.patch.object(mock_det.custom_prepare, "finished") as mock_finished, mock.patch.object( mock_det.custom_prepare, "publish_file_location" ) as mock_publish_file_location: - mock_det._stopped = stopped + mock_det.stopped = stopped if expected_exception: mock_det.unstage() - assert mock_det._stopped is True + assert mock_det.stopped is True else: mock_det.unstage() mock_finished.assert_called_once() mock_publish_file_location.assert_called_with(done=True, successful=True) - assert mock_det._stopped is False + assert mock_det.stopped is False def test_stop_detector_backend(mock_det): @@ -436,15 +436,15 @@ def test_publish_file_location(mock_det, scaninfo): mock.call( MessageEndpoints.public_file(scaninfo["scanID"], mock_det.name), msg, - pipe=mock_det._producer.pipeline.return_value, + pipe=mock_det.producer.pipeline.return_value, ), mock.call( MessageEndpoints.file_event(mock_det.name), msg, - pipe=mock_det._producer.pipeline.return_value, + pipe=mock_det.producer.pipeline.return_value, ), ] - assert mock_det._producer.set_and_publish.call_args_list == expected_calls + assert mock_det.producer.set_and_publish.call_args_list == expected_calls def test_stop(mock_det): @@ -456,7 +456,7 @@ def test_stop(mock_det): mock_det.stop() mock_stop_det.assert_called_once() mock_stop_detector_backend.assert_called_once() - assert mock_det._stopped is True + assert mock_det.stopped is True @pytest.mark.parametrize( @@ -520,13 +520,13 @@ def test_finished(mock_det, stopped, cam_state, daq_status, scaninfo, expected_e with pytest.raises(Exception): mock_det.timeout = 0.1 mock_det.custom_prepare.finished() - assert mock_det._stopped is stopped + assert mock_det.stopped is stopped mock_stop_backend.assert_called() mock_stop_det.assert_called_once() else: mock_det.custom_prepare.finished() if stopped: - assert mock_det._stopped is stopped + assert mock_det.stopped is stopped mock_stop_backend.assert_called() mock_stop_det.assert_called_once() diff --git a/tests/test_falcon_csaxs.py b/tests/test_falcon_csaxs.py index c9b2b2b..6d76774 100644 --- a/tests/test_falcon_csaxs.py +++ b/tests/test_falcon_csaxs.py @@ -223,15 +223,15 @@ def test_publish_file_location(mock_det, scaninfo): mock.call( MessageEndpoints.public_file(scaninfo["scanID"], mock_det.name), msg, - pipe=mock_det._producer.pipeline.return_value, + pipe=mock_det.producer.pipeline.return_value, ), mock.call( MessageEndpoints.file_event(mock_det.name), msg, - pipe=mock_det._producer.pipeline.return_value, + pipe=mock_det.producer.pipeline.return_value, ), ] - assert mock_det._producer.set_and_publish.call_args_list == expected_calls + assert mock_det.producer.set_and_publish.call_args_list == expected_calls @pytest.mark.parametrize( @@ -281,16 +281,16 @@ def test_unstage( with mock.patch.object(mock_det.custom_prepare, "finished") as mock_finished, mock.patch.object( mock_det.custom_prepare, "publish_file_location" ) as mock_publish_file_location: - mock_det._stopped = stopped + mock_det.stopped = stopped if expected_abort: mock_det.unstage() - assert mock_det._stopped == stopped + assert mock_det.stopped is stopped assert mock_publish_file_location.call_count == 0 else: mock_det.unstage() mock_finished.assert_called_once() mock_publish_file_location.assert_called_with(done=True, successful=True) - assert mock_det._stopped == False + assert mock_det.stopped is stopped def test_stop(mock_det): @@ -302,7 +302,7 @@ def test_stop(mock_det): mock_det.stop() mock_stop_det.assert_called_once() mock_stop_detector_backend.assert_called_once() - assert mock_det._stopped == True + assert mock_det.stopped is True @pytest.mark.parametrize( @@ -318,7 +318,7 @@ def test_finished(mock_det, stopped, scaninfo): ) as mock_stop_det, mock.patch.object( mock_det.custom_prepare, "stop_detector_backend" ) as mock_stop_file_writer: - mock_det._stopped = stopped + mock_det.stopped = stopped mock_det.dxp.current_pixel._read_pv.mock_data = int( scaninfo["num_points"] * scaninfo["frames_per_trigger"] ) @@ -328,6 +328,6 @@ def test_finished(mock_det, stopped, scaninfo): mock_det.scaninfo.frames_per_trigger = scaninfo["frames_per_trigger"] mock_det.scaninfo.num_points = scaninfo["num_points"] mock_det.custom_prepare.finished() - assert mock_det._stopped == stopped + assert mock_det.stopped is stopped mock_stop_det.assert_called_once() mock_stop_file_writer.assert_called_once() diff --git a/tests/test_pilatus_csaxs.py b/tests/test_pilatus_csaxs.py index e8fdf08..89dac10 100644 --- a/tests/test_pilatus_csaxs.py +++ b/tests/test_pilatus_csaxs.py @@ -114,7 +114,7 @@ def test_stage( mock_det.scaninfo.frames_per_trigger = scaninfo["frames_per_trigger"] mock_det.filewriter.compile_full_filename.return_value = scaninfo["filepath"] mock_det.device_manager.add_device("mokev", value=12.4) - mock_det._stopped = stopped + mock_det.stopped = stopped with mock.patch.object( mock_det.custom_prepare, "prepare_data_backend" ) as mock_data_backend, mock.patch.object( @@ -218,15 +218,15 @@ def test_publish_file_location(mock_det, scaninfo): mock.call( MessageEndpoints.public_file(scaninfo["scanID"], mock_det.name), msg, - pipe=mock_det._producer.pipeline.return_value, + pipe=mock_det.producer.pipeline.return_value, ), mock.call( MessageEndpoints.file_event(mock_det.name), msg, - pipe=mock_det._producer.pipeline.return_value, + pipe=mock_det.producer.pipeline.return_value, ), ] - assert mock_det._producer.set_and_publish.call_args_list == expected_calls + assert mock_det.producer.set_and_publish.call_args_list == expected_calls @pytest.mark.parametrize( @@ -451,15 +451,15 @@ def test_unstage( with mock.patch.object(mock_det.custom_prepare, "finished") as mock_finished, mock.patch.object( mock_det.custom_prepare, "publish_file_location" ) as mock_publish_file_location: - mock_det._stopped = stopped + mock_det.stopped = stopped if expected_exception: mock_det.unstage() - assert mock_det._stopped == True + assert mock_det.stopped is True else: mock_det.unstage() mock_finished.assert_called_once() mock_publish_file_location.assert_called_with(done=True, successful=True) - assert mock_det._stopped == False + assert mock_det.stopped is False def test_stop(mock_det): @@ -474,7 +474,7 @@ def test_stop(mock_det): mock_stop_det.assert_called_once() mock_stop_file_writer.assert_called_once() mock_close_file_writer.assert_called_once() - assert mock_det._stopped == True + assert mock_det.stopped is True @pytest.mark.parametrize( @@ -506,19 +506,19 @@ def test_finished(mock_det, stopped, mcs_stage_state, expected_exception): mock_det.custom_prepare, "close_file_writer" ) as mock_close_file_writer: mock_dm.devices.mcs.obj._staged = mcs_stage_state - mock_det._stopped = stopped + mock_det.stopped = stopped if expected_exception: with pytest.raises(Exception): mock_det.timeout = 0.1 mock_det.custom_prepare.finished() - assert mock_det._stopped == stopped + assert mock_det.stopped is stopped mock_stop_file_friter.assert_called() mock_stop_det.assert_called_once() mock_close_file_writer.assert_called_once() else: mock_det.custom_prepare.finished() if stopped: - assert mock_det._stopped == stopped + assert mock_det.stopped is stopped mock_stop_file_friter.assert_called() mock_stop_det.assert_called_once()