discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] Simple display sink in wx


From: Achilleas Anastasopoulos
Subject: Re: [Discuss-gnuradio] Simple display sink in wx
Date: Mon, 12 Feb 2007 20:58:34 -0500
User-agent: Mozilla Thunderbird 1.0.2 (Windows/20050317)

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)...

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           

--
_______________________________________________________
Achilleas Anastasopoulos                        
Associate Professor
EECS Department               Voice : (734)615-4024
UNIVERSITY OF MICHIGAN        Fax   : (734)763-8041
Ann Arbor, MI 48109-2122      E-mail: address@hidden
URL: http://www-personal.engin.umich.edu/~anastas/      
_______________________________________________________




reply via email to

[Prev in Thread] Current Thread [Next in Thread]