автоматическое приведение изображения matplotlib в соответствие с другой меткой субплота - PullRequest
0 голосов
/ 31 августа 2018

проблема

Я пытаюсь нанести изображение рядом с некоторыми данными. Тем не менее, я бы хотел, чтобы изображение расширялось, чтобы оно находилось на одном уровне с метками сюжета. Например, следующий код (с использованием этого учебного изображения ):

# make the incorrect figure
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
fig = plt.figure(figsize=(8,3))
ax_image = plt.subplot(1,2,1)
plt.imshow(mpimg.imread('stinkbug.png'))
plt.subplot(1,2,2)
plt.plot([0,1],[2,3])
plt.ylabel("y")
plt.xlabel("want image flush with bottom of this label")
fig.tight_layout()
ax_image.axis('off')
fig.savefig("incorrect.png")

дает этот участок с дополнительным пробелом:

incorrect image

Хакерская попытка решения

Я бы хотел сюжет, который не тратит пустое пространство. Следующий хакерский код (в духе эта ссылка SO ) выполняет это:

# make the correct figure with manually changing the size
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
fig = plt.figure(figsize=(8,3))
ax_image = fig.add_axes([0.02,0,0.45,1.0])
plt.imshow(mpimg.imread('stinkbug.png'))
plt.subplot(1,2,2)
plt.plot([0,1],[2,3])
plt.ylabel("y")
plt.xlabel("want image flush with bottom of this label")
fig.tight_layout()
ax_image.axis('off')
fig.savefig("correct.png")

получая следующий рисунок:

correct image

Вопрос

Есть ли способ построить изображение вровень с другими вспомогательными участками, не прибегая к ручной настройке размеров фигуры?

1 Ответ

0 голосов
/ 31 августа 2018

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

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib.transforms as mtrans

fig, (ax_image, ax) = plt.subplots(ncols=2, figsize=(8,3))

ax_image.imshow(mpimg.imread('https://matplotlib.org/_images/stinkbug.png'))
ax_image.set_aspect("auto")
ax.plot([0,1],[2,3])
ax.set_ylabel("y")
xlabel = ax.set_xlabel("want image flush with bottom of this label")
fig.tight_layout()
ax_image.axis('off')

fig.canvas.draw()
xlabel_bbox = ax.xaxis.get_tightbbox(fig.canvas.get_renderer())
xlabel_bbox = xlabel_bbox.transformed(fig.transFigure.inverted())
bbox1 = ax.get_position().union((ax.get_position(),xlabel_bbox))
bbox2 = ax_image.get_position()
bbox3 = mtrans.Bbox.from_bounds(bbox2.x0, bbox1.y0, bbox2.width, bbox1.height)
ax_image.set_position(bbox3)

plt.show()

enter image description here

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

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib.transforms as mtrans

fig, (ax_image, ax) = plt.subplots(ncols=2, figsize=(8,3))

ax_image.imshow(mpimg.imread('https://matplotlib.org/_images/stinkbug.png'))
ax.plot([0,1],[2,3])
ax.set_ylabel("y")
xlabel = ax.set_xlabel("want image flush with bottom of this label")
fig.tight_layout()
ax_image.axis('off')

fig.canvas.draw()
xlabel_bbox = ax.xaxis.get_tightbbox(fig.canvas.get_renderer())
xlabel_bbox = xlabel_bbox.transformed(fig.transFigure.inverted())
bbox1 = ax.get_position().union((ax.get_position(),xlabel_bbox))
bbox2 = ax_image.get_position()
aspect=bbox2.height/bbox2.width
bbox3 = mtrans.Bbox.from_bounds(bbox2.x0-(bbox1.height/aspect-bbox2.width)/2., 
                                bbox1.y0, bbox1.height/aspect, bbox1.height)
ax_image.set_position(bbox3)

plt.show()

enter image description here

...