pyplot 和半对数刻度:如何使用变换绘制圆

mar*_*tin 2 geometry logarithm matplotlib

我想在用 pyplot 绘制的图中有一个圆,但我需要在 x 轴上使用对数刻度。

我愿意:

ax = plt.axes()

point1 = plt.Circle((x,y), x, color='r',clip_on=False, 
                    transform = ax.transAxes, alpha = .5)

plt.xscale('log')

current_fig = plt.gcf()

current_fig.gca().add_artist(point1)
Run Code Online (Sandbox Code Playgroud)

如您所见,我希望圆的半径等于 x 坐标。

我的问题是,如果我使用,就像这里写的那样transAxes,那么我得到的圆实际上是一个圆(否则它在x上拉伸,看起来像一个切成两半的椭圆),但x坐标是0。如果,另一方面,我使用transData代替transAxes,然后我得到了 x 坐标的正确值,但圆再次被拉伸并切成两半。

我不太介意拉伸,但我不喜欢切割,我希望它至少是一个完整的椭圆。

知道如何获得我想要的东西吗?

ali*_*i_m 5

也许最简单的方法就是使用绘图标记而不是Circle. 例如:

ax.plot(x,y,marker='o',ms=x*5,mfc=(1.,0.,0.,0.5),mec='None')
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个始终看起来“圆形”的圆,并且以正确的 x,y 坐标为中心,尽管其大小与 x 和 y 比例无关。如果您只关心中心位置,那么您可以随意调整,ms=直到看起来合适为止。

更通用的方法是为圆构建一个新的复合变换 - 您应该查看本关于变换的教程。基本上,从图形到数据空间的转换是这样构造的:

transData = transScale + (transLimits + transAxes)
Run Code Online (Sandbox Code Playgroud)

其中transScale处理数据的任何非线性(例如对数)缩放,transLimits将数据的 x 和 y 限制映射到轴的单位空间,并将transAxes轴边界框的角映射到显示空间。

您希望保持圆看起来像圆/椭圆(即,不根据 x 轴的对数缩放来扭曲它),但您仍然希望将其转换到数据坐标中的正确中心位置。为此,您可以构建缩放翻译,然后将其与transLimits和结合起来transAxes

from matplotlib.transforms import ScaledTranslation

ax = plt.axes(xscale='log')
x,y = 10,0
ax.set_ylim(-11,11)
ax.set_xlim(1E-11,1E11)

# use the axis scale tform to figure out how far to translate 
circ_offset = ScaledTranslation(x,y,ax.transScale)

# construct the composite tform
circ_tform = circ_offset + ax.transLimits + ax.transAxes

# create the circle centred on the origin, apply the composite tform
circ = plt.Circle((0,0),x,color='r',alpha=0.5,transform=circ_tform)
ax.add_artist(circ)
plt.show()
Run Code Online (Sandbox Code Playgroud)

显然,x 轴的缩放会有点奇怪和任意 - 您需要尝试构建转换的方式,以便准确获得您想要的结果。