Matplotlib,添加多行文本.添加可以跟随曲线的文本

dus*_*tin 5 python curve text matplotlib

我已经将文本添加到绘图中,在每行中编码,然后调整它看起来像样,增加或减少宽度,或更改位置.但是,有没有办法让Python知道你想要文本的位置以及你想要它的设置方式?然后我可以添加文本,Python将计算出细节.

例如,看看下面的图片:

在此输入图像描述

在图中,我在左上角有3行文字,在图的线上有一行.

我不得不调整3条线以获得合适的间距.这不是一项艰巨的任务,但如果我能说这里是文本,这里就是位置,那将很容易,然后Python以适当的间距堆叠它.

对于单独的线路,我不得不进行调整,因此它不在线上并降低线路.对于这种情况,有可能告诉python我想在情节上方的文字和80%下线?

我习惯于LaTeX在没有硬编码坐标的情况下进行调整的地方.优点是

(1) if I want to change the location, I can change the percentage shift and not the coordinate.

(2) if the line is angled, the text will adjust to the line.
Run Code Online (Sandbox Code Playgroud)

(2)的优点是我试图将文字放在图中顶部向上倾斜的文本上.

可以这样做,还是我要求多少?如果是这样,我该怎么做?

以下是实现该图的代码:

import numpy as np
import pylab

r1 = 1  #  AU Earth                                                                 
r2 = 1.524  #  AU Mars                                                              
deltanu = 75 * np.pi / 180  #  angle in radians                                     
mu = 38.86984154054163

c = np.sqrt(r1 ** 2 + r2 ** 2 - 2 * r1 * r2 * np.cos(deltanu))   
s = (r1 + r2 + c) / 2
am = s / 2


def g(a):
    alphag = 2* np.pi - 2 * np.arcsin(np.sqrt(s / (2 * a)))
    return (np.sqrt(a ** 3 / mu)
            * (alphag - betag - (np.sin(alphag) - np.sin(betag))))


def f(a):
    alpha = 2 * np.arcsin(np.sqrt(s / (2 * a)))
    beta = 2 * np.arcsin(np.sqrt((s - c) / (2 * a)))
    return (np.sqrt(a **3 / mu) * (alpha - betag - (np.sin(alpha)
                                                      - np.sin(betag))))


betag = -2 * np.arcsin(np.sqrt((s - c) / (2 * a)))
a = np.linspace(am, 2, 500000)

a = np.linspace(am, 2, 500000)

fig = pylab.figure()
ax = fig.add_subplot(111)
ax.plot(a, f(a), color = '#000000')
ax.plot(a, g(a), color = '#000000')
pylab.xlim((0.9, 2))
pylab.ylim((0, 2))

pylab.xlabel('Semi-major Axis $a$ in AU')
pylab.ylabel('Time of Flight in Years')
pylab.text(1, 1.8, '$r_1 = 1.0$ AU', fontsize = 11, color = 'r')
pylab.text(1, 1.7, '$r_2 = 1.524$ AU', fontsize = 11, color = 'r')
pylab.text(1, 1.6, '$\\Delta \\nu = 75^{\\circ}$', fontsize = 11,
           color = 'r')
pylab.text(1.75, 0.35, '$\\alpha = \\alpha_0$', fontsize = 11,
           color = 'r')
pylab.savefig('lamberttransferties.eps', format = 'eps')
pylab.show()
Run Code Online (Sandbox Code Playgroud)

Sau*_*tro 13

您可以使用行分隔符\n:

 pylab.text(1, 1.5, '$r_1 = 1.0$ AU\n' +\
                    '$r_2 = 1.524$ AU\n' +\
                    '$\\Delta \\nu = 75^{\\circ}$', fontsize = 11, color = 'r')
Run Code Online (Sandbox Code Playgroud)

pylab.text()默认情况下使用数据坐标,但您可以使用(0,0)左下角和(1,1)右上角的相对位置,传递参数transform.看这个例子:

pylab.text(0.6, 0.75, 'using axis coords', transform=ax.transAxes)
Run Code Online (Sandbox Code Playgroud)

参数:verticalalignment并且horizontalalignment还可以为您提供极大的帮助.假设您想要在角落放置文本:

pylab.text(1.,1.,'top-right', transform=ax.transAxes,
           horizontalalignment='right', verticalalignment='top')

pylab.text(0.,0.,'bottom-left', transform=ax.transAxes,
           horizontalalignment='left', verticalalignment='bottom')
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

要根据您的数据自动计算文本角度,您可以执行以下方法:

  • 检测数据最近点
  • 找到最近点附近的序列并使用此序列拟合曲线(下面的示例使用四阶曲线)
  • 计算您希望放置文本的点处的导数
  • 使用ax.get_data_ratio()OBS 更正指示:ax.axis('scaled')例如,如果使用则不需要

该算法可以实现如下:

def rtext(line,x,y,s, **kwargs):
    from scipy.optimize import curve_fit
    xdata,ydata = line.get_data()
    dist = np.sqrt((x-xdata)**2 + (y-ydata)**2)
    dmin = dist.min()
    TOL_to_avoid_rotation = 0.3
    if dmin > TOL_to_avoid_rotation:
        r = 0.
    else:
        index = dist.argmin()
        xs = xdata[ [index-2,index-1,index,index+1,index+2] ]
        ys = ydata[ [index-2,index-1,index,index+1,index+2] ]
        def f(x,a0,a1,a2,a3):
            return a0 + a1*x + a2*x**2 + a3*x**3
        popt, pcov = curve_fit(f, xs, ys, p0=(1,1,1,1))
        a0,a1,a2,a3 = popt
        ax = pylab.gca()
        derivative = (a1 + 2*a2*x + 3*a3*x**2)
        derivative /= ax.get_data_ratio()
        r = np.arctan( derivative )
    return pylab.text(x, y, s, rotation=np.rad2deg(r), **kwargs)
Run Code Online (Sandbox Code Playgroud)

以下测试示例显示了如何使用它:

ax = pylab.subplot(111)
thetas = np.linspace(0,6*np.pi,1000)
i = np.arange(len(thetas))
xdata = (1. + (3.-1.)*i/len(thetas))*np.cos(thetas)
ydata = (1. + (3.-1.)*i/len(thetas))*np.sin(thetas)
ax.plot(xdata, ydata, color = 'b')
pylab.xlabel('x')
pylab.ylabel('y')
for x, y in zip(xdata,ydata)[::25]:
    rtext(ax.lines[0], x, y,
          '$\\alpha = \\alpha_0$', fontsize = 14, color = 'r',
          horizontalalignment='center', verticalalignment='center')
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

更改 verticalalignment='bottom'

在此输入图像描述