Question

I want to know how to create a popup box in a basemap plot. When I hover my mouse over a location , it should trigger the popup box.

Is this possible?

Was it helpful?

Solution

Yes it is possible thanks to matplotlib's event handling framework. I couldn't find an already written example which does what you are particularly interested in so I wrote one (which I will put forward for inclusion in the matplotlib source).

I would read http://matplotlib.sourceforge.net/users/event_handling.html thoroughly to best understand what is going on. Please note that although it sounds like the perfect solution "pick_event" is for mouse clicks -not for mouse over- events and doesn't work in this case.

My code, which could be objectified very nicely should one want, looks like:

import matplotlib.pyplot as plt

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


points_with_annotation = []
for i in range(10):
    point, = plt.plot(i, i, 'o', markersize=10)

    annotation = ax.annotate("Mouseover point %s" % i,
        xy=(i, i), xycoords='data',
        xytext=(i + 1, i), 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)
        )
    # by default, disable the annotation visibility
    annotation.set_visible(False)

    points_with_annotation.append([point, annotation])


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()

on_move_id = fig.canvas.mpl_connect('motion_notify_event', on_move)

plt.show()

Hopefully everything should be fairly readable. A high level overview of the code goes:

  • Create a list of [point, annotation] pairs, where by default the annotation is not visible
  • Register a function, "on_move", to be called every time there is mouse motion detected
  • The on_move function iterates through each point and annotation, if the mouse is now over one of the points, make its associated annotation visible, if it is not, make it invisible. (the contains method is documented here)

Screenshot of the result

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top