pricklypear/neuron/gaussstim.mod

224 lines
4.9 KiB
Modula-2

COMMENT
This mod file is based on netstim.mod in NEURON
modified by Yi Zhou to generate Gaussian interval distributions
ENDCOMMENT
NEURON {
POINT_PROCESS GaussStim
RANGE x
RANGE interval, number, start, factor, refrac
RANGE N_backward, N_forward, N_normal, N_total
RANGE rnd
RANGE rand
}
PARAMETER {
interval = 10 (ms) <1e-9,1e9> : ideal time between spikes (ms)
number = 10000 <0,1e9> : maximum number of spikes
start = 10 (ms) : delay before first spiketime
factor = 4 : fraction of mean to compute std (= mean / factor)
refrac = 0.5 <0,3> : absolute refractory period (upper limit of firing = 1 kHz)
: refrac >= dt, otherwise x can't be reset to 0
}
ASSIGNED {
x : if x > 0, cell is in refractory period
event (ms) : spiketime of next event in absolute time
on
end (ms)
m (ms) : mean of Gaussian
diff (ms)
N_forward : swap spike whose value exceed forwardly one interval
N_backward : swap spike whose value exceed backwardly one interval
N_normal
N_total
rnd
rand
}
PROCEDURE seed(x) {
set_seed(x)
}
INITIAL {
on = 0
x = 0
diff = 0
m = interval / 2 : each T has normal distribution N(interval/2, interval/2/factor)
N_forward = 0
N_backward = 0
N_normal = 0
N_total = 0
if (start >= 0 && number > 0) {
:: generate the first spiketime
event = start + invl(m)
:: make sure first spiketime is not before 0
if (event < 0) {
event = 0
}
:: skip directly to next event
net_send(event, 3)
}
}
PROCEDURE init_sequence(t(ms)) {
:: Turn on spike generation if n_spikes_max > 0
:: - "on" is set to 1
:: - "event" is set to "t" (input of this call)
:: - "end" is set to "interval * n_spikes_max"
if (number > 0) {
on = 1
event = t
end = t + 1e-6 + interval * (number-1)
}
}
PROCEDURE event_time() {
:: Generate the next spiketime
:: - call invl which calls normrand()
:: define local variables
LOCAL diff2, T
:: BAD diff gets overwritten in invl :facepalm:
diff2 = diff
:: if n_spikes_max is larger than 0
if (number > 0) {
:: generate a new interval until next spiketime
T = invl(m)
:: BAD useless
rnd = T
:: if new spiketime T is equal to an existing spiketime
if (T == 0 && diff2 == 0) {
T = T + dt
}
:: compute absolute time of next event (relative to 0 ms)
event = event + diff2 + T
:: augment total counter
N_total = N_total + 1
}
:: if next event is after the end, turn off spike generation
if (event > end) {
on = 0 :: BAD not the role of this function
}
}
FUNCTION invl(mean (ms)) (ms) {
:: Returns a new interval invl
:: Warning: also sets the global variable diff
:: define local variable
LOCAL std
:: compute standard deviation
if (mean <= 0.) {
mean = .01 (ms)
}
std = mean / factor
:: generate new interval invl
invl = normrand(mean, std)
:: make sure invl is within 0 and max interval
if (invl >= interval) {
:: decrease invl by n*interval
invl = fmod(invl, interval)
:: augment forward counter
N_forward = N_forward + 1
} else if (invl < 0) {
:: increase invl by n*interval
invl = fmod(invl, interval) + interval
:: augment backward counter
N_backward = N_backward + 1
} else {
:: augment normal counter
N_normal = N_normal + 1
}
:: overwrite global variable diff
diff = interval - invl
}
NET_RECEIVE(w) {
:: EXTERNAL CALL
if (flag == 0) {
if (w > 0 && on == 0) {
:: turn on spike generation
init_sequence(t)
net_send(0, 1)
} else if (w < 0 && on == 1) {
:: turn off spike generation
on = 0
}
}
:: MAIN CALL
if (flag == 1 && on == 1) {
if (x == 0) { :: time to spike (refractory period has passed)
:: set x to random uniform number (useless, just needs to > 0)
rand = scop_random() : [0, 1] uniform
x = rand
:: output event to synapse
net_event(t)
:: generate next spiketime
event_time()
:: if next spiketime is between refrac and refrac+dt
if (event-t >= refrac && event-t <= refrac+dt) {
:: move next spiketime up by one dt (just after refrac)
event = event + dt
}
:: if spike generation is turned on
if (on == 1) {
:: skip directly to next event
net_send(event - t, 1)
}
:: refractory period call
net_send(refrac, 2)
} else if (x != 0) { :: time to spike (within refractory period)
:: output event to synapse
net_event(t) :: BAD even still emitted even though refractory period, should be deleted
:: generate next spiketime
event_time() : although this spike will be ignored, still call next spike (independent cycles)
:: if spike generation is turned on
if (on == 1) {
:: skip directly to next event
net_send(event - t, 1)
}
}
}
:: REFRACTORY PERIOD CALL (END OF REFRACTORY PERIOD)
if (flag == 2) {
x = 0
}
:: INITIAL CALL
if (flag == 3) {
:: if spike generation is not yet turned on
if (on == 0) {
:: turn on spike generation
init_sequence(t)
:: call net_receive directly
net_send(0, 1)
}
}
}