使用Sympy求解Morris-Lecar模型零相线时遇TypeError错误的解决方法及绘图问题
使用Sympy求解Morris-Lecar模型零相线时遇TypeError错误的解决方法及绘图问题
嘿,我来帮你搞定这个问题!你遇到的TypeError其实是代码里混着用了scipy和sympy的函数导致的,咱们一步步拆解修正:
错误原因分析
你导入了scipy作为sp,又导入sympy作为spy,但在定义m_infinity、n_infinity这些函数时,用了sp.tanh(scipy的数值tanh函数),可V是sympy的符号变量——scipy的数值函数根本没法处理sympy的符号类型,自然就抛出了那个“没有可调用的tanh方法”的错误。
修正步骤&完整代码
咱们统一用sympy做符号求解,后续绘图再用数值计算库,代码如下:
# 导入需要的库:sympy做符号求解,numpy和matplotlib做数值绘图 import sympy as spy import numpy as np import matplotlib.pyplot as plt # 定义所有符号变量(注意去掉重复的I) V, V_1, V_2, V_3, V_4, n, g_Ca, g_K, g_L, C_M, I, V_Ca, V_K, V_L, phsi = spy.symbols('V V_1 V_2 V_3 V_4 n g_Ca g_K g_L C_M I V_Ca V_K V_L phsi') # 定义模型中的各个函数,全部使用sympy的符号函数 def m_infinity(V): return (1.0 + spy.tanh((V - V_1) / V_2)) / 2.0 def n_infinity(V): return (1.0 + spy.tanh((V - V_3) / V_4)) / 2.0 def tau_n(V): return 1 / (phsi * spy.cosh((V - V_3) / (2 * V_4))) def I_L(V): return g_L * (V - V_L) def I_K(V, n): return g_K * n * (V - V_K) def I_Ca(V): return g_Ca * m_infinity(V) * (V - V_Ca) # 定义Morris-Lecar模型的微分方程 dVdt = (I - I_Ca(V) - I_K(V, n) - I_L(V)) / C_M dndt = (n_infinity(V) - n) / tau_n(V) # 求解零相线:分别令dV/dt=0和dn/dt=0,解出n关于V的表达式 Vnull = spy.solve(spy.Eq(dVdt, 0), n)[0] nnull = spy.solve(spy.Eq(dndt, 0), n)[0] # 打印美观的符号表达式 print("V零相线(n关于V的表达式):") spy.pprint(Vnull) print("\nn零相线(n关于V的表达式):") spy.pprint(nnull) # ---------------------- 绘制零相线 ---------------------- # 设定模型的参数值(这里用经典的Morris-Lecar参数,可根据需求调整) params = { V_1: -1.2, V_2: 18.0, V_3: 12.0, V_4: 17.0, g_Ca: 4.4, g_K: 8.0, g_L: 2.0, C_M: 20.0, V_Ca: 120.0, V_K: -84.0, V_L: -60.0, phsi: 0.04, I: 50.0 # 输入电流大小 } # 将符号表达式转换为numpy可计算的函数 Vnull_func = spy.lambdify(V, Vnull.subs(params), 'numpy') nnull_func = spy.lambdify(V, nnull.subs(params), 'numpy') # 生成膜电位V的取值范围 V_vals = np.linspace(-100, 50, 200) # 计算对应的n值 n_vals_Vnull = Vnull_func(V_vals) n_vals_nnull = nnull_func(V_vals) # 绘图 plt.figure(figsize=(8, 6)) plt.plot(V_vals, n_vals_Vnull, label='V-nullcline', color='#1f77b4', linewidth=2) plt.plot(V_vals, n_vals_nnull, label='n-nullcline', color='#ff7f0e', linewidth=2) plt.xlabel('Membrane Potential V (mV)', fontsize=12) plt.ylabel('n', fontsize=12) plt.title('Morris-Lecar Model Nullclines', fontsize=14, pad=15) plt.legend(fontsize=10) plt.grid(True, alpha=0.3) plt.show()
关键修正点说明
- 统一函数库:把所有
sp.tanh、sp.cosh换成spy.tanh、spy.cosh,让sympy的符号变量能被正确处理。 - 清理重复变量:符号定义里重复写了
I,已经移除。 - 美观输出:用
spy.pprint替代普通print,输出的符号表达式结构更清晰。 - 数值绘图:通过
spy.lambdify把符号表达式转成numpy可计算的函数,代入参数后就能画出零相线了。
运行修正后的代码,你就能得到预期的零相线表达式,并且能看到直观的零相线图像啦~
备注:内容来源于stack exchange,提问作者Mariam Ismail
相关产品推荐
相关产品推荐

