Câu trả lời:
Các bản đồ màu tiêu chuẩn cũng có phiên bản đảo ngược. Họ có cùng tên với cách _r
giải quyết đến cùng. ( Tài liệu ở đây. )
Trong matplotlib, một bản đồ màu không phải là một danh sách, nhưng nó chứa danh sách các màu của nó như colormap.colors
. Và mô-đun matplotlib.colors
cung cấp một chức năng ListedColormap()
để tạo một bản đồ màu từ một danh sách. Vì vậy, bạn có thể đảo ngược bất kỳ bản đồ màu bằng cách làm
colormap_r = ListedColormap(colormap.colors[::-1])
ListedColormap
s (nghĩa là rời rạc, thay vì nội suy) có colors
thuộc tính. Đảo ngược LinearSegmentedColormaps
phức tạp hơn một chút. (Bạn cần đảo ngược mọi mục trong _segmentdata
dict.)
LinearSegmentedColormaps
, tôi chỉ làm điều này cho một số màu. Đây là một IPython Notebook về nó.
Giải pháp khá đơn giản. Giả sử bạn muốn sử dụng lược đồ màu "mùa thu". Phiên bản tiêu chuẩn:
cmap = matplotlib.cm.autumn
Để đảo ngược phổ màu colormap, hãy sử dụng hàm get_cmap () và nối '_r' vào tiêu đề colormap như thế này:
cmap_reversed = matplotlib.cm.get_cmap('autumn_r')
Vì LinearSegmentedColormaps
dựa trên một từ điển màu đỏ, xanh lá cây và xanh dương, nên cần phải đảo ngược từng mục:
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
Xem nó hoạt động:
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')
BIÊN TẬP
Tôi không nhận được bình luận của user3445587. Nó hoạt động tốt trên colormap cầu vồng:
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')
Nhưng nó đặc biệt hoạt động tốt cho các bản đồ được khai báo tùy chỉnh, vì không có mặc định _r
cho bản đồ màu được khai báo tùy chỉnh. Ví dụ sau được lấy từ 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')
Kể từ Matplotlib 2.0, có một reversed()
phương thức cho ListedColormap
và LinearSegmentedColorMap
các đối tượng, vì vậy bạn chỉ có thể làm
cmap_reversed = cmap.reversed()
Đây là tài liệu.
Có hai loại linearSegmentedColormaps. Trong một số, _seributiondata được đưa ra một cách rõ ràng, ví dụ, cho máy bay phản lực:
>>> 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))}
Đối với cầu vồng, _seributiondata được đưa ra như sau:
>>> cm.rainbow._segmentdata
{'blue': <function <lambda> at 0x7fac32ac2b70>, 'red': <function <lambda> at 0x7fac32ac7840>, 'green': <function <lambda> at 0x7fac32ac2d08>}
Chúng ta có thể tìm thấy các hàm trong nguồn matplotlib, nơi chúng được đưa ra là
_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)
}
Mọi thứ bạn muốn đã được thực hiện trong matplotlib, chỉ cần gọi cm.revcmap, đảo ngược cả hai loại phân đoạn, vì vậy
cm.revcmap(cm.rainbow._segmentdata)
nên thực hiện công việc - bạn chỉ cần tạo một linearSegmentData mới từ đó. Trong revcmap, việc đảo ngược chức năng dựa trên SegmentData được thực hiện với
def _reverser(f):
def freversed(x):
return f(1 - x)
return freversed
trong khi các danh sách khác được đảo ngược như bình thường
valnew = [(1.0 - x, y1, y0) for x, y0, y1 in reversed(val)]
Vì vậy, thực sự tất cả những gì bạn muốn, là
def reverse_colourmap(cmap, name = 'my_cmap_r'):
return mpl.colors.LinearSegmentedColormap(name, cm.revcmap(cmap._segmentdata))
Không có cách dựng sẵn (chưa) đảo ngược các bản đồ màu tùy ý, nhưng một giải pháp đơn giản là thực sự không sửa đổi thanh màu mà tạo ra một đối tượng Bình thường hóa đảo ngược:
from matplotlib.colors import Normalize
class InvertedNormalize(Normalize):
def __call__(self, *args, **kwargs):
return 1 - super(InvertedNormalize, self).__call__(*args, **kwargs)
Sau đó, bạn có thể sử dụng plot_surface
chức năng này với và các hàm vẽ đồ thị Matplotlib khác bằng cách thực hiện, ví dụ:
inverted_norm = InvertedNormalize(vmin=10, vmax=100)
ax.plot_surface(..., cmap=<your colormap>, norm=inverted_norm)
Điều này sẽ làm việc với bất kỳ colormap Matplotlib.