Antworten:
Die Standard-Farbkarten haben auch alle umgekehrte Versionen. Sie haben die gleichen Namen mit _rbis zum Ende angeheftet. ( Dokumentation hier. )
In matplotlib ist eine Farbkarte keine Liste, sondern enthält die Liste ihrer Farben als colormap.colors. Das Modul matplotlib.colorsbietet eine Funktion ListedColormap()zum Generieren einer Farbkarte aus einer Liste. Sie können also jede Farbkarte umkehren, indem Sie dies tun
colormap_r = ListedColormap(colormap.colors[::-1])
ListedColormaps (dh diskret und nicht interpoliert) haben ein colorsAttribut. Das Umkehren LinearSegmentedColormapsist etwas komplexer. (Sie müssen jeden Punkt im _segmentdataDiktat umkehren .)
LinearSegmentedColormapsich dies nur für einige Farbkarten getan. Hier ist ein IPython-Notizbuch darüber.
Die Lösung ist ziemlich einfach. Angenommen, Sie möchten das Farbkartenschema "Herbst" verwenden. Die Standardversion:
cmap = matplotlib.cm.autumn
Um das Farbspektrum der Farbkarte umzukehren, verwenden Sie die Funktion get_cmap () und hängen Sie '_r' wie folgt an den Titel der Farbkarte an:
cmap_reversed = matplotlib.cm.get_cmap('autumn_r')
Da a LinearSegmentedColormapsauf einem Wörterbuch aus Rot, Grün und Blau basiert, muss jedes Element umgekehrt werden:
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
Sehen Sie, dass es funktioniert:
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')
BEARBEITEN
Ich bekomme den Kommentar von user3445587 nicht. Es funktioniert gut auf der Regenbogen-Farbkarte:
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')
Es funktioniert jedoch besonders gut für benutzerdefinierte deklarierte Farbkarten, da es keine Standardeinstellung _rfür benutzerdefinierte deklarierte Farbkarten gibt. Das folgende Beispiel stammt von 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')
Ab Matplotlib 2.0 gibt es eine reversed()Methode für ListedColormapund LinearSegmentedColorMapObjekte, sodass Sie dies einfach tun können
cmap_reversed = cmap.reversed()
Hier ist die Dokumentation.
Es gibt zwei Arten von LinearSegmentedColormaps. In einigen Fällen werden die _segmentdata explizit angegeben, z. B. für 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))}
Für den Regenbogen werden _segmentdata wie folgt angegeben:
>>> cm.rainbow._segmentdata
{'blue': <function <lambda> at 0x7fac32ac2b70>, 'red': <function <lambda> at 0x7fac32ac7840>, 'green': <function <lambda> at 0x7fac32ac2d08>}
Wir können die Funktionen in der Quelle von matplotlib finden, wo sie als angegeben sind
_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)
}
Alles, was Sie wollen, ist bereits in matplotlib erledigt. Rufen Sie einfach cm.revcmap auf, wodurch beide Arten von Segmentdaten umgekehrt werden
cm.revcmap(cm.rainbow._segmentdata)
sollte den Job machen - Sie können einfach ein neues LinearSegmentData daraus erstellen. In revcmap erfolgt die Umkehrung funktionsbasierter SegmentData mit
def _reverser(f):
def freversed(x):
return f(1 - x)
return freversed
während die anderen Listen wie gewohnt umgekehrt werden
valnew = [(1.0 - x, y1, y0) for x, y0, y1 in reversed(val)]
Also eigentlich ist das Ganze was du willst
def reverse_colourmap(cmap, name = 'my_cmap_r'):
return mpl.colors.LinearSegmentedColormap(name, cm.revcmap(cmap._segmentdata))
Es gibt (noch) keine integrierte Möglichkeit, beliebige Farbkarten umzukehren, aber eine einfache Lösung besteht darin, die Farbleiste nicht zu ändern, sondern ein invertierendes Normalisierungsobjekt zu erstellen:
from matplotlib.colors import Normalize
class InvertedNormalize(Normalize):
def __call__(self, *args, **kwargs):
return 1 - super(InvertedNormalize, self).__call__(*args, **kwargs)
Sie können dies dann mit plot_surfaceund anderen Matplotlib-Plotfunktionen verwenden, indem Sie z
inverted_norm = InvertedNormalize(vmin=10, vmax=100)
ax.plot_surface(..., cmap=<your colormap>, norm=inverted_norm)
Dies funktioniert mit jeder Matplotlib-Farbkarte.