有没有一种有效的方法可以在 python 中将 2D 图存储为矢量图形? [英] Is there an efficient way to store 2D plots as a vector graphic in python?

查看:85
本文介绍了有没有一种有效的方法可以在 python 中将 2D 图存储为矢量图形?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试将python图形存储为矢量图形,以改善其在乳胶文档中的外观.对于一维绘图,这很好用:

将 numpy 导入为 np将Matplotlib导入为mplmpl.use('svg')new_rc_params = {"font.family":时代","font.size":12"font.serif":[],"svg.fonttype":'none'}#将文本存储为文本,而不是路径mpl.rcParams.update(new_rc_params)导入matplotlib.pyplot作为pltx = 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')

通过这种方式,我可以在inkscape中打开svg文件,并将其转换为pdf/pdf_tex,并且绘图中的每个文本都将在文档中的乳胶中呈现->与文档中其他所有位置相同的字体和字体大小.

二维图变得像 svg 文件一样大.因此,我想将绘图存储为 pdf(同样,我想将文本保留为文本.这就是我不能将绘图存储为 .png 的原因):

  mpl.use('pdf')new_rc_params = {"font.family":时代","font.size":12"font.serif":[]}#"svg.fonttype":'none'}#此处不再需要,因为我们不再使用svgmpl.rcParams.update(new_rc_params)导入matplotlib.pyplot作为pltx = np.linspace(-.5, .5, 1024)x,y = np.meshgrid(x,x)z = np.exp(-(x ** 2 + y ** 2))plt.figure()plt.title('高斯图:\ $ 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 MB).但是,文本存储为文本.

不幸的是,我现在无法在inkscape中打开pdf,因为它总是会在一段时间后崩溃.可能文件已经太大了.有什么建议么?在这种情况下,进一步下采样可能会起作用,但一般情况下可能不会.

解决方案

这是我在评论中建议的答案:

大型pdf/svg文件是由于将每个矩形存储在pcolormesh中作为矢量图形而产生的.

将图存储为svg/pdf时,我想要实现的目的是获得高分辨率图像,一旦将文件插入到乳胶文档中,文本就会呈现出来.如果分辨率足够好,绘图本身并不需要是矢量图形.

所以这是我的建议(导入的库与上面的相同):

  mpl.use('svg')new_rc_params = {"font.family":'Times',#python可能不知道Times,但是无论如何它都会用不同的字体替换它.无论如何最终决定取决于乳胶文件"font.size":12,#选择字体大小有助于乳胶将所有标签,刻度等放置在正确的位置"font.serif":[],"svg.fonttype": 'none'} #将文本存储为文本,而不是路径mpl.rcParams.update(new_rc_params)plt.figure(figsize =(6.49/2,6.49/2))#大约是A4文档文本宽度的一半plt.pcolormesh(x, y, z, rasterized = True) # 这就是诀窍.它将在python中渲染图像!plt.xlabel('Math expression: \$a + b = c\$') # 我们需要反斜杠,否则python会渲染数学表达式,这会混淆latexplt.savefig('test.svg',dpi = 1000,format ='svg',bbox_inches ='tight')#取决于最终图形的尺寸,1000 dpi对于A4文档绝对足够

存储 svg 文件后,在 Inkscape 中打开它.另存为 pdf 并在省略 PDF 中的文本并创建 LaTex 文件"处打勾.在您的乳胶文件中,您必须使用

\begin{figure}\定心\input{test.pdf_tex}\caption{这应该与您的 xlabel 具有相同的字体类型和大小}\end{图}

导入2D图.就是这样:)

I'm currently trying to store python plots as vector graphics to improve their appearance in a latex document. For 1D plots this works quite fine:

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')

This way I can open the svg file in inkscape and convert it to pdf/pdf_tex and every text in the plot will be rendered in latex within the document --> same font and fontsize as everywhere else in the document.

2D plot get increadibly large as svg files. Therefore I want to store the plot as a pdf (again, I want to keep text as text. That's why I can't store the plot as .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')

This stores the 2D plot as a pdf. Anyway, storing the plot takes a while now and it gets quite large (even with only 500 x 500 points in the plot it's about 11 MB). But, the text is stored as text.

Unfortunately I can't open the pdf in inkscape now, for it always crashes after a while. Probably the file is already to large. Any suggestions? Further downsampling might work in this case, but probably not in general.

解决方案

Here is an answer I suggested in the comments:

The large pdf/svg files result from storing every rectangle in pcolormesh as a vector graphic.

What I wanted to achieve with storing the plot as svg/pdf was to get a high-res image where the text is rendered once I insert the file in my latex document. The plot itself does not really need to be a vector graphic if the resolution is good enough.

So here is my suggestion (imported libraries are the same as above):

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

Once you have stored the svg file, open it in Inkscape. Save as pdf and set the tick at 'Omit text in PDF and create LaTex file'. In your latex file you have to use

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

to import your 2D plot. That's it :)

这篇关于有没有一种有效的方法可以在 python 中将 2D 图存储为矢量图形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆