summaryrefslogtreecommitdiff
path: root/gr-qtgui/lib
diff options
context:
space:
mode:
authorTom Rondeau <tom@trondeau.com>2013-10-22 14:03:39 -0400
committerTom Rondeau <tom@trondeau.com>2013-10-29 12:23:09 -0400
commitccb5384d759d8736e596574be770ad36222ef4a1 (patch)
treec5a5a544b09c53890fe199044b9fee7c9de73dc7 /gr-qtgui/lib
parentdaac8bc5f7c41afa678935344ef25f4f92206b3e (diff)
qtgui: fixed histogram autoscaling features. Added example script.
Diffstat (limited to 'gr-qtgui/lib')
-rw-r--r--gr-qtgui/lib/HistogramDisplayPlot.cc133
-rw-r--r--gr-qtgui/lib/histogram_sink_f_impl.cc6
-rw-r--r--gr-qtgui/lib/histogram_sink_f_impl.h1
-rw-r--r--gr-qtgui/lib/histogramdisplayform.cc44
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();
}