修改以下代码,代码要求为:根据温度数据和坐标数据表格,绘制XY、YZ、XZ、平面的等值线图,时间间隔4小时一次生成一个图,每天一幅的组图,结合各平面生成三维冻结壁演化图,温度数值为0的等温线即为冰柱,冰柱相交为冰墙,在冻结壁云图绘制中去除坐标线框,保留温度图例。原来代码为import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.colors as mcolors
from scipy.interpolate import griddata
from scipy.spatial.distance import cdist
import trimesh
import os
from datetime import datetime, timedelta
import warnings
warnings.filterwarnings('ignore')
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from skimage import measure
class OptimizedFreezingWallAnalysis:
def __init__(self, temp_data_file, coord_data_file, stl_file=None):
"""初始化冻结壁分析系统"""
# 设置中文字体
self.set_chinese_font()
# 设置工作目录
self.base_dir = r'C:\Users\Admin\Desktop\工况1温度处理'
self.output_dir = os.path.join(self.base_dir, '冻结壁分析结果')
os.makedirs(self.output_dir, exist_ok=True)
# 构建完整文件路径
temp_data_path = os.path.join(self.base_dir, temp_data_file)
coord_data_path = os.path.join(self.base_dir, coord_data_file)
# 加载数据
self.load_data(temp_data_path, coord_data_path)
# 加载边坡模型(可选)
self.slope_mesh = None
if stl_file:
stl_path = os.path.join(self.base_dir, stl_file)
if os.path.exists(stl_path):
self.load_slope_model(stl_path)
# 预处理数据
self.preprocess_data()
# 圆柱体参数
self.cylinder_radius = 0.5 # 圆柱体半径 (米)
self.flattened_ratio = 0.3 # 扁圆柱压缩比例
print(f"冻结壁分析系统初始化完成\n结果保存到: {self.output_dir}")
def set_chinese_font(self):
"""设置中文字体支持"""
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
def load_data(self, temp_data_file, coord_data_file):
"""加载温度和坐标数据"""
print("加载数据...")
# 加载温度数据
self.temp_df = pd.read_excel(temp_data_file)
self.temp_df.columns = ['时间', '测点ID', '温度']
# 加载坐标数据
self.coord_df = pd.read_excel(coord_data_file)
self.coord_df.columns = ['测点ID', 'X', 'Y', 'Z']
# 合并数据
self.merged_df = pd.merge(self.temp_df, self.coord_df, on='测点ID')
self.merged_df['时间'] = pd.to_datetime(self.merged_df['时间'])
print(f"加载数据: {len(self.merged_df)}条记录, {len(self.coord_df)}个测点")
def load_slope_model(self, stl_file):
"""加载边坡三维模型"""
print(f"加载STL模型: {stl_file}")
try:
self.slope_mesh = trimesh.load_mesh(stl_file)
print(f"加载成功: {len(self.slope_mesh.vertices)}顶点, {len(self.slope_mesh.faces)}面")
except Exception as e:
print(f"STL加载失败: {e}")
def preprocess_data(self):
"""数据预处理"""
# 提取唯一日期和时间
self.merged_df['日期'] = self.merged_df['时间'].dt.date
self.merged_df['小时'] = self.merged_df['时间'].dt.hour
self.dates = sorted(self.merged_df['日期'].unique())
# 提取测点信息
self.monitoring_points = self.merged_df[['测点ID', 'X', 'Y', 'Z']].drop_duplicates()
# 创建插值网格
min_x, max_x = self.coord_df['X'].min(), self.coord_df['X'].max()
min_y, max_y = self.coord_df['Y'].min(), self.coord_df['Y'].max()
min_z, max_z = self.coord_df['Z'].min(), self.coord_df['Z'].max()
grid_points = 30
self.x_grid = np.linspace(min_x - 10, max_x + 10, grid_points)
self.y_grid = np.linspace(min_y - 10, max_y + 10, grid_points)
self.z_grid = np.linspace(min_z - 5, max_z + 10, grid_points)
self.X_grid, self.Y_grid, self.Z_grid = np.meshgrid(
self.x_grid, self.y_grid, self.z_grid, indexing='ij'
)
print(f"预处理完成: {len(self.dates)}天数据, 网格分辨率{grid_points}")
def plot_temperature_time_series(self):
"""绘制优化线宽的温度时间序列图 - 线宽缩放到0.25倍"""
print("绘制温度时间序列图...")
fig, axes = plt.subplots(2, 1, figsize=(15, 12))
point_ids = self.monitoring_points['测点ID'].unique()
# 温度时间序列图 - 线宽缩放到0.25倍
for point_id in point_ids:
point_data = self.merged_df[self.merged_df['测点ID'] == point_id].sort_values('时间')
freeze_mask = point_data['温度'] <= 0
# 使用缩放到0.25倍的线宽
axes[0].plot(point_data['时间'], point_data['温度'],
linewidth=0.25, alpha=0.7,
label=f'测点{point_id}' if point_id == point_ids[0] else "")
if freeze_mask.any():
freeze_times = point_data.loc[freeze_mask, '时间']
freeze_temps = point_data.loc[freeze_mask, '温度']
axes[0].scatter(freeze_times, freeze_temps, color='red', s=10, alpha=0.6)
axes[0].axhline(y=0, color='r', linestyle='--', alpha=0.7, label='冻结温度 (0°C)')
axes[0].set_title('各测点温度时间序列 (线宽0.25)', fontsize=14)
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# 冻结测点数量时间序列
freeze_counts = [len(self.merged_df[(self.merged_df['日期'] == date) &
(self.merged_df['温度'] <= 0)])
for date in self.dates]
axes[1].plot(self.dates, freeze_counts, 'bo-', linewidth=1, markersize=3)
axes[1].set_title('每日冻结测点数量变化', fontsize=14)
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(os.path.join(self.output_dir, "优化线宽温度时间序列图.png"), dpi=300)
plt.close()
print("已保存温度时间序列图")
def create_ice_wall_effect(self, ax, freezing_points):
"""创建冰柱扩散成冰墙的效果"""
if len(freezing_points) < 3:
return
points = freezing_points[['X', 'Y', 'Z']].values
temperatures = freezing_points['温度'].values
# 创建冰墙表面效果
try:
# 使用凸包算法创建冰墙表面
from scipy.spatial import ConvexHull
if len(points) >= 4:
hull = ConvexHull(points[:, :2]) # 只在XY平面创建凸包
# 为每个凸包顶点添加高度信息
for simplex in hull.simplices:
# 创建冰墙多边形
vertices = []
for idx in simplex:
point = points[idx]
# 创建从地面到测点高度的冰柱
base_point = [point[0], point[1], points[:, 2].min()]
vertices.append([point[0], point[1], point[2]])
vertices.append([base_point[0], base_point[1], base_point[2]])
if len(vertices) >= 3:
# 创建半透明的冰面
poly = Poly3DCollection([vertices], alpha=0.3,
facecolor='lightblue',
edgecolor='blue', linewidth=0.5)
ax.add_collection3d(poly)
except Exception as e:
print(f"冰墙效果创建失败: {e}")
def generate_freezing_cloud_series(self):
"""生成4小时间隔冻结壁云图序列 - 修改为4小时间隔"""
print("生成4小时间隔冻结壁云图序列...")
# 确定冻结时间范围
freeze_mask = self.merged_df['温度'] <= 0
if not freeze_mask.any():
print("未检测到冻结数据")
return
start_time = self.merged_df.loc[freeze_mask, '时间'].min()
end_time = self.merged_df.loc[freeze_mask, '时间'].max()
# 生成4小时间隔的时间点 - 修改为4小时
current_time = start_time
time_points = []
while current_time <= end_time:
time_points.append(current_time)
current_time += timedelta(hours=4) # 改为4小时
# 按天分组
daily_groups = {}
for t in time_points:
day = t.date()
daily_groups.setdefault(day, []).append(t)
# 生成每日组图
for day, times in daily_groups.items():
fig = plt.figure(figsize=(20, 12))
fig.suptitle(f'冻结壁演化 - {day}', fontsize=16)
plot_count = min(len(times), 6) # 最多6个子图
for i, t in enumerate(times[:plot_count], 1):
ax = fig.add_subplot(2, 3, i, projection='3d')
self.plot_optimized_cloud(ax, t) # 使用优化后的云图绘制方法
plt.tight_layout(rect=[0, 0, 1, 0.95])
plt.savefig(os.path.join(self.output_dir, f"冻结壁组图_{day.strftime('%Y%m%d')}.png"),
dpi=300, bbox_inches='tight')
plt.close()
print(f"已保存{day}冻结壁组图")
def plot_optimized_cloud(self, ax, time_point):
"""优化后的冻结壁云图绘制 - 去除坐标线框,保留温度图例"""
# 获取当前时间点数据
time_mask = (self.merged_df['时间'] >= time_point - timedelta(minutes=30)) & \
(self.merged_df['时间'] <= time_point + timedelta(minutes=30))
time_data = self.merged_df[time_mask]
if time_data.empty:
return
# 分离冻结和非冻结点
freezing_points = time_data[time_data['温度'] <= 0]
non_freezing_points = time_data[time_data['温度'] > 0]
# 绘制非冻结测点 - 保留温度图例
scatter_plot = None
if not non_freezing_points.empty:
scatter_plot = ax.scatter(non_freezing_points['X'], non_freezing_points['Y'], non_freezing_points['Z'],
c=non_freezing_points['温度'], cmap='coolwarm', s=30, alpha=0.8,
vmin=-20, vmax=20) # 设置固定的温度范围
# 绘制冻结测点 - 冰柱效果
if not freezing_points.empty:
# 使用不同的颜色和形状表示冻结程度
ax.scatter(freezing_points['X'], freezing_points['Y'], freezing_points['Z'],
c='darkblue', s=80, marker='^', alpha=0.9, label='冻结测点')
# 创建冰墙扩散效果
self.create_ice_wall_effect(ax, freezing_points)
# 绘制从地面到冻结点的冰柱
min_z = time_data['Z'].min()
for _, point in freezing_points.iterrows():
ax.plot([point['X'], point['X']],
[point['Y'], point['Y']],
[min_z, point['Z']],
'b-', alpha=0.3, linewidth=2)
# 去除坐标线框
ax.grid(False)
ax.xaxis.pane.set_alpha(0)
ax.yaxis.pane.set_alpha(0)
ax.zaxis.pane.set_alpha(0)
ax.xaxis.pane.set_edgecolor('none')
ax.yaxis.pane.set_edgecolor('none')
ax.zaxis.pane.set_edgecolor('none')
# 设置坐标轴标签
ax.set_xlabel('X (mm)')
ax.set_ylabel('Y (mm)')
ax.set_zlabel('Z (mm)')
# 添加温度图例
if scatter_plot is not None:
cbar = plt.colorbar(scatter_plot, ax=ax, shrink=0.6, aspect=20)
cbar.set_label('温度 (°C)')
# 设置子图标题
ax.set_title(f"{time_point.strftime('%Y-%m-%d %H:%M')}\n冻结测点: {len(freezing_points)}",
fontsize=10, pad=10)
def run_analysis(self):
"""运行完整分析流程"""
print("启动冻结壁分析...")
self.plot_temperature_time_series()
self.generate_freezing_cloud_series()
print("分析完成!")
# ========================= 使用示例 =========================
if __name__ == "__main__":
analyzer = OptimizedFreezingWallAnalysis(
temp_data_file='温度数据.xlsx',
coord_data_file='坐标数据.xlsx',
stl_file='complex_model.stl' # 可选参数
)
analyzer.run_analysis()