[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r8774 - gnuradio/branches/developers/jblum/gr-wxglgui/
From: |
jblum |
Subject: |
[Commit-gnuradio] r8774 - gnuradio/branches/developers/jblum/gr-wxglgui/src/python |
Date: |
Wed, 2 Jul 2008 23:41:15 -0600 (MDT) |
Author: jblum
Date: 2008-07-02 23:41:15 -0600 (Wed, 02 Jul 2008)
New Revision: 8774
Modified:
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py
gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
Log:
incrdecr buttons, plotter something
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
2008-07-03 05:12:53 UTC (rev 8773)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/common.py
2008-07-03 05:41:15 UTC (rev 8774)
@@ -1,23 +1,23 @@
#
# 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.
-#
+#
from gnuradio import gr, window
import threading
@@ -27,12 +27,12 @@
##################################################
# Stream decimator chain
-##################################################
+##################################################
class stream_decimator(gr.hier_block2):
"""!
Convert the stream to a vector, decimate the vector to achieve the
vector rate.
"""
-
+
def __init__(self, item_size, sample_rate, vec_rate, vec_len):
"""!
Create the block chain.
@@ -45,19 +45,19 @@
self.vec_len = vec_len
#init
gr.hier_block2.__init__(
- self,
+ self,
"stream_decimator_block",
gr.io_signature(1, 1, item_size),
gr.io_signature(1, 1, item_size*vec_len),
)
#create blocks
- s2v = gr.stream_to_vector(item_size, vec_len)
+ s2v = gr.stream_to_vector(item_size, vec_len)
self.one_in_n = gr.keep_one_in_n(item_size * vec_len, 1)
#connect
self.connect(self, s2v, self.one_in_n, self)
#initial update
self.set_sample_rate(sample_rate)
-
+
def set_sample_rate(self, sample_rate):
"""!
Set the new sampling rate and update the decimator.
@@ -68,14 +68,14 @@
##################################################
# FFT block chain
-##################################################
+##################################################
class _fft_chain_base(gr.hier_block2):
"""!
Create an fft block chain, with real/complex input.
The fft stream is written to a message sink.
This block provides a callback to set the average on/off.
"""
-
+
def __init__(self, sample_rate, fft_size, frame_rate, ref_scale,
avg_alpha, average):
"""!
Create an fft block.
@@ -84,7 +84,7 @@
"""
#init
gr.hier_block2.__init__(
- self,
+ self,
"fft_block",
gr.io_signature(1, 1, self.item_size),
gr.io_signature(1, 1, gr.sizeof_float*fft_size),
@@ -99,12 +99,12 @@
#create fft
fft_window = window.blackmanharris(fft_size)
fft = self.fft_block[0](fft_size, True, fft_window)
- power = sum(map(lambda x: x*x, fft_window))
+ power = sum(map(lambda x: x*x, fft_window))
#filter fft, convert to dB
c2mag = gr.complex_to_mag(fft_size)
self.avg = gr.single_pole_iir_filter_ff(1.0, fft_size)
log = gr.nlog10_ff(
- 20,
+ 20,
fft_size,
-10*math.log10(fft_size) # Adjust for number of bins
-10*math.log10(power/fft_size) # Adjust for windowing
loss
@@ -116,7 +116,7 @@
self.set_sample_rate = self.sd.set_sample_rate
#initial update
self.set_average(average)
- self.set_avg_alpha(avg_alpha)
+ self.set_avg_alpha(avg_alpha)
def set_sample_rate(self, sample_rate):
"""!
@@ -134,7 +134,7 @@
self.average = average
if self.average: self.avg.set_taps(self.avg_alpha)
else: self.avg.set_taps(1.0)
-
+
def set_avg_alpha(self, avg_alpha):
"""!
Set the average alpha and set the taps if average was on.
@@ -142,33 +142,24 @@
"""
self.avg_alpha = avg_alpha
self.set_average(self.average)
-
+
class fft_chain_f(_fft_chain_base):
- item_size = gr.sizeof_float
+ item_size = gr.sizeof_float
fft_block = (gr.fft_vfc, )
class fft_chain_c(_fft_chain_base):
- item_size = gr.sizeof_gr_complex
+ item_size = gr.sizeof_gr_complex
fft_block = (gr.fft_vcc, )
-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)
- self.SetFont(font)
-
+##################################################
+# Input Watcher Thread
+##################################################
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)
@@ -177,9 +168,54 @@
self.keep_running = True
self.start()
- def run(self):
+ def run(self):
while self.keep_running:
self.handle_msg(self.msgq.delete_head())
+##################################################
+# WX Shared Classes
+##################################################
+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, parent, label):
+ wx.StaticText.__init__(self, parent, -1, label)
+ font = self.GetFont()
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
+ self.SetFont(font)
+
+class IncrDecrButtons(wx.BoxSizer):
+ """!
+ A horizontal box sizer with a increment and a decrement button.
+ """
+
+ def __init__(self, parent, on_incr, on_decr):
+ """!
+ @param parent the parent window
+ @param on_incr the event handler for increment
+ @param on_decr the event handler for decrement
+ """
+ wx.BoxSizer.__init__(self, wx.HORIZONTAL)
+ self._incr_button = wx.Button(parent, -1, '+',
style=wx.BU_EXACTFIT)
+ self._incr_button.Bind(wx.EVT_BUTTON, on_incr)
+ self.Add(self._incr_button, 0, wx.ALIGN_CENTER_VERTICAL)
+ self._decr_button = wx.Button(parent, -1, ' - ',
style=wx.BU_EXACTFIT)
+ self._decr_button.Bind(wx.EVT_BUTTON, on_decr)
+ self.Add(self._decr_button, 0, wx.ALIGN_CENTER_VERTICAL)
+
+ def Enable(self):
+ self._incr_button.Enable()
+ self._decr_button.Enable()
+
+ def Disable(self):
+ self._incr_button.Disable()
+ self._decr_button.Disable()
+
+##################################################
+# Shared Functions
+##################################################
def get_exp(num):
"""!
Get the exponent of the number in base 10.
@@ -196,7 +232,7 @@
@return the closest number
"""
exp = get_exp(num)
- nums = numpy.array((1, 2, 5, 10))*(10**exp)
+ nums = numpy.array((1, 2, 5, 10))*(10**exp)
return nums[numpy.argmin(numpy.abs(nums - num))]
def get_clean_incr(num):
@@ -207,7 +243,7 @@
"""
exp = get_exp(num)
num = get_clean_num(num)
- base = int(num/10**exp)
+ base = int(num/10**exp)
return {
1: 2,
2: 5,
@@ -221,7 +257,7 @@
@return the next lower number
"""
exp = get_exp(num)
- num = get_clean_num(num)
+ num = get_clean_num(num)
base = int(num/10**exp)
return {
1: .5,
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
2008-07-03 05:12:53 UTC (rev 8773)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/fftsink.py
2008-07-03 05:41:15 UTC (rev 8774)
@@ -1,23 +1,23 @@
#
# 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.
-#
+#
##################################################
# Imports
@@ -34,7 +34,7 @@
DEFAULT_FRAME_RATE = 30
DEFAULT_WIN_SIZE = (640, 240)
DIV_LEVELS = (1, 2, 5, 10, 20)
-FFT_PLOT_COLOR_SPEC = (0, 0, 1)
+FFT_PLOT_COLOR_SPEC = (0, 0, 1)
PEAK_VALS_COLOR_SPEC = (0, 1, 0)
##################################################
@@ -44,16 +44,16 @@
"""!
A control panel with wx widgits to control the plotter and fft block
chain.
"""
-
+
def __init__(self, parent):
"""!
Create a new control panel.
@param parent the wx parent window
"""
self.parent = parent
- wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
+ wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
control_box = wx.BoxSizer(wx.VERTICAL)
-
+
#checkboxes for average and peak hold
control_box.AddStretchSpacer()
control_box.Add(common.LabelText(self, 'Options'), 0,
wx.ALIGN_CENTER)
@@ -61,9 +61,9 @@
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,
self._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(common.LabelText(self, 'Set dB/div'), 0,
wx.ALIGN_CENTER)
@@ -75,25 +75,19 @@
self.radio_buttons.append(radio_button)
radio_box.Add(radio_button, 0, wx.ALIGN_LEFT)
control_box.Add(radio_box, 0, wx.EXPAND)
-
+
#ref lvl buttons
control_box.AddStretchSpacer()
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,
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,
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)
+ self._ref_lvl_buttons = common.IncrDecrButtons(self,
self._on_incr_ref_level, self._on_decr_ref_level)
+ control_box.Add(self._ref_lvl_buttons, 0, wx.ALIGN_CENTER)
control_box.AddStretchSpacer()
#set sizer
self.SetSizerAndFit(control_box)
#update
self.update()
-
+
def update(self):
"""!
Read the state of the fft plot settings and update the control
panel.
@@ -101,21 +95,21 @@
#update checkboxes
self.average_check_box.SetValue(self.parent.average)
self.peak_hold_check_box.SetValue(self.parent.peak_hold)
- #update radio buttons
+ #update radio buttons
try:
index = list(DIV_LEVELS).index(self.parent.y_per_div)
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]
+ 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_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()
@@ -124,9 +118,9 @@
##################################################
class fft_window(wx.Panel):
def __init__(
- self,
+ self,
parent,
- size,
+ size,
title,
real,
baseband_freq,
@@ -138,14 +132,14 @@
peak_hold,
set_average,
set_sample_rate,
- ):
+ ):
#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.x_divs = 8.0 #approximate
self.y_per_div = y_per_div
self.y_divs = y_divs
self.ref_level = ref_level
@@ -154,9 +148,9 @@
self.fft_set_average = set_average
self.fft_set_sample_rate = set_sample_rate
self.peak_vals = []
- #init panel and plot
- wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER)
- self.plotter = plotter.grid_plotter(self)
+ #init panel and plot
+ wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER)
+ self.plotter = plotter.grid_plotter(self)
self.plotter.SetSize(wx.Size(*size))
self.plotter.set_title(title)
self.plotter.set_y_units('Amplitude (dB)')
@@ -168,7 +162,7 @@
self.SetSizerAndFit(main_box)
#update
self.update()
-
+
def plot(self, samples):
"""!
Plot the samples onto the grid as channel 1.
@@ -176,61 +170,61 @@
@param samples the fft array
"""
#peak hold calculation
- if self.peak_hold:
+ if self.peak_hold:
if len(self.peak_vals) != len(samples): self.peak_vals
= samples
self.peak_vals = numpy.maximum(samples, self.peak_vals)
#plot the fft
self.plotter.set_waveform(
- channel=1,
+ channel=1,
samples=samples,
color_spec=FFT_PLOT_COLOR_SPEC,
)
#plot the peak hold
self.plotter.set_waveform(
- channel=2,
+ channel=2,
samples=self.peak_vals,
color_spec=PEAK_VALS_COLOR_SPEC,
- )
+ )
#update the plotter
self.plotter.update()
-
+
def update(self):
#update fft block
self.fft_set_average(self.average)
self.fft_set_sample_rate(self.sample_rate)
#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
- x_per_div = common.get_clean_num(x_width/self.x_divs)
- exp = common.get_exp(x_per_div)
+ x_per_div = common.get_clean_num(x_width/self.x_divs)
+ exp = common.get_exp(x_per_div)
#calculate units and scalar
if exp > 7: x_units, scalar = 'GHz', 1e-9
elif exp > 4: x_units, scalar = 'MHz', 1e-6
elif exp > 1: x_units, scalar = 'KHz', 1e-3
else: x_units, scalar = 'Hz', 1e-0
#update the x grid
- if self.real:
+ if self.real:
self.plotter.set_x_grid(
- scalar*self.baseband_freq,
- scalar*self.baseband_freq +
scalar*self.sample_rate/2.0,
+ 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*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)
+ 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 and plotter
self.control_panel.update()
self.plotter.update()
-
+
##################################################
# Set parameters on-the-fly
##################################################
@@ -239,10 +233,10 @@
self.update()
def set_baseband_freq(self, baseband_freq):
self.baseband_freq = baseband_freq
- self.update()
+ self.update()
def set_average(self, average):
self.average = average
- self.update()
+ self.update()
def set_peak_hold(self, peak_hold):
self.peak_hold = peak_hold
self.update()
@@ -252,39 +246,39 @@
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 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 sink base block for real and complex types
-##################################################
+##################################################
class _fft_sink_base(gr.hier_block2):
"""!
An fft block with real/complex inputs and a gui window.
"""
-
+
def __init__(
- self,
+ self,
parent,
- baseband_freq=0,
- ref_scale=2.0,
+ baseband_freq=0,
+ ref_scale=2.0,
y_per_div=10,
- y_divs=8,
+ y_divs=8,
ref_level=50,
- sample_rate=1,
+ sample_rate=1,
fft_size=512,
frame_rate=DEFAULT_FRAME_RATE,
- average=False,
- avg_alpha=None,
- title='',
+ average=False,
+ avg_alpha=None,
+ title='',
size=DEFAULT_WIN_SIZE,
peak_hold=False,
- ):
+ ):
#ensure avg alpha
if avg_alpha is None: avg_alpha = 2.0/frame_rate
#init
gr.hier_block2.__init__(
- self,
+ self,
"fft_sink",
gr.io_signature(1, 1, self.item_size),
gr.io_signature(0, 0, 0),
@@ -292,10 +286,10 @@
#blocks
copy = gr.kludge_copy(self.item_size)
fft = self.fft_chain(
- sample_rate=sample_rate,
- fft_size=fft_size,
- frame_rate=frame_rate,
- ref_scale=ref_scale,
+ sample_rate=sample_rate,
+ fft_size=fft_size,
+ frame_rate=frame_rate,
+ ref_scale=ref_scale,
avg_alpha=avg_alpha,
average=average,
)
@@ -305,19 +299,19 @@
self.connect(self, copy, fft, sink)
#create window
self.win = fft_window(
- parent=parent,
+ parent=parent,
size=size,
title=title,
real = self.real,
baseband_freq=baseband_freq,
- sample_rate=sample_rate,
+ sample_rate=sample_rate,
y_per_div=y_per_div,
y_divs=y_divs,
- ref_level=ref_level,
+ ref_level=ref_level,
average=average,
peak_hold=peak_hold,
set_average=fft.set_average,
- set_sample_rate=fft.set_sample_rate,
+ set_sample_rate=fft.set_sample_rate,
)
#register callbacks from window for external use
self.set_baseband_freq = self.win.set_baseband_freq
@@ -329,7 +323,7 @@
self.set_sample_rate = self.win.set_sample_rate
#setup the input watcher
common.input_watcher(msgq, self._handle_msg)
-
+
def _handle_msg(self, msg):
"""!
Handle the message from the fft sink message queue.
@@ -344,10 +338,10 @@
# If so, we take only the last one
if nitems > 1:
start = itemsize * (nitems - 1)
- s = s[start:start+itemsize]
+ s = s[start:start+itemsize]
#convert to floating point numbers
- samples = numpy.fromstring(s, numpy.float32)
- num_samps = len(samples)
+ 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]))
@@ -355,10 +349,10 @@
self.win.plot(samples)
class fft_sink_f(_fft_sink_base):
- fft_chain = common.fft_chain_f
+ fft_chain = common.fft_chain_f
item_size = gr.sizeof_float
real = True
-class fft_sink_c(_fft_sink_base):
+class fft_sink_c(_fft_sink_base):
fft_chain = common.fft_chain_c
item_size = gr.sizeof_gr_complex
real = False
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py
2008-07-03 05:12:53 UTC (rev 8773)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/plotter.py
2008-07-03 05:41:15 UTC (rev 8774)
@@ -1,23 +1,23 @@
#
# 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 wx
import wx.glcanvas
@@ -43,7 +43,7 @@
"""!
Plotter base class for all plot types.
"""
-
+
def __init__(self, parent):
"""!
Create a new plotter base.
@@ -55,7 +55,7 @@
self._resized_flag = True
wx.EVT_PAINT(self, self.OnPaint)
wx.EVT_SIZE(self, self.OnSize)
-
+
def OnSize(self, event):
"""!
Flag the resize event.
@@ -75,7 +75,7 @@
glEnableClientState(GL_VERTEX_ARRAY)
self._gl_init_flag = True
#check for a change in window size
- if self._resized_flag:
+ if self._resized_flag:
self.width, self.height = self.GetSize()
glViewport(0, 0, self.width, self.height)
glMatrixMode(GL_PROJECTION)
@@ -86,13 +86,13 @@
self._resized_flag = False
self._changed = True
self.draw()
-
+
def update(self): wx.PostEvent(self, wx.PaintEvent())
-
+
def clear(self): glClear(GL_COLOR_BUFFER_BIT)
class grid_plotter(_plotter_base):
-
+
def __init__(self, parent):
"""!
Create a new grid plotter.
@@ -111,7 +111,7 @@
self.set_x_grid(-1, 1, 1)
self.set_y_grid(-1, 1, 1)
_plotter_base.__init__(self, parent)
-
+
def set_legend(self, legend):
"""!
Set the legend on/off.
@@ -121,7 +121,7 @@
self.legend = legend
self._changed = True
self.semaphore.release()
-
+
def set_title(self, title):
"""!
Set the title.
@@ -165,7 +165,7 @@
self.x_step = float(x_step)
self._changed = True
self.semaphore.release()
-
+
def set_y_grid(self, y_min, y_max, y_step):
"""!
Set the y grid parameters.
@@ -179,7 +179,7 @@
self.y_step = float(y_step)
self._changed = True
self.semaphore.release()
-
+
def draw(self):
"""!
Draw the grid and waveforms.
@@ -198,7 +198,7 @@
glFlush()
self.SwapBuffers()
self.semaphore.release()
-
+
def _draw_waveforms(self):
"""!
Draw the waveforms for each channel.
@@ -212,31 +212,29 @@
num_samps = len(samples)
#use opengl to scale the waveform
glPushMatrix()
- glTranslated(self.padding_left, self.padding_top, 0)
- glScaled(
-
(self.width-self.padding_left-self.padding_right),
-
(self.height-self.padding_top-self.padding_bottom),
+ glTranslatef(self.padding_left, self.padding_top, 0)
+ glScalef(
+
(self.width-self.padding_left-self.padding_right),
+
(self.height-self.padding_top-self.padding_bottom),
1,
)
- glTranslated(0, 1, 0)
+ glTranslatef(0, 1, 0)
if isinstance(samples, tuple):
- x_arr, y_arr = samples
- glScaled(1.0/(self.x_max-self.x_min),
-1.0/(self.y_max-self.y_min), 1)
- glTranslated(-self.x_min, -self.y_min, 0)
+ x_scale, x_trans = 1.0/(self.x_max-self.x_min),
-self.x_min
+ points = zip(*samples)
else:
- x_arr = numpy.arange(0, num_samps)
- y_arr = samples
- glScaled(1.0/(num_samps-1),
-1.0/(self.y_max-self.y_min), 1)
- glTranslated(0, -self.y_min, 0)
+ x_scale, x_trans = 1.0/(num_samps-1), 0
+ points = zip(numpy.arange(0, num_samps),
samples)
+ glScalef(x_scale, -1.0/(self.y_max-self.y_min), 1)
+ glTranslatef(x_trans, -self.y_min, 0)
#draw the points/lines
glColor3f(*color_spec)
- points = zip(x_arr, y_arr)
#if marker == '+': #TODO make a texture?
# points = numpy.concatenate([((x, y+4), (x,
y-4), (x+4, y), (x-4, y)) for x, y in points])
glVertexPointer(2, GL_FLOAT, 0, points)
glDrawArrays({None: GL_LINE_STRIP, '.': GL_POINTS, '+':
GL_LINES}[marker], 0, len(points))
glPopMatrix()
-
+
def _draw_grid(self):
"""!
Draw the border, grid, title, and units.
@@ -250,7 +248,7 @@
self._draw_rect(self.width-self.padding_right, 0,
self.padding_right, self.height)
self._draw_rect(0, self.height-self.padding_bottom, self.width,
self.padding_bottom)
self._draw_rect(0, 0, self.padding_left, self.height)
-
+
##################################################
# Draw Inner Border
##################################################
@@ -261,62 +259,62 @@
glVertex3f(self.width - self.padding_right, self.height -
self.padding_bottom, 0)
glVertex3f(self.padding_left, self.height -
self.padding_bottom, 0)
glEnd()
-
+
##################################################
# Draw Grid X
##################################################
for tick in self._get_ticks(self.x_min, self.x_max,
self.x_step):
scaled_tick =
(self.width-self.padding_left-self.padding_right)*(tick-self.x_min)/(self.x_max-self.x_min)
+ self.padding_left
-
+
glColor3f(*GRID_LINE_COLOR_SPEC)
self._draw_line(
- (scaled_tick, self.padding_top, 0),
- (scaled_tick, self.height-self.padding_bottom,
0),
+ (scaled_tick, self.padding_top, 0),
+ (scaled_tick, self.height-self.padding_bottom,
0),
)
self._draw_tick_label(tick, (scaled_tick,
self.height-.75*self.padding_bottom))
-
+
##################################################
# Draw Grid Y
##################################################
for tick in self._get_ticks(self.y_min, self.y_max,
self.y_step):
scaled_tick =
(self.height-self.padding_top-self.padding_bottom)*(1 -
(tick-self.y_min)/(self.y_max-self.y_min)) + self.padding_top
-
+
glColor3f(*GRID_LINE_COLOR_SPEC)
self._draw_line(
- (self.padding_left, scaled_tick, 0),
- (self.width-self.padding_right, scaled_tick,
0),
+ (self.padding_left, scaled_tick, 0),
+ (self.width-self.padding_right, scaled_tick, 0),
)
self._draw_tick_label(tick, (.75*self.padding_left,
scaled_tick))
-
+
##################################################
# Draw Title
- ##################################################
+ ##################################################
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
font.SetWeight(wx.FONTWEIGHT_BOLD)
#draw x units
txt = gltext.Text(self.title, font=font,
font_size=TITLE_TEXT_FONT_SIZE, centered=True)
txt.draw_text(wx.Point(self.width/2.0, .5*self.padding_top))
-
+
##################################################
# Draw Units
##################################################
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
- font.SetWeight(wx.FONTWEIGHT_BOLD)
+ font.SetWeight(wx.FONTWEIGHT_BOLD)
#draw x units
txt = gltext.Text(self.x_units, font=font,
font_size=UNITS_TEXT_FONT_SIZE, centered=True)
txt.draw_text(wx.Point(
-
(self.width-self.padding_left-self.padding_right)/2.0 + self.padding_left,
+
(self.width-self.padding_left-self.padding_right)/2.0 + self.padding_left,
self.height-.25*self.padding_bottom,
)
)
#draw y units
txt = gltext.Text(self.y_units, font=font,
font_size=UNITS_TEXT_FONT_SIZE, centered=True)
txt.draw_text(wx.Point(
- .25*self.padding_left,
+ .25*self.padding_left,
(self.height-self.padding_top-self.padding_bottom)/2.0 + self.padding_top,
), rotation=90,
)
-
+
##################################################
# Draw Legend
##################################################
@@ -327,15 +325,15 @@
#draw colored rectangle
glColor3f(*color_spec)
self._draw_rect(
- self.width - self.padding_right - x_off
- LEGEND_BOX_WIDTH/2,
-
(self.padding_top-LEGEND_BOX_HEIGHT)/2.0,
- LEGEND_BOX_WIDTH,
+ self.width - self.padding_right - x_off
- LEGEND_BOX_WIDTH/2,
+
(self.padding_top-LEGEND_BOX_HEIGHT)/2.0,
+ LEGEND_BOX_WIDTH,
LEGEND_BOX_HEIGHT,
)
#draw label text
txt = gltext.Text('Ch%s'%channel,
font_size=LEGEND_TEXT_FONT_SIZE, centered=True)
txt.draw_text(wx.Point(self.width -
self.padding_right - x_off, self.padding_top/2.0))
-
+
def _draw_tick_label(self, tick, coor):
"""!
Format the tick value and draw it at the coordinate.
@@ -351,7 +349,7 @@
#draw
txt = gltext.Text(tick_str, font_size=TICK_TEXT_FONT_SIZE,
centered=True)
txt.draw_text(wx.Point(*coor))
-
+
def _get_ticks(self, min, max, step):
"""!
Determine the positions for the ticks.
@@ -372,7 +370,7 @@
start = int(math.ceil(min/step))
stop = int(math.floor(max/step))
return [i*step for i in range(start, stop+1)]
-
+
def _draw_line(self, coor1, coor2):
"""!
Draw a line from coor1 to coor2.
@@ -383,7 +381,7 @@
glVertex3f(*coor1)
glVertex3f(*coor2)
glEnd()
-
+
def _draw_rect(self, x, y, width, height):
"""!
Draw a rectangle on the x, y plane.
@@ -399,7 +397,7 @@
glVertex3f(x+width, y+height, 0)
glVertex3f(x, y+height, 0)
glEnd()
-
+
def set_waveform(self, channel, samples, color_spec, marker=None):
"""!
Set the waveform for a given channel.
@@ -414,17 +412,17 @@
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, 'Demo', wx.DefaultPosition)
vbox = wx.BoxSizer(wx.VERTICAL)
-
+
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)
plotter.set_x_grid(-1, 1, .2)
plotter.set_y_grid(-1, 1, .4)
vbox.Add(plotter, 1, wx.EXPAND)
-
+
frame.SetSizerAndFit(vbox)
frame.SetSize(wx.Size(800, 600))
frame.Show()
Modified: gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
===================================================================
--- gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
2008-07-03 05:12:53 UTC (rev 8773)
+++ gnuradio/branches/developers/jblum/gr-wxglgui/src/python/scopesink.py
2008-07-03 05:41:15 UTC (rev 8774)
@@ -1,23 +1,23 @@
#
# 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.
-#
+#
##################################################
# Imports
@@ -36,9 +36,9 @@
DEFAULT_WIN_SIZE = (640, 240)
DEFAULT_V_SCALE = 1000
TRIGGER_MODES = (
- ('Auto', gr.gr_TRIG_AUTO),
- ('Neg', gr.gr_TRIG_NEG_SLOPE),
- ('Pos', gr.gr_TRIG_POS_SLOPE),
+ ('Auto', gr.gr_TRIG_AUTO),
+ ('Neg', gr.gr_TRIG_NEG_SLOPE),
+ ('Pos', gr.gr_TRIG_POS_SLOPE),
)
TRIGGER_LEVELS = (
('Auto', None),
@@ -65,80 +65,73 @@
"""!
A control panel with wx widgits to control the plotter and scope block.
"""
- def __init__(self, parent):
+ def __init__(self, parent):
"""!
Create a new control panel.
@param parent the wx parent window
"""
self.parent = parent
- wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
+ wx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)
control_box = wx.BoxSizer(wx.VERTICAL)
-
+
#begin control box
control_box.AddSpacer(2)
-
- #trigger menu
+
+ #trigger options
control_box.AddSpacer(2)
- control_box.Add(common.LabelText(self, 'Trigger Menu'), 0,
wx.ALIGN_CENTER)
+ control_box.Add(common.LabelText(self, 'Trigger Options'), 0,
wx.ALIGN_CENTER)
control_box.AddSpacer(2)
- #trigger mode
+ #trigger mode
hbox = wx.BoxSizer(wx.HORIZONTAL)
- control_box.Add(hbox, 1, wx.ALIGN_LEFT)
- hbox.Add(wx.StaticText(self, -1, ' Channel '), 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
- self.trigger_channel_chooser = wx.Choice(self, -1,
choices=map(lambda ch: "Ch%d"%ch, range(1, parent.num_inputs+1)))
+ control_box.Add(hbox, 1, wx.EXPAND)
+ hbox.Add(wx.StaticText(self, -1, ' Channel '), 1,
wx.ALIGN_CENTER_VERTICAL)
+ self.trigger_channel_chooser = wx.Choice(self, -1,
choices=["Ch%d"%ch for ch in range(1, parent.num_inputs+1)])
self.trigger_channel_chooser.Bind(wx.EVT_CHOICE,
self._on_trigger_channel)
- hbox.Add(self.trigger_channel_chooser, 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
- #trigger mode
+ hbox.Add(self.trigger_channel_chooser, 0,
wx.ALIGN_CENTER_VERTICAL)
+ #trigger mode
hbox = wx.BoxSizer(wx.HORIZONTAL)
- control_box.Add(hbox, 1, wx.ALIGN_LEFT)
- hbox.Add(wx.StaticText(self, -1, ' Mode '), 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
+ control_box.Add(hbox, 1, wx.EXPAND)
+ hbox.Add(wx.StaticText(self, -1, ' Mode '), 1,
wx.ALIGN_CENTER_VERTICAL)
self.trigger_mode_chooser = wx.Choice(self, -1, choices=[tm[0]
for tm in TRIGGER_MODES])
self.trigger_mode_chooser.Bind(wx.EVT_CHOICE,
self._on_trigger_mode)
- hbox.Add(self.trigger_mode_chooser, 0, wx.ALIGN_CENTER_VERTICAL
| wx.ALIGN_LEFT)
+ hbox.Add(self.trigger_mode_chooser, 0, wx.ALIGN_CENTER_VERTICAL)
#trigger level
hbox = wx.BoxSizer(wx.HORIZONTAL)
- control_box.Add(hbox, 1, wx.ALIGN_LEFT)
- hbox.Add(wx.StaticText(self, -1, ' Level '), 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
+ control_box.Add(hbox, 1, wx.EXPAND)
+ hbox.Add(wx.StaticText(self, -1, ' Level '), 1,
wx.ALIGN_CENTER_VERTICAL)
self.trigger_level_chooser = wx.Choice(self, -1, choices=[tl[0]
for tl in TRIGGER_LEVELS])
self.trigger_level_chooser.Bind(wx.EVT_CHOICE,
self._on_trigger_level)
- hbox.Add(self.trigger_level_chooser, 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
-
- #setup axes menu
+ hbox.Add(self.trigger_level_chooser, 0,
wx.ALIGN_CENTER_VERTICAL)
+
+ #axes options
+ SPACING = 15
control_box.AddSpacer(2)
- control_box.Add(common.LabelText(self, 'Axes Menu'), 0,
wx.ALIGN_CENTER)
+ control_box.Add(common.LabelText(self, 'Axes Options'), 0,
wx.ALIGN_CENTER)
#x axis divs
hbox = wx.BoxSizer(wx.HORIZONTAL)
- control_box.Add(hbox, 1, wx.ALIGN_LEFT)
- hbox.Add(wx.StaticText(self, -1, ' Secs/Div '), 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
- self.x_plus_button = wx.Button(self, -1, '+',
style=wx.BU_EXACTFIT)
- self.x_plus_button.Bind(wx.EVT_BUTTON, self._on_incr_x_divs)
- hbox.Add(self.x_plus_button, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_LEFT)
- self.x_minus_button = wx.Button(self, -1, ' - ',
style=wx.BU_EXACTFIT)
- self.x_minus_button.Bind(wx.EVT_BUTTON, self._on_decr_x_divs)
- hbox.Add(self.x_minus_button, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_LEFT)
+ control_box.Add(hbox, 1, wx.EXPAND)
+ hbox.Add(wx.StaticText(self, -1, ' Secs/Div '), 1,
wx.ALIGN_CENTER_VERTICAL)
+ self.x_buttons = common.IncrDecrButtons(self,
self._on_incr_x_divs, self._on_decr_x_divs)
+ hbox.Add(self.x_buttons, 0, wx.ALIGN_CENTER_VERTICAL)
+ hbox.AddSpacer(SPACING)
#y axis divs
hbox = wx.BoxSizer(wx.HORIZONTAL)
- control_box.Add(hbox, 1, wx.ALIGN_LEFT)
- hbox.Add(wx.StaticText(self, -1, ' Units/Div '), 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
- self.y_plus_button = wx.Button(self, -1, '+',
style=wx.BU_EXACTFIT)
- self.y_plus_button.Bind(wx.EVT_BUTTON, self._on_incr_y_divs)
- hbox.Add(self.y_plus_button, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_LEFT)
- self.y_minus_button = wx.Button(self, -1, ' - ',
style=wx.BU_EXACTFIT)
- self.y_minus_button.Bind(wx.EVT_BUTTON, self._on_decr_y_divs)
- hbox.Add(self.y_minus_button, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_LEFT)
+ control_box.Add(hbox, 1, wx.EXPAND)
+ hbox.Add(wx.StaticText(self, -1, ' Units/Div '), 1,
wx.ALIGN_CENTER_VERTICAL)
+ self.y_buttons = common.IncrDecrButtons(self,
self._on_incr_x_divs, self._on_decr_x_divs)
+ hbox.Add(self.y_buttons, 0, wx.ALIGN_CENTER_VERTICAL)
+ hbox.AddSpacer(SPACING)
#y axis ref lvl
hbox = wx.BoxSizer(wx.HORIZONTAL)
- control_box.Add(hbox, 1, wx.ALIGN_LEFT)
- hbox.Add(wx.StaticText(self, -1, ' Y Offset '), 0,
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT)
- self.y_off_plus_button = wx.Button(self, -1, '+',
style=wx.BU_EXACTFIT)
- self.y_off_plus_button.Bind(wx.EVT_BUTTON, self._on_incr_y_off)
- hbox.Add(self.y_off_plus_button, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_LEFT)
- self.y_off_minus_button = wx.Button(self, -1, ' - ',
style=wx.BU_EXACTFIT)
- self.y_off_minus_button.Bind(wx.EVT_BUTTON, self._on_decr_y_off)
- hbox.Add(self.y_off_minus_button, 0, wx.ALIGN_CENTER_VERTICAL |
wx.ALIGN_LEFT)
+ control_box.Add(hbox, 1, wx.EXPAND)
+ hbox.Add(wx.StaticText(self, -1, ' Y Offset '), 1,
wx.ALIGN_CENTER_VERTICAL)
+ self.y_off_buttons = common.IncrDecrButtons(self,
self._on_incr_x_divs, self._on_decr_x_divs)
+ hbox.Add(self.y_off_buttons, 0, wx.ALIGN_CENTER_VERTICAL)
+ hbox.AddSpacer(SPACING)
- control_box.AddSpacer(2)
- control_box.Add(common.LabelText(self, 'Channel Menu'), 0,
wx.ALIGN_CENTER)
+ #misc options
+ control_box.AddSpacer(2)
+ control_box.Add(common.LabelText(self, 'Range Options'), 0,
wx.ALIGN_CENTER)
#ac couple check box
self.ac_couple_check_box = wx.CheckBox(parent=self,
style=wx.CHK_2STATE, label="AC Couple")
self.ac_couple_check_box.Bind(wx.EVT_CHECKBOX,
self._on_ac_couple)
@@ -146,19 +139,19 @@
#autorange check box
self.autorange_check_box = wx.CheckBox(parent=self,
style=wx.CHK_2STATE, label="Autorange")
self.autorange_check_box.Bind(wx.EVT_CHECKBOX,
self._on_autorange)
- control_box.Add(self.autorange_check_box, 0, wx.ALIGN_LEFT)
+ control_box.Add(self.autorange_check_box, 0, wx.ALIGN_LEFT)
#Run button
self.run_button = wx.Button(self, -1, '', style=wx.BU_EXACTFIT)
self.run_button.Bind(wx.EVT_BUTTON, self._on_run)
- control_box.Add(self.run_button, 0, wx.EXPAND)
-
+ control_box.Add(self.run_button, 0, wx.EXPAND)
+
#end control box
control_box.AddSpacer(2)
#set sizer
self.SetSizerAndFit(control_box)
#update
self.update()
-
+
def update(self):
"""!
Read the state of the scope plot settings and update the
control panel.
@@ -176,16 +169,12 @@
else: self.run_button.SetLabel('Run')
#update the y adj buttons
if self.parent.autorange:
- self.y_plus_button.Disable()
- self.y_minus_button.Disable()
- self.y_off_plus_button.Disable()
- self.y_off_minus_button.Disable()
- else:
- self.y_plus_button.Enable()
- self.y_minus_button.Enable()
- self.y_off_plus_button.Enable()
- self.y_off_minus_button.Enable()
-
+ self.y_buttons.Disable()
+ self.y_off_buttons.Disable()
+ else:
+ self.y_buttons.Enable()
+ self.y_off_buttons.Enable()
+
##################################################
# Event handlers
##################################################
@@ -194,7 +183,7 @@
def _on_autorange(self, event):
self.parent.set_autorange(event.IsChecked())
def _on_trigger_channel(self, event):
self.parent.set_trigger_channel_index(self.trigger_channel_chooser.GetSelection())
def _on_trigger_mode(self, event):
self.parent.set_trigger_mode_index(self.trigger_mode_chooser.GetSelection())
- def _on_trigger_level(self, event):
self.parent.set_trigger_level_index(self.trigger_level_chooser.GetSelection())
+ def _on_trigger_level(self, event):
self.parent.set_trigger_level_index(self.trigger_level_chooser.GetSelection())
def _on_incr_x_divs(self, event):
self.parent.set_x_per_div(common.get_clean_incr(self.parent.x_per_div))
def _on_decr_x_divs(self, event):
self.parent.set_x_per_div(common.get_clean_decr(self.parent.x_per_div))
def _on_incr_y_divs(self, event):
self.parent.set_y_per_div(common.get_clean_incr(self.parent.y_per_div))
@@ -208,9 +197,9 @@
##################################################
class scope_window(wx.Panel):
def __init__(
- self,
+ self,
parent,
- size,
+ size,
title,
scope,
frame_rate,
@@ -219,7 +208,7 @@
x_per_div,
y_per_div,
ac_couple,
- ):
+ ):
#check num inputs
assert num_inputs <= len(CHANNEL_COLOR_SPECS)
#setup
@@ -247,9 +236,9 @@
self.frame_rate = frame_rate
self.frame_counter = 0
self._init = False #HACK
- #init panel and plot
+ #init panel and plot
wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER)
- self.plotter = plotter.grid_plotter(self)
+ self.plotter = plotter.grid_plotter(self)
self.plotter.SetSize(wx.Size(*size))
self.plotter.set_title(title)
self.plotter.set_legend(self.num_inputs > 1)
@@ -261,14 +250,14 @@
self.SetSizerAndFit(main_box)
#update
self.update()
-
+
def plot(self, sampleses):
"""!
Plot the list of arrays of samples onto the grid.
Each samples array gets its own channel.
@param sampleses the array of arrays
"""
- if not self._init: #HACK
+ if not self._init: #HACK
self._init = True
self.update()
if not self.running: return
@@ -281,42 +270,42 @@
#ac coupling
if self.ac_couple:
sampleses = [samples - numpy.average(samples)
for samples in sampleses]
- #autorange
+ #autorange
if self.autorange and time.time() - self.autorange_ts >
AUTORANGE_UPDATE_RATE:
bounds = [common.get_min_max(samples) for
samples in sampleses]
y_min = min(*[bound[0] for bound in bounds])
y_max = max(*[bound[1] for bound in bounds])
#adjust the y per div
- y_per_div =
common.get_clean_num((y_max-y_min)/self.y_divs)
+ y_per_div =
common.get_clean_num((y_max-y_min)/self.y_divs)
if self.y_per_div != y_per_div:
self.set_y_per_div(y_per_div)
#adjust the y offset
y_off =
self.y_per_div*round((y_max+y_min)/2/self.y_per_div)
- if self.y_off != y_off: self.set_y_off(y_off)
+ if self.y_off != y_off: self.set_y_off(y_off)
self.autorange_ts = time.time()
#plot each waveform
for i, samples in enumerate(sampleses):
- #number of samples to scale to the screen
+ #number of samples to scale to the screen
num_samps =
int(self.x_per_div*self.x_divs*self.sample_rate)
#handle num samps out of bounds
while num_samps > len(samples): samples =
numpy.concatenate((samples, samples))
if num_samps < 2: num_samps = 0
#plot samples
self.plotter.set_waveform(
- channel=i+1,
+ channel=i+1,
samples=samples[:num_samps],
color_spec=CHANNEL_COLOR_SPECS[i],
)
#update the plotter
- self.plotter.update()
+ self.plotter.update()
self.frame_counter = (self.frame_counter + 1)%self.decim
-
+
def update(self):
#update the frame decimation
self.decim = max(1,
int(self.sample_rate/self.scope.get_samples_per_output_record()/self.frame_rate))
#update the scope
if self._init: #HACK avoid segfaults, only set after a sample
has arrived
self.scope.set_trigger_channel(self.trigger_channel_index)
-
self.scope.set_trigger_mode(TRIGGER_MODES[self.trigger_mode_index][1])
+
self.scope.set_trigger_mode(TRIGGER_MODES[self.trigger_mode_index][1])
self.scope.set_sample_rate(self.sample_rate)
#update the x axis
exp = common.get_exp(self.x_per_div)
@@ -326,21 +315,21 @@
else: x_units, scalar = 'ns', 1e9
self.plotter.set_x_units('Time (%s)'%x_units)
self.plotter.set_x_grid(
- scalar*self.x_off,
- scalar*self.x_per_div*self.x_divs + scalar*self.x_off,
+ scalar*self.x_off,
+ scalar*self.x_per_div*self.x_divs + scalar*self.x_off,
scalar*self.x_per_div,
)
#update the y axis
self.plotter.set_y_units('Units')
self.plotter.set_y_grid(
- -1*self.y_per_div*self.y_divs/2.0 + self.y_off,
- self.y_per_div*self.y_divs/2.0 + self.y_off,
+ -1*self.y_per_div*self.y_divs/2.0 + self.y_off,
+ self.y_per_div*self.y_divs/2.0 + self.y_off,
self.y_per_div,
)
#update control panel and plotter
self.control_panel.update()
self.plotter.update()
-
+
##################################################
# Set parameters on-the-fly
##################################################
@@ -383,27 +372,27 @@
##################################################
# Scope sink block
-##################################################
+##################################################
class scope_sink_f(gr.hier_block2):
"""!
A scope block with a gui window.
"""
-
+
def __init__(
- self,
+ self,
parent,
- title='',
+ title='',
sample_rate=1,
size=DEFAULT_WIN_SIZE,
frame_rate=DEFAULT_FRAME_RATE,
v_scale=DEFAULT_V_SCALE,
- t_scale=None,
+ t_scale=None,
num_inputs=1,
ac_couple=False,
):
#init
gr.hier_block2.__init__(
- self,
+ self,
"scope_sink",
gr.io_signature(num_inputs, num_inputs,
gr.sizeof_float),
gr.io_signature(0, 0, 0),
@@ -412,11 +401,11 @@
msgq = gr.msg_queue(2)
scope = gr.oscope_sink_f(sample_rate, msgq)
#connect
- for i in range(num_inputs):
+ for i in range(num_inputs):
self.connect((self, i), (scope, i))
#create window
self.win = scope_window(
- parent=parent,
+ parent=parent,
size=size,
title=title,
scope=scope,
@@ -431,11 +420,11 @@
self.set_sample_rate = self.win.set_sample_rate
#setup the input watcher
common.input_watcher(msgq, self._handle_msg)
-
+
def _handle_msg(self, msg):
nchan = int(msg.arg1()) # number of channels of data in msg
nsamples = int(msg.arg2()) # number of samples in each channel
s = msg.to_string() # get the body of the msg as a string
samples = numpy.fromstring(s, numpy.float32)
- samps_per_ch = len(samples)/nchan
+ samps_per_ch = len(samples)/nchan
self.win.plot([samples[samps_per_ch*i:samps_per_ch*(i+1)] for i
in range(nchan)])
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r8774 - gnuradio/branches/developers/jblum/gr-wxglgui/src/python,
jblum <=