/* -*- c++ -*- */ /* * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ #ifndef FREQUENCY_DISPLAY_PLOT_C #define FREQUENCY_DISPLAY_PLOT_C #include <FrequencyDisplayPlot.h> #include "qtgui_types.h" #include <qwt_scale_draw.h> #include <qwt_legend.h> #include <qwt_legend_item.h> #include <QColor> #include <iostream> /*********************************************************************** * Widget to provide mouse pointer coordinate text **********************************************************************/ class FreqDisplayZoomer: public QwtPlotZoomer, public FreqOffsetAndPrecisionClass { public: FreqDisplayZoomer(QwtPlotCanvas* canvas, const unsigned int freqPrecision) : QwtPlotZoomer(canvas), FreqOffsetAndPrecisionClass(freqPrecision) { setTrackerMode(QwtPicker::AlwaysOn); } virtual void updateTrackerText() { updateDisplay(); } void SetUnitType(const std::string &type) { _unitType = type; } protected: using QwtPlotZoomer::trackerText; virtual QwtText trackerText(QPoint const &p) const { QwtDoublePoint dp = QwtPlotZoomer::invTransform(p); QwtText t(QString("%1 %2, %3 dB") .arg(dp.x(), 0, 'f', GetFrequencyPrecision()) .arg(_unitType.c_str()).arg(dp.y(), 0, 'f', 2)); return t; } private: std::string _unitType; }; /*********************************************************************** * Main frequency display plotter widget **********************************************************************/ FrequencyDisplayPlot::FrequencyDisplayPlot(int nplots, QWidget* parent) : DisplayPlot(nplots, parent) { _startFrequency = 0; _stopFrequency = 4000; _useCenterFrequencyFlag = false; _numPoints = 1024; _minFFTPoints = new double[_numPoints]; _maxFFTPoints = new double[_numPoints]; _xAxisPoints = new double[_numPoints]; setAxisTitle(QwtPlot::xBottom, "Frequency (Hz)"); setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(0)); _minYAxis = -120; _maxYAxis = 10; setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine); setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis); setAxisTitle(QwtPlot::yLeft, "Power (dB)"); QList<QColor> default_colors; default_colors << QColor(Qt::blue) << QColor(Qt::red) << QColor(Qt::green) << QColor(Qt::black) << QColor(Qt::cyan) << QColor(Qt::magenta) << QColor(Qt::yellow) << QColor(Qt::gray) << QColor(Qt::darkRed) << QColor(Qt::darkGreen) << QColor(Qt::darkBlue) << QColor(Qt::darkGray); // Automatically deleted when parent is deleted for(int i = 0; i < _nplots; i++) { _dataPoints.push_back(new double[_numPoints]); memset(_dataPoints[i], 0x0, _numPoints*sizeof(double)); _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i))); _plot_curve[i]->attach(this); #if QWT_VERSION < 0x060000 _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints); #else _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints); #endif setColor(i, default_colors[i]); } _min_fft_plot_curve = new QwtPlotCurve("Minimum Power"); _min_fft_plot_curve->attach(this); const QColor _default_min_fft_color = Qt::magenta; SetMinFFTColor(_default_min_fft_color); #if QWT_VERSION < 0x060000 _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints); #else _min_fft_plot_curve->setRawSamples(_xAxisPoints, _minFFTPoints, _numPoints); #endif _min_fft_plot_curve->setVisible(false); _max_fft_plot_curve = new QwtPlotCurve("Maximum Power"); _max_fft_plot_curve->attach(this); QColor _default_max_fft_color = Qt::darkYellow; SetMaxFFTColor(_default_max_fft_color); #if QWT_VERSION < 0x060000 _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints); #else _max_fft_plot_curve->setRawSamples(_xAxisPoints, _maxFFTPoints, _numPoints); #endif _max_fft_plot_curve->setVisible(false); _lower_intensity_marker= new QwtPlotMarker(); _lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine); QColor _default_marker_lower_intensity_color = Qt::cyan; SetMarkerLowerIntensityColor(_default_marker_lower_intensity_color); _lower_intensity_marker->attach(this); _upper_intensity_marker = new QwtPlotMarker(); _upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine); QColor _default_marker_upper_intensity_color = Qt::green; SetMarkerUpperIntensityColor(_default_marker_upper_intensity_color); _upper_intensity_marker->attach(this); memset(_xAxisPoints, 0x0, _numPoints*sizeof(double)); for(int64_t number = 0; number < _numPoints; number++){ _minFFTPoints[number] = 200.0; _maxFFTPoints[number] = -280.0; } _markerPeakAmplitude = new QwtPlotMarker(); QColor _default_marker_peak_amplitude_color = Qt::yellow; SetMarkerPeakAmplitudeColor(_default_marker_peak_amplitude_color); /// THIS CAUSES A PROBLEM! //_markerPeakAmplitude->attach(this); _markerNoiseFloorAmplitude = new QwtPlotMarker(); _markerNoiseFloorAmplitude->setLineStyle(QwtPlotMarker::HLine); QColor _default_marker_noise_floor_amplitude_color = Qt::darkRed; SetMarkerNoiseFloorAmplitudeColor(_default_marker_noise_floor_amplitude_color); _markerNoiseFloorAmplitude->attach(this); _markerCF= new QwtPlotMarker(); _markerCF->setLineStyle(QwtPlotMarker::VLine); QColor _default_marker_CF_color = Qt::lightGray; SetMarkerCFColor(_default_marker_CF_color); _markerCF->attach(this); _markerCF->hide(); _peakFrequency = 0; _peakAmplitude = -HUGE_VAL; _noiseFloorAmplitude = -HUGE_VAL; replot(); _zoomer = new FreqDisplayZoomer(canvas(), 0); #if QWT_VERSION < 0x060000 _zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); #endif _zoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); _zoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton); const QColor default_zoomer_color(Qt::darkRed); setZoomerColor(default_zoomer_color); // Do this after the zoomer has been built _resetXAxisPoints(); // Turn off min/max hold plots in legend QWidget *w; QwtLegend* legendDisplay = legend(); w = legendDisplay->find(_min_fft_plot_curve); ((QwtLegendItem*)w)->setChecked(true); w = legendDisplay->find(_max_fft_plot_curve); ((QwtLegendItem*)w)->setChecked(true); } FrequencyDisplayPlot::~FrequencyDisplayPlot() { for(int i = 0; i < _nplots; i++) delete [] _dataPoints[i]; delete[] _maxFFTPoints; delete[] _minFFTPoints; delete[] _xAxisPoints; } void FrequencyDisplayPlot::setYaxis(double min, double max) { // Get the new max/min values for the plot _minYAxis = min; _maxYAxis = max; // Set the axis max/min to the new values setAxisScale(QwtPlot::yLeft, _minYAxis, _maxYAxis); // Reset the base zoom level to the new axis scale set here _zoomer->setZoomBase(); } void FrequencyDisplayPlot::SetFrequencyRange(const double constStartFreq, const double constStopFreq, const double constCenterFreq, const bool useCenterFrequencyFlag, const double units, const std::string &strunits) { double startFreq = constStartFreq / units; double stopFreq = constStopFreq / units; double centerFreq = constCenterFreq / units; _xAxisMultiplier = units; _useCenterFrequencyFlag = useCenterFrequencyFlag; if(_useCenterFrequencyFlag){ startFreq = (startFreq + centerFreq); stopFreq = (stopFreq + centerFreq); } bool reset = false; if((startFreq != _startFrequency) || (stopFreq != _stopFrequency)) reset = true; if(stopFreq > startFreq) { _startFrequency = startFreq; _stopFrequency = stopFreq; if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (_zoomer != NULL)){ double display_units = ceil(log10(units)/2.0); setAxisScaleDraw(QwtPlot::xBottom, new FreqDisplayScaleDraw(display_units)); setAxisTitle(QwtPlot::xBottom, QString("Frequency (%1)").arg(strunits.c_str())); if(reset) _resetXAxisPoints(); ((FreqDisplayZoomer*)_zoomer)->SetFrequencyPrecision(display_units); ((FreqDisplayZoomer*)_zoomer)->SetUnitType(strunits); } } } double FrequencyDisplayPlot::GetStartFrequency() const { return _startFrequency; } double FrequencyDisplayPlot::GetStopFrequency() const { return _stopFrequency; } void FrequencyDisplayPlot::replot() { _markerNoiseFloorAmplitude->setYValue(_noiseFloorAmplitude); // Make sure to take into account the start frequency if(_useCenterFrequencyFlag){ _markerPeakAmplitude->setXValue((_peakFrequency/1000.0) + _startFrequency); } else{ _markerPeakAmplitude->setXValue(_peakFrequency + _startFrequency); } _markerPeakAmplitude->setYValue(_peakAmplitude); QwtPlot::replot(); } void FrequencyDisplayPlot::PlotNewData(const std::vector<double*> dataPoints, const int64_t numDataPoints, const double noiseFloorAmplitude, const double peakFrequency, const double peakAmplitude, const double timeInterval) { if(!_stop) { if(numDataPoints > 0) { if(numDataPoints != _numPoints) { _numPoints = numDataPoints; delete[] _minFFTPoints; delete[] _maxFFTPoints; delete[] _xAxisPoints; _xAxisPoints = new double[_numPoints]; _minFFTPoints = new double[_numPoints]; _maxFFTPoints = new double[_numPoints]; for(int i = 0; i < _nplots; i++) { delete[] _dataPoints[i]; _dataPoints[i] = new double[_numPoints]; #if QWT_VERSION < 0x060000 _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints); #else _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints); #endif } #if QWT_VERSION < 0x060000 _min_fft_plot_curve->setRawData(_xAxisPoints, _minFFTPoints, _numPoints); _max_fft_plot_curve->setRawData(_xAxisPoints, _maxFFTPoints, _numPoints); #else _min_fft_plot_curve->setRawSamples(_xAxisPoints, _minFFTPoints, _numPoints); _max_fft_plot_curve->setRawSamples(_xAxisPoints, _maxFFTPoints, _numPoints); #endif _resetXAxisPoints(); ClearMaxData(); ClearMinData(); } for(int i = 0; i < _nplots; i++) { memcpy(_dataPoints[i], dataPoints[i], numDataPoints*sizeof(double)); } for(int64_t point = 0; point < numDataPoints; point++){ if(dataPoints[0][point] < _minFFTPoints[point]) { _minFFTPoints[point] = dataPoints[0][point]; } if(dataPoints[0][point] > _maxFFTPoints[point]) { _maxFFTPoints[point] = dataPoints[0][point]; } } _noiseFloorAmplitude = noiseFloorAmplitude; _peakFrequency = peakFrequency; _peakAmplitude = peakAmplitude; SetUpperIntensityLevel(_peakAmplitude); replot(); } } } void FrequencyDisplayPlot::PlotNewData(const double* dataPoints, const int64_t numDataPoints, const double noiseFloorAmplitude, const double peakFrequency, const double peakAmplitude, const double timeInterval) { std::vector<double*> vecDataPoints; vecDataPoints.push_back((double*)dataPoints); PlotNewData(vecDataPoints, numDataPoints, noiseFloorAmplitude, peakFrequency, peakAmplitude, timeInterval); } void FrequencyDisplayPlot::ClearMaxData() { for(int64_t number = 0; number < _numPoints; number++) { _maxFFTPoints[number] = _minYAxis; } } void FrequencyDisplayPlot::ClearMinData() { for(int64_t number = 0; number < _numPoints; number++) { _minFFTPoints[number] = _maxYAxis; } } void FrequencyDisplayPlot::SetMaxFFTVisible(const bool visibleFlag) { _max_fft_visible = visibleFlag; _max_fft_plot_curve->setVisible(visibleFlag); } const bool FrequencyDisplayPlot::GetMaxFFTVisible() const { return _max_fft_visible; } void FrequencyDisplayPlot::SetMinFFTVisible(const bool visibleFlag) { _min_fft_visible = visibleFlag; _min_fft_plot_curve->setVisible(visibleFlag); } const bool FrequencyDisplayPlot::GetMinFFTVisible() const { return _min_fft_visible; } void FrequencyDisplayPlot::_resetXAxisPoints() { double fft_bin_size = (_stopFrequency-_startFrequency) / static_cast<double>(_numPoints); double freqValue = _startFrequency; for(int64_t loc = 0; loc < _numPoints; loc++) { _xAxisPoints[loc] = freqValue; freqValue += fft_bin_size; } setAxisScale(QwtPlot::xBottom, _startFrequency, _stopFrequency); // Set up zoomer base for maximum unzoom x-axis // and reset to maximum unzoom level QwtDoubleRect zbase = _zoomer->zoomBase(); zbase.setLeft(_startFrequency); zbase.setRight(_stopFrequency); _zoomer->zoom(zbase); _zoomer->setZoomBase(zbase); _zoomer->zoom(0); } void FrequencyDisplayPlot::SetLowerIntensityLevel(const double lowerIntensityLevel) { _lower_intensity_marker->setYValue(lowerIntensityLevel); } void FrequencyDisplayPlot::SetUpperIntensityLevel(const double upperIntensityLevel) { _upper_intensity_marker->setYValue(upperIntensityLevel); } void FrequencyDisplayPlot::SetTraceColour(QColor c) { _plot_curve[0]->setPen(QPen(c)); } void FrequencyDisplayPlot::SetBGColour(QColor c) { QPalette palette; palette.setColor(canvas()->backgroundRole(), c); canvas()->setPalette(palette); } void FrequencyDisplayPlot::ShowCFMarker(const bool show) { if (show) _markerCF->show(); else _markerCF->hide(); } void FrequencyDisplayPlot::OnPickerPointSelected(const QwtDoublePoint & p) { QPointF point = p; //fprintf(stderr,"OnPickerPointSelected %f %f %d\n", point.x(), point.y(), _xAxisMultiplier); point.setX(point.x() * _xAxisMultiplier); emit plotPointSelected(point); } void FrequencyDisplayPlot::OnPickerPointSelected6(const QPointF & p) { QPointF point = p; //fprintf(stderr,"OnPickerPointSelected %f %f %d\n", point.x(), point.y(), _xAxisMultiplier); point.setX(point.x() * _xAxisMultiplier); emit plotPointSelected(point); } void FrequencyDisplayPlot::SetMinFFTColor (QColor c) { _min_fft_color = c; _min_fft_plot_curve->setPen(QPen(c)); } const QColor FrequencyDisplayPlot::GetMinFFTColor() const {return _min_fft_color;} void FrequencyDisplayPlot::SetMaxFFTColor (QColor c) { _max_fft_color = c; _max_fft_plot_curve->setPen(QPen(c)); } const QColor FrequencyDisplayPlot::GetMaxFFTColor() const {return _max_fft_color;} void FrequencyDisplayPlot::SetMarkerLowerIntensityColor (QColor c) { _marker_lower_intensity_color = c; _lower_intensity_marker->setLinePen(QPen(c)); } const QColor FrequencyDisplayPlot::GetMarkerLowerIntensityColor () const {return _marker_lower_intensity_color;} void FrequencyDisplayPlot::SetMarkerLowerIntensityVisible (bool visible) { _marker_lower_intensity_visible = visible; if (visible) _lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine); else _lower_intensity_marker->setLineStyle(QwtPlotMarker::NoLine); } const bool FrequencyDisplayPlot::GetMarkerLowerIntensityVisible () const {return _marker_lower_intensity_visible;} void FrequencyDisplayPlot::SetMarkerUpperIntensityColor (QColor c) { _marker_upper_intensity_color = c; _upper_intensity_marker->setLinePen(QPen(c, 0, Qt::DotLine)); } const QColor FrequencyDisplayPlot::GetMarkerUpperIntensityColor () const {return _marker_upper_intensity_color;} void FrequencyDisplayPlot::SetMarkerUpperIntensityVisible (bool visible) { _marker_upper_intensity_visible = visible; if (visible) _upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine); else _upper_intensity_marker->setLineStyle(QwtPlotMarker::NoLine); } const bool FrequencyDisplayPlot::GetMarkerUpperIntensityVisible () const {return _marker_upper_intensity_visible;} void FrequencyDisplayPlot::SetMarkerPeakAmplitudeColor (QColor c) { _marker_peak_amplitude_color = c; _markerPeakAmplitude->setLinePen(QPen(c)); QwtSymbol symbol; symbol.setStyle(QwtSymbol::Diamond); symbol.setSize(8); symbol.setPen(QPen(c)); symbol.setBrush(QBrush(c)); #if QWT_VERSION < 0x060000 _markerPeakAmplitude->setSymbol(symbol); #else _markerPeakAmplitude->setSymbol(&symbol); #endif } const QColor FrequencyDisplayPlot::GetMarkerPeakAmplitudeColor () const {return _marker_peak_amplitude_color;} void FrequencyDisplayPlot::SetMarkerNoiseFloorAmplitudeColor (QColor c) { _marker_noise_floor_amplitude_color = c; _markerNoiseFloorAmplitude->setLinePen(QPen(c, 0, Qt::DotLine)); } const QColor FrequencyDisplayPlot::GetMarkerNoiseFloorAmplitudeColor () const {return _marker_noise_floor_amplitude_color;} void FrequencyDisplayPlot::SetMarkerNoiseFloorAmplitudeVisible (bool visible) { _marker_noise_floor_amplitude_visible = visible; if (visible) _markerNoiseFloorAmplitude->setLineStyle(QwtPlotMarker::HLine); else _markerNoiseFloorAmplitude->setLineStyle(QwtPlotMarker::NoLine); } const bool FrequencyDisplayPlot::GetMarkerNoiseFloorAmplitudeVisible () const {return _marker_noise_floor_amplitude_visible;} void FrequencyDisplayPlot::SetMarkerCFColor (QColor c) { _marker_CF_color = c; _markerCF->setLinePen(QPen(c, 0, Qt::DotLine)); } const QColor FrequencyDisplayPlot::GetMarkerCFColor () const {return _marker_CF_color;} #endif /* FREQUENCY_DISPLAY_PLOT_C */