Python 3.x 当存在多个同名字体时,按族名称设置matplotlib字体

Python 3.x 当存在多个同名字体时,按族名称设置matplotlib字体,python-3.x,matplotlib,fonts,Python 3.x,Matplotlib,Fonts,当两者具有相同的名称和特征时,如何告诉matplotlib使用特定的字体变体 例如,我可以告诉matplotlib使用拉丁现代罗马语: #!/usr/bin/env python3 # -*- coding: utf-8 -*- import numpy as np from pathlib import Path import matplotlib as mpl import PyQt5 mpl.use('Qt5Agg') import matplotlib.pyplot as plt

当两者具有相同的名称和特征时,如何告诉
matplotlib
使用特定的字体变体

例如,我可以告诉
matplotlib
使用拉丁现代罗马语:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import numpy as np
from pathlib import Path

import matplotlib as mpl
import PyQt5
mpl.use('Qt5Agg')
import matplotlib.pyplot as plt

mpl.rcParams['font.family'] = 'Latin Modern Roman'
mpl.rcParams['font.weight'] = '400'
mpl.rcParams['font.style'] = 'normal'
mpl.rcParams['font.variant'] = 'normal'
mpl.rcParams['mathtext.fontset'] = 'custom'
mpl.rcParams['mathtext.default'] = 'it'
mpl.rcParams['mathtext.rm'] = 'Latin Modern Roman:normal'
mpl.rcParams['mathtext.it'] = 'Latin Modern Roman:italic'
mpl.rcParams['mathtext.bf'] = 'Latin Modern Roman:bold'

mpl.rcParams['xtick.labelsize'] = 8
mpl.rcParams['ytick.labelsize'] = 8
mpl.rcParams['axes.titlesize'] = 10
mpl.rcParams['axes.labelsize'] = 10

x = np.linspace(0,2*np.pi,100)
y = np.sin(x)

fig1 = plt.figure(figsize=(3, 3*(9/16)), dpi=300)
ax1 = fig1.gca()
ax1.plot(x, y, c='r', linewidth=1.0, zorder=20)
ax1.set_xlabel(r'$x\ label$')
ax1.set_ylabel(r'$y\ label$')
fig1.tight_layout(pad=0.15)
plt.show()

好的,很好。但是,如果我想使用拉丁现代罗马语的一个特定的“子样式”呢?例如,在我的系统上,当我通过以下方式列出具有
name='Latin Modern Roman'
weight=400
style='normal'
variant='normal'
的可用字体条目时:

fonts = mpl.font_manager.fontManager.ttflist
for f in fonts:
    if (f.name=='Latin Modern Roman'):
        if all([(f.style=='normal'),(f.weight==400),(f.style=='normal'),(f.variant=='normal')]):
            print(f.name)
            print(Path(f.fname).stem)
            print(f.fname)
            print('weight : %s'%str(f.weight))
            print('style : %s'%str(f.style))
            print('stretch : %s'%str(f.stretch))
            print('variant : %s'%str(f.variant))
            print('\n')
我得到:

Latin Modern Roman
lmroman9-regular
/usr/share/texmf/fonts/opentype/public/lm/lmroman9-regular.otf
weight : 400
style : normal
stretch : normal
variant : normal

...
...

Latin Modern Roman
lmroman10-regular
/usr/share/texmf/fonts/opentype/public/lm/lmroman10-regular.otf
weight : 400
style : normal
stretch : normal
variant : normal
那么,我如何告诉
matplotlib
我想要使用
lmroman9 regular.otf
vs
lmroman10 regular.otf
?在
mpl.rcParams
中,我只能指定
font.family
font.weight
font.style
font.variant
因此,如果两个
.otf
文件具有所有相同的值,我如何告诉它使用一个
.otf
?字体之间实际上存在差异,例如:

我已尝试使用
matplotlib.FontProperties
实例直接引用
.otf
文件,然后重命名它,然后指向新名称,如:

prop = mpl.font_manager.FontProperties(fname='/usr/share/fonts/opentype/lmodern/lmroman10-regular.otf')
prop.set_name('Latin Modern Roman Type 10')
mpl.rcParams['font.family'] = 'Latin Modern Roman Type 10'
但后来我发现找不到
findfont:Font-family['Latin-Modern-Roman Type 10']。回到DejaVu Sans。
因为
prop.get_name()
仍然(神秘地)返回
拉丁现代罗马
而不是
拉丁现代罗马类型10

如何告诉
matplotlib
我想使用一个而不是另一个

在大多数
set\u label
set\u ticklab
调用中(如本例),可以显式使用
fontproperties
指向
font\u manager.fontproperties()
实例,但我正在寻找一种通过
rcParams
全局设置该实例的方法

注意:我不想在
matplotlib
中使用
LaTeX
渲染(
text.usetex

系统:

  • Windows 10 Pro 19042上WSL2上的Ubuntu-20.04
  • linux上的Python 3.8.5/[GCC 9.3.0]
  • matplotlib 3.4.1

  • 这是一个非常好的问题。我将提供我找到该特定问题解决方案的方法。为了复制它,我们首先必须从下载给定的字体(我下载了常规版本10和常规版本17以查看更清晰的区别)。安装后,我们可以通过
    matplotlib
    检查是否找到新字体:

    从matplotlib导入字体管理器
    font_manager.font_manager.findSystemFonts(FontText='otf')#Matplotlib与
    #.otf扩展还有两个扩展,即“”。ttc'和'.ttf',可以通过
    #字体管理器。获取同义词(“otf”)
    
    找到
    .otf
    文件的指定路径后,我们可以使用
    font\u管理器
    将特定版本设置为所选字体

    #这将创建一个包含文件的对象,并为其指定自定义名称
    #以下是这方面的想法:https://stackoverflow.com/questions/35668219/how-to-set-up-a-custom-font-with-custom-path-to-matplotlib-global-font
    fe=font\u manager.FontEntry(
    fname='C:\\Users\\\\AppData\\Local\\Microsoft\\Windows\\font\\latin-modern-roman.mroman10-regular.otf',
    name='10erLatin')
    font_manager.fontManager.ttflist.insert(0,fe)
    mpl.rcParams['font.family']=fe.name
    
    让我们把它画出来,以便我们以后可以看到它是否有效

    将numpy导入为np
    从pathlib导入路径
    将matplotlib导入为mpl
    #导入PyQt5
    #mpl.use('Qt5Agg')#我想内联绘制它;)
    将matplotlib.pyplot作为plt导入
    mpl.rcParams['font.family']=fe.name
    mpl.rcParams['font.weight']='400'
    mpl.rcParams['font.style']='normal'
    mpl.rcParams['font.variant']='normal'
    mpl.rcParams['mathtext.fontset']='custom'
    mpl.rcParams['mathtext.default']='it'
    mpl.rcParams['mathtext.rm']=fe.name+':normal'
    mpl.rcParams['mathtext.it']=fe.name+':斜体'
    mpl.rcParams['mathtext.bf']=fe.name+':粗体'
    mpl.rcParams['xtick.labelsize']=8
    mpl.rcParams['ytick.labelsize']=8
    mpl.rcParams['axes.titlesize']=10
    mpl.rcParams['axes.labelsize']=10
    x=np.linspace(0,2*np.pi,100)
    y=np.sin(x)
    图1=plt.图(图大小=(3,3*(9/16)),dpi=300)
    ax1=图1.gca()
    ax1.绘图(x,y,c='r',线宽=1.0,zorder=20)
    ax1.set_xlabel(r'$x\label$)
    ax1.set_ylabel(r'$y\label$)
    图1.紧凑布局(pad=0.15)
    plt.show()
    

    让我们将其更改为常规字体的17个版本

    fe=font\u manager.FontEntry(
    fname='C:\\Users\\\\AppData\\Local\\Microsoft\\Windows\\font\\latin-modern-roman.mroman17-regular.otf',
    name='17erLatin')
    font_manager.fontManager.ttflist.insert(0,fe)
    mpl.rcParams['font.family']=fe.name
    
    同样,让我们绘制它(使用与上面完全相同的代码来创建该绘图,只是预先执行给定的代码)


    如果我的后见不算太糟的话,那么文本在全球范围内发生了变化。还有一些其他函数可能很有用,但是,它们实际上隐藏在中。如果遇到问题,请告诉我。

    您是否尝试过按照中的建议设置
    fontproperties=prop
    ?这在数学模式下不起作用,并且还需要在每个
    set_label()
    set_ticklebals()
    调用中设置
    fontproperties=prop
    ,这不方便/不可维护。我正在寻找通过
    rcParams
    全局设置的方法,这正是我想要的!谢谢你,扬尼克!