1 #ifndef FREQUENCY_DISPLAY_PLOT_C
2 #define FREQUENCY_DISPLAY_PLOT_C
4 #include <FrequencyDisplayPlot.h>
6 #include <qwt_scale_draw.h>
8 class FreqPrecisionClass
11 FreqPrecisionClass(const int freqPrecision)
13 _frequencyPrecision = freqPrecision;
16 virtual ~FreqPrecisionClass()
20 virtual unsigned int GetFrequencyPrecision() const
22 return _frequencyPrecision;
25 virtual void SetFrequencyPrecision(const unsigned int newPrecision)
27 _frequencyPrecision = newPrecision;
30 unsigned int _frequencyPrecision;
36 class FreqDisplayScaleDraw: public QwtScaleDraw, public FreqPrecisionClass
39 FreqDisplayScaleDraw(const unsigned int precision)
40 : QwtScaleDraw(), FreqPrecisionClass(precision)
44 virtual ~FreqDisplayScaleDraw()
48 virtual QwtText label(double value) const
50 return QString("%1").arg(value, 0, 'f', GetFrequencyPrecision());
59 class FreqDisplayZoomer: public QwtPlotZoomer, public FreqPrecisionClass
62 FreqDisplayZoomer(QwtPlotCanvas* canvas, const unsigned int freqPrecision)
63 : QwtPlotZoomer(canvas),FreqPrecisionClass(freqPrecision)
65 setTrackerMode(QwtPicker::AlwaysOn);
68 virtual ~FreqDisplayZoomer(){
72 virtual void updateTrackerText(){
76 void SetUnitType(const std::string &type)
82 using QwtPlotZoomer::trackerText;
83 virtual QwtText trackerText( const QwtDoublePoint& p ) const
85 QwtText t(QString("%1 %2, %3 dB").
86 arg(p.x(), 0, 'f', GetFrequencyPrecision()).
87 arg(_unitType.c_str()).arg(p.y(), 0, 'f', 2));
92 std::string _unitType;
95 FrequencyDisplayPlot::FrequencyDisplayPlot(QWidget* parent)
99 _stopFrequency = 4000;
101 timespec_reset(&_lastReplot);
103 resize(parent->width(), parent->height());
105 _useCenterFrequencyFlag = false;
108 _dataPoints = new double[_numPoints];
109 _minFFTPoints = new double[_numPoints];
110 _maxFFTPoints = new double[_numPoints];
111 _xAxisPoints = new double[_numPoints];
113 // Disable polygon clipping
114 QwtPainter::setDeviceClipping(false);
116 // We don't need the cache here
117 canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
118 canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
121 palette.setColor(canvas()->backgroundRole(), QColor("white"));
122 canvas()->setPalette(palette);
124 setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)");
125 setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0));
129 setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
130 setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis);
131 setAxisTitle(QwtPlot::yLeft, "Power (dB)");
133 // Automatically deleted when parent is deleted
134 _fft_plot_curve = new QwtPlotCurve("Power Spectrum");
135 _fft_plot_curve->attach(this);
136 _fft_plot_curve->setPen(QPen(Qt::blue));
137 _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints);
139 _min_fft_plot_curve = new QwtPlotCurve("Minimum Power");
140 _min_fft_plot_curve->attach(this);
141 _min_fft_plot_curve->setPen(QPen(Qt::magenta));
142 _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints);
143 _min_fft_plot_curve->setVisible(false);
145 _max_fft_plot_curve = new QwtPlotCurve("Maximum Power");
146 _max_fft_plot_curve->attach(this);
147 _max_fft_plot_curve->setPen(QPen(Qt::darkYellow));
148 _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints);
149 _max_fft_plot_curve->setVisible(false);
151 _lower_intensity_marker = new QwtPlotMarker();
152 _lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
153 _lower_intensity_marker->setLinePen(QPen(Qt::cyan));
154 _lower_intensity_marker->attach(this);
156 _upper_intensity_marker = new QwtPlotMarker();
157 _upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine);
158 _upper_intensity_marker->setLinePen(QPen(Qt::green, 0, Qt::DotLine));
159 _upper_intensity_marker->attach(this);
161 memset(_dataPoints, 0x0, _numPoints*sizeof(double));
162 memset(_xAxisPoints, 0x0, _numPoints*sizeof(double));
164 for(int64_t number = 0; number < _numPoints; number++){
165 _minFFTPoints[number] = 200.0;
166 _maxFFTPoints[number] = -280.0;
169 // set up peak marker
172 _markerPeakAmplitude = new QwtPlotMarker();
173 _markerPeakAmplitude->setLinePen(QPen(Qt::yellow));
174 symbol.setStyle(QwtSymbol::Diamond);
176 symbol.setPen(QPen(Qt::yellow));
177 symbol.setBrush(QBrush(Qt::yellow));
178 _markerPeakAmplitude->setSymbol(symbol);
179 _markerPeakAmplitude->attach(this);
181 _markerNoiseFloorAmplitude = new QwtPlotMarker();
182 _markerNoiseFloorAmplitude->setLineStyle(QwtPlotMarker::HLine);
183 _markerNoiseFloorAmplitude->setLinePen(QPen(Qt::darkRed, 0, Qt::DotLine));
184 _markerNoiseFloorAmplitude->attach(this);
187 _peakAmplitude = -HUGE_VAL;
189 _noiseFloorAmplitude = -HUGE_VAL;
193 _zoomer = new FreqDisplayZoomer(canvas(), 0);
194 #if QT_VERSION < 0x040000
195 _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
196 Qt::RightButton, Qt::ControlModifier);
198 _zoomer->setMousePattern(QwtEventPattern::MouseSelect2,
199 Qt::RightButton, Qt::ControlModifier);
201 _zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
204 _panner = new QwtPlotPanner(canvas());
205 _panner->setAxisEnabled(QwtPlot::yRight, false);
206 _panner->setMouseButton(Qt::MidButton);
208 // Avoid jumping when labels with more/less digits
209 // appear/disappear when scrolling vertically
211 const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font());
212 QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft);
213 sd->setMinimumExtent( fm.width("100.00") );
215 const QColor c(Qt::darkRed);
216 _zoomer->setRubberBandPen(c);
217 _zoomer->setTrackerPen(c);
219 // Do this after the zoomer has been built
223 FrequencyDisplayPlot::~FrequencyDisplayPlot()
225 delete[] _dataPoints;
226 delete[] _maxFFTPoints;
227 delete[] _minFFTPoints;
228 delete[] _xAxisPoints;
230 // _fft_plot_curves deleted when parent deleted
231 // _zoomer and _panner deleted when parent deleted
235 FrequencyDisplayPlot::set_yaxis(double min, double max)
237 // Get the new max/min values for the plot
241 // Set the axis max/min to the new values
242 setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis);
244 // Reset the base zoom level to the new axis scale set here
245 _zoomer->setZoomBase();
249 FrequencyDisplayPlot::SetFrequencyRange(const double constStartFreq,
250 const double constStopFreq,
251 const double constCenterFreq,
252 const bool useCenterFrequencyFlag,
253 const double units, const std::string &strunits)
255 double startFreq = constStartFreq / units;
256 double stopFreq = constStopFreq / units;
257 double centerFreq = constCenterFreq / units;
259 _useCenterFrequencyFlag = useCenterFrequencyFlag;
261 if(_useCenterFrequencyFlag){
262 startFreq = (startFreq + centerFreq);
263 stopFreq = (stopFreq + centerFreq);
267 if((startFreq != _startFrequency) || (stopFreq != _stopFrequency))
270 if(stopFreq > startFreq) {
271 _startFrequency = startFreq;
272 _stopFrequency = stopFreq;
274 if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (_zoomer != NULL)){
275 double display_units = ceil(log10(units)/2.0);
276 setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(display_units));
277 setAxisTitle(QwtPlot::xBottom, QString("Frequency (%1)").arg(strunits.c_str()));
282 ((FreqDisplayZoomer*)_zoomer)->SetFrequencyPrecision(display_units);
283 ((FreqDisplayZoomer*)_zoomer)->SetUnitType(strunits);
290 FrequencyDisplayPlot::GetStartFrequency() const
292 return _startFrequency;
296 FrequencyDisplayPlot::GetStopFrequency() const
298 return _stopFrequency;
302 FrequencyDisplayPlot::replot()
304 _markerNoiseFloorAmplitude->setYValue(_noiseFloorAmplitude);
306 // Make sure to take into account the start frequency
307 if(_useCenterFrequencyFlag){
308 _markerPeakAmplitude->setXValue((_peakFrequency/1000.0) + _startFrequency);
311 _markerPeakAmplitude->setXValue(_peakFrequency + _startFrequency);
313 _markerPeakAmplitude->setYValue(_peakAmplitude);
319 FrequencyDisplayPlot::resizeSlot( QSize *s )
321 resize(s->width(), s->height());
325 FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDataPoints,
326 const double noiseFloorAmplitude, const double peakFrequency,
327 const double peakAmplitude, const double timeInterval)
329 // Only update plot if there is data and if the time interval has elapsed
330 if((numDataPoints > 0) &&
331 (diff_timespec(get_highres_clock(), _lastReplot) > timeInterval)) {
333 if(numDataPoints != _numPoints) {
334 _numPoints = numDataPoints;
336 delete[] _dataPoints;
337 delete[] _minFFTPoints;
338 delete[] _maxFFTPoints;
339 delete[] _xAxisPoints;
340 _dataPoints = new double[_numPoints];
341 _xAxisPoints = new double[_numPoints];
342 _minFFTPoints = new double[_numPoints];
343 _maxFFTPoints = new double[_numPoints];
345 _fft_plot_curve->setRawData(_xAxisPoints, _dataPoints, _numPoints);
346 _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints);
347 _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints);
354 memcpy(_dataPoints, dataPoints, numDataPoints*sizeof(double));
355 for(int64_t point = 0; point < numDataPoints; point++){
356 if(dataPoints[point] < _minFFTPoints[point]){
357 _minFFTPoints[point] = dataPoints[point];
359 if(dataPoints[point] > _maxFFTPoints[point]){
360 _maxFFTPoints[point] = dataPoints[point];
364 _noiseFloorAmplitude = noiseFloorAmplitude;
365 _peakFrequency = peakFrequency;
366 _peakAmplitude = peakAmplitude;
368 SetUpperIntensityLevel(_peakAmplitude);
372 _lastReplot = get_highres_clock();
377 FrequencyDisplayPlot::ClearMaxData()
379 for(int64_t number = 0; number < _numPoints; number++){
380 _maxFFTPoints[number] = _minYAxis;
385 FrequencyDisplayPlot::ClearMinData()
387 for(int64_t number = 0; number < _numPoints; number++){
388 _minFFTPoints[number] = _maxYAxis;
393 FrequencyDisplayPlot::SetMaxFFTVisible(const bool visibleFlag)
395 _max_fft_plot_curve->setVisible(visibleFlag);
399 FrequencyDisplayPlot::SetMinFFTVisible(const bool visibleFlag)
401 _min_fft_plot_curve->setVisible(visibleFlag);
405 FrequencyDisplayPlot::_resetXAxisPoints()
407 double fft_bin_size = (_stopFrequency-_startFrequency) / static_cast<double>(_numPoints);
408 double freqValue = _startFrequency;
409 for(int64_t loc = 0; loc < _numPoints; loc++){
410 _xAxisPoints[loc] = freqValue;
411 freqValue += fft_bin_size;
414 setAxisScale(QwtPlot::xBottom, _startFrequency, _stopFrequency);
416 // Set up zoomer base for maximum unzoom x-axis
417 // and reset to maximum unzoom level
418 QwtDoubleRect zbase = _zoomer->zoomBase();
419 zbase.setLeft(_startFrequency);
420 zbase.setRight(_stopFrequency);
421 _zoomer->zoom(zbase);
422 _zoomer->setZoomBase(zbase);
427 FrequencyDisplayPlot::SetLowerIntensityLevel(const double lowerIntensityLevel)
429 _lower_intensity_marker->setYValue( lowerIntensityLevel );
433 FrequencyDisplayPlot::SetUpperIntensityLevel(const double upperIntensityLevel)
435 _upper_intensity_marker->setYValue( upperIntensityLevel );
439 #endif /* FREQUENCY_DISPLAY_PLOT_C */