如何在Matplotlib中获得固定的像素高度、固定的数据x/y纵横比以及自动删除水平空白边距?
让我们以此为出发点,基于: 这让我可以做:如何在Matplotlib中获得固定的像素高度、固定的数据x/y纵横比以及自动删除水平空白边距?,matplotlib,Matplotlib,让我们以此为出发点,基于: 这让我可以做: ./main.py 400 && identify main.png 要生成正确的所需高度为400像素的图像,请执行以下操作: main.png PNG 533x400 533x400+0+0 8-bit sRGB 6058B 0.000u 0:00.000 然而,在绘图的左侧和右侧都有很多空白。这个空间是由于1的固定纵横比造成的,这也是我想要的(x和y数据具有相同的大小)。我们可以通过删除set\u aspect调用来确认,该调
./main.py 400 && identify main.png
要生成正确的所需高度为400像素的图像,请执行以下操作:
main.png PNG 533x400 533x400+0+0 8-bit sRGB 6058B 0.000u 0:00.000
然而,在绘图的左侧和右侧都有很多空白。这个空间是由于1
的固定纵横比造成的,这也是我想要的(x和y数据具有相同的大小)。我们可以通过删除set\u aspect
调用来确认,该调用提供了一个具有合理大小的边距的数字:
但是我也想要1/1的纵横比
我曾尝试用几种方法从中删除此空间:但没有一种方法满足了我的要求
例如,如果我添加:
plt.savefig(bbox_inches='tight',
我得到了想要的图像:
但高度不再是我想要的400:
main.png PNG 189x345 189x345+0+0 8-bit sRGB 4792B 0.000u 0:00.000
或者,如果我尝试添加:
plt.tight_layout(pad=0)
高度正确,但未删除水平空间:
我可以做的一件事是显式设置宽度,如下所示:
import sys
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
h = int(sys.argv[1])
w = int(sys.argv[2])
fig, ax = plt.subplots(nrows=2, ncols=1)
wi, hi = fig.get_size_inches()
fig.set_size_inches(hi*(w/h), hi)
t = np.arange(-10., 10., 1.)
a = ax[0]
a.set_aspect(1)
a.plot(t, t, '.')
a = ax[1]
a.plot(t, -t, '.')
a.set_aspect(1)
plt.tight_layout(pad=1)
plt.savefig(
'main.png',
format='png',
dpi=h/hi,
facecolor='y',
)
并将其与:
./main.py 400 250 && identify main.png
其中250是通过反复试验选择的,这确实给出了精确的像素尺寸和好看的输出:
但是我不希望通过反复试验来找到值250,我希望它由matplotlib自动确定
这可能就是问题所在,但如果没有具体的例子就很难确定
在matplotlib==3.2.2上测试。我不知道是否理解您的问题,但如果您想限制1x2子地块布局图形中的空白,只需创建一个宽度为高度一半的图形:
h = 400
nrows = 2
w = h/nrows
dpi = 100
fig, ax = plt.subplots(nrows=nrows, ncols=1, figsize=(w/dpi, h/dpi), dpi=dpi)
t = np.arange(-10., 10., 1.)
a = ax[0]
a.set_aspect(1)
a.plot(t, t, '.')
a = ax[1]
a.plot(t, -t, '.')
a.set_aspect(1)
plt.tight_layout(pad=1)
plt.savefig(
'main.png',
format='png',
dpi=dpi,
facecolor='y',
)
>识别main.png
main.png png 200x400 200x400+0+0 8位sRGB 6048B 0.000u 0:00.000
我不知道我是否理解你的问题,但如果你想用1x2子地块布局限制图形中的空白,你只需创建一个宽度为高度一半的图形:
h = 400
nrows = 2
w = h/nrows
dpi = 100
fig, ax = plt.subplots(nrows=nrows, ncols=1, figsize=(w/dpi, h/dpi), dpi=dpi)
t = np.arange(-10., 10., 1.)
a = ax[0]
a.set_aspect(1)
a.plot(t, t, '.')
a = ax[1]
a.plot(t, -t, '.')
a.set_aspect(1)
plt.tight_layout(pad=1)
plt.savefig(
'main.png',
format='png',
dpi=dpi,
facecolor='y',
)
>识别main.png
main.png png 200x400 200x400+0+0 8位sRGB 6048B 0.000u 0:00.000
SVG输出+
plt.savefig(bbox\u inches='tight'
+Inkscape转换
这太糟糕了,但它做了我想要的,没有很多额外的样板,所以我们开始:
#!/usr/bin/env python3
import sys
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
h = int(sys.argv[1])
fig, ax = plt.subplots(nrows=2, ncols=1)
t = np.arange(-10., 10., 1.)
a = ax[0]
a.set_aspect(1)
a.plot(t, t, '.')
a = ax[1]
a.plot(t, -t, '.')
a.set_aspect(1)
plt.savefig(
'main.svg',
format='svg',
dpi=h/fig.get_size_inches()[1],
facecolor='y',
bbox_inches='tight',
)
然后:
inkscape -b FFF -e main.png -h 400 main.svg
输出:
bbox\u inches='tight'
提供了一个外观不错的图像,没有太多的边框,但会使我丢失确切的大小,因此我们使用SVG输出作为解决这一问题的方法
这应该可以很好地工作,因为SVG是一种矢量格式,因此应该无缝地扩展到任何大小
我使用Inkscape进行转换,因为Imagemagick需要您手动计算分辨率:
在Inkscape 0.92.5上测试。SVG输出+
plt.savefig(bbox\u inches='tight'
+Inkscape转换
这太糟糕了,但它做了我想要的,没有很多额外的样板,所以我们开始:
#!/usr/bin/env python3
import sys
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
h = int(sys.argv[1])
fig, ax = plt.subplots(nrows=2, ncols=1)
t = np.arange(-10., 10., 1.)
a = ax[0]
a.set_aspect(1)
a.plot(t, t, '.')
a = ax[1]
a.plot(t, -t, '.')
a.set_aspect(1)
plt.savefig(
'main.svg',
format='svg',
dpi=h/fig.get_size_inches()[1],
facecolor='y',
bbox_inches='tight',
)
然后:
inkscape -b FFF -e main.png -h 400 main.svg
输出:
bbox\u inches='tight'
提供了一个外观不错的图像,没有太多的边框,但会使我丢失确切的大小,因此我们使用SVG输出作为解决这一问题的方法
这应该可以很好地工作,因为SVG是一种矢量格式,因此应该无缝地扩展到任何大小
我使用Inkscape进行转换,因为Imagemagick需要您手动计算分辨率:
在Inkscape 0.92.5上测试。好的,我应该用它进行更多的测试。这个解决方案是合理的。但是,自己进行nrow/ncol操作有点烦人。如果添加了其他垂直非绘图区域元素,空间也会返回,例如
a.set_title('a',fontdict=dict(fontsize='75'))
。虽然在实践中这可能并不常见(字体大小过大)。我现在还注意到,在更一般的情况下,纵横比也需要考虑(这个答案适用于a.set\u aspect(1)
)。好的,我应该对此进行更多的测试。这个解决方案是合理的。但我自己必须进行nrow/ncol操作有点烦人。如果添加了其他垂直非绘图区域元素,空间也会返回,例如a.set_title('a',fontdict=dict(fontsize='75'))
。尽管在实践中这可能并不常见(字体太大了)。我现在还注意到,在更一般的情况下,纵横比也需要考虑(这个答案适用于a.set\u aspect(1)
)的特定情况)。