Qwt spectrogram value() method vs setValueMatrix
Im trying to implement a waterfall plot using qwt spectrogram, i can already plot instantaneous data on the spectrogram using QwtMatrixRasterData::setValueMatrix and am wondering if i should be implementing the value() method instead. Why would someone use value method over setvaluematrix? I have seen it done both ways.
Re: Qwt spectrogram value() method vs setValueMatrix
Quote:
Originally Posted by
earless
Why would someone use value method over setvaluematrix?
All spectrograms use QwtRasterData::value() method only !
QwtMatrixRasterData is convenience for use cases, where you have a value matrix ( pixelHint and resampling can be implemented from the matrix ). But often the data is no matrix ( f.e. something irregular ), or you don't want to waste memory for creating a copy, or your data is huge and you need to use the initRaster/discardRaster scope to load values from somewhere according to the current plot scales.
In general you can say that using QwtMatrixRasterData might be easier to use - when your data is a matrix - but deriving from QwtRasterData allows more flexibility and individual optimizations.
Note that I recently did a couple of performance optimizations for spectrograms in trunk. Depending on the refresh rate you need, those might be of interest for your. For testing you could enable DEBUG_RENDER in qwt_plot_spectrogram.cpp to see what performance you can expect for the image composition on your box.
Uwe
PS: a waterfall plot example is on my TODO list since quite some time. The special thing about this is, that the spectrogram could simply shift the image of the previous content down calculating the new values of the top rows only. Performance can be improved significantly this way.
Re: Qwt spectrogram value() method vs setValueMatrix
Thanks for the reply Uwe. I got the waterfall working using the value method. What im doing is add my data to a buffer and shift out the old data with the new samples, this gets the waterfall scrolling nicely. The only problem is it slows down my system quite a bit, the gui becomes less responsive. I think its because the entire waterfall is being redrawn from scratch every time the value method is called. Is there a way i can shift the current waterfall by one pixel and only draw the last line? The buffer is about lengthXheightXsizeof(double)=1024x200x8=1.6MB big. Is this too much data?
This is my QwtRasterData::value() method implementation.
Code:
double WaterfallData::value(double x, double y) const
{
double returnValue = -90.0;
double height = interval(Qt::YAxis).maxValue();
double left = interval(Qt::XAxis).minValue();
double right = interval(Qt::XAxis).maxValue();
double ylen = static_cast<double>(_historyLength-1);
double xlen = static_cast<double>(_dataPoints-1);
const unsigned int intY = static_cast<unsigned int>((1.0 - y/height) * ylen);
const unsigned int intX = static_cast<unsigned int>((((x - left) / (right-left)) * xlen) + 0.5);
const int location = (intY * _dataPoints) + intX;
//ensure location is valid
if((location > -1) && (location < WATERFALL_AREA)){
returnValue = _waterfallDataBuffer[location];
}
return returnValue;
}
Re: Qwt spectrogram value() method vs setValueMatrix
Quote:
The buffer is about lengthXheightXsizeof(double)=1024x200x8=1.6MB big. Is this too much data?
For the image composition the size/resolution of the target paint device ( in your case the size of the plot canvas ) is a maximum. Guess in your case the resolution of your data is way below that and you should implement the QwtRasterData::pixelHint() method.
Considering a canvas of 1200x1200 pixels the loop ( calling value() in each iteration ) would be reduced from 1444000 to 204800 for your data. How much effect you will have of course depends on the geometry of your canvas, but in this example only 15% of the loop would be left ( In case of using QwtMatrixRasterData the pixelHint method is provided automatically ).
Quote:
Is there a way i can shift the current waterfall by one pixel and only draw the last line?
Sure by overloading renderImage(). But I don't have the details before having tried this myself - that's why I will implement such an example some day.
Uwe