2016-06-01 193 views
1

我想將一些從gnuplot的繪圖代碼移植到matplotlib,並且正在努力移植由顏色名稱指定的不連續顏色映射。 關於如何在matplotlib中做到這一點的任何建議?轉換gnuplot顏色映射到matplotlib

# Establish a 3-section color palette with lower 1/4 in the blues, 
# and middle 1/2 light green to yellow, and top 1/4 reds 
set palette defined (0 'dark-blue', 0.5 'light-blue', \\ 
        0.5 'light-green', 1 'green', 1.5 'yellow', \\ 
        1.5 'red', 2 'dark-red') 
# Establish that the palette range, such that the middle green range corresponds 
# to 0.95 to 1.05 
set cbrange [0.9:1.1] 

Desired colorbar

+1

恐怕沒有1:1翻譯matplotlib。看看cdicts和'LinearSegmentedColormap',但是你必須使用RGB值(並且我必須承認,它並不急於理解這些cdicts)。 http://stackoverflow.com/questions/32524471/custom-colormap-in-python和http://matplotlib.org/examples/pylab_examples/custom_cmap.html –

回答

2

巴特的功能是非常好的。但是,如果您想自己製作色彩映射表,則可以按照在custom_cmap example from the mpl website中完成的方式使用字典來定義像這樣的色彩映射表。

這裏的那是相當接近的顏色表的例子:

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

cdict = {'red': ((0.0, 0.0, 0.0), # From 0 to 0.25, we fade the red and green channels 
        (0.25, 0.5, 0.5), # up a little, to make the blue a bit more grey 

        (0.25, 0.0, 0.0), # From 0.25 to 0.75, we fade red from 0.5 to 1 
        (0.75, 1.0, 1.0), # to fade from green to yellow 

        (1.0, 0.5, 0.5)), # From 0.75 to 1.0, we bring the red down from 1 
             # to 0.5, to go from bright to dark red 

     'green': ((0.0, 0.0, 0.0), # From 0 to 0.25, we fade the red and green channels 
        (0.25, 0.6, 0.6), # up a little, to make the blue a bit more grey 

        (0.25, 1.0, 1.0), # Green is 1 from 0.25 to 0.75 (we add red 
        (0.75, 1.0, 1.0), # to turn it from green to yellow) 

        (0.75, 0.0, 0.0), # No green needed in the red upper quarter 
        (1.0, 0.0, 0.0)), 

     'blue': ((0.0, 0.9, 0.9), # Keep blue at 0.9 from 0 to 0.25, and adjust its 
        (0.25, 0.9, 0.9), # tone using the green and red channels 

        (0.25, 0.0, 0.0), # No blue needed above 0.25 
        (1.0, 0.0, 0.0)) 

      } 

cmap = colors.LinearSegmentedColormap('BuGnYlRd',cdict) 

data = 0.9 + (np.random.rand(8,8) * 0.2) # Data in range 0.9 to 1.1 

p=plt.imshow(data,interpolation='nearest',cmap=cmap,vmin=0.9,vmax=1.1) 

plt.colorbar(p) 

plt.show() 

enter image description here

+0

這的確非常接近。是否可以縮放這個活動範圍以應用從0.9到1.1而不是0到1? –

+0

是的,這很容易,色彩地圖不需要改變。你可以改變數據的範圍和'imshow'的'vmin'和'vmax'。我將編輯答案向您展示 – tom

+0

完美,並且很好的解釋每個顏色通道顏色映射語句中相當棘手的問題。 –

4

我用這個腳本多年,真的不記得如何或在哪裏我得到它(編輯:經過一番搜索,this似乎是源,但它需要對Python3進行一些小改動),但它在快速創建自定義彩色地圖方面幫了我很大忙。它允許您簡單地指定一個包含位置(0..1)和顏色的字典,並創建一個線性顏色圖表;例如make_colormap({0:'w',1:'k'})創建一個從白色到黑色的線性彩色地圖。

import numpy as np 
import matplotlib.pylab as pl 

def make_colormap(colors): 
    from matplotlib.colors import LinearSegmentedColormap, ColorConverter 
    from numpy import sort 

    z = np.array(sorted(colors.keys())) 
    n = len(z) 
    z1 = min(z) 
    zn = max(z) 
    x0 = (z - z1)/(zn - z1) 

    CC = ColorConverter() 
    R = [] 
    G = [] 
    B = [] 
    for i in range(n): 
     Ci = colors[z[i]]  
     if type(Ci) == str: 
      RGB = CC.to_rgb(Ci) 
     else: 
      RGB = Ci 
     R.append(RGB[0]) 
     G.append(RGB[1]) 
     B.append(RGB[2]) 

    cmap_dict = {} 
    cmap_dict['red'] = [(x0[i],R[i],R[i]) for i in range(len(R))] 
    cmap_dict['green'] = [(x0[i],G[i],G[i]) for i in range(len(G))] 
    cmap_dict['blue'] = [(x0[i],B[i],B[i]) for i in range(len(B))] 
    mymap = LinearSegmentedColormap('mymap',cmap_dict) 
    return mymap 

test1 = make_colormap({0.:'#40004b',0.5:'#ffffff',1.:'#00441b'}) 
test2 = make_colormap({0.:'b',0.25:'w',0.251:'g',0.75:'y',0.751:'r',1:'k'}) 

data = np.random.random((10,10)) 

pl.figure() 
pl.subplot(121) 
pl.imshow(data, interpolation='nearest', cmap=test1) 
pl.colorbar() 

pl.subplot(122) 
pl.imshow(data, interpolation='nearest', cmap=test2) 
pl.colorbar() 

enter image description here

+0

好吧,很酷! –

+0

非常好。該功能有助於隱藏單獨指定顏色通道的複雜情況。是否可以縮放活動範圍以應用從0.9到1.1而不是0到1?是否可以像'make_colormap({0:'w',0.5:'k',0.5:'r',1:'b'})一樣指定重複值? –

+0

對於範圍'0.9--1.1',請參閱湯姆斯的答案(這裏同樣適用)。重複值現在不起作用(我剛剛測試過);我會使用實用的方法,並簡單地使用'({0:'w',0.5:'k',0.500000000001:'r',1:'b'})',但是你可以改變這個函數並自動執行重複值。 – Bart