matplotlib鼠标悬停在轴之间的注解上

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

bounty将在5天后过期。回答此问题可获得+50声望奖励。warped希望吸引更多人关注此问题。

我正在寻找两个子情节之间绘制的注解线。
此时,我正在通过访问引发“motion_notify_event”的ax来重新示例化注解。
最小示例:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import ConnectionPatch

def update_line_annotation(event, line):
    x, y = event.xdata, event.ydata
    ax = event.inaxes

    global annot # in the real use case, annot is stored as class attribute
    annot = ax.annotate(
        f'{line}',
        xy=(x, y),
        xytext=(5, 5),
        textcoords='offset points',
    )

def hover(event):
    annot.set_visible(False)
    fig.canvas.draw_idle()

    for line in cons:
        cont, ind = line.contains(event)
        if cont:
            update_line_annotation(event, line)
            annot.set_visible(True)
            break
  

if __name__ == '__main__':
    fig, axes = plt.subplots(ncols=2)

    annot = axes[0].annotate(
        f'',
        xy=(0,0),
        xytext=(20, 20),
        textcoords='offset points',
    )
    annot.set_visible(False)

    cons = []
    for a in range(2):
        con = ConnectionPatch(
            xyA=np.random.randint(0,10,2),
            xyB=np.random.randint(0,10,2),
            coordsA='data',
            coordsB='data',
            axesA=axes[0],
            axesB=axes[1],
        )
        cons.append(con)
        axes[1].add_artist(con)

    fig.canvas.mpl_connect('motion_notify_event', hover)
    
    for ax in axes:
        ax.set_ylim(0,9)
        ax.set_xlim(0,9)

    plt.show()

我目前的方法有两个问题:

  • 如果光标位于左坐标轴中,则注解绘制在右坐标轴后面。
  • 如果光标在两个轴之间,则会抛出错误,因为event.inaxes返回None,而None没有注解方法。

我有两种可能的解决方案,但我在matplotlib中找不到必要的功能:

  • 相对于右轴进行所有注记。这需要获取相对于该轴的xdata,ydata坐标
  • 生成与ConnectionPatch相关的所有注解

非常感谢您的帮助!

xqkwcwgp

xqkwcwgp1#

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import ConnectionPatch

def hover(event):
    for line in cons:
        cont, ind = line.contains(event)
        if cont:
            annot = line.annotate(
                f'This is line {line}',
                xy=(0.5, 0.5),  # Anchor the annotation at the center of the ConnectionPatch
                xycoords=line.get_path(),  # Use the coordinates of the ConnectionPatch
                ha='center',
                va='center',
            )
            annot.set_visible(True)
            break
  

if __name__ == '__main__':
    fig, axes = plt.subplots(ncols=2)

    cons = []
    for a in range(2):
        con = ConnectionPatch(
            xyA=np.random.randint(0,10,2),
            xyB=np.random.randint(0,10,2),
            coordsA='data',
            coordsB='data',
            axesA=axes[0],
            axesB=axes[1],
        )
        cons.append(con)
        axes[1].add_artist(con)

    fig.canvas.mpl_connect('motion_notify_event', hover)
    
    for ax in axes:
        ax.set_ylim(0,9)
        ax.set_xlim(0,9)

    plt.show()

此代码创建两个子绘图区,然后在它们之间绘制两个ConnectionPatch对象。当鼠标悬停在其中一条线上时,将使用ConnectionPatch的坐标向该线本身添加一个注解。这可以避免您描述的问题,即注解将绘制在其中一个子绘图区的后面,或者event.inaxes将为None

相关问题