Using Brian in functions -- unresolved identifiers

Description of problem

When defining variables that are used in the neuron group differential equations or in the synaptic parameters (so basically any of the equations that are assigned in quotations), it is straightforward to assign them to a variable name and, for example, sweep over different values of that variable.

However, if the neuron group or synaptic connections are defined within a function and that function is called from another file, I have been unable to pass parameter values into that function for assignment in these equations. In fact, I cannot even be assign values within the function and then use them in these string-equations.

I am guessing the issue has to do with how Brian uses namespaces, but nonetheless I have not come across any working solutions.

Note, that I have basically made a function that generates different population/synapse configurations so that I can sweep over different combinations and would therefore like to be able to pass in different parameters into this function and then into NeuronGroup and Synapses Brian functions.

KeyError: β€˜The identifier β€œU” could not be resolved.’

Hi @bryan . Could you come up with a minimal example showing the issue (can be completely made up) – I am a bit confused about what exactly you are trying to do.
Thanks, Marcel

Hi @mstimberg, the issue occurs (minimally I think) as follows:

file_1.py
def generate_population(X):
    eqs = '''
             dv/dt = (-v)/(30*ms) : 1
              '''
    G = NeuronGroup(N, eqs, threshold='v>1', reset='v = 0', method='exact')
    S = Synapses(G, G, model='w : 1', on_pre='v_post += X*w')
    return G,S

file2.py
from file1 import generate_population
start_scope()
G, S = generate_population(X)
net = Network(G,S)
net.run(100*ms)

KeyError: β€˜The identifier β€œX” could not be resolved.’

Thank you for the help!

Thanks, that makes things indeed clearer. The problem in this code is that Brian is resolving external variables at the point where net.run is called – β€œX” needs to be visible there (in your example code it kind of is actually, but it refers to an unknown variable X which I guess in your real code is replaced by a concrete value for example).
There are at least two ways to deal with this:

  1. You can have a group-specific namespace in the synapses that you create in generate_population, i.e. they carry their own interpretation of external variables:
 S = Synapses(G, G, model='w : 1', on_pre='v_post += X*w', namespace={'X': X})

Note that if you do it, you will have to specific all external constants that S refers to in the namespace argument.

  1. You can make the X variable part of the synaptic equations and assign to it, e.g.:
S = Synapses(G, G, model='''w : 1
                            X : 1 (constant, shared)''',
             on_pre='v_post += X*w')
# S.connect(...) needs to be called here
S.X = X

Hope that helps, best
Marcel

This indeed solves the problem. Thank you for you timely responses. I have been very much enjoying using the Brian Simulator.

Cheers

1 Like