2010-07-19 169 views
138

我想知道如何簡單地顛倒給定顏色映射的顏色順序以便將它與plot_surface一起使用。在matplotlib中反轉顏色映射

+0

標題應該是「恢復」而不是「反轉」。它們是有區別的! – 2017-11-23 17:33:58

回答

268

標準色彩映射也都有相反的版本。他們與_r相同的名字結束了。 (Documentation here.

+0

這不適用於「amfhot」:「ValueError:Colormap amfhot_r無法識別」。我想「hot_r」就足夠了。 – shockburner 2015-05-01 18:26:26

+0

同樣,「ValueError:Colormap red_r無法識別。」 – 2017-05-19 15:14:05

12

在matplotlib中,顏色貼圖不是一個列表,但它包含顏色列表colormap.colors。並且模塊matplotlib.colors提供功能ListedColormap()以從列表生成顏色映射。所以,你可以通過做

colormap_r = ListedColormap(colormap.colors[::-1]) 
+7

+1。但是,這通常不會反轉任何色彩映射。只有'ListedColormap's(即離散的,而不是插值的)具有'colors'屬性。反轉'LinearSegmentedColormaps'有點複雜。 (您需要反轉'_segmentdata'字典中的每個項目。) – 2013-06-15 21:22:09

+3

關於「LinearSegmentedColormaps」的反轉,我只是對一些色彩地圖做了這個。 [這是一個IPython筆記本。](http://nbviewer.ipython.org/github/kwinkunks/notebooks/blob/master/Matteo_colourmaps.ipynb) – kwinkunks 2014-04-26 12:57:12

+0

@kwinkunks我認爲你的筆記本中的功能是不正確的,看到答案低於 – Mattijn 2016-01-14 02:30:34

6

作爲LinearSegmentedColormaps是基於紅色,綠色和藍色的字典推翻任何彩色地圖,有必要扭轉每個項目:

import matplotlib.pyplot as plt 
import matplotlib as mpl 
def reverse_colourmap(cmap, name = 'my_cmap_r'): 
    """ 
    In: 
    cmap, name 
    Out: 
    my_cmap_r 

    Explanation: 
    t[0] goes from 0 to 1 
    row i: x y0 y1 -> t[0] t[1] t[2] 
       /
       /
    row i+1: x y0 y1 -> t[n] t[1] t[2] 

    so the inverse should do the same: 
    row i+1: x y1 y0 -> 1-t[0] t[2] t[1] 
       /
       /
    row i: x y1 y0 -> 1-t[n] t[2] t[1] 
    """   
    reverse = [] 
    k = [] 

    for key in cmap._segmentdata:  
     k.append(key) 
     channel = cmap._segmentdata[key] 
     data = [] 

     for t in channel:      
      data.append((1-t[0],t[2],t[1]))    
     reverse.append(sorted(data))  

    LinearL = dict(zip(k,reverse)) 
    my_cmap_r = mpl.colors.LinearSegmentedColormap(name, LinearL) 
    return my_cmap_r 

看到,它的工作原理:

my_cmap   
<matplotlib.colors.LinearSegmentedColormap at 0xd5a0518> 

my_cmap_r = reverse_colourmap(my_cmap) 

fig = plt.figure(figsize=(8, 2)) 
ax1 = fig.add_axes([0.05, 0.80, 0.9, 0.15]) 
ax2 = fig.add_axes([0.05, 0.475, 0.9, 0.15]) 
norm = mpl.colors.Normalize(vmin=0, vmax=1) 
cb1 = mpl.colorbar.ColorbarBase(ax1, cmap = my_cmap, norm=norm,orientation='horizontal') 
cb2 = mpl.colorbar.ColorbarBase(ax2, cmap = my_cmap_r, norm=norm, orientation='horizontal') 

enter image description here

ED IT


我沒有得到user3445587的評論。它工作正常的彩虹顏色映射:

cmap = mpl.cm.jet 
cmap_r = reverse_colourmap(cmap) 

fig = plt.figure(figsize=(8, 2)) 
ax1 = fig.add_axes([0.05, 0.80, 0.9, 0.15]) 
ax2 = fig.add_axes([0.05, 0.475, 0.9, 0.15]) 
norm = mpl.colors.Normalize(vmin=0, vmax=1) 
cb1 = mpl.colorbar.ColorbarBase(ax1, cmap = cmap, norm=norm,orientation='horizontal') 
cb2 = mpl.colorbar.ColorbarBase(ax2, cmap = cmap_r, norm=norm, orientation='horizontal') 

enter image description here

但它特別適用漂亮的自定義聲明色彩映射表,因爲沒有一個默認_r自定義聲明的colormaps。下面的示例http://matplotlib.org/examples/pylab_examples/custom_cmap.html採取:

cdict1 = {'red': ((0.0, 0.0, 0.0), 
        (0.5, 0.0, 0.1), 
        (1.0, 1.0, 1.0)), 

     'green': ((0.0, 0.0, 0.0), 
        (1.0, 0.0, 0.0)), 

     'blue': ((0.0, 0.0, 1.0), 
        (0.5, 0.1, 0.0), 
        (1.0, 0.0, 0.0)) 
     } 

blue_red1 = mpl.colors.LinearSegmentedColormap('BlueRed1', cdict1) 
blue_red1_r = reverse_colourmap(blue_red1) 

fig = plt.figure(figsize=(8, 2)) 
ax1 = fig.add_axes([0.05, 0.80, 0.9, 0.15]) 
ax2 = fig.add_axes([0.05, 0.475, 0.9, 0.15]) 

norm = mpl.colors.Normalize(vmin=0, vmax=1) 
cb1 = mpl.colorbar.ColorbarBase(ax1, cmap = blue_red1, norm=norm,orientation='horizontal') 
cb2 = mpl.colorbar.ColorbarBase(ax2, cmap = blue_red1_r, norm=norm, orientation='horizontal') 

enter image description here

+0

這個例子並不完整,因爲段數據不在列表中,因此它不必是可逆的(例如標準彩虹色圖)。 我認爲原則上所有的LinearSegmentedColormaps都應該可以使用lambda函數作爲彩虹色圖中的可逆方式嗎? – overseas 2015-12-28 16:03:45

+0

@ user3445587我添加了一些示例,但我認爲它在標準彩虹色圖上運行得很好 – Mattijn 2016-01-14 02:28:03

+0

由於它太長了,我添加了一個新的答案,它應該適用於所有類型的LinearSegmentData。 問題是,對於彩虹,_segmentdata的實現方式不同。所以你的代碼 - 至少在我的機器上 - 不適用於彩虹色圖。 – overseas 2016-01-14 09:58:24

1

有兩種類型LinearSegmentedColormaps的。在一些中,_segmentdata明確給出,例如,用於噴氣:

>>> cm.jet._segmentdata 
{'blue': ((0.0, 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), (0.65, 0, 0), (1, 0, 0)), 'red': ((0.0, 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89, 1, 1), (1, 0.5, 0.5)), 'green': ((0.0, 0, 0), (0.125, 0, 0), (0.375, 1, 1), (0.64, 1, 1), (0.91, 0, 0), (1, 0, 0))} 

對於彩虹,_segmentdata給出如下:

>>> cm.rainbow._segmentdata 
{'blue': <function <lambda> at 0x7fac32ac2b70>, 'red': <function <lambda> at 0x7fac32ac7840>, 'green': <function <lambda> at 0x7fac32ac2d08>} 

我們可以在matplotlib的來源,發現的功能,他們給出你想要的已經在做matplotlib

_rainbow_data = { 
     'red': gfunc[33], # 33: lambda x: np.abs(2 * x - 0.5), 
     'green': gfunc[13], # 13: lambda x: np.sin(x * np.pi), 
     'blue': gfunc[10], # 10: lambda x: np.cos(x * np.pi/2) 
} 

一切,只需撥打cm.revcmap,其反轉兩種類型segmentdata,所以

cm.revcmap(cm.rainbow._segmentdata) 

應該做的工作 - 你可以簡單地創建一個新的LinearSegmentData。在revcmap,功能基於SegmentData逆轉與

def _reverser(f): 
    def freversed(x): 
     return f(1 - x) 
    return freversed 

完成,而其他列表顛倒照常

valnew = [(1.0 - x, y1, y0) for x, y0, y1 in reversed(val)] 

所以實際上你想整個事情,是

def reverse_colourmap(cmap, name = 'my_cmap_r'): 
    return mpl.colors.LinearSegmentedColormap(name, cm.revcmap(cmap._segmentdata)) 
2

解決方案非常簡單。假設你想使用「秋季」色彩圖方案。標準版:

cmap = matplotlib.cm.autumn 

要反轉顏色表色彩頻譜,使用get_cmap()函數,並追加「_r」的顏色表標題是這樣的:

cmap_reversed = matplotlib.cm.get_cmap('autumn_r') 
1

沒有內置的方式(尚)逆轉任意色彩映射的,但一個簡單的解決方案是真正無法修改顏色條,而是創建一個反向規範化對象:

from matplotlib.colors import Normalize 

class InvertedNormalize(Normalize): 
    def __call__(self, *args, **kwargs): 
     return 1 - super(InvertedNormalize, self).__call__(*args, **kwargs) 

可以再用使用和其他Matplotlib繪圖功能

inverted_norm = InvertedNormalize(vmin=10, vmax=100) 
ax.plot_surface(..., cmap=<your colormap>, norm=inverted_norm) 

這將適用於任何Matplotlib顏色映射。

+0

現在有! https://matplotlib.org/api/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib.colors.ListedColormap.reversed – 2018-03-06 21:59:30

0

由於Matplotlib 2.0,對於ListedColormapLinearSegmentedColorMap對象reversed()方法,所以你可以做

cmap_reversed = cmap.reverse()

的文檔見here