2 # Copyright 2008 Free Software Foundation, Inc.
4 # This file is part of GNU Radio
6 # GNU Radio is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3, or (at your option)
11 # GNU Radio is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with GNU Radio; see the file COPYING. If not, write to
18 # the Free Software Foundation, Inc., 51 Franklin Street,
19 # Boston, MA 02110-1301, USA.
24 def bind_to_visible_event(win, callback):
26 Bind a callback to a window when its visibility changes.
27 Specifically, callback when the window changes visibility
28 when a notebook tab event in one of the parents occurs.
29 @param win the wx window
30 @param callback a 1 param function
32 #is the window visible in the hierarchy
33 def is_wx_window_visible(my_win):
35 parent = my_win.GetParent()
36 if not parent: return True #reached the top of the hierarchy
37 #if we are hidden, then finish, otherwise keep traversing up
38 if isinstance(parent, wx.Notebook) and parent.GetCurrentPage() != my_win: return False
40 #call the callback, the arg is shown or not
41 def callback_factory(my_win, my_callback):
43 def the_callback(*args):
44 visible = is_wx_window_visible(my_win)
45 if cache[0] != visible: my_callback(visible)
48 handler = callback_factory(win, callback)
49 #bind the handler to all the parent notebooks
51 if isinstance(win, wx.Notebook):
52 win.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, handler)
53 if not win.GetParent():
54 win.Bind(wx.EVT_ACTIVATE, handler)
57 #A macro to apply an index to a key
58 index_key = lambda key, i: "%s_%d"%(key, i+1)
60 def _register_access_method(destination, controller, key):
62 Helper function for register access methods.
63 This helper creates distinct set and get methods for each key
64 and adds them to the destination object.
66 def set(value): controller[key] = value
67 setattr(destination, 'set_'+key, set)
68 def get(): return controller[key]
69 setattr(destination, 'get_'+key, get)
71 def register_access_methods(destination, controller):
73 Register setter and getter functions in the destination object for all keys in the controller.
74 @param destination the object to get new setter and getter methods
75 @param controller the pubsub controller
77 for key in controller.keys(): _register_access_method(destination, controller, key)
79 ##################################################
80 # Input Watcher Thread
81 ##################################################
82 from gnuradio import gru
84 class input_watcher(gru.msgq_runner):
86 Input watcher thread runs forever.
87 Read messages from the message queue.
88 Forward messages to the message handler.
90 def __init__ (self, msgq, controller, msg_key, arg1_key='', arg2_key=''):
91 self._controller = controller
92 self._msg_key = msg_key
93 self._arg1_key = arg1_key
94 self._arg2_key = arg2_key
95 gru.msgq_runner.__init__(self, msgq, self.handle_msg)
97 def handle_msg(self, msg):
98 if self._arg1_key: self._controller[self._arg1_key] = msg.arg1()
99 if self._arg2_key: self._controller[self._arg2_key] = msg.arg2()
100 self._controller[self._msg_key] = msg.to_string()
103 ##################################################
105 ##################################################
111 Get the exponent of the number in base 10.
112 @param num the floating point number
113 @return the exponent as an integer
115 if num == 0: return 0
116 return int(math.floor(math.log10(abs(num))))
118 def get_clean_num(num):
120 Get the closest clean number match to num with bases 1, 2, 5.
121 @param num the number
122 @return the closest number
124 if num == 0: return 0
125 sign = num > 0 and 1 or -1
127 nums = numpy.array((1, 2, 5, 10))*(10**exp)
128 return sign*nums[numpy.argmin(numpy.abs(nums - abs(num)))]
130 def get_clean_incr(num):
132 Get the next higher clean number with bases 1, 2, 5.
133 @param num the number
134 @return the next higher number
136 num = get_clean_num(num)
138 coeff = int(round(num/10**exp))
148 def get_clean_decr(num):
150 Get the next lower clean number with bases 1, 2, 5.
151 @param num the number
152 @return the next lower number
154 num = get_clean_num(num)
156 coeff = int(round(num/10**exp))
166 def get_min_max(samples):
168 Get the minimum and maximum bounds for an array of samples.
169 @param samples the array of real values
170 @return a tuple of min, max
173 mean = numpy.average(samples)
174 rms = numpy.max([scale_factor*((numpy.sum((samples-mean)**2)/len(samples))**.5), .1])
177 return min_val, max_val
179 def get_min_max_fft(fft_samps):
181 Get the minimum and maximum bounds for an array of fft samples.
182 @param samples the array of real values
183 @return a tuple of min, max
185 #get the peak level (max of the samples)
186 peak_level = numpy.max(fft_samps)
187 #separate noise samples
188 noise_samps = numpy.sort(fft_samps)[:len(fft_samps)/2]
190 noise_floor = numpy.average(noise_samps)
191 #get the noise deviation
192 noise_dev = numpy.std(noise_samps)
193 #determine the maximum and minimum levels
194 max_level = peak_level
195 min_level = noise_floor - abs(2*noise_dev)
196 return min_level, max_level