commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r5634 - in grc/branches/jblum_work/src: . Graphics


From: jblum
Subject: [Commit-gnuradio] r5634 - in grc/branches/jblum_work/src: . Graphics
Date: Sun, 3 Jun 2007 08:14:57 -0600 (MDT)

Author: jblum
Date: 2007-06-03 08:14:56 -0600 (Sun, 03 Jun 2007)
New Revision: 5634

Modified:
   grc/branches/jblum_work/src/ActionHandler.py
   grc/branches/jblum_work/src/Actions.py
   grc/branches/jblum_work/src/DataType.py
   grc/branches/jblum_work/src/Graphics/Bars.py
   grc/branches/jblum_work/src/Graphics/Dialogs.py
   grc/branches/jblum_work/src/Graphics/__init__.py
   grc/branches/jblum_work/src/MathExprParser.py
Log:
created help display for math expressions, added a data type for raw 
expressions, added intelligent casting to functions

Modified: grc/branches/jblum_work/src/ActionHandler.py
===================================================================
--- grc/branches/jblum_work/src/ActionHandler.py        2007-06-03 05:23:38 UTC 
(rev 5633)
+++ grc/branches/jblum_work/src/ActionHandler.py        2007-06-03 14:14:56 UTC 
(rev 5634)
@@ -140,7 +140,7 @@
                        # enable a select few actions 
                        Graphics.enable_usrp_diagnostics()      #try to enable 
usrp diagnostics
                        for action in (APPLICATION_QUIT, FLOW_GRAPH_NEW, 
FLOW_GRAPH_OPEN, FLOW_GRAPH_SAVE_AS, 
-                                                                       
ABOUT_WINDOW_DISPLAY, COLORS_WINDOW_DISPLAY, HOTKEYS_WINDOW_DISPLAY,
+                                                                       
ABOUT_WINDOW_DISPLAY, COLORS_WINDOW_DISPLAY, HOTKEYS_WINDOW_DISPLAY, 
MATH_EXPR_WINDOW_DISPLAY,
                                                                        
FLOW_GRAPH_WINDOW_RESIZE, PREFS_WINDOW_DISPLAY, FLOW_GRAPH_SNAP_SHOT): 
                                get_action_from_name(action).set_sensitive(True)
                        if self.flow_graph_file_path == '':
@@ -233,6 +233,8 @@
                        Graphics.DataTypeColorsDialog()
                elif state == HOTKEYS_WINDOW_DISPLAY:
                        Graphics.HotKeysDialog()
+               elif state == MATH_EXPR_WINDOW_DISPLAY:
+                       Graphics.MathExprDialog()
                elif state == FLOW_GRAPH_WINDOW_RESIZE:
                        dimensions = 
Graphics.FlowGraphWindowSizeDialog(self.flow_graph).run()
                        if dimensions != None:

Modified: grc/branches/jblum_work/src/Actions.py
===================================================================
--- grc/branches/jblum_work/src/Actions.py      2007-06-03 05:23:38 UTC (rev 
5633)
+++ grc/branches/jblum_work/src/Actions.py      2007-06-03 14:14:56 UTC (rev 
5634)
@@ -73,6 +73,7 @@
 HOTKEYS_WINDOW_DISPLAY = 'hotkeys window display'
 USRP_DIAGNOSTICS_DISPLAY = 'usrp diagnostics display'
 PREFS_WINDOW_DISPLAY = 'prefs window display'
+MATH_EXPR_WINDOW_DISPLAY = 'expression window display'
 
 
######################################################################################################
 #      actions
@@ -96,6 +97,7 @@
        gtk.Action(ABOUT_WINDOW_DISPLAY, '_About', 'About this program', 
'gtk-about'),
        gtk.Action(COLORS_WINDOW_DISPLAY, '_Colors', 'Data Type Colors', 
'gtk-select-color'),
        gtk.Action(HOTKEYS_WINDOW_DISPLAY, '_HotKeys', 'Hot Keys', 'gtk-info'),
+       gtk.Action(MATH_EXPR_WINDOW_DISPLAY, '_Math Expressions', 'Mathematical 
Expressions', 'gtk-convert'),
        gtk.Action(FLOW_GRAPH_RUN, '_Run', 'Run the flow graph', 'gtk-execute'),
        gtk.Action(FLOW_GRAPH_STOP, '_Stop', 'Stop the flow graph', 'gtk-stop'),
        gtk.Action(FLOW_GRAPH_SNAP_SHOT, 'S_nap Shot', 'Take a snap shot image 
of the flow graph', 'gtk-print'),

Modified: grc/branches/jblum_work/src/DataType.py
===================================================================
--- grc/branches/jblum_work/src/DataType.py     2007-06-03 05:23:38 UTC (rev 
5633)
+++ grc/branches/jblum_work/src/DataType.py     2007-06-03 14:14:56 UTC (rev 
5634)
@@ -124,6 +124,17 @@
 
#############################################################################################
  
 #      Special Types
 
#############################################################################################
+class RawExpr(DataType):
+       ''' A raw mathematical expression.      '''
+       type = 'raw'
+       def __init__(self, data=''):
+               ''' Raw data type contructor. Default value is blank string.    
'''
+               DataType.__init__(self, data)
+       def parse(self):
+               ''' Return the raw data returned by the parser  '''
+               data = DataType.parse(self)
+               return MathExprParser.eval_expr(data)
+
 class String(DataType):
        ''' The string data type.       '''
        type = 'string'
@@ -314,11 +325,5 @@
        
 if __name__ == '__main__':
        print "put things here to test DataTypes"
-       dt = String('2fsg56', min=3, max=5)
-       print dt.is_valid()
-       dt = IntVector('2, 3,', min=3, max=5)
-       print dt.is_valid()
-       dt = Hex('0xfe', min=0, max=254)
-       print dt.is_valid()
        
        
\ No newline at end of file

Modified: grc/branches/jblum_work/src/Graphics/Bars.py
===================================================================
--- grc/branches/jblum_work/src/Graphics/Bars.py        2007-06-03 05:23:38 UTC 
(rev 5633)
+++ grc/branches/jblum_work/src/Graphics/Bars.py        2007-06-03 14:14:56 UTC 
(rev 5634)
@@ -76,7 +76,6 @@
                                                (gtk.Action('Options', 
'_Options', None, None), 
                                                        [
                                                                
FLOW_GRAPH_WINDOW_RESIZE,       
-                                                               
USRP_DIAGNOSTICS_DISPLAY,
                                                                
PREFS_WINDOW_DISPLAY,                                   
                                                         ]),
                                                (gtk.Action('Help', '_Help', 
None, None), 
@@ -84,6 +83,8 @@
                                                                
ABOUT_WINDOW_DISPLAY,
                                                                
COLORS_WINDOW_DISPLAY,
                                                                
HOTKEYS_WINDOW_DISPLAY,
+                                                               
MATH_EXPR_WINDOW_DISPLAY,
+                                                               
USRP_DIAGNOSTICS_DISPLAY,
                                                        ])
                                                                                
                
                                         ]

Modified: grc/branches/jblum_work/src/Graphics/Dialogs.py
===================================================================
--- grc/branches/jblum_work/src/Graphics/Dialogs.py     2007-06-03 05:23:38 UTC 
(rev 5633)
+++ grc/branches/jblum_work/src/Graphics/Dialogs.py     2007-06-03 14:14:56 UTC 
(rev 5634)
@@ -198,3 +198,82 @@
                        self.vbox.pack_start(label)
                self.run()
                self.destroy()          
+               
+######################################################################################################
                 
+class MathExprDialog(gtk.Dialog):
+       """ A dialog to test math expressions for the parser.   """
+       HELP_MSG = """\
+<span size="small">
+<b>Operators - Complex   <i>(complex arguments)</i></b> 
+       + - * / ^
+       
+<b>Trigonometric Functions   <i>(complex arguments, radians)</i></b> 
+       sin(z) cos(z) tan(z) asin(z) acos(z) atan(z) 
+       sinh(z) cosh(z) tanh(z) asinh(z) acosh(z) atanh(z)
+       
+<b>Misc Functions   <i>(complex arguments)</i></b> 
+       pow(b, p) sqrt(z)
+       abs(z*) mag(z*) real(z*) imag(z*) conj(z*) - z can be a vector
+       arg(z) - complex angle
+       log10(z) log(z, [b=e]) ln(z) exp(z) 
+
+<b>Misc Functions   <i>(floating point arguments)</i></b> 
+       floor(f) ceil(f) radians(deg) degrees(rad) mod(f1, f2) atan2(y, x) 
sgn(f)
+
+<b>Filter Taps Generators   <i>(floating point arguments)</i></b> 
+       low_pass(gain, samp_rate, cutoff_freq, width, [window=hamming], 
[beta=6.76])
+       high_pass(gain, samp_rate, cutoff_freq, width, [window=hamming], 
[beta=6.76])   
+       band_pass(gain, samp_rate, low_cutoff_freq, high_cutoff_freq, width, 
[window=hamming], [beta=6.76])
+       complex_band_pass(gain, samp_rate, low_cutoff_freq, high_cutoff_freq, 
width, [window=hamming], [beta=6.76])
+       band_reject(gain, samp_rate, low_cutoff_freq, high_cutoff_freq, width, 
[window=hamming], [beta=6.76])   
+       gaussian(gain, spb, bt, int ntaps)
+       hilbert(int ntaps, [window=rectangular], [beta=6.76])
+       root_raised_cosine(gain, samp_rate, symbol_rate, alpha, int ntaps) 
+       window(window, int ntaps, beta)
+       
+<b>Window Types for Filters</b>
+       hamming hann blackman rectangular kaiser
+       
+<b>Using Vectors</b>
+       () (num1,) (num2, num2, ...)
+       
+<b>Test Your Expressions Below:</b>
+</span>\
+"""
+       def __init__(self):
+               """     Create a new gtk Dialog with a close button, an extry 
box, and an output text box.      """             
+               gtk.Dialog.__init__(self, buttons=('gtk-close', 
gtk.RESPONSE_CLOSE))
+               #       Create the title and label      #
+               self.set_title('Mathematical Expressions')
+               label = gtk.Label()
+               label.set_markup(self.HELP_MSG)
+               label.show()
+               self.vbox.pack_start(label, False)              
+               self.set_size_request(600, 600)
+               # create the entry box and connect it to a new handler #
+               self.param = GraphicalParam('Expression', RawExpr(''))
+               self.input_obj = self.param.get_input_object()
+               self.input_obj.entry.connect("changed", self.handle_changed)
+               self.vbox.pack_start(self.input_obj, False)             
+               #       create a text box for parser output     #
+               self.text_box = TextDisplay()
+               self.text_box.set_text('')                      
+               # add the scrolled window for the text box #
+               scrolled_window = gtk.ScrolledWindow()
+               scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, 
gtk.POLICY_AUTOMATIC)
+               scrolled_window.add_with_viewport(self.text_box)
+               scrolled_window.show()          
+               self.vbox.pack_start(scrolled_window, True)     
+               self.handle_changed()   #initial display
+               self.run()
+               self.destroy()
+               
+       def handle_changed(self, widget=None):
+               ''' Handle changed in the param's entry box.
+                       Call the default change handler and then update the 
text box.   '''
+               self.param.handle_changed()
+               if self.param.get_data_type().is_valid():
+                       text = str(self.param.get_data_type().parse())
+               else: text = self.param.get_data_type().msg
+               self.text_box.set_text(text)    
+               
\ No newline at end of file

Modified: grc/branches/jblum_work/src/Graphics/__init__.py
===================================================================
--- grc/branches/jblum_work/src/Graphics/__init__.py    2007-06-03 05:23:38 UTC 
(rev 5633)
+++ grc/branches/jblum_work/src/Graphics/__init__.py    2007-06-03 14:14:56 UTC 
(rev 5634)
@@ -24,5 +24,5 @@
 #      only import the modules that need external access #
 from MainWindow import MainWindow
 from FlowGraphFileDialog import FlowGraphFileDialog
-from Dialogs import 
PreferencesDialog,FlowGraphWindowSizeDialog,LooseChangesMessage,AboutDialog,DataTypeColorsDialog,HotKeysDialog
+from Dialogs import 
PreferencesDialog,FlowGraphWindowSizeDialog,LooseChangesMessage,AboutDialog,DataTypeColorsDialog,HotKeysDialog,MathExprDialog
 from USRPDiagnostics import USRPDiagnosticsDialog,enable_usrp_diagnostics

Modified: grc/branches/jblum_work/src/MathExprParser.py
===================================================================
--- grc/branches/jblum_work/src/MathExprParser.py       2007-06-03 05:23:38 UTC 
(rev 5633)
+++ grc/branches/jblum_work/src/MathExprParser.py       2007-06-03 14:14:56 UTC 
(rev 5634)
@@ -21,7 +21,8 @@
        Josh Blum
        This file provides:
        eval_expr for evaluating string expressions,
-       verify_complex, verify_float, verify_int for casting numbers. 
+       verify_complex, verify_float, verify_int for casting numbers,
+       and verify_number for picking the best representation.
 """
 
 import math,cmath
@@ -32,9 +33,9 @@
 _WHITESPACE = (' ', '\t', '')
 
 _CONSTANTS = { #constans must be lower case
-       'pi' : complex(cmath.pi),
-       'e' : complex(cmath.e),
-       'j' : complex(1j),
+       'pi' : cmath.pi,
+       'e' : cmath.e,
+       'j' : 1j,
        
        'hamming' : gr.firdes.WIN_HAMMING,      #filter windows
        'hann' : gr.firdes.WIN_HANN,
@@ -44,11 +45,11 @@
 }
        
 #########################################################
-##     Complex mathematical functions 
+##     Number parsers
 #########################################################
 
 def verify_complex(num):
-       ''' Verify that the number is indeed a number.
+       ''' Verify that the number is a complex number.
                Raise an exception if number cannot be cast to a complex.
                Return the value as a complex.  '''
        try: c_num = complex(num)       #ensure that the num can be complex
@@ -72,20 +73,36 @@
        if f_num - int(f_num) != 0: raise ValueError('Expected an integer but 
found "%s".'%(f_num,))
        return int(f_num)
        
+def verify_number(num):
+       ''' Try to cast the number into its most primative form.
+               In this order: int, float, or complex. 
+               Raise an exception if num is not a number.
+               Return a number of type listed above. '''
+       try: return verify_int(num)     #try int
+       except:
+               try: return verify_float(num)   #try float
+               except: return verify_complex(num)      #complex or fail
+
+#########################################################
+##     Complex mathematical functions 
+#########################################################
+       
 def _complex_abs_v(*args):
        ''' Compute the abs of a complex number or vector.      '''
        sum = 0
        for arg in args: 
                if _is_list(arg): sum = sum + _complex_abs_v(*arg)
-               else: sum = sum + complex(arg).real*complex(arg).real + 
complex(arg).imag*complex(arg).imag
-       return complex(sum**0.5)
+               else: sum = sum + \
+                       verify_complex(arg).real*verify_complex(arg).real + \
+                       verify_complex(arg).imag*verify_complex(arg).imag
+       return verify_number(cmath.sqrt(sum))                   
 
 def _complex_real_v(*args):
        ''' Get the real part of a number or vector.    '''
        result = list()
        for arg in args: 
                if _is_list(arg): result.append(_complex_real_v(*arg))
-               else: result.append(complex(complex(arg).real))
+               else: result.append(verify_number(verify_complex(arg).real))
        return result
 
 def _complex_imag_v(*args):
@@ -93,7 +110,7 @@
        result = list()
        for arg in args:  
                if _is_list(arg): result.append(_complex_imag_v(*arg))
-               else: result.append(complex(complex(arg).imag))
+               else: result.append(verify_number(verify_complex(arg).imag))
        return result
 
 def _complex_conj_v(*args):
@@ -101,12 +118,12 @@
        result = list()
        for arg in args:  
                if _is_list(arg): result.append(_complex_conj_v(*arg))
-               else: result.append(complex(complex(arg).conjugate()))
+               else: 
result.append(verify_number(verify_complex(arg).conjugate()))
        return result
 
 def _complex_arg(arg):
        ''' Get the angle of the complex number (radians).      '''
-       return complex(math.atan2(complex(arg).imag, complex(arg).real))
+       return verify_number(math.atan2(verify_complex(arg).imag, 
verify_complex(arg).real))
 
 def _handle_filter(filter, *filter_args):
        ''' Pass the filter arguments to the filter function. 
@@ -120,8 +137,8 @@
                gr.firdes.band_reject : ((5, 6, 7), (0, 1, 2, 3, 4, 6), ()),
                gr.firdes.complex_band_pass : ((5, 6, 7), (0, 1, 2, 3, 4, 6), 
()),
                
-               gr.firdes.high_pass : ((4, 5, 6), (0, 1, 2, 3, 4, 6), ()),
-               gr.firdes.low_pass : ((4, 5, 6), (0, 1, 2, 3, 4, 6), ()),
+               gr.firdes.high_pass : ((4, 5, 6), (0, 1, 2, 3, 5), ()),
+               gr.firdes.low_pass : ((4, 5, 6), (0, 1, 2, 3, 5), ()),
                
                gr.firdes.gaussian : ((4,), (0, 1, 2), (3,)),
                gr.firdes.hilbert : ((1, 2, 3), (2,), (0,)),
@@ -134,13 +151,11 @@
        for i,arg in enumerate(filter_args):
                if i in floats: filter_args[i] = verify_float(arg)
                if i in ints: filter_args[i] = verify_int(arg)  
-       taps = list(filter(*filter_args))
-       # convert all taps to complex #
-       for i,tap in enumerate(taps): taps[i] = complex(tap)
+       taps = list(filter(*filter_args))       #the taps must be a list
        return taps 
 
 _FUNCTIONS = {
-       'pow' : lambda b, p: b**p,
+       'pow' : lambda b, p: verify_number(b**p),       #complex power
        'sqrt' : cmath.sqrt,
 
        'abs' : _complex_abs_v,
@@ -150,26 +165,26 @@
        'conj' : _complex_conj_v,
        'arg' : _complex_arg,
        
-       'sin' : cmath.sin,      
-       'cos' : cmath.cos,
-       'tan' : cmath.tan,
+       'sin' : lambda z: verify_number(cmath.sin(z)),  
+       'cos' : lambda z: verify_number(cmath.cos(z)),
+       'tan' : lambda z: verify_number(cmath.tan(z)),
        
-       'asin' : cmath.asin,
-       'acos' : cmath.acos,
-       'atan' : cmath.atan,
+       'asin' : lambda z: verify_number(cmath.asin(z)),
+       'acos' : lambda z: verify_number(cmath.acos(z)),
+       'atan' : lambda z: verify_number(cmath.atan(z)),
        
-       'sinh' : cmath.sinh,    #hyperbolics
-       'cosh' : cmath.cosh,
-       'tanh' : cmath.tanh,
+       'sinh' : lambda z: verify_number(cmath.sinh(z)),        #hyperbolics
+       'cosh' : lambda z: verify_number(cmath.cosh(z)),
+       'tanh' : lambda z: verify_number(cmath.tanh(z)),
        
-       'asinh' : cmath.asinh,
-       'acosh' : cmath.acosh,
-       'atanh' : cmath.atanh,
+       'asinh' : lambda z: verify_number(cmath.asinh(z)),
+       'acosh' : lambda z: verify_number(cmath.acosh(z)),
+       'atanh' : lambda z: verify_number(cmath.atanh(z)),
        
-       'log10' : cmath.log10,
-       'log' : cmath.log,      #optional 2nd argument as base
+       'log10' : lambda z: verify_number(cmath.log10(z)),
+       'log' : lambda *z: verify_number(cmath.log(*z)),        #optional 2nd 
argument as base
        'ln' : lambda z: cmath.log(z), #only allow natural log
-       'exp' : cmath.exp,      
+       'exp' : lambda z: verify_number(cmath.exp(z)),  
        
        'band_pass' : lambda *args: _handle_filter(gr.firdes.band_pass, *args), 
#taps generators
        'band_reject' : lambda *args: _handle_filter(gr.firdes.band_reject, 
*args),
@@ -181,11 +196,13 @@
        'root_raised_cosine' : lambda *args: 
_handle_filter(gr.firdes.root_raised_cosine, *args),
        'window' : lambda *args: _handle_filter(gr.firdes.window, *args),
        
-       'floor' : lambda f: complex(math.floor(verify_float(f))),
-       'ceil' : lambda f: complex(math.ceil(verify_float(f))),
-       'radians' : lambda f: complex(math.radians(verify_float(f))),
-       'degrees' : lambda f: complex(math.degrees(verify_float(f))),
-       'fmod' : lambda f1, f2: complex(math.fmod(verify_float(f1), 
verify_float(f2))),
+       'floor' : lambda f: math.floor(verify_float(f)),
+       'ceil' : lambda f: math.ceil(verify_float(f)),
+       'radians' : lambda f: math.radians(verify_float(f)),
+       'degrees' : lambda f: math.degrees(verify_float(f)),
+       'mod' : lambda f1, f2: math.fmod(verify_float(f1), verify_float(f2)),
+       'atan2' : lambda y, x: math.atan2(verify_float(y), verify_float(x)),
+       'sgn' : lambda f: abs(f)/f
 }
 
 #########################################################
@@ -199,7 +216,7 @@
 def _is_constant(symbol): return symbol in _CONSTANTS.keys()
 
 def _is_number(symbol):        
-       try: complex(symbol)
+       try: verify_number(symbol)
        except: return False
        return True
        
@@ -262,18 +279,18 @@
        if not arg1_is_list and not arg2_is_list and \
                _is_number(arg1) and _is_number(arg2):  #non vector operations
                if op == '^-':
-                       return arg1**(-1*arg2)
+                       return verify_number(arg1**(-1*arg2))
                elif op == '^':
-                       return arg1**arg2
+                       return verify_number(arg1**arg2)
                elif op == '*':
-                       return arg1 * arg2
+                       return verify_number(arg1 * arg2)
                elif op == '/':
-                       try: return arg1 / arg2
+                       try: return verify_number(arg1 / arg2)
                        except ZeroDivisionError: raise 
ZeroDivisionError('Cannot divide "%s" by 0.'%(arg1,))
                elif op == '+':
-                       return arg1 + arg2
+                       return verify_number(arg1 + arg2)
                elif op == '-':
-                       return arg1 - arg2
+                       return verify_number(arg1 - arg2)
        raise ArithmeticError('Operation of "%s" cannot be performed on "%s", 
"%s".'%(op, arg1, arg2))  
        
 #########################################################
@@ -348,12 +365,12 @@
                Make comma separated values into lists (represent vectors).
                Return the final value of the expression.       '''
        for i,element in enumerate(nested_elements):    
-               # simplify the nested lists     #
+               # simplify the nested lists #
                if _is_list(element): nested_elements[i] = 
_simplify_nested_elements(element)
                # substitute in values for constants #
                elif _is_constant(element): nested_elements[i] = 
_CONSTANTS[element]
                # substitute in values for numbers #
-               elif _is_number(element): nested_elements[i] = complex(element) 
        
+               elif _is_number(element): nested_elements[i] = 
verify_number(element)                   
        # handle functions #
        for function in _FUNCTIONS.keys():
                while function in nested_elements:





reply via email to

[Prev in Thread] Current Thread [Next in Thread]