Question

I have a two panel wxPython GUI set up. In my right panel, I have a map display using Basemap. On this basemap (of the United States) I plot a scatter plot of different cities. I would like to be able to click on these dots and have a pop up window within my GUI that gives some information relative to that dot I select (ex. City, lat/long, etc. -- I would have all this info stored in a list or other means).

I have come across AnnoteFinder, but this does not seem to work inside my GUI (it will work if i use Basemap by itelf and not in my 2 panel GUI). Also, this just puts some text on top of the dot -- I would rather have a small window show up.

Example of my code so far:

#Setting up Map Figure
self.figure = Figure(None,dpi=75)
self.canvas = FigureCanvas(self.PlotPanel, -1, self.figure)
self.axes = self.figure.add_axes([0,0,1,1],frameon=False)
self.SetColor( (255,255,255) )

#Basemap Setup
self.map = Basemap(llcrnrlon=-119, llcrnrlat=22, urcrnrlon=-64,
                    urcrnrlat=49, projection='lcc', lat_1=33, lat_2=45,
                    lon_0=-95, resolution='h', area_thresh=10000,ax=self.axes)
self.map.drawcoastlines()
self.map.drawcountries()
self.map.drawstates()
self.figure.canvas.draw()

#Set up Scatter Plot
m = Basemap(llcrnrlon=-119, llcrnrlat=22, urcrnrlon=-64,
            urcrnrlat=49, projection='lcc', lat_1=33, lat_2=45,
            lon_0=-95, resolution='h', area_thresh=10000,ax=self.axes)

x,y=m(Long,Lat)

#Scatter Plot (they plot the same thing)
self.map.plot(x,y,'ro')
self.map.scatter(x,y,90)

self.figure.canvas.draw()

Any thoughts?

Was it helpful?

Solution

Check out this answer. Basically you set up a pick event that creates an annotation on the graph. This annotation can pop up as a tooltip-style text box.

Note that this doesn't produce a real GUI "window" (i.e., a dialog box or other control with close button, title bar, etc.), but just an annotation on the plot itself. However, from looking at the code you can see how it determines the artist (e.g., point) you've clicked on. Once you have that info, you could run whatever code you want with it, for instance creating a wxPython dialog instead of an annotation.

Edit re your question about the last few lines: Based on your code, it looks like you'd want to do:

pts = self.map.scatter(x, y, 90)
self.figure.canvas.mpl_connect('pick_event', DataCursor(plt.gca()))
pts.set_picker(5)

Another edit re your question about having different text in the annotation: You may have to play around with the event object a bit to extract the information you want. As described at http://matplotlib.sourceforge.net/users/event_handling.html#simple-picking-example , different artist types (i.e., different kinds of plots) will provide different event information.

I have some old code that does almost exactly what you described (displaying city name when a point on the map is clicked). I have to admit I don't remember exactly how all of it works, but my code has this in the DataCursor:

def __call__(self, event):
    self.event = event
    xdata, ydata = event.artist._offsets[:,0], event.artist._offsets[:,1]
    #self.x, self.y = xdata[event.ind], ydata[event.ind]
    self.x, self.y = event.mouseevent.xdata, event.mouseevent.ydata
    if self.x is not None:
        city = clim['Name'][event.ind[0]]
        if city == self.annotation.get_text() and self.annotation.get_visible():
            # You can click the visible annotation to remove it
            self.annotation.set_visible(False)
            event.canvas.draw()
            return
        self.annotation.xy = self.x, self.y
        self.annotation.set_text(city)
        self.annotation.set_visible(True)
        event.canvas.draw()

clim['Name'] is the list of city names, and I was able to index into that using event.ind to get the city name corresponding to the picked point. Your code may need to be slightly different depending on the format of your data, but that should give you an idea.

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