Научная графика в Python

Автор: Шабанов Павел Александрович

E-mail: [email protected]

URL: Заметки по программированию в науках о Земле

Дата последнего обновления: 12.03.2017

Глава 3 Текст и шрифты

Содержание главы

  1. Файл настройки matplotlibrc;

  2. Текст на рисунке;

  3. Наборы шрифтов. Стили и форматы;

  4. Кириллица и matplotlib. Подписи по-русски;

  5. Работа с математическими формулами. Поддержка LaTex.

Текст является одним из базовых графических элементов рисунка в matplotlib. Подписи координатных осей и их делений, заголовки, пояснительные подписи на графиках и диаграммах - это всё текст. В Matplotlib возможна поддержка кириллицы для создания научной графики с подписями на русском языке. Одним из весомых преимуществ matplotlib при работе с текстом является простая поддержка математических формул с помощью LaTex.

Электронные ресурсы:

In [19]:
# Преамбула
%matplotlib inline

import os
import matplotlib.pyplot as plt
import numpy as np

def save(name='', fmt='png'):
    pwd = os.getcwd()
    iPath = './pictures/{}'.format(fmt)
    if not os.path.exists(iPath):
        os.mkdir(iPath)
    os.chdir(iPath)
    plt.savefig('{}.{}'.format(name, fmt), fmt='png')
    os.chdir(pwd)
    #plt.close()

3.1 Файл настройки matplotlibrc

В matplotlib существует файл настройки в котором хранятся значения по умолчанию для разных свойств графических элементов. Он называется matplotlibrc. Он инициализируется при каждой загрузке модуля matplotlib. Изменив содержание файла matplotlibrc можно сохранить пользовательские настройки для работы при следующих загрузках модуля matplotlib. Чтобы узнать какой именно файл настройки используется при инициализации, можно воспользоваться специальной функцией matplotlib.matplotlib_fname().

Для работы с настройками в интерактивном режиме, то есть из консоли или в скрипте, существует matplotlib.rcParams. C помощью matplotlib.rcParams можно, во-первых, установить все параметры рисования (шрифты, толшина/тип линий, оформление рамок) на необходимые значения, а во-вторых, увидеть, собственно, список настроек, то есть список того, что можно изменить.

In [20]:
import matplotlib as mpl

print mpl.matplotlib_fname() # показывает откуда был загружен текуший файл matplotlibrc

mpl.rcParams # показывает текущие настройки

# mpl.rcParamsDefault # показывает значения параметров, которые хранятся в файле matplotlibrc

# mpl.rcdefaults() сбрасывает значения на те, которые хранятся в файле matplotlibrc
C:\Users\pasha\Anaconda2\lib\site-packages\matplotlib\mpl-data\matplotlibrc
Out[20]:
RcParams({u'_internal.classic_mode': False,
          u'agg.path.chunksize': 0,
          u'animation.avconv_args': [],
          u'animation.avconv_path': u'avconv',
          u'animation.bitrate': -1,
          u'animation.codec': u'h264',
          u'animation.convert_args': [],
          u'animation.convert_path': u'convert',
          u'animation.ffmpeg_args': [],
          u'animation.ffmpeg_path': u'ffmpeg',
          u'animation.frame_format': u'png',
          u'animation.html': u'none',
          u'animation.mencoder_args': [],
          u'animation.mencoder_path': u'mencoder',
          u'animation.writer': u'ffmpeg',
          u'axes.autolimit_mode': u'data',
          u'axes.axisbelow': u'line',
          u'axes.edgecolor': u'k',
          u'axes.facecolor': u'w',
          u'axes.formatter.limits': [-7, 7],
          u'axes.formatter.offset_threshold': 4,
          u'axes.formatter.use_locale': False,
          u'axes.formatter.use_mathtext': False,
          u'axes.formatter.useoffset': True,
          u'axes.grid': False,
          u'axes.grid.axis': u'both',
          u'axes.grid.which': u'major',
          u'axes.hold': None,
          u'axes.labelcolor': u'k',
          u'axes.labelpad': 4.0,
          u'axes.labelsize': u'medium',
          u'axes.labelweight': u'normal',
          u'axes.linewidth': 0.8,
          u'axes.prop_cycle': cycler(u'color', [u'#1f77b4', u'#ff7f0e', u'#2ca02c', u'#d62728', u'#9467bd', u'#8c564b', u'#e377c2', u'#7f7f7f', u'#bcbd22', u'#17becf']),
          u'axes.spines.bottom': True,
          u'axes.spines.left': True,
          u'axes.spines.right': True,
          u'axes.spines.top': True,
          u'axes.titlepad': 6.0,
          u'axes.titlesize': u'large',
          u'axes.titleweight': u'normal',
          u'axes.unicode_minus': True,
          u'axes.xmargin': 0.05,
          u'axes.ymargin': 0.05,
          u'axes3d.grid': True,
          u'backend': 'module://ipykernel.pylab.backend_inline',
          u'backend.qt4': u'PyQt4',
          u'backend.qt5': u'PyQt5',
          u'backend_fallback': True,
          u'boxplot.bootstrap': None,
          u'boxplot.boxprops.color': u'k',
          u'boxplot.boxprops.linestyle': u'-',
          u'boxplot.boxprops.linewidth': 1.0,
          u'boxplot.capprops.color': u'k',
          u'boxplot.capprops.linestyle': u'-',
          u'boxplot.capprops.linewidth': 1.0,
          u'boxplot.flierprops.color': u'k',
          u'boxplot.flierprops.linestyle': u'none',
          u'boxplot.flierprops.linewidth': 1.0,
          u'boxplot.flierprops.marker': u'o',
          u'boxplot.flierprops.markeredgecolor': u'k',
          u'boxplot.flierprops.markerfacecolor': u'none',
          u'boxplot.flierprops.markersize': 6.0,
          u'boxplot.meanline': False,
          u'boxplot.meanprops.color': u'C2',
          u'boxplot.meanprops.linestyle': u'--',
          u'boxplot.meanprops.linewidth': 1.0,
          u'boxplot.meanprops.marker': u'^',
          u'boxplot.meanprops.markeredgecolor': u'C2',
          u'boxplot.meanprops.markerfacecolor': u'C2',
          u'boxplot.meanprops.markersize': 6.0,
          u'boxplot.medianprops.color': u'C1',
          u'boxplot.medianprops.linestyle': u'-',
          u'boxplot.medianprops.linewidth': 1.0,
          u'boxplot.notch': False,
          u'boxplot.patchartist': False,
          u'boxplot.showbox': True,
          u'boxplot.showcaps': True,
          u'boxplot.showfliers': True,
          u'boxplot.showmeans': False,
          u'boxplot.vertical': True,
          u'boxplot.whiskerprops.color': u'k',
          u'boxplot.whiskerprops.linestyle': u'-',
          u'boxplot.whiskerprops.linewidth': 1.0,
          u'boxplot.whiskers': 1.5,
          u'contour.corner_mask': True,
          u'contour.negative_linestyle': u'dashed',
          u'datapath': u'C:\\Users\\pasha\\Anaconda2\\lib\\site-packages\\matplotlib\\mpl-data',
          u'date.autoformatter.day': u'%Y-%m-%d',
          u'date.autoformatter.hour': u'%m-%d %H',
          u'date.autoformatter.microsecond': u'%M:%S.%f',
          u'date.autoformatter.minute': u'%d %H:%M',
          u'date.autoformatter.month': u'%Y-%m',
          u'date.autoformatter.second': u'%H:%M:%S',
          u'date.autoformatter.year': u'%Y',
          u'docstring.hardcopy': False,
          u'errorbar.capsize': 0.0,
          u'examples.directory': u'',
          u'figure.autolayout': False,
          u'figure.dpi': 72.0,
          u'figure.edgecolor': (1, 1, 1, 0),
          u'figure.facecolor': (1, 1, 1, 0),
          u'figure.figsize': [6.0, 4.0],
          u'figure.frameon': True,
          u'figure.max_open_warning': 20,
          u'figure.subplot.bottom': 0.125,
          u'figure.subplot.hspace': 0.2,
          u'figure.subplot.left': 0.125,
          u'figure.subplot.right': 0.9,
          u'figure.subplot.top': 0.88,
          u'figure.subplot.wspace': 0.2,
          u'figure.titlesize': u'large',
          u'figure.titleweight': u'normal',
          u'font.cursive': [u'Apple Chancery',
                            u'Textile',
                            u'Zapf Chancery',
                            u'Sand',
                            u'Script MT',
                            u'Felipa',
                            u'cursive'],
          u'font.family': [u'fantasy'],
          u'font.fantasy': [u'Arial',
                            u'Times New Roman',
                            u'Tahoma',
                            u'Comic Sans MS',
                            u'Courier'],
          u'font.monospace': [u'DejaVu Sans Mono',
                              u'Bitstream Vera Sans Mono',
                              u'Computer Modern Typewriter',
                              u'Andale Mono',
                              u'Nimbus Mono L',
                              u'Courier New',
                              u'Courier',
                              u'Fixed',
                              u'Terminal',
                              u'monospace'],
          u'font.sans-serif': [u'DejaVu Sans',
                               u'Bitstream Vera Sans',
                               u'Computer Modern Sans Serif',
                               u'Lucida Grande',
                               u'Verdana',
                               u'Geneva',
                               u'Lucid',
                               u'Arial',
                               u'Helvetica',
                               u'Avant Garde',
                               u'sans-serif'],
          u'font.serif': [u'DejaVu Serif',
                          u'Bitstream Vera Serif',
                          u'Computer Modern Roman',
                          u'New Century Schoolbook',
                          u'Century Schoolbook L',
                          u'Utopia',
                          u'ITC Bookman',
                          u'Bookman',
                          u'Nimbus Roman No9 L',
                          u'Times New Roman',
                          u'Times',
                          u'Palatino',
                          u'Charter',
                          u'serif'],
          u'font.size': 10.0,
          u'font.stretch': u'normal',
          u'font.style': u'normal',
          u'font.variant': u'normal',
          u'font.weight': u'normal',
          u'grid.alpha': 1.0,
          u'grid.color': u'#b0b0b0',
          u'grid.linestyle': u'-',
          u'grid.linewidth': 0.8,
          u'hatch.color': u'k',
          u'hatch.linewidth': 1.0,
          u'hist.bins': 10,
          u'image.aspect': u'equal',
          u'image.cmap': u'viridis',
          u'image.composite_image': True,
          u'image.interpolation': u'nearest',
          u'image.lut': 256,
          u'image.origin': u'upper',
          u'image.resample': True,
          u'interactive': True,
          u'keymap.all_axes': [u'a'],
          u'keymap.back': [u'left', u'c', u'backspace'],
          u'keymap.forward': [u'right', u'v'],
          u'keymap.fullscreen': [u'f', u'ctrl+f'],
          u'keymap.grid': [u'g'],
          u'keymap.home': [u'h', u'r', u'home'],
          u'keymap.pan': [u'p'],
          u'keymap.quit': [u'ctrl+w', u'cmd+w'],
          u'keymap.save': [u's', u'ctrl+s'],
          u'keymap.xscale': [u'k', u'L'],
          u'keymap.yscale': [u'l'],
          u'keymap.zoom': [u'o'],
          u'legend.borderaxespad': 0.5,
          u'legend.borderpad': 0.4,
          u'legend.columnspacing': 2.0,
          u'legend.edgecolor': u'0.8',
          u'legend.facecolor': u'inherit',
          u'legend.fancybox': True,
          u'legend.fontsize': u'medium',
          u'legend.framealpha': 0.8,
          u'legend.frameon': True,
          u'legend.handleheight': 0.7,
          u'legend.handlelength': 2.0,
          u'legend.handletextpad': 0.8,
          u'legend.labelspacing': 0.5,
          u'legend.loc': u'best',
          u'legend.markerscale': 1.0,
          u'legend.numpoints': 1,
          u'legend.scatterpoints': 1,
          u'legend.shadow': False,
          u'lines.antialiased': True,
          u'lines.color': u'C0',
          u'lines.dash_capstyle': u'butt',
          u'lines.dash_joinstyle': u'round',
          u'lines.dashdot_pattern': [4.8, 1.2, 0.8, 1.2],
          u'lines.dashed_pattern': [2.8, 1.2],
          u'lines.dotted_pattern': [1.1, 1.1],
          u'lines.linestyle': u'-',
          u'lines.linewidth': 1.5,
          u'lines.marker': u'None',
          u'lines.markeredgewidth': 1.0,
          u'lines.markersize': 6.0,
          u'lines.scale_dashes': True,
          u'lines.solid_capstyle': u'projecting',
          u'lines.solid_joinstyle': u'round',
          u'markers.fillstyle': u'full',
          u'mathtext.bf': u'sans:bold',
          u'mathtext.cal': u'cursive',
          u'mathtext.default': u'it',
          u'mathtext.fallback_to_cm': True,
          u'mathtext.fontset': u'dejavusans',
          u'mathtext.it': u'sans:italic',
          u'mathtext.rm': u'sans',
          u'mathtext.sf': u'sans',
          u'mathtext.tt': u'monospace',
          u'nbagg.transparent': True,
          u'patch.antialiased': True,
          u'patch.edgecolor': u'k',
          u'patch.facecolor': u'C0',
          u'patch.force_edgecolor': False,
          u'patch.linewidth': 1.0,
          u'path.effects': [],
          u'path.simplify': True,
          u'path.simplify_threshold': 0.1111111111111111,
          u'path.sketch': None,
          u'path.snap': True,
          u'pdf.compression': 6,
          u'pdf.fonttype': 3,
          u'pdf.inheritcolor': False,
          u'pdf.use14corefonts': False,
          u'pgf.debug': False,
          u'pgf.preamble': [],
          u'pgf.rcfonts': True,
          u'pgf.texsystem': u'xelatex',
          u'plugins.directory': u'.matplotlib_plugins',
          u'polaraxes.grid': True,
          u'ps.distiller.res': 6000,
          u'ps.fonttype': 3,
          u'ps.papersize': u'letter',
          u'ps.useafm': False,
          u'ps.usedistiller': False,
          u'savefig.bbox': None,
          u'savefig.directory': u'~',
          u'savefig.dpi': u'figure',
          u'savefig.edgecolor': u'w',
          u'savefig.facecolor': u'w',
          u'savefig.format': u'png',
          u'savefig.frameon': True,
          u'savefig.jpeg_quality': 95,
          u'savefig.orientation': u'portrait',
          u'savefig.pad_inches': 0.1,
          u'savefig.transparent': False,
          u'scatter.marker': u'o',
          u'svg.fonttype': u'path',
          u'svg.hashsalt': None,
          u'svg.image_inline': True,
          u'text.antialiased': True,
          u'text.color': u'k',
          u'text.dvipnghack': None,
          u'text.hinting': u'auto',
          u'text.hinting_factor': 8,
          u'text.latex.preamble': [],
          u'text.latex.preview': False,
          u'text.latex.unicode': False,
          u'text.usetex': False,
          u'timezone': u'UTC',
          u'tk.window_focus': False,
          u'toolbar': u'toolbar2',
          u'verbose.fileo': u'sys.stdout',
          u'verbose.level': u'silent',
          u'webagg.open_in_browser': True,
          u'webagg.port': 8988,
          u'webagg.port_retries': 50,
          u'xtick.bottom': True,
          u'xtick.color': u'k',
          u'xtick.direction': u'out',
          u'xtick.labelsize': u'medium',
          u'xtick.major.bottom': True,
          u'xtick.major.pad': 3.5,
          u'xtick.major.size': 3.5,
          u'xtick.major.top': True,
          u'xtick.major.width': 0.8,
          u'xtick.minor.bottom': True,
          u'xtick.minor.pad': 3.4,
          u'xtick.minor.size': 2.0,
          u'xtick.minor.top': True,
          u'xtick.minor.visible': False,
          u'xtick.minor.width': 0.6,
          u'xtick.top': False,
          u'ytick.color': u'k',
          u'ytick.direction': u'out',
          u'ytick.labelsize': u'medium',
          u'ytick.left': True,
          u'ytick.major.left': True,
          u'ytick.major.pad': 3.5,
          u'ytick.major.right': True,
          u'ytick.major.size': 3.5,
          u'ytick.major.width': 0.8,
          u'ytick.minor.left': True,
          u'ytick.minor.pad': 3.4,
          u'ytick.minor.right': True,
          u'ytick.minor.size': 2.0,
          u'ytick.minor.visible': False,
          u'ytick.minor.width': 0.6,
          u'ytick.right': False})

3.2 Текст на рисунке

Одними из самых базовых графических команд являются команды, отображающие текст. Самой простой такой командой, не привязаной к какому-либо объекту вроде координатной оси или делений координатной оси, является команда plt.text().

В качестве входящих данных она принимает координаты положения будующей строки и сам текст в виде строки. По умолчанию координаты положения строки будут приурочены к области изменения данных. Можно задать положение текста в относительных координатах (см. пример ниже), когда вся область рисования изменяется по обеим координатным осям от 0 до 1 включительно. Таким образом, координата (0.5, 0.5) в относительных координатах означает центр области рисования. Текст можно выровнять с помощью параметров horizontalalignment и verticalalignment, а также заключать его в рамку с цветным фоном, передав параметр bbox. Bbox - это словарь, работающий со свойствами прямоугольника, то есть объектом Rectangle.

Помимо метода text() существуют и другие методы отображения текста в pyplot. Ниже представлен список текстовых команд в pyplot, в квадратных скобках указан альтернативный синтаксис вызова аналогичных команд в ООП стиле. Подробнее об ООП стиле будет рассказано позже.

  • plt.xlabel() - добавляет подпись оси абсции OX [matplotlib.axes.Axes.set_xlabel()];

  • plt.ylabel() - добавляет подпись оси ординат OY [matplotlib.axes.Axes.set_ylabel()];

  • plt.title() - добавляет заголовок для области рисования Axes [matplotlib.axes.Axes.set_title()];

  • plt.figtext() - добавляет текст на рисунок Figure [matplotlib.figure.Figure.text()];

  • plt.suptitle() - добавляет заголовок для рисунка Figure [matplotlib.figure.Figure.suptitle()];

  • plt.annotate() - добавляет примечание, которое состоит из текста и необязательной стрелки в указанную область на рисунке [matplotlib.axes.Axes.annotate()]

Каждый текст на рисунке - это экземпляр либо исходного класса, либо дочернего класса для matplotlib.text.Text.

In [21]:
# Пример 3.2

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

a = 1.
x = np.arange(-2*np.pi, 2*np.pi, 0.05)
# Уравнение кардиоиды
xz = a*(2*np.cos(x) - np.cos(2*x))
yz = a*(2*np.sin(x) - np.sin(2*x))

fig = plt.figure()
plt.plot(xz, yz)

# Текст в координатах данных
str1 = plt.text(-np.pi/2., np.pi/2., 'Text in absolute coords', fontsize=14)   # выравнивание по левому краю
print('Text class: %s' % str1.__class__)

# Текст в рамке
plt.text(0.5, 0.5, 'Text with borders', fontsize=14,
         # выравнивание по вертикали и по горизонтали по центру
         horizontalalignment='center', verticalalignment='center',
         bbox=dict(facecolor='pink', alpha=0.5))

# Текст в относительных координатах области рисования ax
ax = fig.add_subplot(111)   # создаём область рисования ax
plt.text(0.5, 0.5, 'Text in relative coords', fontsize=14,
         horizontalalignment='right', verticalalignment='center',
         transform=ax.transAxes)
plt.grid()

save('pic_3_2', fmt='png')
save('pic_3_2', fmt='pdf')

plt.show()
Text class: <class 'matplotlib.text.Text'>
---------------------------------------------------------------------------
WindowsError                              Traceback (most recent call last)
<ipython-input-21-ee8eb93e9969> in <module>()
     31 plt.grid()
     32 
---> 33 save('pic_3_2', fmt='png')
     34 save('pic_3_2', fmt='pdf')
     35 

<ipython-input-19-30d462799fb4> in save(name, fmt)
     10     iPath = './pictures/{}'.format(fmt)
     11     if not os.path.exists(iPath):
---> 12         os.mkdir(iPath)
     13     os.chdir(iPath)
     14     plt.savefig('{}.{}'.format(name, fmt), fmt='png')

WindowsError: [Error 3] : './pictures/png'

3.3 Наборы шрифтов. Стили и форматы

Из настроек matplotlibrc или rcParams нас интересуют fonts, то есть шрифты. Есть 5 наборов шрифтов:

  • cursive;

  • fantasy;

  • monospace;

  • sans-serif;

  • serif.

Один из этих пяти наборов является текущим. За это отвечает параметр font.family. Каждый набор может состоять из одного или более шрифтов. Причём можно указывать шрифты, которые не установлены в ОС. Работать такие шрифты не будут, но формально указать их можно. Такая настройка определяет шрифт для всех подписей и текста на рисунке. Если конкретную подпись необходимо сделать другим шрифтом, можно указать шрифт из текущего стиля прямо в команде, передав в качестве соответствующего параметра словарь: {'fontname':'название_шрифта'}.

Помимо семейств, текст также может иметь стиль. Атрибут стиля style может быть либо 'italic', либо 'oblique', либо 'normal' (по умолчанию). Толщина или "жирность" шрифта, может быть задана через атрибут fontweight, который принимает значения 'bold', 'light' или 'normal' (по умолчанию). Стили и форматы можно комбинировать.

In [ ]:
# Пример 3.3

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

mpl.rcParams['font.fantasy'] = 'Arial', 'Times New Roman', 'Tahoma', 'Comic Sans MS', 'Courier'
mpl.rcParams['font.family'] = 'fantasy'

# Текущий стиль-семейство шрифтов
cfam = mpl.rcParams.get('font.family')[0]
print('cfam %s' % cfam)
cfont = mpl.rcParams.get('font.fantasy')[0]

# Первый шрифт в текущем семействе
print(mpl.rcParams.get('font.%s' % cfam))


N = 100
x = np.arange(N)
# Задаём выборку из Гамма-распредления с параметрами формы=1. и масштаба=3.0
y = np.random.gamma(1.0, 3.0, N)

fig = plt.figure()
cc = plt.hist(y) 

text_style = ['italic', 'oblique', 'normal']
font_weights = ['bold', 'light', 'normal']
for i, ts in enumerate(text_style):
    plt.text(6, 20-5*i, '%s text style' % ts, {'fontname':'Courier'}, style=ts, fontsize=14)
    plt.text(6, 35-4*i, '%s & %s text style' % (ts, font_weights[i]), {'fontname':'Courier'}, 
             style=ts, fontweight=font_weights[i], fontsize=12)
    
plt.title('Title has %s font' % cfont, fontweight='normal', color='k', fontsize=16)
plt.xlabel('Bold weight', {'fontname':'Times New Roman'}, fontweight='bold', fontsize=16)
plt.ylabel('Light weight', {'fontname':'Times New Roman'}, fontweight='light', fontsize=14)
plt.grid(True)

save('pic_3_3', fmt='png')
save('pic_3_3', fmt='pdf')

plt.show()

3.4 Кириллица и matplotlib. Подписи по-русски

Кириллица "из коробки" не поддерживается в matplotlib. Однако настроить поддержку русского алфавита несложно. Основная проблема matplotlib для отображения кириллических символов состоит в том, что по умолчанию используются шрифты, которые не поддерживают кириллицу. Соответственно, решение проблемы отображения русского алфавита заключается в смене шрифта на тот, который поддерживает кириллицу. В ОС Windows это может быть, например, Arial, Times New Roman или Tahoma. Сделать это можно как в теле самой программы-скрипта, так и в профильных настройках.

У каждого стиля шрифта определены списки из реальных шрифтов, которыми пользуются в текстовых процессорах и редакторах. Чтобы поставить шрифт, который будет корректно отображать кириллицу, можно воспользоваться таким примером:

In [ ]:
import matplotlib as mpl
mpl.rcParams['font.family'] = 'fantasy'
mpl.rcParams['font.fantasy'] = 'Arial', 'Times New Roman', 'Tahoma'

Таким образом, набор fantasy будет основным, и из него будет использован шрифт Arial. Если он не будет найден, то будет выбран второй по списку и так далее. Оба представленных шрифта корректно отображают кирилличекие символы.

Можно использовать и такой синтаксис:

In [ ]:
# Пример 3.4.1

from matplotlib import rc
 
font = {'family': 'Courier New',
        'weight': 'normal'}
rc('font', **font)

cfam = mpl.rcParams.get('font.family')[0]
print cfam
cfont = mpl.rcParams.get('font.fantasy')[0]
print cfont

plt.text(0.25, 0.45, u'Стиль %s по умолчанию' % cfam)
plt.text(0.25, 0.25, u'Шрифт Arial', {'fontname':'Arial'})

plt.xlabel(u'Ось абсцисс', {'fontname':'Arial'})
plt.ylabel(u'Ось ординат', {'fontname':'Times New Roman'})
plt.title(u'Заголовок и буква Ё! А также разные шрифты элементов рисунка',{'fontname':'Tahoma'})
plt.grid()

save('pic_3_4_1', fmt='png')
save('pic_3_4_1', fmt='pdf')

plt.show()

Список доступных в ОС шрифтов можно узнать, например, вот так:

In [ ]:
import matplotlib.font_manager as fm
for i, font in enumerate(sorted(fm.findSystemFonts())):
    # Шрифтов в системе очень много. Полный список занимает не одну страницу A4
    if(i % 50 == 0):
        print i, font

Для поиска по названию известного вам шрифта в ОС можно воспользоваться функцией findfont:

In [ ]:
import matplotlib.font_manager as fm
print 'Courier New - %s' % fm.findfont('Courier New') # Ищем Courier New
print 'Times New Roman - %s' % fm.findfont('times new roman') # Ищем times new roman строчными буквами
print 'Comic Sans MS - %s' % fm.findfont('COMIC SANS MS') # Ищем COMIC SANS MS прописными буквами

Вторым необходимым условием для отображения на рисунках matplotlib русских букв является использование unicode-строк. В python3 все строки являются юникодовыми, там дополнительных примочек не нужно. В python2 необходимо преобразовывать обычную строку в юникод-строку:

In [ ]:
str1 = 'строка 1' # обычная строка
print str1,type(str1)
str2 = u'строка 1' # unicode-строка
print str2,type(str2)

Также ставим в начале скрипта: # -- coding: utf-8 -- . В GUI Spyder такая запись вставляется в новый созданный скрипт по умолчанию.

In [ ]:
# -*- coding: utf-8 -*-
# Пример 3.4.2

from math import pi
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

#mpl.rcdefaults() # cбрасываем настройки на "по умолчанию"
mpl.rcParams['font.family'] = 'fantasy'
mpl.rcParams['font.fantasy'] = 'Times New Roman', 'Ubuntu','Arial','Tahoma','Calibri'

x = np.arange(-pi,pi+0.1,0.1)

fig = plt.figure()
ax1 = fig.add_subplot(111)
y = np.tanh(x)
y2 = np.arctan(x)
ax1.plot(x,y,'k--',label=u'Гиперболический тангенс')
ax1.plot(x,y2,'b',label=u'Арктангенс')

st = u'Заголовок по-русски'
sy = u'Ось ординат OY по-русски'
sx = u'Ось абсцисс OX по-русски'

ax1.set_title(st,size=20,color='green')
ax1.set_xlabel(sx,size=14,color='orange')
ax1.set_ylabel(sy,size=12, color='black')
ax1.grid(True)
ax1.legend(loc='best',frameon=False)

plt.tight_layout() # автоматическое выравнивание элементов на холсте plt

save('pic_3_4_2', fmt='png')
save('pic_3_4_2', fmt='pdf')

plt.show()

3.5 Работа с математическими формулами. Поддержка LaTex

Для работы с LaTex необходимо установить его дистрибутив! Создатели iPython Notebooks советуют использовать MikTex

Существенным преимуществом matplotlib является безбарьерная работа с LaTex. Нужно, чтобы в системе был установлена библиотека LaTeX (именно библиотека, а не редактор). Код LaTex оформляется в виде "raw" строки (перед строкой ставится символ r -> r'строка'). Также в настройках pyplot нужно указать, чтобы текст отрисовывался с учётом синтаксиса LaTeX. Это можно сделать через plt.rc('text', usetex=True).

In [ ]:
# Пример 3.5

import matplotlib.pyplot as plt
import numpy as np

# Преамблуа для работы с LaTeX
plt.rc('text', usetex=True)

N = 100
x = np.arange(N)
z1 = np.cos(x/10.)
z2 = np.cos(x/20.)

fig = plt.figure()
plt.fill_between(x, z2, z1, color='green', alpha=0.25) 
plt.plot(x, z1, color='green', linewidth=4.0)
plt.plot(x, z2, color='green', linewidth=4.0, alpha=0.5)
plt.title(r'$\S1.3.2 \LaTeX example$')
plt.text(22, 0.5, r'$ e=mc^2 $', fontsize='16')
plt.text(55, -0.5, r'$\displaystyle\sum_{n=1}^\infty\frac{-e^{i\pi}}{2^n}$!', fontsize=18, rotation=60)

plt.grid(True)
plt.xlabel(r'\textbf{Time (s)}')
plt.ylabel(r'\textit{Sin(x) \& cos(x)}', color='red', rotation=45)

save('pic_3_5', fmt='png')
save('pic_3_5', fmt='pdf')

plt.show()

Для корректного отображения не латеховского кода, нужно не забыть отключить его поддержку, если элементы LaTeX использовались для создания рисунка.

In [ ]:
plt.rc('text', usetex=False)
In [ ]: