forked from jealie/BCBG-model
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbcbg2.hpp
522 lines (461 loc) · 20.5 KB
/
bcbg2.hpp
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
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
/* vim: set ft=cpp: */
#ifndef BCBG2_HPP
#define BCBG2_HPP
#include "constants.hpp"
#include <iostream>
#include "math.h"
#include "string.h"
#include <vector>
#include "stdio.h"
#include <stdlib.h>
#include <boost/random.hpp>
template < typename T >
T **Allocate2DArray( int nRows, int nCols)
{
T **ppi;
T *pool;
T *curPtr;
//(step 1) allocate memory for array of elements of column
ppi = new T*[nRows];
//(step 2) allocate memory for array of elements of each row
pool = new T [nRows * nCols];
// Now point the pointers in the right place
curPtr = pool;
for( int i = 0; i < nRows; i++)
{
*(ppi + i) = curPtr;
curPtr += nCols;
}
return ppi;
}
template < typename T >
void Free2DArray(T** Array)
{
delete [] *Array;
delete [] Array;
}
typedef struct _MemorySCN
{
std::vector <float> S_backup;
std::vector <std::vector <float> > H_in_RK4_backup;
std::vector <std::vector <float> > Hp_in_RK4_backup;
} MemorySCN;
typedef struct _MemoryMCN
{
std::vector <std::vector <float> > S_backup;
std::vector <std::vector <std::vector <float> > > H_in_RK4_backup;
std::vector <std::vector <std::vector <float> > > Hp_in_RK4_backup;
} MemoryMCN;
typedef struct _MemoryBCBG2
{
int tmod_backup;
int previous_tmod_backup;
std::vector <MemorySCN > scns;
std::vector <MemoryMCN > mcns;
} MemoryBCBG2;
class BCBG2
{
public:
#ifdef TSIROGIANNIS_2010
BCBG2() : _uni_gaussian(base_generator_t(42u), boost::normal_distribution<>(3.0f, 1.0f)) {}
#else
//BCBG2() : _uni_one_gaussian(base_generator_t(42u), boost::normal_distribution<>(1.0f, 0.5f)) {} // version with noise
BCBG2() : _uni_one_gaussian(base_generator_t(42u), boost::normal_distribution<>(1.0f, 0.0f)) {} // no noise
#endif
void initialize(int nucleus_type, int max_tau, float dt);
void update(float dt);
void updateSingleChannelNucleus(int steps);
void updateSingleChannelNucleus(int steps, int integration_method);
void updateSingleChannelNucleusWithNoise(int steps, int integration_method);
void updateSingleChannelNucleusTsiro(int steps, float value);
float updateSingleChannelNucleusTsiro(int steps); // returns the random cortical firing rate used
void updateMultiChannelsNucleus(int steps);
void updateMultiChannelsNucleus_basic_test(int steps, float time);
void updateMultiChannelsNucleus_humphries_test(int steps, float time);
float scalevar(float m);
float scalevarreduc(float m, float reduc);
void updateMultiChannelsNucleus_exploexplo_test(int steps, float time, int i);
void hammerizeSingleChannelNucleus(int steps);
void hammerizeSingleChannelNucleusTsiro(int steps);
void updateSingleChannelNucleusVana(float input, int bunch);
void updateSingleChannelNucleusDebug(float time_of_peak_in_s, float dt, float nb_of_s);
void testPSPSingleChannelNucleus(int pulse, int steps);
void stabilize_all(int steps);
bool testTimingResponse();
float basic_test(int ch, float time);
float exploexplo_test(int ch, float time, int i);
float exploexplo_testbis(int ch, float time, float debut_time, float end_time);
float visualization_humphries_et_al_2006(int ch, float time);
void updateNucleusCells(int steps);
void autopiloteNucleusCells(int steps, float* values);
void save_all();
void load_all();
void save_all(MemoryBCBG2& mem);
void load_all(MemoryBCBG2& mem);
class SingleChannelNucleus;
friend class SingleChannelNucleus;
class MultiChannelsNucleus;
friend class MultiChannelsNucleus;
class NucleusCells;
friend class NucleusCells;
SingleChannelNucleus* add_single_channel_nucleus(float Smax, float Sini, float vh, float k, int damping, float* dists, float* diams, int compartment_nb, const char* id);
MultiChannelsNucleus* add_multi_channels_nucleus(int channels_number, float Smax, float Sini, float vh, float k, int connectivity_type, float* dists, float* diams, int compartment_nb, const char* id);
NucleusCells* add_nucleus_cells(int cells_number, float Smax, float Sini, float vh, float k, float V_rest, float R, float Rm, float Ri, float* dists, float* diams, int compartment_nb, const char* id);
SingleChannelNucleus* get_single_channel_nucleus(int i) {return SCN[i];};
MultiChannelsNucleus* get_multi_channels_nucleus(int i) {return MCN[i];};
NucleusCells* get_nucleus_cells(int i) {return NC[i];};
protected:
// general variables of the circuit
int tmod;
int previous_tmod;
int max_tau;
int nucleus_type;
float dt;
float treal;
// list of nuclei
std::vector <SingleChannelNucleus *> SCN;
std::vector <MultiChannelsNucleus *> MCN;
std::vector <NucleusCells *> NC;
int n_nuclei; // counter used in the addition of nuclei
// random generator
typedef boost::mt19937 base_generator_t;
typedef boost::variate_generator<base_generator_t, boost::normal_distribution<> > rand_t;
rand_t _uni_one_gaussian;
// for use in store/restore function
int tmod_backup;
int previous_tmod_backup;
};
class Constants {
public:
// defining some constants
static const float A_AMPA = 0.001 * 5.43656365692; // 2*e
static const float D_AMPA = 0.65238763883017081; // (1/4)*e
static const float A_NMDA = 0.001 * 0.27182818284590454; // 0.1*e
static const float D_NMDA = 0.027182818284590453; // (1/100)*e
static const float A_GABA = 0.001 * 5.4365636569180902; // 2*e
static const float D_GABA = 0.45304697140984085; // (1/6)*e
};
class BCBG2::MultiChannelsNucleus
{
public:
friend class BCBG2;
MultiChannelsNucleus(BCBG2& bg) : bg_(bg) {}
void initialize_multi_channels_nucleus(int ch_n, float Smax, float Sini, float vh, float k, int connectivity_type, float* dists, float* diams, int compartment_nb, const char* id);
void update_multi_channels_nucleus_stabilize(int steps);
void update_multi_channels_nucleus_evo();
void set_afferent(float A, float D, int Sign, float C, int T, float distance, MultiChannelsNucleus* N);
void set_afferent(float A, float D, int Sign, float C, int T, float connexion_scheme, float distance, MultiChannelsNucleus* N);
float compute_distance_factor(float distance);
void initialize_new_afferent();
void display(std::ostream&);
void set_dt(float value);
// various getter/setter
float get_S(int tau_in, int ch_n) { return S[tau_in][ch_n]; }
// Warning ! get_S() returns S for _last step done_ not for _current step_
float get_S(int ch_n) { return S[(bg_.tmod - 1 + bg_.max_tau) % bg_.max_tau][ch_n]; }
void set_S(float value, int tau_in, int ch_n) { S[tau_in][ch_n] = value; }
void set_S(float value, int ch_n) { S[bg_.tmod][ch_n] = value; }
int get_afferents_number() { return n; }
int get_channels_number() { return ch_n; }
char* get_name() { return id; }
void save(MemoryMCN& mem);
void load(MemoryMCN& mem);
protected:
// to access the constants of the circuit
BCBG2& bg_;
// general variables of the multi_channels_nucleus
int ch_n; // number of concurrent channels
std::vector <std::vector <float> > S; //output frequency
float Smax;
float vh;
float k;
float kvh;
float dt;
char *id;
float Rm; // Membrane resistance
float Ri; // Internal resistivity
float membrane_area; // Surface of the neuron
std::vector <float> distances; // used to reconstruct a simple model of dendrites
std::vector <float> diameters; // used to reconstruct a simple model of dendrites
// afferents
float k1,k2,k3,k4,k5,k6,k7;
std::vector <std::vector <float> > H_in;
std::vector <std::vector <std::vector <float> > > H_in_RK4;
std::vector <std::vector <std::vector <float> > > Hp_in_RK4;
std::vector <std::vector <std::vector <float> > > Hpp_in_RK4;
std::vector <float> A_in;
std::vector <float> D_in;
std::vector <float> C_in;
std::vector <float> ADC_in;
std::vector <float> DD_in;
std::vector <float> D2_in;
std::vector <float> dtADC_in;
std::vector <float> dtDD_in;
std::vector <float> dtD2_in;
std::vector <int> T_in;
std::vector <int> Sign_in;
std::vector <float> conn_scheme_in;
std::vector <MultiChannelsNucleus *> N_in;
int n; // counter used in the addition of afferents
// to store/restore the state of a circuit
std::vector <std::vector <float> > S_backup; //output frequency
std::vector <std::vector <std::vector <float> > > H_in_RK4_backup;
std::vector <std::vector <std::vector <float> > > Hp_in_RK4_backup;
};
class BCBG2::NucleusCells
{
// this class implements the cell-level approximation
// NOT TO BE USED - THIS IS NOT FINISHED
// Use instead the classes SingleChannelNucleus (single channel allows quick simulation) and MultiChannelsNucleus (the multi channels version)
public:
struct Target {
BCBG2::NucleusCells * target_nucleus;
int cell_number;
int ion_channel_number;
float T;
float distance_factor;
};
struct IonChannel {
float A; // |
float D; // |
float Vrev; // |
bool is_nmda; // | these informations are duplicated for each cell
float time_to_add; // |
float to_add; // |
};
struct Spike {
int target_number;
float t;
float t_expiration; // set to the same value as IonChannel
};
friend class BCBG2;
NucleusCells(BCBG2& bg) : bg_(bg), is_firing(rng) {}
void initialize_cells(int cells_n, float Smax, float Sini, float V_threshold, float k, float V_rest, float R, float Rm, float Ri, float* dists, float* diams, int compartment_nb, const char* id, int nucleus_number);
int affect_ion_channel(float A, float D, float Vrev, bool is_nmda);
void add_efferent_axon(NucleusCells* nc, float cs, int T, float C, float distance_factor, int ion_channel_n);
void add_afferent_axon(NucleusCells* nc, float cs, int T, float C, float distance_factor, int ion_channel_n);
void add_afferent_synapse(NucleusCells* source_nucleus, float cs, int T, float C, float distance_factor, int ion_channel_n);
bool set_afferent(float A, float D, int S, float C, int T, float cs, float distance, NucleusCells* N);
bool add(float A, float D, float Vrev, float C, int T, float cs, float distance, NucleusCells* N);
bool nmda(float A, float D, float Vrev, float C, int T, float cs, float distance, NucleusCells* N);
bool add_ampa_gaba_nmda(float A, float D, float Vrev, float C, int T, float cs, float distance, NucleusCells* N, bool is_nmda);
void set_dt(float value);
void fast_add_g(int cell_i, int ion_channel_i, float distance_factor, float t_sent);
void add_g(int cell_i, int ion_channel_i, float distance_factor, float t_sent);
void update_cells();
void set_rate(float rate, bool reset);
void set_rate(float rate); // wrapper around previous function, with reset=true
void prepare_next_iteration();
void display(std::ostream& os);
void display_summary(std::ostream& os);
// various getter/setter
int get_nucleus_number() {
return this->nucleus_number;
}
float get_S(int cell_i) { float hz=0; for (int i=0; i<times_of_spikes[cell_i].size(); i++) {if (bg_.treal - times_of_spikes[cell_i][i] < 1.) {hz+=1.;} } return (hz); }
float get_meanS()
{
float hz=0;
for (int cell_i=0; cell_i<cells_n; cell_i++) {
for (int i=0; i<times_of_spikes[cell_i].size(); i++) {
if (bg_.treal - times_of_spikes[cell_i][i] < 1.) {
hz+=1.;
}
}
}
return (hz/((float)cells_n));
}
void debugg()
{
float now = bg_.treal;
std::cout << "NOW=" << now << std::endl;
std::cout << "DT=" << bg_.dt << std::endl;
for (int cell_i=0; cell_i<cells_n; cell_i++) {
std::cout << cell_i << " : " << last_spiked[cell_i] << std::endl;
}
}
float get_instantaneous_S3()
{
float hz=0;
for (int cell_i=0; cell_i<cells_n; cell_i++) {
for (int i=0; i<times_of_spikes[cell_i].size(); i++) {
if (bg_.treal - times_of_spikes[cell_i][i] < 0.1) {
hz+=1.;
}
}
}
return (10.*hz/((float)cells_n));
}
float get_instantaneous_S2()
{
float now = bg_.treal;
int nb_discharging = 0;
for (int cell_i=0; cell_i<cells_n; cell_i++) {
if (now - last_spiked[cell_i] < absolute_refractory_period-dt) { // refractory period dependent of maximum rate
nb_discharging++;
}
}
return (((float)nb_discharging) / ((float)cells_n)) * (absolute_refractory_period/dt);
}
float get_instantaneous_S()
{
float now = bg_.treal;
float isi=1./Smax;
float no_spiking_cells = 0.;
for (int cell_i=0; cell_i<cells_n; cell_i++) {
if (now - last_spiked[cell_i] >= 1./Smax + 2.*dt) {
isi += now - last_spiked[cell_i];
no_spiking_cells = no_spiking_cells + 1.;
}
}
if (no_spiking_cells == 0.) {
return 0.;
}
return (no_spiking_cells)/isi;
}
float get_meanV() { float v=0; for (int cell_i=0; cell_i<cells_n; cell_i++) { v+=V[cell_i];} return (v/((float)cells_n)); } // TODO TODO TODO TODO TODO original
float get_meanV_no_silenced() { float v=0; for (int cell_i=0; cell_i<cells_n; cell_i++) { if (V[cell_i] != V_rest) {v+=V[cell_i];}} return (v/((float)cells_n)); } // corrected to exclude silenced
float get_meanG() { float gg=0; for (int cell_i=0; cell_i<cells_n; cell_i++) { for (int ion_channel_i=0; ion_channel_i<ion_channels.size(); ion_channel_i++) {gg+=g[cell_i][ion_channel_i];}} return (gg/((float)cells_n*((float)ion_channels.size()))); }
float get_mean_inc_sum_v() { float mean_inc_sum_v=0; for (int cell_i=0; cell_i<cells_n; cell_i++) { mean_inc_sum_v+=inc_sum_v[cell_i];} return (mean_inc_sum_v/((float)cells_n)); }
float get_V(int cells_i) { return V[cells_i]; }
int get_afferents_number() { return n; }
char* get_name() { return id; }
int get_cells_number() {return cells_n; }
float get_ion_channel_time_to_add(int ion_channel_i) {return ion_channels[ion_channel_i].time_to_add; } // TODO this is dirty, all cells should share ion_channels (see struct IonChannel)
void save();
void restore();
protected:
// to access the constants of the circuit
BCBG2& bg_;
boost::mt19937 rng;
boost::uniform_01<boost::mt19937> is_firing;
// general variables of the nucleus_cells
int cells_n; // number of cells
std::vector <std::vector <float> > S; //output frequency
float Smax;
std::vector <float> V_threshold;
std::vector <float> V_reset; // Reset potential
std::vector <float> V; // Mean voltage of the neurons
std::vector <float> inc_sum_v; // Mean input voltage of the neurons from ionic channels
std::vector <std::vector <float> > g;
std::vector <std::vector <float> > next_g;
float V_rest; // Mean resting voltage
float R; // Membrane input resistance
float Rm; // Membrane resistance
float Ri; // Internal resistivity
float membrane_area; // Surface of the neuron
std::vector <float> distances; // used to reconstruct a simple model of dendrites
std::vector <float> diameters; // used to reconstruct a simple model of dendrites
float absolute_refractory_period;
float time_to_vanish;
float dt;
char *id;
int nucleus_number;
// afferents
float k1,k2,k3,k4,k5,k6,k7;
std::vector <float> Vrev_in; // Reversal Potential associated with synapse
std::vector <float> Distance_factor_in; // Distance factor computed as a single or multi compartment with sealed end
std::vector <NucleusCells *> N_in;
int n; // counter used in the addition of afferents
std::vector <float> last_spiked; // TODO
std::vector <struct IonChannel> ion_channels; // TODO
std::vector <std::vector <struct Target> > targets; // TODO
std::vector <std::vector <struct Spike> > spikes; // TODO
std::vector <std::vector <float> > times_of_spikes; // TODO
};
class BCBG2::SingleChannelNucleus
{
public:
friend class BCBG2;
SingleChannelNucleus(BCBG2& bg) : bg_(bg) {}
void initialize_single_channel_nucleus(float Smax, float Sini, float vh, float k, int damping, float* dists, float* diams, int compartment_nb, const char* id);
void update_single_channel_nucleus_stabilize(int steps);
void update_single_channel_nucleus_evo();
float get_all_inputs() // for debugging purpose
{
float r = 0;
r += A_in[0] * C_in[0] * N_in[0]->get_S((bg_.tmod - T_in[0] - 1 + bg_.max_tau ) % bg_.max_tau);
r += A_in[2] * C_in[2] * N_in[2]->get_S((bg_.tmod - T_in[2] - 1 + bg_.max_tau ) % bg_.max_tau);
return r;
}
void update_single_channel_nucleus_euler();
void update_single_channel_nucleus_rk3();
void update_single_channel_nucleus_evo_Hp();
void update_single_channel_nucleus_vana();
void update_single_channel_nucleus_damping_vana();
void update_single_channel_nucleus();
void set_afferent(float A, float D, int Sign, float C, int T, float distance, SingleChannelNucleus* N);
void set_afferent(float A, float D, int Sign, float C, int T, float to_be_ignored, float distance, SingleChannelNucleus* N); // Dummy function, calls other "set_afferent"
void set_afferent(float nu, int T, SingleChannelNucleus* N);
float compute_distance_factor(float distance);
void initialize_new_afferent();
void display(std::ostream&);
void display_Hs() {for (int i=0;i<n;i++) std::cout << "H=" << H_in_RK4[i][0] << " Hp=" << Hp_in_RK4[i][0] << std::endl; std::cout <<"-------------" << std::endl;}; // for debug
void set_dt(float value);
void save();
void load();
void save(MemorySCN& mem);
void load(MemorySCN& mem);
// various getter/setter
float get_S(int tau_in) { if (is_damped) {return Phi_in_RK4[tau_in];} else {return S[tau_in];} }
// Warning ! get_S() returns S for _last step done_ not for _current step_
float get_S() { if (is_damped) {return Phi_in_RK4[(bg_.tmod - 1 + bg_.max_tau) % bg_.max_tau];} else {return S[(bg_.tmod - 1 + bg_.max_tau) % bg_.max_tau];} }
void set_S(float value, int tau_in) { S[tau_in] = value; }
void set_S(float value) { S[bg_.tmod] = value; }
float get_H(int i) { return H_in_RK4[i][(bg_.tmod - 1 + bg_.max_tau) % bg_.max_tau]; }
float get_V() {float V=0; for (int i=0;i<n;i++) V+= H_in_RK4[i][(bg_.tmod + bg_.max_tau) % bg_.max_tau] * Sign_in[i]; return V; }
float get_Hp(int i) { return Hp_in_RK4[i][(bg_.tmod - 1 + bg_.max_tau) % bg_.max_tau]; }
void scale_Hp(int i, float value) { Hp_in_RK4[i][(bg_.tmod - 1 + bg_.max_tau) % bg_.max_tau] *= value; }
int get_afferents_number() { return n; }
char* get_name() { return id; }
protected:
// to access the constants of the circuit
BCBG2& bg_;
// general variables of the multi_channels_nucleus
std::vector <float> S; //output frequency
float Smax;
float vh;
float k;
float kvh;
float dt;
char *id;
int is_damped;
float Rm; // Membrane resistance
float Ri; // Internal resistivity
float membrane_area; // Surface of the neuron
std::vector <float> distances; // used to reconstruct a simple model of dendrites
std::vector <float> diameters; // used to reconstruct a simple model of dendrites
// afferents
std::vector <float> H_in;
float k1,k2,k3,k4,k5,k6,k7;
float k1bis,k2bis,k3bis;
std::vector <float> Phi_in_RK4;
std::vector <float> Phip_in_RK4;
std::vector <std::vector <float> > H_in_RK4;
std::vector <std::vector <float> > Hp_in_RK4;
std::vector <std::vector <float> > Hpp_in_RK4;
std::vector <float> H_in_old;
std::vector <float> Hp_in;
std::vector <float> Hpp_in;
std::vector <float> Hp_in_old;
std::vector <float> Hpp_in_old;
std::vector <float> A_in;
std::vector <float> D_in;
std::vector <float> C_in;
std::vector <float> ADC_in;
std::vector <float> DD_in;
std::vector <float> D2_in;
std::vector <float> nu_in;
std::vector <float> dtADC_in;
std::vector <float> dtDD_in;
std::vector <float> dtD2_in;
std::vector <int> T_in;
std::vector <int> Sign_in;
std::vector <SingleChannelNucleus *> N_in;
int n; // counter used in the addition of afferents
// to store/restore the state of a circuit
std::vector <float> S_backup; //output frequency
std::vector <std::vector <float> > H_in_RK4_backup;
std::vector <std::vector <float> > Hp_in_RK4_backup;
};
#endif