From 519b248261336dbf48533bc9e7c684e49d74ba61 Mon Sep 17 00:00:00 2001 From: Jacob Date: Tue, 10 Aug 2021 23:51:50 +0200 Subject: [PATCH] Abend 10.Aug --- measurement.py | 6 +- model.py | 46 +++++++--- plot_data.py | 49 +++++++---- sensor.py | 40 +++++---- trial2/wxglade.wxg | 190 +++++++++++++++++++++++++++++++++++++++++ trial2/wxglade.wxg~ | 174 +++++++++++++++++++++++++++++++++++++ trial2/wxglade_out.py | 138 ++++++++++++++++++++++++++++++ trial2/wxglade_out.py~ | 117 +++++++++++++++++++++++++ view.py | 9 +- 9 files changed, 717 insertions(+), 52 deletions(-) create mode 100644 trial2/wxglade.wxg create mode 100644 trial2/wxglade.wxg~ create mode 100644 trial2/wxglade_out.py create mode 100644 trial2/wxglade_out.py~ diff --git a/measurement.py b/measurement.py index 852e794..529fda6 100644 --- a/measurement.py +++ b/measurement.py @@ -2,7 +2,7 @@ import os class Measurement: - def __init__(self, name, sensors, path=None, comment=None): + def __init__(self, name, path=None, comment=None): self.name = name self.path = os.path.join(path or "./meas_values", self.name) os.makedirs(self.path) @@ -18,8 +18,8 @@ class Measurement: data: list of tuples: (timestamp, value) """ if sensor_name not in self.data_files: - self.data_files[sensor_name] = open(os.path.join(self.path, f"{sensor_name}_data.csv")) - for timestamp, value in data: + self.data_files[sensor_name] = open(os.path.join(self.path, f"{sensor_name}_data.csv"), "w") + for timestamp, value in zip(data[0], data[1]): self.data_files[sensor_name].write(f"{timestamp.isoformat()}, {timestamp.timestamp()}, {value}\n") def save_version_text(self, comment): diff --git a/model.py b/model.py index 19b5a68..a33ecaa 100644 --- a/model.py +++ b/model.py @@ -5,34 +5,58 @@ Data: - dict with sensor data (temp, pressure, current) - dict with drivers (magnetic field control) """ +from datetime import datetime +from threading import Event, Thread +from time import sleep from sensor import Sensor +from measurement import Measurement +from plot_data import PlotData + +class DataGrabber(Thread): + def __init__(self, sensors, drivers, plot_data): + super().__init__() + self.measurement = None + self.sensors = sensors + self.drivers = drivers + self.plot_data = plot_data + self.exit_request = Event() + + def run(self): + while not self.exit_request.is_set(): + for name, sens in self.sensors.items(): + dat = sens.get_data + self.plot_data.append_data(name,dat) + if self.measurement is not None: + self.measurement.append_data(name, dat) + sleep(1) class Model: def __init__(self): + self.plot_data = PlotData() self.sensors = {"temp": Sensor(), "keks": Sensor()} self.drivers = [] self.measurement = None - self.plot_data = None - pass + self.data_grabber = DataGrabber(self.sensors, self.drivers, self.plot_data) + self.data_grabber.start() - def start_measuring(self): - for sens in self.sensors.values(): - sens.start_measuring() + def start_measuring(self, meas_name=""): + name = meas_name or f"meas_{datetime.utcnow().isoformat().replace(':', '-')}" + self.measurement = Measurement(name) + self.data_grabber.measurement = self.measurement def save_measuring(self, path="temp_temp.csv"): - for sens in self.sensors.values(): - sens.save_measuring() + print("Has no use delete me maybe") def stop_measuring(self): - for sens in self.sensors.values(): - sens.stop_measuring() + self.measurement = None + self.data_grabber.measurement = None def clear(self): - for sens in self.sensors.values(): - sens.clear() + self.plot_data.clear() def exit(self): + self.data_grabber.exit_request.set() for sens in self.sensors.values(): sens.exit() diff --git a/plot_data.py b/plot_data.py index 3e8abfa..bf8f672 100644 --- a/plot_data.py +++ b/plot_data.py @@ -1,15 +1,21 @@ import numpy as np -from datetime import datetime +from datetime import datetime, timedelta + class PlotData(): def __init__(self): - self.refresh_rate = 1 # ms - self.timeout = 100 # cycles + self.refresh_rate = 1 # ms + self.timeout = 100 # cycles self.data = {"time": np.array([0])} self.start_time = datetime.utcnow() self.queues = {} + def clear(self): + for key in self.data: + self.data[key] = np.array([]) + def get(self, key): + return self.data.get(key, np.full_like(self.data["time"], np.nan, dtype=np.double)) def append_data(self, sensor_name, data): """ @@ -17,25 +23,37 @@ class PlotData(): """ if sensor_name not in self.data: self.queues[sensor_name] = [] - self.data[sensor_name] = np.full_like(self.data["time"], np.nan) - - for data_tuple in data.values(): - self.queues[sensor_name].append(data_tuple) + self.data[sensor_name] = np.full_like(self.data["time"], np.nan, dtype=np.double) + for time, dat in zip(data[0], data[1]): + self.queues[sensor_name].append((time, dat)) running = True while running: - #TODO timeout clean + # TODO timeout clean and time clean + for sensor, que in self.queues.items(): + index = -1 + for time, _ in que: + if time < self.start_time \ + + timedelta(milliseconds=int(self.data["time"][-1]) + self.refresh_rate): + index += 1 + if index >= 0: + self.queues[sensor] = que[index:] + #TODO timeout not working as intended + #if timeout is reached add empty values on sensors + #if self.start_time + timedelta(milliseconds=int(self.data["time"][-1])+self.timeout) < datetime.utcnow(): + # for sensor, que in self.queues.items(): + # if len(que) == 0: + # que.append((self.start_time,np.nan)) + for que in self.queues.values(): if len(que) == 0: running = False - break - - for sensor,que in self.queues.items(): - self.data[sensor] = np.append(self.data[sensor], que[0]) - que = que[1:] - - + return + for sensor, que in self.queues.items(): + self.data[sensor] = np.append(self.data[sensor], que[0][1]) + self.queues[sensor] = que[1:] + self.data["time"] = np.append(self.data["time"],self.data["time"][-1]+self.refresh_rate) """ TODO @@ -46,4 +64,3 @@ class PlotData(): return update np array """ - diff --git a/sensor.py b/sensor.py index ca0e838..d2b1ca1 100644 --- a/sensor.py +++ b/sensor.py @@ -14,18 +14,16 @@ class SensorWorker(Thread): self.message_queue = message_queue self.produceData = Event() self.exit_request = Event() - self.file = open("temp.csv", "w") def run(self): """ Worker method of a python Thread. Called when the Thread is started. """ while not self.exit_request.is_set(): if self.produceData.is_set(): temp = random() - ts = datetime.now() + ts = datetime.utcnow() self.message_queue.put((ts, temp)) - self.file.write(f"{ts} - {temp}\n") else: - self.file.flush() + pass sleep(1) @@ -34,38 +32,44 @@ class Sensor(object): def __init__(self): super(Sensor, self).__init__() - self.data = [] - self.t = [] self.measureQueue = Queue() self.measureThread = SensorWorker(self.measureQueue) self.measureThread.start() + self.measureThread.produceData.set() + def start_measuring(self): self.measureThread.produceData.set() print("I started meas") - def save_measuring(self, path="temp_temp.csv"): - print("I saved meas") - np.savetxt(path, np.array(self.data)) def stop_measuring(self): self.measureThread.produceData.clear() print("I stopped meas") - def clear(self): - self.data = [] - self.t = [] - print("I cleared meas") - def exit(self): self.stop_measuring() self.measureThread.exit_request.set() @property def get_data(self): + time = [] + val = [] while not self.measureQueue.empty(): t, data = self.measureQueue.get() - self.data.append(data) - self.t.append(t) - print(self.data) - return self.t, self.data + time.append(t) + val.append(data) + return time, val + + + + + # def clear(self): + # self.data = [] + # self.t = [] + # print("I cleared meas") + # + # def save_measuring(self, path="temp_temp.csv"): + # print("I saved meas") + # np.savetxt(path, np.array(self.data)) + diff --git a/trial2/wxglade.wxg b/trial2/wxglade.wxg new file mode 100644 index 0000000..3ec5da6 --- /dev/null +++ b/trial2/wxglade.wxg @@ -0,0 +1,190 @@ + + + + + + 1920, 1080 + frame + + 1 + 1 + 1 + + + + + + + + + + + + frame_statusbar + + + + + + + + + 2 + 3 + 0 + 0 + + 2, 1 + 0 + wxEXPAND + + wxVERTICAL + + + 0 + + + + + + + 0 + + + + + + + 0 + + + + + + + + 0 + wxEXPAND + + + + notebook_1_pane_1 + notebook_1_pane_2 + notebook_1_pane_3 + notebook_1_pane_4 + + + + + + + + + + + + + + + + + 2, 1 + 0 + wxEXPAND + + 2 + 1 + 10 + 0 + + 0 + wxEXPAND + + 3 + 1 + 0 + 0 + + 0 + + + + + + 0 + + + + + + 0 + + + + + + + + 0 + wxEXPAND + + 3 + 1 + 0 + 0 + + 0 + + + + + + 0 + + + + + + 0 + + + + + + + + + + + 0 + wxEXPAND + + 1 + 3 + 0 + 0 + + 0 + + + + + + 0 + + + + + + 0 + + + + + + + + + + + diff --git a/trial2/wxglade.wxg~ b/trial2/wxglade.wxg~ new file mode 100644 index 0000000..69defe0 --- /dev/null +++ b/trial2/wxglade.wxg~ @@ -0,0 +1,174 @@ + + + + + + 474, 290 + frame + + 1 + + + + + + + 2 + 3 + 0 + 0 + + 2, 1 + 0 + wxEXPAND + + wxVERTICAL + + + 0 + + + + + + + 0 + + + + + + + 0 + + + + + + + + 0 + wxEXPAND + + + + notebook_1_pane_1 + notebook_1_pane_2 + notebook_1_pane_3 + notebook_1_pane_4 + + + + + + + + + + + + + + + + + 2, 1 + 0 + wxEXPAND + + 2 + 1 + 10 + 0 + + 0 + wxEXPAND + + 3 + 1 + 0 + 0 + + 0 + + + + + + 0 + + + + + + 0 + + + + + + + + 0 + wxEXPAND + + 3 + 1 + 0 + 0 + + 0 + + + + + + 0 + + + + + + 0 + + + + + + + + + + + 0 + wxEXPAND + + 1 + 3 + 0 + 0 + + 0 + + + + + + 0 + + + + + + 0 + + + + + + + + + + + diff --git a/trial2/wxglade_out.py b/trial2/wxglade_out.py new file mode 100644 index 0000000..6745c19 --- /dev/null +++ b/trial2/wxglade_out.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# +# generated by wxGlade 1.0.2 on Sun Jul 4 21:29:50 2021 +# + +import wx + +# begin wxGlade: dependencies +# end wxGlade + +# begin wxGlade: extracode +# end wxGlade + + +class MyFrame(wx.Frame): + def __init__(self, *args, **kwds): + # begin wxGlade: MyFrame.__init__ + kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + self.SetSize((1920, 1080)) + self.SetTitle("frame") + + # Menu Bar + self.frame_menubar = wx.MenuBar() + wxglade_tmp_menu = wx.Menu() + wxglade_tmp_menu.Append(wx.ID_ANY, "Quit", "") + self.frame_menubar.Append(wxglade_tmp_menu, "File") + self.SetMenuBar(self.frame_menubar) + # Menu Bar end + + self.frame_statusbar = self.CreateStatusBar(1) + self.frame_statusbar.SetStatusWidths([-1]) + # statusbar fields + frame_statusbar_fields = ["frame_statusbar"] + for i in range(len(frame_statusbar_fields)): + self.frame_statusbar.SetStatusText(frame_statusbar_fields[i], i) + + # Tool Bar + self.frame_toolbar = wx.ToolBar(self, -1) + self.SetToolBar(self.frame_toolbar) + self.frame_toolbar.Realize() + # Tool Bar end + + self.panel_1 = wx.Panel(self, wx.ID_ANY) + + grid_sizer_1 = wx.GridBagSizer(0, 0) + + sizer_1 = wx.BoxSizer(wx.VERTICAL) + grid_sizer_1.Add(sizer_1, (0, 0), (2, 1), wx.EXPAND, 0) + + label_1 = wx.StaticText(self.panel_1, wx.ID_ANY, "Text1") + sizer_1.Add(label_1, 0, 0, 0) + + label_2 = wx.StaticText(self.panel_1, wx.ID_ANY, u"Für") + sizer_1.Add(label_2, 0, 0, 0) + + label_3 = wx.StaticText(self.panel_1, wx.ID_ANY, "Statis") + sizer_1.Add(label_3, 0, 0, 0) + + self.notebook_1 = wx.Notebook(self.panel_1, wx.ID_ANY) + grid_sizer_1.Add(self.notebook_1, (0, 1), (1, 1), wx.EXPAND, 0) + + self.notebook_1_pane_1 = wx.Panel(self.notebook_1, wx.ID_ANY) + self.notebook_1.AddPage(self.notebook_1_pane_1, "notebook_1_pane_1") + + self.notebook_1_pane_2 = wx.Panel(self.notebook_1, wx.ID_ANY) + self.notebook_1.AddPage(self.notebook_1_pane_2, "notebook_1_pane_2") + + self.notebook_1_pane_3 = wx.Panel(self.notebook_1, wx.ID_ANY) + self.notebook_1.AddPage(self.notebook_1_pane_3, "notebook_1_pane_3") + + self.notebook_1_pane_4 = wx.Panel(self.notebook_1, wx.ID_ANY) + self.notebook_1.AddPage(self.notebook_1_pane_4, "notebook_1_pane_4") + + grid_sizer_3 = wx.GridBagSizer(10, 0) + grid_sizer_1.Add(grid_sizer_3, (0, 2), (2, 1), wx.EXPAND, 0) + + grid_sizer_4 = wx.GridBagSizer(0, 0) + grid_sizer_3.Add(grid_sizer_4, (0, 0), (1, 1), wx.EXPAND, 0) + + self.button_1 = wx.Button(self.panel_1, wx.ID_ANY, "button_1") + grid_sizer_4.Add(self.button_1, (0, 0), (1, 1), 0, 0) + + self.button_2 = wx.Button(self.panel_1, wx.ID_ANY, "button_2") + grid_sizer_4.Add(self.button_2, (1, 0), (1, 1), 0, 0) + + self.button_3 = wx.Button(self.panel_1, wx.ID_ANY, "button_3") + grid_sizer_4.Add(self.button_3, (2, 0), (1, 1), 0, 0) + + grid_sizer_5 = wx.GridBagSizer(0, 0) + grid_sizer_3.Add(grid_sizer_5, (1, 0), (1, 1), wx.EXPAND, 0) + + self.button_7 = wx.Button(self.panel_1, wx.ID_ANY, "button_7") + grid_sizer_5.Add(self.button_7, (0, 0), (1, 1), 0, 0) + + self.button_8 = wx.Button(self.panel_1, wx.ID_ANY, "button_8") + grid_sizer_5.Add(self.button_8, (1, 0), (1, 1), 0, 0) + + self.button_9 = wx.Button(self.panel_1, wx.ID_ANY, "button_9") + grid_sizer_5.Add(self.button_9, (2, 0), (1, 1), 0, 0) + + grid_sizer_2 = wx.GridBagSizer(0, 0) + grid_sizer_1.Add(grid_sizer_2, (1, 1), (1, 1), wx.EXPAND, 0) + + self.button_4 = wx.Button(self.panel_1, wx.ID_ANY, "button_4") + grid_sizer_2.Add(self.button_4, (0, 0), (1, 1), 0, 0) + + self.button_5 = wx.Button(self.panel_1, wx.ID_ANY, "button_5") + grid_sizer_2.Add(self.button_5, (0, 1), (1, 1), 0, 0) + + self.button_6 = wx.Button(self.panel_1, wx.ID_ANY, "button_6") + grid_sizer_2.Add(self.button_6, (0, 2), (1, 1), 0, 0) + + self.panel_1.SetSizer(grid_sizer_1) + + self.Layout() + + # end wxGlade + + def test(self, event): # wxGlade: MyFrame. + print("Event handler 'test' not implemented!") + event.Skip() + +# end of class MyFrame + +class MyApp(wx.App): + def OnInit(self): + self.frame = MyFrame(None, wx.ID_ANY, "") + self.SetTopWindow(self.frame) + self.frame.Show() + return True + +# end of class MyApp + +if __name__ == "__main__": + app = MyApp(0) + app.MainLoop() diff --git a/trial2/wxglade_out.py~ b/trial2/wxglade_out.py~ new file mode 100644 index 0000000..25b140a --- /dev/null +++ b/trial2/wxglade_out.py~ @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +# +# generated by wxGlade 1.0.2 on Sun Jul 4 21:20:06 2021 +# + +import wx + +# begin wxGlade: dependencies +# end wxGlade + +# begin wxGlade: extracode +# end wxGlade + + +class MyFrame(wx.Frame): + def __init__(self, *args, **kwds): + # begin wxGlade: MyFrame.__init__ + kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + self.SetSize((474, 290)) + self.SetTitle("frame") + + # Menu Bar + self.frame_menubar = wx.MenuBar() + self.SetMenuBar(self.frame_menubar) + # Menu Bar end + + self.panel_1 = wx.Panel(self, wx.ID_ANY) + + grid_sizer_1 = wx.GridBagSizer(0, 0) + + sizer_1 = wx.BoxSizer(wx.VERTICAL) + grid_sizer_1.Add(sizer_1, (0, 0), (2, 1), wx.EXPAND, 0) + + label_1 = wx.StaticText(self.panel_1, wx.ID_ANY, "Text1") + sizer_1.Add(label_1, 0, 0, 0) + + label_2 = wx.StaticText(self.panel_1, wx.ID_ANY, u"Für") + sizer_1.Add(label_2, 0, 0, 0) + + label_3 = wx.StaticText(self.panel_1, wx.ID_ANY, "Statis") + sizer_1.Add(label_3, 0, 0, 0) + + self.notebook_1 = wx.Notebook(self.panel_1, wx.ID_ANY) + grid_sizer_1.Add(self.notebook_1, (0, 1), (1, 1), wx.EXPAND, 0) + + self.notebook_1_pane_1 = wx.Panel(self.notebook_1, wx.ID_ANY) + self.notebook_1.AddPage(self.notebook_1_pane_1, "notebook_1_pane_1") + + self.notebook_1_pane_2 = wx.Panel(self.notebook_1, wx.ID_ANY) + self.notebook_1.AddPage(self.notebook_1_pane_2, "notebook_1_pane_2") + + self.notebook_1_pane_3 = wx.Panel(self.notebook_1, wx.ID_ANY) + self.notebook_1.AddPage(self.notebook_1_pane_3, "notebook_1_pane_3") + + self.notebook_1_pane_4 = wx.Panel(self.notebook_1, wx.ID_ANY) + self.notebook_1.AddPage(self.notebook_1_pane_4, "notebook_1_pane_4") + + grid_sizer_3 = wx.GridBagSizer(10, 0) + grid_sizer_1.Add(grid_sizer_3, (0, 2), (2, 1), wx.EXPAND, 0) + + grid_sizer_4 = wx.GridBagSizer(0, 0) + grid_sizer_3.Add(grid_sizer_4, (0, 0), (1, 1), wx.EXPAND, 0) + + self.button_1 = wx.Button(self.panel_1, wx.ID_ANY, "button_1") + grid_sizer_4.Add(self.button_1, (0, 0), (1, 1), 0, 0) + + self.button_2 = wx.Button(self.panel_1, wx.ID_ANY, "button_2") + grid_sizer_4.Add(self.button_2, (1, 0), (1, 1), 0, 0) + + self.button_3 = wx.Button(self.panel_1, wx.ID_ANY, "button_3") + grid_sizer_4.Add(self.button_3, (2, 0), (1, 1), 0, 0) + + grid_sizer_5 = wx.GridBagSizer(0, 0) + grid_sizer_3.Add(grid_sizer_5, (1, 0), (1, 1), wx.EXPAND, 0) + + self.button_7 = wx.Button(self.panel_1, wx.ID_ANY, "button_7") + grid_sizer_5.Add(self.button_7, (0, 0), (1, 1), 0, 0) + + self.button_8 = wx.Button(self.panel_1, wx.ID_ANY, "button_8") + grid_sizer_5.Add(self.button_8, (1, 0), (1, 1), 0, 0) + + self.button_9 = wx.Button(self.panel_1, wx.ID_ANY, "button_9") + grid_sizer_5.Add(self.button_9, (2, 0), (1, 1), 0, 0) + + grid_sizer_2 = wx.GridBagSizer(0, 0) + grid_sizer_1.Add(grid_sizer_2, (1, 1), (1, 1), wx.EXPAND, 0) + + self.button_4 = wx.Button(self.panel_1, wx.ID_ANY, "button_4") + grid_sizer_2.Add(self.button_4, (0, 0), (1, 1), 0, 0) + + self.button_5 = wx.Button(self.panel_1, wx.ID_ANY, "button_5") + grid_sizer_2.Add(self.button_5, (0, 1), (1, 1), 0, 0) + + self.button_6 = wx.Button(self.panel_1, wx.ID_ANY, "button_6") + grid_sizer_2.Add(self.button_6, (0, 2), (1, 1), 0, 0) + + self.panel_1.SetSizer(grid_sizer_1) + + self.Layout() + # end wxGlade + +# end of class MyFrame + +class MyApp(wx.App): + def OnInit(self): + self.frame = MyFrame(None, wx.ID_ANY, "") + self.SetTopWindow(self.frame) + self.frame.Show() + return True + +# end of class MyApp + +if __name__ == "__main__": + app = MyApp(0) + app.MainLoop() diff --git a/view.py b/view.py index 93da7d1..771e9ba 100644 --- a/view.py +++ b/view.py @@ -53,8 +53,8 @@ class PlotPanel(wx.Panel): def init_plot_data(self): self.ax = self.fig.add_subplot() self.fig.legend() - self.x, self.y = self.model.sensors["temp"].get_data - (self.im,) = self.ax.plot(self.x, self.y, "-.",label="temp") + dat = self.model.plot_data + (self.im,) = self.ax.plot(dat.get("time"), dat.get("temp"), "-.",label="temp") self.toolbar.update() # Not sure why this is needed - ADS def get_toolbar(self): @@ -63,9 +63,10 @@ class PlotPanel(wx.Panel): return self.toolbar def on_paint(self, event): - self.x, self.y = self.model.sensors["temp"].get_data + dat = self.model.plot_data.data # print(self.x) - self.im.set_data(self.x, self.y) + + self.im.set_data(dat.get("time"), dat.get("temp")) self.ax.relim() self.ax.autoscale_view() self.canvas.draw()