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

时间:2017-11-12 20:13:47

标签: python matplotlib unicode latex text-rendering

我在使用默认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')

test.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': False中添加rcParams(并保留'mathtext.fontset': 'cm'),则所有减号都会正确呈现,但问题仍然存在于乘法符号中。

乘法符号错误在旧版matplotlib上似乎不是问题(我已经测试过1.5.1,1.4.3和1.3.1)。然而,这些matplotib坚持只生产10-2,1,10 -1,1,10,10 2等刻度标签,因此不需要乘法符号。

3 个答案:

答案 0 :(得分:6)

我发现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')

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

enter image description here

答案 1 :(得分:0)

问题原因

我现在明白发生了什么。 yticklabels都具有类似于

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

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

解决方案

可以使用matplotlib的tick formatters来解决这个问题。但是,我希望保留默认(次要)刻度标签位置和(预期)格式,因此更简单的解决方案就是撕掉刻度标签的\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以修复与减号相似的问题。

结果图像: test.png 敏锐的LaTeX眼睛可能会发现xticklabels中的缺陷仍然略微偏离。这与问题无关,但是因为xticklabels中的数字未包含在$...$中而发生。

答案 2 :(得分:0)

为了掩盖警告,我在邮件上使用了filterwarnings()

import warnings

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

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