• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

Python/Matplotlib/Pyside快速时间追踪滚动

python 来源:user2304916 5次浏览

我有很大的时间痕迹,必须视觉检查,所以我需要一个快速滚动工具。Python/Matplotlib/Pyside快速时间追踪滚动

如何实现最快的Maplotlib/Pyside滚动?

我知道,我添加了一个PySide滚动条到MPL图中,并用set_xlim()方法更新了图的x范围。这个速度不够快,特别是因为在最终的应用程序中,我必须在不同的子图中至少有8个时间轨迹,它们必须全部滚动到一起。 A figure of the plot is attached。

是否有改进的余地?

在这里,我附上演示代码,演示相对较低的滚动。它很长,但几乎都是锅炉板代码。有趣的位(需要改进)在xpos_changed()方法中,绘图xlimits被改变。

编辑:下面我并入由tcaswell提出了一些微优化,但更新速度没有提高。

from PySide import QtGui, QtCore 
import pylab as plt 
import numpy as np 

N_SAMPLES = 1e6 

def test_plot(): 
    time = np.arange(N_SAMPLES)*1e-3 
    sample = np.random.randn(N_SAMPLES) 
    plt.plot(time, sample, label="Gaussian noise") 
    plt.title("1000s Timetrace \n (use the slider to scroll and the spin-box to set the width)") 
    plt.xlabel('Time (s)') 
    plt.legend(fancybox=True) 
    q = ScrollingToolQT(plt.gcf(), scroll_step=10) 
    return q # WARNING: it's important to return this object otherwise 
       # python will delete the reference and the GUI will not respond! 


class ScrollingToolQT(object): 
    def __init__(self, fig, scroll_step=10): 
     # Setup data range variables for scrolling 
     self.fig = fig 
     self.scroll_step = scroll_step 
     self.xmin, self.xmax = fig.axes[0].get_xlim() 
     self.width = 1 # axis units 
     self.pos = 0 # axis units 
     self.scale = 1e3 # conversion betweeen scrolling units and axis units 

     # Save some MPL shortcuts 
     self.ax = self.fig.axes[0] 
     self.draw = self.fig.canvas.draw 
     #self.draw_idle = self.fig.canvas.draw_idle 

     # Retrive the QMainWindow used by current figure and add a toolbar 
     # to host the new widgets 
     QMainWin = fig.canvas.parent() 
     toolbar = QtGui.QToolBar(QMainWin) 
     QMainWin.addToolBar(QtCore.Qt.BottomToolBarArea, toolbar) 

     # Create the slider and spinbox for x-axis scrolling in toolbar 
     self.set_slider(toolbar) 
     self.set_spinbox(toolbar) 

     # Set the initial xlimits coherently with values in slider and spinbox 
     self.ax.set_xlim(self.pos,self.pos+self.width) 
     self.draw() 

    def set_slider(self, parent): 
     self.slider = QtGui.QSlider(QtCore.Qt.Horizontal, parent=parent) 
     self.slider.setTickPosition(QtGui.QSlider.TicksAbove) 
     self.slider.setTickInterval((self.xmax-self.xmin)/10.*self.scale) 
     self.slider.setMinimum(self.xmin*self.scale) 
     self.slider.setMaximum((self.xmax-self.width)*self.scale) 
     self.slider.setSingleStep(self.width*self.scale/4.) 
     self.slider.setPageStep(self.scroll_step*self.width*self.scale) 
     self.slider.setValue(self.pos*self.scale) # set the initial position 
     self.slider.valueChanged.connect(self.xpos_changed) 
     parent.addWidget(self.slider) 

    def set_spinbox(self, parent): 
     self.spinb = QtGui.QDoubleSpinBox(parent=parent) 
     self.spinb.setDecimals(3) 
     self.spinb.setRange(0.001,3600.) 
     self.spinb.setSuffix(" s") 
     self.spinb.setValue(self.width) # set the initial width 
     self.spinb.valueChanged.connect(self.xwidth_changed) 
     parent.addWidget(self.spinb) 

    def xpos_changed(self, pos): 
     #pprint("Position (in scroll units) %f\n" %pos) 
     pos /= self.scale 
     self.ax.set_xlim(pos, pos+self.width) 
     self.draw() 

    def xwidth_changed(self, width): 
     #pprint("Width (axis units) %f\n" % step) 
     if width <= 0: return 
     self.width = width 
     self.slider.setSingleStep(self.width*self.scale/5.) 
     self.slider.setPageStep(self.scroll_step*self.width*self.scale) 
     old_xlim = self.ax.get_xlim() 
     self.xpos_changed(old_xlim[0]*self.scale) 


if __name__ == "__main__": 
    q = test_plot() 
    plt.show() 


===========解决方案如下:

这似乎有点更快/更敏感:

from PySide import QtGui, QtCore 
import pylab as plt 
import numpy as np 

N_SAMPLES = 1e6 

def test_plot(): 
    time = np.arange(N_SAMPLES)*1e-3 
    sample = np.random.randn(N_SAMPLES) 
    plt.plot(time, sample, label="Gaussian noise") 
    plt.legend(fancybox=True) 
    plt.title("Use the slider to scroll and the spin-box to set the width") 
    q = ScrollingToolQT(plt.gcf()) 
    return q # WARNING: it's important to return this object otherwise 
       # python will delete the reference and the GUI will not respond! 


class ScrollingToolQT(object): 
    def __init__(self, fig): 
     # Setup data range variables for scrolling 
     self.fig = fig 
     self.xmin, self.xmax = fig.axes[0].get_xlim() 
     self.step = 1 # axis units 

     self.scale = 1e3 # conversion betweeen scrolling units and axis units 

     # Retrive the QMainWindow used by current figure and add a toolbar 
     # to host the new widgets 
     QMainWin = fig.canvas.parent() 
     toolbar = QtGui.QToolBar(QMainWin) 
     QMainWin.addToolBar(QtCore.Qt.BottomToolBarArea, toolbar) 

     # Create the slider and spinbox for x-axis scrolling in toolbar 
     self.set_slider(toolbar) 
     self.set_spinbox(toolbar) 

     # Set the initial xlimits coherently with values in slider and spinbox 
     self.set_xlim = self.fig.axes[0].set_xlim 
     self.draw_idle = self.fig.canvas.draw_idle 
     self.ax = self.fig.axes[0] 
     self.set_xlim(0, self.step) 
     self.fig.canvas.draw() 

    def set_slider(self, parent): 
     # Slider only support integer ranges so use ms as base unit 
     smin, smax = self.xmin*self.scale, self.xmax*self.scale 

     self.slider = QtGui.QSlider(QtCore.Qt.Horizontal, parent=parent) 
     self.slider.setTickPosition(QtGui.QSlider.TicksAbove) 
     self.slider.setTickInterval((smax-smin)/10.) 
     self.slider.setMinimum(smin) 
     self.slider.setMaximum(smax-self.step*self.scale) 
     self.slider.setSingleStep(self.step*self.scale/5.) 
     self.slider.setPageStep(self.step*self.scale) 
     self.slider.setValue(0) # set the initial position 
     self.slider.valueChanged.connect(self.xpos_changed) 
     parent.addWidget(self.slider) 

    def set_spinbox(self, parent): 
     self.spinb = QtGui.QDoubleSpinBox(parent=parent) 
     self.spinb.setDecimals(3) 
     self.spinb.setRange(0.001, 3600.) 
     self.spinb.setSuffix(" s") 
     self.spinb.setValue(self.step) # set the initial width 
     self.spinb.valueChanged.connect(self.xwidth_changed) 
     parent.addWidget(self.spinb) 

    def xpos_changed(self, pos): 
     #pprint("Position (in scroll units) %f\n" %pos) 
     #  self.pos = pos/self.scale 
     pos /= self.scale 
     self.set_xlim(pos, pos + self.step) 
     self.draw_idle() 

    def xwidth_changed(self, xwidth): 
     #pprint("Width (axis units) %f\n" % step) 
     if xwidth <= 0: return 
     self.step = xwidth 
     self.slider.setSingleStep(self.step*self.scale/5.) 
     self.slider.setPageStep(self.step*self.scale) 
     old_xlim = self.ax.get_xlim() 
     self.xpos_changed(old_xlim[0] * self.scale) 
#  self.set_xlim(self.pos,self.pos+self.step) 
#  self.fig.canvas.draw() 

if __name__ == "__main__": 
    q = test_plot() 
    plt.show() 

版权声明:本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。
喜欢 (0)