ProximanovaMetropolis
ProximanovaMetropolis

Reputation: 55

Matplotlib: Display a scatter plot on top of an image with the right ordering and size

I have some coordinates that I want to display on top of an image with the right size and axes labels. The coordinates, which run from -750 to +750 on the X-axis and -400 to +450 (not +400) on the Y-axis, look like this:

[('-397.91', '58.91'), ('-569.73', '179.18'), ('-461.73', '306.82'), ('-199.09', '186.55'), ('-348.82', '-169.36'), ('-125.45', '-243.00'), ('4.64', '-267.55'), ('110.18', '-265.09'), ('267.27', '-12.27'), ('-687.55', '390.27')]

The image to be used as the background is as follows:

Background image to be used

The intended result is something like this: (There is a ball in the top-left pocket in addition to the nine visible on-screen.)

Actual picture

For this I have written the following.

#Conversion of dataframe to array of tuples:
plotdata = list(data.to_records(index=False)) #data is the dataframe of coordinates
print(plotdata)

img = plt.imread("American-style pool table diagram.png")
fig = plt.figure(figsize = (15, 9))
fig, ax = plt.subplots()
fig.set_size_inches(15, 9)
ax.imshow(img, extent=[-750, 750, -400, 450], zorder=1)
x, y = zip(*plotdata)
plt.scatter(x, y, data=data, color='red', zorder=2)

I am facing two problems.

  1. When the line ax.imshow(img, extent=[-750, 750, -400, 450], zorder=1) is commented out, in order to show only the coordinates, I get all the coordinates in a straight line (probably in the order that they appear in the plotdata list), instead of the intended locations. It looks like this:

Wrong Order

  1. When the code is run as such, with the image being displayed below the plot, the labels of the axes are distorted and the entire scatter plot is compressed into a tiny area at the centre of the image.

Super-Compressed

What might be a problem with the aspect ratio of the image and how do I fix it so that the points appear as they should, in the right locations across the image?

Upvotes: 0

Views: 2872

Answers (1)

p479h
p479h

Reputation: 199

The first problem you have is that you created 2 images. The code works fine other than that. The problem with your data points is that they are strings. But it is easy to convert them to floats. Follows my code and output:

import random
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot
import numpy as np
import matplotlib.pyplot as plt


#Conversion of dataframe to array of tuples:

data = [('-397.91', '58.91'), ('-569.73', '179.18'), ('-461.73', '306.82'), ('-199.09', '186.55'), ('-348.82', '-169.36'), ('-125.45', '-243.00'), ('4.64', '-267.55'), ('110.18', '-265.09'), ('267.27', '-12.27'), ('-687.55', '390.27')]
x = [float(i[0]) for i in data]
y = [float(i[1]) for i in data]
img = plt.imread(r"dir\icons\planet.png")
fig, ax = plt.subplots()
fig.set_size_inches(15, 9)
im=ax.imshow(img, extent=[-750, 750, -400, 450], zorder=1)
ax.scatter(x, y, color='red', zorder=2, s=100)
plt.show()

example

Upvotes: 2

Related Questions