如何使用Matplotlib的fig.transFigure在ylabel旁及画布任意位置绘制Patch图形
我创建了一组点序列,希望将其转换为Patch对象,目标是把该Patch绘制在y轴标签左侧(如下图红色部分所示),或是画布的任意其他位置。
虽然使用Gridspec也可以实现该需求,但我更希望通过Patch来完成。
import matplotlib.pyplot as plt import numpy as np plt.figure() npoints = 100 td = np.linspace(np.pi*3/4, np.pi*5/4, npoints) xd = np.cos(td) yd = np.sin(td) plt.plot(xd,yd)

编辑1
目前我已经可以成功创建Patch对象,仅需将其移动到坐标轴外侧即可,可通过平移或缩放操作实现。我确认实现该需求的核心参考为Matplotlib官方的变换系统教程,更具体来说,解决方案需要用到fig.transFigure。对应代码如下:
import matplotlib.pyplot as plt import numpy as np import matplotlib.path as mpath import matplotlib.patches as mpatches npoints = 100 td = np.linspace(np.pi*3/4, np.pi*5/4, npoints) xd = np.cos(td) yd = np.sin(td) fig, ax = plt.subplots() ax.axis([-2, 0, -1, 1]) verts=np.c_[xd,yd] codes = np.ones(len(xd))*2 # 除第一个点外所有点都为Path.LINETO类型 codes[0] = 1 # 仅第一个点为Path.MOVETO类型 path1 = mpath.Path(verts, codes) patch = mpatches.PathPatch(path1, facecolor='none') ax.add_patch(patch)
运行结果:
编辑2:接近完成!
为使用取值范围在[0,1]之间的Figure坐标,我对定义路径的点做了归一化处理。我没有使用向坐标轴添加Patch的ax.add_patch()方法,而是使用fig.add_artist()将Patch添加到画布上,覆盖在坐标轴上方。对应代码如下:
import matplotlib.pyplot as plt import numpy as np import matplotlib.path as mpath import matplotlib.patches as mpatches # 归一化数据 def normalize(x): return (x - min(x)) / (max(x) - min(x)) npoints = 100 td = np.linspace(np.pi*3/4, np.pi*5/4, npoints) xd = np.cos(td) yd = np.sin(td) xd = normalize(xd) yd = normalize(yd) fig, ax = plt.subplots() ax.axis([-2, 2, -1, 1]) verts=np.c_[xd,yd] codes = np.ones(len(xd))*2 # 除第一个点外所有点都为Path.LINETO类型 codes[0] = 1 # 仅第一个点为Path.MOVETO类型 path1 = mpath.Path(verts, codes) patch1 = mpatches.PathPatch(path1, facecolor='none') ax.add_patch(patch1) patch2 = mpatches.PathPatch(path1, fc='none', ec='red', transform=fig.transFigure) fig.add_artist(patch2)
目前的运行结果如下:
接下来只需要使用Affine2D对Patch进行缩放和平移即可。
编辑3:完成!
最终我成功实现了需求,由于我暂时没搞清楚scale()和translate()参数使用的坐标系,所以通过试错法确定了参数值,目前还希望能获取到精确的y轴中心(画布坐标中的0.5位置)来优化实现。完整代码如下:
import numpy as np import matplotlib.path as mpath import matplotlib.patches as mpatches # 归一化数据 def normalize(x): return (x - min(x)) / (max(x) - min(x)) npoints = 100 td = np.linspace(np.pi*3/4, np.pi*5/4, npoints) xd = np.cos(td) yd = np.sin(td) xd = normalize(xd) yd = normalize(yd) fig, ax = plt.subplots() ax.axis([-2, 2, -1, 1]) verts=np.c_[xd,yd] codes = np.ones(len(xd))*2 # 除第一个点外所有点都为Path.LINETO类型 codes[0] = 1 # 仅第一个点为Path.MOVETO类型 path1 = mpath.Path(verts, codes) patch1 = mpatches.PathPatch(path1, fc='none', ec='green') ax.add_patch(patch1) # 在坐标轴内部绘制 patch2 = mpatches.PathPatch(path1, fc='none', ec='C0', transform=fig.transFigure) fig.add_artist(patch2) # 在画布层级绘制,该方法可行 import matplotlib.transforms as mtransforms tt = fig.transFigure + mtransforms.Affine2D().scale(0.02, 0.8).translate(10,45) patch3 = mpatches.PathPatch(path1, fc='none', ec='red', transform=tt) fig.add_artist(patch3)
最终运行结果如下:
内容的提问来源于stack exchange,提问作者Pedro
相关产品推荐
相关产品推荐

