TIF
TIF

Reputation: 323

Continuous rather than discrete intensity gradient describing function in python

I'm trying to plot a function using an intensity/colour scale and it turns out discrete rather than being a continuous of colour where white (for example) is max. intensity and black is 0. It doesn't seem to be affected by the number of points in the 'np.linspace' which is what I'm a bit confused about.

x = y = np.linspace(0, 4*np.pi, 2000)

def cos(x, y):
    return np.cos(x)**2

def squared(x, y):
    return x**2

X, Y = np.meshgrid(x, y)

Z = cos(X, Y)
plt.contourf(Z, cmap = 'Greys')

Z = squared(X, Y)
plt.contourf(Z, cmap = 'Greys')

enter image description here

enter image description here

Upvotes: 0

Views: 482

Answers (2)

Carlos Azevedo
Carlos Azevedo

Reputation: 680

plt.contourf is supposed to be discrete as it shows - so you can see the contours. One option that you have for that scenario is the following:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm

x = y = np.linspace(0, 4*np.pi, 2000)

def cos(x, y):
    return np.cos(x)**2

def squared(x, y):
    return x**2

X, Y = np.meshgrid(x, y)
Z = cos(X, Y)

plt.imshow(Z, vmin = 0., vmax = 1., cmap=plt.cm.gray_r) # gray_r to reverse color and make it as you show in your images
plt.show()

Upvotes: 2

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339310

Here you are plotting a filled contour plot. A contour plot mostly makes sense if you want to show discrete contours. E.g. weather maps often show isobars in that style or geographic maps show lines of equal terrain height via "contours".

By default, matplotlib chooses a number of ~8 contours, but the exact number may vary depending on the data scale.

You can choose the number of levels (approximately) via the levels argument. So increasing that number will show you a more continuous gradient.

plt.contourf(Z, levels = 121, cmap = 'Greys')

enter image description here

In general, however, if a continuous image is desired, one would rather plot an image indeed,

dx = dy = np.diff(x)[0]
extent = x.min()-dx/2, x.max()+dx/2, y.min()-dx/2, y.max()+dx/2
plt.imshow(Z, cmap = 'Greys', extent=extent, aspect="auto")

enter image description here

You may notice how there is almost no visual difference between the two, yet the imshow approach is much (much, much) faster, because no contouring algorithm needs to be used.

Upvotes: 2

Related Questions