I am new to PyQt4 and real time plots. I am trying to plot some random real time data on PyQt4 application using matplotlib and Python2.7 . My code looks like this:
#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import random
from PyQt4 import QtGui
from PyQt4 import QtCore
import sys
import time
class mplCanvas(FigureCanvas):
def __init__(self, parent=None):
self.fig = plt.figure(1)
self.ax = self.fig.add_subplot(111)
self.ax.grid(True)
self.manager = plt.get_current_fig_manager()
super(mplCanvas, self).__init__(self.fig)
self.setParent(parent)
self.init_figure()
class CustomFigCanvas(mplCanvas):
def __init__(self, *args, **kwargs):
mplCanvas.__init__(self, *args, **kwargs)
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.updateFigure)
def init_figure(self):
xaxis = np.arange(0, 100, 1)
yaxis = np.array([0]*100)
self.ax.set_title("Realtime Waveform Plot")
self.ax.set_xlabel("Time")
self.ax.set_ylabel("Amplitude")
self.ax.axis([0, 100, -1.5, 1.5])
self.line1 = self.ax.plot(xaxis, yaxis, '-')
self.values = []
def addData(self):
self.values.append(random.random() * 2 - 1)
def updateFigure(self):
self.addData()
CurrentXAxis=np.arange(len(self.values)-100, len(self.values), 1)
self.line1[0].set_data(CurrentXAxis, np.array(self.values[-100:]))
self.ax.axis([CurrentXAxis.min(), CurrentXAxis.max(), -1.5, 1.5])
self.manager.canvas.draw()
And in the main application I call graph = CustomFigCanvas()
But all it does is it prints the plot with a straight line at 0 and the graph does not update at all. I cannot figure out what am I doing wrong. Why my plot is not updating? I was trying several options and still have the same result. I tried to do QThread to emit samples of data but it still did not work. All I get is a straight line. Do you have any suggestions? Any tips would be much appreciated. Thank you.
The main problem is that you set up a QTimer
but never start it. So the updating function will never be called. What you need to do is something like
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.updateFigure)
self.timer.start(1000) # 1000 milliseconds
Another problem is then how you create the data to update. The way it is in the code produces arrays of different length for the x and y coordinates, leading to errors.
Here is a complete running example where I also got rid of the unnecessary double subclassing.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import random
from PyQt4 import QtGui
from PyQt4 import QtCore
import sys
class CustomFigCanvas(FigureCanvas):
def __init__(self, parent=None, *args, **kwargs):
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111)
self.ax.grid(True)
super(CustomFigCanvas, self).__init__(self.fig)
self.setParent(parent)
self.init_figure()
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.updateFigure)
self.timer.start(1000)
def init_figure(self):
xaxis = np.arange(0, 100, 1)
yaxis = np.array([0]*100)
self.ax.set_title("Realtime Waveform Plot")
self.ax.set_xlabel("Time")
self.ax.set_ylabel("Amplitude")
self.ax.axis([0, 100, -1.5, 1.5])
self.line1 = self.ax.plot(xaxis, yaxis, '-')
self.values = []
self.fig.tight_layout()
def addData(self):
self.values.append(random.random() * 2 - 1)
def updateFigure(self):
self.addData()
CurrentXAxis=np.arange(len(self.values))
self.line1[0].set_data(CurrentXAxis, np.array(self.values))
self.ax.axis([CurrentXAxis.min()-0.001, CurrentXAxis.max()+0.001, -1.5, 1.5])
self.fig.canvas.draw()
class App(QtGui.QMainWindow):
def __init__(self, parent=None):
super(App, self).__init__(parent)
self.tab = QtGui.QWidget()
self.setCentralWidget(self.tab)
self.tablayout = QtGui.QVBoxLayout(self.tab)
self.canvas = CustomFigCanvas()
self.tablayout.addWidget(self.canvas)
app = QtGui.QApplication(sys.argv)
thisapp = App()
thisapp.show()
app.exec_()
In your code you had the following errors:
{your timer}.start({period in ms})
self.manager.canvas.draw()
to self.draw()
init_figure
was never declared in mplCanvas
import sys
from PyQt4 import QtGui
import numpy as np
import matplotlib
matplotlib.use("Qt4Agg")
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import random
from PyQt4 import QtCore
class mplCanvas(FigureCanvas):
def __init__(self, parent=None):
self.fig = plt.figure(1)
self.ax = self.fig.add_subplot(111)
self.ax.grid(True)
super(mplCanvas, self).__init__(figure=self.fig)
self.setParent(parent)
self.init_figure()
def init_figure(self):
pass
class CustomFigCanvas(mplCanvas):
def __init__(self, *args, **kwargs):
mplCanvas.__init__(self, *args, **kwargs)
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.updateFigure)
self.timer.start(100)
def init_figure(self):
xaxis = np.arange(0, 100, 1)
self.values = [0]*100
yaxis = np.array(self.values)
self.ax.set_title("Realtime Waveform Plot")
self.ax.set_xlabel("Time")
self.ax.set_ylabel("Amplitude")
self.ax.axis([0, 100, -1.5, 1.5])
self.line1 = self.ax.plot(xaxis, yaxis, '-')
def addData(self):
self.values.append(random.random() * 2 - 1)
def updateFigure(self):
self.addData()
CurrentXAxis = np.arange(len(self.values)-100, len(self.values), 1)
self.line1[0].set_data(CurrentXAxis, np.array(self.values[-100:]))
self.ax.axis([CurrentXAxis.min(), CurrentXAxis.max(), -1.5, 1.5])
self.draw()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main_widget = QtGui.QWidget()
l = QtGui.QVBoxLayout(main_widget)
graph = CustomFigCanvas(main_widget)
l.addWidget(graph)
main_widget.show()
sys.exit(app.exec_())
Screenshot:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.