From d699cb6338e41f798386976c5ee71700403617f2 Mon Sep 17 00:00:00 2001 From: "C.A.P. Linssen" Date: Mon, 1 Dec 2025 15:16:51 +0100 Subject: [PATCH] clean up dictionary access in templates --- .../codegeneration/nest_code_generator.py | 2 +- .../nest_compartmental_code_generator.py | 1 + .../ReadFromDictionaryToTmp.jinja2 | 1 - .../point_neuron/common/NeuronHeader.jinja2 | 21 ++++++++-------- .../common/SynapseHeader.h.jinja2 | 17 ++++++------- .../CommonPropertiesDictionaryWriter.jinja2 | 3 ++- .../directives_cpp/WriteInDictionary.jinja2 | 10 ++++---- .../cm_neuron/@NEURON_NAME@.cpp.jinja2 | 12 ++++++---- .../cm_neuroncurrents_@NEURON_NAME@.h.jinja2 | 24 +++++++++---------- ...rtiesDictionaryMemberInitialization.jinja2 | 1 - .../CommonPropertiesDictionaryReader.jinja2 | 1 - .../CommonPropertiesDictionaryWriter.jinja2 | 1 - .../ReadFromDictionaryToTmp.jinja2 | 1 - .../directives_cpp/WriteInDictionary.jinja2 | 1 - 14 files changed, 46 insertions(+), 50 deletions(-) delete mode 120000 pynestml/codegeneration/resources_genn/directives_cpp/ReadFromDictionaryToTmp.jinja2 delete mode 120000 pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryMemberInitialization.jinja2 delete mode 120000 pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryReader.jinja2 delete mode 120000 pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryWriter.jinja2 delete mode 120000 pynestml/codegeneration/resources_spinnaker/directives_cpp/ReadFromDictionaryToTmp.jinja2 delete mode 120000 pynestml/codegeneration/resources_spinnaker/directives_cpp/WriteInDictionary.jinja2 diff --git a/pynestml/codegeneration/nest_code_generator.py b/pynestml/codegeneration/nest_code_generator.py index 9b51b454d..9fdeea088 100644 --- a/pynestml/codegeneration/nest_code_generator.py +++ b/pynestml/codegeneration/nest_code_generator.py @@ -606,7 +606,7 @@ def _get_synapse_model_namespace(self, synapse: ASTModel) -> Dict: namespace["has_state_vectors"] = False namespace["vector_symbols"] = [] - namespace['names_namespace'] = synapse.get_name() + "_names" + namespace["names_namespace"] = synapse.get_name() + "_names" # event handlers priority # XXX: this should be refactored in case we have additional modulatory (3rd-factor) spiking input ports in the synapse diff --git a/pynestml/codegeneration/nest_compartmental_code_generator.py b/pynestml/codegeneration/nest_compartmental_code_generator.py index 3448aff20..2d3766447 100644 --- a/pynestml/codegeneration/nest_compartmental_code_generator.py +++ b/pynestml/codegeneration/nest_compartmental_code_generator.py @@ -578,6 +578,7 @@ def _get_neuron_model_namespace(self, neuron: ASTModel) -> Dict: namespace["nestml_version"] = pynestml.__version__ namespace["now"] = datetime.datetime.utcnow() namespace["tracing"] = FrontendConfiguration.is_dev + namespace["names_namespace"] = "names" # helper functions namespace["ast_node_factory"] = ASTNodeFactory diff --git a/pynestml/codegeneration/resources_genn/directives_cpp/ReadFromDictionaryToTmp.jinja2 b/pynestml/codegeneration/resources_genn/directives_cpp/ReadFromDictionaryToTmp.jinja2 deleted file mode 120000 index c397e3981..000000000 --- a/pynestml/codegeneration/resources_genn/directives_cpp/ReadFromDictionaryToTmp.jinja2 +++ /dev/null @@ -1 +0,0 @@ -../../resources_nest/point_neuron/directives_cpp/ReadFromDictionaryToTmp.jinja2 \ No newline at end of file diff --git a/pynestml/codegeneration/resources_nest/point_neuron/common/NeuronHeader.jinja2 b/pynestml/codegeneration/resources_nest/point_neuron/common/NeuronHeader.jinja2 index c19871483..74f1e3598 100644 --- a/pynestml/codegeneration/resources_nest/point_neuron/common/NeuronHeader.jinja2 +++ b/pynestml/codegeneration/resources_nest/point_neuron/common/NeuronHeader.jinja2 @@ -23,6 +23,7 @@ along with NEST. If not, see . {%- import 'directives_cpp/ContinuousInputBufferGetter.jinja2' as continuous_buffer_getter with context %} {%- import 'directives_cpp/FunctionDeclaration.jinja2' as function_declaration with context %} {%- import 'directives_cpp/OutputEvent.jinja2' as output_event with context %} +{%- import 'directives_cpp/WriteInDictionary.jinja2' as write_in_dictionary with context %} /** * {{neuronName}}.h * @@ -360,8 +361,8 @@ public: // Functions for getting/setting parameters and state values. // ------------------------------------------------------------------------- - void get_status(DictionaryDatum &) const override; - void set_status(const DictionaryDatum &) override; + void get_status(DictionaryDatum&) const override; + void set_status(const DictionaryDatum&) override; {% if paired_synapse is defined %} // support for spike archiving @@ -1046,13 +1047,13 @@ inline nest_port_t {{neuronName}}::handles_test_event(nest::DataLoggingRequest& return B_.logger_.connect_logging_device(dlr, recordablesMap_); } -inline void {{neuronName}}::get_status(DictionaryDatum &__d) const +inline void {{neuronName}}::get_status(DictionaryDatum&__d) const { // parameters {%- for variable_symbol in neuron.get_parameter_symbols() %} {%- set variable = utils.get_parameter_variable_by_name(astnode, variable_symbol.get_symbol_name()) %} {%- filter indent(2) %} -{%- include "directives_cpp/WriteInDictionary.jinja2" %} +{{ write_in_dictionary.WriteInDictionary("__d", declarations.print_variable_type(variable_symbol), "nest::" + names_namespace + "::_" + variable_symbol.get_symbol_name(), "get_" + printer_no_origin.print(variable) + "()") }} {%- endfilter %} {%- endfor %} @@ -1060,9 +1061,9 @@ inline void {{neuronName}}::get_status(DictionaryDatum &__d) const {%- for variable_symbol in neuron.get_state_symbols() %} {%- set variable = utils.get_state_variable_by_name(astnode, variable_symbol.get_symbol_name()) %} {%- if not is_delta_kernel(neuron.get_kernel_by_name(variable_symbol.name)) %} -{%- filter indent(2) %} -{%- include "directives_cpp/WriteInDictionary.jinja2" %} -{%- endfilter %} +{%- filter indent(2) %} +{{ write_in_dictionary.WriteInDictionary("__d", declarations.print_variable_type(variable_symbol), "nest::" + names_namespace + "::_" + variable_symbol.get_symbol_name(), "get_" + printer_no_origin.print(variable) + "()") }} +{%- endfilter %} {%- endif -%} {%- endfor %} @@ -1097,11 +1098,11 @@ inline void {{neuronName}}::get_status(DictionaryDatum &__d) const (*__d)[nest::names::recordables] = recordablesMap_.get_list(); {%- if uses_numeric_solver %} {%- if numeric_solver == "rk45" %} - def< double >(__d, nest::{{ neuronName }}_names::gsl_abs_error_tol, P_.__gsl_abs_error_tol); + {{ write_in_dictionary.WriteInDictionary("__d", "double", "nest::" + names_namespace + "::gsl_abs_error_tol", "P_.__gsl_abs_error_tol") }} if ( P_.__gsl_abs_error_tol <= 0. ){ throw nest::BadProperty( "The gsl_abs_error_tol must be strictly positive." ); } - def< double >(__d, nest::{{ neuronName }}_names::gsl_rel_error_tol, P_.__gsl_rel_error_tol); + {{ write_in_dictionary.WriteInDictionary("__d", "double", "nest::" + names_namespace + "::gsl_rel_error_tol", "P_.__gsl_rel_error_tol") }} if ( P_.__gsl_rel_error_tol < 0. ){ throw nest::BadProperty( "The gsl_rel_error_tol must be zero or positive." ); } @@ -1109,7 +1110,7 @@ inline void {{neuronName}}::get_status(DictionaryDatum &__d) const {%- endif %} } -inline void {{neuronName}}::set_status(const DictionaryDatum &__d) +inline void {{neuronName}}::set_status(const DictionaryDatum&__d) { // parameters {%- for variable_symbol in neuron.get_parameter_symbols() %} diff --git a/pynestml/codegeneration/resources_nest/point_neuron/common/SynapseHeader.h.jinja2 b/pynestml/codegeneration/resources_nest/point_neuron/common/SynapseHeader.h.jinja2 index b3cd2142b..e740c84d3 100644 --- a/pynestml/codegeneration/resources_nest/point_neuron/common/SynapseHeader.h.jinja2 +++ b/pynestml/codegeneration/resources_nest/point_neuron/common/SynapseHeader.h.jinja2 @@ -19,6 +19,7 @@ You should have received a copy of the GNU General Public License along with NEST. If not, see . #} {%- import 'directives_cpp/FunctionDeclaration.jinja2' as function_declaration with context %} +{%- import 'directives_cpp/WriteInDictionary.jinja2' as write_in_dictionary with context %} {%- if tracing %}/* generated by {{self._TemplateReference__context.name}} */ {% endif -%} /** * {{synapseName}}.h @@ -1076,7 +1077,7 @@ void {{synapseName}}< targetidentifierT >::get_status( DictionaryDatum& __d ) const { ConnectionBase::get_status( __d ); - def< long >( __d, names::size_of, sizeof( *this ) ); + {{ write_in_dictionary.WriteInDictionary("__d", "long", "names::size_of", "sizeof( *this )") }} // parameters and state variables {%- filter indent(2,True) %} @@ -1086,14 +1087,14 @@ void {%- if not isHomogeneous %} {%- if variable.get_name() == nest_codegen_opt_delay_variable %} {#- special case for NEST special variable delay #} -def< {{ declarations.print_variable_type(variable_symbol) }} >( __d, names::delay, {{ printer.print(variable) }} ); // NEST special case for delay variable -def(__d, nest::{{ synapseName }}_names::_{{ nest_codegen_opt_delay_variable }}, {{ printer.print(variable) }}); -{#- special case for NEST special variable weight #} +{{ write_in_dictionary.WriteInDictionary("__d", declarations.print_variable_type(variable_symbol), "names::delay", printer.print(variable)) }} // NEST special case for delay variable +{{ write_in_dictionary.WriteInDictionary("__d", "double", names_namespace + "::_" + nest_codegen_opt_delay_variable, printer.print(variable)) }} // NEST special case for delay variable {%- elif variable.get_name() == synapse_weight_variable %} -def< {{ declarations.print_variable_type(variable_symbol) }} >( __d, names::weight, {{ printer.print(variable) }} ); // NEST special case for weight variable -def< {{ declarations.print_variable_type(variable_symbol) }} >( __d, nest::{{ synapseName }}_names::_{{ synapse_weight_variable }}, {{ printer.print(variable) }} ); // NEST special case for weight variable -{%- else %} -{%- include "directives_cpp/WriteInDictionary.jinja2" %} +{#- special case for NEST special variable weight #} +{{ write_in_dictionary.WriteInDictionary("__d", declarations.print_variable_type(variable_symbol), "names::weight", printer.print(variable)) }} // NEST special case for weight variable +{{ write_in_dictionary.WriteInDictionary("__d", "double", names_namespace + "::_" + synapse_weight_variable, printer.print(variable)) }} // NEST special case for weight variable +{%- elif not variable_symbol.is_internals() %} +{{ write_in_dictionary.WriteInDictionary("__d", declarations.print_variable_type(variable_symbol), names_namespace + "::_" + variable_symbol.get_symbol_name(), "get_" + printer_no_origin.print(variable) + "()") }} {%- endif %} {%- endif %} {%- endfor %} diff --git a/pynestml/codegeneration/resources_nest/point_neuron/directives_cpp/CommonPropertiesDictionaryWriter.jinja2 b/pynestml/codegeneration/resources_nest/point_neuron/directives_cpp/CommonPropertiesDictionaryWriter.jinja2 index 9791b58d7..f3c433933 100644 --- a/pynestml/codegeneration/resources_nest/point_neuron/directives_cpp/CommonPropertiesDictionaryWriter.jinja2 +++ b/pynestml/codegeneration/resources_nest/point_neuron/directives_cpp/CommonPropertiesDictionaryWriter.jinja2 @@ -2,8 +2,9 @@ In general case creates an @param variable VariableSymbol Variable for which the initialization should be done #} +{%- import 'directives_cpp/WriteInDictionary.jinja2' as write_in_dictionary with context %} {%- if tracing %}/* generated by {{self._TemplateReference__context.name}} */ {% endif %} {%- if variable_symbol.has_vector_parameter() %} {{ raise('Vector parameters not supported in common properties dictionary.') }} {%- endif %} -def< {{ declarations.print_variable_type(variable_symbol) }} >(d, nest::{{ synapseName }}_names::_{{ printer_no_origin.print(variable) }}, this->{{ printer_no_origin.print(variable) }} ); +{{ write_in_dictionary.WriteInDictionary("d", declarations.print_variable_type(variable_symbol), "nest::" + names_namespace + "::_" + variable_symbol.get_symbol_name(), "get_" + printer_no_origin.print(variable) + "()") }} diff --git a/pynestml/codegeneration/resources_nest/point_neuron/directives_cpp/WriteInDictionary.jinja2 b/pynestml/codegeneration/resources_nest/point_neuron/directives_cpp/WriteInDictionary.jinja2 index 2d8d62d40..1f0be5806 100644 --- a/pynestml/codegeneration/resources_nest/point_neuron/directives_cpp/WriteInDictionary.jinja2 +++ b/pynestml/codegeneration/resources_nest/point_neuron/directives_cpp/WriteInDictionary.jinja2 @@ -1,8 +1,6 @@ {# - Generates an instruction to write a value into the dictionary of registered variables. - @param variable VariableSymbol +Write a value into a dictionary. #} -{%- if tracing %}/* generated by {{self._TemplateReference__context.name}} */ {% endif %} -{%- if not variable_symbol.is_internals() %} -def< {{declarations.print_variable_type(variable_symbol)}} >(__d, nest::{{names_namespace}}::_{{variable_symbol.get_symbol_name()}}, get_{{printer_no_origin.print(variable)}}()); -{%- endif %} +{%- macro WriteInDictionary(dict_name, variable_type, variable_name, value) -%} +def< {{ variable_type }} >({{ dict_name }}, {{ variable_name }}, {{ value }}); +{%- endmacro -%} diff --git a/pynestml/codegeneration/resources_nest_compartmental/cm_neuron/@NEURON_NAME@.cpp.jinja2 b/pynestml/codegeneration/resources_nest_compartmental/cm_neuron/@NEURON_NAME@.cpp.jinja2 index 9fc7bf66f..322ac1fe5 100644 --- a/pynestml/codegeneration/resources_nest_compartmental/cm_neuron/@NEURON_NAME@.cpp.jinja2 +++ b/pynestml/codegeneration/resources_nest_compartmental/cm_neuron/@NEURON_NAME@.cpp.jinja2 @@ -1,3 +1,4 @@ +{%- import 'directives_cpp/WriteInDictionary.jinja2' as write_in_dictionary with context %} /* * cm_default.cpp * @@ -78,7 +79,8 @@ nest::{{neuronSpecificFileNamesCmSyns["main"]}}::{{neuronSpecificFileNamesCmSyns void {{neuronSpecificFileNamesCmSyns["main"]}}::get_status( DictionaryDatum& statusdict ) { - def< double >( statusdict, names::V_th, V_th_ ); + {{ write_in_dictionary.WriteInDictionary("statusdict", "double", "V_th", "V_th_") }} + ArchivingNode::get_status( statusdict ); // add all recordables to the status dictionary @@ -94,16 +96,16 @@ void Compartment{{cm_unique_suffix}}* compartment = c_tree_.get_compartment( comp_idx_ ); // add compartment info - def< long >( dd, names::comp_idx, comp_idx_ ); - def< long >( dd, names::parent_idx, compartment->p_index ); + {{ write_in_dictionary.WriteInDictionary("dd", "long", "comp_idx", "comp_idx_") }} + {{ write_in_dictionary.WriteInDictionary("dd", "long", "parent_idx", "compartment->p_index") }} compartment_ad.push_back( dd ); // add receptor info c_tree_.neuron_currents.add_receptor_info( receptor_ad, compartment->comp_index ); } // add compartment info and receptor info to the status dictionary - def< ArrayDatum >( statusdict, names::compartments, compartment_ad ); - def< ArrayDatum >( statusdict, names::receptors, receptor_ad ); + {{ write_in_dictionary.WriteInDictionary("statusdict", "ArrayDatum", "compartments", "compartment_ad") }} + {{ write_in_dictionary.WriteInDictionary("statusdict", "ArrayDatum", "receptors", "receptor_ad") }} } void diff --git a/pynestml/codegeneration/resources_nest_compartmental/cm_neuron/cm_neuroncurrents_@NEURON_NAME@.h.jinja2 b/pynestml/codegeneration/resources_nest_compartmental/cm_neuron/cm_neuroncurrents_@NEURON_NAME@.h.jinja2 index 576abcda0..675f9ea19 100644 --- a/pynestml/codegeneration/resources_nest_compartmental/cm_neuron/cm_neuroncurrents_@NEURON_NAME@.h.jinja2 +++ b/pynestml/codegeneration/resources_nest_compartmental/cm_neuron/cm_neuroncurrents_@NEURON_NAME@.h.jinja2 @@ -21,6 +21,7 @@ along with NEST. If not, see . {%- if tracing %}/* generated by {{self._TemplateReference__context.name}} */ {% endif -%} {%- import 'directives_cpp/FunctionDeclaration.jinja2' as function_declaration with context %} +{%- import 'directives_cpp/WriteInDictionary.jinja2' as write_in_dictionary with context %} #ifndef SYNAPSES_NEAT_H_{{cm_unique_suffix | upper }} #define SYNAPSES_NEAT_H_{{cm_unique_suffix | upper }} @@ -712,30 +713,27 @@ public: void add_receptor_info( ArrayDatum& ad, long compartment_index ) { - {%- with %} - {%- for synapse_name, synapse_info in syns_info.items() %} +{%- for synapse_name, synapse_info in syns_info.items() %} for( std::size_t syn_it = 0; syn_it != {{synapse_name}}{{synapse_suffix}}.neuron_{{synapse_name}}_synapse_count; syn_it++) { DictionaryDatum dd = DictionaryDatum( new Dictionary ); - def< long >( dd, names::receptor_idx, syn_it ); - def< long >( dd, names::comp_idx, compartment_index ); - def< std::string >( dd, names::receptor_type, "{{synapse_name}}" ); +{{ write_in_dictionary.WriteInDictionary("dd", "long", "receptor_idx", "syn_it") }} +{{ write_in_dictionary.WriteInDictionary("dd", "long", "comp_idx", "compartment_index") }} +{{ write_in_dictionary.WriteInDictionary("dd", "std::string", "receptor_type", synapse_name) }} ad.push_back( dd ); } - {% endfor -%} +{% endfor -%} - {%- for continuous_name, continuous_info in con_in_info.items() %} +{%- for continuous_name, continuous_info in con_in_info.items() %} for( std::size_t con_it = 0; con_it != {{continuous_name}}{{continuous_suffix}}.neuron_{{continuous_name}}_continuous_input_count; con_it++) { DictionaryDatum dd = DictionaryDatum( new Dictionary ); - def< long >( dd, names::receptor_idx, con_it ); - def< long >( dd, names::comp_idx, compartment_index ); - def< std::string >( dd, names::receptor_type, "{{continuous_name}}" ); +{{ write_in_dictionary.WriteInDictionary("dd", "long", "receptor_idx", "syn_it") }} +{{ write_in_dictionary.WriteInDictionary("dd", "long", "comp_idx", "compartment_index") }} +{{ write_in_dictionary.WriteInDictionary("dd", "std::string", "receptor_type", continuous_name) }} ad.push_back( dd ); } - {% endfor -%} - - {% endwith -%} +{% endfor -%} }; void set_buffers( std::vector< RingBuffer >& buffers) diff --git a/pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryMemberInitialization.jinja2 b/pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryMemberInitialization.jinja2 deleted file mode 120000 index b624869a4..000000000 --- a/pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryMemberInitialization.jinja2 +++ /dev/null @@ -1 +0,0 @@ -../../resources_nest/point_neuron/directives_cpp/CommonPropertiesDictionaryMemberInitialization.jinja2 \ No newline at end of file diff --git a/pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryReader.jinja2 b/pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryReader.jinja2 deleted file mode 120000 index a6430d12a..000000000 --- a/pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryReader.jinja2 +++ /dev/null @@ -1 +0,0 @@ -../../resources_nest/point_neuron/directives_cpp/CommonPropertiesDictionaryReader.jinja2 \ No newline at end of file diff --git a/pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryWriter.jinja2 b/pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryWriter.jinja2 deleted file mode 120000 index 3863a9aba..000000000 --- a/pynestml/codegeneration/resources_spinnaker/directives_cpp/CommonPropertiesDictionaryWriter.jinja2 +++ /dev/null @@ -1 +0,0 @@ -../../resources_nest/point_neuron/directives_cpp/CommonPropertiesDictionaryWriter.jinja2 \ No newline at end of file diff --git a/pynestml/codegeneration/resources_spinnaker/directives_cpp/ReadFromDictionaryToTmp.jinja2 b/pynestml/codegeneration/resources_spinnaker/directives_cpp/ReadFromDictionaryToTmp.jinja2 deleted file mode 120000 index c397e3981..000000000 --- a/pynestml/codegeneration/resources_spinnaker/directives_cpp/ReadFromDictionaryToTmp.jinja2 +++ /dev/null @@ -1 +0,0 @@ -../../resources_nest/point_neuron/directives_cpp/ReadFromDictionaryToTmp.jinja2 \ No newline at end of file diff --git a/pynestml/codegeneration/resources_spinnaker/directives_cpp/WriteInDictionary.jinja2 b/pynestml/codegeneration/resources_spinnaker/directives_cpp/WriteInDictionary.jinja2 deleted file mode 120000 index f7356be5e..000000000 --- a/pynestml/codegeneration/resources_spinnaker/directives_cpp/WriteInDictionary.jinja2 +++ /dev/null @@ -1 +0,0 @@ -../../resources_nest/point_neuron/directives_cpp/WriteInDictionary.jinja2 \ No newline at end of file