コード例 #1
0
    def _set_setpoints(self, names, values):

        kwargs = dict(zip(names, np.atleast_1d(values)))

        set_point = FieldVector()
        set_point.copy(self._set_point)
        if len(kwargs) == 3:
            set_point.set_vector(**kwargs)
        else:
            set_point.set_component(**kwargs)

        self._adjust_child_instruments(set_point.get_components("x", "y", "z"))

        self._set_point = set_point
コード例 #2
0
ファイル: AMI430.py プロジェクト: mwilmer/Qcodes
class AMI430_3D(Instrument):
    def __init__(self, name, instrument_x, instrument_y, instrument_z,
                 field_limit, **kwargs):
        super().__init__(name, **kwargs)

        if not isinstance(name, str):
            raise ValueError("Name should be a string")

        instruments = [instrument_x, instrument_y, instrument_z]

        if not all(
            [isinstance(instrument, AMI430) for instrument in instruments]):
            raise ValueError("Instruments need to be instances "
                             "of the class AMI430")

        self._instrument_x = instrument_x
        self._instrument_y = instrument_y
        self._instrument_z = instrument_z

        if repr(field_limit).isnumeric() or isinstance(field_limit,
                                                       collections.Iterable):
            self._field_limit = field_limit
        else:
            raise ValueError("field limit should either be"
                             " a number or an iterable")

        self._set_point = FieldVector(x=self._instrument_x.field(),
                                      y=self._instrument_y.field(),
                                      z=self._instrument_z.field())

        # Get-only parameters that return a measured value
        self.add_parameter('cartesian_measured',
                           get_cmd=partial(self._get_measured, 'x', 'y', 'z'),
                           unit='T')

        self.add_parameter('x_measured',
                           get_cmd=partial(self._get_measured, 'x'),
                           unit='T')

        self.add_parameter('y_measured',
                           get_cmd=partial(self._get_measured, 'y'),
                           unit='T')

        self.add_parameter('z_measured',
                           get_cmd=partial(self._get_measured, 'z'),
                           unit='T')

        self.add_parameter('spherical_measured',
                           get_cmd=partial(self._get_measured, 'r', 'theta',
                                           'phi'),
                           unit='T')

        self.add_parameter('phi_measured',
                           get_cmd=partial(self._get_measured, 'phi'),
                           unit='deg')

        self.add_parameter('theta_measured',
                           get_cmd=partial(self._get_measured, 'theta'),
                           unit='deg')

        self.add_parameter('field_measured',
                           get_cmd=partial(self._get_measured, 'r'),
                           unit='T')

        self.add_parameter('cylindrical_measured',
                           get_cmd=partial(self._get_measured, 'rho', 'phi',
                                           'z'),
                           unit='T')

        self.add_parameter('rho_measured',
                           get_cmd=partial(self._get_measured, 'rho'),
                           unit='T')

        # Get and set parameters for the set points of the coordinates
        self.add_parameter('cartesian',
                           get_cmd=partial(self._get_setpoints, 'x', 'y', 'z'),
                           set_cmd=self._set_cartesian,
                           unit='T',
                           vals=Anything())

        self.add_parameter('x',
                           get_cmd=partial(self._get_setpoints, 'x'),
                           set_cmd=self._set_x,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('y',
                           get_cmd=partial(self._get_setpoints, 'y'),
                           set_cmd=self._set_y,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('z',
                           get_cmd=partial(self._get_setpoints, 'z'),
                           set_cmd=self._set_z,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('spherical',
                           get_cmd=partial(self._get_setpoints, 'r', 'theta',
                                           'phi'),
                           set_cmd=self._set_spherical,
                           unit='tuple?',
                           vals=Anything())

        self.add_parameter('phi',
                           get_cmd=partial(self._get_setpoints, 'phi'),
                           set_cmd=self._set_phi,
                           unit='deg',
                           vals=Numbers())

        self.add_parameter('theta',
                           get_cmd=partial(self._get_setpoints, 'theta'),
                           set_cmd=self._set_theta,
                           unit='deg',
                           vals=Numbers())

        self.add_parameter('field',
                           get_cmd=partial(self._get_setpoints, 'r'),
                           set_cmd=self._set_r,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('cylindrical',
                           get_cmd=partial(self._get_setpoints, 'rho', 'phi',
                                           'z'),
                           set_cmd=self._set_cylindrical,
                           unit='tuple?',
                           vals=Anything())

        self.add_parameter('rho',
                           get_cmd=partial(self._get_setpoints, 'rho'),
                           set_cmd=self._set_rho,
                           unit='T',
                           vals=Numbers())

    def _verify_safe_setpoint(self, setpoint_values):

        if repr(self._field_limit).isnumeric():
            return np.linalg.norm(setpoint_values) < self._field_limit

        answer = any([
            limit_function(*setpoint_values)
            for limit_function in self._field_limit
        ])

        return answer

    def _set_fields(self, values):
        """
        Set the fields of the x/y/z magnets. This function is called
        whenever the field is changed and performs several safety checks
        to make sure no limits are exceeded.

        Args:
            values (tuple): a tuple of cartesian coordinates (x, y, z).
        """
        log.debug("Checking whether fields can be set")

        # Check if exceeding the global field limit
        if not self._verify_safe_setpoint(values):
            raise ValueError("_set_fields aborted; field would exceed limit")

        # Check if the individual instruments are ready
        for name, value in zip(["x", "y", "z"], values):

            instrument = getattr(self, "_instrument_{}".format(name))
            if instrument.ramping_state() == "ramping":
                msg = '_set_fields aborted; magnet {} is already ramping'
                raise AMI430Exception(msg.format(instrument))

        # Now that we know we can proceed, call the individual instruments

        log.debug("Field values OK, proceeding")
        for operator in [np.less, np.greater]:
            # First ramp the coils that are decreasing in field strength.
            # This will ensure that we are always in a safe region as
            # far as the quenching of the magnets is concerned
            for name, value in zip(["x", "y", "z"], values):

                instrument = getattr(self, "_instrument_{}".format(name))
                current_actual = instrument.field()

                # If the new set point is practically equal to the
                # current one then do nothing
                if np.isclose(value, current_actual, rtol=0, atol=1e-8):
                    continue
                # evaluate if the new set point is smaller or larger
                # than the current value
                if not operator(abs(value), abs(current_actual)):
                    continue

                instrument.set_field(value, perform_safety_check=False)

    def _request_field_change(self, instrument, value):
        """
        This method is called by the child x/y/z magnets if they are set
        individually. It results in additional safety checks being
        performed by this 3D driver.
        """
        if instrument is self._instrument_x:
            self._set_x(value)
        elif instrument is self._instrument_y:
            self._set_y(value)
        elif instrument is self._instrument_z:
            self._set_z(value)
        else:
            msg = 'This magnet doesnt belong to its specified parent {}'
            raise NameError(msg.format(self))

    def _get_measured(self, *names):

        x = self._instrument_x.field()
        y = self._instrument_y.field()
        z = self._instrument_z.field()
        measured_values = FieldVector(x=x, y=y, z=z).get_components(*names)

        # Convert angles from radians to degrees
        d = dict(zip(names, measured_values))

        # Do not do "return list(d.values())", because then there is
        # no guaranty that the order in which the values are returned
        # is the same as the original intention
        return_value = [d[name] for name in names]

        if len(names) == 1:
            return_value = return_value[0]

        return return_value

    def _get_setpoints(self, *names):

        measured_values = self._set_point.get_components(*names)

        # Convert angles from radians to degrees
        d = dict(zip(names, measured_values))
        return_value = [d[name] for name in names]
        # Do not do "return list(d.values())", because then there is
        # no guarantee that the order in which the values are returned
        # is the same as the original intention

        if len(names) == 1:
            return_value = return_value[0]

        return return_value

    def _set_cartesian(self, values):
        x, y, z = values
        self._set_point.set_vector(x=x, y=y, z=z)
        self._set_fields(self._set_point.get_components("x", "y", "z"))

    def _set_x(self, x):
        self._set_point.set_component(x=x)
        self._set_fields(self._set_point.get_components("x", "y", "z"))

    def _set_y(self, y):
        self._set_point.set_component(y=y)
        self._set_fields(self._set_point.get_components("x", "y", "z"))

    def _set_z(self, z):
        self._set_point.set_component(z=z)
        self._set_fields(self._set_point.get_components("x", "y", "z"))

    def _set_spherical(self, values):
        r, theta, phi = values
        self._set_point.set_vector(r=r, theta=theta, phi=phi)
        self._set_fields(self._set_point.get_components("x", "y", "z"))

    def _set_r(self, r):
        self._set_point.set_component(r=r)
        self._set_fields(self._set_point.get_components("x", "y", "z"))

    def _set_theta(self, theta):
        self._set_point.set_component(theta=theta)
        self._set_fields(self._set_point.get_components("x", "y", "z"))

    def _set_phi(self, phi):
        self._set_point.set_component(phi=phi)
        self._set_fields(self._set_point.get_components("x", "y", "z"))

    def _set_cylindrical(self, values):
        rho, phi, z = values
        self._set_point.set_vector(rho=rho, phi=phi, z=z)
        self._set_fields(self._set_point.get_components("x", "y", "z"))

    def _set_rho(self, rho):
        self._set_point.set_component(rho=rho)
        self._set_fields(self._set_point.get_components("x", "y", "z"))