19

I am trying to plot 2D field data using matplotlib. So basically I want something similar to this:

enter image description here

In my actual case I have data stored in a file on my harddrive. However for simplicity consider the function z = f(x, y). I want a smooth 2D plot where z is visualised using color. I managed the plotting with the following lines of code:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-1, 1, 21)
y = np.linspace(-1, 1, 21)
z = np.array([i*i+j*j for j in y for i in x])

X, Y = np.meshgrid(x, y)
Z = z.reshape(21, 21)

plt.pcolor(X, Y, Z)
plt.show()

However, the plot I obtain is very coarse. Is there a very simple way to smooth the plot? I know something similar is possible with surface plots, however, those are 3D. I could change the camera angle to obtain a 2D representation, but I am convinced there is an easier way. I also tried imshow but then I have to think in graphic coordinates where the origin is in the upper left corner.

Problem solved

I managed to solve my problem using:

plt.imshow(Z,origin='lower',interpolation='bilinear')

Paul H
  • 65,268
  • 20
  • 159
  • 136
Aeronaelius
  • 1,291
  • 3
  • 12
  • 31
  • The only thing that separates the linked plot with yours is that your grid is much coarser. Change 21 to something larger, say 101, or 1001. – wflynny May 28 '15 at 14:56
  • Yes I know, but even with a low number of grid points a smooth plot can be obtained using interpolation. `imshow` has that ability. Can I do something similar with `pcolor`? – Aeronaelius May 28 '15 at 14:58
  • Please edit your question to describe _exactly_ what you want, with a representative example. – wflynny May 28 '15 at 15:02

3 Answers3

12

If you can't change your mesh granularity, then try to go with imshow, which will essentially plot any 2D matrix as an image, where the values of each matrix cell represent the color to make that pixel. Using your example values:

In [3]: x = y = np.linspace(-1, 1, 21)
In [4]: z = np.array([i*i+j*j for j in y for i in x])
In [5]: Z = z.reshape(21, 21)
In [7]: plt.imshow(Z, interpolation='bilinear')
Out[7]: <matplotlib.image.AxesImage at 0x7f4864277650>
In [8]: plt.show()

enter image description here

wflynny
  • 18,065
  • 5
  • 46
  • 67
  • I am aware of that. But the case I presented was a simple one. I actually have data stored in a `txt` file so I cannot adjust the data. So yes, in a simple function case I could do that. But what do you do in case of data obtained from a 3rd party? – Aeronaelius May 28 '15 at 15:00
  • 1
    Thanks I came to this too just now. I also added `origin='lower'` as a parameter to have the origin at the lower left corner. – Aeronaelius May 28 '15 at 15:17
12

you can use contourf

plt.contourf(X, Y, Z)

enter image description here

EDIT:

For more levels (smoother colour transitions), you can use more levels (contours)

For example:

plt.contourf(X, Y, Z, 100)

enter image description here

tmdavison
  • 64,360
  • 12
  • 187
  • 165
0

You can do this using pcolor or pcolormesh if you provide an option to use Gouraud shading:

import numpy as np
from matplotlib import pyplot as plt

y, x = np.meshgrid(np.linspace(-1, 1, 5), np.linspace(-1, 1, 5))
z = x**2+y**2
_, [ax1, ax2] = plt.subplots(1,2)
ax1.pcolormesh(x, y, z)
ax1.set_title("Default shading")
ax2.pcolormesh(x, y, z, shading='gouraud')
ax2.set_title("Gouraud shaing")

output of commands above. Plot with and without gouraud shading

Janus
  • 5,421
  • 2
  • 26
  • 37