2012-09-25 15 views
6

Ich verwende diesen Code derzeit, um Popup-Annotationen auf einer Karte zu haben, wenn ich auf einen Punkt in einem Grundkarten-Matplotlib-Plot klicke.Python und Matplotlib und Anmerkungen mit 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() 

Was ich frage mich, ist, wie die Anmerkungen zeigen Mausbewegung mit, anstatt auf einen Punkt klicken?

Ich habe "motion_notify_event" gesehen, aber es scheint, dass der Code Fehler bekommt, wenn ich die Maus um den Plotbereich bewege. Irgendwelche Gedanken?

Antwort

8

Werfen Sie einen Blick auf this question und 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

Ich habe beide Links gesehen, aber ich bin mir nicht sicher, wie ich sie in meinem aktuellen Format implementiere. Ich sehe auch nicht, wie "pick_event" eine nicht anklickbare Aktion ist? – mcfly

+6

Ich akzeptiere diese Antwort, aber es ist nicht die richtige Antwort. Allerdings hat Root eine andere Frage verlinkt, die diese [Frage] verlinkt (http://stackoverflow.com/questions/4453143/point-and-line-tooltips-in-matplotlib/4620352#4620352), die den richtigen Weg gibt, um zu schweben und anzuzeigen Anmerkungen. Hinweis: Ich habe immer noch Anmerkungen anstelle von wx.tooltip verwendet. Es funktioniert sehr gut! – 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() 

Hier ist der Code ist ein auf einer Karte koordinieren plotten und ein Pop-up während des Schwebens ermöglichen. Ich habe den Code für das on_move Ereignis aus der Antwort auf diese Frage: Matplotlib basemap: Popup box Hoffe, dass dies hilft.

+0

Es wäre schön, eine Erklärung dazu zu haben, warum wir den Code so schreiben sollten und nicht einfach den Code einfügen und sagen, dass Sie ihn irgendwo haben. Dies würde auch anderen helfen, wenn sie in Zukunft zu Ihrer Antwort kommen. – rsz

+0

@rsz Entschuldigung. Bearbeitet. – samuelv

Verwandte Themen