Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
921 views
in Technique[技术] by (71.8m points)

python - How does pyplot.contourf choose colors from a colormap?

I have been playing with the from_levels_and_colors function, so that I can have an extended colorbar on a pcolormesh plot, similar to contourf. Here is my example contourf plot:

import numpy as np
import matplotlib.pyplot as plt

a = np.arange(12)[:,np.newaxis] * np.ones(8)
levels = np.arange(1.5, 10, 2)

plt.contourf(a, cmap='RdYlBu', levels=levels, extend='both')
plt.colorbar()

contouf example

To produce an analogous pcolormesh plot I need to supply a sequence of colors, so I have:

from matplotlib.colors import from_levels_and_colors

n_colors = len(levels) + 1
cmap = plt.get_cmap('RdYlBu', n_colors)
colors = cmap(range(cmap.N))
cmap, norm = from_levels_and_colors(levels, colors, extend='both')
plt.pcolormesh(a, cmap=cmap, norm=norm)
plt.colorbar()

pcolormesh example

The middle four colors in the pcolormesh are lighter than in the contourf. How might I choose them so they match?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem is that the colors for a contourf plot are taken from the middle of the respecive interval. To replicate the same behaviour for a pcolor plot, you need to select the colors not simply as equally spaced range from the colormap (colors = cmap(range(cmap.N))), but as the two endpoints of the map and the respective means between the level boundaries.

cnorm = plt.Normalize(vmin=levels[0],vmax=levels[-1])
clevels = [levels[0]] + list(0.5*(levels[1:]+levels[:-1])) + [levels[-1]]
colors=plt.cm.RdYlBu(cnorm(clevels))

Complete code:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors

a = np.arange(12)[:,np.newaxis] * np.ones(8)
levels = np.arange(1.5, 10, 2)

fig, (ax,ax2) = plt.subplots(ncols=2)

ax.set_title("contourf")
cf = ax.contourf(a, levels=levels, cmap='RdYlBu', extend='both') #, 
fig.colorbar(cf, ax=ax)

##### pcolormesh

cnorm = plt.Normalize(vmin=levels[0],vmax=levels[-1])
clevels = [levels[0]] + list(0.5*(levels[1:]+levels[:-1])) + [levels[-1]]
colors=plt.cm.RdYlBu(cnorm(clevels))

cmap, norm = matplotlib.colors.from_levels_and_colors(levels, colors, extend='both')
cf = ax2.pcolormesh(a, cmap=cmap, norm=norm)
ax2.set_title("pcolormesh")
fig.colorbar(cf,ax=ax2)


plt.tight_layout()
plt.show()

enter image description here

To better understand the solution, you may want to replace the line cmap, norm = matplotlib.colors.from_levels_and_colors(levels, colors, extend='both') by

norm=matplotlib.colors.BoundaryNorm(levels, ncolors=len(levels)-1)

cmap = matplotlib.colors.ListedColormap(colors[1:-1], N=len(levels)-1)
cmap.set_under(colors[0])
cmap.set_over(colors[-1])
cmap.colorbar_extend = "both"

This may make it clearer, where the colors and the colormap eventually used originate from.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...