From 2c73b806bda42676b75834e027cbe0f68796b5d9 Mon Sep 17 00:00:00 2001 From: mahipalimkar Date: Mon, 24 Mar 2025 17:53:47 +0000 Subject: [PATCH 1/3] Changed before_run code in numpy and c++ template --- .../numpy_rt/templates/spikegenerator.py_ | 44 ++++++++++---- .../templates/spikegenerator.cpp | 58 ++++++++++++++----- 2 files changed, 77 insertions(+), 25 deletions(-) diff --git a/brian2/codegen/runtime/numpy_rt/templates/spikegenerator.py_ b/brian2/codegen/runtime/numpy_rt/templates/spikegenerator.py_ index 63c16767c..f0d862cb0 100644 --- a/brian2/codegen/runtime/numpy_rt/templates/spikegenerator.py_ +++ b/brian2/codegen/runtime/numpy_rt/templates/spikegenerator.py_ @@ -1,5 +1,32 @@ -{# USES_VARIABLES { _spikespace, neuron_index, _timebins, _period_bins, _lastindex, t_in_timesteps } #} -{% extends 'common_group.py_' %} +{% extends 'common_group.py.jinja2' %} + +{% block before_code %} +# Copy of the SpikeGeneratorGroup.before_run code +dt = {{dt.item()}} # Always copy dt +period = {{period_}} # Always copy period + +# Always recalculate timesteps +current_t = {{t}}[0] +timesteps = ({{_spike_time}} / dt).astype(np.int32) +current_step = int(current_t / dt) + +# Always update _lastindex +in_the_past = np.nonzero(timesteps < current_step)[0] +if len(in_the_past): + {{_lastindex}}[0] = in_the_past[-1] + 1 +else: + {{_lastindex}}[0] = 0 + +# Always recalculate _timebins +shift = 1e-3 * dt +timebins = np.asarray(({{_spike_time}} + shift) / dt, dtype=np.int32) + +{{_timebins}}[:] = timebins + +# Always recalculate period_bins (ignore limit checks) +period_bins = int(round(period / dt)) +{{_period_bins}}[0] = period_bins +{% endblock %} {% block maincode %} _the_period = {{_period_bins}} @@ -8,18 +35,13 @@ _n_spikes = 0 _lastindex_before = {{_lastindex}} -if _the_period > 0: - _timebin %= _the_period - # If there is a periodicity in the SpikeGenerator, we need to reset the - # lastindex when the period has passed - if _lastindex_before > 0 and {{_timebins}}[_lastindex_before - 1] >= _timebin: - _lastindex_before = 0 +# Always reset _lastindex if period is applied +_timebin %= _the_period +_lastindex_before = 0 -_n_spikes = _numpy.searchsorted({{_timebins}}[_lastindex_before:], - _timebin, side='right') +_n_spikes = _numpy.searchsorted({{_timebins}}, _timebin, side='right') {{_lastindex}} = _lastindex_before + _n_spikes - _indices = {{neuron_index}}[_lastindex_before:_lastindex_before+_n_spikes] {{_spikespace}}[:_n_spikes] = _indices diff --git a/brian2/devices/cpp_standalone/templates/spikegenerator.cpp b/brian2/devices/cpp_standalone/templates/spikegenerator.cpp index 691a55805..425de1540 100644 --- a/brian2/devices/cpp_standalone/templates/spikegenerator.cpp +++ b/brian2/devices/cpp_standalone/templates/spikegenerator.cpp @@ -1,23 +1,54 @@ -{# USES_VARIABLES { _spikespace, neuron_index, _timebins, _period_bins, _lastindex, t_in_timesteps, N } #} +{# USES_VARIABLES { _spikespace, neuron_index, _timebins, _period_bins, _lastindex, t_in_timesteps, N, _spike_time, dt, period } #} {% extends 'common_group.cpp' %} + +{% block before_code %} + // Copy of the SpikeGeneratorGroup.before_run code + const double _dt = {{dt.item()}}; // Always copy dt + const double _period = {{period_}}; // Always copy period + + // Always recalculate _timesteps + const double _current_t = {{t}}[0]; + std::vector _timesteps({{_spike_time}}.size()); + for (size_t i = 0; i < _timesteps.size(); i++) { + _timesteps[i] = static_cast({{_spike_time}}[i] / _dt); + } + const int32_t _current_step = static_cast(_current_t / _dt); + + // Always update _lastindex + int32_t _last_idx = 0; + for (size_t i = 0; i < _timesteps.size(); i++) { + if (_timesteps[i] < _current_step) { + _last_idx = i + 1; + } else { + break; + } + } + {{_lastindex}} = _last_idx; + + // Always recalculate _timebins + const double _shift = 1e-3 * _dt; + std::vector _timebins({{_spike_time}}.size()); + for (size_t i = 0; i < _timebins.size(); i++) { + _timebins[i] = static_cast({{_spike_time}}[i] + _shift) / _dt; + } + {{_timebins}} = _timebins; + + // Always recalculate _period_bins (no checks) + {{_period_bins}} = static_cast(std::round(_period / _dt)); +{% endblock %} + {% block maincode %} const int32_t _the_period = {{_period_bins}}; int32_t _timebin = {{t_in_timesteps}}; - const int32_t _n_spikes = 0; - - if (_the_period > 0) { - _timebin %= _the_period; - // If there is a periodicity in the SpikeGenerator, we need to reset the - // lastindex when the period has passed - if ({{_lastindex}} > 0 && {{_timebins}}[{{_lastindex}} - 1] >= _timebin) - {{_lastindex}} = 0; - } + + // Always recalculate timebin with period + _timebin %= _the_period; + {{_lastindex}} = 0; int32_t _cpp_numspikes = 0; - for(size_t _idx={{_lastindex}}; _idx < _num_timebins; _idx++) - { + for (size_t _idx = {{_lastindex}}; _idx < _num_timebins; _idx++) { if ({{_timebins}}[_idx] > _timebin) break; @@ -28,5 +59,4 @@ {{_lastindex}} += _cpp_numspikes; - -{% endblock %} \ No newline at end of file +{% endblock %} From b92b4ff9f66fe1d35e216b71802dcc6f292e1a98 Mon Sep 17 00:00:00 2001 From: mahipalimkar Date: Mon, 24 Mar 2025 19:19:19 +0000 Subject: [PATCH 2/3] Modified before_run code in numpy, c++ templates --- .../runtime/numpy_rt/templates/spikegenerator.py_ | 5 +++-- .../cpp_standalone/templates/spikegenerator.cpp | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/brian2/codegen/runtime/numpy_rt/templates/spikegenerator.py_ b/brian2/codegen/runtime/numpy_rt/templates/spikegenerator.py_ index f0d862cb0..ca9d17755 100644 --- a/brian2/codegen/runtime/numpy_rt/templates/spikegenerator.py_ +++ b/brian2/codegen/runtime/numpy_rt/templates/spikegenerator.py_ @@ -6,7 +6,8 @@ dt = {{dt.item()}} # Always copy dt period = {{period_}} # Always copy period # Always recalculate timesteps -current_t = {{t}}[0] +from brian2 import defaultclock # Use Brian 2's clock instead of 't' +current_t = defaultclock.t timesteps = ({{_spike_time}} / dt).astype(np.int32) current_step = int(current_t / dt) @@ -30,7 +31,7 @@ period_bins = int(round(period / dt)) {% block maincode %} _the_period = {{_period_bins}} -_timebin = {{t_in_timesteps}} +_timebin = int(defaultclock.t / {{dt.item()}}) # Use Brian 2's clock instead of 't_in_timesteps' _n_spikes = 0 _lastindex_before = {{_lastindex}} diff --git a/brian2/devices/cpp_standalone/templates/spikegenerator.cpp b/brian2/devices/cpp_standalone/templates/spikegenerator.cpp index 425de1540..2e62218fb 100644 --- a/brian2/devices/cpp_standalone/templates/spikegenerator.cpp +++ b/brian2/devices/cpp_standalone/templates/spikegenerator.cpp @@ -1,4 +1,4 @@ -{# USES_VARIABLES { _spikespace, neuron_index, _timebins, _period_bins, _lastindex, t_in_timesteps, N, _spike_time, dt, period } #} +{# USES_VARIABLES { _spikespace, neuron_index, _timebins, _period_bins, _lastindex, N, _spike_time, dt, period } #} {% extends 'common_group.cpp' %} {% block before_code %} @@ -7,12 +7,14 @@ const double _period = {{period_}}; // Always copy period // Always recalculate _timesteps - const double _current_t = {{t}}[0]; std::vector _timesteps({{_spike_time}}.size()); for (size_t i = 0; i < _timesteps.size(); i++) { _timesteps[i] = static_cast({{_spike_time}}[i] / _dt); } - const int32_t _current_step = static_cast(_current_t / _dt); + + // Get current simulation time from Brian 2's clock instead of 't' + extern double defaultclock_t; + const int32_t _current_step = static_cast(defaultclock_t / _dt); // Always update _lastindex int32_t _last_idx = 0; @@ -40,7 +42,7 @@ {% block maincode %} const int32_t _the_period = {{_period_bins}}; - int32_t _timebin = {{t_in_timesteps}}; + int32_t _timebin = static_cast(defaultclock_t / {{dt.item()}}); // Use Brian 2's clock instead of 't_in_timesteps' // Always recalculate timebin with period _timebin %= _the_period; From 8ace7ee13161603a0258164e0db777e3e077bf47 Mon Sep 17 00:00:00 2001 From: mahipalimkar Date: Mon, 24 Mar 2025 19:23:15 +0000 Subject: [PATCH 3/3] Added before_run codeblock in numpy and C++ templates --- brian2/devices/cpp_standalone/templates/spikegenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brian2/devices/cpp_standalone/templates/spikegenerator.cpp b/brian2/devices/cpp_standalone/templates/spikegenerator.cpp index 2e62218fb..eeaba2580 100644 --- a/brian2/devices/cpp_standalone/templates/spikegenerator.cpp +++ b/brian2/devices/cpp_standalone/templates/spikegenerator.cpp @@ -35,7 +35,7 @@ } {{_timebins}} = _timebins; - // Always recalculate _period_bins (no checks) + // Always recalculate _period_bins {{_period_bins}} = static_cast(std::round(_period / _dt)); {% endblock %}