X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=gr-wxgui%2Fsrc%2Fpython%2Ffft_window.py;h=f4f485f4b06030f67522ddb65162bebbc8b568c2;hb=2057623cf8f9e9738954b146d3a23577110f7906;hp=0529e6a5d6d77eb2070fbda7468fa2c1cecb1fb8;hpb=60633c60dda8bd0ac8c7b5fde72eac62aa0f9490;p=debian%2Fgnuradio diff --git a/gr-wxgui/src/python/fft_window.py b/gr-wxgui/src/python/fft_window.py index 0529e6a5..f4f485f4 100644 --- a/gr-wxgui/src/python/fft_window.py +++ b/gr-wxgui/src/python/fft_window.py @@ -1,5 +1,5 @@ # -# Copyright 2008 Free Software Foundation, Inc. +# Copyright 2008, 2009, 2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -37,6 +37,7 @@ import forms ################################################## SLIDER_STEPS = 100 AVG_ALPHA_MIN_EXP, AVG_ALPHA_MAX_EXP = -3, 0 +PERSIST_ALPHA_MIN_EXP, PERSIST_ALPHA_MAX_EXP = -2, 0 DEFAULT_WIN_SIZE = (600, 300) DEFAULT_FRAME_RATE = gr.prefs().get_long('wxgui', 'fft_rate', 30) DB_DIV_MIN, DB_DIV_MAX = 1, 20 @@ -64,6 +65,8 @@ class control_panel(wx.Panel): """ self.parent = parent wx.Panel.__init__(self, parent, style=wx.SUNKEN_BORDER) + parent[SHOW_CONTROL_PANEL_KEY] = True + parent.subscribe(SHOW_CONTROL_PANEL_KEY, self.Show) control_box = wx.BoxSizer(wx.VERTICAL) control_box.AddStretchSpacer() #checkboxes for average and peak hold @@ -95,7 +98,38 @@ class control_panel(wx.Panel): for widget in (avg_alpha_text, avg_alpha_slider): parent.subscribe(AVERAGE_KEY, widget.Enable) widget.Enable(parent[AVERAGE_KEY]) + parent.subscribe(AVERAGE_KEY, widget.ShowItems) + #allways show initially, so room is reserved for them + widget.ShowItems(True) # (parent[AVERAGE_KEY]) + + parent.subscribe(AVERAGE_KEY, self._update_layout) + + forms.check_box( + sizer=options_box, parent=self, label='Persistence', + ps=parent, key=USE_PERSISTENCE_KEY, + ) + #static text and slider for persist alpha + persist_alpha_text = forms.static_text( + sizer=options_box, parent=self, label='Persist Alpha', + converter=forms.float_converter(lambda x: '%.4f'%x), + ps=parent, key=PERSIST_ALPHA_KEY, width=50, + ) + persist_alpha_slider = forms.log_slider( + sizer=options_box, parent=self, + min_exp=PERSIST_ALPHA_MIN_EXP, + max_exp=PERSIST_ALPHA_MAX_EXP, + num_steps=SLIDER_STEPS, + ps=parent, key=PERSIST_ALPHA_KEY, + ) + for widget in (persist_alpha_text, persist_alpha_slider): + parent.subscribe(USE_PERSISTENCE_KEY, widget.Enable) + widget.Enable(parent[USE_PERSISTENCE_KEY]) + parent.subscribe(USE_PERSISTENCE_KEY, widget.ShowItems) + #allways show initially, so room is reserved for them + widget.ShowItems(True) # (parent[USE_PERSISTENCE_KEY]) + parent.subscribe(USE_PERSISTENCE_KEY, self._update_layout) + #trace menu for trace in TRACES: trace_box = wx.BoxSizer(wx.HORIZONTAL) @@ -142,6 +176,7 @@ class control_panel(wx.Panel): ) #set sizer self.SetSizerAndFit(control_box) + #mouse wheel event def on_mouse_wheel(event): if event.GetWheelRotation() < 0: self._on_incr_ref_level(event) @@ -156,9 +191,17 @@ class control_panel(wx.Panel): def _on_decr_ref_level(self, event): self.parent[REF_LEVEL_KEY] = self.parent[REF_LEVEL_KEY] - self.parent[Y_PER_DIV_KEY] def _on_incr_db_div(self, event): - self.parent[Y_PER_DIV_KEY] = min(DB_DIV_MAX, self.parent[Y_PER_DIV_KEY]*2) + self.parent[Y_PER_DIV_KEY] = min(DB_DIV_MAX, common.get_clean_incr(self.parent[Y_PER_DIV_KEY])) def _on_decr_db_div(self, event): - self.parent[Y_PER_DIV_KEY] = max(DB_DIV_MIN, self.parent[Y_PER_DIV_KEY]/2) + self.parent[Y_PER_DIV_KEY] = max(DB_DIV_MIN, common.get_clean_decr(self.parent[Y_PER_DIV_KEY])) + ################################################## + # subscriber handlers + ################################################## + def _update_layout(self,key): + # Just ignore the key value we get + # we only need to now that the visability or size of something has changed + self.parent.Layout() + #self.parent.Fit() ################################################## # FFT window with plotter and control panel @@ -181,7 +224,10 @@ class fft_window(wx.Panel, pubsub.pubsub): avg_alpha_key, peak_hold, msg_key, + use_persistence, + persist_alpha, ): + pubsub.pubsub.__init__(self) #setup self.samples = EMPTY_TRACE @@ -202,6 +248,8 @@ class fft_window(wx.Panel, pubsub.pubsub): self[REF_LEVEL_KEY] = ref_level self[BASEBAND_FREQ_KEY] = baseband_freq self[RUNNING_KEY] = True + self[USE_PERSISTENCE_KEY] = use_persistence + self[PERSIST_ALPHA_KEY] = persist_alpha for trace in TRACES: #a function that returns a function #so the function wont use local trace @@ -230,6 +278,8 @@ class fft_window(wx.Panel, pubsub.pubsub): self.plotter.enable_legend(True) self.plotter.enable_point_label(True) self.plotter.enable_grid_lines(True) + self.plotter.set_use_persistence(use_persistence) + self.plotter.set_persist_alpha(persist_alpha) #setup the box with plot and controls self.control_panel = control_panel(self) main_box = wx.BoxSizer(wx.HORIZONTAL) @@ -245,26 +295,23 @@ class fft_window(wx.Panel, pubsub.pubsub): Y_PER_DIV_KEY, X_DIVS_KEY, Y_DIVS_KEY, REF_LEVEL_KEY, ): self.subscribe(key, self.update_grid) + self.subscribe(USE_PERSISTENCE_KEY, self.plotter.set_use_persistence) + self.subscribe(PERSIST_ALPHA_KEY, self.plotter.set_persist_alpha) #initial update self.update_grid() + def autoscale(self, *args): """ Autoscale the fft plot to the last frame. Set the dynamic range and reference level. """ if not len(self.samples): return - #get the peak level (max of the samples) - peak_level = numpy.max(self.samples) - #get the noise floor (averge the smallest samples) - noise_floor = numpy.average(numpy.sort(self.samples)[:len(self.samples)/4]) - #padding - noise_floor -= abs(noise_floor)*.5 - peak_level += abs(peak_level)*.1 - #set the reference level to a multiple of y divs - self[REF_LEVEL_KEY] = self[Y_DIVS_KEY]*math.ceil(peak_level/self[Y_DIVS_KEY]) + min_level, max_level = common.get_min_max_fft(self.samples) #set the range to a clean number of the dynamic range - self[Y_PER_DIV_KEY] = common.get_clean_num((peak_level - noise_floor)/self[Y_DIVS_KEY]) + self[Y_PER_DIV_KEY] = common.get_clean_num(1+(max_level - min_level)/self[Y_DIVS_KEY]) + #set the reference level to a multiple of y per div + self[REF_LEVEL_KEY] = self[Y_PER_DIV_KEY]*round(.5+max_level/self[Y_PER_DIV_KEY]) def _reset_peak_vals(self, *args): self.peak_vals = EMPTY_TRACE