Есть ли эффективный способ сохранить 2D-графики в виде векторной графики в Python? - PullRequest
0 голосов
/ 24 мая 2018

В настоящее время я пытаюсь сохранить графики Python как векторную графику, чтобы улучшить их внешний вид в латексном документе.Для 1D графиков это работает довольно хорошо:

import numpy as np
import matplotlib as mpl
mpl.use('svg')
new_rc_params = {
    "font.family": 'Times',
    "font.size": 12,
    "font.serif": [],
    "svg.fonttype": 'none'} #to store text as text, not as path
mpl.rcParams.update(new_rc_params)
import matplotlib.pyplot as plt

x = np.linspace(-.5, .5, 1024)

plt.figure()
plt.plot(x, x)
plt.title('\$x = y\$')
plt.xlabel('\$x\$ [m]')
plt.ylabel('\$y\$ [m]')
plt.savefig('test.svg', format = 'svg', bbox_inches = 'tight')

Таким образом, я могу открыть файл svg в inkscape и преобразовать его в pdf / pdf_tex, и каждый текст на графике будет отображаться в латексе внутри документа -> тот же шрифт и размер шрифта, что и везде в документе.

2D-график становится невероятно большим, как svg-файлы.Поэтому я хочу сохранить график в формате PDF (опять же, я хочу сохранить текст как текст. Вот почему я не могу сохранить график как .png):

mpl.use('pdf')
new_rc_params = {
    "font.family": 'Times',
    "font.size": 12,
    "font.serif": []
    }
    #"svg.fonttype": 'none'} #not needed here since we don't use svg anymore
mpl.rcParams.update(new_rc_params)
import matplotlib.pyplot as plt

x = np.linspace(-.5, .5, 1024)
x, y = np.meshgrid(x, x)
z = np.exp(-(x**2 + y**2))

plt.figure()
plt.title('Gaussian plot: \$z = \exp{-(x^2 + y^2)}\$')
plt.pcolormesh(x, y, z)
plt.colorbar()
plt.savefig('test.pdf', bbox_inches='tight', format='pdf')

При этом 2D-график сохраняется какPDFВ любом случае, сохранение графика занимает некоторое время, и оно становится довольно большим (даже если на графике только 500 x 500 точек, это около 11 МБ).Но текст хранится в виде текста.

К сожалению, я не могу открыть pdf в inkscape, потому что он всегда вылетает через некоторое время.Вероятно, файл уже слишком большой.Какие-либо предложения?В этом случае может сработать дальнейшее понижение частоты дискретизации, но, вероятно, не в целом.

1 Ответ

0 голосов
/ 24 мая 2018

Вот ответ, который я предложил в комментариях:

Большие файлы pdf / svg являются результатом хранения каждого прямоугольника в pcolormesh как векторной графики.

Чего я хотел добиться с помощью сохраненияСюжет в формате svg / pdf заключался в том, чтобы получить изображение в высоком разрешении, где текст отображается после того, как я вставлю файл в свой латексный документ.Сам график не обязательно должен быть векторной графикой, если разрешение достаточно хорошее.

Итак, вот мое предложение (импортированные библиотеки такие же, как указано выше):

mpl.use('svg')
new_rc_params = {
    "font.family": 'Times', #probably python doesn't know Times, but it will replace it with a different font anyway. The final decision is up to the latex document anyway
    "font.size": 12, #choosing the font size helps latex to place all the labels, ticks etc. in the right place
    "font.serif": [],
    "svg.fonttype": 'none'} #to store text as text, not as path
mpl.rcParams.update(new_rc_params)

plt.figure(figsize = (6.49/2, 6.49/2)) #that's about half the text width of an A4 document
plt.pcolormesh(x, y, z, rasterized = True) # That's the trick. It will render the image already in python!
plt.xlabel('Math expression: \$a + b = c\$') # We need the backslashes because otherwise python will render the mathematic expression which will confuse latex
plt.savefig('test.svg', dpi = 1000, format = 'svg', bbox_inches = 'tight') # depends on your final figure size, 1000 dpi should be definitely enough for A4 documents

Один разВы сохранили файл SVG, откройте его в Inkscape.Сохраните как pdf и установите флажок «Пропустить текст в PDF и создать файл LaTex».В вашем латексном файле вы должны использовать

\begin{figure}
    \centering
    \input{test.pdf_tex}
    \caption{This should have the same font type and size as your xlabel}
\end{figure}

, чтобы импортировать 2D-график.Вот и все:)

...