#include #include #include #include #include #include #include #include #include #include #include #include "plot.h" class MyZoomer: public QwtPlotZoomer { public: MyZoomer( QWidget *canvas ): QwtPlotZoomer( canvas ) { setTrackerMode( AlwaysOn ); } virtual QwtText trackerTextF( const QPointF &pos ) const { QColor bg( Qt::white ); bg.setAlpha( 200 ); QwtText text = QwtPlotZoomer::trackerTextF( pos ); text.setBackgroundBrush( QBrush( bg ) ); return text; } }; class SpectrogramData: public QwtRasterData { public: SpectrogramData() { setInterval( Qt::XAxis, QwtInterval( -1.5, 1.5 ) ); setInterval( Qt::YAxis, QwtInterval( -1.5, 1.5 ) ); setInterval( Qt::ZAxis, QwtInterval( 0.0, 10.0 ) ); } virtual double value( double x, double y ) const { const double c = 0.842; //const double c = 0.33; const double v1 = x * x + ( y - c ) * ( y + c ); const double v2 = x * ( y + c ) + x * ( y + c ); return 1.0 / ( v1 * v1 + v2 * v2 ); } }; class LinearColorMapRGB: public QwtLinearColorMap { public: LinearColorMapRGB(): QwtLinearColorMap( Qt::darkCyan, Qt::red, QwtColorMap::RGB ) { addColorStop( 0.1, Qt::cyan ); addColorStop( 0.6, Qt::green ); addColorStop( 0.95, Qt::yellow ); } }; class LinearColorMapIndexed: public QwtLinearColorMap { public: LinearColorMapIndexed(): QwtLinearColorMap( Qt::darkCyan, Qt::red, QwtColorMap::Indexed ) { addColorStop( 0.1, Qt::cyan ); addColorStop( 0.6, Qt::green ); addColorStop( 0.95, Qt::yellow ); } }; class HueColorMap: public QwtColorMap { public: // class backported from Qwt 6.2 HueColorMap(): d_hue1(0), d_hue2(359), d_saturation(150), d_value(200) { updateTable(); } virtual QRgb rgb( const QwtInterval &interval, double value ) const { if ( qIsNaN(value) ) return 0u; const double width = interval.width(); if ( width <= 0 ) return 0u; if ( value <= interval.minValue() ) return d_rgbMin; if ( value >= interval.maxValue() ) return d_rgbMax; const double ratio = ( value - interval.minValue() ) / width; int hue = d_hue1 + qRound( ratio * ( d_hue2 - d_hue1 ) ); if ( hue >= 360 ) { hue -= 360; if ( hue >= 360 ) hue = hue % 360; } return d_rgbTable[hue]; } virtual unsigned char colorIndex( const QwtInterval &, double ) const { // we don't support indexed colors return 0; } private: void updateTable() { for ( int i = 0; i < 360; i++ ) d_rgbTable[i] = QColor::fromHsv( i, d_saturation, d_value ).rgb(); d_rgbMin = d_rgbTable[ d_hue1 % 360 ]; d_rgbMax = d_rgbTable[ d_hue2 % 360 ]; } int d_hue1, d_hue2, d_saturation, d_value; QRgb d_rgbMin, d_rgbMax, d_rgbTable[360]; }; class AlphaColorMap: public QwtAlphaColorMap { public: AlphaColorMap() { //setColor( QColor("DarkSalmon") ); setColor( QColor("SteelBlue") ); } }; Plot::Plot( QWidget *parent ): QwtPlot( parent ), d_alpha(255) { d_spectrogram = new QwtPlotSpectrogram(); d_spectrogram->setRenderThreadCount( 0 ); // use system specific thread count d_spectrogram->setCachePolicy( QwtPlotRasterItem::PaintCache ); QList contourLevels; for ( double level = 0.5; level < 10.0; level += 1.0 ) contourLevels += level; d_spectrogram->setContourLevels( contourLevels ); d_spectrogram->setData( new SpectrogramData() ); d_spectrogram->attach( this ); const QwtInterval zInterval = d_spectrogram->data()->interval( Qt::ZAxis ); // A color bar on the right axis QwtScaleWidget *rightAxis = axisWidget( QwtPlot::yRight ); rightAxis->setTitle( "Intensity" ); rightAxis->setColorBarEnabled( true ); setAxisScale( QwtPlot::yRight, zInterval.minValue(), zInterval.maxValue() ); enableAxis( QwtPlot::yRight ); plotLayout()->setAlignCanvasToScales( true ); setColorMap( Plot::RGBMap ); // LeftButton for the zooming // MidButton for the panning // RightButton: zoom out by 1 // Ctrl+RighButton: zoom out to full size QwtPlotZoomer* zoomer = new MyZoomer( canvas() ); zoomer->setMousePattern( QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier ); zoomer->setMousePattern( QwtEventPattern::MouseSelect3, Qt::RightButton ); QwtPlotPanner *panner = new QwtPlotPanner( canvas() ); panner->setAxisEnabled( QwtPlot::yRight, false ); panner->setMouseButton( Qt::MidButton ); // Avoid jumping when labels with more/less digits // appear/disappear when scrolling vertically const QFontMetrics fm( axisWidget( QwtPlot::yLeft )->font() ); QwtScaleDraw *sd = axisScaleDraw( QwtPlot::yLeft ); sd->setMinimumExtent( fm.width( "100.00" ) ); const QColor c( Qt::darkBlue ); zoomer->setRubberBandPen( c ); zoomer->setTrackerPen( c ); } void Plot::showContour( bool on ) { d_spectrogram->setDisplayMode( QwtPlotSpectrogram::ContourMode, on ); replot(); } void Plot::showSpectrogram( bool on ) { d_spectrogram->setDisplayMode( QwtPlotSpectrogram::ImageMode, on ); d_spectrogram->setDefaultContourPen( on ? QPen( Qt::black, 0 ) : QPen( Qt::NoPen ) ); replot(); } void Plot::setColorMap( int type ) { QwtScaleWidget *axis = axisWidget( QwtPlot::yRight ); const QwtInterval zInterval = d_spectrogram->data()->interval( Qt::ZAxis ); d_mapType = type; int alpha = d_alpha; switch( type ) { case Plot::HueMap: { d_spectrogram->setColorMap( new HueColorMap() ); axis->setColorMap( zInterval, new HueColorMap() ); break; } case Plot::AlphaMap: { alpha = 255; d_spectrogram->setColorMap( new AlphaColorMap() ); axis->setColorMap( zInterval, new AlphaColorMap() ); break; } case Plot::IndexMap: { d_spectrogram->setColorMap( new LinearColorMapIndexed() ); axis->setColorMap( zInterval, new LinearColorMapIndexed() ); break; } case Plot::RGBMap: default: { d_spectrogram->setColorMap( new LinearColorMapRGB() ); axis->setColorMap( zInterval, new LinearColorMapRGB() ); } } d_spectrogram->setAlpha( alpha ); replot(); } void Plot::setAlpha( int alpha ) { // setting an alpha value doesn't make sense in combination // with a color map interpolating the alpha value d_alpha = alpha; if ( d_mapType != Plot::AlphaMap ) { d_spectrogram->setAlpha( alpha ); replot(); } } #ifndef QT_NO_PRINTER void Plot::printPlot() { QPrinter printer( QPrinter::HighResolution ); printer.setOrientation( QPrinter::Landscape ); printer.setOutputFileName( "spectrogram.pdf" ); QPrintDialog dialog( &printer ); if ( dialog.exec() ) { QwtPlotRenderer renderer; if ( printer.colorMode() == QPrinter::GrayScale ) { renderer.setDiscardFlag( QwtPlotRenderer::DiscardBackground ); renderer.setDiscardFlag( QwtPlotRenderer::DiscardCanvasBackground ); renderer.setDiscardFlag( QwtPlotRenderer::DiscardCanvasFrame ); renderer.setLayoutFlag( QwtPlotRenderer::FrameWithScales ); } renderer.renderTo( this, printer ); } } #endif