2 # Copyright 2009 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.
27 ##################################################
29 ##################################################
32 Get the exponent of the number in base 10.
33 @param num the floating point number
34 @return the exponent as an integer
37 return int(math.floor(math.log10(abs(num))))
39 def get_si_components(num):
41 Get the SI units for the number.
42 Extract the coeff and exponent of the number.
43 The exponent will be a multiple of 3.
44 @param num the floating point number
45 @return the tuple coeff, exp, prefix
50 exp = min(max(exp, -24), 24) #bounds on SI table below
63 return coeff, exp, prefix
67 Format a floating point number into scientific notation.
68 @param num the number to format
69 @return a label string
71 coeff, exp, prefix = get_si_components(num)
72 if -3 <= exp < 3: return '%g'%num
73 return '%.3ge%d'%(coeff, exp)
75 def eng_format(num, units=''):
77 Format a floating point number into engineering notation.
78 @param num the number to format
79 @param units the units to append
80 @return a label string
82 coeff, exp, prefix = get_si_components(num)
83 if -3 <= exp < 3: return '%g'%num
84 return '%g%s%s%s'%(coeff, units and ' ' or '', prefix, units)
86 ##################################################
87 # Interface with thread safe lock/unlock
88 ##################################################
90 _lock = threading.Lock()
91 def lock(self): self._lock.acquire()
92 def unlock(self): self._lock.release()
94 ##################################################
95 # Periodic update thread for point label
96 ##################################################
97 class point_label_thread(threading.Thread, mutex):
99 def __init__(self, plotter):
100 self._plotter = plotter
101 self._coor_queue = list()
102 #bind plotter mouse events
103 self._plotter.Bind(wx.EVT_MOTION, lambda evt: self.enqueue(evt.GetPosition()))
104 self._plotter.Bind(wx.EVT_LEAVE_WINDOW, lambda evt: self.enqueue(None))
106 threading.Thread.__init__(self)
109 def enqueue(self, coor):
111 self._coor_queue.append(coor)
115 last_ts = time.time()
116 last_coor = coor = None
121 #get most recent coor change
123 coor = self._coor_queue[-1]
124 self._coor_queue = list()
126 #update if coor change, or enough time expired
127 if last_coor != coor or (time.time() - last_ts) > (1.0/2.0):
128 self._plotter.set_point_label_coordinate(coor)
130 last_ts = time.time()
131 except wx.PyDeadObjectError: pass