我见过许多在 Matplotlib 中使用指定单一颜色的注释箭头的示例。我想知道是否可以根据颜色图设置颜色,以便指定颜色图的整个颜色范围显示在单个箭头上。我知道可以将箭头的颜色设置为颜色图中的单一颜色,但我希望有一个箭头显示给定颜色图的所有颜色。
下面显示了使用注释箭头的简单示例。在文档中,我没有找到任何指定颜色图的方法。如果我天真地指定颜色图,则会因无效的 RGBA 参数而收到错误。
import matplotlib.pyplot as plt
RdPu = plt.get_cmap('RdPu')
ax = plt.subplot(111)
ax.annotate("Test", xy=(0.2, 0.2), xycoords='data',
xytext=(0.8, 0.8), textcoords='data',
size=20, arrowprops=dict(color=RdPu),
)
plt.show()
Run Code Online (Sandbox Code Playgroud)
好吧,让我们制作《彩虹箭》吧。;-)
当然没有内置方法可以使用颜色渐变为箭头着色。相反,人们需要手动构建箭头。我可以想到两个选择。(1) 创建一个颜色渐变并用箭头的圆周路径剪辑它。(2) 制作一个LineCollection带有颜色渐变的图形,然后为其添加箭头。
下面是第二个选项:
import matplotlib.pyplot as plt
import matplotlib.transforms
import matplotlib.path
import numpy as np
from matplotlib.collections import LineCollection
def rainbowarrow(ax, start, end, cmap="viridis", n=50,lw=3):
cmap = plt.get_cmap(cmap,n)
# Arrow shaft: LineCollection
x = np.linspace(start[0],end[0],n)
y = np.linspace(start[1],end[1],n)
points = np.array([x,y]).T.reshape(-1,1,2)
segments = np.concatenate([points[:-1],points[1:]], axis=1)
lc = LineCollection(segments, cmap=cmap, linewidth=lw)
lc.set_array(np.linspace(0,1,n))
ax.add_collection(lc)
# Arrow head: Triangle
tricoords = [(0,-0.4),(0.5,0),(0,0.4),(0,-0.4)]
angle = np.arctan2(end[1]-start[1],end[0]-start[0])
rot = matplotlib.transforms.Affine2D().rotate(angle)
tricoords2 = rot.transform(tricoords)
tri = matplotlib.path.Path(tricoords2, closed=True)
ax.scatter(end[0],end[1], c=1, s=(2*lw)**2, marker=tri, cmap=cmap,vmin=0)
ax.autoscale_view()
fig,ax = plt.subplots()
ax.axis([0,5,0,4])
ax.set_aspect("equal")
rainbowarrow(ax, (3,3), (2,2.5), cmap="viridis", n=100,lw=3)
rainbowarrow(ax, (1,1), (1.5,1.5), cmap="jet", n=50,lw=7)
rainbowarrow(ax, (4,1.3), (2.7,1.0), cmap="RdYlBu", n=23,lw=5)
plt.show()
Run Code Online (Sandbox Code Playgroud)
注释箭头是单个箭头。因此,您需要单独绘制任意数量的箭头。为了让每个箭头获得颜色,您可以使用该arrowprops=dict(color="<some color>")参数。
要从颜色图中获取颜色,您可以使用值调用颜色图。这里箭头的长度可以作为编码为颜色的数量。
import matplotlib.pyplot as plt
import numpy as np
RdPu = plt.get_cmap('RdPu')
ax = plt.subplot(111)
ax.axis([-6,2,-4.5,3.2])
ax.set_aspect("equal")
X = np.linspace(0,1,17, endpoint=False)
Xt =np.sin(2.5*X+3)
Yt = 3*np.cos(2.6*X+3.4)
Xh = np.linspace(-0.5,-5,17)
Yh = -1.3*Xh-5
#Distance
D = np.sqrt((Xh-Xt)**2+(Yh-Yt)**2)
norm = plt.Normalize(D.min(), D.max())
for xt, yt, xh, yh, d in zip(Xt,Yt,Xh,Yh,D):
ax.annotate("Test", xy=(xh,yh), xycoords='data',
xytext=(xt,yt), textcoords='data',
size=10, arrowprops=dict(color=RdPu(norm(d))))
plt.show()
Run Code Online (Sandbox Code Playgroud)