2012-09-25 32 views
6

Actualmente estoy empleando este código para tener anotaciones emergentes en un mapa cuando hago clic en un punto en un gráfico de Matplotlib del mapa base.Python y Matplotlib y anotaciones con Mouse Hover

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

Lo que estoy preguntando, es la forma de mostrar las anotaciones usando cursor del mouse en lugar de hacer clic en un punto?

He visto "motion_notify_event" pero parece que el código tiene errores cuando muevo el mouse por el área de trazado. ¿Alguna idea?

Respuesta

8

Tome un vistazo a this question y 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() 
+0

he visto estos dos enlaces, sin embargo, no estoy seguro de cómo implementarlos en mi formato actual. Tampoco veo cómo "pick_event" es una acción no clicable? – mcfly

+6

acepto esta respuesta, pero no es la respuesta correcta. Sin embargo, Root vinculó otra pregunta que vinculaba esta [pregunta] (http://stackoverflow.com/questions/4453143/point-and-line-tooltips-in-matplotlib/4620352#4620352) que proporciona la forma correcta de desplazarse y mostrar anotaciones Nota: Todavía utilicé anotaciones en lugar de wx.tooltip. ¡Funciona muy bien! – mcfly

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

Aquí está el código para trazar una coordenada en un mapa y activar una ventana emergente durante el vuelo estacionario. Obtuve el código para el evento on_move de la respuesta a esta pregunta: Matplotlib basemap: Popup box Espero que esto ayude.

+0

Sería bueno tener una explicación sobre esto, sobre por qué deberíamos escribir el código de esta manera y no solo pegar el código y decir que lo tienes de alguna parte. Esto ayudaría a otros también si llegan a tu respuesta en el futuro. – rsz

+0

@rsz lo siento. Editado – samuelv

Cuestiones relacionadas