How to keep some text relative to the line into the plot when the plot changes

爱⌒轻易说出口 提交于 2020-01-05 05:32:25

问题


I would like to put some text below a horizontal line in a plot that changes with changing two parameters. I use a function to plot and python widgets to set two controls that change the plot and at the same time change the distances of the x and y-axis.

My iPhyton code is:

from ipywidgets import widgets
from IPython.display import display
import matplotlib.pyplot as plt
import numpy as np
%matplotlib notebook

def update_plot(h1, h2):
    plt.figure( figsize = (9,4) )
    ax=plt.subplot(111)
    D = np.arange(0.5, 12.0, 0.0100)
    r = np.sqrt((h1-h2)**2 + D**2)
    freq = 865.7 #freq = 915 MHz
    lmb = 300/freq 
    H = D**2/(D**2+2*h1*h2)
    theta = 4*np.pi*h1*h2/(lmb*D)
    q_e = H**2*(np.sin(theta))**2 + (1 - H*np.cos(theta))**2
    q_e_rcn1 = 1
    P_x_G = 4 # 4 Watt EIRP
    sigma = 1.94
    N_1 = np.random.normal(0,sigma,D.shape)
    rnd = 10**(-N_1/10)
    F = 10 # 
    plt.semilogx(r,10*np.log10( 1000*(P_x_G*1.622*((lmb)**2) *0.5*1) / (((4*np.pi*r)**2) *1.2*1*F)*q_e*rnd*q_e_rcn1 ),
             label='Multipath')
    plt.axhline(y = -18, linewidth=1.2, color='black',ls='--')
    #plt.text(0.60, -22, r"T Threshold")
    ax.text(0.02, 0.37, "T Threshold",
        verticalalignment='bottom', horizontalalignment='left',
        transform=ax.transAxes,
        color='brown', fontsize=10)
    plt.xlabel('Separation Distance, r (m)')
    plt.ylabel('Received Power, $P_t$ (dBm)')
    plt.grid(True,which="both",ls=":")
    plt.legend()
    #####################

r_height = widgets.FloatSlider(min=0.5, max=4, value=0.9, description= 'R_Height:')
t_height = widgets.FloatSlider(min=0.15, max=1.5, value=0.5, description= 'T_Height:')
widgets.interactive(update_plot, h1=r_height, h2=t_height)

Matplotlib documentation in "Text in Matplotlib Plots" indicates different ways to place text into the plot. I have tried two forms: the set of the exact position into the plot (commented) and the relative position. The first way place the text close to the horizontal line but goes outside the frame when it changes the plot with the controls. The second way to keep the text at a distance from the y-axis but does not change as the horizontal line goes up and down when the parameters change.

I would like to find a way to put the text close to the horizontal line but at a certain distance of the y=0 axis.

Regards


回答1:


I think you would want to position the text in a blended coordinate system where the x coordinate is the axes coordinate system and the y coordinate is the data coordinate system. Such blended coordinate systems is conveniently already available through the ax.get_yaxis_transform(). E.g. to place the text 2% away from the y axis, at a y coordinate of -18,

ax.text(0.02, -18, "T Threshold", transform=ax.get_yaxis_transform() )

In general you may want to create the plot only once, and then using the sliders, only update the relevant parts of it. In total this would look like:

from ipywidgets import widgets
from IPython.display import display
import matplotlib.pyplot as plt
import numpy as np
%matplotlib notebook
import ipywidgets


fig, ax = plt.subplots()
line, = ax.semilogx([],[], label='Multipath')
hline = ax.axhline(y = 0, linewidth=1.2, color='black',ls='--')
text = ax.text(0, 0, "T Threshold",
                verticalalignment='top', horizontalalignment='left',
                transform=ax.get_yaxis_transform(),
                color='brown', fontsize=10)
ax.set_xlabel('Separation Distance, r (m)')
ax.set_ylabel('Received Power, $P_t$ (dBm)')
ax.grid(True,which="both",ls=":")
ax.legend()

def update_plot(h1, h2):
    D = np.arange(0.5, 12.0, 0.0100)
    r = np.sqrt((h1-h2)**2 + D**2)
    freq = 865.7 #freq = 915 MHz
    lmb = 300/freq 
    H = D**2/(D**2+2*h1*h2)
    theta = 4*np.pi*h1*h2/(lmb*D)
    q_e = H**2*(np.sin(theta))**2 + (1 - H*np.cos(theta))**2
    q_e_rcn1 = 1
    P_x_G = 4 # 4 Watt EIRP
    sigma = 1.94
    N_1 = np.random.normal(0,sigma,D.shape)
    rnd = 10**(-N_1/10)
    F = 10
    y = 10*np.log10( 1000*(P_x_G*1.622*((lmb)**2) *0.5*1) / (((4*np.pi*r)**2) *1.2*1*F)*q_e*rnd*q_e_rcn1 )
    line.set_data(r,y)

    hline.set_ydata(-18)
    text.set_position((0.02, -18.5))
    ax.relim()
    ax.autoscale_view()
    fig.canvas.draw_idle()

r_height = widgets.FloatSlider(min=0.5, max=4, value=0.9, description= 'R_Height:')
t_height = widgets.FloatSlider(min=0.15, max=1.5, value=0.5, description= 'T_Height:')
widgets.interactive(update_plot, h1=r_height, h2=t_height)

Note that the sliders will now appear below the plot, as they are created afterwards - this might a bearable downside given the advantages of a much better responsivity of the slider changes due to not recreating the complete plot at each slider movement.



来源:https://stackoverflow.com/questions/51266355/how-to-keep-some-text-relative-to-the-line-into-the-plot-when-the-plot-changes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!