Python 如何在Matplotlib中使用图形内有文本的cutom标记? 背景

Python 如何在Matplotlib中使用图形内有文本的cutom标记? 背景,python,matplotlib,text,latex,markers,Python,Matplotlib,Text,Latex,Markers,在Matplotlib中,我们可以使用mathtext作为标记,使用$$() 问题: 有没有办法把这篇文章放在一个圆形或长方形的盒子里,或者其他不同的形状?与所示的注册符号类似 我想在绘图上使用此标记,如下所示: 此绘图中使用了文本“$T$”,我希望文本包含在圆形或矩形中 解决方案 正如在回答的评论中所建议的那样,我在文本标记之前绘制了一个大一点的正方形标记。这解决了问题。 最终数字如下所示: 编辑:最简单的方法是简单地将补丁放置在与标记相同的位置,使其成为所需的“帧”。只需确保它们具有较低的

在Matplotlib中,我们可以使用mathtext作为标记,使用
$$()

问题: 有没有办法把这篇文章放在一个圆形或长方形的盒子里,或者其他不同的形状?与所示的注册符号类似

我想在绘图上使用此标记,如下所示:

此绘图中使用了文本“$T$”,我希望文本包含在圆形或矩形中

解决方案 正如在回答的评论中所建议的那样,我在文本标记之前绘制了一个大一点的正方形标记。这解决了问题。 最终数字如下所示:

编辑:最简单的方法是简单地将补丁放置在与标记相同的位置,使其成为所需的“帧”。只需确保它们具有较低的
zorder
,这样它们就不会覆盖数据点

更复杂的方法如下:

你可以做补丁。下面是我用来制作自定义问号的示例:

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.markers as m

fig, ax = plt.subplots()
lim = -5.8, 5.7
ax.set(xlim = lim, ylim = lim)

marker_obj = m.MarkerStyle('$?$') #Here you place your letter
path = marker_obj.get_path().transformed(marker_obj.get_transform())

path._vertices = np.array(path._vertices)*8 #To make it larger
patch = mpl.patches.PathPatch(path, facecolor="cornflowerblue", lw=2)
ax.add_patch(patch)

def translate_verts(patch, i=0, j=0, z=None):
    patch._path._vertices = patch._path._vertices + [i, j]

def rescale_verts(patch, factor = 1):
    patch._path._vertices = patch._path._vertices * factor

#translate_verts(patch, i=-0.7, j=-0.1)

circ = mpl.patches.Arc([0,0], 11, 11,
                       angle=0.0, theta1=0.0, theta2=360.0,
                       lw=10, facecolor = "cornflowerblue",
                       edgecolor = "black")
ax.add_patch(circ)#One of the rings around the questionmark

circ = mpl.patches.Arc([0,0], 10.5, 10.5,
                       angle=0.0, theta1=0.0, theta2=360.0,
                       lw=10, edgecolor = "cornflowerblue")
ax.add_patch(circ)#Another one of the rings around the question mark

circ = mpl.patches.Arc([0,0], 10, 10,
                       angle=0.0, theta1=0.0, theta2=360.0,
                       lw=10, edgecolor = "black")
ax.add_patch(circ)



if __name__ == "__main__":
    ax.axis("off")
    ax.set_position([0, 0, 1, 1])
    fig.canvas.draw()
    #plt.savefig("question.png", dpi=40)
    plt.show()

编辑,第二个答案: 创建由其他修补程序组成的自定义修补程序:

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.art3d as art3d


class PlanetPatch(mpl.patches.Circle):
    """
        This class combines many patches to make a custom patch
        The best way to reproduce such a thing is to read the
        source code for all patches you plan on combining.
        Also make use of ratios as often as possible to maintain
        proportionality between patches of different sizes"""
    cz = 0
    def __init__(self, xy, radius,
                 color = None, linewidth = 20,
                 edgecolor = "black", ringcolor = "white",
                 *args, **kwargs):
        ratio = radius/6
        mpl.patches.Circle.__init__(self, xy, radius,
                                    linewidth = linewidth*ratio,
                                    color = color,
                                    zorder = PlanetPatch.cz,
                                    *args, **kwargs)
        self.set_edgecolor(edgecolor)
        xy_ringcontour = np.array(xy)+[0, radius*-0.2/6]
        self.xy_ringcontour = xy_ringcontour - np.array(xy)
        self.ring_contour = mpl.patches.Arc(xy_ringcontour,
                                15*radius/6, 4*radius/6,
                                angle =10, theta1 = 165,
                                theta2 = 14.5,
                                fill = False, 
                                linewidth = 65*linewidth*ratio/20,
                                zorder = 1+PlanetPatch.cz)

        self.ring_inner = mpl.patches.Arc(xy_ringcontour,
                                 15*radius/6, 4*radius/6,
                                 angle = 10, theta1 = 165 ,
                                 theta2 = 14.5,fill = False,
                                 linewidth = 36*linewidth*ratio/20,
                                 zorder = 2+PlanetPatch.cz)

        self.top = mpl.patches.Wedge([0,0], radius, theta1 = 8,
                                     theta2 = 192,
                                     zorder=3+PlanetPatch.cz)
        self.xy_init = xy
        self.top._path._vertices=self.top._path._vertices+xy

        self.ring_contour._edgecolor = self._edgecolor
        self.ring_inner.set_edgecolor(ringcolor)
        self.top._facecolor = self._facecolor

    def add_to_ax(self, ax):
        ax.add_patch(self)
        ax.add_patch(self.ring_contour)
        ax.add_patch(self.ring_inner)
        ax.add_patch(self.top)


    def translate(self, dx, dy):
        self._center = self.center + [dx,dy]
        self.ring_inner._center = self.ring_inner._center +[dx, dy]
        self.ring_contour._center = self.ring_contour._center + [dx,dy]
        self.top._path._vertices = self.top._path._vertices + [dx,dy]

    def set_xy(self, new_xy):
        """As you can see all patches have different ways
            to have their positions updated"""
        new_xy = np.array(new_xy)
        self._center = new_xy
        self.ring_inner._center = self.xy_ringcontour + new_xy
        self.ring_contour._center = self.xy_ringcontour + new_xy
        self.top._path._vertices += new_xy - self.xy_init 

fig  = plt.figure(figsize=(6, 6))
ax = fig.add_subplot()
lim = -8.5, 8.6
ax.set(xlim = lim, ylim = lim,
       facecolor = "black")
planets = []
colors = mpl.colors.cnames
colors = [c for c in colors]
for x in range(100):
    xy = np.random.randint(-7, 7, 2)
    r = np.random.randint(1, 15)/30
    color = np.random.choice(colors)
    planet = PlanetPatch(xy, r, linewidth = 20,
                         color = color,
                         ringcolor = np.random.choice(colors),
                         edgecolor = np.random.choice(colors))
    planet.add_to_ax(ax)
    planets.append(planet)


fig.canvas.draw()
#plt.savefig("planet.png", dpi=10)
plt.show()


然后事情变得更加复杂,因为您必须将此自定义标记创建为补丁。因为每个面片的位置、边、中心和顶点的定义都有点不同,所以这里的事情变得很棘手。如果您真的想这样做,最好阅读您计划使用的补丁程序的源代码。我还将添加另一个答案,并举例说明我创建了一个自定义补丁。或者,您可以简单地使用lower
zorder
将矩形放置在与“T”相同的位置,以确保它们位于“T”的下方。