Thank you!
Based on what we discussed, I wrote a code that is just an example of what I am doing. It includes two exc and inh populations and feedforward poisson input. All synapses are fast, and just EE synapses are slow. What do you think about it?
I actually prefer not to have this run_regurarly because I am implementing a hierarchical network, and this is just one layer of that.
from brian2 import *
# Parameters
tau_slow = 10*ms # Time constant for slow exponential kernel
tau = 10*ms # Time constant for post-synaptic current decay
# Number of neurons
N = 3
rate = 100*Hz # Rate of the Poisson input
eqs = '''
dv/dt = (-v + I_slow) / tau : volt
dI_slow/dt = -I_slow / tau : volt
I_exc = I_slow + I_fast : volt
I_fast : volt
I_inh : volt
'''
# Neuron group with excitatory neurons
exc = NeuronGroup(N, eqs, threshold='v > 0.5*volt', reset='v = 0*volt', method='euler')
exc.v = 0*volt
# Inhibitory population
inh = NeuronGroup(N, eqs, threshold='v > 0.5*volt', reset='v = 0*volt', method='euler')
inh.v = 0*volt
# Define the Poisson spike train for excitatory neurons
poisson_group = PoissonGroup(10, rates=rate)
# Connect PoissonGroup to excitatory neurons
poisson_syn = Synapses(poisson_group, exc, model='w:1', on_pre='I_fast += w*volt') # fast feedforward
poisson_syn.connect()
syn_ee = Synapses(exc, exc, "w : 1", on_pre="I_slow += w*volt") # excitatory ei synapse (slow)
syn_ee.connect()
syn_ee.w = np.random.rand(3,3).flatten()
syn_ie = Synapses(inh, exc, "w : 1", on_pre="I_inh -= w*volt") # Inhibitory ie synapse (fast)
syn_ie.connect()
syn_ie.w = np.random.rand(3,3).flatten()
syn_ei = Synapses(exc, inh, "w : 1", on_pre="I_fast += w*volt") # excitatory ei synapse (fast)
syn_ei.connect()
syn_ei.w = np.random.rand(3,3).flatten()
syn_ii = Synapses(inh, inh, "w : 1", on_pre="I_inh -= w*volt") # Inhibitory ii synapse (fast)
syn_ii.connect()
syn_ii.w = np.random.rand(3,3).flatten()
# Reset previous current before applying synapses
exc.run_regularly("I_fast = 0*volt; I_inh=0*volt", when="before_synapses", dt=defaultclock.dt)
# Apply new currents after applying synapses
exc.run_regularly("v += I_fast; v -= I_inh", when="after_synapses", dt=defaultclock.dt)
# Reset previous current before applying synapses
inh.run_regularly("I_fast = 0*volt; I_inh=0*volt", when="before_synapses", dt=defaultclock.dt)
# Apply new currents after applying synapses
inh.run_regularly("v += I_fast; v -= I_inh", when="after_synapses", dt=defaultclock.dt)
# Monitor for recording variables
M = StateMonitor(exc, ['v', 'I_exc'], record=True)
spike_monitor_exc = SpikeMonitor(exc)
spike_monitor_inh = SpikeMonitor(inh)
# Run the simulation
run(20*ms)
figure(figsize=(15, 6))
# Plot post-synaptic current
subplot(121)
plot(M.t/ms, M.I_exc[0], label='I_exc')
xlabel('Time (ms)')
ylabel('I_exc')
legend()
# Plot spike trains
subplot(122)
plot(spike_monitor_exc.t/ms, spike_monitor_exc.i, '.k', label='Excitatory neurons')
plot(spike_monitor_inh.t/ms, spike_monitor_inh.i, '.r', label='Inhibitory neurons')
xlabel('Time (ms)')
ylabel('Neuron index')
title('Spike trains')
legend()
show()
PS. code runs without error with no response.