matplotlib 在具有多个轴的图形上绘制线条

aoyhnmkz  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(140)

我已经创建了一个具有多个轴的图形,并向其中的一些轴添加了AnchoredText。此AnchoredText就像一个标签,将它所在的轴连接到外部轴,如下所示:
[ Example image ](英文)
我试过像这样使用AnnnotationBbox:

from matplotlib import pyplot as plt
from matplotlib.offsetbox import AnchoredText, AnnotationBbox, TextArea

fig_width = 16
fig_height = 9

fig = plt.figure(figsize=(fig_width, fig_height))

fig.add_axes(
    (0, 0, 1, 1),
    alpha=1,
    xticks=[],
    yticks=[],
)

fig.get_axes()[-1].set_xlim(0, fig_width)
fig.get_axes()[-1].set_ylim(0, fig_height)

fig.add_axes(
    (0.66, 0.225, 0.075, 0.025),
    label="L1",
    alpha=1,
    xticks=[],
    yticks=[],
)

axis = fig.get_axes()[-1]

axis.set_xlim(
    fig_width * 0.66, fig_width * (0.66 + .075)
)
axis.set_ylim(
    fig_height * .225, fig_height * (.225 + .025)
)

circle = AnchoredText(
        s="L1",
        frameon=False,
        loc="upper left",
        prop=dict(bbox=dict(boxstyle="circle")),
    )

axis.add_artist(circle)

fig.add_axes(
    (0.62, 0.28, 0.03, 0.04),
    label="L2",
    alpha=1,
    xticks=[],
    yticks=[],
)

axis = fig.get_axes()[-1]

axis.set_xlim(
    fig_width * 0.62, fig_width * (0.62 + .03)
)
axis.set_ylim(
    fig_height * .28, fig_height * (.28 + .04)
)

def get_axes(fig, name):
    for ax in fig.axes:
        label = ax.get_label()

        if label == name:
            return ax

l1 = get_axes(fig, "L1") # Gets axis with given label
l2 = get_axes(fig, "L2")
offsetbox = TextArea("Test")
    
# Get the top outer limit of the l2 axis
xlim = (l2.get_xlim()[0] + l2.get_xlim()[1]) / 2
ylim = l2.get_ylim()[1]
xy = [xlim, ylim]

# Approximating the coordinates of AnchoredText
xlim2 = l1.get_xlim()[0] * 0.25
ylim2 = l1.get_ylim()[0] * 0.75
xy2 = [xlim2, ylim2]

ab = AnnotationBbox(
   offsetbox,
   xy2,
   xybox=xy,
   xycoords="data",
   boxcoords=("axes fraction", "data"),
   box_alignment=(0.0, 0.5),
   arrowprops=dict(arrowstyle="-"),
)

l1.add_artist(ab)

plt.show()

运行上面的代码并没有在我的图中添加行,我不知道为什么。有没有更好的方法来解决这个问题?如果有的话,我如何才能得到AnchoredText的限制?

h5qlskok

h5qlskok1#

这里是刺它。诀窍是绘制子情节在一个一般的空白(和透明)轴,然后绘制一条线连接子情节。

from matplotlib import pyplot as plt
from matplotlib.offsetbox import AnchoredText

# Initialize figure
fig, ax_canvas = plt.subplots(figsize=(12, 6), constrained_layout=True)

# Set order of drawing, Ax canvas will be the last one so that the line connecting the other plots is on top
ax_canvas.set_zorder(10)
# Hide the main axis to set our blank canvas
ax_canvas.set_axis_off()
# Make background transparent so that it does not cover other plots when we draw the connecting line
ax_canvas.patch.set_facecolor('None')
ax_canvas.patch.set_visible(False)
# Set dimensions so it's easier to plot the line correctly
ax_canvas.set_xlim([0, 1])
ax_canvas.set_ylim([0, 1])

# First subplot axes in the canvas
left1, bottom1, width1, height1 = [0.1, 0.5, 0.5, 0.4]
ax1 = fig.add_axes([left1, bottom1, width1, height1])
ax1.set_zorder(0)
ax1.set_xlim([0, 1])
ax1.set_ylim([0, 1])
ax1.text(0.5, 0.5, 'Ax 1')

# Add the circle
circle = AnchoredText(
    s="L1",
    frameon=False,
    loc="upper left",
    prop=dict(bbox=dict(boxstyle="circle")),
)
ax1.add_artist(circle)

# Second axes in the canvas
left2, bottom2, width2, height2 = [0.45, 0.15, 0.3, 0.2]
ax2 = fig.add_axes([left2, bottom2, width2, height2])
ax1.set_zorder(0)
ax2.set_xlim([0, 1])
ax2.set_ylim([0, 1])
ax2.text(0.5, 0.5, 'Ax 2')

# Line connecting Ax1 and Ax2 in the Ax canvas
# The values below are eyeballed based on the ax_canvas having x and y limits 0 to 1
# Roughly where the circle is in Ax1, x middle of Ax2
x_line = [0.125, 0.6]
# Roughly where the circle is in Ax1, height of Ax2
y_line = [0.87, 0.35]
ax_canvas.plot(x_line, y_line, c='k', ls='--')

plt.show()

相关问题