
That is sure possible. We can start with a normal pie chart. Then we would need to get the images into the plot. This is done using plt.imread
and by using a matplotlib.offsetbox.OffsetImage
. We would need to find good coordinates and zoom levels to place the image, such that it overlapps completely with respective pie wedge. Then the Path of the pie's wedge is used as a clip path of the image, such that only the part inside the wedge is left over. Setting the zorder of the unfilled wedge to a high number ensures the borders to be placed on top of the image. This way it looks like the wedges are filled with the image.
import matplotlib.pyplot as plt
from matplotlib.patches import PathPatch
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
total = [5,7,4]
labels = ["Raspberries", "Blueberries", "Blackberries"]
plt.title('Berries')
plt.gca().axis("equal")
wedges, texts = plt.pie(total, startangle=90, labels=labels,
wedgeprops = { 'linewidth': 2, "edgecolor" :"k","fill":False, })
def img_to_pie( fn, wedge, xy, zoom=1, ax = None):
if ax==None: ax=plt.gca()
im = plt.imread(fn, format='png')
path = wedge.get_path()
patch = PathPatch(path, facecolor='none')
ax.add_patch(patch)
imagebox = OffsetImage(im, zoom=zoom, clip_path=patch, zorder=-10)
ab = AnnotationBbox(imagebox, xy, xycoords='data', pad=0, frameon=False)
ax.add_artist(ab)
positions = [(-1,0.3),(0,-0.5),(0.5,0.5)]
zooms = [0.4,0.4,0.4]
for i in range(3):
fn = "data/{}.png".format(labels[i].lower())
img_to_pie(fn, wedges[i], xy=positions[i], zoom=zooms[i] )
wedges[i].set_zorder(10)
plt.show()