Search code examples
pythonmatplotlibprojection

Plotting an image as background of a polar projection scatterplot in matplotlib


I am programming a darts bot. It is calculated where the bot hit the board and now I want to visualize this using matplotlib.

What I have: Displaying the position where the bot hit the board with a regular polar projection with axis and stuff.

What I need: Setting a dartboard as background and plotting the X&Y (or theta & r respectively) on top.

What I tried: Joining my piece of code together with the accepted answer of: Plot polar plot on top of image?

This is what my code looks like now:

import numpy as np
from matplotlib import pyplot as plt

# throw three darts:
rad = np.asarray([10000, 11000, 9400]) # consider these as distances from bull's eye in 10*µm
azi = np.asarray([352, 0, 10]) # in degrees
azi = np.deg2rad(azi) # conversion into radians

fig = plt.gcf()

axes_coords = [0, 0, 1, 1] # plotting full width and height

ax_polar = fig.add_axes(axes_coords, projection='polar')
ax_polar.patch.set_alpha(0)
ax_polar.scatter(azi, rad)
ax_polar.set_ylim(0, 17000)
ax_polar.set_xlim(0, 2*np.pi)
ax_polar.set_theta_offset(0.5*np.pi) # 0° should be on top, not right
ax_polar.set_theta_direction(direction=-1) # clockwise

plt.show()

The above code works fine. If you run it, you will see that the bot hit close to T20 field which is located straight above bull's eye.

Now if I want to add the image, I insert the following code before plt.show()

pic = plt.imread('Board_cd.png')
ax_image = fig.add_axes(axes_coords)
ax_image.imshow(pic, alpha=.5)
ax_image.axis('off')  # don't show the axes ticks/lines/etc. associated with the image

The picture looks like this: Dartboard

But the result isn't very satisfying: enter image description here

What am I doing wrong?


Solution

  • Running the code you show in the question you should get a warning

    MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance. In a future version, a new instance will always be created and returned. Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance.

    The solution is already given inside the warning, namely to give the axes a unique label, e.g.

    ax_polar = fig.add_axes(axes_coords, projection='polar', label="ax polar")
    # ...
    ax_image = fig.add_axes(axes_coords, label="ax image")
    

    The resulting dart board should then look like

    enter image description here