Réponses:
Les cartes de couleurs standard ont également toutes des versions inversées. Ils ont les mêmes noms avec _rcloués à la fin. ( Documentation ici. )
Dans matplotlib, une carte de couleurs n'est pas une liste, mais elle contient la liste de ses couleurs en tant que colormap.colors. Et le module matplotlib.colorsfournit une fonction ListedColormap()pour générer une carte de couleurs à partir d'une liste. Vous pouvez donc inverser n'importe quelle carte de couleur en faisant
colormap_r = ListedColormap(colormap.colors[::-1])
ListedColormaps (c'est-à-dire discrets, plutôt qu'interpolés) ont un colorsattribut. L'inversion LinearSegmentedColormapsest un peu plus complexe. (Vous devez inverser chaque élément du _segmentdatadicton.)
LinearSegmentedColormaps, je viens de le faire pour certaines cartes de couleurs. Voici un bloc-notes IPython à ce sujet.
La solution est assez simple. Supposons que vous souhaitiez utiliser le schéma de couleurs "automne". La version standard:
cmap = matplotlib.cm.autumn
Pour inverser le spectre de couleurs de la palette de couleurs, utilisez la fonction get_cmap () et ajoutez «_r» au titre de la palette de couleurs comme ceci:
cmap_reversed = matplotlib.cm.get_cmap('autumn_r')
Comme un LinearSegmentedColormapsest basé sur un dictionnaire de rouge, vert et bleu, il est nécessaire d'inverser chaque élément:
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
Assurez-vous que cela fonctionne:
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')
ÉDITER
Je ne reçois pas le commentaire de user3445587. Cela fonctionne bien sur la palette de couleurs arc-en-ciel:
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')
Mais cela fonctionne particulièrement bien pour les cartes de couleurs déclarées personnalisées, car il n'y a pas de valeur _rpar défaut pour les cartes de couleurs déclarées personnalisées. Exemple suivant tiré de 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')
Depuis Matplotlib 2.0, il existe une reversed()méthode pour ListedColormapet des LinearSegmentedColorMapobjets, vous pouvez donc simplement faire
cmap_reversed = cmap.reversed()
Voici la documentation.
Il existe deux types de LinearSegmentedColormaps. Dans certains, les _segmentdata sont donnés explicitement, par exemple, pour 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))}
Pour arc-en-ciel, _segmentdata est donné comme suit:
>>> cm.rainbow._segmentdata
{'blue': <function <lambda> at 0x7fac32ac2b70>, 'red': <function <lambda> at 0x7fac32ac7840>, 'green': <function <lambda> at 0x7fac32ac2d08>}
Nous pouvons trouver les fonctions dans la source de matplotlib, où elles sont données comme
_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)
}
Tout ce que vous voulez est déjà fait dans matplotlib, appelez simplement cm.revcmap, qui inverse les deux types de données de segment, donc
cm.revcmap(cm.rainbow._segmentdata)
devrait faire le travail - vous pouvez simplement créer un nouveau LinearSegmentData à partir de cela. Dans revcmap, l'inversion de SegmentData basée sur une fonction se fait avec
def _reverser(f):
def freversed(x):
return f(1 - x)
return freversed
tandis que les autres listes sont inversées comme d'habitude
valnew = [(1.0 - x, y1, y0) for x, y0, y1 in reversed(val)]
Donc en fait, tout ce que vous voulez, c'est
def reverse_colourmap(cmap, name = 'my_cmap_r'):
return mpl.colors.LinearSegmentedColormap(name, cm.revcmap(cmap._segmentdata))
Il n'y a pas (encore) de méthode intégrée pour inverser les palettes de couleurs arbitraires, mais une solution simple consiste en fait à ne pas modifier la barre de couleurs mais à créer un objet Normalize inverseur:
from matplotlib.colors import Normalize
class InvertedNormalize(Normalize):
def __call__(self, *args, **kwargs):
return 1 - super(InvertedNormalize, self).__call__(*args, **kwargs)
Vous pouvez ensuite l'utiliser avec d' plot_surfaceautres fonctions de traçage de Matplotlib en faisant par exemple
inverted_norm = InvertedNormalize(vmin=10, vmax=100)
ax.plot_surface(..., cmap=<your colormap>, norm=inverted_norm)
Cela fonctionnera avec n'importe quelle palette de couleurs Matplotlib.