Обратная цветовая карта в matplotlib - PullRequest
198 голосов
/ 19 июля 2010

Я хотел бы знать, как просто изменить порядок цветов данной карты цветов, чтобы использовать ее с plot_surface.

Ответы [ 7 ]

372 голосов
/ 19 июля 2010

Стандартные карты цветов также имеют обратную версию.У них одинаковые имена с _r, прикрепленными к концу.( Документация здесь. )

15 голосов
/ 16 июня 2013

В matplotlib карта цветов не является списком, но содержит список своих цветов как colormap.colors.А модуль matplotlib.colors предоставляет функцию ListedColormap() для генерации цветовой карты из списка.Таким образом, вы можете перевернуть любую цветовую карту, выполнив

colormap_r = ListedColormap(colormap.colors[::-1])
9 голосов
/ 18 декабря 2015

Поскольку 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

EDIT


Я не получил комментарий от пользователя 3445587. Отлично работает на карте цветов радуги:

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. Следующий пример взят из 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

6 голосов
/ 07 марта 2018

Начиная с Matplotlib 2.0, существует reversed() метод для ListedColormap и LinearSegmentedColorMap объектов, поэтому вы можете просто сделать

cmap_reversed = cmap.reversed()

Здесь это документация.

6 голосов
/ 20 июня 2017

Решение довольно простое. Предположим, вы хотите использовать цветовую схему «осень». Стандартная версия:

cmap = matplotlib.cm.autumn

Чтобы изменить цветовую гамму карты цветов, используйте функцию get_cmap () и добавьте '_r' к заголовку карты цветов следующим образом:

cmap_reversed = matplotlib.cm.get_cmap('autumn_r')
1 голос
/ 08 августа 2017

Нет встроенного способа (пока) реверсирования произвольных цветовых карт, но одно простое решение состоит в том, чтобы фактически не изменять цветовую панель, а создать инвертирующий объект нормализации:

from matplotlib.colors import Normalize

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

Затем можно использоватьэто с plot_surface и другими функциями построения Matplotlib, например:

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

Это будет работать с любой цветовой картой Matplotlib.

1 голос
/ 14 января 2016

Существует два типа LinearSegmentedColormaps. В некоторых случаях _segmentdata дается явно, например, для jet:

>>> 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, где они заданы как

_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)
}

Все, что вы хотите, уже сделано в matplotlib, просто вызовите cm.revcmap, который инвертирует оба типа сегмента данных, поэтому

cm.revcmap(cm.rainbow._segmentdata)

должен выполнить эту работу - вы можете просто создать новую LinearSegmentData из этого. В revcmap обращение сегментированных данных на основе функций выполняется с помощью

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)) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...