Merged r9481:9518 on jblum/grc_reorganize into trunk. Reorganized grc source under...
[debian/gnuradio] / grc / src / platforms / python / 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
20 from utils import expr_utils
21 from .. base.FlowGraph import FlowGraph as _FlowGraph
22 from Block import Block
23 from Connection import Connection
24
25 def get_variable_code(variable):
26         """
27         Get the code representation for a variable.
28         Normally this is the value parameter.
29         For the variable chooser, use the index and choices.
30         Avoid using the to_code method of the variables,
31         as this forces evaluation before the variables are evaluated.
32         @param variable the variable block
33         @return the code string
34         """
35         if variable.get_key() == 'variable_chooser':
36                 choices = variable.get_param('choices').get_value()
37                 value_index = variable.get_param('value_index').get_value()
38                 return "(%s)[%s]"%(choices, value_index)
39         return variable.get_param('value').get_value()
40
41 class FlowGraph(_FlowGraph):
42
43         def _get_io_signature(self, pad_key):
44                 """
45                 Get an io signature for this flow graph.
46                 The pad key determines the directionality of the io signature.
47                 @param pad_key a string of pad_source or pad_sink
48                 @return a dict with: type, nports, vlen, size
49                 """
50                 pads = filter(lambda b: b.get_key() == pad_key, self.get_enabled_blocks())
51                 if not pads: return {
52                         'nports': '0',
53                         'type': '',
54                         'vlen': '0',
55                         'size': '0',
56                 }
57                 pad = pads[0] #take only the first, user should not have more than 1
58                 #load io signature
59                 return {
60                         'nports': str(pad.get_param('nports').evaluate()),
61                         'type': str(pad.get_param('type').evaluate()),
62                         'vlen': str(pad.get_param('vlen').evaluate()),
63                         'size': pad.get_param('type').get_opt('size'),
64                 }
65
66         def get_input_signature(self):
67                 """
68                 Get the io signature for the input side of this flow graph.
69                 The io signature with be "0", "0" if no pad source is present.
70                 @return a string tuple of type, num_ports, port_size
71                 """
72                 return self._get_io_signature('pad_source')
73
74         def get_output_signature(self):
75                 """
76                 Get the io signature for the output side of this flow graph.
77                 The io signature with be "0", "0" if no pad sink is present.
78                 @return a string tuple of type, num_ports, port_size
79                 """
80                 return self._get_io_signature('pad_sink')
81
82         def get_imports(self):
83                 """
84                 Get a set of all import statments in this flow graph namespace.
85                 @return a set of import statements
86                 """
87                 imports = sum([block.get_imports() for block in self.get_enabled_blocks()], [])
88                 imports = sorted(set(imports))
89                 return imports
90
91         def get_variables(self):
92                 """
93                 Get a list of all variables in this flow graph namespace.
94                 Exclude paramterized variables.
95                 @return a sorted list of variable blocks in order of dependency (indep -> dep)
96                 """
97                 variables = filter(lambda b: b.get_key() in (
98                         'variable', 'variable_slider', 'variable_chooser', 'variable_text_box'
99                 ), self.get_enabled_blocks())
100                 #map var id to variable block
101                 id2var = dict([(var.get_id(), var) for var in variables])
102                 #map var id to variable code
103                 #variable code is a concatenation of all param code (without the id param)
104                 id2expr = dict([(var.get_id(), get_variable_code(var)) for var in variables])
105                 #sort according to dependency
106                 sorted_ids = expr_utils.sort_variables(id2expr)
107                 #create list of sorted variable blocks
108                 variables = [id2var[id] for id in sorted_ids]
109                 return variables
110
111         def get_parameters(self):
112                 """
113                 Get a list of all paramterized variables in this flow graph namespace.
114                 @return a list of paramterized variables
115                 """
116                 parameters = filter(lambda b: b.get_key() == 'parameter', self.get_enabled_blocks())
117                 return parameters
118
119         def evaluate(self, expr):
120                 """
121                 Evaluate the expression.
122                 @param expr the string expression
123                 @throw Exception bad expression
124                 @return the evaluated data
125                 """
126                 if self.is_flagged():
127                         self.deflag()
128                         #reload namespace
129                         n = dict()
130                         #load imports
131                         for imp in self.get_imports():
132                                 try: exec imp in n
133                                 except: pass
134                         #load parameters
135                         np = dict()
136                         for parameter in self.get_parameters():
137                                 try:
138                                         e = eval(parameter.get_param('value').to_code(), n, n)
139                                         np[parameter.get_id()] = e
140                                 except: pass
141                         n.update(np) #merge param namespace
142                         #load variables
143                         for variable in self.get_variables():
144                                 try:
145                                         e = eval(get_variable_code(variable), n, n)
146                                         n[variable.get_id()] = e
147                                 except: pass
148                         #make namespace public
149                         self.n = n
150                 #evaluate
151                 e = eval(expr, self.n, self.n)
152                 return e