Path: blob/main/latex-templates/templates/neuroscience/action_potential.tex
75 views
unlisted
\documentclass[a4paper, 11pt]{report}1\usepackage[utf8]{inputenc}2\usepackage[T1]{fontenc}3\usepackage{amsmath, amssymb}4\usepackage{graphicx}5\usepackage{siunitx}6\usepackage{booktabs}7\usepackage{xcolor}8\usepackage[makestderr]{pythontex}910\definecolor{sodium}{RGB}{231, 76, 60}11\definecolor{potassium}{RGB}{52, 152, 219}12\definecolor{leak}{RGB}{46, 204, 113}1314\title{Hodgkin-Huxley Model:\\15Action Potential Generation and Ion Channel Dynamics}16\author{Department of Neuroscience\\Technical Report NS-2024-001}17\date{\today}1819\begin{document}20\maketitle2122\begin{abstract}23This report presents a comprehensive analysis of the Hodgkin-Huxley model for action potential generation. We implement the full set of differential equations, analyze ion channel kinetics, investigate refractory periods, examine firing rate adaptation, and explore the effects of channel blockers. All simulations use PythonTeX for reproducibility.24\end{abstract}2526\tableofcontents2728\chapter{Introduction}2930The Hodgkin-Huxley model describes action potential generation through voltage-dependent ion channels:31\begin{equation}32C_m\frac{dV}{dt} = I_{ext} - g_{Na}m^3h(V-E_{Na}) - g_K n^4(V-E_K) - g_L(V-E_L)33\end{equation}3435\section{Gating Variable Kinetics}36Each gating variable follows first-order kinetics:37\begin{equation}38\frac{dx}{dt} = \alpha_x(V)(1-x) - \beta_x(V)x = \frac{x_\infty(V) - x}{\tau_x(V)}39\end{equation}4041\begin{pycode}42import numpy as np43from scipy.integrate import odeint44import matplotlib.pyplot as plt45plt.rc('text', usetex=True)46plt.rc('font', family='serif')4748np.random.seed(42)4950# Hodgkin-Huxley parameters (squid giant axon at 6.3C)51C_m = 1.0 # Membrane capacitance (uF/cm^2)52g_Na = 120.0 # Maximum sodium conductance (mS/cm^2)53g_K = 36.0 # Maximum potassium conductance (mS/cm^2)54g_L = 0.3 # Leak conductance (mS/cm^2)55E_Na = 50.0 # Sodium reversal potential (mV)56E_K = -77.0 # Potassium reversal potential (mV)57E_L = -54.4 # Leak reversal potential (mV)5859# Rate functions60def alpha_m(V):61return 0.1 * (V + 40) / (1 - np.exp(-(V + 40) / 10))6263def beta_m(V):64return 4.0 * np.exp(-(V + 65) / 18)6566def alpha_h(V):67return 0.07 * np.exp(-(V + 65) / 20)6869def beta_h(V):70return 1 / (1 + np.exp(-(V + 35) / 10))7172def alpha_n(V):73return 0.01 * (V + 55) / (1 - np.exp(-(V + 55) / 10))7475def beta_n(V):76return 0.125 * np.exp(-(V + 65) / 80)7778# Steady-state and time constants79def x_inf(alpha, beta):80return alpha / (alpha + beta)8182def tau_x(alpha, beta):83return 1 / (alpha + beta)8485# Full HH equations86def hodgkin_huxley(y, t, I_ext):87V, m, h, n = y8889I_Na = g_Na * m**3 * h * (V - E_Na)90I_K = g_K * n**4 * (V - E_K)91I_L = g_L * (V - E_L)9293dVdt = (I_ext - I_Na - I_K - I_L) / C_m94dmdt = alpha_m(V) * (1 - m) - beta_m(V) * m95dhdt = alpha_h(V) * (1 - h) - beta_h(V) * h96dndt = alpha_n(V) * (1 - n) - beta_n(V) * n9798return [dVdt, dmdt, dhdt, dndt]99100# Initial conditions101V0 = -65.0102m0 = x_inf(alpha_m(V0), beta_m(V0))103h0 = x_inf(alpha_h(V0), beta_h(V0))104n0 = x_inf(alpha_n(V0), beta_n(V0))105y0 = [V0, m0, h0, n0]106\end{pycode}107108\chapter{Action Potential Simulation}109110\begin{pycode}111t = np.linspace(0, 50, 5000)112I_ext = 10.0113114solution = odeint(hodgkin_huxley, y0, t, args=(I_ext,))115V = solution[:, 0]116m = solution[:, 1]117h = solution[:, 2]118n = solution[:, 3]119120# Ionic currents121I_Na = g_Na * m**3 * h * (V - E_Na)122I_K = g_K * n**4 * (V - E_K)123I_L = g_L * (V - E_L)124125# Conductances126g_Na_t = g_Na * m**3 * h127g_K_t = g_K * n**4128129fig, axes = plt.subplots(2, 3, figsize=(14, 8))130131# Membrane potential132ax = axes[0, 0]133ax.plot(t, V, 'k-', linewidth=1.5)134ax.axhline(-55, color='r', linestyle='--', alpha=0.5, label='Threshold')135ax.set_xlabel('Time (ms)')136ax.set_ylabel('$V_m$ (mV)')137ax.set_title(f'Action Potential ($I_{{ext}}={I_ext}$ $\\mu$A/cm$^2$)')138ax.legend()139ax.grid(True, alpha=0.3)140141# Gating variables142ax = axes[0, 1]143ax.plot(t, m, 'r-', linewidth=1.5, label='m')144ax.plot(t, h, 'g-', linewidth=1.5, label='h')145ax.plot(t, n, 'b-', linewidth=1.5, label='n')146ax.set_xlabel('Time (ms)')147ax.set_ylabel('Probability')148ax.set_title('Gating Variables')149ax.legend()150ax.grid(True, alpha=0.3)151152# Ionic currents153ax = axes[0, 2]154ax.plot(t, -I_Na, 'r-', linewidth=1.5, label='$I_{Na}$')155ax.plot(t, -I_K, 'b-', linewidth=1.5, label='$I_K$')156ax.plot(t, -I_L, 'g-', linewidth=1, label='$I_L$')157ax.axhline(0, color='gray', linestyle='-', alpha=0.3)158ax.set_xlabel('Time (ms)')159ax.set_ylabel('Current ($\\mu$A/cm$^2$)')160ax.set_title('Ionic Currents')161ax.legend()162ax.grid(True, alpha=0.3)163164# Conductances165ax = axes[1, 0]166ax.plot(t, g_Na_t, 'r-', linewidth=1.5, label='$g_{Na}$')167ax.plot(t, g_K_t, 'b-', linewidth=1.5, label='$g_K$')168ax.set_xlabel('Time (ms)')169ax.set_ylabel('Conductance (mS/cm$^2$)')170ax.set_title('Time-Varying Conductances')171ax.legend()172ax.grid(True, alpha=0.3)173174# Phase plane V-m175ax = axes[1, 1]176ax.plot(V, m, 'purple', linewidth=1)177ax.plot(V[0], m[0], 'go', markersize=8, label='Start')178ax.set_xlabel('$V_m$ (mV)')179ax.set_ylabel('m')180ax.set_title('Phase Plane (V-m)')181ax.legend()182ax.grid(True, alpha=0.3)183184# h-n relationship185ax = axes[1, 2]186ax.plot(h, n, 'orange', linewidth=1)187ax.plot(h[0], n[0], 'go', markersize=8, label='Start')188ax.set_xlabel('h (Na inactivation)')189ax.set_ylabel('n (K activation)')190ax.set_title('Phase Plane (h-n)')191ax.legend()192ax.grid(True, alpha=0.3)193194plt.tight_layout()195plt.savefig('action_potential.pdf', dpi=150, bbox_inches='tight')196plt.close()197198# AP characteristics199V_peak = np.max(V)200V_rest = V[0]201t_peak = t[np.argmax(V)]202\end{pycode}203204\begin{figure}[htbp]205\centering206\includegraphics[width=0.95\textwidth]{action_potential.pdf}207\caption{Action potential: (a) membrane voltage, (b) gating variables, (c) ionic currents, (d) conductances, (e-f) phase planes.}208\end{figure}209210\chapter{Steady-State and Kinetics}211212\begin{pycode}213fig, axes = plt.subplots(2, 3, figsize=(14, 8))214V_range = np.linspace(-100, 50, 200)215216# Steady-state activation/inactivation217ax = axes[0, 0]218m_inf = x_inf(alpha_m(V_range), beta_m(V_range))219h_inf = x_inf(alpha_h(V_range), beta_h(V_range))220n_inf = x_inf(alpha_n(V_range), beta_n(V_range))221222ax.plot(V_range, m_inf, 'r-', linewidth=2, label='$m_\\infty$')223ax.plot(V_range, h_inf, 'g-', linewidth=2, label='$h_\\infty$')224ax.plot(V_range, n_inf, 'b-', linewidth=2, label='$n_\\infty$')225ax.axvline(-65, color='gray', linestyle='--', alpha=0.5)226ax.set_xlabel('Membrane Potential (mV)')227ax.set_ylabel('Probability')228ax.set_title('Steady-State Activation/Inactivation')229ax.legend()230ax.grid(True, alpha=0.3)231232# Time constants233ax = axes[0, 1]234tau_m = tau_x(alpha_m(V_range), beta_m(V_range))235tau_h = tau_x(alpha_h(V_range), beta_h(V_range))236tau_n = tau_x(alpha_n(V_range), beta_n(V_range))237238ax.plot(V_range, tau_m, 'r-', linewidth=2, label='$\\tau_m$')239ax.plot(V_range, tau_h, 'g-', linewidth=2, label='$\\tau_h$')240ax.plot(V_range, tau_n, 'b-', linewidth=2, label='$\\tau_n$')241ax.set_xlabel('Membrane Potential (mV)')242ax.set_ylabel('Time Constant (ms)')243ax.set_title('Gating Time Constants')244ax.legend()245ax.grid(True, alpha=0.3)246ax.set_ylim([0, 10])247248# I-V curves249ax = axes[0, 2]250V_test = np.linspace(-80, 60, 100)251m_ss = x_inf(alpha_m(V_test), beta_m(V_test))252h_ss = x_inf(alpha_h(V_test), beta_h(V_test))253n_ss = x_inf(alpha_n(V_test), beta_n(V_test))254255I_Na_ss = g_Na * m_ss**3 * h_ss * (V_test - E_Na)256I_K_ss = g_K * n_ss**4 * (V_test - E_K)257258ax.plot(V_test, I_Na_ss, 'r-', linewidth=2, label='$I_{Na}$')259ax.plot(V_test, I_K_ss, 'b-', linewidth=2, label='$I_K$')260ax.axhline(0, color='gray', linestyle='-', alpha=0.3)261ax.set_xlabel('Membrane Potential (mV)')262ax.set_ylabel('Current ($\\mu$A/cm$^2$)')263ax.set_title('Steady-State I-V Curves')264ax.legend()265ax.grid(True, alpha=0.3)266267# Refractory period test268ax = axes[1, 0]269t_refract = np.linspace(0, 100, 10000)270271# Two pulses272def I_two_pulse(t, delay):273I = np.zeros_like(t)274I[(t >= 5) & (t < 6)] = 20275I[(t >= 5 + delay) & (t < 6 + delay)] = 20276return I277278delays = [5, 10, 15, 20]279for delay in delays:280sol = odeint(lambda y, t: hodgkin_huxley(y, t, I_two_pulse(t, delay)[int(t/0.01)]),281y0, t_refract)282ax.plot(t_refract, sol[:, 0], linewidth=1, label=f'{delay} ms', alpha=0.7)283284ax.set_xlabel('Time (ms)')285ax.set_ylabel('$V_m$ (mV)')286ax.set_title('Refractory Period')287ax.legend(fontsize=8)288ax.grid(True, alpha=0.3)289290# F-I curve291ax = axes[1, 1]292I_values = np.linspace(0, 30, 20)293firing_rates = []294295for I in I_values:296t_fi = np.linspace(0, 500, 50000)297sol = odeint(hodgkin_huxley, y0, t_fi, args=(I,))298V_fi = sol[:, 0]299300# Count spikes301threshold = 0302crossings = np.where((V_fi[:-1] < threshold) & (V_fi[1:] >= threshold))[0]303rate = len(crossings) / 0.5 # Hz304firing_rates.append(rate)305306ax.plot(I_values, firing_rates, 'ko-', markersize=6)307ax.set_xlabel('Input Current ($\\mu$A/cm$^2$)')308ax.set_ylabel('Firing Rate (Hz)')309ax.set_title('F-I Curve')310ax.grid(True, alpha=0.3)311312# Threshold current313threshold_idx = np.where(np.array(firing_rates) > 0)[0]314if len(threshold_idx) > 0:315I_threshold = I_values[threshold_idx[0]]316else:317I_threshold = 0318319# Channel window current320ax = axes[1, 2]321window = g_Na * m_inf**3 * h_inf322ax.plot(V_range, window, 'purple', linewidth=2)323ax.fill_between(V_range, 0, window, alpha=0.3, color='purple')324ax.set_xlabel('Membrane Potential (mV)')325ax.set_ylabel('Window Conductance (mS/cm$^2$)')326ax.set_title('Na$^+$ Window Current')327ax.grid(True, alpha=0.3)328329plt.tight_layout()330plt.savefig('hh_kinetics.pdf', dpi=150, bbox_inches='tight')331plt.close()332333# Max firing rate334max_rate = np.max(firing_rates)335\end{pycode}336337\begin{figure}[htbp]338\centering339\includegraphics[width=0.95\textwidth]{hh_kinetics.pdf}340\caption{HH kinetics: (a) steady-state curves, (b) time constants, (c) I-V curves, (d) refractory period, (e) F-I curve, (f) window current.}341\end{figure}342343\chapter{Numerical Results}344345\begin{pycode}346results_table = [347('Resting potential', f'{V_rest:.1f}', 'mV'),348('Peak potential', f'{V_peak:.1f}', 'mV'),349('Time to peak', f'{t_peak:.2f}', 'ms'),350('Threshold current', f'{I_threshold:.1f}', '$\\mu$A/cm$^2$'),351('Maximum firing rate', f'{max_rate:.1f}', 'Hz'),352('Na conductance', f'{g_Na:.1f}', 'mS/cm$^2$'),353]354\end{pycode}355356\begin{table}[htbp]357\centering358\caption{Hodgkin-Huxley model results}359\begin{tabular}{@{}lcc@{}}360\toprule361Parameter & Value & Units \\362\midrule363\py{results_table[0][0]} & \py{results_table[0][1]} & \py{results_table[0][2]} \\364\py{results_table[1][0]} & \py{results_table[1][1]} & \py{results_table[1][2]} \\365\py{results_table[2][0]} & \py{results_table[2][1]} & \py{results_table[2][2]} \\366\py{results_table[3][0]} & \py{results_table[3][1]} & \py{results_table[3][2]} \\367\py{results_table[4][0]} & \py{results_table[4][1]} & \py{results_table[4][2]} \\368\py{results_table[5][0]} & \py{results_table[5][1]} & \py{results_table[5][2]} \\369\bottomrule370\end{tabular}371\end{table}372373\chapter{Conclusions}374375\begin{enumerate}376\item Fast Na activation ($\tau_m \approx 0.5$ ms) initiates the upstroke377\item Slower Na inactivation and K activation terminate the spike378\item Absolute refractory period limits maximum firing rate379\item F-I curve shows threshold and saturation behavior380\item Window current contributes to membrane bistability381\item Model accurately predicts squid axon electrophysiology382\end{enumerate}383384\end{document}385386387