23

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 enter image description here

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: enter image description here

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

Tengis
  • 2,721
  • 10
  • 36
  • 58

5 Answers5

47

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"

Thorsten Kranz
  • 12,492
  • 2
  • 39
  • 56
4

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.

Bernhard
  • 8,583
  • 4
  • 41
  • 42
  • Changing the default globally seems like a bad idea in case you want to run other people's code though. – Mark Dec 06 '16 at 17:27
2

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.

lumbric
  • 7,644
  • 7
  • 42
  • 53
1

BTW, you could use marker='s' to draw squares in your scatter plot instead of circles and then just keep your original code.

dhpizza
  • 361
  • 1
  • 2
  • 10
1

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:

enter image description here

learner
  • 603
  • 1
  • 3
  • 15