diff options
author | Tom Rondeau <tom@trondeau.com> | 2015-01-04 15:31:54 -0500 |
---|---|---|
committer | Tom Rondeau <tom@trondeau.com> | 2015-01-04 15:31:54 -0500 |
commit | 028db97b47c7246a2d73748855b6108f2f78240a (patch) | |
tree | f9cf3f4bb61750921238b5bc801d581864048d77 | |
parent | c67281b69d115e778e9aa5f04e431e032c59b512 (diff) | |
parent | 3ee2c52ccb27b54bf626721001512f6013b648c3 (diff) |
Merge remote-tracking branch 'garverp/offlineplotfixes'
-rw-r--r-- | gr-qtgui/apps/CMakeLists.txt | 1 | ||||
-rwxr-xr-x | gr-qtgui/apps/gr_spectrogram_plot | 190 | ||||
-rw-r--r-- | gr-qtgui/apps/plot_form.py | 1 | ||||
-rw-r--r-- | gr-qtgui/apps/plot_spectrogram_base.py | 2 | ||||
-rw-r--r-- | gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h | 1 | ||||
-rw-r--r-- | gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h | 1 | ||||
-rw-r--r-- | gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h | 4 | ||||
-rw-r--r-- | gr-qtgui/lib/WaterfallDisplayPlot.cc | 4 | ||||
-rw-r--r-- | gr-qtgui/lib/waterfall_sink_c_impl.cc | 6 | ||||
-rw-r--r-- | gr-qtgui/lib/waterfall_sink_c_impl.h | 1 | ||||
-rw-r--r-- | gr-qtgui/lib/waterfall_sink_f_impl.cc | 6 | ||||
-rw-r--r-- | gr-qtgui/lib/waterfall_sink_f_impl.h | 1 | ||||
-rw-r--r-- | gr-qtgui/lib/waterfalldisplayform.cc | 25 |
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; +} + |