I want to plot the data from a sensor in real time to two figures (simultaneously) using wx and matplotlib (data is coming through Arduino Serial). I have been able to plot the data on the second plot, but not in the first one, as it can be checked in this screenshot:
I am using wx.boxsizer to create 3 parts in the window (function Initbody), where the second and the third parts are for each graph. Then the function InitMPL calls to matplotlib. Finally I use a thread to call to the animation for the graph plotting. Find here the full code:
import wx
import numpy as np
import matplotlib.figure as mfigure
import matplotlib.animation as manim
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
import serial.tools.list_ports
import threading
import data
import gui
import read_serial
import data_proc as dproc
class FlowBattGUI(wx.Frame):
def __init__(self, data_queue=None, parent=None):
super().__init__(None, style=wx.MAXIMIZE_BOX | wx.RESIZE_BORDER
| wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX, title='Flow Battery Gui')
creds = sheets.verify_and_cred()
self.service = sheets.build('sheets', 'v4', credentials=creds)
self.data_queue = data_queue
self.InitGUI()
def InitGUI(self):
self.SetSize(1800, 1000)
self.Center()
self.InitMenu()
panel = wx.Panel(self)
self.InitBody(panel)
# Initalize the main GUI components
def InitBody(self, panel : wx.Panel):
body_sizer = wx.BoxSizer(wx.VERTICAL)
CtrlPanelsizer = wx.BoxSizer(wx.HORIZONTAL)
self.InitCtrlPanel(panel, CtrlPanelsizer)
body_sizer.Add(CtrlPanelsizer, 0, wx.EXPAND)
ocvsizer = wx.BoxSizer(wx.HORIZONTAL)
l1 = wx.StaticText(panel,label = "OCV vs time", style = wx.ALIGN_CENTRE)
body_sizer.Add(l1, 0, wx.ALIGN_CENTER_HORIZONTAL, 20)
self.InitMPL(panel, ocvsizer)
body_sizer.Add(ocvsizer, 1, wx.EXPAND)
m2sizer = wx.BoxSizer(wx.HORIZONTAL)
l2 = wx.StaticText(panel,label = "Derivative vs time", style = wx.ALIGN_CENTRE)
body_sizer.Add(l2, 0, wx.ALIGN_CENTER_HORIZONTAL, 20)
self.InitMPL(panel, m2sizer)
body_sizer.Add(m2sizer, 1, wx.EXPAND)
bsizer = wx.BoxSizer(wx.HORIZONTAL)
self.InitCmdPanel(panel, bsizer)
body_sizer.Add(bsizer, 0, wx.EXPAND, 5)
panel.SetSizer(body_sizer)
# Initialize the MatPlotLib section
def InitMPL(self, panel : wx.Panel, sizer : wx.BoxSizer):
self.fig = mfigure.Figure()
self.ax = self.fig.subplots()
self.fig.set_figheight(2)
self.canv = FigureCanvasWxAgg(panel, wx.ID_ANY, self.fig)
self.times = []
self.values = []
self.animator = manim.FuncAnimation(self.fig, self.anim, interval=600)
sizer.Add(self.canv, 1, wx.ALL | wx.EXPAND, 5)
def anim(self,i):
if self.data_queue == None:
# this is to setup the data queue
if i != 0:
self.values.append(np.random.rand())
else:
self.values = []
return
self.ax.clear()
self.ax.plot(np.arange(1,i+1), self.values, 'd-')
else:
# data queue is already set up
new_data = None
if i != 0:
if len(self.times) == 60:
# clear data after 60 points
self.values = []
self.times = []
# should be of type SensorData
if not self.data_queue:
return
new_data = self.data_queue.pop(0)
if new_data == None:
return
if new_data.data == None or new_data.time == None:
return
self.values.append(float(new_data.data))
self.times.append(float(new_data.time))
else:
self.values = []
return
self.ax.clear()
self.ax.plot(np.arange(1,len(self.values)+1), self.values, 'd-')
t = threading.Thread(target=self.writeData, args=[new_data])
t.start()
def writeData(self, new_data):
sheets.append_range(self.service, new_data, "Sheet1!A2")
data.append_data(new_data.encstr)
def start_gui(data_queue : list):
print(data_queue)
# Create a new app in wx
app = wx.App()
frame = FlowBattGUI(data_queue, None)
frame.Show(True)
app.MainLoop()
Is this possible?
