コード例 #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
    def _set_target(self, coordinate: str, target: float) -> None:
        """
        The function to set a target value for a coordinate, i.e. the set_cmd
        for the XXX_target parameters
        """
        # first validate the new target
        valid_vec = FieldVector()
        valid_vec.copy(self._target_vector)
        valid_vec.set_component(**{coordinate: target})
        components = valid_vec.get_components('x', 'y', 'z')
        if not self._field_limits(*components):
            raise ValueError(f'Cannot set {coordinate} target to {target}, '
                             'that would violate the field_limits. ')

        # update our internal target cache
        self._target_vector.set_component(**{coordinate: target})

        # actually assign the target on the slaves
        cartesian_targ = self._target_vector.get_components('x', 'y', 'z')
        for targ, slave in zip(cartesian_targ, self.submodules.values()):
            slave.field_target(targ)
コード例 #3
0
 def observe(current_field: FieldVector):
     new_loc = FieldVector()
     new_loc.copy(current_field)
     locations.append(new_loc)
     objectives_meas.append(self.objective())
コード例 #4
0
    def set_field(self,
                  target_field: FieldVector,
                  n_steps: int = 10,
                  absolute: bool = True,
                  ramp_rate: float = 1e-3,
                  observer_fn: Optional[Callable[[FieldVector], None]] = None,
                  verbose: bool = False,
                  threshold: float = 1e-6) -> None:
        """
        Sets the field controlled by this problem's instrument to a
        given target field by taking small steps, measuring, and then
        updating the target accordingly.

        Args:
            target_field: The value of the field that should be set,
                or the difference between the current and target field
                if `absolute=True`.
            n_steps: The number of steps that should be taken in order
                to reach the given target.
            absolute: Indicates whether `target_field` is the target field,
                or a difference from the current field to the target.
            ramp_rate: A rate at which the field can be safely swept between
                points.
            observer_fn: A callable which gets called after each small step.
            threshold: If the norm of the difference between the current and
                target field is smaller than this value, no further steps
                will be taken.
        """
        if IPYTHON and ipw is not None:
            status = ipw.Label()

            def update(field: FieldVector):
                status.value = field.repr_spherical()

            def finish():
                status.value = "Move complete."

            display(status)
        else:

            def update(field: FieldVector):
                print(
                    f'Magnet reached (r, phi, theta) = ({field.r}, {field.phi}, {field.theta})',
                    end='\r')

            def finish():
                print("Move complete.")

        target = FieldVector()
        if absolute:
            target.copy(target_field)
        else:
            initial = self.instrument.field_measured()
            target = target_field + initial

        with temporary_setting(
                self.instrument.field_ramp_rate,
                FieldVector(x=ramp_rate, y=ramp_rate, z=ramp_rate)):

            for step_amount in np.linspace(0, 1, n_steps + 1)[1:]:
                current = self.instrument.field_measured()
                intermediate_target = step_amount * (target -
                                                     current) + current

                if (intermediate_target - current).norm() <= threshold:
                    print("Step threshold met, stopping move early.")
                    break

                if verbose:
                    print(
                        f"Setting field target to {intermediate_target.repr_spherical()}"
                    )
                self.instrument.field_target(intermediate_target)
                self.instrument.ramp()

                time.sleep(0.1)
                current = self.instrument.field_measured()
                if observer_fn is not None:
                    observer_fn(current)
                update(current)
                time.sleep(0.1)

        finish()
コード例 #5
0
    def optimize_at_fixed_magnitude(
            self,
            r: float,
            phi_range: Interval[float],
            n_phi: int,
            theta_range: Interval[float],
            n_theta: int,
            return_extra: bool = False,
            n_steps: int = 5,
            plot: bool = False,
            verbose: bool = False,
            ramp_rate: float = 1.5e-3) -> OptionalExtra[FieldVector]:
        """
        Given the magnitude of a magnetic field, maximizes the objective
        over the spherical coordinates phi and theta by an exhaustive
        search.

        Args:
            r: The magnitude of the magnetic field to be optimized over
                angles.
            phi_range: The interval over which phi will be searched.
            n_phi: The number of distinct values of phi to be evaluated.
            theta_range: The interval over which theta will be searched.
            n_theta: The number of distinct values of theta to be evaluated.
            return_extra: If `True`, this method will return additional
                data as a dictionary.
            plot: If `True`, produces a plot of the path that this
                method took to find the optimal objective value.

        Returns:
            The optimal field found by an exhaustive seach.
            If `return_extra=True`, this method returns a tuple of the
            optimal field and a dictionary containing diagnostic data.
        """

        locations = []
        objectives_meas = []

        still_to_visit = [
            FieldVector(r=r, phi=phi, theta=theta)
            for phi in np.linspace(phi_range[0], phi_range[1], n_phi)
            for theta in np.linspace(theta_range[0], theta_range[1], n_theta)
        ]

        def observe(current_field: FieldVector):
            new_loc = FieldVector()
            new_loc.copy(current_field)
            locations.append(new_loc)
            objectives_meas.append(self.objective())

        while still_to_visit:
            # Find the nearest point.
            current = self.instrument.field_measured()
            nearest = min(still_to_visit, key=current.distance)
            still_to_visit.remove(nearest)
            print(
                f"Evaluating at phi = {nearest.phi}, theta = {nearest.theta}")
            self.set_field(nearest,
                           absolute=True,
                           n_steps=n_steps,
                           ramp_rate=ramp_rate,
                           observer_fn=observe,
                           verbose=verbose)
            observe(self.instrument.field_measured())

        extra = {'objectives': objectives_meas, 'field_vectors': locations}
        idx_flat_best = np.argmax(objectives_meas)
        optimum = FieldVector()
        optimum.copy(locations[idx_flat_best])

        # Renormalize to desired B.
        optimum['r'] = r

        # Move the field before returning.
        print(
            f"Found optimum for |B| = {r} at ({optimum.phi}, {optimum.theta})."
        )
        self.set_field(optimum, absolute=True)

        if plot:
            plt_xs = [vec.phi for vec in extra['field_vectors']]
            plt_ys = [vec.theta for vec in extra['field_vectors']]
            plt.figure()
            plt.plot(
                plt_xs,
                plt_ys,
            )
            plt.scatter(plt_xs, plt_ys, c=extra['objectives'])
            plt.colorbar()

        if return_extra:
            return optimum, extra
        else:
            return optimum