Exemple #1
0
    def _build_model(self, traj, brian_list, network_dict):
        """Builds the neuron groups from `traj`.

        Adds the neuron groups to `brian_list` and `network_dict`.

        """
        assert(isinstance(traj,SingleRun))

        model = traj.parameters.model

        # Create the equations for both models
        eqs_dict = self._build_model_eqs(traj)

        # Create inhibitory neurons
        eqs_i = eqs_dict['i']
        neurons_i = NeuronGroup(N=model.N_i,
                              model = eqs_i,
                              threshold=model.V_th,
                              reset=model.reset_func,
                              refractory=model.refractory,
                              freeze=True,
                              compile=True,
                              method='Euler')

        # Create excitatory neurons
        eqs_e = eqs_dict['e']
        neurons_e = NeuronGroup(N=model.N_e,
                              model = eqs_e,
                              threshold=model.V_th,
                              reset=model.reset_func,
                              refractory=model.refractory,
                              freeze=True,
                              compile=True,
                              method='Euler')


        # Set the bias terms
        neurons_e.mu =rand(model.N_e) * (model.mu_e_max - model.mu_e_min) + model.mu_e_min
        neurons_i.mu =rand(model.N_i) * (model.mu_i_max - model.mu_i_min) + model.mu_i_min

        # Set initial membrane potentials
        neurons_e.V = rand(model.N_e)
        neurons_i.V = rand(model.N_i)

        # Add both groups to the `brian_list` and the `network_dict`
        brian_list.append(neurons_i)
        brian_list.append(neurons_e)
        network_dict['neurons_e']=neurons_e
        network_dict['neurons_i']=neurons_i
    def _build_model(self, traj, brian_list, network_dict):
        """Builds the neuron groups from `traj`.

        Adds the neuron groups to `brian_list` and `network_dict`.

        """

        model = traj.parameters.model

        # Create the equations for both models
        eqs_dict = self._build_model_eqs(traj)

        # Create inhibitory neurons
        eqs_i = eqs_dict['i']
        neurons_i = NeuronGroup(N=model.N_i,
                                model=eqs_i,
                                threshold=model.V_th,
                                reset=model.reset_func,
                                refractory=model.refractory,
                                freeze=True,
                                compile=True,
                                method='Euler')

        # Create excitatory neurons
        eqs_e = eqs_dict['e']
        neurons_e = NeuronGroup(N=model.N_e,
                                model=eqs_e,
                                threshold=model.V_th,
                                reset=model.reset_func,
                                refractory=model.refractory,
                                freeze=True,
                                compile=True,
                                method='Euler')

        # Set the bias terms
        neurons_e.mu = rand(
            model.N_e) * (model.mu_e_max - model.mu_e_min) + model.mu_e_min
        neurons_i.mu = rand(
            model.N_i) * (model.mu_i_max - model.mu_i_min) + model.mu_i_min

        # Set initial membrane potentials
        neurons_e.V = rand(model.N_e)
        neurons_i.V = rand(model.N_i)

        # Add both groups to the `brian_list` and the `network_dict`
        brian_list.append(neurons_i)
        brian_list.append(neurons_e)
        network_dict['neurons_e'] = neurons_e
        network_dict['neurons_i'] = neurons_i
def ousim(mu_amp, mu_offs, sigma_amp, sigma_offs, freq, V_th):
    # mu_amp, mu_offs, sigma_amp, sigma_offs, freq, V_th = config
    if sigma_amp > sigma_offs:
        sigma_amp = sigma_offs
    # print("Setting up OU LIF simulation...")
    ounet = Network()
    clock.reinit_default_clock()
    eqs =Equations('dV/dt = mu-(V+V0)/tau + sigma*I/sqrt(dt) : volt')
    eqs+=Equations('dI/dt = -I/dt + xi/sqrt(dt) : 1')
    eqs+=Equations('mu = mu_amp*sin(t*freq*2*pi) + mu_offs : volt/second')
    eqs+=Equations('sigma = sigma_amp*sin(t*freq*2*pi) + sigma_offs :'
                                                        ' volt/sqrt(second)')
    eqs.prepare()
    ounrn = NeuronGroup(1, eqs, threshold=V_th, refractory=t_refr,
                                                                reset=V_reset)
    ounet.add(ounrn)

    ounrn.V = V0
    V_mon = StateMonitor(ounrn, 'V', record=True)
    st_mon = SpikeMonitor(ounrn)
    ounet.add(V_mon, st_mon)

    ounet.run(duration)

    V_mon.insert_spikes(st_mon, value=V_th*2)
    times = V_mon.times
    membrane = V_mon[0]
    return times, st_mon.spiketimes[0], membrane
def pif_reset():
    defaultclock.reinit()
    sim = Network()
    I = 0.2*nA
    R = 1*Mohm
    lifeq = """
    dV/dt = I*R/ms : volt
    Vth : volt
    """
    thstep = 15*mV
    nrn = NeuronGroup(1, lifeq, threshold="V>=Vth", reset="V=0*mV")
    nrn.V = 0*mV
    nrn.Vth = thstep
    sim.add(nrn)

    #connection = Connection(inputgrp, nrn, state="V", weight=0.5*mV)
    #sim.add(inputgrp, connection)

    vmon = StateMonitor(nrn, "V", record=True)
    thmon = StateMonitor(nrn, "Vth", record=True)
    spikemon = SpikeMonitor(nrn, record=True)

    sim.add(vmon, thmon, spikemon)
    sim.run(duration)
    return vmon, thmon, spikemon
def runsim(fin):
    clear(True)
    gc.collect()
    defaultclock.reinit()
    weight = 0.16*mV
    sim = Network()
    duration = 2.0*second
    Vth = 15*mV
    Vreset = 13.65*mV
    trefr = 2*ms
    lifeq = """
    dV/dt = -V/(10*ms) : volt
    Vth : volt
    """
    nrndef = {"model": lifeq, "threshold": "V>=Vth", "reset": "V=Vreset",
              "refractory": 0.1*ms}
    inputgroups = []
    connections = []
    neurons = []
    Nneurons = len(fin)
    neurons = NeuronGroup(Nneurons, **nrndef)
    neurons.V = 0*mV
    neurons.Vth = 15*mV
    for idx in range(Nneurons):
        fin_i = fin[idx]*Hz
        inputgrp = PoissonGroup(50, fin_i)
        conn = Connection(inputgrp, neurons[idx], state="V", weight=weight)
        inputgroups.append(inputgrp)
        connections.append(conn)
    voltagemon = StateMonitor(neurons, "V", record=True)
    spikemon = SpikeMonitor(neurons, record=True)
    sim.add(neurons, voltagemon, spikemon)
    sim.add(*inputgroups)
    sim.add(*connections)

    @network_operation
    def refractory_threshold(clock):
        for idx in range(Nneurons):
            if (len(spikemon.spiketimes[idx])
                    and clock.t < spikemon.spiketimes[idx][-1]*second+trefr):
                neurons.Vth[idx] = 100*mV
            else:
                neurons.Vth[idx] = Vth

    sim.add(refractory_threshold)
    print("Running simulation of {} neurons for {} s".format(Nneurons, duration))
    sim.run(duration, report="stdout")
    mnpss = []
    allnpss = []
    outisi = []
    for idx in range(Nneurons):
        vmon = voltagemon[idx]
        smon = spikemon[idx]
        if not len(smon):
            continue
        outisi.append(duration*1000/len(smon))
        if len(smon) > 0:
            npss = sl.tools.npss(vmon, smon, 0*mV, 15*mV, 10*ms, 2*ms)
        else:
            npss = 0
        mnpss.append(np.mean(npss))
        allnpss.append(npss)
    return outisi, mnpss
def run_simulation(realizations=1, trials=1, t=3000 * ms, alpha=1, ree=1, k=50, winlen=50 * ms, verbose=True, t_stim=0):
    """
    Run the whole simulation with the specified parameters. All model parameter are set in the function.

    Keyword arguments:
    :param realizations: number of repititions of the whole simulation, number of network instances
    :param trials: number of trials for network instance
    :param t: simulation time
    :param alpha: scaling factor for number of neurons in the network
    :param ree: clustering coefficient
    :param k: number of clusters
    :param t_stim : duration of stimulation of a subset of clusters
    :param winlen: length of window in ms
    :param verbose: plotting flag
    :return: numpy matrices with spike times
    """

    # The equations defining our neuron model
    eqs_string = """
                dV/dt = (mu - V)/tau + x: volt
                dx/dt = -1.0/tau_2*(x - y/tau_1) : volt/second
                dy/dt = -y/tau_1 : volt
                mu : volt
                tau: second
                tau_2: second
                tau_1: second
                """
    # Model parameters
    n_e = int(4000 * alpha)  # number of exc neurons
    n_i = int(1000 * alpha)  # number of inh neurons
    tau_e = 15 * ms  # membrane time constant (for excitatory synapses)
    tau_i = 10 * ms  # membrane time constant (for inhibitory synapses)
    tau_syn_2_e = 3 * ms  # exc synaptic time constant tau2 in paper
    tau_syn_2_i = 2 * ms  # inh synaptic time constant tau2 in paper
    tau_syn_1 = 1 * ms  # exc/inh synaptic time constant tau1 in paper
    vt = -50 * mV  # firing threshold
    vr = -65 * mV  # reset potential
    dv = vt - vr  # delta v
    refrac = 5 * ms  # absolute refractory period

    # scale the weights to ensure same variance in the inputs
    wee = 0.024 * dv * np.sqrt(1.0 / alpha)
    wie = 0.014 * dv * np.sqrt(1.0 / alpha)
    wii = -0.057 * dv * np.sqrt(1.0 / alpha)
    wei = -0.045 * dv * np.sqrt(1.0 / alpha)

    # Connection probability
    p_ee = 0.2
    p_ii = 0.5
    p_ie = 0.5
    p_ei = 0.5

    # determine probs for inside and outside of clusters
    p_in, p_out = get_cluster_connection_probs(ree, k, p_ee)

    mu_min_e, mu_max_e = 1.1, 1.2
    mu_min_i, mu_max_i = 1.0, 1.05

    # increase cluster weights if there are clusters
    wee_cluster = wee if p_in == p_out else 1.9 * wee

    # define numpy array for data storing
    all_data = np.zeros((realizations, trials, n_e + n_i, int(t / winlen) // 2))

    for realization in range(realizations):
        # clear workspace to make sure that is a new realization of the network
        clear(True, True)
        reinit()

        # set up new random bias parameter for every type of neuron
        mu_e = vr + np.random.uniform(mu_min_e, mu_max_e, n_e) * dv  # bias for excitatory neurons
        mu_i = vr + np.random.uniform(mu_min_i, mu_max_i, n_i) * dv  # bias for excitatory neurons

        # Let's create an equation object from our string and parameters
        model_eqs = Equations(eqs_string)

        # Let's create 5000 neurons
        all_neurons = NeuronGroup(
            N=n_e + n_i,
            model=model_eqs,
            threshold=vt,
            reset=vr,
            refractory=refrac,
            freeze=True,
            method="Euler",
            compile=True,
        )

        # Divide the neurons into excitatory and inhibitory ones
        neurons_e = all_neurons[0:n_e]
        neurons_i = all_neurons[n_e : n_e + n_i]

        # set the bias
        neurons_e.mu = mu_e
        neurons_i.mu = mu_i
        neurons_e.tau = tau_e
        neurons_i.tau = tau_i
        neurons_e.tau_2 = tau_syn_2_e
        neurons_i.tau_2 = tau_syn_2_i
        all_neurons.tau_1 = tau_syn_1

        # set up connections
        connections = Connection(all_neurons, all_neurons, "y")

        # do the cluster connection like cross validation: cluster neuron := test idx; other neurons := train idx
        kf = KFold(n=n_e, n_folds=k)
        for idx_out, idx_in in kf:  # idx_out holds all other neurons; idx_in holds all cluster neurons
            # connect current cluster to itself
            connections.connect_random(
                all_neurons[idx_in[0] : idx_in[-1]],
                all_neurons[idx_in[0] : idx_in[-1]],
                sparseness=p_in,
                weight=wee_cluster,
            )
            # connect current cluster to other neurons
            connections.connect_random(
                all_neurons[idx_in[0] : idx_in[-1]], all_neurons[idx_out[0] : idx_out[-1]], sparseness=p_out, weight=wee
            )

        # connect all excitatory to all inhibitory, irrespective of clustering
        connections.connect_random(all_neurons[0:n_e], all_neurons[n_e : (n_e + n_i)], sparseness=p_ie, weight=wie)
        # connect all inhibitory to all excitatory
        connections.connect_random(all_neurons[n_e : (n_e + n_i)], all_neurons[0:n_e], sparseness=p_ei, weight=wei)
        # connect all inhibitory to all inhibitory
        connections.connect_random(
            all_neurons[n_e : (n_e + n_i)], all_neurons[n_e : (n_e + n_i)], sparseness=p_ii, weight=wii
        )

        # set up spike monitors
        spike_mon_e = SpikeMonitor(neurons_e)
        spike_mon_i = SpikeMonitor(neurons_i)
        # set up network with monitors
        network = Network(all_neurons, connections, spike_mon_e, spike_mon_i)

        # run this network for some number of trials, every time with
        for trial in range(trials):
            # different initial values
            all_neurons.V = vr + (vt - vr) * np.random.rand(len(all_neurons)) * 1.4

            # Calibration phase
            # run for the first half of the time to let the neurons adapt
            network.run(t / 2)

            # reset monitors to start recording phase
            spike_mon_i.reinit()
            spike_mon_e.reinit()

            # stimulation if duration is given
            # define index variable for the stimulation possibility (is 0 for stimulation time=0)
            t_stim_idx = int(t_stim / (winlen / ms))
            if not (t_stim == 0):
                # Stimulation phase, increase input to subset of clusters
                all_neurons[:400].mu += 0.07 * dv
                network.run(t_stim * ms, report="text")
                # set back to normal
                all_neurons[:400].mu -= 0.07 * dv
                # save data
                all_data[realization, trial, :n_e, :t_stim_idx] = spikes_counter(spike_mon_e, winlen)
                all_data[realization, trial, n_e:, :t_stim_idx] = spikes_counter(spike_mon_i, winlen)
                # reset monitors
                spike_mon_e.reinit()
                spike_mon_i.reinit()
            # run the remaining time of the simulation
            network.run((t / 2) - t_stim * ms, report="text")

            # save results
            all_data[realization, trial, :n_e, t_stim_idx:] = spikes_counter(spike_mon_e, winlen)
            all_data[realization, trial, n_e:, t_stim_idx:] = spikes_counter(spike_mon_i, winlen)

            if verbose:
                plt.ion()
                plt.figure()
                raster_plot(spike_mon_e)
                plt.title("Excitatory neurons")

            spike_mon_e.reinit()
            spike_mon_i.reinit()

    return all_data
import spikerlib as sl
import numpy as np
import sys


sim = Network()
duration = 200*ms
dt = 0.1*ms
tau = 10*ms
Vth = 15*mV
Vreset = 0*mV
Vreset = 13.65*mV
lifeq = "dV/dt = -V/tau : volt"

lifnrn = NeuronGroup(1, lifeq, threshold="V>=Vth", reset=Vreset)
lifnrn.V = Vreset
sim.add(lifnrn)

Nin = 200
fin = 80*Hz
Sin = 0.6
sigma = 0.0*ms
weight = 0.1*mV
inputs = sl.tools.fast_synchronous_input_gen(Nin, fin, Sin, sigma, duration)
connection = Connection(inputs, lifnrn, "V", weight=weight)
sim.add(inputs, connection)

vmon = StateMonitor(lifnrn, "V", record=True)
spikemon = SpikeMonitor(lifnrn)
sim.add(vmon, spikemon)
                    delay=syn_delay,
                    weight = -jEI*1./(tau2i),
                    sparseness=pIE)

conn_ii = Connection(neurons_i,
                    neurons_i,
                    'yi',
                    delay=syn_delay,
                    weight = -jII*1./(tau2i),
                    sparseness=pII)



# Set the initial membrane potential somewhere between the reversal potential and slightly
# above the firing threshold. This will make some cells fire at t=0.
neurons_e.V = np.random.uniform(V_reset, V_th * 1.1, N_e)
neurons_i.V = np.random.uniform(V_reset, V_th * 1.1, N_i)




# Make some monitors to record spikes of all neurons and the membrane potential of a few
spike_mon_e = SpikeMonitor(neurons_e)
spike_mon_i = SpikeMonitor(neurons_i)
#state_mon_v_e = StateMonitor(neurons_e, 'V', record=[0,1,2])
#state_mon_v_i = StateMonitor(neurons_i, 'V', record=[0,1])
#state_mon_isyn = StateMonitor(neurons_i, 'Isyn', record=[0,1])



# Put everything into the network conn_ii conn_ee_clusters, conn_ei, conn_ie,  
Exemple #9
0
def run_simulation(realizations=1, trials=1, t=3000 * ms, alpha=1, ree=1,
                   k=50, winlen = 50 * ms, verbose=True, t_stim = 0):
    """
    Run the whole simulation with the specified parameters. All model parameter are set in the function.

    Keyword arguments:
    :param realizations: number of repititions of the whole simulation, number of network instances
    :param trials: number of trials for network instance
    :param t: simulation time
    :param alpha: scaling factor for number of neurons in the network
    :param ree: clustering coefficient
    :param k: number of clusters
    :param t_stim : duration of stimulation of a subset of clusters
    :param winlen: length of window in ms
    :param verbose: plotting flag
    :return: numpy matrices with spike times
    """

    # The equations defining our neuron model
    eqs_string = '''
                dV/dt = (mu - V)/tau + x: volt
                dx/dt = -1.0/tau_2*(x - y/tau_1) : volt/second
                dy/dt = -y/tau_1 : volt
                mu : volt
                tau: second
                tau_2: second
                tau_1: second
                '''
    # Model parameters
    n_e = int(4000 * alpha)  # number of exc neurons
    n_i = int(1000 * alpha)  # number of inh neurons
    tau_e = 15 * ms  # membrane time constant (for excitatory synapses)
    tau_i = 10 * ms  # membrane time constant (for inhibitory synapses)
    tau_syn_2_e = 3 * ms  # exc synaptic time constant tau2 in paper
    tau_syn_2_i = 2 * ms  # inh synaptic time constant tau2 in paper
    tau_syn_1 = 1 * ms  # exc/inh synaptic time constant tau1 in paper
    vt = -50 * mV  # firing threshold
    vr = -65 * mV  # reset potential
    dv = vt - vr # delta v
    refrac = 5 * ms  # absolute refractory period

    # scale the weights to ensure same variance in the inputs
    wee = 0.024 * dv * np.sqrt(1. / alpha)
    wie = 0.014 * dv * np.sqrt(1. / alpha)
    wii = -0.057 * dv * np.sqrt(1. / alpha)
    wei = -0.045 * dv * np.sqrt(1. / alpha)

    # Connection probability
    p_ee = 0.2
    p_ii = 0.5
    p_ie = 0.5
    p_ei = 0.5
    
    # determine probs for inside and outside of clusters
    p_in, p_out = get_cluster_connection_probs(ree, k, p_ee)

    mu_min_e, mu_max_e = 1.1, 1.2
    mu_min_i, mu_max_i = 1.0, 1.05

    # increase cluster weights if there are clusters
    wee_cluster = wee if p_in == p_out else 1.9 * wee

    # define numpy array for data storing
    all_data = np.zeros((realizations, trials, n_e+n_i, int(t/winlen)//2))

    for realization in range(realizations):
        # clear workspace to make sure that is a new realization of the network
        clear(True, True)
        reinit()

        # set up new random bias parameter for every type of neuron
        mu_e = vr + np.random.uniform(mu_min_e, mu_max_e, n_e) * dv  # bias for excitatory neurons
        mu_i = vr + np.random.uniform(mu_min_i, mu_max_i, n_i) * dv  # bias for excitatory neurons

        # Let's create an equation object from our string and parameters
        model_eqs = Equations(eqs_string)

        # Let's create 5000 neurons
        all_neurons = NeuronGroup(N=n_e + n_i,
                                  model=model_eqs,
                                  threshold=vt,
                                  reset=vr,
                                  refractory=refrac,
                                  freeze=True,
                                  method='Euler',
                                  compile=True)

        # Divide the neurons into excitatory and inhibitory ones
        neurons_e = all_neurons[0:n_e]
        neurons_i = all_neurons[n_e:n_e + n_i]

        # set the bias
        neurons_e.mu = mu_e
        neurons_i.mu = mu_i
        neurons_e.tau = tau_e
        neurons_i.tau = tau_i
        neurons_e.tau_2 = tau_syn_2_e
        neurons_i.tau_2 = tau_syn_2_i
        all_neurons.tau_1 = tau_syn_1

        # set up connections
        connections = Connection(all_neurons, all_neurons, 'y')

        # do the cluster connection like cross validation: cluster neuron := test idx; other neurons := train idx
        kf = KFold(n=n_e, n_folds=k)
        for idx_out, idx_in in kf:  # idx_out holds all other neurons; idx_in holds all cluster neurons
            # connect current cluster to itself
            connections.connect_random(all_neurons[idx_in[0]:idx_in[-1]], all_neurons[idx_in[0]:idx_in[-1]],
                                       sparseness=p_in, weight=wee_cluster)
            # connect current cluster to other neurons
            connections.connect_random(all_neurons[idx_in[0]:idx_in[-1]], all_neurons[idx_out[0]:idx_out[-1]],
                                       sparseness=p_out, weight=wee)

        # connect all excitatory to all inhibitory, irrespective of clustering
        connections.connect_random(all_neurons[0:n_e], all_neurons[n_e:(n_e + n_i)], sparseness=p_ie, weight=wie)
        # connect all inhibitory to all excitatory
        connections.connect_random(all_neurons[n_e:(n_e + n_i)], all_neurons[0:n_e], sparseness=p_ei, weight=wei)
        # connect all inhibitory to all inhibitory
        connections.connect_random(all_neurons[n_e:(n_e + n_i)], all_neurons[n_e:(n_e + n_i)], sparseness=p_ii,
                                   weight=wii)

        # set up spike monitors
        spike_mon_e = SpikeMonitor(neurons_e)
        spike_mon_i = SpikeMonitor(neurons_i)
        # set up network with monitors
        network = Network(all_neurons, connections, spike_mon_e, spike_mon_i)

        # run this network for some number of trials, every time with
        for trial in range(trials):
            # different initial values
            all_neurons.V = vr + (vt - vr) * np.random.rand(len(all_neurons)) * 1.4

            # Calibration phase
            # run for the first half of the time to let the neurons adapt
            network.run(t/2)

            # reset monitors to start recording phase
            spike_mon_i.reinit()
            spike_mon_e.reinit()

            # stimulation if duration is given
            # define index variable for the stimulation possibility (is 0 for stimulation time=0)
            t_stim_idx = int(t_stim / (winlen/ms))
            if not(t_stim==0):
                # Stimulation phase, increase input to subset of clusters
                all_neurons[:400].mu += 0.07 * dv
                network.run(t_stim * ms, report='text')
                # set back to normal
                all_neurons[:400].mu -= 0.07 * dv
                # save data
                all_data[realization, trial, :n_e, :t_stim_idx] = spikes_counter(spike_mon_e, winlen)
                all_data[realization, trial, n_e:, :t_stim_idx] = spikes_counter(spike_mon_i, winlen)
                # reset monitors
                spike_mon_e.reinit()
                spike_mon_i.reinit()
            # run the remaining time of the simulation
            network.run((t/2) - t_stim*ms, report='text')

            # save results
            all_data[realization, trial, :n_e, t_stim_idx:] = spikes_counter(spike_mon_e, winlen)
            all_data[realization, trial, n_e:, t_stim_idx:] = spikes_counter(spike_mon_i, winlen)

            if verbose:
                plt.ion()
                plt.figure()
                raster_plot(spike_mon_e)
                plt.title('Excitatory neurons')

            spike_mon_e.reinit()
            spike_mon_i.reinit()

    return all_data
dn/dt=5*(alphan*(1-n)-betan*n) : 1

alphan=-0.01/mV*(V+34*mV)/(exp(-0.1/mV*(V+34*mV))-1)/ms : Hz

betan=0.125*exp(-(V+44*mV)/(80*mV))/ms : Hz

dgExc/dt = -gExc*(1./taue) : siemens

dgInh/dt = -gInh*(1./taui) : siemens

Iapp : amp

'''
neuron = NeuronGroup(1, eqs, threshold=threshold, method='RK')

neuron.V = -70*mV

# delays
B1, A1, A2, A3 = 5*ms, 20*ms, 30*ms, 40*ms
target_delay = A2-B1  # delay to be learned by neuron

spikes_A = [(0, 10*ms), (0, 115*ms), (0, 300*ms), (0, 450*ms)]
spikes_B = [(1, 10*ms), (1, 130*ms), (1, 335*ms), (1, 475*ms)]
inputs = SpikeGeneratorGroup(2, spikes_A+spikes_B)
synapse_A = Synapses(inputs[0], neuron,
                     model="w : siemens", pre="gExc_post += w")
synapse_A[:,:] = 3
synapse_A.w = WExc
synapse_A.delay[0] = A1
synapse_A.delay[1] = A2
synapse_A.delay[2] = A3
tau = 20*ms
Nnrns = 4
Ningroups = 1
Nin_per_group = 50
fin = 20*Hz
ingroup_sync = [0.5]
sigma = 0*ms
weight = 2.0*mV
Nallin = Nin_per_group*Ningroups
Nin = 25  # total number of connections each cell receives

lifeq_exc = Equations("dV/dt = (Vrest-V)/tau : volt")
lifeq_exc.prepare()
nrngroup = NeuronGroup(Nnrns, lifeq_exc, threshold="V>Vth", reset=Vrest,
                       refractory=2*ms)
nrngroup.V = Vrest
network.add(nrngroup)
print("Setting up inputs and connections ...")
ingroups = []
inpconns = []
for ing in range(Ningroups):
    ingroup = sl.tools.fast_synchronous_input_gen(Nin_per_group, fin,
                                                  ingroup_sync[ing], sigma, duration,
                                                  shuffle=False)
    inpconn = Connection(ingroup, nrngroup, 'V')
    ingroups.append(ingroup)
    inpconns.append(inpconn)
inputneurons = []

# CONNECTIONS
Sin = []