Developing Models
From NEST
This is just the beginning of a node-writing tutorial. It will still take some more time until it's finished. --Eppler 16:03, 12 March 2007 (CET)
All models in NEST are derived from the base class Node. Neuron models are derived directly from the base class, whereas devices use the base classes Device and Recorder. The base classes define some pure virtual functions that have to be implemented in a derived model class. The most important functions are:
- void calibrate(): Set scheduler dependent internal parameters. This function is called by the scheduler right before the simulation is performed. Here you can reset the size of ring buffers, and set variables that depend on the state of the scheduler.
- void update(Time const & origin, const long_t from, const long_t to): Update the dynamic state of the model. Here, the model propagates its internal state from one time step to the next. The parameter origin represents the beginning of the current network time slice (in steps of Δmin, the minimal connection delay in the network). to and from refer to the actual time steps that have to be considered inside of the slice. They are expressed in units of h, the simulation resolution.
- void set_properties(const DictionaryDatum & d): Set user defined parameters of the model. This function is called when SetStatus is executed in SLI.
- void get_properties(DictionaryDatum & d) const: Retrieve a dictionary with parameters from the model. This is the C++ end of the SLI function GetStatus.
The following sections will explain each of these functions in detail with the help of an example model, called my_model.
Contents |
Model description
The model that's used as an example is a simple and unrealistic neuron model. We want it to do the following:
- It should have an internal variable counter that counts the number of spikes it received from other neurons.
- If counter reaches a specific number threshold it should send out a spike to each of its target nodes.
- For more complexity, the number of incoming spikes is multiplied with a constant factor, factor that can be set by the user.It should default to 1.
Transfering the description to SLI
The possibility to receive a special type of event is controlled by the presence of an overloaded version of Node::handle(EventT) for this specific type of event. The default implementation in the base class will throw UnexpectedEvent for each incoming event.
Updating the Internal State
A typical update method of a neuron model will look like this:
void nest::iaf_neuron::update(Time const & origin, const long_t from, const long_t to)
{
assert(to >= 0 && (delay) from < Scheduler::get_min_delay());
assert(from < to);
for ( long_t lag = from ; lag < to ; ++lag )
{
if ( r_ == 0 )
{
// neuron not refractory
y3_ = P30_*(y0_ + I_e_) + P31_*y1_ + P32_*y2_ + P33_*y3_;
}
else // neuron is absolute refractory
--r_;
// alpha shape PSCs
y2_ = P21_*y1_ + P22_ * y2_;
y1_ *= P11_;
// apply spikes delivered in this step
y1_ += PSCInitialValue_* spikes_.get_value(lag); // the spikes arriving at T+1 have an
// immediate effect on the state of the
// neuron
// threshold crossing
if (y3_ >= Theta_)
{
r_ = RefractoryCounts_;
y3_=V_reset_;
// A supra-threshold membrane potential should never be observable.
// The reset at the time of threshold crossing enables accurate integration
// independent of the computation step size, see [2,3] for details.
set_spiketime(Time::step(origin.get_steps()+lag+1));
SpikeEvent se;
network()->send(*this, se, lag);
}
// set new input current
y0_ = currents_.get_value(lag);
// voltage logging for entire time slice
potentials_[network()->get_slice() % 2][lag] = y3_ + U0_;
}
}
Sending Events
During simulation, interactions are realised by events that travel from a sending node to the receiving node. Nodes can send and receive events. Typically, a node sends only one type of event, while it may handle several event types. Events are the only way by which a node can exchange information with its environment. There are different types of events, depending on the information which is to be transmitted between the nodes. The following event types are available:
* SpikeEvent * RateEvent * CurrentEvent * PotentialEvent
Each event carries a time-stamp according to the time when it was created.
Each model can only send a single type of event. So it is not possible for a neuron to send SpikeEvents and CurrentEvents. The type of event is defined in my_model::check_connection(). If we assume that the model should send SpikeEvents, this function would look like this:
port my_model::check_connection(Node& r, port rp)
{
SpikeEvent e;
e.set_sender(*this);
e.set_receiver(r);
e.set_rport(rp);
return r.connect_sender(e);
}
Handling Incoming Events
Testing the Model
For the operation of NEST it is essential that each model does the right things.
- Does connecting work
The basic skeleton of these
