pyqt

时间:2016-09-30 11:41:13

标签: optimization plot grid pyqt 2d

我有一个使用PyQt4实现的gui程序。该程序控制一个光束分析器,它返回四个7500个元素向量。前两个是位置矢量(X和Y),后两个是X和Y的强度矢量。我想要做的是在图中创建一个网格(XY)并将强度绘制为颜色,如下图所示。 Figure 1 - Side Gaussian function are my raw data and I want to plot like this

我已经设法如何做到这一点,但我遇到了优化问题。

def emitGraph(self):
    zz = zeros([len(self.slit_data_pos[self.slit][::100]), len(self.slit_data_pos[self.slit + 1][::100])])
    for i in xrange(len(self.slit_data_pos[self.slit][::100])):
        for j in xrange(len(self.slit_data_pos[self.slit + 1][::100])):
            zz[i,j] = self.mesh(i, j, self.slit_data_int[self.slit][::100], self.slit_data_int[self.slit + 1][::100])

    self.graph.emit(
        self.slit_data_pos[self.slit][::100],
        self.slit_data_int[self.slit][::100],
        self.slit_data_pos[self.slit + 1][::100],
        self.slit_data_int[self.slit + 1][::100],
        zz
        )
   self.timerGraph = threading.Timer(0.2, self.emitGraph).start()

def mesh(self, i, j, intx, inty):
    norm_max = max(max(intx), max(inty))
    intx = [x/norm_max for x in intx]
    inty = [y/norm_max for y in inty]
    return intx[i]*inty[j]

正如您在下面的代码中看到的,我有两个循环来填充zz矩阵(最初为7500x7500)。我现在每个矢量只使用75个点,并使用计时器每0.2秒显示一次。我必须这样做,因为如果我使用所有数据,填充zz矩阵然后绘制将需要很长时间。

我绘制代码的部分是(在另一个对象/线程中):

def graph_update(self, slit_samples_positionsX, slit_samples_intensitiesX, slit_samples_positionsY, slit_samples_intensitiesY, zz):

    # self.matplotlibWidget.axis.plot(slit_samples_positionsX, slit_samples_intensitiesX)
    # self.matplotlibWidget.axis.plot(slit_samples_positionsY, slit_samples_intensitiesY)
    self.matplotlibWidget.axis.imshow(zz, cmap=cm.jet)
    self.matplotlibWidget.canvas.draw()

我的问题是如何改善数据计算以提高图表的分辨率和显示速率?还是有更快的方法来创建这种情节吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

每0.2秒创建一个整个网格。您还可以每0.2秒创建一个新绘图。这会降低您的应用程序速度。 每次调用struct RatioCompare { bool operator()(const Item &i1, const Item &i2) const { double i1value= i1.getRatio(); double i2value= i2.getRatio(); return i1value < i2value; } }; 时,创建一个新的计时器也可能是一个问题。

为了改进你的程序,我们的想法是创建一次网格,只更新里面的数据。 此外,只创建一次绘图,使用新数据更新它。 原则上,numpy在阵列操作中非常快,并且在屏幕上绘制数据应该不是问题。看看你的代码,一个问题可能是你实际上使用列表而不是numpy数组工作了很多。因此,尽量避免列表创建和for循环。实际上,我认为你可以完全摆脱priority_queue<Item, vector<Item>, RatioCompare > pq; for(int i=0; i<n; i++) { pq.push(tosteal[i]); } while(!pq.empty()) { Item consider= pq.top(); cout<< "Name: "<< consider.getName()<< "Ratio "<< consider.getRatio()<<endl; pq.pop(); } 功能,从而节省大量时间。

关于情节,请不要在每次更新时致电emitGraph!如果例如mesh是您的imshow-plot,那么只需通过调用imshow()

更新此图表

如果您可以提供有关您正在使用的阵列形状的更多信息,并告诉我们self.image是什么,我可能会帮助您更多。

此时您可能还想看看下面的代码,它试图模仿光束分析器并且运行速度非常快。

self.image.set_data(zz)

修改(回答以下评论,询问如何计算self.slit):

如果我理解正确,from PyQt4 import QtGui, QtCore import numpy as np from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar from matplotlib.figure import Figure import sys, time, random class WorkerObject(QtCore.QObject): signalStatus = QtCore.pyqtSignal(object) def __init__(self, parent=None): super(self.__class__, self).__init__(parent) self.data = np.zeros((600,800)) self.x = np.arange(0,800) self.y = np.arange(0,600) self.Y, self.X = np.meshgrid(self.x, self.y) self.f = lambda x, y, x0, y0, sigmax, sigmay : 0.96*np.exp(-((x-x0)/float(sigmax))**2)*np.exp(-((y-y0)/float(sigmay))**2) @QtCore.pyqtSlot() def startWork(self): print "StartWork" x0 = random.randint(250,550) y0 = random.randint(250,350) sigmax = random.randint(100,200) sigmay = random.randint(100,200) while 1 > 0: x0, y0, sigmax, sigmay = self.doWork(x0, y0, sigmax, sigmay) def doWork(self, x0, y0, sigmax, sigmay): dx, dy, dsx, dsy = random.randint(0,1)*2-1, random.randint(0,1)*2-1, random.randint(0,1)*2-1, random.randint(0,1)*2-1 self.data[:,:] = (self.f(self.X, self.Y, x0+dx, y0+dy, sigmax+dsx, sigmay+dsy)+np.random.random((600,800))*0.04)*(1.+np.random.rand()*0.04-0.02) self.signalStatus.emit(self.data) time.sleep(0.04) return x0+dx, y0+dy, sigmax+dsx, sigmay+dsy class App(QtGui.QMainWindow): signalStatus = QtCore.pyqtSignal(object) abortSignal = QtCore.pyqtSignal() def __init__(self, parent=None): super(App, self).__init__(parent) self.button_start = QtGui.QPushButton('Start',self) self.button_cancel = QtGui.QPushButton('Cancel', self) self.label_status = QtGui.QLabel('', self) self.mainbox = QtGui.QWidget(self) self.layout = QtGui.QVBoxLayout() self.mainbox.setLayout(self.layout) self.setCentralWidget(self.mainbox) self.layout.addWidget(self.button_start) self.layout.addWidget(self.button_cancel) self.layout.addWidget(self.label_status) self.fig = Figure((6.0, 3.0), dpi=72) self.canvas = FigureCanvas(self.fig) self.canvas.setParent(self) self.canvastoolbar = NavigationToolbar(self.canvas, self) self.fig.patch.set_alpha(0.0) self.ax = self.fig.add_subplot(111) self.x = np.arange( 0,800 ); self.y = np.arange( 0,600 ) self.im = self.ax.imshow(np.zeros((600, 800)), origin='upper', vmin=0, vmax=1 ) self.pv, = self.ax.plot( np.zeros(600) ,self.y , color="white" , alpha=0.6, lw=2 ) self.ph, = self.ax.plot( self.x ,np.zeros(800) , color="white" , alpha=0.6, lw=2) self.ax.set_xlim([0,800]); self.ax.set_ylim([0,600]) self.layout.addWidget(self.canvas) self.layout.addWidget(self.canvastoolbar) self.initWorker() def initWorker(self): self.worker = WorkerObject() self.worker_thread = QtCore.QThread() self._connectSignals() self.worker.moveToThread(self.worker_thread) self.worker_thread.start() def _connectSignals(self): self.button_start.clicked.connect(self.worker.startWork) self.button_cancel.clicked.connect(self.forceWorkerQuit) self.worker.signalStatus.connect(self.updateStatus) def forceWorkerQuit(self): print "calculation aborted" if self.worker_thread.isRunning(): self.worker_thread.terminate() self.worker_thread.start() @QtCore.pyqtSlot(object) def updateStatus(self, obj): self.im.set_data(obj) argm = np.unravel_index(np.argmax(obj), (600,800)) self.pv.set_data(obj[:,argm[0]]*250, self.y) self.ph.set_data(self.x, obj[argm[1], :]*250) self.fig.canvas.draw() if __name__=='__main__': app = QtGui.QApplication(sys.argv) thisapp = App() thisapp.show() sys.exit(app.exec_()) 是X方向的累积强度,zz是Y方向的强度。如果slit_data_int[0]那么在numpy中使用矩阵乘法(np.outer)可以更好地计算:

slit_data_int[1]