Dear All,
I am relatively new to nest and want to implement a new neuron model.
I've worked a lot with SpiNNaker previously.
I am a research assistant and PhD student at the Technical Faculty in Bielefeld, Germany.
Currently, I am trying to implement a new neuron model into nest. Because I want to use
this model later on in the neurorbotics platform (NRP) I directly installed the NRP
and I am using the nest version installed together with the NRP.
I followed the instructions at:
https://nest.github.io/nest-simulator/extension_modules
I am able to install mymodule and to run the neuron model pif_psc_alpha coming with it.
Now I tried to extend mymodule with a new neuron model. To achieve that I copied the
iaf_psc_exp model's cpp and h file, renamed them to iaf_psc_exp_semd and changed them
according to pif_psc_alpha.
I was able to include the model into the nest library and run a short example script.
Unfortunately, the iaf_psc_exp_semd model doesn't react to any stimulation with
spikes.
The membrane potential always stays at E_L.
When I use the same python script but with the iad_psc_exp model I see a clear change
in the membrane potential.
Could someone check the files I've created for the new iaf_psc_exp_semd model to see
what is wrong/missing?
Thanks a lot and best regards,
Thorben Schoepe
First file:
/*
* iaf_psc_exp_semd.h
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef IAF_PSC_EXP_SEMD_H
#define IAF_PSC_EXP_SEMD_H
// Includes from nestkernel:
#include "archiving_node.h"
#include "connection.h"
#include "event.h"
#include "nest_types.h"
#include "recordables_map.h"
#include "ring_buffer.h"
#include "universal_data_logger.h"
// Includes from sli:
#include "dictdatum.h"
namespace mynest
{
/* BeginDocumentation
Name: iaf_psc_exp - Leaky integrate-and-fire neuron model with exponential
PSCs.
Description:
iaf_psc_expp is an implementation of a leaky integrate-and-fire model
with exponential shaped postsynaptic currents (PSCs) according to [1].
Thus, postsynaptic currents have an infinitely short rise time.
The threshold crossing is followed by an absolute refractory period (t_ref)
during which the membrane potential is clamped to the resting potential
and spiking is prohibited.
The linear subthresold dynamics is integrated by the Exact
Integration scheme [2]. The neuron dynamics is solved on the time
grid given by the computation step size. Incoming as well as emitted
spikes are forced to that grid.
An additional state variable and the corresponding differential
equation represents a piecewise constant external current.
The general framework for the consistent formulation of systems with
neuron like dynamics interacting by point events is described in
[2]. A flow chart can be found in [3].
Remarks:
The present implementation uses individual variables for the
components of the state vector and the non-zero matrix elements of
the propagator. Because the propagator is a lower triangular matrix
no full matrix multiplication needs to be carried out and the
computation can be done "in place" i.e. no temporary state vector
object is required.
The template support of recent C++ compilers enables a more succinct
formulation without loss of runtime performance already at minimal
optimization levels. A future version of iaf_psc_exp will probably
address the problem of efficient usage of appropriate vector and
matrix objects.
Parameters:
The following parameters can be set in the status dictionary.
E_L double - Resting membrane potential in mV.
C_m double - Capacity of the membrane in pF
tau_m double - Membrane time constant in ms.
tau_syn_ex double - Time constant of postsynaptic excitatory currents in ms
tau_syn_in double - Time constant of postsynaptic inhibitory currents in ms
t_ref double - Duration of refractory period (V_m = V_reset) in ms.
V_m double - Membrane potential in mV
V_th double - Spike threshold in mV.
V_reset double - Reset membrane potential after a spike in mV.
I_e double - Constant input current in pA.
t_spike double - Point in time of last spike in ms.
Remarks:
If tau_m is very close to tau_syn_ex or tau_syn_in, the model
will numerically behave as if tau_m is equal to tau_syn_ex or
tau_syn_in, respectively, to avoid numerical instabilities.
For details, please see IAF_Neruons_Singularity.ipynb in the
NEST source code (docs/model_details).
iaf_psc_exp can handle current input in two ways: Current input
through receptor_type 0 are handled as stepwise constant current
input as in other iaf models, i.e., this current directly enters
the membrane potential equation. Current input through
receptor_type 1, in contrast, is filtered through an exponential
kernel with the time constant of the excitatory synapse,
tau_syn_ex. For an example application, see [4].
References:
[1] Misha Tsodyks, Asher Uziel, and Henry Markram (2000) Synchrony Generation
in Recurrent Networks with Frequency-Dependent Synapses, The Journal of
Neuroscience, 2000, Vol. 20 RC50 p. 1-5
[2] Rotter S & Diesmann M (1999) Exact simulation of time-invariant linear
systems with applications to neuronal modeling. Biologial Cybernetics
81:381-402.
[3] Diesmann M, Gewaltig M-O, Rotter S, & Aertsen A (2001) State space
analysis of synchronous spiking in cortical neural networks.
Neurocomputing 38-40:565-571.
[4] Schuecker J, Diesmann M, Helias M (2015) Modulated escape from a
metastable state driven by colored noise.
Physical Review E 92:052119
Sends: SpikeEvent
Receives: SpikeEvent, CurrentEvent, DataLoggingRequest
SeeAlso: iaf_psc_exp_ps
FirstVersion: March 2006
Author: Moritz Helias
*/
/**
* Leaky integrate-and-fire neuron with exponential PSCs.
*/
class iaf_psc_exp_semd : public nest::Archiving_Node
{
public:
iaf_psc_exp_semd();
iaf_psc_exp_semd( const iaf_psc_exp_semd& );
/**
* Import sets of overloaded virtual functions.
* @see Technical Issues / Virtual Functions: Overriding, Overloading, and
* Hiding
*/
using nest::Node::handle;
using nest::Node::handles_test_event;
nest::port send_test_event( Node&, nest::port, nest::synindex, bool );
void handle( nest::SpikeEvent& );
void handle( nest::CurrentEvent& );
void handle( nest::DataLoggingRequest& );
nest::port handles_test_event( nest::SpikeEvent&, nest::port );
nest::port handles_test_event( nest::CurrentEvent&, nest::port );
nest::port handles_test_event( nest::DataLoggingRequest&, nest::port );
void get_status( DictionaryDatum& ) const;
void set_status( const DictionaryDatum& );
private:
void init_state_( const Node& proto );
void init_buffers_();
void calibrate();
void update(nest::Time const&, const long, const long );
// The next two classes need to be friends to access the State_ class/member
friend class nest::RecordablesMap< iaf_psc_exp_semd >;
friend class nest::UniversalDataLogger< iaf_psc_exp_semd >;
// ----------------------------------------------------------------
/**
* Independent parameters of the model.
*/
struct Parameters_
{
/** Membrane time constant in ms. */
double Tau_;
/** Membrane capacitance in pF. */
double C_;
/** Refractory period in ms. */
double t_ref_;
/** Resting potential in mV. */
double E_L_;
/** External current in pA */
double I_e_;
/** Threshold, RELATIVE TO RESTING POTENTAIL(!).
I.e. the real threshold is (E_L_+Theta_). */
double Theta_;
/** reset value of the membrane potential */
double V_reset_;
/** Time constant of excitatory synaptic current in ms. */
double tau_ex_;
/** Time constant of inhibitory synaptic current in ms. */
double tau_in_;
Parameters_(); //!< Sets default parameter values
void get( DictionaryDatum& ) const; //!< Store current values in dictionary
/** Set values from dictionary.
* @returns Change in reversal potential E_L, to be passed to State_::set()
*/
double set( const DictionaryDatum& );
};
// ----------------------------------------------------------------
/**
* State variables of the model.
*/
struct State_
{
// state variables
//! synaptic stepwise constant input current, variable 0
double i_0_;
double i_1_; //!< presynaptic stepwise constant input current
double i_syn_ex_; //!< postsynaptic current for exc. inputs, variable 1
double i_syn_in_; //!< postsynaptic current for inh. inputs, variable 1
double V_m_; //!< membrane potential, variable 2
//! absolute refractory counter (no membrane potential propagation)
int r_ref_;
State_(); //!< Default initialization
void get( DictionaryDatum&, const Parameters_& ) const;
/** Set values from dictionary.
* @param dictionary to take data from
* @param current parameters
* @param Change in reversal potential E_L specified by this dict
*/
void set( const DictionaryDatum&, const Parameters_&, const double );
};
// ----------------------------------------------------------------
/**
* Buffers of the model.
*/
struct Buffers_
{
Buffers_( iaf_psc_exp_semd& );
Buffers_( const Buffers_&, iaf_psc_exp_semd& );
/** buffers and sums up incoming spikes/currents */
nest::RingBuffer spikes_ex_;
nest::RingBuffer spikes_in_;
std::vector< nest::RingBuffer > currents_;
//! Logger for all analog data
nest::UniversalDataLogger< iaf_psc_exp_semd > logger_;
};
// ----------------------------------------------------------------
/**
* Internal variables of the model.
*/
struct Variables_
{
/** Amplitude of the synaptic current.
This value is chosen such that a post-synaptic potential with
weight one has an amplitude of 1 mV.
@note mog - I assume this, not checked.
*/
// double PSCInitialValue_;
// time evolution operator
double P20_;
double P11ex_;
double P11in_;
double P21ex_;
double P21in_;
double P22_;
double weighted_spikes_ex_;
double weighted_spikes_in_;
int RefractoryCounts_;
};
// Access functions for UniversalDataLogger -------------------------------
//! Read out the real membrane potential
inline double
get_V_m_() const
{
return S_.V_m_ + P_.E_L_;
}
inline double
get_weighted_spikes_ex_() const
{
return V_.weighted_spikes_ex_;
}
inline double
get_weighted_spikes_in_() const
{
return V_.weighted_spikes_in_;
}
inline double
get_I_syn_ex_() const
{
return S_.i_syn_ex_;
}
inline double
get_I_syn_in_() const
{
return S_.i_syn_in_;
}
// ----------------------------------------------------------------
/**
* @defgroup iaf_psc_exp_data
* Instances of private data structures for the different types
* of data pertaining to the model.
* @note The order of definitions is important for speed.
* @{
*/
Parameters_ P_;
State_ S_;
Variables_ V_;
Buffers_ B_;
/** @} */
//! Mapping of recordables names to access functions
static nest::RecordablesMap< iaf_psc_exp_semd > recordablesMap_;
};
inline nest::port
mynest::iaf_psc_exp_semd::send_test_event( Node& target,
nest::port receptor_type,
nest::synindex,
bool )
{
nest::SpikeEvent e;
e.set_sender( *this );
return target.handles_test_event( e, receptor_type );
}
inline nest::port
mynest::iaf_psc_exp_semd::handles_test_event( nest::SpikeEvent&, nest::port
receptor_type )
{
if ( receptor_type != 0 )
throw nest::UnknownReceptorType( receptor_type, get_name() );
return 0;
}
inline nest::port
mynest::iaf_psc_exp_semd::handles_test_event( nest::CurrentEvent&, nest::port
receptor_type )
{
if ( receptor_type == 0 )
return 0;
else if ( receptor_type == 1 )
return 1;
else
throw nest::UnknownReceptorType( receptor_type, get_name() );
}
inline nest::port
mynest::iaf_psc_exp_semd::handles_test_event( nest::DataLoggingRequest& dlr,
nest::port receptor_type )
{
if ( receptor_type != 0 )
throw nest::UnknownReceptorType( receptor_type, get_name() );
return B_.logger_.connect_logging_device( dlr, recordablesMap_ );
}
inline void
iaf_psc_exp_semd::get_status( DictionaryDatum& d ) const
{
P_.get( d );
S_.get( d, P_ );
Archiving_Node::get_status( d );
( *d )[ nest::names::recordables ] = recordablesMap_.get_list();
}
inline void
iaf_psc_exp_semd::set_status( const DictionaryDatum& d )
{
Parameters_ ptmp = P_; // temporary copy in case of errors
const double delta_EL = ptmp.set( d ); // throws if BadProperty
State_ stmp = S_; // temporary copy in case of errors
stmp.set( d, ptmp, delta_EL ); // throws if BadProperty
// We now know that (ptmp, stmp) are consistent. We do not
// write them back to (P_, S_) before we are also sure that
// the properties to be set in the parent class are internally
// consistent.
Archiving_Node::set_status( d );
// if we get here, temporaries contain consistent set of properties
P_ = ptmp;
S_ = stmp;
}
} // namespace
#endif // IAF_PSC_EXP_SEMD_H
Second file:
/*
* iaf_psc_exp_semd.cpp
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "iaf_psc_exp_semd.h"
// C++ includes:
#include <limits>
// Includes from libnestutil:
#include "numerics.h"
#include "propagator_stability.h"
// Includes from nestkernel:
#include "event_delivery_manager_impl.h"
#include "exceptions.h"
#include "kernel_manager.h"
#include "universal_data_logger_impl.h"
// Includes from sli:
#include "dict.h"
#include "dictutils.h"
#include "doubledatum.h"
#include "integerdatum.h"
#include "lockptrdatum.h"
using namespace nest;
/* ----------------------------------------------------------------
* Recordables map
* ---------------------------------------------------------------- */
nest::RecordablesMap< mynest::iaf_psc_exp_semd >
mynest::iaf_psc_exp_semd::recordablesMap_;
namespace nest
{
// Override the create() method with one call to RecordablesMap::insert_()
// for each quantity to be recorded.
template <>
void
RecordablesMap< mynest::iaf_psc_exp_semd >::create()
{
// use standard names whereever you can for consistency!
insert_( names::V_m, &mynest::iaf_psc_exp_semd::get_V_m_ );
insert_( names::weighted_spikes_ex,
&mynest::iaf_psc_exp_semd::get_weighted_spikes_ex_ );
insert_( names::weighted_spikes_in,
&mynest::iaf_psc_exp_semd::get_weighted_spikes_in_ );
insert_( names::I_syn_ex, &mynest::iaf_psc_exp_semd::get_I_syn_ex_ );
insert_( names::I_syn_in, &mynest::iaf_psc_exp_semd::get_I_syn_in_ );
}
}
/* ----------------------------------------------------------------
* Default constructors defining default parameters and state
* ---------------------------------------------------------------- */
mynest::iaf_psc_exp_semd::Parameters_::Parameters_()
: Tau_( 10.0 ) // in ms
, C_( 250.0 ) // in pF
, t_ref_( 2.0 ) // in ms
, E_L_( -70.0 ) // in mV
, I_e_( 0.0 ) // in pA
, Theta_( -55.0 - E_L_ ) // relative E_L_
, V_reset_( -70.0 - E_L_ ) // in mV
, tau_ex_( 2.0 ) // in ms
, tau_in_( 2.0 ) // in ms
{
}
mynest::iaf_psc_exp_semd::State_::State_()
: i_0_( 0.0 )
, i_syn_ex_( 0.0 )
, i_syn_in_( 0.0 )
, V_m_( 0.0 )
, r_ref_( 0 )
{
}
/* ----------------------------------------------------------------
* Parameter and state extractions and manipulation functions
* ---------------------------------------------------------------- */
void
mynest::iaf_psc_exp_semd::Parameters_::get( DictionaryDatum& d ) const
{
def< double >( d, names::E_L, E_L_ ); // resting potential
def< double >( d, names::I_e, I_e_ );
def< double >( d, names::V_th, Theta_ + E_L_ ); // threshold value
def< double >( d, names::V_reset, V_reset_ + E_L_ );
def< double >( d, names::C_m, C_ );
def< double >( d, names::tau_m, Tau_ );
def< double >( d, names::tau_syn_ex, tau_ex_ );
def< double >( d, names::tau_syn_in, tau_in_ );
def< double >( d, names::t_ref, t_ref_ );
}
double
mynest::iaf_psc_exp_semd::Parameters_::set( const DictionaryDatum& d )
{
// if E_L_ is changed, we need to adjust all variables defined relative to
// E_L_
const double ELold = E_L_;
updateValue< double >( d, names::E_L, E_L_ );
const double delta_EL = E_L_ - ELold;
if ( updateValue< double >( d, names::V_reset, V_reset_ ) )
V_reset_ -= E_L_;
else
V_reset_ -= delta_EL;
if ( updateValue< double >( d, names::V_th, Theta_ ) )
Theta_ -= E_L_;
else
Theta_ -= delta_EL;
updateValue< double >( d, names::I_e, I_e_ );
updateValue< double >( d, names::C_m, C_ );
updateValue< double >( d, names::tau_m, Tau_ );
updateValue< double >( d, names::tau_syn_ex, tau_ex_ );
updateValue< double >( d, names::tau_syn_in, tau_in_ );
updateValue< double >( d, names::t_ref, t_ref_ );
if ( V_reset_ >= Theta_ )
throw nest::BadProperty( "Reset potential must be smaller than threshold."
);
if ( C_ <= 0 )
throw nest::BadProperty( "Capacitance must be strictly positive." );
if ( Tau_ <= 0 || tau_ex_ <= 0 || tau_in_ <= 0 )
throw nest::BadProperty(
"Membrane and synapse time constants must be strictly positive." );
if ( t_ref_ < 0 )
throw nest::BadProperty( "Refractory time must not be negative." );
return delta_EL;
}
void
mynest::iaf_psc_exp_semd::State_::get( DictionaryDatum& d, const Parameters_& p )
const
{
def< double >( d, names::V_m, V_m_ + p.E_L_ ); // Membrane potential
}
void
mynest::iaf_psc_exp_semd::State_::set( const DictionaryDatum& d,
const Parameters_& p,
double delta_EL )
{
if ( updateValue< double >( d, names::V_m, V_m_ ) )
V_m_ -= p.E_L_;
else
V_m_ -= delta_EL;
}
mynest::iaf_psc_exp_semd::Buffers_::Buffers_( iaf_psc_exp_semd& n )
: logger_( n )
{
}
mynest::iaf_psc_exp_semd::Buffers_::Buffers_( const Buffers_&, iaf_psc_exp_semd& n
)
: logger_( n )
{
}
/* ----------------------------------------------------------------
* Default and copy constructor for node
* ---------------------------------------------------------------- */
mynest::iaf_psc_exp_semd::iaf_psc_exp_semd()
: Archiving_Node()
, P_()
, S_()
, B_( *this )
{
recordablesMap_.create();
}
mynest::iaf_psc_exp_semd::iaf_psc_exp_semd( const iaf_psc_exp_semd& n )
: Archiving_Node( n )
, P_( n.P_ )
, S_( n.S_ )
, B_( n.B_, *this )
{
}
/* ----------------------------------------------------------------
* Node initialization functions
* ---------------------------------------------------------------- */
void
mynest::iaf_psc_exp_semd::init_state_( const Node& proto )
{
const iaf_psc_exp_semd& pr = downcast< iaf_psc_exp_semd >( proto );
S_ = pr.S_;
}
void
mynest::iaf_psc_exp_semd::init_buffers_()
{
B_.spikes_ex_.clear(); // includes resize
B_.spikes_in_.clear(); // includes resize
B_.currents_.clear(); // includes resize
B_.logger_.reset();
Archiving_Node::clear_history();
}
void
mynest::iaf_psc_exp_semd::calibrate()
{
B_.currents_.resize( 2 );
// ensures initialization in case mm connected after Simulate
B_.logger_.init();
const double h = Time::get_resolution().get_ms();
// numbering of state vaiables: i_0 = 0, i_syn_ = 1, V_m_ = 2
// commented out propagators: forward Euler
// needed to exactly reproduce Tsodyks network
// these P are independent
V_.P11ex_ = std::exp( -h / P_.tau_ex_ );
// P11ex_ = 1.0-h/tau_ex_;
V_.P11in_ = std::exp( -h / P_.tau_in_ );
// P11in_ = 1.0-h/tau_in_;
V_.P22_ = std::exp( -h / P_.Tau_ );
// P22_ = 1.0-h/Tau_;
// these are determined according to a numeric stability criterion
V_.P21ex_ = propagator_32( P_.tau_ex_, P_.Tau_, P_.C_, h );
V_.P21in_ = propagator_32( P_.tau_in_, P_.Tau_, P_.C_, h );
// P21ex_ = h/C_;
// P21in_ = h/C_;
V_.P20_ = P_.Tau_ / P_.C_ * ( 1.0 - V_.P22_ );
// P20_ = h/C_;
// TauR specifies the length of the absolute refractory period as
// a double in ms. The grid based iaf_psc_exp can only handle refractory
// periods that are integer multiples of the computation step size (h).
// To ensure consistency with the overall simulation scheme such conversion
// should be carried out via objects of class nest::Time. The conversion
// requires 2 steps:
// 1. A time object r is constructed defining representation of
// TauR in tics. This representation is then converted to computation
// time steps again by a strategy defined by class nest::Time.
// 2. The refractory time in units of steps is read out get_steps(), a
// member function of class nest::Time.
//
// Choosing a TauR that is not an integer multiple of the computation time
// step h will leed to accurate (up to the resolution h) and self-consistent
// results. However, a neuron model capable of operating with real valued
// spike time may exhibit a different effective refractory time.
V_.RefractoryCounts_ = Time( Time::ms( P_.t_ref_ ) ).get_steps();
// since t_ref_ >= 0, this can only fail in error
assert( V_.RefractoryCounts_ >= 0 );
}
void
mynest::iaf_psc_exp_semd::update( const Time& origin, const long from, const long to
)
{
assert(
to >= 0 && ( delay ) from < kernel().connection_manager.get_min_delay()
);
assert( from < to );
// evolve from timestep 'from' to timestep 'to' with steps of h each
for ( long lag = from; lag < to; ++lag )
{
if ( S_.r_ref_ == 0 ) // neuron not refractory, so evolve V
S_.V_m_ = S_.V_m_ * V_.P22_ + S_.i_syn_ex_ * V_.P21ex_ // membrane potential
equals membrane potential times exponetial decay plus postsynpatic excitatory/inhibitory
currents time numerical stability factor plus new input current times exponential decay
+ S_.i_syn_in_ * V_.P21in_ + ( P_.I_e_ + S_.i_0_ ) * V_.P20_; // S_.V_m :
membrane potential
else
// V_.P22 : membrane potential decay
{ // S_.i_syn_ex / S_.i_syn_in : excitatory / inhibitory
postsynaptic current
} // V_.P21in / V_.P21ex : numeric stability criterion parameter
// P_.I_e : static input current
{
// S_.i_0_ : presynaptic input current this timestep
} // S_.i_1_ : presynaptic input current next timestep
{
}
--S_.r_ref_; // neuron is absolute refractory
// exponential decaying PSCs
S_.i_syn_ex_ *= V_.P11ex_;
S_.i_syn_in_ *= V_.P11in_;
// add evolution of presynaptic input current
S_.i_syn_ex_ += ( 1. - V_.P11ex_ ) * S_.i_1_;
// the spikes arriving at T+1 have an immediate effect on the state of the
// neuron
V_.weighted_spikes_ex_ = B_.spikes_ex_.get_value( lag );
V_.weighted_spikes_in_ = B_.spikes_in_.get_value( lag );
S_.i_syn_ex_ += V_.weighted_spikes_ex_;
S_.i_syn_in_ += V_.weighted_spikes_in_;
if ( S_.V_m_ >= P_.Theta_ ) // threshold crossing
{
S_.r_ref_ = V_.RefractoryCounts_;
S_.V_m_ = P_.V_reset_;
set_spiketime( Time::step( origin.get_steps() + lag + 1 ) );
SpikeEvent se;
kernel().event_delivery_manager.send( *this, se, lag );
}
// set new input current
S_.i_0_ = B_.currents_[ 0 ].get_value( lag );
S_.i_1_ = B_.currents_[ 1 ].get_value( lag );
// log state data
B_.logger_.record_data( origin.get_steps() + lag );
}
}
void
mynest::iaf_psc_exp_semd::handle( SpikeEvent& e )
{
assert( e.get_delay() > 0 );
if ( e.get_weight() >= 0.0 )
B_.spikes_ex_.add_value( e.get_rel_delivery_steps(
kernel().simulation_manager.get_slice_origin() ),
e.get_weight() * e.get_multiplicity() );
else
B_.spikes_in_.add_value( e.get_rel_delivery_steps(
kernel().simulation_manager.get_slice_origin() ),
e.get_weight() * e.get_multiplicity() );
}
void
mynest::iaf_psc_exp_semd::handle( CurrentEvent& e )
{
assert( e.get_delay() > 0 );
const double c = e.get_current();
const double w = e.get_weight();
// add weighted current; HEP 2002-10-04
if ( 0 == e.get_rport() )
{
B_.currents_[ 0 ].add_value(
e.get_rel_delivery_steps(
kernel().simulation_manager.get_slice_origin() ),
w * c );
}
if ( 1 == e.get_rport() )
{
B_.currents_[ 1 ].add_value(
e.get_rel_delivery_steps(
kernel().simulation_manager.get_slice_origin() ),
w * c );
}
}
void
mynest::iaf_psc_exp_semd::handle( DataLoggingRequest& e )
{
B_.logger_.handle( e );
}