Ambiguous on_pre operation

I have a problem with setting up a slightly comlicated on_pre operation.

Here’s the code that is supposed to increase the voltage of post-synapse. The set-up is standard: An LIF neuron connected to a spike generating source. However, I noticed a combination of “synaptic equations + spike generator object” leads to the correct behavior while some others don’t. In such a way that it seems unpredictable.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
Created on Wed Oct  5 11:43:46 2022

@author: arash

import matplotlib.pyplot as plt
import numpy as np
import brian2 as b2

def plot():
    """to plot results"""
    fig, axs = plt.subplots(4,1, sharex=True)

    for i in range(G.N):
        axs[0].plot(monS.t, monG.v[i,:], label='v')
    for id_ in range(len(S)):
        axs[1].plot(monS.t, monS.g[id_,:] ,label='g'+str(id_))
        axs[2].plot(monS.t, monS.h[id_,:] ,label='h'+str(id_))
        axs[3].plot(monS.t, monS.v_post[id_,:] ,label='v_post_'+str(id_))
    for ax in axs:


G = b2.NeuronGroup(1, 
                   dv/dt = -(v+70*mV)/tau : volt (unless refractory)
                   tau = 10*ms : second (shared)

# a convenient way to switch spike generation method
if spk_gen =='poisson':
    P = b2.PoissonGroup(1, rates= 50*b2.Hz)
    indices = np.array([0, 1, 2])
    times = np.array([1, 20, 30])*
    P = b2.SpikeGeneratorGroup(3, indices, times)

S = b2.Synapses(P, G, 
                dg/dt = (-g + h)/tau_s : 1 (clock-driven)
                dh/dt = -h/tau_s : 1 (clock-driven)
                tau_s = 5*ms : second (shared)
                J = 10*mV : volt
                v_post += J*g
                h = 1
                ''', # here is when the bug might be...

monG = b2.StateMonitor(G, ['v'],True)
monS = b2.StateMonitor(S, ['h','g','v_post'], record=True)
G.v = -70*b2.mV*

Running this leads to the expected result that is depicted below:

However, if I change the spk_gen flag and create spikes from SpikeGeneratorGroup, then the same code leads to the following, suggesting that the post_synapse is not updated at all:

Interestingly, if I change my on_pre argument using some explicit numerical value, say v_post += 10*mV, ..., or v_post += J (no multiplication by g), It works:

Why is that? How can I predict the behavior and how can I avoid unwanted responses?
Thank you very much!


Hi @arashgmn. The problem is that at the beginning of your simulation, g and h are both 0. This means that the very first spike for each synapse does not have any effect. In the PoissonGroup input, you have a single synapse that receives all the spikes, and all but the first one therefore have the expected effect. In the SpikeGeneratorGroup version, you create 3 synapses, and each of them only receives a single spike, so none of them is propagated. If you use a stimulation that is more similar to your PoissonGroup example, e.g.:

    indices = [0, 0, 0]
    times = [1, 20, 30]*
    P = b2.SpikeGeneratorGroup(1, indices, times)

you will get the expected result (note that the first spike triggers updates of g and h but no post-synaptic change):

Hope that clears things up!

It makes complete sense! Thank you @mstimberg for your prompt response. Hope this prevents others to make the same silly mistake :smiley:

1 Like