修改 matplotlib 颜色图

bay*_*man 2 python matplotlib python-3.x

我正在尝试使用 Python 生成此图像的类似版本:

原图

我很接近但无法弄清楚如何修改 matplotlib 颜色图以使值 <0.4 变为白色。我尝试屏蔽这些值并使用,set_bad但我最终得到了一个真正的块状外观,失去了原始图像中看到的漂亮平滑的轮廓。

  • 具有连续颜色图的结果(问题:没有白色):

    具有所有颜色的图像

  • 结果set_bad(问题:没有平滑过渡到白色):

    带有屏蔽值的图像

到目前为止的代码:

from netCDF4 import Dataset as NetCDFFile
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.basemap import Basemap
nc = NetCDFFile('C:/myfile1.nc')
nc1 = NetCDFFile('C:/myfile2.nc')
lat = nc.variables['lat'][:]
lon = nc.variables['lon'][:]
time = nc.variables['time'][:]
uwnd = nc.variables['uwnd'][:]
vwnd = nc1.variables['vwnd'][:]
map = Basemap(llcrnrlon=180.,llcrnrlat=0.,urcrnrlon=340.,urcrnrlat=80.)
lons,lats = np.meshgrid(lon,lat)
x,y = map(lons,lats)
speed = np.sqrt(uwnd*uwnd+vwnd*vwnd)
#speed = np.ma.masked_where(speed < 0.4, speed)
#cmap = plt.cm.jet
#cmap.set_bad(color='white')
levels = np.arange(0.0,3.0,0.1)
ticks = np.arange(0.0,3.0,0.2)
cs = map.contourf(x,y,speed[0],levels, cmap='jet')
vw = plt.quiver(x,y,speed)
cbar = plt.colorbar(cs, orientation='horizontal', cmap='jet', spacing='proportional',ticks=ticks)
cbar.set_label('850 mb Vector Wind Anomalies (m/s)')
map.drawcoastlines()
map.drawparallels(np.arange(20,80,20),labels=[1,1,0,0], linewidth=0.5)
map.drawmeridians(np.arange(200,340,20),labels=[0,0,0,1], linewidth=0.5)
#plt.show()
plt.savefig('phase8_850wind_anom.png',dpi=600)
Run Code Online (Sandbox Code Playgroud)

Tom*_*eus 7

获得平滑结果的答案在于构建您自己的颜色图。要做到这一点,必须创建一个 RGBA 矩阵:一个矩阵,每一行都有红色、绿色、蓝色和 Alpha(透明度;0 表示像素没有任何覆盖信息和是透明的)。

例如,到某个点的距离以二维方式绘制。然后:

  • 对于高于某个临界值的任何距离,颜色将从标准颜色图中获取。
  • 对于低于某个临界值的任何距离,颜色将从白色线性变为前面提到的地图的第一种颜色。

选择完全取决于您要显示的内容。颜色图及其大小取决于您的问题。例如,您可以选择不同类型的插值:线性、指数、...;单色或多色颜色图;等等..

编码:

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

from mpl_toolkits.axes_grid1 import make_axes_locatable

# create colormap
# ---------------

# create a colormap that consists of
# - 1/5 : custom colormap, ranging from white to the first color of the colormap
# - 4/5 : existing colormap

# set upper part: 4 * 256/4 entries
upper = mpl.cm.jet(np.arange(256))

# set lower part: 1 * 256/4 entries
# - initialize all entries to 1 to make sure that the alpha channel (4th column) is 1
lower = np.ones((int(256/4),4))
# - modify the first three columns (RGB):
#   range linearly between white (1,1,1) and the first color of the upper colormap
for i in range(3):
  lower[:,i] = np.linspace(1, upper[0,i], lower.shape[0])

# combine parts of colormap
cmap = np.vstack(( lower, upper ))

# convert to matplotlib colormap
cmap = mpl.colors.ListedColormap(cmap, name='myColorMap', N=cmap.shape[0])

# show some example
# -----------------

# open a new figure
fig, ax = plt.subplots()

# some data to plot: distance to point at (50,50)
x,y = np.meshgrid(np.linspace(0,99,100),np.linspace(0,99,100))
z   = (x-50)**2. + (y-50)**2.

# plot data, apply colormap, set limit such that our interpretation is correct
im = ax.imshow(z, interpolation='nearest', cmap=cmap, clim=(0,5000))

# add a colorbar to the bottom of the image
div  = make_axes_locatable(ax)
cax  = div.append_axes('bottom', size='5%', pad=0.4)
cbar = plt.colorbar(im, cax=cax, orientation='horizontal')

# save/show the image
plt.savefig('so.png')
plt.show()
Run Code Online (Sandbox Code Playgroud)

结果:

在此处输入图片说明