From 36649d4e472172fe840444ac0268c7b6b4da94b4 Mon Sep 17 00:00:00 2001 From: jcorgan Date: Thu, 14 Aug 2008 18:43:15 +0000 Subject: Merged changeset r9241:9289 from jblum/glwxgui into trunk. Adds OpenGL versions of fftsink, waterfallsink, and scopesink, and new constsink. See README.gl for use. (Josh Blum) git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@9290 221aa14e-8319-0410-a670-987f0aec2ac5 --- gr-wxgui/src/python/fftsink_nongl.py | 603 +++++++++++++++++++++++++++++++++++ 1 file changed, 603 insertions(+) create mode 100644 gr-wxgui/src/python/fftsink_nongl.py (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py new file mode 100644 index 000000000..f4e9143f1 --- /dev/null +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -0,0 +1,603 @@ +#!/usr/bin/env python +# +# Copyright 2003,2004,2005,2006,2007 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, gru, window +from gnuradio.wxgui import stdgui2 +import wx +import plot +import numpy +import threading +import math + +DIV_LEVELS = (1, 2, 5, 10, 20) + +default_fftsink_size = (640,240) +default_fft_rate = gr.prefs().get_long('wxgui', 'fft_rate', 15) + +class fft_sink_base(object): + def __init__(self, input_is_real=False, baseband_freq=0, y_per_div=10, + y_divs=8, ref_level=50, + sample_rate=1, fft_size=512, + fft_rate=default_fft_rate, + average=False, avg_alpha=None, title='', peak_hold=False): + + # initialize common attributes + self.baseband_freq = baseband_freq + self.y_per_div=y_per_div + self.y_divs = y_divs + self.ref_level = ref_level + self.sample_rate = sample_rate + self.fft_size = fft_size + self.fft_rate = fft_rate + self.average = average + if avg_alpha is None: + self.avg_alpha = 2.0 / fft_rate + else: + self.avg_alpha = avg_alpha + self.title = title + self.peak_hold = peak_hold + self.input_is_real = input_is_real + self.msgq = gr.msg_queue(2) # queue that holds a maximum of 2 messages + + def set_y_per_div(self, y_per_div): + self.y_per_div = y_per_div + + def set_ref_level(self, ref_level): + self.ref_level = ref_level + + def set_average(self, average): + self.average = average + if average: + self.avg.set_taps(self.avg_alpha) + else: + self.avg.set_taps(1.0) + self.win.peak_vals = None + + def set_peak_hold(self, enable): + self.peak_hold = enable + self.win.set_peak_hold(enable) + + def set_avg_alpha(self, avg_alpha): + self.avg_alpha = avg_alpha + + def set_baseband_freq(self, baseband_freq): + self.baseband_freq = baseband_freq + + def set_sample_rate(self, sample_rate): + self.sample_rate = sample_rate + self._set_n() + + def _set_n(self): + self.one_in_n.set_n(max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) + + +class fft_sink_f(gr.hier_block2, fft_sink_base): + def __init__(self, parent, baseband_freq=0, ref_scale=2.0, + y_per_div=10, y_divs=8, ref_level=50, sample_rate=1, fft_size=512, + fft_rate=default_fft_rate, average=False, avg_alpha=None, + title='', size=default_fftsink_size, peak_hold=False): + + gr.hier_block2.__init__(self, "fft_sink_f", + gr.io_signature(1, 1, gr.sizeof_float), + gr.io_signature(0,0,0)) + + fft_sink_base.__init__(self, input_is_real=True, baseband_freq=baseband_freq, + y_per_div=y_per_div, y_divs=y_divs, ref_level=ref_level, + sample_rate=sample_rate, fft_size=fft_size, + fft_rate=fft_rate, + average=average, avg_alpha=avg_alpha, title=title, + peak_hold=peak_hold) + + self.s2p = gr.stream_to_vector(gr.sizeof_float, self.fft_size) + self.one_in_n = gr.keep_one_in_n(gr.sizeof_float * self.fft_size, + max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) + + mywindow = window.blackmanharris(self.fft_size) + self.fft = gr.fft_vfc(self.fft_size, True, mywindow) + power = 0 + for tap in mywindow: + power += tap*tap + + self.c2mag = gr.complex_to_mag(self.fft_size) + self.avg = gr.single_pole_iir_filter_ff(1.0, self.fft_size) + + # FIXME We need to add 3dB to all bins but the DC bin + self.log = gr.nlog10_ff(20, self.fft_size, + -10*math.log10(self.fft_size) # Adjust for number of bins + -10*math.log10(power/self.fft_size) # Adjust for windowing loss + -20*math.log10(ref_scale/2)) # Adjust for reference scale + + self.sink = gr.message_sink(gr.sizeof_float * self.fft_size, self.msgq, True) + self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2mag, self.avg, self.log, self.sink) + + self.win = fft_window(self, parent, size=size) + self.set_average(self.average) + self.set_peak_hold(self.peak_hold) + +class fft_sink_c(gr.hier_block2, fft_sink_base): + def __init__(self, parent, baseband_freq=0, ref_scale=2.0, + y_per_div=10, y_divs=8, ref_level=50, sample_rate=1, fft_size=512, + fft_rate=default_fft_rate, average=False, avg_alpha=None, + title='', size=default_fftsink_size, peak_hold=False): + + gr.hier_block2.__init__(self, "fft_sink_c", + gr.io_signature(1, 1, gr.sizeof_gr_complex), + gr.io_signature(0,0,0)) + + fft_sink_base.__init__(self, input_is_real=False, baseband_freq=baseband_freq, + y_per_div=y_per_div, y_divs=y_divs, ref_level=ref_level, + sample_rate=sample_rate, fft_size=fft_size, + fft_rate=fft_rate, + average=average, avg_alpha=avg_alpha, title=title, + peak_hold=peak_hold) + + self.s2p = gr.stream_to_vector(gr.sizeof_gr_complex, self.fft_size) + self.one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex * self.fft_size, + max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) + + mywindow = window.blackmanharris(self.fft_size) + self.fft = gr.fft_vcc(self.fft_size, True, mywindow) + power = 0 + for tap in mywindow: + power += tap*tap + + self.c2mag = gr.complex_to_mag(self.fft_size) + self.avg = gr.single_pole_iir_filter_ff(1.0, self.fft_size) + + # FIXME We need to add 3dB to all bins but the DC bin + self.log = gr.nlog10_ff(20, self.fft_size, + -10*math.log10(self.fft_size) # Adjust for number of bins + -10*math.log10(power/self.fft_size) # Adjust for windowing loss + -20*math.log10(ref_scale/2)) # Adjust for reference scale + + self.sink = gr.message_sink(gr.sizeof_float * self.fft_size, self.msgq, True) + self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2mag, self.avg, self.log, self.sink) + + self.win = fft_window(self, parent, size=size) + self.set_average(self.average) + self.set_peak_hold(self.peak_hold) + + +# ------------------------------------------------------------------------ + +myDATA_EVENT = wx.NewEventType() +EVT_DATA_EVENT = wx.PyEventBinder (myDATA_EVENT, 0) + + +class DataEvent(wx.PyEvent): + def __init__(self, data): + wx.PyEvent.__init__(self) + self.SetEventType (myDATA_EVENT) + self.data = data + + def Clone (self): + self.__class__ (self.GetId()) + + +class input_watcher (threading.Thread): + def __init__ (self, msgq, fft_size, event_receiver, **kwds): + threading.Thread.__init__ (self, **kwds) + self.setDaemon (1) + self.msgq = msgq + self.fft_size = fft_size + self.event_receiver = event_receiver + self.keep_running = True + self.start () + + def run (self): + while (self.keep_running): + msg = self.msgq.delete_head() # blocking read of message queue + itemsize = int(msg.arg1()) + nitems = int(msg.arg2()) + + s = msg.to_string() # get the body of the msg as a string + + # There may be more than one FFT frame in the message. + # If so, we take only the last one + if nitems > 1: + start = itemsize * (nitems - 1) + s = s[start:start+itemsize] + + complex_data = numpy.fromstring (s, numpy.float32) + de = DataEvent (complex_data) + wx.PostEvent (self.event_receiver, de) + del de + +class control_panel(wx.Panel): + + class LabelText(wx.StaticText): + def __init__(self, window, label): + wx.StaticText.__init__(self, window, -1, label) + font = self.GetFont() + font.SetWeight(wx.FONTWEIGHT_BOLD) + font.SetUnderlined(True) + self.SetFont(font) + + def __init__(self, parent): + self.parent = parent + wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER) + control_box = wx.BoxSizer(wx.VERTICAL) + + #checkboxes for average and peak hold + control_box.AddStretchSpacer() + control_box.Add(self.LabelText(self, 'Options'), 0, wx.ALIGN_CENTER) + self.average_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Average") + self.average_check_box.Bind(wx.EVT_CHECKBOX, parent.on_average) + control_box.Add(self.average_check_box, 0, wx.EXPAND) + self.peak_hold_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Peak Hold") + self.peak_hold_check_box.Bind(wx.EVT_CHECKBOX, parent.on_peak_hold) + control_box.Add(self.peak_hold_check_box, 0, wx.EXPAND) + + #radio buttons for div size + control_box.AddStretchSpacer() + control_box.Add(self.LabelText(self, 'Set dB/div'), 0, wx.ALIGN_CENTER) + radio_box = wx.BoxSizer(wx.VERTICAL) + self.radio_buttons = list() + for y_per_div in DIV_LEVELS: + radio_button = wx.RadioButton(self, -1, "%d dB/div"%y_per_div) + radio_button.Bind(wx.EVT_RADIOBUTTON, self.on_radio_button_change) + self.radio_buttons.append(radio_button) + radio_box.Add(radio_button, 0, wx.ALIGN_LEFT) + control_box.Add(radio_box, 0, wx.EXPAND) + + #ref lvl buttons + control_box.AddStretchSpacer() + control_box.Add(self.LabelText(self, 'Adj Ref Lvl'), 0, wx.ALIGN_CENTER) + control_box.AddSpacer(2) + button_box = wx.BoxSizer(wx.HORIZONTAL) + self.ref_plus_button = wx.Button(self, -1, '+', style=wx.BU_EXACTFIT) + self.ref_plus_button.Bind(wx.EVT_BUTTON, parent.on_incr_ref_level) + button_box.Add(self.ref_plus_button, 0, wx.ALIGN_CENTER) + self.ref_minus_button = wx.Button(self, -1, ' - ', style=wx.BU_EXACTFIT) + self.ref_minus_button.Bind(wx.EVT_BUTTON, parent.on_decr_ref_level) + button_box.Add(self.ref_minus_button, 0, wx.ALIGN_CENTER) + control_box.Add(button_box, 0, wx.ALIGN_CENTER) + control_box.AddStretchSpacer() + #set sizer + self.SetSizerAndFit(control_box) + #update + self.update() + + def update(self): + """! + Read the state of the fft plot settings and update the control panel. + """ + #update checkboxes + self.average_check_box.SetValue(self.parent.fftsink.average) + self.peak_hold_check_box.SetValue(self.parent.fftsink.peak_hold) + #update radio buttons + try: + index = list(DIV_LEVELS).index(self.parent.fftsink.y_per_div) + self.radio_buttons[index].SetValue(True) + except: pass + + def on_radio_button_change(self, evt): + selected_radio_button = filter(lambda rb: rb.GetValue(), self.radio_buttons)[0] + index = self.radio_buttons.index(selected_radio_button) + self.parent.fftsink.set_y_per_div(DIV_LEVELS[index]) + +class fft_window (wx.Panel): + def __init__ (self, fftsink, parent, id = -1, + pos = wx.DefaultPosition, size = wx.DefaultSize, + style = wx.DEFAULT_FRAME_STYLE, name = ""): + + self.fftsink = fftsink + #init panel and plot + wx.Panel.__init__(self, parent, -1) + self.plot = plot.PlotCanvas(self, id, pos, size, style, name) + #setup the box with plot and controls + self.control_panel = control_panel(self) + main_box = wx.BoxSizer (wx.HORIZONTAL) + main_box.Add (self.plot, 1, wx.EXPAND) + main_box.Add (self.control_panel, 0, wx.EXPAND) + self.SetSizerAndFit(main_box) + + self.peak_hold = False + self.peak_vals = None + + self.plot.SetEnableGrid (True) + # self.SetEnableZoom (True) + # self.SetBackgroundColour ('black') + + self.build_popup_menu() + self.set_baseband_freq(0.0) + + EVT_DATA_EVENT (self, self.set_data) + wx.EVT_CLOSE (self, self.on_close_window) + self.plot.Bind(wx.EVT_RIGHT_UP, self.on_right_click) + self.plot.Bind(wx.EVT_MOTION, self.evt_motion) + + self.input_watcher = input_watcher(fftsink.msgq, fftsink.fft_size, self) + + def set_scale(self, freq): + x = max(abs(self.fftsink.sample_rate), abs(self.fftsink.baseband_freq)) + if x >= 1e9: + self._scale_factor = 1e-9 + self._units = "GHz" + self._format = "%3.6f" + elif x >= 1e6: + self._scale_factor = 1e-6 + self._units = "MHz" + self._format = "%3.3f" + else: + self._scale_factor = 1e-3 + self._units = "kHz" + self._format = "%3.3f" + + def set_baseband_freq(self, baseband_freq): + if self.peak_hold: + self.peak_vals = None + self.set_scale(baseband_freq) + self.fftsink.set_baseband_freq(baseband_freq) + + def on_close_window (self, event): + print "fft_window:on_close_window" + self.keep_running = False + + + def set_data (self, evt): + dB = evt.data + L = len (dB) + + if self.peak_hold: + if self.peak_vals is None: + self.peak_vals = dB + else: + self.peak_vals = numpy.maximum(dB, self.peak_vals) + + if self.fftsink.input_is_real: # only plot 1/2 the points + x_vals = ((numpy.arange (L/2) * (self.fftsink.sample_rate + * self._scale_factor / L)) + + self.fftsink.baseband_freq * self._scale_factor) + self._points = numpy.zeros((len(x_vals), 2), numpy.float64) + self._points[:,0] = x_vals + self._points[:,1] = dB[0:L/2] + if self.peak_hold: + self._peak_points = numpy.zeros((len(x_vals), 2), numpy.float64) + self._peak_points[:,0] = x_vals + self._peak_points[:,1] = self.peak_vals[0:L/2] + else: + # the "negative freqs" are in the second half of the array + x_vals = ((numpy.arange (-L/2, L/2) + * (self.fftsink.sample_rate * self._scale_factor / L)) + + self.fftsink.baseband_freq * self._scale_factor) + self._points = numpy.zeros((len(x_vals), 2), numpy.float64) + self._points[:,0] = x_vals + self._points[:,1] = numpy.concatenate ((dB[L/2:], dB[0:L/2])) + if self.peak_hold: + self._peak_points = numpy.zeros((len(x_vals), 2), numpy.float64) + self._peak_points[:,0] = x_vals + self._peak_points[:,1] = numpy.concatenate ((self.peak_vals[L/2:], self.peak_vals[0:L/2])) + + lines = [plot.PolyLine (self._points, colour='BLUE'),] + if self.peak_hold: + lines.append(plot.PolyLine (self._peak_points, colour='GREEN')) + + graphics = plot.PlotGraphics (lines, + title=self.fftsink.title, + xLabel = self._units, yLabel = "dB") + x_range = x_vals[0], x_vals[-1] + ymax = self.fftsink.ref_level + ymin = self.fftsink.ref_level - self.fftsink.y_per_div * self.fftsink.y_divs + y_range = ymin, ymax + self.plot.Draw (graphics, xAxis=x_range, yAxis=y_range, step=self.fftsink.y_per_div) + + def set_peak_hold(self, enable): + self.peak_hold = enable + self.peak_vals = None + + def on_average(self, evt): + # print "on_average" + self.fftsink.set_average(evt.IsChecked()) + self.control_panel.update() + + def on_peak_hold(self, evt): + # print "on_peak_hold" + self.fftsink.set_peak_hold(evt.IsChecked()) + self.control_panel.update() + + def on_incr_ref_level(self, evt): + # print "on_incr_ref_level" + self.fftsink.set_ref_level(self.fftsink.ref_level + + self.fftsink.y_per_div) + + def on_decr_ref_level(self, evt): + # print "on_decr_ref_level" + self.fftsink.set_ref_level(self.fftsink.ref_level + - self.fftsink.y_per_div) + + def on_incr_y_per_div(self, evt): + # print "on_incr_y_per_div" + self.fftsink.set_y_per_div(next_up(self.fftsink.y_per_div, DIV_LEVELS)) + self.control_panel.update() + + def on_decr_y_per_div(self, evt): + # print "on_decr_y_per_div" + self.fftsink.set_y_per_div(next_down(self.fftsink.y_per_div, DIV_LEVELS)) + self.control_panel.update() + + def on_y_per_div(self, evt): + # print "on_y_per_div" + Id = evt.GetId() + if Id == self.id_y_per_div_1: + self.fftsink.set_y_per_div(1) + elif Id == self.id_y_per_div_2: + self.fftsink.set_y_per_div(2) + elif Id == self.id_y_per_div_5: + self.fftsink.set_y_per_div(5) + elif Id == self.id_y_per_div_10: + self.fftsink.set_y_per_div(10) + elif Id == self.id_y_per_div_20: + self.fftsink.set_y_per_div(20) + self.control_panel.update() + + def on_right_click(self, event): + menu = self.popup_menu + for id, pred in self.checkmarks.items(): + item = menu.FindItemById(id) + item.Check(pred()) + self.plot.PopupMenu(menu, event.GetPosition()) + + def evt_motion(self, event): + if not hasattr(self, "_points"): + return # Got here before first window data update + + # Clip to plotted values + (ux, uy) = self.plot.GetXY(event) # Scaled position + x_vals = numpy.array(self._points[:,0]) + if ux < x_vals[0] or ux > x_vals[-1]: + tip = self.GetToolTip() + if tip: + tip.Enable(False) + return + + # Get nearest X value (is there a better way)? + ind = numpy.argmin(numpy.abs(x_vals-ux)) + x_val = x_vals[ind] + db_val = self._points[ind, 1] + text = (self._format+" %s dB=%3.3f") % (x_val, self._units, db_val) + + # Display the tooltip + tip = wx.ToolTip(text) + tip.Enable(True) + tip.SetDelay(0) + self.SetToolTip(tip) + + def build_popup_menu(self): + self.id_incr_ref_level = wx.NewId() + self.id_decr_ref_level = wx.NewId() + self.id_incr_y_per_div = wx.NewId() + self.id_decr_y_per_div = wx.NewId() + self.id_y_per_div_1 = wx.NewId() + self.id_y_per_div_2 = wx.NewId() + self.id_y_per_div_5 = wx.NewId() + self.id_y_per_div_10 = wx.NewId() + self.id_y_per_div_20 = wx.NewId() + self.id_average = wx.NewId() + self.id_peak_hold = wx.NewId() + + self.plot.Bind(wx.EVT_MENU, self.on_average, id=self.id_average) + self.plot.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold) + self.plot.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level) + self.plot.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level) + self.plot.Bind(wx.EVT_MENU, self.on_incr_y_per_div, id=self.id_incr_y_per_div) + self.plot.Bind(wx.EVT_MENU, self.on_decr_y_per_div, id=self.id_decr_y_per_div) + self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_1) + self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_2) + self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_5) + self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_10) + self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_20) + + # make a menu + menu = wx.Menu() + self.popup_menu = menu + menu.AppendCheckItem(self.id_average, "Average") + menu.AppendCheckItem(self.id_peak_hold, "Peak Hold") + menu.Append(self.id_incr_ref_level, "Incr Ref Level") + menu.Append(self.id_decr_ref_level, "Decr Ref Level") + # menu.Append(self.id_incr_y_per_div, "Incr dB/div") + # menu.Append(self.id_decr_y_per_div, "Decr dB/div") + menu.AppendSeparator() + # we'd use RadioItems for these, but they're not supported on Mac + menu.AppendCheckItem(self.id_y_per_div_1, "1 dB/div") + menu.AppendCheckItem(self.id_y_per_div_2, "2 dB/div") + menu.AppendCheckItem(self.id_y_per_div_5, "5 dB/div") + menu.AppendCheckItem(self.id_y_per_div_10, "10 dB/div") + menu.AppendCheckItem(self.id_y_per_div_20, "20 dB/div") + + self.checkmarks = { + self.id_average : lambda : self.fftsink.average, + self.id_peak_hold : lambda : self.fftsink.peak_hold, + self.id_y_per_div_1 : lambda : self.fftsink.y_per_div == 1, + self.id_y_per_div_2 : lambda : self.fftsink.y_per_div == 2, + self.id_y_per_div_5 : lambda : self.fftsink.y_per_div == 5, + self.id_y_per_div_10 : lambda : self.fftsink.y_per_div == 10, + self.id_y_per_div_20 : lambda : self.fftsink.y_per_div == 20, + } + + +def next_up(v, seq): + """ + Return the first item in seq that is > v. + """ + for s in seq: + if s > v: + return s + return v + +def next_down(v, seq): + """ + Return the last item in seq that is < v. + """ + rseq = list(seq[:]) + rseq.reverse() + + for s in rseq: + if s < v: + return s + return v + + +# ---------------------------------------------------------------- +# Standalone test app +# ---------------------------------------------------------------- + +class test_app_block (stdgui2.std_top_block): + def __init__(self, frame, panel, vbox, argv): + stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv) + + fft_size = 256 + + # build our flow graph + input_rate = 20.48e3 + + # Generate a complex sinusoid + #src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 2e3, 1) + src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1) + + # We add these throttle blocks so that this demo doesn't + # suck down all the CPU available. Normally you wouldn't use these. + thr1 = gr.throttle(gr.sizeof_gr_complex, input_rate) + + sink1 = fft_sink_c (panel, title="Complex Data", fft_size=fft_size, + sample_rate=input_rate, baseband_freq=100e3, + ref_level=0, y_per_div=20, y_divs=10) + vbox.Add (sink1.win, 1, wx.EXPAND) + + self.connect(src1, thr1, sink1) + + #src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 1) + src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1) + thr2 = gr.throttle(gr.sizeof_float, input_rate) + sink2 = fft_sink_f (panel, title="Real Data", fft_size=fft_size*2, + sample_rate=input_rate, baseband_freq=100e3, + ref_level=0, y_per_div=20, y_divs=10) + vbox.Add (sink2.win, 1, wx.EXPAND) + + self.connect(src2, thr2, sink2) + +def main (): + app = stdgui2.stdapp (test_app_block, "FFT Sink Test App") + app.MainLoop () + +if __name__ == '__main__': + main () -- cgit From 924831afcdb187b3de670be6fd1f6147d62be5cf Mon Sep 17 00:00:00 2001 From: jblum Date: Wed, 10 Sep 2008 01:23:21 +0000 Subject: Replaced """! with """. Exclamation mark showed in doxygen docs. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@9549 221aa14e-8319-0410-a670-987f0aec2ac5 --- gr-wxgui/src/python/fftsink_nongl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py index f4e9143f1..d455ddc27 100644 --- a/gr-wxgui/src/python/fftsink_nongl.py +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -278,7 +278,7 @@ class control_panel(wx.Panel): self.update() def update(self): - """! + """ Read the state of the fft plot settings and update the control panel. """ #update checkboxes -- cgit From d9744799b7df6c09180778540bf55eb9dc84281b Mon Sep 17 00:00:00 2001 From: jcorgan Date: Fri, 20 Mar 2009 02:16:20 +0000 Subject: Merged r10463:10658 from jblum/gui_guts into trunk. Trunk passes distcheck. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@10660 221aa14e-8319-0410-a670-987f0aec2ac5 --- gr-wxgui/src/python/fftsink_nongl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py index d455ddc27..a1033e818 100644 --- a/gr-wxgui/src/python/fftsink_nongl.py +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -319,7 +319,7 @@ class fft_window (wx.Panel): # self.SetBackgroundColour ('black') self.build_popup_menu() - self.set_baseband_freq(0.0) + self.set_baseband_freq(self.fftsink.baseband_freq) EVT_DATA_EVENT (self, self.set_data) wx.EVT_CLOSE (self, self.on_close_window) -- cgit From a9154607d6f6fd2bfbafd732dccf9edef35e1e6e Mon Sep 17 00:00:00 2001 From: jcorgan Date: Fri, 10 Jul 2009 01:26:37 +0000 Subject: Refactor msgq thread classes to use gru.msgq_runner git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@11407 221aa14e-8319-0410-a670-987f0aec2ac5 --- gr-wxgui/src/python/fftsink_nongl.py | 45 +++++++++++++++--------------------- 1 file changed, 19 insertions(+), 26 deletions(-) (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py index a1033e818..ca5e91fdb 100644 --- a/gr-wxgui/src/python/fftsink_nongl.py +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -25,7 +25,6 @@ from gnuradio.wxgui import stdgui2 import wx import plot import numpy -import threading import math DIV_LEVELS = (1, 2, 5, 10, 20) @@ -193,34 +192,28 @@ class DataEvent(wx.PyEvent): self.__class__ (self.GetId()) -class input_watcher (threading.Thread): +class input_watcher (gru.msgq_runner): def __init__ (self, msgq, fft_size, event_receiver, **kwds): - threading.Thread.__init__ (self, **kwds) - self.setDaemon (1) - self.msgq = msgq self.fft_size = fft_size self.event_receiver = event_receiver - self.keep_running = True - self.start () - - def run (self): - while (self.keep_running): - msg = self.msgq.delete_head() # blocking read of message queue - itemsize = int(msg.arg1()) - nitems = int(msg.arg2()) - - s = msg.to_string() # get the body of the msg as a string - - # There may be more than one FFT frame in the message. - # If so, we take only the last one - if nitems > 1: - start = itemsize * (nitems - 1) - s = s[start:start+itemsize] - - complex_data = numpy.fromstring (s, numpy.float32) - de = DataEvent (complex_data) - wx.PostEvent (self.event_receiver, de) - del de + gru.msgq_runner.__init__(self, msgq, self.handle_msg) + + def handle_msg(self, msg): + itemsize = int(msg.arg1()) + nitems = int(msg.arg2()) + + s = msg.to_string() # get the body of the msg as a string + + # There may be more than one FFT frame in the message. + # If so, we take only the last one + if nitems > 1: + start = itemsize * (nitems - 1) + s = s[start:start+itemsize] + + complex_data = numpy.fromstring (s, numpy.float32) + de = DataEvent (complex_data) + wx.PostEvent (self.event_receiver, de) + del de class control_panel(wx.Panel): -- cgit From 230e062e51d43f389520207cf147838c666a1f21 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 28 Oct 2009 16:17:24 -0700 Subject: Added window option to wxgui fft and waterfall sink. Added rectangular window function to window.py. Average stays hidden in waterfall, fft, and numbersink wrappers (only avg_alpha shows/hides). Fixed options in waterfall wrapper to model after fft and numbersink average params. --- gr-wxgui/src/python/fftsink_nongl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py index ca5e91fdb..b3a48a716 100644 --- a/gr-wxgui/src/python/fftsink_nongl.py +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -93,7 +93,7 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): def __init__(self, parent, baseband_freq=0, ref_scale=2.0, y_per_div=10, y_divs=8, ref_level=50, sample_rate=1, fft_size=512, fft_rate=default_fft_rate, average=False, avg_alpha=None, - title='', size=default_fftsink_size, peak_hold=False): + title='', size=default_fftsink_size, peak_hold=False, **kwargs): gr.hier_block2.__init__(self, "fft_sink_f", gr.io_signature(1, 1, gr.sizeof_float), @@ -136,7 +136,7 @@ class fft_sink_c(gr.hier_block2, fft_sink_base): def __init__(self, parent, baseband_freq=0, ref_scale=2.0, y_per_div=10, y_divs=8, ref_level=50, sample_rate=1, fft_size=512, fft_rate=default_fft_rate, average=False, avg_alpha=None, - title='', size=default_fftsink_size, peak_hold=False): + title='', size=default_fftsink_size, peak_hold=False, **kwargs): gr.hier_block2.__init__(self, "fft_sink_c", gr.io_signature(1, 1, gr.sizeof_gr_complex), -- cgit From 49fa13f9fce2037d176c86bf326a7e25a78b72a5 Mon Sep 17 00:00:00 2001 From: Martin Dudok van Heel Date: Mon, 26 Apr 2010 19:40:41 +0200 Subject: Add analog CRT screen afterglow emulation for gr-wxgui --- gr-wxgui/src/python/fftsink_nongl.py | 60 ++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 10 deletions(-) (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py index ca5e91fdb..f1c1f4396 100644 --- a/gr-wxgui/src/python/fftsink_nongl.py +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -37,7 +37,7 @@ class fft_sink_base(object): y_divs=8, ref_level=50, sample_rate=1, fft_size=512, fft_rate=default_fft_rate, - average=False, avg_alpha=None, title='', peak_hold=False): + average=False, avg_alpha=None, title='', peak_hold=False,emulate_analog=False,analog_alpha=0.2): # initialize common attributes self.baseband_freq = baseband_freq @@ -52,6 +52,9 @@ class fft_sink_base(object): self.avg_alpha = 2.0 / fft_rate else: self.avg_alpha = avg_alpha + self.emulate_analog = emulate_analog + self.analog_alpha = analog_alpha + self.title = title self.peak_hold = peak_hold self.input_is_real = input_is_real @@ -75,6 +78,14 @@ class fft_sink_base(object): self.peak_hold = enable self.win.set_peak_hold(enable) + def set_emulate_analog(self, enable): + self.emulate_analog = enable + self.win.set_emulate_analog(enable) + + def set_analog_alpha(self, analog_alpha): + self.analog_alpha = analog_alpha + self.win.set_analog_alpha(analog_alpha) + def set_avg_alpha(self, avg_alpha): self.avg_alpha = avg_alpha @@ -93,7 +104,7 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): def __init__(self, parent, baseband_freq=0, ref_scale=2.0, y_per_div=10, y_divs=8, ref_level=50, sample_rate=1, fft_size=512, fft_rate=default_fft_rate, average=False, avg_alpha=None, - title='', size=default_fftsink_size, peak_hold=False): + title='', size=default_fftsink_size, peak_hold=False, emulate_analog=False,analog_alpha=0.2): gr.hier_block2.__init__(self, "fft_sink_f", gr.io_signature(1, 1, gr.sizeof_float), @@ -104,7 +115,7 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): sample_rate=sample_rate, fft_size=fft_size, fft_rate=fft_rate, average=average, avg_alpha=avg_alpha, title=title, - peak_hold=peak_hold) + peak_hold=peak_hold,emulate_analog=emulate_analog,analog_alpha=analog_alpha) self.s2p = gr.stream_to_vector(gr.sizeof_float, self.fft_size) self.one_in_n = gr.keep_one_in_n(gr.sizeof_float * self.fft_size, @@ -131,12 +142,14 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): self.win = fft_window(self, parent, size=size) self.set_average(self.average) self.set_peak_hold(self.peak_hold) + self.set_emulate_analog(self.emulate_analog) + self.set_analog_alpha(self.analog_alpha) class fft_sink_c(gr.hier_block2, fft_sink_base): def __init__(self, parent, baseband_freq=0, ref_scale=2.0, y_per_div=10, y_divs=8, ref_level=50, sample_rate=1, fft_size=512, fft_rate=default_fft_rate, average=False, avg_alpha=None, - title='', size=default_fftsink_size, peak_hold=False): + title='', size=default_fftsink_size, peak_hold=False, emulate_analog=False,analog_alpha=0.2): gr.hier_block2.__init__(self, "fft_sink_c", gr.io_signature(1, 1, gr.sizeof_gr_complex), @@ -147,7 +160,7 @@ class fft_sink_c(gr.hier_block2, fft_sink_base): sample_rate=sample_rate, fft_size=fft_size, fft_rate=fft_rate, average=average, avg_alpha=avg_alpha, title=title, - peak_hold=peak_hold) + peak_hold=peak_hold, emulate_analog=emulate_analog,analog_alpha=analog_alpha) self.s2p = gr.stream_to_vector(gr.sizeof_gr_complex, self.fft_size) self.one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex * self.fft_size, @@ -173,6 +186,8 @@ class fft_sink_c(gr.hier_block2, fft_sink_base): self.win = fft_window(self, parent, size=size) self.set_average(self.average) + self.set_emulate_analog(self.emulate_analog) + self.set_analog_alpha(self.analog_alpha) self.set_peak_hold(self.peak_hold) @@ -236,6 +251,9 @@ class control_panel(wx.Panel): self.average_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Average") self.average_check_box.Bind(wx.EVT_CHECKBOX, parent.on_average) control_box.Add(self.average_check_box, 0, wx.EXPAND) + self.emulate_analog_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Emulate Analog") + self.emulate_analog_check_box.Bind(wx.EVT_CHECKBOX, parent.on_emulate_analog) + control_box.Add(self.emulate_analog_check_box, 0, wx.EXPAND) self.peak_hold_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Peak Hold") self.peak_hold_check_box.Bind(wx.EVT_CHECKBOX, parent.on_peak_hold) control_box.Add(self.peak_hold_check_box, 0, wx.EXPAND) @@ -276,6 +294,7 @@ class control_panel(wx.Panel): """ #update checkboxes self.average_check_box.SetValue(self.parent.fftsink.average) + self.emulate_analog_check_box.SetValue(self.parent.fftsink.emulate_analog) self.peak_hold_check_box.SetValue(self.parent.fftsink.peak_hold) #update radio buttons try: @@ -306,6 +325,10 @@ class fft_window (wx.Panel): self.peak_hold = False self.peak_vals = None + + self.emulate_analog=False + self.analog_alpha=0.2 + self.plot.SetEnableGrid (True) # self.SetEnableZoom (True) @@ -394,6 +417,14 @@ class fft_window (wx.Panel): y_range = ymin, ymax self.plot.Draw (graphics, xAxis=x_range, yAxis=y_range, step=self.fftsink.y_per_div) + def set_emulate_analog(self, enable): + self.emulate_analog = enable + self.plot.set_emulate_analog( enable) + + def set_analog_alpha(self, analog_alpha): + self.analog_alpha = analog_alpha + self.plot.set_analog_alpha(analog_alpha) + def set_peak_hold(self, enable): self.peak_hold = enable self.peak_vals = None @@ -403,6 +434,11 @@ class fft_window (wx.Panel): self.fftsink.set_average(evt.IsChecked()) self.control_panel.update() + def on_emulate_analog(self, evt): + # print "on_analog" + self.fftsink.set_emulate_analog(evt.IsChecked()) + self.control_panel.update() + def on_peak_hold(self, evt): # print "on_peak_hold" self.fftsink.set_peak_hold(evt.IsChecked()) @@ -486,9 +522,11 @@ class fft_window (wx.Panel): self.id_y_per_div_10 = wx.NewId() self.id_y_per_div_20 = wx.NewId() self.id_average = wx.NewId() + self.id_emulate_analog = wx.NewId() self.id_peak_hold = wx.NewId() self.plot.Bind(wx.EVT_MENU, self.on_average, id=self.id_average) + self.plot.Bind(wx.EVT_MENU, self.on_emulate_analog, id=self.id_emulate_analog) self.plot.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold) self.plot.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level) self.plot.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level) @@ -504,6 +542,7 @@ class fft_window (wx.Panel): menu = wx.Menu() self.popup_menu = menu menu.AppendCheckItem(self.id_average, "Average") + menu.AppendCheckItem(self.id_emulate_analog, "Emulate Analog") menu.AppendCheckItem(self.id_peak_hold, "Peak Hold") menu.Append(self.id_incr_ref_level, "Incr Ref Level") menu.Append(self.id_decr_ref_level, "Decr Ref Level") @@ -519,6 +558,7 @@ class fft_window (wx.Panel): self.checkmarks = { self.id_average : lambda : self.fftsink.average, + self.id_emulate_analog : lambda : self.fftsink.emulate_analog, self.id_peak_hold : lambda : self.fftsink.peak_hold, self.id_y_per_div_1 : lambda : self.fftsink.y_per_div == 1, self.id_y_per_div_2 : lambda : self.fftsink.y_per_div == 2, @@ -561,11 +601,11 @@ class test_app_block (stdgui2.std_top_block): fft_size = 256 # build our flow graph - input_rate = 20.48e3 + input_rate = 100*20.48e3 # Generate a complex sinusoid - #src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 2e3, 1) - src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1) + #src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 100*2e3, 1) + src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 100*5.75e3, 1) # We add these throttle blocks so that this demo doesn't # suck down all the CPU available. Normally you wouldn't use these. @@ -578,8 +618,8 @@ class test_app_block (stdgui2.std_top_block): self.connect(src1, thr1, sink1) - #src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 1) - src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1) + #src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 100*2e3, 1) + src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 100*5.75e3, 1) thr2 = gr.throttle(gr.sizeof_float, input_rate) sink2 = fft_sink_f (panel, title="Real Data", fft_size=fft_size*2, sample_rate=input_rate, baseband_freq=100e3, -- cgit From 3a730f46faf1942c713350b312a1dfeffb587550 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Thu, 13 May 2010 13:11:13 -0700 Subject: gr-wxgui: Renamed "emulate analog" feature to "use persistence" --- gr-wxgui/src/python/fftsink_nongl.py | 70 ++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py index 8735e98ae..0854d6668 100644 --- a/gr-wxgui/src/python/fftsink_nongl.py +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -37,7 +37,7 @@ class fft_sink_base(object): y_divs=8, ref_level=50, sample_rate=1, fft_size=512, fft_rate=default_fft_rate, - average=False, avg_alpha=None, title='', peak_hold=False,emulate_analog=False,analog_alpha=0.2): + average=False, avg_alpha=None, title='', peak_hold=False,use_persistence=False,persist_alpha=0.2): # initialize common attributes self.baseband_freq = baseband_freq @@ -52,8 +52,8 @@ class fft_sink_base(object): self.avg_alpha = 2.0 / fft_rate else: self.avg_alpha = avg_alpha - self.emulate_analog = emulate_analog - self.analog_alpha = analog_alpha + self.use_persistence = use_persistence + self.persist_alpha = persist_alpha self.title = title self.peak_hold = peak_hold @@ -78,13 +78,13 @@ class fft_sink_base(object): self.peak_hold = enable self.win.set_peak_hold(enable) - def set_emulate_analog(self, enable): - self.emulate_analog = enable - self.win.set_emulate_analog(enable) + def set_use_persistence(self, enable): + self.use_persistence = enable + self.win.set_use_persistence(enable) - def set_analog_alpha(self, analog_alpha): - self.analog_alpha = analog_alpha - self.win.set_analog_alpha(analog_alpha) + def set_persist_alpha(self, persist_alpha): + self.persist_alpha = persist_alpha + self.win.set_persist_alpha(persist_alpha) def set_avg_alpha(self, avg_alpha): self.avg_alpha = avg_alpha @@ -104,7 +104,7 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): def __init__(self, parent, baseband_freq=0, ref_scale=2.0, y_per_div=10, y_divs=8, ref_level=50, sample_rate=1, fft_size=512, fft_rate=default_fft_rate, average=False, avg_alpha=None, - title='', size=default_fftsink_size, peak_hold=False, emulate_analog=False,analog_alpha=0.2, **kwargs): + title='', size=default_fftsink_size, peak_hold=False, use_persistence=False,persist_alpha=0.2, **kwargs): gr.hier_block2.__init__(self, "fft_sink_f", gr.io_signature(1, 1, gr.sizeof_float), @@ -115,7 +115,7 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): sample_rate=sample_rate, fft_size=fft_size, fft_rate=fft_rate, average=average, avg_alpha=avg_alpha, title=title, - peak_hold=peak_hold,emulate_analog=emulate_analog,analog_alpha=analog_alpha) + peak_hold=peak_hold,use_persistence=use_persistence,persist_alpha=persist_alpha) self.s2p = gr.stream_to_vector(gr.sizeof_float, self.fft_size) self.one_in_n = gr.keep_one_in_n(gr.sizeof_float * self.fft_size, @@ -142,14 +142,14 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): self.win = fft_window(self, parent, size=size) self.set_average(self.average) self.set_peak_hold(self.peak_hold) - self.set_emulate_analog(self.emulate_analog) - self.set_analog_alpha(self.analog_alpha) + self.set_use_persistence(self.use_persistence) + self.set_persist_alpha(self.persist_alpha) class fft_sink_c(gr.hier_block2, fft_sink_base): def __init__(self, parent, baseband_freq=0, ref_scale=2.0, y_per_div=10, y_divs=8, ref_level=50, sample_rate=1, fft_size=512, fft_rate=default_fft_rate, average=False, avg_alpha=None, - title='', size=default_fftsink_size, peak_hold=False, emulate_analog=False,analog_alpha=0.2, **kwargs): + title='', size=default_fftsink_size, peak_hold=False, use_persistence=False,persist_alpha=0.2, **kwargs): gr.hier_block2.__init__(self, "fft_sink_c", gr.io_signature(1, 1, gr.sizeof_gr_complex), @@ -160,7 +160,7 @@ class fft_sink_c(gr.hier_block2, fft_sink_base): sample_rate=sample_rate, fft_size=fft_size, fft_rate=fft_rate, average=average, avg_alpha=avg_alpha, title=title, - peak_hold=peak_hold, emulate_analog=emulate_analog,analog_alpha=analog_alpha) + peak_hold=peak_hold, use_persistence=use_persistence,persist_alpha=persist_alpha) self.s2p = gr.stream_to_vector(gr.sizeof_gr_complex, self.fft_size) self.one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex * self.fft_size, @@ -186,8 +186,8 @@ class fft_sink_c(gr.hier_block2, fft_sink_base): self.win = fft_window(self, parent, size=size) self.set_average(self.average) - self.set_emulate_analog(self.emulate_analog) - self.set_analog_alpha(self.analog_alpha) + self.set_use_persistence(self.use_persistence) + self.set_persist_alpha(self.persist_alpha) self.set_peak_hold(self.peak_hold) @@ -251,9 +251,9 @@ class control_panel(wx.Panel): self.average_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Average") self.average_check_box.Bind(wx.EVT_CHECKBOX, parent.on_average) control_box.Add(self.average_check_box, 0, wx.EXPAND) - self.emulate_analog_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Emulate Analog") - self.emulate_analog_check_box.Bind(wx.EVT_CHECKBOX, parent.on_emulate_analog) - control_box.Add(self.emulate_analog_check_box, 0, wx.EXPAND) + self.use_persistence_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Persistence") + self.use_persistence_check_box.Bind(wx.EVT_CHECKBOX, parent.on_use_persistence) + control_box.Add(self.use_persistence_check_box, 0, wx.EXPAND) self.peak_hold_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Peak Hold") self.peak_hold_check_box.Bind(wx.EVT_CHECKBOX, parent.on_peak_hold) control_box.Add(self.peak_hold_check_box, 0, wx.EXPAND) @@ -294,7 +294,7 @@ class control_panel(wx.Panel): """ #update checkboxes self.average_check_box.SetValue(self.parent.fftsink.average) - self.emulate_analog_check_box.SetValue(self.parent.fftsink.emulate_analog) + self.use_persistence_check_box.SetValue(self.parent.fftsink.use_persistence) self.peak_hold_check_box.SetValue(self.parent.fftsink.peak_hold) #update radio buttons try: @@ -326,8 +326,8 @@ class fft_window (wx.Panel): self.peak_hold = False self.peak_vals = None - self.emulate_analog=False - self.analog_alpha=0.2 + self.use_persistence=False + self.persist_alpha=0.2 self.plot.SetEnableGrid (True) @@ -417,13 +417,13 @@ class fft_window (wx.Panel): y_range = ymin, ymax self.plot.Draw (graphics, xAxis=x_range, yAxis=y_range, step=self.fftsink.y_per_div) - def set_emulate_analog(self, enable): - self.emulate_analog = enable - self.plot.set_emulate_analog( enable) + def set_use_persistence(self, enable): + self.use_persistence = enable + self.plot.set_use_persistence( enable) - def set_analog_alpha(self, analog_alpha): - self.analog_alpha = analog_alpha - self.plot.set_analog_alpha(analog_alpha) + def set_persist_alpha(self, persist_alpha): + self.persist_alpha = persist_alpha + self.plot.set_persist_alpha(persist_alpha) def set_peak_hold(self, enable): self.peak_hold = enable @@ -434,9 +434,9 @@ class fft_window (wx.Panel): self.fftsink.set_average(evt.IsChecked()) self.control_panel.update() - def on_emulate_analog(self, evt): + def on_use_persistence(self, evt): # print "on_analog" - self.fftsink.set_emulate_analog(evt.IsChecked()) + self.fftsink.set_use_persistence(evt.IsChecked()) self.control_panel.update() def on_peak_hold(self, evt): @@ -522,11 +522,11 @@ class fft_window (wx.Panel): self.id_y_per_div_10 = wx.NewId() self.id_y_per_div_20 = wx.NewId() self.id_average = wx.NewId() - self.id_emulate_analog = wx.NewId() + self.id_use_persistence = wx.NewId() self.id_peak_hold = wx.NewId() self.plot.Bind(wx.EVT_MENU, self.on_average, id=self.id_average) - self.plot.Bind(wx.EVT_MENU, self.on_emulate_analog, id=self.id_emulate_analog) + self.plot.Bind(wx.EVT_MENU, self.on_use_persistence, id=self.id_use_persistence) self.plot.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold) self.plot.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level) self.plot.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level) @@ -542,7 +542,7 @@ class fft_window (wx.Panel): menu = wx.Menu() self.popup_menu = menu menu.AppendCheckItem(self.id_average, "Average") - menu.AppendCheckItem(self.id_emulate_analog, "Emulate Analog") + menu.AppendCheckItem(self.id_use_persistence, "Persistence") menu.AppendCheckItem(self.id_peak_hold, "Peak Hold") menu.Append(self.id_incr_ref_level, "Incr Ref Level") menu.Append(self.id_decr_ref_level, "Decr Ref Level") @@ -558,7 +558,7 @@ class fft_window (wx.Panel): self.checkmarks = { self.id_average : lambda : self.fftsink.average, - self.id_emulate_analog : lambda : self.fftsink.emulate_analog, + self.id_use_persistence : lambda : self.fftsink.use_persistence, self.id_peak_hold : lambda : self.fftsink.peak_hold, self.id_y_per_div_1 : lambda : self.fftsink.y_per_div == 1, self.id_y_per_div_2 : lambda : self.fftsink.y_per_div == 2, -- cgit From 2057623cf8f9e9738954b146d3a23577110f7906 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Thu, 13 May 2010 13:16:46 -0700 Subject: gr-wxgui: update copyrights --- gr-wxgui/src/python/fftsink_nongl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py index 0854d6668..508b4e772 100644 --- a/gr-wxgui/src/python/fftsink_nongl.py +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2003,2004,2005,2006,2007,2009 Free Software Foundation, Inc. +# Copyright 2003,2004,2005,2006,2007,2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # -- cgit From f919f9dcbb54a08e6e26d6c229ce92fb784fa1b2 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Fri, 13 Apr 2012 18:36:53 -0400 Subject: Removed whitespace and added dtools/bin/remove-whitespace as a tool to do this in the future. The sed script was provided by Moritz Fischer. --- gr-wxgui/src/python/fftsink_nongl.py | 94 ++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 47 deletions(-) (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py index 508b4e772..c756d8a3b 100644 --- a/gr-wxgui/src/python/fftsink_nongl.py +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -1,31 +1,31 @@ #!/usr/bin/env python # # Copyright 2003,2004,2005,2006,2007,2009,2010 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, gru, window from gnuradio.wxgui import stdgui2 import wx import plot import numpy -import math +import math DIV_LEVELS = (1, 2, 5, 10, 20) @@ -33,7 +33,7 @@ default_fftsink_size = (640,240) default_fft_rate = gr.prefs().get_long('wxgui', 'fft_rate', 15) class fft_sink_base(object): - def __init__(self, input_is_real=False, baseband_freq=0, y_per_div=10, + def __init__(self, input_is_real=False, baseband_freq=0, y_per_div=10, y_divs=8, ref_level=50, sample_rate=1, fft_size=512, fft_rate=default_fft_rate, @@ -73,7 +73,7 @@ class fft_sink_base(object): else: self.avg.set_taps(1.0) self.win.peak_vals = None - + def set_peak_hold(self, enable): self.peak_hold = enable self.win.set_peak_hold(enable) @@ -98,7 +98,7 @@ class fft_sink_base(object): def _set_n(self): self.one_in_n.set_n(max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) - + class fft_sink_f(gr.hier_block2, fft_sink_base): def __init__(self, parent, baseband_freq=0, ref_scale=2.0, @@ -116,17 +116,17 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): fft_rate=fft_rate, average=average, avg_alpha=avg_alpha, title=title, peak_hold=peak_hold,use_persistence=use_persistence,persist_alpha=persist_alpha) - + self.s2p = gr.stream_to_vector(gr.sizeof_float, self.fft_size) self.one_in_n = gr.keep_one_in_n(gr.sizeof_float * self.fft_size, max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) - + mywindow = window.blackmanharris(self.fft_size) self.fft = gr.fft_vfc(self.fft_size, True, mywindow) power = 0 for tap in mywindow: power += tap*tap - + self.c2mag = gr.complex_to_mag(self.fft_size) self.avg = gr.single_pole_iir_filter_ff(1.0, self.fft_size) @@ -135,7 +135,7 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): -10*math.log10(self.fft_size) # Adjust for number of bins -10*math.log10(power/self.fft_size) # Adjust for windowing loss -20*math.log10(ref_scale/2)) # Adjust for reference scale - + self.sink = gr.message_sink(gr.sizeof_float * self.fft_size, self.msgq, True) self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2mag, self.avg, self.log, self.sink) @@ -165,13 +165,13 @@ class fft_sink_c(gr.hier_block2, fft_sink_base): self.s2p = gr.stream_to_vector(gr.sizeof_gr_complex, self.fft_size) self.one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex * self.fft_size, max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) - + mywindow = window.blackmanharris(self.fft_size) self.fft = gr.fft_vcc(self.fft_size, True, mywindow) power = 0 for tap in mywindow: power += tap*tap - + self.c2mag = gr.complex_to_mag(self.fft_size) self.avg = gr.single_pole_iir_filter_ff(1.0, self.fft_size) @@ -180,7 +180,7 @@ class fft_sink_c(gr.hier_block2, fft_sink_base): -10*math.log10(self.fft_size) # Adjust for number of bins -10*math.log10(power/self.fft_size) # Adjust for windowing loss -20*math.log10(ref_scale/2)) # Adjust for reference scale - + self.sink = gr.message_sink(gr.sizeof_float * self.fft_size, self.msgq, True) self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2mag, self.avg, self.log, self.sink) @@ -203,7 +203,7 @@ class DataEvent(wx.PyEvent): self.SetEventType (myDATA_EVENT) self.data = data - def Clone (self): + def Clone (self): self.__class__ (self.GetId()) @@ -231,20 +231,20 @@ class input_watcher (gru.msgq_runner): del de class control_panel(wx.Panel): - - class LabelText(wx.StaticText): + + class LabelText(wx.StaticText): def __init__(self, window, label): wx.StaticText.__init__(self, window, -1, label) font = self.GetFont() font.SetWeight(wx.FONTWEIGHT_BOLD) font.SetUnderlined(True) self.SetFont(font) - + def __init__(self, parent): self.parent = parent - wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER) + wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER) control_box = wx.BoxSizer(wx.VERTICAL) - + #checkboxes for average and peak hold control_box.AddStretchSpacer() control_box.Add(self.LabelText(self, 'Options'), 0, wx.ALIGN_CENTER) @@ -255,9 +255,9 @@ class control_panel(wx.Panel): self.use_persistence_check_box.Bind(wx.EVT_CHECKBOX, parent.on_use_persistence) control_box.Add(self.use_persistence_check_box, 0, wx.EXPAND) self.peak_hold_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Peak Hold") - self.peak_hold_check_box.Bind(wx.EVT_CHECKBOX, parent.on_peak_hold) + self.peak_hold_check_box.Bind(wx.EVT_CHECKBOX, parent.on_peak_hold) control_box.Add(self.peak_hold_check_box, 0, wx.EXPAND) - + #radio buttons for div size control_box.AddStretchSpacer() control_box.Add(self.LabelText(self, 'Set dB/div'), 0, wx.ALIGN_CENTER) @@ -269,12 +269,12 @@ class control_panel(wx.Panel): self.radio_buttons.append(radio_button) radio_box.Add(radio_button, 0, wx.ALIGN_LEFT) control_box.Add(radio_box, 0, wx.EXPAND) - + #ref lvl buttons control_box.AddStretchSpacer() control_box.Add(self.LabelText(self, 'Adj Ref Lvl'), 0, wx.ALIGN_CENTER) control_box.AddSpacer(2) - button_box = wx.BoxSizer(wx.HORIZONTAL) + button_box = wx.BoxSizer(wx.HORIZONTAL) self.ref_plus_button = wx.Button(self, -1, '+', style=wx.BU_EXACTFIT) self.ref_plus_button.Bind(wx.EVT_BUTTON, parent.on_incr_ref_level) button_box.Add(self.ref_plus_button, 0, wx.ALIGN_CENTER) @@ -287,7 +287,7 @@ class control_panel(wx.Panel): self.SetSizerAndFit(control_box) #update self.update() - + def update(self): """ Read the state of the fft plot settings and update the control panel. @@ -296,14 +296,14 @@ class control_panel(wx.Panel): self.average_check_box.SetValue(self.parent.fftsink.average) self.use_persistence_check_box.SetValue(self.parent.fftsink.use_persistence) self.peak_hold_check_box.SetValue(self.parent.fftsink.peak_hold) - #update radio buttons + #update radio buttons try: index = list(DIV_LEVELS).index(self.parent.fftsink.y_per_div) self.radio_buttons[index].SetValue(True) except: pass - + def on_radio_button_change(self, evt): - selected_radio_button = filter(lambda rb: rb.GetValue(), self.radio_buttons)[0] + selected_radio_button = filter(lambda rb: rb.GetValue(), self.radio_buttons)[0] index = self.radio_buttons.index(selected_radio_button) self.parent.fftsink.set_y_per_div(DIV_LEVELS[index]) @@ -311,41 +311,41 @@ class fft_window (wx.Panel): def __init__ (self, fftsink, parent, id = -1, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = ""): - + self.fftsink = fftsink - #init panel and plot - wx.Panel.__init__(self, parent, -1) - self.plot = plot.PlotCanvas(self, id, pos, size, style, name) + #init panel and plot + wx.Panel.__init__(self, parent, -1) + self.plot = plot.PlotCanvas(self, id, pos, size, style, name) #setup the box with plot and controls self.control_panel = control_panel(self) main_box = wx.BoxSizer (wx.HORIZONTAL) main_box.Add (self.plot, 1, wx.EXPAND) main_box.Add (self.control_panel, 0, wx.EXPAND) self.SetSizerAndFit(main_box) - + self.peak_hold = False self.peak_vals = None self.use_persistence=False self.persist_alpha=0.2 - + self.plot.SetEnableGrid (True) # self.SetEnableZoom (True) # self.SetBackgroundColour ('black') - + self.build_popup_menu() self.set_baseband_freq(self.fftsink.baseband_freq) - + EVT_DATA_EVENT (self, self.set_data) wx.EVT_CLOSE (self, self.on_close_window) self.plot.Bind(wx.EVT_RIGHT_UP, self.on_right_click) self.plot.Bind(wx.EVT_MOTION, self.evt_motion) - + self.input_watcher = input_watcher(fftsink.msgq, fftsink.fft_size, self) def set_scale(self, freq): - x = max(abs(self.fftsink.sample_rate), abs(self.fftsink.baseband_freq)) + x = max(abs(self.fftsink.sample_rate), abs(self.fftsink.baseband_freq)) if x >= 1e9: self._scale_factor = 1e-9 self._units = "GHz" @@ -364,7 +364,7 @@ class fft_window (wx.Panel): self.peak_vals = None self.set_scale(baseband_freq) self.fftsink.set_baseband_freq(baseband_freq) - + def on_close_window (self, event): print "fft_window:on_close_window" self.keep_running = False @@ -381,7 +381,7 @@ class fft_window (wx.Panel): self.peak_vals = numpy.maximum(dB, self.peak_vals) if self.fftsink.input_is_real: # only plot 1/2 the points - x_vals = ((numpy.arange (L/2) * (self.fftsink.sample_rate + x_vals = ((numpy.arange (L/2) * (self.fftsink.sample_rate * self._scale_factor / L)) + self.fftsink.baseband_freq * self._scale_factor) self._points = numpy.zeros((len(x_vals), 2), numpy.float64) @@ -415,7 +415,7 @@ class fft_window (wx.Panel): ymax = self.fftsink.ref_level ymin = self.fftsink.ref_level - self.fftsink.y_per_div * self.fftsink.y_divs y_range = ymin, ymax - self.plot.Draw (graphics, xAxis=x_range, yAxis=y_range, step=self.fftsink.y_per_div) + self.plot.Draw (graphics, xAxis=x_range, yAxis=y_range, step=self.fftsink.y_per_div) def set_use_persistence(self, enable): self.use_persistence = enable @@ -489,7 +489,7 @@ class fft_window (wx.Panel): def evt_motion(self, event): if not hasattr(self, "_points"): return # Got here before first window data update - + # Clip to plotted values (ux, uy) = self.plot.GetXY(event) # Scaled position x_vals = numpy.array(self._points[:,0]) @@ -510,7 +510,7 @@ class fft_window (wx.Panel): tip.Enable(True) tip.SetDelay(0) self.SetToolTip(tip) - + def build_popup_menu(self): self.id_incr_ref_level = wx.NewId() self.id_decr_ref_level = wx.NewId() @@ -524,7 +524,7 @@ class fft_window (wx.Panel): self.id_average = wx.NewId() self.id_use_persistence = wx.NewId() self.id_peak_hold = wx.NewId() - + self.plot.Bind(wx.EVT_MENU, self.on_average, id=self.id_average) self.plot.Bind(wx.EVT_MENU, self.on_use_persistence, id=self.id_use_persistence) self.plot.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold) @@ -537,7 +537,7 @@ class fft_window (wx.Panel): self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_5) self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_10) self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_20) - + # make a menu menu = wx.Menu() self.popup_menu = menu -- cgit From 02484c4d8880b317e92077748e48989e0c0c0b34 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 20 Mar 2013 09:55:25 -0400 Subject: wxgui: fix scaling issue of nongl FFT plot (issue #523). wxgui: add some noise to the fftsink_nongl test case. --- gr-wxgui/src/python/fftsink_nongl.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py index c756d8a3b..c38abbb22 100644 --- a/gr-wxgui/src/python/fftsink_nongl.py +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -132,7 +132,7 @@ class fft_sink_f(gr.hier_block2, fft_sink_base): # FIXME We need to add 3dB to all bins but the DC bin self.log = gr.nlog10_ff(20, self.fft_size, - -10*math.log10(self.fft_size) # Adjust for number of bins + -20*math.log10(self.fft_size) # Adjust for number of bins -10*math.log10(power/self.fft_size) # Adjust for windowing loss -20*math.log10(ref_scale/2)) # Adjust for reference scale @@ -177,7 +177,7 @@ class fft_sink_c(gr.hier_block2, fft_sink_base): # FIXME We need to add 3dB to all bins but the DC bin self.log = gr.nlog10_ff(20, self.fft_size, - -10*math.log10(self.fft_size) # Adjust for number of bins + -20*math.log10(self.fft_size) # Adjust for number of bins -10*math.log10(power/self.fft_size) # Adjust for windowing loss -20*math.log10(ref_scale/2)) # Adjust for reference scale @@ -606,6 +606,8 @@ class test_app_block (stdgui2.std_top_block): # Generate a complex sinusoid #src1 = gr.sig_source_c (input_rate, gr.GR_SIN_WAVE, 100*2e3, 1) src1 = gr.sig_source_c (input_rate, gr.GR_CONST_WAVE, 100*5.75e3, 1) + noise1 = analog.noise_source_c(analog.GR_UNIFORM, 1.0/10) + add1 = blocks.add_cc() # We add these throttle blocks so that this demo doesn't # suck down all the CPU available. Normally you wouldn't use these. @@ -616,17 +618,24 @@ class test_app_block (stdgui2.std_top_block): ref_level=0, y_per_div=20, y_divs=10) vbox.Add (sink1.win, 1, wx.EXPAND) - self.connect(src1, thr1, sink1) + self.connect(src1, (add1,0)) + self.connect(noise1, (add1,1)) + self.connect(add1, thr1, sink1) #src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 100*2e3, 1) src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 100*5.75e3, 1) + noise2 = analog.noise_source_f(analog.GR_UNIFORM, 1.0/10) + add2 = blocks.add_ff() + thr2 = gr.throttle(gr.sizeof_float, input_rate) sink2 = fft_sink_f (panel, title="Real Data", fft_size=fft_size*2, sample_rate=input_rate, baseband_freq=100e3, ref_level=0, y_per_div=20, y_divs=10) vbox.Add (sink2.win, 1, wx.EXPAND) - self.connect(src2, thr2, sink2) + self.connect(src2, (add2,0)) + self.connect(noise2, (add2,1)) + self.connect(add2, thr2, sink2) def main (): app = stdgui2.stdapp (test_app_block, "FFT Sink Test App") -- cgit From 97dc187c612d8aa126215db708f265566fce0fda Mon Sep 17 00:00:00 2001 From: Marcus Leech Date: Tue, 19 Mar 2013 14:29:17 -0400 Subject: wxgui: make dummy set_callback stub in nongl sinks. Doesn't work, but also doesn't break the code. --- gr-wxgui/src/python/fftsink_nongl.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gr-wxgui/src/python/fftsink_nongl.py') diff --git a/gr-wxgui/src/python/fftsink_nongl.py b/gr-wxgui/src/python/fftsink_nongl.py index c38abbb22..473cc424c 100644 --- a/gr-wxgui/src/python/fftsink_nongl.py +++ b/gr-wxgui/src/python/fftsink_nongl.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2003,2004,2005,2006,2007,2009,2010 Free Software Foundation, Inc. +# Copyright 2003-2007,2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -99,6 +99,8 @@ class fft_sink_base(object): def _set_n(self): self.one_in_n.set_n(max(1, int(self.sample_rate/self.fft_size/self.fft_rate))) + def set_callback(self, callb): + return class fft_sink_f(gr.hier_block2, fft_sink_base): def __init__(self, parent, baseband_freq=0, ref_scale=2.0, -- cgit