Ejemplo n.º 1
0
    def get_siblings_positions(self, use=None, write_pos=True):
        """Get the last positions for all siblings.
        If write_pos is True and a sibling has already been moved before,
        it's last write position is used. Otherwise its read position is used
        instead.

        :param use: the already calculated positions. If a sibling is in this
                    dictionary, the position stored here is used instead
        :type use: dict <PoolElement, :class:`~sardana.sardanavalue.SardanaValue` >
        :param write_pos: determines if should try to use the last set point
                          [default: True]
        :type write_pos: bool
        :return: a dictionary with siblings write positions
        :rtype:
            dict <PoolElement, position(float?) >"""
        positions = {}
        for sibling in self.siblings:
            pos_attr = sibling.get_position(propagate=0)
            if use and sibling in use:
                pos = use[sibling]
            elif pos_attr.has_write_value() and write_pos:
                pos = pos_attr.w_value
            else:
                if pos_attr.in_error():
                    raise PoolException("Cannot get '%s' position" %
                                        sibling.name,
                                        exc_info=pos_attr.exc_info)
                pos_value = pos_attr.calc_pseudo()
                if pos_value.error:
                    raise PoolException("Cannot get '%s' position" %
                                        sibling.name,
                                        exc_info=pos_value.exc_info)
                pos = pos_value.value
            positions[sibling] = pos
        return positions
Ejemplo n.º 2
0
    def calculate_motion(self, new_position, items=None, calculated=None):
        # if items already contains the positions for this pseudo motor
        # underlying motors it means the motion has already been calculated
        # by a sibling
        if items is not None and len(items):
            physical_elements = self.get_physical_elements_set()
            s_items = set(items)
            if s_items == physical_elements:
                if calculated is not None and self in calculated:
                    return

        user_elements = self.get_user_elements()
        positions = self.get_siblings_positions(
            use=calculated, write_pos=self.drift_correction)
        positions[self] = new_position
        pseudo_positions = len(positions) * [None]
        for pseudo, position in list(positions.items()):
            pseudo_positions[pseudo.axis - 1] = position
        curr_physical_positions = self._position.get_physical_positions()
        physical_positions = self.controller.calc_all_physical(
            pseudo_positions, curr_physical_positions)
        if physical_positions.error:
            raise PoolException(
                "Cannot calculate motion: "
                "calc_all_physical raises exception",
                exc_info=physical_positions.exc_info)
        else:
            if physical_positions.value is None:
                raise PoolException("Cannot calculate motion: "
                                    "calc_all_physical returns None")

        if items is None:
            items = {}
        for new_position, element in zip(physical_positions.value,
                                         user_elements):
            if new_position is None:
                raise PoolException("Cannot calculate motion: %s reports "
                                    "position to be None" % element.name)
            # TODO: use Sardana attribute configuration and
            #  get rid of accessing tango - see sardana-org/sardana#663
            from sardana.tango.core.util import _check_attr_range
            try:
                _check_attr_range(element.name, "position", new_position)
            except ValueError as e:
                # TODO: don't concatenate exception message whenever
                #  tango-controls/pytango#340 is fixed
                msg = "requested move of {} is outside of limits ({})".format(
                    element.name, str(e))
                raise ValueError(msg) from e

            element.calculate_motion(new_position,
                                     items=items,
                                     calculated=calculated)
        return items
Ejemplo n.º 3
0
    def calculate_motion(self, new_position, items=None, calculated=None):
        # if items already contains the positions for this pseudo motor
        # underlying motors it means the motion has already been calculated
        # by a sibling
        if items is not None and len(items):
            physical_elements = self.get_physical_elements_set()
            s_items = set(items)
            if s_items == physical_elements:
                if calculated is not None and self in calculated:
                    return

        user_elements = self.get_user_elements()
        positions = self.get_siblings_positions(
            use=calculated, write_pos=self.drift_correction)
        positions[self] = new_position
        pseudo_positions = len(positions) * [None]
        for pseudo, position in positions.items():
            pseudo_positions[pseudo.axis - 1] = position
        curr_physical_positions = self._position.get_physical_positions()
        physical_positions = self.controller.calc_all_physical(
            pseudo_positions, curr_physical_positions)
        if physical_positions.error:
            raise PoolException(
                "Cannot calculate motion: "
                "calc_all_physical raises exception",
                exc_info=physical_positions.exc_info)
        else:
            if physical_positions.value is None:
                raise PoolException("Cannot calculate motion: "
                                    "calc_all_physical returns None")

        if items is None:
            items = {}
        for new_position, element in zip(physical_positions.value,
                                         user_elements):
            if new_position is None:
                raise PoolException("Cannot calculate motion: %s reports "
                                    "position to be None" % element.name)
            element.calculate_motion(new_position,
                                     items=items,
                                     calculated=calculated)
        return items
Ejemplo n.º 4
0
 def get_physical_positions(self):
     ret = []
     for pos_attr in self.obj.get_physical_position_attribute_iterator():
         # if underlying moveable doesn't have position yet, it is because
         # of a cold start
         if not pos_attr.has_value():
             pos_attr.update(propagate=0)
         if pos_attr.in_error():
             raise PoolException("Cannot get '%' position" % pos_attr.obj.name,
                                 exc_info=pos_attr.exc_info)
         ret.append(pos_attr.value)
     return ret
Ejemplo n.º 5
0
 def get_physical_values(self):
     ret = []
     for value_attr in self.obj.get_physical_value_attribute_iterator():
         # if underlying channel doesn't have value yet, it is because
         # of a cold start
         if not value_attr.has_value():
             value_attr.update(propagate=0)
         if value_attr.in_error():
             raise PoolException("Cannot get '%s' value" % value_attr.obj.name,
                                 exc_info=value_attr.exc_info)
         ret.append(value_attr.value)
     return ret
Ejemplo n.º 6
0
    def calculate_motion(self, new_position, items=None, calculated=None):
        # if items already contains the positions for this pseudo motor
        # underlying motors it means the motion has already been calculated
        # by a sibling
        if items is not None and len(items):
            physical_elements = self.get_physical_elements_set()
            s_items = set(items)
            if s_items == physical_elements:
                if calculated is not None and self in calculated:
                    return

        user_elements = self.get_user_elements()
        positions = self.get_siblings_positions(use=calculated,
                                                write_pos=self.drift_correction)
        positions[self] = new_position
        pseudo_positions = len(positions) * [None]
        for pseudo, position in positions.items():
            pseudo_positions[pseudo.axis - 1] = position
        curr_physical_positions = self._position.get_physical_positions()
        physical_positions = self.controller.calc_all_physical(pseudo_positions,
                                                               curr_physical_positions)
        if physical_positions.error:
            raise PoolException("Cannot calculate motion: "
                                "calc_all_physical raises exception",
                                exc_info=physical_positions.exc_info)
        else:
            if physical_positions.value is None:
                raise PoolException("Cannot calculate motion: "
                                    "calc_all_physical returns None")

        if items is None:
            items = {}

         positions = physical_positions.value
         if not hasattr(positions , "__iter__"):
             positions = [positions]
         for new_position, element in zip(positions, user_elements):
            if new_position is None:
                raise PoolException("Cannot calculate motion: %s reports "
                                    "position to be None" % element.name)
            # TODO: get the configuration for an specific sardana class and
            # get rid of AttributeProxy - see sardana-org/sardana#663
            config = AttributeProxy(element.name + '/position').get_config()
            try:
                high = float(config.max_value)
            except ValueError:
                high = None
            try:
                low = float(config.min_value)
            except ValueError:
                low = None
            if high is not None:
                if float(new_position) > high:
                    msg = "requested movement of %s is above its upper limit"\
                        % element.name
                    raise RuntimeError(msg)
            if low is not None:
                if float(new_position) < low:
                    msg = "requested movement of %s is below its lower limit"\
                        % element.name
                    raise RuntimeError(msg)

            element.calculate_motion(new_position, items=items,
                                     calculated=calculated)