I am looking to annotate lines that are drawn between two subplots.
At this moment, I am re-instantiating the annotation by accessing ax that fired the 'motion_notify_event'.
Minimal example:
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()
There are two problems with my current approach:
- if the cursor is located in the left ax, then the annotation is drawn behind the right ax.
- if the cursor is between the two ax, then errors are thrown, because event.inaxes returns None, and None has no annotation method.
I have two possible solutions, for which I cannot find the necessary functionality in matplotlib:
- make all annotations with respect to the right ax. This requires getting xdata, ydata coordinates with respect to that ax
- make all annotations with respect to the ConnectionPatch
Help is greatly appreciated!
from matplotlib mouseover annotation between axes
No comments:
Post a Comment