def define_lif(): tau = 10. Vr = 0. Vth = 10. noise = 0. ref = 0. ST = bp.types.NeuState({'V': 0, 'sp_t': -1e7, 'spike': 0., 'input': 0.}, ) @bp.integrate def int_f(V, t, Isyn): return (-V + Vr + Isyn) / tau, noise / tau def update(ST, _t): if _t - ST['sp_t'] > ref: V = int_f(ST['V'], _t, ST['input']) if V >= Vth: V = Vr ST['sp_t'] = _t ST['spike'] = True ST['V'] = V else: ST['spike'] = False ST['input'] = 0. return bp.NeuType(name='LIF', ST=ST, steps=update, mode='scalar')
def get_model(a=1., b=3., c=1., d=5., s=4., x_r=-1.6, r=0.001, Vth=1.9): state = bp.types.NeuState({ 'x': 0., 'y': 0., 'z': 0., 'spike': 0., 'input': 0. }) @bp.integrate def int_x(x, t, y, z, Isyn): return y - a * x**3 + b * x * x - z + Isyn @bp.integrate def int_y(y, t, x): return c - d * x * x - y @bp.integrate def int_z(z, t, x): return r * (s * (x - x_r) - z) def update(ST, _t): ST['y'] = int_y(ST['y'], _t, ST['x']) ST['z'] = int_z(ST['z'], _t, ST['x']) x = int_x(ST['x'], _t, ST['y'], ST['z'], ST['input']) ST['spike'] = np.logical_and(x >= Vth, ST['x'] < Vth) ST['x'] = x ST['input'] = 0. return bp.NeuType(name='Hindmarsh_Rose_model', ST=state, steps=update)
def get_fr_neu(): ST = bp.types.NeuState({'r': 0, 'nothing': 0.}) def update(ST, _t): ST['nothing'] = 0. return bp.NeuType(name='fr_zombie_neuron', ST=ST, steps=update, mode='scalar')
def rate_neuron(): ST = bp.types.NeuState(['r', 'input']) def g(r, I): r += I return r def update(ST): ST['r'] = g(ST['r'], ST['input']) def reset(ST): ST['input'] = 0. return bp.NeuType(name='rate', steps=[update, reset], ST=ST, mode='vector')
def get_model(a=0.7, b=0.8, tau=12.5, Vth=1.9): state = bp.types.NeuState({'v': 0., 'w': 1., 'spike': 0., 'input': 0.}) @bp.integrate def int_w(w, t, v): return (v + a - b * w) / tau @bp.integrate def int_v(v, t, w, Iext): return v - v * v * v / 3 - w + Iext def update(ST, _t): ST['w'] = int_w(ST['w'], _t, ST['v']) v = int_v(ST['v'], _t, ST['w'], ST['input']) ST['spike'] = np.logical_and(v >= Vth, ST['v'] < Vth) ST['v'] = v ST['input'] = 0. return bp.NeuType(name='FitzHugh_Nagumo', ST=state, steps=update)
def define_model(): """ A 1D model for codimension 2 bifurcation testing. .. math:: \dot{x} = \mu+ \lambda x - x**3 """ lambd = 0 mu = 0 @bp.integrate def int_x(x, t): dxdt = mu + lambd * x - x**3 return dxdt def update(ST, _t): ST['x'] = int_x(ST['x'], _t) return bp.NeuType(name="dummy_model", ST=bp.types.NeuState({'x': 0.}), steps=update)
def define_model(): """ A dummy 1D test neuronal model. .. math:: \dot{x} = x**3-x + I """ @bp.integrate def int_x(x, t, input): dxdt = x**3 - x + input return dxdt def update(ST, _t): ST['x'] = int_x(ST['x'], _t, ST['input']) ST['input'] = 0. return bp.NeuType(name="dummy_model", ST=bp.types.NeuState({ 'x': -10, 'input': 0. }), steps=update)
def get_GeneralizedIF(V_rest=-70., V_reset=-70., V_th_inf=-50., V_th_reset=-60., R=20., C=1., tau=20., a=0., b=0.01, k1=0.2, k2=0.02, R1=0., R2=1., A1=0., A2=0., noise=0., mode='scalar'): """ Generalized Integrate-and-Fire model (GeneralizedIF model). .. math:: &\\frac{d I_j}{d t} = - k_j I_j &\\frac{d V}{d t} = ( - (V - V_{rest}) + R\\sum_{j}I_j + RI) / \\tau &\\frac{d V_{th}}{d t} = a(V - V_{rest}) - b(V_{th} - V_{th\\infty}) When V meet Vth, Generalized IF neuron fire: .. math:: &I_j \\leftarrow R_j I_j + A_j &V \\leftarrow V_{reset} &V_{th} \\leftarrow max(V_{th_{reset}}, V_{th}) Note that I_j refers to arbitrary number of internal currents. ST refers to neuron state, members of ST are listed below: =============== ================= ============================================== **Member name** **Initial Value** **Explanation** --------------- ----------------- ---------------------------------------------- V -70. Membrane potential. input 0. External and synaptic input current. spike 0. Flag to mark whether the neuron is spiking. Can be seen as bool. V_th -50. Spiking threshold potential. I1 0. Internal current 1. I2 0. Internal current 2. t_last_spike -1e7 Last spike time stamp. =============== ================= ============================================== Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: V_rest (float): Resting potential. V_reset (float): Reset potential after spike. V_th_inf (float): Target value of threshold potential V_th updating. V_th_reset (float): Free parameter, should be larger than V_reset. R (float): Membrane resistance. C (float): Membrane capacitance. tau (float): Membrane time constant. Compute by R * C. a (float): Coefficient describes the dependence of V_th on membrane potential. b (float): Coefficient describes V_th update. k1 (float): Constant pf I1. k2 (float): Constant of I2. R1 (float): Free parameter. R2 (float): Free parameter. A1 (float): Free parameter. A2 (float): Free parameter. noise (float): noise. mode (str): Data structure of ST members. Returns: bp.Neutype: return description of Generalized IF model. References: .. [1] Mihalaş, Ştefan, and Ernst Niebur. "A generalized linear integrate-and-fire neural model produces diverse spiking behaviors." Neural computation 21.3 (2009): 704-718. """ ST = bp.types.NeuState({ 'V': -70., 'input': 0., 'spike': 0., 'V_th': -50., 'I1': 0., 'I2': 0., 't_last_spike': -1e7 }) @bp.integrate def int_I1(I1, _t): return -k1 * I1 @bp.integrate def int_I2(I2, _t): return -k2 * I2 @bp.integrate def int_V_th(V_th, _t, V): return a * (V - V_rest) - b * (V_th - V_th_inf) @bp.integrate def int_V(V, _t, I_ext, I1, I2): return (-(V - V_rest) + R * I_ext + R * I1 + R * I2) / tau def update(ST, _t): ST['spike'] = 0 I1 = int_I1(ST['I1'], _t) I2 = int_I2(ST['I2'], _t) V_th = int_V_th(ST['V_th'], _t, ST['V']) V = int_V(ST['V'], _t, ST['input'], ST['I1'], ST['I2']) if V > ST['V_th']: V = V_reset I1 = R1 * I1 + A1 I2 = R2 * I2 + A2 V_th = max(V_th, V_th_reset) ST['spike'] = 1 ST['t_last_spike'] = _t ST['I1'] = I1 ST['I2'] = I2 ST['V_th'] = V_th ST['V'] = V def reset(ST): ST['input'] = 0. if mode == 'scalar': return bp.NeuType(name='GeneralizedIF_neuron', ST=ST, steps=(update, reset), mode=mode) elif mode == 'vector': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode == 'matrix': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) else: raise ValueError("BrainPy does not support mode '%s'." % (mode))
def define_hh(E_Na=50., g_Na=120., E_K=-77., g_K=36., E_Leak=-54.387, g_Leak=0.03, C=1.0, Vth=20., Iext=10.): ST = bp.types.NeuState( { 'V': -65., 'm': 0., 'h': 0., 'n': 0., 'sp': 0., 'inp': 0. }, help='Hodgkin–Huxley neuron state.\n' '"V" denotes membrane potential.\n' '"n" denotes potassium channel activation probability.\n' '"m" denotes sodium channel activation probability.\n' '"h" denotes sodium channel inactivation probability.\n' '"sp" denotes spiking state.\n' '"inp" denotes synaptic input.\n') @bp.integrate def int_m(m, t, V): alpha = 0.1 * (V + 40) / (1 - math.exp(-(V + 40) / 10)) beta = 4.0 * math.exp(-(V + 65) / 18) return alpha * (1 - m) - beta * m @bp.integrate def int_h(h, t, V): alpha = 0.07 * math.exp(-(V + 65) / 20.) beta = 1 / (1 + math.exp(-(V + 35) / 10)) return alpha * (1 - h) - beta * h @bp.integrate def int_n(n, t, V): alpha = 0.01 * (V + 55) / (1 - math.exp(-(V + 55) / 10)) beta = 0.125 * math.exp(-(V + 65) / 80) return alpha * (1 - n) - beta * n @bp.integrate def int_V(V, t, m, h, n, Isyn): INa = g_Na * m**3 * h * (V - E_Na) IK = g_K * n**4 * (V - E_K) IL = g_Leak * (V - E_Leak) dvdt = (-INa - IK - IL + Isyn) / C return dvdt def update(ST, _t): m = int_m(ST['m'], _t, ST['V']) h = int_h(ST['h'], _t, ST['V']) n = int_n(ST['n'], _t, ST['V']) V = int_V(ST['V'], _t, m, h, n, ST['inp']) sp = (ST['V'] < Vth) and (V >= Vth) ST['sp'] = sp ST['V'] = V ST['m'] = m ST['h'] = h ST['n'] = n ST['inp'] = Iext return bp.NeuType(name='HH_neuron', ST=ST, steps=update, mode='scalar')
def get_Izhikevich(a=0.02, b=0.20, c=-65., d=8., t_refractory=0., noise=0., V_th=30., type=None, mode='scalar'): ''' The Izhikevich neuron model. .. math :: \\frac{d V}{d t} &= 0.04 V^{2}+5 V+140-u+I \\frac{d u}{d t} &=a(b V-u) .. math :: \\text{if} v \\geq 30 \\text{mV}, \\text{then} \\begin{cases} v \\leftarrow c \\\\ u \\leftarrow u+d \\end{cases} ST refers to neuron state, members of ST are listed below: =============== ======== ================== =========================================== **Member name** **Type** **Initial values** **Explanation** --------------- -------- ------------------ ------------------------------------------- V float -65 Membrane potential. u float 1 Recovery variable. input float 0 External and synaptic input current. spike float 0 Flag to mark whether the neuron is spiking. Can be seen as bool. t_last_spike float -1e7 Last spike time stamp. =============== ======== ================== =========================================== Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: type (str): The neuron spiking type. a (float): It determines the time scale of the recovery variable :math:`u`. b (float): It describes the sensitivity of the recovery variable :math:`u` to the sub-threshold fluctuations of the membrane potential :math:`v`. c (float): It describes the after-spike reset value of the membrane potential :math:`v` caused by the fast high-threshold :math:`K^{+}` conductance. d (float): It describes after-spike reset of the recovery variable :math:`u` caused by slow high-threshold :math:`Na^{+}` and :math:`K^{+}` conductance. t_refractory (float): Refractory period length. [ms] noise(float): The noise fluctuation. V_th (float): The membrane potential threshold. mode (str): Data structure of ST members. Returns: bp.Neutype: return description of Izhikevich model. References: .. [1] Izhikevich, Eugene M. "Simple model of spiking neurons." IEEE Transactions on neural networks 14.6 (2003): 1569-1572. .. [2] Izhikevich, Eugene M. "Which model to use for cortical spiking neurons?." IEEE transactions on neural networks 15.5 (2004): 1063-1070. Parameters of spiking types: =========================== ======= ======= ======= ======= **Type** **a** **b** **c** **d** --------------------------- ------- ------- ------- ------- Regular Spiking 0.02 0.20 -65 8 Intrinsically Bursting 0.02 0.20 -55 4 Chattering 0.02 0.20 -50 2 Fast Spiking 0.10 0.20 -65 2 Thalamo-cortical 0.02 0.25 -65 0.05 Resonator 0.10 0.26 -65 2 Low-threshold Spiking 0.02 0.25 -65 2 tonic spiking 0.02 0.40 -65 2 phasic spiking 0.02 0.25 -65 6 tonic bursting 0.02 0.20 -50 2 phasic bursting 0.02 0.25 -55 0.05 mixed mode 0.02 0.20 -55 4 spike frequency adaptation 0.01 0.20 -65 8 Class 1 0.02 -0.1 -55 6 Class 2 0.20 0.26 -65 0 spike latency 0.02 0.20 -65 6 subthreshold oscillation 0.05 0.26 -60 0 resonator 0.10 0.26 -60 -1 integrator 0.02 -0.1 -55 6 rebound spike 0.03 0.25 -60 4 rebound burst 0.03 0.25 -52 0 threshold variability 0.03 0.25 -60 4 bistability 1.00 1.50 -60 0 depolarizing afterpotential 1.00 0.20 -60 -21 accommodation 0.02 1.00 -55 4 inhibition-induced spiking -0.02 -1.00 -60 8 inhibition-induced bursting -0.026 -1.00 -45 0 =========================== ======= ======= ======= ======= ''' ST = bp.types.NeuState({ 'V': -65., 'u': 1., 'input': 0., 'spike': 0., 't_last_spike': -1e7 }) if type in ['tonic', 'tonic spiking']: a, b, c, d = [0.02, 0.40, -65.0, 2.0] elif type in ['phasic', 'phasic spiking']: a, b, c, d = [0.02, 0.25, -65.0, 6.0] elif type in ['tonic bursting']: a, b, c, d = [0.02, 0.20, -50.0, 2.0] elif type in ['phasic bursting']: a, b, c, d = [0.02, 0.25, -55.0, 0.05] elif type in ['mixed mode']: a, b, c, d = [0.02, 0.20, -55.0, 4.0] elif type in ['SFA', 'spike frequency adaptation']: a, b, c, d = [0.01, 0.20, -65.0, 8.0] elif type in ['Class 1', 'class 1']: a, b, c, d = [0.02, -0.1, -55.0, 6.0] elif type in ['Class 2', 'class 2']: a, b, c, d = [0.20, 0.26, -65.0, 0.0] elif type in [ 'spike latency', ]: a, b, c, d = [0.02, 0.20, -65.0, 6.0] elif type in ['subthreshold oscillation']: a, b, c, d = [0.05, 0.26, -60.0, 0.0] elif type in [ 'resonator', ]: a, b, c, d = [0.10, 0.26, -60.0, -1.0] elif type in [ 'integrator', ]: a, b, c, d = [0.02, -0.1, -55.0, 6.0] elif type in [ 'rebound spike', ]: a, b, c, d = [0.03, 0.25, -60.0, 4.0] elif type in [ 'rebound burst', ]: a, b, c, d = [0.03, 0.25, -52.0, 0.0] elif type in [ 'threshold variability', ]: a, b, c, d = [0.03, 0.25, -60.0, 4.0] elif type in [ 'bistability', ]: a, b, c, d = [1.00, 1.50, -60.0, 0.0] elif type in ['DAP', 'depolarizing afterpotential']: a, b, c, d = [1.00, 0.20, -60.0, -21.0] elif type in [ 'accommodation', ]: a, b, c, d = [0.02, 1.00, -55.0, 4.0] elif type in [ 'inhibition-induced spiking', ]: a, b, c, d = [-0.02, -1.00, -60.0, 8.0] elif type in [ 'inhibition-induced bursting', ]: a, b, c, d = [-0.026, -1.00, -45.0, 0] # Neurons elif type in ['Regular Spiking', 'RS']: a, b, c, d = [0.02, 0.2, -65, 8] elif type in ['Intrinsically Bursting', 'IB']: a, b, c, d = [0.02, 0.2, -55, 4] elif type in ['Chattering', 'CH']: a, b, c, d = [0.02, 0.2, -50, 2] elif type in ['Fast Spiking', 'FS']: a, b, c, d = [0.1, 0.2, -65, 2] elif type in ['Thalamo-cortical', 'TC']: a, b, c, d = [0.02, 0.25, -65, 0.05] elif type in ['Resonator', 'RZ']: a, b, c, d = [0.1, 0.26, -65, 2] elif type in ['Low-threshold Spiking', 'LTS']: a, b, c, d = [0.02, 0.25, -65, 2] @bp.integrate def int_u(u, t, V): return a * (b * V - u) @bp.integrate def int_V(V, t, u, Isyn): dfdt = 0.04 * V * V + 5 * V + 140 - u + Isyn dgdt = noise return dfdt, dgdt if np.any(t_refractory > 0.): def update(ST, _t): if (_t - ST['t_last_spike']) > t_refractory: V = int_V(ST['V'], _t, ST['u'], ST['input']) u = int_u(ST['u'], _t, ST['V']) if V >= V_th: V = c u += d ST['t_last_spike'] = _t ST['spike'] = True ST['V'] = V ST['u'] = u else: def update(ST, _t): V = int_V(ST['V'], _t, ST['u'], ST['input']) u = int_u(ST['u'], _t, ST['V']) if V >= V_th: V = c u += d ST['t_last_spike'] = _t ST['spike'] = True ST['V'] = V ST['u'] = u def reset(ST): ST['input'] = 0. if mode == 'scalar': return bp.NeuType(name='Izhikevich_neuron', ST=ST, steps=(update, reset), mode=mode) elif mode == 'vector': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode == 'matrix': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) else: raise ValueError("BrainPy does not support mode '%s'." % (mode))
def update(ST, _t): V = int_f(ST['V'], _t, ST['input']) if V >= V_threshld: ST['spike'] = 1. V = V_reset else: ST['spike'] = 0. ST['V'] = V ST['input'] = 0. neu = bp.NeuType(name='LIF', ST=bp.types.NeuState({ 'V': 0, 'spike': 0., 'input': 0. }), steps=update, mode='scalar') # ------- # synapse # ------- tau_decay = 2. JE = 1 / np.sqrt(prob * num_exc) JI = 1 / np.sqrt(prob * num_inh) @bp.integrate def ints(s, t):
def get_HindmarshRose(a=1., b=3., c=1., d=5., r=0.01, s=4., V_rest=-1.6, mode='scalar'): """ Hindmarsh-Rose neuron model. .. math:: &\\frac{d V}{d t} = y - a V^3 + b V^2 - z + I &\\frac{d y}{d t} = c - d V^2 - y &\\frac{d z}{d t} = r (s (V - V_{rest}) - z) =============== ================= ===================================== **Member name** **Initial Value** **Explanation** --------------- ----------------- ------------------------------------- V -1.6 Membrane potential. y -10. Gating variable. z 0. Gating variable. input 0. External and synaptic input current. =============== ================= ===================================== Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: a (float): Model parameter. Fixed to a value best fit neuron activity. b (float): Model parameter. Allows the model to switch between bursting and spiking, controls the spiking frequency. c (float): Model parameter. Fixed to a value best fit neuron activity. d (float): Model parameter. Fixed to a value best fit neuron activity. r (float): Model parameter. Controls slow variable z's variation speed. Governs spiking frequency when spiking, and affects the number of spikes per burst when bursting. s (float): Model parameter. Governs adaption. V_rest (float): Membrane resting potential. mode (str): Data structure of ST members. Returns: bp.NeuType: return description of Hindmarsh-Rose neuron model. References: .. [1] Hindmarsh, James L., and R. M. Rose. "A model of neuronal bursting using three coupled first order differential equations." Proceedings of the Royal society of London. Series B. Biological sciences 221.1222 (1984): 87-102. .. [2] Storace, Marco, Daniele Linaro, and Enno de Lange. "The Hindmarsh–Rose neuron model: bifurcation analysis and piecewise-linear approximations." Chaos: An Interdisciplinary Journal of Nonlinear Science 18.3 (2008): 033128. """ ST = bp.types.NeuState({'V': -1.6, 'y': -10., 'z': 0., 'input': 0}) @bp.integrate def int_V(V, _t, y, z, I_ext): return y - a * V * V * V + b * V * V - z + I_ext @bp.integrate def int_y(y, _t, V): return c - d * V * V - y @bp.integrate def int_z(z, _t, V): return r * (s * (V - V_rest) - z) def update(ST, _t): V = int_V(ST['V'], _t, ST['y'], ST['z'], ST['input']) y = int_y(ST['y'], _t, ST['V']) z = int_z(ST['z'], _t, ST['V']) ST['V'] = V ST['y'] = y ST['z'] = z def reset(ST): ST['input'] = 0 if mode == 'scalar': return bp.NeuType(name="HindmarshRose_neuron", ST=ST, steps=(update, reset), mode=mode) elif mode == 'vector': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode == 'matrix': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) else: raise ValueError("BrainPy does not support mode '%s'." % (mode))
ST['ge'] = int_ge(ST['ge'], _t) ST['gi'] = int_gi(ST['gi'], _t) ST['spike'] = 0. if (_t - ST['sp_t']) > ref: V = int_V(ST['V'], _t, ST['ge'], ST['gi']) ST['spike'] = 0. if V >= Vt: ST['V'] = Vr ST['spike'] = 1. ST['sp_t'] = _t else: ST['V'] = V neuron = bp.NeuType(name='COBA', ST=neu_ST, steps=neu_update, mode='scalar') def update1(pre, post, pre2post): for pre_id in range(len(pre2post)): if pre['spike'][pre_id] > 0.: post_ids = pre2post[pre_id] for i in post_ids: post['ge'][i] += we exc_syn = bp.SynType('exc_syn', steps=update1, ST=bp.types.SynState([]), mode='vector')
def get_ResonateandFire(b=-1., omega=10., V_th=1., V_reset=1., x_reset=0., mode='scalar'): """Resonate-and-fire neuron model. .. math:: \\frac{d x}{d t} = b x - \\omega y \\frac{d y}{d t} = \\omega x + b y When spike, .. math:: x \\leftarrow 0 y \\leftarrow 1 Or we can write the equations in equivalent complex form: .. math:: \\frac{d z}{d t} = (b + i \\omega) z z = x + i y \\in \\mathbb{C} When spike, .. math:: z \\leftarrow i ST refers to neuron state, members of ST are listed below: =============== ================= ============================================== **Member name** **Initial Value** **Explanation** --------------- ----------------- ---------------------------------------------- V 0. Voltage-like variable. x 0. Current-like variable. input 0. External and synaptic input current. spike 0. Flag to mark whether the neuron is spiking. Can be seen as bool. t_last_spike -1e7 Last spike time stamp. =============== ================= ============================================== Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: b (float): Parameter, refers to the rate of attrsction to the rest. omega (float): Parameter. refers to the frequency of the oscillations. V_th (float): Threshold potential of spike. V_reset (float): Reset value for voltage-like variable after spike. x_reset (float): Reset value for current-like variable after spike. mode (str): Data structure of ST members. Returns: bp.Neutype: return description of RF model. References: .. [1] Izhikevich, Eugene M. "Resonate-and-fire neurons." Neural networks 14.6-7 (2001): 883-894. """ ST = bp.types.NeuState({ 'V': 0., 'x': 0., 'input': 0., 'spike': 0., 't_last_spike': -1e7 }) @bp.integrate def int_x(x, _t, V): #input--internal return b * x - omega * V @bp.integrate def int_V(V, _t, x): #V return omega * x + b * V def update(ST, _t): # update variables ST['spike'] = 0 x = ST['x'] x += ST['input'] V = ST['V'] x = int_x(x, _t, V) V = int_V(V, _t, x) if V > V_th: V = V_reset x = x_reset ST['spike'] = 1 ST['t_last_spike'] = _t ST['x'] = x ST['V'] = V def reset(ST): ST['input'] = 0. if mode == 'scalar': return bp.NeuType(name='RF_neuron', ST=ST, steps=(update, reset), mode=mode) elif mode == 'vector': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode == 'matrix': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) else: raise ValueError("BrainPy does not support mode '%s'." % (mode))
def get_QuaIF(V_rest=-65., V_reset=-68., V_th=-30., a_0 = .07, V_c = -50, R=1., C=10., tau=10., t_refractory=0., noise=0., mode='scalar'): """Quadratic Integrate-and-Fire neuron model. .. math:: \\tau \\frac{d V}{d t}=a_0(V-V_{rest})(V-V_c) + RI(t) where the parameters are taken to be :math:`a_0` =0.07, and :math:`V_c = -50 mV` (Latham et al., 2000 [2]_). ST refers to neuron state, members of ST are listed below: =============== ================= ========================================================= **Member name** **Initial Value** **Explanation** --------------- ----------------- --------------------------------------------------------- V 0. Membrane potential. input 0. External and synaptic input current. spike 0. Flag to mark whether the neuron is spiking. Can be seen as bool. refractory 0. Flag to mark whether the neuron is in refractory period. Can be seen as bool. t_last_spike -1e7 Last spike time stamp. =============== ================= ========================================================= Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: a_0 (float): Coefficient describes membrane potential update. Larger than 0. V_c (float): Critical voltage for spike initiation. Must be larger than V_rest. V_rest (float): Resting potential. V_reset (float): Reset potential after spike. V_th (float): Threshold potential of spike. R (float): Membrane resistance. C (float): Membrane capacitance. tau (float): Membrane time constant. Compute by R * C. t_refractory (int): Refractory period length.(ms) noise (float): noise. Returns: bp.Neutype: return description of QuaIF model. References: .. [1] Gerstner, Wulfram, et al. Neuronal dynamics: From single neurons to networks and models of cognition. Cambridge University Press, 2014. .. [2] P. E. Latham, B.J. Richmond, P. Nelson and S. Nirenberg (2000) Intrinsic dynamics in neuronal networks. I. Theory. J. Neurophysiology 83, pp. 808–827. """ if mode == 'vector': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode == 'matrix': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode != 'scalar': raise ValueError("BrainPy does not support mode '%s'." % (mode)) ST = bp.types.NeuState( {'V': 0, 'input': 0, 'spike': 0, 'refractory': 0, 't_last_spike': -1e7} ) @bp.integrate def int_V(V, _t, I_ext): return (a_0* (V - V_rest)*(V-V_c) + R * I_ext) / tau, noise / tau def update(ST, _t): ST['spike'] = 0 if _t - ST['t_last_spike'] <= t_refractory: ST['refractory'] = 1. else: ST['refractory'] = 0. V = int_V(ST['V'], _t, ST['input']) if V >= V_th: V = V_reset ST['spike'] = 1 ST['t_last_spike'] = _t ST['V'] = V def reset(ST): ST['input'] = 0. return bp.NeuType(name='QuaIF_neuron', ST=ST, steps=(update, reset), mode=mode)
def get_Izhikevich(mode=None): state = bp.types.NeuState({'V': 0., 'u': 1., 'sp': 0., 'input': 0.}) global a, b, c, d if mode in ['tonic', 'tonic spiking']: a, b, c, d = [0.02, 0.40, -65.0, 2.0] elif mode in ['phasic', 'phasic spiking']: a, b, c, d = [0.02, 0.25, -65.0, 6.0] elif mode in ['tonic bursting']: a, b, c, d = [0.02, 0.20, -50.0, 2.0] elif mode in ['phasic bursting']: a, b, c, d = [0.02, 0.25, -55.0, 0.05] elif mode in ['mixed mode']: a, b, c, d = [0.02, 0.20, -55.0, 4.0] elif mode in ['SFA', 'spike frequency adaptation']: a, b, c, d = [0.01, 0.20, -65.0, 8.0] elif mode in ['Class 1', 'class 1']: a, b, c, d = [0.02, -0.1, -55.0, 6.0] elif mode in ['Class 2', 'class 2']: a, b, c, d = [0.20, 0.26, -65.0, 0.0] elif mode in ['spike latency', ]: a, b, c, d = [0.02, 0.20, -65.0, 6.0] elif mode in ['subthreshold oscillation', ]: a, b, c, d = [0.05, 0.26, -60.0, 0.0] elif mode in ['resonator', ]: a, b, c, d = [0.10, 0.26, -60.0, -1.0] elif mode in ['integrator', ]: a, b, c, d = [0.02, -0.1, -55.0, 6.0] elif mode in ['rebound spike', ]: a, b, c, d = [0.03, 0.25, -60.0, 4.0] elif mode in ['rebound burst', ]: a, b, c, d = [0.03, 0.25, -52.0, 0.0] elif mode in ['threshold variability', ]: a, b, c, d = [0.03, 0.25, -60.0, 4.0] elif mode in ['bistability', ]: a, b, c, d = [1.00, 1.50, -60.0, 0.0] elif mode in ['DAP', 'depolarizing afterpotential']: a, b, c, d = [1.00, 0.20, -60.0, -21.0] elif mode in ['accomodation', ]: a, b, c, d = [0.02, 1.00, -55.0, 4.0] elif mode in ['inhibition-induced spiking', ]: a, b, c, d = [-0.02, -1.00, -60.0, 8.0] elif mode in ['inhibition-induced bursting', ]: a, b, c, d = [-0.026, -1.00, -45.0, 0.0] @bp.integrate def int_u(u, t, V): return a * (b * V - u) @bp.integrate def int_V(V, t, u, Isyn): return 0.04 * V * V + 5 * V + 140 - u + Isyn def update(ST, _t): V = int_V(ST['V'], _t, ST['u'], ST['input']) u = int_u(ST['u'], _t, ST['V']) if V >= Vth: V = c u += d ST['sp'] = True ST['V'] = V ST['u'] = u ST['input'] = 0. return bp.NeuType(name='Izhikevich', ST=state, steps=update, mode='scalar')
r2 = 1.0 + k * rho * np.sum(r1) * dx r = r1 / r2 Irec = rho * np.dot(Jxx, r) * dx dudt = (-u + Irec + Iext) / tau return (dudt, ), r def neu_update(ST, _t, Jxx): ST['u'], ST['r'] = int_u(ST['u'], _t, Jxx, ST['input']) ST['input'] = 0. requires = {'Jxx': bp.types.Array(dim=2, help='Weight connection matrix.')} cann = bp.NeuType(name='CANN', steps=neu_update, ST=bp.types.NeuState(['x', 'u', 'r', 'input']), requires=requires) # connection # # ---------- # def make_conn(x): assert np.ndim(x) == 1 x_left = np.reshape(x, (len(x), 1)) x_right = np.repeat(x.reshape((1, -1)), len(x), axis=0) d = dist(x_left - x_right) jxx = J0 * np.exp(-0.5 * np.square(d / a)) / (np.sqrt(2 * np.pi) * a) return jxx
@bp.integrate def int_f(V, t, Isyn): return (-V + Isyn + 2 * np.sin(2 * np.pi * t / tau)) / tau def update(ST, _t): V = int_f(ST['V'], _t, ST['input']) spike = V >= Vth ST['spike'] = spike ST['V'] = np.where(spike, Vr, V) ST['input'] = 0. ST = bp.types.NeuState({'V': 0, 'spike': 0., 'input': 0.}) lif = bp.NeuType(name='LIF', ST=ST, steps=update) group = bp.NeuGroup(lif, geometry=2000, monitors=['spike']) inputs = np.linspace(2., 4., group.num) group.run(duration=10 * 1000., inputs=('input', inputs), report=True) idx = int(5 * 1000. / bp.profile.get_dt()) indices, times = bp.measure.raster_plot(group.mon.spike[idx:], group.mon.ts[idx:]) plt.plot((times % tau) / tau, inputs[indices], ',') plt.xlabel('Spike phase') plt.ylabel('Parameter (input)') plt.show()
def get_AdExIF(V_rest=-65., V_reset=-68., V_th=-30., V_T=-59.9, delta_T=3.48, a=1., b=1, R=1, C=10., tau=10., tau_w=30., t_refractory=0., noise=0., mode='scalar'): """Adaptive Exponential Integrate-and-Fire neuron model. .. math:: \\tau_m\\frac{d V}{d t}= - (V-V_{rest}) + \\Delta_T e^{\\frac{V-V_T}{\\Delta_T}} - R w + RI(t) \\tau_w \\frac{d w}{d t}=a(V-V_{rest}) - w + b \\tau_w \\sum \\delta (t-t^f) ST refers to neuron state, members of ST are listed below: =============== ================= ========================================================= **Member name** **Initial Value** **Explanation** --------------- ----------------- --------------------------------------------------------- V 0. Membrane potential. w 0. Adaptation current. input 0. External and synaptic input current. spike 0. Flag to mark whether the neuron is spiking. Can be seen as bool. refractory 0. Flag to mark whether the neuron is in refractory period. Can be seen as bool. t_last_spike -1e7 Last spike time stamp. =============== ================= ========================================================= Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: a (float): b (float): V_rest (float): Resting potential. V_reset (float): Reset potential after spike. V_th (float): Threshold potential of spike. V_T (float): Threshold potential of steady/non-steady. delta_T (float): Spike slope factor. R (float): Membrane resistance. C (float): Membrane capacitance. tau (float): Membrane time constant. Compute by R * C. tau_w (float): Time constant of the adaptation current. t_refractory (int): Refractory period length. noise (float): noise. Returns: bp.Neutype: return description of ExpIF model. References: .. [1] Fourcaud-Trocmé, Nicolas, et al. "How spike generation mechanisms determine the neuronal response to fluctuating inputs." Journal of Neuroscience 23.37 (2003): 11628-11640. """ ST = bp.types.NeuState({ 'V': 0, 'w': 0, 'input': 0, 'spike': 0, 'refractory': 0, 't_last_spike': -1e7 }) @bp.integrate def int_V(V, _t, w, I_ext): # integrate u(t) return (-(V - V_rest) + delta_T * np.exp( (V - V_T) / delta_T) - R * w + R * I_ext) / tau, noise / tau @bp.integrate def int_w(w, _t, V): return (a * (V - V_rest) - w) / tau_w, noise / tau_w def update(ST, _t): ST['spike'] = 0 ST['refractory'] = True if _t - ST[ 't_last_spike'] <= t_refractory else False if not ST['refractory']: w = int_w(ST['w'], _t, ST['V']) V = int_V(ST['V'], _t, w, ST['input']) if V >= V_th: V = V_reset w += b ST['spike'] = 1 ST['t_last_spike'] = _t ST['V'] = V ST['w'] = w def reset(ST): ST['input'] = 0. if mode == 'scalar': return bp.NeuType(name='AdExIF_neuron', ST=ST, steps=(update, reset), mode=mode) elif mode == 'vector': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode == 'matrix': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) else: raise ValueError("BrainPy does not support mode '%s'." % (mode))
def get_AdQuaIF(a=1, b=.1, a_0=.07, V_c=-50, V_rest=-65., V_reset=-68., V_th=-30., R=1., C=10., tau=10., tau_w=10., t_refractory=0., noise=0., mode='scalar'): """Adaptive Quadratic Integrate-and-Fire neuron model. .. math:: \\tau_m \\frac{d V}{d t}=a_0(V-V_{rest})(V-V_c) - R w + RI(t) \\tau_w \\frac{d w}{d t}=a(V-V_{rest}) - w + b \\tau_w \\sum \\delta (t-t^f) ST refers to neuron state, members of ST are listed below: =============== ================= ========================================================= **Member name** **Initial Value** **Explanation** --------------- ----------------- --------------------------------------------------------- V 0. Membrane potential. w 0. Adaptation current. input 0. External and synaptic input current. spike 0. Flag to mark whether the neuron is spiking. Can be seen as bool. refractory 0. Flag to mark whether the neuron is in refractory period. Can be seen as bool. t_last_spike -1e7 Last spike time stamp. =============== ================= ========================================================= Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: a (float): b (float): a_0 (float): Coefficient describes membrane potential update. Larger than 0. V_c (float): Critical voltage for spike initiation. Must be larger than V_rest. V_rest (float): Resting potential. V_reset (float): Reset potential after spike. V_th (float): Threshold potential of spike. R (float): Membrane resistance. C (float): Membrane capacitance. tau (float): Membrane time constant. Compute by R * C. tau_w (float): Time constant of the adaptation current. t_refractory (int): Refractory period length.(ms) noise (float): noise. Returns: bp.Neutype: return description of QuaIF model. References: .. [1] Gerstner, Wulfram, et al. Neuronal dynamics: From single neurons to networks and models of cognition. Cambridge University Press, 2014. """ if mode == 'vector': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode == 'matrix': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode != 'scalar': raise ValueError("BrainPy does not support mode '%s'." % (mode)) ST = bp.types.NeuState({ 'V': 0, 'w': 0, 'input': 0, 'spike': 0, 'refractory': 0, 't_last_spike': -1e7 }) @bp.integrate def int_V(V, _t, w, I_ext): return (a_0 * (V - V_rest) * (V - V_c) - R * w + R * I_ext) / tau, noise / tau @bp.integrate def int_w(w, _t, V): return (a * (V - V_rest) - w) / tau_w, noise / tau_w def update(ST, _t): ST['spike'] = 0 if _t - ST['t_last_spike'] <= t_refractory: ST['refractory'] = 1. else: ST['refractory'] = 0. w = int_w(ST['w'], _t, ST['V']) V = int_V(ST['V'], _t, w, ST['input']) if V >= V_th: V = V_reset w += b ST['spike'] = 1 ST['t_last_spike'] = _t ST['V'] = V ST['w'] = w def reset(ST): ST['input'] = 0. return bp.NeuType(name='AdQuaIF_neuron', ST=ST, steps=(update, reset), mode=mode)
def get_HH(noise=NOISE, V_th=V_THRESHOLD, C=C, E_Na=E_NA, E_K=E_K, E_leak=E_LEAK, g_Na=G_NA, g_K=G_K, g_leak=G_LEAK): ''' A Hodgkin–Huxley neuron implemented in BrainPy. .. math:: & C \\frac {dV} {dt} = -(\\bar{g}_{Na} m^3 h (V-E_{Na}) + \\bar{g}_K n^4 (V-E_K) + g_{leak} (V - E_{leak})) + I(t) & \\frac {dx} {dt} = \\alpha_x (1-x) - \\beta_x, \\quad x\\in \\ {\\rm{Na, K, leak}} & \\alpha_m(V) = \\frac {0.1(V+40)}{1-exp(\\frac{-(V + 40)} {10})} & \\beta_m(V) = 4.0 exp(\\frac{-(V + 65)} {18}) & \\alpha_h(V) = 0.07 exp(\\frac{-(V+65)}{20}) & \\beta_h(V) = \\frac 1 {1 + exp(\\frac{-(V + 35)} {10})} & \\alpha_n(V) = \\frac {0.01(V+55)}{1-exp(-(V+55)/10)} & \\beta_n(V) = 0.125 exp(\\frac{-(V + 65)} {80}) ST refers to the neuron state, items in ST are listed below: =============== ================== ========================================================= **Member name** **Initial values** **Explanation** --------------- ------------------ --------------------------------------------------------- V -65 Membrane potential. m 0.05 gating variable of the sodium ion channel. n 0.32 gating variable of the potassium ion channel. h 0.60 gating variable of the sodium ion channel. input 0 External and synaptic input current. spike 0 Flag to mark whether the neuron is spiking. Can be seen as bool. =============== ================== ========================================================= Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: noise (float): the noise fluctuation. V_th (float): the spike threshold (mV). C (float): capacitance (ufarad). E_Na (float): reversal potential of sodium (mV). E_K (float): reversal potential of potassium (mV). E_leak (float): reversal potential of unspecific (mV). g_Na (float): conductance of sodium channel (msiemens). g_K (float): conductance of potassium channel (msiemens). g_leak (float): conductance of unspecific channels (msiemens). Returns: bp.NeuType References: .. [1] Hodgkin, Alan L., and Andrew F. Huxley. "A quantitative description of membrane current and its application to conduction and excitation in nerve." The Journal of physiology 117.4 (1952): 500. ''' # define variables and initial values ST = bp.types.NeuState( { 'V': -65., 'm': 0.05, 'h': 0.60, 'n': 0.32, 'spike': 0., 'input': 0. }, help='Hodgkin–Huxley neuron state.\n' '"V" denotes membrane potential.\n' '"n" denotes potassium channel activation probability.\n' '"m" denotes sodium channel activation probability.\n' '"h" denotes sodium channel inactivation probability.\n' '"spike" denotes spiking state.\n' '"input" denotes synaptic input.\n') @bp.integrate def int_m(m, _t, V): alpha = 0.1 * (V + 40) / (1 - np.exp(-(V + 40) / 10)) beta = 4.0 * np.exp(-(V + 65) / 18) return alpha * (1 - m) - beta * m @bp.integrate def int_h(h, _t, V): alpha = 0.07 * np.exp(-(V + 65) / 20.) beta = 1 / (1 + np.exp(-(V + 35) / 10)) return alpha * (1 - h) - beta * h @bp.integrate def int_n(n, _t, V): alpha = 0.01 * (V + 55) / (1 - np.exp(-(V + 55) / 10)) beta = 0.125 * np.exp(-(V + 65) / 80) return alpha * (1 - n) - beta * n @bp.integrate def int_V(V, _t, m, h, n, I_ext): I_Na = (g_Na * np.power(m, 3.0) * h) * (V - E_Na) I_K = (g_K * np.power(n, 4.0)) * (V - E_K) I_leak = g_leak * (V - E_leak) dVdt = (-I_Na - I_K - I_leak + I_ext) / C return dVdt, noise / C # update the variables change over time (for each step) def update(ST, _t): m = np.clip(int_m(ST['m'], _t, ST['V']), 0., 1.) # use np.clip to limit the int_m to between 0 and 1. h = np.clip(int_h(ST['h'], _t, ST['V']), 0., 1.) n = np.clip(int_n(ST['n'], _t, ST['V']), 0., 1.) V = int_V(ST['V'], _t, m, h, n, ST['input']) # solve V from int_V equation. spike = np.logical_and(ST['V'] < V_th, V >= V_th) # spike when reach threshold. ST['spike'] = spike ST['V'] = V ST['m'] = m ST['h'] = h ST['n'] = n def reset(ST): ST['input'] = 0. return bp.NeuType(name='HH_neuron', ST=ST, steps=(update, reset), mode='vector')
def get_MorrisLecar(noise=0., V_Ca=130., g_Ca=4.4, V_K=-84., g_K=8., V_Leak=-60., g_Leak=2., C=20., V1=-1.2, V2=18., V3=2., V4=30., phi=0.04, mode='vector'): """ The Morris-Lecar neuron model. (Also known as :math:`I_{Ca}+I_K`-model.) .. math:: &C\\frac{dV}{dt} = - g_{Ca} M_{\\infty} (V - V_{Ca})- g_{K} W(V - V_{K}) - g_{Leak} (V - V_{Leak}) + I_{ext} &\\frac{dW}{dt} = \\frac{W_{\\infty}(V) - W}{ \\tau_W(V)} ST refers to neuron state, members of ST are listed below: =============== ================= ========================================================= **Member name** **Initial Value** **Explanation** --------------- ----------------- --------------------------------------------------------- V -20. Membrane potential. W 0.02 Gating variable, refers to the fraction of opened K+ channels. input 0. External and synaptic input current. =============== ================= ========================================================= Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: noise (float): The noise fluctuation. V_Ca (float): Equilibrium potentials of Ca+.(mV) g_Ca (float): Maximum conductance of corresponding Ca+.(mS/cm2) V_K (float): Equilibrium potentials of K+.(mV) g_K (float): Maximum conductance of corresponding K+.(mS/cm2) V_Leak (float): Equilibrium potentials of leak current.(mV) g_Leak (float): Maximum conductance of leak current.(mS/cm2) C (float): Membrane capacitance.(uF/cm2) V1 (float): Potential at which M_inf = 0.5.(mV) V2 (float): Reciprocal of slope of voltage dependence of M_inf.(mV) V3 (float): Potential at which W_inf = 0.5.(mV) V4 (float): Reciprocal of slope of voltage dependence of W_inf.(mV) phi (float): A temperature factor.(1/s) mode (str): Data structure of ST members. Returns: bp.Neutype: return description of Morris-Lecar model. References: .. [1] Meier, Stephen R., Jarrett L. Lancaster, and Joseph M. Starobin. "Bursting regimes in a reaction-diffusion system with action potential-dependent equilibrium." PloS one 10.3 (2015): e0122401. """ ST = bp.types.NeuState({'V': -20, 'W': 0.02, 'input': 0.}) @bp.integrate def int_W(W, _t, V): tau_W = 1 / (phi * np.cosh((V - V3) / (2 * V4))) W_inf = (1 / 2) * (1 + np.tanh((V - V3) / V4)) dWdt = (W_inf - W) / tau_W return dWdt @bp.integrate def int_V(V, _t, W, Isyn): M_inf = (1 / 2) * (1 + np.tanh((V - V1) / V2)) I_Ca = g_Ca * M_inf * (V - V_Ca) I_K = g_K * W * (V - V_K) I_Leak = g_Leak * (V - V_Leak) dVdt = (-I_Ca - I_K - I_Leak + Isyn) / C return dVdt, noise / C def update(ST, _t): W = int_W(ST['W'], _t, ST['V']) V = int_V(ST['V'], _t, ST['W'], ST['input']) ST['V'] = V ST['W'] = W ST['input'] = 0. def reset(ST): ST['input'] = 0. if mode == 'scalar': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode == 'vector': return bp.NeuType(name='MorrisLecar_neuron', ST=ST, steps=[update, reset], mode=mode) elif mode == 'matrix': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) else: raise ValueError("BrainPy does not support mode '%s'." % (mode))
def test_hh(num, device): print('Scale:{}, Model:HH, Device:{}, '.format(num, device), end='') st_build = time.time() bp.profile.set(jit=True, device=device, dt=0.1, numerical_method='exponential') num_exc = int(num * 0.8) num_inh = int(num * 0.2) num = num_exc + num_inh Cm = 200 # Membrane Capacitance [pF] gl = 10. # Leak Conductance [nS] El = -60. # Resting Potential [mV] g_Na = 20. * 1000 ENa = 50. # reversal potential (Sodium) [mV] g_Kd = 6. * 1000 # K Conductance [nS] EK = -90. # reversal potential (Potassium) [mV] VT = -63. Vt = -20. # Time constants taue = 5. # Excitatory synaptic time constant [ms] taui = 10. # Inhibitory synaptic time constant [ms] # Reversal potentials Ee = 0. # Excitatory reversal potential (mV) Ei = -80. # Inhibitory reversal potential (Potassium) [mV] # excitatory synaptic weight we = 6.0 * np.sqrt(3200) / np.sqrt( num_exc) # excitatory synaptic conductance [nS] # inhibitory synaptic weight wi = 67.0 * np.sqrt(800) / np.sqrt( num_inh) # inhibitory synaptic conductance [nS] inf = 0.05 neu_ST = bp.types.NeuState('V', 'm', 'n', 'h', 'sp', 'ge', 'gi') @bp.integrate def int_ge(ge, t): return -ge / taue @bp.integrate def int_gi(gi, t): return -gi / taui @bp.integrate def int_m(m, t, V): a = 13.0 - V + VT b = V - VT - 40.0 m_alpha = 0.32 * a / (exp(a / 4.) - 1.) m_beta = 0.28 * b / (exp(b / 5.) - 1.) dmdt = (m_alpha * (1. - m) - m_beta * m) return dmdt @bp.integrate def int_m_zeroa(m, t, V): b = V - VT - 40.0 m_alpha = 0.32 m_beta = 0.28 * b / (exp(b / 5.) - 1.) dmdt = (m_alpha * (1. - m) - m_beta * m) return dmdt @bp.integrate def int_m_zerob(m, t, V): a = 13.0 - V + VT m_alpha = 0.32 * a / (exp(a / 4.) - 1.) m_beta = 0.28 dmdt = (m_alpha * (1. - m) - m_beta * m) return dmdt @bp.integrate def int_h(h, t, V): h_alpha = 0.128 * exp((17. - V + VT) / 18.) h_beta = 4. / (1. + exp(-(V - VT - 40.) / 5.)) dhdt = (h_alpha * (1. - h) - h_beta * h) return dhdt @bp.integrate def int_n(n, t, V): c = 15. - V + VT n_alpha = 0.032 * c / (exp(c / 5.) - 1.) n_beta = .5 * exp((10. - V + VT) / 40.) dndt = (n_alpha * (1. - n) - n_beta * n) return dndt @bp.integrate def int_n_zero(n, t, V): n_alpha = 0.032 n_beta = .5 * exp((10. - V + VT) / 40.) dndt = (n_alpha * (1. - n) - n_beta * n) return dndt @bp.integrate def int_V(V, t, m, h, n, ge, gi): g_na_ = g_Na * (m * m * m) * h g_kd_ = g_Kd * (n * n * n * n) dvdt = (gl * (El - V) + ge * (Ee - V) + gi * (Ei - V) - g_na_ * (V - ENa) - g_kd_ * (V - EK)) / Cm return dvdt def neu_update(ST, _t): ST['ge'] = int_ge(ST['ge'], _t) ST['gi'] = int_gi(ST['gi'], _t) if abs(ST['V'] - (40.0 + VT)) < inf: ST['m'] = int_m_zerob(ST['m'], _t, ST['V']) elif abs(ST['V'] - (13.0 + VT)) < inf: ST['m'] = int_m_zeroa(ST['m'], _t, ST['V']) else: ST['m'] = int_m(ST['m'], _t, ST['V']) ST['h'] = int_h(ST['h'], _t, ST['V']) if abs(ST['V'] - (15.0 + VT)) > inf: ST['n'] = int_n(ST['n'], _t, ST['V']) else: ST['n'] = int_n_zero(ST['n'], _t, ST['V']) V = int_V(ST['V'], _t, ST['m'], ST['h'], ST['n'], ST['ge'], ST['gi']) sp = ST['V'] < Vt and V >= Vt ST['sp'] = sp ST['V'] = V neuron = bp.NeuType(name='CUBA-HH', ST=neu_ST, steps=neu_update, mode='scalar') requires_exc = { 'pre': bp.types.NeuState( ['sp'], help='Pre-synaptic neuron state must have "spike" item.'), 'post': bp.types.NeuState( ['ge'], help='Post-synaptic neuron state must have "V" and "input" item.') } def update_syn_exc(ST, pre, post): if pre['sp']: post['ge'] += we exc_syn = bp.SynType(name='exc_syn', ST=bp.types.SynState(), requires=requires_exc, steps=update_syn_exc, mode='scalar') requires_inh = { 'pre': bp.types.NeuState( ['sp'], help='Pre-synaptic neuron state must have "spike" item.'), 'post': bp.types.NeuState( ['gi'], help='Post-synaptic neuron state must have "V" and "input" item.') } def update_syn_inh(ST, pre, post): if pre['sp']: post['gi'] -= wi inh_syn = bp.SynType(name='inh_syn', ST=bp.types.SynState(), requires=requires_inh, steps=update_syn_inh, mode='scalar') group = bp.NeuGroup(neuron, geometry=num) group.ST['V'] = El + (np.random.randn(num_exc + num_inh) * 5. - 5.) group.ST['ge'] = (np.random.randn(num_exc + num_inh) * 1.5 + 4.) * 10. group.ST['gi'] = (np.random.randn(num_exc + num_inh) * 12. + 20.) * 10. exc_conn = bp.SynConn(exc_syn, pre_group=group[:num_exc], post_group=group, conn=bp.connect.FixedProb(prob=0.02)) inh_conn = bp.SynConn(inh_syn, pre_group=group[num_exc:], post_group=group, conn=bp.connect.FixedProb(prob=0.02)) net = bp.Network(group, exc_conn, inh_conn) ed_build = time.time() st_run = time.time() net.run(duration=1000.0) ed_run = time.time() build_time = float(ed_build - st_build) run_time = float(ed_run - st_run) print('BuildT:{:.2f}s, RunT:{:.2f}s'.format(build_time, run_time)) return run_time, build_time
def get_WilsonCowan(c1=12., c2=4., c3=13., c4=11., k_e=1., k_i=1., tau_e=1., tau_i=1., r_e=1., r_i=1., slope_e=1.2, slope_i=1., theta_e=2.8, theta_i=4., mode='scalar'): """ Wilson-Cowan firing rate neuron model. Each neuron refers to a column of neurons, including excitatory and inhibitory neurons. .. math:: &\\tau_e\\frac{d a_e(t)}{d t} = - a_e(t) + (k_e - r_e * a_e(t)) * \\mathcal{S}_e(c_1 a_e(t) - c_2 a_i(t) + I_{ext_e}(t)) &\\tau_i\\frac{d a_i(t)}{d t} = - a_i(t) + (k_i - r_i * a_i(t)) * \\mathcal{S}_i(c_3 a_e(t) - c_4 a_i(t) + I_{ext_j}(t)) &\\mathcal{S}(x) = \\frac{1}{1 + exp(- a(x - \\theta))} - \\frac{1}{1 + exp(a\\theta)} ST refers to neuron state, members of ST are listed below: =============== ================= ========================================================= **Member name** **Initial Value** **Explanation** --------------- ----------------- --------------------------------------------------------- a_e 0.1 The proportion of excitatory cells firing per unit time. a_i 0.05 The proportion of inhibitory cells firing per unit time. input_e 0. External input to excitatory cells. input_i 0. External input to inhibitory cells. =============== ================= ========================================================= Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: c1 (float): Weight from E-neurons to E-neurons. c2 (float): Weight from I-neurons to E-neurons. c3 (float): Weight from E-neurons to I-neurons. c4 (float): Weight from I-neurons to I-neurons. k_e (float): Model parameter, control E-neurons' refractory period together with r_e. k_i (float): Model parameter, control I-neurons' refractory period together with r_i. tau_e (float): Time constant of E-neurons' activity. tau_i (float): Time constant of I-neurons' activity. r_e (float): Model parameter, control E-neurons' refractory period together with k_e. r_i (float): Model parameter, control I-neurons' refractory period together with k_i. slope_e (float): E-neurons' sigmoid function slope parameter. slope_i (float): I-neurons' sigmoid function slope parameter. theta_e (float): E-neurons' sigmoid function phase parameter. theta_i (float): I-neurons' sigmoid function phase parameter. mode (str): Data structure of ST members. References: .. [1] Wilson, Hugh R., and Jack D. Cowan. "Excitatory and inhibitory interactions in localized populations of model neurons." Biophysical journal 12.1 (1972): 1-24. """ ST = bp.types.NeuState({ 'a_e': 0.1, 'a_i': 0.05, 'input_e': 0., 'input_i': 0. }) def mysigmoid(x, a, theta): return 1 / (1 + np.exp(-a * (x - theta))) - 1 / (1 + np.exp(a * theta)) @bp.integrate def int_a_e(a_e, _t, a_i, I_ext_e): return (-a_e + (k_e - r_e * a_e) * mysigmoid( c1 * a_e - c2 * a_i + I_ext_e, slope_e, theta_e)) / tau_e @bp.integrate def int_a_i(a_i, _t, a_e, I_ext_i): return (-a_i + (k_i - r_i * a_i) * mysigmoid( c3 * a_e - c4 * a_i + I_ext_i, slope_i, theta_i)) / tau_i def update(ST, _t): a_e = int_a_e(ST['a_e'], _t, ST['a_i'], ST['input_e']) a_i = int_a_i(ST['a_i'], _t, ST['a_e'], ST['input_i']) ST['a_e'] = a_e ST['a_i'] = a_i def reset(ST): ST['input_e'] = 0 ST['input_i'] = 0 if mode == 'scalar': return bp.NeuType(name='WilsonCowan_neuron', ST=ST, steps=(update, reset), mode=mode) elif mode == 'vector': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode == 'matrix': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) else: raise ValueError("BrainPy does not support mode '%s'." % (mode))
def get_NaK_model(V_th=20., type='low-threshold'): """The I-Na,p+I-K model. Parameters ---------- V_th : float A float number that specifies the threshold of treating elevated membrane potential as a spike. Unit in ``mV``. Default is 20. type : str A string that specifies whether the I-Na,p+I-K model has a high (``high-threshold``) or low threshold (``low-threshold``). Default is ``low-threshold``. Returns ------- return_dict : bp.NeuType The necessary variables. """ if not (type == 'low-threshold' or 'high-threshold'): raise ValueError("Argument `type` must be either `low-threshold`" "or `high-threshold`") if type == 'high-threshold': C = 1 E_L = -80 g_L = 8 g_Na = 20 g_K = 10 E_K = -90 E_Na = 60 Vm_half = -20 k_m = 15 Vn_half = -25 k_n = 5 tau = 1 else: # low-threshold C = 1 E_L = -78 # different from high-threshold model g_L = 8 g_Na = 20 g_K = 10 E_K = -90 E_Na = 60 Vm_half = -20 k_m = 15 Vn_half = -45 # different from high-threshold model k_n = 5 tau = 1 ST = bp.types.NeuState({'V': -65., 'n': 0., 'sp': 0., 'inp': 0.}) @bp.integrate def int_n(n, t, V): n_inf = 1 / (1 + np.exp((Vn_half - V) / k_n)) dndt = (n_inf - n) / tau return dndt @bp.integrate def int_V(V, t, n, input): m_inf = 1 / (1 + np.exp((Vm_half - V) / k_m)) I_leak = g_L * (V - E_L) I_Na = g_Na * m_inf * (V - E_Na) I_K = g_K * n * (V - E_K) dvdt = (-I_leak - I_Na - I_K + input) / C return dvdt def update(ST, _t): n = np.clip(int_n(ST['n'], _t, ST['V']), 0., 1.) V = int_V(ST['V'], _t, n, ST['inp']) sp = np.logical_and(ST['V'] < V_th, V >= V_th) ST['V'] = V ST['n'] = n ST['sp'] = sp ST['inp'] = 0. return bp.NeuType(name="NaK_model", ST=ST, steps=update, mode='vector')
def run_brianpy(num_neu, duration, device='cpu'): num_inh = int(num_neu / 5) num_exc = num_neu - num_inh bp.profile.set(jit=True, device=device, dt=dt) # Parameters taum = 20 taue = 5 taui = 10 Vt = -50 Vr = -60 El = -60 Erev_exc = 0. Erev_inh = -80. I = 20. we = 0.6 # excitatory synaptic weight (voltage) wi = 6.7 # inhibitory synaptic weight ref = 5.0 neu_ST = bp.types.NeuState({ 'sp_t': -1e7, 'V': Vr, 'spike': 0., 'ge': 0., 'gi': 0. }) @bp.integrate def int_ge(ge, t): return -ge / taue @bp.integrate def int_gi(gi, t): return -gi / taui @bp.integrate def int_V(V, t, ge, gi): return (ge * (Erev_exc - V) + gi * (Erev_inh - V) + (El - V) + I) / taum def neu_update(ST, _t): ST['ge'] = int_ge(ST['ge'], _t) ST['gi'] = int_gi(ST['gi'], _t) ST['spike'] = 0. if (_t - ST['sp_t']) > ref: V = int_V(ST['V'], _t, ST['ge'], ST['gi']) ST['spike'] = 0. if V >= Vt: ST['V'] = Vr ST['spike'] = 1. ST['sp_t'] = _t else: ST['V'] = V neuron = bp.NeuType(name='COBA', ST=neu_ST, steps=neu_update, mode='scalar') def syn_update1(pre, post, pre2post): for pre_id in range(len(pre2post)): if pre['spike'][pre_id] > 0.: post_ids = pre2post[pre_id] for i in post_ids: post['ge'][i] += we exc_syn = bp.SynType('exc_syn', steps=syn_update1, ST=bp.types.SynState([]), mode='vector') def syn_update2(pre, post, pre2post): for pre_id in range(len(pre2post)): if pre['spike'][pre_id] > 0.: post_ids = pre2post[pre_id] for i in post_ids: post['gi'][i] += wi inh_syn = bp.SynType('inh_syn', steps=syn_update2, ST=bp.types.SynState([]), mode='vector') group = bp.NeuGroup(neuron, geometry=num_exc + num_inh) group.ST['V'] = np.random.randn(num_exc + num_inh) * 5. - 55. exc_conn = bp.SynConn(exc_syn, pre_group=group[:num_exc], post_group=group, conn=bp.connect.FixedProb(prob=0.02)) inh_conn = bp.SynConn(inh_syn, pre_group=group[num_exc:], post_group=group, conn=bp.connect.FixedProb(prob=0.02)) net = bp.Network(group, exc_conn, inh_conn) t0 = time.time() net.run(duration) t = time.time() - t0 print(f'BrainPy ({device}) used time {t} s.') return t
def update(ST, _t_): m = np.clip(int_m(ST['m'], _t_, ST['V']), 0., 1.) h = np.clip(int_h(ST['h'], _t_, ST['V']), 0., 1.) n = np.clip(int_n(ST['n'], _t_, ST['V']), 0., 1.) V = int_V(ST['V'], _t_, m, h, n, ST['inp']) sp = np.logical_and(ST['V'] < Vth, V >= Vth) ST['sp'] = sp ST['V'] = V ST['m'] = m ST['h'] = h ST['n'] = n ST['inp'] = 0. HH = bp.NeuType(name='HH_neuron', requires={"ST": ST}, steps=update, vector_based=True) tau = 10. Vr = 0. Vth2 = 10. ref = 0. ST = bp.types.NeuState({'V': 0, 'sp_t': -1e7, 'sp': 0., 'inp': 0.}, ) @bp.integrate def int_f(V, t, Isyn): return (-V + Vr + Isyn) / tau
return dvdt def neu_update(ST, _t): ST['ge'] = int_ge(ST['ge'], _t) ST['gi'] = int_gi(ST['gi'], _t) ST['m'] = int_m(ST['m'], _t, ST['V']) ST['h'] = int_h(ST['h'], _t, ST['V']) ST['n'] = int_n(ST['n'], _t, ST['V']) V = int_V(ST['V'], _t, ST['m'], ST['h'], ST['n'], ST['ge'], ST['gi']) sp = np.logical_and(ST['V'] < Vt, V >= Vt) ST['sp'] = sp ST['V'] = V neuron = bp.NeuType(name='CUBA-HH', ST=neu_ST, steps=neu_update, mode='vector') def exc_update(pre, post, pre2post): for pre_id in range(len(pre2post)): if pre['sp'][pre_id] > 0.: post_ids = pre2post[pre_id] # post['ge'][post_ids] += we for p_id in post_ids: post['ge'][p_id] += we def inh_update(pre, post, pre2post): for pre_id in range(len(pre2post)): if pre['sp'][pre_id] > 0.: post_ids = pre2post[pre_id]
def get_LIF(V_rest=0., V_reset=-5., V_th=20., R=1., tau=10., t_refractory=5., noise=0., mode='scalar'): """Leaky Integrate-and-Fire neuron model. .. math:: \\tau \\frac{d V}{d t}=-(V-V_{rest}) + RI(t) ST refers to neuron state, members of ST are listed below: =============== ================= ========================================================= **Member name** **Initial Value** **Explanation** --------------- ----------------- --------------------------------------------------------- V 0. Membrane potential. input 0. External and synaptic input current. spike 0. Flag to mark whether the neuron is spiking. Can be seen as bool. refractory 0. Flag to mark whether the neuron is in refractory period. Can be seen as bool. t_last_spike -1e7 Last spike time stamp. =============== ================= ========================================================= Note that all ST members are saved as floating point type in BrainPy, though some of them represent other data types (such as boolean). Args: V_rest (float): Resting potential. V_reset (float): Reset potential after spike. V_th (float): Threshold potential of spike. R (float): Membrane resistance. C (float): Membrane capacitance. tau (float): Membrane time constant. Compute by R * C. t_refractory (int): Refractory period length.(ms) noise (float): noise. mode (str): Data structure of ST members. Returns: bp.Neutype: return description of LIF model. References: .. [1] Gerstner, Wulfram, et al. Neuronal dynamics: From single neurons to networks and models of cognition. Cambridge University Press, 2014. """ ST = bp.types.NeuState({ 'V': 0, 'input': 0, 'spike': 0, 'refractory': 0, 't_last_spike': -1e7 }) @bp.integrate def int_V(V, _t, I_ext): # integrate u(t) return (-(V - V_rest) + R * I_ext) / tau, noise / tau def update(ST, _t): # update variables ST['spike'] = 0 if _t - ST['t_last_spike'] <= t_refractory: ST['refractory'] = 1. else: ST['refractory'] = 0. V = int_V(ST['V'], _t, ST['input']) if V >= V_th: V = V_reset ST['spike'] = 1 ST['t_last_spike'] = _t ST['V'] = V def reset(ST): ST['input'] = 0. if mode == 'scalar': return bp.NeuType(name='LIF_neuron', ST=ST, steps=(update, reset), mode=mode) elif mode == 'vector': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) elif mode == 'matrix': raise ValueError("mode of function '%s' can not be '%s'." % (sys._getframe().f_code.co_name, mode)) else: raise ValueError("BrainPy does not support mode '%s'." % (mode))