Initial commit
This commit is contained in:
142
A题/ZJ_v2/fig11_heatmap_temp_signal.py
Normal file
142
A题/ZJ_v2/fig11_heatmap_temp_signal.py
Normal file
@@ -0,0 +1,142 @@
|
||||
"""
|
||||
Fig 11: Two-Parameter Heatmap (Temperature × Signal Quality)
|
||||
Shows interaction effects on TTE
|
||||
"""
|
||||
|
||||
import os
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from plot_style import set_oprice_style, save_figure
|
||||
|
||||
def compute_tte_surface(T_a_range, psi_range):
|
||||
"""Compute TTE for grid of (T_a, psi) values"""
|
||||
|
||||
T_grid, psi_grid = np.meshgrid(T_a_range, psi_range)
|
||||
tte_grid = np.zeros_like(T_grid)
|
||||
|
||||
# Battery capacity
|
||||
Q_full = 2.78 # Ah
|
||||
V_avg = 3.8 # V
|
||||
E_total = Q_full * V_avg # Wh
|
||||
|
||||
# Baseline power components
|
||||
P_bg = 5.0
|
||||
P_scr = 8.0 * 0.3 # L = 0.3
|
||||
P_cpu = 35.0 * 0.4 # C = 0.4
|
||||
P_gps = 0.015 # Minimal
|
||||
|
||||
for i in range(len(psi_range)):
|
||||
for j in range(len(T_a_range)):
|
||||
T_a = T_grid[i, j]
|
||||
psi = psi_grid[i, j]
|
||||
|
||||
# Network power depends on signal quality (worse signal = more power)
|
||||
k_net_base = 7.0
|
||||
k_net = k_net_base * (1 + 2 * (1 - psi))
|
||||
P_net = k_net * 0.05 # N = 0.05
|
||||
|
||||
# Temperature affects efficiency (cold reduces capacity, hot increases resistance)
|
||||
temp_factor = 1.0
|
||||
if T_a < 10:
|
||||
temp_factor = 0.8 + 0.02 * T_a # Reduced capacity in cold
|
||||
elif T_a > 30:
|
||||
temp_factor = 1.0 + 0.01 * (T_a - 30) # Increased losses in heat
|
||||
|
||||
P_total = (P_bg + P_scr + P_cpu + P_net + P_gps) * temp_factor
|
||||
|
||||
tte_grid[i, j] = E_total / P_total
|
||||
|
||||
return T_grid, psi_grid, tte_grid
|
||||
|
||||
def make_figure(config):
|
||||
"""Generate Fig 11: Two-Parameter Heatmap"""
|
||||
|
||||
set_oprice_style()
|
||||
|
||||
# Parameter ranges
|
||||
T_a_range = np.linspace(-10, 40, 50) # °C
|
||||
psi_range = np.linspace(0.1, 1.0, 50) # Signal quality (0=poor, 1=excellent)
|
||||
|
||||
# Compute TTE surface
|
||||
T_grid, psi_grid, tte_grid = compute_tte_surface(T_a_range, psi_range)
|
||||
|
||||
# Create figure
|
||||
fig, ax = plt.subplots(figsize=(12, 9))
|
||||
|
||||
# Heatmap
|
||||
im = ax.contourf(T_grid, psi_grid, tte_grid, levels=20, cmap='RdYlGn', alpha=0.9)
|
||||
|
||||
# Contour lines
|
||||
contours = ax.contour(T_grid, psi_grid, tte_grid, levels=10, colors='k',
|
||||
linewidths=0.5, alpha=0.3)
|
||||
ax.clabel(contours, inline=True, fontsize=8, fmt='%.1f h')
|
||||
|
||||
# Colorbar
|
||||
cbar = fig.colorbar(im, ax=ax, label='Time to Empty (hours)')
|
||||
cbar.ax.tick_params(labelsize=9)
|
||||
|
||||
# Mark baseline condition
|
||||
T_baseline = 25
|
||||
psi_baseline = 0.8
|
||||
ax.plot(T_baseline, psi_baseline, 'r*', markersize=20,
|
||||
markeredgecolor='white', markeredgewidth=1.5,
|
||||
label='Baseline Condition', zorder=5)
|
||||
|
||||
# Mark danger zones
|
||||
# Cold + poor signal
|
||||
ax.add_patch(plt.Rectangle((-10, 0.1), 15, 0.3,
|
||||
fill=False, edgecolor='red', linewidth=2,
|
||||
linestyle='--', label='Critical Zone'))
|
||||
ax.text(-5, 0.25, 'Battery Killer\\n(Cold + Poor Signal)',
|
||||
fontsize=9, color='darkred', ha='center',
|
||||
bbox=dict(boxstyle='round', facecolor='white', alpha=0.7))
|
||||
|
||||
# Optimal zone
|
||||
ax.add_patch(plt.Rectangle((15, 0.7), 15, 0.25,
|
||||
fill=False, edgecolor='green', linewidth=2,
|
||||
linestyle='--', label='Optimal Zone'))
|
||||
ax.text(22.5, 0.825, 'Optimal\\n(Mild + Good Signal)',
|
||||
fontsize=9, color='darkgreen', ha='center',
|
||||
bbox=dict(boxstyle='round', facecolor='white', alpha=0.7))
|
||||
|
||||
# Labels and styling
|
||||
ax.set_xlabel('Ambient Temperature (°C)', fontsize=11)
|
||||
ax.set_ylabel('Signal Quality (Ψ)', fontsize=11)
|
||||
ax.set_title('TTE Sensitivity to Temperature and Signal Quality (Interaction Effect)',
|
||||
fontsize=12, fontweight='bold')
|
||||
ax.set_xlim(-10, 40)
|
||||
ax.set_ylim(0.1, 1.0)
|
||||
ax.legend(loc='upper left', framealpha=0.9, fontsize=9)
|
||||
|
||||
# Add statistics
|
||||
tte_min = np.min(tte_grid)
|
||||
tte_max = np.max(tte_grid)
|
||||
tte_range = tte_max - tte_min
|
||||
|
||||
stats_text = f'TTE Range:\\n' + \
|
||||
f'Min: {tte_min:.2f}h\\n' + \
|
||||
f'Max: {tte_max:.2f}h\\n' + \
|
||||
f'Spread: {tte_range:.2f}h ({tte_range/tte_max*100:.1f}%)'
|
||||
|
||||
ax.text(0.98, 0.02, stats_text, transform=ax.transAxes,
|
||||
fontsize=9, verticalalignment='bottom', horizontalalignment='right',
|
||||
bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8),
|
||||
family='monospace')
|
||||
|
||||
# Save
|
||||
figure_dir = config.get('global', {}).get('figure_dir', 'figures')
|
||||
os.makedirs(figure_dir, exist_ok=True)
|
||||
output_base = os.path.join(figure_dir, 'Fig11_Heatmap_Temp_Signal')
|
||||
save_figure(fig, output_base, dpi=config.get('global', {}).get('dpi', 300))
|
||||
plt.close()
|
||||
|
||||
return {
|
||||
"output_files": [f"{output_base}.pdf", f"{output_base}.png"],
|
||||
"computed_metrics": {
|
||||
"tte_min_h": float(tte_min),
|
||||
"tte_max_h": float(tte_max),
|
||||
"tte_range_h": float(tte_range)
|
||||
},
|
||||
"validation_flags": {},
|
||||
"pass": True
|
||||
}
|
||||
Reference in New Issue
Block a user