我想在我的轴实例(ax1)坐标系中的任意位置和任意尺寸绘制一个矩形,从左到右进行渐变颜色填充。
我的第一个想法是创建一个路径补丁并以某种方式将其填充设置为颜色渐变。但根据此帖子,没有办法做到这一点。
接下来我尝试使用颜色条。我使用 fig.add_axes([left, bottom, width, height])
创建了第二个轴实例
ax2并为其添加了一个颜色条。
ax2 = fig.add_axes([0, 0, width, height/8])
colors = [grad_start_color, grad_end_color]
index = [0.0, 1.0]
cm = LinearSegmentedColormap.from_list('my_colormap', zip(index, colors))
colorbar.ColorbarBase(ax2, cmap=cm, orientation='horizontal')
但是传递给
fig.add_axes()
的位置参数位于fig的坐标系中,与ax1的坐标系不匹配。
我该怎么做?
我一直在问自己类似的问题,并花了一些时间寻找答案,最后发现这可以很容易地通过
imshow
来完成:
from matplotlib import pyplot
pyplot.imshow([[0.,1.], [0.,1.]],
cmap = pyplot.cm.Greens,
interpolation = 'bicubic'
)
可以指定颜色图、使用什么插值等等。我发现非常有趣的另一件事是可以指定要使用颜色图的哪一部分。这是通过
vmin
和 vmax
: 完成的
pyplot.imshow([[64, 192], [64, 192]],
cmap = pyplot.cm.Greens,
interpolation = 'bicubic',
vmin = 0, vmax = 255
)
受到这个例子的启发
我选择了
X = [[0.,1.], [0.,1.]]
来使渐变从左到右变化。通过将数组设置为类似 X = [[0.,0.], [1.,1.]]
的值,您将获得从上到下的渐变。一般来说,可以指定每个角的颜色,其中 X = [[i00, i01],[i10, i11]]
、i00
、i01
、i10
和 i11
指定左上角、右上、左下和分别是右下角。增加 X
的大小显然可以为更具体的点设置颜色。
你解决过这个问题吗?我想要同样的东西,并使用here,
的坐标映射找到了答案 #Map axis to coordinate system
def maptodatacoords(ax, dat_coord):
tr1 = ax.transData.transform(dat_coord)
#create an inverse transversion from display to figure coordinates:
fig = ax.get_figure()
inv = fig.transFigure.inverted()
tr2 = inv.transform(tr1)
#left, bottom, width, height are obtained like this:
datco = [tr2[0,0], tr2[0,1], tr2[1,0]-tr2[0,0],tr2[1,1]-tr2[0,1]]
return datco
#Plot a new axis with a colorbar inside
def crect(ax,x,y,w,h,c,**kwargs):
xa, ya, wa, ha = maptodatacoords(ax, [(x,y),(x+w,y+h)])
fig = ax.get_figure()
axnew = fig.add_axes([xa, ya, wa, ha])
cp = mpl.colorbar.ColorbarBase(axnew, cmap=plt.get_cmap("Reds"),
orientation='vertical',
ticks=[],
**kwargs)
cp.outline.set_linewidth(0.)
plt.sca(ax)
希望这对将来需要类似功能的人有所帮助。我最终使用了补丁对象网格而不是。
像这样怎么样?
import matplotlib as mpl
import matplotlib.pyplot as plt
def cname2hex(cname):
colors = dict(mpl.colors.BASE_COLORS, **mpl.colors.CSS4_COLORS) # dictionary. key: names, values: hex codes
try:
hex = colors[cname]
return hex
except KeyError:
print(cname, ' is not registered as default colors by matplotlib!')
return None
def hex2rgb(hex, normalize=False):
h = hex.strip('#')
rgb = np.asarray(list(int(h[i:i + 2], 16) for i in (0, 2, 4)))
return rgb
def draw_rectangle_gradient(ax, x1, y1, width, height, color1='white', color2='blue', alpha1=0.0, alpha2=0.5, n=100):
# convert color names to rgb if rgb is not given as arguments
if not color1.startswith('#'):
color1 = cname2hex(color1)
if not color2.startswith('#'):
color2 = cname2hex(color2)
color1 = hex2rgb(color1) / 255. # np array
color2 = hex2rgb(color2) / 255. # np array
# Create an array of the linear gradient between the two colors
gradient_colors = []
for segment in np.linspace(0, width, n):
interp_color = [(1 - segment / width) * color1[j] + (segment / width) * color2[j] for j in range(3)]
interp_alpha = (1 - segment / width) * alpha1 + (segment / width) * alpha2
gradient_colors.append((*interp_color, interp_alpha))
for i, color in enumerate(gradient_colors):
ax.add_patch(plt.Rectangle((x1 + width/n * i, y1), width/n, height, color=color, linewidth=0, zorder=0))
return ax
# SAMPLE
fig, ax = plt.subplots(figsize=(4, 2))
ax.set_xlim(0, 100)
ax.set_ylim(0, 40)
draw_rectangle_gradient(ax, 0, 0, 30, 10, color1='blue', color2='orange', alpha1=1, alpha2=1)
draw_rectangle_gradient(ax, 40, 15, 40, 10, color1='white', color2='pink', alpha1=1, alpha2=1)
draw_rectangle_gradient(ax, 15, 30, 80, 5, color1='gold', color2='red', alpha1=0.0, alpha2=1)