在 Jupyter 和导出的 PDF 或 PNG 中绘制不同的 LaTeX 字体

问题描述 投票:0回答:1

我正在尝试创建我在 jupyter 实验室中用绘图绘制的 PDF,但我在字体方面遇到了很多麻烦。 Plotly 对浏览器中的所有普通文本使用正确的字体,但所有 LaTeX 代码标签都使用不同的字体。这是可以预料的,因为plotly 使用 MathJax 进行渲染,并且显然它被配置为使用

STIX
。我可以接受这一点,并将非 LaTeX 字体更改为
STIX
(如果它与导出的图形一致)。真正困扰我的是,当我将绘图导出为 PDF 时,LaTeX 标签使用另一种字体。由于某种原因,MathJax 默认为
MathJax_Main
。如果导出为 PNG 或 PDF,为了完全混淆,默认使用普通字体
Liberation Serif

因此,这里有一些用于创建绘图的示例代码。我在 Debian 11 和 python 3.9 上运行它。如果有任何用处,我可以添加完整的

requirements.txt

import plotly.graph_objects as go
from plotly.express.colors import qualitative

layout = go.Layout(
    font=dict(
        family='Latin Modern Math',
        color='black',
        size=20,
    ),
    colorway=qualitative.D3,
    width=600,
    height=320,
    margin=dict(l=10,r=10,t=10,b=10),
    paper_bgcolor='rgba(255,255,255,1)',
    plot_bgcolor='rgba(0,0,0,0)',
    xaxis=dict(
        showline=True,
        linecolor='black',
        ticks='inside',
        exponentformat='e',
        mirror='ticks',
    ),
    yaxis=dict(
        showline=True,
        linecolor='black',
        ticks='inside',
        exponentformat='e',
        mirror='ticks',
    ),
    legend=dict(
        xanchor="left",
        yanchor="bottom",
        x=0.1,
        y=1.01,
    ),
)

fig = go.Figure(layout=layout)

X = np.linspace(0, 2 * np.pi, 100)
Y1 = np.sin(X)
Y2 = np.cos(X)
fig.add_trace(go.Scatter(x=X, y=Y1, name=r'$\text{The quick brown fox jumps over the lazy dog}$'))
fig.add_trace(go.Scatter(x=X, y=Y2, name='The quick brown fox jumps over the lazy dog'))
fig.show()

浏览器输出

乳胶:STIX
师范:拉丁现代数学

PDF 导出

LaTeX:MathJax_Main
正常:解放衬线

PNG 导出

LaTeX:MathJax_Main
正常:解放衬线

我想问题的根源是无论后台导出(Kaleido,也许)和/或MathJax要么找不到正确的字体,要么使用不同的配置。但我不知道该配置在哪里或者它应该是什么样子。

编辑1

我查看了plotly和kaleido的源代码。看起来 kaleido 附带了自己的 mathjax,所以这可能是问题所在。如果我理解正确,则将图交给Kaleido(https://github.com/plotly/plotly.py/blob/24cda54b22b7c541a30fd6a080e4ccf5a0684106/packages/python/plotly/plotly/io/_kaleido.py#L145),它实现了

PlotlyScope
。 Kaleido 然后调用
_perform_transform
(https://github.com/plotly/Kaleido/blob/6a46ecae926b4c004bf7232383cf7c74c70748fd/repos/kaleido/py/kaleido/scopes/plotly.py#L153),它创建一个 JSON 转储和管道到某个子进程,该子进程返回最终图像。您可以看到
PlotlyScope
有一个成员
mathjax
,在我的例子中它指向
$HOME/venvs/jupyter/lib/python3.9/site-packages/kaleido/executable/etc/mathjax/MathJax.js
。在这个链中我看不到任何字体规范被改变。所以我假设子进程(Kaleido 正在运行)接收到正确的字体规范,但随后默认为任何字体,因为它找不到字体。不幸的是,当发生这种情况时,不会打印任何错误。

plotly jupyter-lab mathjax
1个回答
0
投票

我知道这是一篇 2 年前的帖子,但对于任何可能关心的人来说。我也遇到了同样的问题,你的分析非常好。我创建了一个 kaleido 分支,至少在我的笔记本电脑上解决了这个问题。

目前有一个关于同一问题的未决问题,其中提到了您的帖子。如果有人感兴趣的话,我已经在那里发布了我的详细解决方案。链接是https://github.com/plotly/plotly.py/issues/3828#issuecomment-1798544806

正如那里提到的,我可能很快就会创建一个拉取请求,但如果其他人也测试它,那就太好了。

© www.soinside.com 2019 - 2024. All rights reserved.