def __inner_init_default__(self): if self.__initialized: return sourceEdt = _c.determineEdt(self.dataref) if not sourceEdt.isIntermediate(): _essentia.VectorInput.__init__(self, self.dataref, str(sourceEdt)) self.__initialized = True return if sourceEdt == _c.Edt.LIST_EMPTY or \ sourceEdt == _c.Edt.LIST_INTEGER or \ sourceEdt == _c.Edt.LIST_REAL or \ sourceEdt == _c.Edt.LIST_MIXED: self.dataref = _c.convertData(self.dataref, _c.Edt.VECTOR_REAL) _essentia.VectorInput.__init__(self, self.dataref, _c.Edt.VECTOR_REAL) self.__initialized = True return if sourceEdt == _c.Edt.LIST_LIST_REAL or sourceEdt == _c.Edt.LIST_LIST_INTEGER: self.dataref = _c.convertData(self.dataref, _c.Edt.MATRIX_REAL) _essentia.VectorInput.__init__(self, self.dataref, _c.Edt.MATRIX_REAL) self.__initialized = True return raise TypeError('Unable to initialize VectorInput because it is '+\ 'being connected to None or a Pool, and the '+\ 'VectorInput\'s data consists of an unsupported Pool '+\ 'type: '+str(sourceEdt))
def compute(self, *args): inputNames = self.inputNames() if len(args) != len(inputNames): raise ValueError(name+'.compute requires '+str(len(inputNames))+' argument(s), '+str(len(args))+' given') # we have to make some exceptions for YamlOutput and PoolAggregator # because they expect cpp Pools if name in ('YamlOutput', 'PoolAggregator', 'SvmClassifier', 'PCA', 'GaiaTransform'): args = (args[0].cppPool,) # verify that all types match and do any necessary conversions result = [] convertedArgs = [] for i in range(len(inputNames)): goalType = _c.Edt(self.inputType(inputNames[i])) try: convertedData = _c.convertData(args[i], goalType) except TypeError: raise TypeError('Error cannot convert argument %s to %s' \ %(str(_c.determineEdt(args[i])), str(goalType))) convertedArgs.append(convertedData) results = self.__compute__(*convertedArgs) # we have to make an exceptional case for YamlInput, because we need # to wrap the Pool that it outputs w/ our python Pool from common.py if name in ('YamlInput', 'PoolAggregator', 'SvmClassifier', 'PCA', 'GaiaTransform', 'Extractor'): return _c.Pool(results) else: return results
def configure(self, **kwargs): # verify that all types match and do any necessary conversions for name, val in kwargs.iteritems(): goalType = self.paramType(name) try: convertedVal = _c.convertData(val, goalType) except TypeError: # as e: # catching exception as sth is only #available as from python 2.6 raise TypeError('Error cannot convert parameter %s to %s'\ %(str(_c.determineEdt(val)),str(goalType))) #\''+name+'\' parameter: '+str(e)) kwargs[name] = convertedVal self.__configure__(**kwargs)
def compute(self, *args): inputNames = self.inputNames() if len(args) != len(inputNames): raise ValueError(name+'.compute requires '+str(len(inputNames))+' argument(s), '+str(len(args))+' given') # we have to make some exceptions for YamlOutput and PoolAggregator # because they expect cpp Pools if name in ('YamlOutput', 'PoolAggregator', 'SvmClassifier', 'PCA', 'GaiaTransform'): args = (args[0].cppPool,) # verify that all types match and do any necessary conversions result = [] convertedArgs = [] for i in range(len(inputNames)): arg = args[i] if type(args[i]).__module__ == 'numpy': if not args[i].flags['C_CONTIGUOUS']: arg = copy(args[i]) goalType = _c.Edt(self.inputType(inputNames[i])) try: convertedData = _c.convertData(arg, goalType) except TypeError: raise TypeError('Error cannot convert argument %s to %s' \ %(str(_c.determineEdt(arg)), str(goalType))) convertedArgs.append(convertedData) results = self.__compute__(*convertedArgs) # we have to make an exceptional case for YamlInput, because we need # to wrap the Pool that it outputs w/ our python Pool from common.py if name in ('YamlInput', 'PoolAggregator', 'SvmClassifier', 'PCA', 'GaiaTransform', 'Extractor'): return _c.Pool(results) # MusicExtractor and FreesoundExtractor output two pools if name in ('MusicExtractor', 'FreesoundExtractor'): return (_c.Pool(results[0]), _c.Pool(results[1])) # In the case of MetadataReader, the 7th output is also a Pool if name in ('MetadataReader'): return results[:7] + (_c.Pool(results[7]),) + results[8:] else: return results
def translate(composite_algo, output_filename, dot_graph=False): '''Takes in a class that is derived from essentia.streaming.CompositeBase and an output-filename and writes output-filename.h and output-filename.cpp versions of the given class.''' if not inspect.isclass(composite_algo): raise TypeError('"composite_algo" argument must be a class') if not streaming.CompositeBase in inspect.getmro(composite_algo): raise TypeError( '"composite_algo" argument must inherit from essentia.streaming.CompositeBase' ) param_names, _, _, default_values = inspect.getargspec( composite_algo.__init__) param_names.remove('self') # these marker objects are used to track where config params travel in the network marker_objs = {} if not default_values and param_names: # python vars have no type so we cannot know what type they are!! raise TypeError('"composite_algo" arguments must have default values') if param_names: for param_name, value in zip(param_names, default_values): marker_objs[param_name] = MarkerObject(value) ### Before we call their function we need to neuter all of the configure methods of each ### streaming algorithm so that our markers won't cause the configure method to vomit configure_log = {} def dummy_configure(self, **kwargs): lbl = 0 algo_name = self.name() + '_' + str(lbl) # increment lbl to generate a unique name for inner algo lowered_algo_names = [name.lower() for name in configure_log.keys()] while algo_name.lower() in lowered_algo_names: algo_name = algo_name[:algo_name.index('_') + 1] + str(lbl) lbl += 1 # algo_name is now unique configure_log[algo_name] = {} configure_log[algo_name]['instance'] = self configure_log[algo_name]['parameters'] = kwargs # We need to actually call the internal configure method because algorithms like silencerate # need to be configured so we can use its outputs. However we can't use our marker objects, # so we remove the marker objects that don't have a default value associated with them, and # for those that do have a default value, we use that value instead of the MarkerObject # itself kwargs_no_markers = dict(kwargs) for key, value in kwargs.iteritems(): if value in marker_objs.values(): if value.default_value == None: del kwargs_no_markers[key] else: kwargs_no_markers[key] = value.default_value self.real_configure(**kwargs_no_markers) # iterate over all streaming_algos streaming_algos = inspect.getmembers( streaming, lambda obj: inspect.isclass(obj) and \ _essentia.StreamingAlgorithm in inspect.getmro(obj) ) streaming_algos = [member[1] for member in streaming_algos] for algo in streaming_algos: algo.real_configure = algo.configure algo.configure = dummy_configure ### Now generate an instance of their composite algorithm ### algo_inst = composite_algo(**marker_objs) # overwrite the dummy configure with the real configure method, so # translate can be called several times in the same file for a different # compositebase without entering in an infinite loop for algo in streaming_algos: algo.configure = algo.real_configure ### Do some checking on their network ### for algo in [logitem['instance'] for logitem in configure_log.values()]: if isinstance(algo, streaming.VectorInput): raise TypeError( 'essentia.streaming.VectorInput algorithms are not allowed for translatable composite algorithms' ) if isinstance(algo, streaming.AudioLoader) or \ isinstance(algo, streaming.EasyLoader) or \ isinstance(algo, streaming.MonoLoader) or \ isinstance(algo, streaming.EqloudLoader): raise TypeError( 'No type of AudioLoader is allowed for translatable composite algorithms' ) if isinstance(algo, streaming.AudioWriter) or \ isinstance(algo, streaming.MonoWriter): raise TypeError( 'No type of AudioWriter is allowed for translatable composite algorithms' ) if isinstance(algo, streaming.FileOutput): raise TypeError( 'essentia.streaming.FileOutput algorithms are not allowed for translatable composite algorithms' ) def sort_by_key(configure_log): # sort algorithms and conf values: sitems = configure_log.items() sitems.sort() sorted_algos = [] sorted_params = [] for k, v in sitems: sorted_params.append(v) sorted_algos.append(k) return sorted_algos, sorted_params sorted_algos, sorted_params = sort_by_key(configure_log) ### generate .h code ### h_code = '''// Generated automatically by essentia::translate #ifndef STREAMING_''' + composite_algo.__name__.upper() + ''' #define STREAMING_''' + composite_algo.__name__.upper() + ''' #include "streamingalgorithmcomposite.h" class ''' + composite_algo.__name__ + ''' : public essentia::streaming::AlgorithmComposite { protected: ''' for algo_name in sorted_algos: h_code += ' essentia::streaming::Algorithm* _' + algo_name.lower( ) + ';\n' h_code += ''' public: ''' + composite_algo.__name__ + '''(); ~''' + composite_algo.__name__ + '''() { ''' for algo_name in sorted_algos: h_code += ' delete _' + algo_name.lower() + ';\n' h_code += ''' } void declareParameters() { ''' if param_names: for param_name, default_value in zip(param_names, default_values): h_code += ' declareParameter("' + param_name + '", "", "", ' if isinstance(default_value, basestring): h_code += '"' + default_value + '"' else: h_code += str(default_value) h_code += ');\n' h_code += ''' } void configure(); void createInnerNetwork(); void reset(); static const char* name; static const char* version; static const char* description; }; #endif ''' ### Generate .cpp code ### cpp_code = '''// Generated automatically by essentia::translate #include "''' + output_filename + '''.h" #include "algorithmfactory.h" #include "taskqueue.h" using namespace std; using namespace essentia; using namespace essentia::streaming; const char* ''' + composite_algo.__name__ + '''::name = "''' + composite_algo.__name__ + '''"; const char* ''' + composite_algo.__name__ + '''::version = "1.0"; const char* ''' + composite_algo.__name__ + '''::description = DOC("");\n\n''' ################################ # CONSTRUCTOR ################################ cpp_code += composite_algo.__name__ + '''::''' + composite_algo.__name__ + '''(): ''' for algo_name in sorted_algos: cpp_code += '_' + algo_name.lower() + '(0), ' cpp_code = cpp_code[:-2] + ''' { setName("''' + composite_algo.__name__ + '''"); declareParameters(); AlgorithmFactory& factory = AlgorithmFactory::instance();\n\n''' # create inner algorithms for algo_name in sorted_algos: cpp_code += ' _' + algo_name.lower( ) + ' = factory.create("' + algo_name[:algo_name.rindex('_')] + '");\n' cpp_code += '}\n\n' ################################ # INNER NETWORK ################################ # declaration of inputs and output and connecting the network should not be # done in the constructor, as there are algos like silencerate which # inputs/outputs depend on the configuration parameters. Hence, it is safer to # do it in the configure() function cpp_code += 'void ' + composite_algo.__name__ + '::createInnerNetwork() {\n' # declare inputs for input_alias, connector in algo_inst.inputs.iteritems(): input_owner_name = None input_name = None for algo_name, properties in zip( sorted_algos, sorted_params): #configure_log.iteritems(): if properties['instance'] == connector.input_algo: input_owner_name = algo_name input_name = connector.name break if not input_owner_name: raise RuntimeError('Could not determine owner of the \'' + input_alias + '\' input') cpp_code += ' declareInput(_' + input_owner_name.lower( ) + '->input("' + input_name + '"), "' + input_alias + '", "");\n' cpp_code += '\n' # declare outputs aliases, connectors = sort_by_key(algo_inst.outputs) for output_alias, connector in zip(aliases, connectors): output_owner_name = None output_name = None for algo_name, properties in zip( sorted_algos, sorted_params): #configure_log.iteritems(): if properties['instance'] == connector.output_algo: output_owner_name = algo_name output_name = connector.name break if not output_owner_name: raise RuntimeError('Could not determine owner of the \'' + output_alias + '\' output') cpp_code += ' declareOutput(_' + output_owner_name.lower( ) + '->output("' + output_name + '"), "' + output_alias + '", "");\n' cpp_code += '\n' # make connections for algo_name, properties in zip( sorted_algos, sorted_params): #configure_log.iteritems(): for left_connector, right_connectors in properties[ 'instance'].connections.iteritems(): for right_connector in right_connectors: if isinstance(right_connector, streaming._StreamConnector): cpp_code += ' connect( _'+\ inner_algo_name(left_connector.output_algo, configure_log).lower() + \ '->output("'+left_connector.name+'"), _' + \ inner_algo_name(right_connector.input_algo, configure_log).lower() + \ '->input("'+right_connector.name+'") );\n' elif isinstance(right_connector, types.NoneType): cpp_code += ' connect( _'+\ inner_algo_name(left_connector.output_algo, configure_log).lower() + \ '->output("'+left_connector.name+'"), NOWHERE );\n' cpp_code = cpp_code[:-1] cpp_code += ''' }\n\n''' ################################ # CONFIGURE ################################ cpp_code += 'void ' + composite_algo.__name__ + '::configure() {\n' # configure method # create local variable for every composite parameter for composite_param_name in param_names: param_edt = find_edt(composite_param_name, marker_objs[composite_param_name], configure_log) cpp_code += ' '+edt_cpp_code[param_edt]+' '+composite_param_name + \ ' = parameter("'+composite_param_name+'").to' + \ edt_parameter_code[param_edt]+'();\n' cpp_code += '\n' # configure inner algorithms for algo_name, properties in zip( sorted_algos, sorted_params): #configure_log.iteritems(): # skip if inner algorithm wasn't configured explicitly if not properties['parameters']: continue for param_name, value in properties['parameters'].iteritems(): type = common.determineEdt(value) if 'LIST' in str(type) or 'VECTOR' in str(type): if type in [common.Edt.VECTOR_STRING]: cpp_code += ' const char* ' + param_name + '[] = {' for s in value: cpp_code += '\"' + s + '\"' + ',' elif type in [common.Edt.VECTOR_REAL, common.Edt.LIST_REAL]: cpp_code += ' Real ' + param_name + '[] = {' for f in value: cpp_code += str(f) + ',' elif type in [common.Edt.VECTOR_INT, common.Edt.LIST_INT]: cpp_code += ' int' + param_name + '[] = {' for i in value: cpp_code += str(i) + ',' cpp_code = cpp_code[:-1] + '};\n' cpp_code += ' _' + algo_name.lower() + '->configure(' for param_name, value in properties['parameters'].iteritems(): if isinstance(value, MarkerObject): # figure out which composite param it is composite_param_name = None for marker_name, marker_obj in marker_objs.iteritems(): if marker_obj == value: composite_param_name = marker_name break if not composite_param_name: raise RuntimeError( 'Could not determine which composite parameter to use to configure inner algorithm \'' + algo_name + '\'s parameter \'' + param_name + '\'') cpp_code += '"' + param_name + '", ' + composite_param_name + ', ' else: type = common.determineEdt(value) if 'LIST' in str(type) or 'VECTOR' in str(type): if type in [common.Edt.VECTOR_STRING]: cpp_code += '"' + param_name + '", ' + 'arrayToVector<string>(' + param_name + ') ' elif type in [ common.Edt.VECTOR_REAL, common.Edt.LIST_REAL ]: cpp_code += '"' + param_name + '", ' + 'arrayToVector<Real>(' + param_name + ') ' elif type in [common.Edt.VECTOR_INT, common.Edt.LIST_INT]: cpp_code += '"' + param_name + '", ' + 'arrayToVector<int>(' + param_name + ') ' elif isinstance(value, basestring): cpp_code += '"' + param_name + '", "' + value + '", ' elif isinstance(value, bool): if value: cpp_code += '"' + param_name + '", true, ' else: cpp_code += '"' + param_name + '", false, ' else: cpp_code += '"' + param_name + '", ' + str(value) + ', ' cpp_code = cpp_code[:-2] + ');\n' cpp_code += ' createInnerNetwork();\n}\n\n' ################################ # RESET ################################ cpp_code += 'void ' + composite_algo.__name__ + '::reset() {\n' for algo_name in sorted_algos: cpp_code += ' _' + algo_name.lower() + '->reset();\n' cpp_code += '}\n\n' ################################ # DESTRUCTOR ################################ # see h_code. Each algo from the composite is deleted separately instead of # calling deleteNetwork # cpp_code += composite_algo.__name__+'''::~'''+composite_algo.__name__+'''() { # deleteNetwork(_''' + input_owner_name.lower() + '''); #}''' # cpp_code +='\n' # ################################ # end of cpp code ################################ if dot_graph: ### generate .dot code ### dot_code = 'digraph ' + output_filename + ' {\n' dot_code += ' rankdir=LR\n' # if instead of top-down left-right is prefered # general formatting options: dot_code += ' node [color=black, fontname=Verdana, weight=1, fontsize=8, shape=Mrecord]\n' dot_code += ' edge [color=black, style=solid, weight=1, arrowhead="dotnormal", arrowtail="dot", arrowsize=1, fontsize=6]\n' # for each input generate nodes for name in algo_inst.inputs.keys(): dot_code += ' ' + name + ' [label="' + name + '"];\n' dot_code += generate_dot_cluster(configure_log, composite_algo.__name__, algo_inst) # for each output generate nodes for name in algo_inst.outputs.keys(): dot_code += ' ' + name + ' [label="' + name + '"];\n' dot_code += '}' ### Write files ### f = open(output_filename + '.h', 'w') f.write(h_code) f.close() f = open(output_filename + '.cpp', 'w') f.write(cpp_code) f.close() if dot_graph: f = open(output_filename + '.dot', 'w') f.write(dot_code) f.close()
def translate(composite_algo, output_filename, dot_graph=False): '''Takes in a class that is derived from essentia.streaming.CompositeBase and an output-filename and writes output-filename.h and output-filename.cpp versions of the given class.''' if not inspect.isclass(composite_algo): raise TypeError('"composite_algo" argument must be a class') if not streaming.CompositeBase in inspect.getmro(composite_algo): raise TypeError('"composite_algo" argument must inherit from essentia.streaming.CompositeBase') param_names, _, _, default_values = inspect.getargspec(composite_algo.__init__) param_names.remove('self') # these marker objects are used to track where config params travel in the network marker_objs = {} if not default_values and param_names: # python vars have no type so we cannot know what type they are!! raise TypeError('"composite_algo" arguments must have default values') if param_names: for param_name, value in zip(param_names, default_values): marker_objs[param_name] = MarkerObject(value) ### Before we call their function we need to neuter all of the configure methods of each ### streaming algorithm so that our markers won't cause the configure method to vomit configure_log = {} def dummy_configure(self, **kwargs): lbl = 0 algo_name = self.name()+'_'+str(lbl) # increment lbl to generate a unique name for inner algo lowered_algo_names = [name.lower() for name in configure_log.keys()] while algo_name.lower() in lowered_algo_names: algo_name = algo_name[:algo_name.index('_')+1] + str(lbl) lbl +=1 # algo_name is now unique configure_log[algo_name] = {} configure_log[algo_name]['instance'] = self configure_log[algo_name]['parameters'] = kwargs # We need to actually call the internal configure method because algorithms like silencerate # need to be configured so we can use its outputs. However we can't use our marker objects, # so we remove the marker objects that don't have a default value associated with them, and # for those that do have a default value, we use that value instead of the MarkerObject # itself kwargs_no_markers = dict(kwargs) for key, value in kwargs.iteritems(): if value in marker_objs.values(): if value.default_value == None: del kwargs_no_markers[key] else: kwargs_no_markers[key] = value.default_value self.real_configure(**kwargs_no_markers) # iterate over all streaming_algos streaming_algos = inspect.getmembers( streaming, lambda obj: inspect.isclass(obj) and \ _essentia.StreamingAlgorithm in inspect.getmro(obj) ) streaming_algos = [member[1] for member in streaming_algos] for algo in streaming_algos: algo.real_configure = algo.configure algo.configure = dummy_configure ### Now generate an instance of their composite algorithm ### algo_inst = composite_algo(**marker_objs) # overwrite the dummy configure with the real configure method, so # translate can be called several times in the same file for a different # compositebase without entering in an infinite loop for algo in streaming_algos: algo.configure = algo.real_configure ### Do some checking on their network ### for algo in [ logitem['instance'] for logitem in configure_log.values() ]: if isinstance(algo, streaming.VectorInput): raise TypeError('essentia.streaming.VectorInput algorithms are not allowed for translatable composite algorithms') if isinstance(algo, streaming.AudioLoader) or \ isinstance(algo, streaming.EasyLoader) or \ isinstance(algo, streaming.MonoLoader) or \ isinstance(algo, streaming.EqloudLoader): raise TypeError('No type of AudioLoader is allowed for translatable composite algorithms') if isinstance(algo, streaming.AudioWriter) or \ isinstance(algo, streaming.MonoWriter): raise TypeError('No type of AudioWriter is allowed for translatable composite algorithms') if isinstance(algo, streaming.FileOutput): raise TypeError('essentia.streaming.FileOutput algorithms are not allowed for translatable composite algorithms') def sort_by_key(configure_log): # sort algorithms and conf values: sitems = configure_log.items() sitems.sort() sorted_algos = [] sorted_params= [] for k,v in sitems: sorted_params.append(v) sorted_algos.append(k) return sorted_algos, sorted_params sorted_algos, sorted_params = sort_by_key(configure_log) ### generate .h code ### h_code = '''// Generated automatically by essentia::translate #ifndef STREAMING_''' + composite_algo.__name__.upper() + ''' #define STREAMING_''' + composite_algo.__name__.upper()+ ''' #include "streamingalgorithmcomposite.h" class '''+composite_algo.__name__+''' : public essentia::streaming::AlgorithmComposite { protected: ''' for algo_name in sorted_algos: h_code += ' essentia::streaming::Algorithm* _'+algo_name.lower()+';\n' h_code += ''' public: '''+composite_algo.__name__+'''(); ~'''+composite_algo.__name__+'''() { ''' for algo_name in sorted_algos: h_code += ' delete _'+algo_name.lower()+';\n' h_code += ''' } void declareParameters() { ''' if param_names: for param_name, default_value in zip(param_names, default_values): h_code += ' declareParameter("'+param_name+'", "", "", ' if isinstance(default_value, basestring): h_code += '"'+default_value+'"' else: h_code += str(default_value) h_code += ');\n' h_code += ''' } void configure(); void createInnerNetwork(); void reset(); static const char* name; static const char* version; static const char* description; }; #endif ''' ### Generate .cpp code ### cpp_code = '''// Generated automatically by essentia::translate #include "'''+output_filename+'''.h" #include "algorithmfactory.h" #include "taskqueue.h" using namespace std; using namespace essentia; using namespace essentia::streaming; const char* '''+composite_algo.__name__+'''::name = "'''+composite_algo.__name__+'''"; const char* '''+composite_algo.__name__+'''::version = "1.0"; const char* '''+composite_algo.__name__+'''::description = DOC("");\n\n''' ################################ # CONSTRUCTOR ################################ cpp_code += composite_algo.__name__+'''::'''+composite_algo.__name__+'''(): ''' for algo_name in sorted_algos: cpp_code += '_' + algo_name.lower() + '(0), ' cpp_code = cpp_code[:-2] + ''' { setName("''' + composite_algo.__name__ + '''"); declareParameters(); AlgorithmFactory& factory = AlgorithmFactory::instance();\n\n''' # create inner algorithms for algo_name in sorted_algos: cpp_code += ' _'+algo_name.lower()+' = factory.create("'+algo_name[:algo_name.rindex('_')]+'");\n' cpp_code+='}\n\n' ################################ # INNER NETWORK ################################ # declaration of inputs and output and connecting the network should not be # done in the constructor, as there are algos like silencerate which # inputs/outputs depend on the configuration parameters. Hence, it is safer to # do it in the configure() function cpp_code += 'void ' + composite_algo.__name__ + '::createInnerNetwork() {\n' # declare inputs for input_alias, connector in algo_inst.inputs.iteritems(): input_owner_name = None input_name = None for algo_name, properties in zip(sorted_algos, sorted_params): #configure_log.iteritems(): if properties['instance'] == connector.input_algo: input_owner_name = algo_name input_name = connector.name break if not input_owner_name: raise RuntimeError('Could not determine owner of the \''+input_alias+'\' input') cpp_code += ' declareInput(_'+input_owner_name.lower()+'->input("'+input_name+'"), "'+input_alias+'", "");\n' cpp_code += '\n' # declare outputs aliases, connectors = sort_by_key(algo_inst.outputs) for output_alias, connector in zip(aliases, connectors): output_owner_name = None output_name = None for algo_name, properties in zip(sorted_algos, sorted_params): #configure_log.iteritems(): if properties['instance'] == connector.output_algo: output_owner_name = algo_name output_name = connector.name break if not output_owner_name: raise RuntimeError('Could not determine owner of the \''+output_alias+'\' output') cpp_code += ' declareOutput(_'+output_owner_name.lower()+'->output("'+output_name+'"), "'+output_alias+'", "");\n' cpp_code += '\n' # make connections for algo_name, properties in zip(sorted_algos, sorted_params): #configure_log.iteritems(): for left_connector, right_connectors in properties['instance'].connections.iteritems(): for right_connector in right_connectors: if isinstance(right_connector, streaming._StreamConnector): cpp_code += ' connect( _'+\ inner_algo_name(left_connector.output_algo, configure_log).lower() + \ '->output("'+left_connector.name+'"), _' + \ inner_algo_name(right_connector.input_algo, configure_log).lower() + \ '->input("'+right_connector.name+'") );\n' elif isinstance(right_connector, types.NoneType): cpp_code += ' connect( _'+\ inner_algo_name(left_connector.output_algo, configure_log).lower() + \ '->output("'+left_connector.name+'"), NOWHERE );\n' cpp_code = cpp_code[:-1] cpp_code += ''' }\n\n''' ################################ # CONFIGURE ################################ cpp_code += 'void '+composite_algo.__name__+'::configure() {\n' # configure method # create local variable for every composite parameter for composite_param_name in param_names: param_edt = find_edt(composite_param_name, marker_objs[composite_param_name], configure_log) cpp_code += ' '+edt_cpp_code[param_edt]+' '+composite_param_name + \ ' = parameter("'+composite_param_name+'").to' + \ edt_parameter_code[param_edt]+'();\n' cpp_code += '\n' # configure inner algorithms for algo_name, properties in zip(sorted_algos, sorted_params): #configure_log.iteritems(): # skip if inner algorithm wasn't configured explicitly if not properties['parameters']: continue for param_name, value in properties['parameters'].iteritems(): type = common.determineEdt(value) if 'LIST' in str(type) or 'VECTOR' in str(type): if type in [common.Edt.VECTOR_STRING]: cpp_code += ' const char* ' + param_name + '[] = {' for s in value: cpp_code += '\"' + s + '\"' + ',' elif type in[common.Edt.VECTOR_REAL, common.Edt.LIST_REAL]: cpp_code += ' Real ' + param_name + '[] = {' for f in value: cpp_code += str(f) + ',' elif type in [common.Edt.VECTOR_INT, common.Edt.LIST_INT]: cpp_code += ' int' + param_name + '[] = {' for i in value: cpp_code += str(i) + ',' cpp_code = cpp_code[:-1]+'};\n' cpp_code += ' _'+algo_name.lower()+'->configure(' for param_name, value in properties['parameters'].iteritems(): if isinstance(value, MarkerObject): # figure out which composite param it is composite_param_name = None for marker_name, marker_obj in marker_objs.iteritems(): if marker_obj == value: composite_param_name = marker_name break if not composite_param_name: raise RuntimeError('Could not determine which composite parameter to use to configure inner algorithm \''+algo_name+'\'s parameter \''+param_name+'\'') cpp_code += '"'+param_name+'", '+composite_param_name+', ' else: type = common.determineEdt(value) if 'LIST' in str(type) or 'VECTOR' in str(type): if type in [common.Edt.VECTOR_STRING]: cpp_code += '"'+param_name+'", '+'arrayToVector<string>(' + param_name + ') ' elif type in[common.Edt.VECTOR_REAL, common.Edt.LIST_REAL]: cpp_code += '"'+param_name+'", '+'arrayToVector<Real>(' + param_name + ') ' elif type in [common.Edt.VECTOR_INT, common.Edt.LIST_INT]: cpp_code += '"'+param_name+'", '+'arrayToVector<int>(' + param_name + ') ' elif isinstance(value, basestring): cpp_code += '"'+param_name+'", "'+value+'", ' elif isinstance(value, bool): if value: cpp_code += '"'+param_name+'", true, ' else: cpp_code += '"'+param_name+'", false, ' else: cpp_code += '"'+param_name+'", '+str(value)+', ' cpp_code = cpp_code[:-2] + ');\n' cpp_code += ' createInnerNetwork();\n}\n\n' ################################ # RESET ################################ cpp_code += 'void '+composite_algo.__name__+'::reset() {\n' for algo_name in sorted_algos: cpp_code += ' _' + algo_name.lower() + '->reset();\n' cpp_code += '}\n\n' ################################ # DESTRUCTOR ################################ # see h_code. Each algo from the composite is deleted separately instead of # calling deleteNetwork # cpp_code += composite_algo.__name__+'''::~'''+composite_algo.__name__+'''() { # deleteNetwork(_''' + input_owner_name.lower() + '''); #}''' # cpp_code +='\n' # ################################ # end of cpp code ################################ if dot_graph: ### generate .dot code ### dot_code = 'digraph ' + output_filename +' {\n' dot_code += ' rankdir=LR\n' # if instead of top-down left-right is prefered # general formatting options: dot_code += ' node [color=black, fontname=Verdana, weight=1, fontsize=8, shape=Mrecord]\n' dot_code += ' edge [color=black, style=solid, weight=1, arrowhead="dotnormal", arrowtail="dot", arrowsize=1, fontsize=6]\n' # for each input generate nodes for name in algo_inst.inputs.keys(): dot_code += ' '+name+' [label="'+name+'"];\n' dot_code += generate_dot_cluster(configure_log, composite_algo.__name__, algo_inst) # for each output generate nodes for name in algo_inst.outputs.keys(): dot_code += ' '+name+' [label="'+name+'"];\n' dot_code += '}' ### Write files ### f = open(output_filename+'.h', 'w') f.write(h_code) f.close() f = open(output_filename+'.cpp', 'w') f.write(cpp_code) f.close() if dot_graph: f = open(output_filename+'.dot', 'w') f.write(dot_code) f.close()