Python 使用matplotlib在对数刻度上居中标注

Python 使用matplotlib在对数刻度上居中标注,python,matplotlib,Python,Matplotlib,我有以下情况,不言自明;请参见下面粘贴的图和工作示例 我想知道如何在维度线中间排列文本。 import numpy as np import matplotlib.pyplot as plt # Dimension line def annotation_line(ax, xmin, xmax, y, text, ytext=0, linecolor='black', linewidth=1, fontsize=12): ax.annotate('', xy=(xmin, y), xy

我有以下情况,不言自明;请参见下面粘贴的图和工作示例

我想知道如何在维度线中间排列文本。

import numpy as np
import matplotlib.pyplot as plt

# Dimension line
def annotation_line(ax, xmin, xmax, y, text, ytext=0, linecolor='black', linewidth=1, fontsize=12):
    ax.annotate('', xy=(xmin, y), xytext=(xmax, y), xycoords='data', textcoords='data', arrowprops={'arrowstyle': '|-|', 'color':linecolor, 'linewidth':linewidth})
    ax.annotate('', xy=(xmin, y), xytext=(xmax, y), xycoords='data', textcoords='data', arrowprops={'arrowstyle': '<->', 'color':linecolor, 'linewidth':linewidth})
    xcenter = xmin + (xmax - xmin) / 2
    if ytext==0:
        ytext = y + ( ax.get_ylim()[1] - ax.get_ylim()[0] ) / 20
    ax.annotate(text, xy=(xcenter, ytext), ha='center', va='bottom', fontsize=fontsize)

# Toy data
N = 8
y = np.zeros(N)
x1 = np.linspace(1, 1000, N, endpoint=True)

fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x1, y, 'o')
annotation_line(ax=ax, text='TEXT 1', xmin=1, xmax=100, y=0.01, ytext=0, linewidth=1, linecolor='gray', fontsize=12)
ax.set_xscale('log')
将numpy导入为np
将matplotlib.pyplot作为plt导入
#尺寸线
def注释_行(ax,xmin,xmax,y,text,ytext=0,linecolor='black',linewidth=1,fontsize=12):
ax.annotation(“”,xy=(xmin,y),xytext=(xmax,y),xycoords='data',textcoords='data',arrowprops={'arrowstyle':'|-|','color':linecolor,'linewidth':linewidth})
ax.annotation(“”,xy=(xmin,y),xytext=(xmax,y),xycoords='data',textcoords='data',arrowprops={'arrowstyle':“”,'color':linecolor,'linewidth':linewidth})
xcenter=xmin+(xmax-xmin)/2
如果ytext==0:
ytext=y+(ax.get_ylim()[1]-ax.get_ylim()[0])/20
ax.annotate(text,xy=(xcenter,ytext),ha='center',va='bottom',fontsize=fontsize)
#玩具数据
N=8
y=np.零(N)
x1=np.linspace(1,1000,N,端点=True)
图,ax=plt.子批次(图尺寸=(10,6))
轴图(x1,y,'o')
注释线(ax=ax,text=text 1',xmin=1,xmax=100,y=0.01,ytext=0,线宽=1,linecolor=gray,fontsize=12)
ax.setxscale('log'))

简单的解决方案是按照@JohanC的建议,以对数坐标计算中点

另一种解决方案是使用箭头的坐标来找到它的中点。然而,这种方法也有缺点。首先,需要在中间步骤显式绘制地物,因为坐标仅在绘制时有效;其次,需要在绘制注释之前设置对数比例。另一方面,不管轴的缩放比例如何,代码都可以工作

import numpy as np
import matplotlib.pyplot as plt

# Dimension line
def annotation_line(ax, xmin, xmax, y, text, ytext=0, linecolor='black', linewidth=1, fontsize=12):
    an = ax.annotate('', xy=(xmin, y), xytext=(xmax, y), xycoords='data', textcoords='data', arrowprops={'arrowstyle': '|-|', 'color':linecolor, 'linewidth':linewidth})
    ax.annotate('', xy=(xmin, y), xytext=(xmax, y), xycoords='data', textcoords='data', arrowprops={'arrowstyle': '<->', 'color':linecolor, 'linewidth':linewidth})
    ax.figure.canvas.draw() # draw to get actual coordinates
    p = an.arrow_patch.get_path().transformed(ax.transAxes.inverted())
    xmin, xmax = np.min(p.vertices[:,0]),np.max(p.vertices[:,0])
    xcenter = xmin+(xmax-xmin)/2
    if ytext==0:
        ytext = y + ( ax.get_ylim()[1] - ax.get_ylim()[0] ) / 20
    ax.annotate(text, xy=(xcenter, ytext), xycoords=('axes fraction','data'), ha='center', va='bottom', fontsize=fontsize)
    return an

# Toy data
N = 8
y = np.zeros(N)
x1 = np.linspace(1, 1000, N, endpoint=True)

fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x1, y, 'o')
ax.set_xscale('log') # must do before the call to annotation_line
an = annotation_line(ax=ax, text='TEXT 1', xmin=1, xmax=100, y=0.01, ytext=0, linewidth=1, linecolor='gray', fontsize=12)
将numpy导入为np
将matplotlib.pyplot作为plt导入
#尺寸线
def注释_行(ax,xmin,xmax,y,text,ytext=0,linecolor='black',linewidth=1,fontsize=12):
an=ax.annotation(“”,xy=(xmin,y),xytext=(xmax,y),xycoords='data',textcoords='data',arrowprops={'arrowstyle':'-|','color':linecolor,'linewidth':linewidth})
ax.annotation(“”,xy=(xmin,y),xytext=(xmax,y),xycoords='data',textcoords='data',arrowprops={'arrowstyle':“”,'color':linecolor,'linewidth':linewidth})
ax.figure.canvas.draw()#绘制以获取实际坐标
p=一个.arrow\u patch.get\u path().transformed(ax.transAxes.inversed())
xmin,xmax=np.min(p.vertices[:,0]),np.max(p.vertices[:,0])
xcenter=xmin+(xmax-xmin)/2
如果ytext==0:
ytext=y+(ax.get_ylim()[1]-ax.get_ylim()[0])/20
ax.annotate(text,xy=(xcenter,ytext),xycoords=('axes fraction','data'),ha='center',va='bottom',fontsize=fontsize)
归还
#玩具数据
N=8
y=np.零(N)
x1=np.linspace(1,1000,N,端点=True)
图,ax=plt.子批次(图尺寸=(10,6))
轴图(x1,y,'o')
ax.setxscale('log')#必须在调用注释行之前执行
an=annotation_行(ax=ax,text=text 1',xmin=1,xmax=100,y=0.01,ytext=0,线宽=1,linecolor='gray',fontsize=12)

您可以计算logspace中的中心,然后取指数:
xcenter=10**((np.log10(xmin)+np.log10(xmax))/2)
。请注意,这相当于
xcenter=(xmin*xmax)**.5