root/trunk/src/neuron/nmodl/netstim2.mod @ 888

Revision 888, 5.1 KB (checked in by apdavison, 2 years ago)

Merged reorganization branch changes r872:887 to trunk

  • Property svn:executable set to *
  • Property svn:keywords set to Id
Line 
1: Based on:
2:     $Id$
3: but with fixed duration rather than fixed number of spikes, and an interval
4: that can safely be varied during the simulation
5: Modified by Andrew Davison, UNIC, CNRS
6
7NEURON  {
8  ARTIFICIAL_CELL NetStimFD
9  RANGE interval, start, duration
10  RANGE noise
11  THREADSAFE : only true if every instance has its own distinct Random
12  POINTER donotuse
13}
14
15PARAMETER {
16        interval        = 10 (ms) <1e-9,1e9> : time between spikes (msec)
17        duration        = 100 (ms) <0,1e9>   : duration of firing (msec)
18        start           = 50 (ms)            : start of first spike
19        noise           = 0 <0,1>            : amount of randomness (0.0 - 1.0)
20}
21
22ASSIGNED {
23        event (ms)
24        on
25        donotuse
26        valid
27}
28
29PROCEDURE seed(x) {
30        set_seed(x)
31}
32
33INITIAL {
34        valid = 4
35        on = 0 : off
36        if (noise < 0) {
37                noise = 0
38        }
39        if (noise > 1) {
40                noise = 1
41        }
42        if (start >= 0 && duration > 0) {
43                : randomize the first spike so on average it occurs at
44                : start + noise*interval
45                invl(interval) : for some reason, the first invl() call seems to give implausibly large values, so we discard it
46                event = start + invl(interval) - interval*(1. - noise)
47                : but not earlier than 0
48                if (event < 0) {
49                        event = 0
50                }
51                if (event < start+duration) {
52                        on = 1
53                        net_send(event, 3)
54                }
55        }
56}       
57
58PROCEDURE init_sequence(t(ms)) {
59        if (duration > 0) {
60                on = 1
61                event = 0
62        }
63}
64
65FUNCTION invl(mean (ms)) (ms) {
66        if (mean <= 0.0) {
67                mean = 0.01 (ms) : I would worry if it were 0.0
68        }
69        if (noise == 0) {
70                invl = mean
71        }else{
72                invl = (1.0 - noise)*mean + noise*mean*erand()
73        }
74}
75VERBATIM
76double nrn_random_pick(void* r);
77void* nrn_random_arg(int argpos);
78ENDVERBATIM
79
80FUNCTION erand() {
81VERBATIM
82        if (_p_donotuse) {
83                /*
84                :Supports separate independent but reproducible streams for
85                : each instance. However, the corresponding hoc Random
86                : distribution MUST be set to Random.negexp(1)
87                */
88                _lerand = nrn_random_pick(_p_donotuse);
89        }else{
90                /* only can be used in main thread */
91                if (_nt != nrn_threads) {
92hoc_execerror("multithread random in NetStim"," only via hoc Random");
93                }
94ENDVERBATIM
95                : the old standby. Cannot use if reproducible parallel sim
96                : independent of nhost or which host this instance is on
97                : is desired, since each instance on this cpu draws from
98                : the same stream
99                erand = exprand(1)
100VERBATIM
101        }
102ENDVERBATIM
103}
104
105PROCEDURE noiseFromRandom() {
106VERBATIM
107 {
108        void** pv = (void**)(&_p_donotuse);
109        if (ifarg(1)) {
110                *pv = nrn_random_arg(1);
111        }else{
112                *pv = (void*)0;
113        }
114 }
115ENDVERBATIM
116}
117
118PROCEDURE next_invl() {
119        if (duration > 0) {
120                event = invl(interval)
121        }
122        if (t+event >= start+duration) {
123                on = 0
124        }
125        :printf("t=%g, event=%g, t+event=%g, on=%g\n", t, event, t+event, on)
126}
127
128NET_RECEIVE (w) {
129        if (flag == 0) { : external event
130                :printf("external event. w = %g\n", w)
131                if (w > 0) { : turn on spike sequence
132                        : but not if a netsend is on the queue
133                        init_sequence(t)
134                        : randomize the first spike so on average it occurs at
135                        : noise*interval (most likely interval is always 0)
136                        next_invl()
137                        event = event - interval*(1.0 - noise)
138                        valid = valid + 1 : events with previous values of valid will be ignored.
139                        net_send(event, valid)
140                }else if (w < 0) { : turn off spiking definitively
141                        on = 0
142                }
143        }
144        if (flag == 3) { : from INITIAL
145                if (on == 1) { : but ignore if turned off by external event
146                        init_sequence(t)
147                        net_send(0, valid)
148                        :printf("init_sequence(%g)\n", t)
149                }
150        }
151        if (flag == valid && on == 1) {
152                net_event(t)
153                next_invl()
154                :printf("%g %g %g flag=%g valid=%g\n", t, interval, event, flag, valid)
155                if (on == 1) {
156                        net_send(event, valid)
157                }
158        }
159}
160
161COMMENT
162Presynaptic spike generator
163---------------------------
164
165This mechanism has been written to be able to use synapses in a single
166neuron receiving various types of presynaptic trains.  This is a "fake"
167presynaptic compartment containing a spike generator.  The trains
168of spikes can be either periodic or noisy (Poisson-distributed)
169
170Parameters;
171   noise:       between 0 (no noise-periodic) and 1 (fully noisy)
172   interval:    mean time between spikes (ms)
173   [number:     number of spikes (independent of noise)] - deleted
174   duration:    duration of spiking (ms) - added
175
176Written by Z. Mainen, modified by A. Destexhe, The Salk Institute
177
178Modified by Michael Hines for use with CVode
179The intrinsic bursting parameters have been removed since
180generators can stimulate other generators to create complicated bursting
181patterns with independent statistics (see below)
182
183Modified by Michael Hines to use logical event style with NET_RECEIVE
184This stimulator can also be triggered by an input event.
185If the stimulator is in the on==0 state (no net_send events on queue)
186 and receives a positive weight
187event, then the stimulator changes to the on=1 state and goes through
188its entire spike sequence before changing to the on=0 state. During
189that time it ignores any positive weight events. If, in an on!=0 state,
190the stimulator receives a negative weight event, the stimulator will
191change to the on==0 state. In the on==0 state, it will ignore any ariving
192net_send events. A change to the on==1 state immediately fires the first spike of
193its sequence.
194
195ENDCOMMENT
196
Note: See TracBrowser for help on using the browser.