diff options
author | Martin Braun <martin.braun@ettus.com> | 2014-08-03 16:23:02 +0200 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2014-08-26 12:49:26 +0200 |
commit | 5b992d4ccc9ae9c3c2b3c7b82540f48f1d50627c (patch) | |
tree | 5bb5ef12c17df91604862b30ef5687160cab8418 /gr-qtgui/lib/VectorDisplayPlot.cc | |
parent | df693a90525ec4a49435ed4e3fb5cfec7643b61a (diff) |
qtgui: Added a 'vector sink'.
This is a sink similar to the freq sink, which takes vectors as input
and plots them as-is.
Diffstat (limited to 'gr-qtgui/lib/VectorDisplayPlot.cc')
-rw-r--r-- | gr-qtgui/lib/VectorDisplayPlot.cc | 629 |
1 files changed, 629 insertions, 0 deletions
diff --git a/gr-qtgui/lib/VectorDisplayPlot.cc b/gr-qtgui/lib/VectorDisplayPlot.cc new file mode 100644 index 0000000000..2babfea1cc --- /dev/null +++ b/gr-qtgui/lib/VectorDisplayPlot.cc @@ -0,0 +1,629 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014 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 VECTOR_DISPLAY_PLOT +#define VECTOR_DISPLAY_PLOT + +#include <gnuradio/qtgui/VectorDisplayPlot.h> + +#include <gnuradio/qtgui/qtgui_types.h> +#include <qwt_scale_draw.h> +#include <qwt_legend.h> +#include <QColor> +#include <iostream> + +#if QWT_VERSION < 0x060100 +#include <qwt_legend_item.h> +#else /* QWT_VERSION < 0x060100 */ +#include <qwt_legend_data.h> +#include <qwt_legend_label.h> +#endif /* QWT_VERSION < 0x060100 */ + +/*********************************************************************** + * Widget to provide mouse pointer coordinate text + **********************************************************************/ +class VectorDisplayZoomer: public QwtPlotZoomer +{ +public: +#if QWT_VERSION < 0x060100 + VectorDisplayZoomer(QwtPlotCanvas* canvas) +#else /* QWT_VERSION < 0x060100 */ + VectorDisplayZoomer(QWidget* canvas) +#endif /* QWT_VERSION < 0x060100 */ + : QwtPlotZoomer(canvas), + d_x_units(" "), + d_y_units(" ") + { + setTrackerMode(QwtPicker::AlwaysOn); + } + + virtual void updateTrackerText() + { + updateDisplay(); + } + + void setXUnits(const QString &units) + { + d_x_units = units; + } + + void setYUnits(const QString &units) + { + d_y_units = units; + } + +protected: + using QwtPlotZoomer::trackerText; + virtual QwtText trackerText(QPoint const &p) const + { + QwtDoublePoint dp = QwtPlotZoomer::invTransform(p); + QwtText t(QString("%1 %2, %3 %4") + .arg(dp.x(), 0, 'f', 2) + .arg(d_x_units) + .arg(dp.y(), 0, 'f', 2) + .arg(d_y_units) + ); + return t; + } + +private: + QString d_x_units; //!< Units on x-Axis (e.g. Hz) + QString d_y_units; //!< Units on y-Axis (e.g. V) +}; + + +/*********************************************************************** + * Main frequency display plotter widget + **********************************************************************/ +VectorDisplayPlot::VectorDisplayPlot(int nplots, QWidget* parent) + : DisplayPlot(nplots, parent), + d_x_axis_label("x"), + d_y_axis_label("y") +{ + d_numPoints = 1024; + d_x_axis_start = 0; + d_x_axis_step = 1.0; + d_ymin = -10; + d_ymax = 10; + + d_min_vec_data = new double[d_numPoints]; + d_max_vec_data = new double[d_numPoints]; + d_xdata = new double[d_numPoints]; + + setAxisTitle(QwtPlot::xBottom, d_x_axis_label); + setAxisScale(QwtPlot::xBottom, d_x_axis_start, d_numPoints-1); + + setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine); + setAxisScale(QwtPlot::yLeft, d_ymin, d_ymax); + setAxisTitle(QwtPlot::yLeft, d_y_axis_label); + + 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); + + // Create a curve for each input + // Automatically deleted when parent is deleted + for(int i = 0; i < d_nplots; i++) { + d_ydata.push_back(new double[d_numPoints]); + memset(d_ydata[i], 0x0, d_numPoints*sizeof(double)); + + d_plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i))); + d_plot_curve[i]->attach(this); + + QwtSymbol *symbol = new QwtSymbol(QwtSymbol::NoSymbol, QBrush(default_colors[i]), + QPen(default_colors[i]), QSize(7,7)); + +#if QWT_VERSION < 0x060000 + d_plot_curve[i]->setRawData(d_xdata, d_ydata[i], d_numPoints); + d_plot_curve[i]->setSymbol(*symbol); +#else + d_plot_curve[i]->setRawSamples(d_xdata, d_ydata[i], d_numPoints); + d_plot_curve[i]->setSymbol(symbol); +#endif + setLineColor(i, default_colors[i]); + } + + // Create min/max plotter curves + d_min_vec_plot_curve = new QwtPlotCurve("Min Hold"); + d_min_vec_plot_curve->attach(this); + const QColor default_min_fft_color = Qt::magenta; + setMinVecColor(default_min_fft_color); +#if QWT_VERSION < 0x060000 + d_min_vec_plot_curve->setRawData(d_xdata, d_min_vec_data, d_numPoints); +#else + d_min_vec_plot_curve->setRawSamples(d_xdata, d_min_vec_data, d_numPoints); +#endif + d_min_vec_plot_curve->setVisible(false); + d_min_vec_plot_curve->setZ(0); + + d_max_vec_plot_curve = new QwtPlotCurve("Max Hold"); + d_max_vec_plot_curve->attach(this); + QColor default_max_fft_color = Qt::darkYellow; + setMaxVecColor(default_max_fft_color); +#if QWT_VERSION < 0x060000 + d_max_vec_plot_curve->setRawData(d_xdata, d_max_vec_data, d_numPoints); +#else + d_max_vec_plot_curve->setRawSamples(d_xdata, d_max_vec_data, d_numPoints); +#endif + d_max_vec_plot_curve->setVisible(false); + d_max_vec_plot_curve->setZ(0); + + d_lower_intensity_marker= new QwtPlotMarker(); + d_lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine); + QColor default_marker_lower_intensity_color = Qt::cyan; + setMarkerLowerIntensityColor(default_marker_lower_intensity_color); + d_lower_intensity_marker->attach(this); + + d_upper_intensity_marker = new QwtPlotMarker(); + d_upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine); + QColor default_marker_upper_intensity_color = Qt::green; + setMarkerUpperIntensityColor(default_marker_upper_intensity_color); + d_upper_intensity_marker->attach(this); + + memset(d_xdata, 0x0, d_numPoints*sizeof(double)); + + for(int64_t number = 0; number < d_numPoints; number++){ + d_min_vec_data[number] = 1e6; + d_max_vec_data[number] = -1e6; + } + + d_marker_ref_level = new QwtPlotMarker(); + d_marker_ref_level->setLineStyle(QwtPlotMarker::HLine); + QColor d_default_marker_ref_level_color = Qt::darkRed; + setMarkerRefLevelAmplitudeColor(d_default_marker_ref_level_color); + d_marker_ref_level->attach(this); + + d_ref_level = -HUGE_VAL; + + d_zoomer = new VectorDisplayZoomer(canvas()); + +#if QWT_VERSION < 0x060000 + d_zoomer->setSelectionFlags(QwtPicker::RectSelection | QwtPicker::DragSelection); +#endif + + d_zoomer->setMousePattern(QwtEventPattern::MouseSelect2, + Qt::RightButton, Qt::ControlModifier); + d_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 +#if QWT_VERSION < 0x060100 + QWidget *w; + QwtLegend* legendDisplay = legend(); + w = legendDisplay->find(d_min_vec_plot_curve); + ((QwtLegendItem*)w)->setChecked(true); + w = legendDisplay->find(d_max_vec_plot_curve); + ((QwtLegendItem*)w)->setChecked(true); +#else /* QWT_VERSION < 0x060100 */ + QWidget *w; + w = ((QwtLegend*)legend())->legendWidget(itemToInfo(d_min_vec_plot_curve)); + ((QwtLegendLabel*)w)->setChecked(true); + w = ((QwtLegend*)legend())->legendWidget(itemToInfo(d_max_vec_plot_curve)); + ((QwtLegendLabel*)w)->setChecked(true); +#endif /* QWT_VERSION < 0x060100 */ + + replot(); +} + +VectorDisplayPlot::~VectorDisplayPlot() +{ + for(int i = 0; i < d_nplots; i++) + delete [] d_ydata[i]; + delete[] d_max_vec_data; + delete[] d_min_vec_data; + delete[] d_xdata; +} + +void +VectorDisplayPlot::setYaxis(double min, double max) +{ + // Get the new max/min values for the plot + d_ymin = min; + d_ymax = max; + + // Set the axis max/min to the new values + setAxisScale(QwtPlot::yLeft, d_ymin, d_ymax); + + // Reset the base zoom level to the new axis scale set here. + // But don't do it if we set the axis due to auto scaling. + if(!d_autoscale_state) + d_zoomer->setZoomBase(); +} + +double +VectorDisplayPlot::getYMin() const +{ + return d_ymin; +} + +double +VectorDisplayPlot::getYMax() const +{ + return d_ymax; +} + +void VectorDisplayPlot::setXAxisLabel(const QString &label) +{ + d_x_axis_label = label; + setAxisTitle(QwtPlot::xBottom, label); +} + +void VectorDisplayPlot::setYAxisLabel(const QString &label) +{ + d_y_axis_label = label; + setAxisTitle(QwtPlot::yLeft, label); +} + +void VectorDisplayPlot::setXAxisUnit(const QString &unit) +{ + ((VectorDisplayZoomer*)d_zoomer)->setXUnits(unit); +} + +void VectorDisplayPlot::setYAxisUnit(const QString &unit) +{ + ((VectorDisplayZoomer*)d_zoomer)->setYUnits(unit); +} + +void +VectorDisplayPlot::setXAxisValues( + const double start, + const double step +) { + bool reset = false; + if((start != d_x_axis_start) || (step != d_x_axis_step)) + reset = true; + + d_x_axis_start = start; + d_x_axis_step = step; + + if((axisScaleDraw(QwtPlot::xBottom) != NULL) && (d_zoomer != NULL)) { + setAxisTitle(QwtPlot::xBottom, d_x_axis_label); + if(reset) { + _resetXAxisPoints(); + clearMaxData(); + clearMinData(); + } + } +} + +void +VectorDisplayPlot::replot() +{ + d_marker_ref_level->setYValue(d_ref_level); + QwtPlot::replot(); +} + +void +VectorDisplayPlot::plotNewData( + const std::vector<double*> dataPoints, + const int64_t numDataPoints, + const double refLevel, + const double timeInterval +) { + if(!d_stop) { + if(numDataPoints > 0) { + if(numDataPoints != d_numPoints) { + d_numPoints = numDataPoints; + + delete[] d_min_vec_data; + delete[] d_max_vec_data; + delete[] d_xdata; + d_xdata = new double[d_numPoints]; + d_min_vec_data = new double[d_numPoints]; + d_max_vec_data = new double[d_numPoints]; + + for(int i = 0; i < d_nplots; i++) { + delete[] d_ydata[i]; + d_ydata[i] = new double[d_numPoints]; + +#if QWT_VERSION < 0x060000 + d_plot_curve[i]->setRawData(d_xdata, d_ydata[i], d_numPoints); +#else + d_plot_curve[i]->setRawSamples(d_xdata, d_ydata[i], d_numPoints); +#endif + } +#if QWT_VERSION < 0x060000 + d_min_vec_plot_curve->setRawData(d_xdata, d_min_vec_data, d_numPoints); + d_max_vec_plot_curve->setRawData(d_xdata, d_max_vec_data, d_numPoints); +#else + d_min_vec_plot_curve->setRawSamples(d_xdata, d_min_vec_data, d_numPoints); + d_max_vec_plot_curve->setRawSamples(d_xdata, d_max_vec_data, d_numPoints); +#endif + _resetXAxisPoints(); + clearMaxData(); + clearMinData(); + } + + double bottom=1e20, top=-1e20; + for(int n = 0; n < d_nplots; n++) { + + memcpy(d_ydata[n], dataPoints[n], numDataPoints*sizeof(double)); + + for(int64_t point = 0; point < numDataPoints; point++) { + if(dataPoints[n][point] < d_min_vec_data[point]) { + d_min_vec_data[point] = dataPoints[n][point]; + } + if(dataPoints[n][point] > d_max_vec_data[point]) { + d_max_vec_data[point] = dataPoints[n][point]; + } + + // Find overall top and bottom values in plot. + // Used for autoscaling y-axis. + if(dataPoints[n][point] < bottom) { + bottom = dataPoints[n][point]; + } + if(dataPoints[n][point] > top) { + top = dataPoints[n][point]; + } + } + } + + if(d_autoscale_state) + _autoScale(bottom, top); + + d_ref_level = refLevel; + + replot(); + } + } +} + +void +VectorDisplayPlot::clearMaxData() +{ + for(int64_t number = 0; number < d_numPoints; number++) { + d_max_vec_data[number] = d_ymin; + } +} + +void +VectorDisplayPlot::clearMinData() +{ + for(int64_t number = 0; number < d_numPoints; number++) { + d_min_vec_data[number] = d_ymax; + } +} + +void +VectorDisplayPlot::_autoScale(double bottom, double top) +{ + // Auto scale the y-axis with a margin of 10 dB on either side. + d_ymin = bottom-10; + d_ymax = top+10; + setYaxis(d_ymin, d_ymax); +} + +void +VectorDisplayPlot::setAutoScale(bool state) +{ + d_autoscale_state = state; +} + +void +VectorDisplayPlot::setMaxVecVisible(const bool visibleFlag) +{ + d_max_vec_visible = visibleFlag; + d_max_vec_plot_curve->setVisible(visibleFlag); +} + +const bool +VectorDisplayPlot::getMaxVecVisible() const +{ + return d_max_vec_visible; +} + +void +VectorDisplayPlot::setMinVecVisible(const bool visibleFlag) +{ + d_min_vec_visible = visibleFlag; + d_min_vec_plot_curve->setVisible(visibleFlag); +} + +const bool +VectorDisplayPlot::getMinVecVisible() const +{ + return d_min_vec_visible; +} + +void +VectorDisplayPlot::_resetXAxisPoints() +{ + double xValue = d_x_axis_start; + for(int64_t loc = 0; loc < d_numPoints; loc++) { + d_xdata[loc] = xValue; + xValue += d_x_axis_step; + } + + setAxisScale(QwtPlot::xBottom, d_xdata[0], d_xdata[d_numPoints-1]); + + // Set up zoomer base for maximum unzoom x-axis + // and reset to maximum unzoom level + QwtDoubleRect zbase = d_zoomer->zoomBase(); + d_zoomer->zoom(zbase); + d_zoomer->setZoomBase(zbase); + d_zoomer->setZoomBase(true); + d_zoomer->zoom(0); +} + +void +VectorDisplayPlot::setLowerIntensityLevel(const double lowerIntensityLevel) +{ + d_lower_intensity_marker->setYValue(lowerIntensityLevel); +} + +void +VectorDisplayPlot::setUpperIntensityLevel(const double upperIntensityLevel) +{ + d_upper_intensity_marker->setYValue(upperIntensityLevel); +} + +void +VectorDisplayPlot::setTraceColour(QColor c) +{ + d_plot_curve[0]->setPen(QPen(c)); +} + +void +VectorDisplayPlot::setBGColour(QColor c) +{ + QPalette palette; + palette.setColor(canvas()->backgroundRole(), c); + canvas()->setPalette(palette); +} + +void +VectorDisplayPlot::onPickerPointSelected(const QwtDoublePoint & p) +{ + QPointF point = p; + point.setX(point.x()); + emit plotPointSelected(point); +} + +void +VectorDisplayPlot::onPickerPointSelected6(const QPointF & p) +{ + QPointF point = p; + point.setX(point.x()); + emit plotPointSelected(point); +} + +void +VectorDisplayPlot::setMinVecColor (QColor c) +{ + d_min_vec_color = c; + d_min_vec_plot_curve->setPen(QPen(c)); +} + +const QColor +VectorDisplayPlot::getMinVecColor() const +{ + return d_min_vec_color; +} + +void +VectorDisplayPlot::setMaxVecColor (QColor c) +{ + d_max_vec_color = c; + d_max_vec_plot_curve->setPen(QPen(c)); +} + +const QColor +VectorDisplayPlot::getMaxVecColor() const +{ + return d_max_vec_color; +} + +void +VectorDisplayPlot::setMarkerLowerIntensityColor (QColor c) +{ + d_marker_lower_intensity_color = c; + d_lower_intensity_marker->setLinePen(QPen(c)); +} +const QColor +VectorDisplayPlot::getMarkerLowerIntensityColor () const +{ + return d_marker_lower_intensity_color; +} + +void +VectorDisplayPlot::setMarkerLowerIntensityVisible (bool visible) +{ + d_marker_lower_intensity_visible = visible; + if(visible) + d_lower_intensity_marker->setLineStyle(QwtPlotMarker::HLine); + else + d_lower_intensity_marker->setLineStyle(QwtPlotMarker::NoLine); +} +const bool +VectorDisplayPlot::getMarkerLowerIntensityVisible() const +{ + return d_marker_lower_intensity_visible; +} + +void +VectorDisplayPlot::setMarkerUpperIntensityColor(QColor c) +{ + d_marker_upper_intensity_color = c; + d_upper_intensity_marker->setLinePen(QPen(c, 0, Qt::DotLine)); +} + +const QColor +VectorDisplayPlot::getMarkerUpperIntensityColor() const +{ + return d_marker_upper_intensity_color; +} + +void +VectorDisplayPlot::setMarkerUpperIntensityVisible(bool visible) +{ + d_marker_upper_intensity_visible = visible; + if(visible) + d_upper_intensity_marker->setLineStyle(QwtPlotMarker::HLine); + else + d_upper_intensity_marker->setLineStyle(QwtPlotMarker::NoLine); +} + +const bool +VectorDisplayPlot::getMarkerUpperIntensityVisible() const +{ + return d_marker_upper_intensity_visible; +} + +void +VectorDisplayPlot::setMarkerRefLevelAmplitudeColor(QColor c) +{ + d_marker_ref_level_color = c; + d_marker_ref_level->setLinePen(QPen(c, 0, Qt::DotLine)); +} + +const QColor +VectorDisplayPlot::getMarkerRefLevelAmplitudeColor() const +{ + return d_marker_ref_level_color; +} + +void +VectorDisplayPlot::setMarkerRefLevelAmplitudeVisible(bool visible) +{ + d_marker_ref_level_visible = visible; + if(visible) + d_marker_ref_level->setLineStyle(QwtPlotMarker::HLine); + else + d_marker_ref_level->setLineStyle(QwtPlotMarker::NoLine); +} + +const bool +VectorDisplayPlot::getMarkerRefLevelAmplitudeVisible() const +{ + return d_marker_ref_level_visible; +} + +#endif /* VECTOR_DISPLAY_PLOT */ |