mirror of
https://github.com/bec-project/ophyd_devices.git
synced 2025-06-24 19:51:09 +02:00
refactor: restructured class
This commit is contained in:
@ -1,47 +1,87 @@
|
|||||||
""" Class for EpicsMotorRecord stages for tomography purposes"""
|
""" Class for EpicsMotorRecord rotation stages for omography applications."""
|
||||||
|
|
||||||
from ophyd import EpicsMotor
|
from ophyd import EpicsMotor
|
||||||
from ophyd import Component
|
from ophyd import Component
|
||||||
from ophyd_devices.utils import bec_utils
|
from ophyd_devices.utils import bec_utils
|
||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
class TomoRotation(ABC):
|
|
||||||
|
|
||||||
def __init__(*args, parent=None, **kwargs):
|
class RotationBaseError(Exception):
|
||||||
self.parent._has_mod360 = False
|
"""Error specific for TomoRotationBase"""
|
||||||
self.parent._has_freerun = False
|
|
||||||
|
|
||||||
def apply_mod360(self)->None:
|
|
||||||
"""to be overriden by children"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class EpicsMotorTomoRotationError(Exception):
|
class ReadOnlyError(RotationBaseError):
|
||||||
"""Error specific for EpicsMotorTomoRotation"""
|
"""ReadOnly Error specific to TomoRotationBase"""
|
||||||
|
|
||||||
class TomoRotationEpics(TomoRotation):
|
|
||||||
|
|
||||||
def __init__(*args, parent=None, **kwargs):
|
class EpicsMotorRotationError(Exception):
|
||||||
|
"""Error specific for TomoRotationBase"""
|
||||||
|
|
||||||
|
|
||||||
|
class RotationDeviceMixin:
|
||||||
|
|
||||||
|
def __init__(self, *args, parent=None, **kwargs):
|
||||||
|
"""Mixin class to add rotation specific methods and properties.
|
||||||
|
This class should not be used directly, but inherited by the children classes and implement the methods if needed.
|
||||||
|
Args:
|
||||||
|
|
||||||
|
parent: parent class needs to inherit from TomoRotationBase
|
||||||
|
|
||||||
|
Methods:
|
||||||
|
These methods need to be overridden by the children classes
|
||||||
|
|
||||||
|
apply_mod360: Apply modulos 360 to the current position
|
||||||
|
get_valid_rotation_modes: Get valid rotation modes for the implemented motor
|
||||||
|
"""
|
||||||
super().__init__(*args, parent=parent, **kwargs)
|
super().__init__(*args, parent=parent, **kwargs)
|
||||||
self.parent._has_mod360 = False
|
self.parent._has_mod360 = False
|
||||||
self.parent._has_freerun = False
|
self.parent._has_freerun = False
|
||||||
|
self._valid_rotation_modes = []
|
||||||
|
|
||||||
|
def apply_mod360(self) -> None:
|
||||||
|
"""Method to apply the modulus 360 operation on the specific device.
|
||||||
|
|
||||||
|
Children classes should override this method
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_valid_rotation_modes(self) -> list[str]:
|
||||||
|
"""Get valid rotation modes for the implemented motor
|
||||||
|
|
||||||
|
Chilren classes should ensure that all valid rotation modes are written
|
||||||
|
in the _valid_rotation_modes list as strings
|
||||||
|
"""
|
||||||
|
return self._valid_rotation_modes
|
||||||
|
|
||||||
|
|
||||||
def apply_mod360(self)->None:
|
class EpicsMotorRotationMixin(RotationDeviceMixin):
|
||||||
"""tbd"""
|
|
||||||
if self.has_mod360 and self.allow_mod360.get():
|
def __init__(self, *args, parent=None, **kwargs):
|
||||||
cur_val = self.user_readback.get()
|
"""Mixin class implementing rotation specific functionality and parameter for EpicsMotorRecord.
|
||||||
new_val = cur_val %360
|
|
||||||
|
Args:
|
||||||
|
parent: parent class should inherit from TomoRotationBase
|
||||||
|
"""
|
||||||
|
super().__init__(*args, parent=parent, **kwargs)
|
||||||
|
self.parent._has_mod360 = True
|
||||||
|
self.parent._has_freerun = True
|
||||||
|
self._valid_rotation_modes = ["target", "radiography"]
|
||||||
|
|
||||||
|
def apply_mod360(self) -> None:
|
||||||
|
"""Apply modulos 360 to the current position using the set_current_position method of ophyd EpicsMotor."""
|
||||||
|
if self.parent.has_mod360 and self.parent.allow_mod360.get():
|
||||||
|
cur_val = self.parent.user_readback.get()
|
||||||
|
new_val = cur_val % 360
|
||||||
try:
|
try:
|
||||||
self.set_current_position(new_val)
|
self.parent.set_current_position(new_val)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise(exc)
|
error_msg = f"Failed to set net position {new_val} from {cur_val} on device {self.parent.name} with error {exc}"
|
||||||
|
raise EpicsMotorRotationError(error_msg) from exc
|
||||||
|
|
||||||
# def get_valid_rotation_modes(self) -> None:
|
def get_valid_rotation_modes(self) -> None:
|
||||||
|
"""Get valid rotation modes for Epics motor"""
|
||||||
|
return self._valid_rotation_modes
|
||||||
|
|
||||||
|
|
||||||
class EpicsMotorTomoRotation(EpicsMotor):
|
class RotationBase:
|
||||||
|
|
||||||
allow_mod360 = Component(
|
allow_mod360 = Component(
|
||||||
bec_utils.ConfigSignal,
|
bec_utils.ConfigSignal,
|
||||||
@ -50,22 +90,21 @@ class EpicsMotorTomoRotation(EpicsMotor):
|
|||||||
config_storage_name="tomo_config",
|
config_storage_name="tomo_config",
|
||||||
)
|
)
|
||||||
|
|
||||||
USER_ACCESS = ["apply_mod360"]
|
USER_ACCESS = ["apply_mod360", "get_valid_rotation_modes"]
|
||||||
|
|
||||||
custom_prepare_cls = TomoRotationEpics
|
custom_prepare_cls = RotationDeviceMixin
|
||||||
|
|
||||||
def __init__(self, name:str, prefix:str, *args, tomo_rotation_config:dict=None, **kwargs):
|
def __init__(self, *args, name: str, tomo_rotation_config: dict = None, **kwargs):
|
||||||
|
self.name = name
|
||||||
super().__init__(name=name, prefix=prefix, *args, **kwargs)
|
self.tomo_config = {"allow_mod360": False}
|
||||||
self.tomo_config={'allow_mod360' : False}
|
|
||||||
self._has_mod360 = None
|
self._has_mod360 = None
|
||||||
self._has_freerun = None
|
self._has_freerun = None
|
||||||
|
|
||||||
#To be discussed what is the appropriate way
|
for k, v in tomo_rotation_config.items():
|
||||||
[self.tomo_config.update({key : value}) for key,value in tomo_rotation_config.items() if tomo_rotation_config ]
|
self.tomo_config[k] = v
|
||||||
|
|
||||||
self.custom_prepare = self.custom_prepare_cls(parent=self)
|
self.custom_prepare = self.custom_prepare_cls(parent=self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_mod360(self) -> bool:
|
def has_mod360(self) -> bool:
|
||||||
"""tbd"""
|
"""tbd"""
|
||||||
@ -73,40 +112,35 @@ class EpicsMotorTomoRotation(EpicsMotor):
|
|||||||
|
|
||||||
@has_mod360.setter
|
@has_mod360.setter
|
||||||
def has_mod360(self):
|
def has_mod360(self):
|
||||||
raise(f'ReadOnly Property of {self.name}')
|
raise ReadOnlyError(f"ReadOnly Property of {self.name}")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_freerun(self) -> bool:
|
def has_freerun(self) -> bool:
|
||||||
|
"""Property to check if the motor has freerun option"""
|
||||||
return self._has_freerun
|
return self._has_freerun
|
||||||
|
|
||||||
@has_freerun.setter
|
@has_freerun.setter
|
||||||
def has_freerun(self):
|
def has_freerun(self):
|
||||||
raise(f'ReadOnly Property of {self.name}')
|
"""Property setter for has_freerun"""
|
||||||
|
raise ReadOnlyError(f"ReadOnly Property of {self.name}")
|
||||||
@abstractmethod
|
|
||||||
def apply_mod360(self):
|
|
||||||
"""to be implemented"""
|
|
||||||
|
|
||||||
def apply_mod360(self):
|
def apply_mod360(self):
|
||||||
|
"""Apply modulos 360 to the current position"""
|
||||||
self.custom_prepare.apply_mod360()
|
self.custom_prepare.apply_mod360()
|
||||||
|
|
||||||
# def get_valid_rotation_modes(self):
|
def get_valid_rotation_modes(self):
|
||||||
# return self.custom_prepare.get_valid_rotation_modes(self)
|
"""Get valid rotation modes for the implemented motor"""
|
||||||
|
return self.custom_prepare.get_valid_rotation_modes()
|
||||||
|
|
||||||
|
|
||||||
|
class EpicsMotorTomoRotation(EpicsMotor, RotationBase):
|
||||||
|
|
||||||
|
custom_prepare_cls = EpicsMotorRotationMixin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, name: str, prefix: str, *args, tomo_rotation_config: dict = None, **kwargs):
|
||||||
|
|
||||||
|
super().__init__(
|
||||||
|
name=name, prefix=prefix, tomo_rotation_config=tomo_rotation_config, *args, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
self.custom_prepare = self.custom_prepare_cls(*args, parent=self, **kwargs)
|
||||||
|
Reference in New Issue
Block a user