How can I make the xtick labels of a plot be simple drawings using matplotlib?

I would remove the tick labels and replace the text with patches. Here is a brief example of performing this task:

import matplotlib.pyplot as plt
import matplotlib.patches as patches


# define where to put symbols vertically
TICKYPOS = -.6

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))

# set ticks where your images will be
ax.get_xaxis().set_ticks([2,4,6,8])
# remove tick labels
ax.get_xaxis().set_ticklabels([])


# add a series of patches to serve as tick labels
ax.add_patch(patches.Circle((2,TICKYPOS),radius=.2,
                            fill=True,clip_on=False))
ax.add_patch(patches.Circle((4,TICKYPOS),radius=.2,
                            fill=False,clip_on=False))
ax.add_patch(patches.Rectangle((6-.1,TICKYPOS-.05),.2,.2,
                               fill=True,clip_on=False))
ax.add_patch(patches.Rectangle((8-.1,TICKYPOS-.05),.2,.2,
                               fill=False,clip_on=False))

This results in the following figure:

enter image description here

It is key to set clip_on to False, otherwise patches outside the axes will not be shown. The coordinates and sizes (radius, width, height, etc.) of the patches will depend on where your axes is in the figure. For example, if you are considering doing this with subplots, you will need to be sensitive of the patches placement so as to not overlap any other axes. It may be worth your time investigating Transformations, and defining the positions and sizes in an other unit (Axes, Figure or display).

If you have specific image files that you want to use for the symbols, you can use the BboxImage class to create artists to be added to the axes instead of patches. For example I made a simple icon with the following script:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(1,1),dpi=400)
ax = fig.add_axes([0,0,1,1],frameon=False)
ax.set_axis_off()

ax.plot(range(10),linewidth=32)
ax.plot(range(9,-1,-1),linewidth=32)

fig.savefig('thumb.png')

producing this image:

enter image description here

Then I created a BboxImage at the location I want the tick label and of the size I want:

lowerCorner = ax.transData.transform((.8,TICKYPOS-.2))
upperCorner = ax.transData.transform((1.2,TICKYPOS+.2))

bbox_image = BboxImage(Bbox([lowerCorner[0],
                             lowerCorner[1],
                             upperCorner[0],
                             upperCorner[1],
                             ]),
                       norm = None,
                       origin=None,
                       clip_on=False,
                       )

Noticed how I used the transData transformation to convert from data units to display units, which are required in the definition of the Bbox.

Now I read in the image using the imread routine, and set it’s results (a numpy array) to the data of bbox_image and add the artist to the axes:

bbox_image.set_data(imread('thumb.png'))
ax.add_artist(bbox_image)

This results in an updated figure:
enter image description here

If you do directly use images, make sure to import the required classes and methods:

from matplotlib.image import BboxImage,imread
from matplotlib.transforms import Bbox

Leave a Comment