Spike-based synaptic coincidence detection

26 views
Skip to first unread message

Wilhelm Braun

unread,
Dec 4, 2019, 4:29:49 AM12/4/19
to Brian Development
Dear all,

I wonder whether there is a simple way to implement a spike-based synaptic coincidence detector in brian2.

It should, for one synaptic connection, count pre-synaptic spikes in a certain fixed time window up to the current simulation time, and then determine how many spikes fall in this window. If this count exceeds a certain number of spikes, some post-synaptic event is triggered.

This is related to my previous question ("Update summed variables with general function"), which maybe wasn't very clear. The solution suggested in the answer to that post implemented some form of coincidence detection, but only approximately with the help of a special input variable.

Thanks a lot for your answer.

Best,

Wilhelm

Marcel Stimberg

unread,
Dec 4, 2019, 12:42:17 PM12/4/19
to brian-de...@googlegroups.com
Hi Wilhelm,

in general, I'd recommend using some kind of "activity trace" for the
coincidence detection or simply use a neuron model with a short time
constant that will act as a coincidence detector all by itself. However,
if you need a more abstract model that explicitly counts spikes in an
interval, you can introduce a "spike counter" variable and use two
synaptic pathways
(https://brian2.readthedocs.io/en/stable/user/synapses.html#multiple-pathways),
one that increases the counter for each spike, and one that decreases
the counter again after a certain interval. This way, the spike counter
variables will always store the number of spikes during the preceding
interval and you can use it to trigger a threshold. Here's a little
example that shows what I mean, using a 10ms window:

from brian2 import *

inp = PoissonGroup(1, rates=50*Hz)
out = NeuronGroup(1, 'spike_counter : integer')
syn = Synapses(inp, out, on_pre={'up': 'spike_counter += 1',
                                 'down': 'spike_counter -= 1'},
               delay={'up': 0*ms, 'down': 10*ms})
syn.connect()
inp_mon = SpikeMonitor(inp)
out_mon = StateMonitor(out, 'spike_counter', record=0)
run(100*ms)
plt.plot(out_mon.t/ms, out_mon.spike_counter[0])
plt.plot(inp_mon.t/ms, np.zeros_like(inp_mon.t), 'rx')
plt.show()

If you really need this counter to be per synapse an not per neuron,
then things get a little more complicated. I did no think this through
in detail, but I think you'll have to introduce a dummy group that just
contains the spike_counter and elicits events (with one neuron per
synapse), and then use this group to deliver the final events to the
target group. So instead of in -> syn -> out, you'd use a structure like
in -> syn -> dummy -> syn2 -> out.

Hope that helps, best

  Marcel


Wilhelm Braun

unread,
Dec 5, 2019, 8:20:33 AM12/5/19
to Brian Development
Hi Marcel,

thanks a lot for your swift and super helpful answer. It's amazing how flexible brian2 is in the end. Your suggestion is exactly what I needed.

I have an additional short question about the introduction of delays when using 'run_on_event'- is it possible, in addition to an 'event_delay' (which specifies the minimal amount of temporal separation between events), to also specify a delay similar to a synaptic delay? Concretely,

group_recorded = NeuronGroup(N,  eqs, threshold="V > vthr", events = {'event_1': 'condition_1'}, reset='V=V_reset', refractory= tref, method = 'euler')

group_recorded
.run_on_event('event_1', 'w += increment; last_event = t') #How to add a delay here, so that w is only incremented a certain time after event_1 begins?

Thanks again.

Best,

Wilhelm

Marcel Stimberg

unread,
Dec 6, 2019, 8:45:29 AM12/6/19
to brian-de...@googlegroups.com

Hi Wilhelm,

I have an additional short question about the introduction of delays when using 'run_on_event'- is it possible, in addition to an 'event_delay' (which specifies the minimal amount of temporal separation between events), to also specify a delay similar to a synaptic delay? Concretely,

group_recorded = NeuronGroup(N,  eqs, threshold="V > vthr", events = {'event_1': 'condition_1'}, reset='V=V_reset', refractory= tref, method = 'euler')

group_recorded
.run_on_event('event_1', 'w += increment; last_event = t') #How to add a delay here, so that w is only incremented a certain time after event_1 begins?


The only way to trigger events with a delay is to use synapses. In your case, you could remove the `w += increment` from the run_on_event call, and instead use a synapse to apply it with a certain delay:

delayed_trigger = Synapses(group_recorded, group_recorded,
                           on_pre='w_post += increment', on_event='event_1',
                           delay=...)

delayed_trigger.connect(j='i')  # connect each neuron to itself

Best,

  Marcel

Wilhelm Braun

unread,
Dec 9, 2019, 4:36:46 AM12/9/19
to Brian Development
Hi Marcel,

thanks a lot again for this very helpful answer.

Best,

Wilhelm
Reply all
Reply to author
Forward
0 new messages