Slow plotting performance with linewidth 3.

350 views
Skip to first unread message

Till Stensitzki

unread,
Mar 4, 2014, 6:48:51 AM3/4/14
to pyqt...@googlegroups.com
Hi,

i get quite abysmal performance for a 3-plot widget, each with 2 line plots, each 400-points.
Setting the line width to 1 gives an at reasonable  performance, but still not very fast.
Am i doing something wrong or is it the Qt graphics system at fault?

thanks for the nice package,
Till

import numpy as np

import pyqtgraph as pg

from pyqtgraph.widgets.RemoteGraphicsView import RemoteGraphicsView

from PyQt4 import QtCore, QtGui

pg.GraphicsLayout

p = pg.mkPen

avgFps = 0.0

lastUpdate = pg.ptime.time()

timer = QtCore.QTimer()

class SpecWidget(RemoteGraphicsView):

    """

    Widget whic uses pyqtgraph to plot both spectra, the relative errors and


    the signal.


    """


    def __init__(self, parent=None):

        super(SpecWidget, self).__init__(parent, debug=False)

        glw = self.pg.GraphicsLayout()

        self.glw = glw

        gpen = {'color': "g", 'width': 3}

        rpen = {'color': "r", 'width': 3}

        self.spectrum = glw.addPlot()

        self.setCentralItem(glw)

        self.probe = self.spectrum.plot(pen=gpen)

        self.ref = self.spectrum.plot(pen=rpen)

        glw.nextRow()

        self.err = glw.addPlot()

        self.probe_err = self.err.plot(pen=gpen)

        self.ref_err = self.err.plot(pen=rpen)

        glw.nextRow()

        self.signal = glw.addPlot()

        self.sig = self.signal.plot(pen=gpen)

        self.sig_m = self.signal.plot(pen=rpen)

        self.lastUpdate = pg.ptime.time()

        timer.timeout.connect(self.update_data)


    def update_data(self):

        x = np.arange(400)    

        self.probe.setData(x, np.random.randn(400), _callSync='off')

        self.ref.setData(x, np.random.randn(400), _callSync='off')

        self.probe_err.setData(x, np.random.randn(400), _callSync='off')

        self.ref_err.setData(x, np.random.randn(400),  _callSync='off')

        self.sig.setData(x, np.random.randn(400), _callSync='off')

        self.sig_m.setData(x, np.random.randn(400), _callSync='off')

        global avgFps

        global lastUpdate

        now = pg.ptime.time()

        fps = 1.0 / (now - lastUpdate)

        lastUpdate = now

        avgFps = avgFps * 0.8 + fps * 0.2

        print "Generating %0.2f fps" % avgFps



Luke Campagnola

unread,
Mar 4, 2014, 2:31:48 PM3/4/14
to pyqt...@googlegroups.com
On Tue, Mar 4, 2014 at 6:48 AM, Till Stensitzki <mail...@gmx.de> wrote:
i get quite abysmal performance for a 3-plot widget, each with 2 line plots, each 400-points.
Setting the line width to 1 gives an at reasonable  performance, but still not very fast.
Am i doing something wrong or is it the Qt graphics system at fault?
 
[snip]
 
class SpecWidget(RemoteGraphicsView):

Is there a reason you are using RemoteGraphicsView? If you need extra CPU cycles in the main GUI process, this can help. Otherwise, I would avoid it because it is tricky to use correctly:
 
    def update_data(self):

        x = np.arange(400)    

        self.probe.setData(x, np.random.randn(400), _callSync='off')


The problem (or, at least the most obvious one to me) is here--self.probe is a proxy to a PlotDataItem in the remote process. When you ask for self.probe.setData, a request is sent to the remote process, and a new proxy is returned that represents the setData method. Then when you call this proxy with the new plot data, a second message is sent to the remote process that updates the plot. This process is then repeated for each of the six plots, yielding abysmal performance.

To speed this up, you can either keep a local copy of each setData method to avoid re-acquiring the proxies at every update:

    self.probe_setData = self.probe.setData
    ...
    self.probe_setData(x, y, _callSync='off')

Or, you can tell each of the plot proxies to defer their attribute lookups, which would cause the entire expression "self.plot.setData(x, y, ...)" to be condensed into a single message:

    self.probe._setProxyOptions(deferGetattr=True)
    # (and so on for the other 5 plots)


Luke

Till Stensitzki

unread,
Mar 4, 2014, 4:42:27 PM3/4/14
to pyqt...@googlegroups.com
Yeah, there is a reason: i use pyqtgraph for data acquisition, and while the data recording happens in another thread, i am not to sure if it releases the gil. So my hope is that the remote plotting does excatly what i want. Saving the proxy helped a lot, maybe i am now able to drop guiqwt (my home computer is much faster than the one in the lab.)

Till
Reply all
Reply to author
Forward
0 new messages