我怎么知道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
与 lmroman10-regular.otf
?在 mpl.rcParams
我只能指定 font.family
, font.weight
, font.style
和font.variant
所以如果两个 .otf
文件具有所有相同的值,我如何告诉它使用一个 .otf
而不是另一个?字体之间实际上是有区别的,例如:
我尝试引用.otf
直接使用 matplotlib.FontProperties
文件实例,然后重命名它,然后指向新名称,例如:
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()
仍然(神秘地)返回Latin Modern Roman
而不是Latin Modern Roman Type 10
我怎么知道matplotlib
我想使用其中一个而不是另一个?
可以显式使用 fontproperties
指向font_manager.FontProperties()
大多数set_label
中的实例和set_ticklabel
调用(如 answer ),但我正在寻找一种通过 rcParams
进行全局设置的方法.
注意:我不想使用 LaTeX
在 text.usetex
中渲染 ( matplotlib
) .
系统:
- Windows 10 Pro 19042 上 WSL2 上的 Ubuntu-20.04
- Linux 上的 Python 3.8.5/[GCC 9.3.0]
- 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: https://stackoverflow.com/questions/35668219/how-to-set-up-a-custom-font-with-custom-path-to-matplotlib-global-font
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 中。 。如果您遇到问题,请告诉我。
关于python-3.x - 当有多个同名字体时,按家族名称设置 matplotlib 字体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67401784/