Matplotlib:绘制椭圆以在对数刻度上进行注释

问题描述

使用 matplotlib,我想在符号学图上绘制一个椭圆。

考虑下图和相关代码

import numpy as np
import scipy.io
from matplotlib import pyplot as plt
from matplotlib.patches import Ellipse

plt.figure(figsize=[3.3,3.3])
plt.rcParams.update({'font.size': 8,'text.usetex': True})

plt.semilogy([1,2,3,4],[4,8,12,16],color='r')
plt.semilogy([1,[2,4,6,8],[12,15,20,27],color='b')

ax = plt.gca()
plt.annotate('blue curve',xy=(1.5,22.5),xytext=(1.5,ha='center',va='center')
plt.annotate('',xy=(2,15),22),arrowprops=dict(width=0.1,headwidth=2,headlength=2,color='grey'))
plt.annotate('red curves',xy=(2.5,xytext=(2.5,xy=(3,color='grey'))
ax.add_patch(Ellipse(xy=(3,10),width=0.2,height=10,color="grey",fill=False,lw=1,zorder=5))

plt.grid()
plt.xlabel('x')
plt.ylabel('y')

plt.savefig('filename.pdf',format='pdf')

plt.show()

enter image description here

如您所见,椭圆由于 y 轴上的对数刻度而变形。我试图在自然尺度上重叠一个新轴,我也试图从现有问题(例如 this one)中获得灵感:两种方法都不起作用,因为不幸的是,我对 Python 的了解接近于零.

是否有一种简单的方法可以在不大量修改现有代码的情况下绘制(未变形的)椭圆?

解决方法

answer in the Q&A you linked to 确实为您的问题提供了解决方案。您想使用那里记录的复合转换。我已经修改了你脚本的相关部分来做到这一点。

注意:使用此方法需要进行的一项更改是椭圆的高度以轴坐标(我使用高度为 0.5)而不是像您那样以数据坐标 (height=10) 给出。可能有一种方法可以通过另一个变换在数据坐标中给出它,但我没有在这里包含它。我还稍微移动了椭圆中心,使其以两条红线为中心。

from matplotlib.transforms import ScaledTranslation

# Ellipse centre coordinates
x,y = 3,8

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

# construct the composite tform
ell_tform = ell_offset + ax.transLimits + ax.transAxes

# Create the ellipse centred on the origin,apply the composite tform
ax.add_patch(Ellipse(xy=(0,0),width=0.2,height=0.5,color="grey",fill=False,lw=1,zorder=5,transform=ell_tform))

enter image description here