1""" 2=============== 3Pick Event Demo 4=============== 5 6 7You can enable picking by setting the "picker" property of an artist 8(for example, a matplotlib Line2D, Text, Patch, Polygon, AxesImage, 9etc...) 10 11There are a variety of meanings of the picker property: 12 13* *None* - picking is disabled for this artist (default) 14 15* bool - if *True* then picking will be enabled and the artist will fire a pick 16 event if the mouse event is over the artist. 17 18 Setting ``pickradius`` will add an epsilon tolerance in points and the artist 19 will fire off an event if its data is within epsilon of the mouse event. For 20 some artists like lines and patch collections, the artist may provide 21 additional data to the pick event that is generated, for example, the indices 22 of the data within epsilon of the pick event 23 24* function - if picker is callable, it is a user supplied function which 25 determines whether the artist is hit by the mouse event. 26 27 hit, props = picker(artist, mouseevent) 28 29 to determine the hit test. If the mouse event is over the artist, return 30 hit=True and props is a dictionary of properties you want added to the 31 PickEvent attributes. 32 33After you have enabled an artist for picking by setting the "picker" 34property, you need to connect to the figure canvas pick_event to get 35pick callbacks on mouse press events. For example, 36 37 def pick_handler(event): 38 mouseevent = event.mouseevent 39 artist = event.artist 40 # now do something with this... 41 42 43The pick event (matplotlib.backend_bases.PickEvent) which is passed to 44your callback is always fired with two attributes: 45 46 mouseevent - the mouse event that generate the pick event. The 47 mouse event in turn has attributes like x and y (the coordinates in 48 display space, such as pixels from left, bottom) and xdata, ydata (the 49 coords in data space). Additionally, you can get information about 50 which buttons were pressed, which keys were pressed, which Axes 51 the mouse is over, etc. See matplotlib.backend_bases.MouseEvent 52 for details. 53 54 artist - the matplotlib.artist that generated the pick event. 55 56Additionally, certain artists like Line2D and PatchCollection may 57attach additional meta data like the indices into the data that meet 58the picker criteria (for example, all the points in the line that are within 59the specified epsilon tolerance) 60 61The examples below illustrate each of these methods. 62""" 63 64import matplotlib.pyplot as plt 65from matplotlib.lines import Line2D 66from matplotlib.patches import Rectangle 67from matplotlib.text import Text 68from matplotlib.image import AxesImage 69import numpy as np 70from numpy.random import rand 71 72 73# Fixing random state for reproducibility 74np.random.seed(19680801) 75 76 77def pick_simple(): 78 # simple picking, lines, rectangles and text 79 fig, (ax1, ax2) = plt.subplots(2, 1) 80 ax1.set_title('click on points, rectangles or text', picker=True) 81 ax1.set_ylabel('ylabel', picker=True, bbox=dict(facecolor='red')) 82 line, = ax1.plot(rand(100), 'o', picker=True, pickradius=5) 83 84 # pick the rectangle 85 ax2.bar(range(10), rand(10), picker=True) 86 for label in ax2.get_xticklabels(): # make the xtick labels pickable 87 label.set_picker(True) 88 89 def onpick1(event): 90 if isinstance(event.artist, Line2D): 91 thisline = event.artist 92 xdata = thisline.get_xdata() 93 ydata = thisline.get_ydata() 94 ind = event.ind 95 print('onpick1 line:', np.column_stack([xdata[ind], ydata[ind]])) 96 elif isinstance(event.artist, Rectangle): 97 patch = event.artist 98 print('onpick1 patch:', patch.get_path()) 99 elif isinstance(event.artist, Text): 100 text = event.artist 101 print('onpick1 text:', text.get_text()) 102 103 fig.canvas.mpl_connect('pick_event', onpick1) 104 105 106def pick_custom_hit(): 107 # picking with a custom hit test function 108 # you can define custom pickers by setting picker to a callable 109 # function. The function has the signature 110 # 111 # hit, props = func(artist, mouseevent) 112 # 113 # to determine the hit test. if the mouse event is over the artist, 114 # return hit=True and props is a dictionary of 115 # properties you want added to the PickEvent attributes 116 117 def line_picker(line, mouseevent): 118 """ 119 Find the points within a certain distance from the mouseclick in 120 data coords and attach some extra attributes, pickx and picky 121 which are the data points that were picked. 122 """ 123 if mouseevent.xdata is None: 124 return False, dict() 125 xdata = line.get_xdata() 126 ydata = line.get_ydata() 127 maxd = 0.05 128 d = np.sqrt( 129 (xdata - mouseevent.xdata)**2 + (ydata - mouseevent.ydata)**2) 130 131 ind, = np.nonzero(d <= maxd) 132 if len(ind): 133 pickx = xdata[ind] 134 picky = ydata[ind] 135 props = dict(ind=ind, pickx=pickx, picky=picky) 136 return True, props 137 else: 138 return False, dict() 139 140 def onpick2(event): 141 print('onpick2 line:', event.pickx, event.picky) 142 143 fig, ax = plt.subplots() 144 ax.set_title('custom picker for line data') 145 line, = ax.plot(rand(100), rand(100), 'o', picker=line_picker) 146 fig.canvas.mpl_connect('pick_event', onpick2) 147 148 149def pick_scatter_plot(): 150 # picking on a scatter plot (matplotlib.collections.RegularPolyCollection) 151 152 x, y, c, s = rand(4, 100) 153 154 def onpick3(event): 155 ind = event.ind 156 print('onpick3 scatter:', ind, x[ind], y[ind]) 157 158 fig, ax = plt.subplots() 159 ax.scatter(x, y, 100*s, c, picker=True) 160 fig.canvas.mpl_connect('pick_event', onpick3) 161 162 163def pick_image(): 164 # picking images (matplotlib.image.AxesImage) 165 fig, ax = plt.subplots() 166 ax.imshow(rand(10, 5), extent=(1, 2, 1, 2), picker=True) 167 ax.imshow(rand(5, 10), extent=(3, 4, 1, 2), picker=True) 168 ax.imshow(rand(20, 25), extent=(1, 2, 3, 4), picker=True) 169 ax.imshow(rand(30, 12), extent=(3, 4, 3, 4), picker=True) 170 ax.set(xlim=(0, 5), ylim=(0, 5)) 171 172 def onpick4(event): 173 artist = event.artist 174 if isinstance(artist, AxesImage): 175 im = artist 176 A = im.get_array() 177 print('onpick4 image', A.shape) 178 179 fig.canvas.mpl_connect('pick_event', onpick4) 180 181 182if __name__ == '__main__': 183 pick_simple() 184 pick_custom_hit() 185 pick_scatter_plot() 186 pick_image() 187 plt.show() 188