Question

I'm using PyQwt to plot a moderate data set (666528 points) and its takes a rdiculously long time to replot zoom, ect.

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    2.115    2.115    2.116    2.116 {built-in method replot}

I was expecting something closer to 100mS rather than 2.1sec

It looks like others have been having the same issues with Qwt but the solution sugestions have all pertained to options available in Qwt6, but there are only python bindings for v5.
Thus, I'm using Qwt version 5.2.1 with Python 2.7.2.

In Qwt6 the suggestion have been to set the Paint Attributes for ClipPolygons, FilterPoints, MinimizeMemory , ImageBuffer apportiatly. From what I understand the problem is with drawing all the points which largly maps to the same pixels and the paint repaints the same pixel over and over again, rather than just painting the pixels once.

I've tried setting a few attributes I do have available on the Plot Curve as follows but with no noticable differance in speed.

def addSignals(self, signals):
    for signal in signals:
        curve = QwtPlotCurve(signal.name())
        curve.setPaintAttribute(QwtPlotCurve.PaintFiltered, False)
        curve.setPaintAttribute(QwtPlotCurve.ClipPolygons, True)
        curve.setData(signal.x(), signal.y())
        curve.setRenderHint(QwtPlotItem.RenderAntialiased)
        curve.setPen(QPen(Qt.cyan))
        curve.attach(self)
    self.replot()

The data being loaded into PlotCurve object via setData is a numpy array from the signal object. And the method shown is attached to a subclassed QwtPlot object

Am I missing an options that available in my Qwt Version or is this only practical in v6? What are my options in speeding this up?

Thanks

Was it helpful?

Solution

Well, Qwt 5 should not be much slower for your use case.

More important is what versions of Qt is used and what type of graphics system is behind: f.e Qt4/X11 is hardware accelerated.

But at least an easy to see performance issue of your code is antialiasing:

you can enable it when zooming in deep ( in this situation it is no problem because almost all polygons are clipped away ), but when displaying more than 600000 lines it is completely pointless.

The general idea behind showing a data set of many points ( > 600000 is not moderate anymore in terms of QPainter ) is to implement several data sets for different zoom levels. Here QwtPlotWeedingFitter can help ( don't use it inside replot ! ) - but then you need Qwt6.

But better ask on the Qwt support channels, I don't read here often.

OTHER TIPS

Qt 4.7 was about performance improvements, so you should consider to upgrade !

AFAIR the raster paint engine ( the one you have with QWS or Windows ) in Qt 4.6 had a serious performance issue with QPainter::drawPolyline(), where the time increases more than linear ( guess some algo O(n*n) was involved ) with the number of points - something that hits you drastically for a curve with 600000 lines.

The fastest option you have for your use case is Qt4/X11 as it is truly hardware accelerated. Note that with Qt 4.8 you have to enable the "native" graphicssystem manually ( before it was the default setting on X11 ) and that Qt5/X11 is not accelerated anymore.

When using C++ you could use Qwt 6.1, where you also have the option of an OpenGL based canvas. I also have some code that renders a pixmap via an offline QGLPixelBuffer, what is very likely to make it into Qwt 6.2.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top