在下面的代码中,我有一个循环,它将根据我的输入数据读取不同的文本文件,然后进行一些计算。我也在绘制一个依赖于时间的函数。所以如果循环的长度是5,那么我将在一个图中有5个不同的叠加。由于每条曲线都对应一个流动时间,因此我想在图形中使用适当的t1值对每条曲线进行注释,该值对于循环中的每次迭代都会发生变化。理想情况下,我希望有一条带箭头的线指向每条曲线并具有相应的注释。
我还想在图表中自动更新图例,即。图中的每条曲线应对应于t1的特定值。我已经看了一些例子,但我无法为我的问题找到任何工作。我请求SO社区帮助我。
在这个示例代码中,我提供了三个文本文件。因此,如果代码运行,它将生成3个叠加层。每个注释应对应于循环中计算的t1的唯一值。
更新1:我修改了代码,以便根据循环中计算的每个t1值更新图例。这是一个微不足道的修复。我仍然无法用t1的值注释每条曲线。
# ... package imports ...
import numpy as np
from scipy.interpolate import griddata
from matplotlib import pyplot as plt
from scipy import integrate
from scipy import interpolate
import math
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
from scipy.interpolate import RectBivariateSpline
plt.ioff()
Uj = 0.944
W = 30.48
dj = 0.3048
dj_length = (2*dj)
Ho_bar = 44.607
Ho_bar = (Ho_bar-(2*dj))
Ho = (Ho_bar*(1/W))
djo = 1.2192
rho = 998
D = W/W
path = "Location where the text files are located"
FT_init = 3.610
delt = 0.15
TS_init = 140
TS_init0 = 100
flowtime = np.linspace(50,2350,3)
timestep = ((flowtime-FT_init)/delt)+ TS_init
timestep = np.array(np.round(timestep,-2),dtype = 'int')
def Ekbar(KE_h,Y4):
plt.figure(1,figsize=(4.5,2.875))
plt.plot(KE_h,Y4,label=(t1[s]))
plt.ticklabel_format(style = 'sci', axis = 'x', scilimits=(0,0))
plt.ylim(Y4.min(),Y4.max())
plt.xlabel("X")
plt.ylabel('Y')
plt.tight_layout()
for s in range(len(timestep)):
flowtime1 = flowtime
flowtime1[s] = (timestep[s]-TS_init)*delt+FT_init
flowtime1[s] = np.array(np.round(flowtime[s]),dtype = 'int')
q = np.array(flowtime1)
timestepstring=str(timestep[s]).zfill(4)
t = ((Uj*dj)/(W*W))*q ## Nondimensional time
t1 = np.round(t,decimals=2)
fname = path+"ddn130AE-"+timestepstring+".txt"
f10 = open(fname,'r')
data = np.loadtxt(f10,skiprows=1)
data = data[np.logical_not(data[:,11]== 0)]
data = data[data[:, 2].argsort()]
Y = data[:,2] # Assigning Y to column 2 from the text file
limitz = np.nonzero(Y==dj_length)[0][0]
Vf = data[:,11]
Vf = Vf[limitz:]
Tr = data[:,9]
Tr = Tr[limitz:]
X = data[:,1]
X = X[limitz:]
Y = data[:,2]
Y = Y[limitz:]
U_bar = data[:,3]
U_bar = U_bar[limitz:]
V_bar = data[:,4]
V_bar = V_bar[limitz:]
U = (U_bar/Uj)
V = (V_bar/Uj)
limit = np.nonzero(Y==Y.max())[0][0]
limit1 = np.nonzero(X==X.max())[0][0]
Y1 = Y[limit]
X1 = X[limit1]
nx = (5*(W/dj))
ny = (5*(Y1/dj))
pts = np.vstack((X, Y)).T
U1 = np.vstack((U))
V1 = np.vstack((V))
# The new x and y coordinates for the grid
x = np.linspace(X.min(), X.max(), nx)
y = np.linspace(Y.min(), Y.max(), ny)
r = np.meshgrid(y,x)[::-1]
ipts = np.vstack(a.ravel() for a in r).T
Uf = griddata(pts,U1,ipts,method='nearest')
Vf = griddata(pts,V1,ipts,method='nearest')
Uf1 = np.multiply(Uf,Uf)
Vf1 = np.multiply(Vf,Vf)
velsum = np.array(Uf1+Vf1)
velsum = np.reshape(velsum,(len(x),len(y)))
KE_int = interpolate.RectBivariateSpline(x,y,velsum)
Sip1 = KE_int(x,y)
axisx = np.linspace(0,D,num=len(Sip1))
KE_h = np.zeros(len(Sip1[0]))
for i in range(len(Sip1[0])):
KE_h[i] = integrate.simps(Sip1[:,i],axisx,axis=0)
KE_h1 = integrate.simps(Sip1,axisx,axis=0)
Y4 = np.linspace(Y.min(),Y1,num=len(KE_h))
Y4 = Y4/W
Ekbar(KE_h,Y4)
plt.savefig('test.png',format = 'png', dpi=1200, bbox_inches='tight')
答案 0 :(得分:2)
我仍然认为这个问题应该通过一个小的示例代码进行简化。
要添加注释,您需要知道两个位置,
例如,您可以使用水平峰值点,并使用类似于图例标签的标签对其进行注释。假设文本位置具有以下x坐标
annot_txt_pose = [2.0e-2, 2.0e-2, 1.5e-2]
虽然假设y坐标与注释y坐标相同。然后在每个绘图命令之后,您可以使用以下代码来注释曲线
label_str = "%s"%t1[s]
# maximum x value annotation
annot_idx = np.argmax(KE_h)
# annotation arrow tip position
arrow_tip = KE_h[annot_idx],Y4[annot_idx]
# annotation text position
text_pos = annot_txt_pose[s],Y4[annot_idx]
plt.plot(arrow_tip[0], arrow_tip[1], 'o')
ax.annotate(label_str, xy=arrow_tip, xytext=text_pos, arrowprops=dict(facecolor='black', shrink=0.05))