Setting up nodes values for different iteration of a model


#1

Hello

I am completely new with modeling spiking neuron networks in general and with nengo in particular. I have recently developed a network which is supposed to mimic some experimental data of mine. The model seems to work properly and I manage to access the data properly. However, my problem, right now, is that I don’t manage to create a batch in which I manipulate the values of the 2 nodes of the network to mimic different conditions. Do you have an idea how I should do this?
Here is what I have:

model = nengo.Network()
sample_stim1   =   Piecewise({0: 0, 0.450: 1)})
sample_stim2   =   Piecewise({0: 0, 0.450: -1)})
test_stim1    =   Piecewise({0: 0, 0.450: 0, 1.350: -1, 1.800: ,1, 2.250: 0})
test_stim2    =   Piecewise({0: 0, 0.450: 0, 1.350: 1, 1.800: ,-1, 2.250: 0})

with model:
    stim_mem = nengo.Node(sample_stim)#here sample stim should take the values of either sample_stim1                                                                                #                                                                  #or sample_stim2
    stim_vis = nengo.Node(test_stim)#here test_stim should take the values of either test_stim1                                                                                #                                                                  #or test_stim2

for j in range (0, numtrials) #num trials is the number of iteration 
        with nengo.Simulator(model) as sim:
                 tmp=np.random.choice([-1,1])
                 if tmp==1:
                        stim_mem=sample_stim1
                        stim_vis=test_stim1
                 else:
                        stim_mem=sample_stim2
                        stim_vis=test_stim2
                sim.run(trial_duration)

#2

There are a few syntax errors in your code that prevent it from running, which makes it a little bit harder to help, but to answer your question the easiest way to do this (fewest changes to the code in its current form) would be to substitute the output attribute of the nengo.Node with the new process (rather than reassigning the variable, which doesn’t do what you want because that simply creates a new variable with the same name, in Python).

In other words, replace:

...
                        stim_mem=sample_stim1
                        stim_vis=test_stim1
                 else:
                        stim_mem=sample_stim2
                        stim_vis=test_stim2
...

with:

...
                        stim_mem.output=sample_stim1
                        stim_vis.output=test_stim1
                 else:
                        stim_mem.output=sample_stim2
                        stim_vis.output=test_stim2
...

#3

Hello Aaron
Sorry for the syntax errors, it was not my actual code…
It seems I still have a lot to learn about how nengo works and how to simulate models. I’ve tried what you propose but I don’t think I understood correctly, because I don’t manage to make it work properly.

I’ve then tried to change things a little but it still does not work. Here is my actual code, but the values do not change on each iteration of the simulation:

    model = nengo.Network()

def Pick_S(x):
    if x==1:
        sample_stim=S1
    else:
        sample_stim=S2
    return sample_stim
 
def Pick_T(x):
    if x==1:
        test_stim=T1
    else:
        test_stim=T2
    return test_stim

tmp=np.random.choice([-1,1])
sample_stim= Pick_S(tmp)
test_stim= Pick_S(tmp)

with model:
   
    stim_mem = nengo.Node(sample_stim)
    stim_vis = nengo.Node(test_stim)

    Stim_mem    = nengo.Probe(stim_mem)
    Stim_vis    = nengo.Probe(stim_vis)

for i in range(0,10):
    with nengo.Simulator(model) as sim:
        tmp=np.random.choice([-1,1])
        sample_stim= Pick_S(tmp) # same results whether I use sample_stim.output=Pick_S(tmp) or not
        test_stim= Pick_S(tmp) # same results whether I use test_stim.output=Pick_T(tmp) or not
        sim.run(trial_duration)
        Sample_values[i,:]  = np.transpose(sim.data[Stim_mem])
        Test_values[i,:]    = np.transpose(sim.data[Stim_vis])

#4

It looks like you tried sample_stim = ... and sample_stim.output = ... but neither is what I suggested. My suggestion above was to modify the output attribute on the node itself, as in stim_mem.output = ..., where stim_mem is the Node (not the Process). Here is your code, modified to run, and plot each trial to demonstrate randomness.

import numpy as np
import matplotlib.pyplot as plt

import nengo
from nengo.processes import Piecewise

S1 = Piecewise({0: 0, 0.450: 1})
S2 = Piecewise({0: 0, 0.450: -1})
T1 = Piecewise({0: 0, 0.450: 0, 1.350: -1, 1.800: 1, 2.250: 0})
T2 = Piecewise({0: 0, 0.450: 0, 1.350: 1, 1.800: -1, 2.250: 0})
trial_duration = 2.5
n_trials = 10

def Pick_S(x):
    if x==1:
        sample_stim=S1
    else:
        sample_stim=S2
    return sample_stim
 
def Pick_T(x):
    if x==1:
        test_stim=T1
    else:
        test_stim=T2
    return test_stim

tmp = np.random.choice([-1,1])
sample_stim = Pick_S(tmp)
test_stim = Pick_T(tmp)

model = nengo.Network()

with model:
   
    stim_mem = nengo.Node(sample_stim)
    stim_vis = nengo.Node(test_stim)

    Stim_mem = nengo.Probe(stim_mem)
    Stim_vis = nengo.Probe(stim_vis)

Sample_values = []
Test_values = []
for i in range(n_trials):
    with nengo.Simulator(model) as sim:
        tmp=np.random.choice([-1,1])
        stim_mem.output = Pick_S(tmp)
        stim_vis.output = Pick_T(tmp)
        sim.run(trial_duration)
        Sample_values.append(np.transpose(sim.data[Stim_mem]))
        Test_values.append(np.transpose(sim.data[Stim_vis]))

fig, ax = plt.subplots(1, 2, figsize=(16, 5), sharey=True)
ax[0].set_title("Sample_values")
ax[1].set_title("Test_values")
for i in range(n_trials):
    ax[0].plot(sim.trange(), Sample_values[i].T)
    ax[1].plot(sim.trange(), Test_values[i].T)
ax[0].set_xlabel("Time (s)")
ax[1].set_xlabel("Time (s)")
fig.show()


#5

And here is an alternative, but (IMO) cleaner and more Pythonic way of doing this, by use of a function to abstract away the notion of a trial – including picking the stimuli, building, simulating, and returning the results. You can extend this to analyze the data and return some analysis instead. Note that I also use fixed seeds for the RNG in order to make sure that each time you run this you get the same set of stimuli across all trials (for reproducibility). Hope this helps.

import numpy as np
import matplotlib.pyplot as plt

import nengo
from nengo.processes import Piecewise

S1 = Piecewise({0: 0, 0.450: 1})
S2 = Piecewise({0: 0, 0.450: -1})
T1 = Piecewise({0: 0, 0.450: 0, 1.350: -1, 1.800: 1, 2.250: 0})
T2 = Piecewise({0: 0, 0.450: 0, 1.350: 1, 1.800: -1, 2.250: 0})
trial_duration = 2.5
n_trials = 10

def run_trial(stim_seed):
    stim_rng = np.random.RandomState(seed=stim_seed)
    condition = stim_rng.choice(range(2))
    S = [S1, S2][condition]
    T = [T1, T2][condition]
    
    with nengo.Network() as model:
        stim_mem = nengo.Node(output=S)
        stim_vis = nengo.Node(output=T)
        
        probe_mem = nengo.Probe(stim_mem)
        probe_vis = nengo.Probe(stim_vis)
        
    with nengo.Simulator(model) as sim:
        sim.run(trial_duration)
        
    return sim.data[probe_mem], sim.data[probe_vis]

data = []
for i in range(n_trials):
    data.append(run_trial(stim_seed=i))

#6

Thanks so much. It seems to be working. Now, I’ll analyze this and try to understand how it works now and why it didn’t work before.