Completed
Push — 0.7.dev ( 4ba2e4...25f492 )
by Andrei
59s
created

central_element.__init__()   A

Complexity

Conditions 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
1
"""!
2
3
@brief Oscillatory Neural Network based on Hodgkin-Huxley Neuron Model
4
@details Based on article description:
5
         - D.Chik, R.Borisyuk, Y.Kazanovich. Selective attention model with spiking elements. 2009.
6
7
@authors Andrei Novikov ([email protected])
8
@date 2014-2017
9
@copyright GNU Public License
10
11
@cond GNU_PUBLIC_LICENSE
12
    PyClustering is free software: you can redistribute it and/or modify
13
    it under the terms of the GNU General Public License as published by
14
    the Free Software Foundation, either version 3 of the License, or
15
    (at your option) any later version.
16
    
17
    PyClustering is distributed in the hope that it will be useful,
18
    but WITHOUT ANY WARRANTY; without even the implied warranty of
19
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
    GNU General Public License for more details.
21
    
22
    You should have received a copy of the GNU General Public License
23
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
@endcond
25
26
"""
27
28
from pyclustering.nnet import *;
0 ignored issues
show
Unused Code introduced by
IntEnum was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
initial_type was imported with wildcard, but is not used.
Loading history...
29
30
from scipy.integrate import odeint;
0 ignored issues
show
Configuration introduced by
The import scipy.integrate could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
31
32
from pyclustering.utils import allocate_sync_ensembles;
33
34
import numpy;
0 ignored issues
show
Configuration introduced by
The import numpy could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
35
import random;
36
37
class hhn_parameters:
38
    """!
39
    @brief Describes parameters of Hodgkin-Huxley Oscillatory Network.
40
    
41
    @see hhn_network
42
    
43
    """
44
    
45
    def __init__(self):
46
        """!
47
        @brief    Default constructor of parameters for Hodgkin-Huxley Oscillatory Network.
48
        @details  Constructor initializes parameters by default non-zero values that can be
49
                  used for simple simulation.
50
        """
51
        
52
        ## Intrinsic noise.
53
        self.nu      = random.random() * 2.0 - 1.0;
54
        
55
        ## Maximal conductivity for sodium current.
56
        self.gNa     = 120.0 * (1 + 0.02 * self.nu);
57
        
58
        ## Maximal conductivity for potassium current.
59
        self.gK      = 36.0 * (1 + 0.02 * self.nu);
60
        
61
        ## Maximal conductivity for leakage current.
62
        self.gL      = 0.3 * (1 + 0.02 * self.nu);
63
        
64
        
65
        ## Reverse potential of sodium current [mV].
66
        self.vNa     = 50.0;
67
        
68
        ## Reverse potential of potassium current [mV].
69
        self.vK      = -77.0;
70
        
71
        ## Reverse potantial of leakage current [mV].
72
        self.vL      = -54.4;
73
        
74
        ## Rest potential [mV].
75
        self.vRest   = -65.0;    
76
        
77
        
78
        ## External current [mV] for central element 1.
79
        self.Icn1    = 5.0;
80
        
81
        ## External current [mV] for central element 2.
82
        self.Icn2    = 30.0;
83
        
84
        
85
        ## Synaptic reversal potential [mV] for inhibitory effects.
86
        self.Vsyninh = -80.0;    
87
        
88
        ## Synaptic reversal potential [mV] for exciting effects.
89
        self.Vsynexc = 0.0;
90
        
91
        ## Alfa-parameter for alfa-function for inhibitory effect.
92
        self.alfa_inhibitory     = 6.0;
93
        
94
        ## Betta-parameter for alfa-function for inhibitory effect.
95
        self.betta_inhibitory    = 0.3;
96
        
97
        
98
        ## Alfa-parameter for alfa-function for excitatoty effect.
99
        self.alfa_excitatory     = 40.0;
100
        
101
        ## Betta-parameter for alfa-function for excitatoty effect.
102
        self.betta_excitatory    = 2.0;
103
        
104
        
105
        ## Strength of the synaptic connection from PN to CN1.
106
        self.w1 = 0.1;
107
        
108
        ## Strength of the synaptic connection from CN1 to PN.
109
        self.w2 = 9.0;
110
        
111
        ## Strength of the synaptic connection from CN2 to PN.
112
        self.w3 = 5.0;
113
        
114
        
115
        ## Period of time [ms] when high strength value of synaptic connection exists from CN2 to PN.
116
        self.deltah = 650.0;
117
        
118
        ## Threshold of the membrane potential that should exceeded by oscillator to be considered as an active.
119
        self.threshold = -10;
120
        
121
        ## Affects pulse counter.
122
        self.eps = 0.16;
123
124
125
class central_element:
126
    """!
127
    @brief Central element consist of two central neurons that are described by a little bit different dynamic than peripheral.
128
    
129
    @see hhn_network
130
    
131
    """
132
    
133
    def __init__(self):
134
        """!
135
        @brief Constructor of central element.
136
        
137
        """
138
        
139
        ## Membrane potential of cenral neuron (V).
140
        self.membrane_potential      = 0.0;
141
        
142
        ## Activation conductance of the sodium channel (m).
143
        self.active_cond_sodium      = 0.0;
144
        
145
        ## Inactivaton conductance of the sodium channel (h).
146
        self.inactive_cond_sodium    = 0.0;
147
        
148
        ## Activaton conductance of the sodium channel (h).
149
        self.active_cond_potassium   = 0.0;
150
        
151
        ## Spike generation of central neuron.
152
        self.pulse_generation = False;
153
        
154
        ## Timestamps of generated pulses.
155
        self.pulse_generation_time = [];
156
    
157
    def __repr__(self):
158
        """!
159
        @brief Returns string that represents central element.
160
        
161
        """
162
        return "%s, %s" % (self.membrane_potential, self.pulse_generation_time);
163
164
165
class hhn_network(network):
166
    """!
167
    @brief Oscillatory Neural Network with central element based on Hodgkin-Huxley neuron model. Interaction between oscillators is performed via
168
           central element (no connection between oscillators that are called as peripheral). Peripheral oscillators receive external stimulus.
169
           Central element consist of two oscillators: the first is used for synchronization some ensemble of oscillators and the second controls
170
           synchronization of the first cental oscillator with verious ensembles.
171
    
172
    Example:
173
    @code
174
        # change period of time when high strength value of synaptic connection exists from CN2 to PN.
175
        params = hhn_parameters();
176
        params.deltah = 400;
177
        
178
        # create oscillatory network with stimulus
179
        net = hhn_network(6, [0, 0, 25, 25, 47, 47], params);
180
        
181
        # simulate network
182
        (t, dyn) = net.simulate(1200, 600);
183
        
184
        # draw network output during simulation
185
        draw_dynamics(t, dyn, x_title = "Time", y_title = "V", separate = True);
186
    @endcode
187
    
188
    """
189
    
190
    def __init__(self, num_osc, stimulus = None, parameters = None, type_conn = None, type_conn_represent = conn_represent.MATRIX):
191
        """!
192
        @brief Constructor of oscillatory network based on Hodgkin-Huxley meuron model.
193
        
194
        @param[in] num_osc (uint): Number of peripheral oscillators in the network.
195
        @param[in] stimulus (list): List of stimulus for oscillators, number of stimulus should be equal to number of peripheral oscillators.
196
        @param[in] parameters (hhn_parameters): Parameters of the network.
197
        @param[in] type_conn (conn_type): Type of connections between oscillators in the network (ignored for this type of network).
198
        @param[in] type_conn_represent (conn_represent): Internal representation of connection in the network: matrix or list.
199
        
200
        """
201
          
202
        super().__init__(num_osc, conn_type.NONE, type_conn_represent);
203
        
204
        self._membrane_dynamic_pointer = None;        # final result is stored here.
205
        
206
        self._membrane_potential        = [0.0] * self._num_osc;
207
        self._active_cond_sodium        = [0.0] * self._num_osc;
208
        self._inactive_cond_sodium      = [0.0] * self._num_osc;
209
        self._active_cond_potassium     = [0.0] * self._num_osc;
210
        self._link_activation_time      = [0.0] * self._num_osc;
211
        self._link_pulse_counter        = [0.0] * self._num_osc;
212
        self._link_deactivation_time    = [0.0] * self._num_osc;
213
        self._link_weight3              = [0.0] * self._num_osc;
214
        self._pulse_generation_time     = [ [] for i in range(self._num_osc) ];
215
        self._pulse_generation          = [False] * self._num_osc;
216
        
217
        self._noise = [random.random() * 2.0 - 1.0 for i in range(self._num_osc)];
218
        
219
        self._central_element = [central_element(), central_element()];
220
        
221
        if (stimulus is None):
222
            self._stimulus = [0.0] * self._num_osc;
223
        else:
224
            self._stimulus = stimulus;
225
        
226
        if (parameters is not None):
227
            self._params = parameters;
228
        else:
229
            self._params = hhn_parameters();
230
    
231
    
232
    def simulate(self, steps, time, solution = solve_type.RK4, collect_dynamic = True):
233
        """!
234
        @brief Performs static simulation of oscillatory network based on Hodgkin-Huxley neuron model.
235
        
236
        @param[in] steps (uint): Number steps of simulations during simulation.
237
        @param[in] time (double): Time of simulation.
238
        @param[in] solution (solve_type): Type of solver for differential equations.
239
        @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.
240
        
241
        @return (list) Dynamic of oscillatory network. If argument 'collect_dynamic' = True, than return dynamic for the whole simulation time,
242
                otherwise returns only last values (last step of simulation) of dynamic.
243
        
244
        """
245
        
246
        return self.simulate_static(steps, time, solution, collect_dynamic);
247
    
248
    
249
    def simulate_static(self, steps, time, solution = solve_type.RK4, collect_dynamic = False):
250
        """!
251
        @brief Performs static simulation of oscillatory network based on Hodgkin-Huxley neuron model.
252
        
253
        @param[in] steps (uint): Number steps of simulations during simulation.
254
        @param[in] time (double): Time of simulation.
255
        @param[in] solution (solve_type): Type of solver for differential equations.
256
        @param[in] collect_dynamic (bool): If True - returns whole dynamic of oscillatory network, otherwise returns only last values of dynamics.
257
        
258
        @return (list) Dynamic of oscillatory network. If argument 'collect_dynamic' = True, than return dynamic for the whole simulation time,
259
                otherwise returns only last values (last step of simulation) of dynamic.
260
        
261
        """
262
        
263
        self._membrane_dynamic_pointer = None;
264
        
265
        # Check solver before simulation
266
        if (solution == solve_type.FAST):
267
            raise NameError("Solver FAST is not support due to low accuracy that leads to huge error.");
268
        elif (solution == solve_type.RKF45):
269
            raise NameError("Solver RKF45 is not support in python version.");
270
        
271
        dyn_memb = None;
272
        dyn_time = None;
273
        
274
        # Store only excitatory of the oscillator
275
        if (collect_dynamic == True):
276
            dyn_memb = [];
277
            dyn_time = [];
278
            
279
        step = time / steps;
280
        int_step = step / 10.0;
281
        
282
        for t in numpy.arange(step, time + step, step):
283
            # update states of oscillators
284
            memb = self._calculate_states(solution, t, step, int_step);
285
            
286
            # update states of oscillators
287
            if (collect_dynamic == True):
288
                dyn_memb.append(memb);
289
                dyn_time.append(t);
290
            else:
291
                dyn_memb = memb;
292
                dyn_time = t;
293
        
294
        self._membrane_dynamic_pointer = dyn_memb;
295
        return (dyn_time, dyn_memb);
296
    
297
    
298
    def _calculate_states(self, solution, t, step, int_step):
0 ignored issues
show
Unused Code introduced by
The argument solution seems to be unused.
Loading history...
299
        """!
300
        @brief Caclculates new state of each oscillator in the network. Returns only excitatory state of oscillators.
301
        
302
        @param[in] solution (solve_type): Type solver of the differential equations.
303
        @param[in] t (double): Current time of simulation.
304
        @param[in] step (uint): Step of solution at the end of which states of oscillators should be calculated.
305
        @param[in] int_step (double): Differentiation step that is used for solving differential equation.
306
        
307
        @return (list) New states of membrance potentials for peripheral oscillators and for cental elements as a list where
308
                the last two values correspond to central element 1 and 2.
309
                 
310
        """
311
        
312
        next_membrane           = [0.0] * self._num_osc;
313
        next_active_sodium      = [0.0] * self._num_osc;
314
        next_inactive_sodium    = [0.0] * self._num_osc;
315
        next_active_potassium   = [0.0] * self._num_osc;
316
        
317
        # Update states of oscillators
318
        for index in range (0, self._num_osc, 1):
319
            result = odeint(self.hnn_state, 
320
                            [ self._membrane_potential[index], self._active_cond_sodium[index], self._inactive_cond_sodium[index], self._active_cond_potassium[index] ], 
321
                            numpy.arange(t - step, t, int_step), 
322
                            (index , ));
323
                            
324
            [ next_membrane[index], next_active_sodium[index], next_inactive_sodium[index], next_active_potassium[index] ] = result[len(result) - 1][0:4];        
325
        
326
        next_cn_membrane            = [0.0, 0.0];
327
        next_cn_active_sodium       = [0.0, 0.0];
328
        next_cn_inactive_sodium     = [0.0, 0.0];
329
        next_cn_active_potassium    = [0.0, 0.0];
330
        
331
        # Update states of central elements
332
        for index in range(0, len(self._central_element)):
333
            result = odeint(self.hnn_state, 
334
                            [ self._central_element[index].membrane_potential, self._central_element[index].active_cond_sodium, self._central_element[index].inactive_cond_sodium, self._central_element[index].active_cond_potassium ], 
335
                            numpy.arange(t - step, t, int_step), 
336
                            (self._num_osc + index , ));
337
                            
338
            [ next_cn_membrane[index], next_cn_active_sodium[index], next_cn_inactive_sodium[index], next_cn_active_potassium[index] ] = result[len(result) - 1][0:4];
339
        
340
        # Noise generation
341
        self._noise = [ 1.0 + 0.01 * (random.random() * 2.0 - 1.0) for i in range(self._num_osc)];
342
        
343
        # Updating states of PNs
344
        self.__update_peripheral_neurons(t, step, next_membrane, next_active_sodium, next_inactive_sodium, next_active_potassium);
345
        
346
        # Updation states of CN
347
        self.__update_central_neurons(t, next_cn_membrane, next_cn_active_sodium, next_cn_inactive_sodium, next_cn_active_potassium);
348
        
349
        return next_membrane + next_cn_membrane;
350
    
351
    
352
    def __update_peripheral_neurons(self, t, step, next_membrane, next_active_sodium, next_inactive_sodium, next_active_potassium):
353
        """!
354
        @brief Update peripheral neurons in line with new values of current in channels.
355
        
356
        @param[in] t (doubles): Current time of simulation.
357
        @param[in] step (uint): Step (time duration) during simulation when states of oscillators should be calculated.
358
        @param[in] next_membrane (list): New values of membrane potentials for peripheral neurons.
359
        @Param[in] next_active_sodium (list): New values of activation conductances of the sodium channels for peripheral neurons.
360
        @param[in] next_inactive_sodium (list): New values of inactivaton conductances of the sodium channels for peripheral neurons.
361
        @param[in] next_active_potassium (list): New values of activation conductances of the potassium channel for peripheral neurons.
362
        
363
        """
364
        
365
        self._membrane_potential = next_membrane[:];
366
        self._active_cond_sodium = next_active_sodium[:];
367
        self._inactive_cond_sodium = next_inactive_sodium[:];
368
        self._active_cond_potassium = next_active_potassium[:];
369
        
370
        for index in range(0, self._num_osc):
371
            if (self._pulse_generation[index] is False):
372
                if (self._membrane_potential[index] > 0.0):
373
                    self._pulse_generation[index] = True;
374
                    self._pulse_generation_time[index].append(t);
375
            else:
376
                if (self._membrane_potential[index] < 0.0):
377
                    self._pulse_generation[index] = False;
378
            
379
            # Update connection from CN2 to PN
380
            if (self._link_weight3[index] == 0.0):
381
                if ( (self._membrane_potential[index] > self._params.threshold) and (self._membrane_potential[index] > self._params.threshold) ):
382
                    self._link_pulse_counter[index] += step;
383
                
384
                    if (self._link_pulse_counter[index] >= 1 / self._params.eps):
385
                        self._link_weight3[index] = self._params.w3;
386
                        self._link_activation_time[index] = t;
387
            else:
388
                if ( not ((self._link_activation_time[index] < t) and (t < self._link_activation_time[index] + self._params.deltah)) ):
389
                    self._link_weight3[index] = 0.0;
390
                    self._link_pulse_counter[index] = 0.0;
391
    
392
    
393
    def __update_central_neurons(self, t, next_cn_membrane, next_cn_active_sodium, next_cn_inactive_sodium, next_cn_active_potassium):
394
        """!
395
        @brief Update of central neurons in line with new values of current in channels.
396
        
397
        @param[in] t (doubles): Current time of simulation.
398
        @param[in] next_membrane (list): New values of membrane potentials for central neurons.
399
        @Param[in] next_active_sodium (list): New values of activation conductances of the sodium channels for central neurons.
400
        @param[in] next_inactive_sodium (list): New values of inactivaton conductances of the sodium channels for central neurons.
401
        @param[in] next_active_potassium (list): New values of activation conductances of the potassium channel for central neurons.
402
        
403
        """
404
        
405
        for index in range(0, len(self._central_element)):
406
            self._central_element[index].membrane_potential = next_cn_membrane[index];
407
            self._central_element[index].active_cond_sodium = next_cn_active_sodium[index];
408
            self._central_element[index].inactive_cond_sodium = next_cn_inactive_sodium[index];
409
            self._central_element[index].active_cond_potassium = next_cn_active_potassium[index];
410
            
411
            if (self._central_element[index].pulse_generation is False):
412
                if (self._central_element[index].membrane_potential > 0.0):
413
                    self._central_element[index].pulse_generation = True;
414
                    self._central_element[index].pulse_generation_time.append(t);
415
            else:
416
                if (self._central_element[index].membrane_potential < 0.0):
417
                    self._central_element[index].pulse_generation = False;
418
    
419
    
420
    def hnn_state(self, inputs, t, argv):
421
        """!
422
        @brief Returns new values of excitatory and inhibitory parts of oscillator and potential of oscillator.
423
        
424
        @param[in] inputs (list): States of oscillator for integration [v, m, h, n] (see description below).
425
        @param[in] t (double): Current time of simulation.
426
        @param[in] argv (tuple): Extra arguments that are not used for integration - index of oscillator.
427
        
428
        @return (list) new values of oscillator [v, m, h, n], where:
429
                v - membrane potantial of oscillator,
430
                m - activation conductance of the sodium channel,
431
                h - inactication conductance of the sodium channel,
432
                n - activation conductance of the potassium channel.
433
        
434
        """
435
        
436
        index = argv;
437
        
438
        v = inputs[0]; # membrane potential (v).
439
        m = inputs[1]; # activation conductance of the sodium channel (m).
440
        h = inputs[2]; # inactivaton conductance of the sodium channel (h).
441
        n = inputs[3]; # activation conductance of the potassium channel (n).
442
        
443
        # Calculate ion current
444
        # gNa * m[i]^3 * h * (v[i] - vNa) + gK * n[i]^4 * (v[i] - vK) + gL  (v[i] - vL)
445
        active_sodium_part = self._params.gNa * (m ** 3) * h * (v - self._params.vNa);
446
        inactive_sodium_part = self._params.gK * (n ** 4) * (v - self._params.vK);
447
        active_potassium_part = self._params.gL * (v - self._params.vL);
448
        
449
        Iion = active_sodium_part + inactive_sodium_part + active_potassium_part;
450
        
451
        Iext = 0.0;
452
        Isyn = 0.0;
453
        if (index < self._num_osc): 
454
            # PN - peripheral neuron - calculation of external current and synaptic current.
455
            Iext = self._stimulus[index] * self._noise[index];    # probably noise can be pre-defined for reducting compexity            
456
            
457
            memory_impact1 = 0.0;
458
            for i in range(0, len(self._central_element[0].pulse_generation_time)):
459
                # TODO: alfa function shouldn't be calculated here (long procedure)
460
                memory_impact1 += self.__alfa_function(t - self._central_element[0].pulse_generation_time[i], self._params.alfa_inhibitory, self._params.betta_inhibitory);
461
            
462
            memory_impact2 = 0.0;
463
            for i in range(0, len(self._central_element[1].pulse_generation_time)):
464
                # TODO: alfa function shouldn't be calculated here (long procedure)
465
                memory_impact2 += self.__alfa_function(t - self._central_element[1].pulse_generation_time[i], self._params.alfa_inhibitory, self._params.betta_inhibitory);        
466
    
467
            Isyn = self._params.w2 * (v - self._params.Vsyninh) * memory_impact1 + self._link_weight3[index] * (v - self._params.Vsyninh) * memory_impact2;            
468
        else:
469
            # CN - central element.
470
            central_index = index - self._num_osc;
471
            if (central_index == 0):
472
                Iext = self._params.Icn1;   # CN1
473
                
474
                memory_impact = 0.0;
475
                for index_oscillator in range(0, self._num_osc):
476
                    for index_generation in range(0, len(self._pulse_generation_time[index_oscillator])):
477
                        # TODO: alfa function shouldn't be calculated here (long procedure)
478
                        memory_impact += self.__alfa_function(t - self._pulse_generation_time[index_oscillator][index_generation], self._params.alfa_excitatory, self._params.betta_excitatory);
479
                 
480
                Isyn = self._params.w1 * (v - self._params.Vsynexc) * memory_impact;
481
                
482
            elif (central_index == 1):
483
                Iext = self._params.Icn2;   # CN2
484
                Isyn = 0.0;
485
                
486
            else:
487
                assert 0;
488
        
489
        
490
        # Membrane potential
491
        dv = -Iion + Iext - Isyn;
492
        
493
        # Calculate variables
494
        potential = v - self._params.vRest;
495
        am = (2.5 - 0.1 * potential) / (math.exp(2.5 - 0.1 * potential) - 1.0);
496
        ah = 0.07 * math.exp(-potential / 20.0);
497
        an = (0.1 - 0.01 * potential) / (math.exp(1.0 - 0.1 * potential) - 1.0);
498
        
499
        bm = 4.0 * math.exp(-potential / 18.0);
500
        bh = 1.0 / (math.exp(3.0 - 0.1 * potential) + 1.0);
501
        bn = 0.125 * math.exp(-potential / 80.0);
502
        
503
        dm = am * (1.0 - m) - bm * m;
504
        dh = ah * (1.0 - h) - bh * h;
505
        dn = an * (1.0 - n) - bn * n;
506
        
507
        return [dv, dm, dh, dn];
508
        
509
        
510
    def allocate_sync_ensembles(self, tolerance = 0.1):
511
        """!
512
        @brief Allocates clusters in line with ensembles of synchronous oscillators where each. Synchronous ensemble corresponds to only one cluster.
513
        
514
        @param[in] tolerance (double): maximum error for allocation of synchronous ensemble oscillators.
515
        
516
        @return (list) Grours (lists) of indexes of synchronous oscillators. For example [ [index_osc1, index_osc3], [index_osc2], [index_osc4, index_osc5] ].
517
        
518
        """
519
        
520
        ignore = set();
521
        
522
        ignore.add(self._num_osc);
523
        ignore.add(self._num_osc + 1);
524
        
525
        return allocate_sync_ensembles(self._membrane_dynamic_pointer, tolerance, 20.0, ignore);
526
    
527
    
528
    def __alfa_function(self, time, alfa, betta):
529
        """!
530
        @brief Calculates value of alfa-function for difference between spike generation time and current simulation time.
531
        
532
        @param[in] time (double): Difference between last spike generation time and current time.
533
        @param[in] alfa (double): Alfa parameter for alfa-function.
534
        @param[in] betta (double): Betta parameter for alfa-function.
535
        
536
        @return (double) Value of alfa-function.
537
        
538
        """
539
        
540
        return alfa * time * math.exp(-betta * time);
541