#!/usr/bin/env python
# coding: utf-8
# # Action Potential Tutorial
# ## - from passive membrane to Hodgkin-Huxley model
#
# ##### Developed in the Neural Engineering Laboratory at the University of Missouri by Ben Latimer & Ziao Chen
#
#
#
# ## Introduction videos of neurobiology basics
#
# Note: This will not work inside the NeuroLab browser.If the videos below do not play, please visit https://youtu.be/ in your native browser.
# In[ ]:
from IPython.display import HTML,YouTubeVideo
YouTubeVideo('PtKAeihnbv0')
# In[ ]:
YouTubeVideo('RTRZNK9Aahc')
# In[ ]:
YouTubeVideo('U0NpTdge3aw')
# ### In this tutorial, we'll explore the properties of the cell membrane and the mechanisms of the action potential. We'll introduce you how to simulate a cell in the NEURON + Python environment. If this is your first time coding, don't worry! Just click the "Run" button above to go through step-by-step. You don't need to change anything yet.
#
# ### Before you start any project, you need to get the tools. In Python, we do this using the "import" statement in the cell below. Click "Run" to proceed.
# In[1]:
from neuron import h
h.load_file('stdrun.hoc')
# ## 1) Create the cell and define its geometry
#
# ### NEURON defines a cell as a cylinder. Remember, cells in NEURON are simplified. We will make a one-compartment cell which is just a cylinder with length and diameter.
#
#
# In[2]:
#Create the soma section and define the default parameters
soma = h.Section(name='soma')
soma.diam = 200 # micrometers
soma.L = 100 # micrometers
# ## 2) Define the cell's biophysics
#
# ### Insert the Hodgkin-Huxley channels and define the conductance. First let's make a passive cell by setting the conductances of the active channels (gNa,gK) to 0.
# In[3]:
soma.cm = 1.4884e-4/6.2832e-4 # membrane capacitance uF/cm2
soma.insert('hh')
soma.gnabar_hh = 0 # Sodium channel
soma.gkbar_hh = 0 # Potassium channel
soma.gl_hh = 2.0e-5 # leak channel S/cm2
soma.el_hh = -70 # reveral potential mV
h.v_init= -60
# ## 3) Inject Current
#
# ### Neuroscientists call this experiment a "current clamp". We place an electrode into the cell and inject current.
# In[4]:
# Inject current in the middle of the soma
stim = h.IClamp(soma(0.5))
stim.delay = 100.0 # delay in ms
stim.dur = 500.0 # duration in ms
stim.amp = 1.0 # amplitude in nA
# ## 4) Define simulation parameters and run!
# In[5]:
h.tstop = tstop = 800 # how long to run the simulation in ms
h.dt = 0.025 # time step (resolution) of the simulation in ms
# define two vectors for recording variables
v0_vec = h.Vector()
t_vec = h.Vector()
# record the voltage (_ref_v) and time (_ref_t) into the vectors we just created
v0_vec.record(soma(0.5)._ref_v)
t_vec.record(h._ref_t)
h.run()
# ## 5) Visualize the membrane potential
#
# ### The data isn't going to visualize itself! We use a package called matplotlib to draw the vectors so we can see them.
# In[6]:
# use inline plot
get_ipython().run_line_magic('matplotlib', 'inline')
# use interactive plot
# %matplotlib notebook
import matplotlib.pyplot as plt # We use this package for visualization
plt.figure()
plt.plot(t_vec, v0_vec,'b')
plt.xlim(0, tstop)
plt.xlabel('time (ms)')
plt.ylabel('mV')
plt.show()
# ## 6) Get some action potentials!
#
# ### We will make the conductances of the active channels nonzero so that we will see some action potentials.
# In[7]:
soma.gnabar_hh = 0.12 # Sodium channel S/cm2
soma.gkbar_hh = 0.012 # Potassium channel S/cm2
stim.delay = 100.0 # delay in ms
stim.dur = 150.0 # duration in ms
stim.amp = 0.03 # amplitude in nA
h.tstop = tstop = 350
# run the simulation!
h.run()
plt.figure(figsize=(10,5))
plt.plot(t_vec, v0_vec,'b')
plt.xlim(0, tstop)
plt.xlabel('time (ms)')
plt.ylabel('mV')
plt.show()
# ## 7) Record the gating variables
#
# ### You should see some spikes in the plot above. If you don't, go back to the top of the notebook and run all the cells again. Neurons spike because of the voltage dependent proteins embedded in their membranes. Let's record those and then plot them just as we did for the membrane voltage.
# In[8]:
m_na = h.Vector()
h_na = h.Vector()
n_k = h.Vector()
m_na.record(soma(0.5)._ref_m_hh)
h_na.record(soma(0.5)._ref_h_hh)
n_k.record(soma(0.5)._ref_n_hh)
h.run()
# ## 8) Visualize membrane potential and gating variables together
# ### This should look familiar. We're just going to plot all of the variables we just recorded at the same time so we can investigate how spikes occur.
# In[9]:
plt.figure(figsize=(10,10))
plt.subplot(2,1,1)
plt.plot(t_vec, v0_vec,'b')
plt.xlim(0, tstop)
plt.ylabel('mV')
plt.subplot(2,1,2)
plt.plot(t_vec, m_na,'r')
plt.plot(t_vec, h_na,'b')
plt.plot(t_vec, n_k, 'g')
plt.xlim(0, tstop)
plt.xlabel('time (ms)')
plt.ylabel('Probability')
plt.legend(['m','h','n'])
plt.show()
# ### You did it! Now you understand how a neuron is implemented in code. Time for the hard part... understanding the science and math behind those spikes. You can move on to the next section and change variables (such as the conductances of the Na and K channels) using the interactive controls to see the effects.
#
# ## 9) Interact with the model
#
# ##### So far, we've built the cell and simulated it with one set of parameters. But what if we want to change the parameters to see the effect on the output? In this part of the tutorial, we'll set the model up and then use sliders to interact with the parameters. Don't worry about all the code that's coming up, it's just a repeat of what we've already done.
# In[ ]:
from neuron import h
import ipywidgets as widgets
from ipywidgets import HBox,VBox,Label,Layout
from IPython.display import display
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
h.load_file('stdrun.hoc')
soma = h.Section(name='soma')
soma.L = 100 # um
soma.insert('hh')
stim = h.IClamp(soma(0.5))
v0_vec = h.Vector()
t_vec = h.Vector()
m_na = h.Vector()
h_na = h.Vector()
n_k = h.Vector()
m_na.record(soma(0.5)._ref_m_hh)
h_na.record(soma(0.5)._ref_h_hh)
n_k.record(soma(0.5)._ref_n_hh)
v0_vec.record(soma(0.5)._ref_v)
t_vec.record(h._ref_t)
def activemodel(diam,cm,el,gl,gna,gk,tstop,dur,amp,fig):
soma.diam = diam
soma.cm = cm*1.4884e-4/6.2832e-4
soma.gnabar_hh = gna*1e-3
soma.gkbar_hh = gk*1e-3
soma.gl_hh = gl*1e-6
soma.el_hh = el
stim.delay = dur[0]
stim.dur = dur[1]-dur[0]
stim.amp = amp
h.tstop = tstop
h.v_init = el
h.run()
plt.close()
plt.figure(figsize=(12,10))
plt.subplot(2,1,1)
plt.plot(t_vec, v0_vec,'b')
plt.xlim(0, tstop)
plt.ylabel('mV')
plt.legend('V')
plt.subplot(2,1,2)
plt.plot(t_vec, m_na,'r')
plt.plot(t_vec, h_na,'b')
plt.plot(t_vec, n_k, 'g')
plt.xlim(0, tstop)
plt.xlabel('time (ms)')
plt.ylabel('Probability')
plt.legend(['m','h','n'])
plt.show()
# In[ ]:
# default settings
diam = 200
cm = 1
el = -70
gl = 30
gna0 = 120
gk0 = 12
tstop = 500
dur = [100,400]
amp = 0.1
w_reset = widgets.Button(description='Reset',icon='history',button_style='primary')
w_fig = widgets.ToggleButton(value=False,description='Interactive plot',icon='window-restore',button_style='success')
w_pass = widgets.ToggleButton(value=False,icon='check',button_style='info')
w_el = widgets.FloatSlider(value=el,min=-80,max=-60,step=.2,continuous_update=False,readout_format='.1f')
w_gl = widgets.FloatSlider(value=gl,min=5,max=50,step=.2,continuous_update=False,readout_format='.1f')
w_gna = widgets.FloatSlider(value=gna0,min=0,max=200,step=.5,continuous_update=False,readout_format='.1f')
w_gk = widgets.FloatSlider(value=gk0,min=0,max=30,step=.1,continuous_update=False,readout_format='.1f')
w_tstop = widgets.FloatText(value=tstop)
w_dur = widgets.FloatRangeSlider(value=dur,min=0,max=500,step=5,continuous_update=False,readout_format='.0f')
w_amp = widgets.FloatLogSlider(value=amp,min=-3,max=1,step=.04,continuous_update=False,readout_format='.3f')
w_diam = widgets.FloatSlider(value=diam,min=100,max=300,step=2,continuous_update=False,readout_format='.0f')
w_cm = widgets.FloatLogSlider(value=cm,min=-1,max=1,step=.05,continuous_update=False,readout_format='.1f')
def reset_default(*args):
w_pass.value = False
w_el.value = el; w_gl.value = gl
w_gna.value = gna0; w_gk.value = gk0
w_gna.disabled = w_gk.disabled = False
w_dur.max = w_tstop.value = tstop; w_dur.value = dur
w_diam.value = diam; w_cm.value = cm
w_reset.on_click(reset_default)
def interactive_fig(*arg):
if w_fig.value:
w_fig.icon = 'window-maximize'; w_fig.description='Inline plot'
get_ipython().run_line_magic('matplotlib', 'notebook')
get_ipython().run_line_magic('matplotlib', 'notebook')
else:
w_fig.icon = 'window-restore'; w_fig.description='Interactive plot'
get_ipython().run_line_magic('matplotlib', 'inline')
w_fig.observe(interactive_fig,'value')
def update_pass(*args):
if w_pass.value:
global gna,gk
gna = w_gna.value
gk = w_gk.value
w_gna.value = w_gk.value = 0
w_gna.disabled = w_gk.disabled = True
else:
w_gna.value = gna
w_gk.value = gk
w_gna.disabled = w_gk.disabled = False
w_pass.observe(update_pass,'value')
def update_dur(*args):
w_dur.max = w_tstop.value
w_tstop.observe(update_dur,'value')
ui = VBox([HBox([w_reset,w_fig]), HBox([VBox([Label('Passive Cell'),Label(r'\( E_{l}\ (mV) \)'),Label(r'\( g_{leak}\ (\mu S/cm^2) \)'),
Label(r'\( g_{Na}\ (mS/cm^2) \)'),Label(r'\( g_{K}\ (mS/cm^2) \)')],layout=Layout(width='14%')),
VBox([w_pass,w_el,w_gl,w_gna,w_gk],layout=Layout(width='36%')),
VBox([Label(r'\( tstop\ (ms) \)'),Label(r'\( Injection\ duration\ (ms) \)'),Label(r'\( I_{inject}\ (nA) \)'),
Label(r'\( soma\ diameter\ (\mu m) \)'),Label(r'\( capacitance\ scale \)')],layout=Layout(width='14%')),
VBox([w_tstop,w_dur,w_amp,w_diam,w_cm],layout=Layout(width='36%')) ]) ])
out = widgets.interactive_output(activemodel,{'el':w_el,'gl':w_gl,'gna':w_gna,'gk':w_gk,
'tstop':w_tstop,'dur':w_dur,'amp':w_amp,'diam':w_diam,'cm':w_cm,'fig':w_fig})
display(ui,out)
# In[ ]: