Changeset 8986

Show
Ignore:
Timestamp:
07/23/08 17:32:23
Author:
jblum
Message:

variable graph resolution

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • grc/trunk/notes/todo.txt

    r8985 r8986  
    1313-hotkeys in action descriptions 
    1414-log slider gui control 
    15 -variable resolution graph structure 
    1615-recursive/nested categories 
     16 
     17############ Maybe: #################### 
    1718-icons for certain blocks, + for add 
    1819-zoom in/out 
    19 -hide io type
     20-hide io type param
    2021 
    2122############ Problems: #################### 
    2223-catch error on open non-existant files 
    23 -variables dependent on variables that change 
    24 -flow graph, try mouse DRAG_MOTION? 
    2524 
    2625############ Suggestions: #################### 
  • grc/trunk/src/grc_gnuradio/Generator.py

    r8956 r8986  
    2626import stat 
    2727from Cheetah.Template import Template 
     28import expr_utils 
    2829 
    2930##The default binary to execute python files. 
     
    7778                @return a string of python code 
    7879                """ 
    79                 #load the namespace 
    8080                imports = self._flow_graph.get_imports() 
    8181                variables = self._flow_graph.get_variables() 
     82                #list of blocks not including variables and imports 
    8283                blocks = sorted(self._flow_graph.get_blocks(), lambda x, y: cmp(x.get_id(), y.get_id())) 
    8384                blocks = filter(lambda b: b not in (imports + variables) and b.get_enabled(), blocks) 
     85                #list of callbacks 
     86                callbacks = sum([block.get_callbacks() for block in self._flow_graph.get_blocks()], []) 
     87                #list of variable names 
     88                var_ids = [var.get_id() for var in variables] 
     89                #map var id to the expression (prepend self.) 
     90                var_id2expr = dict( 
     91                        [(var.get_id(), expr_utils.expr_prepend(var.get_make().split('\n')[0], var_ids, 'self.')) 
     92                        for var in variables] 
     93                ) 
     94                #create graph structure for variables 
     95                variable_graph = expr_utils.get_graph(var_id2expr) 
     96                #map var id to direct dependents 
     97                #for each var id, make a list of all 2nd order edges 
     98                #use all edges of that id that are not also 2nd order edges 
     99                #meaning: list variables the ONLY depend directly on this variable 
     100                #and not variables that also depend indirectly on this variable 
     101                var_id2deps = dict( 
     102                        [(var_id, filter(lambda e: e not in sum([list(variable_graph.get_edges(edge)) 
     103                                for edge in variable_graph.get_edges(var_id)], []), variable_graph.get_edges(var_id) 
     104                                ) 
     105                        ) 
     106                        for var_id in var_ids] 
     107                ) 
     108                #map var id to callbacks 
     109                var_id2cbs = dict( 
     110                        [(var_id, filter(lambda c: var_id in expr_utils.expr_split(c), callbacks)) 
     111                        for var_id in var_ids] 
     112                ) 
     113                #load the namespace 
    84114                namespace = { 
    85115                        'imports': imports, 
     
    88118                        'blocks': blocks, 
    89119                        'connections': self._flow_graph.get_connections(), 
    90                         'callbacks': sum([block.get_callbacks() for block in self._flow_graph.get_blocks()], []), 
    91120                        'gui_type': self._flow_graph.get_option('generate_options'), 
     121                        'var_id2expr': var_id2expr, 
     122                        'var_id2deps': var_id2deps, 
     123                        'var_id2cbs': var_id2cbs, 
    92124                } 
    93125                #build the template 
  • grc/trunk/src/grc_gnuradio/Param.py

    r8985 r8986  
    214214                #add self. to variables 
    215215                if self.get_parent().self_flag: 
    216                         code_splits = expr_utils.expr_split(code) 
    217216                        var_ids = [var.get_id() for var in self.get_parent().get_parent().get_variables()] 
    218                         for i, cs in enumerate(code_splits): 
    219                                 if cs in var_ids: code_splits[i] = "self.%s"%cs 
    220                         code = ''.join(code_splits) 
     217                        code = expr_utils.expr_prepend(code, var_ids, 'self.') 
    221218                return code 
    222219 
  • grc/trunk/src/grc_gnuradio/blocks/options.xml

    r8939 r8986  
    7171The window size (width, height) must be between (300, 300) and (2048, 2048). 
    7272 
    73 The generate options controls the type of code generated (wx-graphical or non-graphical). \ 
     73The generate options controls the type of code generated. \ 
    7474Non-graphical flow graphs should avoid using graphical sinks or graphical variable controls. 
     75 
     76The id of this block determines the name of the generated file and the name of the class. \ 
     77For example, an id of my_block will generate the file my_block.py and class my_block(gr.... 
    7578        </doc> 
    7679</block> 
  • grc/trunk/src/grc_gnuradio/data/flow_graph.tmpl

    r8910 r8986  
    88##@param blocks the signal blocks 
    99##@param connections the connections 
    10 ##@param callbacks the block callback strings 
    1110##@param gui_type the type of gui (wx gui or no gui) 
     11##@param var_id2expr variable id map to expression 
     12##@param var_id2deps variable id map to direct dependencies 
     13##@param var_id2cbs variable id map to callback strings 
    1214######################################################## 
    1315#import time 
     
    146148######################################################## 
    147149##Create Callbacks 
    148 ##      Determine block callbacks that depend on the variable. 
    149 ##      Write a set method for this variable that calls the callbacks. 
     150##      Write a set method for this variable that calls the callbacks 
     151##      and sets the direct variable dependencies. 
    150152######################################################## 
    151153#for $var in $variables 
    152154        #set $id = $var.get_id() 
    153         #set $var_callbacks = filter(lambda c: id in ''.join(c.split('(')[1:]), $callbacks) 
    154155        def set_$(id)(self, $id): 
    155156                self.$id = $id 
    156         #for $callback in $var_callbacks 
     157        #for $dep in $var_id2deps[$id] 
     158                self.set_$(dep)($var_id2expr[$dep]) 
     159        #end for 
     160        #for $callback in $var_id2cbs[$id] 
    157161                self.$callback 
    158162        #end for 
  • grc/trunk/src/grc_gnuradio/expr_utils.py

    r8885 r8986  
    2424VAR_CHARS = string.letters + string.digits + '_' 
    2525 
     26class graph(object): 
     27        """! 
     28        Simple graph structure held in a dictionary. 
     29        """ 
     30 
     31        def __init__(self): self._graph = dict() 
     32 
     33        def __str__(self): return str(self._graph) 
     34 
     35        def add_node(self, node_key): 
     36                if self._graph.has_key(node_key): return 
     37                self._graph[node_key] = set() 
     38 
     39        def remove_node(self, node_key): 
     40                if not self._graph.has_key(node_key): return 
     41                for edges in self._graph.values(): 
     42                        if node_key in edges: edges.remove(node_key) 
     43                self._graph.pop(node_key) 
     44 
     45        def add_edge(self, src_node_key, dest_node_key): 
     46                self._graph[src_node_key].add(dest_node_key) 
     47 
     48        def remove_edge(self, src_node_key, dest_node_key): 
     49                self._graph[src_node_key].remove(dest_node_key) 
     50 
     51        def get_nodes(self): return self._graph.keys() 
     52 
     53        def get_edges(self, node_key): return self._graph[node_key] 
     54 
    2655def expr_split(expr): 
    2756        """! 
     
    4170                elif char in ("'", '"'): 
    4271                        toks.append(tok) 
    43                         tok = char  
     72                        tok = char 
    4473                        quote = char 
    4574                else: 
     
    4978        toks.append(tok) 
    5079        return filter(lambda t: t, toks) 
     80 
     81def expr_prepend(expr, vars, prepend): 
     82        """! 
     83        Search for vars in the expression and add the prepend. 
     84        @param expr an expression string 
     85        @param vars a list of variable names 
     86        @param prepend the prepend string 
     87        @return a new expression with the prepend 
     88        """ 
     89        expr_splits = expr_split(expr) 
     90        for i, es in enumerate(expr_splits): 
     91                if es in vars: expr_splits[i] = prepend + es 
     92        return ''.join(expr_splits) 
    5193 
    5294def get_variable_dependencies(expr, vars): 
     
    60102        return set(filter(lambda v: v in expr_toks, vars)) 
    61103 
     104def get_graph(exprs): 
     105        """! 
     106        Get a graph representing the variable dependencies 
     107        @param exprs a mapping of variable name to expression 
     108        @return a graph of variable deps 
     109        """ 
     110        vars = exprs.keys() 
     111        #get dependencies for each expression, load into graph 
     112        var_graph = graph() 
     113        for var in vars: var_graph.add_node(var) 
     114        for var, expr in exprs.iteritems(): 
     115                for dep in get_variable_dependencies(expr, vars): 
     116                        var_graph.add_edge(dep, var) 
     117        return var_graph 
     118 
    62119def sort_variables(exprs): 
    63120        """! 
     
    67124        @throws AssertionError circular dependencies 
    68125        """ 
    69         vars = exprs.keys() 
    70         #get dependencies for each expression 
    71         vars_deps = dict([(var, get_variable_dependencies(expr, vars)) for var, expr in exprs.iteritems()]) 
     126        var_graph = get_graph(exprs) 
    72127        sorted_vars = list() 
    73128        #determine dependency order 
    74         while vars_deps
    75                 #get a list of vars with no dependencies 
    76                 indep_vars = set(filter(lambda v: not vars_deps[v], vars_deps.keys())) 
     129        while var_graph.get_nodes()
     130                #get a list of nodes with no edges 
     131                indep_vars = filter(lambda var: not var_graph.get_edges(var), var_graph.get_nodes()) 
    77132                assert indep_vars 
    78                 #remove inpep vars from dict 
    79                 for var in indep_vars: vars_deps.pop(var) 
    80133                #add the indep vars to the end of the list 
    81134                sorted_vars.extend(sorted(indep_vars)) 
    82                 #remove deps from other vars involving indep_vars 
    83                 for var in vars_deps.keys(): vars_deps[var] -= indep_vars 
    84         return sorted_vars 
     135                #remove each edge-less node from the graph 
     136                for var in indep_vars: var_graph.remove_node(var) 
     137        return reversed(sorted_vars) 
    85138 
     139if __name__ == '__main__': 
     140        for i in sort_variables({'x':'1', 'y':'x+1', 'a':'x+y', 'b':'y+1', 'c':'a+b+x+y'}): print i