PDA

View Full Version : setRenderThreadCount with Curves and SpectroCurve ??



jesse_mark
20th February 2013, 16:09
Hello,

I am trying to use QwtPoltCurve and QwtSpectroCurve for a large number of points, over 2M. But there a slow when replot the curves. Specially when Zooing or panning.

from a previous post, Uwe recommended me to use "setRenderThreadCount" with the curve and that was an added implementation for SVN trunk before qt6.1 was released.

Now i am using qt6.1 downloaded from this (http://sourceforge.net/projects/qwt/) website.

but this method is not available at least with the version i just downloaded.
any suggestion or recommendation how to improve the speed of zooming and panning (reploting) of the curves ?? with different PenSize.

Thank you so much.

Uwe
21st February 2013, 07:13
...but this method is not available at least with the version i just downloaded.
You find it in its base class, QwtPlotItem::setRenderThreadCount().

Multithreading is used by QwtPlotCurve in a special combination, where the curve is rendered to a QImage before painting ( see the scatterplot example ).Together with avoiding the overhead of QPainter this is indeed a drastic performance improvement. The same could be done in QwtPlotSpectroCurve - probably 1-2 h of work

This special mode is implemented for pens with a pen size <= 1 as this means setting an RGB value at a position in an image only. For a larger pen width some algo for rendering a circle to a QImage without using QPainter would be necessary .

Another optimization I can imagine is to introduce a cache for the translated colors. The value -> color translation doesn't need to be done again and again for every replot.

When you have a good idea for a Qwt example using QwtPlotSpectroCurve ( with synthetic data ) I would have a look at this class.

Uwe

jesse_mark
21st February 2013, 16:17
by trying both qwt versions, which svn for qwt6.0 and the new release qwt6.1, for the qwtPoltCurve there was a big performance improvement for the replot with > 2M points.
this even without using the Multithreading and with using qwtSymbols with size >1 (exactly size=3), i still see a performance improvement when using the Curve.I was able to pan and zoom much more smoothly.

but with SpectroCurve it is still the same, slow to pan and zoom.


The same could be done in QwtPlotSpectroCurve - probably 1-2 h of work
Man, this is probably for you just 1-2h, with me and my basic level its probably 1-2 weeks :p.

So, to have this performance improvement with SpectroCurve, what do i need to do ?? can you explain more for me please?
do you think, this improvement will be soon available with next updates of SVN trunk ??



When you have a good idea for a Qwt example using QwtPlotSpectroCurve ( with synthetic data ) I would have a look at this class.

Well, as a good use of SpectroCurve, in my case now, i have a lot of points and each point has a different (weight/value), I filter these points using their weight. Now, I am using just a curve with symbol for each point.

To have a different color for each point to indicate its weight, will make the filtering more efficient, and will give lot more information about the represented points.

synthetic data, I really do not have one, but i can make a file with random values for 2M points, but that may look so random.

Thanks for all your help and support.

Uwe
23rd February 2013, 12:40
by trying both qwt versions, which svn for qwt6.0 and the new release qwt6.1, for the qwtPoltCurve there was a big performance improvement for the replot with > 2M points.
this even without using the Multithreading and with using qwtSymbols with size >1 (exactly size=3), i still see a performance improvement when using the Curve.I was able to pan and zoom much more smoothly..
Multithreading is only implemented for QwtPlotCurve::Dots with a pen width <= 1 in combination with QwtPlotCurve::ImageBuffer.

When using symbols I expect 2 reasons for the performance improvement:



Qwt 6.1 tries to autodetect if it is faster to render the symbol to a QPixmap once and using this pixmap later. With Qwt 6.0 this has to be enabled explicitly by setting the QwtPlotCurve::CacheSymbols flag.
As Qwt 6.1 reintroduced using integer coordinates for paint devices with integer based coordinate systems it is possible to filter out points that are mapped to the same position ( QwtPlotCurve::FilterPoints ).




So, to have this performance improvement with SpectroCurve, what do i need to do ??

You can't have the same performance as the situation is different, all what could be done easily is:



calculating the colors in advance
rendering multithreaded to a QImage for a pen width <= 1


There might be more optimizations, when using a simple color map with a couple of colors only.

Uwe

jesse_mark
25th February 2013, 15:25
With Qwt 6.0 this has to be enabled explicitly by setting the QwtPlotCurve::CacheSymbols flag.

tried to set the PaintAttribute to CacheSymbols, but u can not find this flag, the flags i could found were only :
ClipPolygons
FilterPoints
MinimizeMemory
ImageBuffer

so how should i set this flag??



You can't have the same performance as the situation is different, all what could be done easily is:

* calculating the colors in advance

how can I calculate it ?? do i have to overloaded some function ? or set specific flag/s ??


* rendering multithreaded to a QImage for a pen width <= 1

is it the the same way with the curve ??



btw: how to find which version the library is and if it a an SVN or final release?

Thank you so much.

Uwe
25th February 2013, 19:32
tried to set the PaintAttribute to CacheSymbols, but u can not find this flag, the flags i could found were only :
ClipPolygons
FilterPoints
MinimizeMemory
ImageBuffer

These are the flags you find in Qwt 6.1, where you have QwtSymbol::setCachePolicy(). But as the default setting is to autodetect the best choice for the situation you don't need to take care of it anymore.

btw: how to find which version the library is and if it a an SVN or final release?.
Downloading from SVN trunk is always the current development branch ( at the moment 6.1 ), all other SVN branches are maintenance branches for a previous release. So f.e in the qwt-6.0 branch you find the latest 6.0 release with binary compatible bug fixes.

All packages can be found here: http://sourceforge.net/projects/qwt/files. Alle packages in qwt are final releases, all packages in qwt-beta not.

Concerning the optimizations I wrote about what could be done in theory - but QwtPlotSpectroCurve is not prepared to offer them. But it is is a very simple class ( the draw method has only 51 lines of code ) and you should be able to overload it and implement something tailored for your situation.

Check the implementation and you will agree.

Uwe

jesse_mark
26th February 2013, 17:01
These are the flags you find in Qwt 6.1

so this means i am using two different versions of qwt6.1, probably qwt6.1 old SVN version and the last release qwt6.1-rc3 , as The two have the same PaintAttribute, one simple different was the older qwt6.1 use

grid->setMajPen() while the other use grid->setMajorPen(). and they differ in performance when reploting the curve with lot of points.


Thanks, I'll have a look at the spectroCurve implementation and see if I can do your suggestions.

Added after 1 57 minutes:

Well, I was trying to overload the drawDots method,

.h


#ifndef SPECTROCURVE_H
#define SPECTROCURVE_H
#include <qwt_plot_spectrocurve.h>

class SpectroCurve : public QwtPlotSpectroCurve
{

public:
SpectroCurve(QWidget * = NULL);

protected:
virtual void drawDots( QPainter *,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
const QRectF &canvasRect, int from, int to ) const;

};

#endif // SPECTROCURVE_H


.cpp



#include "spectrocurve.h"
#include "qwt_plot_spectrocurve.h"
#include "qwt_color_map.h"
#include "qwt_scale_map.h"
#include "qwt_painter.h"
#include <qpainter.h>

SpectroCurve::SpectroCurve( QWidget *parent ):
QwtPlotSpectroCurve()
{

}

void QwtPlotSpectroCurve::drawDots( QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
const QRectF &canvasRect, int from, int to ) const
{
// if ( !d_data->colorRange.isValid() )
// return;

// const bool doAlign = QwtPainter::roundingAlignment( painter );

// const QwtColorMap::Format format = d_data->colorMap->format();
// if ( format == QwtColorMap::Indexed )
// d_data->colorTable = d_data->colorMap->colorTable( d_data->colorRange );

// const QwtSeriesData<QwtPoint3D> *series = data();

// for ( int i = from; i <= to; i++ )
// {
// const QwtPoint3D sample = series->sample( i );

// double xi = xMap.transform( sample.x() );
// double yi = yMap.transform( sample.y() );
// if ( doAlign )
// {
// xi = qRound( xi );
// yi = qRound( yi );
// }

// if ( d_data->paintAttributes & QwtPlotSpectroCurve::ClipPoints )
// {
// if ( !canvasRect.contains( xi, yi ) )
// continue;
// }

// if ( format == QwtColorMap::RGB )
// {
// const QRgb rgb = d_data->colorMap->rgb(
// d_data->colorRange, sample.z() );

// painter->setPen( QPen( QColor( rgb ), d_data->penWidth ) );
// }
// else
// {
// const unsigned char index = d_data->colorMap->colorIndex(
// d_data->colorRange, sample.z() );

// painter->setPen( QPen( QColor( d_data->colorTable[index] ),
// d_data->penWidth ) );
// }

// QwtPainter::drawPoint( painter, QPointF( xi, yi ) );
// }

// d_data->colorTable.clear();
}


I keep getting error when i try to compile it.

error: undefined reference to `VTT for SpectroCurve'
error: undefined reference to `vtable for SpectroCurve'

I wonder if i can use the same code the drawDots method has, so i can play around to understand the code, but
these errors are thrown.

error: invalid use of incomplete type 'struct QwtPlotSpectroCurve::PrivateData'
error: forward declaration of 'struct QwtPlotSpectroCurve::PrivateData'


thanks