Simple gap junction within two neurons

Hi, now I’m trying to implement one of the simplest simulation of gap junction according to example in Brian2.
https://brian2.readthedocs.io/en/stable/examples/synapses.gapjunctions.html

What I want to do is that, there are two neuron and one gap junction from pre to post neuron.
The tried program is below, and it seems my description of synapse equation and/or definition of unit is a bit wrong?

from brian2 import *

# Parameters
    # Neuron Parameters
    
N1 = 1
N2 = 1
    
Cm  = 289.5*pF
gL = 28.95*nS
EL = -70*mV
Vt = -57*mV
Vr = -70*mV
tau_ref = 5*ms

w = 4*mV

# I = 1*nA
    
# Neuron model
neuron_eqs = '''
dv/dt = (gL*(EL-v) + I +Igap)/Cm    : volt
I : amp
Igap : amp
'''

neurons_pre = NeuronGroup(N1, neuron_eqs, threshold='v>Vt', reset='v = Vr', refractory=5*ms,
                method='exact')
neurons_pre.v = EL
neurons_pre.I = 1*nA


neurons_post = NeuronGroup(N2, neuron_eqs, threshold='v>Vt', reset='v = Vr', refractory=5*ms,
                method='exact')
neurons_post.v = EL
neurons_post.I = 0*nA


S = Synapses(neurons_pre, neurons_post, '''
             w : 1 # gap junction conductance
             Igap_syn = w * (v_pre - v_post) : volt
             ''')
S.connect(i=[0,1],j=0) 

neuron_pre_mon = SpikeMonitor(neurons_pre)
neuron_post_mon = SpikeMonitor(neurons_post)
neuron_pre_state = StateMonitor(neurons_pre, 'v', record=True)
neuron_post_state = StateMonitor(neurons_post, 'v', record=True)


run(20 * ms)

subplot(411)
plot(neuron_pre_mon.t/ms, neuron_pre_mon.i,',k')
xlim(0,20)

subplot(412)
plot(neuron_pre_state.t/ms, neuron_pre_state.v[0]/mV)
xlim(0,20)
xlabel('t (ms)')
ylabel('v (mV)')

subplot(413)
plot(neuron_post_mon.t/ms, neuron_post_mon.i,',k')
xlim(0,20)

subplot(414)
plot(neuron_post_state.t/ms, neuron_post_state.v[0]/mV)
xlim(0,20)
xlabel('t (ms)')
ylabel('v (mV)')


show()

I want to see, like actual gap junction, pre-neuron also gets voltage change from post-neuron. That’s bidirectional transmission of response through electric synapse.

If somebody can advice me, or share some information, I’m really glad to solve the problems!!

Ysj

Hi,
there are a few issues in the code. The error you are getting is due to the S.connect line, where you are trying to connect the first and second neuron from group neuron_pre (i.e. neurons with indices 0 and 1) to the neuron in the second group. This fails, since the group neuron_pre only contains a single neuron. Replacing it with S.connect(i=0, j=0) will make it work. But as a general rule, you should only have one NeuronGroup object for each different neuron model – in your case the two neurons use the same model (equations, threshold, …) and could therefore be represented by the same object. This not only has the advantage of increased efficiency (arguably not that important for a simple model like this), but also makes things simpler later on. For example, you do not need to duplicate monitors any more.

This leads to this code, ignoring the synapse for the moment:

neurons = NeuronGroup(N1 + N2, neuron_eqs, threshold='v>Vt', reset='v = Vr',
                      refractory=5 * ms, method='exact')
neurons.v = EL
neurons.I = [1, 0] * nA

# …
neuron_mon = SpikeMonitor(neurons)
neuron_state = StateMonitor(neurons, 'v', record=True)

In your synaptic model, you are declaring a gap-junction current I_syn, but this current is not applied to any neuron, so it won’t have any effect. You need to use a summed variable, as in the gap junction example (it is “summed”, because each neuron could be connected to several other neurons). Also note that the gap junction conductance w needs to have units of siemens, otherwise multiplying it with the difference in membrane potential won’t give you a current.
Now, in the gap junction example we use Igap_post which means that the current is only applied to the post-synaptic neuron. This admittedly looks odd, since as you say, transmission through an electric synapse is bidirectional. The explanation is that the example uses two connections for each electrical synapse, i.e. there is one synapse connecting neuron 0 → 1, and another one connecting neuron 1 → 0, leading to bidirectional transmission. In principle it is possible to only have a single connection per electrical synapse and set both a _pre and a _post variable, but there is a technical limitation that prevents this from working when you connect a group to itself. So I’d simply use the “double connection trick”:

S = Synapses(neurons, neurons, '''
             w : siemens (constant) # gap junction conductance
             Igap_post = w * (v_pre - v_post) : amp (summed)
             ''')
S.connect(i=[0, 1], j=[1, 0])  # or simply S.connect() since it connects all-to-all

Now, there is one more thing that is missing: by default the value of S.w is 0, so you have to set it to something else. Note that using the “double connection trick” you have to take care yourself that the conductance is the same in both directions:

S.w = 10*nS  # Uses the same conductance everywhere

A final note: It seems that in your example you are relying on the first neuron to make the second neuron spiking (since the second’s neuron input current is 0). This won’t work, since you are using an integrate-and-fire model, which does not model the membrane potential during an action potential. This means, the membrane potential of the first neuron will never go above the threshold and can therefore never “pull” the second neuron over it. There are still interesting things to analyze in integrate-and-fire models with gap junctions, e.g. subthreshold interactions or the synchronization of intrinsically spiking neurons (as in the example in the documentation). But if you are interested in seeing the effect of an action potential on another neuron, you need to switch your model to something else (Hodgkin-Huxley type, Morris&Lecar, Hindmarsh&Rosen, …).

Hi Marcel,

Thank you so much for your detailed and kind explanation.
I’m glad you told me underlying tricks and the potential target by implementing this synapse. Thank you very much again for a lot of explanation and tried to make me understand algorithms and the further.

May I ask one more question to you?
I really know, the Brian website contains lots of nice examples that we can try first.
Are there further website or community that we can find basic Brian example to know fundamental grammar and/or examples? (of course here is one of them!)

I share the modified code here, as maybe users are of interest to look at the outcome.

from brian2 import *

# Parameters
    # Neuron Parameters
    
N1 = 1
N2 = 1
    
Cm  = 289.5*pF
gL = 28.95*nS
EL = -70*mV
Vt = -57*mV
Vr = -70*mV
tau_ref = 5*ms

w = 4*mV

# Time constants
taue = 5*ms
taui = 10*ms
# Reversal potentials
Ee = 0*mV
Ei = -80*mV
we = 30*nS  # excitatory synaptic weight
wi = 6*nS

# I = 1*nA
    
# Neuron model
neuron_eqs = '''
dv/dt = (gL*(EL-v) +ge*(Ee-v) +gi*(Ei-v) +I +Igap)/Cm    : volt
dge/dt = -ge*(1./taue) : siemens
dgi/dt = -gi*(1./taui) : siemens
I : amp
Igap : amp
'''

neurons = NeuronGroup(N1 + N2, neuron_eqs, threshold='v>Vt', reset='v = Vr', refractory=5*ms,
                method='euler')
neurons.v = EL
neurons.I = [1, 0]*nA
neurons.ge = [0, 0]*nS
neurons.gi = [0, 0]*nS


S = Synapses(neurons, neurons, '''
             w : siemens (constant) # gap junction conductance
             Igap_post = w * (v_pre - v_post) : amp (summed)
             ''')
S.connect(i=[0, 1], j=[1, 0])  # or simply S.connect() since it connects all-to-all
S.w = 10*nS  # Uses the same conductance everywhere

neuron_mon = SpikeMonitor(neurons)
neuron_state = StateMonitor(neurons, 'v', record=True)

run(50 * ms)

subplot(211)
plot(neuron_state.t/ms, neuron_state.v[0]/mV)
xlim(0,50)

subplot(212)
plot(neuron_state.t/ms, neuron_state.v[1]/mV)
xlim(0,50)

show()

Hi @ysj, you are welcome :blush:.

I don’t know of any collection of simple examples outside of our documentation (including the tutorials). There are a number of models that were used in publications on ModelDB, but these are mostly quite complex. We’ve been long thinking about having some kind of “model gallery”, but so far we were lacking the (time) resources to make this happen…

Thanks for sharing your full script. Just a small remark: for code samples, the best is to post them like this (i.e. between ```Python and ```), so they get nicely highlighted and special characters do not mess around with the formatting:

```Python
from brian2 import *
# more code ...
```

I edited your post to apply this.

Hi Marcel,

Thank you very much for your information and also for the editing!!
I can guess it is much works to make that kind of things additionally.

Ysj

1 Like