Jawaban:
Colormaps standar juga semuanya memiliki versi terbalik. Mereka memiliki nama yang sama dengan _rditempel sampai akhir. ( Dokumentasi di sini. )
Dalam matplotlib peta warna bukan daftar, tetapi berisi daftar warnanya sebagai colormap.colors. Dan modul matplotlib.colorsmenyediakan fungsi ListedColormap()untuk menghasilkan peta warna dari daftar. Jadi, Anda dapat membalikkan peta warna apa pun dengan melakukan
colormap_r = ListedColormap(colormap.colors[::-1])
ListedColormaps (yaitu diskrit, alih-alih diinterpolasi) yang memiliki colorsatribut. Membalik LinearSegmentedColormapssedikit lebih rumit. (Anda harus membalikkan setiap item dalam _segmentdatadikt.)
LinearSegmentedColormaps, saya hanya melakukan ini untuk beberapa colourmaps. Inilah Notebook IPython tentang hal itu.
Solusinya cukup mudah. Misalkan Anda ingin menggunakan skema colormap "musim gugur". Versi standar:
cmap = matplotlib.cm.autumn
Untuk membalikkan spektrum warna colormap, gunakan fungsi get_cmap () dan tambahkan '_r' ke judul colormap seperti ini:
cmap_reversed = matplotlib.cm.get_cmap('autumn_r')
Karena LinearSegmentedColormapsdidasarkan pada kamus merah, hijau dan biru, Anda perlu membalik setiap item:
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
Lihat itu berfungsi:
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')
EDIT
Saya tidak mendapatkan komentar dari user3445587. Ini berfungsi dengan baik pada rainbow colormap:
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')
Tapi itu terutama berfungsi baik untuk colormaps yang dinyatakan kustom, karena tidak ada default _runtuk colormaps dinyatakan kustom. Contoh berikut diambil dari 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')
Pada Matplotlib 2.0, ada reversed()metode untuk ListedColormapdan LinearSegmentedColorMapobjek, jadi Anda bisa melakukannya
cmap_reversed = cmap.reversed()
Ini dokumentasinya.
Ada dua jenis LinearSegmentedColormaps. Dalam beberapa, _segmentdata diberikan secara eksplisit, misalnya, untuk 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))}
Untuk pelangi, _segmentdata diberikan sebagai berikut:
>>> cm.rainbow._segmentdata
{'blue': <function <lambda> at 0x7fac32ac2b70>, 'red': <function <lambda> at 0x7fac32ac7840>, 'green': <function <lambda> at 0x7fac32ac2d08>}
Kita dapat menemukan fungsi-fungsi di sumber matplotlib, di mana mereka diberikan sebagai
_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)
}
Semua yang Anda inginkan sudah dilakukan di matplotlib, panggil saja cm.revcmap, yang membalikkan kedua jenis segmentdata, jadi
cm.revcmap(cm.rainbow._segmentdata)
harus melakukan pekerjaan - Anda cukup membuat LinearSegmentData baru dari itu. Di revcmap, pembalikan fungsi berdasarkan SegmentData dilakukan dengan
def _reverser(f):
def freversed(x):
return f(1 - x)
return freversed
sementara daftar lainnya dibalik seperti biasa
valnew = [(1.0 - x, y1, y0) for x, y0, y1 in reversed(val)]
Jadi sebenarnya semua yang Anda inginkan, adalah
def reverse_colourmap(cmap, name = 'my_cmap_r'):
return mpl.colors.LinearSegmentedColormap(name, cm.revcmap(cmap._segmentdata))
Tidak ada cara bawaan untuk membalikkan colormaps yang sewenang-wenang, tetapi satu solusi sederhana adalah dengan benar-benar tidak memodifikasi colorbar tetapi untuk membuat objek Normalisasi pembalik:
from matplotlib.colors import Normalize
class InvertedNormalize(Normalize):
def __call__(self, *args, **kwargs):
return 1 - super(InvertedNormalize, self).__call__(*args, **kwargs)
Anda kemudian dapat menggunakan ini dengan plot_surfacedan fungsi merencanakan Matplotlib lainnya dengan melakukan mis
inverted_norm = InvertedNormalize(vmin=10, vmax=100)
ax.plot_surface(..., cmap=<your colormap>, norm=inverted_norm)
Ini akan bekerja dengan colormap Matplotlib.