Merged changeset r9285:9377 from jblum/grc into trunk, with distcheck fixes
[debian/gnuradio] / grc / src / grc_gnuradio / FlowGraph.py
1 """
2 Copyright 2008 Free Software Foundation, Inc.
3 This file is part of GNU Radio
4
5 GNU Radio Companion is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 GNU Radio Companion is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18 """
19 ##@package grc_gnuradio.FlowGraph
20 #Primative flow graph.
21 #@author Josh Blum
22
23 from utils import expr_utils
24 from grc.elements.FlowGraph import FlowGraph as _FlowGraph
25 from Block import Block
26 from Connection import Connection
27
28 class FlowGraph(_FlowGraph):
29
30         def _get_io_signature(self, pad_key):
31                 """!
32                 Get an io signature for this flow graph.
33                 The pad key determines the directionality of the io signature.
34                 @param pad_key a string of pad_source or pad_sink
35                 @return a dict with: type, nports, vlen, size
36                 """
37                 pads = filter(lambda b: b.get_key() == pad_key, self.get_enabled_blocks())
38                 if not pads: return {
39                         'nports': '0',
40                         'type': '',
41                         'vlen': '0',
42                         'size': '0',
43                 }
44                 pad = pads[0] #take only the first, user should not have more than 1
45                 #load io signature
46                 return {
47                         'nports': str(pad.get_param('nports').evaluate()),
48                         'type': str(pad.get_param('type').evaluate()),
49                         'vlen': str(pad.get_param('vlen').evaluate()),
50                         'size': pad.get_param('type').get_opt('size'),
51                 }
52
53         def get_input_signature(self):
54                 """!
55                 Get the io signature for the input side of this flow graph.
56                 The io signature with be "0", "0" if no pad source is present.
57                 @return a string tuple of type, num_ports, port_size
58                 """
59                 return self._get_io_signature('pad_source')
60
61         def get_output_signature(self):
62                 """!
63                 Get the io signature for the output side of this flow graph.
64                 The io signature with be "0", "0" if no pad sink is present.
65                 @return a string tuple of type, num_ports, port_size
66                 """
67                 return self._get_io_signature('pad_sink')
68
69         def get_imports(self):
70                 """!
71                 Get a set of all import statments in this flow graph namespace.
72                 @return a set of import statements
73                 """
74                 imports = sum([block.get_imports() for block in self.get_enabled_blocks()], [])
75                 imports = sorted(set(imports))
76                 return imports
77
78         def get_variables(self):
79                 """!
80                 Get a list of all variables in this flow graph namespace.
81                 Exclude paramterized variables.
82                 @return a sorted list of variable blocks in order of dependency (indep -> dep)
83                 """
84                 variables = filter(lambda b: b.get_key() in (
85                         'variable', 'variable_slider', 'variable_chooser', 'variable_text_box'
86                 ), self.get_enabled_blocks())
87                 #map var id to variable block
88                 id2var = dict([(var.get_id(), var) for var in variables])
89                 #map var id to variable code
90                 #variable code is a concatenation of all param code (without the id param)
91                 id2expr = dict([(var.get_id(), 
92                         ' '.join([param.to_code() for param in filter(lambda p: p.get_key() != 'id',var.get_params())])
93                 ) for var in variables])
94                 #sort according to dependency
95                 sorted_ids = expr_utils.sort_variables(id2expr)
96                 #create list of sorted variable blocks
97                 variables = [id2var[id] for id in sorted_ids]
98                 return variables
99
100         def get_parameters(self):
101                 """!
102                 Get a list of all paramterized variables in this flow graph namespace.
103                 @return a list of paramterized variables
104                 """
105                 parameters = filter(lambda b: b.get_key() == 'parameter', self.get_enabled_blocks())
106                 return parameters
107
108         def evaluate(self, expr):
109                 """!
110                 Evaluate the expression.
111                 @param expr the string expression
112                 @throw Exception bad expression
113                 @return the evaluated data
114                 """
115                 if self.is_flagged():
116                         self.deflag()
117                         #reload namespace
118                         n = dict()
119                         #load imports
120                         for imp in self.get_imports():
121                                 try: exec imp in n
122                                 except: pass
123                         #load parameters
124                         np = dict()
125                         for parameter in self.get_parameters():
126                                 try:
127                                         e = eval(parameter.get_param('value').to_code(), n, n)
128                                         np[parameter.get_id()] = e
129                                 except: pass
130                         n.update(np) #merge param namespace
131                         #load variables
132                         for variable in self.get_variables():
133                                 try:
134                                         if variable.get_key() == 'variable_chooser':
135                                                 choices = variable.get_param('choices').to_code()
136                                                 value_index = variable.get_param('value_index').to_code()
137                                                 e = eval("%s[%s]"%(choices, value_index), n, n)
138                                         else:
139                                                 e = eval(variable.get_param('value').to_code(), n, n)
140                                         n[variable.get_id()] = e
141                                 except: pass
142                         #make namespace public
143                         self.n = n
144                 #evaluate
145                 e = eval(expr, self.n, self.n)
146                 return e
147