-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKTzV2_Stimuli.cs
345 lines (309 loc) · 12.6 KB
/
KTzV2_Stimuli.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
using System;
using KTzV2.Maths.Random;
namespace KTzV2.Stimuli
{
public enum StimulusType
{
Delta,
DeltaTrain,
PoissonProcess,
DeltaWhenInactive,
None
}
public static class FExternalStimulus
{
/// <summary>
///
/// </summary>
/// <param name="t0">time for first stimulus</param>
/// <param name="stimulusIntensity">the (mean) intensity of the stimulus</param>
/// <param name="deltat">time interval between two consecutive delta stimulus</param>
/// <param name="n">amount of delta stimulus</param>
/// <param name="r">the inverse of the Poisson rate (timesteps/event)</param>
/// <param name="intensityStdDev">the std deviation of the generated signal</param>
/// <returns>The desired stimulus type</returns>
public static ExternalStimulusBase Get(StimulusType st, Int32 t0, Double stimulusIntensity, Int32 deltat, Int32 n, Double r, Double intensityStdDev)
{
switch (st)
{
case StimulusType.Delta : return new DeltaStimulus(t0, stimulusIntensity);
case StimulusType.DeltaTrain : return new DeltaTrainStimulus(t0, stimulusIntensity, deltat, n);
case StimulusType.PoissonProcess : return new PoissonProcess(r, stimulusIntensity, intensityStdDev);
case StimulusType.DeltaWhenInactive : return new DeltaWhenInactive(t0, stimulusIntensity);
case StimulusType.None : return new ExternalStimulusBase();
}
throw new ArgumentOutOfRangeException("unrecognized stimulus type!");
}
}
/// <summary>
/// interface to implement an external stimulus
/// </summary>
public interface IExternalStimulus
{
/// <summary>
/// timestep for stimulation
/// </summary>
Int32 timeForStimulus { get; }
/// <summary>
/// gets the signal of the stimulus for the given timestep
/// </summary>
/// <param name="timestep">the timestep to get the signal</param>
/// <returns></returns>
Double GetSignal(Int32 timestep);
}
public class ExternalStimulusBase : IExternalStimulus
{
/// <summary>
/// timestep for stimulation
/// </summary>
public Int32 timeForStimulus { get; protected set; }
public ExternalStimulusBase()
{ }
/// <summary>
/// gets the signal of the stimulus for the given timestep
/// </summary>
/// <param name="timestep">the timestep to get the signal</param>
/// <returns>the intensity of the signal of the stimulus</returns>
public virtual Double GetSignal(Int32 timestep)
{
return 0.0;
}
public virtual void SetNextStimulusTime(Int32 timeForNextStimulus)
{
return;
}
}
public class DeltaWhenInactive : ExternalStimulusBase
{
private Double StimulusIntensity { get; set; }
//public Int32 timeForStimulus { get; private set; }
public DeltaWhenInactive(Int32 t0, Double stimulusIntensity)
{
this.timeForStimulus = t0;
this.StimulusIntensity = stimulusIntensity;
}
public override Double GetSignal(Int32 timestep)
{
if (timestep == this.timeForStimulus)
{
//Console.WriteLine("estimulo t={0:d}",timestep);
return this.StimulusIntensity;
}
else
{
return 0.0;
}
}
public override void SetNextStimulusTime(Int32 timeForNextStimulus)
{
this.timeForStimulus = timeForNextStimulus;
}
}
public class DeltaTrainStimulus : ExternalStimulusBase
{
private Double stimulusIntensity { get; set; }
private Int32[] timeForStimulusDT { get; set; }
private Int32 nextTime { get; set; }
/// <summary>
/// creates a delta train stimulus (a set of n delta stimulus, each separated by deltat time of another)
/// </summary>
/// <param name="t0">time for first stimulus</param>
/// <param name="deltat">time interval between two consecutive delta stimulus</param>
/// <param name="n">amount of delta stimulus</param>
/// <param name="stimulusIntensity">the intensity of the stimulus</param>
public DeltaTrainStimulus(Int32 t0, Double stimulusIntensity, Int32 deltat, Int32 n)
{
if (n < 1) throw new ArgumentOutOfRangeException("n must be >= 1");
this.stimulusIntensity = stimulusIntensity;
this.timeForStimulusDT = new Int32[n + 1];
this.timeForStimulusDT[0] = t0;
Int32 i = 1;
while (i < n)
{
this.timeForStimulusDT[i] = t0 + i * deltat;
i++;
}
//
// if this.nextTime == n, there won't be anything in this.timeForStimulus, so the program will throw an exception: ArgumentOutOfRangeException
// to fix this, we put t0 as this.timeForStimulus[n], so it will never be equal to any timestep after this.timeForStimulus[n-1] and
// this.nextTime won't be summed up anymore.
//
this.timeForStimulusDT[n] = t0;
this.nextTime = 0;
}
public override Double GetSignal(Int32 timestep)
{
if (timestep == this.timeForStimulusDT[this.nextTime])
{
this.nextTime++;
return stimulusIntensity;
}
else
{
return 0.0;
}
}
}
public class DeltaStimulus : ExternalStimulusBase
{
private Double stimulusIntensity { get; set; }
//private Int32 timeForStimulus { get; set; }
public DeltaStimulus(Int32 timeForStimulus, Double stimulusIntensity)
{
this.stimulusIntensity = stimulusIntensity;
this.timeForStimulus = timeForStimulus;
}
public override Double GetSignal(Int32 timestep)
{
if (timestep == this.timeForStimulus)
{
return stimulusIntensity;
}
else
{
return 0.0;
}
}
}
/// <summary>
/// Class to create a list of signals (randomly distributed like a gaussian) organized in time like a Poisson process (exponential interval distribution between events)
/// </summary>
public class PoissonProcess : ExternalStimulusBase
{
/// <summary>
/// gaussian random number generator to get the signal intensity
/// </summary>
private GaussianRand signalIntensity { get; set; }
/// <summary>
/// random number to calculate the interval distribution
/// </summary>
private HomogeneousRand rand { get; set; }
/// <summary>
/// inverse of the Poisson process rate (unit: timesteps/events)
/// </summary>
public Double r { get; private set; }
/// <summary>
/// creates a Poisson process of undefined time duration
/// </summary>
/// <param name="r">the inverse of the Poisson rate (timesteps/event)</param>
/// <param name="signalMean">the mean intensity of the generated signal</param>
/// <param name="signalStdDev">the std deviation of the generated signal</param>
public PoissonProcess(Double r, Double signalMean, Double signalStdDev)
{
this.r = 1.0D - Math.Exp(-1.0D/r); // this is the probability of firing, and it is constant
this.rand = new HomogeneousRand();
this.signalIntensity = new GaussianRand(signalMean, signalStdDev);
}
/// <summary>
/// gets the signal intensity at the specified time
/// </summary>
/// <param name="timestep">the specified time to get the signal</param>
/// <returns>the signal intensity (gaussian distributed around its mean)</returns>
public override Double GetSignal(Int32 timestep)
{
return this.signalIntensity.getRandom()*(this.rand.GetRandomGT0LT1() < this.r? 1.0D : 0.0D);
}
}
/*
/// <summary>
/// Class to create a list of signals (randomly distributed like a gaussian) organized in time like a Poisson process (exponential interval distribution between events)
/// </summary>
/*
public class PoissonProcess : ExternalStimulusBase
{
/// <summary>
/// gaussian random number generator to get the signal intensity
/// </summary>
private GaussianRand signalIntensity { get; set; }
/// <summary>
/// random number to calculate the interval distribution
/// </summary>
private HomogeneousRand rand { get; set; }
/// <summary>
/// inverse of the Poisson process rate (unit: timesteps/events)
/// </summary>
public Double r { get; private set; }
/// <summary>
/// indicates the time when will occur the next fire of this event
/// </summary>
private Int32 timeForNextFire { get; set; }
///// <summary>
///// the state of the Poisson signal... each index is for each timestep the signal is running
///// </summary>
//private Int32[] signalState { get; set; }
///// <summary>
///// creates a Poisson process with the specified parameters
///// </summary>
///// <param name="r">the inverse of the Poisson rate (timesteps/event)</param>
///// <param name="signalMean">the mean intensity of the signal to generate</param>
///// <param name="signalStdDev">the std dev of the signal to generate</param>
///// <param name="totalTimesteps">total amount of timesteps that this process will take</param>
//public PoissonProcess(Double r, Double signalMean, Double signalStdDev, Int32 totalTimesteps)
// : this(r, signalMean, signalStdDev)
//{
// this.GenerateSignal(totalTimesteps);
//}
/// <summary>
/// creates a Poisson process of undefined time duration
/// </summary>
/// <param name="r">the inverse of the Poisson rate (timesteps/event)</param>
/// <param name="signalMean">the mean intensity of the generated signal</param>
/// <param name="signalStdDev">the std deviation of the generated signal</param>
public PoissonProcess(Double r, Double signalMean, Double signalStdDev)
{
this.r = r;
this.rand = new HomogeneousRand();
this.signalIntensity = new GaussianRand(signalMean, signalStdDev);
this.timeForNextFire = this.NextTimeInterval();
}
///// <summary>
///// generates an array of size totalTimesteps with the Poisson signal
///// </summary>
///// <param name="totalTimesteps">total amount of timesteps that this process will take</param>
//private void GenerateSignal(Int32 totalTimesteps)
//{
// this.signalState = new Int32[totalTimesteps];
// Int32 nextFire = this.NextTimeInterval(), i = 0;
// while (i < totalTimesteps)
// {
// if (i == nextFire)
// {
// this.signalState[i] = 1;
// nextFire += this.NextTimeInterval();
// }
// else
// {
// this.signalState[i] = 0;
// }
// i++;
// }
//}
/// <summary>
/// get the next time interval (in timesteps) between two adjacent signals exponentialy distributed
/// </summary>
/// <returns>the time interval in timesteps</returns>
private Int32 NextTimeInterval()
{
return 1 - (Int32)(Math.Log(this.rand.GetRandomGT0LT1()) * this.r);
}
/// <summary>
/// gets the signal intensity at the specified time
/// </summary>
/// <param name="timestep">the specified time to get the signal</param>
/// <returns>the signal intensity (gaussian distributed around its mean)</returns>
public override Double GetSignal(Int32 timestep)
{
if (timestep == this.timeForNextFire)
{
this.timeForNextFire += this.NextTimeInterval();
return this.signalIntensity.getRandom();
}
else
{
return 0.0;
}
//return this.signalState[timestep] * this.gRand.getRandom();
}
}
/**/
}