[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Discuss-gnuradio] Simple display sink in wx
From: |
Martin Dvh |
Subject: |
Re: [Discuss-gnuradio] Simple display sink in wx |
Date: |
Wed, 14 Feb 2007 01:35:39 +0100 |
User-agent: |
Debian Thunderbird 1.0.2 (X11/20070113) |
Achilleas Anastasopoulos wrote:
> Martin,
>
> thanks for the block.
> Indeed it is exactly what I wanted (and even more)!!!
>
> One question: since a throttle is not attached to this block,
> why do we need separate sample_rate and number_rate parameters?
> The only place I saw them used is
>
> one_in_n = gr.keep_one_in_n(gr.sizeof_float,
> max(1, int(sample_rate/number_rate)))
>
> which implies that only the ratio of sample_rate/number_rate
> is important. Unless number_rate actually controls the
> real rate at which numbers are displayed (which I cannot figure out how)...
The number_rate limits the outputting of numbers to the screen.
If this would get more then around 50 numbers/sec this will use up all display
resources and your gui will freeze.
(xfree can't display more numbers/sec then your monitors refreshrate anyway)
This is the same effect you get when using the fftsink with a too high fft_rate.
Martin
>
> Thanks
> Achilleas
>
>
> Martin Dvh wrote:
>
>> Achilleas Anastasopoulos wrote:
>>
>>> Hi,
>>>
>>> it would be very useful to have a
>>> wx sink that displays the value of its input.
>>> This way we can check in real time values
>>> that change slowly (eg, snr, bit error rate, etc.)
>>
>>
>> Your widh is my command:
>> Attached is a patch which adds a number_sink_f and number_sink_c to
>> gr-wxgui.
>> You must apply it in the root of your gnuradio tree.
>> patch -p0 <numbersink.patch
>>
>> You can also find it in gr-wxgui in my work-in-progress development
>> tree in svn:
>> gnuradio/branches/developers/nldudok1/general-wip
>>
>> You use it in the following way:
>>
>> from gnuradio.wxgui import numbersink
>>
>> numsink = numbersink.number_sink_f (self, panel,
>> unit='volts',label="input level", avg_alpha=1.0e-5,average=True,
>> sample_rate=input_rate/sw_decim,
>> factor=1.0,base_value=0,
>> minval=-100.0, maxval=100.0,
>> ref_level=0, decimal_places=5,number_rate=15)
>> vbox.Add (numsink.win, 1, wx.EXPAND)
>> self.connect(some_float_source,numsink)
>>
>> You can set several options by right-mouse-click.
>> (Show gauge, number of digits, avaraging)
>> You use it just like an oscope or fft sink.
>>
>> the parameters:
>> fg flowgraph, the flowgraph (use self if you work with a
>> stdgui.gui_flow_graph)
>> parent wxguipanel, The wxgui parent (use panel if you work with a
>> stdgui.gui_flow_graph)
>> unit string, the unit you want to display, for example 'volt'
>> or 'Watt', free text.
>> base_value float, an offset which is added to the value
>> minval float, min value for the gauge
>> maxval float, max value for the gauge
>> factor float, scaling factor, value is multiplied by this (sort
>> of gain)
>> decimal_places int, the number of decimal places shown
>> ref_level ignored (API compatibility with scope and fft-sink)
>> sample_rate float, samplerate of input
>> number_rate float or int, rate at which values are displayed
>> (framerate, default is 15)
>> average bool, use averaging or not
>> avg_alpha float, average alpha, determines the speed of averaging
>> label string, the label which goes with this value (for example
>> 'frequency' or 'input power')
>> size default=(640,240), the graphical size of this numbersink
>> peak_hold bool, hold at peak or not.
>>
>>
>>> Unfortunately there is no how_to_write_a_wx_block
>>> so I have no idea how to go about it.
>>>
>>> If someone can help me by providing a stripped down
>>> version of one of the wx sinks (*eg, the oscope, or fft)
>>> then I can take a crack at it.
>>> Even better if one can implement this :-)
>>
>>
>> I hope you like it.
>>
>> Eric, is this maybe something for trunk.
>> I don't know if the code is clean enough.
>>
>> Greetings,
>> Martin
>>
>>> Thanks,
>>> Achilleas
>>>
>>>
>>> _______________________________________________
>>> Discuss-gnuradio mailing list
>>> address@hidden
>>> http://lists.gnu.org/mailman/listinfo/discuss-gnuradio
>>>
>>
>>
>>
>> ------------------------------------------------------------------------
>>
>> Index: gr-wxgui/src/python/numbersink.py
>> ===================================================================
>> --- gr-wxgui/src/python/numbersink.py (revision 0)
>> +++ gr-wxgui/src/python/numbersink.py (revision 0)
>> @@ -0,0 +1,614 @@
>> +#!/usr/bin/env python
>> +#
>> +# Copyright 2003,2004,2005,2006 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 2, 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., 59 Temple Place - Suite 330,
>> +# Boston, MA 02111-1307, USA.
>> +# +
>> +from gnuradio import gr, gru, window
>> +from gnuradio.wxgui import stdgui
>> +import wx
>> +#from wx import StaticText
>> +import gnuradio.wxgui.plot as plot
>> +import Numeric
>> +import threading
>> +import math +
>> +default_numbersink_size = (640,240)
>> +default_number_rate = gr.prefs().get_long('wxgui', 'number_rate', 15)
>> +
>> +class number_sink_base(object):
>> + def __init__(self, input_is_real=False, unit='',base_value=0,
>> minval=-100.0,maxval=100.0,factor=1.0,decimal_places=10, ref_level=50,
>> + sample_rate=1, +
>> number_rate=default_number_rate,
>> + average=False, avg_alpha=None, label='',
>> peak_hold=False):
>> +
>> + # initialize common attributes
>> + self.unit=unit
>> + self.base_value = base_value
>> + self.minval=minval
>> + self.maxval=maxval
>> + self.factor=factor
>> + self.y_divs = 8
>> + self.decimal_places=decimal_places
>> + self.ref_level = ref_level
>> + self.sample_rate = sample_rate
>> + number_size=1
>> + self.number_size = number_size
>> + self.number_rate = number_rate
>> + self.average = average
>> + if avg_alpha is None:
>> + self.avg_alpha = 2.0 / number_rate
>> + else:
>> + self.avg_alpha = avg_alpha
>> + self.label = label
>> + self.peak_hold = peak_hold
>> + self.show_gauge = True
>> + self.input_is_real = input_is_real
>> + self.msgq = gr.msg_queue(2) # queue that holds a
>> maximum of 2 messages
>> +
>> + def set_decimal_places(self, decimal_places):
>> + self.decimal_places = decimal_places
>> +
>> + def set_ref_level(self, ref_level):
>> + self.ref_level = ref_level
>> +
>> + def print_current_value(self, comment):
>> + print comment,self.win.current_value
>> +
>> + def set_average(self, average):
>> + self.average = average
>> + if average:
>> + self.avg.set_taps(self.avg_alpha)
>> + self.set_peak_hold(False)
>> + else:
>> + self.avg.set_taps(1.0)
>> +
>> + def set_peak_hold(self, enable):
>> + self.peak_hold = enable
>> + if enable:
>> + self.set_average(False)
>> + self.win.set_peak_hold(enable)
>> +
>> + def set_show_gauge(self, enable):
>> + self.show_gauge = enable
>> + self.win.set_show_gauge(enable)
>> +
>> + def set_avg_alpha(self, avg_alpha):
>> + self.avg_alpha = avg_alpha
>> +
>> + def set_base_value(self, base_value):
>> + self.base_value = base_value
>> + +
>> +class number_sink_f(gr.hier_block, number_sink_base):
>> + def __init__(self, fg, parent,
>> unit='',base_value=0,minval=-100.0,maxval=100.0,factor=1.0,
>> + decimal_places=10, ref_level=50, sample_rate=1,
>> #number_size=512,
>> + number_rate=default_number_rate, average=False,
>> avg_alpha=None,
>> + label='', size=default_numbersink_size,
>> peak_hold=False):
>> +
>> + number_sink_base.__init__(self, unit=unit,
>> input_is_real=True, base_value=base_value,
>> +
>> minval=minval,maxval=maxval,factor=factor,
>> + decimal_places=decimal_places,
>> ref_level=ref_level,
>> + sample_rate=sample_rate,
>> #number_size=number_size,
>> + number_rate=number_rate,
>> + average=average, avg_alpha=avg_alpha,
>> label=label,
>> + peak_hold=peak_hold)
>> + + number_size=1 + #s2p =
>> gr.stream_to_vector(gr.sizeof_float, number_size)
>> + one_in_n = gr.keep_one_in_n(gr.sizeof_float,
>> + max(1,
>> int(sample_rate/number_rate)))
>> +
>> + + #c2mag = gr.complex_to_mag(number_size)
>> + self.avg = gr.single_pole_iir_filter_ff(1.0, number_size)
>> +
>> + # FIXME We need to add 3dB to all bins but the DC bin
>> + #log = gr.nlog10_ff(20, number_size,
>> + #
>> -20*math.log10(number_size)-10*math.log10(power/number_size))
>> + sink = gr.message_sink(gr.sizeof_float , self.msgq, True)
>> +
>> + #fg.connect (s2p, one_in_n, fft, c2mag, self.avg, log, sink)
>> + fg.connect(self.avg,one_in_n,sink)
>> + gr.hier_block.__init__(self, fg, self.avg, sink)
>> + self.win = number_window(self, parent, size=size,label=label)
>> + self.set_average(self.average)
>> +
>> +
>> +class number_sink_c(gr.hier_block, number_sink_base):
>> + def __init__(self, fg, parent,
>> unit='',base_value=0,minval=-100.0,maxval=100.0,factor=1.0,
>> + decimal_places=10, ref_level=50, sample_rate=1,
>> #number_size=512,
>> + number_rate=default_number_rate, average=False,
>> avg_alpha=None,
>> + label='', size=default_numbersink_size,
>> peak_hold=False):
>> +
>> + number_sink_base.__init__(self, unit=unit,
>> input_is_real=False, base_value=base_value,factor=factor,
>> +
>> minval=minval,maxval=maxval,decimal_places=decimal_places,
>> ref_level=ref_level,
>> + sample_rate=sample_rate,
>> #number_size=number_size,
>> + number_rate=number_rate,
>> + average=average, avg_alpha=avg_alpha,
>> label=label,
>> + peak_hold=peak_hold)
>> +
>> + number_size=1 + one_in_n =
>> gr.keep_one_in_n(gr.sizeof_gr_complex,
>> + max(1,
>> int(sample_rate/number_rate)))
>> +
>> + + #c2mag = gr.complex_to_mag(number_size)
>> + self.avg = gr.single_pole_iir_filter_cc(1.0, number_size)
>> +
>> + # FIXME We need to add 3dB to all bins but the DC bin
>> + #log = gr.nlog10_ff(20, number_size,
>> + #
>> -20*math.log10(number_size)-10*math.log10(power/number_size))
>> + sink = gr.message_sink(gr.sizeof_gr_complex , self.msgq, True)
>> +
>> + #fg.connect (s2p, one_in_n, fft, c2mag, self.avg, log, sink)
>> + fg.connect(self.avg,one_in_n,sink)
>> + gr.hier_block.__init__(self, fg, self.avg, sink)
>> + self.win = number_window(self, parent, size=size,label=label)
>> + self.set_average(self.average)
>> +
>> +
>> +#
>> ------------------------------------------------------------------------
>> +
>> +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, number_size, event_receiver, **kwds):
>> + threading.Thread.__init__ (self, **kwds)
>> + self.setDaemon (1)
>> + self.msgq = msgq
>> + self.number_size = number_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 number 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 = Numeric.fromstring (s, Numeric.Float32)
>> + de = DataEvent (complex_data)
>> + wx.PostEvent (self.event_receiver, de)
>> + del de
>> +
>> +#========================================================================================
>>
>> +class static_text_window (wx.StaticText): #plot.PlotCanvas):
>> + def __init__ (self, parent, numbersink,id = -1,label="number",
>> + pos = wx.DefaultPosition, size = wx.DefaultSize,
>> + style = wx.DEFAULT_FRAME_STYLE, name = ""):
>> + #plot.PlotCanvas.__init__ (self, parent, id, pos, size,
>> style, name)
>> + wx.StaticText.__init__(self, parent, id, label, pos, size,
>> style, name)
>> + #self.static_text=wx.StaticText( parent, id, label, pos,
>> (size[0]/2,size[1]/2), style, name)
>> + #gauge_style = wx.GA_HORIZONTAL
>> + #self.gauge=wx.Gauge( parent, id, range=1000,
>> pos=(pos[0],pos[1]+size[1]/2),size=(size[0]/2,size[1]/2),
>> style=gauge_style, name = "gauge")
>> + #wx.BoxSizer.__init__ (self,wx.VERTICAL)
>> + #self.Add (self.static_text, 0, wx.EXPAND)
>> + #self.Add (self.gauge, 1, wx.EXPAND)
>> + self.parent=parent
>> + self.label=label
>> + #self.y_range = None
>> + self.numbersink = numbersink
>> + self.peak_hold = False
>> + self.peak_vals = None
>> +
>> + #self.SetEnableGrid (True)
>> + # self.SetEnableZoom (True)
>> + # self.SetBackgroundColour ('black')
>> + + self.build_popup_menu()
>> + + #EVT_DATA_EVENT (self, self.set_data)
>> + #wx.EVT_CLOSE (self, self.on_close_window)
>> + #self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
>> + self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
>> +
>> + #self.input_watcher = input_watcher(numbersink.msgq,
>> numbersink.number_size, self)
>> +
>> +
>> + def on_close_window (self, event):
>> + print "number_window:on_close_window"
>> + self.keep_running = False
>> +
>> +
>> + def set_peak_hold(self, enable):
>> + self.peak_hold = enable
>> + self.peak_vals = None
>> +
>> + def update_y_range (self):
>> + ymax = self.numbersink.ref_level
>> + ymin = self.numbersink.ref_level -
>> self.numbersink.decimal_places * self.numbersink.y_divs
>> + self.y_range = self._axisInterval ('min', ymin, ymax)
>> +
>> + def on_average(self, evt):
>> + # print "on_average"
>> + self.numbersink.set_average(evt.IsChecked())
>> +
>> + def on_peak_hold(self, evt):
>> + # print "on_peak_hold"
>> + self.numbersink.set_peak_hold(evt.IsChecked())
>> +
>> + def on_show_gauge(self, evt):
>> + # print "on_show_gauge"
>> + #if evt.IsChecked():
>> + self.numbersink.set_show_gauge(evt.IsChecked())
>> + print evt.IsChecked()
>> + # print "show gauge"
>> + #else:
>> + # self.parent.gauge.Hide()
>> + # print "hide gauge"
>> +
>> + def on_incr_ref_level(self, evt):
>> + # print "on_incr_ref_level"
>> + self.numbersink.set_ref_level(self.numbersink.ref_level
>> + + self.numbersink.decimal_places)
>> +
>> + def on_decr_ref_level(self, evt):
>> + # print "on_decr_ref_level"
>> + self.numbersink.set_ref_level(self.numbersink.ref_level
>> + - self.numbersink.decimal_places)
>> +
>> + def on_incr_decimal_places(self, evt):
>> + # print "on_incr_decimal_places"
>> +
>> self.numbersink.set_decimal_places(self.numbersink.decimal_places+1)
>> #next_up(self.numbersink.decimal_places, (1,2,5,10,20)))
>> +
>> + def on_decr_decimal_places(self, evt):
>> + # print "on_decr_decimal_places"
>> +
>> self.numbersink.set_decimal_places(max(self.numbersink.decimal_places-1,0))
>> #next_down(self.numbersink.decimal_places, (1,2,5,10,20)))
>> +
>> + def on_decimal_places(self, evt):
>> + # print "on_decimal_places"
>> + Id = evt.GetId()
>> + if Id == self.id_decimal_places_0:
>> + self.numbersink.set_decimal_places(0)
>> + elif Id == self.id_decimal_places_1:
>> + self.numbersink.set_decimal_places(1)
>> + elif Id == self.id_decimal_places_2:
>> + self.numbersink.set_decimal_places(2)
>> + elif Id == self.id_decimal_places_3:
>> + self.numbersink.set_decimal_places(3)
>> + elif Id == self.id_decimal_places_6:
>> + self.numbersink.set_decimal_places(6)
>> + elif Id == self.id_decimal_places_9:
>> + self.numbersink.set_decimal_places(9)
>> +
>> + + 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.PopupMenu(menu, event.GetPosition())
>> +
>> +
>> + def build_popup_menu(self):
>> + #self.id_hide_gauge = wx.NewId()
>> + self.id_show_gauge = wx.NewId()
>> + self.id_incr_ref_level = wx.NewId()
>> + self.id_decr_ref_level = wx.NewId()
>> + self.id_incr_decimal_places = wx.NewId()
>> + self.id_decr_decimal_places = wx.NewId()
>> + self.id_decimal_places_0 = wx.NewId()
>> + self.id_decimal_places_1 = wx.NewId()
>> + self.id_decimal_places_2 = wx.NewId()
>> + self.id_decimal_places_3 = wx.NewId()
>> + self.id_decimal_places_6 = wx.NewId()
>> + self.id_decimal_places_9 = wx.NewId()
>> + self.id_average = wx.NewId()
>> + self.id_peak_hold = wx.NewId()
>> +
>> + self.Bind(wx.EVT_MENU, self.on_average, id=self.id_average)
>> + self.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold)
>> + #self.Bind(wx.EVT_MENU, self.on_hide_gauge,
>> id=self.id_hide_gauge)
>> + self.Bind(wx.EVT_MENU, self.on_show_gauge,
>> id=self.id_show_gauge)
>> + self.Bind(wx.EVT_MENU, self.on_incr_ref_level,
>> id=self.id_incr_ref_level)
>> + self.Bind(wx.EVT_MENU, self.on_decr_ref_level,
>> id=self.id_decr_ref_level)
>> + self.Bind(wx.EVT_MENU, self.on_incr_decimal_places,
>> id=self.id_incr_decimal_places)
>> + self.Bind(wx.EVT_MENU, self.on_decr_decimal_places,
>> id=self.id_decr_decimal_places)
>> + self.Bind(wx.EVT_MENU, self.on_decimal_places,
>> id=self.id_decimal_places_0)
>> + self.Bind(wx.EVT_MENU, self.on_decimal_places,
>> id=self.id_decimal_places_1)
>> + self.Bind(wx.EVT_MENU, self.on_decimal_places,
>> id=self.id_decimal_places_2)
>> + self.Bind(wx.EVT_MENU, self.on_decimal_places,
>> id=self.id_decimal_places_3)
>> + self.Bind(wx.EVT_MENU, self.on_decimal_places,
>> id=self.id_decimal_places_6)
>> + self.Bind(wx.EVT_MENU, self.on_decimal_places,
>> id=self.id_decimal_places_9)
>> +
>> +
>> + # 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_hide_gauge, "Hide gauge")
>> + menu.AppendCheckItem(self.id_show_gauge, "Show gauge")
>> + 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_decimal_places, "Incr decimal places")
>> + menu.Append(self.id_decr_decimal_places, "Decr decimal places")
>> + menu.AppendSeparator()
>> + # we'd use RadioItems for these, but they're not supported on
>> Mac
>> + menu.AppendCheckItem(self.id_decimal_places_0, "0 decimal
>> places")
>> + menu.AppendCheckItem(self.id_decimal_places_1, "1 decimal
>> places")
>> + menu.AppendCheckItem(self.id_decimal_places_2, "2 decimal
>> places")
>> + menu.AppendCheckItem(self.id_decimal_places_3, "3 decimal
>> places")
>> + menu.AppendCheckItem(self.id_decimal_places_6, "6 decimal
>> places")
>> + menu.AppendCheckItem(self.id_decimal_places_9, "9 decimal
>> places")
>> +
>> + self.checkmarks = {
>> + self.id_average : lambda : self.numbersink.average,
>> + self.id_peak_hold : lambda :
>> self.numbersink.peak_hold,# self.id_hide_gauge : lambda :
>> self.numbersink.hide_gauge,
>> + self.id_show_gauge : lambda : self.numbersink.show_gauge,
>> + self.id_decimal_places_0 : lambda :
>> self.numbersink.decimal_places == 0,
>> + self.id_decimal_places_1 : lambda :
>> self.numbersink.decimal_places == 1,
>> + self.id_decimal_places_2 : lambda :
>> self.numbersink.decimal_places == 2,
>> + self.id_decimal_places_3 : lambda :
>> self.numbersink.decimal_places == 3,
>> + self.id_decimal_places_6 : lambda :
>> self.numbersink.decimal_places == 6,
>> + self.id_decimal_places_9 : lambda :
>> self.numbersink.decimal_places == 9,
>> + }
>> +
>> +
>> +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
>> +
>> +
>> +#========================================================================================
>>
>> +class number_window (plot.PlotCanvas):
>> + def __init__ (self, numbersink, parent, id = -1,label="number",
>> + pos = wx.DefaultPosition, size = wx.DefaultSize,
>> + style = wx.DEFAULT_FRAME_STYLE, name = ""):
>> + plot.PlotCanvas.__init__ (self, parent, id, pos, size, style,
>> name)
>> + #wx.StaticText.__init__(self, parent, id, label, pos,
>> (size[0]/2,size[1]/2), style, name)
>> + #print 'parent',parent
>> + self.static_text=static_text_window( self, numbersink,id,
>> label, pos, (size[0]/2,size[1]/2), style, name)
>> + gauge_style = wx.GA_HORIZONTAL
>> + vbox=wx.BoxSizer(wx.VERTICAL)
>> + vbox.Add (self.static_text, 0, wx.EXPAND)
>> + self.current_value=None
>> + if numbersink.input_is_real:
>> + self.gauge=wx.Gauge( self, id, range=1000,
>> pos=(pos[0],pos[1]+size[1]/2),size=(size[0]/2,size[1]/2),
>> style=gauge_style, name = "gauge")
>> + vbox.Add (self.gauge, 1, wx.EXPAND)
>> + else:
>> + self.gauge=wx.Gauge( self, id, range=1000,
>> pos=(pos[0],pos[1]+size[1]/3),size=(size[0]/2,size[1]/3),
>> style=gauge_style, name = "gauge")
>> + #hbox=wx.BoxSizer(wx.HORIZONTAL)
>> + self.gauge_imag=wx.Gauge( self, id, range=1000,
>> pos=(pos[0],pos[1]+size[1]*2/3),size=(size[0]/2,size[1]/3),
>> style=gauge_style, name = "gauge_imag")
>> + vbox.Add (self.gauge, 1, wx.EXPAND)
>> + vbox.Add (self.gauge_imag, 1, wx.EXPAND)
>> + #vbox.Add (hbox, 1, wx.EXPAND)
>> + self.sizer = vbox
>> + self.SetSizer (self.sizer)
>> + self.SetAutoLayout (True)
>> + self.sizer.Fit (self)
>> +
>> + self.label=label
>> + #self.y_range = None
>> + self.numbersink = numbersink
>> + self.peak_hold = False
>> + self.peak_vals = None
>> +
>> + #self.SetEnableGrid (True)
>> + # self.SetEnableZoom (True)
>> + # self.SetBackgroundColour ('black')
>> + + #self.build_popup_menu()
>> + + EVT_DATA_EVENT (self, self.set_data)
>> + wx.EVT_CLOSE (self, self.on_close_window)
>> + #self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
>> + #self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
>> +
>> + self.input_watcher = input_watcher(numbersink.msgq,
>> numbersink.number_size, self)
>> +
>> +
>> + def on_close_window (self, event):
>> + print "number_window:on_close_window"
>> + self.keep_running = False
>> +
>> + def set_show_gauge(self, enable):
>> + self.show_gauge = enable
>> + if enable:
>> + self.gauge.Show()
>> + if not self.numbersink.input_is_real:
>> + self.gauge_imag.Show()
>> + #print 'show'
>> + else:
>> + self.gauge.Hide()
>> + if not self.numbersink.input_is_real:
>> + self.gauge_imag.Hide()
>> + #print 'hide'
>> +
>> + def set_data (self, evt):
>> + numbers = evt.data
>> + L = len (numbers)
>> +
>> + if self.peak_hold:
>> + if self.peak_vals is None:
>> + self.peak_vals = numbers
>> + else:
>> + self.peak_vals = Numeric.maximum(numbers,
>> self.peak_vals)
>> + numbers = self.peak_vals
>> +
>> + if self.numbersink.input_is_real:
>> + real_value=numbers[0]*self.numbersink.factor +
>> self.numbersink.base_value
>> + imag_value=0.0
>> + self.current_value=real_value
>> + else:
>> + real_value=numbers[0]*self.numbersink.factor +
>> self.numbersink.base_value
>> + imag_value=numbers[1]*self.numbersink.factor +
>> self.numbersink.base_value
>> + self.current_value=complex(real_value,imag_value)
>> + #x = max(abs(self.numbersink.sample_rate),
>> abs(self.numbersink.base_value))
>> + x = max(real_value, imag_value)
>> + if x >= 1e9:
>> + sf = 1e-9
>> + unit_prefix = "G"
>> + elif x >= 1e6:
>> + sf = 1e-6
>> + unit_prefix = "M"
>> + elif x>= 1e3:
>> + sf = 1e-3
>> + unit_prefix = "k"
>> + else :
>> + sf = 1
>> + unit_prefix = ""
>> + #self.update_y_range ()
>> + if self.numbersink.input_is_real:
>> + showtext = "%s: %.*f %s%s" % (self.label,
>> self.numbersink.decimal_places,real_value*sf,unit_prefix,self.numbersink.unit)
>>
>> + else:
>> + showtext = "%s: %.*f,%.*f %s%s" % (self.label,
>> self.numbersink.decimal_places,real_value*sf,
>> +
>> self.numbersink.decimal_places,imag_value*sf,unit_prefix,self.numbersink.unit)
>>
>> + self.static_text.SetLabel(showtext)
>> + #print
>> (int(float((real_value-self.numbersink.base_value)*1000.0/(self.numbersink.maxval-self.numbersink.minval)))+500)
>>
>> +
>> self.gauge.SetValue(int(float((real_value-self.numbersink.base_value)*1000.0/(self.numbersink.maxval-self.numbersink.minval)))+500)
>>
>> + if not self.numbersink.input_is_real:
>> +
>> self.gauge.SetValue(int(float((imag_value-self.numbersink.base_value)*1000.0/(self.numbersink.maxval-self.numbersink.minval)))+500)
>>
>> +
>> + def set_peak_hold(self, enable):
>> + self.peak_hold = enable
>> + self.peak_vals = None
>> +
>> + def update_y_range (self):
>> + ymax = self.numbersink.ref_level
>> + ymin = self.numbersink.ref_level -
>> self.numbersink.decimal_places * self.numbersink.y_divs
>> + self.y_range = self._axisInterval ('min', ymin, ymax)
>> +
>> + def on_average(self, evt):
>> + # print "on_average"
>> + self.numbersink.set_average(evt.IsChecked())
>> +
>> + def on_peak_hold(self, evt):
>> + # print "on_peak_hold"
>> + self.numbersink.set_peak_hold(evt.IsChecked())
>> +
>> +
>> +
>> +
>> +
>> +
>> +
>> +
>> +
>> +
>> +# ----------------------------------------------------------------
>> +# Deprecated interfaces
>> +# ----------------------------------------------------------------
>> +
>> +# returns (block, win).
>> +# block requires a single input stream of float
>> +# win is a subclass of wxWindow
>> +
>> +def make_number_sink_f(fg, parent, label, number_size, input_rate,
>> ymin = 0, ymax=50):
>> + + block = number_sink_f(fg, parent, label=label,
>> number_size=number_size, sample_rate=input_rate,
>> + decimal_places=(ymax - ymin)/8, ref_level=ymax)
>> + return (block, block.win)
>> +
>> +# returns (block, win).
>> +# block requires a single input stream of gr_complex
>> +# win is a subclass of wxWindow
>> +
>> +def make_number_sink_c(fg, parent, label, number_size, input_rate,
>> ymin=0, ymax=50):
>> + block = number_sink_c(fg, parent, label=label,
>> number_size=number_size, sample_rate=input_rate,
>> + decimal_places=(ymax - ymin)/8, ref_level=ymax)
>> + return (block, block.win)
>> +
>> +
>> +# ----------------------------------------------------------------
>> +# Standalone test app
>> +# ----------------------------------------------------------------
>> +
>> +class test_app_flow_graph (stdgui.gui_flow_graph):
>> + def __init__(self, frame, panel, vbox, argv):
>> + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
>> +
>> + #number_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 = number_sink_c (self, panel, label="Complex Data",
>> number_size=number_size,
>> + # sample_rate=input_rate, base_value=100e3,
>> + # ref_level=0, decimal_places=3)
>> + #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 = number_sink_f (self, panel, unit='Hz',label="Real
>> Data", avg_alpha=0.001,#number_size=number_size*2,
>> + sample_rate=input_rate, base_value=100e3,
>> + ref_level=0, decimal_places=3)
>> + vbox.Add (sink2.win, 1, wx.EXPAND)
>> + sink3 = number_sink_c (self, panel, unit='V',label="Complex
>> Data", avg_alpha=0.001,#number_size=number_size*2,
>> + sample_rate=input_rate, base_value=0,
>> + ref_level=0, decimal_places=3)
>> + vbox.Add (sink3.win, 1, wx.EXPAND)
>> + self.connect (src2, thr2, sink2)
>> + self.connect (src1, thr1, sink3)
>> +def main ():
>> + app = stdgui.stdapp (test_app_flow_graph,
>> + "Number Sink Test App")
>> + app.MainLoop ()
>> +
>> +if __name__ == '__main__':
>> + main ()
>>
>> Property changes on: gr-wxgui/src/python/numbersink.py
>> ___________________________________________________________________
>> Name: svn:executable
>> + *
>>
>> Index: gr-wxgui/src/python/Makefile.am
>> ===================================================================
>> --- gr-wxgui/src/python/Makefile.am (revision 4343)
>> +++ gr-wxgui/src/python/Makefile.am (working copy)
>> @@ -37,4 +37,5 @@
>> scopesink.py \
>> waterfallsink.py \
>> slider.py \
>> - stdgui.py
>> + stdgui.py \
>> + numbersink.py
>
>