feat: Fix module and deprecate rotation base class
CI for tomcat_bec / test (push) Failing after 43s
CI for tomcat_bec / test (pull_request) Failing after 35s

This commit is contained in:
2026-07-28 09:52:44 +02:00
parent 73d51bb4df
commit a82876b66c
3 changed files with 145 additions and 2 deletions
@@ -0,0 +1,143 @@
from abc import ABC, abstractmethod
from bec_lib import bec_logger
from ophyd import Component as Cpt
from ophyd import EpicsMotor
from typeguard import typechecked
from typing import Protocol, runtime_checkable
from ophyd_devices.utils.bec_utils import ConfigSignal
logger = bec_logger.logger
class OphydRotationBaseError(Exception):
"""Exception specific for implementation of rotation stages."""
@runtime_checkable
class BECRotationProtocol(Protocol):
"""Protocol which defines functionality for a tomography stage for ophyd devices"""
allow_mod360: Cpt
"""Signal to define whether mod360 operations are allowed. """
@property
def has_mod360(self) -> bool:
"""Property to check if the motor has mod360 option
Returns:
bool: True if mod360 is possible on device, False otherwise
"""
@property
def has_freerun(self) -> bool:
"""Property to check if the motor has freerun option
Returns:
bool: True if freerun is allowed, False otherwise
"""
@property
def valid_rotation_modes(self) -> list[str]:
"""Method to get the valid rotation modes for the implemented motor.
Returns:
list: List of strings with valid rotation modes
"""
def apply_mod360(self) -> None:
"""Method to apply the modulus 360 operation on the specific device.
Childrens should override this method
"""
class OphydRotationBase(BECRotationProtocol, ABC):
allow_mod360 = Cpt(ConfigSignal, name="allow_mod360", value=False, kind="config")
def __init__(self, *args, **kwargs):
"""
Base class to implement functionality specific for rotation devices.
Childrens should override the instance attributes:
- has_mod360
- has_freerun
- valid_rotation_modes
"""
# pylint: disable=protected-access
self._has_mod360 = False
self._has_freerun = False
self._valid_rotation_modes = []
if "allow_mod360" in kwargs:
if not isinstance(kwargs["allow_mod360"], bool):
raise ValueError("allow_mod360 must be a boolean")
self.allow_mod360.put(kwargs["allow_mod360"])
super().__init__(*args, **kwargs)
@abstractmethod
def apply_mod360(self) -> None:
"""Method to apply the modulus 360 operation on the specific device.
Childrens should override this method
"""
@property
def has_mod360(self) -> bool:
"""Property to check if the device has mod360 operation.
ReadOnly property, childrens should override this method.
"""
return self._has_mod360
@property
def has_freerun(self) -> bool:
"""Property to check if the device has freerun operation.
ReadOnly property, childrens should override this method.
"""
return self._has_freerun
@property
def valid_rotation_modes(self) -> list:
"""Method to get the valid rotation modes for the specific device."""
return self._valid_rotation_modes
@typechecked
@valid_rotation_modes.setter
def valid_rotation_modes(self, value: list[str]):
"""Method to set the valid rotation modes for the specific device."""
self._valid_rotation_modes = value
return self._valid_rotation_modes
# pylint: disable=too-many-ancestors
class EpicsRotationBase(OphydRotationBase, EpicsMotor):
"""Class for Epics rotation devices."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._has_freerun = True
self._has_freerun = True
self._valid_rotation_modes = ["target", "radiography"]
def apply_mod360(self) -> None:
"""Apply modulos 360 operation for EpicsMotorRecord.
EpicsMotor has the function "set_current_position" which can be used for this purpose.
In addition, there is a check if mod360 is allowed and available.
"""
if self.has_mod360 and self.allow_mod360.get():
cur_val = self.user_readback.get()
new_val = cur_val % 360
try:
self.set_current_position(new_val)
except Exception as exc:
error_msg = f"Failed to set new position {new_val} from {cur_val} on device {self.name} with error {exc}"
raise OphydRotationBaseError(error_msg) from exc
return
logger.info(
f"Did not apply mod360 for device {self.name} with has_mod={self.has_mod360} and allow_mod={self.allow_mod360.get()}"
)
+2 -2
View File
@@ -1,4 +1,4 @@
""" Module for Tomcat rotation motors.
"""Module for Tomcat rotation motors.
The following classes implement the rotation motors for:
@@ -11,7 +11,7 @@ import time
import numpy as np
from ophyd import DeviceStatus
from ophyd_devices.interfaces.base_classes.ophyd_rotation_base import EpicsRotationBase
from tomcat_bec.devices.rotation_base.ophyd_rotation_base import EpicsRotationBase
from ophyd_devices.interfaces.protocols.bec_protocols import BECFlyerProtocol, BECScanProtocol