Change NeuronGroup attributes throughout run

I have a network containing neurons, synapses and Poisson external inputs. I am running this for 1s. Then, I want to do two things:
i) add additional Poisson inputs to the network and
ii) modify the refractory period for some neurons.

What would be the most elegant way to achieve this? Is there an example doing something similar that I have missed?

I hope that it’s ok that I am posting pseudocode, because I am not really sure what approach would be best:

# define neurons, synapses, Poisson inputs
neu = NeuronGroup(…)
syn = Synapses(…)
poi1 = PoissonInput(…)
poi2 = PoissonInput(…)

# network with only one Poisson input
net = Network(neu, syn, poi1)*s)

# add second Poisson input
# TODO modify parameters for NeuronGroup*s)

Can I directly modify the NeuronGroup in the net.objects set? Or can I extract the net.objects, modify something, and then recreate the network?

Hi @nspiller. There are some notes about changing parameters in between runs in the tutorial here: Introduction to Brian part 3: Simulations β€” Brian 2 2.5.1 documentation It does not entirely address your questions, though.

Regarding the two things you want to change:

  1. Yes, you can add a new PoissonInput to the Network like this. Brian only allows adding some types of objects between runs, though (e.g. you could not add a new NeuronGroup in the same way). A more general mechanism that will always work is to add the object from the start, but toggle its active flag. In your example:
neu = NeuronGroup(…)
syn = Synapses(…)
poi1 = PoissonInput(…)
poi2 = PoissonInput(…)

# network with all inputs, but poi2 is inactive = False
net = Network(neu, syn, poi1, poi2)*s)

# activate second Poisson input = True*s)

But again just to be clear: your proposed approach works perfectly fine for PoissonInput.
2. Regarding modifying the refractoriness of the neurons: If you define the refractory period via a variable of your model as described in Refractoriness β€” Brian 2 2.5.1 documentation, you can change this parameter for each (or some) of the neurons in between runs:*s)
neu.ref[:10] = 5*ms  # Set refractoriness for first 10 neurons to 5ms*s)

The Network only contains references to the various objects, changing things directly in the NeuronGroup object is therefore enough; you do not have to worry about getting this information back to the Network. In some situations, e.g. when you create your model in a function that returns a Network object, you might not have direct access to the NeuronGroup object via a variable. In that case, you can extract the object from the Network via its name (which is a name like neurongroup by default, but I’d recommend setting it to something more specific):

neu = NeuronGroup(..., name='my_neurons')
net = Network(neu, ...)
net['my_neurons'].ref = ...  #  equivalent to neu.ref = ...

Hope that helps!

Hi @mstimberg ,
Thank you so much for your response, have tried your solutions, and they appear to work nicely for my models.

  1. This approach looks elegant, I will adapt it.
  2. Awesome, I did not know that you could change the individual components, such as NeuronGroup after you have defined the Network model. I have already defined the refractory period as a variable, so I could easily adapt your code.

Again, thank you very much for your help :slight_smile:

All the best

1 Like

Glad it helped :slight_smile: Just a small note: I just edited my response to remove β€œ(note that both PoissonInputs cannot target the same variable in the NeuronGroup, though)” – I got confused myself about this, two PoissonInputs can target the same variable just fine (I had summed variables in mind, which is quite a different thing).