diff --git a/models/clopath_synapse.h b/models/clopath_synapse.h index 0252e7f019..f707aefb5e 100644 --- a/models/clopath_synapse.h +++ b/models/clopath_synapse.h @@ -61,13 +61,6 @@ synapses can only be connected to neuron models that are capable of doing this archiving. So far, compatible models are ``aeif_psc_delta_clopath`` and ``hh_psc_alpha_clopath``. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - See also [2]_, [3]_. Parameters diff --git a/models/cont_delay_synapse.h b/models/cont_delay_synapse.h index a5759c2622..340cd6ef5b 100644 --- a/models/cont_delay_synapse.h +++ b/models/cont_delay_synapse.h @@ -222,7 +222,7 @@ cont_delay_synapse< targetidentifierT >::send( Event& e, size_t t, const CommonS e.set_receiver( *get_target( t ) ); e.set_weight( weight_ ); e.set_rport( get_rport() ); - double orig_event_offset = e.get_offset(); + double orig_event_offset = e.get_stamp().get_offset(); double total_offset = orig_event_offset + delay_offset_; // As far as i have seen, offsets are outside of tics regime provided // by the Time-class to allow more precise spike-times, hence comparing @@ -231,16 +231,16 @@ cont_delay_synapse< targetidentifierT >::send( Event& e, size_t t, const CommonS if ( total_offset < Time::get_resolution().get_ms() ) { e.set_delay_steps( get_delay_steps() ); - e.set_offset( total_offset ); + e.get_stamp().set_offset( total_offset ); } else { e.set_delay_steps( get_delay_steps() - 1 ); - e.set_offset( total_offset - Time::get_resolution().get_ms() ); + e.get_stamp().set_offset( total_offset - Time::get_resolution().get_ms() ); } e(); // reset offset to original value - e.set_offset( orig_event_offset ); + e.get_stamp().set_offset( orig_event_offset ); return true; } diff --git a/models/eprop_synapse_bsshslm_2020.h b/models/eprop_synapse_bsshslm_2020.h index 52223ca67b..bb8742461d 100644 --- a/models/eprop_synapse_bsshslm_2020.h +++ b/models/eprop_synapse_bsshslm_2020.h @@ -76,13 +76,6 @@ For more information on the optimizers, see the documentation of the weight opti Details on the event-based NEST implementation of e-prop can be found in [2]_. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/ht_synapse.h b/models/ht_synapse.h index 1221e89116..d83c8a0b20 100644 --- a/models/ht_synapse.h +++ b/models/ht_synapse.h @@ -54,13 +54,6 @@ Synaptic dynamics are given by For implementation details see: `HillTononi_model <../model_details/HillTononiModels.ipynb>`_ -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/iaf_bw_2001.cpp b/models/iaf_bw_2001.cpp index e030579183..ff92528d8f 100644 --- a/models/iaf_bw_2001.cpp +++ b/models/iaf_bw_2001.cpp @@ -474,7 +474,7 @@ nest::iaf_bw_2001::update( Time const& origin, const long from, const long to ) S_.s_NMDA_pre += s_NMDA_delta; SpikeEvent se; - se.set_offset( s_NMDA_delta ); + se.get_stamp().set_offset( s_NMDA_delta ); kernel().event_delivery_manager.send( *this, se, lag ); } @@ -509,7 +509,7 @@ nest::iaf_bw_2001::handle( SpikeEvent& e ) } else { - B_.spikes_[ rport - 1 ].add_value( steps, e.get_weight() * e.get_multiplicity() * e.get_offset() ); + B_.spikes_[ rport - 1 ].add_value( steps, e.get_weight() * e.get_multiplicity() * e.get_stamp().get_offset() ); } } diff --git a/models/iaf_chxk_2008.cpp b/models/iaf_chxk_2008.cpp index 62559536ae..0c75b37698 100644 --- a/models/iaf_chxk_2008.cpp +++ b/models/iaf_chxk_2008.cpp @@ -425,7 +425,7 @@ nest::iaf_chxk_2008::update( Time const& origin, const long from, const long to set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; - se.set_offset( dt ); + se.get_stamp().set_offset( dt ); kernel().event_delivery_manager.send( *this, se, lag ); } diff --git a/models/iaf_psc_alpha_ps.cpp b/models/iaf_psc_alpha_ps.cpp index acc3e06d5a..99f567ad1f 100644 --- a/models/iaf_psc_alpha_ps.cpp +++ b/models/iaf_psc_alpha_ps.cpp @@ -470,7 +470,7 @@ nest::iaf_psc_alpha_ps::handle( SpikeEvent& e ) B_.events_.add_spike( e.get_rel_delivery_steps( nest::kernel().simulation_manager.get_slice_origin() ), Tdeliver, - e.get_offset(), + e.get_stamp().get_offset(), e.get_weight() * e.get_multiplicity() ); } @@ -547,7 +547,7 @@ nest::iaf_psc_alpha_ps::emit_spike_( Time const& origin, const long lag, const d // send spike set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; - se.set_offset( S_.last_spike_offset_ ); + se.get_stamp().set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); return; @@ -569,7 +569,7 @@ nest::iaf_psc_alpha_ps::emit_instant_spike_( Time const& origin, const long lag, // send spike set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; - se.set_offset( S_.last_spike_offset_ ); + se.get_stamp().set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); return; diff --git a/models/iaf_psc_delta_ps.cpp b/models/iaf_psc_delta_ps.cpp index 1da42f3dcc..7dda17ca5a 100644 --- a/models/iaf_psc_delta_ps.cpp +++ b/models/iaf_psc_delta_ps.cpp @@ -480,7 +480,7 @@ nest::iaf_psc_delta_ps::emit_spike_( Time const& origin, const long lag, const d // send spike set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; - se.set_offset( S_.last_spike_offset_ ); + se.get_stamp().set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); } @@ -500,7 +500,7 @@ nest::iaf_psc_delta_ps::emit_instant_spike_( Time const& origin, const long lag, // send spike set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; - se.set_offset( S_.last_spike_offset_ ); + se.get_stamp().set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); } @@ -516,7 +516,7 @@ iaf_psc_delta_ps::handle( SpikeEvent& e ) const long Tdeliver = e.get_stamp().get_steps() + e.get_delay_steps() - 1; B_.events_.add_spike( e.get_rel_delivery_steps( kernel().simulation_manager.get_slice_origin() ), Tdeliver, - e.get_offset(), + e.get_stamp().get_offset(), e.get_weight() * e.get_multiplicity() ); } diff --git a/models/iaf_psc_exp_ps.cpp b/models/iaf_psc_exp_ps.cpp index 71f83acc78..efa2938765 100644 --- a/models/iaf_psc_exp_ps.cpp +++ b/models/iaf_psc_exp_ps.cpp @@ -445,7 +445,7 @@ nest::iaf_psc_exp_ps::handle( SpikeEvent& e ) B_.events_.add_spike( e.get_rel_delivery_steps( nest::kernel().simulation_manager.get_slice_origin() ), Tdeliver, - e.get_offset(), + e.get_stamp().get_offset(), e.get_weight() * e.get_multiplicity() ); } @@ -516,7 +516,7 @@ nest::iaf_psc_exp_ps::emit_spike_( const Time& origin, const long lag, const dou set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; - se.set_offset( S_.last_spike_offset_ ); + se.get_stamp().set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); } @@ -537,7 +537,7 @@ nest::iaf_psc_exp_ps::emit_instant_spike_( const Time& origin, const long lag, c set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; - se.set_offset( S_.last_spike_offset_ ); + se.get_stamp().set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); } diff --git a/models/iaf_psc_exp_ps_lossless.cpp b/models/iaf_psc_exp_ps_lossless.cpp index dcbf6435bf..c98b70ca65 100644 --- a/models/iaf_psc_exp_ps_lossless.cpp +++ b/models/iaf_psc_exp_ps_lossless.cpp @@ -489,7 +489,7 @@ nest::iaf_psc_exp_ps_lossless::handle( SpikeEvent& e ) B_.events_.add_spike( e.get_rel_delivery_steps( nest::kernel().simulation_manager.get_slice_origin() ), Tdeliver, - e.get_offset(), + e.get_stamp().get_offset(), e.get_weight() * e.get_multiplicity() ); } @@ -559,7 +559,7 @@ nest::iaf_psc_exp_ps_lossless::emit_spike_( const Time& origin, const long lag, set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; - se.set_offset( S_.last_spike_offset_ ); + se.get_stamp().set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); } @@ -580,7 +580,7 @@ nest::iaf_psc_exp_ps_lossless::emit_instant_spike_( const Time& origin, const lo set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; - se.set_offset( S_.last_spike_offset_ ); + se.get_stamp().set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); } diff --git a/models/iaf_tum_2000.cpp b/models/iaf_tum_2000.cpp index 29ae084558..bbafdd07fe 100644 --- a/models/iaf_tum_2000.cpp +++ b/models/iaf_tum_2000.cpp @@ -429,7 +429,7 @@ nest::iaf_tum_2000::update( const Time& origin, const long from, const long to ) // send spike with datafield SpikeEvent se; - se.set_offset( delta_y_tsp ); + se.get_stamp().set_offset( delta_y_tsp ); kernel().event_delivery_manager.send( *this, se, lag ); } @@ -458,7 +458,7 @@ nest::iaf_tum_2000::handle( SpikeEvent& e ) if ( e.get_rport() == 1 ) { - s *= e.get_offset(); + s *= e.get_stamp().get_offset(); } // separate buffer channels for excitatory and inhibitory inputs diff --git a/models/jonke_synapse.h b/models/jonke_synapse.h index e8bb578566..c9bd4e81d2 100644 --- a/models/jonke_synapse.h +++ b/models/jonke_synapse.h @@ -74,13 +74,6 @@ and This makes it possible to implement update rules which approximate the rule stated in [1]_, and for examples, the rules given in [2]_ and [3]_. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/parrot_neuron_ps.cpp b/models/parrot_neuron_ps.cpp index 18140972a8..6b9c7e1c85 100644 --- a/models/parrot_neuron_ps.cpp +++ b/models/parrot_neuron_ps.cpp @@ -81,7 +81,7 @@ parrot_neuron_ps::update( Time const& origin, long const from, long const to ) // send spike SpikeEvent se; se.set_multiplicity( multiplicity ); - se.set_offset( ev_offset ); + se.get_stamp().set_offset( ev_offset ); kernel().event_delivery_manager.send( *this, se, lag ); for ( unsigned long i = 0; i < multiplicity; ++i ) @@ -121,7 +121,7 @@ parrot_neuron_ps::handle( SpikeEvent& e ) // parrot ignores weight of incoming connection, store multiplicity B_.events_.add_spike( e.get_rel_delivery_steps( nest::kernel().simulation_manager.get_slice_origin() ), Tdeliver, - e.get_offset(), + e.get_stamp().get_offset(), static_cast< double >( e.get_multiplicity() ) ); } } diff --git a/models/poisson_generator_ps.cpp b/models/poisson_generator_ps.cpp index 8f587de1a3..d336986ee5 100644 --- a/models/poisson_generator_ps.cpp +++ b/models/poisson_generator_ps.cpp @@ -262,7 +262,7 @@ nest::poisson_generator_ps::event_hook( DSSpikeEvent& e ) while ( nextspk.first <= V_.t_max_active_ ) { e.set_stamp( nextspk.first ); - e.set_offset( nextspk.second ); + e.get_stamp().set_offset( nextspk.second ); e.get_receiver().handle( e ); // Draw time of next spike diff --git a/models/quantal_stp_synapse.h b/models/quantal_stp_synapse.h index 3c866a3674..c5841e1a5f 100644 --- a/models/quantal_stp_synapse.h +++ b/models/quantal_stp_synapse.h @@ -52,13 +52,6 @@ equations is taken from Maass and Markram 2002 [3]_. The connection weight is interpreted as the maximal weight that can be obtained if all n release sites are activated. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/spike_generator.cpp b/models/spike_generator.cpp index c6153ede4c..0294c16072 100644 --- a/models/spike_generator.cpp +++ b/models/spike_generator.cpp @@ -376,7 +376,7 @@ nest::spike_generator::update( Time const& sliceT0, const long from, const long if ( P_.precise_times_ ) { - se->set_offset( P_.spike_offsets_[ S_.position_ ] ); + se->get_stamp().set_offset( P_.spike_offsets_[ S_.position_ ] ); } if ( not P_.spike_multiplicities_.empty() ) diff --git a/models/spike_train_injector.cpp b/models/spike_train_injector.cpp index 9d596a8e5a..78d0b0f72b 100644 --- a/models/spike_train_injector.cpp +++ b/models/spike_train_injector.cpp @@ -368,7 +368,7 @@ spike_train_injector::update( Time const& sliceT0, const long from, const long t if ( P_.precise_times_ ) { - se.set_offset( P_.spike_offsets_[ S_.position_ ] ); + se.get_stamp().set_offset( P_.spike_offsets_[ S_.position_ ] ); } if ( not P_.spike_multiplicities_.empty() ) diff --git a/models/stdp_dopamine_synapse.h b/models/stdp_dopamine_synapse.h index 118c0054ff..1ade54c0a0 100644 --- a/models/stdp_dopamine_synapse.h +++ b/models/stdp_dopamine_synapse.h @@ -54,13 +54,6 @@ of neurons. The spikes emitted by the pool of dopamine neurons are delivered to the synapse via the assigned volume transmitter. The dopaminergic dynamics is calculated in the synapse itself. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/stdp_facetshw_synapse_hom.h b/models/stdp_facetshw_synapse_hom.h index 2b103eed48..0d7928912f 100644 --- a/models/stdp_facetshw_synapse_hom.h +++ b/models/stdp_facetshw_synapse_hom.h @@ -54,13 +54,6 @@ The modified spike pairing scheme requires the calculation of ``tau_minus_`` within this synapse and not at the neuron site via ``Kplus_`` like in ``stdp_synapse_hom``. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - The synapse IDs are assigned to each synapse in an ascending order (0,1,2, ...) according their first presynaptic activity and is used to group synapses that are updated at once. It is possible to avoid activity dependent synapse diff --git a/models/stdp_nn_pre_centered_synapse.h b/models/stdp_nn_pre_centered_synapse.h index ec2791efbf..111d1342b2 100644 --- a/models/stdp_nn_pre_centered_synapse.h +++ b/models/stdp_nn_pre_centered_synapse.h @@ -76,13 +76,6 @@ occurrence, and is reset to 0 on a post-spike occurrence. The postsynaptic trace (implemented on the postsynaptic neuron side) decays with the time constant ``tau_minus`` and increases to 1 on a post-spike occurrence. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/stdp_nn_restr_synapse.h b/models/stdp_nn_restr_synapse.h index 7562266dc3..b586546086 100644 --- a/models/stdp_nn_restr_synapse.h +++ b/models/stdp_nn_restr_synapse.h @@ -73,13 +73,6 @@ eligibility trace [1]_ (implemented on the postsynaptic neuron side). It decays exponentially with the time constant ``tau_minus`` and increases to 1 on a post-spike occurrence (instead of increasing by 1 as in ``stdp_synapse``). -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/stdp_nn_symm_synapse.h b/models/stdp_nn_symm_synapse.h index 92970ec8ec..4e50792e3b 100644 --- a/models/stdp_nn_symm_synapse.h +++ b/models/stdp_nn_symm_synapse.h @@ -73,13 +73,6 @@ occurrence. The postsynaptic trace (implemented on the postsynaptic neuron side) decays with the time constant ``tau_minus`` and increases to 1 on a post-spike occurrence. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/stdp_pl_synapse_hom.h b/models/stdp_pl_synapse_hom.h index b01a79c79d..e130135bbc 100644 --- a/models/stdp_pl_synapse_hom.h +++ b/models/stdp_pl_synapse_hom.h @@ -60,13 +60,6 @@ Parameters The parameters can only be set by SetDefaults and apply to all synapses of the model. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - References ++++++++++ diff --git a/models/stdp_synapse.h b/models/stdp_synapse.h index 61b3cbcafa..a878068314 100644 --- a/models/stdp_synapse.h +++ b/models/stdp_synapse.h @@ -53,13 +53,6 @@ Description dependent plasticity (as defined in [1]_). Here the weight dependence exponent can be set separately for potentiation and depression. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - See also [2]_, [3]_, [4]_. Parameters diff --git a/models/stdp_synapse_hom.h b/models/stdp_synapse_hom.h index 803f513585..d86e9bc686 100644 --- a/models/stdp_synapse_hom.h +++ b/models/stdp_synapse_hom.h @@ -56,13 +56,6 @@ exponent can be set separately for potentiation and depression. * Guetig STDP [1]_ mu_plus = mu_minus = [0.0,1.0] * van Rossum STDP [4]_ mu_plus = 0.0 mu_minus = 1.0 -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/stdp_triplet_synapse.h b/models/stdp_triplet_synapse.h index f2a8f8ced3..305e4e978d 100644 --- a/models/stdp_triplet_synapse.h +++ b/models/stdp_triplet_synapse.h @@ -57,13 +57,6 @@ plasticity accounting for spike triplet effects (as defined in [1]_). without changing the postsynaptic archiving-node (clip the traces to a maximum of 1). -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/tsodyks2_synapse.h b/models/tsodyks2_synapse.h index a57f300244..fc117b21a7 100644 --- a/models/tsodyks2_synapse.h +++ b/models/tsodyks2_synapse.h @@ -54,13 +54,6 @@ The parameter ``A_se`` from the publications is represented by the synaptic weight. The variable x in the synapse properties is the factor that scales the synaptic weight. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - See also [3]_. Under identical conditions, the tsodyks2_synapse produces slightly diff --git a/models/tsodyks_synapse.h b/models/tsodyks_synapse.h index bb6c1e3938..54467a3432 100644 --- a/models/tsodyks_synapse.h +++ b/models/tsodyks_synapse.h @@ -87,13 +87,6 @@ neuron, however, might choose to have a synaptic current that is not necessarily identical to the concentration of transmitter ``y(t)`` in the synaptic cleft. It may realize an arbitrary postsynaptic effect depending on ``y(t)``. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/tsodyks_synapse_hom.h b/models/tsodyks_synapse_hom.h index e01c49f04b..cf1c24fb8f 100644 --- a/models/tsodyks_synapse_hom.h +++ b/models/tsodyks_synapse_hom.h @@ -86,13 +86,6 @@ might choose to have a synaptic current that is not necessarily identical to the concentration of transmitter y(t) in the synaptic cleft. It may realize an arbitrary postsynaptic effect depending on y(t). -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/urbanczik_synapse.h b/models/urbanczik_synapse.h index 04fcd05d06..a8560148d9 100644 --- a/models/urbanczik_synapse.h +++ b/models/urbanczik_synapse.h @@ -61,13 +61,6 @@ which is continuous in time. Therefore they can only be connected to neuron models that are capable of doing this archiving. So far, the only compatible model is :doc:`pp_cond_exp_mc_urbanczik `. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/models/vogels_sprekeler_synapse.h b/models/vogels_sprekeler_synapse.h index cf30380486..d37e1c9c57 100644 --- a/models/vogels_sprekeler_synapse.h +++ b/models/vogels_sprekeler_synapse.h @@ -47,13 +47,6 @@ irrespective of the order of the pre- and postsynaptic spikes. Each pre-synaptic spike also causes a constant depression of the synaptic weight which differentiates this rule from other classical STDP rules. -.. warning:: - - This synaptic plasticity rule does not take - :ref:`precise spike timing ` into - account. When calculating the weight update, the precise spike time part - of the timestamp is ignored. - Parameters ++++++++++ diff --git a/nestkernel/event.cpp b/nestkernel/event.cpp index 6d33a5f615..4ba4a79a02 100644 --- a/nestkernel/event.cpp +++ b/nestkernel/event.cpp @@ -41,7 +41,6 @@ Event::Event() , d_( 1 ) , stamp_( Time::step( 0 ) ) , stamp_steps_( 0 ) - , offset_( 0.0 ) , w_( 0.0 ) { } diff --git a/nestkernel/event.h b/nestkernel/event.h index 13860bd88a..ceaa309894 100644 --- a/nestkernel/event.h +++ b/nestkernel/event.h @@ -122,14 +122,14 @@ class Event virtual void operator()() = 0; /** - * Change pointer to receiving Node. + * Return reference to receiving Node. */ - void set_receiver( Node& ); + Node& get_receiver() const; /** - * Return reference to receiving Node. + * Change pointer to receiving Node. */ - Node& get_receiver() const; + void set_receiver( Node& ); /** * Return node ID of receiving Node. @@ -172,33 +172,21 @@ class Event void set_sender_node_id_info( const size_t tid, const synindex syn_id, const size_t lcid ); /** - * Return time stamp of the event. - * - * The stamp denotes the time when the event was created. - * The resolution of Stamp is limited by the time base of the - * simulation kernel (@see class nest::Time). - * If this resolution is not fine enough, the creation time - * can be corrected by using the time attribute. - */ - Time const& get_stamp() const; - - /** - * Set the transmission delay of the event. + * Return transmission delay of the event. * * The delay refers to the time until the event is * expected to arrive at the receiver. - * @param t delay. */ - - void set_delay_steps( long ); + long get_delay_steps() const; /** - * Return transmission delay of the event. + * Set the transmission delay of the event. * * The delay refers to the time until the event is * expected to arrive at the receiver. + * @param d delay */ - long get_delay_steps() const; + void set_delay_steps( long d ); /** * Relative spike delivery time in steps. @@ -242,13 +230,14 @@ class Event * object. * @param p Port number of the connection, or -1 if unknown. */ + void set_port( size_t p ); /** * Set the receiver port number (r-port). * * When a connection is established, the receiving Node may issue - * a port number (r-port) to distinguish the incomin + * a port number (r-port) to distinguish the incoming * connection. By the default, the r-port is not used and its port * number defaults to zero. * @param p Receiver port number of the connection, or 0 if unused. @@ -256,27 +245,8 @@ class Event void set_rport( size_t p ); /** - * Return the creation time offset of the Event. * - * Each Event carries the exact time of creation. This - * time need not coincide with an integral multiple of the - * temporal resolution. Rather, Events may be created at any point - * in time. - */ - double get_offset() const; - - /** - * Set the creation time of the Event. * - * Each Event carries the exact time of creation in realtime. This - * time need not coincide with an integral multiple of the - * temporal resolution. Rather, Events may be created at any point - * in time. - * @param t Creation time in realtime. t has to be in [0, h). - */ - void set_offset( double t ); - - /** * Return the weight. */ double get_weight() const; @@ -314,6 +284,20 @@ class Event */ bool is_valid() const; + /** + * Return time stamp of the event. + * + * The stamp denotes the time when the event was created. + */ + Time const& get_stamp() const; + + /** + * Return time stamp of the event. + * + * The stamp denotes the time when the event was created. + */ + Time& get_stamp(); + /** * Set the time stamp of the event. * @@ -384,16 +368,7 @@ class Event mutable long stamp_steps_; /** - * Offset for precise spike times. * - * offset_ specifies a correction to the creation time. - * If the resolution of stamp is not sufficiently precise, - * this attribute can be used to correct the creation time. - * offset_ has to be in [0, h). - */ - double offset_; - - /** * Weight of the connection. */ double w_; @@ -964,6 +939,12 @@ Event::get_stamp() const return stamp_; } +inline Time& +Event::get_stamp() +{ + return stamp_; +} + inline void Event::set_stamp( Time const& s ) { @@ -996,18 +977,6 @@ Event::set_delay_steps( long d ) d_ = d; } -inline double -Event::get_offset() const -{ - return offset_; -} - -inline void -Event::set_offset( double t ) -{ - offset_ = t; -} - inline size_t Event::get_port() const { diff --git a/nestkernel/event_delivery_manager.cpp b/nestkernel/event_delivery_manager.cpp index dbb98504d5..4d827e6874 100644 --- a/nestkernel/event_delivery_manager.cpp +++ b/nestkernel/event_delivery_manager.cpp @@ -668,7 +668,7 @@ EventDeliveryManager::deliver_events_( const size_t tid, const std::vector< Spik { const SpikeDataT& spike_data = recv_buffer[ rank * spike_buffer_size_per_rank + i * SPIKES_PER_BATCH + j ]; se_batch[ j ].set_stamp( prepared_timestamps[ spike_data.get_lag() ] ); - se_batch[ j ].set_offset( spike_data.get_offset() ); + se_batch[ j ].get_stamp().set_offset( spike_data.get_offset() ); tid_batch[ j ] = spike_data.get_tid(); syn_id_batch[ j ] = spike_data.get_syn_id(); lcid_batch[ j ] = spike_data.get_lcid(); @@ -689,7 +689,7 @@ EventDeliveryManager::deliver_events_( const size_t tid, const std::vector< Spik const SpikeDataT& spike_data = recv_buffer[ rank * spike_buffer_size_per_rank + num_batches * SPIKES_PER_BATCH + j ]; se_batch[ j ].set_stamp( prepared_timestamps[ spike_data.get_lag() ] ); - se_batch[ j ].set_offset( spike_data.get_offset() ); + se_batch[ j ].get_stamp().set_offset( spike_data.get_offset() ); tid_batch[ j ] = spike_data.get_tid(); syn_id_batch[ j ] = spike_data.get_syn_id(); lcid_batch[ j ] = spike_data.get_lcid(); @@ -712,7 +712,7 @@ EventDeliveryManager::deliver_events_( const size_t tid, const std::vector< Spik const SpikeDataT& spike_data = recv_buffer[ rank * spike_buffer_size_per_rank + i * SPIKES_PER_BATCH + j ]; se_batch[ j ].set_stamp( prepared_timestamps[ spike_data.get_lag() ] ); - se_batch[ j ].set_offset( spike_data.get_offset() ); + se_batch[ j ].get_stamp().set_offset( spike_data.get_offset() ); syn_id_batch[ j ] = spike_data.get_syn_id(); // for compressed spikes lcid holds the index in the @@ -750,7 +750,7 @@ EventDeliveryManager::deliver_events_( const size_t tid, const std::vector< Spik const SpikeDataT& spike_data = recv_buffer[ rank * spike_buffer_size_per_rank + num_batches * SPIKES_PER_BATCH + j ]; se_batch[ j ].set_stamp( prepared_timestamps[ spike_data.get_lag() ] ); - se_batch[ j ].set_offset( spike_data.get_offset() ); + se_batch[ j ].get_stamp().set_offset( spike_data.get_offset() ); syn_id_batch[ j ] = spike_data.get_syn_id(); // for compressed spikes lcid holds the index in the // compressed_spike_data structure diff --git a/nestkernel/event_delivery_manager_impl.h b/nestkernel/event_delivery_manager_impl.h index 55310a24bd..08e39429d6 100644 --- a/nestkernel/event_delivery_manager_impl.h +++ b/nestkernel/event_delivery_manager_impl.h @@ -129,7 +129,7 @@ EventDeliveryManager::send_off_grid_remote( size_t tid, SpikeEvent& e, const lon // Unroll spike multiplicity as plastic synapses only handle individual spikes. for ( size_t i = 0; i < e.get_multiplicity(); ++i ) { - ( *off_grid_emitted_spikes_register_[ tid ] ).emplace_back( target, lag, e.get_offset() ); + ( *off_grid_emitted_spikes_register_[ tid ] ).emplace_back( target, lag, e.get_stamp().get_offset() ); } } } diff --git a/nestkernel/nest_time.h b/nestkernel/nest_time.h index f579af5659..8fe9090678 100644 --- a/nestkernel/nest_time.h +++ b/nestkernel/nest_time.h @@ -170,12 +170,51 @@ class Time static tic_t compute_max(); ///////////////////////////////////////////////////////////// - // The data: longest integer for tics + // Offset + ///////////////////////////////////////////////////////////// + + /** + * Return the creation time offset of the Event. + * Each Event carries the exact time of creation. This + * time need not coincide with an integral multiple of the + * temporal resolution. Rather, Events may be created at any point + * in time. + */ + double get_offset() const; + + /** + * Set the creation time of the Event. + * Each Event carries the exact time of creation in realtime. This + * time need not coincide with an integral multiple of the + * temporal resolution. Rather, Events may be created at any point + * in time. + * @param t Creation time in realtime. t has to be in [0, h). + */ + void set_offset( double t ); + + ///////////////////////////////////////////////////////////// + // The data ///////////////////////////////////////////////////////////// protected: + /** + * Longest integer for tics. + * The resolution of tic_t is limited by the time base of the + * simulation kernel. + * If this resolution is not fine enough, the creation time + * can be corrected by using the offset_ attribute. + */ tic_t tics; + /** + * Offset for precise spike times. + * offset_ specifies a correction to the creation time. + * If the resolution of stamp is not sufficiently precise, + * this attribute can be used to correct the creation time. + * offset_ has to be in [0, h). + */ + double offset_; + ///////////////////////////////////////////////////////////// // Friend declaration for units and binary operators ///////////////////////////////////////////////////////////// @@ -293,12 +332,14 @@ class Time public: Time() - : tics( 0 ) {}; + : tics( 0 ) + , offset_( 0. ) {}; Time( tic t ) : tics( ( time_abs( t.t ) < LIM_MAX.tics ) ? t.t : ( t.t < 0 ) ? LIM_NEG_INF.tics : LIM_POS_INF.tics ) + , offset_( 0. ) { } @@ -306,6 +347,7 @@ class Time : tics( ( time_abs( t.t ) < LIM_MAX.steps ) ? t.t * Range::TICS_PER_STEP : ( t.t < 0 ) ? LIM_NEG_INF.tics : LIM_POS_INF.tics ) + , offset_( 0. ) { } @@ -313,12 +355,14 @@ class Time : tics( ( time_abs( t.t ) < LIM_MAX.ms ) ? static_cast< tic_t >( t.t * Range::TICS_PER_MS + 0.5 ) : ( t.t < 0 ) ? LIM_NEG_INF.tics : LIM_POS_INF.tics ) + , offset_( 0. ) { } static tic_t fromstamp( ms_stamp ); Time( ms_stamp t ) : tics( fromstamp( t ) ) + , offset_( 0. ) { } @@ -507,7 +551,7 @@ class Time { return LIM_NEG_INF_ms; } - return Range::MS_PER_TIC * tics; + return Range::MS_PER_TIC * tics - offset_; } long @@ -632,6 +676,18 @@ operator*( const Time& t, long factor ) { return factor * t; } + +inline double +Time::get_offset() const +{ + return offset_; +} + +inline void +Time::set_offset( double t ) +{ + offset_ = t; +} } // namespace std::ostream& operator<<( std::ostream&, const nest::Time& ); diff --git a/nestkernel/recording_backend_ascii.cpp b/nestkernel/recording_backend_ascii.cpp index 773aa36a82..7c2adb8bb6 100644 --- a/nestkernel/recording_backend_ascii.cpp +++ b/nestkernel/recording_backend_ascii.cpp @@ -303,11 +303,11 @@ nest::RecordingBackendASCII::DeviceData::write( const Event& event, if ( time_in_steps_ ) { - file_ << event.get_stamp().get_steps() << "\t" << event.get_offset(); + file_ << event.get_stamp().get_steps() << "\t" << event.get_stamp().get_offset(); } else { - file_ << ( event.get_stamp().get_ms() - event.get_offset() ); + file_ << ( event.get_stamp().get_ms() ); } for ( auto& val : double_values ) diff --git a/nestkernel/recording_backend_memory.cpp b/nestkernel/recording_backend_memory.cpp index 3ff816c685..4647161dbf 100644 --- a/nestkernel/recording_backend_memory.cpp +++ b/nestkernel/recording_backend_memory.cpp @@ -197,11 +197,11 @@ nest::RecordingBackendMemory::DeviceData::push_back( const Event& event, if ( time_in_steps_ ) { times_steps_.push_back( event.get_stamp().get_steps() ); - times_offset_.push_back( event.get_offset() ); + times_offset_.push_back( event.get_stamp().get_offset() ); } else { - times_ms_.push_back( event.get_stamp().get_ms() - event.get_offset() ); + times_ms_.push_back( event.get_stamp().get_ms() ); } for ( size_t i = 0; i < double_values.size(); ++i ) diff --git a/nestkernel/recording_backend_screen.cpp b/nestkernel/recording_backend_screen.cpp index 9b31ea6f57..fada8f2f1e 100644 --- a/nestkernel/recording_backend_screen.cpp +++ b/nestkernel/recording_backend_screen.cpp @@ -199,11 +199,11 @@ nest::RecordingBackendScreen::DeviceData::write( const Event& event, if ( time_in_steps_ ) { - std::cout << event.get_stamp().get_steps() << "\t" << event.get_offset(); + std::cout << event.get_stamp().get_steps() << "\t" << event.get_stamp().get_offset(); } else { - std::cout << event.get_stamp().get_ms() - event.get_offset(); + std::cout << event.get_stamp().get_ms(); } for ( auto& val : double_values ) diff --git a/nestkernel/recording_backend_sionlib.cpp b/nestkernel/recording_backend_sionlib.cpp index 5aabb26ebc..216c12ae4d 100644 --- a/nestkernel/recording_backend_sionlib.cpp +++ b/nestkernel/recording_backend_sionlib.cpp @@ -456,7 +456,7 @@ nest::RecordingBackendSIONlib::write( const RecordingDevice& device, const sion_uint64 sender_node_id = static_cast< sion_uint64 >( event.get_sender_node_id() ); const sion_int64 step = static_cast< sion_int64 >( event.get_stamp().get_steps() ); - const double offset = event.get_offset(); + const double offset = event.get_stamp().get_offset(); if ( P_.sion_collective_ ) { diff --git a/nestkernel/structural_plasticity_node.cpp b/nestkernel/structural_plasticity_node.cpp index 07a3af88e4..43903f93dd 100644 --- a/nestkernel/structural_plasticity_node.cpp +++ b/nestkernel/structural_plasticity_node.cpp @@ -264,8 +264,7 @@ nest::StructuralPlasticityNode::connect_synaptic_element( Name name, int n ) void nest::StructuralPlasticityNode::set_spiketime( Time const& t_sp, double offset ) { - const double t_sp_ms = t_sp.get_ms() - offset; - update_synaptic_elements( t_sp_ms ); + update_synaptic_elements( t_sp.get_ms() ); Ca_minus_ += beta_Ca_; } diff --git a/testsuite/pytests/test_stdp_synapse.py b/testsuite/pytests/test_stdp_synapse.py deleted file mode 100644 index ccd0981c6d..0000000000 --- a/testsuite/pytests/test_stdp_synapse.py +++ /dev/null @@ -1,422 +0,0 @@ -# -*- coding: utf-8 -*- -# -# test_stdp_synapse.py -# -# This file is part of NEST. -# -# Copyright (C) 2004 The NEST Initiative -# -# NEST is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# NEST is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with NEST. If not, see . - -from math import exp - -import nest -import numpy as np -import pytest - -DEBUG_PLOTS = False - -if DEBUG_PLOTS: - try: - import matplotlib as mpl # noqa: F401 - import matplotlib.pyplot as plt - - DEBUG_PLOTS = True - except Exception: - DEBUG_PLOTS = False - - -# Defined here so we can use it in init_params() and in parametrization -RESOLUTION = 0.1 # [ms] - - -@nest.ll_api.check_stack -class TestSTDPSynapse: - """ - Compare the STDP synaptic plasticity model against a self-contained Python reference. - - Random pre and post spike times are generated according to a Poisson distribution; some hard-coded spike times are - added to make sure to test for edge cases such as simultaneous pre- and post spike. - """ - - def init_params(self): - self.resolution = RESOLUTION # [ms] - self.simulation_duration = 1000 # [ms] - self.synapse_model = "stdp_synapse" - self.presynaptic_firing_rate = 100.0 # [ms^-1] - self.postsynaptic_firing_rate = 100.0 # [ms^-1] - self.tau_pre = 16.8 - self.tau_post = 33.7 - self.init_weight = 0.5 - self.synapse_parameters = { - "synapse_model": self.synapse_model, - "receptor_type": 0, - # STDP constants - "lambda": 0.01, - "alpha": 0.85, - "mu_plus": 0.0, - "mu_minus": 0.0, - "tau_plus": self.tau_pre, - "Wmax": 15.0, - "weight": self.init_weight, - } - self.neuron_parameters = { - "tau_minus": self.tau_post, - } - - # While the random sequences, fairly long, would supposedly reveal small differences in the weight change - # between NEST and ours, some low-probability events (say, coinciding spikes) can well not have occurred. - # To generate and test every possible combination of pre/post order, we append some hardcoded spike sequences. - self.hardcoded_pre_times = np.array( - [1, 5, 6, 7, 9, 11, 12, 13, 14.5, 16.1, 21, 25, 26, 27, 29, 31, 32, 33, 34.5, 36.1], dtype=float - ) - self.hardcoded_post_times = np.array( - [2, 3, 4, 8, 9, 10, 12, 12.2, 14.1, 15.4, 22, 23, 24, 28, 29, 30, 32, 33.2, 35.1, 36.4], dtype=float - ) - self.hardcoded_trains_length = 5.0 + max(np.amax(self.hardcoded_pre_times), np.amax(self.hardcoded_post_times)) - - def do_nest_simulation_and_compare_to_reproduced_weight(self, fname_snip): - pre_spikes, post_spikes, t_weight_by_nest, weight_by_nest = self.do_the_nest_simulation() - - if DEBUG_PLOTS: - self.plot_weight_evolution( - pre_spikes, - post_spikes, - t_weight_by_nest, - weight_by_nest, - fname_snip=fname_snip, - title_snip=self.nest_neuron_model + " (NEST)", - ) - - ( - t_weight_reproduced_independently, - weight_reproduced_independently, - Kpre_log, - Kpost_log, - ) = self.reproduce_weight_drift(pre_spikes, post_spikes, self.init_weight, fname_snip=fname_snip) - - # ``weight_by_nest`` contains only weight values at pre spike times, ``weight_reproduced_independently`` - # contains the weight at pre *and* post times: check that weights are equal only for pre spike times - assert len(weight_by_nest) > 0 - - difference_matrix = t_weight_by_nest[t_weight_by_nest < self.simulation_duration].reshape( - 1, -1 - ) - t_weight_reproduced_independently.reshape(-1, 1) - pre_spike_reproduced_indices = np.abs(difference_matrix).argmin(axis=0) - time_differences = np.diagonal(difference_matrix[pre_spike_reproduced_indices]) - # make sure all spike times are equal - np.testing.assert_allclose(time_differences, 0, atol=1e-07) - # make sure the weights after the pre_spikes times are equal - np.testing.assert_allclose( - weight_by_nest[t_weight_by_nest < self.simulation_duration], - weight_reproduced_independently[pre_spike_reproduced_indices], - ) - - if DEBUG_PLOTS: - self.plot_weight_evolution( - pre_spikes, - post_spikes, - t_weight_by_nest, - weight_by_nest, - fname_snip=fname_snip, - title_snip=self.nest_neuron_model + " (NEST)", - ) - - self.plot_weight_evolution( - pre_spikes, - post_spikes, - t_weight_reproduced_independently, - weight_reproduced_independently, - Kpre_log, - Kpost_log, - pre_indices=pre_spike_reproduced_indices, - fname_snip=fname_snip + "_ref", - title_snip="Reference", - ) - - def do_the_nest_simulation(self): - """ - This function is where calls to NEST reside. Returns the generated pre- and post spike sequences and the - resulting weight established by STDP. - """ - nest.set_verbosity("M_WARNING") - nest.ResetKernel() - nest.SetKernelStatus( - { - "resolution": self.resolution, - "min_delay": min(self.min_delay, self.dendritic_delay), - "max_delay": max(self.max_delay, self.dendritic_delay), - } - ) - - presynaptic_neuron, postsynaptic_neuron = nest.Create(self.nest_neuron_model, 2, params=self.neuron_parameters) - - generators = nest.Create( - "poisson_generator", - 2, - params=( - { - "rate": self.presynaptic_firing_rate, - "stop": (self.simulation_duration - self.hardcoded_trains_length), - }, - { - "rate": self.postsynaptic_firing_rate, - "stop": (self.simulation_duration - self.hardcoded_trains_length), - }, - ), - ) - presynaptic_generator = generators[0] - postsynaptic_generator = generators[1] - - wr = nest.Create("weight_recorder") - nest.CopyModel(self.synapse_model, self.synapse_model + "_rec", {"weight_recorder": wr}) - - spike_senders = nest.Create( - "spike_generator", - 2, - params=( - {"spike_times": self.hardcoded_pre_times + self.simulation_duration - self.hardcoded_trains_length}, - {"spike_times": self.hardcoded_post_times + self.simulation_duration - self.hardcoded_trains_length}, - ), - ) - - pre_spike_generator = spike_senders[0] - post_spike_generator = spike_senders[1] - - # The recorder is to save the randomly generated spike trains. - spike_recorder = nest.Create("spike_recorder") - - nest.Connect( - presynaptic_generator + pre_spike_generator, - presynaptic_neuron, - syn_spec={"synapse_model": "static_synapse", "weight": 3000.0}, - ) - nest.Connect( - postsynaptic_generator + post_spike_generator, - postsynaptic_neuron, - syn_spec={"synapse_model": "static_synapse", "weight": 3000.0}, - ) - nest.Connect( - presynaptic_neuron + postsynaptic_neuron, spike_recorder, syn_spec={"synapse_model": "static_synapse"} - ) - - # The synapse of interest itself - self.synapse_parameters["synapse_model"] += "_rec" - nest.Connect(presynaptic_neuron, postsynaptic_neuron, syn_spec=self.synapse_parameters) - self.synapse_parameters["synapse_model"] = self.synapse_model - - nest.Simulate(self.simulation_duration) - - all_spikes = nest.GetStatus(spike_recorder, keys="events")[0] - pre_spikes = all_spikes["times"][all_spikes["senders"] == presynaptic_neuron.tolist()[0]] - post_spikes = all_spikes["times"][all_spikes["senders"] == postsynaptic_neuron.tolist()[0]] - - t_hist = nest.GetStatus(wr, "events")[0]["times"] - weight = nest.GetStatus(wr, "events")[0]["weights"] - - return pre_spikes, post_spikes, t_hist, weight - - def reproduce_weight_drift(self, pre_spikes, post_spikes, initial_weight, fname_snip=""): - """Independent, self-contained model of STDP""" - - def facilitate(w, Kpre): - norm_w = (w / self.synapse_parameters["Wmax"]) + ( - self.synapse_parameters["lambda"] - * pow(1 - (w / self.synapse_parameters["Wmax"]), self.synapse_parameters["mu_plus"]) - * Kpre - ) - if norm_w < 1.0: - return norm_w * self.synapse_parameters["Wmax"] - else: - return self.synapse_parameters["Wmax"] - - def depress(w, Kpost): - norm_w = (w / self.synapse_parameters["Wmax"]) - ( - self.synapse_parameters["alpha"] - * self.synapse_parameters["lambda"] - * pow(w / self.synapse_parameters["Wmax"], self.synapse_parameters["mu_minus"]) - * Kpost - ) - if norm_w > 0.0: - return norm_w * self.synapse_parameters["Wmax"] - else: - return 0.0 - - eps = 1e-6 - t = 0.0 - idx_next_pre_spike = 0 - idx_next_post_spike = 0 - t_last_pre_spike = -1 - t_last_post_spike = -1 - - Kplus = 0.0 - Kminus = 0.0 - weight = initial_weight - - t_log = [] - w_log = [] - Kplus_log = [] - Kminus_log = [] - - # Make sure only spikes that were relevant for simulation are actually considered in the test - # For pre-spikes that will be all spikes with: t_pre < sim_duration - pre_spikes = pre_spikes[pre_spikes + eps < self.simulation_duration] - # For post-spikes that will be all spikes with: t_post + d_dend <= latest_pre_spike - post_spikes = post_spikes[post_spikes + self.dendritic_delay <= pre_spikes[-1] + eps] - post_spikes_delayed = post_spikes + self.dendritic_delay - - while idx_next_pre_spike < len(pre_spikes) or idx_next_post_spike < len(post_spikes_delayed): - if idx_next_pre_spike >= pre_spikes.size: - t_next_pre_spike = -1 - else: - t_next_pre_spike = pre_spikes[idx_next_pre_spike] - - if idx_next_post_spike >= post_spikes_delayed.size: - t_next_post_spike = -1 - else: - t_next_post_spike = post_spikes_delayed[idx_next_post_spike] - - if t_next_post_spike >= 0 and (t_next_post_spike + eps < t_next_pre_spike or t_next_pre_spike < 0): - handle_pre_spike = False - handle_post_spike = True - idx_next_post_spike += 1 - elif t_next_pre_spike >= 0 and (t_next_post_spike > t_next_pre_spike + eps or t_next_post_spike < 0): - handle_pre_spike = True - handle_post_spike = False - idx_next_pre_spike += 1 - else: - # simultaneous spikes (both true) or no more spikes to process (both false) - handle_pre_spike = t_next_pre_spike >= 0 - handle_post_spike = t_next_post_spike >= 0 - idx_next_pre_spike += 1 - idx_next_post_spike += 1 - - # integrate to min(t_next_pre_spike, t_next_post_spike) - t_next = t - if handle_pre_spike: - t_next = max(t, t_next_pre_spike) - if handle_post_spike: - t_next = max(t, t_next_post_spike) - - if t_next == t: - # no more spikes to process - t_next = self.simulation_duration - - h = t_next - t - Kplus *= exp(-h / self.tau_pre) - Kminus *= exp(-h / self.tau_post) - t = t_next - - if handle_post_spike: - if not handle_pre_spike or abs(t_next_post_spike - t_last_post_spike) > eps: - if abs(t_next_post_spike - t_last_pre_spike) > eps: - weight = facilitate(weight, Kplus) - - if handle_pre_spike: - if not handle_post_spike or abs(t_next_pre_spike - t_last_pre_spike) > eps: - if abs(t_next_pre_spike - t_last_post_spike) > eps: - weight = depress(weight, Kminus) - t_last_pre_spike = t_next_pre_spike - Kplus += 1.0 - - if handle_post_spike: - t_last_post_spike = t_next_post_spike - Kminus += 1.0 - - # logging - t_log.append(t) - w_log.append(weight) - Kplus_log.append(Kplus) - Kminus_log.append(Kminus) - - if DEBUG_PLOTS: - self.plot_weight_evolution( - pre_spikes, - post_spikes, - t_log, - w_log, - Kplus_log, - Kminus_log, - fname_snip=fname_snip + "_ref", - title_snip="Reference", - ) - - return np.array(t_log), np.array(w_log), Kplus_log, Kminus_log - - def plot_weight_evolution( - self, - pre_spikes, - post_spikes, - t_log, - w_log, - Kpre_log=None, - Kpost_log=None, - pre_indices=slice(-1), - fname_snip="", - title_snip="", - ): - if not DEBUG_PLOTS: # make pylint happy if no matplotlib - return - - # pylint: disable=E0601 - fig, ax = plt.subplots(nrows=3) - - n_spikes = len(pre_spikes) - for i in range(n_spikes): - ax[0].plot(2 * [pre_spikes[i]], [0, 1], linewidth=2, color="blue", alpha=0.4) - ax[0].set_ylabel("Pre spikes") - ax0_ = ax[0].twinx() - if Kpre_log: - ax0_.plot(t_log, Kpre_log) - - n_spikes = len(post_spikes) - for i in range(n_spikes): - ax[1].plot(2 * [post_spikes[i]], [0, 1], linewidth=2, color="red", alpha=0.4) - ax1_ = ax[1].twinx() - ax[1].set_ylabel("Post spikes") - if Kpost_log: - ax1_.plot(t_log, Kpost_log) - - ax[2].plot(t_log[pre_indices], w_log[pre_indices], marker="o", label="nestml") - ax[2].set_ylabel("w") - - ax[2].set_xlabel("Time [ms]") - for _ax in ax: - _ax.grid(which="major", axis="both") - _ax.grid(which="minor", axis="x", linestyle=":", alpha=0.4) - _ax.minorticks_on() - _ax.set_xlim(0.0, self.simulation_duration) - - fig.suptitle(title_snip) - fig.savefig("/tmp/nest_stdp_synapse_test" + fname_snip + ".png", dpi=300) - plt.close(fig) - - @pytest.mark.parametrize("dend_delay", [RESOLUTION, 1.0]) - @pytest.mark.parametrize("model", ["iaf_psc_exp", "iaf_cond_exp"]) - @pytest.mark.parametrize("min_delay", (1.0, 0.4, RESOLUTION)) - @pytest.mark.parametrize("max_delay", (1.0, 3.0)) - @pytest.mark.parametrize("t_ref", (RESOLUTION, 0.5, 1.0, 1.1, 2.5)) - def test_stdp_synapse(self, dend_delay, model, min_delay, max_delay, t_ref): - self.init_params() - self.dendritic_delay = dend_delay - self.nest_neuron_model = model - self.min_delay = min(min_delay, max_delay) - self.max_delay = max(min_delay, max_delay) - self.neuron_parameters["t_ref"] = t_ref - self.synapse_parameters["delay"] = self.dendritic_delay - - fname_snip = "_[nest_neuron_mdl=" + self.nest_neuron_model + "]" - fname_snip += "_[dend_delay=" + str(self.dendritic_delay) + "]" - fname_snip += "_[t_ref=" + str(self.neuron_parameters["t_ref"]) + "]" - self.do_nest_simulation_and_compare_to_reproduced_weight(fname_snip=fname_snip)