1

I am trying to develop a simple code in NEST: a network constituted by 10 identical neurons connected between them in order to form a loop. I would like to use arrays to develop this code, but I obtained error messages related to mismatch of argument type. Below I copy my code:

# SIMPLE NET -- FIRST TRIAL
# First example of a net made by 10 exicitatory neurons
# modeled by IAF models, which are connected in a loop
# and each neuron receives a synaptic current of double
# exponential type with rise and decay times respectively
# of 0.5 s. and 3 s.

###############################################################################
# Import the necessary modules

import pylab
import nest
import nest.raster_plot
import nest.voltage_trace
import numpy as np

###############################################################################
# Create the NODES
nest.SetDefaults("iaf_psc_alpha",
{"C_m": 10.0,
"tau_m": 15.58,
"t_ref": 2.0,
"E_L": -65.0,
"V_th": -40.0,
"V_reset": -65.0})

neurons  = nest.Create("iaf_psc_alpha",10)

###############################################################################
# SYNAPTIC CURRENTS NODES
exc   = 0.5
ini   = 3.0
Istim = 0.0
Istim1 = 20.0

nest.SetStatus(neurons[:1],  {"tau_syn_ex": exc, "tau_syn_in": ini, "I_e": Istim1})
nest.SetStatus(neurons[1:],  {"tau_syn_ex": exc, "tau_syn_in": ini, "I_e": Istim})

###############################################################################
# OUTPUT DEVICE
voltmeter1 = nest.Create("voltmeter")
nest.Connect(voltmeter1, neurons[1])

voltmeter2 = nest.Create("voltmeter")
nest.Connect(voltmeter2, neurons[2])

voltmeter3 = nest.Create("voltmeter")
nest.Connect(voltmeter3, neurons[3])

spikes = nest.Create('spike_detector')
###############################################################################
# EXCITATORY CONNECTION BETWEEN NODES in a LOOP
weight = 200.0
delay  = 1.0

#'excitatory',

for i in range(1,9,1):
 nest.Connect(neurons[i], neurons[i+1], syn_spec={'weight': weight, 'delay': delay})
 
 nest.Connect(neurons[10], neurons[1], syn_spec={'weight': weight, 'delay': delay})

###############################################################################
# SPIKE DETECTOR
nest.Connect(neurons,  spikes)

###############################################################################
#SIMULATIONS AND OUTPUTS
nest.Simulate(400.0)

nest.voltage_trace.from_device(voltmeter1)
nest.voltage_trace.from_device(voltmeter2)
nest.voltage_trace.from_device(voltmeter3)
nest.voltage_trace.show()

nest.raster_plot.from_device(spikes, hist=True)
nest.raster_plot.show()
Robin De Schepper
  • 4,942
  • 4
  • 35
  • 56
VDF
  • 143
  • 6
  • If any of the answers solved your problem, please accept them by clicking the gray checkmark under the votes on the left of the answer. If not, please comment on them explaining why the answer doesn't apply, or ask for clarifications. – Robin De Schepper Mar 15 '21 at 10:37
  • Is there also a specific error you encountered? – Robin De Schepper Mar 15 '21 at 10:48

1 Answers1

2

In Python arrays are indexed from zero, so the ten neurons created are neurons[0] to neurons[9]. To close the ring you need to connect the last neuron neurons[9] to the first neurons[0]. The neurons[10] does not exist.

Note also, that you close the ring 9 times, since the second Connect() call is also indented and thereby is inside the for loop.

If you use another Python feature, that negative indices are counted from the back, then your loop becomes very simple. Try something like this:

for i in range(10):
    print(f"connect {(i-1)%10} -> {i}")
    nest.Connect([neurons[i-1]], [neurons[i]], syn_spec={'weight': weight, 'delay': delay})

(You can of course omit the print() call. I just added it to show what happens.)

As you see this closes your ring automatically and you do not need the extra Connect() call. In Python lists and numpy arrays the convention is that neurons[-1] is the last element of the array, neurons[-2] is the one before the last, etc. Nice effect is that you see the 10 everywhere and it's easy to replace with a variable for the number of neurons. Also there is need anymore for making the range() so complex.

Additional note: For long rings it may be much faster to do array slicing:

nest.Connect(neurons[:-1], neurons[1:], syn_spec={'weight': weight, 'delay': delay})
nest.Connect([neurons[-1]], [neurons[0]], syn_spec={'weight': weight, 'delay': delay})

In this variant you need only two connect calls (without the Python for loop!), so most of the connections can be generated by the NEST kernel without returning control to Python after each synapse. Generally the fewer calls the better the kernel can make use of parallelization.

TerhorstD
  • 265
  • 1
  • 2
  • 12
  • Thanks for your useful comment. In addition to this remark, I would like also to add that in NEST, it is important to consider `nest.Connect([neurons[i-1]], [neurons[i]],..`, namely the double square bracket, because the Connect command as also other commands in NEST recognize that one is dealing with a list of neurons and not with a simple number (notation without the further square brackets). – VDF Feb 09 '21 at 17:11
  • 1
    You are right, in current versions this is still necessary. You can look forward to the next release where you don't need to remember that anymmore ;) – I also added an optimized way of connecting each neuron to the next. This can be done in a single call (but doesn't close the ring). – TerhorstD Feb 13 '21 at 18:14
  • NEST Simulator 3.0 now uses `NodeCollection` objects as parameters to `Connect()`, which can be [sliced and given as source or target directly](https://nest-simulator.readthedocs.io/en/v3.0/guides/nest2_to_nest3/nest3_features/nest3_node_handles.html). No need for the clumsy list syntax `[neurons[i]]` anymore, just `neurons[i]`. – TerhorstD Aug 10 '21 at 08:14