2012-07-19 17 views
9

यह एक रंग के साथ लाइनों के बीच भरने के लिए संभव है के बीच भरने:matplotlib: निरंतर रंग मैप दो पंक्तियों

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

यह भी एक लाइन के लिए एक सतत रंग मैप का उपयोग करना संभव है:

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

क्या यह संभव है (और उचित रूप से आसान) रंगीन भरने के लिए दो पंक्तियों के बीच निरंतर रंगरूपता का उपयोग करना संभव है? उदाहरण के लिए, एक्स पर दो पंक्तियों (या डेटा के दूसरे सेट के आधार पर) के बीच अंतर के आधार पर रंग भरना x के साथ बदल सकता है।

उत्तर

6

मुझे इस समस्या का समाधान मिला। यह @ हुक के शानदार लेकिन हैकी solution पर बनाता है। आप बहुत सारे छोटे बक्से से दायर 2 डी ग्रिड बनाते हैं। यह सबसे तेज़ समाधान नहीं है लेकिन यह बहुत लचीला होना चाहिए (पैच के लिए लागू होने वाले समाधानों से अधिक)।

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

अच्छा उदाहरण के लिए, हो सकता है आप के लिए एक आत्म लगातार उदाहरण देने के लिए अपने 'रेक्ट()' समारोह जोड़ सकते हैं। धन्यवाद – Ger

+0

धन्यवाद @ जीर, मुझे एहसास नहीं हुआ कि मैं इसे भूल गया हूं और 'रेक्ट' वास्तव में तुच्छ नहीं है –

2

आपका समाधान महान और लचीला है! विशेष रूप से 2 डी मामला वास्तव में अच्छा है। इस तरह की सुविधा को fill_between में जोड़ा जा सकता है, यदि फ़ंक्शन के रंगों के रंग x और y की समान लंबाई की सरणी स्वीकार करेंगे?

fill_between फ़ंक्शन का उपयोग करके 1 डी केस के लिए यहां एक आसान मामला है। यह वही करता है लेकिन जैसा कि यह आयताकार के बजाय ट्रैपेज़ का उपयोग करता है, परिणाम चिकना होता है।

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

संबंधित मुद्दे