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