技術メモ

役に立てる技術的な何か、時々自分用の覚書。幅広く興味があります。

2次元のランダムウォーク

import numpy as np
import matplotlib.pyplot as plt

time = 2000

state = np.zeros(2)
orbit = np.zeros(2)
for t in range(time):
    speed =  1
    randomvec = np.random.random(2) - 0.5
    randomvec *= speed/np.linalg.norm(randomvec)
    state += randomvec
    orbit = np.vstack([orbit, state])

orbit = orbit.T

plt.scatter(0, 0, color="r")
plt.plot(*orbit, lw=0.5)
plt.scatter(*state, color="r")
plt.axis("equal")
plt.show()

f:id:swdrsker:20170421210847p:plain

pythonを使ってFitzHugh南雲方程式のnullclineを描く

pythonでヌルクラインを描く方法
いくつか方法があるようだけど、matplotlibとscipyを組み合わせる方法が良さそうだった。

FitzHugh南雲方程式

FitzHugh南雲方程式とは、一言でいうと神経細胞ニューロン)の挙動を数理的に表した方程式のこと。

ニューロンダイナミクス電気生理学的にモデル化したものとしてはHodgkin-Huxley方程式が最も古く、今でもニューロンのモデル研究で使われることがある。
ホジキンハクスレイ方程式とは、ホジキンとハクスレーがヤリイカの巨大軸索における神経膜の電位変化を調べ、 4次元の微分方程式で書き下したもののことで、この研究で1963年のノーベル生理学賞を受賞している。

このモデルを出発点として色々なモデルの単純化が進められていて、
その代表例がこの FitzHugh-Nagumo方程式。
FitzHugh-Nagumo方程式は、4次元のホジキンハクスレー方程式の「本質」を残したまま
2次元で表現されるように単純化したモデルだってこと。
2次元で表現することで数学的にも解析しやすくなってニューロンモデルの研究が進んだという経緯がある。

具体的には以下の式で表せられる方程式だ。
\dot{u}=c(-v+u-u^3/3+I(t))
\dot{v}=u-bv+a
uは膜電位を表し、vニューロン内部の変数である。まあvの方はどうでもよくて、膜電位によって次のニューロンに信号が伝達するかどうかが決まるからuが大事になってくる。
I(t)は外部からの入力なので、時間変化のある変数になっている。

ここで、色々パラメータがあるけれど、ここを参考に決めた。
a=0.7, b=0.8, c=10

nullclineを見る

参考にしたサイトによると、Iが定常入力の時I=0.34付近でホップ分岐(微分方程式の解が大きく変化すること)が起きるという。
せっかくなので、それを確かめてみようと思う。

ちなみに、ヌルクライン(nullcline)とは、微分方程式においてどんな感じで解が動くかなーというのを見るための曲線で、これを見るとだいたい微分方程式の解の軌跡が予想できる。
下の図では赤や緑の曲線がnullclineに相当していて青のラインが解の軌跡を表している。

外部入力:I=0.33の時

f:id:swdrsker:20170420043215p:plain:w500
f:id:swdrsker:20170420043223p:plain:w500

外部入力:I=0.34の時

f:id:swdrsker:20170420043319p:plain:w500
f:id:swdrsker:20170420043335p:plain:w500

コード

import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as integrate

I = 0.33 # external input
def d_u(u, v):
    c = 10
    return c * (-v + u - pow(u,3)/3 + I)

def d_v(u, v):
    a = 0.7
    b = 0.8
    return u - b * v + a

def fitzhugh(state, t):
    u, v = state
    deltau = d_u(u,v)
    deltav = d_v(u,v)
    return deltau, deltav

# the initial state
u0 = 2.0
v0 = 1.0

t = np.arange(0.0, 20, 0.01)

y0 = [u0, v0]  # the initial state vector
y = integrate.odeint(fitzhugh, y0, t)
u_vec = y[:,0] 
v_vec = y[:,1]

plt.figure()
plt.plot(t, u_vec, label="u")
plt.plot(t, v_vec, label="v")
plt.title("membrane potential")
plt.grid()
plt.legend()

plt.figure()
plt.plot(u_vec, v_vec)
plt.xlabel("u")
plt.ylabel("v")
plt.title("FitzHugh nullcline")
padding = 0.2
umax, umin = u_vec.max() + padding,  u_vec.min() - padding
vmax, vmin = v_vec.max() + padding,  v_vec.min() - padding
U, V = np.meshgrid(np.arange(umin, umax, 0.1), np.arange(umin, vmax, 0.1))
dU = d_u(U, V)
dV = d_v(U, V)
plt.quiver(U, V, dU, dV)
plt.contour(U, V, dV, levels=[0], colors="green")
plt.contour(U, V, dU, levels=[0], colors="red")
plt.xlim([umin, umax])
plt.ylim([vmin, vmax])
plt.grid()
plt.show()

参考サイト
フィッツヒュー・南雲 (FitzHugh-Nagumo) 方程式
[SciPy-user] nullclines for nonlinear ODEs