Neural simulations

From NEST

Jump to: navigation, search

[ An Introduction to SLI ]

A simulation of a network is like an experiment with the difference that it takes place inside the computer's memory rather than in the physical world.

Like in a real experiment, you need a system which you want to investigate. Moreover, you need a clear idea of what you want to learn from the experiment. In the context of a network simulation this means that you have to know which input you want to give to your network and which output you expect.

The next section will illustrate the main concepts of NEST simulations, using a simple simulation. The following sections will then give a step-by-step introduction to the main concepts of NEST simulations. Finally, we will discuss a complex example.

Contents

A simple simulation

The simplest simulation in NEST is that of a network which contains just one neuron:

 1: modeldict using 
 2: iaf_neuron Create /neuron Set


In the first line, we open the model dictionary to make all model names visible.

In the second line, we open the user dictionary, so that our definitions do not end up in the model dictionary.

We are going to simulate a standard integrate and fire model with resting potential at -70 mV and spike threshold at -55 mV. In the third line, we use the model iaf_neuron to create a neuron. The command Create returns a handle to the created neuron, which we store in the variable neuron.

Next, we would like to add a stimulation and a recording device to the neuron, so that we will see something during the simulation.

In our little example, we want to inject a current into the neuron and record its membrane potential. Thus, we need to create the corresponding devices and connect them to the neuron:

 3: voltmeter Create  /vm Set
 4: vm neuron Connect

Lines 5 and 6 create a voltmeter node and connect it to the neuron. The handle to the new voltmeter is stored in the variable vm<code>. In line 6, we see how the stored handles are used in the call to <code>Connect.

By default, the voltmeter will only print membrane potential values, so we configure it to show as the time stamp of each value as well.

 5: vm
 6: <<
 7:   /withtime true
 8: >> SetStatus

Now we create a DC generator which will supply a constant current to our neuron:

 9: dc_generator Create /stim Set
10: stim neuron Connect

Next, we want to set the amplitude of the DC generator such that it delivers enough current to elicit a spike in the neuron:

11: stim
12: <<
13   /amplitude 550.0
14: >> SetStatus

The double angled brackets << and >> delimit a dictionary definition which consists of successive /key value pairs. In our case, there is only one pair: the key /amplitude and its new value 500.0 pA.

We can now run the simulation and expect to see some results:

15: 15.0 Simulate

The command Simulate runs the simulation for the specified number of milliseconds. Below, you see a transscript of the simulation:

SLI ] 15.0 Simulate
Jul 28 15:24:44: *** Info: Simulate
Jul 28 15:24:44: Simulating 15 ms.
Jul 28 15:24:44: *** Info: Scheduler::simulate
Jul 28 15:24:44: Number of threads = 1
Jul 28 15:24:44: *** Info: Scheduler::calibrate
Jul 28 15:24:44: Please wait. Recalibrating elements.
Jul 28 15:24:44: Creating buffer for serial scheduling.
Jul 28 15:24:44: Simulating 3 nodes.
0       -70
1       -70
2       -70
3       -69.7811
4       -69.5644
5       -69.3498
6       -69.1374
7       -68.927
8       -68.7188

The output continues with

115     -55.1067
116     -55.036
117     -70
118     -70
119     -70

until it ends with

136     -70
137     -69.7811
138     -69.5644
139     -69.3498
140     -69.1374
141     -68.927
142     -68.7188
143     -68.5127
144     -68.3086
145     -68.1065
146     -67.9064
147     -67.7084
148     -67.5122
149     -67.3181

After some initial messages from the simulation scheduler, we see the output from the voltmeter. The numbers in the left column represent the network time in steps. The right column contains the values of the membrane potential at that step. The potential is given in mV.

By default, NEST uses a simulation stepsize of 0.1 ms. With a simulation time of 15 ms, we have 150 simulation steps.

The neuron that we have simulated was a standard integrate-and-fire neuron Tuckwell91 with a resting potential of -70 mV and a threshold at -55.0 mV. After 11.6 ms, the membrane potential has reached the threshold value and a spike event occurs. The membrane potential is then clamped to the resing value for 2 ms, the refractory period of the neuron. After the refractory period, the membrane continues to depolarize due to the continuing input current.

Nodes and Models

In NEST, the neural system is a collection of nodes and their interactions. Nodes correspond to things like neurons, synapses, and devices, and are implemented in C++. The network and its configuration are defined at the level of the simulation language interpreter.

Nodes are created from a set of prescribed models which are stored in the dictionary modeldict. The most important models are:

Model name Description
iaf_neuron Simple integrate-and-fire neuron with alpha-function PSCs.
voltmeter Device to observe membrane potentials.
spike_detector Device to observe spike times.
spike_generator Device to generate spikes at specific times.
dc_generator Device to generate a constant current.
ac_generator Device to generate an alternating (sine) current.
poisson_generator Device to generate poisson shotnoise.

In order to make the models visible to the interpreter, the model dictionary has to be opened.

Creating nodes

Nodes are created from a model, using the command Create.

SLI ] modeldict using
SLI ] iaf_neuron Create ==
[0 1]

In the fist line, we have opened the model dictionary. After that, we are able to access the available models and create one integrate and fire neuron from the model iaf_neuron.

The return value of Create is an array of integers that identifies the position of the new node in the network. This array is called address.

In NEST, the network is represented as a tree. The address denotes the position of the node within this tree. The root of the network has the address [0]. The first child of the root node will receive the address [0 1], the second child will receive the address [0 1], and so on.

Often, it is neccessary to have a large number of nodes of the same type. The command CreateMany can be used for this purpose. The following lines of code create 10 integrate and fire neurons:

SLI ] iaf_neuron 10 CreateMany ==
[0 11]

Sub-networks

We can introduce a new level to our network by adding a so called subnet:

SLI ] subnet Create ==
[0 12]

A subnet is like a directory in a file system. In it, we can create new nodes and even new subnets.

NEST maintains a pointer to the location where new nodes will be added. It is called current subnet. We can change the current working subnet, using the command ChangeSubnet:

SLI ] [0 12] ChangeSubnet

The command CurrentSubnet returns the address of the current subnet:

SLI ] CurrentSubnet == [0 12]

New nodes will now be created in the subnet at [0 12] and will receive addresses which start with [0 12 ...]:

SLI ] iaf_neuron Create ==
[0 12 1]

Network structures

Many network models use two or more-dimensional arrangements of identical nodes. In NEST, such structures can be conveniently created, using the command LayoutNetwork. The following lines of code create a 10 by 10 layer of integrate and fire neurons:

SLI ] iaf_neuron [10 10] LayoutNetwork == [0 1]

The return value is the address of the top-level subnet.

Starting from a subnet, it is also possible to determine the dimensions of this subnet, using the command NetworkDimensions. Applied to the address of a subnet, it returns an array with the dimensions of the subnet:

SLI ] [0 1] NetworkDimensions ==
[10 10]

The command PrintNetwork can be used to display the generated structure in a compressed format:

SLI ] [0 1] 1 PrintNetwork
+-[1] subnet dim=[10 10]
   |
   +-[1] subnet dim=[10]
   +-[2] subnet dim=[10]
   +-[3] subnet dim=[10]
   +-[4] subnet dim=[10]
   +-[5] subnet dim=[10]
   +-[6] subnet dim=[10]
   +-[7] subnet dim=[10]
   +-[8] subnet dim=[10]
   +-[9] subnet dim=[10]
   +-[10] subnet dim=[10]

The first parameter of PrintNetwork specifies at which position in the network the command should start. The second parameter defines how many levels will be printed. In this example, we started from the node [0 1], showing the first level.

We see that LayoutNetwork has created a subnet which contains 10 subnets with 10 integrate and fire neurons each.

Arguments Command Result Decription
modelid Create gid Create one node of the specified model.
modelid n CreateMany gid Create n nodes of the specified model.
modelid [d1 ... dn] LayoutNetwork -- Create a subnet with dimensions [d1 ... dn].
[adr] ChangeSubnet -- Go to a new working subnet.
-- CurrentSubnet [adr] Return the current working subnet.

Status information

Nodes have a state which can be extracted and modified. In the follwing example, we display the status information of one the neurons in the layer we have created above:

SLI ] [0 1 1 1] ShowStatus
--------------------------------------------------
Name                     Type                Value
--------------------------------------------------
frozen                   booltype            false
targets                  arraytype           <arraytype>
weights                  arraytype           <arraytype>
delays                   arraytype           <arraytype>
address                  arraytype           <arraytype>
global_id                integertype         1
local_id                 integertype         0
model                    literaltype         iaf_neuron
state                    integertype         32
number_of_targets        integertype         0
u                        doubletype          -70
U0                       doubletype          -70
I0                       doubletype          0
Theta                    doubletype          -55
LowerBound               doubletype          -1.79769e+308
C                        doubletype          250
Tau                      doubletype          10
TauSyn                   doubletype          2
TauR                     doubletype          2
last_spike               doubletype          -0.1
--------------------------------------------------
Total number of entries: 20

Using the command SetStatus, it is possible to change the entries of this so called status dictionary. The following lines of code change the threshold value Theta>/code> to $-60$ mV:

SLI ] [0 1 1 1] << /Theta -60.0 >> SetStatus
SLI ] [0 1 1 1] GetStatus /Theta get =
-60

Please note, that SetStatus is very tolerant with respect to the property that you are trying to change: If it does not know the property, or if the property cannot be changed, there will be no error and no warning! However, SetStatus does complain if the new value does not match in the expected type:

SLI ] [0 1 1 1] << /Theta (60) >> SetStatus
Aug 06 14:00:57: *** Error: getValue<FT>
Aug 06 14:00:57: Entry "Theta" is of incompatible type stringtype. 
Aug 06 14:00:57: The expected type was doubletype.
Error: /EntryTypeMismatch in SetStatus_ad
SLI [2]

In order to find out, which properties of a given model can be changed an which not, you have to refer to the model's documentation.

Connections

Connections between Nodes define possible interactions. A connection between two nodes is established, using the command Connect. Connect returns a number which identifies the connection at the sending node. This number is called port. The port is used to modify the connection.

Each connection has two parameters, a weight and a delay. The weight determines the strength of the connection, the delay determines how long an event needs to travel from the sending to the receiving node. The delay must be a positive number greater or equal to the simulation stepsize.

The commands SetWeight and SetDelay can be used to change weight or delay after a connection has been established.

Example:

SLI ] modeldict using
SLI ] iaf_neuron Create /n1 Set
SLI ] iaf_neuron Create /n2 Set
SLI ] iaf_neuron Create /n3 Set
SLI ]
SLI ] n1 n2 Connect =
0
SLI ] n1 n3 Connect =
1
SLI ]
SLI ] n1 0 5.0 SetWeight
SLI ] n1 1 -5.0 SetWeight

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.

Devices

Devices are network nodes which provide input or output to the network. They encapsulate the stimulation and measurement process. If you want to extract certain information from a simulation, you need a device which is able to deliver this information. Likewise, if you want to send specific input to the network, you need a device which delivers this input.

Devices have a built-in timer which controls the period of application. Outside this interval, a device will remain siltent. The timer can be configured using the command SetStatus.

By definition a device is active in the interval [t1,t2), if we can observe events E with time stamps tE which obey t_1 \leq t_E < t_2 for all E.

In other words, the interval during which the device is active corresponds to the range of time-stamps of the device's events.

Note that it is not possible to generate/observe an event with time stamp 0. Because of this, the value of the property /origin (see below) must be larger than 0.

Device parameters

The following entries of the status dictionary are the same for all stimulation and recording devices:

Property Type Decription
<code>/start double First time of activity, relative to the value

of origin in ms.

/stop double First time of inactivity, relative to the value of

origin in ms.

origin double Origin of the device clock, relative to the

network time in ms.

In general, the following must hold:

  1. start + origin > 0
  2. stop <= start
  3. If stop = start, the device is inactive.

Recording devices

All devices which are used to observe the state of other network nodes are called recording devices. Examples are voltmeter and spike_detector.

Recording devices have properties which control the amount and format of their output.

Update and parallel simulation

NEST simulations are time driven. The simulation time proceeds in discrete steps of size $dt$. In each time slice, all nodes in the system are updated and pending events are delivered.

NEST can use multiple threads to update the system. On symmetric multi processor machines (SMP) this can lead to a considerable performance gain. By default, only one thread is used.

Views
Personal tools