Source code for pytac.device

"""The device class used to represent a particular function of an accelerator
element.

A physical element in an accelerator may have multiple devices: an example at
DLS is a sextupole magnet that contains also horizontal and vertical corrector
magnets and a skew quadrupole.
"""
import pytac
from pytac.exceptions import DataSourceException, HandleException


[docs]class Device(object): """A representation of a property of an element associated with a field. Typically a control system will be used to set and get values on a device. **Methods:** """
[docs] def is_enabled(self): """Whether the device is enabled. Returns: bool: whether the device is enabled. """ raise NotImplementedError()
[docs] def get_value(self, handle, throw): """Read the value from the device. Args: handle (str): pytac.SP or pytac.RB. throw (bool): On failure, if True raise ControlSystemException, if False None will be returned for any PV that fails and log a warning. Returns: float: the value of the PV. """ raise NotImplementedError()
[docs] def set_value(self, value, throw): """Set the value on the device. Args: value (float): the value to set. throw (bool): On failure, if True raise ControlSystemException, if False log a warning. """ raise NotImplementedError()
[docs]class BasicDevice(Device): """A basic implementation of the device class. This device does not have a PV associated with it, nor does it interact with a simulator. In short this device acts as simple storage for data that rarely changes, as it is not affected by changes to other aspects of the accelerator. """ def __init__(self, value, enabled=True): """ Args: value (numeric): can be a number or a list of numbers. enabled (bool-like): Whether the device is enabled. May be a PvEnabler object. """ self.value = value self._enabled = enabled
[docs] def is_enabled(self): """Whether the device is enabled. Returns: bool: whether the device is enabled. """ return bool(self._enabled)
[docs] def get_value(self, handle=None, throw=None): """Read the value from the device. Args: handle (str): Irrelevant in this case as a control system is not used, only supported to conform with the base class. throw (bool): Irrelevant in this case as a control system is not used, only supported to conform with the base class. Returns: numeric: the value of the device. """ return self.value
[docs] def set_value(self, value, throw=None): """Set the value on the device. Args: value (numeric): the value to set. throw (bool): Irrelevant in this case as a control system is not used, only supported to conform with the base class. """ self.value = value
[docs]class EpicsDevice(Device): """An EPICS-aware device. Contains a control system, readback and setpoint PVs. A readback or setpoint PV is required when creating an epics device otherwise a DataSourceException is raised. The device is enabled by default. **Attributes:** Attributes: name (str): The prefix of EPICS PVs for this device. rb_pv (str): The EPICS readback PV. sp_pv (str): The EPICS setpoint PV. .. Private Attributes: _cs (ControlSystem): The control system object used to get and set the value of a PV. _enabled (bool-like): Whether the device is enabled. May be a PvEnabler object. """ def __init__(self, name, cs, enabled=True, rb_pv=None, sp_pv=None): """ Args: name (str): The prefix of EPICS PV for this device. cs (ControlSystem): The control system object used to get and set the value of a PV. enabled (bool-like): Whether the device is enabled. May be a PvEnabler object. rb_pv (str): The EPICS readback PV. sp_pv (str): The EPICS setpoint PV. Raises: DataSourceException: if no PVs are provided. **Methods:** """ if rb_pv is None and sp_pv is None: raise DataSourceException("At least one PV, either {0} or {1} is " "required when creating an EpicsDevice." .format(pytac.RB, pytac.SP)) self.name = name self._cs = cs self.rb_pv = rb_pv self.sp_pv = sp_pv self._enabled = enabled
[docs] def is_enabled(self): """Whether the device is enabled. Returns: bool: whether the device is enabled. """ return bool(self._enabled)
[docs] def get_value(self, handle, throw=True): """Read the value of a readback or setpoint PV. Args: handle (str): pytac.SP or pytac.RB. throw (bool): On failure, if True raise ControlSystemException, if False None will be returned for any PV that fails and log a warning. Returns: float: The value of the PV. Raises: HandleException: if the requested PV doesn't exist. """ if handle == pytac.RB and self.rb_pv: return self._cs.get_single(self.rb_pv, throw) elif handle == pytac.SP and self.sp_pv: return self._cs.get_single(self.sp_pv, throw) else: raise HandleException("Device {0} has no {1} PV.".format(self.name, handle))
[docs] def set_value(self, value, throw=True): """Set the device value. Args: value (float): The value to set. throw (bool): On failure, if True raise ControlSystemException, if False log a warning. Raises: HandleException: if no setpoint PV exists. """ if self.sp_pv is None: raise HandleException("Device {0} has no setpoint PV." .format(self.name)) else: self._cs.set_single(self.sp_pv, value, throw)
[docs] def get_pv_name(self, handle): """Get the PV name for the specified handle. Args: handle (str): The readback or setpoint handle to be returned. Returns: str: A readback or setpoint PV. Raises: HandleException: if the PV doesn't exist. """ if handle == pytac.RB and self.rb_pv: return self.rb_pv elif handle == pytac.SP and self.sp_pv: return self.sp_pv else: raise HandleException("Device {0} has no {1} PV.".format(self.name, handle))
[docs]class PvEnabler(object): """A PvEnabler class to check whether a device is enabled. The class will behave like True if the PV value equals enabled_value, and False otherwise. .. Private Attributes: _pv (str): The PV name. _enabled_value (str): The value for PV for which the device should be considered enabled. _cs (ControlSystem): The control system object. """ def __init__(self, pv, enabled_value, cs): """ Args: pv (str): The PV name. enabled_value (str): The value for PV for which the device should be considered enabled. cs (ControlSystem): The control system object. **Methods:** """ self._pv = pv self._enabled_value = str(int(float(enabled_value))) self._cs = cs def __nonzero__(self): """Used to override the 'if object' clause. Support for Python 2.7. Returns: bool: True if the device should be considered enabled. """ pv_value = self._cs.get_single(self._pv) return self._enabled_value == str(int(float(pv_value))) def __bool__(self): """Used to override the 'if object' clause. Support for Python 3.x. Returns: bool: True if the device should be considered enabled. """ return self.__nonzero__()