четверг, 5 сентября 2013 г.

Matplotlib. Latex Font matching problems.

Сегодня я расскажу немного о проблемах применения сторонних для MatPlotlib шрифтов LaTeX2e. Один из таких шрифтов является lmodern. Но суть ограничивается не только им. Включение пакетов в преамбулу LaTeX, который используется для MatPlotlib достаточно тяжело, т.к. функция кривая, причем это заявляют и сами разработчики. Однако, так как мы с вами из того типа людей, которые постоянно гоняются за мелочами, то нам предстоит решить эту проблему.

Разработчиками MatPlotlib заложены следующие шрифты, которые гарантированно работают при компиляции графика. Список их следующий:
Bitstream Vera Serif, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif

Стоит понимать, что пользоваться только ими и надо и обычному смертному этого хватит. Но если это не так, разработчики советуют нам подключать пакеты в шапку. А именно тут возникают основные проблемы.

Разберем небольшой код:
import matplotlib.pyplot as plt
#LaTeX
plt.rcParams['text.latex.preamble']=[r"\usepackage{lmodern}"]
params = {'text.usetex' : True,
                 'font.size' : 11,
                 'font.family' : 'lmodern',
                 'text.latex.unicode': True,
                  }
plt.rcParams.update(params)

fig = plt.figure()
fig.set_size_inches(3.54,3.54)
plt.plot([1,2,3,4])
plt.xlabel("Excitation-Energy")
plt.ylabel("test")
plt.savefig("graph.pdf",
                  dpi=1000,
                  bbox_inches='tight',
                   )
В нем представлен простейший график
Сразу оговорюсь. Данный график представляет правильный вариант того, как это всё должно выглядеть.

Перейдем к LaTeX:
\documentclass[11pt]{scrartcl}
\usepackage[T1]{fontenc}\usepackage[utf8]{inputenc}\usepackage{lmodern}\usepackage{graphicx}
\begin{document}
\begin{figure} \begin{center} \includegraphics{./graph} \caption{Excitation-Energy} \label{fig:graph} \end{center}\end{figure}
\end{document}
В итоге получаем красивый конечный результат, где отсутствует разница в шрифтах.
 Вот их образцы, первый Ex это MatPlobLib, а второй это уже pdfLaTeX.


Как видим - результат достигнут.

Теперь перейдем к деталям и найдем то как мы это сделали.
Вообще, для совпадения шрифтов в двух pdf документах, приготовленных в LaTeX и в MatPlotlib необходимо соблюдать правила:

  • Размер изображения, которое вы вставляете в LaTeX должно совпадать с желаемым на печати и иметь необходимое количество dpi. Для графика это например 1000, для картинок и прочего значение может быть меньше, начиная с 200.
    Для этого необходимо поставить параметр в savefig('name',  dpi=1000)
    Размер строимой фигуры обычно задается при помощи команды
    fig.set_size_inches( a, b), где fig это созданная ранее фигура.
  • Помимо этого, график должен занимать полный размер вставляемого pdf документа, это сократит ненужные проблемы с пробелами при верстке документа.
    Для этого необходимо подавить лишние поля на графике. С этим параметром необходимо быть осторожным. Может порезать слишком большие шрифты подписи.
    В теже параметры вносим savefig('name', bbox_inches='tight')
  • Необходимо использовать одинаковое семейство шрифтов для графиков и для документа.
Если сообщать в rc параметр 'font.family' : 'lmodern' то на вид, шрифт получается толще чем надо. Однако, если хочешь таким же макаром включить шрифт в преамбулу LaTeX под MatPlotlib случается ошибка. Самая главная проблема в том, что эти два параметра должны выполняться вместе. Необходимо поставить семейство lmodern и в MatPlotlib и в LaTeX. Для этого в параметрах прописываем 'font.family' : 'lmodern', а потом напрямую вводим параметр использования пакета в преамбуле через 
plt.rcParams['text.latex.preamble']=[r"\usepackage{lmodern}"]

На этом всё, мы получаем финальный результат, как и описывалось ранее.