PDA

View Full Version : Can't figure out how to use Spectrogram with captured data



philwinder
13th June 2008, 11:52
Hi,
Qwt Spectrogram looks great, but by default is uses double x, y, data as if the routine is supposed to perform some sort of maths on them. What I need to do is plot data from a few QList<double>'s. I have half stolen the code from the spectrogram example but I think my problem is in the value routine where it seems to crash. The data I am trying to plot is held in "QList<double> spectData[180];" Could you provide some pointers as to how to do it correctly?

Cheers.


class SpectrogramData: public QwtRasterData
{
public:
QpnwPhasedArrayPlot * parent;
// Provide pointer to QpnwPhasedArrayPlot so we can access the data
SpectrogramData( QpnwPhasedArrayPlot * theParent ):
QwtRasterData(QwtDoubleRect(-90, 0, 180, 2000)) // Left, bottom, width, height
{
parent = theParent;
}
// Left as example
virtual QwtRasterData *copy() const
{
return new SpectrogramData(0);
}
// Left as example
virtual QwtDoubleInterval range() const
{
return QwtDoubleInterval(0.0, 4096);
}
// Return data. Crashes here.
virtual double value(double x, double y) const
{
QMessageBox::information(0,"","A");
return parent->spectData[(unsigned int) x+90].at( (unsigned int) y );
}

};



QpnwPhasedArrayPlot::QpnwPhasedArrayPlot(QwtPlot * thePlot)
{
DEBUG->print(QDateTime::currentDateTime().toString("dd.MM.yy hh:mm:ss.zzz") + ": " + "Initialising Plot");

// Create spectrogram
spectrogram = new QwtPlotSpectrogram();

// Create some fake data
for( int x = 0; x < 180; x++ )
for( int y = 0; y < 2000; y++ )
spectData[x].append(y);
spectData[90].clear();
for( int x = 0; x < 2000; x++ )
spectData[90].append(x);

// Attach the data
spectrogram->setData(SpectrogramData(this));
spectrogram->attach(thePlot);
}
//

philwinder
14th June 2008, 00:50
Definitely a problem with the value routine. I can stick static values in there and it works ok. So there seems to be a problem accessing its parents data. So I think I need to know a bit more on how it asks for the data. I thought it might just be asking for data that is out of bounds of the array so I put some error checking in, but to no avail.

Then I tried to return a single value, like:
return parent->spectData[90].at(90);
But that didnt work either. So what else could be causing a crash? Is the parent pointer getting messed up in the copy routine? Or could it be something to do with my multi-dimentional-ness in the data, although it works fine when printf'ing it somewhere.

My most recent code:

class SpectrogramData: public QwtRasterData
{
public:
QpnwPhasedArrayPlot * someParent;
// Provide pointer to QpnwPhasedArrayPlot so we can access the data
SpectrogramData( QpnwPhasedArrayPlot * theParent ):
QwtRasterData(QwtDoubleRect(0.0, 0.0, 180.0, 1999.0)) // Left, bottom, width, height
{
someParent = theParent;
//QMessageBox::information(0,"","Creating Raster");
}
virtual QwtRasterData *copy() const
{
return new SpectrogramData(someParent);
}

virtual QwtDoubleInterval range() const
{
return QwtDoubleInterval(0.0, 4096.0);
}

virtual double value(double x, double y) const
{
//QMessageBox::information(0,"","Real: " + QString::number(y) + " Round: " + QString::number((unsigned int)y));
if( x < 0 || x > 180 || y < 0.0 || y > 1999.0 )
return 0.0;
else
return someParent->spectData[90].at(90);
}
};



QpnwPhasedArrayPlot::QpnwPhasedArrayPlot(QwtPlot * thePlot)
{
// Create spectrogram
spectrogram = new QwtPlotSpectrogram();
// Create some fake data
for( int x = 0; x < 180; x++ )
for( int y = 0; y < 2000; y++ )
spectData[x].append(y);
// Attach the data
spectrogram->setData(SpectrogramData(this));
spectrogram->attach(thePlot);
}

philwinder
14th June 2008, 13:00
Ok,
Ive managed to half get it working, but not very well. What I have had to do is copy the entire array into the SpectrogramData class, the use the data locally.

class SpectrogramData: public QwtRasterData
{
public:
QpnwPhasedArrayPlot * someParent;
QVector< QList<double> > someData;
// Provide pointer to QpnwPhasedArrayPlot so we can access the data
SpectrogramData( QpnwPhasedArrayPlot * theParent ):
QwtRasterData(QwtDoubleRect(0.0, 0.0, 180.0, 2000.0)) // Left, bottom, width, height
{
someParent = theParent;
someData = theParent->spectData;
//QMessageBox::information(0,"","Creating Raster");
}
virtual QwtRasterData *copy() const
{
return new SpectrogramData(someParent);
}

virtual QwtDoubleInterval range() const
{
return QwtDoubleInterval(0.0, 4096.0);
}

virtual double value(double x, double y) const
{
//QMessageBox::information(0,"","Real: " + QString::number(y) + " Round: " + QString::number((unsigned int)y));
QList<double> temp;
if( x < 0.0 || x > 180.0 || y < 0.0 || y > 2000.0 )
return 0.0;
else
{
return someData.at( (unsigned int)x ).at( (unsigned int)y );
}
//return someParent->spectData.at(1).at(1);
//return 100;
}
};

I dont know what problems I will have in updating the data, hopefully replot() should take care of it for me, but I'm not sure.
There is surely a better way of doing this, where the SpectrogramData class can access some external data?

Uwe
16th June 2008, 08:23
Havn't checked your code in detail, but I recommend to implement SpectrogramData::rasterHint() too. In your case the resolution of your data is below the screen resolution and you might reduce the number of rendered points a lot.

Uwe

philwinder
16th June 2008, 21:56
Thanks for the info Uwe, I'll remember that. I still havent arrived at a solution for the data though, I dont really want to be copying whole arrays accross to the SpectrumData class. Maybe I could access the data in the class directly?

Cheers,
Phil

philwinder
16th June 2008, 22:54
This is fast becoming a nightmare. How am I supposed to use the Raster class. Do I create a new instance of the class every time I want to update the spectrogram plot? How can I access external data? How can I access internal data?
Are there alternatives to using the Raster class, like a simple setData in the curve class?

Any hints, tips?
Sorry to be so broad, I just cant quite see any clear path.

Uwe
17th June 2008, 08:28
QwtRasterData is simply an interface for accessing your raster data. You can connect it to any "external" data structure or copy your data in an "internal" member and return the values from there.

If you change the data behind the back of the spectrogram item you have to call spectrogram->invalidatePaintCache() + plot->replot(). But you can also create a new QwtRasterData object and do spectrogram->setData() + plot->replot().

Note, that most Qt containers are implicitely shared. So copying QLists is no problem.

Uwe