Установка размера холста для печати в Matplotlib

Я хотел бы, чтобы Matplotlib/Pyplot генерировал графики с постоянным размером холста. То есть цифры могут иметь разные размеры для размещения описаний осей, но область построения (прямоугольник, внутри которого рисуются кривые) всегда должна иметь одинаковый размер.

Есть ли простой способ достичь этого? Опция figsize pyplot.figure(), кажется, устанавливает общий размер фигуры, а не размер холста, поэтому я получаю другой размер холста всякий раз, когда описание оси занимает больше или меньше места.

Ответ 1

Это одно из моих самых больших разочарований с Matplotlib. Я часто работаю с растровыми данными, где, например, я хочу добавить colormap, legend и некоторый заголовок. Любой простой пример из галереи matplotlib, делающий это, приведет к другому разрешению и, следовательно, к повторной выборке данных. Особенно при анализе изображений вы не хотите никакой (нежелательной) передискретизации.

Вот что я обычно делаю, хотя мне бы хотелось узнать, есть ли более простые или лучшие способы.

Давайте начнем с загрузки изображения и вывода его так же, как и с тем же разрешением:

import matplotlib.pyplot as plt
import urllib2

# load the image
img = plt.imread(urllib2.urlopen('http://upload.wikimedia.org/wikipedia/en/thumb/5/56/Matplotlib_logo.svg/500px-Matplotlib_logo.svg.png'))

# get the dimensions
ypixels, xpixels, bands = img.shape

# get the size in inches
dpi = 72.
xinch = xpixels / dpi
yinch = ypixels / dpi

# plot and save in the same size as the original
fig = plt.figure(figsize=(xinch,yinch))

ax = plt.axes([0., 0., 1., 1.], frameon=False, xticks=[],yticks=[])
ax.imshow(img, interpolation='none')

plt.savefig('D:\\mpl_logo.png', dpi=dpi, transparent=True)

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

Подобным образом, как описано выше, вы можете добавить некоторый запас вокруг изображения, чтобы можно было использовать метки или цветные панели и т.д.

В этом примере добавляется 20% -ный запас над изображением, который затем используется для построения заголовка:

fig = plt.figure(figsize=(xinch,yinch/.8))

ax = plt.axes([0., 0., 1., .8], frameon=False, xticks=[],yticks=[])
ax.imshow(img, interpolation='none')
ax.set_title('Matplotlib is fun!', size=16, weight='bold')

plt.savefig('D:\\mpl_logo_with_title.png', dpi=dpi)

Таким образом, величина y-size (высота) увеличивается, а y-размер осей уменьшается одинаково. Это дает большее (общее) выходное изображение, но область осей будет по-прежнему иметь тот же размер.

Может быть, у меня есть свойство фигуры или осей, такое как .set_scale(), чтобы заставить true 1-on-x выход.