Error encountered with object named ‘readout_layer_subexpression_update’ when running network (with functions in different scripts)

Description of problem

I am running a custom brian2 network inside a genetic algorithm. It works when everything is in the same python script, but after refactoring to be across multiple modular scripts that import functions from others as needed, I get the following error, which I cannot find referenced anywhere on the internet:

Error encountered with object named ‘readout_layer_subexpression_update’.

Note that removing the readout layer from the model causes the same error with the reservoir layer, which is declared before the readout layer. I would really appreciate help as I have tried to fix this for many hours and am on a deadline. I reluctantly posted here as a last resort.

Minimal code to reproduce problem

I am not sure this is possible to provide since my simulation consists of 10 separate python scripts with advanced algorithms, functionality, and data structures (not clear how to condense to a minimal reproducible example). If necessary, I am willing to share some more code. However, the following function is likely the culprit, called in the function following it:

def create_neuron_group(layer_size, model, model_type, parameters, name="neurongroup*"):
    """Create a neuron group with excitatory/inhibitory subgroups"""
    if "reservoir" in name:
        neurone_model=model["reservoir_neurone_model"]
    elif "readout" in name:
        neurone_model=model["readout_neurone_model"]
    else:
        neurone_model=model["neurone_model"]
        

    if model_type == "LIF":
        G = NeuronGroup(
            N=layer_size,
            model=neurone_model,
            method="euler",
            threshold=f"V>{parameters['theta']/mV}*mV",
            reset=model["reset_script"],
            refractory=parameters["refractory"],
            name=name
        )
        G.R = parameters["resistance"]
        G.tau_v = parameters["tau_v"]
        G.baseline_rate = parameters["baseline_rate"]
        
        # Split into subgroups
        n_inhibitory = round(parameters["proportion_inhibitory"] * layer_size)
        G_i = G[:n_inhibitory]
        G_e = G[n_inhibitory:]
    
        if "reservoir" in name:
            G.Vy_readout_ee_synapses = 0*volt
            G.Vy_readout_ei_synapses = 0*volt
            G.Vy_readout_ie_synapses = 0*volt
            G.Vy_readout_ii_synapses = 0*volt
            G.Vy_readout_synapses_efferent = 0*volt
            G.Vy_train_synapses_positive = 0*volt
            G.Vy_train_synapses_negative = 0*volt
        elif "readout" in name:
            G.Vy_reservoir_ee_synapses = 0*volt
            G.Vy_reservoir_ei_synapses = 0*volt
            G.Vy_reservoir_ie_synapses = 0*volt
            G.Vy_reservoir_ii_synapses = 0*volt
            G.Vy_input_synapses_positive = 0*volt
            G.Vy_input_synapses_negative = 0*volt

    print(("network_builder line 94 reached", G), flush=True)
    return G, G_e, G_i
def build_and_run_network(genome, model_config):
    """Build and run the complete network - main simulation function"""
    from models import get_model_equations
    from data_loader import prepare_all_data
    import warnings
    
    start_scope()
    #clear_cache('cython')
    prefs.codegen.target = "numpy"
    set_device('runtime')
    #prefs.codegen.target = "cython"  # Enable C++ compilation for speed
    #warnings.filterwarnings('ignore')


    # Get model equations and prepare data
    model = get_model_equations(genome['model_type'])
    data = prepare_all_data(model_config=model_config)
    parameters = decode_genome_to_parameters(genome, model_config)
    
    # Make data available in Brian2 namespace - not called directly
    input_data_positive = data['input_data']['positive']
    input_data_negative = data['input_data']['negative']
    train_data_positive = data['train_data']['positive']
    train_data_negative = data['train_data']['negative']
    #globals()['input_data_positive'] = data['input_data']['positive']
    #globals()['input_data_negative'] = data['input_data']['negative']
    #globals()['train_data_positive'] = data['train_data']['positive']
    #globals()['train_data_negative'] = data['train_data']['negative']

    namespace = {
        # Data arrays
        'input_data_positive': input_data_positive,
        'input_data_negative': input_data_negative,
        'train_data_positive': train_data_positive,
        'train_data_negative': train_data_negative,
        
        # Common units and constants
        'mV': mV,
        'ms': ms,
        'Hz': Hz,
        'pA': pA,
        'volt': volt,
        'amp': amp,
        'second': second,
        'ohm': ohm,
        'Mohm': Mohm,
        
        # Parameters that might be referenced in equations
        'frequency_factor': parameters['frequency_factor'],
        #'baseline_rate': parameters.get('baseline_rate', 0.01),
        
        # Mathematical functions that might be used in equations
        'rand': np.random.rand,
        'randn': np.random.randn,
        'exp': np.exp,
        'log': np.log,
        'sqrt': np.sqrt,
        'sin': np.sin,
        'cos': np.cos,
        'clip': np.clip,
        'poisson': np.random.poisson,
        
        # Additional parameters for equations
        'tau_v': parameters.get('tau_v', 5*ms),
        'theta': parameters.get('theta', 3*mV),
        'refractory': parameters.get('refractory', 0.15*ms),
        'resistance': parameters.get('resistance', 1*Mohm),
        
        # For Izhikevich model
        'a': parameters.get('a', 0.02),
        'b': parameters.get('b', 0.2),
        'c': parameters.get('c', -65),
        'd': parameters.get('d', 8),
        
        # STDP parameters
        'w_max': parameters.get('w_max', 1.0),
        'pre_trace_tau': parameters.get('pre_trace_tau', 20*ms),
        'post_trace_tau': parameters.get('post_trace_tau', 20*ms),
        'pre_trace_step': parameters.get('pre_trace_step', 0.1),
        'STDP_asymmetry': parameters.get('STDP_asymmetry', 1.0),
        
        # Synaptic parameters
        'tau_nt': parameters.get('tau_nt', 3*ms),
        'tau_ntx': parameters.get('tau_ntx', [100*ms, 100*ms, 100*ms, 100*ms]),
        'u': parameters.get('u', 0.1),
        
        # Weight signs
        'ee_w_sign': parameters.get('ee_w_sign', 1.0),
        'ei_w_sign': parameters.get('ei_w_sign', 5.0),
        'ie_w_sign': parameters.get('ie_w_sign', -5.0),
        'ii_w_sign': parameters.get('ii_w_sign', -3.0),
        
        # Connectivity parameters
        'input_connectivity': parameters.get('input_connectivity', 0.3),
        'reservoir_connectivity': parameters.get('reservoir_connectivity', 0.1),
        'readout_connectivity': parameters.get('readout_connectivity', 0.1),
    }
    
    # Reservoir Layer
    reservoir_layer, reservoir_layer_excitatory, reservoir_layer_inhibitory = create_neuron_group(parameters['reservoir_size'], model, genome['model_type'], parameters, name="reservoir_layer")
    reservoir_ee_synapses = create_synapses(reservoir_layer_excitatory, reservoir_layer_excitatory, model, parameters, parameters['reservoir_connectivity'], "i!=j", parameters['ee_w_sign'], 'reservoir_ee_synapses')
    reservoir_ei_synapses = create_synapses(reservoir_layer_excitatory, reservoir_layer_inhibitory, model, parameters, parameters['reservoir_connectivity'], "True", parameters['ei_w_sign'], 'reservoir_ei_synapses')
    reservoir_ie_synapses = create_synapses(reservoir_layer_inhibitory, reservoir_layer_excitatory, model, parameters, parameters['reservoir_connectivity'], "True", parameters['ie_w_sign'], 'reservoir_ie_synapses')
    reservoir_ii_synapses = create_synapses(reservoir_layer_inhibitory, reservoir_layer_inhibitory, model, parameters, parameters['reservoir_connectivity'], "i!=j", parameters['ii_w_sign'], 'reservoir_ii_synapses')
    
    # Input Layer
    input_layer_positive = PoissonGroup(N=parameters['input_layer_size'], rates="input_data_positive(t)")
    input_layer_negative = PoissonGroup(N=parameters['input_layer_size'], rates="input_data_negative(t)")
    input_synapses_positive = create_synapses(input_layer_positive, reservoir_layer_excitatory, model, parameters, parameters['input_connectivity'], "True", parameters['ee_w_sign'], 'input_synapses_positive')
    input_synapses_negative = create_synapses(input_layer_negative, reservoir_layer_excitatory, model, parameters, parameters['input_connectivity'], "True", parameters['ee_w_sign'], 'input_synapses_negative')

    # Readout Layer # TODO subexpression_update error occurs here
    readout_layer, readout_layer_excitatory, readout_layer_inhibitory = create_neuron_group(2*parameters['readout_layer_size'], model, genome['model_type'], parameters, name="readout_layer")
    readout_excitatory_size = len(readout_layer_excitatory)
    readout_excitatory_positive = readout_layer_excitatory[:round((1-parameters["proportion_inhibitory"])*parameters["readout_layer_size"])]
    readout_excitatory_negative = readout_layer_excitatory[round((1-parameters["proportion_inhibitory"])*parameters["readout_layer_size"]):]
    readout_ee_synapses = create_synapses(readout_layer_excitatory, readout_layer_excitatory, model, parameters, parameters["reservoir_connectivity"], "i!=j", parameters["ee_w_sign"], name="readout_ee_synapses")
    readout_ei_synapses = create_synapses(readout_layer_excitatory, readout_layer_inhibitory, model, parameters, parameters["reservoir_connectivity"], "True", parameters["ei_w_sign"], name="readout_ei_synapses")
    readout_ie_synapses = create_synapses(readout_layer_inhibitory, readout_layer_excitatory, model, parameters, parameters["reservoir_connectivity"], "True", parameters["ie_w_sign"], name="readout_ie_synapses")
    readout_ii_synapses = create_synapses(readout_layer_inhibitory, readout_layer_inhibitory, model, parameters, parameters["reservoir_connectivity"], "i!=j", parameters["ii_w_sign"], name="readout_ii_synapses")
    readout_synapses_efferent = create_synapses(reservoir_layer, readout_layer, model, parameters, parameters["input_connectivity"], "True", parameters["ee_w_sign"], name="readout_synapses_efferent")

    # Training layer
    train_layer_positive = PoissonGroup(N=parameters["readout_layer_size"], rates="train_data_positive(t)")
    train_layer_negative = PoissonGroup(N=parameters["readout_layer_size"], rates="train_data_negative(t)")
    train_synapses_positive = create_synapses(train_layer_positive, readout_excitatory_positive, model, parameters, parameters["input_connectivity"], "True", parameters["ee_w_sign"], name="train_synapses_positive")
    train_synapses_negative = create_synapses(train_layer_negative, readout_excitatory_negative, model, parameters, parameters["input_connectivity"], "True", parameters["ee_w_sign"], name="train_synapses_negative")
    
    # Split readout excitatory into positive/negative

    # Create monitors
    spike_monitor_readout = SpikeMonitor(readout_layer,  name="spike_monitor_readout")
    
    # Run simulation
    train_runtime = data['train_data']['train_size'] * parameters['dt']
    test_runtime = parameters['runtime'] - train_runtime
    
    network = Network([
        # Reservoir
        reservoir_layer,
        reservoir_ee_synapses,
        reservoir_ei_synapses,
        reservoir_ie_synapses,
        reservoir_ii_synapses,
        # Input
        input_layer_positive,
        input_layer_negative,
        input_synapses_positive,
        input_synapses_negative,
        
        # Readout
        readout_layer,
        readout_excitatory_positive,
        readout_excitatory_negative,
        readout_ee_synapses,
        readout_ei_synapses,
        readout_ie_synapses,
        readout_ii_synapses,
        readout_synapses_efferent,

        spike_monitor_readout,

        # Training
        train_layer_positive,
        train_layer_negative,
        train_synapses_positive,
        train_synapses_negative,
    ])

    # Training phase
    print(("network_builder line 360 reached:"), flush=True)
    try:
        network.run(train_runtime)#, namespace=namespace)
    except Exception as e:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        print("ERRORFLAG:", e.with_traceback(exc_traceback), flush=True)
    print(("network_builder line 362 reached"), flush=True)
    
    # Freeze plasticity for testing
    #for synapse in synapses.values():
    #    synapse.plastic = False
    network["reservoir_ee_synapses"].plastic = False
    network["reservoir_ei_synapses"].plastic = False
    network["reservoir_ie_synapses"].plastic = False
    network["reservoir_ii_synapses"].plastic = False
    network["readout_ee_synapses"].plastic = False
    network["readout_ei_synapses"].plastic = False
    network["readout_ie_synapses"].plastic = False
    network["readout_ii_synapses"].plastic = False
    network["readout_synapses_efferent"].plastic = False
    network["train_synapses_positive"].plastic = False
    network["train_synapses_negative"].plastic = False
    
    # Testing phase  
    network.run(test_runtime)#, namespace=namespace)
    
    # Return results
    return {
        #'readout_positive_spikes': network["spike_monitor_readout_positive"],
        #'readout_negative_spikes': network["spike_monitor_readout_negative"],
        'spike_monitor_readout': network["spike_monitor_readout"],
        'series_length': parameters['runtime'] / parameters['dt'],
        'readout_size': readout_excitatory_size // 2,
        'proportion_inhibitory': parameters['proportion_inhibitory']
    }

The network models are as follows (note the Vy_{}_post):

def get_LIF_model():
    """Get Leaky Integrate-and-Fire model equations"""
    return {
        # Neurone Models
        "reservoir_neurone_model" : '''
                                    dV/dt = (R*I-V
                                     + Vy_reservoir_ee_synapses
                                     + Vy_reservoir_ei_synapses
                                     + Vy_reservoir_ie_synapses
                                     + Vy_reservoir_ii_synapses
                                     + Vy_input_synapses_positive
                                     + Vy_input_synapses_negative)/tau_v : volt (unless refractory)
                                    I = poisson(baseline_rate*(frequency_factor/Hz))*pA: amp (constant over dt)
                                    Vy_reservoir_ee_synapses : volt
                                    Vy_reservoir_ei_synapses : volt
                                    Vy_reservoir_ie_synapses : volt
                                    Vy_reservoir_ii_synapses : volt
                                    Vy_input_synapses_positive : volt
                                    Vy_input_synapses_negative : volt
                                    R : ohm
                                    tau_v : second
                                    baseline_rate : 1 (constant)
                                    ''',
        "readout_neurone_model" : '''
                                  dV/dt = (R*I-V
                                   + Vy_readout_ee_synapses
                                   + Vy_readout_ei_synapses
                                   + Vy_readout_ie_synapses
                                   + Vy_readout_ii_synapses
                                   + Vy_readout_synapses_efferent
                                   + Vy_train_synapses_positive
                                   + Vy_train_synapses_negative)/tau_v : volt (unless refractory)
                                  I = poisson(baseline_rate*(frequency_factor/Hz))*pA: amp (constant over dt)
                                  Vy_readout_ee_synapses : volt
                                  Vy_readout_ei_synapses : volt
                                  Vy_readout_ie_synapses : volt
                                  Vy_readout_ii_synapses : volt
                                  Vy_readout_synapses_efferent : volt
                                  Vy_train_synapses_positive : volt
                                  Vy_train_synapses_negative : volt
                                  R : ohm
                                  tau_v : second
                                  baseline_rate : 1 (constant)
                                  ''',
        "neurone_model" : '''
                      dV/dt = (R*I-V
                       + Vy_reservoir_ee_synapses
                       + Vy_reservoir_ei_synapses
                       + Vy_reservoir_ie_synapses
                       + Vy_reservoir_ii_synapses
                       + Vy_input_synapses_positive
                       + Vy_input_synapses_negative
                       + Vy_readout_ee_synapses
                       + Vy_readout_ei_synapses
                       + Vy_readout_ie_synapses
                       + Vy_readout_ii_synapses
                       + Vy_readout_synapses_efferent
                       + Vy_train_synapses_positive
                       + Vy_train_synapses_negative)/tau_v : volt (unless refractory)
                      I = poisson(baseline_rate*(frequency_factor/Hz))*pA: amp (constant over dt)
                      Vy_reservoir_ee_synapses : volt
                      Vy_reservoir_ei_synapses : volt
                      Vy_reservoir_ie_synapses : volt
                      Vy_reservoir_ii_synapses : volt
                      Vy_input_synapses_positive : volt
                      Vy_input_synapses_negative : volt
                      Vy_readout_ee_synapses : volt
                      Vy_readout_ei_synapses : volt
                      Vy_readout_ie_synapses : volt
                      Vy_readout_ii_synapses : volt
                      Vy_readout_synapses_efferent : volt
                      Vy_train_synapses_positive : volt
                      Vy_train_synapses_negative : volt
                      R : ohm
                      tau_v : second
                      baseline_rate : 1 (constant)
                      ''',
        "reset_script" : '''
                         V = 0*mV
                         ''',
        "synapse_model" : '''
                          dpre_trace/dt = -pre_trace/pre_trace_tau : 1 (event-driven)
                          dpost_trace/dt = -post_trace/post_trace_tau : 1 (event-driven)
                          w : 1
                          w_max : 1
                          pre_trace_tau : second
                          post_trace_tau : second
                          pre_trace_step : 1
                          STDP_asymmetry : 1 (constant)
                          post_trace_step = -pre_trace_step*pre_trace_tau/post_trace_tau*STDP_asymmetry : 1
                          dy/dt = -y/tau_nt*plastic : 1 (clock-driven)
                          dx/dt = z/tau_ntx*plastic : 1 (clock-driven)
                          dz/dt = y/tau_nt*plastic - z/tau_ntx : 1 (clock-driven)
                          Vy_{}_post = y*w_sign : volt (summed)
                          u : 1
                          tau_nt : second
                          tau_ntx : second
                          w_sign : volt (constant)
                          plastic : 1
                          ''',
        # Synaptic Models
        "presynaptic_script" : '''
                               V_post += w*w_sign
                               y += u*x*plastic
                               x -= u*x*plastic
                               pre_trace += pre_trace_step
                               dw = (w_max-w)*post_trace*plastic
                               w = clip(w+dw, 0, w_max)
                               ''',
        "postsynaptic_script" : '''
                                post_trace += post_trace_step
                                dw = (w_max-w)*pre_trace*plastic
                                w = clip(w+dw, 0, w_max)
                                ''',
        "rebalance_script" : '''
                      V_post -= 0*mv
                      '''
}

What you have already tried

  • explicitly setting the namespace
  • sending the namespace to every declared NeuronGroup and/or Synapse objects
  • sending the namespace to network.run()
  • using magic function configuration (just run() instead of network.run())
  • writing input data vector TimedArrays to global()
  • debugging by printing out model f-string formatting (.format(name))
  • removing the readout layer and various synapses
  • transplanting functions that worked in the singular python script
  • segregating model equations by readout and reservoir
  • initialising unused Vy_{}_post parameters to 0*mv
  • using clear_cache(“cython”) and/or removing start_scope()
  • finding similar issues (a Google search with “subexpression_update” leads only to a single Brian documentation page about the source code that is unhelpful)
  • consulting an LLM at maximum settings
  • some other stuff I can’t recall at present

Expected output (if relevant)

  • The network runs without an error

Actual output (if relevant)

  • Error encountered with object named ‘readout_layer_subexpression_update’.

Full traceback of error (if relevant)

I suspect the “full” traceback is being cut off, and I tried to find the “debug log” that is mentioned in the error output, and also to find where brian2 would store such a log, but I could not. If there is a location where I can find it, I will be happy to retrieve and post it.

Error in simulation: Error encountered with object named ‘readout_layer_subexpression_update’.
Object was created here (most recent call only, full details in debug log):
File ‘[filepath]\network_builder.py’, line 72, in create_neuron_group
G = NeuronGroup(

An error occurred when preparing an object. (See above for original error message and traceback.)

Hi @MisterOrbit The full error message would indeed be helpful, it should be in the lines above what you posted., which also contain the path to the debug log,.. These files have names like brian_debug_65j71xx0.log end are in the temporary directory by default – on Unix systems this would be /tmp, but I am not sure what the equivalent is on Windows. The only thing I can see from the object name in the error is that it is about the NeuronGroup named readout_layer and that it concerns an expression in the equations marked with (constant over dt) – maybe this helps a bit with debugging.

Hi @mstimberg ,

Thanks for the quick reply.

I found the “Temp” folder within which brian2 generates its logs. Logs were not being generated until I imported brian2 in each independent script file. This behaviour is unrelated to the error itself but may be an issue for others with similar cases of multiple modular script files. ( The log generating mechanism may fail when errors are passed outside of where brian2 was imported.)

Additionally, the original error output did not provide any extra details above (neither the extended traceback nor any details about the log). I was using a try/except to print the exception when it occurs (which is why there is the added prefix “Error in simulation: ”). This was only revealing the final error caused by the original error in the traceback.

After importing brian2 in each script, I was able to get the log to generate, and find the error. It was caused by a simpler KeyError and AttributeError, which I have now fixed. The second debug log is pasted at the end.

I now have another error that is also not generating a log nor any additional details, even after brian2 has been imported in each script file:

Error in simulation: Error encountered with object named ‘poissongroup’.
Object was created here (most recent call only, full details in debug log):
File ‘c:\Users\jhyan_8hz0dhz\OneDrive\Documents\School_University\Research\Modular Scripts\network_builder.py’, line 297, in build_and_run_network
input_layer_positive = PoissonGroup(N=parameters[‘input_layer_size’], rates=“input_data_positive(t)”)

An error occurred when preparing an object. (See above for original error message and traceback.)

Since this is now a different error, I am not sure whether to close this one and create a new forum post or not. If that is required, I will do so.

Debug Log 2 (with AttributeError):

2025-09-19 17:25:31,453 DEBUG      brian2: Logging to file: C:\Users\JHYAN_~1\AppData\Local\Temp\brian_debug_gzzmb4bk.log, copy of main script saved as: C:\Users\JHYAN_~1\AppData\Local\Temp\brian_script_uaulv6bl.py
2025-09-19 17:25:31,453 DEBUG      brian2: Python interpreter: C:\Python310\python.exe
2025-09-19 17:25:31,454 DEBUG      brian2: Platform: win32
2025-09-19 17:25:31,454 DEBUG      brian2: brian version is: 2.8.0.4
2025-09-19 17:25:31,454 DEBUG      brian2: numpy version is: 2.2.3
2025-09-19 17:25:31,454 DEBUG      brian2: scipy version is: 1.15.3
2025-09-19 17:25:31,454 DEBUG      brian2: sympy version is: 1.13.3
2025-09-19 17:25:31,457 DEBUG      brian2: python version is: 3.10.5 (tags/v3.10.5:f377153, Jun  6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)]
2025-09-19 17:25:31,458 DEBUG      brian2: Cache size for target 'cython': 135 MB
2025-09-19 17:25:32,580 DEBUG      brian2.synapses.synapses: Creating synapses from group 'reservoir_layer_subgroup_1' to group 'reservoir_layer_subgroup_1', using generator '_k for _k in sample(N_post, p=0.284452045882073) if i!=_k'
2025-09-19 17:25:32,658 DEBUG      brian2.synapses.synapses: Creating synapses from group 'reservoir_layer_subgroup_1' to group 'reservoir_layer_subgroup', using generator '_k for _k in sample(N_post, p=0.284452045882073) if True'
2025-09-19 17:25:32,730 DEBUG      brian2.synapses.synapses: Creating synapses from group 'reservoir_layer_subgroup' to group 'reservoir_layer_subgroup_1', using generator '_k for _k in sample(N_post, p=0.284452045882073) if True'
2025-09-19 17:25:32,793 DEBUG      brian2.synapses.synapses: Creating synapses from group 'reservoir_layer_subgroup' to group 'reservoir_layer_subgroup', using generator '_k for _k in sample(N_post, p=0.284452045882073) if i!=_k'
2025-09-19 17:25:32,859 DEBUG      brian2.synapses.synapses: Creating synapses from group 'poissongroup' to group 'reservoir_layer_subgroup_1', using generator '_k for _k in sample(N_post, p=0.5866923016247526) if True'
2025-09-19 17:25:32,912 DEBUG      brian2.synapses.synapses: Creating synapses from group 'poissongroup_1' to group 'reservoir_layer_subgroup_1', using generator '_k for _k in sample(N_post, p=0.5866923016247526) if True'
2025-09-19 17:25:32,979 DEBUG      brian2.synapses.synapses: Creating synapses from group 'readout_layer_subgroup_1' to group 'readout_layer_subgroup_1', using generator '_k for _k in sample(N_post, p=0.284452045882073) if i!=_k'
2025-09-19 17:25:33,046 DEBUG      brian2.synapses.synapses: Creating synapses from group 'readout_layer_subgroup_1' to group 'readout_layer_subgroup', using generator '_k for _k in sample(N_post, p=0.284452045882073) if True'
2025-09-19 17:25:33,109 DEBUG      brian2.synapses.synapses: Creating synapses from group 'readout_layer_subgroup' to group 'readout_layer_subgroup_1', using generator '_k for _k in sample(N_post, p=0.284452045882073) if True'
2025-09-19 17:25:33,169 DEBUG      brian2.synapses.synapses: Creating synapses from group 'readout_layer_subgroup' to group 'readout_layer_subgroup', using generator '_k for _k in sample(N_post, p=0.284452045882073) if i!=_k'
2025-09-19 17:25:33,226 DEBUG      brian2.synapses.synapses: Creating synapses from group 'reservoir_layer' to group 'readout_layer', using generator '_k for _k in sample(N_post, p=0.5866923016247526) if True'
2025-09-19 17:25:33,294 DEBUG      brian2.synapses.synapses: Creating synapses from group 'poissongroup_2' to group 'readout_layer_subgroup_2', using generator '_k for _k in sample(N_post, p=0.5866923016247526) if True'
2025-09-19 17:25:33,344 DEBUG      brian2.synapses.synapses: Creating synapses from group 'poissongroup_3' to group 'readout_layer_subgroup_3', using generator '_k for _k in sample(N_post, p=0.5866923016247526) if True'
2025-09-19 17:25:33,442 DEBUG      brian2.core.network.before_run: Preparing network 'network' with 99 objects: readout_layer_subexpression_update, reservoir_layer_subexpression_update, input_synapses_negative, input_synapses_positive, readout_ee_synapses, readout_ei_synapses, readout_ie_synapses, readout_ii_synapses, readout_layer, readout_synapses_efferent, reservoir_ee_synapses, reservoir_ei_synapses, reservoir_ie_synapses, reservoir_ii_synapses, reservoir_layer, train_synapses_negative, train_synapses_positive, readout_synapses_efferent_summed_variable_Vy_readout_synapses_efferent_post, input_synapses_negative_stateupdater, input_synapses_negative_summed_variable_Vy_input_synapses_negative_post, input_synapses_positive_stateupdater, input_synapses_positive_summed_variable_Vy_input_synapses_positive_post, readout_ee_synapses_stateupdater, readout_ee_synapses_summed_variable_Vy_readout_ee_synapses_post, readout_ei_synapses_stateupdater, readout_ei_synapses_summed_variable_Vy_readout_ei_synapses_post, readout_ie_synapses_stateupdater, readout_ie_synapses_summed_variable_Vy_readout_ie_synapses_post, readout_ii_synapses_stateupdater, readout_ii_synapses_summed_variable_Vy_readout_ii_synapses_post, readout_layer_stateupdater, readout_synapses_efferent_stateupdater, reservoir_ee_synapses_stateupdater, reservoir_ee_synapses_summed_variable_Vy_reservoir_ee_synapses_post, reservoir_ei_synapses_stateupdater, reservoir_ei_synapses_summed_variable_Vy_reservoir_ei_synapses_post, reservoir_ie_synapses_stateupdater, reservoir_ie_synapses_summed_variable_Vy_reservoir_ie_synapses_post, reservoir_ii_synapses_stateupdater, reservoir_ii_synapses_summed_variable_Vy_reservoir_ii_synapses_post, reservoir_layer_stateupdater, train_synapses_negative_stateupdater, train_synapses_negative_summed_variable_Vy_train_synapses_negative_post, train_synapses_positive_stateupdater, train_synapses_positive_summed_variable_Vy_train_synapses_positive_post, poissongroup, poissongroup_1, poissongroup_1_spike_thresholder, poissongroup_2, poissongroup_2_spike_thresholder, poissongroup_3, poissongroup_3_spike_thresholder, poissongroup_spike_thresholder, readout_layer_spike_thresholder, reservoir_layer_spike_thresholder, readout_layer_subgroup_2, readout_layer_subgroup_3, spike_monitor_readout, input_synapses_negative_down, input_synapses_negative_up, input_synapses_positive_down, input_synapses_positive_up, readout_ee_synapses_down, readout_ee_synapses_up, readout_ei_synapses_down, readout_ei_synapses_up, readout_ie_synapses_down, readout_ie_synapses_up, readout_ii_synapses_down, readout_ii_synapses_up, readout_synapses_efferent_down, readout_synapses_efferent_up, reservoir_ee_synapses_down, reservoir_ee_synapses_up, reservoir_ei_synapses_down, reservoir_ei_synapses_up, reservoir_ie_synapses_down, reservoir_ie_synapses_up, reservoir_ii_synapses_down, reservoir_ii_synapses_up, train_synapses_negative_down, train_synapses_negative_up, train_synapses_positive_down, train_synapses_positive_up, input_synapses_negative_post, input_synapses_positive_post, readout_ee_synapses_post, readout_ei_synapses_post, readout_ie_synapses_post, readout_ii_synapses_post, readout_synapses_efferent_post, reservoir_ee_synapses_post, reservoir_ei_synapses_post, reservoir_ie_synapses_post, reservoir_ii_synapses_post, train_synapses_negative_post, train_synapses_positive_post, readout_layer_spike_resetter, reservoir_layer_spike_resetter
2025-09-19 17:25:33,495 DEBUG      brian2.stateupdaters.base.method_choice: Group input_synapses_negative: using numerical integration method euler (took 0.01s)
2025-09-19 17:25:33,508 DEBUG      brian2.stateupdaters.base.method_choice: Group input_synapses_positive: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,524 DEBUG      brian2.stateupdaters.base.method_choice: Group readout_ee_synapses: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,540 DEBUG      brian2.stateupdaters.base.method_choice: Group readout_ei_synapses: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,556 DEBUG      brian2.stateupdaters.base.method_choice: Group readout_ie_synapses: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,571 DEBUG      brian2.stateupdaters.base.method_choice: Group readout_ii_synapses: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,603 DEBUG      brian2.stateupdaters.base.method_choice: Group readout_layer: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,628 DEBUG      brian2.stateupdaters.base.method_choice: Group readout_synapses_efferent: using numerical integration method euler (took 0.01s)
2025-09-19 17:25:33,641 DEBUG      brian2.stateupdaters.base.method_choice: Group reservoir_ee_synapses: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,658 DEBUG      brian2.stateupdaters.base.method_choice: Group reservoir_ei_synapses: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,674 DEBUG      brian2.stateupdaters.base.method_choice: Group reservoir_ie_synapses: using numerical integration method euler (took 0.02s)
2025-09-19 17:25:33,689 DEBUG      brian2.stateupdaters.base.method_choice: Group reservoir_ii_synapses: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,705 DEBUG      brian2.stateupdaters.base.method_choice: Group reservoir_layer: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,721 DEBUG      brian2.stateupdaters.base.method_choice: Group train_synapses_negative: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,737 DEBUG      brian2.stateupdaters.base.method_choice: Group train_synapses_positive: using numerical integration method euler (took 0.00s)
2025-09-19 17:25:33,829 DEBUG      brian2.core.network.before_run: Preparing network 'network' with 99 objects: readout_layer_subexpression_update, reservoir_layer_subexpression_update, input_synapses_negative, input_synapses_positive, readout_ee_synapses, readout_ei_synapses, readout_ie_synapses, readout_ii_synapses, readout_layer, readout_synapses_efferent, reservoir_ee_synapses, reservoir_ei_synapses, reservoir_ie_synapses, reservoir_ii_synapses, reservoir_layer, train_synapses_negative, train_synapses_positive, readout_synapses_efferent_summed_variable_Vy_readout_synapses_efferent_post, input_synapses_negative_stateupdater, input_synapses_negative_summed_variable_Vy_input_synapses_negative_post, input_synapses_positive_stateupdater, input_synapses_positive_summed_variable_Vy_input_synapses_positive_post, readout_ee_synapses_stateupdater, readout_ee_synapses_summed_variable_Vy_readout_ee_synapses_post, readout_ei_synapses_stateupdater, readout_ei_synapses_summed_variable_Vy_readout_ei_synapses_post, readout_ie_synapses_stateupdater, readout_ie_synapses_summed_variable_Vy_readout_ie_synapses_post, readout_ii_synapses_stateupdater, readout_ii_synapses_summed_variable_Vy_readout_ii_synapses_post, readout_layer_stateupdater, readout_synapses_efferent_stateupdater, reservoir_ee_synapses_stateupdater, reservoir_ee_synapses_summed_variable_Vy_reservoir_ee_synapses_post, reservoir_ei_synapses_stateupdater, reservoir_ei_synapses_summed_variable_Vy_reservoir_ei_synapses_post, reservoir_ie_synapses_stateupdater, reservoir_ie_synapses_summed_variable_Vy_reservoir_ie_synapses_post, reservoir_ii_synapses_stateupdater, reservoir_ii_synapses_summed_variable_Vy_reservoir_ii_synapses_post, reservoir_layer_stateupdater, train_synapses_negative_stateupdater, train_synapses_negative_summed_variable_Vy_train_synapses_negative_post, train_synapses_positive_stateupdater, train_synapses_positive_summed_variable_Vy_train_synapses_positive_post, poissongroup, poissongroup_1, poissongroup_1_spike_thresholder, poissongroup_2, poissongroup_2_spike_thresholder, poissongroup_3, poissongroup_3_spike_thresholder, poissongroup_spike_thresholder, readout_layer_spike_thresholder, reservoir_layer_spike_thresholder, readout_layer_subgroup_2, readout_layer_subgroup_3, spike_monitor_readout, input_synapses_negative_down, input_synapses_negative_up, input_synapses_positive_down, input_synapses_positive_up, readout_ee_synapses_down, readout_ee_synapses_up, readout_ei_synapses_down, readout_ei_synapses_up, readout_ie_synapses_down, readout_ie_synapses_up, readout_ii_synapses_down, readout_ii_synapses_up, readout_synapses_efferent_down, readout_synapses_efferent_up, reservoir_ee_synapses_down, reservoir_ee_synapses_up, reservoir_ei_synapses_down, reservoir_ei_synapses_up, reservoir_ie_synapses_down, reservoir_ie_synapses_up, reservoir_ii_synapses_down, reservoir_ii_synapses_up, train_synapses_negative_down, train_synapses_negative_up, train_synapses_positive_down, train_synapses_positive_up, input_synapses_negative_post, input_synapses_positive_post, readout_ee_synapses_post, readout_ei_synapses_post, readout_ie_synapses_post, readout_ii_synapses_post, readout_synapses_efferent_post, reservoir_ee_synapses_post, reservoir_ei_synapses_post, reservoir_ie_synapses_post, reservoir_ii_synapses_post, train_synapses_negative_post, train_synapses_positive_post, readout_layer_spike_resetter, reservoir_layer_spike_resetter
2025-09-19 17:25:33,984 ERROR      brian2: 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\JHYAN_~1\AppData\Local\Temp\brian_debug_gzzmb4bk.log  Additionally, you can also include a copy of the script that was run, available at: C:\Users\JHYAN_~1\AppData\Local\Temp\brian_script_uaulv6bl.py Thanks!
Traceback (most recent call last):
  File "c:\Users\jhyan_8hz0dhz\OneDrive\Documents\School\_University\Research\Modular Scripts\main.py", line 160, in <module>
    results = run_limited_experiment()
  File "c:\Users\jhyan_8hz0dhz\OneDrive\Documents\School\_University\Research\Modular Scripts\main.py", line 95, in run_limited_experiment
    return run_experiment(
  File "c:\Users\jhyan_8hz0dhz\OneDrive\Documents\School\_University\Research\Modular Scripts\main.py", line 63, in run_experiment
    best_individual, fitness_history, elite_archive = simulate_ecosystem(
  File "c:\Users\jhyan_8hz0dhz\OneDrive\Documents\School\_University\Research\Modular Scripts\ecosystem.py", line 238, in simulate_ecosystem
    demes, generation_stats, generation_best, mutation_strength = run_generation(
  File "c:\Users\jhyan_8hz0dhz\OneDrive\Documents\School\_University\Research\Modular Scripts\ecosystem.py", line 153, in run_generation
    new_deme = evolve_deme(deme, fitness_key, mutation_strength, simulate_config)
  File "c:\Users\jhyan_8hz0dhz\OneDrive\Documents\School\_University\Research\Modular Scripts\ecosystem.py", line 58, in evolve_deme
    elite = copy.deepcopy(sorted_deme[i])
AttributeError: 'numpy._ArrayFunctionDispatcher' object has no attribute 'deepcopy'

Just to let you know, I am working on the older codebase that is still working so there is not as much urgency.

Hi @MisterOrbit Thanks for the update and the additional information. The way the logging and error reporting system works is indeed not great for complex setups, we have been planning to address this issue for a long time but haven’t yet found the time to actually do it (see Restructure package to allow clean import in libraries · Issue #1217 · brian-team/brian2 · GitHub).

Regarding the new error: I might be mistaken, but this does not seem to be a problem in Brian itself, but rather in the optimization code or potentially an incompatibility with newer numpy versions? Or is it possible that there is a variable copy that overwrote the name of the copy module?

Hi @mstimberg ,

I am glad to see that the log not generating was a known issue and there are plans to address it.

The error with the copy object was indeed due to a conflict between the numpy.copy() function and the copy module. I had already resolved that error, and only included the log above with that error because it was the latest available log before it ceased to generate for the second time (I thought it may be of some marginal benefit). The newest error with the PoissonGroup is still occurring and I have not had time to focus on it as I am instead woking on the old codebase. Even stranger, the error is now returning as:

Error in simulation: Error encountered with object named ‘input_layer_negative’.
Object was created here (most recent call only, full details in debug log):
File ‘c:\Users\jhyan_8hz0dhz\OneDrive\Documents\School_University\Research\Modular Scripts\network_builder.py’, line 289, in build_and_run_network
input_layer_negative = PoissonGroup(N=parameters[‘input_layer_size’], rates=“input_data_negative(t)”, name=“input_layer_negative”)

In words: the error has switched from reporting the source as the input_layer_positive object to the input_layer_negative object without any apparent reason. In my code, the input_layer_negative NeuronGoup is declared immediately after the input_layer_positive NeuronGroup when the network is constructed and differs only in the input data supplied as a TimedArray, which makes the issue more puzzling (why would it first occur in the positive layer, then randomly switch to occur in the negative layer, and not switch back?). Additionally, the log file is no longer generating again, even with import brian2 in each script file.

I am aware that I may be asking for too much with this support post, since I have no debug log nor traceback, and it is infeasible to share my entire code both because of its size and its complexity, which would put a burden on anyone who would go through it.

If you have any suggestions to get the log to generate, I can try them. Otherwise, since I have a workaround for now (with my old code) and this issue is particularly elusive, I will come back to this thread or make a new one when I can investigate it further.

Thank you for your help so far.

Hi @MisterOrbit. Your comment sounds as if you talked about the PoissonGroup issue before, but I don’t find any reference to it in your earlier posts. That the error “randomly switches” from one object to the other can happen if there is an error in both of them, so it depends on the order of checks. For a PoissonGroup to fail at the time of run, the issue is very likely with the definition of the rates – either it doesn’t find the input_data_positive array (but from your code posted in the first comment, it looks good), or the input_data_positive variable does not refer to a 1-dimensional TimedArray. This is what I’d check first.

From looking at your code, one more comment: the use of the namespace argument is currently commented out, but if you use it, you should not include units or functions provided by default, this are always available, even if you are using an empty namespace (see Namespaces — Brian 2 0.0.post128 documentation).