From 3e71b9a8af83529c9a2f79a0ccdf95e8d74ebf1d Mon Sep 17 00:00:00 2001 From: Martin Killenberg <martin.killenberg@desy.de> Date: Mon, 30 Jan 2023 11:53:05 +0100 Subject: [PATCH] re-introduce measurement in a separate thread --- Python_script/MeasurementPlot.py | 31 +++++++++++++++++++++++++++---- Python_script/prototype.py | 17 +++++++++++++++-- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/Python_script/MeasurementPlot.py b/Python_script/MeasurementPlot.py index e26c23e..5e72951 100644 --- a/Python_script/MeasurementPlot.py +++ b/Python_script/MeasurementPlot.py @@ -2,6 +2,7 @@ import pandas as pd import matplotlib.pyplot as plt import numpy as np import time +import queue # Different exceptions can be thrown while plotting, depending on the backend. # We catch them all locally and raise our own exception instead @@ -53,7 +54,28 @@ class MeasurementPlot: labels = [pc.get_label() for pc in all_path_collections] self.ax1[1].legend(all_path_collections, labels, loc='lower right') - def draw(self, data_frame, pdf_name=''): + self.data_queue = queue.Queue(10) + + def stop(self): + self.data_queue.put((None, None, True)) + + def draw_in_other_thread(self, data_frame, pdf_name=''): + # A shallow copy is enough (although not strictly 100 % thread safe). Data is only appended and + # the data members are not altered. + frame_copy = data_frame.copy() + try: + self.data_queue.put_nowait((frame_copy, pdf_name, False)) + except queue.Full: + pass + + def drawing_loop(self): + while True: + data_frame, pdf_name, stop_thread = self.data_queue.get() + if stop_thread: + return + self.draw_in_this_thread(data_frame, pdf_name='') + + def draw_in_this_thread(self, data_frame, pdf_name=''): timestamps = data_frame.TIMESTAMP minimum, maximum = self.get_extended_min_max(timestamps) self.ax1[0].set_xlim(minimum, maximum) @@ -106,6 +128,7 @@ if __name__ == '__main__': plt.ion() measurements = [] + #FIXME: The loop should run in a separate thread and use draw_in_other_thread for i in range(20): measurement = { 'TIMESTAMP': i, @@ -116,11 +139,11 @@ if __name__ == '__main__': 'S21_MAGNITUDE': 0.3*i } measurements.append(measurement) - data_frame = pd.DataFrame(measurements) - m.draw(data_frame) + my_data_frame = pd.DataFrame(measurements) + m.draw_in_this_thread(my_data_frame) print(str(i)) time.sleep(0.3) print('I am done. ') plt.ioff() - m.draw(data_frame, 'the.pdf') + m.draw_in_this_thread(my_data_frame, 'the.pdf') diff --git a/Python_script/prototype.py b/Python_script/prototype.py index 4050036..cc7a055 100755 --- a/Python_script/prototype.py +++ b/Python_script/prototype.py @@ -14,6 +14,7 @@ import json import MeasurementPlot import sys import analysis +import threading TEMPERATURE_STABLE = 0x1 HUMIDITY_STABLE = 0x2 @@ -137,7 +138,17 @@ class Measurements: plt.close() return sweep_values + # wrapper function which calls the impl in a separate thread and runs the + # plotting loop def perform_single_measurement(self, output, target_temp, target_hum, soaking_time, n_stable_reads): + measurement_thread = threading.Thread(target=self.perform_single_measurement_impl, + args=(output, target_temp, target_hum, soaking_time, + n_stable_reads)) + measurement_thread.start() + self.measurement_plot.drawing_loop() + measurement_thread.join() + + def perform_single_measurement_impl(self, output, target_temp, target_hum, soaking_time, n_stable_reads): with open(output, mode='w', newline='') as csv_file: fieldnames = ['TIMESTAMP', 'TARGET_TEMPERATURE', 'READBACK_TEMPERATURE', 'TARGET_HUMIDITY', 'READBACK_HUMIDITY', 'RF_POWER', 'RF_FREQUENCY', 'DUT_IDENTIFIER', 'RUN_ID', @@ -256,6 +267,8 @@ class Measurements: writer.writerow(measurement) + self.measurement_plot.stop() + def sleep_until(self, wakeup_time): remaining_sleep_time = wakeup_time - self.clock.time() if remaining_sleep_time > 0: @@ -294,7 +307,7 @@ class Measurements: } self.data_collection.append(measurement) data_frame = pd.DataFrame(self.data_collection) - self.measurement_plot.draw(data_frame) + self.measurement_plot.draw_in_other_thread(data_frame) def current_milli_time(self): return int(round(self.clock.time() * 1000)) @@ -363,7 +376,7 @@ def plot_output(output_basename, measurements_appendices, show_blocking_plot, ti if show_blocking_plot: plt.ioff() plot = MeasurementPlot.MeasurementPlot(title) - plot.draw(combined_data_frame, output_basename + '_graph.pdf') + plot.draw_in_this_thread(combined_data_frame, output_basename + '_graph.pdf') def run_temperature_sweep_from_file(temperature_sweep_file, meas): with open(temperature_sweep_file) as file: -- GitLab