horcle_buzz
horcle_buzz

Reputation: 2161

Point picker event_handler drawing line and displaying coordinates in matplotlib

I have the following class that draws a vertical line through the y-axis, so that when I click on it a horizontal line gets drawn at the location. My goal is to get the y-coordinate to actually print right at the y-axis where the horizontal line gets drawn. For testing, I am trying to print a title with the y-ccordinate, but it is not working as expected.

What I am trying to really accomplish is to make the y-axis on a bar plot clickable so that the user can select a point on the y-axis, and then a bunch of "stuff" happens (including the drawing of a horizontal line). I really see no other way to make this happen, other than drawing a plottable vertical line through the y-axis to make it pickable. This seems rather kludgey, but I have not had any success with any other methods.

import matplotlib.pyplot as plt

class PointPicker(object):
    def __init__(self):

        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111)
        self.lines2d, = self.ax.plot((0, 0), (-6000, 10000), 'k-', linestyle='-',picker=5)

        self.fig.canvas.mpl_connect('pick_event', self.onpick)
        self.fig.canvas.mpl_connect('key_press_event', self.onpress)
        fig.canvas.mpl_connect('button_press_event', self.onclick)

    def onpress(self, event):
        """define some key press events"""
        if event.key.lower() == 'q':
            sys.exit()

    def onpick(self,event):
        x = event.mouseevent.xdata
        y = event.mouseevent.ydata
        L =  self.ax.axhline(y=y)
        print(y)
        ax.axvspan(0, 0, facecolor='y', alpha=0.5, picker=10)
        self.fig.canvas.draw()

    def onclick(event):
        self.fig.canvas.set_title('Selected item came from {}'.format(event.ydata))
        print(event.xdata, event.ydata)

if __name__ == '__main__':

    plt.ion()
    p = PointPicker()
    plt.show()

Assuming there is no ther way to achieve my end result, all is well with this method, except I cannot for the life of me get the title to print (using the self.fig.canvas.set_title('Selected item came from {}'.format(event.ydata)).

Upvotes: 0

Views: 2167

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339052

You can use the 'button_press_event' to connect to a method, which verifies that the click has happened close enough to the yaxis spine and then draws a horizontal line using the clicked coordinate.

import matplotlib.pyplot as plt

class PointPicker(object):
    def __init__(self, ax, clicklim=0.05):
        self.fig=ax.figure
        self.ax = ax
        self.clicklim = clicklim
        self.horizontal_line = ax.axhline(y=.5, color='y', alpha=0.5)
        self.text = ax.text(0,0.5, "")
        print self.horizontal_line
        self.fig.canvas.mpl_connect('button_press_event', self.onclick)


    def onclick(self, event):
        if event.inaxes == self.ax:
            x = event.xdata
            y = event.ydata
            xlim0, xlim1 = ax.get_xlim()
            if x <= xlim0+(xlim1-xlim0)*self.clicklim:
                self.horizontal_line.set_ydata(y)
                self.text.set_text(str(y))
                self.text.set_position((xlim0, y))
                self.fig.canvas.draw()


if __name__ == '__main__':

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.bar([0,2,3,5],[4,5,1,3], color="#dddddd")
    p = PointPicker(ax)
    plt.show()

enter image description here

Upvotes: 4

Related Questions