Input current in a neuron


#1

Good evening,

I’m studying Nengo simulator and I have some doubts about the input current J: in order to understand how it works, I have realized a very simple network with one RS Izhikevich neuron connected with a nengo.Node.

 import numpy as np
 from scipy import signal
 import os
 import nengo
 
 model = nengo.Network()
 with model:
     
     #### INPUT
     
         #Square wave at 10 Hz 
     stim_pre = nengo.Node(lambda t: 4*(signal.square(2 * np.pi * 10 * t, duty=0.5)+ 1))
     #stim_pre = nengo.Node([.5])
     
     ens = nengo.Ensemble(n_neurons=1, dimensions=1, neuron_type = nengo.Izhikevich())
 
     nengo.Connection(stim_pre, ens.neurons)
     
     ### Probe
     spike_pre = nengo.Probe(ens.neurons)
         #Voltage
     pre_voltage = nengo.Probe(ens.neurons, 'voltage')
         #Stimuli
     prestim=nengo.Probe(stim_pre)
     
 with nengo.Simulator(model, dt = 0.001) as sim:
     sim.run(1)
     time=sim.trange()

I have assigned to the nengo.Node different values:

  • Constant value J = 8;
  • Constant value J = 0.5;
  • Square wave with amplitude J = 8;

I get some results that I cannot understand, as the attached figure shows: to understand what is going on, I have looked at the implementation of the neurons, considering that the voltage of the neurons has [mV] as order of magnitude.

dV = (0.04 * voltage ** 2 + 5 * voltage + 140 - recovery + J) * 1000

So, also the current J has some order of magnitude or I have misunderstood how the nengo.Node works and how it provides current to the neuron?
In general, if I had n neurons inside the ensemble and I created this connection nengo.Connection(input_node,ensemble) , each of them would receive the same current I have declared?

Thank you in advance, I hope you can help me.

Kind regards

Emanuele


#2

Yes, J does have a magnitude. I’m not sure what it is off the top of my head. Judging from these notes on tuning curves and these notes on Izhekivitch neurons, it seems to be Hz.

Yes, but in this case, you would not be connecting to ens.neurons so the current would be modified by the encoders of the ensemble.


#3

I looked at the code of the Izhikevich neurons and the membrane voltage gets reset to -65 whenever the neuron spikes (i.e. membrane voltage exceeds 30) in the same timestep. It seems that this is happening in every timestep which fixes the membrane voltage at the observed -65. You might want to probe the actual spikes to verify that this is what is happening.

J is a current and the units (I think that is what you mean here, not the magnitude?) are definitely not Hz, but Ampere (A) (= charge / time = Coulomb/second = C/s) with some magnitude prefix. Probably mA (milli Ampere), but the 1000 factor in the implementation confuses me. It’s purpose is not clear to me: Does it account for the voltages being in mV? (But shouldn’t it be a division by 1000 in that case?) Or does it account for the timestep? (Though, that seems to be done in the next line and why would the factor of 1000 be hard coded?)


#4

So I should have two scenario:

  • if I wanted to provide directly 50 mA to the neurons in the ensemble, I should have to make a connection like this: nengo.Connection(input, ens.neurons) and the input is not encoded;
  • if I provided the input to the ensemble (nengo.Connection(input, ens) ) I should give the same encoded input to all the neurons in the ensemble.
    Is it right or I don’t understand something?

I checked the spikes of the neuron, and the neuron seems to spike every time step: according to you, it fires every time steps and so the voltage is reset.

I thought that all the calculations for the voltage are in µV [micro Volt], and the 1000 factor was used to give the membrane potential in mV, as it does. Could this be true also for the J current? I mean, from µA [micro Ampere] to mA [milli Ampere]?


#5

In the original paper everything is in mV.


#6

So, in order to give as input a generic quantity x with a unit prefix of µ [10-6], how do I declare the input? Of course, considering a direct link between the input and the neuron: nengo.Connection(stim_pre, ens.neurons[0])
I made some proofs considering an input equal to 15 and changing the order of magnitude, but I still don’t understand the correct behaviour.

I get these scenarios:

  • If I give a stimulus whose amplitude is with a magnitude less or equal to 10-2, the neuron doesn’t fire, so the stimulus is low;
  • if I give a stimulus with a magnitude equal to 10-1 the neuron fires with a burst (it should fire single spikes due to the fact is RS - neuron) when the input is high.
  • if I give a stimulus with a magnitude equal exactly to 15, the neuron fires but after the falling edge.

If is it possible, could you tell me where I’m wrong and why the voltage decreases until -250 mV?

Thank you in advance.

Emanuele


#7

I figure it out what was wrong. If I want give a J current equal to the signal that the neuron should represent, I must fix properly the gain, bias and encoder values due to the fact J = αex + Jbias; so I fixed α = e = 1 and Jbias= 0. In this way I have J = x and I can give directly the current I declared in the neuron, as the figure shows.
input_voltage

In order to see if I understand how NEF works, are these the next steps of Nengo?

  1. It computes the neural activity ai of the neuron (i.e. the spiking rate?)
  2. It decodes the neural activity with the following equation, due to the fact that the input changes in time: x˜ = ai(t)* h(t)di.

If these two steps are right, I would have some questions.

  • How is it evaluated the neural activity from the neuron model? I know that ai = G [J(t)], where G is the neuron model. But how can I pass from the voltage equation to the firing rate of the neuron?
  • From the simulator, can I know the value of the decoder di?
  • To see if the output of the ensemble is x˜, I have to compute the convolution. Can I do that considering the following code?
    out_ens = nengo.Probe(ens, synapse = tau), where tau is the costant term of the postsynaptic filter?

Thank you in advance,

Emanuele