Goal: Realtime data plot using Pandas.
We plot realtime data for the first time. There is issue, such as focus stealing. We can deal with this with low level matplotlib.
7: Realtime Plotting Using Simple Data
Before we go into complex plotting, we have to walk the walk, and plot the plot, run the script.
Python Source Code
I recommend you to get an overview with reading the source. So you won’t get lost along the way.
Interpolate from SciPy
Smoothing our realtime data is easy with SciPy.
import paho.mqtt.client as mqtt import matplotlib import matplotlib.pyplot as plt import numpy as np import time from scipy import interpolate
Looks like there’s no complex stuff. But in details, some method are longer than usual.
class mqSubscriber: def __init__(self): def chart_setup(self): def update_line(self, new_num): def on_connect(self, client, userdata, flags, rc): def on_message(self, client, userdata, msg): def main(self):
We need to separate chart setup and initial data.
class mqSubscriber: def __init__(self): # save initial parameter self.index = 0 self.chart_setup()
Setting Up Chart
Do not forget to setup the chart.
def chart_setup(self): self.xdata =  self.ydata =  self.fig, self.axes = plt.subplots() self.line, = self.axes.plot( self.xdata, self.ydata, 'r-') self.fig.canvas.mpl_connect( 'close_event', exit)
We will use
self.lines in our class method.
Just very ordinary
def main(self): plt.ion() plt.show() client = mqtt.Client() client.connect("localhost",1883,60) client.on_connect = self.on_connect client.on_message = self.on_message client.loop_forever()
Except that we have this two lines:
We should set the interactive mode on in realtime plot,
Event Handler: On Connect
Nothing special. The same as official documentation.
def on_connect(self, client, userdata, flags, rc): print("Connected with result code "+str(rc)) client.subscribe("topic/signal")
Event Handler: On Message
We need to update the line. I put the detail on its own method.
def on_message(self, client, userdata, msg): float_num = float(msg.payload.decode()) self.update_line(float_num)
Since the data change over time passes, we need to update the limit
# recompute the ax.dataLim # update ax.viewLim using the new dataLim self.axes.relim() self.axes.autoscale_view()
This is why I set
self.axes on the chart setup.
All good, the data displayed correctly.
Except that when I call
The window steal focus.
I can’t evenm type on my terminal,
because the focus always go back to matplotlib chart.
Nothing so bad. I google, then I find the answer on stackoverflow.
def on_message(self, client, userdata, msg): ... # issue: steal focus plt.draw() self.fig.canvas.draw_idle() self.fig.canvas.start_event_loop(0.001) time.sleep(0.1)
This is why I set
self.fig on the first place.
I must admit, that I do no really understand about, what’s really going on here. But this works for me. Maybe I will go deep into low level matplotlib some other time.
Interpolation can be done this way:
n = len(self.ydata) tck = interpolate.splrep( self.xdata, self.ydata, s=0) xfit = np.arange(0, n-1, np.pi/50) yfit = interpolate.splev(xfit, tck, der=0)
But we should aware that we can’t interpolate data, if the number of data is insufficient.
The result of interpolation can be displayed in below figure.
MQTT Message Handler
The complete method is here below.
Afterr get the right
we can update the data series into matplotlib axes.
def update_line(self, new_num): self.index += 1 self.xdata.append(self.index) self.ydata.append(new_num) if self.index <= 3: self.line.set_xdata(self.xdata) self.line.set_ydata(self.ydata) else: n = len(self.ydata) tck = interpolate.splrep( self.xdata, self.ydata, s=0) xfit = np.arange(0, n-1, np.pi/50) yfit = interpolate.splev(xfit, tck, der=0) self.line.set_xdata(xfit) self.line.set_ydata(yfit)
This is why I set
self.line from the very beginning.
We can humbly run the class in peace.
mqSub = mqSubscriber() mqSub.main()
It is a good time to run the code above.
This chart video below, should help you figure out, the result of code above.
As you can see the start point is stuck there, we will need to enhance the plot, so it looks like moving chart.
What is Next 🤔?
Simple realtime plotting achieved,but the real challenge is smoothing time series using dataframe. We have already solve smoothing time series in previous article, we still need to combine the trick with above plot, and also we need to make pretty chart.
This is the minimum viable prototype that we want to achieve.
Consider continue reading [ Python - MQTT - Smooth Timeseries Plot ].