Добавить горизонтальную линию с условной окраской - PullRequest
1 голос
/ 06 мая 2019

Я строю contourf график, используя matplotlib.pyplot. Теперь я хочу, чтобы горизонтальная линия (или что-то вроде ax.vspan тоже работало бы) с условной раскраской на y = 0. Я покажу вам, что у меня есть и что я хотел бы получить. Я хочу сделать это с массивом, скажем, landsurface, который представляет собой сушу, океан или лед. Этот массив заполнен 1 (суша), 2 (океан) или 3 (лед) и имеет len(locs) (то есть ось X).

Это код сюжета:

plt.figure()
ax=plt.axes()
clev=np.arange(0.,50.,.5)
plt.contourf(locs,height-surfaceheight,var,clev,extend='max')
plt.xlabel('Location')
plt.ylabel('Height above ground level [m]')
cbar = plt.colorbar()
cbar.ax.set_ylabel('o3 mixing ratio [ppb]')
plt.show()

Это то, что я имею до сих пор:

Original

Вот что я хочу:

Edited

Заранее большое спасибо!

Ответы [ 2 ]

1 голос
/ 06 мая 2019

Введение

Я собираюсь использовать коллекцию строк .

enter image description here Поскольку у меня нет ваших исходных данных, я подделал некоторые данные, используя простую синусоидальную кривую и нанеся на базовую линию цветовые коды, соответствующие малым, средним и высоким значениям кривой

код

Обычный шаблон, нам нужно явно импортировать LineCollection

import matplotlib.pyplot as plt                                                  
import numpy as np                                                               
from matplotlib.collections import LineCollection

Просто чтобы построить что-то, синусоида (х г

x = np.linspace(0, 50, 101)                                                      
y = np.sin(0.3*x)

Цветовое кодирование от значений кривой (соответствующих типам вашей поверхности) до LineCollection цветов, обратите внимание, что LineCollection требует , чтобы цвета были заданы как кортежи RGBA, но я видел примеры использования цветные струны, ба!

# 1 when near min, 2 when near 0, 3 when near max
z = np.where(y<-0.5, 1, np.where(y<+0.5, 2, 3))                                  

col_d = {1:(0.4, 0.4, 1.0, 1), # blue, near min
         2:(0.4, 1.0, 0.4, 1), # green, near zero
         3:(1.0, 0.4, 0.4, 1)} # red, near max                     
# prepare the list of colors
colors = [col_d[n] for n in z]                                                   

В наборе строк нам нужна последовательность сегментов, здесь я решил разместить мою кодированную линию в y=0, но вы можете просто добавить константу к s, чтобы перемещать ее вверх и вниз.
Я признаю, что формирование последовательности сегментов немного сложнее ...

# build the sequence of segments
s = np.zeros(101)                                                                
segments=np.array(list(zip(zip(x,x[1:]),zip(s,s[1:])))).transpose((0,2,1))       
# and fill the LineCollection
lc = LineCollection(segments, colors=colors, linewidths=5, 
                    antialiaseds=0, # to prevent artifacts between lines 
                    zorder=3        # to force drawing over the curve)                                                                 lc = LineCollection(segments, colors=colors, linewidths=5) # possibly add zorder=...                      

Наконец-то мы положили все на холст

# plot the function and the line collection
fig, ax = plt.subplots()                                                         
ax.plot(x,y)                                                                     
ax.add_collection(lc) 
0 голосов
/ 06 мая 2019

Я бы предложил добавить imshow() с соответствующими extent, например ::100100

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

### generate some data
np.random.seed(19680801)
npts = 50
x = np.random.uniform(0, 1, npts)
y = np.random.uniform(0, 1, npts)
X,Y=np.meshgrid(x,y)
z = x * np.exp(-X**2 - Y**2)*100

### create a colormap of three distinct colors for each landmass
landmass_cmap=colors.ListedColormap(["b","r","g"])
x_land=np.linspace(0,1,len(x)) ## this should be scaled to your "location"

## generate some fake landmass types (either 0, 1, or 2) with probabilites
y_land=np.random.choice(3, len(x), p=[0.1, 0.6, 0.3]) 
print(y_land) 

fig=plt.figure()
ax=plt.axes()
clev=np.arange(0.,50.,.5)

## adjust the "height" of the landmass 
x0,x1=0,1
y0,y1=0,0.05 ## y1 is the "height" of the landmass
## make sure that you're passing sensible zorder here and in your .contourf()
im = ax.imshow(y_land.reshape((-1,len(x))),cmap=landmass_cmap,zorder=2,extent=(x0,x1,y0,y1))
plt.contourf(x,y,z,clev,extend='max',zorder=1)

ax.set_xlim(0,1)
ax.set_ylim(0,1)

ax.plot()
ax.set_xlabel('Location')
ax.set_ylabel('Height above ground level [m]')
cbar = plt.colorbar()
cbar.ax.set_ylabel('o3 mixing ratio [ppb]')

## add a colorbar for your listed colormap
cax = fig.add_axes([0.2, 0.95, 0.5, 0.02]) # x-position, y-position, x-width, y-height
bounds = [0,1,2,3]
norm = colors.BoundaryNorm(bounds, landmass_cmap.N)
cb2 = colorbar.ColorbarBase(cax, cmap=landmass_cmap,
                                norm=norm,
                                boundaries=bounds,
                                ticks=[0.5,1.5,2.5],
                                spacing='proportional',
                                orientation='horizontal')
cb2.ax.set_xticklabels(['sea','land','ice'])

plt.show()

Выходы:

Exemplary plot now with legend

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...