diff options
Diffstat (limited to 'gr-wxgui/src/python')
-rw-r--r-- | gr-wxgui/src/python/common.py | 25 | ||||
-rw-r--r-- | gr-wxgui/src/python/fft_window.py | 20 | ||||
-rw-r--r-- | gr-wxgui/src/python/forms/converters.py | 9 | ||||
-rw-r--r-- | gr-wxgui/src/python/forms/forms.py | 11 | ||||
-rw-r--r-- | gr-wxgui/src/python/plotter/waterfall_plotter.py | 2 | ||||
-rw-r--r-- | gr-wxgui/src/python/scopesink_gl.py | 2 | ||||
-rw-r--r-- | gr-wxgui/src/python/waterfall_window.py | 12 |
7 files changed, 48 insertions, 33 deletions
diff --git a/gr-wxgui/src/python/common.py b/gr-wxgui/src/python/common.py index d555a1f05..9c97ce1ec 100644 --- a/gr-wxgui/src/python/common.py +++ b/gr-wxgui/src/python/common.py @@ -137,6 +137,25 @@ def get_min_max(samples): scale_factor = 3 mean = numpy.average(samples) rms = numpy.max([scale_factor*((numpy.sum((samples-mean)**2)/len(samples))**.5), .1]) - min = mean - rms - max = mean + rms - return min, max + min_val = mean - rms + max_val = mean + rms + return min_val, max_val + +def get_min_max_fft(fft_samps): + """ + Get the minimum and maximum bounds for an array of fft samples. + @param samples the array of real values + @return a tuple of min, max + """ + #get the peak level (max of the samples) + peak_level = numpy.max(fft_samps) + #separate noise samples + noise_samps = numpy.sort(fft_samps)[:len(fft_samps)/2] + #get the noise floor + noise_floor = numpy.average(noise_samps) + #get the noise deviation + noise_dev = numpy.std(noise_samps) + #determine the maximum and minimum levels + max_level = peak_level + min_level = noise_floor - abs(2*noise_dev) + return min_level, max_level diff --git a/gr-wxgui/src/python/fft_window.py b/gr-wxgui/src/python/fft_window.py index 0529e6a5d..e025c28dd 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 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -156,9 +156,9 @@ 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])) ################################################## # FFT window with plotter and control panel @@ -254,17 +254,11 @@ class fft_window(wx.Panel, pubsub.pubsub): 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 diff --git a/gr-wxgui/src/python/forms/converters.py b/gr-wxgui/src/python/forms/converters.py index 9f757aa84..db14d2752 100644 --- a/gr-wxgui/src/python/forms/converters.py +++ b/gr-wxgui/src/python/forms/converters.py @@ -72,12 +72,14 @@ class bool_converter(abstract_converter): self._true = true self._false = false def external_to_internal(self, v): - return bool(v) + if v == self._true: return True + if v == self._false: return False + raise Exception, 'Value "%s" is not a possible option.'%v def internal_to_external(self, v): if v: return self._true else: return self._false def help(self): - return "Value must be cast-able to type bool." + return "Value must be in (%s, %s)."%(self._true, self._false) class eval_converter(abstract_converter): """ @@ -134,8 +136,7 @@ class slider_converter(abstract_converter): self._scaler = float(maximum - minimum)/num_steps self._cast = cast def external_to_internal(self, v): - #slider's internal representation is an integer - return int(round((v - self._offset)/self._scaler)) + return (v - self._offset)/self._scaler def internal_to_external(self, v): return self._cast(v*self._scaler + self._offset) def help(self): diff --git a/gr-wxgui/src/python/forms/forms.py b/gr-wxgui/src/python/forms/forms.py index c69315b03..8dc58367d 100644 --- a/gr-wxgui/src/python/forms/forms.py +++ b/gr-wxgui/src/python/forms/forms.py @@ -176,7 +176,7 @@ class _slider_base(_form_base): self._add_widget(self._slider, label, flag=wx.EXPAND) def _handle(self, event): self[INT_KEY] = self._slider.GetValue() - def _update(self, value): self._slider.SetValue(value) + def _update(self, value): self._slider.SetValue(int(round(value))) ######################################################################## # Static Text Form @@ -224,11 +224,18 @@ class text_box(_form_base): def __init__(self, label='', width=-1, converter=converters.eval_converter(), **kwargs): _form_base.__init__(self, converter=converter, **kwargs) self._text_box = wx.TextCtrl(self._parent, size=wx.Size(width, -1), style=wx.TE_PROCESS_ENTER) + self._default_bg_colour = self._text_box.GetBackgroundColour() self._text_box.Bind(wx.EVT_TEXT_ENTER, self._handle) + self._text_box.Bind(wx.EVT_TEXT, self._update_color) self._add_widget(self._text_box, label) + def _update_color(self, *args): + if self._text_box.GetValue() == self[INT_KEY]: + self._text_box.SetBackgroundColour(self._default_bg_colour) + else: self._text_box.SetBackgroundColour('#EEDDDD') + def _handle(self, event): self[INT_KEY] = self._text_box.GetValue() - def _update(self, value): self._text_box.SetValue(value) + def _update(self, value): self._text_box.SetValue(value); self._update_color() ######################################################################## # Slider Form diff --git a/gr-wxgui/src/python/plotter/waterfall_plotter.py b/gr-wxgui/src/python/plotter/waterfall_plotter.py index 2e0669961..d32b0ca0a 100644 --- a/gr-wxgui/src/python/plotter/waterfall_plotter.py +++ b/gr-wxgui/src/python/plotter/waterfall_plotter.py @@ -209,7 +209,7 @@ class waterfall_plotter(grid_plotter_base): self._pointer = 0 if self._num_lines and self._fft_size: GL.glBindTexture(GL.GL_TEXTURE_2D, self._waterfall_texture) - data = numpy.zeros(self._num_lines*self._fft_size*4, numpy.uint8).tostring() + data = numpy.zeros(self._num_lines*ceil_log2(self._fft_size)*4, numpy.uint8).tostring() GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, ceil_log2(self._fft_size), self._num_lines, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, data) self._resize_texture_flag = False diff --git a/gr-wxgui/src/python/scopesink_gl.py b/gr-wxgui/src/python/scopesink_gl.py index b4ae0f339..a5e3ca3ce 100644 --- a/gr-wxgui/src/python/scopesink_gl.py +++ b/gr-wxgui/src/python/scopesink_gl.py @@ -50,7 +50,7 @@ class ac_couple_block(gr.hier_block2): self.connect(self, lpf, mute, (sub, 1)) #subscribe controller.subscribe(ac_couple_key, lambda x: mute.set_mute(not x)) - controller.subscribe(sample_rate_key, lambda x: lpf.set_taps(2.0/x)) + controller.subscribe(sample_rate_key, lambda x: lpf.set_taps(0.05)) #initialize controller[ac_couple_key] = ac_couple controller[sample_rate_key] = controller[sample_rate_key] diff --git a/gr-wxgui/src/python/waterfall_window.py b/gr-wxgui/src/python/waterfall_window.py index c00992e14..28e67a830 100644 --- a/gr-wxgui/src/python/waterfall_window.py +++ b/gr-wxgui/src/python/waterfall_window.py @@ -237,16 +237,10 @@ class waterfall_window(wx.Panel, pubsub.pubsub): Does not affect the current data in the waterfall. """ 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 + min_level, max_level = common.get_min_max_fft(self.samples) #set the range and level - self[REF_LEVEL_KEY] = peak_level - self[DYNAMIC_RANGE_KEY] = peak_level - noise_floor + self[REF_LEVEL_KEY] = max_level + self[DYNAMIC_RANGE_KEY] = max_level - min_level def handle_msg(self, msg): """ |