summaryrefslogtreecommitdiff
path: root/gr-wxgui/src/python/plotter/common.py
diff options
context:
space:
mode:
Diffstat (limited to 'gr-wxgui/src/python/plotter/common.py')
-rw-r--r--gr-wxgui/src/python/plotter/common.py133
1 files changed, 133 insertions, 0 deletions
diff --git a/gr-wxgui/src/python/plotter/common.py b/gr-wxgui/src/python/plotter/common.py
new file mode 100644
index 000000000..88215e039
--- /dev/null
+++ b/gr-wxgui/src/python/plotter/common.py
@@ -0,0 +1,133 @@
+#
+# Copyright 2009 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import threading
+import time
+import math
+import wx
+
+##################################################
+# Number formatting
+##################################################
+def get_exp(num):
+ """
+ Get the exponent of the number in base 10.
+ @param num the floating point number
+ @return the exponent as an integer
+ """
+ if num == 0: return 0
+ return int(math.floor(math.log10(abs(num))))
+
+def get_si_components(num):
+ """
+ Get the SI units for the number.
+ Extract the coeff and exponent of the number.
+ The exponent will be a multiple of 3.
+ @param num the floating point number
+ @return the tuple coeff, exp, prefix
+ """
+ num = float(num)
+ exp = get_exp(num)
+ exp -= exp%3
+ exp = min(max(exp, -24), 24) #bounds on SI table below
+ prefix = {
+ 24: 'Y', 21: 'Z',
+ 18: 'E', 15: 'P',
+ 12: 'T', 9: 'G',
+ 6: 'M', 3: 'k',
+ 0: '',
+ -3: 'm', -6: 'u',
+ -9: 'n', -12: 'p',
+ -15: 'f', -18: 'a',
+ -21: 'z', -24: 'y',
+ }[exp]
+ coeff = num/10**exp
+ return coeff, exp, prefix
+
+def sci_format(num):
+ """
+ Format a floating point number into scientific notation.
+ @param num the number to format
+ @return a label string
+ """
+ coeff, exp, prefix = get_si_components(num)
+ if -3 <= exp < 3: return '%g'%num
+ return '%.3ge%d'%(coeff, exp)
+
+def eng_format(num, units=''):
+ """
+ Format a floating point number into engineering notation.
+ @param num the number to format
+ @param units the units to append
+ @return a label string
+ """
+ coeff, exp, prefix = get_si_components(num)
+ if -3 <= exp < 3: return '%g'%num
+ return '%g%s%s%s'%(coeff, units and ' ' or '', prefix, units)
+
+##################################################
+# Interface with thread safe lock/unlock
+##################################################
+class mutex(object):
+ _lock = threading.Lock()
+ def lock(self): self._lock.acquire()
+ def unlock(self): self._lock.release()
+
+##################################################
+# Periodic update thread for point label
+##################################################
+class point_label_thread(threading.Thread, mutex):
+
+ def __init__(self, plotter):
+ self._plotter = plotter
+ self._coor_queue = list()
+ #bind plotter mouse events
+ self._plotter.Bind(wx.EVT_MOTION, lambda evt: self.enqueue(evt.GetPosition()))
+ self._plotter.Bind(wx.EVT_LEAVE_WINDOW, lambda evt: self.enqueue(None))
+ self._plotter.Bind(wx.EVT_RIGHT_DOWN, lambda evt: plotter.enable_point_label(not plotter.enable_point_label()))
+ self._plotter.Bind(wx.EVT_LEFT_DOWN, lambda evt: plotter.call_freq_callback(evt.GetPosition()))
+ #start the thread
+ threading.Thread.__init__(self)
+ self.start()
+
+ def enqueue(self, coor):
+ self.lock()
+ self._coor_queue.append(coor)
+ self.unlock()
+
+ def run(self):
+ last_ts = time.time()
+ last_coor = coor = None
+ try:
+ while True:
+ time.sleep(1.0/30.0)
+ self.lock()
+ #get most recent coor change
+ if self._coor_queue:
+ coor = self._coor_queue[-1]
+ self._coor_queue = list()
+ self.unlock()
+ #update if coor change, or enough time expired
+ if last_coor != coor or (time.time() - last_ts) > (1.0/2.0):
+ self._plotter.set_point_label_coordinate(coor)
+ last_coor = coor
+ last_ts = time.time()
+ except wx.PyDeadObjectError: pass