Пример #1
0
        def data_received(is_raw, plot_data, data_uuid):
            # When a parameter is changed, `pause_acquisition` is set.
            # This means that the we should skip new data until we are sure that
            # it was recorded with the new settings.
            if not self.parameters.pause_acquisition.value:
                if data_uuid != self.data_uuid:
                    return

                data_loaded = pickle.loads(plot_data)

                if not is_raw:
                    is_locked = self.parameters.lock.value

                    if not check_plot_data(is_locked, data_loaded):
                        print(
                            "warning: incorrect data received for lock state, ignoring!"
                        )
                        return

                    self.parameters.to_plot.value = plot_data
                    self._generate_signal_stats(data_loaded)

                    # update signal history (if in locked state)
                    (
                        self.parameters.control_signal_history.value,
                        self.parameters.monitor_signal_history.value,
                    ) = update_signal_history(
                        self.parameters.control_signal_history.value,
                        self.parameters.monitor_signal_history.value,
                        data_loaded,
                        is_locked,
                        self.parameters.control_signal_history_length.value,
                    )
                else:
                    self.parameters.acquisition_raw_data.value = plot_data
Пример #2
0
    def update_std(self, to_plot, max_std_history_length=10):
        if self.parameters.lock.value and to_plot:
            to_plot = pickle.loads(to_plot)
            if to_plot and check_plot_data(True, to_plot):
                error_signal = to_plot.get('error_signal')
                control_signal = to_plot.get('control_signal')

                self.error_std_history.append(np.std(error_signal))
                self.control_std_history.append(np.std(control_signal))

                self.error_std_history = self.error_std_history[
                    -max_std_history_length:]
                self.control_std_history = self.control_std_history[
                    -max_std_history_length:]

                if error_signal and control_signal:
                    self.ids.error_std.setText('%.2f' %
                                               np.mean(self.error_std_history))
                    self.ids.control_std.setText(
                        '%.2f' % np.mean(self.control_std_history))
Пример #3
0
    def replot(self, to_plot):
        time_beginning = time()

        if self._should_reposition_reset_view_button:
            self._should_reposition_reset_view_button = False
            self.position_reset_view_button()

        if (
            time_beginning - self.last_plot_time <= self.plot_rate_limit
            and not self._plot_paused
        ):
            # don't plot too often at it only causes unnecessary load
            # this does not apply if plot is paused, because in this case we want
            # to collect all the data that we can get in order to pass it to the
            # autolock
            return

        self.last_plot_time = time_beginning

        # NOTE: this is necessary if OpenGL is activated. Otherwise, the
        # plot is way too small. This command apparently causes a repaint
        # and works fine even though the values are nonsense.
        if not self._fixed_opengl_bug:
            self._fixed_opengl_bug = True
            self.resize(
                self.parent().frameGeometry().width(),
                self.parent().frameGeometry().height(),
            )

        if self.parameters.pause_acquisition.value:
            return

        if to_plot is not None:
            to_plot = pickle.loads(to_plot)

            if to_plot is None:
                return

            if not check_plot_data(self.parameters.lock.value, to_plot):
                return

            # we also call this if the laser is not locked because it resets
            # the history in this case
            history, slow_history = self.update_signal_history(to_plot)

            if self.parameters.lock.value:
                self.signal1.setVisible(False)
                self.signal2.setVisible(False)
                self.control_signal.setVisible(True)
                self.control_signal_history.setVisible(True)
                self.slow_history.setVisible(self.parameters.pid_on_slow_enabled.value)
                self.monitor_signal_history.setVisible(
                    not self.parameters.dual_channel.value
                )
                self.combined_signal.setVisible(True)
                self.signal_strength_a.setVisible(False)
                self.signal_strength_b.setVisible(False)
                self.signal_strength_a2.setVisible(False)
                self.signal_strength_b2.setVisible(False)
                self.signal_strength_a_fill.setVisible(False)
                self.signal_strength_b_fill.setVisible(False)

                error_signal, control_signal = (
                    to_plot["error_signal"],
                    to_plot["control_signal"],
                )
                all_signals = (error_signal, control_signal, history, slow_history)

                self.plot_data_locked(to_plot)
                self.plot_autolock_target_line(None)
            else:
                dual_channel = self.parameters.dual_channel.value
                self.signal1.setVisible(True)
                monitor_signal = to_plot.get("monitor_signal")
                error_signal_2 = to_plot.get("error_signal_2")
                self.signal2.setVisible(
                    error_signal_2 is not None or monitor_signal is not None
                )
                self.combined_signal.setVisible(dual_channel)
                self.control_signal.setVisible(False)
                self.control_signal_history.setVisible(False)
                self.slow_history.setVisible(False)
                self.monitor_signal_history.setVisible(False)

                s1 = to_plot["error_signal_1"]
                s2 = error_signal_2 if error_signal_2 is not None else monitor_signal

                combined_error_signal = combine_error_signal(
                    (s1, s2),
                    dual_channel,
                    self.parameters.channel_mixing.value,
                    self.parameters.combined_offset.value,
                )

                if self._plot_paused:
                    self._cached_plot_data.append(combined_error_signal)
                    # don't save too much
                    self._cached_plot_data = self._cached_plot_data[-20:]
                    return

                all_signals = [s1, s2] + [combined_error_signal]
                self.last_plot_data = all_signals

                self.plot_data_unlocked((s1, s2), combined_error_signal)
                self.plot_autolock_target_line(combined_error_signal)

                if self.parameters.modulation_frequency.value != 0:
                    # check whether to plot signal strengths using quadratures
                    s1q = to_plot.get("error_signal_1_quadrature")
                    s2q = to_plot.get("error_signal_2_quadrature")

                    self.signal_strength_a.setVisible(s1q is not None)
                    self.signal_strength_a2.setVisible(s1q is not None)
                    self.signal_strength_a_fill.setVisible(s1q is not None)

                    self.signal_strength_b.setVisible(s2q is not None)
                    self.signal_strength_b2.setVisible(s2q is not None)
                    self.signal_strength_b_fill.setVisible(s2q is not None)

                    if s1q is not None:
                        max_signal_strength_V = (
                            self.plot_signal_strength(
                                s1,
                                s1q,
                                self.signal_strength_a,
                                self.signal_strength_a2,
                                self.signal_strength_a_fill,
                                self.parameters.offset_a.value,
                                self.parameters.plot_color_0.value,
                            )
                            / V
                        )
                        all_signals.append(
                            [
                                max_signal_strength_V * V,
                                -1 * max_signal_strength_V * V,
                            ]
                        )

                        self.signal_power1.emit(
                            peak_voltage_to_dBm(max_signal_strength_V)
                        )
                    else:
                        self.signal_power1.emit(INVALID_POWER)

                    if s2q is not None:
                        max_signal_strength2_V = (
                            self.plot_signal_strength(
                                s2,
                                s2q,
                                self.signal_strength_b,
                                self.signal_strength_b2,
                                self.signal_strength_b_fill,
                                self.parameters.offset_b.value,
                                self.parameters.plot_color_1.value,
                            )
                            / V
                        )

                        all_signals.append(
                            [
                                max_signal_strength2_V * V,
                                -1 * max_signal_strength2_V * V,
                            ]
                        )

                        self.signal_power2.emit(
                            peak_voltage_to_dBm(max_signal_strength2_V)
                        )
                    else:
                        self.signal_power2.emit(INVALID_POWER)
                else:
                    self.signal_strength_a.setVisible(False)
                    self.signal_strength_b.setVisible(False)
                    self.signal_strength_a2.setVisible(False)
                    self.signal_strength_b2.setVisible(False)
                    self.signal_strength_a_fill.setVisible(False)
                    self.signal_strength_b_fill.setVisible(False)

                    self.signal_power1.emit(INVALID_POWER)
                    self.signal_power2.emit(INVALID_POWER)

        time_end = time()
        time_diff = time_end - time_beginning
        new_rate_limit = 2 * time_diff

        if new_rate_limit < DEFAULT_PLOT_RATE_LIMIT:
            new_rate_limit = DEFAULT_PLOT_RATE_LIMIT

        self.plot_rate_limit = new_rate_limit
Пример #4
0
    def replot(self, to_plot):
        # NOTE: this is necessary if OpenGL is activated. Otherwise, the
        # plot is way too small. This command apparently causes a repaint
        # and works fine even though the values are nonsense.
        if not self._fixed_opengl_bug:
            self._fixed_opengl_bug = True
            self.resize(self.parent().frameGeometry().width(),
                        self.parent().frameGeometry().height())

        if self.parameters.pause_acquisition.value:
            return

        if to_plot is not None and not self.touch_start:
            to_plot = pickle.loads(to_plot)

            if to_plot is None:
                return

            if not check_plot_data(self.parameters.lock.value, to_plot):
                return

            # we also call this if the laser is not locked because it resets
            # the history in this case
            history, slow_history = self.update_control_signal_history(to_plot)

            if self.parameters.lock.value:
                self.last_plot_data = to_plot

                self.signal1.setVisible(False)
                self.signal2.setVisible(False)
                self.control_signal.setVisible(True)
                self.control_signal_history.setVisible(True)
                self.slow_history.setVisible(
                    self.parameters.pid_on_slow_enabled.value)
                self.combined_signal.setVisible(True)

                error_signal, control_signal = to_plot[
                    'error_signal'], to_plot['control_signal']
                all_signals = (error_signal, control_signal, history,
                               slow_history)

                self.plot_data_locked(to_plot)
                self.update_plot_scaling(all_signals)
                self.plot_autolock_target_line(None)
            else:
                dual_channel = self.parameters.dual_channel.value
                self.signal1.setVisible(True)
                self.signal2.setVisible(dual_channel)
                self.combined_signal.setVisible(dual_channel)
                self.control_signal.setVisible(False)
                self.control_signal_history.setVisible(False)
                self.slow_history.setVisible(False)

                s1, s2 = to_plot['error_signal_1'], to_plot['error_signal_2']
                combined_error_signal = combine_error_signal(
                    (s1, s2), dual_channel,
                    self.parameters.channel_mixing.value)
                all_signals = [s1, s2] + [combined_error_signal]
                self.last_plot_data = all_signals

                self.plot_data_unlocked((s1, s2), combined_error_signal)
                self.plot_autolock_target_line(combined_error_signal)
                self.update_plot_scaling(all_signals if dual_channel else [s1])
Пример #5
0
    def react_to_new_spectrum(self, plot_data):
        """React to new spectrum data.

        If this is executed for the first time, a reference spectrum is
        recorded.

        If the autolock is approaching the desired line, a correlation
        function of the spectrum with the reference spectrum is calculated
        and the laser current is adapted such that the targeted line is centered.

        After this procedure is done, the real lock is turned on and after some
        time the lock is verified.

        If automatic relocking is desired, the control and error signals are
        continuously monitored after locking.
        """
        if self.parameters.pause_acquisition.value:
            return

        if plot_data is None or not self.parameters.autolock_running.value:
            return

        plot_data = pickle.loads(plot_data)
        if plot_data is None:
            return

        is_locked = self.parameters.lock.value

        # check that `plot_data` contains the information we need
        # otherwise skip this round
        if not check_plot_data(is_locked, plot_data):
            return

        if is_locked:
            error_signal = plot_data['error_signal']
            control_signal = plot_data['control_signal']
        else:
            combined_error_signal = combine_error_signal(
                (plot_data['error_signal_1'], plot_data['error_signal_2']),
                self.parameters.dual_channel.value,
                self.parameters.channel_mixing.value)

        try:
            if self.parameters.autolock_approaching.value:
                # we have already recorded a spectrum and are now approaching
                # the line by decreasing the scan range and adapting the
                # center current multiple times.
                if self.approacher is None:
                    self.approacher = Approacher(self.control,
                                                 self.parameters,
                                                 self.first_error_signal,
                                                 self.target_zoom,
                                                 allow_ramp_speed_change=True)
                approaching_finished = self.approacher.approach_line(
                    combined_error_signal)
                if approaching_finished:
                    self._lock()

            elif self.parameters.autolock_watching.value:
                # the laser was locked successfully before. Now we check
                # periodically whether the laser is still in lock
                return self.watch_lock(error_signal, control_signal)

            else:
                # we are done with approaching and have started the lock.
                # skip some data and check whether we really are in lock
                # afterwards.
                return self.after_lock(error_signal, control_signal,
                                       plot_data.get('slow'))

        except SpectrumUncorrelatedException:
            print('spectrum uncorrelated')
            if self.parameters.watch_lock.value:
                print('retry')
                self.relock()
            else:
                self.exposed_stop()
                self.parameters.autolock_failed.value = True

        except Exception:
            traceback.print_exc()
            self.exposed_stop()
Пример #6
0
    def react_to_new_spectrum(self, plot_data):
        """React to new spectrum data.

        If this is executed for the first time, a reference spectrum is
        recorded.

        If the autolock is approaching the desired line, a correlation
        function of the spectrum with the reference spectrum is calculated
        and the laser current is adapted such that the targeted line is centered.

        After this procedure is done, the real lock is turned on and after some
        time the lock is verified.

        If automatic relocking is desired, the control and error signals are
        continuously monitored after locking.
        """
        if self.parameters.pause_acquisition.value:
            return

        if plot_data is None or not self.parameters.autolock_running.value:
            return

        plot_data = pickle.loads(plot_data)
        if plot_data is None:
            return

        is_locked = self.parameters.lock.value

        # check that `plot_data` contains the information we need
        # otherwise skip this round
        if not check_plot_data(is_locked, plot_data):
            return

        try:
            if not is_locked:
                combined_error_signal = combine_error_signal(
                    (plot_data["error_signal_1"],
                     plot_data.get("error_signal_2")),
                    self.parameters.dual_channel.value,
                    self.parameters.channel_mixing.value,
                    self.parameters.combined_offset.value,
                )

                if (self.autolock_mode_detector is not None
                        and not self.autolock_mode_detector.done):
                    self.autolock_mode_detector.handle_new_spectrum(
                        combined_error_signal)
                    self.additional_spectra.append(combined_error_signal)

                    if self.autolock_mode_detector.done:
                        self.start_autolock(self.autolock_mode_detector.mode)
                    else:
                        return

                return self.algorithm.handle_new_spectrum(
                    combined_error_signal)

            else:
                error_signal = plot_data["error_signal"]
                control_signal = plot_data["control_signal"]

                return self.after_lock(error_signal, control_signal,
                                       plot_data.get("slow"))

        except Exception:
            traceback.print_exc()
            self.parameters.autolock_failed.value = True
            self.exposed_stop()