[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r9149 - in gnuradio/branches/features/experimental-gui
From: |
jblum |
Subject: |
[Commit-gnuradio] r9149 - in gnuradio/branches/features/experimental-gui: . plotter |
Date: |
Fri, 1 Aug 2008 19:15:31 -0600 (MDT) |
Author: jblum
Date: 2008-08-01 19:15:31 -0600 (Fri, 01 Aug 2008)
New Revision: 9149
Modified:
gnuradio/branches/features/experimental-gui/plotter/waterfall_plotter.py
gnuradio/branches/features/experimental-gui/todo.txt
gnuradio/branches/features/experimental-gui/waterfall_window.py
gnuradio/branches/features/experimental-gui/waterfallsink.py
Log:
waterfall legend
Modified:
gnuradio/branches/features/experimental-gui/plotter/waterfall_plotter.py
===================================================================
--- gnuradio/branches/features/experimental-gui/plotter/waterfall_plotter.py
2008-08-01 23:33:00 UTC (rev 9148)
+++ gnuradio/branches/features/experimental-gui/plotter/waterfall_plotter.py
2008-08-02 01:15:31 UTC (rev 9149)
@@ -25,6 +25,11 @@
import numpy
import gltext
+LEGEND_LEFT_PAD = 7
+LEGEND_RIGHT_PAD = 3
+LEGEND_NUM_BLOCKS = 10
+LEGEND_BLOCK_WIDTH = 8
+LEGEND_FONT_SIZE = 8
PADDING = 35, 60, 40, 60 #top, right, bottom, left
RGBA_ARRAY = \
[numpy.array((0, 2*i, 1 - 2*i, 0), numpy.uint8) for i in range(0, 128)]
+ \
@@ -40,9 +45,10 @@
"""
#init
grid_plotter_base.__init__(self, parent, PADDING)
- self._num_frames = 128
self._buffer_init = False
self._data_queue = list()
+ self._minimum = 0
+ self._maximum = 0
def _gl_init(self):
"""!
@@ -63,6 +69,7 @@
if self.changed():
glNewList(self._grid_compiled_list_id,
GL_COMPILE)
self._draw_grid()
+ self._draw_legend()
glEndList()
self.changed(False)
#draw the grid
@@ -84,22 +91,23 @@
def _draw_waterfall(self, data):
"""!
- Draw the waterfall display using pixels from the PBO.
+ Draw a new sample onto the waterfall display.
The pixels will be scaled to fit within the grid area.
+ @param data the fft bsample as color data
"""
fft_size = len(data)/4
#pixel zoom
x_zoom =
float(self.width-self.padding_left-self.padding_right)/fft_size
- y_zoom =
float(self.height-self.padding_top-self.padding_bottom+1)/self._num_frames
+ y_zoom =
float(self.height-self.padding_top-self.padding_bottom+1)/self._num_lines
#draw and shift the previous samples
glReadBuffer(GL_FRONT)
glPixelZoom(1, 1)
glRasterPos2f(self.padding_left+1,
self.height-self.padding_bottom-int(y_zoom))
glCopyPixels(
- self.padding_left+1,
- self.padding_bottom,
- self.width-self.padding_left-self.padding_right,
-
self.height-self.padding_top-self.padding_bottom-int(y_zoom),
+ self.padding_left+1,
+ self.padding_bottom,
+ self.width-self.padding_left-self.padding_right,
+
self.height-self.padding_top-self.padding_bottom-int(y_zoom),
GL_COLOR,
)
#draw a new fft sample
@@ -107,55 +115,42 @@
glRasterPos2f(self.padding_left+1,
self.height-self.padding_bottom-1)
glDrawPixels(fft_size, 1, GL_RGBA, GL_UNSIGNED_BYTE, data)
- def _update_data(self):
+ def _draw_legend(self):
"""!
- Set all of the samples in the data queue to pixel buffer.
+ Draw the color scale legend.
"""
- while self._data_queue:
- data = self._data_queue.pop(0)
- #init or reinit the pixel buffer
- if self._buffer_init and len(data)/4 != self._fft_size:
- self._fft_size = len(data)/4
- #initial data
- init_data =
numpy.zeros(self._fft_size*self._num_frames*4, numpy.uint8).tostring()
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,
self._waterfall_buffer_top)
- glBufferData(
- GL_PIXEL_UNPACK_BUFFER_ARB,
- len(init_data), init_data,
- GL_STATIC_DRAW,
- )
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,
self._waterfall_buffer_bottom)
- glBufferData(
- GL_PIXEL_UNPACK_BUFFER_ARB,
- len(init_data), init_data,
- GL_STATIC_DRAW,
- )
- #load the color data into the pixel buffers
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,
self._waterfall_buffer_top)
- glBufferSubData(
- GL_PIXEL_UNPACK_BUFFER_ARB,
-
(self._num_frames-self._frame_ptr-1)*self._fft_size*4,
- len(data), data,
- )
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,
self._waterfall_buffer_bottom)
- glBufferSubData(
- GL_PIXEL_UNPACK_BUFFER_ARB,
- self._frame_ptr*self._fft_size*4,
- len(data), data,
- )
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0) #unbind
- #increment the pointer
- self._frame_ptr = (self._frame_ptr + 1)%self._num_frames
+ block_height =
float(self.height-self.padding_top-self.padding_bottom)/LEGEND_NUM_BLOCKS
+ #draw each legend block
+ for i in range(LEGEND_NUM_BLOCKS):
+ proportion = i/float(LEGEND_NUM_BLOCKS-1)
+ dB = proportion*(self._maximum - self._minimum) +
self._minimum
+ color = RGBA_ARRAY[int(255*proportion)]
+ glColor4f(*map(lambda c: c/255.0, color))
+ #coordinates
+ x = self.width-self.padding_right + LEGEND_LEFT_PAD
+ y = self.height - (i+1)*block_height -
self.padding_bottom
+ #block
+ self._draw_rect(x, y, LEGEND_BLOCK_WIDTH, block_height)
+ #block label
+ txt = gltext.Text('%ddB'%int(dB),
font_size=LEGEND_FONT_SIZE)
+
txt.draw_text(wx.Point(x+LEGEND_BLOCK_WIDTH+LEGEND_RIGHT_PAD, y+block_height/4))
- def set_samples(self, samples, min, max):
+ def set_samples(self, samples, min, max, num_lines):
"""!
Set the samples to the waterfall.
Convert the samples to color data.
@param samples the array of floats
@param min the minimum value to scale
@param max the maximum value to scale
+ @param num_lines the number of lines
"""
self.semaphore.acquire(True)
+ #set the min, max values
+ if self._minimum != min or self._maximum != max:
+ self._minimum = min
+ self._maximum = max
+ self.changed(True)
+ self._num_lines = num_lines
#normalize the samples to min/max
samples = (samples - min)*float(255/(max-min))
samples = numpy.minimum(samples, 255) #clip
Modified: gnuradio/branches/features/experimental-gui/todo.txt
===================================================================
--- gnuradio/branches/features/experimental-gui/todo.txt 2008-08-01
23:33:00 UTC (rev 9148)
+++ gnuradio/branches/features/experimental-gui/todo.txt 2008-08-02
01:15:31 UTC (rev 9149)
@@ -4,9 +4,6 @@
-controller property with default value for cache
-use iteritems in cli.py
-add/remove listener in cli.py
--channel model needs sample rate param
-constsink: replace mpsk recv with costas + clock recovery
--costas loop needs set methods
--2d waterfallsink
-give numbersink the treatment
-run expand on all files (sorry tabs)
Modified: gnuradio/branches/features/experimental-gui/waterfall_window.py
===================================================================
--- gnuradio/branches/features/experimental-gui/waterfall_window.py
2008-08-01 23:33:00 UTC (rev 9148)
+++ gnuradio/branches/features/experimental-gui/waterfall_window.py
2008-08-02 01:15:31 UTC (rev 9149)
@@ -37,7 +37,11 @@
DEFAULT_FRAME_RATE = 30
DEFAULT_WIN_SIZE = (600, 300)
DIV_LEVELS = (1, 2, 5, 10, 20)
+MIN_NUM_LINES, MAX_NUM_LINES = 1000, 10
+MIN_DYNAMIC_RANGE, MAX_DYNAMIC_RANGE = 10, 200
DYNAMIC_RANGE_KEY = 'dynamic_range'
+NUM_LINES_KEY = 'num_lines'
+Y_DIVS_KEY = 'y_divs'
X_DIVS_KEY = 'x_divs'
REF_LEVEL_KEY = 'ref_level'
BASEBAND_FREQ_KEY = 'baseband_freq'
@@ -84,6 +88,12 @@
control_box.AddSpacer(2)
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)
+ #num lines buttons
+ control_box.AddStretchSpacer()
+ control_box.Add(common.LabelText(self, 'Set Num Lines'), 0,
wx.ALIGN_CENTER)
+ control_box.AddSpacer(2)
+ self._num_lines_buttons = common.IncrDecrButtons(self,
self._on_incr_num_lines, self._on_decr_num_lines)
+ control_box.Add(self._num_lines_buttons, 0, wx.ALIGN_CENTER)
#run/stop
control_box.AddStretchSpacer()
self.run_button = common.RunStopButtonController(self,
parent.controller, RUNNING_KEY)
@@ -95,17 +105,23 @@
# Event handlers
##################################################
def _on_incr_dynamic_range(self, event):
- self.parent.set_dynamic_range(
- 2.0*self.parent.controller[DYNAMIC_RANGE_KEY])
+ self.parent.set_dynamic_range(common.get_clean_incr(
+ min(self.parent.controller[DYNAMIC_RANGE_KEY],
MAX_DYNAMIC_RANGE)))
def _on_decr_dynamic_range(self, event):
- self.parent.set_dynamic_range(
- 0.5*self.parent.controller[DYNAMIC_RANGE_KEY])
+ self.parent.set_dynamic_range(common.get_clean_decr(
+ max(self.parent.controller[DYNAMIC_RANGE_KEY],
MIN_DYNAMIC_RANGE)))
def _on_incr_ref_level(self, event):
self.parent.set_ref_level(
self.parent.controller[REF_LEVEL_KEY] +
self.parent.controller[DYNAMIC_RANGE_KEY]/10)
def _on_decr_ref_level(self, event):
self.parent.set_ref_level(
self.parent.controller[REF_LEVEL_KEY] -
self.parent.controller[DYNAMIC_RANGE_KEY]/10)
+ def _on_incr_num_lines(self, event):
+ self.parent.set_num_lines(
+ min(self.parent.controller[NUM_LINES_KEY]+10,
MAX_NUM_LINES))
+ def _on_decr_num_lines(self, event):
+ self.parent.set_num_lines(
+ max(self.parent.controller[NUM_LINES_KEY]-10,
MIN_NUM_LINES))
##################################################
# Waterfall window with plotter and control panel
@@ -121,6 +137,7 @@
fft_size,
baseband_freq,
sample_rate_key,
+ frame_rate_key,
dynamic_range,
ref_level,
average_key,
@@ -133,6 +150,7 @@
self.real = real
self.fft_size = fft_size
self.sample_rate_key = sample_rate_key
+ self.frame_rate_key = frame_rate_key
self.average_key = average_key
self.avg_alpha_key = avg_alpha_key
#init panel and plot
@@ -150,6 +168,8 @@
self.ext_controller[self.average_key] =
self.ext_controller[self.average_key]
self.ext_controller[self.avg_alpha_key] =
self.ext_controller[self.avg_alpha_key]
self._register_set_prop(self.controller, DYNAMIC_RANGE_KEY,
dynamic_range)
+ self._register_set_prop(self.controller, NUM_LINES_KEY, 128)
+ self._register_set_prop(self.controller, Y_DIVS_KEY, 10)
self._register_set_prop(self.controller, X_DIVS_KEY, 8)
#approximate
self._register_set_prop(self.controller, REF_LEVEL_KEY,
ref_level)
self._register_set_prop(self.controller, BASEBAND_FREQ_KEY,
baseband_freq)
@@ -157,7 +177,10 @@
#register events
self.ext_controller.add_listener(msg_key, self.handle_msg)
self.ext_controller.add_listener(self.sample_rate_key,
self.update_grid)
+ self.ext_controller.add_listener(self.frame_rate_key,
self.update_grid)
self.controller.add_listener(BASEBAND_FREQ_KEY,
self.update_grid)
+ self.controller.add_listener(NUM_LINES_KEY, self.update_grid)
+ self.controller.add_listener(Y_DIVS_KEY, self.update_grid)
self.controller.add_listener(X_DIVS_KEY, self.update_grid)
#initial update
self.update_grid()
@@ -179,8 +202,10 @@
else: samples = numpy.concatenate((samples[num_samps/2+1:],
samples[:num_samps/2]))
#plot the fft
self.plotter.set_samples(
- samples, self.controller[REF_LEVEL_KEY],
+ samples,
+ self.controller[REF_LEVEL_KEY],
self.controller[DYNAMIC_RANGE_KEY] +
self.controller[REF_LEVEL_KEY],
+ self.controller[NUM_LINES_KEY],
)
#update the plotter
self.plotter.update()
@@ -195,7 +220,10 @@
"""
#grid parameters
sample_rate = self.ext_controller[self.sample_rate_key]
+ frame_rate = self.ext_controller[self.frame_rate_key]
baseband_freq = self.controller[BASEBAND_FREQ_KEY]
+ num_lines = self.controller[NUM_LINES_KEY]
+ y_divs = self.controller[Y_DIVS_KEY]
x_divs = self.controller[X_DIVS_KEY]
#determine best fitting x_per_div
if self.real: x_width = sample_rate/2.0
@@ -223,7 +251,9 @@
#update x units
self.plotter.set_x_units('Frequency (%s)'%x_units)
#update y grid
- self.plotter.set_y_grid(0, 10, 1)
+ duration = float(num_lines)/frame_rate
+ y_per_div = common.get_clean_num(duration/y_divs)
+ self.plotter.set_y_grid(0, duration, y_per_div)
#update y units
self.plotter.set_y_units('Time (s)')
#update plotter
Modified: gnuradio/branches/features/experimental-gui/waterfallsink.py
===================================================================
--- gnuradio/branches/features/experimental-gui/waterfallsink.py
2008-08-01 23:33:00 UTC (rev 9148)
+++ gnuradio/branches/features/experimental-gui/waterfallsink.py
2008-08-02 01:15:31 UTC (rev 9149)
@@ -31,6 +31,7 @@
# Constants
##################################################
SAMPLE_RATE_KEY = 'sample_rate'
+FRAME_RATE_KEY = 'frame_rate'
AVERAGE_KEY = 'average'
AVG_ALPHA_KEY = 'avg_alpha'
MSG_KEY = 'msg'
@@ -89,6 +90,7 @@
self.controller.set_provider(AVG_ALPHA_KEY, fft.avg_alpha)
self.controller.add_listener(SAMPLE_RATE_KEY,
fft.set_sample_rate)
self.controller.set_provider(SAMPLE_RATE_KEY, fft.sample_rate)
+ self.controller.set_provider(FRAME_RATE_KEY,
fft._sd.frame_rate) #FIXME
#start input watcher
common.input_watcher(msgq, lambda x:
self.controller.set(MSG_KEY, x))
#create window
@@ -101,6 +103,7 @@
fft_size=fft_size,
baseband_freq=baseband_freq,
sample_rate_key=SAMPLE_RATE_KEY,
+ frame_rate_key=FRAME_RATE_KEY,
dynamic_range=dynamic_range,
ref_level=ref_level,
average_key=AVERAGE_KEY,
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r9149 - in gnuradio/branches/features/experimental-gui: . plotter,
jblum <=