commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] r4662 - gnuradio/branches/developers/nldudok1/general-


From: nldudok1
Subject: [Commit-gnuradio] r4662 - gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python
Date: Tue, 27 Feb 2007 15:50:12 -0700 (MST)

Author: nldudok1
Date: 2007-02-27 15:50:12 -0700 (Tue, 27 Feb 2007)
New Revision: 4662

Added:
   
gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python/parallelsink.py
Modified:
   
gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python/Makefile.am
Log:
added general parallel datasink

Modified: 
gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python/Makefile.am
===================================================================
--- 
gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python/Makefile.am
   2007-02-27 17:45:35 UTC (rev 4661)
+++ 
gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python/Makefile.am
   2007-02-27 22:50:12 UTC (rev 4662)
@@ -38,4 +38,5 @@
        waterfallsink.py                \
        slider.py                       \
        stdgui.py                       \
-       numbersink.py           
+       numbersink.py                   \
+       parallelsink.py
\ No newline at end of file

Added: 
gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python/parallelsink.py
===================================================================
--- 
gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python/parallelsink.py
                               (rev 0)
+++ 
gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python/parallelsink.py
       2007-02-27 22:50:12 UTC (rev 4662)
@@ -0,0 +1,508 @@
+#!/usr/bin/env python
+#
+# Copyright 2003,2004,2005 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
+import gnuradio.wxgui.plot as plot
+import Numeric
+import threading
+import math    
+
+default_parallelgraphsink_size = (640,240)
+
+class parallel_graph_sink_base(object):
+    def __init__(self, input_is_real=False, baseband_freq=0, y_per_div=10, 
ref_level=0,
+                 sample_rate=1, block_size=512, display_rate=15,
+                 average=False, avg_alpha=None, title='', peak_hold=False,
+                 xminval=None,xmaxval=None,xstart=None,xend=None):
+
+        # initialize common attributes
+        self.baseband_freq = baseband_freq
+        self.y_divs = 8
+        self.y_per_div=y_per_div
+        self.ref_level = ref_level
+        self.sample_rate = sample_rate
+        self.block_size = block_size
+        self.display_rate = display_rate
+        self.average = average
+        if avg_alpha is None:
+            self.avg_alpha = 2.0 / display_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
+        self.xstart=xstart
+        self.xend=xend
+        self.xminval=xminval
+        self.xmaxval=xmaxval
+        self.show_all=False
+        if((xstart is None) & (xend is None)):
+          self.show_all=True
+        if(xstart is None):
+          self.xstart=0
+        if(xend is None):
+          self.xend=block_size
+        if(xminval is None):
+          self.xminval=0.0
+        if(xmaxval is None):
+          self.xmaxval=float(block_size-1)
+
+
+    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)
+            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_avg_alpha(self, avg_alpha):
+        self.avg_alpha = avg_alpha
+
+    def set_baseband_freq(self, baseband_freq):
+        self.baseband_freq = baseband_freq
+        
+class parallel_graph_sink_f(gr.hier_block, parallel_graph_sink_base):
+    def __init__(self, fg, parent, baseband_freq=0,
+                 y_per_div=10, ref_level=0, sample_rate=1, block_size=512,
+                 display_rate=15, average=True, avg_alpha=None, title='',
+                 size=default_parallelgraphsink_size, peak_hold=False,
+                 xminval=None,xmaxval=None,xstart=None,xend=None,
+                 log_type=None,log_offset=0):
+
+        parallel_graph_sink_base.__init__(self, input_is_real=True, 
baseband_freq=baseband_freq,
+                               y_per_div=y_per_div, ref_level=ref_level,
+                               sample_rate=sample_rate, block_size=block_size,
+                               display_rate=display_rate,
+                               average=average, avg_alpha=avg_alpha, 
title=title,
+                               peak_hold=peak_hold,
+                               
xminval=xminval,xmaxval=xmaxval,xstart=xstart,xend=xend)
+
+        one_in_n = gr.keep_one_in_n(gr.sizeof_float * block_size,
+                                    max(1, 
int(sample_rate/block_size/display_rate)))
+        self.avg = gr.single_pole_iir_filter_ff(1.0, block_size)
+        sink = gr.message_sink(gr.sizeof_float * block_size, self.msgq, True)
+        if not (log_type is None):
+          log = gr.nlog10_ff(20, block_size, log_offset)
+        if log_type is None:
+          fg.connect(one_in_n, self.avg, sink)
+        elif log_type=='PRE_AVG':
+          fg.connect(one_in_n,log, self.avg, sink)
+        elif log_type=='POST_AVG':
+          fg.connect(one_in_n, self.avg,log, sink)
+        else:
+          print 'warning log=',log,' not understood.'
+          print "use 'PRE_AVG', 'POST_AVG' or None"
+        gr.hier_block.__init__(self, fg, one_in_n, sink)
+        self.win = parallel_window(self, parent, size=size)
+        self.set_average(self.average)
+
+
+class parallel_graph_sink_c(gr.hier_block, parallel_graph_sink_base):
+    def __init__(self, fg, parent, baseband_freq=0,
+                 y_per_div=10, ref_level=0, sample_rate=1, block_size=512,
+                 display_rate=15, average=False, avg_alpha=None, title='',
+                 size=default_parallelgraphsink_size, peak_hold=False,
+                 xminval=None,xmaxval=None,xstart=None,xend=None,
+                 log_type=None,log_offset=0):
+
+        parallel_graph_sink_base.__init__(self, input_is_real=False, 
baseband_freq=baseband_freq,
+                               y_per_div=y_per_div, ref_level=ref_level,
+                               sample_rate=sample_rate, block_size=block_size,
+                               display_rate=display_rate,
+                               average=average, avg_alpha=avg_alpha, 
title=title,
+                               peak_hold=peak_hold,
+                               
xminval=xminval,xmaxval=xmaxval,xstart=xstart,xend=xend)
+
+        one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex * block_size,
+                                    max(1, 
int(sample_rate/block_size/display_rate)))
+
+        c2mag = gr.complex_to_mag(block_size)
+        self.avg = gr.single_pole_iir_filter_ff(1.0, block_size)
+        sink = gr.message_sink(gr.sizeof_float * block_size, self.msgq, True)
+
+        if not (log_type is None):
+          log = gr.nlog10_ff(20, block_size, log_offset)
+        if log_type is None:
+          fg.connect(one_in_n,c2mag, self.avg, sink)
+        elif log_type=='PRE_AVG':
+          fg.connect(one_in_n,c2mag,log, self.avg, sink)
+        elif log_type=='POST_AVG':
+          fg.connect(one_in_n, c2mag,self.avg,log, sink)
+        else:
+          print 'warning log=',log,' not understood.'
+          print "use 'PRE_AVG', 'POST_AVG' or None"
+        gr.hier_block.__init__(self, fg, one_in_n, sink)
+
+        self.win = parallel_window(self, parent, size=size)
+        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, block_size, event_receiver, **kwds):
+        threading.Thread.__init__ (self, **kwds)
+        self.setDaemon (1)
+        self.msgq = msgq
+        self.block_size = block_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 = Numeric.fromstring (s, Numeric.Float32)
+            de = DataEvent (complex_data)
+            wx.PostEvent (self.event_receiver, de)
+            del de
+    
+
+class parallel_window (plot.PlotCanvas):
+    def __init__ (self, parallelgraphsink, parent, id = -1,
+                  pos = wx.DefaultPosition, size = wx.DefaultSize,
+                  style = wx.DEFAULT_FRAME_STYLE, name = ""):
+        plot.PlotCanvas.__init__ (self, parent, id, pos, size, style, name)
+
+        self.y_range = None
+        self.parallelgraphsink = parallelgraphsink
+        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.input_watcher = input_watcher(parallelgraphsink.msgq, 
parallelgraphsink.block_size, self)
+
+
+    def on_close_window (self, event):
+        print "parallel_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 = Numeric.maximum(dB, self.peak_vals)
+                dB = self.peak_vals
+
+        x = max(abs(self.parallelgraphsink.sample_rate), 
abs(self.parallelgraphsink.baseband_freq))
+        if x >= 1e9:
+            sf = 1e-9
+            units = "GHz"
+        elif x >= 1e6:
+            sf = 1e-6
+            units = "MHz"
+        else:
+            sf = 1e-3
+            units = "kHz"
+        xstep=1
+        xstart=self.parallelgraphsink.xstart
+        xend=self.parallelgraphsink.xend
+        xgain=(self.parallelgraphsink.xmaxval - 
self.parallelgraphsink.xminval)/L
+        xoffset=self.parallelgraphsink.xminval
+        #xgain=(maxval - minval)/(xend-xstart)
+        #xoffset=minval-xstart
+        if  self.parallelgraphsink.show_all: #plot all points
+            x_vals = ((Numeric.arrayrange (L)
+                       * xgain)
+                      + xoffset)
+            points = Numeric.zeros((len(x_vals), 2), Numeric.Float64)
+            points[:,0] = x_vals
+            points[:,1] = dB[0:L]
+        else:
+            x_vals = ((Numeric.arrayrange (xstart,xend,xstep)
+                       * xgain)
+                      + xoffset)
+            points = Numeric.zeros((len(x_vals), 2), Numeric.Float64)
+            points[:,0] = x_vals
+            points[:,1] = dB[xstart:xend]            
+
+
+        lines = plot.PolyLine (points, colour='BLUE')
+
+        graphics = plot.PlotGraphics ([lines],
+                                      title=self.parallelgraphsink.title,
+                                      xLabel = units, yLabel = "dB")
+
+        self.Draw (graphics, xAxis=None, yAxis=self.y_range)
+        self.update_y_range ()
+
+    def set_peak_hold(self, enable):
+        self.peak_hold = enable
+        self.peak_vals = None
+
+    def update_y_range (self):
+        ymax = self.parallelgraphsink.ref_level + 
0.5*self.parallelgraphsink.y_per_div * self.parallelgraphsink.y_divs
+        ymin = self.parallelgraphsink.ref_level - 
0.5*self.parallelgraphsink.y_per_div * self.parallelgraphsink.y_divs
+        self.y_range = self._axisInterval ('min', ymin, ymax)
+
+    def on_average(self, evt):
+        # print "on_average"
+        self.parallelgraphsink.set_average(evt.IsChecked())
+
+    def on_peak_hold(self, evt):
+        # print "on_peak_hold"
+        self.parallelgraphsink.set_peak_hold(evt.IsChecked())
+
+    def on_incr_ref_level(self, evt):
+        # print "on_incr_ref_level"
+        self.parallelgraphsink.set_ref_level(self.parallelgraphsink.ref_level
+                                   + self.parallelgraphsink.y_per_div)
+
+    def on_decr_ref_level(self, evt):
+        # print "on_decr_ref_level"
+        self.parallelgraphsink.set_ref_level(self.parallelgraphsink.ref_level
+                                   - self.parallelgraphsink.y_per_div)
+
+    def on_incr_y_per_div(self, evt):
+        # print "on_incr_y_per_div"
+        
self.parallelgraphsink.set_y_per_div(next_up(self.parallelgraphsink.y_per_div, 
(0.01,0.05,0.1,0.2,0.5,1,2,5,10,20,50,100,200,500,1000,2000,5000,10000,20000,50000,100000,200000,500000,1000000)))
+
+    def on_decr_y_per_div(self, evt):
+        # print "on_decr_y_per_div"
+        
self.parallelgraphsink.set_y_per_div(next_down(self.parallelgraphsink.y_per_div,
 
(0.01,0.05,0.1,0.2,0.5,1,2,5,10,20,50,100,200,500,1000,2000,5000,10000,20000,50000,100000,200000,500000,1000000)))
+
+    def on_y_per_div(self, evt):
+        # print "on_y_per_div"
+        Id = evt.GetId()
+        if Id == self.id_y_per_div_1:
+            self.parallelgraphsink.set_y_per_div(1)
+        elif Id == self.id_y_per_div_2:
+            self.parallelgraphsink.set_y_per_div(2)
+        elif Id == self.id_y_per_div_5:
+            self.parallelgraphsink.set_y_per_div(5)
+        elif Id == self.id_y_per_div_10:
+            self.parallelgraphsink.set_y_per_div(10)
+        elif Id == self.id_y_per_div_20:
+            self.parallelgraphsink.set_y_per_div(20)
+
+        
+    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_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.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_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_y_per_div, 
id=self.id_incr_y_per_div)
+        self.Bind(wx.EVT_MENU, self.on_decr_y_per_div, 
id=self.id_decr_y_per_div)
+        self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_1)
+        self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_2)
+        self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_5)
+        self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_10)
+        self.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.parallelgraphsink.average,
+            self.id_peak_hold : lambda : self.parallelgraphsink.peak_hold,
+            self.id_y_per_div_1 : lambda : self.parallelgraphsink.y_per_div == 
1,
+            self.id_y_per_div_2 : lambda : self.parallelgraphsink.y_per_div == 
2,
+            self.id_y_per_div_5 : lambda : self.parallelgraphsink.y_per_div == 
5,
+            self.id_y_per_div_10 : lambda : self.parallelgraphsink.y_per_div 
== 10,
+            self.id_y_per_div_20 : lambda : self.parallelgraphsink.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
+
+
+# ----------------------------------------------------------------
+#                    Deprecated interfaces
+# ----------------------------------------------------------------
+
+# returns (block, win).
+#   block requires a single input stream of float
+#   win is a subclass of wxWindow
+
+def make_parallel_graph_sink_f(fg, parent, title, block_size, input_rate, ymin 
= 0, ymax=50):
+    
+    block = parallel_graph_sink_f(fg, parent, title=title, 
block_size=block_size, sample_rate=input_rate,
+                       y_per_div=(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_parallel_graph_sink_c(fg, parent, title, block_size, input_rate, 
ymin=0, ymax=50):
+    block = parallel_graph_sink_c(fg, parent, title=title, 
block_size=block_size, sample_rate=input_rate,
+                       y_per_div=(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)
+
+        block_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, 10)
+        #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)
+
+        #convert to parallel stream
+        s2p1=gr.serial_to_parallel(gr.sizeof_gr_complex,block_size)
+
+        sink1 = parallel_graph_sink_c (self, panel, title="Complex Data", 
block_size=block_size,
+                            sample_rate=input_rate, baseband_freq=100e3,
+                            ref_level=0, y_per_div=10)
+        vbox.Add (sink1.win, 1, wx.EXPAND)
+        self.connect (src1, thr1,s2p1, sink1)
+
+        src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 10)
+        #src2 = gr.sig_source_f (input_rate, gr.GR_CONST_WAVE, 5.75e3, 1)
+        thr2 = gr.throttle(gr.sizeof_float, input_rate)
+        #convert to parallel stream
+        s2p2=gr.serial_to_parallel(gr.sizeof_float,block_size*2)
+        sink2 = parallel_graph_sink_f (self, panel, title="Real Data", 
block_size=block_size*2,
+                            sample_rate=input_rate, baseband_freq=100e3,
+                            ref_level=0, 
y_per_div=10,xstart=int(block_size*1.9))
+        vbox.Add (sink2.win, 1, wx.EXPAND)
+        self.connect (src2, thr2, s2p2,sink2)
+
+def main ():
+    app = stdgui.stdapp (test_app_flow_graph,
+                         "Parallel Sink Test App")
+    app.MainLoop ()
+
+if __name__ == '__main__':
+    main ()


Property changes on: 
gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python/parallelsink.py
___________________________________________________________________
Name: svn:executable
   + *





reply via email to

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