Changeset 8707

Show
Ignore:
Timestamp:
06/25/08 14:12:06
Author:
jcorgan
Message:

Applied changesets r8581, r8584, r8585, and r8586 on trunk to release branch.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gnuradio/branches/releases/3.1/gr-wxgui/src/python/fftsink2.py

    r8339 r8707  
    2424from gnuradio.wxgui import stdgui2 
    2525import wx 
    26 import gnuradio.wxgui.plot as plot 
     26import plot 
    2727import numpy 
    2828import threading 
    2929import math     
     30 
     31DIV_LEVELS = (1, 2, 5, 10, 20) 
    3032 
    3133default_fftsink_size = (640,240) 
     
    6971        else: 
    7072            self.avg.set_taps(1.0) 
    71        self.win.peak_vals = None 
    72          
     73        self.win.peak_vals = None 
     74         
    7375    def set_peak_hold(self, enable): 
    7476        self.peak_hold = enable 
     
    121123        # FIXME  We need to add 3dB to all bins but the DC bin 
    122124        self.log = gr.nlog10_ff(20, self.fft_size, 
    123                                -10*math.log10(self.fft_size)           # Adjust for number of bins 
    124                               -10*math.log10(power/self.fft_size)      # Adjust for windowing loss 
    125                               -20*math.log10(ref_scale/2))             # Adjust for reference scale 
    126                                
     125                               -10*math.log10(self.fft_size)                # Adjust for number of bins 
     126                               -10*math.log10(power/self.fft_size)        # Adjust for windowing loss 
     127                               -20*math.log10(ref_scale/2))                # Adjust for reference scale 
     128                                
    127129        self.sink = gr.message_sink(gr.sizeof_float * self.fft_size, self.msgq, True) 
    128        self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2mag, self.avg, self.log, self.sink) 
     130        self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2mag, self.avg, self.log, self.sink) 
    129131 
    130132        self.win = fft_window(self, parent, size=size) 
    131133        self.set_average(self.average) 
    132  
     134        self.set_peak_hold(self.peak_hold) 
    133135 
    134136class fft_sink_c(gr.hier_block2, fft_sink_base): 
     
    164166        # FIXME  We need to add 3dB to all bins but the DC bin 
    165167        self.log = gr.nlog10_ff(20, self.fft_size, 
    166                                 -10*math.log10(self.fft_size)          # Adjust for number of bins 
    167                                -10*math.log10(power/self.fft_size)     # Adjust for windowing loss 
    168                                -20*math.log10(ref_scale/2))            # Adjust for reference scale 
    169                                  
     168                                -10*math.log10(self.fft_size)                # Adjust for number of bins 
     169                                -10*math.log10(power/self.fft_size)        # Adjust for windowing loss 
     170                                -20*math.log10(ref_scale/2))                # Adjust for reference scale 
     171                                 
    170172        self.sink = gr.message_sink(gr.sizeof_float * self.fft_size, self.msgq, True) 
    171        self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2mag, self.avg, self.log, self.sink) 
     173        self.connect(self, self.s2p, self.one_in_n, self.fft, self.c2mag, self.avg, self.log, self.sink) 
    172174 
    173175        self.win = fft_window(self, parent, size=size) 
    174176        self.set_average(self.average) 
     177        self.set_peak_hold(self.peak_hold) 
    175178 
    176179 
     
    219222            wx.PostEvent (self.event_receiver, de) 
    220223            del de 
     224 
     225class control_panel(wx.Panel): 
    221226     
    222  
    223 class fft_window (plot.PlotCanvas): 
     227    class LabelText(wx.StaticText):     
     228        def __init__(self, window, label): 
     229            wx.StaticText.__init__(self, window, -1, label) 
     230            font = self.GetFont() 
     231            font.SetWeight(wx.FONTWEIGHT_BOLD) 
     232            font.SetUnderlined(True) 
     233            self.SetFont(font) 
     234     
     235    def __init__(self, parent): 
     236        self.parent = parent 
     237        wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER)     
     238        control_box = wx.BoxSizer(wx.VERTICAL) 
     239         
     240        #checkboxes for average and peak hold 
     241        control_box.AddStretchSpacer() 
     242        control_box.Add(self.LabelText(self, 'Options'), 0, wx.ALIGN_CENTER) 
     243        self.average_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Average") 
     244        self.average_check_box.Bind(wx.EVT_CHECKBOX, parent.on_average) 
     245        control_box.Add(self.average_check_box, 0, wx.EXPAND) 
     246        self.peak_hold_check_box = wx.CheckBox(parent=self, style=wx.CHK_2STATE, label="Peak Hold") 
     247        self.peak_hold_check_box.Bind(wx.EVT_CHECKBOX, parent.on_peak_hold)  
     248        control_box.Add(self.peak_hold_check_box, 0, wx.EXPAND) 
     249        
     250        #radio buttons for div size 
     251        control_box.AddStretchSpacer() 
     252        control_box.Add(self.LabelText(self, 'Set dB/div'), 0, wx.ALIGN_CENTER) 
     253        radio_box = wx.BoxSizer(wx.VERTICAL) 
     254        self.radio_buttons = list() 
     255        for y_per_div in DIV_LEVELS: 
     256            radio_button = wx.RadioButton(self, -1, "%d dB/div"%y_per_div) 
     257            radio_button.Bind(wx.EVT_RADIOBUTTON, self.on_radio_button_change) 
     258            self.radio_buttons.append(radio_button) 
     259            radio_box.Add(radio_button, 0, wx.ALIGN_LEFT) 
     260        control_box.Add(radio_box, 0, wx.EXPAND) 
     261         
     262        #ref lvl buttons 
     263        control_box.AddStretchSpacer() 
     264        control_box.Add(self.LabelText(self, 'Adj Ref Lvl'), 0, wx.ALIGN_CENTER) 
     265        control_box.AddSpacer(2) 
     266        button_box = wx.BoxSizer(wx.HORIZONTAL)         
     267        self.ref_plus_button = wx.Button(self, -1, '+', style=wx.BU_EXACTFIT) 
     268        self.ref_plus_button.Bind(wx.EVT_BUTTON, parent.on_incr_ref_level) 
     269        button_box.Add(self.ref_plus_button, 0, wx.ALIGN_CENTER) 
     270        self.ref_minus_button = wx.Button(self, -1, ' - ', style=wx.BU_EXACTFIT) 
     271        self.ref_minus_button.Bind(wx.EVT_BUTTON, parent.on_decr_ref_level) 
     272        button_box.Add(self.ref_minus_button, 0, wx.ALIGN_CENTER) 
     273        control_box.Add(button_box, 0, wx.ALIGN_CENTER) 
     274        control_box.AddStretchSpacer() 
     275        #set sizer 
     276        self.SetSizerAndFit(control_box) 
     277        #update 
     278        self.update() 
     279         
     280    def update(self): 
     281        """! 
     282        Read the state of the fft plot settings and update the control panel. 
     283        """ 
     284        #update checkboxes 
     285        self.average_check_box.SetValue(self.parent.fftsink.average) 
     286        self.peak_hold_check_box.SetValue(self.parent.fftsink.peak_hold) 
     287        #update radio buttons     
     288        try: 
     289            index = list(DIV_LEVELS).index(self.parent.fftsink.y_per_div) 
     290            self.radio_buttons[index].SetValue(True) 
     291        except: pass 
     292         
     293    def on_radio_button_change(self, evt): 
     294        selected_radio_button = filter(lambda rb: rb.GetValue(), self.radio_buttons)[0]  
     295        index = self.radio_buttons.index(selected_radio_button) 
     296        self.parent.fftsink.set_y_per_div(DIV_LEVELS[index]) 
     297 
     298class fft_window (wx.Panel): 
    224299    def __init__ (self, fftsink, parent, id = -1, 
    225300                  pos = wx.DefaultPosition, size = wx.DefaultSize, 
    226301                  style = wx.DEFAULT_FRAME_STYLE, name = ""): 
    227         plot.PlotCanvas.__init__ (self, parent, id, pos, size, style, name) 
    228  
    229         self.y_range = None 
     302         
    230303        self.fftsink = fftsink 
     304        #init panel and plot  
     305        wx.Panel.__init__(self, parent, -1)                   
     306        self.plot = plot.PlotCanvas(self, id, pos, size, style, name)        
     307        #setup the box with plot and controls 
     308        self.control_panel = control_panel(self) 
     309        main_box = wx.BoxSizer (wx.HORIZONTAL) 
     310        main_box.Add (self.plot, 1, wx.EXPAND) 
     311        main_box.Add (self.control_panel, 0, wx.EXPAND) 
     312        self.SetSizerAndFit(main_box) 
     313         
    231314        self.peak_hold = False 
    232315        self.peak_vals = None 
    233316         
    234         self.SetEnableGrid (True) 
     317        self.plot.SetEnableGrid (True) 
    235318        # self.SetEnableZoom (True) 
    236319        # self.SetBackgroundColour ('black') 
    237320         
    238321        self.build_popup_menu() 
    239        self.set_baseband_freq(0.0) 
    240                 
     322        self.set_baseband_freq(0.0) 
     323                 
    241324        EVT_DATA_EVENT (self, self.set_data) 
    242325        wx.EVT_CLOSE (self, self.on_close_window) 
    243         self.Bind(wx.EVT_RIGHT_UP, self.on_right_click) 
    244         self.Bind(wx.EVT_MOTION, self.evt_motion) 
    245          
     326        self.plot.Bind(wx.EVT_RIGHT_UP, self.on_right_click) 
     327        self.plot.Bind(wx.EVT_MOTION, self.evt_motion) 
     328         
    246329        self.input_watcher = input_watcher(fftsink.msgq, fftsink.fft_size, self) 
    247330 
    248331    def set_scale(self, freq): 
    249         x = max(abs(self.fftsink.sample_rate), abs(self.fftsink.baseband_freq))  
     332        x = max(abs(self.fftsink.sample_rate), abs(self.fftsink.baseband_freq))         
    250333        if x >= 1e9: 
    251334            self._scale_factor = 1e-9 
    252335            self._units = "GHz" 
    253            self._format = "%3.6f" 
     336            self._format = "%3.6f" 
    254337        elif x >= 1e6: 
    255338            self._scale_factor = 1e-6 
    256339            self._units = "MHz" 
    257            self._format = "%3.3f" 
     340            self._format = "%3.3f" 
    258341        else: 
    259342            self._scale_factor = 1e-3 
    260343            self._units = "kHz" 
    261            self._format = "%3.3f" 
     344            self._format = "%3.3f" 
    262345 
    263346    def set_baseband_freq(self, baseband_freq): 
    264        if self.peak_hold: 
    265            self.peak_vals = None 
    266        self.set_scale(baseband_freq) 
    267        self.fftsink.set_baseband_freq(baseband_freq) 
    268          
     347        if self.peak_hold: 
     348            self.peak_vals = None 
     349        self.set_scale(baseband_freq) 
     350        self.fftsink.set_baseband_freq(baseband_freq) 
     351         
    269352    def on_close_window (self, event): 
    270353        print "fft_window:on_close_window" 
     
    284367        if self.fftsink.input_is_real:     # only plot 1/2 the points 
    285368            x_vals = ((numpy.arange (L/2) * (self.fftsink.sample_rate  
    286                       * self._scale_factor / L)) 
     369                       * self._scale_factor / L)) 
    287370                      + self.fftsink.baseband_freq * self._scale_factor) 
    288371            self._points = numpy.zeros((len(x_vals), 2), numpy.float64) 
    289372            self._points[:,0] = x_vals 
    290373            self._points[:,1] = dB[0:L/2] 
    291            if self.peak_hold: 
    292                self._peak_points = numpy.zeros((len(x_vals), 2), numpy.float64) 
    293                self._peak_points[:,0] = x_vals 
    294                self._peak_points[:,1] = self.peak_vals[0:L/2] 
     374            if self.peak_hold: 
     375                self._peak_points = numpy.zeros((len(x_vals), 2), numpy.float64) 
     376                self._peak_points[:,0] = x_vals 
     377                self._peak_points[:,1] = self.peak_vals[0:L/2] 
    295378        else: 
    296379            # the "negative freqs" are in the second half of the array 
     
    301384            self._points[:,0] = x_vals 
    302385            self._points[:,1] = numpy.concatenate ((dB[L/2:], dB[0:L/2])) 
    303            if self.peak_hold: 
    304                self._peak_points = numpy.zeros((len(x_vals), 2), numpy.float64) 
    305                self._peak_points[:,0] = x_vals 
    306                self._peak_points[:,1] = numpy.concatenate ((self.peak_vals[L/2:], self.peak_vals[0:L/2])) 
     386            if self.peak_hold: 
     387                self._peak_points = numpy.zeros((len(x_vals), 2), numpy.float64) 
     388                self._peak_points[:,0] = x_vals 
     389                self._peak_points[:,1] = numpy.concatenate ((self.peak_vals[L/2:], self.peak_vals[0:L/2])) 
    307390 
    308391        lines = [plot.PolyLine (self._points, colour='BLUE'),] 
    309        if self.peak_hold: 
    310            lines.append(plot.PolyLine (self._peak_points, colour='GREEN')) 
     392        if self.peak_hold: 
     393            lines.append(plot.PolyLine (self._peak_points, colour='GREEN')) 
    311394 
    312395        graphics = plot.PlotGraphics (lines, 
    313396                                      title=self.fftsink.title, 
    314397                                      xLabel = self._units, yLabel = "dB") 
    315  
    316         self.Draw (graphics, xAxis=None, yAxis=self.y_range) 
    317         self.update_y_range () 
    318  
     398        x_range = x_vals[0], x_vals[-1] 
     399        ymax = self.fftsink.ref_level 
     400        ymin = self.fftsink.ref_level - self.fftsink.y_per_div * self.fftsink.y_divs 
     401        y_range = ymin, ymax 
     402        self.plot.Draw (graphics, xAxis=x_range, yAxis=y_range, step=self.fftsink.y_per_div)         
    319403 
    320404    def set_peak_hold(self, enable): 
     
    322406        self.peak_vals = None 
    323407 
    324     def update_y_range (self): 
    325         ymax = self.fftsink.ref_level 
    326         ymin = self.fftsink.ref_level - self.fftsink.y_per_div * self.fftsink.y_divs 
    327         self.y_range = self._axisInterval ('min', ymin, ymax) 
    328  
    329408    def on_average(self, evt): 
    330409        # print "on_average" 
    331410        self.fftsink.set_average(evt.IsChecked()) 
     411        self.control_panel.update() 
    332412 
    333413    def on_peak_hold(self, evt): 
    334414        # print "on_peak_hold" 
    335415        self.fftsink.set_peak_hold(evt.IsChecked()) 
     416        self.control_panel.update() 
    336417 
    337418    def on_incr_ref_level(self, evt): 
     
    347428    def on_incr_y_per_div(self, evt): 
    348429        # print "on_incr_y_per_div" 
    349         self.fftsink.set_y_per_div(next_up(self.fftsink.y_per_div, (1,2,5,10,20))) 
     430        self.fftsink.set_y_per_div(next_up(self.fftsink.y_per_div, DIV_LEVELS)) 
     431        self.control_panel.update() 
    350432 
    351433    def on_decr_y_per_div(self, evt): 
    352434        # print "on_decr_y_per_div" 
    353         self.fftsink.set_y_per_div(next_down(self.fftsink.y_per_div, (1,2,5,10,20))) 
     435        self.fftsink.set_y_per_div(next_down(self.fftsink.y_per_div, DIV_LEVELS)) 
     436        self.control_panel.update() 
    354437 
    355438    def on_y_per_div(self, evt): 
     
    366449        elif Id == self.id_y_per_div_20: 
    367450            self.fftsink.set_y_per_div(20) 
     451        self.control_panel.update() 
    368452 
    369453    def on_right_click(self, event): 
     
    372456            item = menu.FindItemById(id) 
    373457            item.Check(pred()) 
    374         self.PopupMenu(menu, event.GetPosition()) 
     458        self.plot.PopupMenu(menu, event.GetPosition()) 
    375459 
    376460    def evt_motion(self, event): 
    377461        if not hasattr(self, "_points"): 
    378            return # Got here before first window data update 
    379             
    380        # Clip to plotted values 
    381         (ux, uy) = self.GetXY(event)      # Scaled position 
     462            return # Got here before first window data update 
     463             
     464        # Clip to plotted values 
     465        (ux, uy) = self.plot.GetXY(event)      # Scaled position 
    382466        x_vals = numpy.array(self._points[:,0]) 
    383467        if ux < x_vals[0] or ux > x_vals[-1]: 
     
    411495        self.id_average = wx.NewId() 
    412496        self.id_peak_hold = wx.NewId() 
    413          
    414         self.Bind(wx.EVT_MENU, self.on_average, id=self.id_average) 
    415         self.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold) 
    416         self.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level) 
    417         self.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level) 
    418         self.Bind(wx.EVT_MENU, self.on_incr_y_per_div, id=self.id_incr_y_per_div) 
    419         self.Bind(wx.EVT_MENU, self.on_decr_y_per_div, id=self.id_decr_y_per_div) 
    420         self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_1) 
    421         self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_2) 
    422         self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_5) 
    423         self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_10) 
    424         self.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_20) 
     497         
     498        self.plot.Bind(wx.EVT_MENU, self.on_average, id=self.id_average) 
     499        self.plot.Bind(wx.EVT_MENU, self.on_peak_hold, id=self.id_peak_hold) 
     500        self.plot.Bind(wx.EVT_MENU, self.on_incr_ref_level, id=self.id_incr_ref_level) 
     501        self.plot.Bind(wx.EVT_MENU, self.on_decr_ref_level, id=self.id_decr_ref_level) 
     502        self.plot.Bind(wx.EVT_MENU, self.on_incr_y_per_div, id=self.id_incr_y_per_div) 
     503        self.plot.Bind(wx.EVT_MENU, self.on_decr_y_per_div, id=self.id_decr_y_per_div) 
     504        self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_1) 
     505        self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_2) 
     506        self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_5) 
     507        self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_10) 
     508        self.plot.Bind(wx.EVT_MENU, self.on_y_per_div, id=self.id_y_per_div_20) 
    425509         
    426510        # make a menu 
     
    497581        sink1 = fft_sink_c (panel, title="Complex Data", fft_size=fft_size, 
    498582                            sample_rate=input_rate, baseband_freq=100e3, 
    499                             ref_level=0, y_per_div=20
     583                            ref_level=0, y_per_div=20, y_divs=10
    500584        vbox.Add (sink1.win, 1, wx.EXPAND) 
    501585 
    502        self.connect(src1, thr1, sink1) 
     586        self.connect(src1, thr1, sink1) 
    503587 
    504588        #src2 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 2e3, 1) 
     
    507591        sink2 = fft_sink_f (panel, title="Real Data", fft_size=fft_size*2, 
    508592                            sample_rate=input_rate, baseband_freq=100e3, 
    509                             ref_level=0, y_per_div=20
     593                            ref_level=0, y_per_div=20, y_divs=10
    510594        vbox.Add (sink2.win, 1, wx.EXPAND) 
    511595 
    512        self.connect(src2, thr2, sink2) 
     596        self.connect(src2, thr2, sink2) 
    513597 
    514598def main (): 
  • gnuradio/branches/releases/3.1/gr-wxgui/src/python/plot.py

    r5553 r8707  
    768768        return self._xUseScopeTicks 
    769769 
    770     def Draw(self, graphics, xAxis = None, yAxis = None, dc = None): 
     770    def Draw(self, graphics, xAxis = None, yAxis = None, dc = None, step=None): 
    771771        """Draw objects in graphics with specified x and y axis. 
    772772        graphics- instance of PlotGraphics with list of PolyXXX objects 
     
    830830            xTextExtent= (0,0) # No text for ticks 
    831831        if self._ySpec is not 'none': 
    832             yticks = self._ticks(yAxis[0], yAxis[1]
     832            yticks = self._ticks(yAxis[0], yAxis[1], step
    833833            yTextExtentBottom= dc.GetTextExtent(yticks[0][1]) 
    834834            yTextExtentTop   = dc.GetTextExtent(yticks[-1][1]) 
     
    12781278                text = 0    # axis values not drawn on right side 
    12791279 
    1280     def _ticks(self, lower, upper): 
     1280    def _ticks(self, lower, upper, step=None): 
    12811281        ideal = (upper-lower)/7. 
    12821282        log = _numpy.log10(ideal) 
     
    12991299            digits = -int(power) 
    13001300            format = '%'+`digits+2`+'.'+`digits`+'f' 
     1301        #force grid when step is not None 
     1302        if step is not None: grid = step 
    13011303        ticks = [] 
    13021304        t = -grid*_numpy.floor(-lower/grid) 
    13031305        while t <= upper: 
     1306            if t == -0: t = 0 #remove neg zero condition 
    13041307            ticks.append( (t, format % (t,)) ) 
    13051308            t = t + grid