diff options
author | Tom Rondeau <tom@trondeau.com> | 2013-10-22 14:03:39 -0400 |
---|---|---|
committer | Tom Rondeau <tom@trondeau.com> | 2013-10-29 12:23:09 -0400 |
commit | ccb5384d759d8736e596574be770ad36222ef4a1 (patch) | |
tree | c5a5a544b09c53890fe199044b9fee7c9de73dc7 /gr-qtgui/lib | |
parent | daac8bc5f7c41afa678935344ef25f4f92206b3e (diff) |
qtgui: fixed histogram autoscaling features. Added example script.
Diffstat (limited to 'gr-qtgui/lib')
-rw-r--r-- | gr-qtgui/lib/HistogramDisplayPlot.cc | 133 | ||||
-rw-r--r-- | gr-qtgui/lib/histogram_sink_f_impl.cc | 6 | ||||
-rw-r--r-- | gr-qtgui/lib/histogram_sink_f_impl.h | 1 | ||||
-rw-r--r-- | gr-qtgui/lib/histogramdisplayform.cc | 44 |
4 files changed, 119 insertions, 65 deletions
diff --git a/gr-qtgui/lib/HistogramDisplayPlot.cc b/gr-qtgui/lib/HistogramDisplayPlot.cc index bcdab6b3f4..68b7d8c3ab 100644 --- a/gr-qtgui/lib/HistogramDisplayPlot.cc +++ b/gr-qtgui/lib/HistogramDisplayPlot.cc @@ -114,12 +114,12 @@ private: HistogramDisplayPlot::HistogramDisplayPlot(int nplots, QWidget* parent) : DisplayPlot(nplots, parent) { - _bins = 100; - _accum = false; + d_bins = 100; + d_accum = false; // Initialize x-axis data array - _xAxisPoints = new double[_bins]; - memset(_xAxisPoints, 0x0, _bins*sizeof(double)); + _xAxisPoints = new double[d_bins]; + memset(_xAxisPoints, 0x0, d_bins*sizeof(double)); _zoomer = new HistogramDisplayZoomer(canvas(), 0); @@ -136,18 +136,17 @@ HistogramDisplayPlot::HistogramDisplayPlot(int nplots, QWidget* parent) _zoomer->setRubberBandPen(c); _zoomer->setTrackerPen(c); - _magnifier->setAxisEnabled(QwtPlot::xBottom, true); - _magnifier->setAxisEnabled(QwtPlot::yLeft, false); - d_semilogx = false; d_semilogy = false; + _autoscale_state = true; + _autoscalex_state = false; setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine); setXaxis(-1, 1); setAxisTitle(QwtPlot::xBottom, "Value"); setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine); - setYaxis(-2.0, _bins); + setYaxis(-2.0, d_bins); setAxisTitle(QwtPlot::yLeft, "Count"); QList<QColor> colors; @@ -159,8 +158,8 @@ HistogramDisplayPlot::HistogramDisplayPlot(int nplots, QWidget* parent) // Setup dataPoints and plot vectors // Automatically deleted when parent is deleted for(int i = 0; i < _nplots; i++) { - _yDataPoints.push_back(new double[_bins]); - memset(_yDataPoints[i], 0, _bins*sizeof(double)); + _yDataPoints.push_back(new double[d_bins]); + memset(_yDataPoints[i], 0, d_bins*sizeof(double)); _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i))); _plot_curve[i]->attach(this); @@ -176,10 +175,10 @@ HistogramDisplayPlot::HistogramDisplayPlot(int nplots, QWidget* parent) QPen(colors[i]), QSize(7,7)); #if QWT_VERSION < 0x060000 - _plot_curve[i]->setRawData(_xAxisPoints, _yDataPoints[i], _bins); + _plot_curve[i]->setRawData(_xAxisPoints, _yDataPoints[i], d_bins); _plot_curve[i]->setSymbol(*symbol); #else - _plot_curve[i]->setRawSamples(_xAxisPoints, _yDataPoints[i], _bins); + _plot_curve[i]->setRawSamples(_xAxisPoints, _yDataPoints[i], d_bins); _plot_curve[i]->setSymbol(symbol); #endif } @@ -210,37 +209,41 @@ HistogramDisplayPlot::plotNewData(const std::vector<double*> dataPoints, if(!_stop) { if((numDataPoints > 0)) { - double bottom = *std::min_element(dataPoints[0], dataPoints[0]+numDataPoints); - double top = *std::max_element(dataPoints[0], dataPoints[0]+numDataPoints); - for(int n = 1; n < _nplots; n++) { - bottom = std::min(bottom, *std::min_element(dataPoints[n], dataPoints[n]+numDataPoints)); - top = std::max(top, *std::max_element(dataPoints[n], dataPoints[n]+numDataPoints)); + // keep track of the min/max values for when autoscaleX is called. + d_xmin = 1e20; + d_xmax = -1e20; + for(int n = 0; n < _nplots; n++) { + d_xmin = std::min(d_xmin, *std::min_element(dataPoints[n], dataPoints[n]+numDataPoints)); + d_xmax = std::max(d_xmax, *std::max_element(dataPoints[n], dataPoints[n]+numDataPoints)); } - _resetXAxisPoints(bottom, top); + // If autoscalex has been clicked, clear the data for the new + // bin widths and reset the x-axis. + if(_autoscalex_state) { + for(int n = 0; n < _nplots; n++) + memset(_yDataPoints[n], 0, d_bins*sizeof(double)); + _resetXAxisPoints(d_xmin, d_xmax); + _autoscalex_state = false; + } int index; - double width = (top - bottom)/(_bins-1); - - // Something's wrong with the data (NaN, Inf, or something else) - if((bottom == top) || (bottom > top)) - return; - for(int n = 0; n < _nplots; n++) { - if(!_accum) - memset(_yDataPoints[n], 0, _bins*sizeof(double)); + if(!d_accum) + memset(_yDataPoints[n], 0, d_bins*sizeof(double)); for(int64_t point = 0; point < numDataPoints; point++) { - index = boost::math::iround(1e-20 + (dataPoints[n][point] - bottom)/width); - index = std::max(std::min(index, _bins), 0); - _yDataPoints[n][static_cast<int>(index)] += 1; + index = boost::math::iround(1e-20 + (dataPoints[n][point] - d_left)/d_width); + if((index >= 0) && (index < d_bins)) + _yDataPoints[n][static_cast<int>(index)] += 1; } } - double height = *std::max_element(_yDataPoints[0], _yDataPoints[0]+_bins); + double height = *std::max_element(_yDataPoints[0], _yDataPoints[0]+d_bins); for(int n = 1; n < _nplots; n++) { - height = std::max(height, *std::max_element(_yDataPoints[n], _yDataPoints[n]+_bins)); + height = std::max(height, *std::max_element(_yDataPoints[n], _yDataPoints[n]+d_bins)); } - _autoScale(0, height); + + if(_autoscale_state) + _autoScaleY(0, height); replot(); } @@ -248,57 +251,71 @@ HistogramDisplayPlot::plotNewData(const std::vector<double*> dataPoints, } void -HistogramDisplayPlot::_resetXAxisPoints(double bottom, double top) +HistogramDisplayPlot::setXaxis(double min, double max) { - double width = (top - bottom)/(_bins-1); - for(long loc = 0; loc < _bins; loc++){ - _xAxisPoints[loc] = bottom + loc*width; - } + _resetXAxisPoints(min, max); +} - if(!_autoscale_state) { - bottom = axisScaleDiv(QwtPlot::xBottom)->lowerBound(); - top = axisScaleDiv(QwtPlot::xBottom)->upperBound(); +void +HistogramDisplayPlot::_resetXAxisPoints(double left, double right) +{ + // Something's wrong with the data (NaN, Inf, or something else) + if((left == right) || (left > right)) + throw std::runtime_error("HistogramDisplayPlot::_resetXAxisPoints left and/or right values are invalid"); + + d_left = left *(1 - copysign(0.1, left)); + d_right = right*(1 + copysign(0.1, right)); + d_width = (d_right - d_left)/(d_bins); + for(long loc = 0; loc < d_bins; loc++){ + _xAxisPoints[loc] = d_left + loc*d_width; } + axisScaleDiv(QwtPlot::xBottom)->setInterval(d_left, d_right); // Set up zoomer base for maximum unzoom x-axis // and reset to maximum unzoom level QwtDoubleRect zbase = _zoomer->zoomBase(); if(d_semilogx) { - setAxisScale(QwtPlot::xBottom, 1e-1, top); + setAxisScale(QwtPlot::xBottom, 1e-1, d_right); zbase.setLeft(1e-1); } else { - setAxisScale(QwtPlot::xBottom, bottom, top); - zbase.setLeft(bottom); + setAxisScale(QwtPlot::xBottom, d_left, d_right); + zbase.setLeft(d_left); } - zbase.setRight(top); + zbase.setRight(d_right); _zoomer->zoom(zbase); _zoomer->setZoomBase(zbase); _zoomer->zoom(0); } void -HistogramDisplayPlot::_autoScale(double bottom, double top) +HistogramDisplayPlot::_autoScaleY(double bottom, double top) { // Auto scale the y-axis with a margin of 20% (10 dB for log scale) - double _bot = bottom - fabs(bottom)*0.20; - double _top = top + fabs(top)*0.20; + double b = bottom - fabs(bottom)*0.20; + double t = top + fabs(top)*0.20; if(d_semilogy) { if(bottom > 0) { - setYaxis(_bot-10, _top+10); + setYaxis(b-10, t+10); } else { - setYaxis(1e-3, _top+10); + setYaxis(1e-3, t+10); } } else { - setYaxis(_bot, _top); + setYaxis(b, t); } } void +HistogramDisplayPlot::setAutoScaleX() +{ + _autoscalex_state = true; +} + +void HistogramDisplayPlot::setAutoScale(bool state) { _autoscale_state = state; @@ -336,7 +353,7 @@ HistogramDisplayPlot::setSemilogy(bool en) void HistogramDisplayPlot::setAccumulate(bool state) { - _accum = state; + d_accum = state; } void @@ -418,21 +435,21 @@ HistogramDisplayPlot::setLineColor(int which, QColor color) void HistogramDisplayPlot::setNumBins(int bins) { - _bins = bins; + d_bins = bins; delete [] _xAxisPoints; - _xAxisPoints = new double[_bins]; - memset(_xAxisPoints, 0x0, _bins*sizeof(double)); + _xAxisPoints = new double[d_bins]; + _resetXAxisPoints(d_left, d_right); for(int i = 0; i < _nplots; i++) { delete [] _yDataPoints[i]; - _yDataPoints[i] = new double[_bins]; - memset(_yDataPoints[i], 0, _bins*sizeof(double)); + _yDataPoints[i] = new double[d_bins]; + memset(_yDataPoints[i], 0, d_bins*sizeof(double)); #if QWT_VERSION < 0x060000 - _plot_curve[i]->setRawData(_xAxisPoints, _yDataPoints[i], _bins); + _plot_curve[i]->setRawData(_xAxisPoints, _yDataPoints[i], d_bins); #else - _plot_curve[i]->setRawSamples(_xAxisPoints, _yDataPoints[i], _bins); + _plot_curve[i]->setRawSamples(_xAxisPoints, _yDataPoints[i], d_bins); #endif } } diff --git a/gr-qtgui/lib/histogram_sink_f_impl.cc b/gr-qtgui/lib/histogram_sink_f_impl.cc index cd4012f4f5..ef8a9a52c6 100644 --- a/gr-qtgui/lib/histogram_sink_f_impl.cc +++ b/gr-qtgui/lib/histogram_sink_f_impl.cc @@ -331,6 +331,12 @@ namespace gr { } void + histogram_sink_f_impl::autoscalex() + { + d_main_gui->autoScaleX(); + } + + void histogram_sink_f_impl::reset() { d_index = 0; diff --git a/gr-qtgui/lib/histogram_sink_f_impl.h b/gr-qtgui/lib/histogram_sink_f_impl.h index 83c8558c1b..995b93bef8 100644 --- a/gr-qtgui/lib/histogram_sink_f_impl.h +++ b/gr-qtgui/lib/histogram_sink_f_impl.h @@ -98,6 +98,7 @@ namespace gr { void enable_semilogx(bool en); void enable_semilogy(bool en); void enable_accumulate(bool en); + void autoscalex(); int nsamps() const; int bins() const; void reset(); diff --git a/gr-qtgui/lib/histogramdisplayform.cc b/gr-qtgui/lib/histogramdisplayform.cc index a56ad86d3a..22d0d67070 100644 --- a/gr-qtgui/lib/histogramdisplayform.cc +++ b/gr-qtgui/lib/histogramdisplayform.cc @@ -39,15 +39,15 @@ HistogramDisplayForm::HistogramDisplayForm(int nplots, QWidget* parent) _layout->addWidget(_displayPlot, 0, 0); setLayout(_layout); - NPointsMenu *nptsmenu = new NPointsMenu(this); - _menu->addAction(nptsmenu); - connect(nptsmenu, SIGNAL(whichTrigger(int)), + d_nptsmenu = new NPointsMenu(this); + _menu->addAction(d_nptsmenu); + connect(d_nptsmenu, SIGNAL(whichTrigger(int)), this, SLOT(setNPoints(const int))); - NPointsMenu *nbinsmenu = new NPointsMenu(this); - nbinsmenu->setText("Number of Bins"); - _menu->addAction(nbinsmenu); - connect(nbinsmenu, SIGNAL(whichTrigger(int)), + d_nbinsmenu = new NPointsMenu(this); + d_nbinsmenu->setText("Number of Bins"); + _menu->addAction(d_nbinsmenu); + connect(d_nbinsmenu, SIGNAL(whichTrigger(int)), this, SLOT(setNumBins(const int))); QAction *accummenu = new QAction("Accumulate", this); @@ -56,6 +56,23 @@ HistogramDisplayForm::HistogramDisplayForm(int nplots, QWidget* parent) connect(accummenu, SIGNAL(triggered(bool)), this, SLOT(setAccumulate(bool))); + _menu->removeAction(_autoscale_act); + _autoscale_act->setText(tr("Auto Scale Y")); + _autoscale_act->setStatusTip(tr("Autoscale Y-axis")); + _autoscale_act->setCheckable(true); + _autoscale_act->setChecked(true); + _autoscale_state = true; + _menu->addAction(_autoscale_act); + + _autoscalex_act = new QAction("Auto Scale X", this); + _autoscalex_act->setStatusTip(tr("Update X-axis scale")); + _autoscalex_act->setCheckable(false); + connect(_autoscalex_act, SIGNAL(changed()), + this, SLOT(autoScaleX())); + _autoscalex_state = false; + _menu->addAction(_autoscalex_act); + + // d_semilogxmenu = new QAction("Semilog X", this); // d_semilogxmenu->setCheckable(true); // _menu->addAction(d_semilogxmenu); @@ -130,6 +147,7 @@ void HistogramDisplayForm::setNPoints(const int npoints) { d_npoints = npoints; + d_nptsmenu->setDiagText(npoints); } void @@ -142,6 +160,13 @@ HistogramDisplayForm::autoScale(bool en) } void +HistogramDisplayForm::autoScaleX() +{ + getPlot()->setAutoScaleX(); + getPlot()->replot(); +} + +void HistogramDisplayForm::setSemilogx(bool en) { d_semilogx = en; @@ -164,11 +189,16 @@ HistogramDisplayForm::setNumBins(const int bins) { getPlot()->setNumBins(bins); getPlot()->replot(); + d_nbinsmenu->setDiagText(bins); } void HistogramDisplayForm::setAccumulate(bool en) { + // Turn on y-axis autoscaling when turning accumulate on. + if(en) { + autoScale(true); + } getPlot()->setAccumulate(en); getPlot()->replot(); } |