Here we'll go through an example that incorporates both widgets and key bindings to create a color selector natively in matplotlib. We'll go through the pieces sequentially: if you close the plot window, you'll have to re-run the script from the beginning.
Again, we'll start with enabling pylab mode:
%pylab
We'd like a way for the user to visually (and interactively) pick any of the $256^3$ RGB colors available to matplotlib. We'll start by displaying an image of all the red and green values, with the blue set to zero. This can be done through the imshow command:
im_arr = np.zeros((256, 256, 3), dtype=np.float32)
im_arr[:, :, 0] = np.linspace(0, 1, 256)
im_arr[:, :, 1] = np.linspace(0, 1, 256)[:, np.newaxis]
fig = plt.figure(figsize=(8, 8))
main_ax = plt.axes([0.1, 0.15, 0.8, 0.8], xticks=[], yticks=[])
im = main_ax.imshow(im_arr, origin='lower', extent=[0, 1, 0, 1])
Next we need a way for the user to express the blue value. We can use a widget for this. Let's add a slider widget to the window which changes the blue pixel value, and adjusts the color we see in the window when it's picked:
from matplotlib.widgets import Slider, AxesWidget
slider_ax = plt.axes([0.1, 0.1, 0.8, 0.02])
slider = Slider(slider_ax, 'Blue', 0.0, 1.0, valinit=0.0, color='#AAAAFF')
def update(val):
im_arr[:, :, 2] = val
im.set_data(im_arr)
fig.canvas.draw()
slider.on_changed(update)
Now that we can visualize any possible RGB color, let's create a way to pick any RGB color. Let's first make a tiny axes and text box where we can display a chosen color and its hex identifier:
cbox_ax = plt.axes([0.1, 0.04, 0.04, 0.04], xticks=[], yticks=[])
cbox_im = cbox_ax.imshow(np.ones((1, 1, 3)))
cbox_txt = cbox_ax.text(1.5, 0.5, "(text)", transform=cbox_ax.transAxes,
fontsize=20, va='center', ha='left')
Now we can create a pick event that lets us pick the appropriate color. Here's where our pre-planning has paid off: the image extent goes from 0 to 1, which is exactly the scale of the color values. So if we pick an event at data coordinate (x, y), then we can set (R, G, B) = (x, y, B), with B set by the value of the slider:
from matplotlib.colors import rgb2hex
def on_pick(event):
r = event.mouseevent.xdata
g = event.mouseevent.ydata
b = slider.val
cbox_im.set_data([[[r, g, b]]])
cbox_txt.set_text(rgb2hex((r, g, b)).upper())
fig.canvas.draw()
im.set_picker(True)
fig.canvas.mpl_connect('pick_event', on_pick)