我在(n_y,n_x)
网格上定义了数据,并将其转换为(n_y,n_x,4)
np.ndarray
中的颜色。我想用pcolormesh
显示这些颜色。
我尝试将facecolors
参数传递给pcolormesh
,它不做任何事情,并使用ListedColormap
将每个(y,x)
单元格映射到一种颜色,但也不起作用。
下面的代码重现了我遇到的问题。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
'''
Define some arbitrary data
'''
dx = 0.01
x_range = [5,8]
y_range = [0,2]
x = np.arange(x_range[0],x_range[1],dx)
y = np.arange(y_range[0],y_range[1],dx)
X,Y = np.meshgrid(x,y)
data = X+Y**2
'''
Define colors based on the data
'''
def data_to_colors(data):
colors = np.moveaxis(np.zeros_like([data]*4),0,-1) # shape (n_y,n_x,4)
# make the data correspond to the blue channel, scaled between 0 and 1
colors[...,2] = (data - data.min()) / (data.max()-data.min())
# make red and green colors 0.5
colors[...,0] = 0.5
colors[...,1] = 0.5
# make the alpha values all 1
colors[...,-1] = 1
return colors
'''
Show with imshow and pcolormesh
'''
fig,axs = plt.subplots(1,3,sharex=True,sharey=True,figsize=(12,4))
# show with imshow
extent = [x_range[0]-dx/2, x_range[-1]+dx/2, y_range[0]-dx/2, y_range[-1]+dx/2]
axs[0].imshow(data_to_colors(data),extent=extent,origin='lower')
axs[0].set_title('imshow (correct)')
# show with pcolormesh and facecolors
axs[1].pcolormesh(X,Y,np.ones_like(X),facecolors=data_to_colors(data.flatten()))
axs[1].set_title('pcolormesh, specifying facecolors')
# show using a ListedColorMap mapping each individual (row,column) to a color
ixs = np.arange(len(x)*len(y))
colors = data_to_colors(data.flatten())
axs[2].pcolormesh(X,Y,ixs.reshape(len(y),len(x)),cmap=ListedColormap(colors))
axs[2].set_title('pcolormesh, using a ListedColormap')
for ax in axs:
ax.set_aspect('equal')
ax.set_xlabel('x')
ax.set_ylabel('y')
fig.tight_layout()
有没有一种方法可以使用pcolormesh
(或者当数据的行/列不一定对应于y/x的常量值时可以使用的任何方法)获得与imshow
相同的结果?
发布于 2020-07-25 04:34:46
对于ListedColormap
,您需要(最多) 256种不同颜色的列表。您可以通过向data_to_colors()
函数提供一个包含256个值的列表来创建它们。创建这些输入值的最简单方法是使用np.linspace(0, 1, 256)
。
对于facecolors
方法,似乎matplotlib需要调用fig.canvas.draw()
来创建facecolors数组。此后,可以通过.set_facecolors
设置它们。同样重要的是,pcolormesh
在网格顶点之间绘制面(与为每个顶点提供颜色的imshow
相反)。因此,与网格中的顶点相比,少了一行和一列。要么你需要在网格中添加额外的行和额外的列,要么从面色中删除一行和一列。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
dx = 0.01
x_range = [5, 8]
y_range = [0, 2]
x = np.arange(x_range[0], x_range[1], dx)
y = np.arange(y_range[0], y_range[1], dx)
X, Y = np.meshgrid(x, y)
data = X + Y ** 2
# Define colors based on the data
def data_to_colors(data):
colors = np.moveaxis(np.zeros_like([data] * 4), 0, -1) # shape (n_y,n_x,4)
# make the data correspond to the blue channel, scaled between 0 and 1
colors[..., 2] = (data - data.min()) / (data.max() - data.min())
# make red and green colors 0.5
colors[..., 0] = 0.5
colors[..., 1] = 0.5
# make the alpha values all 1
colors[..., -1] = 1
return colors
fig, axs = plt.subplots(1, 3, sharex=True, sharey=True, figsize=(12, 4))
# show with imshow
extent = [x_range[0] - dx / 2, x_range[-1] + dx / 2, y_range[0] - dx / 2, y_range[-1] + dx / 2]
axs[0].imshow(data_to_colors(data), extent=extent, origin='lower')
axs[0].set_title('imshow (correct)')
# show by updating the facecolors with set_facecolors
pcmesh = axs[1].pcolormesh(X, Y, data)
fig.canvas.draw()
pcmesh.set_facecolors(data_to_colors(data[:-1, :-1]).reshape(-1, 4))
axs[1].set_title('pcolormesh, using facecolors')
# show using a ListedColorMap mapping each individual (row,column) to a color
colors = data_to_colors(np.linspace(0, 1, 256))
axs[2].pcolormesh(X, Y, data, cmap=ListedColormap(colors))
axs[2].set_title('pcolormesh, using a ListedColormap')
for ax in axs:
ax.set_aspect('equal')
fig.tight_layout()
plt.show()
https://stackoverflow.com/questions/63080124
复制相似问题