在matplotlib中固定大小的矩形?

时间:2018-11-02 15:47:42

标签: python matplotlib

有没有办法在X轴的整个长度上绘制一个矩形,但其固定高度和静态高度为20像素?矩形的高度应保持恒定像素,而不管缩放图或调整图大小。我已经花了数小时寻找解决方案,但是我无法使其正常工作。有什么建议么? 谢谢enter image description here

1 个答案:

答案 0 :(得分:0)

您要创建一个矩形,在坐标轴中定位,并在坐标轴中水平设置尺寸,但高度以像素(屏幕坐标)为单位。

这里的棘手之处在于,简单地应用混合变换是行不通的,因为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。使用回调

或者,您可以使用回调来调整矩形的高度。

i。轴坐标,更新高度

在此,可以在轴坐标中定义矩形,这对于位置和宽度都很有用。然后,可以将高度计算为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像素/数字dpi高。在该插图的内部,您可以创建一个填充整个轴的矩形。

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