How to show annotations with mouse hover
Asked Answered
C

2

6

I am currently employing this code to have pop up annotatations on a map when i click on a point in a Basemap Matplotlib Plot.

dcc = DataCursor(self.figure.gca())
self.figure.canvas.mpl_connect('pick_event',dcc)
plot_handle.set_picker(5)
self.figure.canvas.draw()

class DataCursor(object):

    import matplotlib.pyplot as plt

    text_template = 'x: %0.2f\ny: %0.2f' 
    x, y = 0.0, 0.0 
    xoffset, yoffset = -20 , 20
    text_template = 'A: %s\nB: %s\nC: %s'


    def __init__(self, ax): 
        self.ax = ax 
        self.annotation = ax.annotate(self.text_template,  
                xy=(self.x, self.y), xytext=(0,0),
                textcoords='axes fraction', ha='left', va='bottom', fontsize=10,
                bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=1), 
                arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0') 
                ) 
        self.annotation.set_visible(False)
        self.annotation.draggable()


    def __call__(self, event):

        self.event = event 
        self.x, self.y = event.mouseevent.xdata, event.mouseevent.ydata

        if self.x is not None:
            glim = pickle.load(open("ListA.py","rb"))
            tlim = pickle.load(open("ListB.py","rb"))
            vlim = pickle.load(open("ListC.py","rb"))
            a = glim[event.ind[0]] # ['Name'][event.ind[0]]
            b = tlim[event.ind[0]]
            c = vlim[event.ind[0]]
            temp_temp=self.text_template % (a, b, c)
            if temp_temp == self.annotation.get_text() and self.annotation.get_visible(): 
                self.annotation.set_visible(False) 
                event.canvas.draw() 
                return 
            self.annotation.xy = self.x, self.y
            self.annotation.set_text(self.text_template % (a, b, c))
            self.annotation.set_visible(True)

            event.canvas.draw()

What I am wondering, is how to show the annotations using mouse hover rather than clicking on a point?

I have seen "motion_notify_event" but it seems the code gets errors when i move the mouse around the plot area. Any Thoughts?

Catalyst answered 25/9, 2012 at 5:4 Comment(0)
D
8

Take a look at this question and demo :

from matplotlib.pyplot import figure, show
import numpy as npy
from numpy.random import rand


if 1: # picking on a scatter plot (matplotlib.collections.RegularPolyCollection)

    x, y, c, s = rand(4, 100)
    def onpick3(event):
        ind = event.ind
        print 'onpick3 scatter:', ind, npy.take(x, ind), npy.take(y, ind)

    fig = figure()
    ax1 = fig.add_subplot(111)
    col = ax1.scatter(x, y, 100*s, c, picker=True)
    #fig.savefig('pscoll.eps')
    fig.canvas.mpl_connect('pick_event', onpick3)

show()
Disposed answered 25/9, 2012 at 6:12 Comment(2)
i have seen both of these links, however i am not sure how to implement them in my current format. i also dont see how "pick_event" is a non clickable action?Catalyst
i am accepting this answer, but it is not the right answer. However, Root did link another questionwhich linked this [question] (#4453643) which gives the correct way to hover and display annotations. Note: I still used annotations instead of the wx.tooltip. It works very well!Catalyst
E
0
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

lat = 20.5937
lon = 78.9629
points_with_annotation = list()

#Event is set for any movement and annotations are set to visible when on points with anotation
def on_move(event):
    visibility_changed = False
    for point, annotation in points_with_annotation:
        should_be_visible = (point.contains(event)[0] == True)

        if should_be_visible != annotation.get_visible():
            visibility_changed = True
            annotation.set_visible(should_be_visible)

    if visibility_changed:        
        plt.draw()


fig = plt.figure()
ax = plt.axes()

m = Basemap(projection='mill', llcrnrlat=-90, llcrnrlon=-180, urcrnrlat=90, urcrnrlon=180, resolution='c')
m.fillcontinents(color='white', lake_color='white')
m.drawcoastlines(linewidth=0.5, color='k')
m.drawcountries(linewidth=0.5, color='k')
m.drawmapboundary(fill_color='white')

xpt, ypt = m(lon,lat)
point, = m.plot(xpt, ypt, marker='o', markersize=5, alpha=0.85, visible=True)
annotation = ax.annotate("Lat: %s Lon: %s" % (lat,lon), 
    xy=(xpt, ypt), xycoords='data',
    xytext=(xpt + 1, ypt), textcoords='data',
    horizontalalignment="left",
    arrowprops=dict(arrowstyle="simple",
    connectionstyle="arc3,rad=-0.2"),
    bbox=dict(boxstyle="round", facecolor="w", 
    edgecolor="0.5", alpha=0.9)
        )


annotation.set_visible(False)
points_with_annotation.append([point, annotation])
on_move_id = fig.canvas.mpl_connect('motion_notify_event', on_move)
plt.show()

Here's the code to plot a coordinate on a map and enable a popup during hover. I got the code for the on_move event from the answer to this question : Matplotlib basemap: Popup box Hope this helps.

Estriol answered 27/12, 2017 at 9:58 Comment(2)
It would be nice to have an explanation on this, as to why we should write the code like this and not just paste the code and say that you've got it from somewhere. This would help others too if they come to your answer in the future.Saxophone
@Saxophone sorry. Edited.Estriol

© 2022 - 2024 — McMap. All rights reserved.