diff options
66 files changed, 2902 insertions, 2112 deletions
diff --git a/gr-qtgui/apps/CMakeLists.txt b/gr-qtgui/apps/CMakeLists.txt index 07a8298701..dcce338779 100644 --- a/gr-qtgui/apps/CMakeLists.txt +++ b/gr-qtgui/apps/CMakeLists.txt @@ -21,7 +21,15 @@ include(GrPython) GR_PYTHON_INSTALL( FILES + plot_base.py + plot_psd_base.py + plot_spectrogram_base.py + plot_time_base.py plot_form.py + plot_constellation_form.py + plot_psd_form.py + plot_spectrogram_form.py + plot_time_form.py DESTINATION ${GR_PYTHON_DIR}/gnuradio/qtgui COMPONENT "qtgui_python" ) diff --git a/gr-qtgui/apps/gr_constellation_plot b/gr-qtgui/apps/gr_constellation_plot index 02805a8fd1..92c4e3be15 100755 --- a/gr-qtgui/apps/gr_constellation_plot +++ b/gr-qtgui/apps/gr_constellation_plot @@ -40,37 +40,30 @@ except ImportError: sys.exit(1) try: - from gnuradio.qtgui.plot_form import * + from gnuradio.qtgui.plot_constellation_form import * + from gnuradio.qtgui.plot_base import * except ImportError: - from plot_form import * - -def read_samples(filename, start, in_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_gr_complex, 0) - data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size) - data = data.tolist() - fhandle.close() - - if(len(data) < in_size): - print "Warning: read in {0} samples but asked for {1} samples.".format( - len(data), in_size) - - return data + from plot_constellation_form import * + from plot_base import * class my_top_block(gr.top_block): def __init__(self, filelist, start, nsamples, max_nsamples): gr.top_block.__init__(self) self._filelist = filelist + self._samp_rate = 0 + self._center_freq = 0 self._start = start self._max_nsamps = max_nsamples self._nsigs = len(self._filelist) + self._nsamps = nsamples + self._auto_scale = True - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples + self._y_min = -20 + self._y_max = 20 + self._y_range = 4 + self._y_value = 2 + self.gui_y_axis = None self.qapp = QtGui.QApplication(sys.argv) @@ -80,10 +73,17 @@ class my_top_block(gr.top_block): self._nsigs) n = 0 self.srcs = list() + self._data_min = sys.maxint + self._data_max = -sys.maxint - 1 for f in filelist: - data = read_samples(f, self._start, self._nsamps) + data,_min,_max = read_samples_c(f, self._start, self._nsamps) self.srcs.append(gr.vector_source_c(data)) + if(_min < self._data_min): + self._data_min = _min + if(_max > self._data_max): + self._data_max = _max + # Set default labels based on file names fname = f.split("/")[-1] self.gui_snk.set_line_label(n, "{0}".format(fname)) @@ -95,6 +95,8 @@ class my_top_block(gr.top_block): for i,s in enumerate(self.srcs[1:]): self.connect(s, (self.gui_snk, i+1)) + self.gui_snk.enable_menu(False) + # Get Python Qt references pyQt = self.gui_snk.pyqwidget() self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) @@ -109,7 +111,7 @@ class my_top_block(gr.top_block): self._start = newstart for s,f in zip(self.srcs, self._filelist): - data = read_samples(f, self._start, newnsamps) + data,_min,_max = read_samples_c(f, self._start, newnsamps) s.set_data(data) if(len(data) < newnsamps): newnsamps = len(data) @@ -119,12 +121,33 @@ class my_top_block(gr.top_block): self.start() + def set_y_axis(self, y_min, y_max): + y_min = -y_max + self.gui_snk.set_y_axis(y_min, y_max) + self.gui_snk.set_x_axis(y_min, y_max) + return y_min, y_max + + def auto_scale(self, state): + if(state > 0): + self.set_y_axis(self._data_min, self._data_max) + self._auto_scale = True + self._y_value = self._data_max + self._y_range = self._data_max - self._data_min + self._y_min = 10*self._data_min + self._y_max = 10*self._data_max + + if(self.gui_y_axis): + self.gui_y_axis(self._data_min, self._data_max) + else: + self._auto_scale = False + + def main(): description = "Plots the constellations of a list of files." parser = OptionParser(option_class=eng_option, description=description, conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-N", "--nsamples", type="int", default=1000000, + help="Set the number of samples to display [default=%default]") parser.add_option("-S", "--start", type="int", default=0, help="Starting sample number [default=%default]") (options, args) = parser.parse_args() @@ -148,7 +171,9 @@ def main(): tb = my_top_block(filelist, options.start, nsamples, max_nsamples); - main_box = dialog_box(tb, 'GNU Radio Constellation Plot') + main_box = plot_constellation_form(tb, 'GNU Radio Constellation Plot') + for n in xrange(tb._nsigs): + main_box._style_edit[n].setCurrentIndex(0) main_box.show() tb.run() diff --git a/gr-qtgui/apps/gr_psd_plot_b b/gr-qtgui/apps/gr_psd_plot_b index b5d2104da2..d2c170a1d0 100755 --- a/gr-qtgui/apps/gr_psd_plot_b +++ b/gr-qtgui/apps/gr_psd_plot_b @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,10 +21,12 @@ # from gnuradio import gr -from gnuradio import blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_psd_base as plot_base +except ImportError: + import plot_psd_base as plot_base try: from gnuradio import qtgui @@ -34,144 +36,35 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples_and_pad(filename, start, in_size, min_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_char, 0) - data = scipy.fromfile(fhandle, dtype=scipy.uint8, count=in_size) - data = data.tolist() - fhandle.close() - - # If we have to, append 0's to create min_size samples of data - if(len(data) < min_size): - data += (min_size - len(data)) * [scipy.uint8(0)] - - return data - -class my_top_block(gr.top_block): +class psd_plot_b(plot_base.plot_base): def __init__(self, filelist, fc, samp_rate, psdsize, start, - nsamples, max_nsamples, scale, avg=1.0): - gr.top_block.__init__(self) - - self._filelist = filelist - self._center_freq = fc - self._samp_rate = samp_rate - self._psd_size = psdsize - self._start = start - self._max_nsamps = max_nsamples - self._scale = scale - self._nsigs = len(self._filelist) - self._avg = avg - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) + nsamples, max_nsamples, avg=1.0, auto_scale=True): + 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.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, self._center_freq, self._samp_rate, "GNU Radio PSD Plot", self._nsigs) - n = 0 - self.srcs = list() - self.cnvrt = list() - for f in filelist: - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - self.srcs.append(gr.vector_source_b(data)) - self.cnvrt.append(blocks.char_to_float(1, self._scale)) - - # Set default labels based on file names - fname = f.split("/")[-1] - self.gui_snk.set_line_label(n, "{0}".format(fname)) - n += 1 - - self.connect(self.srcs[0], self.cnvrt[0], self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs[1:]): - self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) - - self.gui_snk.set_update_time(0); - self.gui_snk.set_fft_average(self._avg) - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - self._nsamps = newnsamps - - for s,f in zip(self.srcs, self._filelist): - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - s.set_data(data) - - self.start() + self.setup() def main(): - description = "Plots the PSDs of a list of files. Files are a binary list of chars/bytes." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-L", "--psd-size", type="int", default=2048, - help="Set the FFT size of the PSD [default=%default]") - parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, - help="Set the center frequency of the signal [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-a", "--average", type="float", default=1.0, - help="Set amount of averaging (smaller=more averaging) [default=%default]") - parser.add_option("-s", "--scale", type="eng_float", default=2**(8-1)-1, - help="Set a scaling factor for the char->float conversion [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + description = "Plots the PSDs of a list of files. Files are a binary list of bytes." + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_char) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, - options.center_frequency, options.sample_rate, - options.psd_size, - options.start, nsamples, max_nsamples, - options.scale, options.average) + tb = psd_plot_b(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, options.nsamples, max_nsamples, + options.average) - main_box = dialog_box(tb, 'GNU Radio PSD Plot') + main_box = plot_base.plot_psd_form(tb, 'GNU Radio PSD Plot') main_box.show() tb.run() @@ -182,4 +75,3 @@ if __name__ == "__main__": main() except KeyboardInterrupt: pass - diff --git a/gr-qtgui/apps/gr_psd_plot_c b/gr-qtgui/apps/gr_psd_plot_c index 0f7f4b9bef..06821d6934 100755 --- a/gr-qtgui/apps/gr_psd_plot_c +++ b/gr-qtgui/apps/gr_psd_plot_c @@ -21,9 +21,12 @@ # from gnuradio import gr -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_psd_base as plot_base +except ImportError: + import plot_psd_base as plot_base try: from gnuradio import qtgui @@ -33,139 +36,35 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples_and_pad(filename, start, in_size, min_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_gr_complex, 0) - data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size) - data = data.tolist() - fhandle.close() - - # If we have to, append 0's to create min_size samples of data - if(len(data) < min_size): - data += (min_size - len(data)) * [complex(0,0)] - - return data - -class my_top_block(gr.top_block): +class psd_plot_c(plot_base.plot_base): def __init__(self, filelist, fc, samp_rate, psdsize, start, nsamples, max_nsamples, avg=1.0): - gr.top_block.__init__(self) - - self._filelist = filelist - self._center_freq = fc - self._samp_rate = samp_rate - self._psd_size = psdsize - self._start = start - self._max_nsamps = max_nsamples - self._nsigs = len(self._filelist) - self._avg = avg - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples + plot_base.plot_base.__init__(self, filelist, fc, samp_rate, + psdsize, start, nsamples, + max_nsamples, avg) - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start) + self.read_samples = plot_base.read_samples_c + self.dsize = gr.sizeof_gr_complex + self.src_type = gr.vector_source_c self.gui_snk = qtgui.freq_sink_c(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, self._center_freq, self._samp_rate, "GNU Radio PSD Plot", self._nsigs) - n = 0 - self.srcs = list() - for f in filelist: - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - self.srcs.append(gr.vector_source_c(data)) - - # Set default labels based on file names - fname = f.split("/")[-1] - self.gui_snk.set_line_label(n, "{0}".format(fname)) - n += 1 - - self.connect(self.srcs[0], self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs[1:]): - self.connect(s, (self.gui_snk, i+1)) - - self.gui_snk.set_update_time(0); - self.gui_snk.set_fft_average(self._avg) - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - self._nsamps = newnsamps - - for s,f in zip(self.srcs, self._filelist): - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - s.set_data(data) - - self.start() + self.setup() def main(): description = "Plots the PSDs of a list of files. Files are a binary list of complex floats." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-L", "--psd-size", type="int", default=2048, - help="Set the FFT size of the PSD [default=%default]") - parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, - help="Set the center frequency of the signal [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-a", "--average", type="float", default=1.0, - help="Set amount of averaging (smaller=more averaging) [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, - options.center_frequency, options.sample_rate, - options.psd_size, - options.start, nsamples, max_nsamples, - options.average); + tb = psd_plot_c(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, options.nsamples, max_nsamples, + options.average) - main_box = dialog_box(tb, 'GNU Radio PSD Plot') + main_box = plot_base.plot_psd_form(tb, 'GNU Radio PSD Plot') main_box.show() tb.run() diff --git a/gr-qtgui/apps/gr_psd_plot_f b/gr-qtgui/apps/gr_psd_plot_f index 973f7b29d9..1a6fd5b3d9 100755 --- a/gr-qtgui/apps/gr_psd_plot_f +++ b/gr-qtgui/apps/gr_psd_plot_f @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,9 +21,12 @@ # from gnuradio import gr -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_psd_base as plot_base +except ImportError: + import plot_psd_base as plot_base try: from gnuradio import qtgui @@ -33,139 +36,35 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples_and_pad(filename, start, in_size, min_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_float, 0) - data = scipy.fromfile(fhandle, dtype=scipy.float32, count=in_size) - data = data.tolist() - fhandle.close() - - # If we have to, append 0's to create min_size samples of data - if(len(data) < min_size): - data += (min_size - len(data)) * [scipy.float32(0.0)] - - return data - -class my_top_block(gr.top_block): +class psd_plot_f(plot_base.plot_base): def __init__(self, filelist, fc, samp_rate, psdsize, start, - nsamples, max_nsamples, avg=1.0): - gr.top_block.__init__(self) - - self._filelist = filelist - self._center_freq = fc - self._samp_rate = samp_rate - self._psd_size = psdsize - self._start = start - self._max_nsamps = max_nsamples - self._nsigs = len(self._filelist) - self._avg = avg - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) + nsamples, max_nsamples, avg=1.0, auto_scale=True): + 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 = gr.vector_source_f self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, self._center_freq, self._samp_rate, "GNU Radio PSD Plot", self._nsigs) - n = 0 - self.srcs = list() - for f in filelist: - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - self.srcs.append(gr.vector_source_f(data)) - - # Set default labels based on file names - fname = f.split("/")[-1] - self.gui_snk.set_line_label(n, "{0}".format(fname)) - n += 1 - - self.connect(self.srcs[0], self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs[1:]): - self.connect(s, (self.gui_snk, i+1)) - - self.gui_snk.set_update_time(0); - self.gui_snk.set_fft_average(self._avg) - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - self._nsamps = newnsamps - - for s,f in zip(self.srcs, self._filelist): - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - s.set_data(data) - - self.start() + self.setup() def main(): description = "Plots the PSDs of a list of files. Files are a binary list of floats." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-L", "--psd-size", type="int", default=2048, - help="Set the FFT size of the PSD [default=%default]") - parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, - help="Set the center frequency of the signal [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-a", "--average", type="float", default=1.0, - help="Set amount of averaging (smaller=more averaging) [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_float) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, - options.center_frequency, options.sample_rate, - options.psd_size, - options.start, nsamples, max_nsamples, - options.average); + tb = psd_plot_f(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, options.nsamples, max_nsamples, + options.average) - main_box = dialog_box(tb, 'GNU Radio PSD Plot') + main_box = plot_base.plot_psd_form(tb, 'GNU Radio PSD Plot') main_box.show() tb.run() diff --git a/gr-qtgui/apps/gr_psd_plot_i b/gr-qtgui/apps/gr_psd_plot_i index f27011be22..c11a37fbbe 100755 --- a/gr-qtgui/apps/gr_psd_plot_i +++ b/gr-qtgui/apps/gr_psd_plot_i @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,10 +21,12 @@ # from gnuradio import gr -from gnuradio import blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_psd_base as plot_base +except ImportError: + import plot_psd_base as plot_base try: from gnuradio import qtgui @@ -34,144 +36,35 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples_and_pad(filename, start, in_size, min_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_int, 0) - data = scipy.fromfile(fhandle, dtype=scipy.int32, count=in_size) - data = data.tolist() - fhandle.close() - - # If we have to, append 0's to create min_size samples of data - if(len(data) < min_size): - data += (min_size - len(data)) * [scipy.int32(0)] - - return data - -class my_top_block(gr.top_block): +class psd_plot_i(plot_base.plot_base): def __init__(self, filelist, fc, samp_rate, psdsize, start, - nsamples, max_nsamples, scale, avg=1.0): - gr.top_block.__init__(self) - - self._filelist = filelist - self._center_freq = fc - self._samp_rate = samp_rate - self._psd_size = psdsize - self._start = start - self._max_nsamps = max_nsamples - self._scale = scale - self._nsigs = len(self._filelist) - self._avg = avg - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) + nsamples, max_nsamples, avg=1.0, auto_scale=True): + plot_base.plot_base.__init__(self, filelist, fc, samp_rate, + psdsize, start, nsamples, + max_nsamples, avg) + + self.read_samples = plot_base.read_samples_i + self.dsize = gr.sizeof_float + self.src_type = plot_base.source_ints_to_float self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, self._center_freq, self._samp_rate, "GNU Radio PSD Plot", self._nsigs) - n = 0 - self.srcs = list() - self.cnvrt = list() - for f in filelist: - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - self.srcs.append(gr.vector_source_i(data)) - self.cnvrt.append(blocks.int_to_float(1, self._scale)) - - # Set default labels based on file names - fname = f.split("/")[-1] - self.gui_snk.set_line_label(n, "{0}".format(fname)) - n += 1 - - self.connect(self.srcs[0], self.cnvrt[0], self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs[1:]): - self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) - - self.gui_snk.set_update_time(0); - self.gui_snk.set_fft_average(self._avg) - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - self._nsamps = newnsamps - - for s,f in zip(self.srcs, self._filelist): - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - s.set_data(data) - - self.start() + self.setup() def main(): description = "Plots the PSDs of a list of files. Files are a binary list of integers." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-L", "--psd-size", type="int", default=2048, - help="Set the FFT size of the PSD [default=%default]") - parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, - help="Set the center frequency of the signal [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-a", "--average", type="float", default=1.0, - help="Set amount of averaging (smaller=more averaging) [default=%default]") - parser.add_option("-s", "--scale", type="eng_float", default=2**(32-1)-1, - help="Set a scaling factor for the int->float conversion [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_int) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, - options.center_frequency, options.sample_rate, - options.psd_size, - options.start, nsamples, max_nsamples, - options.scale, options.average) + tb = psd_plot_i(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, options.nsamples, max_nsamples, + options.average) - main_box = dialog_box(tb, 'GNU Radio PSD Plot') + main_box = plot_base.plot_psd_form(tb, 'GNU Radio PSD Plot') main_box.show() tb.run() diff --git a/gr-qtgui/apps/gr_psd_plot_s b/gr-qtgui/apps/gr_psd_plot_s index cd2d4a516e..f2da12fc96 100755 --- a/gr-qtgui/apps/gr_psd_plot_s +++ b/gr-qtgui/apps/gr_psd_plot_s @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,9 +21,12 @@ # from gnuradio import gr -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_psd_base as plot_base +except ImportError: + import plot_psd_base as plot_base try: from gnuradio import qtgui @@ -33,144 +36,35 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples_and_pad(filename, start, in_size, min_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_short, 0) - data = scipy.fromfile(fhandle, dtype=scipy.int16, count=in_size) - data = data.tolist() - fhandle.close() - - # If we have to, append 0's to create min_size samples of data - if(len(data) < min_size): - data += (min_size - len(data)) * [scipy.int16(0)] - - return data - -class my_top_block(gr.top_block): +class psd_plot_s(plot_base.plot_base): def __init__(self, filelist, fc, samp_rate, psdsize, start, - nsamples, max_nsamples, scale, avg=1.0): - gr.top_block.__init__(self) - - self._filelist = filelist - self._center_freq = fc - self._samp_rate = samp_rate - self._psd_size = psdsize - self._start = start - self._max_nsamps = max_nsamples - self._scale = scale - self._nsigs = len(self._filelist) - self._avg = avg - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) + nsamples, max_nsamples, avg=1.0, auto_scale=True): + plot_base.plot_base.__init__(self, filelist, fc, samp_rate, + psdsize, start, nsamples, + max_nsamples, avg) + + self.read_samples = plot_base.read_samples_s + self.dsize = gr.sizeof_float + self.src_type = plot_base.source_shorts_to_float self.gui_snk = qtgui.freq_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, self._center_freq, self._samp_rate, "GNU Radio PSD Plot", self._nsigs) - n = 0 - self.srcs = list() - self.cnvrt = list() - for f in filelist: - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - self.srcs.append(gr.vector_source_s(data)) - self.cnvrt.append(blocks.short_to_float(1, self._scale)) - - # Set default labels based on file names - fname = f.split("/")[-1] - self.gui_snk.set_line_label(n, "{0}".format(fname)) - n += 1 - - self.connect(self.srcs[0], self.cnvrt[0], self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs[1:]): - self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) - - self.gui_snk.set_update_time(0); - self.gui_snk.set_fft_average(self._avg) - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - self._nsamps = newnsamps - - for s,f in zip(self.srcs, self._filelist): - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - s.set_data(data) - - self.start() + self.setup() def main(): description = "Plots the PSDs of a list of files. Files are a binary list of shorts." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-L", "--psd-size", type="int", default=2048, - help="Set the FFT size of the PSD [default=%default]") - parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, - help="Set the center frequency of the signal [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-a", "--average", type="float", default=1.0, - help="Set amount of averaging (smaller=more averaging) [default=%default]") - parser.add_option("-s", "--scale", type="eng_float", default=2**(16-1)-1, - help="Set a scaling factor for the short->float conversion [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_short) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, - options.center_frequency, options.sample_rate, - options.psd_size, - options.start, nsamples, max_nsamples, - options.scale, options.average) + tb = psd_plot_s(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, options.nsamples, max_nsamples, + options.average) - main_box = dialog_box(tb, 'GNU Radio PSD Plot') + main_box = plot_base.plot_psd_form(tb, 'GNU Radio PSD Plot') main_box.show() tb.run() @@ -181,4 +75,3 @@ if __name__ == "__main__": main() except KeyboardInterrupt: pass - diff --git a/gr-qtgui/apps/gr_spectrogram_plot_b b/gr-qtgui/apps/gr_spectrogram_plot_b index 649c2834d6..08ddd9efc3 100755 --- a/gr-qtgui/apps/gr_spectrogram_plot_b +++ b/gr-qtgui/apps/gr_spectrogram_plot_b @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,10 +21,12 @@ # from gnuradio import gr -from gnuradio import blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_spectrogram_base as plot_base +except ImportError: + import plot_spectrogram_base as plot_base try: from gnuradio import qtgui @@ -34,141 +36,35 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples_and_pad(filename, start, in_size, min_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_char, 0) - data = scipy.fromfile(fhandle, dtype=scipy.uint8, count=in_size) - data = data.tolist() - fhandle.close() - - # If we have to, append 0's to create min_size samples of data - if(len(data) < min_size): - data += (min_size - len(data)) * [scipy.uint8(0)] - - return data - -class my_top_block(gr.top_block): +class spectrogram_plot_b(plot_base.plot_base): def __init__(self, filelist, fc, samp_rate, psdsize, start, - nsamples, max_nsamples, scale, avg=1.0): - gr.top_block.__init__(self) - - self._filelist = filelist - self._center_freq = fc - self._samp_rate = samp_rate - self._psd_size = psdsize - self._start = start - self._max_nsamps = max_nsamples - self._scale = scale - self._nsigs = len(self._filelist) - self._avg = avg - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) - self.add = blocks.add_ff() + 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, gr.firdes.WIN_BLACKMAN_hARRIS, self._center_freq, self._samp_rate, - "GNU Radio Spectrogram Plot") - n = 0 - self.srcs = list() - self.cnvrt = list() - for f in filelist: - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - self.srcs.append(gr.vector_source_b(data)) - self.cnvrt.append(blocks.char_to_float(1, self._scale)) - n += 1 - - self.connect(self.add, self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs): - self.connect(s, self.cnvrt[i], (self.add, i)) - - self.gui_snk.set_update_time(0); - self.gui_snk.set_fft_average(self._avg) - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - self._nsamps = newnsamps - - for s,f in zip(self.srcs, self._filelist): - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - s.set_data(data) - - self.start() + "GNU Radio Spectrogram Plot", self._nsigs) + self.setup() def main(): - description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of chars/bytes." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-L", "--psd-size", type="int", default=2048, - help="Set the FFT size of the PSD [default=%default]") - parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, - help="Set the center frequency of the signal [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-a", "--average", type="float", default=1.0, - help="Set amount of averaging (smaller=more averaging) [default=%default]") - parser.add_option("-s", "--scale", type="eng_float", default=2**(8-1)-1, - help="Set a scaling factor for the char->float conversion [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of chars." + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_char) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, - options.center_frequency, options.sample_rate, - options.psd_size, - options.start, nsamples, max_nsamples, - options.scale, options.average); + tb = spectrogram_plot_b(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, options.nsamples, max_nsamples, + options.average); - main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot') + main_box = plot_base.plot_spectrogram_form(tb, 'GNU Radio Time Plot') main_box.show() tb.run() diff --git a/gr-qtgui/apps/gr_spectrogram_plot_c b/gr-qtgui/apps/gr_spectrogram_plot_c index 160072f27c..230170c1ee 100755 --- a/gr-qtgui/apps/gr_spectrogram_plot_c +++ b/gr-qtgui/apps/gr_spectrogram_plot_c @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,10 +21,12 @@ # from gnuradio import gr -from gnuradio import blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_spectrogram_base as plot_base +except ImportError: + import plot_spectrogram_base as plot_base try: from gnuradio import qtgui @@ -34,136 +36,35 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples_and_pad(filename, start, in_size, min_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_gr_complex, 0) - data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size) - data = data.tolist() - fhandle.close() - - # If we have to, append 0's to create min_size samples of data - if(len(data) < min_size): - data += (min_size - len(data)) * [complex(0,0)] - - return data - -class my_top_block(gr.top_block): +class spectrogram_plot_c(plot_base.plot_base): def __init__(self, filelist, fc, samp_rate, psdsize, start, nsamples, max_nsamples, avg=1.0): - gr.top_block.__init__(self) - - self._filelist = filelist - self._center_freq = fc - self._samp_rate = samp_rate - self._psd_size = psdsize - self._start = start - self._max_nsamps = max_nsamples - self._nsigs = len(self._filelist) - self._avg = avg + plot_base.plot_base.__init__(self, filelist, fc, samp_rate, + psdsize, start, nsamples, + max_nsamples, avg) - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start) - self.add = blocks.add_cc() + self.read_samples = plot_base.read_samples_c + self.dsize = gr.sizeof_gr_complex + self.src_type = gr.vector_source_c self.gui_snk = qtgui.waterfall_sink_c(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, self._center_freq, self._samp_rate, - "GNU Radio Spectrogram Plot") - n = 0 - self.srcs = list() - for f in filelist: - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - self.srcs.append(gr.vector_source_c(data)) - n += 1 - - self.connect(self.add, self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs): - self.connect(s, (self.add, i)) - - self.gui_snk.set_update_time(0); - self.gui_snk.set_fft_average(self._avg) - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - self._nsamps = newnsamps - - for s,f in zip(self.srcs, self._filelist): - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - s.set_data(data) - - self.start() + "GNU Radio Spectrogram Plot", self._nsigs) + self.setup() def main(): description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of complex floats." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-L", "--psd-size", type="int", default=2048, - help="Set the FFT size of the PSD [default=%default]") - parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, - help="Set the center frequency of the signal [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-a", "--average", type="float", default=1.0, - help="Set amount of averaging (smaller=more averaging) [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, - options.center_frequency, options.sample_rate, - options.psd_size, - options.start, nsamples, max_nsamples, - options.average); + tb = spectrogram_plot_c(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, options.nsamples, max_nsamples, + options.average); - main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot') + main_box = plot_base.plot_spectrogram_form(tb, 'GNU Radio Spectrogram Plot') main_box.show() tb.run() diff --git a/gr-qtgui/apps/gr_spectrogram_plot_f b/gr-qtgui/apps/gr_spectrogram_plot_f index 3e799395b3..a26f3257f1 100755 --- a/gr-qtgui/apps/gr_spectrogram_plot_f +++ b/gr-qtgui/apps/gr_spectrogram_plot_f @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,10 +21,12 @@ # from gnuradio import gr -from gnuradio import blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_spectrogram_base as plot_base +except ImportError: + import plot_spectrogram_base as plot_base try: from gnuradio import qtgui @@ -34,136 +36,35 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples_and_pad(filename, start, in_size, min_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_float, 0) - data = scipy.fromfile(fhandle, dtype=scipy.float32, count=in_size) - data = data.tolist() - fhandle.close() - - # If we have to, append 0's to create min_size samples of data - if(len(data) < min_size): - data += (min_size - len(data)) * [scipy.float32(0.0)] - - return data - -class my_top_block(gr.top_block): +class spectrogram_plot_f(plot_base.plot_base): def __init__(self, filelist, fc, samp_rate, psdsize, start, nsamples, max_nsamples, avg=1.0): - gr.top_block.__init__(self) - - self._filelist = filelist - self._center_freq = fc - self._samp_rate = samp_rate - self._psd_size = psdsize - self._start = start - self._max_nsamps = max_nsamples - self._nsigs = len(self._filelist) - self._avg = avg + plot_base.plot_base.__init__(self, filelist, fc, samp_rate, + psdsize, start, nsamples, + max_nsamples, avg) - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) - self.add = blocks.add_ff() + self.read_samples = plot_base.read_samples_f + self.dsize = gr.sizeof_float + self.src_type = gr.vector_source_f self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, self._center_freq, self._samp_rate, - "GNU Radio Spectrogram Plot") - n = 0 - self.srcs = list() - for f in filelist: - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - self.srcs.append(gr.vector_source_f(data)) - n += 1 - - self.connect(self.add, self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs): - self.connect(s, (self.add, i)) - - self.gui_snk.set_update_time(0); - self.gui_snk.set_fft_average(self._avg) - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - self._nsamps = newnsamps - - for s,f in zip(self.srcs, self._filelist): - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - s.set_data(data) - - self.start() + "GNU Radio Spectrogram Plot", self._nsigs) + self.setup() def main(): description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of floats." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-L", "--psd-size", type="int", default=2048, - help="Set the FFT size of the PSD [default=%default]") - parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, - help="Set the center frequency of the signal [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-a", "--average", type="float", default=1.0, - help="Set amount of averaging (smaller=more averaging) [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_float) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, - options.center_frequency, options.sample_rate, - options.psd_size, - options.start, nsamples, max_nsamples, - options.average); + tb = spectrogram_plot_f(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, options.nsamples, max_nsamples, + options.average); - main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot') + main_box = plot_base.plot_spectrogram_form(tb, 'GNU Radio Time Plot') main_box.show() tb.run() diff --git a/gr-qtgui/apps/gr_spectrogram_plot_i b/gr-qtgui/apps/gr_spectrogram_plot_i index 444f4115ad..823aedfcbc 100755 --- a/gr-qtgui/apps/gr_spectrogram_plot_i +++ b/gr-qtgui/apps/gr_spectrogram_plot_i @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,10 +21,12 @@ # from gnuradio import gr -from gnuradio import blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_spectrogram_base as plot_base +except ImportError: + import plot_spectrogram_base as plot_base try: from gnuradio import qtgui @@ -34,141 +36,35 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples_and_pad(filename, start, in_size, min_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_int, 0) - data = scipy.fromfile(fhandle, dtype=scipy.int32, count=in_size) - data = data.tolist() - fhandle.close() - - # If we have to, append 0's to create min_size samples of data - if(len(data) < min_size): - data += (min_size - len(data)) * [scipy.int32(0)] - - return data - -class my_top_block(gr.top_block): +class spectrogram_plot_i(plot_base.plot_base): def __init__(self, filelist, fc, samp_rate, psdsize, start, - nsamples, max_nsamples, scale, avg=1.0): - gr.top_block.__init__(self) - - self._filelist = filelist - self._center_freq = fc - self._samp_rate = samp_rate - self._psd_size = psdsize - self._start = start - self._max_nsamps = max_nsamples - self._scale = scale - self._nsigs = len(self._filelist) - self._avg = avg - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) - self.add = blocks.add_ff() + 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_i + self.dsize = gr.sizeof_float + self.src_type = plot_base.source_ints_to_float self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, self._center_freq, self._samp_rate, - "GNU Radio Spectrogram Plot") - n = 0 - self.srcs = list() - self.cnvrt = list() - for f in filelist: - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - self.srcs.append(gr.vector_source_i(data)) - self.cnvrt.append(blocks.int_to_float(1, self._scale)) - n += 1 - - self.connect(self.add, self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs): - self.connect(s, self.cnvrt[i], (self.add, i)) - - self.gui_snk.set_update_time(0); - self.gui_snk.set_fft_average(self._avg) - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - self._nsamps = newnsamps - - for s,f in zip(self.srcs, self._filelist): - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - s.set_data(data) - - self.start() + "GNU Radio Spectrogram Plot", self._nsigs) + self.setup() def main(): - description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of integers." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-L", "--psd-size", type="int", default=2048, - help="Set the FFT size of the PSD [default=%default]") - parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, - help="Set the center frequency of the signal [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-a", "--average", type="float", default=1.0, - help="Set amount of averaging (smaller=more averaging) [default=%default]") - parser.add_option("-s", "--scale", type="eng_float", default=2**(32-1)-1, - help="Set a scaling factor for the int->float conversion [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of ints." + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_int) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, - options.center_frequency, options.sample_rate, - options.psd_size, - options.start, nsamples, max_nsamples, - options.scale, options.average); + tb = spectrogram_plot_i(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, options.nsamples, max_nsamples, + options.average); - main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot') + main_box = plot_base.plot_spectrogram_form(tb, 'GNU Radio Time Plot') main_box.show() tb.run() diff --git a/gr-qtgui/apps/gr_spectrogram_plot_s b/gr-qtgui/apps/gr_spectrogram_plot_s index bb3573ba2c..501d1c425c 100755 --- a/gr-qtgui/apps/gr_spectrogram_plot_s +++ b/gr-qtgui/apps/gr_spectrogram_plot_s @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,10 +21,12 @@ # from gnuradio import gr -from gnuradio import blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_spectrogram_base as plot_base +except ImportError: + import plot_spectrogram_base as plot_base try: from gnuradio import qtgui @@ -34,141 +36,35 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples_and_pad(filename, start, in_size, min_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_short, 0) - data = scipy.fromfile(fhandle, dtype=scipy.int16, count=in_size) - data = data.tolist() - fhandle.close() - - # If we have to, append 0's to create min_size samples of data - if(len(data) < min_size): - data += (min_size - len(data)) * [scipy.int16(0)] - - return data - -class my_top_block(gr.top_block): +class spectrogram_plot_s(plot_base.plot_base): def __init__(self, filelist, fc, samp_rate, psdsize, start, - nsamples, max_nsamples, scale, avg=1.0): - gr.top_block.__init__(self) - - self._filelist = filelist - self._center_freq = fc - self._samp_rate = samp_rate - self._psd_size = psdsize - self._start = start - self._max_nsamps = max_nsamples - self._scale = scale - self._nsigs = len(self._filelist) - self._avg = avg - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) - self.add = blocks.add_ff() + 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_s + self.dsize = gr.sizeof_float + self.src_type = plot_base.source_shorts_to_float self.gui_snk = qtgui.waterfall_sink_f(self._psd_size, gr.firdes.WIN_BLACKMAN_hARRIS, self._center_freq, self._samp_rate, - "GNU Radio Spectrogram Plot") - n = 0 - self.srcs = list() - self.cnvrt = list() - for f in filelist: - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - self.srcs.append(gr.vector_source_s(data)) - self.cnvrt.append(blocks.short_to_float(1, self._scale)) - n += 1 - - self.connect(self.add, self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs): - self.connect(s, self.cnvrt[i], (self.add, i)) - - self.gui_snk.set_update_time(0); - self.gui_snk.set_fft_average(self._avg) - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - self._nsamps = newnsamps - - for s,f in zip(self.srcs, self._filelist): - data = read_samples_and_pad(f, self._start, - self._nsamps, self._psd_size) - s.set_data(data) - - self.start() + "GNU Radio Spectrogram Plot", self._nsigs) + self.setup() def main(): description = "Plots the spectrogram (waterfall) of a list of files. Files are a binary list of shorts." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-L", "--psd-size", type="int", default=2048, - help="Set the FFT size of the PSD [default=%default]") - parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, - help="Set the center frequency of the signal [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-a", "--average", type="float", default=1.0, - help="Set amount of averaging (smaller=more averaging) [default=%default]") - parser.add_option("-s", "--scale", type="eng_float", default=2**(16-1)-1, - help="Set a scaling factor for the short->float conversion [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_short) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, - options.center_frequency, options.sample_rate, - options.psd_size, - options.start, nsamples, max_nsamples, - options.scale, options.average); + tb = spectrogram_plot_s(filelist, + options.center_frequency, options.sample_rate, + options.psd_size, + options.start, options.nsamples, max_nsamples, + options.average); - main_box = dialog_box(tb, 'GNU Radio Spectrogram Plot') + main_box = plot_base.plot_spectrogram_form(tb, 'GNU Radio Time Plot') main_box.show() tb.run() diff --git a/gr-qtgui/apps/gr_time_plot_b b/gr-qtgui/apps/gr_time_plot_b index 4b63c3fd11..0d5ce5e501 100755 --- a/gr-qtgui/apps/gr_time_plot_b +++ b/gr-qtgui/apps/gr_time_plot_b @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,10 +21,12 @@ # from gnuradio import gr -from gnuradio import blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_tiome_base as plot_base +except ImportError: + import plot_time_base as plot_base try: from gnuradio import qtgui @@ -34,132 +36,32 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples(filename, start, in_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_char, 0) - data = scipy.fromfile(fhandle, dtype=scipy.uint8, count=in_size) - data = data.tolist() - fhandle.close() - - if(len(data) < in_size): - print "Warning: read in {0} samples but asked for {1} samples.".format( - len(data), in_size) - - return data - -class gr_time_plot_f(gr.top_block): - def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples, scale): - gr.top_block.__init__(self) - - self._filelist = filelist - self._samp_rate = samp_rate - self._start = start - self._max_nsamps = max_nsamples - self._scale = scale - self._nsigs = len(self._filelist) - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) +class plot_time_b(plot_base.plot_base): + def __init__(self, filelist, samp_rate, + start, nsamples, max_nsamples, + auto_scale): + plot_base.plot_base.__init__(self, filelist, samp_rate, + start, nsamples, max_nsamples, + auto_scale) + self.read_samples = plot_base.read_samples_b + self.dsize = gr.sizeof_float # already converted + self.src_type = plot_base.source_chars_to_float self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate, "GNU Radio Time Plot", self._nsigs) - n = 0 - self.srcs = list() - self.cnvrt = list() - for f in filelist: - data = read_samples(f, self._start, self._nsamps) - self.srcs.append(gr.vector_source_b(data)) - self.cnvrt.append(blocks.char_to_float(1, self._scale)) - - # Set default labels based on file names - fname = f.split("/")[-1] - self.gui_snk.set_line_label(n, "{0}".format(fname)) - n += 1 - - self.connect(self.srcs[0], self.cnvrt[0], self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs[1:]): - self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) - - self.gui_snk.set_update_time(0); - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - - for s,f in zip(self.srcs, self._filelist): - data = read_samples(f, self._start, newnsamps) - s.set_data(data) - if(len(data) < newnsamps): - newnsamps = len(data) - - self._nsamps = newnsamps - self.gui_snk.set_nsamps(self._nsamps) - - self.start() + self.setup() def main(): - description = "Plots a list of files on a scope plot. Files are a binary list of chars/bytes." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-s", "--scale", type="eng_float", default=2**(8-1)-1, - help="Set a scaling factor for the char->float conversion [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + description = "Plots a list of files on a scope plot. Files are a binary list of chars." + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_char) - max_nsamples = min(filesizes) - - tb = gr_time_plot_f(filelist, options.sample_rate, - options.start, nsamples, max_nsamples, - options.scale); + tb = plot_time_b(filelist, options.sample_rate, + options.start, options.nsamples, max_nsamples, + not options.no_auto_scale) - main_box = dialog_box(tb, 'GNU Radio Time Plot') + main_box = plot_base.plot_time_form(tb, 'GNU Radio Time Plot') main_box.show() tb.run() @@ -170,4 +72,3 @@ if __name__ == "__main__": main() except KeyboardInterrupt: pass - diff --git a/gr-qtgui/apps/gr_time_plot_c b/gr-qtgui/apps/gr_time_plot_c index 2f27623e54..4450a2074c 100755 --- a/gr-qtgui/apps/gr_time_plot_c +++ b/gr-qtgui/apps/gr_time_plot_c @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,9 +21,12 @@ # from gnuradio import gr -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_time_base as plot_base +except ImportError: + import plot_time_base as plot_base try: from gnuradio import qtgui @@ -33,127 +36,33 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples(filename, start, in_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_gr_complex, 0) - data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size) - data = data.tolist() - fhandle.close() - - if(len(data) < in_size): - print "Warning: read in {0} samples but asked for {1} samples.".format( - len(data), in_size) - - return data - -class my_top_block(gr.top_block): - def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples): - gr.top_block.__init__(self) - - self._filelist = filelist - self._samp_rate = samp_rate - self._start = start - self._max_nsamps = max_nsamples - self._nsigs = len(self._filelist) - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start) +class plot_time_c(plot_base.plot_base): + def __init__(self, filelist, samp_rate, + start, nsamples, max_nsamples, + auto_scale): + plot_base.plot_base.__init__(self, filelist, samp_rate, + start, nsamples, max_nsamples, + auto_scale) + self.read_samples = plot_base.read_samples_c + self.dsize = gr.sizeof_gr_complex + self.src_type = gr.vector_source_c self.gui_snk = qtgui.time_sink_c(self._nsamps, self._samp_rate, "GNU Radio Time Plot", self._nsigs) - n = 0 - self.srcs = list() - for f in filelist: - data = read_samples(f, self._start, self._nsamps) - self.srcs.append(gr.vector_source_c(data)) - - # Set default labels based on file names - fname = f.split("/")[-1] - self.gui_snk.set_line_label(n, "Re{{{0}}}".format(fname)) - self.gui_snk.set_line_label(n+1, "Im{{{0}}}".format(fname)) - n += 2 - - self.connect(self.srcs[0], self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs[1:]): - self.connect(s, (self.gui_snk, i+1)) - - self.gui_snk.set_update_time(0); - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - - for s,f in zip(self.srcs, self._filelist): - data = read_samples(f, self._start, newnsamps) - s.set_data(data) - if(len(data) < newnsamps): - newnsamps = len(data) - - self._nsamps = newnsamps - self.gui_snk.set_nsamps(self._nsamps) - - self.start() + self._nsigs *= 2 # complex plots have real/imag + self.setup() def main(): description = "Plots a list of files on a scope plot. Files are a binary list of complex floats." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex) - max_nsamples = min(filesizes) - - tb = my_top_block(filelist, options.sample_rate, - options.start, nsamples, max_nsamples); + tb = plot_time_c(filelist, options.sample_rate, + options.start, options.nsamples, max_nsamples, + not options.no_auto_scale) - main_box = dialog_box(tb, 'GNU Radio Time Plot') + main_box = plot_base.plot_time_form(tb, 'GNU Radio Time Plot') main_box.show() tb.run() diff --git a/gr-qtgui/apps/gr_time_plot_f b/gr-qtgui/apps/gr_time_plot_f index e4f4b8d436..4cac6e9323 100755 --- a/gr-qtgui/apps/gr_time_plot_f +++ b/gr-qtgui/apps/gr_time_plot_f @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,9 +21,12 @@ # from gnuradio import gr -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_time_base as plot_base +except ImportError: + import plot_time_base as plot_base try: from gnuradio import qtgui @@ -33,126 +36,32 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples(filename, start, in_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_float, 0) - data = scipy.fromfile(fhandle, dtype=scipy.float32, count=in_size) - data = data.tolist() - fhandle.close() - - if(len(data) < in_size): - print "Warning: read in {0} samples but asked for {1} samples.".format( - len(data), in_size) - - return data - -class gr_time_plot_f(gr.top_block): - def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples): - gr.top_block.__init__(self) - - self._filelist = filelist - self._samp_rate = samp_rate - self._start = start - self._max_nsamps = max_nsamples - self._nsigs = len(self._filelist) - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) +class plot_time_f(plot_base.plot_base): + def __init__(self, filelist, samp_rate, + start, nsamples, max_nsamples, + auto_scale): + plot_base.plot_base.__init__(self, filelist, samp_rate, + start, nsamples, max_nsamples, + auto_scale) + self.read_samples = plot_base.read_samples_f + self.dsize = gr.sizeof_float + self.src_type = gr.vector_source_f self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate, "GNU Radio Time Plot", self._nsigs) - n = 0 - self.srcs = list() - for f in filelist: - data = read_samples(f, self._start, self._nsamps) - self.srcs.append(gr.vector_source_f(data)) - - # Set default labels based on file names - fname = f.split("/")[-1] - self.gui_snk.set_line_label(n, "{0}".format(fname)) - n += 1 - - self.connect(self.srcs[0], self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs[1:]): - self.connect(s, (self.gui_snk, i+1)) - - self.gui_snk.set_update_time(0); - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - - for s,f in zip(self.srcs, self._filelist): - data = read_samples(f, self._start, newnsamps) - s.set_data(data) - if(len(data) < newnsamps): - newnsamps = len(data) - - self._nsamps = newnsamps - self.gui_snk.set_nsamps(self._nsamps) - - self.start() + self.setup() def main(): description = "Plots a list of files on a scope plot. Files are a binary list of floats." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_float) - max_nsamples = min(filesizes) - - tb = gr_time_plot_f(filelist, options.sample_rate, - options.start, nsamples, max_nsamples); + tb = plot_time_f(filelist, options.sample_rate, + options.start, options.nsamples, max_nsamples, + not options.no_auto_scale) - main_box = dialog_box(tb, 'GNU Radio Time Plot') + main_box = plot_base.plot_time_form(tb, 'GNU Radio Time Plot') main_box.show() tb.run() @@ -163,4 +72,3 @@ if __name__ == "__main__": main() except KeyboardInterrupt: pass - diff --git a/gr-qtgui/apps/gr_time_plot_i b/gr-qtgui/apps/gr_time_plot_i index 4895090a10..04229de0cd 100755 --- a/gr-qtgui/apps/gr_time_plot_i +++ b/gr-qtgui/apps/gr_time_plot_i @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,10 +21,12 @@ # from gnuradio import gr -from gnuradio import blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_time_base as plot_base +except ImportError: + import plot_time_base as plot_base try: from gnuradio import qtgui @@ -34,132 +36,32 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples(filename, start, in_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_int, 0) - data = scipy.fromfile(fhandle, dtype=scipy.int32, count=in_size) - data = data.tolist() - fhandle.close() - - if(len(data) < in_size): - print "Warning: read in {0} samples but asked for {1} samples.".format( - len(data), in_size) - - return data - -class gr_time_plot_f(gr.top_block): - def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples, scale): - gr.top_block.__init__(self) - - self._filelist = filelist - self._samp_rate = samp_rate - self._start = start - self._max_nsamps = max_nsamples - self._scale = scale - self._nsigs = len(self._filelist) - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) +class plot_time_i(plot_base.plot_base): + def __init__(self, filelist, samp_rate, + start, nsamples, max_nsamples, + auto_scale): + plot_base.plot_base.__init__(self, filelist, samp_rate, + start, nsamples, max_nsamples, + auto_scale) + self.read_samples = plot_base.read_samples_i + self.dsize = gr.sizeof_float # already converted + self.src_type = plot_base.source_ints_to_float self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate, "GNU Radio Time Plot", self._nsigs) - n = 0 - self.srcs = list() - self.cnvrt = list() - for f in filelist: - data = read_samples(f, self._start, self._nsamps) - self.srcs.append(gr.vector_source_i(data)) - self.cnvrt.append(blocks.int_to_float(1, self._scale)) - - # Set default labels based on file names - fname = f.split("/")[-1] - self.gui_snk.set_line_label(n, "{0}".format(fname)) - n += 1 - - self.connect(self.srcs[0], self.cnvrt[0], self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs[1:]): - self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) - - self.gui_snk.set_update_time(0); - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - - for s,f in zip(self.srcs, self._filelist): - data = read_samples(f, self._start, newnsamps) - s.set_data(data) - if(len(data) < newnsamps): - newnsamps = len(data) - - self._nsamps = newnsamps - self.gui_snk.set_nsamps(self._nsamps) - - self.start() + self.setup() def main(): description = "Plots a list of files on a scope plot. Files are a binary list of integers." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-s", "--scale", type="eng_float", default=2**(32-1)-1, - help="Set a scaling factor for the int->float conversion [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_int) - max_nsamples = min(filesizes) + tb = plot_time_i(filelist, options.sample_rate, + options.start, options.nsamples, max_nsamples, + not options.no_auto_scale) - tb = gr_time_plot_f(filelist, options.sample_rate, - options.start, nsamples, max_nsamples, - options.scale); - - main_box = dialog_box(tb, 'GNU Radio Time Plot') + main_box = plot_base.plot_time_form(tb, 'GNU Radio Time Plot') main_box.show() tb.run() @@ -170,4 +72,3 @@ if __name__ == "__main__": main() except KeyboardInterrupt: pass - diff --git a/gr-qtgui/apps/gr_time_plot_s b/gr-qtgui/apps/gr_time_plot_s index 581190e6df..cc4a8a7812 100755 --- a/gr-qtgui/apps/gr_time_plot_s +++ b/gr-qtgui/apps/gr_time_plot_s @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,9 +21,12 @@ # from gnuradio import gr -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import os, sys +import scipy + +try: + import gnuradio.qtgui.plot_time_base as plot_base +except ImportError: + import plot_time_base as plot_base try: from gnuradio import qtgui @@ -33,132 +36,32 @@ except ImportError: print "Error: Program requires PyQt4 and gr-qtgui." sys.exit(1) -try: - import scipy -except ImportError: - print "Error: Scipy required (www.scipy.org)." - sys.exit(1) - -try: - from gnuradio.qtgui.plot_form import * -except ImportError: - from plot_form import * - -def read_samples(filename, start, in_size): - # Read in_size number of samples from file - fhandle = open(filename, 'r') - fhandle.seek(start*gr.sizeof_short, 0) - data = scipy.fromfile(fhandle, dtype=scipy.int16, count=in_size) - data = data.tolist() - fhandle.close() - - if(len(data) < in_size): - print "Warning: read in {0} samples but asked for {1} samples.".format( - len(data), in_size) - - return data - -class gr_time_plot_f(gr.top_block): - def __init__(self, filelist, samp_rate, start, nsamples, max_nsamples, scale): - gr.top_block.__init__(self) - - self._filelist = filelist - self._samp_rate = samp_rate - self._start = start - self._max_nsamps = max_nsamples - self._scale = scale - self._nsigs = len(self._filelist) - - if(nsamples is None): - self._nsamps = max_nsamples - else: - self._nsamps = nsamples - - self.qapp = QtGui.QApplication(sys.argv) - - self.skip = gr.skiphead(gr.sizeof_float, self._start) +class plot_time_s(plot_base.plot_base): + def __init__(self, filelist, samp_rate, + start, nsamples, max_nsamples, + auto_scale): + plot_base.plot_base.__init__(self, filelist, samp_rate, + start, nsamples, max_nsamples, + auto_scale) + self.read_samples = plot_base.read_samples_s + self.dsize = gr.sizeof_float # already converted + self.src_type = plot_base.source_shorts_to_float self.gui_snk = qtgui.time_sink_f(self._nsamps, self._samp_rate, "GNU Radio Time Plot", self._nsigs) - n = 0 - self.srcs = list() - self.cnvrt = list() - for f in filelist: - data = read_samples(f, self._start, self._nsamps) - self.srcs.append(gr.vector_source_s(data)) - self.cnvrt.append(blocks.short_to_float(1, self._scale)) - - # Set default labels based on file names - fname = f.split("/")[-1] - self.gui_snk.set_line_label(n, "{0}".format(fname)) - n += 1 - - self.connect(self.srcs[0], self.cnvrt[0], self.skip) - self.connect(self.skip, (self.gui_snk, 0)) - - for i,s in enumerate(self.srcs[1:]): - self.connect(s, self.cnvrt[i], (self.gui_snk, i+1)) - - self.gui_snk.set_update_time(0); - - # Get Python Qt references - pyQt = self.gui_snk.pyqwidget() - self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) - - def get_gui(self): - return self.pyWin - - def reset(self, newstart, newnsamps): - self.stop() - self.wait() - - self._start = newstart - - for s,f in zip(self.srcs, self._filelist): - data = read_samples(f, self._start, newnsamps) - s.set_data(data) - if(len(data) < newnsamps): - newnsamps = len(data) - - self._nsamps = newnsamps - self.gui_snk.set_nsamps(self._nsamps) - - self.start() + self.setup() def main(): description = "Plots a list of files on a scope plot. Files are a binary list of shorts." - parser = OptionParser(option_class=eng_option, description=description, - conflict_handler="resolve") - parser.add_option("-N", "--nsamples", type="int", default=None, - help="Set the number of samples to display [default=prints entire file]") - parser.add_option("-S", "--start", type="int", default=0, - help="Starting sample number [default=%default]") - parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, - help="Set the sample rate of the signal [default=%default]") - parser.add_option("-s", "--scale", type="eng_float", default=2**(16-1)-1, - help="Set a scaling factor for the short->float conversion [default=%default]") - (options, args) = parser.parse_args() - - if(len(args) < 1): - parser.print_help() - sys.exit(0) + (options, args) = plot_base.setup_options(description) filelist = list(args) + max_nsamples = plot_base.find_max_nsamples(filelist) - nsamples = options.nsamples - - # Find the smallest number of samples in all files and use that as - # a maximum value possible. - filesizes = [] - for f in filelist: - if(os.path.exists(f)): - filesizes.append(os.path.getsize(f) / gr.sizeof_short) - max_nsamples = min(filesizes) - - tb = gr_time_plot_f(filelist, options.sample_rate, - options.start, nsamples, max_nsamples, - options.scale); + tb = plot_time_s(filelist, options.sample_rate, + options.start, options.nsamples, max_nsamples, + not options.no_auto_scale) - main_box = dialog_box(tb, 'GNU Radio Time Plot') + main_box = plot_base.plot_time_form(tb, 'GNU Radio Time Plot') main_box.show() tb.run() @@ -169,4 +72,3 @@ if __name__ == "__main__": main() except KeyboardInterrupt: pass - diff --git a/gr-qtgui/apps/plot_base.py b/gr-qtgui/apps/plot_base.py new file mode 100644 index 0000000000..5a784b2dfd --- /dev/null +++ b/gr-qtgui/apps/plot_base.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python +# +# Copyright 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, blocks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +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) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_constellation_form import * + from gnuradio.qtgui.plot_psd_form import * + from gnuradio.qtgui.plot_spectrogram_form import * + from gnuradio.qtgui.plot_time_form import * +except ImportError: + from plot_constellation_form import * + from plot_psd_form import * + from plot_spectrogram_form import * + from plot_time_form import * + +def read_samples(filename, start, in_size, min_size, dtype, dtype_size): + # Read in_size number of samples from file + fhandle = open(filename, 'r') + fhandle.seek(start*dtype_size, 0) + data = scipy.fromfile(fhandle, dtype=dtype, count=in_size) + data_min = 1.1*data.min() + data_max = 1.1*data.max() + data = data.tolist() + fhandle.close() + + if(min_size > 0): + if(len(data) < in_size): + print "Warning: read in {0} samples but asked for {1} samples.".format( + len(data), in_size) + else: + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [dtype(0)] + + + return data, data_min, data_max + +def read_samples_f(filename, start, in_size, min_size=0): + return read_samples(filename, start, in_size, min_size, + scipy.float32, gr.sizeof_float) + +def read_samples_i(filename, start, in_size, min_size=0): + return read_samples(filename, start, in_size, min_size, + scipy.int32, gr.sizeof_int) + +def read_samples_s(filename, start, in_size, min_size=0): + return read_samples(filename, start, in_size, min_size, + scipy.int16, gr.sizeof_short) + +def read_samples_b(filename, start, in_size, min_size=0): + return read_samples(filename, start, in_size, min_size, + scipy.uint8, gr.sizeof_char) + +def read_samples_c(filename, start, in_size, min_size=0): + # Complex samples are handled differently + fhandle = open(filename, 'r') + fhandle.seek(start*gr.sizeof_gr_complex, 0) + data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size) + data_min = 1.1*float(min(data.real.min(), data.imag.min())) + data_max = 1.1*float(max(data.real.max(), data.imag.max())) + data = data.tolist() + fhandle.close() + + if(min_size > 0): + if(len(data) < in_size): + print "Warning: read in {0} samples but asked for {1} samples.".format( + len(data), in_size) + else: + # If we have to, append 0's to create min_size samples of data + if(len(data) < min_size): + data += (min_size - len(data)) * [complex(0,0)] + + return data, data_min, data_max + +class source_ints_to_float(gr.hier_block2): + def __init__(self, data): + gr.hier_block2.__init__(self, "ints_to_floats", + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, gr.sizeof_float)) + self.src = gr.vector_source_i(data) + self.cvt = blocks.int_to_float() + self.connect(self.src, self.cvt, self) + + def set_data(self, data): + self.src.set_data(data) + +class source_shorts_to_float(gr.hier_block2): + def __init__(self, data): + gr.hier_block2.__init__(self, "shorts_to_floats", + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, gr.sizeof_float)) + self.src = gr.vector_source_s(data) + self.cvt = blocks.short_to_float() + self.connect(self.src, self.cvt, self) + + def set_data(self, data): + self.src.set_data(data) + +class source_chars_to_float(gr.hier_block2): + def __init__(self, data): + gr.hier_block2.__init__(self, "chars_to_floats", + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, gr.sizeof_float)) + self.src = gr.vector_source_b(data) + self.cvt = blocks.char_to_float() + self.connect(self.src, self.cvt, self) + + def set_data(self, data): + self.src.set_data(data) + +def find_max_nsamples(filelist): + # Find the smallest number of samples in all files and use that as + # a maximum value possible. + filesizes = [] + for f in filelist: + if(os.path.exists(f)): + filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex) + max_nsamples = min(filesizes) + return max_nsamples diff --git a/gr-qtgui/apps/plot_constellation_form.py b/gr-qtgui/apps/plot_constellation_form.py new file mode 100644 index 0000000000..6f67000ea2 --- /dev/null +++ b/gr-qtgui/apps/plot_constellation_form.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# Copyright 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. +# + +import sys +from gnuradio import filter + +try: + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_from import plot_form +except ImportError: + from plot_form import plot_form + +class plot_constellation_form(plot_form): + def __init__(self, top_block, title=''): + plot_form.__init__(self, top_block, title) + + self.right_col_layout = QtGui.QVBoxLayout() + self.right_col_form = QtGui.QFormLayout() + self.right_col_layout.addLayout(self.right_col_form) + self.layout.addLayout(self.right_col_layout, 1,4,1,1) + + self.auto_scale = QtGui.QCheckBox("Auto Scale", self) + if(self.top_block._auto_scale): + self.auto_scale.setChecked(self.top_block._auto_scale) + self.connect(self.auto_scale, QtCore.SIGNAL("stateChanged(int)"), + self.set_auto_scale) + self.right_col_layout.addWidget(self.auto_scale) + + self.add_line_control(self.right_col_layout) + + def set_auto_scale(self, state): + if(state): + self.top_block.auto_scale(True) + else: + self.top_block.auto_scale(False) + + def update_samp_rate(self): + pass + diff --git a/gr-qtgui/apps/plot_form.py b/gr-qtgui/apps/plot_form.py index f6841811a8..5b034407a8 100644 --- a/gr-qtgui/apps/plot_form.py +++ b/gr-qtgui/apps/plot_form.py @@ -27,42 +27,22 @@ except ImportError: print "Error: Program requires PyQt4." sys.exit(1) -class dialog_box(QtGui.QWidget): +class plot_form(QtGui.QWidget): def __init__(self, top_block, title=''): QtGui.QWidget.__init__(self, None) - + self._start = 0 self._end = 0 + self._y_min = 0 + self._y_max = 0 self.top_block = top_block + self.top_block.gui_y_axis = self.gui_y_axis self.setWindowTitle(title) - self.size_val = QtGui.QIntValidator(0, top_block._max_nsamps, self) - - self.start_form = QtGui.QFormLayout() - self.start_edit = QtGui.QLineEdit(self) - self.start_edit.setMinimumWidth(100) - self.start_edit.setText(QtCore.QString("%1").arg(top_block._start)) - self.start_edit.setValidator(self.size_val) - self.start_form.addRow("Start:", self.start_edit) - self.connect(self.start_edit, QtCore.SIGNAL("returnPressed()"), - self.update_points) - - end = top_block._start + top_block._nsamps - self.end_form = QtGui.QFormLayout() - self.end_edit = QtGui.QLineEdit(self) - self.end_edit.setMinimumWidth(100) - self.end_edit.setText(QtCore.QString("%1").arg(end)) - self.end_edit.setValidator(self.size_val) - self.end_form.addRow("End:", self.end_edit) - self.connect(self.end_edit, QtCore.SIGNAL("returnPressed()"), - self.update_points) - self.layout = QtGui.QGridLayout(self) - self.layout.addWidget(top_block.get_gui(), 1,0,1,2) - self.layout.addLayout(self.start_form, 2,0,1,1) - self.layout.addLayout(self.end_form, 2,1,1,1) + self.layout.addWidget(top_block.get_gui(), 1,2,1,2) # Create a save action self.save_act = QtGui.QAction("Save", self) @@ -81,11 +61,241 @@ class dialog_box(QtGui.QWidget): self.menu.addAction(self.save_act) self.menu.addAction(self.exit_act) - self.layout.addWidget(self.menu, 0,0,1,2) - - self.resize(800, 500) + self.layout.addWidget(self.menu, 0,0,1,4) + + self.left_col_form = QtGui.QFormLayout() + self.layout.addLayout(self.left_col_form, 1,0,1,1) + self.layout.setColumnStretch(0, 0) + self.layout.setColumnStretch(2, 1) + + # Create Edit boxes for X-axis start/stop + self.size_val = QtGui.QIntValidator(0, top_block._max_nsamps, self) + + self.start_edit = QtGui.QLineEdit(self) + self.start_edit.setMinimumWidth(100) + self.start_edit.setMaximumWidth(100) + self.start_edit.setText(QtCore.QString("%1").arg(top_block._start)) + self.start_edit.setValidator(self.size_val) + self.left_col_form.addRow("Start:", self.start_edit) + self.connect(self.start_edit, QtCore.SIGNAL("returnPressed()"), + self.update_xaxis_pos) + + end = top_block._start + top_block._nsamps + self.end_edit = QtGui.QLineEdit(self) + self.end_edit.setMinimumWidth(100) + self.end_edit.setMaximumWidth(100) + self.end_edit.setText(QtCore.QString("%1").arg(end)) + self.end_edit.setValidator(self.size_val) + self.left_col_form.addRow("End:", self.end_edit) + self.connect(self.end_edit, QtCore.SIGNAL("returnPressed()"), + self.update_xaxis_pos) + + # Create a slider to move the position in the file + self.posbar = QtGui.QSlider(QtCore.Qt.Horizontal, self) + self.posbar.setMaximum(self.top_block._max_nsamps) + self.posbar.setPageStep(self.top_block._nsamps) + self.connect(self.posbar, QtCore.SIGNAL("valueChanged(int)"), + self.update_xaxis_slider) + self.layout.addWidget(self.posbar, 2,2,1,1) + + # Create Edit boxes for Y-axis min/max + self.y_range_val = QtGui.QDoubleValidator(top_block._y_min, + top_block._y_max, + 4, self) - def update_points(self): + self.y_max_edit = QtGui.QLineEdit(self) + self.y_max_edit.setValidator(self.y_range_val) + self.y_max_edit.setMinimumWidth(100) + self.y_max_edit.setMaximumWidth(100) + self.left_col_form.addRow("Y Max:", self.y_max_edit) + self.connect(self.y_max_edit, QtCore.SIGNAL("returnPressed()"), + self.update_yaxis_pos) + + self.y_min_edit = QtGui.QLineEdit(self) + self.y_min_edit.setValidator(self.y_range_val) + self.y_min_edit.setMinimumWidth(100) + self.y_min_edit.setMaximumWidth(100) + self.left_col_form.addRow("Y Min:", self.y_min_edit) + self.connect(self.y_min_edit, QtCore.SIGNAL("returnPressed()"), + self.update_yaxis_pos) + + self.grid_check = QtGui.QCheckBox("Grid", self) + self.connect(self.grid_check, QtCore.SIGNAL("stateChanged(int)"), + self.set_grid_check) + self.left_col_form.addWidget(self.grid_check) + + self.gui_y_axis(top_block._y_value-top_block._y_range, top_block._y_value) + + # Create a slider to move the plot's y-axis offset + self.ybar = QtGui.QSlider(QtCore.Qt.Vertical, self) + self.ybar.setMinimum(self.top_block._y_min) + self.ybar.setMaximum(self.top_block._y_max) + self.ybar.setPageStep(self.top_block._y_range) + self.ybar.setValue(self.top_block._y_value) + self.connect(self.ybar, QtCore.SIGNAL("valueChanged(int)"), + self.update_yaxis_slider) + self.layout.addWidget(self.ybar, 1,1,1,1) + + # Create an edit box for the Sample Rate + sr = top_block._samp_rate + self.samp_rate_edit = QtGui.QLineEdit(self) + self.samp_rate_edit.setMinimumWidth(100) + self.samp_rate_edit.setMaximumWidth(100) + self.samp_rate_edit.setText(QtCore.QString("%1").arg(sr)) + self.left_col_form.addRow("Sample Rate:", self.samp_rate_edit) + self.connect(self.samp_rate_edit, QtCore.SIGNAL("returnPressed()"), + self.update_samp_rate) + + # Create an edit box for the center frequency + freq = top_block._center_freq + self.freq_edit = QtGui.QLineEdit(self) + self.freq_edit.setMinimumWidth(100) + self.freq_edit.setMaximumWidth(100) + self.freq_edit.setText(QtCore.QString("%1").arg(freq)) + self.left_col_form.addRow("Frequency:", self.freq_edit) + self.connect(self.freq_edit, QtCore.SIGNAL("returnPressed()"), + self.update_samp_rate) + + self.resize(1000, 500) + + def add_line_control(self, layout): + self._line_tabs = QtGui.QTabWidget() + + self._line_pages = [] + self._line_forms = [] + self._label_edit = [] + self._size_edit = [] + self._color_edit = [] + self._style_edit = [] + self._marker_edit = [] + self._alpha_edit = [] + for n in xrange(self.top_block._nsigs): + self._line_pages.append(QtGui.QDialog()) + self._line_forms.append(QtGui.QFormLayout(self._line_pages[-1])) + + label = self.top_block.gui_snk.line_label(n) + self._label_edit.append(QtGui.QLineEdit(self)) + self._label_edit[-1].setMinimumWidth(125) + self._label_edit[-1].setMaximumWidth(125) + self._label_edit[-1].setText(QtCore.QString("%1").arg(label)) + self._line_forms[-1].addRow("Label:", self._label_edit[-1]) + self.connect(self._label_edit[-1], QtCore.SIGNAL("returnPressed()"), + self.update_line_label) + + width = self.top_block.gui_snk.line_width(n) + self._size_edit.append(QtGui.QLineEdit(self)) + self._size_edit[-1].setMinimumWidth(100) + self._size_edit[-1].setMaximumWidth(100) + self._size_edit[-1].setText(QtCore.QString("%1").arg(width)) + self._line_forms[-1].addRow("Width:", self._size_edit[-1]) + self.connect(self._size_edit[-1], QtCore.SIGNAL("returnPressed()"), + self.update_line_size) + + color = self.top_block.gui_snk.line_color(n) + self._color_edit.append(QtGui.QLineEdit(self)) + self._color_edit[-1].setMinimumWidth(100) + self._color_edit[-1].setMaximumWidth(100) + self._color_edit[-1].setText(QtCore.QString("%1").arg(color)) + self._line_forms[-1].addRow("Color:", self._color_edit[-1]) + self.connect(self._color_edit[-1], QtCore.SIGNAL("returnPressed()"), + self.update_line_color) + + self._qtstyles = {"None": QtCore.Qt.NoPen, + "Solid": QtCore.Qt.SolidLine, + "Dash": QtCore.Qt.DashLine, + "Dot": QtCore.Qt.DotLine, + "DashDot": QtCore.Qt.DashDotLine, + "DashDotDot": QtCore.Qt.DashDotDotLine} + self._style_edit.append(QtGui.QComboBox(self)) + self._style_edit[-1].addItems(["None", "Solid", "Dash", + "Dot", "DashDot", "DashDotDot"]) + self._style_edit[-1].setCurrentIndex(1) + self._line_forms[-1].addRow("Style:", self._style_edit[-1]) + self.connect(self._style_edit[-1], + QtCore.SIGNAL("currentIndexChanged(int)"), + self.update_line_style) + + # A bit dangerous, this. If QWT ever changes the lineup, + # we will have to adjust this, too. But we also can't + # really rely on PyQwt right now. + self._qwtmarkers = {"None": -1, + "Circle": 0, + "Rectangle": 1, + "Diamond": 2, + "Triangle": 3, + "Down Triangle": 4, + "Left Triangle": 6, + "Right Triangle": 7, + "Cross": 8, + "X-Cross": 9, + "Horiz. Line": 10, + "Vert. Line": 11, + "Star 1": 12, + "Star 2": 13, + "Hexagon": 14} + self._marker_edit.append(QtGui.QComboBox(self)) + self._marker_edit[-1].addItems(["None", "Circle", "Rectangle", "Diamond", + "Triangle", "Down Triangle", "Left Triangle", + "Right Triangle", "Cross", "X-Cross", + "Horiz. Line", "Vert. Line", "Star 1", + "Star 2", "Hexagon"]) + self._line_forms[-1].addRow("Marker:", self._marker_edit[-1]) + self.connect(self._marker_edit[-1], + QtCore.SIGNAL("currentIndexChanged(int)"), + self.update_line_marker) + + alpha_val = QtGui.QDoubleValidator(0, 1.0, 2, self) + alpha_val.setTop(1.0) + alpha = self.top_block.gui_snk.line_alpha(n) + self._alpha_edit.append(QtGui.QLineEdit(self)) + self._alpha_edit[-1].setMinimumWidth(50) + self._alpha_edit[-1].setMaximumWidth(100) + self._alpha_edit[-1].setText(QtCore.QString("%1").arg(alpha)) + self._alpha_edit[-1].setValidator(alpha_val) + self._line_forms[-1].addRow("Alpha:", self._alpha_edit[-1]) + self.connect(self._alpha_edit[-1], QtCore.SIGNAL("returnPressed()"), + self.update_line_alpha) + + self._line_tabs.addTab(self._line_pages[-1], "{0}".format(label)) + + layout.addWidget(self._line_tabs) + + def update_line_label(self): + index = self._line_tabs.currentIndex() + label = self._label_edit[index].text() + self._line_tabs.setTabText(index, label) + self.top_block.gui_snk.set_line_label(index, str(label)) + + def update_line_size(self): + index = self._line_tabs.currentIndex() + width = self._size_edit[index].text().toUInt()[0] + self.top_block.gui_snk.set_line_width(index, width) + self.update_line_alpha() + + def update_line_color(self): + index = self._line_tabs.currentIndex() + color = str(self._color_edit[index].text()) + self.top_block.gui_snk.set_line_color(index, color) + self.update_line_alpha() + + def update_line_style(self, s_index): + index = self._line_tabs.currentIndex() + style_str = self._style_edit[index].itemText(s_index) + style = self._qtstyles[str(style_str)] + self.top_block.gui_snk.set_line_style(index, int(style)) + + def update_line_marker(self, m_index): + index = self._line_tabs.currentIndex() + marker_str = self._marker_edit[index].itemText(m_index) + marker = self._qwtmarkers[str(marker_str)] + self.top_block.gui_snk.set_line_marker(index, int(marker)) + + def update_line_alpha(self): + index = self._line_tabs.currentIndex() + alpha = self._alpha_edit[index].text().toDouble()[0] + self.top_block.gui_snk.set_line_alpha(index, alpha) + + def update_xaxis_pos(self): newstart = self.start_edit.text().toUInt()[0] newend = self.end_edit.text().toUInt()[0] if(newstart != self._start or newend != self._end): @@ -99,6 +309,54 @@ class dialog_box(QtGui.QWidget): self.top_block.reset(newstart, newnsamps) self._start = newstart self._end = newend + self.posbar.setPageStep(self.top_block._nsamps) + self.posbar.setValue(self._start) + + def update_xaxis_slider(self, value): + self._start = value + self._end = value + self.posbar.pageStep() + + self.start_edit.setText("{0}".format(self._start)) + self.end_edit.setText("{0}".format(self._end)) + + if(value != self.top_block._max_nsamps): + self.top_block.reset(self._start, self.posbar.pageStep()) + + def update_yaxis_pos(self): + newmin = self.y_min_edit.text().toDouble()[0] + newmax = self.y_max_edit.text().toDouble()[0] + if(newmin != self._y_min or newmax != self._y_max): + self._y_min = newmin + self._y_max = newmax + self.top_block._y_range = newmax - newmin + self.ybar.setValue(self._y_max) + self.top_block.set_y_axis(self._y_min, self._y_max) + + def update_yaxis_slider(self, value): + self.top_block._y_value = value + self._y_min = value - self.top_block._y_range + self._y_max = value + + self._y_min, self._y_max = self.top_block.set_y_axis(self._y_min, self._y_max) + + self.gui_y_axis(self._y_min, self._y_max) + + def update_samp_rate(self): + 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.reset(self.top_block._start, + self.top_block._nsamps) + + def gui_y_axis(self, ymin, ymax): + self.y_min_edit.setText("{0:.4f}".format(ymin)) + self.y_max_edit.setText("{0:.4f}".format(ymax)) + + def set_grid_check(self, state): + if(state): + self.top_block.gui_snk.enable_grid(True) + else: + self.top_block.gui_snk.enable_grid(False) def save_figure(self): qpix = QtGui.QPixmap.grabWidget(self.top_block.pyWin) @@ -124,4 +382,3 @@ class dialog_box(QtGui.QWidget): qpix.save(filename, "TIFF"); else: qpix.save(filename, "JPEG"); - diff --git a/gr-qtgui/apps/plot_psd_base.py b/gr-qtgui/apps/plot_psd_base.py new file mode 100644 index 0000000000..a4a6cb871a --- /dev/null +++ b/gr-qtgui/apps/plot_psd_base.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +# +# Copyright 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, blocks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +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) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * + from gnuradio.qtgui.plot_base import * +except ImportError: + from plot_form import * + from plot_base import * + +class plot_base(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._nsigs = len(self._filelist) + self._avg = avg + self._nsamps = nsamples + self._auto_scale = False + + self._y_min = -200 + self._y_max = 400 + self._y_range = 130 + self._y_value = 10 + + self._is_setup = False + + self.qapp = QtGui.QApplication(sys.argv) + + def setup(self): + self.skip = gr.skiphead(self.dsize, self._start) + + n = 0 + self.srcs = list() + self._data_min = sys.maxint + self._data_max = -sys.maxint - 1 + for f in self._filelist: + data,_min,_max = self.read_samples(f, self._start, + self._nsamps, self._psd_size) + if(_min < self._data_min): + self._data_min = _min + if(_max > self._data_max): + self._data_max = _max + + self.srcs.append(self.src_type(data)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_line_label(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0) + self.gui_snk.enable_menu(False) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + self._is_setup = True + + def is_setup(self): + return self._is_setup + + def set_y_axis(self, y_min, y_max): + self.gui_snk.set_y_axis(y_min, y_max) + return y_min, y_max + + def get_gui(self): + if(self.is_setup()): + return self.pyWin + else: + return None + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + + self._data_min = sys.maxint + self._data_max = -sys.maxint - 1 + for s,f in zip(self.srcs, self._filelist): + data,_min,_max = self.read_samples(f, self._start, newnsamps, self._psd_size) + if(_min < self._data_min): + self._data_min = _min + if(_max > self._data_max): + self._data_max = _max + + s.set_data(data) + + self.start() + +def setup_options(desc): + parser = OptionParser(option_class=eng_option, description=desc, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=1000000, + help="Set the number of samples to display [default=prints entire file]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + return (options,args) diff --git a/gr-qtgui/apps/plot_psd_form.py b/gr-qtgui/apps/plot_psd_form.py new file mode 100644 index 0000000000..262734bd67 --- /dev/null +++ b/gr-qtgui/apps/plot_psd_form.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# +# Copyright 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. +# + +import sys +from gnuradio import filter + +try: + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_from import plot_form +except ImportError: + from plot_form import plot_form + +class plot_psd_form(plot_form): + def __init__(self, top_block, title=''): + plot_form.__init__(self, top_block, title) + + self.right_col_layout = QtGui.QVBoxLayout() + self.right_col_form = QtGui.QFormLayout() + self.right_col_layout.addLayout(self.right_col_form) + self.layout.addLayout(self.right_col_layout, 1,4,1,1) + + self.psd_size_val = QtGui.QIntValidator(0, 2**18, self) + self.psd_size_edit = QtGui.QLineEdit(self) + self.psd_size_edit.setMinimumWidth(50) + self.psd_size_edit.setMaximumWidth(100) + self.psd_size_edit.setText(QtCore.QString("%1").arg(top_block._psd_size)) + self.psd_size_edit.setValidator(self.psd_size_val) + self.right_col_form.addRow("FFT:", self.psd_size_edit) + self.connect(self.psd_size_edit, QtCore.SIGNAL("returnPressed()"), + self.update_psd_size) + + self.psd_win_combo = QtGui.QComboBox(self) + self.psd_win_combo.addItems(["None", "Hamming", "Hann", "Blackman", + "Rectangular", "Kaiser", "Blackman-harris"]) + self.psd_win_combo.setCurrentIndex(self.top_block.gui_snk.fft_window()+1) + self.right_col_form.addRow("Window:", self.psd_win_combo) + self.connect(self.psd_win_combo, + QtCore.SIGNAL("currentIndexChanged(int)"), + self.update_psd_win) + + self.psd_avg_val = QtGui.QDoubleValidator(0, 1.0, 4, self) + self.psd_avg_edit = QtGui.QLineEdit(self) + self.psd_avg_edit.setMinimumWidth(50) + self.psd_avg_edit.setMaximumWidth(100) + self.psd_avg_edit.setText(QtCore.QString("%1").arg(top_block._avg)) + self.psd_avg_edit.setValidator(self.psd_avg_val) + self.right_col_form.addRow("Average:", self.psd_avg_edit) + self.connect(self.psd_avg_edit, QtCore.SIGNAL("returnPressed()"), + self.update_psd_avg) + + self.add_line_control(self.right_col_layout) + + def update_psd_size(self): + newpsdsize = self.psd_size_edit.text().toInt()[0] + if(newpsdsize != self.top_block._psd_size): + self.top_block.gui_snk.set_fft_size(newpsdsize) + self.top_block._psd_size = newpsdsize + self.top_block.reset(self.top_block._start, + self.top_block._nsamps) + + def update_psd_win(self, index): + self.top_block.gui_snk.set_fft_window(index-1) + self.top_block.reset(self.top_block._start, + self.top_block._nsamps) + + def update_psd_avg(self): + newpsdavg = self.psd_avg_edit.text().toDouble()[0] + if(newpsdavg != self.top_block._avg): + self.top_block.gui_snk.set_fft_average(newpsdavg) + self.top_block._avg = newpsdavg + 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 new file mode 100644 index 0000000000..adfbfd032f --- /dev/null +++ b/gr-qtgui/apps/plot_spectrogram_base.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python +# +# Copyright 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, blocks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +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) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * + from gnuradio.qtgui.plot_base import * +except ImportError: + from plot_form import * + from plot_base import * + +class plot_base(gr.top_block): + def __init__(self, filelist, fc, samp_rate, psdsize, start, + nsamples, max_nsamples, avg=1.0): + gr.top_block.__init__(self) + + self._filelist = filelist + self._center_freq = fc + self._samp_rate = samp_rate + self._psd_size = psdsize + self._start = start + self._max_nsamps = max_nsamples + self._nsigs = len(self._filelist) + self._avg = avg + self._nsamps = nsamples + self._auto_scale = False + + self._y_min = -200 + self._y_max = 400 + self._y_range = 130 + self._y_value = 10 + + self._is_setup = False + + self.qapp = QtGui.QApplication(sys.argv) + + def setup(self): + self.skip = gr.skiphead(self.dsize, self._start) + + n = 0 + self.srcs = list() + self._data_min = sys.maxint + self._data_max = -sys.maxint - 1 + for f in self._filelist: + data,_min,_max = self.read_samples(f, self._start, + self._nsamps, self._psd_size) + if(_min < self._data_min): + self._data_min = _min + if(_max > self._data_max): + self._data_max = _max + + self.srcs.append(self.src_type(data)) + + # Set default labels based on file names + fname = f.split("/")[-1] + self.gui_snk.set_line_label(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0); + self.gui_snk.enable_menu(False) + self.gui_snk.set_fft_average(self._avg) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + self._is_setup = True + + def is_setup(self): + return self._is_setup + + def set_y_axis(self, y_min, y_max): + self.gui_snk.set_intensity_range(y_min, y_max) + return y_min, y_max + + def get_gui(self): + if(self.is_setup()): + return self.pyWin + else: + return None + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + self.gui_snk.clear_data() + + self._start = newstart + self._nsamps = newnsamps + + self._data_min = sys.maxint + self._data_max = -sys.maxint - 1 + for s,f in zip(self.srcs, self._filelist): + data,_min,_max = self.read_samples(f, self._start, newnsamps, self._psd_size) + if(_min < self._data_min): + self._data_min = _min + if(_max > self._data_max): + self._data_max = _max + + s.set_data(data) + + self.start() + +def setup_options(desc): + parser = OptionParser(option_class=eng_option, description=desc, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=1000000, + help="Set the number of samples to display [default=%default]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-L", "--psd-size", type="int", default=2048, + help="Set the FFT size of the PSD [default=%default]") + parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0, + help="Set the center frequency of the signal [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("-a", "--average", type="float", default=1.0, + help="Set amount of averaging (smaller=more averaging) [default=%default]") + (options, args) = parser.parse_args() + + if(len(args) < 1): + parser.print_help() + sys.exit(0) + + return (options, args) + diff --git a/gr-qtgui/apps/plot_spectrogram_form.py b/gr-qtgui/apps/plot_spectrogram_form.py new file mode 100644 index 0000000000..7f8361e6b1 --- /dev/null +++ b/gr-qtgui/apps/plot_spectrogram_form.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python +# +# Copyright 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. +# + +import sys +from gnuradio import filter + +try: + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_from import plot_form +except ImportError: + from plot_form import plot_form + +class plot_spectrogram_form(plot_form): + def __init__(self, top_block, title=''): + plot_form.__init__(self, top_block, title) + + self.right_col_layout = QtGui.QVBoxLayout() + self.right_col_form = QtGui.QFormLayout() + self.right_col_layout.addLayout(self.right_col_form) + self.layout.addLayout(self.right_col_layout, 1,4,1,1) + + self.psd_size_val = QtGui.QIntValidator(0, 2**18, self) + self.psd_size_edit = QtGui.QLineEdit(self) + self.psd_size_edit.setMinimumWidth(50) + self.psd_size_edit.setMaximumWidth(100) + self.psd_size_edit.setText(QtCore.QString("%1").arg(top_block._psd_size)) + self.psd_size_edit.setValidator(self.psd_size_val) + self.right_col_form.addRow("FFT Size:", self.psd_size_edit) + self.connect(self.psd_size_edit, QtCore.SIGNAL("returnPressed()"), + self.update_psd_size) + + self.psd_win_combo = QtGui.QComboBox(self) + self.psd_win_combo.addItems(["None", "Hamming", "Hann", "Blackman", + "Rectangular", "Kaiser", "Blackman-harris"]) + self.psd_win_combo.setCurrentIndex(self.top_block.gui_snk.fft_window()+1) + self.right_col_form.addRow("Window:", self.psd_win_combo) + self.connect(self.psd_win_combo, + QtCore.SIGNAL("currentIndexChanged(int)"), + self.update_psd_win) + + self.psd_avg_val = QtGui.QDoubleValidator(0, 1.0, 4, self) + self.psd_avg_edit = QtGui.QLineEdit(self) + self.psd_avg_edit.setMinimumWidth(50) + self.psd_avg_edit.setMaximumWidth(100) + self.psd_avg_edit.setText(QtCore.QString("%1").arg(top_block._avg)) + self.psd_avg_edit.setValidator(self.psd_avg_val) + self.right_col_form.addRow("Average:", self.psd_avg_edit) + self.connect(self.psd_avg_edit, QtCore.SIGNAL("returnPressed()"), + self.update_psd_avg) + + self.autoscale_button = QtGui.QPushButton("Auto Scale", self) + self.autoscale_button.setMaximumWidth(100) + self.right_col_layout.addWidget(self.autoscale_button) + self.connect(self.autoscale_button, QtCore.SIGNAL("clicked()"), + self.spectrogram_auto_scale) + + self.add_spectrogram_control(self.right_col_layout) + + def update_psd_size(self): + newpsdsize = self.psd_size_edit.text().toInt()[0] + if(newpsdsize != self.top_block._psd_size): + self.top_block.gui_snk.set_fft_size(newpsdsize) + self.top_block._psd_size = newpsdsize + self.top_block.reset(self.top_block._start, + self.top_block._nsamps) + + def update_psd_win(self, index): + self.top_block.gui_snk.set_fft_window(index-1) + self.top_block.reset(self.top_block._start, + self.top_block._nsamps) + + def update_psd_avg(self): + newpsdavg = self.psd_avg_edit.text().toDouble()[0] + if(newpsdavg != self.top_block._avg): + self.top_block.gui_snk.set_fft_average(newpsdavg) + self.top_block._avg = newpsdavg + self.top_block.reset(self.top_block._start, + self.top_block._nsamps) + + def add_spectrogram_control(self, layout): + self._line_tabs = QtGui.QTabWidget() + + self._line_pages = [] + self._line_forms = [] + self._label_edit = [] + self._size_edit = [] + self._color_edit = [] + self._style_edit = [] + self._marker_edit = [] + self._alpha_edit = [] + for n in xrange(self.top_block._nsigs): + self._line_pages.append(QtGui.QDialog()) + self._line_forms.append(QtGui.QFormLayout(self._line_pages[-1])) + + label = self.top_block.gui_snk.line_label(n) + self._label_edit.append(QtGui.QLineEdit(self)) + self._label_edit[-1].setMinimumWidth(125) + self._label_edit[-1].setMaximumWidth(125) + self._label_edit[-1].setText(QtCore.QString("%1").arg(label)) + self._line_forms[-1].addRow("Label:", self._label_edit[-1]) + self.connect(self._label_edit[-1], QtCore.SIGNAL("returnPressed()"), + self.update_line_label) + + self._qtcolormaps = ["Multi Color", "White Hot", + "Black Hot", "Incandescent"] + self._color_edit.append(QtGui.QComboBox(self)) + self._color_edit[-1].addItems(self._qtcolormaps) + self._line_forms[-1].addRow("Color Map:", self._color_edit[-1]) + self.connect(self._color_edit[-1], + QtCore.SIGNAL("currentIndexChanged(int)"), + self.update_color_map) + + alpha_val = QtGui.QDoubleValidator(0, 1.0, 2, self) + alpha_val.setTop(1.0) + alpha = self.top_block.gui_snk.line_alpha(n) + self._alpha_edit.append(QtGui.QLineEdit(self)) + self._alpha_edit[-1].setMinimumWidth(50) + self._alpha_edit[-1].setMaximumWidth(100) + self._alpha_edit[-1].setText(QtCore.QString("%1").arg(alpha)) + self._alpha_edit[-1].setValidator(alpha_val) + self._line_forms[-1].addRow("Alpha:", self._alpha_edit[-1]) + self.connect(self._alpha_edit[-1], QtCore.SIGNAL("returnPressed()"), + self.update_line_alpha) + + self._line_tabs.addTab(self._line_pages[-1], "{0}".format(label)) + + layout.addWidget(self._line_tabs) + + def update_color_map(self, c_index): + index = self._line_tabs.currentIndex() + self.top_block.gui_snk.set_color_map(index, c_index) + self.update_line_alpha() + + def spectrogram_auto_scale(self): + self.top_block.gui_snk.auto_scale() + _min = self.top_block.gui_snk.min_intensity(0) + _max = self.top_block.gui_snk.max_intensity(0) + if(self.gui_y_axis): + self.gui_y_axis(_min, _max) diff --git a/gr-qtgui/apps/plot_time_base.py b/gr-qtgui/apps/plot_time_base.py new file mode 100644 index 0000000000..c80bace1b6 --- /dev/null +++ b/gr-qtgui/apps/plot_time_base.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# +# Copyright 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, blocks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os, sys + +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) + +try: + import scipy +except ImportError: + print "Error: Scipy required (www.scipy.org)." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_form import * + from gnuradio.qtgui.plot_base import * +except ImportError: + from plot_form import * + from plot_base import * + +class plot_base(gr.top_block): + def __init__(self, filelist, samp_rate, start, + nsamples, max_nsamples, + auto_scale): + gr.top_block.__init__(self) + + self._filelist = filelist + self._samp_rate = samp_rate + self._center_freq = 0 + self._start = start + self._max_nsamps = max_nsamples + self._nsigs = len(self._filelist) + self._auto_scale = auto_scale + self._nsamps = nsamples + self._is_setup = False + + self._y_min = -20 + self._y_max = 20 + self._y_range = 2 + self._y_value = 1 + self.gui_y_axis = None + + self.qapp = QtGui.QApplication(sys.argv) + + def setup(self): + self.skip = gr.skiphead(self.dsize, self._start) + + n = 0 + self.srcs = list() + self._data_min = sys.maxint + self._data_max = -sys.maxint - 1 + for f in self._filelist: + data,_min,_max = self.read_samples(f, self._start, self._nsamps) + if(_min < self._data_min): + self._data_min = _min + if(_max > self._data_max): + self._data_max = _max + + self.srcs.append(self.src_type(data)) + + # Set default labels based on file names + fname = f.split("/")[-1] + if(type(self.gui_snk) == qtgui.time_sink_c_sptr): + self.gui_snk.set_line_label(n, "Re{{{0}}}".format(fname)) + self.gui_snk.set_line_label(n+1, "Im{{{0}}}".format(fname)) + n += 2 + else: + self.gui_snk.set_line_label(n, "{0}".format(fname)) + n += 1 + + self.connect(self.srcs[0], self.skip) + self.connect(self.skip, (self.gui_snk, 0)) + + for i,s in enumerate(self.srcs[1:]): + self.connect(s, (self.gui_snk, i+1)) + + self.gui_snk.set_update_time(0) + self.gui_snk.enable_menu(False) + self.auto_scale(self._auto_scale) + + # Get Python Qt references + pyQt = self.gui_snk.pyqwidget() + self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) + + self._is_setup = True + + def is_setup(self): + return self._is_setup + + def set_y_axis(self, y_min, y_max): + self.gui_snk.set_y_axis(y_min, y_max) + return y_min, y_max + + def get_gui(self): + if(self.is_setup()): + return self.pyWin + else: + return None + + def reset(self, newstart, newnsamps): + self.stop() + self.wait() + + self._start = newstart + + self._data_min = sys.maxint + self._data_max = -sys.maxint - 1 + for s,f in zip(self.srcs, self._filelist): + data,_min,_max = self.read_samples(f, self._start, newnsamps) + if(_min < self._data_min): + self._data_min = _min + if(_max > self._data_max): + self._data_max = _max + + s.set_data(data) + if(len(data) < newnsamps): + newnsamps = len(data) + + self.auto_scale(self._auto_scale) + + self._nsamps = newnsamps + self.gui_snk.set_nsamps(self._nsamps) + + self.start() + + def auto_scale(self, state): + if(state > 0): + self.gui_snk.set_y_axis(self._data_min, self._data_max) + self._auto_scale = True + self._y_value = self._data_max + self._y_range = self._data_max - self._data_min + self._y_min = 10*self._data_min + self._y_max = 10*self._data_max + + if(self.gui_y_axis): + self.gui_y_axis(self._data_min, self._data_max) + else: + self._auto_scale = False + +def setup_options(desc): + parser = OptionParser(option_class=eng_option, description=desc, + conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=1000000, + help="Set the number of samples to display [default=%default]") + parser.add_option("-S", "--start", type="int", default=0, + help="Starting sample number [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0, + help="Set the sample rate of the signal [default=%default]") + parser.add_option("", "--no-auto-scale", action="store_true", default=False, + help="Do not auto-scale the plot [default=%default]") + (options,args) = parser.parse_args() + if(len(args) < 1): + parser.print_help() + sys.exit(0) + return (options,args) + diff --git a/gr-qtgui/apps/plot_time_form.py b/gr-qtgui/apps/plot_time_form.py new file mode 100644 index 0000000000..cff3ad6857 --- /dev/null +++ b/gr-qtgui/apps/plot_time_form.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# +# Copyright 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. +# + +import sys +from gnuradio import filter + +try: + from PyQt4 import QtGui, QtCore + import sip +except ImportError: + print "Error: Program requires PyQt4." + sys.exit(1) + +try: + from gnuradio.qtgui.plot_from import plot_form +except ImportError: + from plot_form import plot_form + +class plot_time_form(plot_form): + def __init__(self, top_block, title=''): + plot_form.__init__(self, top_block, title) + + self.right_col_layout = QtGui.QVBoxLayout() + self.right_col_form = QtGui.QFormLayout() + self.right_col_layout.addLayout(self.right_col_form) + self.layout.addLayout(self.right_col_layout, 1,4,1,1) + + self.auto_scale = QtGui.QCheckBox("Auto Scale", self) + if(self.top_block._auto_scale): + self.auto_scale.setChecked(self.top_block._auto_scale) + self.connect(self.auto_scale, QtCore.SIGNAL("stateChanged(int)"), + self.set_auto_scale) + self.right_col_layout.addWidget(self.auto_scale) + + self.stem = QtGui.QCheckBox("Stem", self) + self.connect(self.stem, QtCore.SIGNAL("stateChanged(int)"), + self.toggle_stem) + self.right_col_layout.addWidget(self.stem) + + self.add_line_control(self.right_col_layout) + + def set_auto_scale(self, state): + if(state): + self.top_block.auto_scale(True) + else: + self.top_block.auto_scale(False) + + def toggle_stem(self, state): + self.top_block.gui_snk.toggle_stem_plot() + if(state): + index = self._qwtmarkers.keys().index('Circle') + else: + index = self._qwtmarkers.keys().index('None') + for n in xrange(self.top_block._nsigs): + self._marker_edit[n].setCurrentIndex(index) + + def update_samp_rate(self): + sr = self.samp_rate_edit.text().toDouble()[0] + self.top_block.gui_snk.set_samp_rate(sr) + diff --git a/gr-qtgui/examples/pyqt_waterfall_c.py b/gr-qtgui/examples/pyqt_waterfall_c.py index 3fce9b9a5a..407e8d1bb0 100755 --- a/gr-qtgui/examples/pyqt_waterfall_c.py +++ b/gr-qtgui/examples/pyqt_waterfall_c.py @@ -146,10 +146,12 @@ class my_top_block(gr.top_block): Rs = 8000 f1 = 100 - f2 = 200 + f2 = 2000 npts = 2048 + taps = filter.firdes.complex_band_pass_2(1, Rs, 1500, 2500, 100, 60) + self.qapp = QtGui.QApplication(sys.argv) ss = open('dark.qss') sstext = ss.read() @@ -161,13 +163,15 @@ class my_top_block(gr.top_block): src = blocks.add_cc() channel = channels.channel_model(0.01) thr = gr.throttle(gr.sizeof_gr_complex, 100*npts) - self.snk1 = qtgui.waterfall_sink_c(npts, filter.firdes.WIN_BLACKMAN_hARRIS, + filt = filter.fft_filter_ccc(1, taps) + self.snk1 = qtgui.waterfall_sink_c(npts, gr.firdes.WIN_BLACKMAN_hARRIS, 0, Rs, - "Complex Waterfall Example") + "Complex Waterfall Example", 2) self.connect(src1, (src,0)) self.connect(src2, (src,1)) self.connect(src, channel, thr, (self.snk1, 0)) + self.connect(thr, filt, (self.snk1, 1)) self.ctrl_win = control_box() self.ctrl_win.attach_signal1(src1) diff --git a/gr-qtgui/examples/pyqt_waterfall_f.py b/gr-qtgui/examples/pyqt_waterfall_f.py index 1c4063e31b..8843f19528 100755 --- a/gr-qtgui/examples/pyqt_waterfall_f.py +++ b/gr-qtgui/examples/pyqt_waterfall_f.py @@ -140,7 +140,7 @@ class my_top_block(gr.top_block): Rs = 8000 f1 = 100 - f2 = 200 + f2 = 2000 npts = 2048 @@ -152,11 +152,12 @@ class my_top_block(gr.top_block): thr = gr.throttle(gr.sizeof_float, 100*npts) self.snk1 = qtgui.waterfall_sink_f(npts, filter.firdes.WIN_BLACKMAN_hARRIS, 0, Rs, - "Real Waterfall Example") + "Real Waterfall Example", 2) self.connect(src1, (src,0)) self.connect(src2, (src,1)) self.connect(src, thr, (self.snk1, 0)) + self.connect(src1, (self.snk1, 1)) self.ctrl_win = control_box() self.ctrl_win.attach_signal1(src1) diff --git a/gr-qtgui/include/qtgui/const_sink_c.h b/gr-qtgui/include/qtgui/const_sink_c.h index 49d64af79c..9a9783bed4 100644 --- a/gr-qtgui/include/qtgui/const_sink_c.h +++ b/gr-qtgui/include/qtgui/const_sink_c.h @@ -27,8 +27,7 @@ #include <qtgui/api.h> #include <gr_sync_block.h> #include <qapplication.h> -#include <qwt_symbol.h> - +#include <filter/firdes.h> namespace gr { namespace qtgui { @@ -55,7 +54,7 @@ namespace gr { */ static sptr make(int size, const std::string &name, - int nconnections, + int nconnections=1, QWidget *parent=NULL); virtual void exec_() = 0; @@ -69,12 +68,22 @@ namespace gr { virtual void set_line_label(int which, const std::string &label) = 0; virtual void set_line_color(int which, const std::string &color) = 0; virtual void set_line_width(int which, int width) = 0; - virtual void set_line_style(int which, Qt::PenStyle style) = 0; - virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0; + virtual void set_line_style(int which, int style) = 0; + virtual void set_line_marker(int which, int marker) = 0; virtual void set_nsamps(const int newsize) = 0; + virtual void set_line_alpha(int which, double alpha) = 0; + + virtual std::string title() = 0; + virtual std::string line_label(int which) = 0; + virtual std::string line_color(int which) = 0; + virtual int line_width(int which) = 0; + virtual int line_style(int which) = 0; + virtual int line_marker(int which) = 0; + virtual double line_alpha(int which) = 0; virtual void set_size(int width, int height) = 0; + virtual void enable_menu(bool en=true) = 0; virtual int nsamps() const = 0; virtual void reset() = 0; diff --git a/gr-qtgui/include/qtgui/freq_sink_c.h b/gr-qtgui/include/qtgui/freq_sink_c.h index 391a27c04a..37a12440a0 100644 --- a/gr-qtgui/include/qtgui/freq_sink_c.h +++ b/gr-qtgui/include/qtgui/freq_sink_c.h @@ -27,7 +27,7 @@ #include <qtgui/api.h> #include <gr_sync_block.h> #include <qapplication.h> -#include <qwt_symbol.h> +#include <filter/firdes.h> namespace gr { namespace qtgui { @@ -62,7 +62,7 @@ namespace gr { static sptr make(int fftsize, int wintype, double fc, double bw, const std::string &name, - int nconnections, + int nconnections=1, QWidget *parent=NULL); virtual void exec_() = 0; @@ -72,20 +72,34 @@ namespace gr { virtual int fft_size() const = 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; + virtual gr::filter::firdes::win_type fft_window() = 0; virtual void set_frequency_range(const double centerfreq, const double bandwidth) = 0; virtual void set_y_axis(double min, double max) = 0; virtual void set_update_time(double t) = 0; + virtual void set_title(const std::string &title) = 0; virtual void set_line_label(int which, const std::string &label) = 0; virtual void set_line_color(int which, const std::string &color) = 0; virtual void set_line_width(int which, int width) = 0; - virtual void set_line_style(int which, Qt::PenStyle style) = 0; - virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0; + virtual void set_line_style(int which, int style) = 0; + virtual void set_line_marker(int which, int marker) = 0; + virtual void set_line_alpha(int which, double alpha) = 0; + + virtual std::string title() = 0; + virtual std::string line_label(int which) = 0; + virtual std::string line_color(int which) = 0; + virtual int line_width(int which) = 0; + virtual int line_style(int which) = 0; + virtual int line_marker(int which) = 0; + virtual double line_alpha(int which) = 0; virtual void set_size(int width, int height) = 0; + virtual void enable_menu(bool en=true) = 0; + virtual void enable_grid(bool en=true) = 0; virtual void reset() = 0; QApplication *d_qApplication; diff --git a/gr-qtgui/include/qtgui/freq_sink_f.h b/gr-qtgui/include/qtgui/freq_sink_f.h index 3f4b9362b6..4682f73c10 100644 --- a/gr-qtgui/include/qtgui/freq_sink_f.h +++ b/gr-qtgui/include/qtgui/freq_sink_f.h @@ -27,7 +27,7 @@ #include <qtgui/api.h> #include <gr_sync_block.h> #include <qapplication.h> -#include <qwt_symbol.h> +#include <filter/firdes.h> namespace gr { namespace qtgui { @@ -62,7 +62,7 @@ namespace gr { static sptr make(int fftsize, int wintype, double fc, double bw, const std::string &name, - int nconnections, + int nconnections=1, QWidget *parent=NULL); virtual void exec_() = 0; @@ -72,6 +72,8 @@ namespace gr { virtual int fft_size() const = 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; + virtual gr::filter::firdes::win_type fft_window() = 0; virtual void set_frequency_range(const double centerfreq, const double bandwidth) = 0; virtual void set_y_axis(double min, double max) = 0; @@ -81,11 +83,22 @@ namespace gr { virtual void set_line_label(int which, const std::string &label) = 0; virtual void set_line_color(int which, const std::string &color) = 0; virtual void set_line_width(int which, int width) = 0; - virtual void set_line_style(int which, Qt::PenStyle style) = 0; - virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0; + virtual void set_line_style(int which, int style) = 0; + virtual void set_line_marker(int which, int marker) = 0; + virtual void set_line_alpha(int which, double alpha) = 0; + + virtual std::string title() = 0; + virtual std::string line_label(int which) = 0; + virtual std::string line_color(int which) = 0; + virtual int line_width(int which) = 0; + virtual int line_style(int which) = 0; + virtual int line_marker(int which) = 0; + virtual double line_alpha(int which) = 0; virtual void set_size(int width, int height) = 0; + virtual void enable_menu(bool en=true) = 0; + virtual void enable_grid(bool en=true) = 0; virtual void reset() = 0; QApplication *d_qApplication; diff --git a/gr-qtgui/include/qtgui/time_sink_c.h b/gr-qtgui/include/qtgui/time_sink_c.h index 972a720a65..ef72f7df58 100644 --- a/gr-qtgui/include/qtgui/time_sink_c.h +++ b/gr-qtgui/include/qtgui/time_sink_c.h @@ -27,7 +27,6 @@ #include <qtgui/api.h> #include <gr_sync_block.h> #include <qapplication.h> -#include <qwt_symbol.h> namespace gr { namespace qtgui { @@ -60,7 +59,7 @@ namespace gr { */ static sptr make(int size, double samp_rate, const std::string &name, - int nconnections, + int nconnections=1, QWidget *parent=NULL); virtual void exec_() = 0; @@ -72,13 +71,25 @@ namespace gr { virtual void set_line_label(int which, const std::string &label) = 0; virtual void set_line_color(int which, const std::string &color) = 0; virtual void set_line_width(int which, int width) = 0; - virtual void set_line_style(int which, Qt::PenStyle style) = 0; - virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0; + virtual void set_line_style(int which, int style) = 0; + virtual void set_line_marker(int which, int marker) = 0; virtual void set_nsamps(const int newsize) = 0; virtual void set_samp_rate(const double samp_rate) = 0; + virtual void set_line_alpha(int which, double alpha) = 0; + + virtual std::string title() = 0; + virtual std::string line_label(int which) = 0; + virtual std::string line_color(int which) = 0; + virtual int line_width(int which) = 0; + virtual int line_style(int which) = 0; + virtual int line_marker(int which) = 0; + virtual double line_alpha(int which) = 0; virtual void set_size(int width, int height) = 0; + virtual void enable_menu(bool en=true) = 0; + virtual void enable_grid(bool en=true) = 0; + virtual void toggle_stem_plot() = 0; virtual int nsamps() const = 0; virtual void reset() = 0; diff --git a/gr-qtgui/include/qtgui/time_sink_f.h b/gr-qtgui/include/qtgui/time_sink_f.h index 274896c038..6f689e7b60 100644 --- a/gr-qtgui/include/qtgui/time_sink_f.h +++ b/gr-qtgui/include/qtgui/time_sink_f.h @@ -27,7 +27,6 @@ #include <qtgui/api.h> #include <gr_sync_block.h> #include <qapplication.h> -#include <qwt_symbol.h> namespace gr { namespace qtgui { @@ -58,7 +57,7 @@ namespace gr { */ static sptr make(int size, double samp_rate, const std::string &name, - int nconnections, + int nconnections=1, QWidget *parent=NULL); virtual void exec_() = 0; @@ -70,13 +69,25 @@ namespace gr { virtual void set_line_label(int which, const std::string &line) = 0; virtual void set_line_color(int which, const std::string &color) = 0; virtual void set_line_width(int which, int width) = 0; - virtual void set_line_style(int which, Qt::PenStyle style) = 0; - virtual void set_line_marker(int which, QwtSymbol::Style marker) = 0; + virtual void set_line_style(int which, int style) = 0; + virtual void set_line_marker(int which, int marker) = 0; virtual void set_nsamps(const int newsize) = 0; virtual void set_samp_rate(const double samp_rate) = 0; + virtual void set_line_alpha(int which, double alpha) = 0; + + virtual std::string title() = 0; + virtual std::string line_label(int which) = 0; + virtual std::string line_color(int which) = 0; + virtual int line_width(int which) = 0; + virtual int line_style(int which) = 0; + virtual int line_marker(int which) = 0; + virtual double line_alpha(int which) = 0; virtual void set_size(int width, int height) = 0; + virtual void enable_menu(bool en=true) = 0; + virtual void enable_grid(bool en=true) = 0; + virtual void toggle_stem_plot() = 0; virtual int nsamps() const = 0; virtual void reset() = 0; diff --git a/gr-qtgui/include/qtgui/waterfall_sink_c.h b/gr-qtgui/include/qtgui/waterfall_sink_c.h index 93557b6a63..5bc921ccb3 100644 --- a/gr-qtgui/include/qtgui/waterfall_sink_c.h +++ b/gr-qtgui/include/qtgui/waterfall_sink_c.h @@ -27,7 +27,7 @@ #include <qtgui/api.h> #include <gr_sync_block.h> #include <qapplication.h> -#include <qwt_symbol.h> +#include <filter/firdes.h> namespace gr { namespace qtgui { @@ -63,34 +63,52 @@ namespace gr { * \param fc center frequency of signal (use for x-axis labels) * \param bw bandwidth of signal (used to set x-axis labels) * \param name title for the plot + * \param nconnections number of signals to be connected to the sink * \param parent a QWidget parent object, if any */ static sptr make(int size, int wintype, double fc, double bw, const std::string &name, + int nconnections=1, QWidget *parent=NULL); virtual void exec_() = 0; virtual PyObject* pyqwidget() = 0; + virtual void clear_data() = 0; + virtual void set_fft_size(const int fftsize) = 0; virtual int fft_size() const = 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; + virtual gr::filter::firdes::win_type fft_window() = 0; virtual void set_frequency_range(const double centerfreq, const double bandwidth) = 0; + virtual void set_intensity_range(const double min, + const double max) = 0; virtual void set_update_time(double t) = 0; virtual void set_title(const std::string &title) = 0; - virtual void set_line_label(const std::string &line) = 0; - virtual void set_line_color(const std::string &color) = 0; - virtual void set_line_width(int width) = 0; - virtual void set_line_style(Qt::PenStyle style) = 0; - virtual void set_line_marker(QwtSymbol::Style marker) = 0; + virtual void set_line_label(int which, const std::string &line) = 0; + virtual void set_line_alpha(int which, double alpha) = 0; + virtual void set_color_map(int which, const int color) = 0; + + virtual std::string title() = 0; + virtual std::string line_label(int which) = 0; + virtual double line_alpha(int which) = 0; + virtual int color_map(int which) = 0; virtual void set_size(int width, int height) = 0; + virtual void auto_scale() = 0; + virtual double min_intensity(int which) = 0; + virtual double max_intensity(int which) = 0; + + virtual void enable_menu(bool en=true) = 0; + virtual void enable_grid(bool en=true) = 0; + QApplication *d_qApplication; }; diff --git a/gr-qtgui/include/qtgui/waterfall_sink_f.h b/gr-qtgui/include/qtgui/waterfall_sink_f.h index a09ab2852f..98a434e668 100644 --- a/gr-qtgui/include/qtgui/waterfall_sink_f.h +++ b/gr-qtgui/include/qtgui/waterfall_sink_f.h @@ -27,7 +27,7 @@ #include <qtgui/api.h> #include <gr_sync_block.h> #include <qapplication.h> -#include <qwt_symbol.h> +#include <filter/firdes.h> namespace gr { namespace qtgui { @@ -62,34 +62,52 @@ namespace gr { * \param fc center frequency of signal (use for x-axis labels) * \param bw bandwidth of signal (used to set x-axis labels) * \param name title for the plot + * \param nconnections number of signals to be connected to the sink * \param parent a QWidget parent object, if any */ static sptr make(int size, int wintype, double fc, double bw, const std::string &name, + int nconnections=1, QWidget *parent=NULL); virtual void exec_() = 0; virtual PyObject* pyqwidget() = 0; + virtual void clear_data() = 0; + virtual void set_fft_size(const int fftsize) = 0; virtual int fft_size() const = 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; + virtual gr::filter::firdes::win_type fft_window() = 0; virtual void set_frequency_range(const double centerfreq, const double bandwidth) = 0; + virtual void set_intensity_range(const double min, + const double max) = 0; virtual void set_update_time(double t) = 0; virtual void set_title(const std::string &title) = 0; - virtual void set_line_label(const std::string &line) = 0; - virtual void set_line_color(const std::string &color) = 0; - virtual void set_line_width(int width) = 0; - virtual void set_line_style(Qt::PenStyle style) = 0; - virtual void set_line_marker(QwtSymbol::Style marker) = 0; + virtual void set_line_label(int which, const std::string &line) = 0; + virtual void set_line_alpha(int which, double alpha) = 0; + virtual void set_color_map(int which, const int color) = 0; + + virtual std::string title() = 0; + virtual std::string line_label(int which) = 0; + virtual double line_alpha(int which) = 0; + virtual int color_map(int which) = 0; virtual void set_size(int width, int height) = 0; + virtual void auto_scale() = 0; + virtual double min_intensity(int which) = 0; + virtual double max_intensity(int which) = 0; + + virtual void enable_menu(bool en=true) = 0; + virtual void enable_grid(bool en=true) = 0; + QApplication *d_qApplication; }; diff --git a/gr-qtgui/lib/DisplayPlot.cc b/gr-qtgui/lib/DisplayPlot.cc index bf1c198897..f39fbee3ac 100644 --- a/gr-qtgui/lib/DisplayPlot.cc +++ b/gr-qtgui/lib/DisplayPlot.cc @@ -113,7 +113,7 @@ DisplayPlot::setLineLabel(int which, QString label) } QString -DisplayPlot::lineLabel(int which) +DisplayPlot::getLineLabel(int which) { return _plot_curve[which]->title().text(); } diff --git a/gr-qtgui/lib/DisplayPlot.h b/gr-qtgui/lib/DisplayPlot.h index 26d9412344..0f038a2a28 100644 --- a/gr-qtgui/lib/DisplayPlot.h +++ b/gr-qtgui/lib/DisplayPlot.h @@ -179,6 +179,7 @@ public slots: void setYaxis(double min, double max); void setXaxis(double min, double max); void setLineLabel(int which, QString label); + QString getLineLabel(int which); void setLineColor(int which, QColor color); QColor getLineColor(int which) const; void setLineWidth(int which, int width); @@ -250,8 +251,6 @@ public slots: void setStop(bool on); - QString lineLabel(int which); - void resizeSlot(QSize *s); // Because of the preprocessing of slots in QT, these are not diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc index 52ff335c32..1ed0911686 100644 --- a/gr-qtgui/lib/FrequencyDisplayPlot.cc +++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc @@ -107,10 +107,16 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(int nplots, QWidget* parent) _plot_curve.push_back(new QwtPlotCurve(QString("Data %1").arg(i))); _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 _plot_curve[i]->setRawData(_xAxisPoints, _dataPoints[i], _numPoints); + _plot_curve[i]->setSymbol(*symbol); #else _plot_curve[i]->setRawSamples(_xAxisPoints, _dataPoints[i], _numPoints); + _plot_curve[i]->setSymbol(symbol); #endif setLineColor(i, default_colors[i]); } diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.cc b/gr-qtgui/lib/TimeDomainDisplayPlot.cc index f3c3b4deb3..1f63b43abd 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.cc +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.cc @@ -249,4 +249,22 @@ TimeDomainDisplayPlot::setSampleRate(double sr, double units, } } +void +TimeDomainDisplayPlot::stemPlot(bool trig) +{ + if(trig) { + for(int i = 0; i < _nplots; i++) { + _plot_curve[i]->setStyle(QwtPlotCurve::Sticks); + setLineMarker(i, QwtSymbol::Ellipse); + } + } + else { + for(int i = 0; i < _nplots; i++) { + _plot_curve[i]->setStyle(QwtPlotCurve::Lines); + setLineMarker(i, QwtSymbol::NoSymbol); + } + } + replot(); +} + #endif /* TIME_DOMAIN_DISPLAY_PLOT_C */ diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.h b/gr-qtgui/lib/TimeDomainDisplayPlot.h index c7d5f27a5d..e4bbf0500a 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.h +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.h @@ -41,6 +41,8 @@ public: void replot(); + void stemPlot(bool trig); + public slots: void setSampleRate(double sr, double units, const std::string &strunits); diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc index be0cfc18a3..05c89e3ecb 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.cc +++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc @@ -40,22 +40,6 @@ namespace pt = boost::posix_time; #include <QDebug> /*********************************************************************** - * Create a time label HH:MM:SS.SSS from an input time - **********************************************************************/ -static QString -make_time_label(double secs) -{ - std::string time_str = pt::to_simple_string(pt::from_time_t(time_t(secs))); - - // lops off the YYYY-mmm-DD part of the string - size_t ind = time_str.find(" "); - if(ind != std::string::npos) - time_str = time_str.substr(ind); - - return QString("").sprintf("%s.%03ld", time_str.c_str(), long(std::fmod(secs*1000, 1000))); -} - -/*********************************************************************** * Text scale widget to provide Y (time) axis text **********************************************************************/ class QwtTimeScaleDraw: public QwtScaleDraw, public TimeScaleData @@ -154,13 +138,6 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(int nplots, QWidget* parent) _lastReplot = 0; - QList<int> colormaps; - colormaps << INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR - << INTENSITY_COLOR_MAP_TYPE_WHITE_HOT - << INTENSITY_COLOR_MAP_TYPE_BLACK_HOT - << INTENSITY_COLOR_MAP_TYPE_INCANDESCENT - << INTENSITY_COLOR_MAP_TYPE_USER_DEFINED; - for(int i = 0; i < _nplots; i++) { d_data.push_back(new WaterfallData(_startFrequency, _stopFrequency, _numPoints, 200)); @@ -181,11 +158,16 @@ WaterfallDisplayPlot::WaterfallDisplayPlot(int nplots, QWidget* parent) d_spectrogram[i]->attach(this); - _intensityColorMapType.push_back(colormaps[i%colormaps.size()]); + _intensityColorMapType.push_back(INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR); setIntensityColorMapType(i, _intensityColorMapType[i], QColor("white"), QColor("white")); + + setAlpha(i, 255/_nplots); } + // Set bottom plot with no transparency as a base + setAlpha(0, 255); + // LeftButton for the zooming // MidButton for the panning // RightButton: zoom out by 1 @@ -357,6 +339,30 @@ WaterfallDisplayPlot::setIntensityRange(const double minIntensity, } } +double +WaterfallDisplayPlot::getMinIntensity(int which) const +{ +#if QWT_VERSION < 0x060000 + QwtDoubleInterval r = d_data[which]->range(); +#else + QwtInterval r = d_data[which]->interval(Qt::ZAxis); +#endif + + return r.minValue(); +} + +double +WaterfallDisplayPlot::getMaxIntensity(int which) const +{ +#if QWT_VERSION < 0x060000 + QwtDoubleInterval r = d_data[which]->range(); +#else + QwtInterval r = d_data[which]->interval(Qt::ZAxis); +#endif + + return r.maxValue(); +} + void WaterfallDisplayPlot::replot() { @@ -384,6 +390,15 @@ WaterfallDisplayPlot::replot() QwtPlot::replot(); } +void +WaterfallDisplayPlot::clearData() +{ + for(int i = 0; i < _nplots; i++) { + d_data[i]->reset(); + } +} + + int WaterfallDisplayPlot::getIntensityColorMapType(int which) const { @@ -495,6 +510,18 @@ WaterfallDisplayPlot::getUserDefinedHighIntensityColor() const return _userDefinedHighIntensityColor; } +int +WaterfallDisplayPlot::getAlpha(int which) +{ + return d_spectrogram[which]->alpha(); +} + +void +WaterfallDisplayPlot::setAlpha(int which, int alpha) +{ + d_spectrogram[which]->setAlpha(alpha); +} + void WaterfallDisplayPlot::_updateIntensityRangeDisplay() { diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.h b/gr-qtgui/lib/WaterfallDisplayPlot.h index e962a6c881..6637adc594 100644 --- a/gr-qtgui/lib/WaterfallDisplayPlot.h +++ b/gr-qtgui/lib/WaterfallDisplayPlot.h @@ -72,14 +72,20 @@ public: const int droppedFrames); void setIntensityRange(const double minIntensity, const double maxIntensity); + double getMinIntensity(int which) const; + double getMaxIntensity(int which) const; void replot(void); + void clearData(); int getIntensityColorMapType(int) const; int getIntensityColorMapType1() const; const QColor getUserDefinedLowIntensityColor() const; const QColor getUserDefinedHighIntensityColor() const; + int getAlpha(int which); + void setAlpha(int which, int alpha); + public slots: void setIntensityColorMapType(const int, const int, const QColor, const QColor); void setIntensityColorMapType1(int); diff --git a/gr-qtgui/lib/const_sink_c_impl.cc b/gr-qtgui/lib/const_sink_c_impl.cc index 808312e8a7..2490e9a618 100644 --- a/gr-qtgui/lib/const_sink_c_impl.cc +++ b/gr-qtgui/lib/const_sink_c_impl.cc @@ -29,6 +29,7 @@ #include <string.h> #include <volk/volk.h> #include <fft/fft.h> +#include <qwt_symbol.h> namespace gr { namespace qtgui { @@ -172,15 +173,21 @@ namespace gr { } void - const_sink_c_impl::set_line_style(int which, Qt::PenStyle style) + const_sink_c_impl::set_line_style(int which, int style) { - d_main_gui->setLineStyle(which, style); + d_main_gui->setLineStyle(which, (Qt::PenStyle)style); } void - const_sink_c_impl::set_line_marker(int which, QwtSymbol::Style marker) + const_sink_c_impl::set_line_marker(int which, int marker) { - d_main_gui->setLineMarker(which, marker); + d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker); + } + + void + const_sink_c_impl::set_line_alpha(int which, double alpha) + { + d_main_gui->setMarkerAlpha(which, (int)(255.0*alpha)); } void @@ -189,6 +196,48 @@ namespace gr { d_main_gui->resize(QSize(width, height)); } + std::string + const_sink_c_impl::title() + { + return d_main_gui->title().toStdString(); + } + + std::string + const_sink_c_impl::line_label(int which) + { + return d_main_gui->lineLabel(which).toStdString(); + } + + std::string + const_sink_c_impl::line_color(int which) + { + return d_main_gui->lineColor(which).toStdString(); + } + + int + const_sink_c_impl::line_width(int which) + { + return d_main_gui->lineWidth(which); + } + + int + const_sink_c_impl::line_style(int which) + { + return d_main_gui->lineStyle(which); + } + + int + const_sink_c_impl::line_marker(int which) + { + return d_main_gui->lineMarker(which); + } + + double + const_sink_c_impl::line_alpha(int which) + { + return (double)(d_main_gui->markerAlpha(which))/255.0; + } + void const_sink_c_impl::set_nsamps(const int newsize) { @@ -229,6 +278,12 @@ namespace gr { } void + const_sink_c_impl::enable_menu(bool en) + { + d_main_gui->enableMenu(en); + } + + void const_sink_c_impl::reset() { d_index = 0; diff --git a/gr-qtgui/lib/const_sink_c_impl.h b/gr-qtgui/lib/const_sink_c_impl.h index 9e943b9a68..3e90d00429 100644 --- a/gr-qtgui/lib/const_sink_c_impl.h +++ b/gr-qtgui/lib/const_sink_c_impl.h @@ -75,13 +75,23 @@ namespace gr { void set_line_label(int which, const std::string &label); void set_line_color(int which, const std::string &color); void set_line_width(int which, int width); - void set_line_style(int which, Qt::PenStyle style); - void set_line_marker(int which, QwtSymbol::Style marker); + void set_line_style(int which, int style); + void set_line_marker(int which, int marker); void set_nsamps(const int size); + void set_line_alpha(int which, double alpha); + + std::string title(); + std::string line_label(int which); + std::string line_color(int which); + int line_width(int which); + int line_style(int which); + int line_marker(int which); + double line_alpha(int which); void set_size(int width, int height); int nsamps() const; + void enable_menu(bool en); void reset(); int work(int noutput_items, diff --git a/gr-qtgui/lib/displayform.cc b/gr-qtgui/lib/displayform.cc index e2475cb95e..40cd8e9742 100644 --- a/gr-qtgui/lib/displayform.cc +++ b/gr-qtgui/lib/displayform.cc @@ -47,6 +47,7 @@ DisplayForm::DisplayForm(int nplots, QWidget* parent) _grid_state = false; // Create a pop-up menu for manipulating the figure + _menu_on = true; _menu = new QMenu(this); _menu->addAction(_stop_act); _menu->addAction(_grid_act); @@ -130,7 +131,7 @@ DisplayForm::resizeEvent( QResizeEvent *e ) void DisplayForm::mousePressEvent( QMouseEvent * e) { - if(e->button() == Qt::RightButton) { + if((e->button() == Qt::RightButton) && (_menu_on)) { QwtPlotLayout *plt = _displayPlot->plotLayout(); QRectF cvs = plt->canvasRect(); @@ -153,7 +154,7 @@ DisplayForm::mousePressEvent( QMouseEvent * e) // Update the line titles if changed externally for(int i = 0; i < _nplots; i++) { - _lines_menu[i]->setTitle(_displayPlot->lineLabel(i)); + _lines_menu[i]->setTitle(_displayPlot->getLineLabel(i)); } _menu->exec(e->globalPos()); } @@ -177,6 +178,11 @@ DisplayForm::Reset() { } +void +DisplayForm::enableMenu(bool en) +{ + _menu_on = en; +} void DisplayForm::closeEvent( QCloseEvent *e ) @@ -240,6 +246,48 @@ DisplayForm::setMarkerAlpha(int which, int alpha) _displayPlot->replot(); } +QString +DisplayForm::title() +{ + return _displayPlot->title().text(); +} + +QString +DisplayForm::lineLabel(int which) +{ + return _displayPlot->getLineLabel(which); +} + +QString +DisplayForm::lineColor(int which) +{ + return _displayPlot->getLineColor(which).name(); +} + +int +DisplayForm::lineWidth(int which) +{ + return _displayPlot->getLineWidth(which); +} + +Qt::PenStyle +DisplayForm::lineStyle(int which) +{ + return _displayPlot->getLineStyle(which); +} + +QwtSymbol::Style +DisplayForm::lineMarker(int which) +{ + return _displayPlot->getLineMarker(which); +} + +int +DisplayForm::markerAlpha(int which) +{ + return _displayPlot->getMarkerAlpha(which); +} + void DisplayForm::setStop(bool on) { diff --git a/gr-qtgui/lib/displayform.h b/gr-qtgui/lib/displayform.h index 99b0e714f4..542ad51d9d 100644 --- a/gr-qtgui/lib/displayform.h +++ b/gr-qtgui/lib/displayform.h @@ -44,6 +44,8 @@ class DisplayForm : public QWidget virtual DisplayPlot* getPlot() = 0; void Reset(); + void enableMenu(bool en=true); + public slots: void resizeEvent( QResizeEvent * e ); void mousePressEvent( QMouseEvent * e); @@ -61,6 +63,14 @@ public slots: void setLineMarker(int which, QwtSymbol::Style style); void setMarkerAlpha(int which, int alpha); + QString title(); + QString lineLabel(int which); + QString lineColor(int which); + int lineWidth(int which); + Qt::PenStyle lineStyle(int which); + QwtSymbol::Style lineMarker(int which); + int markerAlpha(int which); + void setStop(bool on); void setStop(); @@ -87,6 +97,7 @@ protected: QwtPlotGrid *_grid; + bool _menu_on; QMenu *_menu; QAction *_stop_act; diff --git a/gr-qtgui/lib/form_menus.h b/gr-qtgui/lib/form_menus.h index c84ecbfb44..63ab35ed95 100644 --- a/gr-qtgui/lib/form_menus.h +++ b/gr-qtgui/lib/form_menus.h @@ -359,11 +359,13 @@ public: d_act.push_back(new QAction("Low", this)); d_act.push_back(new QAction("Medium", this)); d_act.push_back(new QAction("High", this)); + d_act.push_back(new QAction("Off", this)); connect(d_act[0], SIGNAL(triggered()), this, SLOT(getNone())); connect(d_act[1], SIGNAL(triggered()), this, SLOT(getLow())); connect(d_act[2], SIGNAL(triggered()), this, SLOT(getMedium())); connect(d_act[3], SIGNAL(triggered()), this, SLOT(getHigh())); + connect(d_act[4], SIGNAL(triggered()), this, SLOT(getOff())); QListIterator<QAction*> i(d_act); while(i.hasNext()) { @@ -396,6 +398,7 @@ public slots: void getLow() { emit whichTrigger(d_which, 200); } void getMedium() { emit whichTrigger(d_which, 125); } void getHigh() { emit whichTrigger(d_which, 50); } + void getOff() { emit whichTrigger(d_which, 0); } private: QList<QAction *> d_act; @@ -864,8 +867,8 @@ class ColorMapMenu: public QMenu Q_OBJECT public: - ColorMapMenu(QWidget *parent) - : QMenu("Color Map", parent) + ColorMapMenu(int which, QWidget *parent) + : QMenu("Color Map", parent), d_which(which) { d_act.push_back(new QAction("Multi-Color", this)); d_act.push_back(new QAction("White Hot", this)); @@ -907,15 +910,16 @@ public: } signals: - void whichTrigger(const int type, const QColor &min_color=QColor(), + void whichTrigger(int which, const int type, + const QColor &min_color=QColor(), const QColor &max_color=QColor()); public slots: - void getMultiColor() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR); } - void getWhiteHot() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_WHITE_HOT); } - void getBlackHot() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_BLACK_HOT); } - void getIncandescent() { emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_INCANDESCENT); } - //void getOther(const QString &min_str, const QString &max_str) + void getMultiColor() { emit whichTrigger(d_which, INTENSITY_COLOR_MAP_TYPE_MULTI_COLOR); } + void getWhiteHot() { emit whichTrigger(d_which, INTENSITY_COLOR_MAP_TYPE_WHITE_HOT); } + void getBlackHot() { emit whichTrigger(d_which, INTENSITY_COLOR_MAP_TYPE_BLACK_HOT); } + void getIncandescent() { emit whichTrigger(d_which, INTENSITY_COLOR_MAP_TYPE_INCANDESCENT); } + //void getOther(d_which, const QString &min_str, const QString &max_str) void getOther() { QMessageBox::information(this, "Set low and high intensities", @@ -924,7 +928,7 @@ public: d_min_value = QColorDialog::getColor(d_min_value, this); d_max_value = QColorDialog::getColor(d_max_value, this); - emit whichTrigger(INTENSITY_COLOR_MAP_TYPE_USER_DEFINED, + emit whichTrigger(d_which, INTENSITY_COLOR_MAP_TYPE_USER_DEFINED, d_min_value, d_max_value); } @@ -932,6 +936,62 @@ private: QList<QAction *> d_act; OtherDualAction *d_other; QColor d_max_value, d_min_value; + int d_which; +}; + + +/********************************************************************/ + + +class PopupMenu: public QAction +{ + Q_OBJECT + +public: + PopupMenu(QString desc, QWidget *parent) + : QAction(desc, parent) + { + d_diag = new QDialog(parent); + d_diag->setModal(true); + + d_text = new QLineEdit(); + + QGridLayout *layout = new QGridLayout(d_diag); + QPushButton *btn_ok = new QPushButton(tr("OK")); + QPushButton *btn_cancel = new QPushButton(tr("Cancel")); + + layout->addWidget(d_text, 0, 0, 1, 2); + layout->addWidget(btn_ok, 1, 0); + layout->addWidget(btn_cancel, 1, 1); + + connect(btn_ok, SIGNAL(clicked()), this, SLOT(getText())); + connect(btn_cancel, SIGNAL(clicked()), d_diag, SLOT(close())); + + connect(this, SIGNAL(triggered()), this, SLOT(getTextDiag())); + } + + ~PopupMenu() + {} + +signals: + void whichTrigger(const QString data); + +public slots: + void getTextDiag() + { + d_diag->show(); + } + +private slots: + void getText() + { + emit whichTrigger(d_text->text()); + d_diag->accept(); + } + +private: + QDialog *d_diag; + QLineEdit *d_text; }; diff --git a/gr-qtgui/lib/freq_sink_c_impl.cc b/gr-qtgui/lib/freq_sink_c_impl.cc index 2db5cf56bb..78d7431b20 100644 --- a/gr-qtgui/lib/freq_sink_c_impl.cc +++ b/gr-qtgui/lib/freq_sink_c_impl.cc @@ -28,6 +28,7 @@ #include <gr_io_signature.h> #include <string.h> #include <volk/volk.h> +#include <qwt_symbol.h> namespace gr { namespace qtgui { @@ -121,8 +122,7 @@ namespace gr { } d_main_gui = new FreqDisplayForm(d_nconnections, d_parent); - d_main_gui->setFFTWindowType(d_wintype); - + set_fft_window(d_wintype); set_fft_size(d_fftsize); set_frequency_range(d_center_freq, d_bandwidth); @@ -154,7 +154,6 @@ namespace gr { void freq_sink_c_impl::set_fft_size(const int fftsize) { - d_fftsize = fftsize; d_main_gui->setFFTSize(fftsize); } @@ -167,7 +166,6 @@ namespace gr { void freq_sink_c_impl::set_fft_average(const float fftavg) { - d_fftavg = fftavg; d_main_gui->setFFTAverage(fftavg); } @@ -178,6 +176,18 @@ namespace gr { } void + freq_sink_c_impl::set_fft_window(const filter::firdes::win_type win) + { + d_main_gui->setFFTWindowType(win); + } + + filter::firdes::win_type + freq_sink_c_impl::fft_window() + { + return d_wintype; + } + + void freq_sink_c_impl::set_frequency_range(const double centerfreq, const double bandwidth) { @@ -226,15 +236,21 @@ namespace gr { } void - freq_sink_c_impl::set_line_style(int which, Qt::PenStyle style) + freq_sink_c_impl::set_line_style(int which, int style) + { + d_main_gui->setLineStyle(which, (Qt::PenStyle)style); + } + + void + freq_sink_c_impl::set_line_marker(int which, int marker) { - d_main_gui->setLineStyle(which, style); + d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker); } void - freq_sink_c_impl::set_line_marker(int which, QwtSymbol::Style marker) + freq_sink_c_impl::set_line_alpha(int which, double alpha) { - d_main_gui->setLineMarker(which, marker); + d_main_gui->setMarkerAlpha(which, (int)(255.0*alpha)); } void @@ -243,6 +259,60 @@ namespace gr { d_main_gui->resize(QSize(width, height)); } + std::string + freq_sink_c_impl::title() + { + return d_main_gui->title().toStdString(); + } + + std::string + freq_sink_c_impl::line_label(int which) + { + return d_main_gui->lineLabel(which).toStdString(); + } + + std::string + freq_sink_c_impl::line_color(int which) + { + return d_main_gui->lineColor(which).toStdString(); + } + + int + freq_sink_c_impl::line_width(int which) + { + return d_main_gui->lineWidth(which); + } + + int + freq_sink_c_impl::line_style(int which) + { + return d_main_gui->lineStyle(which); + } + + int + freq_sink_c_impl::line_marker(int which) + { + return d_main_gui->lineMarker(which); + } + + double + freq_sink_c_impl::line_alpha(int which) + { + return (double)(d_main_gui->markerAlpha(which))/255.0; + } + + void + freq_sink_c_impl::enable_menu(bool en) + { + d_main_gui->enableMenu(en); + } + + void + freq_sink_c_impl::enable_grid(bool en) + { + d_main_gui->setGrid(en); + } + void freq_sink_c_impl::reset() { diff --git a/gr-qtgui/lib/freq_sink_c_impl.h b/gr-qtgui/lib/freq_sink_c_impl.h index 4bcf93b372..77a625eb13 100644 --- a/gr-qtgui/lib/freq_sink_c_impl.h +++ b/gr-qtgui/lib/freq_sink_c_impl.h @@ -88,20 +88,34 @@ namespace gr { int fft_size() const; void set_fft_average(const float fftavg); float fft_average() const; + void set_fft_window(const filter::firdes::win_type win); + filter::firdes::win_type fft_window(); void set_frequency_range(const double centerfreq, const double bandwidth); void set_y_axis(double min, double max); void set_update_time(double t); + void set_title(const std::string &title); void set_line_label(int which, const std::string &label); void set_line_color(int which, const std::string &color); void set_line_width(int which, int width); - void set_line_style(int which, Qt::PenStyle style); - void set_line_marker(int which, QwtSymbol::Style marker); + void set_line_style(int which, int style); + void set_line_marker(int which, int marker); + void set_line_alpha(int which, double alpha); + + std::string title(); + std::string line_label(int which); + std::string line_color(int which); + int line_width(int which); + int line_style(int which); + int line_marker(int which); + double line_alpha(int which); void set_size(int width, int height); + void enable_menu(bool en); + void enable_grid(bool en); void reset(); int work(int noutput_items, diff --git a/gr-qtgui/lib/freq_sink_f_impl.cc b/gr-qtgui/lib/freq_sink_f_impl.cc index c0edf415a5..457235df6f 100644 --- a/gr-qtgui/lib/freq_sink_f_impl.cc +++ b/gr-qtgui/lib/freq_sink_f_impl.cc @@ -28,6 +28,7 @@ #include <gr_io_signature.h> #include <string.h> #include <volk/volk.h> +#include <qwt_symbol.h> namespace gr { namespace qtgui { @@ -121,7 +122,7 @@ namespace gr { } d_main_gui = new FreqDisplayForm(d_nconnections, d_parent); - d_main_gui->setFFTWindowType(d_wintype); + set_fft_window(d_wintype); set_fft_size(d_fftsize); set_frequency_range(d_center_freq, d_bandwidth/2.0); @@ -153,7 +154,6 @@ namespace gr { void freq_sink_f_impl::set_fft_size(const int fftsize) { - d_fftsize = fftsize; d_main_gui->setFFTSize(fftsize); } @@ -166,7 +166,6 @@ namespace gr { void freq_sink_f_impl::set_fft_average(const float fftavg) { - d_fftavg = fftavg; d_main_gui->setFFTAverage(fftavg); } @@ -177,6 +176,18 @@ namespace gr { } void + freq_sink_f_impl::set_fft_window(const filter::firdes::win_type win) + { + d_main_gui->setFFTWindowType(win); + } + + filter::firdes::win_type + freq_sink_f_impl::fft_window() + { + return d_wintype; + } + + void freq_sink_f_impl::set_frequency_range(const double centerfreq, const double bandwidth) { @@ -225,17 +236,22 @@ namespace gr { } void - freq_sink_f_impl::set_line_style(int which, Qt::PenStyle style) + freq_sink_f_impl::set_line_style(int which, int style) { - d_main_gui->setLineStyle(which, style); + d_main_gui->setLineStyle(which, (Qt::PenStyle)style); } void - freq_sink_f_impl::set_line_marker(int which, QwtSymbol::Style marker) + freq_sink_f_impl::set_line_marker(int which, int marker) { - d_main_gui->setLineMarker(which, marker); + d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker); } + void + freq_sink_f_impl::set_line_alpha(int which, double alpha) + { + d_main_gui->setMarkerAlpha(which, (int)(255.0*alpha)); + } void freq_sink_f_impl::set_size(int width, int height) @@ -243,6 +259,60 @@ namespace gr { d_main_gui->resize(QSize(width, height)); } + std::string + freq_sink_f_impl::title() + { + return d_main_gui->title().toStdString(); + } + + std::string + freq_sink_f_impl::line_label(int which) + { + return d_main_gui->lineLabel(which).toStdString(); + } + + std::string + freq_sink_f_impl::line_color(int which) + { + return d_main_gui->lineColor(which).toStdString(); + } + + int + freq_sink_f_impl::line_width(int which) + { + return d_main_gui->lineWidth(which); + } + + int + freq_sink_f_impl::line_style(int which) + { + return d_main_gui->lineStyle(which); + } + + int + freq_sink_f_impl::line_marker(int which) + { + return d_main_gui->lineMarker(which); + } + + double + freq_sink_f_impl::line_alpha(int which) + { + return (double)(d_main_gui->markerAlpha(which))/255.0; + } + + void + freq_sink_f_impl::enable_menu(bool en) + { + d_main_gui->enableMenu(en); + } + + void + freq_sink_f_impl::enable_grid(bool en) + { + d_main_gui->setGrid(en); + } + void freq_sink_f_impl::reset() { diff --git a/gr-qtgui/lib/freq_sink_f_impl.h b/gr-qtgui/lib/freq_sink_f_impl.h index 8e3fbf1edc..d0a6b2c14b 100644 --- a/gr-qtgui/lib/freq_sink_f_impl.h +++ b/gr-qtgui/lib/freq_sink_f_impl.h @@ -88,6 +88,8 @@ namespace gr { int fft_size() const; void set_fft_average(const float fftavg); float fft_average() const; + void set_fft_window(const filter::firdes::win_type win); + filter::firdes::win_type fft_window(); void set_frequency_range(const double centerfreq, const double bandwidth); void set_y_axis(double min, double max); @@ -97,11 +99,22 @@ namespace gr { void set_line_label(int which, const std::string &label); void set_line_color(int which, const std::string &color); void set_line_width(int which, int width); - void set_line_style(int which, Qt::PenStyle style); - void set_line_marker(int which, QwtSymbol::Style marker); + void set_line_style(int which, int style); + void set_line_marker(int which, int marker); + void set_line_alpha(int which, double alpha); + + std::string title(); + std::string line_label(int which); + std::string line_color(int which); + int line_width(int which); + int line_style(int which); + int line_marker(int which); + double line_alpha(int which); void set_size(int width, int height); + void enable_menu(bool en); + void enable_grid(bool en); void reset(); int work(int noutput_items, diff --git a/gr-qtgui/lib/freqdisplayform.cc b/gr-qtgui/lib/freqdisplayform.cc index 4163acc826..938c9cc550 100644 --- a/gr-qtgui/lib/freqdisplayform.cc +++ b/gr-qtgui/lib/freqdisplayform.cc @@ -114,6 +114,7 @@ void FreqDisplayForm::setFFTSize(const int newsize) { _fftsize = newsize; + getPlot()->replot(); } void @@ -127,6 +128,7 @@ void FreqDisplayForm::setFFTWindowType(const gr::filter::firdes::win_type newwin) { _fftwintype = newwin; + getPlot()->replot(); } void diff --git a/gr-qtgui/lib/time_sink_c_impl.cc b/gr-qtgui/lib/time_sink_c_impl.cc index 497aeb512d..46db6315eb 100644 --- a/gr-qtgui/lib/time_sink_c_impl.cc +++ b/gr-qtgui/lib/time_sink_c_impl.cc @@ -29,6 +29,7 @@ #include <string.h> #include <volk/volk.h> #include <fft/fft.h> +#include <qwt_symbol.h> namespace gr { namespace qtgui { @@ -165,15 +166,21 @@ namespace gr { } void - time_sink_c_impl::set_line_style(int which, Qt::PenStyle style) + time_sink_c_impl::set_line_style(int which, int style) { - d_main_gui->setLineStyle(which, style); + d_main_gui->setLineStyle(which, (Qt::PenStyle)style); } void - time_sink_c_impl::set_line_marker(int which, QwtSymbol::Style marker) + time_sink_c_impl::set_line_marker(int which, int marker) { - d_main_gui->setLineMarker(which, marker); + d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker); + } + + void + time_sink_c_impl::set_line_alpha(int which, double alpha) + { + d_main_gui->setMarkerAlpha(which, (int)(255.0*alpha)); } void @@ -182,6 +189,48 @@ namespace gr { d_main_gui->resize(QSize(width, height)); } + std::string + time_sink_c_impl::title() + { + return d_main_gui->title().toStdString(); + } + + std::string + time_sink_c_impl::line_label(int which) + { + return d_main_gui->lineLabel(which).toStdString(); + } + + std::string + time_sink_c_impl::line_color(int which) + { + return d_main_gui->lineColor(which).toStdString(); + } + + int + time_sink_c_impl::line_width(int which) + { + return d_main_gui->lineWidth(which); + } + + int + time_sink_c_impl::line_style(int which) + { + return d_main_gui->lineStyle(which); + } + + int + time_sink_c_impl::line_marker(int which) + { + return d_main_gui->lineMarker(which); + } + + double + time_sink_c_impl::line_alpha(int which) + { + return (double)(d_main_gui->markerAlpha(which))/255.0; + } + void time_sink_c_impl::set_nsamps(const int newsize) { @@ -227,6 +276,24 @@ namespace gr { } void + time_sink_c_impl::enable_menu(bool en) + { + d_main_gui->enableMenu(en); + } + + void + time_sink_c_impl::enable_grid(bool en) + { + d_main_gui->setGrid(en); + } + + void + time_sink_c_impl::toggle_stem_plot() + { + d_main_gui->setStem(); + } + + void time_sink_c_impl::reset() { d_index = 0; diff --git a/gr-qtgui/lib/time_sink_c_impl.h b/gr-qtgui/lib/time_sink_c_impl.h index e728351246..bccb7b1197 100644 --- a/gr-qtgui/lib/time_sink_c_impl.h +++ b/gr-qtgui/lib/time_sink_c_impl.h @@ -73,15 +73,27 @@ namespace gr { void set_line_label(int which, const std::string &label); void set_line_color(int which, const std::string &color); void set_line_width(int which, int width); - void set_line_style(int which, Qt::PenStyle style); - void set_line_marker(int which, QwtSymbol::Style marker); + void set_line_style(int which, int style); + void set_line_marker(int which, int marker); void set_nsamps(const int size); void set_samp_rate(const double samp_rate); + void set_line_alpha(int which, double alpha); - void set_size(int width, int height); + std::string title(); + std::string line_label(int which); + std::string line_color(int which); + int line_width(int which); + int line_style(int which); + int line_marker(int which); + double line_alpha(int which); + void set_size(int width, int height); + int nsamps() const; + void enable_menu(bool en); + void enable_grid(bool en); + void toggle_stem_plot(); void reset(); int work(int noutput_items, diff --git a/gr-qtgui/lib/time_sink_f_impl.cc b/gr-qtgui/lib/time_sink_f_impl.cc index 61705218ff..06854c71e7 100644 --- a/gr-qtgui/lib/time_sink_f_impl.cc +++ b/gr-qtgui/lib/time_sink_f_impl.cc @@ -29,6 +29,7 @@ #include <string.h> #include <volk/volk.h> #include <fft/fft.h> +#include <qwt_symbol.h> namespace gr { namespace qtgui { @@ -165,15 +166,21 @@ namespace gr { } void - time_sink_f_impl::set_line_style(int which, Qt::PenStyle style) + time_sink_f_impl::set_line_style(int which, int style) { - d_main_gui->setLineStyle(which, style); + d_main_gui->setLineStyle(which, (Qt::PenStyle)style); } void - time_sink_f_impl::set_line_marker(int which, QwtSymbol::Style marker) + time_sink_f_impl::set_line_marker(int which, int marker) { - d_main_gui->setLineMarker(which, marker); + d_main_gui->setLineMarker(which, (QwtSymbol::Style)marker); + } + + void + time_sink_f_impl::set_line_alpha(int which, double alpha) + { + d_main_gui->setMarkerAlpha(which, (int)(255.0*alpha)); } void @@ -182,6 +189,48 @@ namespace gr { d_main_gui->resize(QSize(width, height)); } + std::string + time_sink_f_impl::title() + { + return d_main_gui->title().toStdString(); + } + + std::string + time_sink_f_impl::line_label(int which) + { + return d_main_gui->lineLabel(which).toStdString(); + } + + std::string + time_sink_f_impl::line_color(int which) + { + return d_main_gui->lineColor(which).toStdString(); + } + + int + time_sink_f_impl::line_width(int which) + { + return d_main_gui->lineWidth(which); + } + + int + time_sink_f_impl::line_style(int which) + { + return d_main_gui->lineStyle(which); + } + + int + time_sink_f_impl::line_marker(int which) + { + return d_main_gui->lineMarker(which); + } + + double + time_sink_f_impl::line_alpha(int which) + { + return (double)(d_main_gui->markerAlpha(which))/255.0; + } + void time_sink_f_impl::set_nsamps(const int newsize) { @@ -227,6 +276,24 @@ namespace gr { } void + time_sink_f_impl::toggle_stem_plot() + { + d_main_gui->setStem(); + } + + void + time_sink_f_impl::enable_menu(bool en) + { + d_main_gui->enableMenu(en); + } + + void + time_sink_f_impl::enable_grid(bool en) + { + d_main_gui->setGrid(en); + } + + void time_sink_f_impl::reset() { d_index = 0; diff --git a/gr-qtgui/lib/time_sink_f_impl.h b/gr-qtgui/lib/time_sink_f_impl.h index 065397bb78..b6aafb19b7 100644 --- a/gr-qtgui/lib/time_sink_f_impl.h +++ b/gr-qtgui/lib/time_sink_f_impl.h @@ -73,15 +73,27 @@ namespace gr { void set_line_label(int which, const std::string &label); void set_line_color(int which, const std::string &color); void set_line_width(int which, int width); - void set_line_style(int which, Qt::PenStyle style); - void set_line_marker(int which, QwtSymbol::Style marker); + void set_line_style(int which, int style); + void set_line_marker(int which, int marker); void set_nsamps(const int newsize); void set_samp_rate(const double samp_rate); + void set_line_alpha(int which, double alpha); + + std::string title(); + std::string line_label(int which); + std::string line_color(int which); + int line_width(int which); + int line_style(int which); + int line_marker(int which); + double line_alpha(int which); void set_size(int width, int height); int nsamps() const; + void enable_menu(bool en); + void enable_grid(bool en); + void toggle_stem_plot(); void reset(); int work(int noutput_items, diff --git a/gr-qtgui/lib/timedisplayform.cc b/gr-qtgui/lib/timedisplayform.cc index 11ceefff3e..95bcde4f27 100644 --- a/gr-qtgui/lib/timedisplayform.cc +++ b/gr-qtgui/lib/timedisplayform.cc @@ -28,6 +28,8 @@ TimeDisplayForm::TimeDisplayForm(int nplots, QWidget* parent) : DisplayForm(nplots, parent) { + d_stem = false; + _intValidator = new QIntValidator(this); _intValidator->setBottom(0); @@ -41,6 +43,11 @@ TimeDisplayForm::TimeDisplayForm(int nplots, QWidget* parent) connect(nptsmenu, SIGNAL(whichTrigger(int)), this, SLOT(setNPoints(const int))); + QAction *stemmenu = new QAction("Stem Plot", this); + _menu->addAction(stemmenu); + connect(stemmenu, SIGNAL(triggered(bool)), + this, SLOT(setStem(bool))); + Reset(); connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)), @@ -115,3 +122,10 @@ TimeDisplayForm::setNPoints(const int npoints) { d_npoints = npoints; } + +void +TimeDisplayForm::setStem(bool trig) +{ + d_stem ^= 1; + getPlot()->stemPlot(d_stem); +} diff --git a/gr-qtgui/lib/timedisplayform.h b/gr-qtgui/lib/timedisplayform.h index df8803c145..f8d059e388 100644 --- a/gr-qtgui/lib/timedisplayform.h +++ b/gr-qtgui/lib/timedisplayform.h @@ -48,6 +48,7 @@ public slots: void setSampleRate(const double samprate); void setYaxis(double min, double max); void setNPoints(const int); + void setStem(bool trig=false); private slots: void newData(const QEvent*); @@ -59,6 +60,8 @@ private: double _stopFrequency; int d_npoints; + + bool d_stem; }; #endif /* TIME_DISPLAY_FORM_H */ diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.cc b/gr-qtgui/lib/waterfall_sink_c_impl.cc index 99a9d89dc9..e182d3c141 100644 --- a/gr-qtgui/lib/waterfall_sink_c_impl.cc +++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc @@ -28,6 +28,7 @@ #include <gr_io_signature.h> #include <string.h> #include <volk/volk.h> +#include <qwt_symbol.h> namespace gr { namespace qtgui { @@ -36,25 +37,28 @@ namespace gr { waterfall_sink_c::make(int fftsize, int wintype, double fc, double bw, const std::string &name, + int nconnections, QWidget *parent) { return gnuradio::get_initial_sptr (new waterfall_sink_c_impl(fftsize, wintype, fc, bw, name, + nconnections, parent)); } waterfall_sink_c_impl::waterfall_sink_c_impl(int fftsize, int wintype, double fc, double bw, const std::string &name, + int nconnections, QWidget *parent) : gr_sync_block("waterfall_sink_c", - gr_make_io_signature(1, -1, sizeof(gr_complex)), + gr_make_io_signature(1, nconnections, sizeof(gr_complex)), gr_make_io_signature(0, 0, 0)), d_fftsize(fftsize), d_fftavg(1.0), d_wintype((filter::firdes::win_type)(wintype)), d_center_freq(fc), d_bandwidth(bw), d_name(name), - d_nconnections(1), d_parent(parent) + d_nconnections(nconnections), d_parent(parent) { d_main_gui = NULL; @@ -117,7 +121,7 @@ namespace gr { } d_main_gui = new WaterfallDisplayForm(d_nconnections, d_parent); - d_main_gui->setFFTWindowType(d_wintype); + set_fft_window(d_wintype); set_fft_size(d_fftsize); set_frequency_range(d_center_freq, d_bandwidth); @@ -147,9 +151,14 @@ namespace gr { } void + waterfall_sink_c_impl::clear_data() + { + d_main_gui->clearData(); + } + + void waterfall_sink_c_impl::set_fft_size(const int fftsize) { - d_fftsize = fftsize; d_main_gui->setFFTSize(fftsize); } @@ -162,7 +171,6 @@ namespace gr { void waterfall_sink_c_impl::set_fft_average(const float fftavg) { - d_fftavg = fftavg; d_main_gui->setFFTAverage(fftavg); } @@ -173,6 +181,18 @@ namespace gr { } void + waterfall_sink_c_impl::set_fft_window(const filter::firdes::win_type win) + { + d_main_gui->setFFTWindowType(win); + } + + filter::firdes::win_type + waterfall_sink_c_impl::fft_window() + { + return d_wintype; + } + + void waterfall_sink_c_impl::set_frequency_range(const double centerfreq, const double bandwidth) { @@ -182,6 +202,13 @@ namespace gr { } void + waterfall_sink_c_impl::set_intensity_range(const double min, + const double max) + { + d_main_gui->setIntensityRange(min, max); + } + + void waterfall_sink_c_impl::set_update_time(double t) { //convert update time to ticks @@ -197,39 +224,81 @@ namespace gr { } void - waterfall_sink_c_impl::set_line_label(const std::string &label) + waterfall_sink_c_impl::set_line_label(int which, const std::string &label) + { + d_main_gui->setLineLabel(which, label.c_str()); + } + + void + waterfall_sink_c_impl::set_color_map(int which, const int color) { - d_main_gui->setLineLabel(0, label.c_str()); + d_main_gui->setColorMap(which, color); } void - waterfall_sink_c_impl::set_line_color(const std::string &color) + waterfall_sink_c_impl::set_line_alpha(int which, double alpha) { - d_main_gui->setLineColor(0, color.c_str()); + d_main_gui->setAlpha(which, (int)(255.0*alpha)); } void - waterfall_sink_c_impl::set_line_width(int width) + waterfall_sink_c_impl::set_size(int width, int height) + { + d_main_gui->resize(QSize(width, height)); + } + + std::string + waterfall_sink_c_impl::title() + { + return d_main_gui->title().toStdString(); + } + + std::string + waterfall_sink_c_impl::line_label(int which) { - d_main_gui->setLineWidth(0, width); + return d_main_gui->lineLabel(which).toStdString(); + } + + int + waterfall_sink_c_impl::color_map(int which) + { + return d_main_gui->getColorMap(which); + } + + double + waterfall_sink_c_impl::line_alpha(int which) + { + return (double)(d_main_gui->markerAlpha(which))/255.0; } void - waterfall_sink_c_impl::set_line_style(Qt::PenStyle style) + waterfall_sink_c_impl::auto_scale() + { + d_main_gui->autoScale(); + } + + double + waterfall_sink_c_impl::min_intensity(int which) { - d_main_gui->setLineStyle(0, style); + return d_main_gui->getMinIntensity(which); + } + + double + waterfall_sink_c_impl::max_intensity(int which) + { + return d_main_gui->getMaxIntensity(which); } void - waterfall_sink_c_impl::set_line_marker(QwtSymbol::Style marker) + waterfall_sink_c_impl::enable_menu(bool en) { - d_main_gui->setLineMarker(0, marker); + d_main_gui->enableMenu(en); } void - waterfall_sink_c_impl::set_size(int width, int height) + waterfall_sink_c_impl::enable_grid(bool en) { - d_main_gui->resize(QSize(width, height)); + d_main_gui->setGrid(en); } void diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.h b/gr-qtgui/lib/waterfall_sink_c_impl.h index 3356059bc4..1d709c6c5f 100644 --- a/gr-qtgui/lib/waterfall_sink_c_impl.h +++ b/gr-qtgui/lib/waterfall_sink_c_impl.h @@ -72,6 +72,7 @@ namespace gr { waterfall_sink_c_impl(int size, int wintype, double fc, double bw, const std::string &name, + int nconnections, QWidget *parent=NULL); ~waterfall_sink_c_impl(); @@ -81,23 +82,38 @@ namespace gr { QWidget* qwidget(); PyObject* pyqwidget(); + void clear_data(); + void set_fft_size(const int fftsize); int fft_size() const; void set_fft_average(const float fftavg); float fft_average() const; + void set_fft_window(const gr::filter::firdes::win_type win); + gr::filter::firdes::win_type fft_window(); void set_frequency_range(const double centerfreq, const double bandwidth); + void set_intensity_range(const double min, const double max); void set_update_time(double t); void set_title(const std::string &title); - void set_line_label(const std::string &label); - void set_line_color(const std::string &color); - void set_line_width(int width); - void set_line_style(Qt::PenStyle style); - void set_line_marker(QwtSymbol::Style marker); + void set_line_label(int which, const std::string &label); + void set_line_alpha(int which, double alpha); + void set_color_map(int which, const int color); + + std::string title(); + std::string line_label(int which); + double line_alpha(int which); + int color_map(int which); void set_size(int width, int height); + void auto_scale(); + double min_intensity(int which); + double max_intensity(int which); + + void enable_menu(bool en); + void enable_grid(bool en); + int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc b/gr-qtgui/lib/waterfall_sink_f_impl.cc index 6d4888f5e7..d59319fd27 100644 --- a/gr-qtgui/lib/waterfall_sink_f_impl.cc +++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc @@ -36,17 +36,20 @@ namespace gr { waterfall_sink_f::make(int fftsize, int wintype, double fc, double bw, const std::string &name, + int nconnections, QWidget *parent) { return gnuradio::get_initial_sptr (new waterfall_sink_f_impl(fftsize, wintype, fc, bw, name, + nconnections, parent)); } waterfall_sink_f_impl::waterfall_sink_f_impl(int fftsize, int wintype, double fc, double bw, const std::string &name, + int nconnections, QWidget *parent) : gr_sync_block("waterfall_sink_f", gr_make_io_signature(1, -1, sizeof(float)), @@ -54,7 +57,7 @@ namespace gr { d_fftsize(fftsize), d_fftavg(1.0), d_wintype((filter::firdes::win_type)(wintype)), d_center_freq(fc), d_bandwidth(bw), d_name(name), - d_nconnections(1), d_parent(parent) + d_nconnections(nconnections), d_parent(parent) { d_main_gui = NULL; @@ -117,7 +120,7 @@ namespace gr { } d_main_gui = new WaterfallDisplayForm(d_nconnections, d_parent); - d_main_gui->setFFTWindowType(d_wintype); + set_fft_window(d_wintype); set_fft_size(d_fftsize); set_frequency_range(d_center_freq, d_bandwidth); @@ -147,9 +150,14 @@ namespace gr { } void + waterfall_sink_f_impl::clear_data() + { + d_main_gui->clearData(); + } + + void waterfall_sink_f_impl::set_fft_size(const int fftsize) { - d_fftsize = fftsize; d_main_gui->setFFTSize(fftsize); } @@ -162,7 +170,6 @@ namespace gr { void waterfall_sink_f_impl::set_fft_average(const float fftavg) { - d_fftavg = fftavg; d_main_gui->setFFTAverage(fftavg); } @@ -173,6 +180,18 @@ namespace gr { } void + waterfall_sink_f_impl::set_fft_window(const filter::firdes::win_type win) + { + d_main_gui->setFFTWindowType(win); + } + + filter::firdes::win_type + waterfall_sink_f_impl::fft_window() + { + return d_wintype; + } + + void waterfall_sink_f_impl::set_frequency_range(const double centerfreq, const double bandwidth) { @@ -182,6 +201,13 @@ namespace gr { } void + waterfall_sink_f_impl::set_intensity_range(const double min, + const double max) + { + d_main_gui->setIntensityRange(min, max); + } + + void waterfall_sink_f_impl::set_update_time(double t) { //convert update time to ticks @@ -197,39 +223,81 @@ namespace gr { } void - waterfall_sink_f_impl::set_line_label(const std::string &label) + waterfall_sink_f_impl::set_line_label(int which, const std::string &label) + { + d_main_gui->setLineLabel(which, label.c_str()); + } + + void + waterfall_sink_f_impl::set_color_map(int which, const int color) { - d_main_gui->setLineLabel(0, label.c_str()); + d_main_gui->setColorMap(which, color); } void - waterfall_sink_f_impl::set_line_color(const std::string &color) + waterfall_sink_f_impl::set_line_alpha(int which, double alpha) { - d_main_gui->setLineColor(0, color.c_str()); + d_main_gui->setAlpha(which, (int)(255.0*alpha)); } void - waterfall_sink_f_impl::set_line_width(int width) + waterfall_sink_f_impl::set_size(int width, int height) + { + d_main_gui->resize(QSize(width, height)); + } + + std::string + waterfall_sink_f_impl::title() + { + return d_main_gui->title().toStdString(); + } + + std::string + waterfall_sink_f_impl::line_label(int which) { - d_main_gui->setLineWidth(0, width); + return d_main_gui->lineLabel(which).toStdString(); + } + + int + waterfall_sink_f_impl::color_map(int which) + { + return d_main_gui->getColorMap(which); + } + + double + waterfall_sink_f_impl::line_alpha(int which) + { + return (double)(d_main_gui->getAlpha(which))/255.0; } void - waterfall_sink_f_impl::set_line_style(Qt::PenStyle style) + waterfall_sink_f_impl::auto_scale() + { + d_main_gui->autoScale(); + } + + double + waterfall_sink_f_impl::min_intensity(int which) { - d_main_gui->setLineStyle(0, style); + return d_main_gui->getMinIntensity(which); + } + + double + waterfall_sink_f_impl::max_intensity(int which) + { + return d_main_gui->getMaxIntensity(which); } void - waterfall_sink_f_impl::set_line_marker(QwtSymbol::Style marker) + waterfall_sink_f_impl::enable_menu(bool en) { - d_main_gui->setLineMarker(0, marker); + d_main_gui->enableMenu(en); } void - waterfall_sink_f_impl::set_size(int width, int height) + waterfall_sink_f_impl::enable_grid(bool en) { - d_main_gui->resize(QSize(width, height)); + d_main_gui->setGrid(en); } void diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.h b/gr-qtgui/lib/waterfall_sink_f_impl.h index 6043363545..6185a25397 100644 --- a/gr-qtgui/lib/waterfall_sink_f_impl.h +++ b/gr-qtgui/lib/waterfall_sink_f_impl.h @@ -71,9 +71,10 @@ namespace gr { public: waterfall_sink_f_impl(int size, int wintype, - double fc, double bw, - const std::string &name, - QWidget *parent=NULL); + double fc, double bw, + const std::string &name, + int nconnections, + QWidget *parent=NULL); ~waterfall_sink_f_impl(); bool check_topology(int ninputs, int noutputs); @@ -82,23 +83,38 @@ namespace gr { QWidget* qwidget(); PyObject* pyqwidget(); + void clear_data(); + void set_fft_size(const int fftsize); int fft_size() const; void set_fft_average(const float fftavg); float fft_average() const; + void set_fft_window(const gr::filter::firdes::win_type win); + gr::filter::firdes::win_type fft_window(); void set_frequency_range(const double centerfreq, const double bandwidth); + void set_intensity_range(const double min, const double max); void set_update_time(double t); void set_title(const std::string &title); - void set_line_label(const std::string &label); - void set_line_color(const std::string &color); - void set_line_width(int width); - void set_line_style(Qt::PenStyle style); - void set_line_marker(QwtSymbol::Style marker); + void set_line_label(int which, const std::string &label); + void set_line_alpha(int which, double alpha); + void set_color_map(int which, const int color); + + std::string title(); + std::string line_label(int which); + double line_alpha(int which); + int color_map(int which); void set_size(int width, int height); + void auto_scale(); + double min_intensity(int which); + double max_intensity(int which); + + void enable_menu(bool en); + void enable_grid(bool en); + int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/gr-qtgui/lib/waterfalldisplayform.cc b/gr-qtgui/lib/waterfalldisplayform.cc index e8e78ea3de..480f18d5b1 100644 --- a/gr-qtgui/lib/waterfalldisplayform.cc +++ b/gr-qtgui/lib/waterfalldisplayform.cc @@ -44,6 +44,31 @@ WaterfallDisplayForm::WaterfallDisplayForm(int nplots, QWidget* parent) _min_val = 1000; _max_val = -1000; + // 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++) { + _lines_menu[i]->clear(); + } + _line_title_act.clear(); + _line_color_menu.clear(); + _line_width_menu.clear(); + _line_style_menu.clear(); + _line_marker_menu.clear(); + _marker_alpha_menu.clear(); + + // Now create our own menus + for(int i = 0; i < nplots; i++) { + ColorMapMenu *colormap = new ColorMapMenu(i, this); + connect(colormap, SIGNAL(whichTrigger(int, const int, const QColor&, const QColor&)), + this, SLOT(setColorMap(int, const int, const QColor&, const QColor&))); + _lines_menu[i]->addMenu(colormap); + + _marker_alpha_menu.push_back(new MarkerAlphaMenu(i, this)); + connect(_marker_alpha_menu[i], SIGNAL(whichTrigger(int, int)), + this, SLOT(setAlpha(int, int))); + _lines_menu[i]->addMenu(_marker_alpha_menu[i]); + } + QAction *autoscale_act = new QAction("Auto Scale", this); autoscale_act->setStatusTip(tr("Autoscale intensity range")); connect(autoscale_act, SIGNAL(triggered()), this, SLOT(autoScale())); @@ -51,11 +76,9 @@ WaterfallDisplayForm::WaterfallDisplayForm(int nplots, QWidget* parent) FFTSizeMenu *sizemenu = new FFTSizeMenu(this); FFTAverageMenu *avgmenu = new FFTAverageMenu(this); FFTWindowMenu *winmenu = new FFTWindowMenu(this); - ColorMapMenu *colormenu = new ColorMapMenu(this); _menu->addMenu(sizemenu); _menu->addMenu(avgmenu); _menu->addMenu(winmenu); - _menu->addMenu(colormenu); _menu->addAction(autoscale_act); connect(sizemenu, SIGNAL(whichTrigger(int)), this, SLOT(setFFTSize(const int))); @@ -63,8 +86,6 @@ WaterfallDisplayForm::WaterfallDisplayForm(int nplots, QWidget* parent) this, SLOT(setFFTAverage(const float))); connect(winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)), this, SLOT(setFFTWindowType(const gr::filter::firdes::win_type))); - connect(colormenu, SIGNAL(whichTrigger(const int, const QColor&, const QColor&)), - this, SLOT(setColorMap(const int, const QColor&, const QColor&))); Reset(); @@ -106,7 +127,7 @@ WaterfallDisplayForm::newData(const QEvent *updateEvent) } getPlot()->plotNewData(dataPoints, numDataPoints, - d_update_time, dataTimestamp, 0); + _time_per_slice, dataTimestamp, 0); } void @@ -135,6 +156,30 @@ WaterfallDisplayForm::getFFTWindowType() const return _fftwintype; } +int +WaterfallDisplayForm::getColorMap(int which) +{ + return getPlot()->getIntensityColorMapType(which); +} + +int +WaterfallDisplayForm::getAlpha(int which) +{ + return getPlot()->getAlpha(which); +} + +double +WaterfallDisplayForm::getMinIntensity(int which) +{ + return getPlot()->getMinIntensity(which); +} + +double +WaterfallDisplayForm::getMaxIntensity(int which) +{ + return getPlot()->getMaxIntensity(which); +} + void WaterfallDisplayForm::setFFTSize(const int newsize) { @@ -163,17 +208,30 @@ WaterfallDisplayForm::setFrequencyRange(const double centerfreq, double units = pow(10, (units10-fmod(units10, 3.0))); int iunit = static_cast<int>(units3); + _samp_rate = bandwidth; + _time_per_slice = (1.0/bandwidth)*_fftsize; + getPlot()->setFrequencyRange(centerfreq, bandwidth, units, strunits[iunit]); + getPlot()->replot(); } void -WaterfallDisplayForm::setColorMap(const int newType, +WaterfallDisplayForm::setColorMap(int which, + const int newType, const QColor lowColor, const QColor highColor) { - getPlot()->setIntensityColorMapType(0, newType, + getPlot()->setIntensityColorMapType(which, newType, lowColor, highColor); + getPlot()->replot(); +} + +void +WaterfallDisplayForm::setAlpha(int which, int alpha) +{ + getPlot()->setAlpha(which, alpha); + getPlot()->replot(); } void @@ -181,6 +239,7 @@ WaterfallDisplayForm::setIntensityRange(const double minIntensity, const double maxIntensity) { getPlot()->setIntensityRange(minIntensity, maxIntensity); + getPlot()->replot(); } void @@ -190,4 +249,11 @@ WaterfallDisplayForm::autoScale() double max_int = _max_val + 10; getPlot()->setIntensityRange(min_int, max_int); + getPlot()->replot(); +} + +void +WaterfallDisplayForm::clearData() +{ + getPlot()->clearData(); } diff --git a/gr-qtgui/lib/waterfalldisplayform.h b/gr-qtgui/lib/waterfalldisplayform.h index e078aeb05a..a6add831fd 100644 --- a/gr-qtgui/lib/waterfalldisplayform.h +++ b/gr-qtgui/lib/waterfalldisplayform.h @@ -45,6 +45,13 @@ class WaterfallDisplayForm : public DisplayForm float getFFTAverage() const; gr::filter::firdes::win_type getFFTWindowType() const; + int getColorMap(int which); + int getAlpha(int which); + double getMinIntensity(int which); + double getMaxIntensity(int which); + + void clearData(); + public slots: void customEvent(QEvent *e); @@ -58,9 +65,12 @@ public slots: void setIntensityRange(const double minIntensity, const double maxIntensity); - void setColorMap(const int newType, - const QColor lowColor, - const QColor highColor); + void setAlpha(int which, int alpha); + + void setColorMap(int which, + const int newType, + const QColor lowColor=QColor("white"), + const QColor highColor=QColor("white")); void autoScale(); @@ -71,6 +81,8 @@ private: uint64_t _numRealDataPoints; QIntValidator* _intValidator; + double _samp_rate; + double _time_per_slice; int _fftsize; float _fftavg; gr::filter::firdes::win_type _fftwintype; diff --git a/gr-qtgui/swig/CMakeLists.txt b/gr-qtgui/swig/CMakeLists.txt index e2beb5327e..d17130597e 100644 --- a/gr-qtgui/swig/CMakeLists.txt +++ b/gr-qtgui/swig/CMakeLists.txt @@ -26,6 +26,7 @@ include(GrSwig) set(GR_SWIG_INCLUDE_DIRS ${GR_QTGUI_INCLUDE_DIRS} ${GR_FFT_INCLUDE_DIRS} + ${GR_FILTER_INCLUDE_DIRS} ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} ${GRUEL_INCLUDE_DIRS} ${QWT_INCLUDE_DIRS} diff --git a/gr-qtgui/swig/qtgui_swig.i b/gr-qtgui/swig/qtgui_swig.i index 9821ccf440..20675503e2 100644 --- a/gr-qtgui/swig/qtgui_swig.i +++ b/gr-qtgui/swig/qtgui_swig.i @@ -21,12 +21,16 @@ */ #define QTGUI_API +#define FILTER_API %include "gnuradio.i" //load generated python docstrings %include "qtgui_swig_doc.i" +// So we understand the firdes window types +%include "filter/firdes.h" + %{ #include "qtgui/sink_c.h" #include "qtgui/sink_f.h" |