Фиксированный размер прямоугольника в matplotlib? - PullRequest
0 голосов
/ 02 ноября 2018

Есть ли способ построить прямоугольник, охватывающий всю длину оси X , но с фиксированной и статической высотой, скажем, 20 пикселей? Высота прямоугольника должна оставаться постоянной величиной пикселей независимо от увеличения или изменения размера графика. Я часами искал решение для этого, но я просто не могу заставить его работать. Какие-либо предложения? Спасибо enter image description here

1 Ответ

0 голосов
/ 03 ноября 2018

Вы хотите создать прямоугольник, позиционированный по координатам осей, а также горизонтально по координатам осей, но с высотой в пиксельных (экранных) координатах.

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

A. Использование смещенного поля

Решение состоит в том, чтобы создать прямоугольник и упаковать его в matplotlib.offsetbox.AuxTransformBox. Тогда применение смешанного преобразования к AuxTransformBox повлияет только на ширину и высоту.
AuxTransformBox затем может быть упакован в matplotlib.offsetbox.AnchoredOffsetbox. Это расположено, подобно легенде, внутри bbox, который по умолчанию является осями bbox. Поскольку оси действительно являются желаемой системой для использования здесь, bbox_to_anchor указывать не нужно. Внутри осей bbox в качестве точки привязки выбран нижний левый угол (loc="lower left").

import matplotlib.pyplot as plt
import matplotlib.offsetbox
import matplotlib.transforms as mtransforms

fig, ax = plt.subplots()

# create rectangle with 
# * lower left corner at (0,0); will later be interpreted as axes coordinates
# * width=1; will later be interpreted in axes coordinates
# * height=20; will later be interpreted as pixel coordinates
rect = plt.Rectangle((0,0), 1,20)

# create transform; axes coordinates along x axis, pixel coordinates along y axis
trans = mtransforms.blended_transform_factory(ax.transAxes, 
                                              mtransforms.IdentityTransform())
# create an offset box from the above transform; the contents will be transformed
# with trans from above
aux = matplotlib.offsetbox.AuxTransformBox(trans)
aux.add_artist(rect)

# create an anchored offsetbox. Its child is the aux box from above,
# its position is the lower left corner of the axes (loc="lower left")
ab = matplotlib.offsetbox.AnchoredOffsetbox("lower left", pad=0, borderpad=0, frameon=False)
ab.set_child(aux)

ax.add_artist(ab)
plt.show()

enter image description here

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

B. Использование обратного вызова

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

я. координаты осей, высота обновления

Здесь прямоугольник может быть определен в координатах осей, что полезно как для положения, так и для ширины. Тогда высота может быть рассчитана как 20 пикселей, разделенные на высоту осей в пикселях. Затем вы можете пересчитывать высоту каждый раз, когда изменяется размер фигуры и изменяется высота осей.

import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms

fig, ax = plt.subplots()

height = 20 # pixels
rect = plt.Rectangle((0,0), 1,1, transform=ax.transAxes)
ax.add_patch(rect)

def update_rect(evt=None):
    bbox_pixel = mtransforms.TransformedBbox(ax.get_position(), fig.transFigure)
    rect.set_height(height/bbox_pixel.height)

update_rect()
fig.canvas.mpl_connect("resize_event", update_rect)

plt.show()
* * II тысяча тридцать-семь. Пиксельные координаты, позиция обновления и ширина

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

import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms

fig, ax = plt.subplots()

pos = (0,0) #axes coordinates
width = 1   #   -"-
rect = plt.Rectangle((0,0), 20,20, transform=None)
ax.add_patch(rect)

def update_rect(evt=None):
    bbox_pixel = mtransforms.TransformedBbox(ax.get_position(), fig.transFigure)
    print(bbox_pixel.width)
    rect.set_width(bbox_pixel.width*width)
    rect.set_xy((bbox_pixel.x0 + pos[0]*bbox_pixel.width, 
                 bbox_pixel.y0 + pos[1]*bbox_pixel.height))

update_rect()
fig.canvas.mpl_connect("resize_event", update_rect)

plt.show()

C. Создание врезки осей

Вы также можете создать врезные оси, расположенные в левом нижнем углу, которые имеют ширину 100% родительских осей и высоту 20 пикселей / дюйм / дюйм. Внутри этой вставки вы можете создать прямоугольник, который заполняет все оси.

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes

fig, ax = plt.subplots()

rect_ax = inset_axes(ax, "100%", 20/fig.dpi, loc="lower left", borderpad=0)
rect_ax.axis("off")

rect=plt.Rectangle((0,0), 1,1, transform=rect_ax.transAxes)
rect_ax.add_patch(rect)

plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...