Bokeh 数学符号渲染完全指南:在图表与控件中使用 LaTeX 和 MathML
【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh
Bokeh 原生支持在图表中渲染数学公式,允许开发者使用 LaTeX 与 MathML 两种标记语言来书写轴标签、标题、刻度标签、标注(Label)以及各类控件文本。本指南以 Bokeh 用户手册的数学符号(Mathematical notation)章节为核心,结合仓库中 examples/styling/mathtext 目录下的完整示例与bokeh.models.text源码实现,系统讲解如何在当前项目中为图表注入专业、美观的数学排版,读完后你将能熟练使用$$...$$、\[...\]、\(...\)定界符书写 LaTeX,并掌握MathML模型与major_label_overrides等核心配置方法。
一、Bokeh 数学符号支持总览
Bokeh 支持用 LaTeX 和 MathML 两种标记语言表达数学记号,目前可应用于以下元素:
| 元素 | 说明 | 相关文档 |
|---|---|---|
| 轴标签(Axis labels) | 通过axis_label属性设置 | 样式指南-绘图章节 |
| 刻度标签(Tick labels) | 通过major_label_overrides覆盖 | 见下文"刻度标签"小节 |
| 标题(Titles) | 通过title属性设置 | 基础注解-标题 |
| 标注(Labels) | Label注解对象 | 基础注解-标注 |
| 颜色条(Color bars) | 颜色条上的标签文本 | 基础注解-颜色条 |
| RangeSlider / Slider 控件 | 控件的title参数 | 交互-控件 |
| Div / Paragraph 控件 | 控件正文中的任意位置 | 交互-控件 |
渲染层面,Bokeh 依赖 MathJax 库来处理 LaTeX 与 MathML 的排版。这意味着你无需在页面中自行引入其他数学渲染库,Bokeh 已经集成了完整的 MathJax 支持。
从源码结构看,Bokeh 在 src/bokeh/models/text.py 中定义了完整的文本模型体系:抽象基类BaseText提供text属性(必填字符串),抽象类MathText作为数学内容的基类,其下派生出TeX(LaTeX 记号)、MathML(MathML 记号)、Ascii(AsciiMath 记号)三个具体模型,另有PlainText表示普通文本。这套模型体系正是 Bokeh 将数学文本作为"一等公民"传递到前端的核心载体。
注意(重要):如果你使用
components函数将 Bokeh 组件嵌入自定义 HTML 模板,务必在模板中显式引入bokeh-mathjax-资源,否则数学公式将无法渲染。
二、使用 LaTeX 记号
2.1 定界符:如何让 Bokeh 识别数学表达式
要使用 LaTeX 记号,只需把字符串直接传给任意受支持的元素。该字符串必须以 MathJax 默认定界符开头和结尾:
$$...$$:块级数学(display math)\[...\]:块级数学的另一种写法\(...\):行内数学(inline math)
例如:r"$$\sin(x)$$"。注意示例代码中普遍使用 Python 原始字符串(r"..."),以避免反斜杠被 Python 转义。
仓库示例 latex_axis_labels_titles_labels.py 同时演示了三种定界符的用法:
from numpy import arange, pi, sin from bokeh.models.annotations.labels import Label from bokeh.plotting import figure, show x = arange(-2*pi, 2*pi, 0.1) y = sin(x) p = figure(height=250, title=r"$$\sin(x)$$ for \[x\] between \(-2\pi\) and $$2\pi$$") p.scatter(x, y, alpha=0.6, size=7) label = Label( text=r"$$y = \sin(x)$$", x=150, y=130, x_units="screen", y_units="screen", ) p.add_layout(label) p.yaxis.axis_label = r"\(\sin(x)\)" p.xaxis.axis_label = r"\[x\pi\]" show(p)2.2 LaTeX 应用于轴标签、标题与标注
将 LaTeX 用作轴标签、标题或标注时,做法完全一致:传入以 MathJax 默认定界符开头和结尾的原始字符串字面量即可。上面的示例中,title、Label.text、p.yaxis.axis_label、p.xaxis.axis_label均直接接收了带定界符的 LaTeX 字符串。
2.3 LaTeX 应用于刻度标签(major_label_overrides)
要给刻度标签添加 LaTeX 记号,需要使用轴对象的major_label_overrides方法。从源码 src/bokeh/models/axes.py 可以看到其定义:
major_label_overrides = Dict(Either(Float, String), TextLike, default={}, help=""" Provide explicit tick label values for specific tick locations that override normal formatting. """)该属性接受一个字典:键是刻度位置的原始数值(或字符串),值是你自定义的替换文本(TextLike类型,意味着它可以是普通字符串,也可以是MathML、TeX等文本模型)。Bokeh 会用字典中的值覆盖对应位置的默认格式化标签。
仓库示例 latex_tick_labels.py 演示了电阻-电流关系图中用 LaTeX 替换普通刻度文本的方法:
from numpy import arange from bokeh.plotting import figure, show x = arange(1, 4.5, 0.25) y = 1 / x plot = figure(height=200) plot.title = "Current over Resistance at a static voltage of 1 volt" plot.scatter(x, y, fill_color="blue", size=5) plot.line(x, y, color="darkgrey") plot.xaxis.axis_label = "Resistance" plot.xaxis.ticker = [1, 2, 3, 4] plot.xaxis.major_label_overrides = { 1: r"1 $$\Omega$$", 2: r"2 $$\Omega$$", 3: r"3 $$\Omega$$", 4: r"4 $$\Omega$$", } plot.yaxis.axis_label = "Current" plot.yaxis.ticker = [0.2, 0.4, 0.6, 0.8, 1.0] plot.yaxis.major_label_overrides = { 0.2: "0.2 $$A$$", 0.4: "0.4 $$A$$", 0.6: "0.6 $$A$$", 0.8: "0.8 $$A$$", 1: "1 $$A$$", } show(plot)关键点:先用plot.xaxis.ticker = [1, 2, 3, 4]明确指定刻度位置,再用major_label_overrides把每个位置映射到带单位符号(欧姆 Ω、安培 A)的 LaTeX 文本,从而实现"单位符号以数学字体排版"的效果。
2.4 LaTeX 应用于 RangeSlider 与 Slider 控件标题
在 RangeSlider 或 Slider 控件的title参数中传入带定界符的原始字符串,即可让控件标题显示数学公式。仓库示例 latex_slider_widget_title.py 演示:
from bokeh.io import show from bokeh.models import Slider slider = Slider(start=0, end=10, value=1, step=.1, title=r"$$\delta \text{ (damping factor, 1/s)}$$") show(slider)这里除了数学符号\delta外,还借助\text{}扩展把普通文字 "damping factor, 1/s" 嵌入数学表达式中,这正是 LaTeX 扩展的典型用法(见下文第五节)。
2.5 LaTeX 应用于 Div 与 Paragraph 控件
在 Div 或 Paragraph 控件的文本中,可以在字符串的任意位置使用 MathJax 默认定界符,实现"正文中混排数学公式"的效果。仓库示例 latex_div_widget.py 演示:
from bokeh.io import show from bokeh.models import Div div = Div( width=400, height=100, background="#fafafa", text=r"The Pythagorean identity is $$\sin^2(x) + \cos^2(x) = 1$$", ) show(div)关闭数学渲染:如果不希望 Div 或 Paragraph 对数学记号做渲染,可以把控件的disable_math属性设为True。该属性在 src/bokeh/models/widgets/markups.py 中定义为disable_math = Bool(False, ...),默认开启数学处理;Markdown 控件同样支持该开关(见 src/bokeh/models/widgets/markdown.py)。
三、调整渲染后数学文本的样式
Bokeh 标准的文本属性(text properties)同样作用于渲染后的数学文本:
- 用
text_font_size改变字号; - 用
text_color改变颜色。
例如,原文档给出的轴标签样式设置:
p.xaxis.axis_label = r"$$\nu \:(10^{15} s^{-1})$$" p.xaxis.axis_label_text_color = "green" p.xaxis.axis_label_text_font_size = "50px"在 latex_blackbody_radiation.py 中可以看到更完整的组合用法:白色轴标签配合暗色主题dark_minimal,并使用了\text{}在公式中混排单位文本:
p.xaxis.axis_label = r"$$\nu \:(10^{15}\ \text{Hz})$$" p.yaxis.axis_label = r"$$B_\nu(\nu, T) \quad\left(10^{-9}\ \text{W} / (\text{m}^2 \cdot \text{sr} \cdot \text{Hz})\right)$$"在 latex_bessel.py 中,标题、轴标签与Label标注共同使用了复杂的求和公式与上下标:
p = figure( width=700, height=500, title=( r"Bessel functions of the first kind: $$J_\alpha(x) = \sum_{m=0}^{\infty}" r"\frac{(-1)^m}{m!\:\Gamma(m+\alpha+1)} \left(\frac{x}{2}\right)^{2m+\alpha}$$" ), ) ... p.title.text_font_size = "14px" p.title.text_color = "white" ... p.add_layout(Label(text=f"$$J_{i}(x)$$", x=xlabel, y=ylabel, text_color="white"))此外,在 Bokeh 主题(theme)中定义的文本颜色与字号对数学文本同样生效。例如上述两个示例分别通过curdoc().theme = 'night_sky'与curdoc().theme = 'dark_minimal'切换主题,数学公式会随之继承主题中的文本样式。
四、LaTeX 扩展与渲染限制
除了基础数学排版,你还可以使用 MathJax 内置的 LaTeX 扩展:
\text{}:在数学表达式中插入字面文本,例如\text{Hz}、\text{ (damping factor, 1/s)},非常适合"物理量 + 单位"的场景;- color 扩展:直接改变渲染颜色,例如
\color{white} \sin(x)。
需要特别注意的是:用 LaTeX 扩展(如\color{})设置的文本属性,优先级高于代码中或主题里设置的其他文本属性,也就是说扩展声明会覆盖同位置的text_color等设置。
同时要明确一个限制:MathJax 对 LaTeX 的支持存在边界,它并不完全等同于完整的 TeX/LaTeX 实现——例如 MathJax 主要支持数学模式(math-mode)下的宏,不支持文本模式(text-mode)宏。从 src/bokeh/models/text.py 中TeX模型的文档注释也能看到这一说明。对复杂宏或扩展行为有疑问时,应以 MathJax 官方文档中 "Differences from Actual TeX" 一节为准,按 MathJax 的实际能力编写公式。
五、使用 MathML 记号
除 LaTeX 外,Bokeh 还支持 MathML。与 LaTeX 的"字符串 + 定界符"方式不同,MathML 需要直接使用bokeh.models.text.MathML模型。该模型的text属性接受一个包含 MathML 标记的字符串,例如 mathml_axis_labels.py 中的演示:
from numpy import arange from bokeh.models import MathML from bokeh.plotting import figure, show x = arange(-10, 10, 0.1) y = (x * 0.5) ** 2 mathml = """ <math> <mrow> <mfrac> <mn>1</mn> <mn>4</mn> </mfrac> <msup> <mi>x</mi> <mn>2</mn> </msup> </mrow> </math> """ plot = figure(height=200) plot.line(x, y) plot.xaxis.axis_label = MathML(text=mathml) show(plot)上面的 MathML 字符串等价于数学表达式1/4 · x²:<mfrac>表示分数,<msup>表示上标,<mi>/<mn>分别表示标识符(变量)与数字。
与 LaTeX 类似,MathML 渲染结果同样支持标准文本属性:
plot.xaxis.axis_label = MathML(text=mathml) plot.xaxis.axis_label_text_color = "green" plot.xaxis.axis_label_text_font_size = "50px"从源码 src/bokeh/models/text.py 可见,MathML继承自MathText(再继承自BaseText),BaseText定义了必填的text属性;同时MathML.__init__支持位置参数直接传入文本,即MathML("<math>...</math>")与MathML(text="...")等价。由于MathML本身属于TextLike类型族,凡是接受TextLike的属性(如major_label_overrides的值、轴标签等)都可以直接传入MathML实例。
六、更多实战示例与进一步阅读
仓库 examples/styling/mathtext 目录还提供了多个可直接运行的高级示例,可作为深入学习的素材:
- latex_normal_distribution.py、latex_schrodinger.py:物理/统计公式在标题、轴标签中的典型应用;
- latex_outline_shapes.py:数学文本与其他图形的组合排版;
- latex_blackbody_radiation.py:轴标签与 Div 控件中混排公式 +
\text{}单位文本 + 主题联动; - latex_bessel.py:求和、分数、希腊字母等复杂公式在标题、轴标签与标注上的综合演示。
这些示例的运行方式与普通 Bokeh 脚本一致:直接执行python examples/styling/mathtext/latex_bessel.py即可在浏览器中查看渲染效果(部分示例依赖scipy,如贝塞尔函数示例)。
七、要点速查
- 定界符三件套:
$$...$$、\[...\]、\(...\),字符串用r"..."原始字符串书写; - 应用范围:轴标签、标题、标注、刻度标签(
major_label_overrides)、颜色条、Slider/RangeSlider 标题、Div/Paragraph 文本; - 刻度标签:
axis.major_label_overrides = {位置: 文本},文本可为字符串或MathML/TeX模型; - 关闭渲染:Div/Paragraph 设置
disable_math=True; - MathML:使用
MathML(text="...")模型,支持text_font_size、text_color; - 样式继承:文本属性与主题均对数学文本生效,但
\color{}等 LaTeX 扩展声明的样式优先级更高; - 嵌入注意:使用
components时记得在 HTML 模板中包含bokeh-mathjax-资源。
【免费下载链接】bokehInteractive Data Visualization in the browser, from Python项目地址: https://gitcode.com/GitHub_Trending/bo/bokeh
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考