"Matplotlib对数刻度上的倾斜文本?"

2024-10-04 01:29:27 发布

您现在位置:Python中文网/ 问答频道 /正文

可能是我搞不懂,或者是在用rotation绘制text()到{}或{}绘图时,matplotlib中有一个错误。在

我的代码如下:

from pylab import *

# =================== deltaV-vs-trust
figure( figsize=( 12, 8 ) )

times     = array( [ 1.0,  60.0, 3600.0, 86400.0, 604800,  2592000, 31556926, 315569260,  3155692600  ] )
timeText  =        [ 'sec','min','hour', 'day',   'week',  'month', 'year',   '10years',  '100years'  ]
dists     = array( [ 1e+1,  1e+2,  1e+3,  1e+4,  1e+5,     1e+6,    6371e+3, 42164e+3, 384400e+3,  1e+9,       1e+10,       5.790918E+010, 1.082089E+011, 1.495979E+011, 2.279366E+011, 7.784120E+011, 1.426725E+012, 2.870972E+012, 4.498253E+012, 1.40621998e+13, 2.99195741e+14, 7.47989354e+15,  4.13425091e+16 ] )
distText  =        [ '10m','100m', '1km','10km', '100km', '1000km', 'LEO',   'GEO',    'Moon',     r'10$^6$km',r'10$^7$km', 'Mercury',       'Venus',       'Earth',        'Mars',     'Jupiter',      'Satrun',      'Uranus',     'Neptune',   'Heliopause', 'Inner Oorth',   'Outer Oorth', 'Alpha Centauri' ] 

vMin = 1e+0; vMax = 1e+8;
aMin = 1e-4; aMax = 1e+2;

As = linspace(aMin,aMax,2); print As
Vs = linspace(vMin,vMax,2); print Vs
As_ = As.copy(); Vs_ = Vs.copy()

for i in range(len(dists)):
    dist = dists[i]
    ts    = sqrt( 2*dist / As )
    As_[:] = As [:]
    Vs_    = As * ts    
    if( Vs_[0] < Vs[0] ):
        Vs_[0] = Vs[0]
        As_[0] = Vs_[0]**2 / (2*dist)
    plot( Vs_, As_, 'b-', alpha=0.5 ) 
    plt.text( Vs_[0], As_[0], distText[i], rotation=60, color='b', horizontalalignment='center', verticalalignment='bottom')     # this does not work properly
    #plt.text( Vs_[0], As_[0], distText[i], rotation=60, color='b', horizontalalignment='center', verticalalignment='center')     # this works but does not look nice
    #plt.text( Vs_[0], 1.5*As_[0], distText[i], rotation=60, color='b', horizontalalignment='center', verticalalignment='center')  # a bit better

for i in range(len(times)):
    time = times[i]
    As_[:] = As[:] 
    Vs_ = As * time  
    if( Vs_[1] > Vs[1] ):   
        Vs_[1] = Vs[1] 
        As_[1] = Vs_[1] / time
    plot( Vs_, As_, 'r-', alpha=0.5 ) 
    plt.text(  Vs_[1], As_[1], timeText[i]+"  ", rotation=40, color='r',  horizontalalignment='right', verticalalignment='baseline')

ylabel( r" acceleration [m/s$^2$] " )
xlabel( r" delta-v      [m/s  ] " )
yscale('log')
xscale('log')
grid()
ylim( aMin, aMax )
xlim( vMin, vMax )

show()

结果如下所示(您可以看到文本在相应的行中的位置不正确;对于Inner OorthOuter OorthAlpha Centauri非常明显): enter image description here

我认为这个问题只在大旋转角度下才可见。如果我使用horizontalalignment='center', verticalalignment='center'它可以正常工作,但是它看起来不太好(因为行穿过文本,文本穿过图像的边界)

只是为了上下文-我要做的是这样的情节: http://www.projectrho.com/public_html/rocket/images/enginelist/torchChart.jpg


Tags: textaspltcolorvscentertimesrotation
1条回答
网友
1楼 · 发布于 2024-10-04 01:29:27

关键是'rotation_mode'kwarg到textdoc),直到今晚我才知道它的存在。此控件的作用是如果文本先旋转,然后对齐(默认设置)或对齐,然后旋转。在

为了理解你的问题,我把你的代码清理到(或多或少)符合pep8,并简化了一些计算。在

import matplotlib.pyplot as plt
import numpy as np

# =================== deltaV-vs-trust


times = np.array([1.0,  60.0, 3600.0, 86400.0, 604800,  2592000, 31556926, 315569260,  3155692600])
timeText = ['sec','min','hour', 'day',   'week',  'month', 'year',   '10years',  '100years']

dists= np.array([1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 6371e+3, 42164e+3,
                384400e+3, 1e+9, 1e+10, 5.790918E+010, 1.082089E+011, 1.495979E+011,
                2.279366E+011, 7.784120E+011, 1.426725E+012, 2.870972E+012,
                4.498253E+012, 1.40621998e+13, 2.99195741e+14, 7.47989354e+15,
                4.13425091e+16])

distText = ['10m','100m', '1km','10km', '100km', '1000km', 'LEO',
            'GEO', 'Moon', r'10$^6$km',r'10$^7$km', 'Mercury', 'Venus', 'Earth',
            'Mars', 'Jupiter', 'Satrun', 'Uranus', 'Neptune', 'Heliopause',
            'Oorth', 'Outer Oorth', 'Alpha Centauri']

vMin, vMax = 1e+0, 1e+8
aMin, aMax = 1e-4, 1e+2


As = np.linspace(aMin, aMax, 2)

fig, ax = plt.subplots(figsize=(12, 8))

for dist, text in zip(dists, distText):
    # compute the line
    v = np.sqrt(2*dist * As)
    ax.plot(v, As, 'b-', alpha=0.5)

    # sort out where the label should be
    txt_y = aMin
    txt_x = v[0]
    # clip to the edges
    if (txt_x < vMin):
        txt_x = vMin
        txt_y = vMin**2 / (2*dist)

    ax.text(txt_x, txt_y, text,
            rotation=60, color='b', rotation_mode='anchor',
            horizontalalignment='left',
            verticalalignment='bottom')


for time, txt in zip(times, timeText):
    # compute the line
    x = As * time
    ax.plot(x, As, 'r-', alpha=0.5) 

    # sort out where the label should be
    txt_x = x[-1]
    txt_y = aMax
    # clip to the edges
    if(txt_x > vMax):
        txt_x = vMax
        txt_y = vMax / time

    ax.text(txt_x, txt_y, txt,
            rotation=40, color='r',
            horizontalalignment='right', rotation_mode='anchor',
            verticalalignment='baseline')

ax.set_ylabel(r"acceleration [m/s$^2$]")
ax.set_xlabel(r"delta-v [m/s]")
ax.set_yscale('log')
ax.set_xscale('log')
ax.grid()
ax.set_ylim(aMin, aMax)
ax.set_xlim(vMin, vMax)

enter image description here

相关问题 更多 >