Source code for pytac.element

"""Module containing the element class."""
import pytac
from pytac.data_source import DataSourceManager
from pytac.exceptions import DataSourceException, FieldException


[docs]class Element(object): """Class representing one physical element in an accelerator lattice. An element has zero or more devices (e.g. quadrupole magnet) associated with each of its fields (e.g. 'b1' for a quadrupole). **Attributes:** Attributes: name (str): The name identifying the element. type_ (str): The type of the element. length (float): The length of the element in metres. families (set): The families this element is a member of. .. Private Attributes: _lattice (Lattice): The lattice to which the element belongs. _data_source_manager (DataSourceManager): A class that manages the data sources associated with this element. """ def __init__(self, length, element_type, name=None, lattice=None): """ Args: length (float): The length of the element. element_type (str): The type of the element. name (str): The unique identifier for the element in the ring. lattice (Lattice): The lattice to which the element belongs. **Methods:** """ self.name = name self.type_ = element_type self.length = length self.families = set() self._lattice = lattice self._data_source_manager = DataSourceManager() @property def index(self): """int: The element's index within the ring, starting at 1. """ if self._lattice is None: return None else: return self._lattice._elements.index(self) + 1 @property def s(self): """float: The element's start position within the lattice in metres. """ if self._lattice is None: return None else: return sum([el.length for el in self._lattice[:self.index - 1]]) @property def cell(self): """int: The lattice cell this element is within. N.B. If the element spans multiple cells then the cell it begins in is returned (lowest cell number). """ if self._lattice is None: return None elif self._lattice.cell_length is None: return None else: return int(self.s / self._lattice.cell_length) + 1 def __str__(self): """Return a representation of an element, as a string. Returns: str: A representation of an element. """ repn = "<Element " if self.name is not None: repn += "'{0}', ".format(self.name) if self.index is not None: repn += "index {0}, ".format(self.index) repn += "length {0} m, ".format(self.length) if self.cell is not None: repn += "cell {0}, ".format(self.cell) repn += "families {0}>".format(', '.join(f for f in self.families)) return repn __repr__ = __str__
[docs] def set_data_source(self, data_source, data_source_type): """Add a data source to the element. Args: data_source (DataSource): the data source to be set. data_source_type (str): the type of the data source being set pytac.LIVE or pytac.SIM. """ self._data_source_manager.set_data_source(data_source, data_source_type)
[docs] def get_fields(self): """Get the all fields defined on an element. Includes all fields defined by all data sources. Returns: dict: A dictionary of all the fields defined on an element, separated by data source(key). """ return self._data_source_manager.get_fields()
[docs] def add_device(self, field, device, uc): """Add device and unit conversion objects to a given field. A DeviceDataSource must be set before calling this method, this defaults to pytac.LIVE as that is the only data source that currently uses devices. Args: field (str): The key to store the unit conversion and device objects. device (Device): The device object used for this field. uc (UnitConv): The unit conversion object used for this field. Raises: DataSourceException: if no DeviceDataSource is set. """ try: self._data_source_manager.add_device(field, device, uc) except DataSourceException: raise DataSourceException("No device data source for field {0} on " "element {1}.".format(field, self))
[docs] def get_device(self, field): """Get the device for the given field. A DeviceDataSource must be set before calling this method, this defaults to pytac.LIVE as that is the only data source that currently uses devices. Args: field (str): The lookup key to find the device on an element. Returns: Device: The device on the given field. Raises: DataSourceException: if no DeviceDataSource is set. """ try: return self._data_source_manager.get_device(field) except DataSourceException: raise DataSourceException("No device data source for field {0} on " "element {1}.".format(field, self))
[docs] def get_unitconv(self, field): """Get the unit conversion option for the specified field. Args: field (str): The field associated with this conversion. Returns: UnitConv: The object associated with the specified field. Raises: FieldException: if no unit conversion object is present. """ try: return self._data_source_manager.get_unitconv(field) except FieldException: raise FieldException("No unit conversion option for field {0} on " "element {1}.".format(field, self))
[docs] def set_unitconv(self, field, uc): """Set the unit conversion option for the specified field. Args: field (str): The field associated with this conversion. uc (UnitConv): The unit conversion object to be set. """ self._data_source_manager.set_unitconv(field, uc)
[docs] def add_to_family(self, family): """Add the element to the specified family. Args: family (str): Represents the name of the family. """ self.families.add(family)
[docs] def get_value(self, field, handle=pytac.RB, units=pytac.DEFAULT, data_source=pytac.DEFAULT, throw=True): """Get the value for a field. Returns the value of a field on the element. This value is uniquely identified by a field and a handle. The returned value is either in engineering or physics units. The data_source flag returns either real or simulated values. Args: field (str): The requested field. handle (str): pytac.SP or pytac.RB. units (str): pytac.ENG or pytac.PHYS returned. data_source (str): pytac.LIVE or pytac.SIM. 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 requested field Raises: DataSourceException: if there is no data source on the given field. FieldException: if the element does not have the specified field. """ try: return self._data_source_manager.get_value(field, handle, units, data_source, throw) except DataSourceException: raise DataSourceException("No data source {0} on element {1}." .format(data_source, self)) except FieldException: raise FieldException("Element {0} does not have field {1}." .format(self, field))
[docs] def set_value(self, field, value, handle=pytac.SP, units=pytac.DEFAULT, data_source=pytac.DEFAULT, throw=True): """Set the value for a field. This value can be set on the machine or the simulation. Args: field (str): The requested field. value (float): The value to set. handle (str): pytac.SP or pytac.RB. units (str): pytac.ENG or pytac.PHYS. data_source (str): pytac.LIVE or pytac.SIM. throw (bool): On failure, if True raise ControlSystemException, if False log a warning. Raises: DataSourceException: if arguments are incorrect. FieldException: if the element does not have the specified field. """ try: self._data_source_manager.set_value(field, value, handle, units, data_source, throw) except DataSourceException: raise DataSourceException("No data source {0} on element {1}." .format(data_source, self)) except FieldException: raise FieldException("Element {0} does not have field {1}." .format(self, field))
[docs] def set_lattice(self, lattice): """Set the stored lattice reference for this element to the passed lattice object. Args: lattice (Lattice): lattice object to store a reference to. """ self._lattice = lattice
[docs]class EpicsElement(Element): """EPICS-aware element. Adds get_pv_name() method. **Methods:** """
[docs] def get_pv_name(self, field, handle): """Get PV name for the specified field and handle. Args: field (str): The requested field. handle (str): pytac.RB or pytac.SP. Returns: str: The readback or setpoint PV for the specified field. Raises: DataSourceException: if there is no data source for this field. FieldException: if the specified field doesn't exist. """ try: return (self._data_source_manager._data_sources[pytac.LIVE] .get_device(field).get_pv_name(handle)) except KeyError: raise DataSourceException("No data source for field {0} on " "element {1}.".format(field, self)) except AttributeError: raise DataSourceException("Cannot get PV for field {0} on element " "{1}, as basic devices do not have " "associated PV's.".format(field, self)) except FieldException: raise FieldException("No field {0} on element {1}.".format(field, self))