Simple display sink in wx

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

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 :slight_smile:

Thanks,
Achilleas

Achilleas A. 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 :slight_smile:
I hope you like it.

Eric, is this maybe something for trunk.
I don’t know if the code is clean enough.

Greetings,
Martin

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 D. wrote:

Attached is a patch which adds a number_sink_f and number_sink_c to gr-wxgui.
numsink = numbersink.number_sink_f (self, panel, unit=‘volts’,label=“input level”, avg_alpha=1.0e-5,average=True,
the parameters:
number_rate float or int, rate at which values are displayed (framerate, default is 15)

If someone can help me by providing a stripped down
Martin

+#
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+from gnuradio.wxgui import stdgui
+class number_sink_base(object):

  •    self.factor=factor
    
  •    else:
    
  • def set_ref_level(self, ref_level):
  •    else:
    
  •    self.win.set_show_gauge(enable)
    
  •             decimal_places=10, ref_level=50, sample_rate=1, #number_size=512,
    
  •    #log = gr.nlog10_ff(20, number_size,
    

+class number_sink_c(gr.hier_block, number_sink_base):

  •                           peak_hold=peak_hold)
    
  •    #log = gr.nlog10_ff(20, number_size,
    

+# ------------------------------------------------------------------------
+

  •    self.event_receiver = event_receiver
    
  •    #wx.BoxSizer.__init__ (self,wx.VERTICAL)
    
  •    # self.SetEnableZoom (True)
    
  • def update_y_range (self):
  •    self.numbersink.set_peak_hold(evt.IsChecked())
    
  • def on_incr_decimal_places(self, evt):
  •    if Id == self.id_decimal_places_0:
    
  •        self.numbersink.set_decimal_places(9)
    
  • def build_popup_menu(self):
  •    self.id_decimal_places_6 = wx.NewId()
    
  •    self.Bind(wx.EVT_MENU, self.on_incr_decimal_places, id=self.id_incr_decimal_places)
    
  •    menu = wx.Menu()
    
  •    # we'd use RadioItems for these, but they're not supported on Mac
    
  •        self.id_show_gauge : lambda : self.numbersink.show_gauge,
    
  • “”"
  • “”"
    +class number_window (plot.PlotCanvas):
  •    self.current_value=None
    
  •    self.sizer = vbox
    
  •    #self.SetEnableGrid (True)
    
  •    self.input_watcher = input_watcher(numbersink.msgq, numbersink.number_size, self)
    
  •      if not self.numbersink.input_is_real:
    
  •    L = len (numbers)
    
  •        imag_value=0.0
    
  •    elif x >= 1e6:
    
  •      showtext = "%s: %.*f %s%s" % (self.label, self.numbersink.decimal_places,real_value*sf,unit_prefix,self.numbersink.unit)
    
  •    self.peak_hold = enable
    

+def make_number_sink_f(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,
  •    stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv)
    
  •    # We add these throttle blocks so that this demo doesn't
    
  •    #src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1)
    
  •    self.connect (src1, thr1, sink3)
    

Name: svn:executable

  • stdgui.py
  • stdgui.py \
  • numbersink.py


Achilleas A.
Associate Professor
EECS Department Voice : (734)615-4024
UNIVERSITY OF MICHIGAN Fax : (734)763-8041
Ann Arbor, MI 48109-2122 E-mail: [email protected]
URL: U-M Web Hosting


Achilleas A. wrote:

                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

On Fri, Feb 16, 2007 at 09:49:45AM -0500, Achilleas A.
wrote:

Martin,

I think the display code can be uploaded to the trunk.
All the tests that I have tried work fine.
We can always clean up the code later if needed.

I can do that if there is no objection
Achilleas

Works for me.

Please go ahead and add it.

Thanks,
Eric

Martin,

I think the display code can be uploaded to the trunk.
All the tests that I have tried work fine.
We can always clean up the code later if needed.

I can do that if there is no objection
Achilleas

Martin D. wrote:

You use it in the following way:
self.connect(some_float_source,numsink)
unit string, the unit you want to display, for example ‘volt’
(framerate, default is 15)

so I have no idea how to go about it.
I don’t know if the code is clean enough.
Discuss-gnuradio mailing list
— gr-wxgui/src/python/numbersink.py (revision 0)
+# +# GNU Radio is distributed in the hope that it will be useful,
+import wx
minval=-100.0,maxval=100.0,factor=1.0,decimal_places=10, ref_level=50,

  •    self.factor=factor
    
  •    else:
    
  •        self.set_peak_hold(False)
    
  •    self.show_gauge = enable
    

unit=‘’,base_value=0,minval=-100.0,maxval=100.0,factor=1.0,
minval=minval,maxval=maxval,factor=factor,

  •    one_in_n = gr.keep_one_in_n(gr.sizeof_float,
    
  •    sink = gr.message_sink(gr.sizeof_float , self.msgq, True)
    

unit=‘’,base_value=0,minval=-100.0,maxval=100.0,factor=1.0,
minval=minval,maxval=maxval,decimal_places=decimal_places,

  •                                max(1,
    

+myDATA_EVENT = wx.NewEventType()
+
+

  •        # There may be more than one number in the message.
    

+#========================================================================================
(size[0]/2,size[1]/2), style, name)

  •    self.numbersink = numbersink
    
  •    self.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
    
  • def set_peak_hold(self, enable):
  •    # print "on_average"
    
  •    print evt.IsChecked()
    
  • def on_decr_ref_level(self, evt):
  • def on_decr_decimal_places(self, evt):
  •    elif Id == self.id_decimal_places_1:
    
  •    +    def on_right_click(self, event):
    
  •    self.id_incr_ref_level = wx.NewId()
    
  •    self.id_peak_hold = wx.NewId()
    

id=self.id_decr_ref_level)

  •    self.Bind(wx.EVT_MENU, self.on_decimal_places,
    
  •    menu.AppendCheckItem(self.id_average, "Average")
    
  •    menu.AppendCheckItem(self.id_decimal_places_0, "0 decimal
    

places")
self.numbersink.decimal_places == 1,
+

  • “”"
  •    #print 'parent',parent
    
  •      vbox.Add (self.gauge, 1, wx.EXPAND)
    
  •      #vbox.Add (hbox, 1, wx.EXPAND)
    

numbersink.number_size, self)

  •      if not self.numbersink.input_is_real:
    
  •    L = len (numbers)
    
  •        real_value=numbers[0]*self.numbersink.factor +
    

abs(self.numbersink.base_value))

  •    else :
    

self.numbersink.decimal_places * self.numbersink.y_divs
+
+# ----------------------------------------------------------------

  • return (block, block.win)
  • return (block, block.win)
  •    #number_size = 256
    
  •    # suck down all the CPU available.  Normally you wouldn't use
    
  •    src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 1)
    
  •                        sample_rate=input_rate, base_value=0,
    
  • main ()
    @@ -37,4 +37,5 @@
    scopesink.py
    waterfallsink.py
    slider.py \
  • stdgui.py
  • stdgui.py \
  • numbersink.py


Achilleas A.
Associate Professor
EECS Department Voice : (734)615-4024
UNIVERSITY OF MICHIGAN Fax : (734)763-8041
Ann Arbor, MI 48109-2122 E-mail: [email protected]
URL: U-M Web Hosting


Is it possible to generate a gnuradio block (gr_block)
with two kinds of inputs (say, shorts and floats)?

Looking at the contructor, and the gr_io_signature class
it is not clear how to do that…

gr_block::gr_block ( const std::string & name,
gr_io_signature_sptr input_signature,
gr_io_signature_sptr output_signature
) [protected]

Thanks
Achilleas

On Sun, Feb 18, 2007 at 04:37:10PM -0500, Achilleas A.
wrote:

Thanks
Achilleas

It’s not currently possible, though not too hard to add.
I agree that it would be useful.

The underlying code can deal with different types for the ports. It
uses the port specific sizeof_stream_item(index) to retrieve the info.
The only thing missing is a way to build a gr_io_signature with
different
types for the elements.

Why don’t you take a look at the code in gr_io_signature.{h,cc}, and
let me know if you’ve got any questions about how to make the change.
There are a couple of ways it could go. Probably the easiest is to
create a std::vector<size_t> indexed by stream index instead of just
using the same d_sizeof_stream_item for all of them.

Eric

Achilleas A. wrote:

Martin,

I think the display code can be uploaded to the trunk.
All the tests that I have tried work fine.
We can always clean up the code later if needed.

I can do that if there is no objection
Achilleas
Fine with me,

Martin