zephyr-backend/modules/balloon/gravityw_plot_perday.py
2025-03-05 11:40:19 +08:00

161 lines
4.9 KiB
Python

# 探空气球只有重力波
from dataclasses import dataclass
from io import BytesIO
import matplotlib.pyplot as plt
import numpy as np
from modules.balloon.extract_wave import calculate_wave, is_terrain_wave
lat = 52.21
g = 9.76
def plot_polynomial_fit(ucmp, vcmp, temp, height, poly_ucmp, poly_vcmp, poly_temp):
plt.figure(figsize=(16, 5))
# u 风扰动量
plt.subplot(1, 3, 1)
plt.plot(ucmp, height, linestyle="-")
plt.plot(poly_ucmp(height), height)
plt.ylabel("高度(km)")
plt.xlabel("纬向风(m/s)")
plt.grid(True)
# v 风扰动量
plt.subplot(1, 3, 2)
plt.plot(vcmp, height, linestyle="-")
plt.plot(poly_vcmp(height), height)
plt.ylabel("高度(km)")
plt.xlabel("经向风 (m/s)")
plt.grid(True)
plt.title("观测的二阶多项式拟合", fontsize=16)
# 温度扰动量
plt.subplot(1, 3, 3)
plt.plot(temp, height, linestyle="-")
plt.plot(poly_temp(height), height)
plt.ylabel("高度(km)")
plt.xlabel("温度(K)")
plt.grid(True)
plt.tight_layout()
def plot_sine_fit(residual_ucmp, residual_vcmp, residual_temp, height, u_fit, v_fit, T_fit):
plt.figure(figsize=(16, 5))
# u 风扰动量
plt.subplot(1, 3, 1)
plt.plot(residual_ucmp, height, marker="o", linestyle="None")
plt.plot(u_fit, height)
plt.ylabel("高度(km)")
plt.xlabel("纬向风 (m/s)")
plt.grid(True)
# v 风扰动量
plt.subplot(1, 3, 2)
plt.plot(residual_vcmp, height, marker="o", linestyle="None")
plt.plot(v_fit, height)
plt.ylabel("高度(km)")
plt.xlabel("经向风(m/s)")
plt.grid(True)
plt.title("扰动分量的正弦波拟合", fontsize=16)
# 温度扰动量
plt.subplot(1, 3, 3)
plt.plot(residual_temp, height, marker="o", linestyle="None")
plt.plot(T_fit, height)
plt.ylabel("高度(km)")
plt.xlabel("温度(K)")
plt.grid(True)
plt.tight_layout()
def plot_uv_vector(u_fit, v_fit, height, specified_heights, markers):
plt.figure(figsize=(8, 6))
plt.plot(u_fit, v_fit)
for h, marker in zip(specified_heights, markers):
index = np.abs(height - h).argmin()
plt.scatter(u_fit[index], v_fit[index],
marker=marker, s=100, label=f"{h} km")
# plt.xlim(-8, 8)
# plt.ylim(-4, 4)
plt.axvline(0, color="gray", linestyle="--")
plt.axhline(0, color="gray", linestyle="--")
plt.xlabel("经向风 (m/s)")
plt.ylabel("纬向风(m/s)")
plt.legend()
plt.grid(True)
plt.title("径向风-纬向风矢量图")
def plot_temp_horizontal_wind(uh, T_fit, height, specified_heights, markers):
plt.figure(figsize=(8, 6))
plt.plot(uh, T_fit)
for h, marker in zip(specified_heights, markers):
index = np.abs(height - h).argmin()
plt.scatter(uh[index], T_fit[index],
marker=marker, s=100, label=f"{h} km")
# plt.xlim(-4, 4)
# plt.ylim(-2, 2)
plt.axvline(0, color="gray", linestyle="--")
plt.axhline(0, color="gray", linestyle="--")
plt.xlabel("Horizontal wind (m/s)")
plt.ylabel("Temp (K)")
plt.legend()
plt.grid(True)
plt.title("温度-水平风矢量图")
def render_by_mode_single(data, mode):
wave = calculate_wave(
data[(data["alt"] >= 15) & (data["alt"] <= 25)], lat, g)
@dataclass
class ReturnValue:
image: BytesIO
is_terrain_wave: bool
has_data: bool
if len(wave) == 0:
return ReturnValue(image=BytesIO(), is_terrain_wave=False, has_data=False)
c = is_terrain_wave(data, lat, g)
a, b, omega_upper, w_f, λ_z, λ_h, c_x, c_y, c_z, Ek, E_p, MFu1, MFv1, params_u, params_v, params_T = wave[
:16]
ucmp, vcmp, temp, height, poly_ucmp, poly_vcmp, _, poly_temp, residual_ucmp, residual_vcmp, residual_temp, u_fit, v_fit, T_fit, uh, _ = wave[
16:]
if mode == "观测的二阶多项式拟合":
plot_polynomial_fit(ucmp, vcmp, temp, height, poly_ucmp,
poly_vcmp, poly_temp)
elif mode == "扰动分量的正弦波拟合":
plot_sine_fit(residual_ucmp, residual_vcmp, residual_temp,
height, u_fit, v_fit, T_fit)
elif mode == "径向风-纬向风矢量图":
plot_uv_vector(u_fit, v_fit, height, [15, 20, 25], [
"o", "s", "D"])
elif mode == "温度-水平风矢量图":
plot_temp_horizontal_wind(uh, T_fit, height, [15, 20, 25], [
"o", "s", "D"])
else:
raise ValueError("Unknown mode")
plt.rcParams["font.sans-serif"] = ["SimHei"] # 显示中文
buff = BytesIO()
plt.savefig(buff, format="png")
plt.close()
buff.seek(0)
return ReturnValue(
image=buff,
is_terrain_wave=c,
has_data=True
)