commit-gnuradio
[Top][All Lists]
Advanced

[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,





reply via email to

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