: $Id: netstim.mod 2212 2008-09-08 14:32:26Z hines $
: comments at end
NEURON {
ARTIFICIAL_CELL pj
RANGE interval, number, start, count, intervalVect
RANGE noise
THREADSAFE : only true if every instance has its own distinct Random
POINTER donotuse
}
PARAMETER {
interval = 15 (ms) <1e-9,1e9>: time between spikes (msec)
number = 1 <0,1e9> : number of spikes (independent of noise)
start = 1 (ms) : start of first spike
noise = 0 <0,1> : amount of randomness (0.0 - 1.0)
meani = 15 (ms)
count = 0
intervalVect[100]
}
ASSIGNED {
event (ms)
on
ispike
donotuse
}
PROCEDURE seed(x) {
set_seed(x)
}
INITIAL {
count = 0
FROM i=0 TO 99 {
intervalVect[i] = normrand(meani,5)
}
on = 0 : off
ispike = 0
if (noise < 0) {
noise = 0
}
if (noise > 1) {
noise = 1
}
if (start >= 0 && number > 0) {
on = 1
: randomize the first spike so on average it occurs at
: start + noise*interval
event = start + invl(interval) - interval*(1. - noise)
: but not earlier than 0
if (event < 0) {
event = 0
}
net_send(event, 3)
}
}
PROCEDURE init_sequence(t(ms)) {
if (number > 0) {
on = 1
event = 0
ispike = 0
}
}
FUNCTION invl(mean (ms)) (ms) {
if (mean <= 0.) {
mean = .01 (ms) : I would worry if it were 0.
}
if (noise == 0) {
invl = mean
}else{
invl = (1. - noise)*mean + noise*mean*erand()
}
}
VERBATIM
#ifndef NRN_VERSION_GTEQ_8_2_0
double nrn_random_pick(void* r);
void* nrn_random_arg(int argpos);
#define RANDCAST
#else
#define RANDCAST (Rand*)
#endif
ENDVERBATIM
FUNCTION erand() {
VERBATIM
if (_p_donotuse) {
/*
:Supports separate independent but reproducible streams for
: each instance. However, the corresponding hoc Random
: distribution MUST be set to Random.negexp(1)
*/
_lerand = nrn_random_pick(RANDCAST _p_donotuse);
}else{
/* only can be used in main thread */
if (_nt != nrn_threads) {
hoc_execerror("multithread random in NetStim"," only via hoc Random");
}
ENDVERBATIM
: the old standby. Cannot use if reproducible parallel sim
: independent of nhost or which host this instance is on
: is desired, since each instance on this cpu draws from
: the same stream
erand = exprand(1)
VERBATIM
}
ENDVERBATIM
}
PROCEDURE noiseFromRandom() {
VERBATIM
{
void** pv = (void**)(&_p_donotuse);
if (ifarg(1)) {
*pv = nrn_random_arg(1);
}else{
*pv = (void*)0;
}
}
ENDVERBATIM
}
PROCEDURE next_invl() {
if (number > 0) {
event = invl(interval)
}
if (ispike >= number) {
ispike = 0
number=normrand(15,5)
if (number<=0) {number=-number+1}
event = event + normrand(30,10)
interval = intervalVect[count]
count = count + 1
:interval = normrand(meani,5)
}
}
NET_RECEIVE (w) {
if (flag == 0) { : external event
if (w > 0 && on == 0) { : turn on spike sequence
: but not if a netsend is on the queue
init_sequence(t)
: randomize the first spike so on average it occurs at
: noise*interval (most likely interval is always 0)
next_invl()
event = event - interval*(1. - noise)
net_send(event, 1)
}else if (w < 0) { : turn off spiking definitively
on = 0
}
}
if (flag == 3) { : from INITIAL
if (on == 1) { : but ignore if turned off by external event
init_sequence(t)
net_send(0, 1)
}
}
if (flag == 1 && on == 1) {
ispike = ispike + 1
net_event(t)
next_invl()
if (on == 1) {
net_send(event, 1)
}
}
}