Reputation: 9482
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:
I have two possible solutions, for which I cannot find the necessary functionality in matplotlib:
Help is greatly appreciated!
Upvotes: 2
Views: 642
Reputation: 3608
Specify figure coordinates figure pixels
for the xycoords
of the annotation. Then use event.x
and event.y
instead of xdata
and ydata
.
You can also use plt.annotate
instead of the axes so you don't need to use event.inaxes
at all. So it doesn't matter if that returns None
or not.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import ConnectionPatch
def update_line_annotation(event, line):
x, y = event.x, event.y
global annot # in the real use case, annot is stored as class attribute
annot = plt.annotate(
f'{line}',
xy=(x, y),
xycoords='figure pixels',
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()
Upvotes: 1