渲染 Python 中用 LaTeX 语法定义的数学公式 - 例子
渲染 Python 中用 LaTeX 语法定义的数学公式 - 例子
flyfish
# 导入核心库:matplotlib.pyplot用于绘图,numpy用于数值计算
import matplotlib.pyplot as plt
import numpy as np# 启用LaTeX渲染功能(需系统提前安装TeX环境,如TeX Live)
# 作用:使图表中的数学公式、符号按专业排版标准显示
plt.rcParams['text.usetex'] = True# 创建画布(fig)和子图(ax):fig是绘图窗口容器,ax是实际绘图的区域(单张子图)
fig, ax = plt.subplots()# -------------------------- 1. 生成绘图数据 --------------------------
N = 500 # 横轴采样点数量,数值越大,曲线越平滑(离散点越密集)
sigma = 0.3 # 高斯分布的标准差参数,控制高斯曲线的"宽窄"(sigma越小,曲线越尖锐)
X = np.linspace(-2, 2, N) # 生成横轴数据:从-2到2均匀分布的500个点(覆盖三条曲线的有效范围)# -------------------------- 2. 绘制三条核心曲线 --------------------------
ax.plot(X, np.exp(-X**2 / (2*sigma**2)), "C0", # 1. 高斯分布曲线(蓝色,默认颜色编码C0)# 公式:g(x) = exp(-x²/(2σ²)),常用于概率分布、信号处理等场景X, np.sin(2*np.pi*X), "C2", # 2. 正弦波曲线(绿色,颜色编码C2)# 公式:s(x) = sin(2πx),周期为1,振幅为1X, X > 0, "k--" # 3. 阶跃函数曲线(黑色虚线,"k--"代表black+dashed)# 逻辑:当X>0时取值1,X≤0时取值0,模拟"突变"的边界
)# -------------------------- 3. 设置图例(区分三条曲线) --------------------------
ax.legend(("Gaussian", "sine wave", "step function"), # 图例标签:高斯分布、正弦波、阶跃函数shadow=True, # 为图例添加阴影效果,增强视觉层次感loc=(0.01, 0.85), # 图例位置:距离子图左侧1%、距离底部85%(相对坐标,避免遮挡曲线)handlelength=1.5, # 图例中"线条样本"的长度(单位:字符宽度)fontsize=16 # 图例文字大小
)# -------------------------- 4. 添加箭头与标注(标记高斯分布的特征宽度) --------------------------
# 绘制双向箭头:从(-sigma, 0.2)指向(sigma, 0.2),表示高斯曲线的"2σ宽度"范围
ax.annotate("", # 箭头无额外文本内容(仅靠后续text标注)xy=(-sigma, 0.2), # 箭头的终点坐标(左侧端点)xytext=(sigma, 0.2), # 箭头的起点坐标(右侧端点)arrowprops=dict(arrowstyle="<->", connectionstyle="arc3") # 箭头样式:双向箭头+圆弧过渡
)# 在箭头中间添加"2σ"标注(LaTeX语法:$2\sigma$,σ为希腊字母标准差符号)
ax.text(0, 0.2, # 文本位置:箭头正中间(横轴0,纵轴0.2)r"$2\sigma$", # 标注内容:2倍标准差color="black", # 文本颜色:黑色(与箭头匹配)fontsize=24, # 字体大小(突出显示关键参数)horizontalalignment="center", # 水平对齐:居中(相对于文本位置x=0)verticalalignment="center", # 垂直对齐:居中(相对于文本位置y=0.2)bbox=dict(boxstyle="round", fc="white", ec="black", pad=0.2) # 文本边框:圆角矩形(白底黑边,内边距0.2)
)# -------------------------- 5. 配置X轴(横轴) --------------------------
ax.set_xticks([-2, 0, 2]) # X轴显示的刻度位置(仅保留关键节点,避免杂乱)
# X轴刻度标签:用LaTeX语法格式化,确保符号统一(-2显示为$-2$,+2显示为$+2$)
ax.set_xticklabels([r"$-2$", r"$0$", r"$+2$"], color="k", size=20)# -------------------------- 6. 配置Y轴(左侧纵轴,对应高斯分布) --------------------------
# Y轴标签:混合文本(粗体"Gaussian")和数学符号($g(x)$,高斯函数的标准表示)
# 颜色C0与高斯曲线一致,增强视觉关联
ax.set_ylabel(r"\bf{Gaussian} $g(x)$", color="C0", fontsize=20)
ax.set_yticks([-1, 0, 1]) # Y轴显示的刻度位置(覆盖正弦波的振幅范围和阶跃函数的取值)
# Y轴刻度标签:粗体显示(\bf{}),确保与标签风格统一
ax.set_yticklabels([r"\bf{-1}", r"\bf{0}", r"\bf{1}"], color="k", size=20)# -------------------------- 7. 配置右侧纵轴标签(对应正弦波,避免与左侧冲突) --------------------------
ax.text(1.02, 0.5, # 文本位置:距离子图右侧2%(x=1.02)、垂直居中(y=0.5)r"\bf{sine wave} $s(x)$", # 标签内容:粗体"正弦波" + 数学符号$s(x)$color="C2", # 颜色C2与正弦波曲线一致,增强关联fontsize=20, # 字体大小rotation=90, # 文本旋转90度(竖排,适配右侧纵轴)horizontalalignment="left", # 水平对齐:左对齐(贴近子图边缘)verticalalignment="center", # 垂直对齐:居中clip_on=False, # 允许文本超出子图边界(避免右侧标签被裁剪)transform=ax.transAxes # 坐标系统:使用子图的相对坐标(0~1),而非数据坐标
)# -------------------------- 8. 渲染偏微分方程(PDE)公式:扩散方程 --------------------------
# 定义扩散方程:使用eqnarray*环境(LaTeX的多行公式对齐环境,*表示不显示公式编号)
eq1 = (r"\begin{eqnarray*}"r"\frac{\partial u}{\partial t} &=& D \nabla^2 u" # 扩散方程核心式:u对t的偏导 = D×u的拉普拉斯# 符号说明:u是场变量,t是时间,D是扩散系数,∇²是拉普拉斯算子r"\end{eqnarray*}")# 在子图右上角添加扩散方程(对应正弦波,用绿色标注)
ax.text(1.9, 0.9, # 文本位置:距离右侧0.1、距离顶部0.1(数据坐标,避免超出画布)eq1, # 公式内容(LaTeX语法)color="C2", # 颜色与正弦波一致fontsize=18, # 字体大小horizontalalignment="right", # 水平对齐:右对齐verticalalignment="top" # 垂直对齐:顶部对齐
)# -------------------------- 9. 渲染偏微分方程(PDE)公式:波动方程 --------------------------
# 定义波动方程:同样使用eqnarray*环境
eq2 = (r"\begin{eqnarray*}"r"\frac{\partial^2 u}{\partial t^2} &=& c^2 \nabla^2 u" # 波动方程核心式:u对t的二阶偏导 = c²×u的拉普拉斯# 符号说明:c是波速,其他符号同扩散方程r"\end{eqnarray*}")# 在子图左下角添加波动方程(对应高斯分布,用蓝色标注)
ax.text(-1.6, -0.6, # 文本位置:数据坐标(-1.6, -0.6),避免遮挡曲线eq2, # 公式内容(LaTeX语法)color="C0", # 颜色与高斯曲线一致fontsize=16 # 字体大小
)# -------------------------- 10. 补充希腊字母标注(示例:展示LaTeX的符号支持) --------------------------
ax.text(-2, 0.5, r"alpha: $\alpha$", color="r", fontsize=20) # 标注α(红色)
ax.text(-2, 0.3, r"lambda: $\lambda$", color="b", fontsize=20) # 标注λ(蓝色)# -------------------------- 11. 显示绘制完成的图像 --------------------------
plt.show()
# 导入必要的库:matplotlib用于绘图,numpy用于数值计算
import matplotlib.pyplot as plt
import numpy as np# 启用LaTeX渲染功能(需系统已安装TeX环境),使图表中的数学公式按专业格式显示
plt.rcParams['text.usetex'] = True# 创建画布(fig)和子图(ax),子图是实际绘图的区域
fig, ax = plt.subplots()# -------------------------- 1. 生成绘图数据(界面追踪相关的轮廓数据) --------------------------
N = 500 # 采样点数量,数值越大,曲线越平滑
delta = 0.6 # 界面宽度参数,控制过渡区域的宽窄
X = np.linspace(-1, 1, N) # 生成横轴数据:从-1到1均匀分布的500个点# 绘制三条曲线,分别对应不同的界面模型
# 1. 相场模型的tanh轮廓线(蓝色,默认颜色C0):描述界面的平滑过渡
ax.plot(X, (1 - np.tanh(4 * X / delta)) / 2, # 2. 水平集模型的成分轮廓线(绿色,颜色C2):另一种界面描述方式X, (1.4 + np.tanh(4 * X / delta)) / 4, "C2", # 3. 锐界面模型(黑色虚线,"k--"):理想的突变界面,X<0时为1,X≥0时为0X, X < 0, "k--") # -------------------------- 2. 设置图例(区分三条曲线) --------------------------
ax.legend(("phase field", "level set", "sharp interface"), # 图例标签:相场、水平集、锐界面shadow=True, # 给图例添加阴影效果,增强立体感loc=(0.01, 0.48), # 图例位置:距离左侧1%、距离底部48%的坐标handlelength=1.5, # 图例中线条手柄的长度fontsize=16 # 图例字体大小
)# -------------------------- 3. 添加箭头和标注(标记界面宽度delta) --------------------------
# 绘制双向箭头:从(-delta/2, 0.1)指向(delta/2, 0.1),表示界面宽度范围
ax.annotate("", # 箭头无文本内容xy=(-delta / 2., 0.1), # 箭头终点坐标xytext=(delta / 2., 0.1), # 箭头起点坐标arrowprops=dict(arrowstyle="<->", connectionstyle="arc3") # 箭头样式:双向箭头,圆弧连接
)# 在箭头中间添加delta符号(LaTeX语法:$\delta$)
ax.text(0, 0.1, # 文本位置:箭头中间的正上方r"$\delta$", # 文本内容:希腊字母delta(需LaTeX渲染)color="black", # 文本颜色:黑色fontsize=24, # 字体大小horizontalalignment="center", # 水平对齐:居中verticalalignment="center", # 垂直对齐:居中bbox=dict(boxstyle="round", fc="white", ec="black", pad=0.2) # 文本边框:圆角矩形,白底黑边,内边距0.2
)# -------------------------- 4. 设置X轴(横轴)标签 --------------------------
ax.set_xticks([-1, 0, 1]) # X轴刻度位置:-1、0、1
# X轴刻度标签:使用LaTeX语法,-1显示为$-1$,0显示为$\pm 0$,+1显示为$+1$
ax.set_xticklabels(["$-1$", r"$\pm 0$", "$+1$"], color="k", size=20)# -------------------------- 5. 设置左侧Y轴(纵轴)标签和刻度 --------------------------
# Y轴标签:混合文本(粗体"相场")和数学模式($\phi$,相场变量),颜色对应相场曲线的C0(蓝色)
ax.set_ylabel(r"\bf{phase field} $\phi$", color="C0", fontsize=20)
ax.set_yticks([0, 0.5, 1]) # Y轴刻度位置:0、0.5、1
# Y轴刻度标签:粗体显示0、.5、1(\bf{}表示粗体)
ax.set_yticklabels([r"\bf{0}", r"\bf{.5}", r"\bf{1}"], color="k", size=20)# -------------------------- 6. 设置右侧Y轴标签(水平集变量) --------------------------
ax.text(1.02, 0.5, # 文本位置:距离右侧2%、垂直居中(相对于子图坐标)r"\bf{level set} $\phi$", # 文本内容:粗体"水平集" + 数学变量$\phi$color="C2", # 文本颜色:对应水平集曲线的C2(绿色)fontsize=20, # 字体大小rotation=90, # 文本旋转:90度(竖排)horizontalalignment="left", # 水平对齐:左对齐verticalalignment="center", # 垂直对齐:居中clip_on=False, # 不裁剪超出子图范围的文本transform=ax.transAxes # 坐标系统:使用子图的相对坐标(0-1),而非数据坐标
)# -------------------------- 7. 渲染水平集方程(右侧上方) --------------------------
# 定义水平集方程:使用eqnarray*环境实现多行公式对齐(*表示不编号)
eq1 = (r"\begin{eqnarray*}"r"|\nabla\phi| &=& 1,\\" # 第一行:梯度的模等于1(&表示对齐位置,\\表示换行)r"\frac{\partial \phi}{\partial t} + U|\nabla \phi| &=& 0 " # 第二行:演化方程r"\end{eqnarray*}")# 在子图右上角添加水平集方程
ax.text(1, 0.9, # 文本位置:右侧边缘、距离顶部10%eq1, # 公式内容(LaTeX语法)color="C2", # 颜色:绿色(对应水平集)fontsize=18, # 字体大小horizontalalignment="right", # 水平对齐:右对齐verticalalignment="top" # 垂直对齐:顶部对齐
)# -------------------------- 8. 渲染相场方程(中间偏下) --------------------------
# 定义相场方程:包含自由能泛函和演化方程
eq2 = (r"\begin{eqnarray*}"r"\mathcal{F} &=& \int f\left( \phi, c \right) dV, \\ " # 第一行:自由能泛函(\mathcal{F}表示花体F)r"\frac{ \partial \phi } { \partial t } &=& -M_{ \phi } " # 第二行:相场演化方程(M_phi是迁移率)r"\frac{ \delta \mathcal{F} } { \delta \phi }" # 变分导数项r"\end{eqnarray*}")# 在子图中间偏下位置添加相场方程
ax.text(0.18, 0.18, # 文本位置:距离左侧18%、距离底部18%eq2, # 公式内容(LaTeX语法)color="C0", # 颜色:蓝色(对应相场)fontsize=16 # 字体大小
)# -------------------------- 9. 添加希腊字母标注(示例) --------------------------
ax.text(-1, .30, r"gamma: $\gamma$", color="r", fontsize=20) # 标注gamma(红色)
ax.text(-1, .18, r"Omega: $\Omega$", color="b", fontsize=20) # 标注Omega(蓝色)# -------------------------- 10. 显示图像 --------------------------
plt.show()