当有多个同名字体时按姓氏设置 matplotlib 字体
Set matplotlib font by family name when there are multiple fonts with same name
如何告诉 matplotlib
使用具有相同名称和特征的特定字体变体?
例如,我可以告诉 matplotlib
使用 Latin Modern Roman:
#!/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
还是 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'] not found. Falling back to DejaVu Sans.
因为 prop.get_name()
仍然(神秘地)returns Latin Modern Roman
而不是 Latin Modern Roman Type 10
如何告诉 matplotlib
我想用其中一个?
可以在大多数 set_label
和 set_ticklabel
调用中显式使用 fontproperties
指向 font_manager.FontProperties()
实例(就像在这个 answer 中),但我正在寻找一种通过 rcParams
.
进行全局设置的方法
注意:我不想在 matplotlib
中使用 LaTeX
渲染 (text.usetex
)。
系统:
- Ubuntu-20.04 on WSL2 on Windows 10 Pro 19042
- Python 3.8.5 / [GCC 9.3.0] linux
- matplotlib 3.4.1
这真是个好问题。我将提供找到该特定问题的解决方案的方法。为了重现它,我们首先必须从 here 下载给定的字体(我下载了常规版本 10 和常规版本 17 以查看更明显的区别)。安装后,我们可以通过 matplotlib
:
检查我们的新字体是否被找到
from matplotlib import font_manager
font_manager.font_manager.findSystemFonts(fontext='otf') # Matplotlib associates with
# the .otf extension two more extensions viz. '.ttc' and '.ttf', as can be obtain over
# font_manager.get_fontext_synonyms('otf')
找到 .otf
文件的指定路径后,我们可以使用 font_manager
将该特定版本设为我们选择的字体。
# This will create an object which contains your file and give it a custom name
# Here is the idea of this:
fe = font_manager.FontEntry(
fname='C:\Users\<your_user_name>\AppData\Local\Microsoft\Windows\Fonts\latin-modern-roman.mroman10-regular.otf',
name='10erLatin')
font_manager.fontManager.ttflist.insert(0, fe)
mpl.rcParams['font.family'] = fe.name
让我们绘制它,以便我们稍后可以看到它是否有效。
import numpy as np
from pathlib import Path
import matplotlib as mpl
# import PyQt5
# mpl.use('Qt5Agg') # I want to plot it inline ;)
import matplotlib.pyplot as 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 + ':italic'
mpl.rcParams['mathtext.bf'] = fe.name + ':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()
让我们将其更改为常规字体的 17 版本。
fe = font_manager.FontEntry(
fname='C:\Users\<your_user_name>\AppData\Local\Microsoft\Windows\Fonts\latin-modern-roman.mroman17-regular.otf',
name='17erLatin')
font_manager.fontManager.ttflist.insert(0, fe)
mpl.rcParams['font.family'] = fe.name
再次绘制它(使用与上面完全相同的代码来创建该图,只是事先执行了给定的代码)。
如果我的后见之明还不错,那么文本已全局更改。还有一些其他功能可能有用,但是,它们实际上隐藏在 source code 中。如果您 运行 遇到问题,请告诉我。
如何告诉 matplotlib
使用具有相同名称和特征的特定字体变体?
例如,我可以告诉 matplotlib
使用 Latin Modern Roman:
#!/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
还是 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'] not found. Falling back to DejaVu Sans.
因为 prop.get_name()
仍然(神秘地)returns Latin Modern Roman
而不是 Latin Modern Roman Type 10
如何告诉 matplotlib
我想用其中一个?
可以在大多数 set_label
和 set_ticklabel
调用中显式使用 fontproperties
指向 font_manager.FontProperties()
实例(就像在这个 answer 中),但我正在寻找一种通过 rcParams
.
注意:我不想在 matplotlib
中使用 LaTeX
渲染 (text.usetex
)。
系统:
- Ubuntu-20.04 on WSL2 on Windows 10 Pro 19042
- Python 3.8.5 / [GCC 9.3.0] linux
- matplotlib 3.4.1
这真是个好问题。我将提供找到该特定问题的解决方案的方法。为了重现它,我们首先必须从 here 下载给定的字体(我下载了常规版本 10 和常规版本 17 以查看更明显的区别)。安装后,我们可以通过 matplotlib
:
from matplotlib import font_manager
font_manager.font_manager.findSystemFonts(fontext='otf') # Matplotlib associates with
# the .otf extension two more extensions viz. '.ttc' and '.ttf', as can be obtain over
# font_manager.get_fontext_synonyms('otf')
找到 .otf
文件的指定路径后,我们可以使用 font_manager
将该特定版本设为我们选择的字体。
# This will create an object which contains your file and give it a custom name
# Here is the idea of this:
fe = font_manager.FontEntry(
fname='C:\Users\<your_user_name>\AppData\Local\Microsoft\Windows\Fonts\latin-modern-roman.mroman10-regular.otf',
name='10erLatin')
font_manager.fontManager.ttflist.insert(0, fe)
mpl.rcParams['font.family'] = fe.name
让我们绘制它,以便我们稍后可以看到它是否有效。
import numpy as np
from pathlib import Path
import matplotlib as mpl
# import PyQt5
# mpl.use('Qt5Agg') # I want to plot it inline ;)
import matplotlib.pyplot as 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 + ':italic'
mpl.rcParams['mathtext.bf'] = fe.name + ':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()
让我们将其更改为常规字体的 17 版本。
fe = font_manager.FontEntry(
fname='C:\Users\<your_user_name>\AppData\Local\Microsoft\Windows\Fonts\latin-modern-roman.mroman17-regular.otf',
name='17erLatin')
font_manager.fontManager.ttflist.insert(0, fe)
mpl.rcParams['font.family'] = fe.name
再次绘制它(使用与上面完全相同的代码来创建该图,只是事先执行了给定的代码)。
如果我的后见之明还不错,那么文本已全局更改。还有一些其他功能可能有用,但是,它们实际上隐藏在 source code 中。如果您 运行 遇到问题,请告诉我。