Beispiel #1
0
class Model:
    def __init__(self):
        self.frequency = Observable()
        self.power = Observable(0)
        self.offset = Observable(0)
        self.on = Observable(False)
        self.connected = Observable(False)
        self.clean_jump_active = Observable(False)
        self.clean_scan_active = Observable(False)
        self.clean_scan_progress = Observable()
        self.clean_sweep_state = Observable()
        self.scan_data = Observable({
            't_laser': [],
            'f': [],
            'p_in': [],
            't_pm': [],
            'p_out': []
        })
        self.scan_data_old = Observable({'f': [], 't': []})
        self.scan_time_remaining = Observable()
        self.scan_update_active = Observable(False)

        self.lock = Lock()
        self.data_lock = Lock()

        self.laser = None
        self.power_meter = None
        self.power_meter_connected = Event()
        self.power_meter_connected.clear()
        self.power_meter_thread = None
        self.power_meter_stop = Event()

    def set_startup_frequency(self, frequency):
        self.frequency.set(frequency)

    def connect_laser(self):
        with self.lock:
            self.laser = Laser()
            self.connected.set(True)

    def connect_pm(self):
        rm = visa.ResourceManager()
        resources = rm.list_resources()
        print(resources)
        inst = rm.open_resource(resources[0])
        inst.timeout = 5000
        print(inst.query('*IDN?'))
        self.power_meter = ThorlabsPM100(inst=inst)
        self.power_meter_connected.set()

    def laser_on(self):
        with self.lock:
            self.laser.startup_begin(self.frequency.get())

            while self.laser.check_nop() > 16:
                self.power.set(self.laser.check_power())

            self.on.set(True)

    def laser_off(self):
        # with self.lock:
        self.laser.laser_off()
        self.power.set(0)
        self.on.set(False)

    def disconnect(self):
        with self.lock:
            if self.laser:
                self.laser.itla_disconnect()
            self.connected.set(False)

    def standard_update(self, gui_lock: Lock, update_stop_event: Event):
        while not update_stop_event.is_set():
            time.sleep(0.01)
            with self.lock:
                if not update_stop_event.is_set():
                    self.power.set(self.laser.check_power())
                    freq_thz = self.laser.read(Laser.REG_FreqTHz)
                    freq_ghz = self.laser.read(Laser.REG_FreqGHz)
                    self.frequency.set(freq_thz + freq_ghz / 10000)
                    self.offset.set(self.laser.offset())

    def scan_update(self, end_event: Event, take_data: Event):
        self.power_meter_connected.wait()
        print('PM connected')
        t_prev = None
        p_prev = None
        f_prev = None

        stop_pm_event = Event()
        power_queue = Queue()
        time_queue = Queue()

        pm_read_thread = Thread(target=self.pm_read,
                                args=(time_queue, power_queue, stop_pm_event))
        pm_read_thread.start()

        self.scan_update_active.set(True)

        while not end_event.is_set():
            queue = Queue(maxsize=1)
            laser_read_thread = Thread(target=self.laser_read, args=(queue, ))
            laser_read_thread.start()
            output_powers_list = []
            measured_time_list = []

            laser_read_thread.join()

            stop_pm_event.set()
            pm_read_thread.join()

            while not time_queue.empty():
                measured_time_list.append(time_queue.get())

            while not power_queue.empty():
                output_powers_list.append(power_queue.get())

            pm_read_thread = Thread(target=self.pm_read,
                                    args=(time_queue, power_queue,
                                          stop_pm_event))
            stop_pm_event.clear()
            pm_read_thread.start()

            output_powers = np.array(output_powers_list)
            measured_time = np.array(measured_time_list)

            p_new, offset, t_end = queue.get()
            self.power.set(p_new)
            self.offset.set(offset)
            f_new = self.frequency.get() + offset / 1000

            if t_prev and f_prev and p_prev:
                assert isinstance(f_prev, float)
                assert isinstance(p_prev, float)

                t_duration = t_end - t_prev
                interpolation = ((measured_time - t_prev) / t_duration)
                frequencies = list(interpolation * f_new +
                                   (1 - interpolation) * f_prev)
                input_powers = interpolation * p_new + (1 -
                                                        interpolation) * p_prev
                input_powers_watts = np.power(10, input_powers / 10) / 1000
                relative_powers = list(output_powers / input_powers_watts)

                if abs(offset) < 20 and abs(p_new - 10) < 0.03 and abs(
                        f_prev - f_new) < 0.1 and take_data.is_set():
                    with self.data_lock:
                        data = self.scan_data_old.get()
                        data['f'] += frequencies
                        data['t'] += relative_powers
                        self.scan_data_old.set(data)

            t_prev = t_end
            f_prev = f_new
            p_prev = p_new
        self.scan_update_active.set(False)

    def laser_read(self, queue: Queue):
        with self.lock:
            input_power = self.laser.check_power()
            offset = self.laser.offset()
            t = time.perf_counter()
        results = input_power, offset, t

        queue.put(results)

    def pm_read(self, time_queue: Queue, power_queue: Queue, stop: Event):
        while not stop.is_set():
            power_queue.put(self.power_meter.read)
            time_queue.put(time.perf_counter())

    def pm_update(self, end_event: Event, take_data: Event):
        self.power_meter_connected.wait()
        while not end_event.is_set():
            if take_data.is_set():
                power_out = self.power_meter.read
                with self.data_lock:
                    data = self.scan_data.get()
                    if len(data['t_laser']) > 1 and abs(
                            data['t_laser'][-1] - time.perf_counter()) < 2E-1:
                        data['t_pm'].append(time.perf_counter())
                        data['p_out'].append(power_out)
                        self.scan_data.set(data)

    def clean_jump(self, frequency):
        self.clean_jump_active.set(True)
        self.clean_sweep_stop()
        with self.lock:
            self.laser.wait_nop()
        power_reference = self.power.get()
        with self.lock:
            self.laser.clean_jump_start(frequency)

        # Read the frequency error and wait until it is below a threshold or 2 seconds passes
        wait_time = time.perf_counter() + 2

        with self.lock:
            error_read = self.laser.read(Laser.REG_Cjumpoffset)
        freq_error = error_read / 10.0
        self.offset.set(freq_error)

        while abs(freq_error) > 0.1 and time.perf_counter() < wait_time:
            with self.lock:
                error_read = self.laser.read(Laser.REG_Cjumpoffset)
            freq_error = error_read / 10.0
            self.offset.set(freq_error)

        with self.lock:
            self.laser.wait_nop()

        # Read out the laser's claimed frequency
        with self.lock:
            claim_thz = self.laser.read(Laser.REG_GetFreqTHz)
            claim_ghz = self.laser.read(Laser.REG_GETFreqGHz) / 10
        claim_freq = claim_thz + claim_ghz / 1000.0

        self.frequency.set(claim_freq)

        print('Laser\'s claimed frequency: %f' % claim_freq)

        with self.lock:
            self.laser.clean_jump_finish()

        time_wait = time.perf_counter() + 1

        while self.power.get() < 0.8 * power_reference and time.perf_counter(
        ) < time_wait:
            time.sleep(.1)

        self.clean_sweep_start(0, 1)

        self.clean_jump_active.set(False)

    def clean_sweep_start(self, frequency, speed):
        self.clean_sweep_state.set("Preparing for clean sweep...")
        with self.lock:
            self.laser.clean_sweep_prep(frequency, int(speed * 1000))

        time.sleep(1)

        self.clean_sweep_state.set("Running clean sweep.")
        with self.lock:
            self.laser.clean_sweep_start()

    def clean_sweep_stop(self):
        with self.lock:
            self.laser.clean_sweep_stop()
        self.clean_sweep_state.set(None)

    def clean_sweep_to_offset(self, offset):
        self.clean_sweep_state.set(
            "Sweeping to offset of {} GHz".format(offset))
        with self.lock:
            self.laser.clean_sweep_to_offset(offset)

        while abs(self.offset.get() - offset) > 0.1:
            time.sleep(0.1)
        self.clean_sweep_state.set(
            "Pausing sweep at offset of {} GHz".format(offset))

    def clean_scan(self, start_frequency: float, stop_frequency: float,
                   speed: float, stop: Event, take_data: Event):
        assert stop_frequency > start_frequency
        if not self.power_meter_connected.is_set():
            self.connect_pm()
        jump_frequency = start_frequency
        self.clean_scan_active.set(True)
        self.clean_scan_progress.set(0)
        self.scan_data.set({
            't_laser': [],
            'f': [],
            'p_in': [],
            't_pm': [],
            'p_out': []
        })
        self.scan_data_old.set({'f': [], 't': []})
        take_data.clear()
        # self.power_meter_thread = Thread(target=self.pm_update, args=(stop, take_data))
        # self.power_meter_thread.start()

        scan_start_time = time.perf_counter()
        scan_count = 0

        while jump_frequency < stop_frequency + 0.03 and not stop.is_set():
            power_reference = self.power.get()

            with self.lock:
                self.laser.clean_jump(jump_frequency)
                freq_thz = self.laser.read(Laser.REG_FreqTHz)
                freq_ghz = self.laser.read(Laser.REG_FreqGHz)
                frequency = freq_thz + freq_ghz / 10000
                self.frequency.set(frequency)

            with self.lock:
                self.laser.wait_nop()

            time_wait = time.perf_counter() + 1

            while self.power.get(
            ) < 0.8 * power_reference and time.perf_counter() < time_wait:
                time.sleep(.1)

            time.sleep(0.5)

            power_reference = self.power.get()

            self.clean_sweep_start(50, speed)

            time.sleep(.1)

            take_data.set()

            while self.offset.get() < 10 and not stop.is_set():
                time.sleep(.1)

            while self.offset.get() > -10 and not stop.is_set():
                time.sleep(.1)

            while self.offset.get() < -1 and not stop.is_set():
                time.sleep(0.1)

            take_data.clear()

            time.sleep(0.5)

            with self.lock:
                self.laser.clean_sweep_stop()

            with self.lock:
                self.laser.wait_nop()

            time_wait = time.perf_counter() + 5

            while self.power.get(
            ) < 0.95 * power_reference and time.perf_counter() < time_wait:
                time.sleep(.1)

            jump_frequency += 0.04
            progress = (jump_frequency - start_frequency) / (stop_frequency -
                                                             start_frequency)
            self.clean_scan_progress.set((jump_frequency - start_frequency) /
                                         (stop_frequency - start_frequency))
            time_elapsed = time.perf_counter() - scan_start_time
            scan_count += 1
            average_time_elapsed = time_elapsed / scan_count
            self.scan_time_remaining.set(
                round(average_time_elapsed / progress / 60))

        time.sleep(1)
        # self.power_meter_thread.join()
        self.clean_scan_active.set(False)