繁体   English   中英

Matplotlib mathtext:刻度标签中的字形错误

[英]Matplotlib mathtext: Glyph errors in tick labels

在使用默认mathtext而不是LaTeX数学渲染引擎时,我在 matplotlib 2.0.2 中渲染数学时观察到错误。 mathtext 似乎无法识别某些字形(在我的情况下为减号和乘号)。 真正奇怪的是,只有当这些特定的字形出现在刻度标签中时才会发生错误。 当我故意在例如图形标题中键入一些数学表达式时,它工作正常。

考虑下面的例子和结果图像:

import matplotlib
import matplotlib.pyplot as plt

# Customize matplotlib
matplotlib.rcParams.update({# Use mathtext, not LaTeX
                            'text.usetex': False,
                            # Use the Computer modern font
                            'font.family': 'serif',
                            'font.serif': 'cmr10',
                            'mathtext.fontset': 'cm',
                            })

# Plot
plt.semilogy([-0.03, 0.05], [0.3, 0.05])
plt.title(r'$-6\times 10^{-2}$')
plt.savefig('test.png')

测试.png

如图所示,刻度标签中的乘法和一些减号已被其他字符替换。 如果我使用 LaTeX(通过将'text.usetex'设置为True ),一切都会很好地呈现。 为什么会发生这种情况,更重要的是,如何在不从 mathtext 更改为 LaTeX 的情况下修复它?

附加信息

这是运行示例代码时打印的警告:

mathtext.py:866: MathTextWarning: Font 'default' does not have a glyph for '\times' [U+d7]
  MathTextWarning)
mathtext.py:867: MathTextWarning: Substituting with a dummy symbol.
  warn("Substituting with a dummy symbol.", MathTextWarning)

请注意,指数中出现的减号会正确呈现。 如果我省略'mathtext.fontset': 'cm' ,这些也可能不会呈现,产生另一个类似的警告:

mathtext.py:866: MathTextWarning: Font 'default' does not have a glyph for '-' [U+2212]
  MathTextWarning)
mathtext.py:867: MathTextWarning: Substituting with a dummy symbol.
  warn("Substituting with a dummy symbol.", MathTextWarning)

另外,如果我有'axes.unicode_minus': FalsercParams (并保持'mathtext.fontset': 'cm' ),所有减号渲染正确,但问题仍然是乘法的迹象。

在旧版本的 matplotlib 上乘号错误似乎不是问题(我已经测试了 1.5.1、1.4.3 和 1.3.1)。 然而,这些 matplotib 坚持只在 10⁻²、10⁻¹、1、10、10² 等处生成刻度标签,因此不需要乘号。

错误报告

这已作为错误报告提交给 Matplotlib。

我发现 STIX 字体是现代计算机可接受的替代品。

import matplotlib
import matplotlib.pyplot as plt

# Customize matplotlib
matplotlib.rcParams.update(
    {
        'text.usetex': False,
        'font.family': 'stixgeneral',
        'mathtext.fontset': 'stix',
    }
)

# Plot
plt.semilogy([-0.03, 0.05], [0.3, 0.05])
plt.title(r'$-6\times 10^{-2}$')
plt.savefig('test.png')

这会在我的笔记本电脑上产生以下输出:

在此处输入图片说明

问题原因

我现在明白是怎么回事了。 yticklabels 的格式都类似于

r'$\mathdefault{6\times10^{-2}}$'

这适用于主要刻度标签,其中\\times10^{-2}部分不存在。 我相信这对于次要刻度标签失败,因为\\times\\mathdefault{}\\mathdefault{} 如所陈述在这里\\mathdefault{}被用作用于mathtext,与限制,即少得多的符号可用来产生常规(非数学)文本用相同的字体。 由于\\mathdefault{}都是数学,所以\\mathdefault{}是完全多余的,因此可以安全地将其删除。 这解决了这个问题。

解决方案

可以使用 matplotlib's tick formatters解决这个问题。 然而,我想保留默认(次要)刻度标签位置和(预期)格式,因此更简单的解决方案是\\mathdefault刻度标签的\\mathdefault部分:

import warnings
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.mathtext import MathTextWarning

# Customize matplotlib
matplotlib.rcParams.update({# Use mathtext, not LaTeX
                            'text.usetex': False,
                            # Use the Computer modern font
                            'font.family': 'serif',
                            'font.serif': 'cmr10',
                            'mathtext.fontset': 'cm',
                            # Use ASCII minus
                            'axes.unicode_minus': False,
                            })
# Function implementing the fix
def fix(ax=None):
    if ax is None:
        ax = plt.gca()
    fig = ax.get_figure()
    # Force the figure to be drawn
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', category=MathTextWarning)
        fig.canvas.draw()
    # Remove '\mathdefault' from all minor tick labels
    labels = [label.get_text().replace('\mathdefault', '')
              for label in ax.get_xminorticklabels()]
    ax.set_xticklabels(labels, minor=True)
    labels = [label.get_text().replace('\mathdefault', '')
              for label in ax.get_yminorticklabels()]
    ax.set_yticklabels(labels, minor=True)
# Plot
plt.semilogy([-0.03, 0.05], [0.3, 0.05])
plt.title(r'$-6\times 10^{-2}$')
fix()
plt.savefig('test.png')

编写此修复程序的棘手部分是您无法在绘制图形之前获取刻度标签。 因此我们需要先调用fig.canvas.draw() 这将引发我已压制的警告。 这也意味着您应该尽可能晚地调用fix() ,以便最终绘制所有轴。 最后(如问题中所述), 'axes.unicode_minus'已设置为False以解决与减号类似的问题。

结果图像: 测试.png 敏锐的 LaTeX 眼睛可能会发现 xticklabel 中的缺点仍然略有偏差。 这与问题无关,但发生的原因是 xticklabels 中的数字未包含在$...$

matplotlib 3.1.0 的更新

从 matplotlib 3.1.0 版开始,警告是通过logging模块发出的,而不是warnings 要使警告静音,请替换

    # Force the figure to be drawn
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', category=MathTextWarning)
        fig.canvas.draw()

    # Force the figure to be drawn
    import logging
    logger = logging.getLogger('matplotlib.mathtext')
    original_level = logger.getEffectiveLevel()
    logger.setLevel(logging.ERROR)
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', category=MathTextWarning)
        fig.canvas.draw()
    logger.setLevel(original_level)

现在忽略警告,无论它是通过logging还是warnings

为了掩盖警告,我在消息上使用了filterwarnings()

import warnings

warnings.filterwarnings("ignore", message="Glyph 146 missing from current font.")

因此,请替换“当前字体中缺少 Glyph 146”。 通过您自己的错误消息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM