[英]How can I modify this code so that I am not replotting my graph everytime, matplotlib
I am grabbing data from a device and wanting to plot the voltage of it, with the plot being embedded into the UI . 我正在从设备中获取数据,并希望绘制其电压,并将该图嵌入到UI中 。 I used the example here: http://matplotlib.org/examples/user_interfaces/embedding_in_qt4.html 我在这里使用了示例: http : //matplotlib.org/examples/user_interfaces/embedding_in_qt4.html
This example works fine but when I add 2 or more graphs, the whole UI becomes really slow (using a RPi3) and CPU usage is really high. 这个示例工作正常,但是当我添加2个或更多图形时,整个UI会变得非常慢(使用RPi3)并且CPU使用率会非常高。 I realise this is probably because the graph is constantly being cleared and replotted. 我意识到这可能是因为图形不断被清除和重新绘制。
My code looks like this: 我的代码如下所示:
class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=2, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
def compute_initial_figure(self):
pass
class MyDynamicMplCanvas(MyMplCanvas):
def __init__(self, *args, **kwargs):
MyMplCanvas.__init__(self, *args, **kwargs)
def compute_initial_figure(self):
self.axes.cla()
def update_figure(self,voltage):
self.axes.cla()
self.axes.plot(np.linspace(0,len(voltage)-1,num = len(voltage)), voltage, 'b')
self.axes.set_xlabel("Time")
self.draw()
class worker_thread(QThread):
... #worker thread stuff here
class Monitor(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.exit_button.clicked.connect(exit)
self.ui.go_button.clicked.connect(self.start_monitoring)
self.ui.print_button.clicked.connect(self.test_print)
self.ac_graph = QtGui.QWidget(self)
self.ac_1_graph = MyDynamicMplCanvas(self.ac_graph,width = 10, height =3 , dpi = 60)
self.ui.mplvl.addWidget(self.ac_1_graph)
self.ac_1_graph.axes.set_xlabel("Time")
self.dc_graph = QtGui.QWidget(self)
self.dc_2_graph = MyDynamicMplCanvas(self.dc_graph,width = 10, height =3 , dpi = 60)
self.ui.mplvl_2.addWidget(self.dc_2_graph)
self.ac1_voltage_values = []
self.ac1_current_values = []
self.dc2_voltage_values = []
def start_monitoring(self):
self.worker_thread = worker_thread()
self.connect(self.worker_thread,SIGNAL('grid_done'), self.update_ac_dc_info)
def update_plot_values(self, y_value, y_list):
y_list.append(y_value)
if (len(y_list) == 61):
del y_list[0]
return y_list
def update_ac_dc_info(self,grid_info):
self.ac1_voltage_values = self.update_plot_values((grid_info['ac1_voltage']/10),self.ac1_voltage_values)
self.ac_1_graph.update_figure(self.ac1_voltage_values)
Essentially, when data comes back from my device, I emit a signal from the worker_thread which triggers my UI to update in the main thread, as well as the plot. 本质上,当数据从我的设备返回时,我从worker_thread发出信号,该信号触发我的UI在主线程以及绘图中进行更新。 At this point, how do I just get matplotlib to just accept the new point that came in WITHOUT replotting the whole thing? 在这一点上,我如何让matplotlib接受新的观点,而无需重新介绍整个过程? Many of the examples I've read utilise pyplot which I can't use because I need to embed this in an existing UI. 我阅读的许多示例都使用了pyplot,我无法使用它,因为我需要将其嵌入到现有的UI中。
Instead of clearing the axes everytime there is new data, you can just redraw the line of points. 不必每次都有新数据时都清除轴,而只需重绘点线即可。 This would save some time. 这样可以节省一些时间。
class MyDynamicMplCanvas(MyMplCanvas):
def __init__(self, *args, **kwargs):
MyMplCanvas.__init__(self, *args, **kwargs)
def compute_initial_figure(self):
# empty plot
self.line, = self.axes.plot([],[], color="b")
self.axes.set_xlabel("Time") # xlabel will not change over time
def update_figure(self,voltage):
self.line.set_data(np.linspace(0,len(voltage)-1,num = len(voltage)), voltage)
# now you need to take care of the axis limits yourself
self.axes.set_xlim([0,len(voltage])
self.draw()
Updating only the last new point is a bit tricky, since the plot consist of a single Line2D
object. 仅更新最后一个新点有点棘手,因为绘图由单个Line2D
对象组成。 You could opt for a point plot, where you can plot a single new point every time new data arrives. 您可以选择点图,每次新数据到达时都可以在其中绘制一个新点。
ImportanceOfBeingErnest's method works just fine. ImportanceOfBeingErnest的方法效果很好。 To rescale the axis based on the data: 要根据数据重新缩放轴,请执行以下操作:
self.axes.relim()
self.axes.autoscale_view(True,True,True)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.