Very good question. The answer is yes, but "yes" doesn't tell you how to do it, or what complications might arise. For example, did you know that, by default, there is only a single pseudorandom number generator, and that everything that needs a "random" number will get its number from that generator? And do you know what this implies for simulations that involve randomness?
For example, consider a model that consists of two artificial spiking cells called cell0 and cell1, which have identical properties: interval == 10 ms, number == 10, start == 1, and noise == 1. These two cells aren't connected to each other--they're just "spiking" away at "random" times. Here's the list of times at which they spike:
Code: Select all
time cell
1.347 1
6.015 0
10.123 0
12.628 1
13.663 1
14.913 0
But what if cell 1's start time is 6 ms? Here are the spike times:
Code: Select all
time cell
6.015 0
6.347 1
10.456 1
15.245 1
16.281 1
17.295 0
This demonstrates that the cell spike times are not independent of each other.
Why does this happen? Because the two NetStims are drawing values from the same random number generator. Change any parameter that affects one--interval, start time, number, or noise--and you'll also affect the other, whether you want to or not. Even if all you do is add a third, randomly firing NetStim to your model, and don't connect it to any other cell in the model.
The fix is to prevent the NetStims from using a shared random number generator. And you can do this by making sure that every randomly-firing NetStim is associated with its own random number generator. Example:
Code: Select all
// before creating any randomly-firing NetStims
objref nslist, rlist
nslist = new List() // will hold all randomly-firing NetStims
rlist = new List() // will hold the corresponding instances of the Random class
// Random123 pseudorandom stream identifiers--nonzero integer values
id1 = 1
id2 = 2
id3 = 3
// each time you create a NetStim, also create a corresponding instance of Random
proc makenetstims() { local i localobj ns, rs
rslist = new List()
nslist = new List()
for i = 0, $1-1 {
rs = new Random()
rs.Random123(id1, id2, id3 + i) // so each has its own stream
rslist.append(rs)
rs.negexp(1) // must specify negexp distribution with mean = 1
ns = new NetStim()
nslist.append(ns)
ns.noiseFromRandom(rs)
}
}
makenetstims(NSNUM) // NSNUM has a value that you assigned elsewhere
// ISI, NUM, START, and NOISE have values that you assigned elsewhere
proc setnsparams() { local i
for i = 0,nslist.count()-1 {
nslist.o(i).interval = ISI
nslist.o(i).number = NUM
nslist.o(i).start = START
nslist.o(i).noise = NOISE
}
}
setnsparams()
Great. Now, what about forcing all these generators to start at the same point in their pseudorandom sequences? Just call restart() to make them go back to the start of their sequences.
Code: Select all
proc restart() { local i
for i = 0, rslist.count()-1 rslist.o(i).seq(1)
}
Of course the same strategy can be implemented with Python ("left as an exercise" to all the pythonistas out there).
Be sure to read the Programmer's Reference for documentation of anything in this post that you don't understand. And if the Programmer's Reference isn't clear enough, let me know.