├── _config.yml ├── images └── plotly.png ├── TwoNoisyCoupledNeuron.py ├── ConnectedNeurons_NestLibrary.py ├── .gitignore ├── HHmodel_odeint.py ├── twoCoupledNeuron2.py ├── HHmodel_EulerMethod.py ├── CoupledNeuronLib.py ├── HHmodel_Rung_Kutta.py ├── HH_plotly.py ├── noisyInput.py └── README.md /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /images/plotly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nosratullah/HodgkinHuxely/HEAD/images/plotly.png -------------------------------------------------------------------------------- /TwoNoisyCoupledNeuron.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import CoupledNeuronLib as HH 4 | import scipy as sp 5 | 6 | length = 10000 7 | zeroVoltage = np.zeros(length) 8 | #inputCurrent = np.ones(length)*4 9 | #inputCurrent[1000:2000] = 10 10 | #inputCurrent[2000::] = 3 11 | #inputCurrent2 = np.ones(length)*5.46 12 | noisyInput1 = np.ones(length)*7 + np.random.normal(0,3,length) 13 | noisyInput2 = np.ones(length)*5 + np.random.normal(0,3,length) 14 | preVoltage,preSyn = HH.HodgkinHuxley(noisyInput1,zeroVoltage) 15 | postVoltage,postSyn = HH.HodgkinHuxley(noisyInput2,preVoltage) 16 | plt.figure(figsize=(15,10)) 17 | plt.plot(preVoltage,'r',label='pre synaptic voltage'); 18 | #plt.plot(postVoltage,'b'); 19 | plt.plot(postSyn,'g-.',label='synaptic voltage'); 20 | plt.plot(postVoltage,'b',label='post synaptic voltage'); 21 | #plt.xlim(xmin=0) 22 | plt.ylim(ymax=50) 23 | plt.legend(loc='upper left'); 24 | plt.savefig('coupledNeuron.png',dpi=150) 25 | plt.show() 26 | -------------------------------------------------------------------------------- /ConnectedNeurons_NestLibrary.py: -------------------------------------------------------------------------------- 1 | import nest 2 | import matplotlib.pyplot as plt 3 | 4 | #Creating neurons 5 | neuron1 = nest.Create("iaf_psc_alpha") 6 | nest.SetStatus(neuron1,{"I_e":0.0}) 7 | neuron2 = nest.Create("iaf_psc_alpha") 8 | multimeter1 = nest.Create("multimeter") 9 | nest.SetStatus(multimeter1, {"withtime":True, "record_from":["V_m"]}) 10 | multimeter2 = nest.Create("multimeter") 11 | nest.SetStatus(multimeter2, {"withtime":True, "record_from":["V_m"]}) 12 | nest.SetStatus(neuron2,{"I_e":360.0}) 13 | noise_ex = nest.Create("poisson_generator") 14 | noise_ex = nest.Create("poisson_generator") 15 | noise_in = nest.Create("poisson_generator") 16 | nest.SetStatus(noise_ex, {"rate": 80000.0}) 17 | nest.SetStatus(noise_in, {"rate": 15000.0}) 18 | 19 | syn_dict_ex = {"weight": 1.2} 20 | syn_dict_in = {"weight": -2.0} 21 | nest.Connect(noise_ex, neuron1, syn_spec=syn_dict_ex) 22 | nest.Connect(noise_in, neuron1, syn_spec=syn_dict_in) 23 | 24 | synapse = {"weight":50.0} 25 | #connecting neurons 26 | nest.Connect(neuron1, neuron2, syn_spec = synapse) 27 | nest.Connect(multimeter1,neuron1) 28 | nest.Connect(multimeter2,neuron2) 29 | 30 | nest.Simulate(1000.0) 31 | 32 | dmm1 = nest.GetStatus(multimeter1)[0] 33 | Vms1 = dmm1["events"]["V_m"] 34 | ts1 = dmm1["events"]["times"] 35 | 36 | dmm2 = nest.GetStatus(multimeter2)[0] 37 | Vms2 = dmm2["events"]["V_m"] 38 | ts2 = dmm2["events"]["times"] 39 | 40 | # Plot the result 41 | plt.plot(ts1,-Vms1,'r',label='neuron 1') 42 | plt.plot(ts2,-Vms2,'b',label='neuron 2') 43 | plt.legend(loc='best') 44 | plt.savefig('connectedNeuron.png') 45 | plt.show() 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /HHmodel_odeint.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.integrate import odeint 3 | import matplotlib.pyplot as plt 4 | 5 | 6 | def alpha_n(v): 7 | return 0.01*(v+50)/(1-np.exp(-(v+50)/10)) 8 | def beta_n(v): 9 | return 0.125*np.exp(-(v+60)/80) 10 | def alpha_h(v): 11 | return 0.07*np.exp(-0.05*(v+60)) 12 | def beta_h(v): 13 | return 1/(1+np.exp(-(0.1)*(v+30.0))) 14 | def alpha_m(v): 15 | return 0.1*(v+35.0)/(1-np.exp(-(v+35.0)/10.0)) 16 | def beta_m(v): 17 | return 4.0*np.exp(-0.0556*(v+60)) 18 | 19 | def HHmodel(x,t): 20 | I = 10 21 | v = x[0] #initial values 22 | m = x[1] 23 | h = x[2] 24 | n = x[3] 25 | 26 | Cm = 1.0 #microFarad 27 | E_Na=50 #miliVolt 28 | E_K=-77 #miliVolt 29 | E_l=-54 #miliVolt 30 | g_Na=120 #mScm-2 31 | g_K=36 #mScm-2 32 | g_l=0.03 #mScm-2 33 | Esyn = 4 #mScm-2 34 | 35 | def I_Na(v,m,h): 36 | return g_Na * m**3 * h * (v - E_Na) 37 | def I_K(v,n): 38 | return g_K * n**4 * (v - E_K) 39 | def I_L(v): 40 | return g_l * (v - E_l) 41 | 42 | dvdt = (I - I_Na(v,m,h) - I_K(v,n) - I_L(v))/Cm 43 | dmdt = alpha_m(v)*(1.0 - m) - beta_m(v)*m 44 | dhdt = alpha_h(v)*(1.0 - h) - beta_h(v)*h 45 | dndt = alpha_n(v)*(1.0 - n) - beta_n(v)*n 46 | return [dvdt,dmdt,dhdt,dndt] 47 | 48 | v0 = -65.0 49 | n0 = float(alpha_n(v0)/(alpha_n(v0)+beta_n(v0))) 50 | h0 = float(alpha_h(v0)/(alpha_h(v0)+beta_h(v0))) 51 | m0 = float(alpha_m(v0)/(alpha_m(v0)+beta_m(v0))) 52 | x0 = [v0,m0,h0,n0] 53 | t = np.linspace(0,100,1000) 54 | x = odeint(HHmodel,x0,t) 55 | voltage = x[:,0] 56 | mchannels = x[:,1] 57 | hchannels = x[:,2] 58 | nchannels = x[:,3] 59 | 60 | plt.figure(figsize=(15,20)) 61 | plt.subplot(311) 62 | plt.plot(voltage,'r-',label='voltage') 63 | plt.legend(loc='best') 64 | plt.subplot(312) 65 | plt.plot(voltage,nchannels,'g-.',label='phase plan'); 66 | plt.legend(loc='best') 67 | plt.subplot(313) 68 | plt.plot(nchannels,label='n channels') 69 | plt.subplot(313) 70 | plt.plot(hchannels,label='h channels') 71 | plt.subplot(313) 72 | plt.plot(mchannels,label='m channels') 73 | plt.legend(loc='best') 74 | plt.show() 75 | -------------------------------------------------------------------------------- /twoCoupledNeuron2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def HodgkinHuxley(I,preVoltage): 4 | 5 | #holders 6 | v = [] 7 | m = [] 8 | h = [] 9 | n = [] 10 | s = [] #synaptic channel 11 | Isynlist = [] 12 | dt = 0.05 13 | t = np.linspace(0,10,len(I)) 14 | 15 | #constants 16 | Cm = 1.0 #microFarad 17 | ENa=50 #miliVolt 18 | EK=-77 #miliVolt 19 | El=-54 #miliVolt 20 | E_ampa = 0 #miliVolt 21 | g_Na=120 #mScm-2 22 | g_K=36 #mScm-2 23 | g_l=0.03 #mScm-2 24 | g_syn = 0.3 25 | t_d = 2 #ms Decay time 26 | t_r = 0.4 #ms Raise time 27 | Tij = 0 #ms time delay 28 | #Define functions 29 | def alphaN(v): 30 | return 0.01*(v+50)/(1-np.exp(-(v+50)/10)) 31 | 32 | def betaN(v): 33 | return 0.125*np.exp(-(v+60)/80) 34 | 35 | def alphaM(v): 36 | return 0.1*(v+35)/(1-np.exp(-(v+35)/10)) 37 | 38 | def betaM(v): 39 | return 4.0*np.exp(-0.0556*(v+60)) 40 | 41 | def alphaH(v): 42 | return 0.07*np.exp(-0.05*(v+60)) 43 | 44 | def betaH(v): 45 | return 1/(1+np.exp(-(0.1)*(v+30))) 46 | 47 | def H_pre(preV): 48 | return 1 + np.tanh(preV) 49 | 50 | #Initialize the voltage and the channels : 51 | v.append(-60) 52 | m0 = alphaM(v[0])/(alphaM(v[0])+betaM(v[0])) 53 | n0 = alphaN(v[0])/(alphaN(v[0])+betaN(v[0])) 54 | h0 = alphaH(v[0])/(alphaH(v[0])+betaH(v[0])) 55 | #s0 = alpha_s(preVoltage[0])/(alpha_s(preVoltage[0])+beta_s(preVoltage[0])) 56 | s0 = 0 57 | 58 | #t.append(0) 59 | m.append(m0) 60 | n.append(n0) 61 | h.append(h0) 62 | s.append(s0) 63 | 64 | if (type(preVoltage)==int): 65 | preVoltage = np.zeros(len(I)) #check if preVoltage exists or not 66 | 67 | #solving ODE using Euler's method: 68 | for i in range(1,len(t)): 69 | m.append(m[i-1] + dt*((alphaM(v[i-1])*(1-m[i-1]))-betaM(v[i-1])*m[i-1])) 70 | n.append(n[i-1] + dt*((alphaN(v[i-1])*(1-n[i-1]))-betaN(v[i-1])*n[i-1])) 71 | h.append(h[i-1] + dt*((alphaH(v[i-1])*(1-h[i-1]))-betaH(v[i-1])*h[i-1])) 72 | s.append(s[i-1] + dt * (H_pre(preVoltage[i-1])*((1-s[i-1]/t_r))-(s[i-1]/t_d))) 73 | gNa = g_Na * h[i-1]*(m[i-1])**3 74 | gK = g_K*n[i-1]**4 75 | gl = g_l 76 | INa = gNa*(v[i-1]-ENa) 77 | IK = gK*(v[i-1]-EK) 78 | Il = gl*(v[i-1]-El) 79 | #Synaptic Current comes from the pre neuron 80 | Isyn = -0.1 * s[i-1] * (v[i-1] - E_ampa) 81 | #making a list for Synaptic currents for plotting 82 | Isynlist.append(Isyn) 83 | v.append(v[i-1]+(dt)*((1/Cm)*(I[i-1]-(INa+IK+Il+Isyn)))) 84 | 85 | return v,Isynlist 86 | -------------------------------------------------------------------------------- /HHmodel_EulerMethod.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | #holders 5 | v = [] 6 | m = [] 7 | h = [] 8 | n = [] 9 | dt = 0.05 10 | t = np.linspace(0,10,10000) 11 | 12 | #constants 13 | I = 7 14 | Cm = 1.0 #microFarad 15 | ENa=50 #miliVolt 16 | EK=-77 #miliVolt 17 | El=-54 #miliVolt 18 | g_Na=120 #mScm-2 19 | g_K=36 #mScm-2 20 | g_l=0.03 #mScm-2 21 | 22 | #define alhpa constant and betha constant for n,m,h channels for opening probability 23 | def alphaN(v): 24 | return 0.01*(v+50)/(1-np.exp(-(v+50)/10)) 25 | 26 | def betaN(v): 27 | return 0.125*np.exp(-(v+60)/80) 28 | 29 | def alphaM(v): 30 | return 0.1*(v+35)/(1-np.exp(-(v+35)/10)) 31 | 32 | def betaM(v): 33 | return 4.0*np.exp(-0.0556*(v+60)) 34 | 35 | def alphaH(v): 36 | return 0.07*np.exp(-0.05*(v+60)) 37 | 38 | def betaH(v): 39 | return 1/(1+np.exp(-(0.1)*(v+30))) 40 | 41 | #Initialize the voltage and the channels : 42 | v.append(-60) 43 | m0 = alphaM(v[0])/(alphaM(v[0])+betaM(v[0])) 44 | n0 = alphaN(v[0])/(alphaN(v[0])+betaN(v[0])) 45 | h0 = alphaH(v[0])/(alphaH(v[0])+betaH(v[0])) 46 | 47 | #t.append(0) 48 | m.append(m0) 49 | n.append(n0) 50 | h.append(h0) 51 | 52 | #solving ODE using Euler's method: 53 | for i in range(1,len(t)): 54 | m.append(m[i-1] + dt*((alphaM(v[i-1])*(1-m[i-1]))-betaM(v[i-1])*m[i-1])) 55 | n.append(n[i-1] + dt*((alphaN(v[i-1])*(1-n[i-1]))-betaN(v[i-1])*n[i-1])) 56 | h.append(h[i-1] + dt*((alphaH(v[i-1])*(1-h[i-1]))-betaH(v[i-1])*h[i-1])) 57 | gNa = g_Na*h[i-1]*(m[i-1])**3 58 | gK=g_K*n[i-1]**4 59 | gl=g_l 60 | INa = gNa*(v[i-1]-ENa) 61 | IK = gK*(v[i-1]-EK) 62 | Il=gl*(v[i-1]-El) 63 | #if you want to use some dynamic current try to uncomment the below line and comment the line aftar that. 64 | #v.append(v[i-1]+(dt)*((1/Cm)*(I[i-1]-(INa+IK+Il)))) 65 | v.append(v[i-1]+(dt)*((1/Cm)*(I-(INa+IK+Il)))) 66 | 67 | #Plot the data 68 | plt.figure(figsize=(15,20)) 69 | plt.legend(loc='upper left') 70 | plt.title('Hodgkin Huxely Spike Model') 71 | plt.subplot(3,1,1) 72 | plt.plot(t,v,'b-',label='voltage') 73 | plt.legend(loc='upper left') 74 | plt.xlabel('time (ms)') 75 | plt.ylabel('Voltage') 76 | plt.subplot(3,1,2) 77 | plt.plot(t,n,'y-',label='n channels') 78 | plt.legend(loc='upper left') 79 | plt.xlabel('time') 80 | plt.ylabel('n') 81 | plt.subplot(3,1,2) 82 | plt.plot(t,m,'g-',label='m channels') 83 | plt.legend(loc='upper left') 84 | plt.xlabel('time') 85 | plt.ylabel('m') 86 | plt.subplot(3,1,2) 87 | plt.plot(t,h,'r--',label='h channels') 88 | plt.legend(loc='upper left') 89 | plt.xlabel('time') 90 | plt.ylabel('channels') 91 | plt.subplot(3,1,3) 92 | plt.plot(n,v,'r--',label='Phase plane') 93 | plt.legend(loc='upper left') 94 | plt.xlabel('voltage') 95 | plt.ylabel('n channels') 96 | plt.show() 97 | -------------------------------------------------------------------------------- /CoupledNeuronLib.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def HodgkinHuxley(I,preVoltage): 4 | 5 | #holders 6 | v = [] 7 | m = [] 8 | h = [] 9 | n = [] 10 | s = [] #synaptic channel 11 | Isynlist = [] 12 | dt = 0.05 13 | t = np.linspace(0,10,len(I)) 14 | 15 | #constants 16 | Cm = 1.0 #microFarad 17 | ENa=50 #miliVolt 18 | EK=-77 #miliVolt 19 | El=-54 #miliVolt 20 | Esyn = -30 #miliVolt 21 | g_Na=120 #mScm-2 22 | g_K=36 #mScm-2 23 | g_l=0.03 #mScm-2 24 | g_syn = 0.3 25 | Td = 3 #ms 26 | Tr = 0.2 #ms 27 | Tij = 0 #ms time delay 28 | #Define functions 29 | def alphaN(v): 30 | return 0.01*(v+50)/(1-np.exp(-(v+50)/10)) 31 | 32 | def betaN(v): 33 | return 0.125*np.exp(-(v+60)/80) 34 | 35 | def alphaM(v): 36 | return 0.1*(v+35)/(1-np.exp(-(v+35)/10)) 37 | 38 | def betaM(v): 39 | return 4.0*np.exp(-0.0556*(v+60)) 40 | 41 | def alphaH(v): 42 | return 0.07*np.exp(-0.05*(v+60)) 43 | 44 | def betaH(v): 45 | return 1/(1+np.exp(-(0.1)*(v+30))) 46 | 47 | '''def synAlpha(preV,postV): 48 | return 0.4*0.5*(1+np.tanh(5*(preV-postV)))''' 49 | 50 | def alpha_s(preV): 51 | return 1/(1+np.exp(-(preV))) 52 | def beta_s(preV): 53 | return 1/(1+np.exp(preV)) 54 | 55 | 56 | #Initialize the voltage and the channels : 57 | v.append(-60) 58 | m0 = alphaM(v[0])/(alphaM(v[0])+betaM(v[0])) 59 | n0 = alphaN(v[0])/(alphaN(v[0])+betaN(v[0])) 60 | h0 = alphaH(v[0])/(alphaH(v[0])+betaH(v[0])) 61 | s0 = alpha_s(preVoltage[0])/(alpha_s(preVoltage[0])+beta_s(preVoltage[0])) 62 | 63 | #t.append(0) 64 | m.append(m0) 65 | n.append(n0) 66 | h.append(h0) 67 | s.append(s0) 68 | 69 | if (type(preVoltage)==int): 70 | preVoltage = np.zeros(len(I)) #check if preVoltage exists or not 71 | #solving ODE using Euler's method: 72 | for i in range(1,len(t)): 73 | m.append(m[i-1] + dt*((alphaM(v[i-1])*(1-m[i-1]))-betaM(v[i-1])*m[i-1])) 74 | n.append(n[i-1] + dt*((alphaN(v[i-1])*(1-n[i-1]))-betaN(v[i-1])*n[i-1])) 75 | h.append(h[i-1] + dt*((alphaH(v[i-1])*(1-h[i-1]))-betaH(v[i-1])*h[i-1])) 76 | s.append(s[i-1] + dt*((alpha_s(preVoltage[i-1])*(1-s[i-1]) - beta_s(preVoltage[i-1])*s[i-1]))) 77 | gNa = g_Na * h[i-1]*(m[i-1])**3 78 | gK=g_K*n[i-1]**4 79 | gl=g_l 80 | INa = gNa*(v[i-1]-ENa) 81 | IK = gK*(v[i-1]-EK) 82 | Il=gl*(v[i-1]-El) 83 | #Synaptic Current comes from the pre neuron 84 | Isyn = -0.08 * s[i-1] * (v[i-1] - 2) 85 | #making a list for Synaptic currents for plotting 86 | Isynlist.append(Isyn) 87 | v.append(v[i-1]+(dt)*((1/Cm)*(I[i-1]-(INa+IK+Il+Isyn)))) 88 | 89 | return v,Isynlist 90 | -------------------------------------------------------------------------------- /HHmodel_Rung_Kutta.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | t = np.linspace(0,10,1500) 5 | v = np.zeros(len(t)) 6 | m = np.zeros(len(t)) 7 | h = np.zeros(len(t)) 8 | n = np.zeros(len(t)) 9 | dt = 0.05 10 | I = 10 # nanoAmpeire 11 | Cm = 1.0 # micro F/Cm^2 12 | ENa=50 # miliVolt 13 | EK=-77 # miliVolt 14 | El=-54.4 # miliVolt 15 | g_Na=120 # mS/Cm^2 16 | g_K=36 # mS/Cm^2 17 | g_l=0.03 # mS/Cm^2 18 | 19 | 20 | def alphaN(v): 21 | return 0.01*(v+50)/(1-np.exp(-(v+50)/10)) 22 | 23 | def betaN(v): 24 | return 0.125*np.exp(-(v+60)/80) 25 | 26 | def alphaM(v): 27 | return 0.1*(v+35)/(1-np.exp(-(v+35)/10)) 28 | 29 | def betaM(v): 30 | return 4.0*np.exp(-0.0556*(v+60)) 31 | 32 | def alphaH(v): 33 | return 0.07*np.exp(-0.05*(v+60)) 34 | 35 | def betaH(v): 36 | return 1/(1+np.exp(-(0.1)*(v+30))) 37 | 38 | v[0] = -65 39 | m[0] = alphaM(v[0])/(alphaM(v[0])+betaM(v[0])) 40 | n[0] = alphaN(v[0])/(alphaN(v[0])+betaN(v[0])) 41 | h[0] = alphaH(v[0])/(alphaH(v[0])+betaH(v[0])) 42 | 43 | for i in range(1,len(t)): 44 | 45 | k1 = dt*(alphaN(v[i-1])*(1-n[i-1])-betaN(v[i-1])*n[i-1]) 46 | k2 = dt*(alphaN(v[i-1])*(1-(n[i-1]+0.5*k1))-betaN(v[i-1])*(n[i-1]+0.5*k1)) 47 | k3 = dt*(alphaN(v[i-1])*(1-(n[i-1]+0.5*k2))-betaN(v[i-1])*(n[i-1]+0.5*k2)) 48 | k4 = dt*(alphaN(v[i-1])*(1-(n[i-1]+k3)-betaN(v[i-1])*(n[i-1]+k3))) 49 | 50 | n[i] = n[i-1] + (1/6)*(k1 + 2*k2 + 2*k3 + k4) 51 | 52 | k1 = dt*(alphaM(v[i-1])*(1-m[i-1])-betaM(v[i-1])*m[i-1]) 53 | k2 = dt*(alphaM(v[i-1])*(1-(m[i-1]+0.5*k1))-betaM(v[i-1])*(m[i-1]+0.5*k1)) 54 | k3 = dt*(alphaM(v[i-1])*(1-(m[i-1]+0.5*k2))-betaM(v[i-1])*(m[i-1]+0.5*k2)) 55 | k4 = dt*(alphaM(v[i-1])*(1-(m[i-1]+k3)-betaM(v[i-1])*(m[i-1]+k3))) 56 | 57 | m[i] = m[i-1] + (1/6)*(k1 + 2*k2 + 2*k3 + k4) 58 | 59 | k1 = dt*(alphaH(v[i-1])*(1-h[i-1])-betaH(v[i-1])*h[i-1]) 60 | k2 = dt*(alphaH(v[i-1])*(1-(h[i-1]+0.5*k1))-betaH(v[i-1])*(h[i-1]+0.5*k1)) 61 | k3 = dt*(alphaH(v[i-1])*(1-(h[i-1]+0.5*k2))-betaH(v[i-1])*(h[i-1]+0.5*k2)) 62 | k4 = dt*(alphaH(v[i-1])*(1-(h[i-1]+k3)-betaH(v[i-1])*(h[i-1]+k3))) 63 | 64 | h[i] = h[i-1] + (1/6)*(k1 + 2*k2 + 2*k3 + k4) 65 | 66 | gNa = g_Na*h[i-1]*(m[i-1])**3 67 | gK = g_K*n[i-1]**4 68 | gl = g_l 69 | INa = gNa*(v[i-1]-ENa) 70 | IK = gK*(v[i-1]-EK) 71 | Il = gl*(v[i-1]-El) 72 | k1 = dt*((1./Cm)*(I-(INa+IK+Il))) 73 | k2 = dt*((1./Cm)*(I-(INa+IK+Il) + 0.5*k1)) 74 | k3 = dt*((1./Cm)*(I-(INa+IK+Il) + 0.5*k2)) 75 | k4 = dt*((1./Cm)*(I-(INa+IK+Il) + k3)) 76 | 77 | v[i] = v[i-1] + (1./6.)*(k1 + 2.*k2 + 2.*k3 + k4) 78 | 79 | 80 | #Plot the data 81 | plt.figure(figsize=(10,12)) 82 | plt.legend(loc='upper left') 83 | plt.title('Hodgkin Huxely Model Rung-Kutta method') 84 | plt.subplot(2,1,1) 85 | plt.plot(t,v,'b-',label='voltage') 86 | plt.legend(loc='upper left') 87 | plt.xlabel('time (ms)') 88 | plt.ylabel('Voltage') 89 | plt.subplot(2,1,2) 90 | plt.plot(t,n,'y-') 91 | plt.xlabel('time') 92 | plt.plot(t,m,'m-') 93 | plt.xlabel('time') 94 | plt.plot(t,h,'r-') 95 | plt.xlabel('time') 96 | plt.ylabel('Gates') 97 | plt.legend(['n channel', 'm channel', 'h channel']) 98 | #plt.savefig('HH model Rung-Kutta method.png',transparent=True) 99 | plt.show() 100 | -------------------------------------------------------------------------------- /HH_plotly.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import plotly.graph_objects as go 4 | 5 | 6 | def HHmodel(mean = 0, length = 500, area = 1.0, mode = 'noisy', std = 5): 7 | 8 | if (mode == 'noisy'): 9 | I = np.random.normal(mean,std,length) 10 | if (mode == 'clean'): 11 | I = np.ones(length) * mean 12 | v = np.zeros(length) 13 | m = np.zeros(length) 14 | h = np.zeros(length) 15 | n = np.zeros(length) 16 | dt = 0.05 17 | t = np.linspace(0,100,length) 18 | 19 | #meandiff_sq = np.zeros(length) 20 | 21 | #constants 22 | Cm = area#microFarad 23 | ENa=50 #miliVolt 24 | EK=-77 #miliVolt 25 | El=-54 #miliVolt 26 | g_Na=120*area #mScm-2 27 | g_K=36*area #mScm-2 28 | g_l=0.03*area #mScm-2 29 | 30 | def alphaN(v): 31 | return 0.01*(v+50)/(1-np.exp(-(v+50)/10)) 32 | 33 | def betaN(v): 34 | return 0.125*np.exp(-(v+60)/80) 35 | 36 | def alphaM(v): 37 | return 0.1*(v+35)/(1-np.exp(-(v+35)/10)) 38 | 39 | def betaM(v): 40 | return 4.0*np.exp(-0.0556*(v+60)) 41 | 42 | def alphaH(v): 43 | return 0.07*np.exp(-0.05*(v+60)) 44 | 45 | def betaH(v): 46 | return 1/(1+np.exp(-(0.1)*(v+30))) 47 | 48 | #Initialize the voltage and the channels : 49 | v[0] = -60 50 | m[0] = alphaM(v[0])/(alphaM(v[0])+betaM(v[0])) 51 | n[0] = alphaN(v[0])/(alphaN(v[0])+betaN(v[0])) 52 | h[0] = alphaH(v[0])/(alphaH(v[0])+betaH(v[0])) 53 | 54 | #solving ODE using Euler's method: 55 | for i in range(1,length): 56 | m[i] = m[i-1] + dt*((alphaM(v[i-1])*(1-m[i-1]))-betaM(v[i-1])*m[i-1]) 57 | n[i] = n[i-1] + dt*((alphaN(v[i-1])*(1-n[i-1]))-betaN(v[i-1])*n[i-1]) 58 | h[i] = h[i-1] + dt*((alphaH(v[i-1])*(1-h[i-1]))-betaH(v[i-1])*h[i-1]) 59 | gNa = g_Na * h[i-1]*(m[i-1])**3 60 | gK=g_K*n[i-1]**4 61 | gl=g_l 62 | INa = gNa*(v[i-1]-ENa) 63 | IK = gK*(v[i-1]-EK) 64 | Il= gl * (v[i-1]-El) 65 | v[i] = v[i-1] + (dt*((1/Cm)*(I[i-1]-(INa+IK+Il)))) 66 | 67 | return v 68 | 69 | # Create figure 70 | fig = go.Figure() 71 | 72 | # Add traces, one for each slider step 73 | for step in np.arange(1, 20, 0.1): 74 | fig.add_trace( 75 | go.Scatter( 76 | visible=False, 77 | line=dict(color="#00CED1", width=1), 78 | name= "I: "+ str(step), 79 | #x = np.arange(0, 20, 0.1), 80 | #y = np.sin(step * np.arange(0, 10, 0.01)))) 81 | y = HHmodel(step, length =500, mode = 'clean'))) 82 | 83 | # Make 10th trace visible 84 | fig.data[10].visible = True 85 | 86 | # Create and add slider 87 | steps = [] 88 | for i in range(len(fig.data)): 89 | step = dict( 90 | method="update", 91 | args=[{"visible": [False] * len(fig.data)}, 92 | {"title": "Input Current (mA): " + str(i/10)}], # layout attribute 93 | ) 94 | step["args"][0]["visible"][i] = True # Toggle i'th trace to "visible" 95 | steps.append(step) 96 | 97 | sliders = [dict( 98 | active=10, 99 | currentvalue={"prefix": "Input Current: "}, 100 | pad={"t": 50}, 101 | steps=steps 102 | )] 103 | 104 | fig.update_layout( 105 | sliders=sliders 106 | ) 107 | 108 | fig.show() 109 | -------------------------------------------------------------------------------- /noisyInput.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | 5 | def HHmodel(I,length): 6 | #holders 7 | v = [] 8 | m = [] 9 | h = [] 10 | n = [] 11 | dt = 0.05 12 | t = np.linspace(0,100,length) 13 | 14 | #constants 15 | Cm = 1.0 #microFarad 16 | ENa=50 #miliVolt 17 | EK=-77 #miliVolt 18 | El=-54 #miliVolt 19 | g_Na=120 #mScm-2 20 | g_K=36 #mScm-2 21 | g_l=0.03 #mScm-2 22 | 23 | def alphaN(v): 24 | return 0.01*(v+50)/(1-np.exp(-(v+50)/10)) 25 | 26 | def betaN(v): 27 | return 0.125*np.exp(-(v+60)/80) 28 | 29 | def alphaM(v): 30 | return 0.1*(v+35)/(1-np.exp(-(v+35)/10)) 31 | 32 | def betaM(v): 33 | return 4.0*np.exp(-0.0556*(v+60)) 34 | 35 | def alphaH(v): 36 | return 0.07*np.exp(-0.05*(v+60)) 37 | 38 | def betaH(v): 39 | return 1/(1+np.exp(-(0.1)*(v+30))) 40 | 41 | #Initialize the voltage and the channels : 42 | v.append(-60) 43 | m0 = alphaM(v[0])/(alphaM(v[0])+betaM(v[0])) 44 | n0 = alphaN(v[0])/(alphaN(v[0])+betaN(v[0])) 45 | h0 = alphaH(v[0])/(alphaH(v[0])+betaH(v[0])) 46 | 47 | #t.append(0) 48 | m.append(m0) 49 | n.append(n0) 50 | h.append(h0) 51 | 52 | #solving ODE using Euler's method: 53 | for i in range(1,len(t)): 54 | m.append(m[i-1] + dt*((alphaM(v[i-1])*(1-m[i-1]))-betaM(v[i-1])*m[i-1])) 55 | n.append(n[i-1] + dt*((alphaN(v[i-1])*(1-n[i-1]))-betaN(v[i-1])*n[i-1])) 56 | h.append(h[i-1] + dt*((alphaH(v[i-1])*(1-h[i-1]))-betaH(v[i-1])*h[i-1])) 57 | gNa = g_Na * h[i-1]*(m[i-1])**3 58 | gK=g_K*n[i-1]**4 59 | gl=g_l 60 | INa = gNa*(v[i-1]-ENa) 61 | IK = gK*(v[i-1]-EK) 62 | Il=gl*(v[i-1]-El) 63 | v.append(v[i-1]+(dt)*((1/Cm)*(I[i-1]-(INa+IK+Il)))) 64 | #v.append(v[i-1]+(dt)*((1/Cm)*(I-(INa+IK+Il)))) 65 | return v,t 66 | 67 | 68 | 69 | spikeEvents = [] #timing each spike 70 | length = 1000000*5 #the time period 71 | barcode = np.zeros(length) 72 | noisyI = np.random.normal(0,9,length) 73 | v,t = HHmodel(noisyI,length) 74 | #to count the spikes: 75 | for i in range(1,len(v)): 76 | if (v[i-1] < 0 and v[i] > 0): 77 | spikeEvents.append(round(t[i],3)) 78 | 79 | timeDistribution = [] #to distributing time 80 | for i in range(len(spikeEvents)): 81 | timeDistribution.append(spikeEvents[i]-spikeEvents[i-1]) 82 | #print(spikeEvents) 83 | max(timeDistribution) 84 | timeDistribution = sorted(timeDistribution) 85 | timeDistribution[0] = 0 86 | #plt.scatter(range(len(timeDistribution)),timeDistribution); 87 | len(spikeEvents) 88 | x = range(len(spikeEvents)) 89 | np.mean(spikeEvents) 90 | np.std(spikeEvents) 91 | round((np.std(spikeEvents)/np.mean(spikeEvents)),4) 92 | np.var(spikeEvents) 93 | 94 | plt.figure(figsize=(20,30)) 95 | plt.legend(loc='upper left') 96 | plt.title('Hodgkin Huxely Spike Model with noisy input') 97 | plt.subplot(3,1,1) 98 | plt.plot(t,v,label='voltage with noisy input'); 99 | plt.ylabel('voltage') 100 | plt.legend(loc='upper left') 101 | plt.title('Hodgkin Huxely Spike Model with noisy input') 102 | plt.subplot(3,1,2) 103 | plt.eventplot(spikeEvents,label='Spike events',colors='red'); 104 | plt.legend(loc='upper left') 105 | plt.xlabel('time (ms)') 106 | plt.ylabel('Spikes') 107 | plt.subplot(3,1,3) 108 | plt.hist(timeDistribution,50,label='spike time distribution') 109 | plt.legend(loc='upper left'); 110 | plt.savefig('spikes_random_noise.png') 111 | plt.show() 112 | print('Done.') 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HodgkinHuxely-Spiking 2 | 3 | A Model to simulate neuronal spiking based on Hodgkin Huxley model 4 | 5 | The Hodgkin–Huxley model, or conductance-based model, is a mathematical model that describes 6 | how action potentials in neurons are initiated and propagated. It is a set of nonlinear differential equations 7 | that approximates the electrical characteristics of excitable cells such as neurons and cardiac myocytes. 8 | Alan Lloyd Hodgkin and Andrew Fielding Huxley described the model in 1952 to explain the ionic mechanisms underlying the initiation and propagation of action potentials in the squid giant axon.[1] They received the 1963 Nobel Prize in Physiology or Medicine for this work. 9 | 10 | ![Plotly](images/plotly.png) 11 | 12 | ![finalPlot](https://user-images.githubusercontent.com/13776994/57675235-957fc100-7636-11e9-98be-a7415e59da7c.png) 13 | 14 | # Noisy Input 15 | Neuronal noise or neural noise refers to the random intrinsic electrical fluctuations within neuronal networks. These fluctuations are not associated with encoding a response to internal or external stimuli and can be from one to two orders of magnitude.[1] Most noise commonly occurs below a voltage-threshold that is needed for an action potential to occur, but sometimes it can be present in the form of an action potential; for example, stochastic oscillations in pacemaker neurons in suprachiasmatic nucleus are partially responsible for the organization of circadian rhythms.[2][3] 16 | 17 | ![spikes_random_noise](https://user-images.githubusercontent.com/13776994/58783163-88327280-85f5-11e9-8c39-f9da61eb33b3.png) 18 | 19 | 20 | # Coupled Neuron with Noisy Inputs 21 | Ephaptic coupling is a form of communication within the nervous system and is distinct from direct communication systems like electrical synapses and chemical synapses. It may refer to the coupling of adjacent (touching) nerve fibers caused by the exchange of ions between the cells, or it may refer to coupling of nerve fibers as a result of local electric fields.[5] In either case ephaptic coupling can influence the synchronization and timing of action potential firing in neurons. Myelination is thought to inhibit ephaptic interactions.[6] 22 | 23 | ![coupledNeuron](https://user-images.githubusercontent.com/13776994/61179897-d2aa0480-a621-11e9-83ab-3955643544dd.png) 24 | 25 | # Model 2:[7] 26 | Screen Shot 2019-08-14 at 11 49 32 27 | 28 | ![coupledNeuron](https://user-images.githubusercontent.com/13776994/63001573-2611ab80-be89-11e9-873d-c0e69a54b8fd.png) 29 | 30 | # Connected Neuron using Nest Library(LIF model): 31 | ![connectedNeuron](https://user-images.githubusercontent.com/13776994/63207613-661d9c00-c0de-11e9-8594-e5db80b8de35.png) 32 | 33 | 34 | # refrences 35 | [1] Hodgkin AL, Huxley AF (August 1952). "A quantitative description of membrane current and its application to conduction and excitation in nerve". The Journal of Physiology. 117 (4): 500–44. doi:10.1113/jphysiol.1952.sp004764. PMC 1392413. PMID 12991237. 36 | 37 | [2] Jacobson, G. A. (2005). "Subthreshold voltage noise of rat neocortical pyramidal neurones". J Physiol. 564 (Pt 1): 145–160. doi:10.1113/jphysiol.2004.080903. PMC 1456039. PMID 15695244. 38 | 39 | [3] Ko, C. H. (2010). "Emergence of Noise-Induced Oscillations in the Central Circadian Pacemaker". PLOS Biology. 8 (10): e1000513. doi:10.1371/journal.pbio.1000513. PMC 2953532. PMID 20967239. 40 | 41 | [4] Mazzoni, E. O. (2005). "Circadian Pacemaker Neurons Transmit and Modulate Visual Information to Control a Rapid Behavioral Response". Neuron. 45 (2): 293–300. doi:10.1016/j.neuron.2004.12.038. PMID 15664180. 42 | 43 | [5] Aur D., Jog, MS. (2010) Neuroelectrodynamics: Understanding the brain language, IOS Press, doi:10.3233/978-1-60750-473-3-i 44 | 45 | [6] Hartline DK (May 2008). "What is myelin?". Neuron Glia Biol. 4 (2): 153–63. doi:10.1017/S1740925X09990263. PMID 19737435. 46 | 47 | [7] Flexible resonance in prefrontal networks with strong feedback inhibition, https://doi.org/10.1371/journal.pcbi.1006357 48 | --------------------------------------------------------------------------------