2012-07-19 14 views
9

2行の間を埋める:matplotlibの:連続カラーマップは、それは色と線の間に充填することが可能です

http://matplotlib.sourceforge.net/examples/pylab_examples/fill_between_demo.html

それはラインのための継続的なカラーマップを使用することも可能です:

http://matplotlib.sourceforge.net/examples/pylab_examples/multicolored_line.html

2つの線の間の色付き塗りつぶしに連続カラーマップを使用することは可能ですか?例えば、色の塗りつぶしは、xの2つの線の間の差に基づいて(または別のデータの集合に基づいて)xに沿って変化し得る。

答えて

6

この問題の解決策が見つかりました。それは@Hookedの華麗でもハッキーなsolutionに基づいています。小さな箱がたくさんある場所から2Dグリッドを作成します。これは最速の解決策ではありませんが、かなり柔軟に対応する必要があります(パッチに適用するソリューションよりも)。

import numpy as np 
import pylab as plt 

#Plot a rectangle 
def rect(ax, x, y, w, h, c,**kwargs): 
    #Varying only in x 
    if len(c.shape) is 1: 
     rect = plt.Rectangle((x, y), w, h, color=c, ec=c,**kwargs) 
     ax.add_patch(rect) 
    #Varying in x and y 
    else: 
     #Split into a number of bins 
     N = c.shape[0] 
     hb = h/float(N); yl = y 
     for i in range(N): 
      yl += hb 
      rect = plt.Rectangle((x, yl), w, hb, 
           color=c[i,:], ec=c[i,:],**kwargs) 
      ax.add_patch(rect) 

#Fill a contour between two lines 
def rainbow_fill_between(ax, X, Y1, Y2, colors=None, 
         cmap=plt.get_cmap("Reds"),**kwargs): 
    plt.plot(X,Y1,lw=0) # Plot so the axes scale correctly 

    dx = X[1]-X[0] 
    N = X.size 

    #Pad a float or int to same size as x 
    if (type(Y2) is float or type(Y2) is int): 
     Y2 = np.array([Y2]*N) 

    #No colors -- specify linear 
    if colors is None: 
     colors = [] 
     for n in range(N): 
      colors.append(cmap(n/float(N))) 
    #Varying only in x 
    elif len(colors.shape) is 1: 
     colors = cmap((colors-colors.min()) 
         /(colors.max()-colors.min())) 
    #Varying only in x and y 
    else: 
     cnp = np.array(colors) 
     colors = np.empty([colors.shape[0],colors.shape[1],4]) 
     for i in range(colors.shape[0]): 
      for j in range(colors.shape[1]): 
       colors[i,j,:] = cmap((cnp[i,j]-cnp[:,:].min()) 
            /(cnp[:,:].max()-cnp[:,:].min())) 

    colors = np.array(colors) 

    #Create the patch objects 
    for (color,x,y1,y2) in zip(colors,X,Y1,Y2): 
     rect(ax,x,y2,dx,y1-y2,color,**kwargs) 


# Some Test data  
X = np.linspace(0,10,100) 
Y1 = .25*X**2 - X 
Y2 = X 
g = np.exp(-.3*(X-5)**2) 

#Plot fill and curves changing in x only 
fig, axs =plt.subplots(1,2) 
colors = g 
rainbow_fill_between(axs[0],X,Y1,Y2,colors=colors) 
axs[0].plot(X,Y1,'k-',lw=4) 
axs[0].plot(X,Y2,'k-',lw=4) 

#Plot fill and curves changing in x and y 
colors = np.outer(g,g) 
rainbow_fill_between(axs[1],X,Y1,Y2,colors=colors) 
axs[1].plot(X,Y1,'k-',lw=4) 
axs[1].plot(X,Y2,'k-',lw=4) 
plt.show() 

結果は、 enter image description here

+0

ニースたとえば、多分あなたは、自己一貫性の例を与えるために、あなたの 'RECT()'関数を追加することができます。ありがとうございました – Ger

+0

ありがとう@Ger、私はこれを忘れていたと私は忘れていないと 'rect'は実際には自明ではない –

2

あなたのソリューションは、素晴らしいと柔軟性があります!特に、2Dの場合は本当にいいです。このような機能は、関数のカラーkwargsがxとyの同じ長さの配列を受け入れる場合、多分fill_betweenに追加することができますか?

fill_between機能を使用する1Dのケースでは、より簡単なケースです。それは同じことをしますが、四角形の代わりに台形を使用するので、結果はより滑らかです。

import matplotlib as mpl 
import matplotlib.pyplot as plt 

import numpy as np 
from scipy.stats import norm 

# Select a color map 
cmap = mpl.cm.bwr 

# Some Test data 
npts = 100 
x = np.linspace(-4, 4, npts) 
y = norm.pdf(x) 
z = np.sin(2 * x) 
normalize = mpl.colors.Normalize(vmin=z.min(), vmax=z.max()) 

# The plot 
fig = plt.figure() 
ax = fig.add_axes([0.12, 0.12, 0.68, 0.78]) 
plt.plot(x, y, color="gray") 
for i in range(npts - 1): 
    plt.fill_between([x[i], x[i+1]], [y[i], y[i+1]], color=cmap(normalize(z[i]))) 

cbax = fig.add_axes([0.85, 0.12, 0.05, 0.78]) 
cb = mpl.colorbar.ColorbarBase(cbax, cmap=cmap, norm=normalize, orientation='vertical') 
cb.set_label("Sin function", rotation=270, labelpad=15) 
plt.show() 

enter image description here

関連する問題