summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rondeau <tom@trondeau.com>2015-01-04 15:31:54 -0500
committerTom Rondeau <tom@trondeau.com>2015-01-04 15:31:54 -0500
commit028db97b47c7246a2d73748855b6108f2f78240a (patch)
treef9cf3f4bb61750921238b5bc801d581864048d77
parentc67281b69d115e778e9aa5f04e431e032c59b512 (diff)
parent3ee2c52ccb27b54bf626721001512f6013b648c3 (diff)
Merge remote-tracking branch 'garverp/offlineplotfixes'
-rw-r--r--gr-qtgui/apps/CMakeLists.txt1
-rwxr-xr-xgr-qtgui/apps/gr_spectrogram_plot190
-rw-r--r--gr-qtgui/apps/plot_form.py1
-rw-r--r--gr-qtgui/apps/plot_spectrogram_base.py2
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h4
-rw-r--r--gr-qtgui/lib/WaterfallDisplayPlot.cc4
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.cc6
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.h1
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.cc6
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.h1
-rw-r--r--gr-qtgui/lib/waterfalldisplayform.cc25
13 files changed, 239 insertions, 4 deletions
diff --git a/gr-qtgui/apps/CMakeLists.txt b/gr-qtgui/apps/CMakeLists.txt
index 05accc64d2..3c64cb6e0a 100644
--- a/gr-qtgui/apps/CMakeLists.txt
+++ b/gr-qtgui/apps/CMakeLists.txt
@@ -55,6 +55,7 @@ GR_PYTHON_INSTALL(
gr_spectrogram_plot_i
gr_spectrogram_plot_s
gr_spectrogram_plot_b
+ gr_spectrogram_plot
gr_constellation_plot
DESTINATION ${GR_RUNTIME_DIR}
COMPONENT "qtgui_python"
diff --git a/gr-qtgui/apps/gr_spectrogram_plot b/gr-qtgui/apps/gr_spectrogram_plot
new file mode 100755
index 0000000000..73ccd2f6b9
--- /dev/null
+++ b/gr-qtgui/apps/gr_spectrogram_plot
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 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.
+#
+
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio import filter
+import pmt
+from gnuradio.blocks import parse_file_metadata
+import scipy
+import sys
+import os
+
+try:
+ import gnuradio.qtgui.plot_spectrogram_base as plot_base
+except ImportError:
+ import plot_spectrogram_base as plot_base
+
+try:
+ from gnuradio import qtgui
+ from PyQt4 import QtGui, QtCore
+ import sip
+except ImportError:
+ print "Error: Program requires PyQt4 and gr-qtgui."
+ sys.exit(1)
+
+class spectrogram_plot_c(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+ self.read_samples = plot_base.read_samples_c
+ self.dsize = gr.sizeof_gr_complex
+ self.src_type = blocks.vector_source_c
+ self.gui_snk = qtgui.waterfall_sink_c(self._psd_size,
+ filter.firdes.WIN_BLACKMAN_hARRIS,self._center_freq,
+ self._samp_rate,"GNU Radio Spectrogram Plot (CPX Float)",
+ self._nsigs)
+ self.setup()
+
+class spectrogram_plot_f(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+ self.read_samples = plot_base.read_samples_f
+ self.dsize = gr.sizeof_float
+ self.src_type = blocks.vector_source_f
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size,
+ filter.firdes.WIN_BLACKMAN_hARRIS,self._center_freq,
+ self._samp_rate,
+ "GNU Radio Spectrogram Plot (float)",
+ self._nsigs)
+ self.setup()
+
+class spectrogram_plot_b(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+ self.read_samples = plot_base.read_samples_b
+ self.dsize = gr.sizeof_float
+ self.src_type = plot_base.source_chars_to_float
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size,
+ filter.firdes.WIN_BLACKMAN_hARRIS,self._center_freq,
+ self._samp_rate, "GNU Radio Spectrogram Plot (bin)",
+ self._nsigs)
+ self.setup()
+
+class spectrogram_plot_i(plot_base.plot_base):
+ def __init__(self, filelist, fc, samp_rate, psdsize, start,
+ nsamples, max_nsamples, avg=1.0):
+ plot_base.plot_base.__init__(self, filelist, fc, samp_rate,
+ psdsize, start, nsamples,
+ max_nsamples, avg)
+ self.dsize = gr.sizeof_float
+ self.src_type = plot_base.source_ints_to_float
+ self.gui_snk = qtgui.waterfall_sink_f(self._psd_size,
+ filter.firdes.WIN_BLACKMAN_hARRIS,
+ self._center_freq, self._samp_rate,
+ "GNU Radio Spectrogram Plot (int)",
+ self._nsigs)
+ self.setup()
+
+def read_header(filelist):
+ filename = filelist[0] + '.hdr'
+ try:
+ handle = open(filename,"rb")
+ except IOError:
+ return
+ hdr_start = handle.tell()
+ header_str = handle.read(parse_file_metadata.HEADER_LENGTH)
+ if( len(header_str) == 0 ):
+ return
+ # String to PMT Conversion
+ try:
+ header = pmt.deserialize_str(header_str)
+ except RuntimeError:
+ sys.stderr.write("Can't deserialize header: invalid/corrupt data\n")
+ sys.exit(1)
+ info = parse_file_metadata.parse_header(header,False)
+ return info
+
+def main():
+ description = 'Plots the spectrogram (waterfall) of a file with detached header.'
+ description += ' Assumes header is <input_filename>.hdr'
+ (options, args) = plot_base.setup_options(description)
+ filelist = list(args)
+ # Attempt to read the header information
+ info = read_header(filelist)
+ # If no header, quit
+ if not info:
+ sys.stderr.write('Header not found\n')
+ sys.exit(1)
+
+ max_nsamples = plot_base.find_max_nsamples(filelist)
+ srate = info["rx_rate"]
+
+ # Dispatch the proper function
+ # Complex Types
+ if(info["cplx"] == True):
+ if( info["type"] == "float" ):
+ tb = spectrogram_plot_c(filelist,
+ options.center_frequency,srate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average);
+ else:
+ sys.stderr.write("Complex File Type " + info["type"]+ " not supported.\n")
+ # Real Types
+ else:
+ if( info["type"] == "bytes" ):
+ tb = spectrogram_plot_b(filelist,
+ options.center_frequency,srate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average);
+ elif( info["type"] == "int" ):
+ tb = spectrogram_plot_i(filelist,
+ options.center_frequency,srate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average);
+ elif( info["type"] == "float" ):
+ tb = spectrogram_plot_f(filelist,
+ options.center_frequency,srate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average);
+ elif( info["type"] == "short" ):
+ tb = spectrogram_plot_s(filelist,
+ options.center_frequency,srate,
+ options.psd_size,
+ options.start, options.nsamples, max_nsamples,
+ options.average);
+ else:
+ sys.stderr.write("Real File Type " + info["type"] + " not supported\n")
+ main_box = plot_base.plot_spectrogram_form(tb, 'GNU Radio Spectrogram Plot')
+ main_box.show()
+
+ tb.run()
+ tb.qapp.exec_()
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass
+
diff --git a/gr-qtgui/apps/plot_form.py b/gr-qtgui/apps/plot_form.py
index 75e39ec98e..931565bd3e 100644
--- a/gr-qtgui/apps/plot_form.py
+++ b/gr-qtgui/apps/plot_form.py
@@ -359,6 +359,7 @@ class plot_form(QtGui.QWidget):
sr = self.samp_rate_edit.text().toDouble()[0]
fr = self.freq_edit.text().toDouble()[0]
self.top_block.gui_snk.set_frequency_range(fr, sr)
+ self.top_block._samp_rate = sr
self.top_block.reset(self.top_block._start,
self.top_block._nsamps)
diff --git a/gr-qtgui/apps/plot_spectrogram_base.py b/gr-qtgui/apps/plot_spectrogram_base.py
index 26c336e36c..b252bb8863 100644
--- a/gr-qtgui/apps/plot_spectrogram_base.py
+++ b/gr-qtgui/apps/plot_spectrogram_base.py
@@ -100,6 +100,7 @@ class plot_base(gr.top_block):
self.connect(s, (self.gui_snk, i+1))
self.gui_snk.set_update_time(0);
+ self.gui_snk.set_time_per_fft(self._psd_size/self._samp_rate)
self.gui_snk.enable_menu(False)
self.gui_snk.set_fft_average(self._avg)
@@ -126,6 +127,7 @@ class plot_base(gr.top_block):
self.stop()
self.wait()
self.gui_snk.clear_data()
+ self.gui_snk.set_time_per_fft(self._psd_size/self._samp_rate)
self._start = newstart
self._nsamps = newnsamps
diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h
index bf73db3f1a..9229682b28 100644
--- a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h
+++ b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h
@@ -109,6 +109,7 @@ namespace gr {
virtual void set_fft_size(const int fftsize) = 0;
virtual int fft_size() const = 0;
+ virtual void set_time_per_fft(const double t) = 0;
virtual void set_fft_average(const float fftavg) = 0;
virtual float fft_average() const = 0;
virtual void set_fft_window(const gr::filter::firdes::win_type win) = 0;
diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h
index 4570ef9d54..0bbd7e0231 100644
--- a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h
+++ b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h
@@ -108,6 +108,7 @@ namespace gr {
virtual void set_fft_size(const int fftsize) = 0;
virtual int fft_size() const = 0;
+ virtual void set_time_per_fft(const double t) = 0;
virtual void set_fft_average(const float fftavg) = 0;
virtual float fft_average() const = 0;
virtual void set_fft_window(const gr::filter::firdes::win_type win) = 0;
diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h b/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h
index e885a525b0..10378d4917 100644
--- a/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h
+++ b/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h
@@ -46,6 +46,7 @@ class WaterfallDisplayForm : public DisplayForm
WaterfallDisplayPlot* getPlot();
int getFFTSize() const;
+ double getTimePerFFT();
float getFFTAverage() const;
gr::filter::firdes::win_type getFFTWindowType() const;
@@ -87,6 +88,8 @@ public slots:
void autoScale(bool en=false);
void setPlotPosHalf(bool half);
+ void setTimePerFFT(double t);
+ void setUpdateTime(double t);
private slots:
void newData(const QEvent *updateEvent);
@@ -97,6 +100,7 @@ private:
double d_samp_rate, d_center_freq;
int d_fftsize;
+ double d_time_per_fft;
float d_fftavg;
gr::filter::firdes::win_type d_fftwintype;
double d_units;
diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc
index 86724fe04d..ef1ec3bf03 100644
--- a/gr-qtgui/lib/WaterfallDisplayPlot.cc
+++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc
@@ -62,7 +62,7 @@ public:
virtual QwtText label(double value) const
{
double secs = double(value * getSecondsPerLine());
- return QwtText(QString("").sprintf("%.1f", secs));
+ return QwtText(QString("").sprintf("%.2e", secs));
}
virtual void initiateUpdate()
@@ -119,7 +119,7 @@ protected:
QwtText t(QString("%1 %2, %3 s")
.arg(dp.x(), 0, 'f', getFrequencyPrecision())
.arg(d_unitType.c_str())
- .arg(secs, 0, 'f', 2));
+ .arg(secs, 0, 'e', 2));
return t;
}
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.cc b/gr-qtgui/lib/waterfall_sink_c_impl.cc
index 5e393528d4..a9a2d6c09e 100644
--- a/gr-qtgui/lib/waterfall_sink_c_impl.cc
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc
@@ -458,6 +458,12 @@ namespace gr {
}
}
+ void
+ waterfall_sink_c_impl::set_time_per_fft(double t)
+ {
+ d_main_gui->setTimePerFFT(t);
+ }
+
int
waterfall_sink_c_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.h b/gr-qtgui/lib/waterfall_sink_c_impl.h
index d0e7eb13ba..6ab09bdd9b 100644
--- a/gr-qtgui/lib/waterfall_sink_c_impl.h
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.h
@@ -106,6 +106,7 @@ namespace gr {
void set_intensity_range(const double min, const double max);
void set_update_time(double t);
+ void set_time_per_fft(double t);
void set_title(const std::string &title);
void set_line_label(int which, const std::string &label);
void set_line_alpha(int which, double alpha);
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc b/gr-qtgui/lib/waterfall_sink_f_impl.cc
index 0f7f9e0437..0c1fbbff36 100644
--- a/gr-qtgui/lib/waterfall_sink_f_impl.cc
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc
@@ -465,6 +465,12 @@ namespace gr {
}
}
}
+
+ void
+ waterfall_sink_f_impl::set_time_per_fft(double t)
+ {
+ d_main_gui->setTimePerFFT(t);
+ }
int
waterfall_sink_f_impl::work(int noutput_items,
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.h b/gr-qtgui/lib/waterfall_sink_f_impl.h
index ca6e3f4264..2710f304ec 100644
--- a/gr-qtgui/lib/waterfall_sink_f_impl.h
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.h
@@ -106,6 +106,7 @@ namespace gr {
void set_intensity_range(const double min, const double max);
void set_update_time(double t);
+ void set_time_per_fft(double t);
void set_title(const std::string &title);
void set_line_label(int which, const std::string &label);
void set_line_alpha(int which, double alpha);
diff --git a/gr-qtgui/lib/waterfalldisplayform.cc b/gr-qtgui/lib/waterfalldisplayform.cc
index c1dd8f7aab..9f87504d9c 100644
--- a/gr-qtgui/lib/waterfalldisplayform.cc
+++ b/gr-qtgui/lib/waterfalldisplayform.cc
@@ -48,7 +48,7 @@ WaterfallDisplayForm::WaterfallDisplayForm(int nplots, QWidget* parent)
d_clicked = false;
d_clicked_freq = 0;
-
+ d_time_per_fft = 0;
// We don't use the normal menus that are part of the displayform.
// Clear them out to get rid of their resources.
for(int i = 0; i < nplots; i++) {
@@ -138,7 +138,7 @@ WaterfallDisplayForm::newData(const QEvent *updateEvent)
d_max_val = *max_val;
}
- getPlot()->plotNewData(dataPoints, numDataPoints, d_update_time, dataTimestamp, 0);
+ getPlot()->plotNewData(dataPoints, numDataPoints, d_time_per_fft, dataTimestamp, 0);
}
void
@@ -337,3 +337,24 @@ WaterfallDisplayForm::setPlotPosHalf(bool half)
getPlot()->setPlotPosHalf(half);
getPlot()->replot();
}
+
+void
+WaterfallDisplayForm::setTimePerFFT(double t)
+{
+ d_time_per_fft = t;
+}
+
+double WaterfallDisplayForm::getTimePerFFT()
+{
+ return d_time_per_fft;
+}
+// Override displayform SetUpdateTime() to set FFT time
+void
+WaterfallDisplayForm::setUpdateTime(double t)
+{
+ d_update_time = t;
+ // Assume times are equal unless explictly told by setTimePerFFT()
+ // This is the case when plotting using gr_spectrogram_plot
+ d_time_per_fft = t;
+}
+