[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r8741 - in gnuradio/branches/developers/jblum/gr-wxglg
From: |
jblum |
Subject: |
[Commit-gnuradio] r8741 - in gnuradio/branches/developers/jblum/gr-wxglgui/src: . python |
Date: |
Fri, 27 Jun 2008 15:40:04 -0600 (MDT) |
Author: jblum
Date: 2008-06-27 15:40:03 -0600 (Fri, 27 Jun 2008)
New Revision: 8741
Added:
gnuradio/branches/developers/jblum/gr-wxglgui/src/Makefile.am
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/Makefile.am
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/__init__.py
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
Modified:
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py
Log:
added Makefiles, fft sink callbacks, common module
Added: gnuradio/branches/developers/jblum/gr-wxglgui/src/Makefile.am
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/Makefile.am
(rev 0)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/Makefile.am
2008-06-27 21:40:03 UTC (rev 8741)
@@ -0,0 +1,24 @@
+#
+# Copyright 2008 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 3, 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., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+include $(top_srcdir)/Makefile.common
+
+SUBDIRS = python
Added: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/Makefile.am
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/Makefile.am
(rev 0)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/Makefile.am
2008-06-27 21:40:03 UTC (rev 8741)
@@ -0,0 +1,36 @@
+#
+# Copyright 2008 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 3, 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., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+include $(top_srcdir)/Makefile.common
+
+# Install this stuff so that it ends up as the gnuradio.wxglgui module
+# This usually ends up at:
+# ${prefix}/lib/python${python_version}/site-packages/gnuradio/wxglgui
+
+ourpythondir = $(grpythondir)/wxglgui
+ourlibdir = $(grpyexecdir)/wxglgui
+
+ourpython_PYTHON = \
+ __init__.py \
+ gltext.py \
+ plotter.py \
+ common.py \
+ fftsink.py
Added: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/__init__.py
===================================================================
Added: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
(rev 0)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
2008-06-27 21:40:03 UTC (rev 8741)
@@ -0,0 +1,54 @@
+#
+# Copyright 2008 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 3, 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., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import threading
+import wx
+
+class LabelText(wx.StaticText):
+ """!
+ Label text to give the wx plots a uniform look.
+ Get the default label text and set the font bold.
+ """
+
+ def __init__(self, window, label):
+ wx.StaticText.__init__(self, window, -1, label)
+ font = self.GetFont()
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ font.SetUnderlined(True)
+ self.SetFont(font)
+
+class input_watcher(threading.Thread):
+ """!
+ Input watcher thread runs forever.
+ Read messages from the message queue.
+ Forward messages to the message handler.
+ """
+
+ def __init__ (self, msgq, handle_msg):
+ threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.msgq = msgq
+ self.handle_msg = handle_msg
+ self.keep_running = True
+ self.start()
+
+ def run(self):
+ while self.keep_running:
self.handle_msg(self.msgq.delete_head())
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
2008-06-27 18:53:10 UTC (rev 8740)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
2008-06-27 21:40:03 UTC (rev 8741)
@@ -24,15 +24,16 @@
##################################################
from gnuradio import gr, window
import plotter
+import common
import wx
import math
-import threading
import numpy
##################################################
# Constants
##################################################
DEFAULT_FFT_RATE = gr.prefs().get_long('wxgui', 'fft_rate', 15)
+DEFAULT_WIN_SIZE = (640, 240)
DIV_LEVELS = (1, 2, 5, 10, 20)
##################################################
@@ -43,14 +44,6 @@
A control panel with wx widgits to control the plotter and fft block
chain.
"""
- class LabelText(wx.StaticText):
- def __init__(self, window, label):
- wx.StaticText.__init__(self, window, -1, label)
- font = self.GetFont()
- font.SetWeight(wx.FONTWEIGHT_BOLD)
- font.SetUnderlined(True)
- self.SetFont(font)
-
def __init__(self, parent):
"""!
Create a new control panel.
@@ -62,17 +55,17 @@
#checkboxes for average and peak hold
control_box.AddStretchSpacer()
- control_box.Add(self.LabelText(self, 'Options'), 0,
wx.ALIGN_CENTER)
+ control_box.Add(common.LabelText(self, 'Options'), 0,
wx.ALIGN_CENTER)
self.average_check_box = wx.CheckBox(parent=self,
style=wx.CHK_2STATE, label="Average")
- self.average_check_box.Bind(wx.EVT_CHECKBOX, parent.on_average)
+ self.average_check_box.Bind(wx.EVT_CHECKBOX, self.on_average)
control_box.Add(self.average_check_box, 0, wx.EXPAND)
self.peak_hold_check_box = wx.CheckBox(parent=self,
style=wx.CHK_2STATE, label="Peak Hold")
- self.peak_hold_check_box.Bind(wx.EVT_CHECKBOX,
parent.on_peak_hold)
+ self.peak_hold_check_box.Bind(wx.EVT_CHECKBOX,
self.on_peak_hold)
control_box.Add(self.peak_hold_check_box, 0, wx.EXPAND)
#radio buttons for div size
control_box.AddStretchSpacer()
- control_box.Add(self.LabelText(self, 'Set dB/div'), 0,
wx.ALIGN_CENTER)
+ control_box.Add(common.LabelText(self, 'Set dB/div'), 0,
wx.ALIGN_CENTER)
radio_box = wx.BoxSizer(wx.VERTICAL)
self.radio_buttons = list()
for y_per_div in DIV_LEVELS:
@@ -84,14 +77,14 @@
#ref lvl buttons
control_box.AddStretchSpacer()
- control_box.Add(self.LabelText(self, 'Adj Ref Lvl'), 0,
wx.ALIGN_CENTER)
+ control_box.Add(common.LabelText(self, 'Adj Ref Lvl'), 0,
wx.ALIGN_CENTER)
control_box.AddSpacer(2)
button_box = wx.BoxSizer(wx.HORIZONTAL)
self.ref_plus_button = wx.Button(self, -1, '+',
style=wx.BU_EXACTFIT)
- self.ref_plus_button.Bind(wx.EVT_BUTTON,
parent.on_incr_ref_level)
+ self.ref_plus_button.Bind(wx.EVT_BUTTON, self.on_incr_ref_level)
button_box.Add(self.ref_plus_button, 0, wx.ALIGN_CENTER)
self.ref_minus_button = wx.Button(self, -1, ' - ',
style=wx.BU_EXACTFIT)
- self.ref_minus_button.Bind(wx.EVT_BUTTON,
parent.on_decr_ref_level)
+ self.ref_minus_button.Bind(wx.EVT_BUTTON,
self.on_decr_ref_level)
button_box.Add(self.ref_minus_button, 0, wx.ALIGN_CENTER)
control_box.Add(button_box, 0, wx.ALIGN_CENTER)
control_box.AddStretchSpacer()
@@ -113,10 +106,17 @@
self.radio_buttons[index].SetValue(True)
except: pass
+ ##################################################
+ # Event handlers
+ ##################################################
def on_radio_button_change(self, event):
selected_radio_button = filter(lambda rb: rb.GetValue(),
self.radio_buttons)[0]
index = self.radio_buttons.index(selected_radio_button)
- self.parent.set_y_per_div(DIV_LEVELS[index])
+ self.parent.set_y_per_div(DIV_LEVELS[index])
+ def on_average(self, event): self.parent.set_average(event.IsChecked())
+ def on_peak_hold(self, event):
self.parent.set_peak_hold(event.IsChecked())
+ def on_incr_ref_level(self, event): self.parent.incr_ref_level()
+ def on_decr_ref_level(self, event): self.parent.decr_ref_level()
##################################################
# FFT window with plotter and control panel
@@ -124,7 +124,8 @@
class fft_window(wx.Panel):
def __init__(
self,
- parent,
+ parent,
+ size,
title,
real,
baseband_freq,
@@ -139,41 +140,23 @@
#ensure y_per_div
if y_per_div not in DIV_LEVELS: y_per_div = DIV_LEVELS[0]
#setup
+ self.real = real
+ self.baseband_freq = baseband_freq
+ self.sample_rate = sample_rate
+ self.x_divs = 8.0 #approximate
self.y_per_div = y_per_div
self.y_divs = y_divs
self.ref_level = ref_level
self.average = average
self.peak_hold = peak_hold
- self.set_average = set_average
+ self.fft_set_average = set_average
self.peak_vals = []
- #determine best fitting x_per_div
- x_divs = 8.0 #appoximate
- if real: x_width = sample_rate/2.0
- else: x_width = sample_rate
- exp = math.floor(math.log10(x_width/x_divs))
- x_per_divs = numpy.array((1, 2, 5, 10))*10**exp
- x_per_div = x_per_divs[numpy.argmin(numpy.abs(x_per_divs -
x_width/x_divs))]
- #calculate units and scalar
- if exp >= 9: units, power = 'GHz', 9
- elif exp >= 6: units, power = 'MHz', 6
- elif exp >= 3: units, power = 'KHz', 3
- else: units, power = 'Hz', 0
- scalar = 10**(-1*power)
#init panel and plot
wx.Panel.__init__(self, parent, -1)
- self.plotter = plotter.grid_plotter(self, title,
'Frequency(%s)'%units, 'Amplitude(dB)', 35, 10, 40, 60)
- if real:
- self.plotter.set_x_grid(
- scalar*baseband_freq,
- scalar*baseband_freq + scalar*sample_rate/2.0,
- scalar*x_per_div,
- )
- else:
- self.plotter.set_x_grid(
- scalar*baseband_freq - scalar*sample_rate/2.0,
- scalar*baseband_freq + scalar*sample_rate/2.0,
- scalar*x_per_div,
- )
+ self.plotter = plotter.grid_plotter(self)
+ self.plotter.SetSize(wx.Size(*size))
+ self.plotter.set_title(title)
+ self.plotter.set_y_units('Amplitude (dB)')
#setup the box with plot and controls
self.control_panel = control_panel(self)
main_box = wx.BoxSizer(wx.HORIZONTAL)
@@ -184,6 +167,11 @@
self.update()
def plot(self, samples):
+ """!
+ Plot the samples onto the grid as channel 1.
+ If peak hold is enabled, plot peak vals as channel 2.
+ @param samples the fft array
+ """
#peak hold calculation
if self.peak_hold and len(self.peak_vals) != len(samples):
self.peak_vals = samples
if self.peak_hold: self.peak_vals = numpy.maximum(samples,
self.peak_vals)
@@ -206,9 +194,35 @@
def update(self):
#update average
- self.set_average(self.average)
+ self.fft_set_average(self.average)
#update peak hold
- if not self.peak_hold: self.peak_vals = []
+ if not self.peak_hold: self.peak_vals = []
+ #determine best fitting x_per_div
+ if self.real: x_width = self.sample_rate/2.0
+ else: x_width = self.sample_rate
+ exp = math.floor(math.log10(x_width/self.x_divs))
+ x_per_divs = numpy.array((1, 2, 5, 10))*10**exp
+ x_per_div = x_per_divs[numpy.argmin(numpy.abs(x_per_divs -
x_width/self.x_divs))]
+ #calculate units and scalar
+ if exp >= 9: x_units, scalar = 'GHz', 1e-9
+ elif exp >= 6: x_units, scalar = 'MHz', 1e-6
+ elif exp >= 3: x_units, scalar = 'KHz', 1e-3
+ else: x_units, scalar = 'Hz', 1e-0
+ #update the x grid
+ if self.real:
+ self.plotter.set_x_grid(
+ scalar*self.baseband_freq,
+ scalar*self.baseband_freq +
scalar*self.sample_rate/2.0,
+ scalar*x_per_div,
+ )
+ else:
+ self.plotter.set_x_grid(
+ scalar*self.baseband_freq -
scalar*self.sample_rate/2.0,
+ scalar*self.baseband_freq +
scalar*self.sample_rate/2.0,
+ scalar*x_per_div,
+ )
+ #update x units
+ self.plotter.set_x_units('Frequency (%s)'%x_units)
#update y grid
self.plotter.set_y_grid(self.ref_level-self.y_per_div*self.y_divs,
self.ref_level, self.y_per_div)
#update control panel if non-gui changes occured
@@ -216,25 +230,26 @@
#update the plotter
self.plotter.update()
- def on_average(self, event):
- self.average = event.IsChecked()
+ ##################################################
+ # Set parameters on-the-fly
+ ##################################################
+ def set_baseband_freq(self, baseband_freq):
+ self.baseband_freq = baseband_freq
+ self.update()
+ def set_average(self, average):
+ self.average = average
self.update()
-
- def on_peak_hold(self, event):
- self.peak_hold = event.IsChecked()
+ def set_peak_hold(self, peak_hold):
+ self.peak_hold = peak_hold
self.update()
-
- def on_incr_ref_level(self, event):
- self.ref_level = self.ref_level + self.y_per_div
- self.update()
-
- def on_decr_ref_level(self, event):
- self.ref_level = self.ref_level - self.y_per_div
- self.update()
-
def set_y_per_div(self, y_per_div):
self.y_per_div = y_per_div
self.update()
+ def set_ref_level(self, ref_level):
+ self.ref_level = ref_level
+ self.update()
+ def incr_ref_level(self): self.set_ref_level(self.ref_level +
self.y_per_div)
+ def decr_ref_level(self): self.set_ref_level(self.ref_level -
self.y_per_div)
##################################################
# FFT blocks chain: input -> message sink
@@ -295,35 +310,6 @@
else: self._avg.set_taps(1.0)
##################################################
-# Input watcher for msg queue
-##################################################
-class input_watcher(threading.Thread):
- def __init__ (self, msgq, handle_samples):
- threading.Thread.__init__(self)
- self.setDaemon(1)
- self.msgq = msgq
- self.handle_samples = handle_samples
- 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 frame in the message.
- # If so, we take only the last one
- if nitems > 1:
- start = itemsize * (nitems - 1)
- s = s[start:start+itemsize]
-
- samples = numpy.fromstring(s, numpy.float32)
- self.handle_samples(samples)
-
-##################################################
# FFT sink base block for real and complex types
##################################################
class _fft_sink_base(gr.hier_block2):
@@ -347,6 +333,7 @@
average=False,
avg_alpha=None,
title='',
+ size=DEFAULT_WIN_SIZE,
peak_hold=False,
):
self.real = self.item_size == gr.sizeof_float
@@ -374,6 +361,7 @@
#create window
self.win = fft_window(
parent=parent,
+ size=size,
title=title,
real = self.real,
baseband_freq=baseband_freq,
@@ -385,18 +373,37 @@
peak_hold=peak_hold,
set_average=fft.set_average,
)
+ #register callbacks from window for external use
+ self.set_baseband_freq = self.win.set_baseband_freq
+ self.set_average = self.win.set_average
+ self.set_peak_hold = self.win.set_peak_hold
+ self.set_y_per_div = self.win.set_y_per_div
+ self.set_ref_level = self.win.set_ref_level
#setup the input watcher
- input_watcher(fft.msgq, self._handle_samples)
+ common.input_watcher(fft.msgq, self._handle_msg)
- def _handle_samples(self, samples):
+ def _handle_msg(self, msg):
"""!
+ Handle the message from the fft sink message queue.
If complex, reorder the fft samples so the negative bins come
first.
If real, keep take only the positive bins.
- @param samples an array of fft samples
+ @param msg the fft array as a character array
"""
- num_samples = len(samples)
- if self.real: samples = samples[:num_samples/2]
- else: samples = numpy.concatenate((samples[num_samples/2+1:],
samples[:num_samples/2]))
+ itemsize = int(msg.arg1())
+ nitems = int(msg.arg2())
+ s = msg.to_string()
+ # There may be more than one frame in the message.
+ # If so, we take only the last one
+ if nitems > 1:
+ start = itemsize * (nitems - 1)
+ s = s[start:start+itemsize]
+ #convert to floating point numbers
+ samples = numpy.fromstring(s, numpy.float32)
+ num_samps = len(samples)
+ #reorder fft
+ if self.real: samples = samples[:num_samps/2]
+ else: samples = numpy.concatenate((samples[num_samps/2+1:],
samples[:num_samps/2]))
+ #plot
self.win.plot(samples)
class fft_sink_f(_fft_sink_base): item_size = gr.sizeof_float
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py
2008-06-27 18:53:10 UTC (rev 8740)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py
2008-06-27 21:40:03 UTC (rev 8741)
@@ -43,6 +43,8 @@
UNITS_TEXT_COLOR_SPEC = (0, 0, 0) #black
UNITS_TEXT_FONT_SIZE = 9
+PADDING = 35, 10, 40, 60 #top, right, bottom, left
+
class _plotter_base(wx.glcanvas.GLCanvas):
"""!
Plotter base class for all plot types.
@@ -97,26 +99,47 @@
class grid_plotter(_plotter_base):
- def __init__(self, parent, title, x_units, y_units, padding_top,
padding_right, padding_bottom, padding_left):
+ def __init__(self, parent):
"""!
Create a new grid plotter.
"""
self.grid_compiled_list_id = wx.NewId()
self.channels = dict()
- #store title and unit strings
- self.title = title
- self.x_units = x_units
- self.y_units = y_units
+ #store title and unit strings
+ self.set_title('Title')
+ self.set_x_units('X Units (xx)')
+ self.set_y_units('Y Units (yy)')
#store padding
- self.padding_top = padding_top
- self.padding_right = padding_right
- self.padding_bottom = padding_bottom
- self.padding_left = padding_left
+ self.padding_top, self.padding_right, self.padding_bottom,
self.padding_left = PADDING
#init the grid to some value
self.set_x_grid(-1, 1, 1)
self.set_y_grid(-1, 1, 1)
_plotter_base.__init__(self, parent)
+
+ def set_title(self, title):
+ """!
+ Set the title.
+ @param title the title string
+ """
+ self.title = title
+ self._changed = True
+ def set_x_units(self, x_units):
+ """!
+ Set the x_units.
+ @param x_units the x_units string
+ """
+ self.x_units = x_units
+ self._changed = True
+
+ def set_y_units(self, y_units):
+ """!
+ Set the y_units.
+ @param y_units the y_units string
+ """
+ self.y_units = y_units
+ self._changed = True
+
def set_x_grid(self, x_min, x_max, x_step):
"""!
Set the x grid parameters.
@@ -339,12 +362,12 @@
frame = wx.Frame(None, -1, 'Demo', wx.DefaultPosition)
vbox = wx.BoxSizer(wx.VERTICAL)
- plotter = grid_plotter(frame, 'Demo Grid1', 'Frequency(Hz)',
'Amplitude(dB)', 35, 10, 40, 60)
+ plotter = grid_plotter(frame)
plotter.set_x_grid(-1, 1, .2)
plotter.set_y_grid(-1, 1, .4)
vbox.Add(plotter, 1, wx.EXPAND)
- plotter = grid_plotter(frame, 'Demo Grid2', 'Frequency(Hz)',
'Amplitude(dB)', 35, 10, 40, 60)
+ plotter = grid_plotter(frame)
plotter.set_x_grid(-1, 1, .2)
plotter.set_y_grid(-1, 1, .4)
vbox.Add(plotter, 1, wx.EXPAND)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r8741 - in gnuradio/branches/developers/jblum/gr-wxglgui/src: . python,
jblum <=