Some specific types of neuron groups are available to provide inputs to a network.
Poisson spike trains can be generated as follows:
group=PoissonGroup(100,rates=10*Hz)
Here 100 neurons are defined, which emit spikes independently according to Poisson processes with rates 10 Hz. To have different rates across the group, initialise with an array of rates:
group=PoissonGroup(100,rates=linspace(0*Hz,10*Hz,100))
Inhomogeneous Poisson processes can be defined by passing a function of time that returns the rates:
group=PoissonGroup(100,rates=lambda t:(1+cos(t))*10*Hz)
or:
r0=linspace(0*Hz,10*Hz,100)
group=PoissonGroup(100,rates=lambda t:(1+cos(t))*r0)
There is another class for Poisson inputs: PoissonInput, which updates the state variable of a NeuronGroup dynamically without storing in memory all the Poisson events. It can be used like this:
input = PoissonInput(group, N=N, rate=rate, weight=w, state='I')
In this case, the variable I represents the sum of N independent Poisson spike inputs with rate rate, where each individual synaptic event increases the variable I by w. Several PoissonInput objects can be created for a given NeuronGroup, in which case all the independent inputs are linearly superimposed.
A set of spike trains can be explicitly defined as list of pairs (i,t) (meaning neuron i fires at time t), which used to initialise a SpikeGeneratorGroup:
spiketimes=[(0,1*ms), (1,2*ms)]
input=SpikeGeneratorGroup(5,spiketimes)
The neuron 0 fires at time 1 ms and neuron 1 fires at time 2 ms (there are 5 neurons, but 3 of them never spike). One may also pass a generator instead of a list (in that case the pairs should be ordered in time).
There is a subclass of SpikeGeneratorGroup for generating spikes with a Gaussian distribution:
input=PulsePacket(t=10*ms,n=10,sigma=3*ms)
Here 10 spikes are produced, with spike times distributed according a Gaussian distribution with mean 10 ms and standard deviation 3 ms.
Inputs may also be defined by accessing directly the state variables of a neuron group. The standard way to do this is to insert parameters in the equations:
eqs = '''
dv/dt = (I-v)/tau : volt
I : volt
'''
group = NeuronGroup(100, model=eqs, reset=0*mV, threshold=15*mV)
group.I = linspace(0*mV, 20*mV, 100)
Here the value of the parameter I for each neuron is provided at initialisation time (evenly distributed between 0 mV and 20 mV).
It is possible to change the value of I every timestep by using a user-defined operation (see next section). Alternatively, you can use a TimedArray to specify the values the variable will have at each time interval, for example:
eqs = '''
dv/dt = (I-v)/tau : volt
I : volt
'''
group = NeuronGroup(1, model=eqs, reset=0*mV, threshold=15*mV)
group.I = TimedArray(linspace(0*mV, 20*mV, 100), dt=10*ms)
Here I will have value 0*mV for t between 0 and 10*ms`, ``0.2*mV between 10*ms and 20*ms, and so on. A more intuitive syntax is:
I = TimedArray(linspace(0*mV, 20*mV, 100), dt=10*ms)
eqs = '''
dv/dt = (I(t) * volt - v)/tau : volt
'''
group = NeuronGroup(1, model=eqs, reset=0*mV, threshold=15*mV)
Note however that the more efficient exact linear differential equations solver won’t be used in this case because I(t) could be any function, so the previous mechanism is often preferable. Additionally, be aware that the call to I(t) does return a value without units (as units cannot be stored in arrays), therefore you have to explicitly multiply it with the respective unit.
Another option is to link the variable of one group to the variables of another group using linked_var(), for example:
G = NeuronGroup(...)
H = NeuronGroup(...)
G.V = linked_var(H, 'W')
In this scenario, the variable V in group G will always be updated with the values from variable W in group H. The groups G and H must be the same size (although subgroups can be used if they are not the same size).