# How to activate synaptic pathways on custom events only?

**URL:** <https://brian.discourse.group/t/how-to-activate-synaptic-pathways-on-custom-events-only/1213>\
**Category:** Support\
**Tags:** synapses, custom-event, threshold\
**Created:** [15 May 2024 16:06 UTC](https://brian.discourse.group/t/how-to-activate-synaptic-pathways-on-custom-events-only/1213 "2024-05-15T16:06:47Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mmiekus](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/mmiekus/32/454_2.png) [@mmiekus](https://brian.discourse.group/u/mmiekus)\
**Post date:** [15 May 2024 16:06 UTC](https://brian.discourse.group/t/how-to-activate-synaptic-pathways-on-custom-events-only/1213/1 "2024-05-15T16:06:48Z")

</div>

# Description of problem

Hello, I have neurons with two types of events. I want to activate different synaptic pathways depending on 1) which event occurred and 2) whether it happened at the pre- or post-synaptic neuron. All the information I found in the documentation does not explain such a general case.

# What you have already tried

```auto
import brian2 as br

n = br.NeuronGroup(2, model="dV/dt = cos(t/msecond)/msecond : 1",
                      threshold = "V>=0.3", reset="", events={'under':'V<0.3'})
n.V = [0, -0.5]

s = br.Synapses(n, n,
                model="""
                       a:1
                       b:1
                       c:1
                       d:1""",
                on_event={"path_a":"spike",
                          "path_b":"under",
                          "path_c":"spike",
                          "path_d":"under"},
                on_pre={"path_a":"a=a+1",
                        "path_b":"b=b+1"},
                on_post={"path_c":"c=c+1",
                         "path_d":"d=d+1"})
s.connect(i=0, j=1)
br.run(0.01*br.second)

```

# Actual output

The `spike` and `under` events in this code are recognised correctly. However, both paths a and b get executed at presynaptic spikes, and paths c and d at postsynaptic spikes. Nothing seems to happen at the `under` event. I would like to have paths b and d happen and the pre- or postsynaptic `under` events. How can I do this?  
Thank you

---

<div class="post-metadata">

**Author:** ![mstimberg](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/mstimberg/32/11_2.png) [@mstimberg](https://brian.discourse.group/u/mstimberg)\
**Post date:** [15 May 2024 16:53 UTC](https://brian.discourse.group/t/how-to-activate-synaptic-pathways-on-custom-events-only/1213/2 "2024-05-15T16:53:08Z")

</div>

Hi @mmiekus, very interesting use case! This is a pity, our underlying machinery would support this effortlessly, but we are not exposing this in the `Synapses` interface. In fact, the `on_event` dictionary should only refer to `pre` and `post`, i.e. you can only set one event type for all `pre` and one event type for all `post` pathways. Fixing this in the code is almost trivial, but I’d need to have a more thorough look to make sure that this does not break anything. Do you necessarily need all these pathways to be in a single `Synapses` object, i.e. should they operate on the same variables? Otherwise, you could have two `Synapses` objects, each with a single `pre`/`post` event it listens to.

---

<div class="post-metadata">

**Author:** ![mmiekus](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/mmiekus/32/454_2.png) [@mmiekus](https://brian.discourse.group/u/mmiekus)\
**Post date:** [15 May 2024 17:19 UTC](https://brian.discourse.group/t/how-to-activate-synaptic-pathways-on-custom-events-only/1213/3 "2024-05-15T17:19:05Z")

</div>

Thank you for the response. Unfortunately, I was planning to use the pathways to modify the same synaptic variables. However, the whole setup is actually my attempt at implementing a change in synaptic weight, which should happen when both pre- and postsynaptic neurons are above the threshold (without reset). And the change should happen only once, when the second of the neurons crosses the threshold (and not at each timestep). Maybe you would have any ideas if I can implement it somehow in a more straightforward way? I suppose I can always use some NetworkOperations.  
A simpler question: is there an easy way to get an event only at the first timestep when the threshold condition is fulfilled?

---

<div class="post-metadata">

**Author:** ![mstimberg](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/mstimberg/32/11_2.png) [@mstimberg](https://brian.discourse.group/u/mstimberg)\
**Post date:** [16 May 2024 08:03 UTC](https://brian.discourse.group/t/how-to-activate-synaptic-pathways-on-custom-events-only/1213/4 "2024-05-16T08:03:49Z")

</div>

> [@mmiekus](#):
>
> A simpler question: is there an easy way to get an event only at the first timestep when the threshold condition is fulfilled?

Just a quick answer for this part: The usual way to do this is using a refractory condition, e.g. :

```python
 n = br.NeuronGroup(..., threshold = "V>=0.3", refractory="V >= 0.3")

```

This means that the neuron fires when it crosses 0.3, but then is “refractory” and does no longer emit spikes until it falls under the threshold again. But then, this does not work for custom events, unfortunately… (see [Refractoriness for custom events · Issue #868 · brian-team/brian2 · GitHub](https://github.com/brian-team/brian2/issues/868)).

For custom events, the only workaround is currently to do the same thing but manually:

```python
import brian2 as br
import matplotlib.pyplot as plt

n = br.NeuronGroup(1, """dV/dt = cos(t/msecond)/msecond : 1
                         is_under : boolean""",
                    events={'under': 'V<0.3 and not is_under',
                            'over': 'V>=0.3 and is_under'})
# initial value needs to be correct:
n.is_under = True
n.run_on_event('under', 'is_under = True')
n.run_on_event('over', 'is_under = False')
state_mon = br.StateMonitor(n, 'V', record=True)
under_mon = br.EventMonitor(n, 'under')
over_moon = br.EventMonitor(n, 'over')
br.run(10*br.ms)

plt.plot(state_mon.t/br.ms, state_mon.V[0])
plt.plot(under_mon.t/br.ms, [0.3]*len(under_mon.t), 'v', color='C1')
plt.plot(over_moon.t/br.ms, [0.3]*len(over_moon.t), '^', color='C2')
plt.show()

```

This makes sure that the `under` and `over` events only fire whenever they go over/under 0.3 for the first time:  
 ![Figure_1](https://global.discourse-cdn.com/free1/uploads/brian/original/1X/0a836aae272324098d5ee0af7dabd0349034a923.png)

---

<div class="post-metadata">

**Author:** ![mmiekus](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/mmiekus/32/454_2.png) [@mmiekus](https://brian.discourse.group/u/mmiekus)\
**Post date:** [16 May 2024 09:33 UTC](https://brian.discourse.group/t/how-to-activate-synaptic-pathways-on-custom-events-only/1213/5 "2024-05-16T09:33:21Z")

</div>

Thank you very much!

---

<div class="post-metadata">

**Author:** ![mstimberg](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/mstimberg/32/11_2.png) [@mstimberg](https://brian.discourse.group/u/mstimberg)\
**Post date:** [16 May 2024 09:55 UTC](https://brian.discourse.group/t/how-to-activate-synaptic-pathways-on-custom-events-only/1213/6 "2024-05-16T09:55:41Z")

</div>

> [@mmiekus](#):
>
> However, the whole setup is actually my attempt at implementing a change in synaptic weight, which should happen when both pre- and postsynaptic neurons are above the threshold (without reset). And the change should happen only once, when the second of the neurons crosses the threshold (and not at each timestep).

Hah, if I understand correctly, this should actually be quite straightforward to implement, and doesn’t even need custom events 😊 The trick is to only care about the spike event of the second neuron, but make your weight update conditional on the membrane potential of the first neuron by multiplying it by `int(V_pre >= 0.3)`. This expression will be 0 or 1 depending on whether the pre-synaptic neuron is above the threshold.

Here’s an example:

```python
import brian2 as br
import matplotlib.pyplot as plt
n = br.NeuronGroup(2, model="""dV/dt = cos(2*pi*freq*t)/msecond : 1
                               freq: Hz (constant)""",
                      threshold = "V>=0.3", reset="", refractory="V>=0.3")
n.V = [0, -0.5]
n.freq = [100, 150]*br.Hz
weight_update = 0.1
s = br.Synapses(n, n,
                model="w : 1",
                # update on post-synaptic spike, but only if pre-synaptic is above threshold as well
                on_post="w += int(V_pre>=0.3)*weight_update")
s.connect(i=0, j=1)
state_mon = br.StateMonitor(n, 'V', record=True)
weight_mon = br.StateMonitor(s, 'w', record=True)
spike_mon = br.SpikeMonitor(n)
br.run(0.05*br.second)
plt.plot(state_mon.t/br.ms, state_mon.V[0], color='C0')
plt.plot(state_mon.t/br.ms, state_mon.V[1], color='C1')
post_spikes = spike_mon.spike_trains()[1]
plt.plot(post_spikes/br.ms, [0.3]*len(post_spikes), '^', color='C1')
ax_2 = plt.twinx()
ax_2.plot(weight_mon.t/br.ms, weight_mon.w.T, 'C2')
plt.show()

```

![Figure_1](https://global.discourse-cdn.com/free1/uploads/brian/original/1X/6e093ce1cbf60da6c41c93daf5c69447f3f3d63e.png)  
As you can see, the synaptic weight (green line), is only updated when the post-synaptic neuron (orange line) fires and the pre-synaptic neuron (blue line) is above threshold at the same time.

Hope that gets you going!

---

<div class="post-metadata">

**Author:** ![mmiekus](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/mmiekus/32/454_2.png) [@mmiekus](https://brian.discourse.group/u/mmiekus)\
**Post date:** [16 May 2024 12:43 UTC](https://brian.discourse.group/t/how-to-activate-synaptic-pathways-on-custom-events-only/1213/7 "2024-05-16T12:43:04Z")

</div>

Yes! Thank you! This is more or less what I needed.
