|
|
@@ -1,4 +1,5 @@
|
|
|
import os
|
|
|
+import json
|
|
|
import pandas as pd
|
|
|
import numpy as np
|
|
|
import seaborn as sns
|
|
|
@@ -17,7 +18,6 @@ plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体
|
|
|
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
|
|
|
|
|
|
|
|
|
-# TODO 3个叶片净空距离的分布情况,每10圈算一次净空
|
|
|
|
|
|
def result_main():
|
|
|
|
|
|
@@ -39,18 +39,76 @@ def result_main():
|
|
|
if not os.path.exists(csv_file_path):
|
|
|
pd.DataFrame(columns=['时间', '场站', '风机编号', '采样频率',
|
|
|
'叶片1角度偏差', '叶片2角度偏差', '叶片3角度偏差', '相对角度偏差',
|
|
|
- '叶片1净空值', '叶片2净空值', '叶片3净空值', '平均净空值',
|
|
|
+ '叶片1净空值', '叶片2净空值', '叶片3净空值',
|
|
|
'叶片1扭转', '叶片2扭转', '叶片3扭转', '平均扭转',
|
|
|
'振动幅值', '振动主频']).to_csv(csv_file_path, index=False)
|
|
|
|
|
|
return csv_file_path
|
|
|
|
|
|
|
|
|
+def delete_data(names):
|
|
|
+
|
|
|
+ """
|
|
|
+ 删除历史分析数据
|
|
|
+ :param names: 删除条件
|
|
|
+ :return: csv文件路径
|
|
|
+ """
|
|
|
+
|
|
|
+ # 获取当前程序的绝对路径
|
|
|
+ python_interpreter_path = sys.executable
|
|
|
+ project_directory = os.path.dirname(python_interpreter_path)
|
|
|
+ data_folder = os.path.join(project_directory, 'data')
|
|
|
+
|
|
|
+ # CSV文件路径
|
|
|
+ csv_file_path = os.path.join(data_folder, 'history_data.csv')
|
|
|
+ df = pd.read_csv(csv_file_path)
|
|
|
+
|
|
|
+ for name in names:
|
|
|
+ # 检查条件
|
|
|
+ condition = ((df['时间'].str.contains(name[0])) &
|
|
|
+ (df['场站'].str.contains(name[1])) &
|
|
|
+ (df['风机编号'].str.contains(name[2])))
|
|
|
+
|
|
|
+ # 删除满足条件的行
|
|
|
+ df = df[~condition]
|
|
|
+ # 如果需要,可以将修改后的 DataFrame 保存回 CSV 文件
|
|
|
+ df.to_csv(csv_file_path, index=False)
|
|
|
+
|
|
|
+ return csv_file_path
|
|
|
+
|
|
|
+
|
|
|
+def history_data(name):
|
|
|
+
|
|
|
+ """
|
|
|
+ 读取历史分析数据
|
|
|
+ :param name: 接口返回列表
|
|
|
+ :return:
|
|
|
+ """
|
|
|
+
|
|
|
+ wind_name, turbine_code, time_code = name[1], name[2], name[0]
|
|
|
+ # 获取当前程序的绝对路径
|
|
|
+ python_interpreter_path = sys.executable
|
|
|
+ project_directory = os.path.dirname(python_interpreter_path)
|
|
|
+ data_folder = os.path.join(project_directory, 'data')
|
|
|
+
|
|
|
+ time_code_cleaned = time_code.replace("-", "").replace(":", "").replace(" ", "")
|
|
|
+ json_filename = f"{wind_name}_{turbine_code}_{time_code_cleaned}.json"
|
|
|
+ json_file_path = os.path.join(data_folder, json_filename)
|
|
|
+
|
|
|
+ if not os.path.exists(json_file_path):
|
|
|
+ raise ValueError("文件不存在")
|
|
|
+ with open(json_file_path, 'r') as f:
|
|
|
+ data = json.load(f)
|
|
|
+
|
|
|
+ return data
|
|
|
+
|
|
|
+
|
|
|
def data_analyse(path: List[str]):
|
|
|
|
|
|
"""
|
|
|
创建data目录,把分析数据保存到历史记录中,同时返回全量分析数据
|
|
|
"""
|
|
|
+
|
|
|
locate_file = path[0]
|
|
|
measure_file = path[1]
|
|
|
noise_reduction = 0.000001 # 如果一个距离值的所有样本量小于总样本量的noise_reduction,则被去掉
|
|
|
@@ -89,46 +147,66 @@ def data_analyse(path: List[str]):
|
|
|
tower_dist_root = ff.tower_cal(filtered_data_root, start_root, end_root, sampling_fq_1)
|
|
|
lowpass_data, fft_x, fft_y, tower_freq, tower_max= ff.process_fft(filtered_data_cen, sampling_fq)
|
|
|
|
|
|
- result_line_tip, result_scatter_tip, border_rows_tip, cycle_len_tip \
|
|
|
+ result_line_tip, result_scatter_tip, border_rows_tip, cycle_len_tip, min_tip \
|
|
|
= data_normalize(filtered_data_tip, start_tip, end_tip)
|
|
|
- result_line_root, result_scatter_root, border_rows_root, cycle_len_root \
|
|
|
+ result_line_root, result_scatter_root, border_rows_root, cycle_len_root, min_root \
|
|
|
= data_normalize(filtered_data_root, start_root, end_root)
|
|
|
|
|
|
result_avg_tip, result_diff_tip = blade_shape(result_line_tip)
|
|
|
result_avg_root, result_diff_root = blade_shape(result_line_root)
|
|
|
|
|
|
border_rows_tip_new, angle_tip_new = coordinate_normalize(border_rows_tip, angle_tip)
|
|
|
- print('新俯仰角' + str(angle_tip_new))
|
|
|
- print('轮毂中心距离' + str(dist_cen))
|
|
|
|
|
|
tip_r = radius_cal(border_rows_tip_new, angle_tip_new, dist_cen, angle_cen, axial_inclination, angle_cone)
|
|
|
root_r = radius_cal(border_rows_root, angle_root, dist_cen, angle_cen, axial_inclination, angle_cone)
|
|
|
|
|
|
pitch_angle_tip, aero_dist_tip, v_speed_tip, cen_blade_tip = (
|
|
|
blade_angle_aero_dist(border_rows_tip, tip_r, cycle_len_tip, tower_dist_tip, angle_tip_new))
|
|
|
- pitch_angle_root, aero_dist_root, v_speed_root = (
|
|
|
+ pitch_angle_root, aero_dist_root, v_speed_root, cen_blade_root = (
|
|
|
blade_angle_aero_dist(border_rows_root, root_r, cycle_len_root, tower_dist_root, angle_root))
|
|
|
|
|
|
- dist_distribute = blade_dist_distribute_cal(filtered_data_tip, start_tip, end_tip,
|
|
|
- tower_dist_tip, angle_tip_new, cen_blade_tip)
|
|
|
-
|
|
|
-
|
|
|
- plot_data(result_line_tip, 'line', 'data1')
|
|
|
- # plot_data(result_diff_tip, 'line', 'data_diff_1')
|
|
|
- plot_data(result_scatter_tip, 'scatter', 'data1')
|
|
|
- plot_data(result_line_root, 'line', 'data2')
|
|
|
- # plot_data(result_diff_root, 'line', 'data_diff_2')
|
|
|
- plot_data(result_scatter_root, 'scatter', 'data2')
|
|
|
+ # 将列表转换为 numpy 数组
|
|
|
+ cen_blade_tip_array = np.array(cen_blade_tip)
|
|
|
+ min_tip_array = np.array(min_tip)
|
|
|
+ abs_diff = np.abs(cen_blade_tip_array - min_tip_array) # 计算差值的绝对值
|
|
|
+ blade_dist_tip = abs_diff * np.cos(np.deg2rad(angle_tip_new))
|
|
|
+ blade_dist_tip.tolist() # 如果需要将结果转换回列表
|
|
|
|
|
|
+ dist_distribute = blade_dist_distribute_cal(filtered_data_tip, start_tip, end_tip,
|
|
|
+ tower_dist_tip, angle_tip_new, blade_dist_tip)
|
|
|
+ dist_distribute = [df.round(5) for df in dist_distribute]
|
|
|
+
|
|
|
+ # 获取每个 DataFrame 第二列的最小值和最大值,以及它们对应的第一列的值,并分别保存在列表中
|
|
|
+ min_values = []
|
|
|
+ min_keys = []
|
|
|
+ max_values = []
|
|
|
+ max_keys = []
|
|
|
+ mean_values = []
|
|
|
+ for df in dist_distribute:
|
|
|
+ second_col_min = df[df.columns[1]].min()
|
|
|
+ second_col_max = df[df.columns[1]].max()
|
|
|
+ min_row = df[df[df.columns[1]] == second_col_min]
|
|
|
+ max_row = df[df[df.columns[1]] == second_col_max]
|
|
|
+ min_values.append(second_col_min)
|
|
|
+ min_keys.append(min_row.iloc[0][df.columns[0]])
|
|
|
+ max_values.append(second_col_max)
|
|
|
+ max_keys.append(max_row.iloc[0][df.columns[0]])
|
|
|
+
|
|
|
+ for i in range(3):
|
|
|
+ mean_values.append(round((max_values[i] + min_values[i]) / 2, 2))
|
|
|
|
|
|
for df in result_line_tip:
|
|
|
first_column = df.iloc[:, 0]
|
|
|
+ sec_column = df.iloc[:, 1]
|
|
|
df.iloc[:, 0] = first_column * v_speed_tip
|
|
|
+ df.iloc[:, 1] = sec_column * np.cos(np.deg2rad(angle_tip_new))
|
|
|
|
|
|
for df in result_line_root:
|
|
|
first_column = df.iloc[:, 0]
|
|
|
+ sec_column = df.iloc[:, 1]
|
|
|
df.iloc[:, 0] = first_column * v_speed_root
|
|
|
- print(v_speed_tip, v_speed_root)
|
|
|
+ df.iloc[:, 1] = sec_column * np.cos(np.deg2rad(angle_root))
|
|
|
+
|
|
|
|
|
|
avg_tip = result_avg_tip.iloc[:, 0]
|
|
|
result_avg_tip.iloc[:, 0] = avg_tip * v_speed_tip
|
|
|
@@ -145,7 +223,6 @@ def data_analyse(path: List[str]):
|
|
|
data_root.iloc[:, 0] = data_root.iloc[:, 0] / 5000000
|
|
|
lowpass_data.iloc[:, 0] = lowpass_data.iloc[:, 0] / 5000000
|
|
|
|
|
|
- print('time_length:' + str(data_root.iloc[-1, 0]))
|
|
|
|
|
|
return_list.append(time_code)
|
|
|
return_list.append(wind_name)
|
|
|
@@ -155,10 +232,9 @@ def data_analyse(path: List[str]):
|
|
|
return_list.append(pitch_angle_root[1])
|
|
|
return_list.append(pitch_angle_root[2])
|
|
|
return_list.append(pitch_angle_root[3])
|
|
|
- return_list.append(aero_dist_tip[0])
|
|
|
- return_list.append(aero_dist_tip[1])
|
|
|
- return_list.append(aero_dist_tip[2])
|
|
|
- return_list.append(aero_dist_tip[3])
|
|
|
+ return_list.append(mean_values[0])
|
|
|
+ return_list.append(mean_values[1])
|
|
|
+ return_list.append(mean_values[2])
|
|
|
return_list.append(twist_1)
|
|
|
return_list.append(twist_2)
|
|
|
return_list.append(twist_3)
|
|
|
@@ -166,17 +242,11 @@ def data_analyse(path: List[str]):
|
|
|
return_list.append(tower_max)
|
|
|
return_list.append(tower_freq)
|
|
|
|
|
|
- print(result_line_tip[0].iloc[:, 0])
|
|
|
- print(result_line_root[0].iloc[:, 0])
|
|
|
- print('振动主频' + str(tower_freq))
|
|
|
- print('振动幅值' + str(tower_max))
|
|
|
-
|
|
|
-
|
|
|
# 将return_list转换为DataFrame并追加到CSV文件
|
|
|
df_new_row = pd.DataFrame([return_list],
|
|
|
columns=['时间', '场站', '风机编号', '采样频率',
|
|
|
'叶片1角度偏差', '叶片2角度偏差', '叶片3角度偏差', '相对角度偏差',
|
|
|
- '叶片1净空值', '叶片2净空值', '叶片3净空值', '平均净空值',
|
|
|
+ '叶片1净空值', '叶片2净空值', '叶片3净空值',
|
|
|
'叶片1扭转', '叶片2扭转', '叶片3扭转', '平均扭转',
|
|
|
'振动幅值', '振动主频'])
|
|
|
|
|
|
@@ -268,10 +338,30 @@ def data_analyse(path: List[str]):
|
|
|
'blade_relate': pitch_angle_root[3]
|
|
|
},
|
|
|
'aero_dist': {
|
|
|
- 'blade_1': aero_dist_tip[0],
|
|
|
- 'blade_2': aero_dist_tip[1],
|
|
|
- 'blade_3': aero_dist_tip[2],
|
|
|
- 'blade_avg': aero_dist_tip[3]
|
|
|
+ 'first_blade': {
|
|
|
+ 'x_min': min_keys[0],
|
|
|
+ 'y_min': min_values[0],
|
|
|
+ 'x_max': max_keys[0],
|
|
|
+ 'y_max': max_values[0],
|
|
|
+ 'y_diff': np.abs(max_values[0] - min_values[0]),
|
|
|
+ 'y_ava': mean_values[0]
|
|
|
+ },
|
|
|
+ 'second_blade': {
|
|
|
+ 'x_min': min_keys[1],
|
|
|
+ 'y_min': min_values[1],
|
|
|
+ 'x_max': max_keys[1],
|
|
|
+ 'y_max': max_values[1],
|
|
|
+ 'y_diff': np.abs(max_values[1] - min_values[1]),
|
|
|
+ 'y_ava': mean_values[1]
|
|
|
+ },
|
|
|
+ 'third_blade': {
|
|
|
+ 'x_min': min_keys[2],
|
|
|
+ 'y_min': min_values[2],
|
|
|
+ 'x_max': max_keys[2],
|
|
|
+ 'y_max': max_values[2],
|
|
|
+ 'y_diff': np.abs(max_values[2] - min_values[2]),
|
|
|
+ 'y_ava': mean_values[2]
|
|
|
+ }
|
|
|
},
|
|
|
'blade_twist': {
|
|
|
'blade_1': twist_1,
|
|
|
@@ -301,12 +391,39 @@ def data_analyse(path: List[str]):
|
|
|
if not os.path.exists(csv_file_path):
|
|
|
pd.DataFrame(columns=['时间', '场站', '风机编号', '采样频率',
|
|
|
'叶片1角度偏差', '叶片2角度偏差', '叶片3角度偏差', '相对角度偏差',
|
|
|
- '叶片1净空值', '叶片2净空值', '叶片3净空值', '平均净空值',
|
|
|
+ '叶片1净空值', '叶片2净空值', '叶片3净空值',
|
|
|
'叶片1扭转', '叶片2扭转', '叶片3扭转', '平均扭转',
|
|
|
'振动幅值', '振动主频']).to_csv(csv_file_path, index=False)
|
|
|
|
|
|
df_new_row.to_csv(csv_file_path, mode='a', header=False, index=False)
|
|
|
+
|
|
|
+ time_code_cleaned = time_code.replace("-", "").replace(":", "").replace(" ", "")
|
|
|
+ json_filename = f"{wind_name}_{turbine_code}_{time_code_cleaned}.json"
|
|
|
+ json_file_path = os.path.join(data_folder, json_filename)
|
|
|
+ with open(json_file_path, 'w') as json_file:
|
|
|
+ json.dump(json_output, json_file, indent=4)
|
|
|
+
|
|
|
print(csv_file_path)
|
|
|
+ print(result_line_tip[0].iloc[:, 0])
|
|
|
+ print(result_line_root[0].iloc[:, 0])
|
|
|
+ print('振动主频' + str(tower_freq))
|
|
|
+ print('振动幅值' + str(tower_max))
|
|
|
+ print('最小值', min_values)
|
|
|
+ print('最小值对应的键', min_keys)
|
|
|
+ print('最大值', max_values)
|
|
|
+ print('最大值对应的键', max_keys)
|
|
|
+ print(v_speed_tip, v_speed_root)
|
|
|
+ print('新俯仰角' + str(angle_tip_new))
|
|
|
+ print('轮毂中心距离' + str(dist_cen))
|
|
|
+ print('time_length:' + str(data_root.iloc[-1, 0]))
|
|
|
+
|
|
|
+ plot_data(result_line_tip, 'line', 'data1')
|
|
|
+ # plot_data(result_diff_tip, 'line', 'data_diff_1')
|
|
|
+ plot_data(result_scatter_tip, 'scatter', 'data1')
|
|
|
+ plot_data(result_line_root, 'line', 'data2')
|
|
|
+ # plot_data(result_diff_root, 'line', 'data_diff_2')
|
|
|
+ plot_data(result_scatter_root, 'scatter', 'data2')
|
|
|
+ plot_data(dist_distribute, 'scatter', 'dist_distribute')
|
|
|
|
|
|
return json_output
|
|
|
|
|
|
@@ -491,7 +608,7 @@ def cycle_calculate(data_group: pd.DataFrame, noise_threshold: float, min_distan
|
|
|
|
|
|
|
|
|
def data_normalize(data_group: pd.DataFrame, start_points: pd.DataFrame, end_points: pd.DataFrame) \
|
|
|
- -> Tuple[List[pd.DataFrame], List[pd.DataFrame], List[pd.DataFrame], int]:
|
|
|
+ -> Tuple[List[pd.DataFrame], List[pd.DataFrame], List[pd.DataFrame], int, list]:
|
|
|
|
|
|
"""
|
|
|
提取每个叶片的数据并归一化,输出散点图和拟合图
|
|
|
@@ -550,6 +667,7 @@ def data_normalize(data_group: pd.DataFrame, start_points: pd.DataFrame, end_poi
|
|
|
# 数据分组清洗、求平均
|
|
|
turbines_processed = []
|
|
|
turbines_scattered = []
|
|
|
+ min_list = []
|
|
|
sd_time = [-1, -1]
|
|
|
time_list = list(range(0, normalize_cycle, 1000))
|
|
|
# time_list = [(i + 1) * normalize_cycle / fs * 100 for i in range(fs * 100)] # 生成时间序列
|
|
|
@@ -593,6 +711,7 @@ def data_normalize(data_group: pd.DataFrame, start_points: pd.DataFrame, end_poi
|
|
|
end_index = int(len(diff_points) * 0.95)
|
|
|
subset1 = diff_points[start_index:end_index]
|
|
|
sdr_diff = np.max(subset1) * 1.1
|
|
|
+ min_list.append(min(mean_points))
|
|
|
|
|
|
# 找到第一个和最后一个小于 sdr_diff 的序号
|
|
|
first_index = np.where(diff_points < sdr_diff)[0][0]
|
|
|
@@ -672,7 +791,7 @@ def data_normalize(data_group: pd.DataFrame, start_points: pd.DataFrame, end_poi
|
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
- return turbines_processed, turbines_scattered, border_rows, full_cycle
|
|
|
+ return turbines_processed, turbines_scattered, border_rows, full_cycle, min_list
|
|
|
|
|
|
|
|
|
|
|
|
@@ -832,15 +951,16 @@ def plot_data(data, plot_type: str, data_name: str):
|
|
|
|
|
|
print('正在画图......')
|
|
|
time.sleep(1)
|
|
|
+ save_path = "C:/Users/laiwe/Desktop/"
|
|
|
save_name = fr"{data_name}_{plot_type}.png" # 生成文件名
|
|
|
plt.figure(figsize=(300, 150))
|
|
|
|
|
|
if plot_type == 'line':
|
|
|
for df, color in zip(data, ['blue', 'green', 'red']):
|
|
|
- sns.lineplot(data=df, x='time', y='distance', color=color)
|
|
|
+ sns.lineplot(data=df, x=df.iloc[:, 0], y=df.iloc[:, 1], color=color)
|
|
|
elif plot_type == 'scatter':
|
|
|
for df, (size, color) in zip(data, [(50, 'blue'), (25, 'green'), (10, 'red')]):
|
|
|
- sns.scatterplot(data=df, x='time', y='distance', s=size, color=color)
|
|
|
+ sns.scatterplot(data=df, x=df.iloc[:, 0], y=df.iloc[:, 1], s=size, color=color)
|
|
|
else:
|
|
|
raise ValueError("plot_type must be either 'line' or 'scatter'")
|
|
|
|
|
|
@@ -852,7 +972,7 @@ def plot_data(data, plot_type: str, data_name: str):
|
|
|
plt.ylabel('距离(m)', fontsize=100, fontweight='bold') # 添加y轴标签
|
|
|
axy.tick_params(axis='x', labelsize=10, labelcolor='black', width=2) # 设置x轴刻度标签
|
|
|
axy.tick_params(axis='y', labelsize=60, labelcolor='black', width=10) # 设置y轴刻度标签
|
|
|
- plt.savefig(save_name)
|
|
|
+ plt.savefig(save_path + save_name)
|
|
|
plt.close()
|
|
|
abs_path = os.path.abspath(save_name)
|
|
|
print(f" {save_name} 已完成")
|
|
|
@@ -924,7 +1044,7 @@ def blade_dist_distribute_cal(data_group: pd.DataFrame, start_points: pd.DataFra
|
|
|
tower_clearance = [pd.DataFrame() for _ in range(3)]
|
|
|
|
|
|
# 遍历所有起始时间点
|
|
|
- for i in range(0, len(start_times), 2):
|
|
|
+ for i in range(0, len(start_times) - 2, 2):
|
|
|
|
|
|
# 获取当前起始和结束时间点
|
|
|
start_time = start_times[i]
|
|
|
@@ -941,8 +1061,8 @@ def blade_dist_distribute_cal(data_group: pd.DataFrame, start_points: pd.DataFra
|
|
|
segment.loc[:, 'time'] = (segment['time'] - start_time) / ratio
|
|
|
|
|
|
new_df = pd.DataFrame({
|
|
|
- 'clearance': [clearance],
|
|
|
- 'r_speed': [r_speed]
|
|
|
+ 'r_speed': [r_speed],
|
|
|
+ 'clearance': [clearance]
|
|
|
})
|
|
|
|
|
|
# 将结果添加到相应的 turbine 数据框中
|