[Top][All Lists]
[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
+ *
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r4662 - gnuradio/branches/developers/nldudok1/general-wip/gr-wxgui/src/python,
nldudok1 <=