Reduce number of plotted points in spectrogram plot
Hello,
we are using the spectogram plot to display a 2D Matrix with about 13000x64 values and i would like to optimize the plot speed (currently about 10 fps). Because there are only 1920px pixel in width (display size), much time is wasted to try to plot pixels which physically can't be displayed.
We are also using the magnifier, zoom and pan widget to zoom into an area of interest, therefore i can't modifiy the matrix size.
I looked into the source code but i can't really find the place to change the behaivor of qwt_plot_spectrogram. My goal is to reduce the number of plotted points to the size of the displayed canvas.
Does anybody how i can make this possible?
Many thanks in advance.
Best regards,
Kevin
Re: Reduce number of plotted points in spectrogram plot
Quote:
Originally Posted by
hberg539
we are using the spectogram plot to display a 2D Matrix with about 13000x64 values and i would like to optimize the plot speed (currently about 10 fps). Because there are only 1920px pixel in width (display size), much time is wasted to try to plot pixels which physically can't be displayed.
No QwtPlotSpectrogram runs over the pixels ( in paint device resolution ! ) requesting a value for each pixel from the raster data object.
The resolution of the data only matters if it is lower than the paint device resolution. To have this optimization you need to tell the spectrogram about the resolution by implementing QwtRasterData::pixelHint(). When using QwtMatrixRasterData this implementation is available out of the box. See http://qwt.sourceforge.net/class_qwt...a1e7efe97d39d6
Having a valid QwtRasterData::pixelHint makes a lot of sense in your case as it limits the number of requests ( and color interpolations ) from 1920 x 1920 to 1920 x 64 !
But keep in mind, that 1920 x 64 still means 122880 pixels that need to be calculated and then scaled to 1920 x 1920.
I recommend to have a look at Qwt from SVN trunk, where the spectrogram has some performance improvements. In qwt_plot_spectrogram.cpp you can enable DEBUG_RENDER to get some performance debug printouts you can check with the spectrogram example. The performance of your plot should be better compared with the example as your data resolution is horizontally always less than the screen resolution. If it is worse you should have a closer look at your color map and/or raster data object.
Uwe
Re: Reduce number of plotted points in spectrogram plot
Hello Uwe,
thanks for the explanation. I enabled the render debug and it prints this:
Quote:
renderImage QSize(12290, 65) 36
I also counted the number of calls to value() and it seems that value() is called 798850 (12290x64) times on each draw. The number of calls to value doesn't change when changing the resample mode to NearestNeighbour.
Shouldn't be the number of calls to value() the same as the size of the canvas (about 900x600 when resized) when using MatrixRasterData?
I've looked into the svn repo at svn://svn.code.sf.net/p/qwt/code/trunk qwt-code but there are not much changes relating to qwt_plot_spectrogram after the 6.1.2 release. The latest change was 2014-12-26. Am i on the correct svn server?
Best regards,
Kevin
Added after 1 5 minutes:
When using NearestNeighbour (what we want), value() is called 12290x64 (Matrix size) times. If i zoom into the area, the number of calls to value() decreases.
If i comment out the pixelHint() section for NearestNeighbour, value() calls are less, but the number of calls don't reduce when zoomed in.
Is the returning QRectF of pixelHint() pixels or matrix distances?
Thanks
Re: Reduce number of plotted points in spectrogram plot
Quote:
Originally Posted by
hberg539
I also counted the number of calls to value() and it seems that value() is called 798850 (12290x64) times on each draw.
That seems to be wrong. With the debugger and a breakpoint in value() you should be able to find out where the 12290 is coming from. I would expect that you end up in QwtPlotRasterItem::draw and how paintRect gets calculated.
Quote:
Originally Posted by
hberg539
The number of calls to value doesn't change when changing the resample mode to NearestNeighbour.
Sure, this mode changes how to round from the neighboured values, but doesn't have an impact on the number of requested values.
Quote:
Shouldn't be the number of calls to value() the same as the size of the canvas (about 900x600 when resized) when using MatrixRasterData?
No it should be 900x64 in your case.
Quote:
I've looked into the svn repo at svn://svn.code.sf.net/p/qwt/code/trunk qwt-code but there are not much changes relating to qwt_plot_spectrogram after the 6.1.2 release. The latest change was 2014-12-26. Am i on the correct svn server?
The improvements can be found in the implementation of the color maps.
But 36ms with the demo is good news as you should be significantly faster because of the 64 pixels horizontally.
Uwe
Re: Reduce number of plotted points in spectrogram plot
My matrix size is 12290x64 (the 13000x64 from the first thread was rounded badly). I debugged the code and paintRect has the dimensions 774x496 (seems to be the canvas size).
renderImage QSize(x,x) equals exactly the number of calls to value().
I think there is some issue in QwtMatrixRasterData:: pixelHint():
Code:
QRectF QwtMatrixRasterData
::pixelHint( const QRectF &area
) const {
Q_UNUSED( area )
if ( d_data->resampleMode == NearestNeighbour )
{
const QwtInterval intervalX = interval( Qt::XAxis );
const QwtInterval intervalY = interval( Qt::YAxis );
if ( intervalX.isValid() && intervalY.isValid() )
{
rect
= QRectF( intervalX.
minValue(), intervalY.
minValue(),
d_data->dx, d_data->dy );
}
}
return rect;
}
Without any changes to pixelHint(), value() gets called 798850 times.
If i change d_data->dx to d_data->dx*2, value() only gets called 399425 times (exactly the half).
I can't figure out what's wrong, but increasing the dx/dy values in pixelHint() improves the performance without any visible degradation (until some point, then the resulting image gets pixelated).
It seems that it does not get iterated over the canvas pixels, but over the interval.
Another testcase:
----------------------------------------------
matrix size: 12889x64
paintRect: 774x496
x interval width: 6460.05
y interval width: 36.2334
pixelHint() returns dx=0.525678 and dy=0.566147
Now renderImage returns: QSize(12289, 65)
value() is called 798850 times.
x interval width / dx = 12290
y interval width / dy = 64
----------------------------------------------
It's really strange. I will let this sink in and will look into it after a coffee.
Kevin
Re: Reduce number of plotted points in spectrogram plot
Guess the problem is in QwtPlotRasterItem::draw:
Code:
imageSize.setWidth( qRound( imageArea.width() / pixelRect.width() ) );
What happens if you change this line to:
Code:
double w = imageArea.width() / pixelRect.width();
w = qMin( paintRect.width(), w );
imageSize.setWidth( qRound( w ) );
The same for the height, but in your case pixelRect.height() is usually below paintRect.height().
Uwe
Re: Reduce number of plotted points in spectrogram plot
I tested it, seems to work just fine!
Now QSize(774, 65) has the size of the canvas and value() only gets called 774*65 = 50310 times.
If i zoom into an area, QSize(x,x) reduces and also the calls to value().
The draw time is now reduced from 40-50ms to around 3-4ms!
Great, thanks alot for your help!