diff --git a/sealammonia.fbp b/sealammonia.fbp index af73cfe..1437921 100644 --- a/sealammonia.fbp +++ b/sealammonia.fbp @@ -1863,97 +1863,6 @@ - - 5 - 1 - 1 - wxALL - 0 - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 0 - - 1 - - 0 - 0 - wxID_ANY - Plot - - 0 - - - 0 - - 1 - plot_but - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/serial_plotter.py b/serial_plotter.py index cea419a..fc5c5e6 100644 --- a/serial_plotter.py +++ b/serial_plotter.py @@ -4,7 +4,7 @@ import matplotlib import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation import os, json, traceback, ui, wx -matplotlib.use("WXAgg") +matplotlib.use("WXAgg") # for JetBrains IDE to force use the wx backend class SerialPlotter: def __init__(self) -> None: @@ -35,10 +35,10 @@ class SerialPlotter: wx.MessageBox(f"File has saved as {os.path.split(file)[1]} under {os.path.split(file)[0]} directory!\n") def animation(self, t:int) -> None: - """ render a from of the animated graph """ - # print("hi") + """ render a frame of the animated graph """ try: plt.cla() # clear previous frame + # read the last line from the .csv file, the data start from the second colunm so omit index # 0 file = open(self.settings["file_name"], "r") ndata = np.array([np.asarray(line.split(", ")[1:], dtype=np.float32) for line in file]) if len(ndata) > 0: @@ -64,7 +64,7 @@ class SerialPlotter: except: traceback.print_exc() - def plotting(self) -> None: + def plotting(self) -> FuncAnimation: ani = FuncAnimation(self.fig, self.animation, blit=False) return ani diff --git a/test.py b/test.py index 42341ef..92e1d3c 100644 --- a/test.py +++ b/test.py @@ -1,5 +1,5 @@ from ui import Frame -from threading import * +from multiprocessing import * from read_arduino import * from serial_plotter import * import os, json, wx, warnings @@ -11,7 +11,7 @@ warnings.filterwarnings("ignore", category=DeprecationWarning) HEIGHT = 800 WIDTH = 800 -global ani +global ani, t1 def main(): @@ -39,7 +39,6 @@ def main(): raise ValueError(f"expecting 5 resistor values, but got {len(resistors)}!!!") gen_settings(resistors, input_voltage, bit_rate, port, filename, window_size, delay) - return filename def gen_settings(resistors, input_voltage, bits, port, filename, window_size, delay): @@ -68,34 +67,37 @@ def get_devices(): frame.dev_list.AppendItems(ports) -def runPlot(e): - global ani +def run(e): + """ + run the read_arduino.py and Serial Plotter in parallel + """ + global ani, t1 # the variables to call the plotter and the read_arduino.py, we want them to get tossed around between functions and even programs + main() + if 't1' in globals(): + t1.terminate() # end the previous serial reads, if there is any + + # place the read() function from read_arduino into another process to run it in background + t1 = Process(target=read, args=()) + t1.start() + + # run the plotter. Note that we should not put the plotter class, or function, in another process since + # matplot's FuncAnimation doesn't like that plotter = SerialPlotter() ani = plotter.plotting() plotter.fig.show() - -def run(e): - file = main() - t1 = Thread(target=read, args=()) - t1.setDaemon(True) - t1.start() - - runPlot(e) - frame.btLaunch.Enable(False) - frame.plot_but.Enable(True) # this might have some problem ... what happen if user spamming the plot button? + frame.btLaunch.SetLabelText("Plot") # change the text on the "launch" button to "plot" if not frame.show_msg.GetValue(): frame.Hide() if __name__ == '__main__': + global t1 app = wx.App() frame = Frame(None) get_devices() frame.SetTitle("Cease your resistance! - alpha 0.1.1") frame.btLaunch.Bind(wx.EVT_BUTTON, run) - frame.plot_but.Bind(wx.EVT_BUTTON, - runPlot) # There is one problem with this approch: what happen if user spamming the plot button? if os.path.isfile("settings.json"): print("Found existing settings.json, auto-fill previous inputs!") settings = json.load(open('settings.json', 'r')) @@ -109,3 +111,5 @@ if __name__ == '__main__': frame.Show() app.MainLoop() + if 't1' in globals(): + t1.terminate() # end the process if it has been started \ No newline at end of file diff --git a/ui.py b/ui.py index 18b7a74..89fef7e 100644 --- a/ui.py +++ b/ui.py @@ -8,7 +8,6 @@ ########################################################################### import wx -import wx.xrc ########################################################################### ## Class Frame @@ -92,7 +91,7 @@ class Frame ( wx.Frame ): self.sizer_prompt.Wrap( -1 ) gbSizer8.Add( self.sizer_prompt, wx.GBPosition( 2, 0 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT, 5 ) - self.m_textCtrl26 = wx.TextCtrl( v_entre.GetStaticBox(), wx.ID_ANY, u"20", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.m_textCtrl26 = wx.TextCtrl( v_entre.GetStaticBox(), wx.ID_ANY, u"480", wx.DefaultPosition, wx.DefaultSize, 0 ) self.m_textCtrl26.SetToolTipString( u"Window size for the plot window. If want infinite/maximum size, type 0" ) gbSizer8.Add( self.m_textCtrl26, wx.GBPosition( 2, 1 ), wx.GBSpan( 1, 1 ), wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.TOP|wx.RIGHT|wx.LEFT, 5 ) @@ -137,11 +136,6 @@ class Frame ( wx.Frame ): self.btLaunch.SetDefault() launch_opt.Add( self.btLaunch, wx.GBPosition( 0, 0 ), wx.GBSpan( 1, 1 ), wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL, 5 ) - self.plot_but = wx.Button( self, wx.ID_ANY, u"Plot", wx.DefaultPosition, wx.DefaultSize, 0 ) - self.plot_but.Enable( False ) - - launch_opt.Add( self.plot_but, wx.GBPosition( 0, 1 ), wx.GBSpan( 1, 1 ), wx.ALL, 5 ) - bSizer1.Add( launch_opt, 0, wx.ALIGN_CENTER_HORIZONTAL, 5 )