def convert_name_reference(self, variable):
        """
        Converts a single variable to nest processable format.
        :param variable: a single variable.
        :type variable: ASTVariable
        :return: a nest processable format.
        :rtype: str
        """
        from pynestml.codegeneration.nest_printer import NestPrinter
        assert (variable is not None and isinstance(variable, ASTVariable)), \
            '(PyNestML.CodeGeneration.NestReferenceConverter) No or wrong type of uses-gsl provided (%s)!' % type(
                variable)
        variable_name = NestNamesConverter.convert_to_cpp_name(
            variable.get_complete_name())

        if variable_name == PredefinedVariables.E_CONSTANT:
            return 'numerics::e'
        else:
            symbol = variable.get_scope().resolve_to_symbol(
                variable_name, SymbolKind.VARIABLE)
            if symbol is None:
                # test if variable name can be resolved to a type
                if PredefinedUnits.is_unit(variable.get_complete_name()):
                    return str(
                        UnitConverter.get_factor(
                            PredefinedUnits.get_unit(
                                variable.get_complete_name()).get_unit()))

                code, message = Messages.get_could_not_resolve(variable_name)
                Logger.log_message(
                    log_level=LoggingLevel.ERROR,
                    code=code,
                    message=message,
                    error_position=variable.get_source_position())
                return ''
            else:
                if symbol.is_local():
                    return variable_name + (
                        '[i]' if symbol.has_vector_parameter() else '')
                elif symbol.is_buffer():
                    return NestPrinter.print_origin(symbol) + NestNamesConverter.buffer_value(symbol) \
                           + ('[i]' if symbol.has_vector_parameter() else '')
                else:
                    if symbol.is_function:
                        return 'get_' + variable_name + '()' + (
                            '[i]' if symbol.has_vector_parameter() else '')
                    else:
                        if symbol.is_init_values():
                            temp = NestPrinter.print_origin(symbol)
                            if self.uses_gsl:
                                temp += GSLNamesConverter.name(symbol)
                            else:
                                temp += NestNamesConverter.name(symbol)
                            temp += ('[i]'
                                     if symbol.has_vector_parameter() else '')
                            return temp
                        else:
                            return NestPrinter.print_origin(symbol) + \
                                   NestNamesConverter.name(symbol) + \
                                   ('[i]' if symbol.has_vector_parameter() else '')
    def convert_name_reference(self, variable):
        """
        Converts a single variable to nest processable format.
        :param variable: a single variable.
        :type variable: ASTVariable
        :return: a nest processable format.
        :rtype: str
        """
        from pynestml.codegeneration.nest_printer import NestPrinter
        assert (variable is not None and isinstance(variable, ASTVariable)), \
            '(PyNestML.CodeGeneration.NestReferenceConverter) No or wrong type of uses-gsl provided (%s)!' % type(
                variable)
        variable_name = NestNamesConverter.convert_to_cpp_name(variable.get_complete_name())

        if PredefinedUnits.is_unit(variable.get_complete_name()):
            return str(
                UnitConverter.get_factor(PredefinedUnits.get_unit(variable.get_complete_name()).get_unit()))
        if variable_name == PredefinedVariables.E_CONSTANT:
            return 'numerics::e'
        else:
            symbol = variable.get_scope().resolve_to_symbol(variable_name, SymbolKind.VARIABLE)
            if symbol is None:
                # this should actually not happen, but an error message is better than an exception
                code, message = Messages.get_could_not_resolve(variable_name)
                Logger.log_message(log_level=LoggingLevel.ERROR, code=code, message=message,
                                   error_position=variable.get_source_position())
                return ''
            else:
                if symbol.is_local():
                    return variable_name + ('[i]' if symbol.has_vector_parameter() else '')
                elif symbol.is_buffer():
                    return NestPrinter.print_origin(symbol) + NestNamesConverter.buffer_value(symbol) \
                           + ('[i]' if symbol.has_vector_parameter() else '')
                else:
                    if symbol.is_function:
                        return 'get_' + variable_name + '()' + ('[i]' if symbol.has_vector_parameter() else '')
                    else:
                        if symbol.is_init_values():
                            temp = NestPrinter.print_origin(symbol)
                            if self.uses_gsl:
                                temp += GSLNamesConverter.name(symbol)
                            else:
                                temp += NestNamesConverter.name(symbol)
                            temp += ('[i]' if symbol.has_vector_parameter() else '')
                            return temp
                        else:
                            return NestPrinter.print_origin(symbol) + \
                                   NestNamesConverter.name(symbol) + \
                                   ('[i]' if symbol.has_vector_parameter() else '')
示例#3
0
    def setup_model_generation_helpers(self, neuron: ASTNeuron):
        """
        Returns a namespace for Jinja2 neuron model documentation template.

        :param neuron: a single neuron instance
        :type neuron: ASTNeuron
        :return: a map from name to functionality.
        :rtype: dict
        """
        converter = LatexReferenceConverter()
        latex_expression_printer = LatexExpressionPrinter(converter)

        namespace = dict()

        namespace['now'] = datetime.datetime.utcnow()
        namespace['neuron'] = neuron
        namespace['neuronName'] = str(neuron.get_name())
        namespace['printer'] = NestPrinter(latex_expression_printer)
        namespace['assignments'] = NestAssignmentsHelper()
        namespace['names'] = NestNamesConverter()
        namespace['declarations'] = NestDeclarationsHelper()
        namespace['utils'] = ASTUtils()
        namespace['odeTransformer'] = OdeTransformer()

        import textwrap
        pre_comments_bak = neuron.pre_comments
        neuron.pre_comments = []
        namespace['neuron_source_code'] = textwrap.indent(
            neuron.__str__(), "   ")
        neuron.pre_comments = pre_comments_bak

        return namespace
示例#4
0
    def setup_index_generation_helpers(self, neurons: List[ASTNeuron]):
        """
        Returns a namespace for Jinja2 neuron model index page template.

        :param neurons: a list of neuron instances
        :type neurons: List[ASTNeuron]
        :return: a map from name to functionality.
        :rtype: dict
        """
        converter = LatexReferenceConverter()
        latex_expression_printer = LatexExpressionPrinter(converter)

        namespace = dict()

        namespace['now'] = datetime.datetime.utcnow()
        namespace['neurons'] = neurons
        namespace['neuronNames'] = [
            str(neuron.get_name()) for neuron in neurons
        ]
        namespace['printer'] = NestPrinter(latex_expression_printer)
        namespace['assignments'] = NestAssignmentsHelper()
        namespace['names'] = NestNamesConverter()
        namespace['declarations'] = NestDeclarationsHelper()
        namespace['utils'] = ASTUtils()
        namespace['odeTransformer'] = OdeTransformer()

        return namespace
示例#5
0
def setup_generation_helpers(neuron):
    """
    Returns a standard namespace with often required functionality.
    :param neuron: a single neuron instance
    :type neuron: ASTNeuron
    :return: a map from name to functionality.
    :rtype: dict
    """
    gsl_converter = GSLReferenceConverter()
    gsl_printer = LegacyExpressionPrinter(gsl_converter)
    # helper classes and objects
    converter = NESTReferenceConverter(False)
    legacy_pretty_printer = LegacyExpressionPrinter(converter)

    namespace = dict()

    namespace['neuronName'] = neuron.get_name()
    namespace['neuron'] = neuron
    namespace['moduleName'] = FrontendConfiguration.get_module_name()
    namespace['printer'] = NestPrinter(legacy_pretty_printer)
    namespace['assignments'] = NestAssignmentsHelper()
    namespace['names'] = NestNamesConverter()
    namespace['declarations'] = NestDeclarationsHelper()
    namespace['utils'] = ASTUtils()
    namespace['idemPrinter'] = LegacyExpressionPrinter()
    namespace['outputEvent'] = namespace['printer'].print_output_event(neuron.get_body())
    namespace['is_spike_input'] = ASTUtils.is_spike_input(neuron.get_body())
    namespace['is_current_input'] = ASTUtils.is_current_input(neuron.get_body())
    namespace['odeTransformer'] = OdeTransformer()
    namespace['printerGSL'] = gsl_printer
    namespace['now'] = datetime.datetime.utcnow()

    define_solver_type(neuron, namespace)
    return namespace
示例#6
0
def define_solver_type(neuron, namespace):
    # type: (ASTNeuron, dict) -> None
    """
    For a handed over neuron this method enriches the namespace by methods which are used to solve
    odes.
    :param namespace: a single namespace dict.
    :param neuron: a single neuron
    """
    namespace['useGSL'] = False
    if neuron.get_equations_block() is not None and len(neuron.get_equations_block().get_declarations()) > 0:
        if (not is_functional_shape_present(neuron.get_equations_block().get_ode_shapes())) or \
                len(neuron.get_equations_block().get_ode_equations()) > 1:
            namespace['names'] = GSLNamesConverter()
            namespace['useGSL'] = True
            converter = NESTReferenceConverter(True)
            legacy_pretty_printer = LegacyExpressionPrinter(converter)
            namespace['printer'] = NestPrinter(legacy_pretty_printer)
    return
示例#7
0
    def setup_generation_helpers(self, neuron):
        """
        Returns a standard namespace with often required functionality.
        :param neuron: a single neuron instance
        :type neuron: ASTNeuron
        :return: a map from name to functionality.
        :rtype: dict
        """
        gsl_converter = GSLReferenceConverter()
        gsl_printer = LegacyExpressionPrinter(gsl_converter)
        # helper classes and objects
        converter = NESTReferenceConverter(False)
        legacy_pretty_printer = LegacyExpressionPrinter(converter)

        namespace = dict()

        namespace['neuronName'] = neuron.get_name()
        namespace['neuron'] = neuron
        namespace['moduleName'] = FrontendConfiguration.get_module_name()
        namespace['printer'] = NestPrinter(legacy_pretty_printer)
        namespace['assignments'] = NestAssignmentsHelper()
        namespace['names'] = NestNamesConverter()
        namespace['declarations'] = NestDeclarationsHelper()
        namespace['utils'] = ASTUtils()
        namespace['idemPrinter'] = LegacyExpressionPrinter()
        namespace['outputEvent'] = namespace['printer'].print_output_event(neuron.get_body())
        namespace['is_spike_input'] = ASTUtils.is_spike_input(neuron.get_body())
        namespace['is_current_input'] = ASTUtils.is_current_input(neuron.get_body())
        namespace['odeTransformer'] = OdeTransformer()
        namespace['printerGSL'] = gsl_printer
        namespace['now'] = datetime.datetime.utcnow()
        namespace['tracing'] = FrontendConfiguration.is_dev

        namespace['PredefinedUnits'] = pynestml.symbols.predefined_units.PredefinedUnits
        namespace['UnitTypeSymbol'] = pynestml.symbols.unit_type_symbol.UnitTypeSymbol

        rng_visitor = ASTRandomNumberGeneratorVisitor()
        neuron.accept(rng_visitor)
        namespace['norm_rng'] = rng_visitor._norm_rng_is_used

        self.define_solver_type(neuron, namespace)
        return namespace
示例#8
0
from pynestml.symbol_table.symbol_table import SymbolTable
from pynestml.symbols.predefined_functions import PredefinedFunctions
from pynestml.symbols.predefined_types import PredefinedTypes
from pynestml.symbols.predefined_units import PredefinedUnits
from pynestml.symbols.predefined_variables import PredefinedVariables
from pynestml.utils.logger import Logger, LoggingLevel
from pynestml.utils.model_parser import ModelParser

SymbolTable.initialize_symbol_table(
    ASTSourceLocation(start_line=0, start_column=0, end_line=0, end_column=0))
PredefinedUnits.register_units()
PredefinedTypes.register_types()
PredefinedVariables.register_variables()
PredefinedFunctions.register_functions()
Logger.init_logger(LoggingLevel.INFO)
printer = NestPrinter(ExpressionsPrettyPrinter(), NESTReferenceConverter())


def get_first_statement_in_update_block(model):
    if model.get_neuron_list()[0].get_update_blocks():
        return model.get_neuron_list()[0].get_update_blocks().get_block(
        ).get_stmts()[0]
    return None


def get_first_declaration_in_state_block(model):
    return model.get_neuron_list()[0].get_state_blocks().get_declarations()[0]


def get_first_declared_function(model):
    return model.get_neuron_list()[0].get_functions()[0]
示例#9
0
    def setup_generation_helpers(self, neuron: ASTNeuron) -> Dict:
        """
        Returns a standard namespace with often required functionality.
        :param neuron: a single neuron instance
        :type neuron: ASTNeuron
        :return: a map from name to functionality.
        :rtype: dict
        """
        gsl_converter = GSLReferenceConverter()
        gsl_printer = UnitlessExpressionPrinter(gsl_converter)
        # helper classes and objects
        converter = NESTReferenceConverter(False)
        unitless_pretty_printer = UnitlessExpressionPrinter(converter)

        namespace = dict()

        namespace['neuronName'] = neuron.get_name()
        namespace['neuron'] = neuron
        namespace['moduleName'] = FrontendConfiguration.get_module_name()
        namespace['printer'] = NestPrinter(unitless_pretty_printer)
        namespace['assignments'] = NestAssignmentsHelper()
        namespace['names'] = NestNamesConverter()
        namespace['declarations'] = NestDeclarationsHelper()
        namespace['utils'] = ASTUtils()
        namespace['idemPrinter'] = UnitlessExpressionPrinter()
        namespace['outputEvent'] = namespace['printer'].print_output_event(
            neuron.get_body())
        namespace['is_spike_input'] = ASTUtils.is_spike_input(
            neuron.get_body())
        namespace['is_current_input'] = ASTUtils.is_current_input(
            neuron.get_body())
        namespace['odeTransformer'] = OdeTransformer()
        namespace['printerGSL'] = gsl_printer
        namespace['now'] = datetime.datetime.utcnow()
        namespace['tracing'] = FrontendConfiguration.is_dev

        namespace[
            'PredefinedUnits'] = pynestml.symbols.predefined_units.PredefinedUnits
        namespace[
            'UnitTypeSymbol'] = pynestml.symbols.unit_type_symbol.UnitTypeSymbol

        namespace['initial_values'] = {}
        namespace['uses_analytic_solver'] = neuron.get_name() in self.analytic_solver.keys() \
            and self.analytic_solver[neuron.get_name()] is not None
        if namespace['uses_analytic_solver']:
            namespace['analytic_state_variables'] = self.analytic_solver[
                neuron.get_name()]["state_variables"]
            namespace['analytic_variable_symbols'] = {
                sym:
                neuron.get_equations_block().get_scope().resolve_to_symbol(
                    sym, SymbolKind.VARIABLE)
                for sym in namespace['analytic_state_variables']
            }
            namespace['update_expressions'] = {}
            for sym, expr in self.analytic_solver[
                    neuron.get_name()]["initial_values"].items():
                namespace['initial_values'][sym] = expr
            for sym in namespace['analytic_state_variables']:
                expr_str = self.analytic_solver[
                    neuron.get_name()]["update_expressions"][sym]
                expr_ast = ModelParser.parse_expression(expr_str)
                # pretend that update expressions are in "equations" block, which should always be present, as differential equations must have been defined to get here
                expr_ast.update_scope(
                    neuron.get_equations_blocks().get_scope())
                expr_ast.accept(ASTSymbolTableVisitor())
                namespace['update_expressions'][sym] = expr_ast

            namespace['propagators'] = self.analytic_solver[
                neuron.get_name()]["propagators"]

        namespace['uses_numeric_solver'] = neuron.get_name() in self.analytic_solver.keys() \
            and self.numeric_solver[neuron.get_name()] is not None
        if namespace['uses_numeric_solver']:
            namespace['numeric_state_variables'] = self.numeric_solver[
                neuron.get_name()]["state_variables"]
            namespace['numeric_variable_symbols'] = {
                sym:
                neuron.get_equations_block().get_scope().resolve_to_symbol(
                    sym, SymbolKind.VARIABLE)
                for sym in namespace['numeric_state_variables']
            }
            assert not any([
                sym is None
                for sym in namespace['numeric_variable_symbols'].values()
            ])
            namespace['numeric_update_expressions'] = {}
            for sym, expr in self.numeric_solver[
                    neuron.get_name()]["initial_values"].items():
                namespace['initial_values'][sym] = expr
            for sym in namespace['numeric_state_variables']:
                expr_str = self.numeric_solver[
                    neuron.get_name()]["update_expressions"][sym]
                expr_ast = ModelParser.parse_expression(expr_str)
                # pretend that update expressions are in "equations" block, which should always be present, as differential equations must have been defined to get here
                expr_ast.update_scope(
                    neuron.get_equations_blocks().get_scope())
                expr_ast.accept(ASTSymbolTableVisitor())
                namespace['numeric_update_expressions'][sym] = expr_ast

            namespace['useGSL'] = namespace['uses_numeric_solver']
            namespace['names'] = GSLNamesConverter()
            converter = NESTReferenceConverter(True)
            unitless_pretty_printer = UnitlessExpressionPrinter(converter)
            namespace['printer'] = NestPrinter(unitless_pretty_printer)

        namespace["spike_updates"] = neuron.spike_updates

        rng_visitor = ASTRandomNumberGeneratorVisitor()
        neuron.accept(rng_visitor)
        namespace['norm_rng'] = rng_visitor._norm_rng_is_used

        return namespace
示例#10
0
    def convert_name_reference(self, variable: ASTVariable, prefix='') -> str:
        """
        Converts a single variable to nest processable format.
        :param variable: a single variable.
        :type variable: ASTVariable
        :return: a nest processable format.
        """
        from pynestml.codegeneration.nest_printer import NestPrinter

        if isinstance(variable, ASTExternalVariable):
            _name = str(variable)
            if variable.get_alternate_name():
                # the disadvantage of this approach is that the time the value is to be obtained is not explicitly specified, so we will actually get the value at the end of the min_delay timestep
                return "((POST_NEURON_TYPE*)(__target))->get_" + variable.get_alternate_name(
                ) + "()"

            return "((POST_NEURON_TYPE*)(__target))->get_" + _name + "(_tr_t)"

        if variable.get_name() == PredefinedVariables.E_CONSTANT:
            return 'numerics::e'

        symbol = variable.get_scope().resolve_to_symbol(
            variable.get_complete_name(), SymbolKind.VARIABLE)
        if symbol is None:
            # test if variable name can be resolved to a type
            if PredefinedUnits.is_unit(variable.get_complete_name()):
                return str(
                    UnitConverter.get_factor(
                        PredefinedUnits.get_unit(
                            variable.get_complete_name()).get_unit()))

            code, message = Messages.get_could_not_resolve(variable.get_name())
            Logger.log_message(log_level=LoggingLevel.ERROR,
                               code=code,
                               message=message,
                               error_position=variable.get_source_position())
            return ''

        if symbol.is_local():
            return variable.get_name() + (
                '[' + variable.get_vector_parameter() +
                ']' if symbol.has_vector_parameter() else '')
        if symbol.is_buffer():
            if isinstance(symbol.get_type_symbol(), UnitTypeSymbol):
                units_conversion_factor = UnitConverter.get_factor(
                    symbol.get_type_symbol().unit.unit)
            else:
                units_conversion_factor = 1
            s = ""
            if not units_conversion_factor == 1:
                s += "(" + str(units_conversion_factor) + " * "
            s += NestPrinter.print_origin(
                symbol,
                prefix=prefix) + NestNamesConverter.buffer_value(symbol)
            if symbol.has_vector_parameter():
                s += '[' + variable.get_vector_parameter() + ']'
            if not units_conversion_factor == 1:
                s += ")"
            return s

        if symbol.is_inline_expression:
            return 'get_' + variable.get_name() + '()' + (
                '[i]' if symbol.has_vector_parameter() else '')

        if symbol.is_kernel():
            assert False, "NEST reference converter cannot print kernel; kernel should have been converted during code generation"

        if symbol.is_state():
            temp = ""
            temp += NestNamesConverter.getter(symbol) + "()"
            temp += ('[' + variable.get_vector_parameter() +
                     ']' if symbol.has_vector_parameter() else '')
            return temp

        variable_name = NestNamesConverter.convert_to_cpp_name(
            variable.get_complete_name())
        if symbol.is_local():
            return variable_name + ('[i]'
                                    if symbol.has_vector_parameter() else '')

        if symbol.is_inline_expression:
            return 'get_' + variable_name + '()' + (
                '[i]' if symbol.has_vector_parameter() else '')

        return NestPrinter.print_origin(symbol, prefix=prefix) + \
            NestNamesConverter.name(symbol) + \
            ('[' + variable.get_vector_parameter() + ']' if symbol.has_vector_parameter() else '')
    def convert_name_reference(self, variable, prefix='', with_origins = True):
        """
        Converts a single variable to nest processable format.
        :param variable: a single variable.
        :type variable: ASTVariable
        :return: a nest processable format.
        :rtype: str
        """
        from pynestml.codegeneration.nest_printer import NestPrinter
        assert (variable is not None and isinstance(variable, ASTVariable)), \
            '(PyNestML.CodeGeneration.NestReferenceConverter) No or wrong type of uses-gsl provided (%s)!' % type(
                variable)
        variable_name = NestNamesConverter.convert_to_cpp_name(variable.get_complete_name())

        if variable_name == PredefinedVariables.E_CONSTANT:
            return 'numerics::e'

        assert variable.get_scope() is not None, "Undeclared variable: " + variable.get_complete_name()

        symbol = variable.get_scope().resolve_to_symbol(variable_name, SymbolKind.VARIABLE)
        if symbol is None:
            # test if variable name can be resolved to a type
            if PredefinedUnits.is_unit(variable.get_complete_name()):
                return str(UnitConverter.get_factor(PredefinedUnits.get_unit(variable.get_complete_name()).get_unit()))

            code, message = Messages.get_could_not_resolve(variable_name)
            Logger.log_message(log_level=LoggingLevel.ERROR, code=code, message=message,
                               error_position=variable.get_source_position())
            return ''

        if symbol.is_local():
            return variable_name + ('[i]' if symbol.has_vector_parameter() else '')

        if symbol.is_buffer():
            if isinstance(symbol.get_type_symbol(), UnitTypeSymbol):
                units_conversion_factor = UnitConverter.get_factor(symbol.get_type_symbol().unit.unit)
            else:
                units_conversion_factor = 1
            s = ""
            if not units_conversion_factor == 1:
                s += "(" + str(units_conversion_factor) + " * "
            s += NestPrinter.print_origin(symbol, prefix=prefix) if with_origins else ''
            s += NestNamesConverter.buffer_value(symbol)
            if symbol.has_vector_parameter():
                s += '[i]'
            if not units_conversion_factor == 1:
                s += ")"
            return s

        if symbol.is_inline_expression:
            return 'get_' + variable_name + '()' + ('[i]' if symbol.has_vector_parameter() else '')

        if symbol.is_kernel():
            assert False, "NEST reference converter cannot print kernel; kernel should have been converted during code generation"

        if symbol.is_state():
            temp = NestPrinter.print_origin(symbol, prefix=prefix) if with_origins else ''
            if self.uses_gsl:
                temp += GSLNamesConverter.name(symbol)
            else:
                temp += NestNamesConverter.name(symbol)
            temp += ('[i]' if symbol.has_vector_parameter() else '')
            return temp

        return (NestPrinter.print_origin(symbol, prefix=prefix) if with_origins else '') + \
            NestNamesConverter.name(symbol) + \
            ('[i]' if symbol.has_vector_parameter() else '')