2017-01-19 60 views
1

我從設備中抓取數據並想繪製它的電壓,並且將嵌入到UI中。我用這裏的例子:http://matplotlib.org/examples/user_interfaces/embedding_in_qt4.html我該如何修改此代碼,以便每次都不重新繪製我的圖形,matplotlib

這個例子工作正常,但是當我添加2個或更多的圖表時,整個UI變得非常慢(使用RPi3)並且CPU使用率非常高。我意識到這可能是因爲圖形不斷被清除並重新繪製。

我的代碼如下所示:

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) 

從本質上講,當數據來自我的設備回來,我發出的觸發我的用戶界面在主線程來更新worker_thread的信號,以及劇情。在這一點上,我該如何讓matplotlib接受沒有重新繪製整個事物的新點?我讀過的很多示例都使用了pyplot,我不能使用它,因爲我需要將其嵌入到現有的UI中。

回答

2

而不是每次有新的數據清理軸,你可以重繪一系列的點。這會節省一些時間。

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() 

只更新上一個新的點是有點棘手,因爲劇情由單個Line2D對象。您可以選擇一個點圖,每次新數據到達時您可以繪製一個新點。

+0

感謝您的回覆!我將我的代碼修改爲您發佈的內容,並且工作得很好。我可以在Raspberry Pi上以最小的CPU負載繪製兩張圖。在我有任何時候都有100%的核心擊穿之前。現在我可以在程序運行時做其他事情。發現我的函數'update_plot_values'只負責通過自動刪除列表的最後一個值並附加一個新值來繪製最後一個點,然後將整個列表傳遞給'set_data'!我也解決了軸重新調整問題(如果有人想知道,請參閱我的答案) – jgv115

0

ImportanceOfBeingErnest的方法工作得很好。根據數據重新調整座標軸:

self.axes.relim() 
self.axes.autoscale_view(True,True,True) 
相關問題