Проблемы с контуром и уровнями - PullRequest
0 голосов
/ 10 июня 2019

Мне нужно разделить каждый диапазон синего и кофе на два цвета каждый,

https://i.stack.imgur.com/GqqPj.png

В моем коде ниже я указываю уровни, но разделение не выполняется

lon_0 = lons.mean()
lat_0 = lats.mean()
m = Basemap(projection='merc',llcrnrlat=min_lat,urcrnrlat=max_lat,
            llcrnrlon=min_lon, urcrnrlon=max_lon, resolution='l')
lon, lat = np.meshgrid(lons, lats)
xi, yi = m(lon, lat)

fig = plt.figure(figsize=(10,20))
m.drawparallels(np.arange(-20., 40., 3.), labels=[1,0,0,0], fontsize=12) # Latitude  lines every 5 degrees from -5 to 15. Left zone
m.drawmeridians(np.arange(-90.,-40., 3.), labels=[0,0,0,1], fontsize=12) # longitude lines every 5 degrees from -80 to -45. Down zone

# Add Coastlines, States, and Country Boundaries
m.drawcoastlines(linewidth= 1, color='black')
#m.drawstates()
m.drawcountries(linewidth= 1, color='black')
#m.readshapefile('/home/shared/shapes/bogota/Localidades_Lat_lon', 'Localidades_Lat_lon')
vals = [0.00000,0.00005,0.0001,0.0002,0.0004,0.0006,0.0008,0.0012,0.1]
cmap = mpl.colors.ListedColormap(['#2c7bb6','#0a793a','#77a353','#f1d499','#c96a33','#975114'])

#matplotlib.colors.ListedColormap(colors)

colors = ['#b5277c','#f200ff','#1600ff', "#0188ff", "#02ffaf", "#3db728", "#b2ff00", '#ffe100','#b58c27','#ff0000']
cs = m.contourf(xi, yi, (Agricola.variables['E_PM25J'][0,0,:,:]), cmap=cmap, vmin=0, vmax=np.percentile(np.mean(Agricola.variables['E_PM25J'][:,0,:,:], axis=0), 90.5), levels=vals)
## Add Colorbar
plt.title('Emisiones Agricola', fontsize=20)
cbar = m.colorbar(cs, location='right', pad="2%", size="5%", extend='max')
cbar.set_label("PM2.5 " + "$ug /m^2 s^1$", fontsize=1)
plt.show()

1 Ответ

0 голосов
/ 11 июня 2019

TL; DR Номер матча. от интервалов до нет. цветов. Используйте BoundaryNorm.


У вас есть ряд проблем с вашим кодом, в первую очередь существует расхождение между количеством цветов в вашем ListedColormap и количеством интервалов , определенных списком vals (запомните что вы хотите отобразить 1color ← → 1interval), второе, что вы оставляете на волю случая, когда происходит сопоставление значений с цветовой картой, в то время как Matplotlib имеет инструменты, которые позволяют вам точно указать, что произойдет (а именно matplotlib.colors.BoundaryNorm).

У меня нет ваших данных, поэтому я попытался построить параллельный, более простой пример, который вы сможете адаптировать к вашей проблеме.

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

# dummy data, a sine, 0 in the origin, 1 close to NE corner
x = np.linspace(0, 1, N)
X, Y = np.meshgrid(x, x)
R = np.sqrt(X**2+Y**2)
Z = np.sin(R*3/2)

# the levels that I want to draw on the plot,
# the levels, except for the extremes, are quite arbitrary
# as arbitrary do they seem your level specifications
levels = [0.0, .5, .6, .75, .85, .95, 1.0]
# your colormap
cmap = mcol.ListedColormap(['#2c7bb6', '#0a793a', '#77a353',
                            '#f1d499', '#c96a33', '#975114'])
# the nuber of intervals must be equal to the number of listed colors
assert(len(levels)-1==cmap.N)
# the norm that we use to map values to colors, see the docs    
norm = mcol.BoundaryNorm(levels, cmap.N)

# we are ready to plot
plt.contourf(X, Y, Z, cmap=cmap, levels=levels, norm=norm)
plt.colorbar()

# this is not necessary for your problem but it;s nice in my example    
p = plt.contour(X, Y, Z, levels=levels, colors='k')
plt.clabel(p, inline=1)

#  T H E   E N D
plt.show()

Это приводит к a beautiful graph

...