def create_report_dir(): if not os.path.isdir( os.path.join(FrontendConfiguration.get_target_path(), "..", "report")): os.makedirs( os.path.join(FrontendConfiguration.get_target_path(), "..", "report"))
def generate_code(self, neurons: List[ASTNeuron], synapses: List[ASTSynapse] = None) -> None: """ Generate model documentation and index page for each neuron and synapse that is provided. """ if not os.path.isdir(FrontendConfiguration.get_target_path()): os.makedirs(FrontendConfiguration.get_target_path()) self.generate_index(neurons, synapses) self.generate_neurons(neurons) self.generate_synapses(synapses)
def generate_neuron_code(self, neuron: ASTNeuron) -> None: """ For a handed over neuron, this method generates the corresponding header and implementation file. :param neuron: a single neuron object. """ if not os.path.isdir(FrontendConfiguration.get_target_path()): os.makedirs(FrontendConfiguration.get_target_path()) self.generate_model_h_file(neuron) self.generate_neuron_cpp_file(neuron)
def generate_neuron_code(self, neuron): # type: (ASTNeuron) -> None """ For a handed over neuron, this method generates the corresponding header and implementation file. :param neuron: a single neuron object. """ if not os.path.isdir(FrontendConfiguration.get_target_path()): os.makedirs(FrontendConfiguration.get_target_path()) self.generate_model_h_file(neuron) self.generate_neuron_cpp_file(neuron)
def generate_module_code(self, neurons): # type: (list(ASTNeuron)) -> None """ Generates code that is necessary to integrate neuron models into the NEST infrastructure. :param neurons: a list of neurons :type neurons: list(ASTNeuron) """ namespace = {'neurons': neurons, 'moduleName': FrontendConfiguration.get_module_name(), 'now': datetime.datetime.utcnow()} if not os.path.exists(FrontendConfiguration.get_target_path()): os.makedirs(FrontendConfiguration.get_target_path()) with open(str(os.path.join(FrontendConfiguration.get_target_path(), FrontendConfiguration.get_module_name())) + '.h', 'w+') as f: f.write(str(self._template_module_header.render(namespace))) with open(str(os.path.join(FrontendConfiguration.get_target_path(), FrontendConfiguration.get_module_name())) + '.cpp', 'w+') as f: f.write(str(self._template_module_class.render(namespace))) with open(str(os.path.join(FrontendConfiguration.get_target_path(), 'CMakeLists')) + '.txt', 'w+') as f: f.write(str(self._template_cmakelists.render(namespace))) if not os.path.isdir(os.path.realpath(os.path.join(FrontendConfiguration.get_target_path(), 'sli'))): os.makedirs(os.path.realpath(os.path.join(FrontendConfiguration.get_target_path(), 'sli'))) with open(str(os.path.join(FrontendConfiguration.get_target_path(), 'sli', FrontendConfiguration.get_module_name() + "-init")) + '.sli', 'w+') as f: f.write(str(self._template_sli_init.render(namespace))) code, message = Messages.get_module_generated(FrontendConfiguration.get_target_path()) Logger.log_message(None, code, message, None, LoggingLevel.INFO)
def generate_nest_module_code(neurons): # type: (list(ASTNeuron)) -> None """ Generates code that is necessary to integrate neuron models into the NEST infrastructure. :param neurons: a list of neurons :type neurons: list(ASTNeuron) """ namespace = {'neurons': neurons, 'moduleName': FrontendConfiguration.get_module_name(), 'now': datetime.datetime.utcnow()} if not os.path.exists(FrontendConfiguration.get_target_path()): os.makedirs(FrontendConfiguration.get_target_path()) with open(str(os.path.join(FrontendConfiguration.get_target_path(), FrontendConfiguration.get_module_name())) + '.h', 'w+') as f: f.write(str(template_module_header.render(namespace))) with open(str(os.path.join(FrontendConfiguration.get_target_path(), FrontendConfiguration.get_module_name())) + '.cpp', 'w+') as f: f.write(str(template_module_class.render(namespace))) with open(str(os.path.join(FrontendConfiguration.get_target_path(), 'CMakeLists')) + '.txt', 'w+') as f: f.write(str(template_cmakelists.render(namespace))) if not os.path.isdir(os.path.realpath(os.path.join(FrontendConfiguration.get_target_path(), 'sli'))): os.makedirs(os.path.realpath(os.path.join(FrontendConfiguration.get_target_path(), 'sli'))) with open(str(os.path.join(FrontendConfiguration.get_target_path(), 'sli', FrontendConfiguration.get_module_name() + "-init")) + '.sli', 'w+') as f: f.write(str(template_sli_init.render(namespace))) code, message = Messages.get_module_generated(FrontendConfiguration.get_target_path()) Logger.log_message(None, code, message, None, LoggingLevel.INFO)
def test_from_objects(self): input_path = os.path.join(os.path.dirname(__file__), 'resources', 'CommentTest.nestml') target_path = os.path.join('target') logging_level = 'INFO' module_name = 'module' store_log = False suffix = '' dev = True to_nest(input_path, target_path, logging_level, module_name, store_log, suffix, dev) self.assertTrue(os.path.isfile(os.path.join(FrontendConfiguration.get_target_path(), 'CMakeLists.txt'))) self.assertTrue(os.path.isfile(os.path.join(FrontendConfiguration.get_target_path(), 'commentTest.cpp'))) self.assertTrue(os.path.isfile(os.path.join(FrontendConfiguration.get_target_path(), 'commentTest.h'))) self.assertTrue(os.path.isfile(os.path.join(FrontendConfiguration.get_target_path(), 'module.cpp'))) self.assertTrue(os.path.isfile(os.path.join(FrontendConfiguration.get_target_path(), 'module.h')))
def generate_neuron_code(self, neuron: ASTNeuron): """ Generate model documentation for neuron model. :param neuron: a single neuron object. """ if not os.path.isdir(FrontendConfiguration.get_target_path()): os.makedirs(FrontendConfiguration.get_target_path()) nestml_model_doc = self._template_nestml_model.render( self.setup_model_generation_helpers(neuron)) with open( str( os.path.join(FrontendConfiguration.get_target_path(), neuron.get_name())) + '.rst', 'w+') as f: f.write(str(nestml_model_doc))
def analyse_and_generate_neuron(neuron): # type: (ASTNeuron) -> None """ Analysis a single neuron, solves it and generates the corresponding code. :param neuron: a single neuron. """ code, message = Messages.get_start_processing_neuron(neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) # make normalization # apply spikes to buffers # get rid of convolve, store them and apply then at the end equations_block = neuron.get_equations_block() shape_to_buffers = {} if neuron.get_equations_block() is not None: # extract function names and corresponding incoming buffers convolve_calls = OdeTransformer.get_sum_function_calls(equations_block) for convolve in convolve_calls: shape_to_buffers[str(convolve.get_args()[0])] = str(convolve.get_args()[1]) OdeTransformer.refactor_convolve_call(neuron.get_equations_block()) make_functions_self_contained(equations_block.get_ode_functions()) replace_functions_through_defining_expressions(equations_block.get_ode_equations(), equations_block.get_ode_functions()) # transform everything into gsl processable (e.g. no functional shapes) or exact form. transform_shapes_and_odes(neuron, shape_to_buffers) # update the symbol table neuron.accept(ASTSymbolTableVisitor()) generate_nest_code(neuron) # now store the transformed model store_transformed_model(neuron) # at that point all shapes are transformed into the ODE form and spikes can be applied code, message = Messages.get_code_generated(neuron.get_name(), FrontendConfiguration.get_target_path()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO)
def generate_index(self, neurons: Sequence[ASTNeuron], synapses: Sequence[ASTSynapse]): """ Generate model documentation and index page for each neuron and synapse that is provided. """ nestml_models_index = self._template_nestml_models_index.render(self.setup_index_generation_helpers(neurons, synapses)) with open(str(os.path.join(FrontendConfiguration.get_target_path(), 'index.rst')), 'w+') as f: f.write(str(nestml_models_index))
def generate_neuron_cpp_file(self, neuron: ASTNeuron) -> None: """ For a handed over neuron, this method generates the corresponding implementation file. :param neuron: a single neuron object. """ neuron_cpp_file = self._template_neuron_cpp_file.render(self.setup_generation_helpers(neuron)) with open(str(os.path.join(FrontendConfiguration.get_target_path(), neuron.get_name())) + '.cpp', 'w+') as f: f.write(str(neuron_cpp_file))
def store_transformed_model(self, ast): if FrontendConfiguration.store_log: with open( str( os.path.join(FrontendConfiguration.get_target_path(), '..', 'report', ast.get_name())) + '.txt', 'w+') as f: f.write(str(ast))
def generate_neuron_cpp_file(self, neuron): # type: (ASTNeuron) -> None """ For a handed over neuron, this method generates the corresponding implementation file. :param neuron: a single neuron object. """ neuron_cpp_file = self._template_neuron_cpp_file.render(self.setup_generation_helpers(neuron)) with open(str(os.path.join(FrontendConfiguration.get_target_path(), neuron.get_name())) + '.cpp', 'w+') as f: f.write(str(neuron_cpp_file))
def generate_synapse_code(self, synapse: ASTSynapse): """ Generate model documentation for synapse model. :param synapse: a single synapse object. """ nestml_model_doc = self._template_synapse_nestml_model.render(self.setup_synapse_model_generation_helpers(synapse)) with open(str(os.path.join(FrontendConfiguration.get_target_path(), synapse.get_name())) + '.rst', 'w+') as f: f.write(str(nestml_model_doc))
def generate_model_h_file(neuron): # type: (ASTNeuron) -> None """ For a handed over neuron, this method generates the corresponding header file. :param neuron: a single neuron object. """ # print("!!!", neuron) neuron_h_file = template_neuron_h_file.render(setup_generation_helpers(neuron)) with open(str(os.path.join(FrontendConfiguration.get_target_path(), neuron.get_name())) + '.h', 'w+') as f: f.write(str(neuron_h_file))
def generate_index(self, neurons: List[ASTNeuron]): """ Generate index (list) of all neuron models with links to their generated documentation. """ nestml_models_index = self._template_nestml_models_index.render( self.setup_index_generation_helpers(neurons)) with open( str( os.path.join(FrontendConfiguration.get_target_path(), 'index.rst')), 'w+') as f: f.write(str(nestml_models_index))
def generate_neurons(self, neurons: List[ASTNode]): """ Generate code for the given neurons. :param neurons: a list of neurons. :type neurons: List[ASTNode] """ from pynestml.frontend.frontend_configuration import FrontendConfiguration for neuron in neurons: self.generate_neuron_code(neuron) if not Logger.has_errors(neuron): code, message = Messages.get_code_generated(neuron.get_name(), FrontendConfiguration.get_target_path()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO)
def generate_neurons(self, neurons): # type: (list(ASTNeuron)) -> None """ Analyse a list of neurons, solve them and generate the corresponding code. :param neurons: a list of neurons. """ from pynestml.frontend.frontend_configuration import FrontendConfiguration for neuron in neurons: self.generate_neuron_code(neuron) if not Logger.has_errors(neuron): code, message = Messages.get_code_generated( neuron.get_name(), FrontendConfiguration.get_target_path()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO)
def generate_synapses(self, synapses: Sequence[ASTSynapse]) -> None: """ Generates code for a list of synapses. :param synapses: a list of synapses. """ from pynestml.frontend.frontend_configuration import FrontendConfiguration for synapse in synapses: if Logger.logging_level == LoggingLevel.INFO: print("Generating code for the synapse {}.".format( synapse.get_name())) self.generate_synapse_code(synapse) code, message = Messages.get_code_generated( synapse.get_name(), FrontendConfiguration.get_target_path()) Logger.log_message(synapse, code, message, synapse.get_source_position(), LoggingLevel.INFO)
def store_log_to_file(): with open( str( os.path.join(FrontendConfiguration.get_target_path(), "..", "report", "log")) + ".txt", "w+") as f: f.write(str(Logger.get_json_format()))
def store_transformed_model(self, ast): if FrontendConfiguration.store_log: with open(str(os.path.join(FrontendConfiguration.get_target_path(), '..', 'report', ast.get_name())) + '.txt', 'w+') as f: f.write(str(ast))
def store_log_to_file(): with open( str( os.path.join(FrontendConfiguration.get_target_path(), '..', 'report', 'log')) + '.txt', 'w+') as f: f.write(str(Logger.get_json_format()))
def build(self) -> None: r""" This method can be used to build the generated code and install the resulting extension module into NEST. Raises ------ GeneratedCodeBuildException If any kind of failure occurs during cmake configuration, build, or install. InvalidPathException If a failure occurs while trying to access the target path or the NEST installation path. """ cmake_cmd = ["cmake"] target_path = FrontendConfiguration.get_target_path() install_path = FrontendConfiguration.get_install_path() if install_path is not None: add_libraries_to_sli(install_path) nest_path = self.get_option("nest_path") if not os.path.isdir(target_path): raise InvalidPathException('Target path (' + target_path + ') is not a directory!') if nest_path is None or (not os.path.isdir(nest_path)): raise InvalidPathException('NEST path (' + str(nest_path) + ') is not a directory!') install_prefix = "" if install_path: if not os.path.isabs(install_path): install_path = os.path.abspath(install_path) install_prefix = f"-DCMAKE_INSTALL_PREFIX={install_path}" nest_config_path = f"-Dwith-nest={os.path.join(nest_path, 'bin', 'nest-config')}" cmake_cmd = ['cmake', nest_config_path, install_prefix, '.'] make_all_cmd = ['make', 'all'] make_install_cmd = ['make', 'install'] # remove CMakeCache.txt if exists cmake_cache = os.path.join(target_path, "CMakeCache.txt") if os.path.exists(cmake_cache): os.remove(cmake_cache) # check if we run on win if sys.platform.startswith('win'): shell = True else: shell = False # first call cmake with all the arguments try: result = subprocess.check_call(cmake_cmd, stderr=subprocess.STDOUT, shell=shell, cwd=str(os.path.join(target_path))) except subprocess.CalledProcessError as e: raise GeneratedCodeBuildException( 'Error occurred during \'cmake\'! More detailed error messages can be found in stdout.' ) # now execute make all try: subprocess.check_call(make_all_cmd, stderr=subprocess.STDOUT, shell=shell, cwd=str(os.path.join(target_path))) except subprocess.CalledProcessError as e: raise GeneratedCodeBuildException( 'Error occurred during \'make all\'! More detailed error messages can be found in stdout.' ) # finally execute make install try: subprocess.check_call(make_install_cmd, stderr=subprocess.STDOUT, shell=shell, cwd=str(os.path.join(target_path))) except subprocess.CalledProcessError as e: raise GeneratedCodeBuildException( 'Error occurred during \'make install\'! More detailed error messages can be found in stdout.' )