Как загрузить файл.ttf в matplotlib, используя mpl.rcParams?

У меня есть скрипт matplotlib, который запускается...

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

mpl.rcParams['xtick.labelsize']=16 
...

Я использовал команду

fm.findSystemFonts()

чтобы получить список шрифтов в моей системе. Я обнаружил полный путь к файлу.ttf, который я хотел бы использовать,

'/usr/share/fonts/truetype/anonymous-pro/Anonymous Pro BI.ttf'

Я пытался использовать этот шрифт без успеха с помощью следующих команд

mpl.rcParams['font.family'] = 'anonymous-pro'  

а также

mpl.rcParams['font.family'] = 'Anonymous Pro BI'

которые оба возвращают что-то вроде

/usr/lib/pymodules/python2.7/matplotlib/font_manager.py:1218: UserWarning: findfont: Font family ['anonymous-pro'] not found. Falling back to Bitstream Vera Sans

Могу ли я использовать словарь mpl.rcParams, чтобы установить этот шрифт на своих графиках?

РЕДАКТИРОВАТЬ

После прочтения, кажется, это общая проблема определения имени семейства шрифтов из файла.ttf. Это легко сделать в Linux или Python?

Кроме того, я попытался добавить

mpl.use['agg']
mpl.rcParams['text.usetex'] = False

без успеха

3 ответа

Решение

Указание семейства шрифтов:

Если все, что вам известно, это путь к ttf, то вы можете узнать имя семейства шрифтов, используя get_name метод:

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager

path = '/usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS.ttf'
prop = font_manager.FontProperties(fname=path)
mpl.rcParams['font.family'] = prop.get_name()
fig, ax = plt.subplots()
ax.set_title('Text in a cool font', size=40)
plt.show()

Указание шрифта по пути:

import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager

path = '/usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS.ttf'
prop = font_manager.FontProperties(fname=path)
fig, ax = plt.subplots()
ax.set_title('Text in a cool font', fontproperties=prop, size=40)
plt.show()

Вы можете использовать команду fc-query myfile.ttf для проверки информации метаданных шрифта в соответствии с системой шрифтов Linux (fontconfig). Он должен напечатать вам имена, которые Matplotlib примет. Однако интеграция matplotlib fontconfig сейчас довольно частична, поэтому я боюсь, что вполне возможно, что вы обнаружите ошибки и ограничения, которые не существуют для тех же шрифтов в других приложениях Linux.

(это печальное состояние скрыто всеми жестко закодированными именами шрифтов в конфигурации по умолчанию для matplotlib, как только вы начинаете пытаться изменить их, вы попадаете в опасную страну)

Когда я сделал это менее чем в 100 строках, @nim это также объясняет более подробно, насколько это опасно, некоторые модификации полностью меняют поведение свойства шрифта и размер шрифта.

Предварительные условия: Matplotlib и папка со шрифтами на одном уровне скрипта, содержащего файл шрифта ttf calibri.ttf

Но это то, что я для тебя как пасхальное яйцо:

import os
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from matplotlib import ft2font
from matplotlib.font_manager import ttfFontProperty

__font_dir__ = os.path.join(os.path.dirname(__file__),"font")
fpath = os.path.join(__font_dir__,'calibri.ttf')

font = ft2font.FT2Font(fpath)
fprop = fm.FontProperties(fname=fpath)

ttfFontProp = ttfFontProperty(font)

fontsize=18

fontprop = fm.FontProperties(family='sans-serif',
                            #name=ap.fontprop.name,
                            fname=ttfFontProp.fname,
                            size=fontsize,
                            stretch=ttfFontProp.stretch,
                            style=ttfFontProp.style,
                            variant=ttfFontProp.variant,
                            weight=ttfFontProp.weight)

matplotlib.rcParams.update({'font.size': fontsize,
                        'font.family': 'sans-serif'})

fig, axis = plt.subplots()

axis.set_title('Text in a cool font',fontsize=fontsize,fontproperties=fontprop)

ax_right = axis.twinx()

axis.set_xlabel("some Unit",fontsize=fontsize,fontproperties=fontprop)

leftAxesName,rightAxesName = "left Unit", "right Unit"

axis.set_ylabel(leftAxesName,fontsize=fontsize,fontproperties=fontprop)
if rightAxesName:
    ax_right.set_ylabel(rightAxesName,fontsize=fontsize,fontproperties=fontprop)

for xLabel in axis.get_xticklabels():
    xLabel.set_fontproperties(fontprop)
    xLabel.set_fontsize(fontsize)

for yLabel in axis.get_yticklabels():
    yLabel.set_fontproperties(fontprop)
    yLabel.set_fontsize(fontsize)    

yTickLabelLeft = ax_right.get_yticklabels()

for yLabel in yTickLabelLeft:
    yLabel.set_fontproperties(fontprop)
    yLabel.set_fontsize(fontsize)

axis.plot([0,1],[0,1],label="test")

nrow,ncol=1,1
handels,labels= axis.get_legend_handles_labels()

propsLeft=axis.properties()

propsRight=ax_right.properties()

print(propsLeft['title'],propsLeft['xlabel'],propsLeft['ylabel'])
print(propsRight['ylabel'])

fig.set_tight_layout({'rect': [0, 0, 1, 0.95], 'pad': 0.05, 'h_pad': 1.5})
fig.tight_layout()
fig.set_alpha(True)

leg_fig = plt.figure()

leg = leg_fig.legend(handels, labels, #labels = tuple(bar_names)
   ncol=ncol, mode=None, 
   borderaxespad=0.,
   loc='center',        # the location of the legend handles
   handleheight=None,   # the height of the legend handles
   #fontsize=9,         # prop beats fontsize
   markerscale=None,
   frameon=False,
   prop=fontprop)

plt.show()
Другие вопросы по тегам