Beispiel #1
0
    def set_single(self, pv, value, throw=True):
        """Set the value of a given PV.

        Args:
            pv (string): PV to set the value of.
            value (object): The value to set the PV to.
            throw (bool): On failure: if True, raise ControlSystemException: if
                           False, log a warning.

        Returns:
            bool: True for success, False for failure

        Raises:
            ControlSystemException: if it cannot connect to the specified PV.
        """
        try:
            caput(pv, value, timeout=self._timeout, throw=True)
            return True
        except ca_nothing:
            error_msg = f"Cannot connect to {pv}."
            if throw:
                raise ControlSystemException(error_msg)
            else:
                logging.warning(error_msg)
                return False
Beispiel #2
0
    def get_multiple(self, pvs, throw=True):
        """Get the value for given PVs.

        Args:
            pvs (sequence): PVs to get values of.
            throw (bool): On failure: if True, raise ControlSystemException; if
                           False, None will be returned for any PV that fails
                           and a warning will be logged.

        Returns:
            sequence: the current values of the PVs.

        Raises:
            ControlSystemException: if it cannot connect to one or more PVs.
        """
        results = caget(pvs, timeout=self._timeout, throw=False)
        return_values = []
        failures = []
        for result in results:
            if isinstance(result, ca_nothing):
                logging.warning(f"Cannot connect to {result.name}.")
                if throw:
                    failures.append(result)
                else:
                    return_values.append(None)
            else:
                return_values.append(result)
        if throw and failures:
            raise ControlSystemException(
                f"{len(failures)} caget calls failed.")
        return return_values
Beispiel #3
0
    def get_value(self, field, handle=None, throw=True):
        """Get the value for a field on the Pytac lattice.

        Args:
            field (str): The requested field.
            handle (str, optional): Handle is not needed and is only here to
                                     conform with the structure of the
                                     DataSource base class.
            throw (bool, optional): If the check for completion of outstanding
                                     calculations times out, then:
                                     if True, raise a ControlSystemException;
                                     if False, log a warning and return the
                                     potentially out of date data anyway.

        Returns:
            float: The value of the specified field on this data source.

        Raises:
            FieldException: if the specified field does not exist.
            ControlSystemException: if the calculation completion check fails,
                                     and throw is True.
        """
        # Wait for any outstanding calculations to conclude, to ensure they are
        # complete before a value is returned; if the wait times out then raise
        # an error message or log a warning according to the value of throw.
        if not self._atsim.wait_for_calculations():
            error_msg = ("Check for completion of outstanding "
                         "calculations timed out.")
            if throw:
                raise ControlSystemException(error_msg)
            else:
                logging.warning("Potentially out of date data returned. " +
                                error_msg)
        if field in list(self._field_funcs.keys()):
            # The orbit x_phase and y_phase, and the eta prime_x and prime_y
            # fields are represented by 'px' or 'py' in the ATSimulator data
            # handling functions.
            if (field.startswith('phase')) or (field.find('prime') != -1):
                return self._field_funcs[field]('p' + field[-1])
            elif field.endswith('x'):
                return self._field_funcs[field]('x')
            elif field.endswith('y'):
                return self._field_funcs[field]('y')
            else:
                return self._field_funcs[field]()
        else:
            raise FieldException("Lattice data source {0} does not have field "
                                 "{1}".format(self, field))
Beispiel #4
0
    def get_value(self, field, handle=None, throw=True):
        """Get the value for a field.

        Args:
            field (str): The requested field.
            handle (str, optional): Handle is not needed and is only here to
                                     conform with the structure of the
                                     DataSource base class.
            throw (bool, optional): If the check for completion of outstanding
                                     calculations times out, then:
                                     if True, raise a ControlSystemException;
                                     if False, log a warning and return the
                                     potentially out of date data anyway.

        Returns:
            float: The value of the specified field on this data source.

        Raises:
            FieldException: if the specified field does not exist.
            ControlSystemException: if the calculation completion check fails,
                                     and throw is True.
        """
        # Wait for any outstanding calculations to conclude, to ensure they are
        # complete before a value is returned; if the wait times out then raise
        # an error message or log a warning according to the value of throw.
        if not self._atsim.wait_for_calculations():
            error_msg = ("Check for completion of outstanding "
                         "calculations timed out.")
            if throw:
                raise ControlSystemException(error_msg)
            else:
                logging.warning("Potentially out of date data returned. " +
                                error_msg)
        # Again we assume that every set field has a corresponding get field.
        if field in self._fields:
            return self._get_field_funcs[field]()
        else:
            raise FieldException("No field {0} on AT element {1}."
                                 .format(field, self._at_element))
Beispiel #5
0
    def set_multiple(self, pvs, values, throw=True):
        """Set the values for given PVs.

        Args:
            pvs (sequence): PVs to set the values of.
            values (sequence): values to set to the PVs.
            throw (bool): On failure, if True raise ControlSystemException, if
                           False return a list of True and False values
                           corresponding to successes and failures and log a
                           warning for each PV that fails.

        Returns:
            list(bool): True for success, False for failure; only returned if
                         throw is false and a failure occurs.

        Raises:
            ValueError: if the lists of values and PVs are diffent lengths.
            ControlSystemException: if it cannot connect to one or more PVs.
        """
        if len(pvs) != len(values):
            raise ValueError("Please enter the same number of values as PVs.")
        status = caput(pvs, values, timeout=self._timeout, throw=False)
        return_values = []
        failures = []
        for stat in status:
            if not stat.ok:
                return_values.append(False)
                failures.append(stat)
                logging.warning(f"Cannot connect to {stat.name}.")
            else:
                return_values.append(True)
        if failures:
            if throw:
                raise ControlSystemException(
                    f"{len(failures)} caput calls failed.")
            else:
                return return_values
Beispiel #6
0
    def get_single(self, pv, throw=True):
        """Get the value of a given PV.

        Args:
            pv (string): The process variable given as a string. It can be a
                         readback or a setpoint PV.
            throw (bool): On failure: if True, raise ControlSystemException; if
                           False, return None and log a warning.

        Returns:
            object: the current value of the given PV.

        Raises:
            ControlSystemException: if it cannot connect to the specified PV.
        """
        try:
            return caget(pv, timeout=self._timeout, throw=True)
        except ca_nothing:
            error_msg = f"Cannot connect to {pv}."
            if throw:
                raise ControlSystemException(error_msg)
            else:
                logging.warning(error_msg)
                return None
Beispiel #7
0
def load(mode, control_system=None, directory=None, symmetry=None):
    """Load the elements of a lattice from a directory.

    Args:
        mode (str): The name of the mode to be loaded.
        control_system (ControlSystem): The control system to be used. If none
                                         is provided an EpicsControlSystem will
                                         be created.
        directory (str): Directory where to load the files from. If no
                          directory is given the data directory at the root of
                          the repository is used.
        symmetry (int): The symmetry of the lattice (the number of cells).

    Returns:
        Lattice: The lattice containing all elements.

    Raises:
        ControlSystemException: if the default control system, cothread, is not
                                 installed.
    """
    try:
        if control_system is None:
            # Don't import epics unless we need it to avoid unnecessary
            # installation of cothread
            from pytac import cothread_cs

            control_system = cothread_cs.CothreadControlSystem()
    except ImportError:
        raise ControlSystemException("Please install cothread to load a "
                                     "lattice using the default control "
                                     "system (found in cothread_cs.py).")
    if directory is None:
        directory = Path(__file__).resolve().parent / "data"
    mode_dir = directory / mode
    lat = EpicsLattice(mode, control_system, symmetry=symmetry)
    lat.set_data_source(data_source.DeviceDataSource(), pytac.LIVE)
    with csv_loader(mode_dir / ELEMENTS_FILENAME) as csv_reader:
        for item in csv_reader:
            name = item["name"] if item["name"] != "" else None
            e = element.EpicsElement(float(item["length"]), item["type"], name,
                                     lat)
            e.add_to_family(item["type"])
            e.set_data_source(data_source.DeviceDataSource(), pytac.LIVE)
            lat.add_element(e)
    with csv_loader(mode_dir / EPICS_DEVICES_FILENAME) as csv_reader:
        for item in csv_reader:
            name = item["name"]
            index = int(item["el_id"])
            get_pv = item["get_pv"] if item["get_pv"] else None
            set_pv = item["set_pv"] if item["set_pv"] else None
            pve = True
            d = EpicsDevice(name, control_system, pve, get_pv, set_pv)
            # Devices on index 0 are attached to the lattice not elements.
            target = lat if index == 0 else lat[index - 1]
            target.add_device(item["field"], d, DEFAULT_UC)
        # Add basic devices to the lattice.
        positions = []
        for elem in lat:
            positions.append(elem.s)
        lat.add_device("s_position", SimpleDevice(positions, readonly=True),
                       True)
    simple_devices_file = mode_dir / SIMPLE_DEVICES_FILENAME
    if simple_devices_file.exists():
        with csv_loader(simple_devices_file) as csv_reader:
            for item in csv_reader:
                index = int(item["el_id"])
                field = item["field"]
                value = float(item["value"])
                readonly = item["readonly"].lower() == "true"
                # Devices on index 0 are attached to the lattice not elements.
                target = lat if index == 0 else lat[index - 1]
                target.add_device(field, SimpleDevice(value,
                                                      readonly=readonly), True)
    with csv_loader(mode_dir / FAMILIES_FILENAME) as csv_reader:
        for item in csv_reader:
            lat[int(item["el_id"]) - 1].add_to_family(item["family"])
    unitconv_file = mode_dir / UNITCONV_FILENAME
    if unitconv_file.exists():
        load_unitconv(mode_dir, lat)
    return lat