Matplotlib imshow: Data rotated?
Question:
I was trying to plot some data with scatter. My code is
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from scipy.interpolate import griddata
data = np.loadtxt('file1.txt')
x = data[:,0]
y = data[:,1]
z = data[:,2]
plt.scatter(x, y, c=z, s=100, cmap=mpl.cm.spectral)
cbar=plt.colorbar()
s=18
plt.ylabel(r"$a_v$", size=s)
plt.xlabel(r"$a_{rm min}$", size=s)
plt.xlim([x.min(),x.max()])
plt.ylim([y.min(),y.max()])
plt.show()
The result is
Now I came on the idea to try imshow with the some data, soince I didn’t like the circles of scatter.
So I tried this
from matplotlib.mlab import griddata
import matplotlib.pyplot as plt
data = np.loadtxt('file1.txt')
x = data[:,0]
y = data[:,1]
z = data[:,2]
N = 30j
extent = (min(x), max(x), min(y), max(y))
xs,ys = np.mgrid[extent[0]:extent[1]:N, extent[2]:extent[3]:N]
resampled = griddata(x, y, z, xs, ys)
plt.imshow(resampled.T, extent=extent)
s=18
plt.ylabel(r"$a_v$", size=s)
plt.xlabel(r"$a_{rm min}$", size=s)
plt.xlim([x.min(),x.max()])
plt.ylim([y.min(),y.max()])
cbar=plt.colorbar()
plt.show()
With this result:
My problem is obviosly why imshow()
does invert the data? What happens here exactly?
PS: Here are the data, in case someone would like to play with them
Answers:
It’s not inverted, just flipped. The origin for imshow
default to the upper left rather than the lower left. imshow
has a parameter to specify the origin, it’s named origin. Alternatively you can set the default in your matplotlib.conf
.
Look at the keyword arguments of imshow
. There is origin
. The default is “upper”, but you want “lower”.
The default makes sense for plotting images, that usually start at the top-left corner. For most matrix-plotting, you’ll want origin="lower"
BTW, you could use marker=’s’ to draw squares in your scatter plot instead of circles and then just keep your original code.
Consider to use pcolormesh
or contourf
if you want to plot data of the form f(X, Y) = Z
. imshow
simply plots data Z
, scaling and resampling has do be done manually.
For those who may still have problem with imshow, although the origin
keyword helps, be aware of the coordinate axes as well.
Generally, for an array of shape (M, N), the first index runs along the vertical, the second index runs along the horizontal. The pixel centers are at integer positions ranging from 0 to N’ = N – 1 horizontally and from 0 to M’ = M – 1
You can find more details from the matplotlib website.
For example, consider the following code:
M=5; N=10
a=np.zeros((M, N))
for i in range(M):
for j in range(N):
a[i,j]=i**2
plt.imshow(a, origin="lower")
print(f'here is a:n{a}n')
print(f'shape of a: {a.shape}')
print(f'a[0,0]: {a[0,0]}')
print(f'a[0,5]: {a[0,5]}')
print(f'a[0,9]: {a[0,9]}')
print(f'a[4,0]: {a[4,0]}')
Here is the output:
I was trying to plot some data with scatter. My code is
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from scipy.interpolate import griddata
data = np.loadtxt('file1.txt')
x = data[:,0]
y = data[:,1]
z = data[:,2]
plt.scatter(x, y, c=z, s=100, cmap=mpl.cm.spectral)
cbar=plt.colorbar()
s=18
plt.ylabel(r"$a_v$", size=s)
plt.xlabel(r"$a_{rm min}$", size=s)
plt.xlim([x.min(),x.max()])
plt.ylim([y.min(),y.max()])
plt.show()
The result is
Now I came on the idea to try imshow with the some data, soince I didn’t like the circles of scatter.
So I tried this
from matplotlib.mlab import griddata
import matplotlib.pyplot as plt
data = np.loadtxt('file1.txt')
x = data[:,0]
y = data[:,1]
z = data[:,2]
N = 30j
extent = (min(x), max(x), min(y), max(y))
xs,ys = np.mgrid[extent[0]:extent[1]:N, extent[2]:extent[3]:N]
resampled = griddata(x, y, z, xs, ys)
plt.imshow(resampled.T, extent=extent)
s=18
plt.ylabel(r"$a_v$", size=s)
plt.xlabel(r"$a_{rm min}$", size=s)
plt.xlim([x.min(),x.max()])
plt.ylim([y.min(),y.max()])
cbar=plt.colorbar()
plt.show()
With this result:
My problem is obviosly why imshow()
does invert the data? What happens here exactly?
PS: Here are the data, in case someone would like to play with them
It’s not inverted, just flipped. The origin for imshow
default to the upper left rather than the lower left. imshow
has a parameter to specify the origin, it’s named origin. Alternatively you can set the default in your matplotlib.conf
.
Look at the keyword arguments of imshow
. There is origin
. The default is “upper”, but you want “lower”.
The default makes sense for plotting images, that usually start at the top-left corner. For most matrix-plotting, you’ll want origin="lower"
BTW, you could use marker=’s’ to draw squares in your scatter plot instead of circles and then just keep your original code.
Consider to use pcolormesh
or contourf
if you want to plot data of the form f(X, Y) = Z
. imshow
simply plots data Z
, scaling and resampling has do be done manually.
For those who may still have problem with imshow, although the origin
keyword helps, be aware of the coordinate axes as well.
Generally, for an array of shape (M, N), the first index runs along the vertical, the second index runs along the horizontal. The pixel centers are at integer positions ranging from 0 to N’ = N – 1 horizontally and from 0 to M’ = M – 1
You can find more details from the matplotlib website.
For example, consider the following code:
M=5; N=10
a=np.zeros((M, N))
for i in range(M):
for j in range(N):
a[i,j]=i**2
plt.imshow(a, origin="lower")
print(f'here is a:n{a}n')
print(f'shape of a: {a.shape}')
print(f'a[0,0]: {a[0,0]}')
print(f'a[0,5]: {a[0,5]}')
print(f'a[0,9]: {a[0,9]}')
print(f'a[4,0]: {a[4,0]}')
Here is the output: