如何从 matplotlib 将刻度中文本的原始字符串导出到 svg?

How to export raw strings for text in ticks to svg from matplotlib?

我使用 matplotlib 生成绘图。在大多数情况下,它会按预期工作。但是,如果我在刻度中使用类似 TeX 的文本,它的行为与其他标签或注释中的文本不同。我设置 rc.text.usetex=False 并且标签作为原始文本导出,但刻度的文本被解释。在对数对数图或使用其他 TeX 命令如 \frac 的情况下,它会导致纯数字移动到它们的位置(例如上标或分数)。

我使用以下函数导出带有原始字符串的 svg 图形。之后,我使用 Inkscape 处理细节并将其导出为 PDF 和 TeX,以便使用 put 命令将所有文本放置在图形上。

def export_svg(plt=plt,svg_name='name'):
    plt.rc('text', usetex=False)
    plt.rc('text.latex', unicode = False)
    plt.rc('svg',fonttype = 'none')
    for blub in plt.findobj(match=plt.Text):
        blub.set_text(blub.get_text().replace('$','$'))
    plt.savefig(svg_name + '.svg')

axes.xaxis.get_ticklabels()[2].get_text() 产生 '^{1}$'

axes.xaxis.get_label().get_text() 产生 '\$ x \$'。在svg文件中变成了'$ x $',正是我需要的格式。

有人解决过这个问题吗?我想我必须从 Formatter class 开始以获得刻度格式中缺少的反斜杠。

谢谢

马克

首先,它不仅发生在 loglog 的情况下。报价总是在没有 $ .. $.

的情况下导出

我的解决方法是创建我自己的 Formatter class:

import matplotlib.pyplot as plt

class MyLogFormatterMathtext(plt.LogFormatter):
"""
Format values for log axis; using ``exponent = log_base(value)``
mark_r:
removed \mathdefault
escaped $ with \
"""

def __call__(self, x, pos=None):
    'Return the format for tick val *x* at position *pos*'
    b = self._base
    usetex = rcParams['text.usetex']

    # only label the decades
    if x == 0:
        if usetex:
            return '[=10=]$'
        else:
            return '$0$' #'$\mathdefault{0}$'

    fx = math.log(abs(x)) / math.log(b)
    is_decade = is_close_to_int(fx)

    sign_string = '-' if x < 0 else ''

    # use string formatting of the base if it is not an integer
    if b % 1 == 0.0:
        base = '%d' % b
    else:
        base = '%s' % b

    if not is_decade and self.labelOnlyBase:
        return ''
    elif not is_decade:
        if usetex:
            return (r'$%s%s^{%.2f}$') % \
                                        (sign_string, base, fx)
        else:
            return (r'$%s%s^{%.2f}$') % \
                                        (sign_string, base, fx)
    else:
        if usetex:
            return (r'$%s%s^{%d}$') % (sign_string,
                                       base,
                                       nearest_long(fx))
        else:
            return (r'$%s%s^{%d}$') % (sign_string,
                                                     base,
                                                     nearest_long(fx))

我编辑了 usetex==Trueusetex==False 这两个案例,因为第二个没有产生想要的结果。在我看来,标签中的文本与刻度中的文本相比,处理方式有所不同。 所以我必须使用标准 LogFormatterMathtext if usetex==True 来创建 "familiar look"。对于导出为 svg 格式,我使用:

majorFormatter = MyLogFormatterMathtext()
axes.xaxis.set_major_formatter(majorFormatter)

我更喜欢一个更通用的解决方案,但这个解决方案只是一个权宜之计。 欢迎提出问题或对此解决方案发表评论。