# Synapses cannot be simulated after using \`set\_states\`

**URL:** <https://brian.discourse.group/t/synapses-cannot-be-simulated-after-using-set-states/1475>\
**Category:** Support\
**Tags:** synapses\
**Created:** [23 July 2025 08:29 UTC](https://brian.discourse.group/t/synapses-cannot-be-simulated-after-using-set-states/1475 "2025-07-23T08:29:49Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jasmine9691](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/jasmine9691/32/811_2.png) [@Jasmine9691](https://brian.discourse.group/u/Jasmine9691)\
**Post date:** [23 July 2025 08:29 UTC](https://brian.discourse.group/t/synapses-cannot-be-simulated-after-using-set-states/1475/1 "2025-07-23T08:29:49Z")

</div>

# Description of problem

Hi Brian2 developers and users,

I used `Network.set_states` to restart simulation with the file output by `Network.get_states`. The neurons can be simulated as expected, but the synaptic activity cannot: when the membrane potential of the presynaptic neuron exceeds the threshold, brian2 did not detect this event and the synaptic conductance did not change.

NOTE: `store` and `restore` cannot be used in my case because I’m computing on the server and post-processes results on my PC, which are different platforms. I could ONLY use `set_states` and `get_states` here.

Brian2 version: 2.9.0.  
System: Both CentOS 7 and Windows 10.

# Minimal code to reproduce problem

```python
from brian2.only import *
import brian2.numpy_ as np
import matplotlib.pyplot as plt
import pickle

eqs = '''
dv/dt = (v0 - v) / tau : volt
tau : second
v0 : volt
'''
group = NeuronGroup(2, eqs, threshold='v > 10*mV', reset='v = 0*mV',
                    refractory=5 * ms, method='exact')
group.v = 0 * mV
group.v0 = np.array([20, 0]) * mV
group.tau = np.array([20, 200]) * ms

S = Synapses(group, group, on_pre='v_post += 1 * mV')
S.connect(i=0, j=1)
mon = StateMonitor(group, 'v', record=True)
net = Network(group, S, mon)
# =============================== save states
# net.run(100 * ms)
# with open('state1.pkl', 'wb') as pf:
# pickle.dump(net.get_states(read_only_variables=True), pf)

# =============================== load states
with open('state1.pkl', 'rb') as pf:
    states = pickle.load(pf)
    net.set_states(states)
net.run(50 * ms)
plt.plot(mon.t / ms, mon.v.T / mV)
plt.xlabel('t (ms)')
plt.ylabel('v (mV)')
plt.show()

```

# Expected output (if relevant)

The synaptic event can be detected.

# Actual output (if relevant)

Neuron #1 did not reset its potential when v\>10\*mV

 ![1753259312570](https://global.discourse-cdn.com/free1/uploads/brian/original/1X/dc9a0c18df4efcda204935a256cc62872fbc7ce7.png)

---

<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:** [23 July 2025 14:24 UTC](https://brian.discourse.group/t/synapses-cannot-be-simulated-after-using-set-states/1475/2 "2025-07-23T14:24:30Z")

</div>

Hi @Jasmine9691. I tried to reproduce this issue with your code, but I wasn’t able to right away. I first run the code with the `save_states` part and then again with the `load_states` part and this led to an error since it cannot write read-only variables with `set_state` (the `get_states` stored e.g. `N` of the `NeuronGroup`). After changing `read_only_variables` to `False` it ran, and I can reproduce the problem now.  
The problem is that when you store the states, you are also storing the time of the last spike for the refractoriness mechanism. Since the new simulation starts at 0s, the neuron is considered refractory given that `lastspike + refractory` is in the future. For this specific scenario, you can correct these values with something like:

```python
    # Correct the lastspike... variables to not point into the future
    for objects in states.values():
        for k, v in objects.items():
            if k.startswith("lastspike"):
                v -= 100*ms

```

before using `net.set_states`.

But `get_states` will not store all the internal state of the system, in particular for random numbers and spikes in the queue that have not been delivered yet (particularly relevant if you have synaptic delays). Can you explain in more detail why you cannot use `store` and `restore`? It also uses pickle under the hood, and its file should be transferable in the same way as you do for your pickle file that you create from `get_states`.

---

<div class="post-metadata">

**Author:** ![Jasmine9691](https://yyz2.discourse-cdn.com/free1/user_avatar/brian.discourse.group/jasmine9691/32/811_2.png) [@Jasmine9691](https://brian.discourse.group/u/Jasmine9691)\
**Post date:** [23 July 2025 16:39 UTC](https://brian.discourse.group/t/synapses-cannot-be-simulated-after-using-set-states/1475/3 "2025-07-23T16:39:01Z")

</div>

Hi @mstimberg. Thanks for your kind advice.

> After changing `read_only_variables` to `False` it ran, and I can reproduce the problem now.

Sorry about the typo. This is indeed `False`.

> For this specific scenario, you can correct these values with something like:

The problem has been resolved with your code. For my simulation with more complicated neuron models, I resolved it with `v-=1*ksecond` (v-=100\*ms cannot). However, for neurons that have long refractory periods, this remedy will be inapplicable/inaccurate because a neuron will fire spikes ahead of expected time moments. And I have two questions about it.

1. The neuron is only refractory from `lastspike` to `lastspike + refractory`. In the minimal working example, `lastspike=97.2*ms, refractory=5*ms`. So the neuron is only refractory from `97.2*ms` to `102.2*ms`. When I restarted the simulation, it is reasonable that the neuron didn’t fire spikes from `100*ms` to `102.2*ms`. But why couldn’t it fire after `102.2*ms`, which has already passed the refractory period?

2. Modifying `lastspike` does not influence `SpikeMonitor`, does it?

> Can you explain in more detail why you cannot use `store` and `restore` ?

Hmm, the reasons are rather complex and multi-faceted:

- `set_states` are very flexible for users. For example, I can modify some states like `lastspike`, and I can remove some states if I delete a variable (`restore` will report errors).
- I’m currently coupling brian2 with another library (LAMMPS) to obtain the stimulus to the neurons. LAMMPS is running using MPICH. Brian2 is running in the main process and LAMMPS is running in 24 processes. I did use `store` and `restore` before. However, weeks ago, I found that the file written by `Network.store` cannot be read normally on my PC (Windows 10) during post-processing (in serial). But the problem would be resolved if I ran the simulation in serial so that the stored file is obtained in the serial mode. Then I guess Brian2 is not compatible with MPICH. The error is as follows:

```auto
ERROR Brian 2 encountered an unexpected error. If you think this is a bug in Brian 2, please report this issue either to the discourse forum at <http://brian.discourse.group/>, or to the issue tracker at <https://github.com/brian-team/brian2/issues>. Please include this file with debug information in your report: C:\Users\13372\AppData\Local\Temp\brian_debug_hend29pl.log Additionally, you can also include a copy of the script that was run, available at: C:\Users\13372\AppData\Local\Temp\brian_script_t7rc8j5o.py Thanks! [brian2]
Traceback (most recent call last):
  File "E:\EntericNervousSystem\my_work\postprocess\visualize_network.py", line 24, in <module>
    net.restore(filename=f'{path}/{case_name}/store/net_{read_step}.store')
  File "D:\Anaconda3\envs\enteric_new\lib\site-packages\brian2\core\base.py", line 346, in device_override_decorated_function
    return func(*args, **kwds)
  File "D:\Anaconda3\envs\enteric_new\lib\site-packages\brian2\core\network.py", line 705, in restore
    obj._restore_from_full_state(state[obj.name])
  File "D:\Anaconda3\envs\enteric_new\lib\site-packages\brian2\synapses\synapses.py", line 452, in _restore_from_full_state
    self.queue._restore_from_full_state(queue_state)
  File "brian2\\synapses\\cythonspikequeue.pyx", line 63, in brian2.synapses.cythonspikequeue.SpikeQueue._restore_from_full_state
  File "<stringsource>", line 178, in pair.from_py. __pyx_convert_pair_from_py_int__ and_std_3a __3a_vector_3c_std_3a__ 3a_vector_3c_int32_t_3e ____3e___
ValueError: too many values to unpack (expected 2)

```

I did not report this error in this Brian2 community at that time because I think it might be more flexible if I used `get_states` and `set_states`. Also, I reckoned that brian2 might give low priority to this issue because most users would choose `multiprocessing` for parallel simulation. The reason why LAMMPS chooses MPI is that it is suitable for space decomposition, which is not applicable to computational neuroscience. Anyway, I switched to `set_states` finally.

---

<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:** [28 July 2025 16:21 UTC](https://brian.discourse.group/t/synapses-cannot-be-simulated-after-using-set-states/1475/4 "2025-07-28T16:21:17Z")

</div>

> [@Jasmine9691](#):
>
> The problem has been resolved with your code. For my simulation with more complicated neuron models, I resolved it with `v-=1*ksecond` (v-=100\*ms cannot). However, for neurons that have long refractory periods, this remedy will be inapplicable/inaccurate because a neuron will fire spikes ahead of expected time moments.

The time you subtract should correspond to the time at the end of the previous run (100ms in your example code). E.g. if a neuron with a 5ms refractory period spikes at 99ms and you save its state after 100ms, you want the `lastspike` variable to be at -1ms for the second simulation, so that it stays refractory until 4ms.

> [@Jasmine9691](#):
>
> The neuron is only refractory from `lastspike` to `lastspike + refractory`. In the minimal working example, `lastspike=97.2*ms, refractory=5*ms`. So the neuron is only refractory from `97.2*ms` to `102.2*ms`. When I restarted the simulation, it is reasonable that the neuron didn’t fire spikes from `100*ms` to `102.2*ms`. But why couldn’t it fire after `102.2*ms`, which has already passed the refractory period?

The time in the second simulation starts at 0ms, and it will not spike until `lastspike + refractory`, i.e. for the first 102.2ms of the simulation. In your minimal example from above, you only run the second simulation for 50ms, so it never gets to the point where it spikes again. If you run it for e.g. 150ms, you see this effect quite clearly:

 ![Figure_1](https://global.discourse-cdn.com/free1/uploads/brian/original/1X/3db0cc9b373874ca884f629c58a1eaf0ebf8f38e.png)

> [@Jasmine9691](#):
>
> Modifying `lastspike` does not influence `SpikeMonitor`, does it?

The `lastspike` variable is only used for the refractoriness mechanism, so it does not affect `SpikeMonitor` directly (of course, it affects it indirectly by preventing the neuron from spiking…).

> [@Jasmine9691](#):
>
> `set_states` are very flexible for users. For example, I can modify some states like `lastspike`, and I can remove some states if I delete a variable (`restore` will report errors).

Yes, but note that you can also access and modify variables before/after you `restore`, giving you the same flexibility in that regard. It is true that `store`/`restore` assumes an unchanged network, but you can always use it on a full network and then set objects you do not want to simulate as inactive (by setting their `active` attribute to `False`) instead of removing them from the network.

Regarding the `restore` error: from the message, I think the issue is not with MPI, but I rather suspect that the machine that called `Network.store`did not use the optimized Cython version of the spike queue and fell back to the Python implementation (there should have been a warning about this). This has less good performance, but also uses a slightly different format when storing the internal state to disk (it probably shouldn’t!), leading to the error you saw. These days, with Python wheels and conda packages, it is rather unusual to not have the Cython spike queue available. Is it possible that you were running Brian 2 directly from the source directory without installation, or that you did an installation from source without Cython and/or a C++ compiler available?
