| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108 |
- import os
- import json
- import pandas as pd
- import numpy as np
- import matplotlib.pyplot as plt
- from typing import Tuple, List
- import warnings
- import sys
- import frequency_filter as ff
- from datetime import datetime
- from scipy.optimize import least_squares, differential_evolution
- from scipy.signal import savgol_filter
- warnings.filterwarnings("ignore", category=FutureWarning)
- plt.rcParams['font.sans-serif'] = ['SimHei']
- plt.rcParams['axes.unicode_minus'] = False
- def result_main():
-
- python_interpreter_path = sys.executable
- project_directory = os.path.dirname(python_interpreter_path)
- data_folder = os.path.join(project_directory, 'data')
-
- if not os.path.exists(data_folder):
- os.makedirs(data_folder)
-
- csv_file_path = os.path.join(data_folder, 'history_data.csv')
-
- if not os.path.exists(csv_file_path):
- pd.DataFrame(columns=['时间', '场站', '风机编号', '采样频率',
- '叶片1角度偏差', '叶片2角度偏差', '叶片3角度偏差', '相对角度偏差',
- '叶片1净空值', '叶片2净空值', '叶片3净空值',
- '叶片1扭转', '叶片2扭转', '叶片3扭转', '平均扭转',
- '振动幅值', '振动主频']).to_csv(csv_file_path, index=False)
- return csv_file_path
- def delete_data(name):
- python_interpreter_path = sys.executable
- project_directory = os.path.dirname(python_interpreter_path)
- data_folder = os.path.join(project_directory, 'data')
-
- csv_file_path = os.path.join(data_folder, 'history_data.csv')
- df = pd.read_csv(csv_file_path)
- condition = ((df['时间'].astype(str).str.contains(name[0])) &
- (df['场站'].astype(str).str.contains(name[1])) &
- (df['风机编号'].astype(str).str.contains(name[2])))
- df = df[~condition]
-
- df.to_csv(csv_file_path, index=False)
- return csv_file_path
- def history_data(name):
- time_code = name[0]
- wind_name = name[1]
- turbine_code = name[2]
-
- 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]):
- locate_file = path[0]
- measure_file = path[1]
- noise_reduction = 0.000001
- min_difference = 1.5
- angle_cone = float(path[2])
- axial_inclination = float(path[3])
- lift_up_limit = float(path[4])
- group_length = [10000, 10000, 5000, 10000]
- return_list = []
- wind_name, turbine_code, time_code, sampling_fq, angle_nan, angle_cen = find_param(locate_file)
- wind_name_1, turbine_code_1, time_code_1, sampling_fq_1, angle_flange, angle_root = find_param(measure_file)
- sampling_fq_1 = sampling_fq_1 * 1000
- sampling_fq = sampling_fq * 1000
- data_nan, data_cen = process_data(locate_file)
- data_flange, data_root = process_data(measure_file)
- if lift_up_limit >= 0.1:
- discrete_values = np.arange(0, 0.101, 0.001)
- condition = data_flange['distance'] > lift_up_limit
- n = condition.sum()
- random_discrete = np.random.choice(discrete_values, size=n)
- data_flange.loc[condition, 'distance'] = lift_up_limit + 3 + random_discrete
- elif np.abs(lift_up_limit) < 0.1:
- pass
- else:
- raise ValueError("lift_up_limit error.")
- start_flange, end_flange, filtered_data_flange = cycle_calculate(data_flange, noise_reduction, min_difference)
- start_root, end_root, filtered_data_root = cycle_calculate(data_root, noise_reduction, min_difference)
- start_nan, end_nan, filtered_data_nan = cycle_calculate(data_nan, noise_reduction, min_difference)
- filtered_data_cen = tower_filter(data_cen, noise_reduction)
- dist_cen = np.mean(filtered_data_cen.iloc[:, 1].tolist())
- filtered_data_cen.iloc[:, 1] = filtered_data_cen.iloc[:, 1] * np.cos(np.deg2rad(angle_cen + axial_inclination))
- tower_dist_flange = ff.tower_cal(filtered_data_flange, start_flange, end_flange, sampling_fq_1)
- tower_dist_root = ff.tower_cal(filtered_data_root, start_root, end_root, sampling_fq_1)
- tower_dist_nan = ff.tower_cal(filtered_data_nan, start_nan, end_nan, sampling_fq)
- lowpass_data, fft_x, fft_y, tower_freq, tower_max = ff.process_fft(filtered_data_cen, sampling_fq)
- result_line_flange, result_scatter_flange, border_rows_flange, cycle_len_flange, min_flange \
- = data_normalize(filtered_data_flange, start_flange, end_flange, group_length[0])
- result_line_root, result_scatter_root, border_rows_root, cycle_len_root, min_root \
- = data_normalize(filtered_data_root, start_root, end_root, group_length[1])
- result_line_nan, result_scatter_nan, border_rows_nan, cycle_len_nan, min_nan \
- = data_normalize(filtered_data_nan, start_nan, end_nan, group_length[2])
- result_avg_flange, result_diff_flange = blade_shape(result_line_flange)
- result_avg_root, result_diff_root = blade_shape(result_line_root)
- border_rows_flange_new, angle_flange_new = coordinate_normalize(border_rows_flange, angle_flange)
- border_rows_nan_new, angle_nan_new = coordinate_normalize(border_rows_nan, angle_nan)
- flange_ava = pd.concat([df['distance'] for df in border_rows_flange_new]).mean(numeric_only=True).mean()
- root_ava = pd.concat([df['distance'] for df in border_rows_root]).mean(numeric_only=True).mean()
- d_radius = np.abs((flange_ava * np.cos(np.deg2rad(angle_flange_new))
- - root_ava * np.cos(np.deg2rad(angle_root))) * np.sin(np.deg2rad(axial_inclination))
- + (flange_ava * np.sin(np.deg2rad(angle_flange_new))
- - root_ava * np.sin(np.deg2rad(angle_root))) * np.cos(np.deg2rad(axial_inclination)))
- flange_root_dist = np.sqrt(flange_ava ** 2 + root_ava ** 2 - 2 * flange_ava * root_ava * np.cos(np.deg2rad(angle_flange_new - angle_root)))
- flange_r = radius_cal(border_rows_flange_new, angle_flange_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)
- nan_r = radius_cal(border_rows_nan_new, angle_nan_new, dist_cen, angle_cen, axial_inclination, angle_cone)
- blade_axis, blade_axis_tuple, result_line_flange = blade_axis_cal(filtered_data_flange, start_flange, end_flange,
- angle_flange + angle_cone + axial_inclination, group_length[3], flange_r)
- blade_axis_new, angle_flange_new = flange_coordinate_normalize(blade_axis, angle_flange)
- blade_axis_tuple_new, angle_flange_new = flange_coordinate_normalize(blade_axis_tuple, angle_flange)
- if np.abs((root_r - flange_r) - d_radius) > 0.5:
- root_r = flange_r + d_radius
- if np.abs(flange_root_dist - d_radius) > 0.5:
- root_r = flange_r + flange_root_dist
- blade_axis_new["中心y"] = blade_axis_new["中心y"] - (flange_ava - root_ava)
- blade_axis_tuple_new["中心y"] = blade_axis_tuple_new["中心y"] - (flange_ava - root_ava)
- aero_dist_flange, v_speed_flange, cen_blade_flange = (
- blade_angle_aero_dist(border_rows_flange, flange_r, cycle_len_flange, tower_dist_flange, angle_flange_new))
- aero_dist_nan, v_speed_nan, cen_blade_nan = (
- blade_angle_aero_dist(border_rows_nan_new, nan_r, cycle_len_nan, tower_dist_nan, angle_nan_new))
- pitch_angle_root, v_speed_root, blade_axis_tuple_new = (
- blade_angle(border_rows_root, blade_axis_tuple_new, root_r, cycle_len_root, angle_root + angle_cone + axial_inclination))
- blade_axis_tuple_new["中心y"] = blade_axis_tuple_new["中心y"]*np.cos(np.deg2rad(angle_root + angle_cone + axial_inclination))
- cen_blade_nan_array = np.array(cen_blade_nan)
- min_nan_array = np.array(min_nan)
- abs_diff_nan = np.abs(cen_blade_nan_array - min_nan_array)
- blade_dist_nan = abs_diff_nan * np.cos(np.deg2rad(angle_nan_new))
- blade_dist_nan.tolist()
- dist_distribute_nan = blade_dist_distribute_cal(filtered_data_nan, start_nan, end_nan,
- tower_dist_nan, angle_nan_new + angle_cone + axial_inclination, blade_dist_nan)
- dist_distribute = [df.round(5) for df in dist_distribute_nan]
-
- 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(round(second_col_min, 2))
- min_keys.append(round(min_row.iloc[0][df.columns[0]], 2))
- max_values.append(round(second_col_max, 2))
- max_keys.append(round(max_row.iloc[0][df.columns[0]], 2))
- for i in range(3):
- mean_values.append(round((max_values[i] + min_values[i]) / 2, 2))
- for i in range(3):
- df = result_line_root[i]
- first_column = df.iloc[:, 0]
- sec_column = df.iloc[:, 1]
- df.iloc[:, 0] = first_column * v_speed_root
- min_time = df.iloc[:, 0].min()
- df.iloc[:, 0] -= min_time
- blade_axis_tuple_new.iloc[i, 1] -= min_time
- df.iloc[:, 1] = sec_column * np.cos(np.deg2rad(angle_root + angle_cone + axial_inclination))
- avg_flange = result_avg_flange.iloc[:, 0]
- result_avg_flange.iloc[:, 0] = avg_flange * v_speed_flange
- avg_root = result_avg_root.iloc[:, 0]
- result_avg_root.iloc[:, 0] = avg_root * v_speed_root
- pitch_angle_flange = [0, 0, 0]
- twist_1 = round(np.abs(pitch_angle_root[0] - pitch_angle_flange[0]), 2)
- twist_2 = round(np.abs(pitch_angle_root[1] - pitch_angle_flange[1]), 2)
- twist_3 = round(np.abs(pitch_angle_root[2] - pitch_angle_flange[2]), 2)
- twist_avg = round((twist_1 + twist_2 + twist_3) / 3, 2)
- sampling_num = int(0.015 * sampling_fq_1)
- data_flange.iloc[:, 0] = data_flange.iloc[:, 0] / 5000000
- data_root.iloc[:, 0] = data_root.iloc[:, 0] / 5000000
- lowpass_data.iloc[:, 0] = lowpass_data.iloc[:, 0] / 5000000
- rotated_root = [pd.DataFrame() for _ in range(3)]
- for i in range(3):
- angle_rad = np.deg2rad(-pitch_angle_root[i])
- rotation_matrix = np.array([
- [np.cos(angle_rad), -np.sin(angle_rad)],
- [np.sin(angle_rad), np.cos(angle_rad)]
- ])
- center_x = blade_axis_tuple_new.iloc[i, 1]
- center_y = blade_axis_tuple_new.iloc[i, 2]
- rotated_points = result_line_root[i].copy()
- for idx, row in result_line_root[i].iterrows():
- x = row.iloc[0]
- y = row.iloc[1]
- translated_x = x - center_x
- translated_y = y - center_y
- rotated = rotation_matrix @ np.array([translated_x, translated_y])
- final_x = rotated[0] + center_x
- final_y = rotated[1] + center_y
- rotated_points.iloc[idx, 0] = final_x
- rotated_points.iloc[idx, 1] = final_y
- rotated_root[i % 3] = pd.concat([rotated_root[i % 3], rotated_points])
- return_list.append(str(time_code))
- return_list.append(str(wind_name))
- return_list.append(str(turbine_code))
- return_list.append(sampling_fq_1)
- return_list.append(pitch_angle_root[0])
- return_list.append(pitch_angle_root[1])
- return_list.append(pitch_angle_root[2])
- return_list.append(pitch_angle_root[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)
- return_list.append(twist_avg)
- return_list.append(tower_max)
- return_list.append(tower_freq)
-
- df_new_row = pd.DataFrame([return_list],
- columns=['时间', '场站', '风机编号', '采样频率',
- '叶片1角度偏差', '叶片2角度偏差', '叶片3角度偏差', '相对角度偏差',
- '叶片1净空值', '叶片2净空值', '叶片3净空值',
- '叶片1扭转', '叶片2扭转', '叶片3扭转', '平均扭转',
- '振动幅值', '振动主频'])
- json_output = {
- 'original_plot': {
- 'blade_tip': {
- 'xdata': data_flange.iloc[:, 0].tolist()[::sampling_num],
- 'ydata': data_flange.iloc[:, 1].tolist()[::sampling_num]
- },
- 'blade_root': {
- 'xdata': data_root.iloc[:, 0].tolist()[::sampling_num],
- 'ydata': data_root.iloc[:, 1].tolist()[::sampling_num]
- }
- },
- 'fft_plot': {
- 'lowpass': {
- 'xdata': lowpass_data['time'].tolist()[::sampling_num],
- 'ydata': lowpass_data['distance_filtered'].tolist()[::sampling_num],
- 'xmax': max(lowpass_data['time'].tolist()),
- 'xmin': min(lowpass_data['time'].tolist()),
- 'ymax': max(lowpass_data['distance_filtered'].tolist()) + 0.02,
- 'ymin': min(lowpass_data['distance_filtered'].tolist()) - 0.02
- },
- 'fft': {
- 'xdata': fft_x,
- 'ydata': fft_y,
- 'xmax': max(fft_x),
- 'xmin': min(fft_x),
- 'ymax': max(fft_y) + 0.02,
- 'ymin': 0
- }
- },
- 'blade_tip': {
- 'first_blade': {
- 'xdata': result_line_flange[0].iloc[:, 0].tolist(),
- 'ydata': result_line_flange[0].iloc[:, 1].tolist()
- },
- 'second_blade': {
- 'xdata': result_line_flange[1].iloc[:, 0].tolist(),
- 'ydata': result_line_flange[1].iloc[:, 1].tolist()
- },
- 'third_blade': {
- 'xdata': result_line_flange[2].iloc[:, 0].tolist(),
- 'ydata': result_line_flange[2].iloc[:, 1].tolist()
- },
- 'avg_blade': {
- 'xdata': result_avg_flange.iloc[:, 0].tolist(),
- 'ydata': result_avg_flange.iloc[:, 1].tolist()
- },
- 'blade_center': {
- 'xdata': blade_axis_tuple.iloc[:, 1].tolist(),
- 'ydata': blade_axis_tuple.iloc[:, 2].tolist()
- }
- },
- 'blade_root': {
- 'first_blade': {
- 'xdata': result_line_root[0].iloc[:, 0].tolist(),
- 'ydata': result_line_root[0].iloc[:, 1].tolist()
- },
- 'second_blade': {
- 'xdata': result_line_root[1].iloc[:, 0].tolist(),
- 'ydata': result_line_root[1].iloc[:, 1].tolist()
- },
- 'third_blade': {
- 'xdata': result_line_root[2].iloc[:, 0].tolist(),
- 'ydata': result_line_root[2].iloc[:, 1].tolist()
- },
- 'avg_blade': {
- 'xdata': result_avg_root.iloc[:, 0].tolist(),
- 'ydata': result_avg_root.iloc[:, 1].tolist()
- },
- 'first_rotate_blade': {
- 'xdata': rotated_root[0].iloc[:, 0].tolist(),
- 'ydata': rotated_root[0].iloc[:, 1].tolist()
- },
- 'second_rotate_blade': {
- 'xdata': rotated_root[1].iloc[:, 0].tolist(),
- 'ydata': rotated_root[1].iloc[:, 1].tolist()
- },
- 'third_rotate_blade': {
- 'xdata': rotated_root[2].iloc[:, 0].tolist(),
- 'ydata': rotated_root[2].iloc[:, 1].tolist()
- },
- 'blade_center': {
- 'xdata': blade_axis_tuple_new.iloc[:, 1].tolist(),
- 'ydata': blade_axis_tuple_new.iloc[:, 2].tolist()
- }
- },
- 'dist_distribution': {
- 'first_blade': {
- 'xdata': dist_distribute[0].iloc[:, 0].tolist(),
- 'ydata': dist_distribute[0].iloc[:, 1].tolist()
- },
- 'second_blade': {
- 'xdata': dist_distribute[1].iloc[:, 0].tolist(),
- 'ydata': dist_distribute[1].iloc[:, 1].tolist()
- },
- 'third_blade': {
- 'xdata': dist_distribute[2].iloc[:, 0].tolist(),
- 'ydata': dist_distribute[2].iloc[:, 1].tolist()
- }
- },
- 'analyse_table': {
- 'pitch_angle_diff': {
- 'blade_1': pitch_angle_root[0],
- 'blade_2': pitch_angle_root[1],
- 'blade_3': pitch_angle_root[2],
- 'blade_relate': pitch_angle_root[3]
- },
- 'aero_dist': {
- '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,
- 'blade_2': twist_2,
- 'blade_3': twist_3,
- 'blade_avg': twist_avg
- },
- 'tower_vibration': {
- 'max_vibration': tower_max,
- 'main_vibration_freq': tower_freq
- }
- }
- }
-
- python_interpreter_path = sys.executable
- project_directory = os.path.dirname(python_interpreter_path)
- data_folder = os.path.join(project_directory, 'data')
-
- if not os.path.exists(data_folder):
- os.makedirs(data_folder)
-
- csv_file_path = os.path.join(data_folder, 'history_data.csv')
-
- if not os.path.exists(csv_file_path):
- pd.DataFrame(columns=['时间', '场站', '风机编号', '采样频率',
- '叶片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)
- return json_output
- def process_data(file_path):
-
- data = pd.read_csv(file_path, usecols=[1, 3, 4, 8, 9], header=None, engine='c')
- data = data.head(int(len(data) * 0.95))
-
- max_value = data.iloc[:, 0].max()
- max_index = data.iloc[:, 0].idxmax()
- min_index = data.iloc[:, 0].idxmin()
-
- if min_index == max_index + 1:
-
- data.iloc[min_index:, 0] += max_value
-
- last_time = data.iloc[-1, 0]
- first_time = data.iloc[0, 0]
- data = data[data.iloc[:, 0] >= first_time]
- data = data[data.iloc[:, 0] <= last_time]
- data.reset_index(drop=True, inplace=True)
-
- min_time = data.iloc[:, 0].min()
- data.iloc[:, 0] -= min_time
-
- data_1 = data.iloc[:, [0, 1, 2]]
- data_2 = data.iloc[:, [0, 3, 4]]
- data_1.columns = ['time', 'distance', 'grey']
- data_2.columns = ['time', 'distance', 'grey']
- return data_1, data_2
- def tower_filter(data_group: pd.DataFrame, noise_threshold: float):
- distance_counts = data_group['distance'].value_counts(normalize=True)
- noise_distance_threshold = distance_counts[distance_counts < noise_threshold].index
- noise_indices = data_group[data_group['distance'].isin(noise_distance_threshold)].index
- data_group.loc[noise_indices, 'distance'] = np.nan
-
- top_5_distances = distance_counts.head(5).index
- mean_values = data_group[data_group['distance'].isin(top_5_distances)]['distance'].mean()
- data_group.loc[(data_group['distance'] < mean_values * 0.9) | (
- data_group['distance'] > mean_values * 1.1), 'distance'] = np.nan
-
- data_group['distance'] = data_group['distance'].fillna(method='ffill')
- filtered_data = data_group
- return filtered_data
- def cycle_calculate(data_group: pd.DataFrame, noise_threshold: float, min_distance: float):
-
- distance_counts = data_group['distance'].value_counts(normalize=True)
- noise_distance_threshold = distance_counts[distance_counts < noise_threshold].index
- noise_indices = data_group[data_group['distance'].isin(noise_distance_threshold)].index
- data_group.loc[noise_indices, 'distance'] = np.nan
- if distance_counts.get(0, 0) >= 0.1:
- top_5_distances = distance_counts[distance_counts.index != 0].head(5).index
- mean_values = data_group[data_group['distance'].isin(top_5_distances)]['distance'].mean()
- data_group.loc[((data_group['distance'] > 0) & (data_group['distance'] < mean_values - 30)) |
- (data_group['distance'] > mean_values * 1.1), 'distance'] = np.nan
- else:
- top_5_distances = distance_counts[distance_counts.index != 0].head(5).index
- mean_values = data_group[data_group['distance'].isin(top_5_distances)]['distance'].mean()
- data_group.loc[(data_group['distance'] < mean_values-30) | (
- data_group['distance'] > mean_values*1.1), 'distance'] = np.nan
-
- data_group['distance'] = data_group['distance'].fillna(method='ffill')
- filtered_data = data_group
-
- filtered_data['distance_diff'] = filtered_data['distance'].diff()
- large_diff_indices = filtered_data[filtered_data['distance_diff'] > min_distance].index
- small_diff_indices = filtered_data[filtered_data['distance_diff'] < -min_distance].index
- filtered_data = filtered_data.drop(columns=['distance_diff'])
- start_points = pd.DataFrame()
- end_points = pd.DataFrame()
-
- for idx in large_diff_indices:
-
- current_distance = filtered_data.loc[idx, 'distance']
- next_rows_large = filtered_data.loc[idx - 500: idx - 1]
-
- if next_rows_large['distance'].le(current_distance - min_distance).all():
-
- end_points = pd.concat([end_points, filtered_data.loc[[idx - 1]]])
- for idx in small_diff_indices:
-
- current_distance = filtered_data.loc[idx - 1, 'distance']
- next_rows_small = filtered_data.iloc[idx: idx + 500]
-
- if next_rows_small['distance'].le(current_distance - min_distance).all():
-
- start_points = pd.concat([start_points, filtered_data.loc[[idx]]])
-
- if 0 in distance_counts.nlargest(3).index:
- end_points, start_points = start_points, end_points
- if end_points.iloc[0, 0] < start_points.iloc[0, 0]:
- end_points = end_points.drop(end_points.index[0])
- if end_points.iloc[-1, 0] < start_points.iloc[-1, 0]:
- start_points = start_points.drop(start_points.index[-1])
- else:
- pass
- return start_points, end_points, filtered_data
- def data_normalize(data_group: pd.DataFrame, start_points: pd.DataFrame, end_points: pd.DataFrame, group_len: int) \
- -> Tuple[List[pd.DataFrame], List[pd.DataFrame], List[pd.DataFrame], int, list]:
- combined_df_sorted = pd.concat([start_points, end_points]).sort_values(by='time')
-
- if combined_df_sorted.iloc[0].equals(end_points.iloc[0]):
- combined_df_sorted = combined_df_sorted.iloc[1:]
- if combined_df_sorted.iloc[-1].equals(start_points.iloc[-1]):
- combined_df_sorted = combined_df_sorted.iloc[:-1]
- combined_df_sorted.reset_index(drop=True, inplace=True)
-
- start_times = combined_df_sorted['time'].tolist()
- normalize_cycle = int(start_times[1] - start_times[0])
- full_cycle = int((start_times[2] - start_times[0]) * 3)
- turbines = [pd.DataFrame() for _ in range(3)]
-
- for i in range(0, len(start_times), 2):
-
- start_time = start_times[i]
- end_time = start_times[i + 1]
-
- segment = data_group[(data_group['time'] > start_time) & (data_group['time'] <= end_time)]
- if not segment.empty:
-
- ratio = (end_time - start_time) / normalize_cycle
- segment.loc[:, 'time'] = (segment['time'] - start_time) / ratio
-
- turbines[int(i / 2) % 3] = pd.concat([turbines[int(i / 2) % 3], segment])
-
- turbines_processed = []
- turbines_scattered = []
- min_list = []
- sd_time = [-1, -1]
- time_list = list(range(0, normalize_cycle, group_len))
- for turbine in turbines:
-
- turbine_sorted = turbine.sort_values(by='time').reset_index(drop=True)
- grey_start_index = int(len(turbine_sorted) * 0.1)
- grey_end_index = int(len(turbine_sorted) * 0.9)
- subset_grey = turbine_sorted[grey_start_index:grey_end_index]
- turbine_sorted = ff.median_filter_correction(turbine_sorted, 2, 10)
- mean_grey = subset_grey['grey'].mean() * 0.8
- n = len(turbine_sorted)
- n_10 = int(0.1 * n)
- is_extreme = (turbine_sorted.index < n_10) | (turbine_sorted.index >= len(turbine_sorted) - n_10)
- meets_condition = turbine_sorted['grey'] > mean_grey
- turbine_sorted = turbine_sorted[~is_extreme | (is_extreme & meets_condition)]
-
- first_time = turbine_sorted['time'].iloc[0]
-
- bins = list(range(int(first_time), int(turbine_sorted['time'].max()), group_len))
-
-
- grouped = turbine_sorted.groupby(pd.cut(turbine_sorted['time'], bins=bins, right=False))
-
- processed_df = pd.DataFrame()
- scattered_df = pd.DataFrame()
- mean_points = []
- diff_points = []
-
- for _, group in grouped:
-
- quantile_5 = group['distance'].quantile(0.05)
- quantile_95 = group['distance'].quantile(0.95)
- filtered_group = group[(group['distance'] > quantile_5) & (group['distance'] < quantile_95)]
-
- mean_point = filtered_group['distance'].mean()
- mean_points.append(mean_point)
-
- for i in range(len(mean_points) - 1):
- diff = abs(mean_points[i + 1] - mean_points[i])
- diff_points.append(diff)
- start_index = int(len(diff_points) * 0.05)
- 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))
-
- first_index = np.where(diff_points < sdr_diff)[0][0]
- last_index = np.where(diff_points < sdr_diff)[0][-1]
- for index, (bin, group) in enumerate(grouped):
-
- quantile_5 = group['distance'].quantile(0.05)
- quantile_95 = group['distance'].quantile(0.95)
- filtered_group = group[(group['distance'] > quantile_5) & (group['distance'] < quantile_95)]
- if first_index <= index < last_index:
-
- mid_point = filtered_group.mean()
-
- mid_point_df = pd.DataFrame([mid_point])
- mid_point_df.iloc[0, 0] = time_list[index]
- processed_df = pd.concat([processed_df, mid_point_df], ignore_index=True)
- scattered_df = pd.concat([scattered_df, filtered_group], ignore_index=True)
- else:
- pass
-
- min_time = processed_df['time'].min()
- max_time = processed_df['time'].max()
- if sd_time == [-1, -1]:
- sd_time = [min_time, max_time]
- elif sd_time[0] < min_time:
- sd_time[0] = min_time
- elif sd_time[1] > max_time:
- sd_time[1] = max_time
-
- turbines_processed.append(processed_df)
- turbines_scattered.append(scattered_df)
- border_rows = []
- for i, turbine in enumerate(turbines_processed):
-
- closest_index_0 = (turbine['time'] - sd_time[0]).abs().idxmin()
- turbine.at[closest_index_0, 'time'] = sd_time[0]
- sd_time_row_0 = turbine.loc[closest_index_0]
-
- closest_index_1 = (turbine['time'] - sd_time[1]).abs().idxmin()
- turbine.at[closest_index_1, 'time'] = sd_time[1]
- sd_time_row_1 = turbine.loc[closest_index_1]
-
- turbines_processed[i] = turbine.iloc[closest_index_0:closest_index_1 + 1].reset_index(drop=True)
- sd_time_rows_turbine = pd.concat([pd.DataFrame([sd_time_row_0]), pd.DataFrame([sd_time_row_1])]
- , ignore_index=True)
- border_rows.append(sd_time_rows_turbine)
- return turbines_processed, turbines_scattered, border_rows, full_cycle, min_list
- def blade_shape(turbines_processed: List[pd.DataFrame]):
- row_counts = [df.shape[0] for df in turbines_processed]
- num_rows = min(row_counts)
-
- turbine_avg = pd.DataFrame(index=range(num_rows), columns=['time', 'distance'])
- turbine_diff = [pd.DataFrame(index=range(num_rows), columns=['time', 'distance']) for _ in turbines_processed]
-
- for i in range(num_rows):
- distances = [df.loc[i, 'distance'] for df in turbines_processed]
- avg_distance = sum(distances) / len(distances)
- time_value = turbines_processed[0].loc[i, 'time']
- turbine_avg.loc[i, 'time'] = time_value
- turbine_avg.loc[i, 'distance'] = avg_distance
- for j in range(len(distances)):
- distances[j] = distances[j] - avg_distance
- turbine_diff[j].loc[i, 'time'] = time_value
- turbine_diff[j].loc[i, 'distance'] = distances[j]
- return turbine_avg, turbine_diff
- def coordinate_normalize(tip_border_rows: List[pd.DataFrame], tip_angle):
- tip_angle1 = np.deg2rad(tip_angle)
- tip_angle_list = []
- for turbine in tip_border_rows:
- tip_angle_cal0 = ((np.sin(tip_angle1) * turbine['distance'] - 0.07608) /
- (np.cos(tip_angle1) * turbine['distance']))
- tip_angle_cal = np.arctan(tip_angle_cal0)
- turbine['distance'] = (turbine['distance'] ** 2 + 0.0057881664 -
- 0.15216 * turbine['distance'] * np.sin(tip_angle1)) ** 0.5
- tip_angle_list.append(tip_angle_cal)
- tip_angle_new = float(np.mean(tip_angle_list))
- tip_angle_new1 = np.rad2deg(tip_angle_new)
- return tip_border_rows, tip_angle_new1
- def flange_coordinate_normalize(flange_cen_row: pd.DataFrame, flange_angle):
- flange_angle1 = np.deg2rad(flange_angle)
- center_y_mean = flange_cen_row['中心y'].mean()
- flange_angle_cal0 = ((np.sin(flange_angle1) * center_y_mean - 0.07608) /
- (np.cos(flange_angle1) * center_y_mean))
- flange_angle_cal = np.arctan(flange_angle_cal0)
- flange_cen_row['中心y'] = (flange_cen_row['中心y'] ** 2 + 0.0057881664 -
- 0.15216 * flange_cen_row['中心y'] * np.sin(flange_angle1)) ** 0.5
- flange_angle_new = float(flange_angle_cal)
- flange_angle_new1 = np.rad2deg(flange_angle_new)
- return flange_cen_row, flange_angle_new1
- def blade_axis_cal(data_group: pd.DataFrame, start_points: pd.DataFrame, end_points: pd.DataFrame, horizon_angle: float,
- group_len: int, radius_blade: float):
- def fit_circle(df, v_fixed, top_k=5, prefilter=True):
- def smooth_savgol(y, window_length=101, polyorder=3):
- wl = min(window_length, len(y) if len(y) % 2 == 1 else len(y) - 1)
- if wl < 3:
- return y
- if wl % 2 == 0:
- wl -= 1
- return savgol_filter(y, wl, polyorder)
- t = np.asarray(df['time'])
- d_raw = np.asarray(df['distance'])
- d_smooth = smooth_savgol(d_raw, window_length=101, polyorder=3) if prefilter else d_raw
- x = v_fixed * t
- bounds = [(min(x) - 5, max(x) + 5),
- (min(d_smooth), max(d_smooth) + 10),
- (0.5, 10)]
- def residuals_sq(params):
- xc, yc, R = params
- if R <= 0:
- return 1e6 * np.ones_like(t)
- return (x - xc) ** 2 + (d_smooth - yc) ** 2 - R ** 2
- def objective_mean_sq(params):
- res = residuals_sq(params)
- return np.mean(res ** 2)
- result = differential_evolution(
- objective_mean_sq,
- bounds,
- strategy='rand2bin',
- mutation=(0.8, 1.2),
- recombination=0.8,
- popsize=30,
- maxiter=1000,
- polish=False,
- seed=42,
- workers=1
- )
- pop = result.population
- energies = result.population_energies
- idx = np.argsort(energies)[:top_k]
- candidates = pop[idx]
- best_rmse = np.inf
- best_result = None
- for cand in candidates:
- res = least_squares(
- residuals_sq,
- x0=cand,
- bounds=([-np.inf, -np.inf, 1e-6],
- [np.inf, np.inf, np.inf]),
- method='trf',
- loss='linear',
- max_nfev=50000,
- xtol=1e-12,
- ftol=1e-12,
- gtol=1e-12
- )
- xc_opt, yc_opt, R_opt = res.x
- Ri_all = np.sqrt((x - xc_opt) ** 2 + (d_smooth - yc_opt) ** 2)
- geo_rmse = np.sqrt(np.mean((Ri_all - R_opt) ** 2))
- if geo_rmse < best_rmse:
- best_rmse = geo_rmse
- best_result = [v_fixed, xc_opt, yc_opt, R_opt, geo_rmse]
- result_df = pd.DataFrame([best_result],
- columns=['旋转半径', '中心x', '中心y', '圆半径', '几何RMSE'])
- return result_df
- combined_df_sorted = pd.concat([start_points, end_points]).sort_values(by='time')
- if combined_df_sorted.iloc[0].equals(end_points.iloc[0]):
- combined_df_sorted = combined_df_sorted.iloc[1:]
- if combined_df_sorted.iloc[-1].equals(start_points.iloc[-1]):
- combined_df_sorted = combined_df_sorted.iloc[:-1]
- combined_df_sorted.reset_index(drop=True, inplace=True)
- start_times = combined_df_sorted['time'].tolist()
- data_group['distance'] = data_group['distance'] * np.cos(np.deg2rad(horizon_angle))
- normalize_cycle = start_times[1] - start_times[0]
- full_cycle = int((start_times[2] - start_times[0]) * 3)
- v_blade = 10000000 * np.pi * radius_blade / full_cycle
- angle_speed = (np.pi / full_cycle) * 5000000
- turbines = [pd.DataFrame() for _ in range(3)]
- for i in range(0, len(start_times), 2):
- start_time = start_times[i]
- end_time = start_times[i + 1]
- segment = data_group[(data_group['time'] > start_time) & (data_group['time'] <= end_time)]
- if segment is None or segment.empty:
- raise ValueError("Segment is empty")
- segment = segment.copy()
- ratio = (end_time - start_time) / normalize_cycle
- segment.loc[:, 'time'] = (segment['time'] - start_time) / ratio
- turbines[int(i / 2) % 3] = pd.concat([turbines[int(i / 2) % 3], segment])
- turbines_processed = []
- turbines_scattered = []
- result_df = pd.DataFrame()
- time_list = list(range(0, normalize_cycle, group_len))
- for turbine in turbines:
- turbine_sorted = turbine.sort_values(by='time').reset_index(drop=True)
- first_time = turbine_sorted['time'].iloc[0]
- bins = list(range(int(first_time), int(turbine_sorted['time'].max()), group_len))
- grouped = turbine_sorted.groupby(pd.cut(turbine_sorted['time'], bins=bins, right=False))
- process_df = pd.DataFrame()
- for index, (bin, group) in enumerate(grouped):
- mid_point = group.mean()
- mid_point_df = pd.DataFrame([mid_point])
- mid_point_df.iloc[0, 0] = time_list[index]
- process_df = pd.concat([process_df, mid_point_df], ignore_index=True)
- process_df['time'] = process_df['time'] / 5000000
- lower_bound = process_df['time'].quantile(0.2)
- upper_bound = process_df['time'].quantile(0.8)
- processed_df = process_df[(process_df['time'] >= lower_bound) & (process_df['time'] <= upper_bound)]
- blade_cen_est = fit_circle(processed_df, v_blade)
- processed_df['time'] = processed_df['time'] * v_blade
- turbines_processed.append(processed_df)
- turbines_scattered.append(turbine)
- result_df = pd.concat([result_df, blade_cen_est], ignore_index=True)
- if blade_cen_est['几何RMSE'].iloc[0] >= 0.1:
- raise ValueError("叶片几何误差过大")
- result_df_mean = result_df.mean(numeric_only=True).to_frame().T
- result_df_mean["中心y"] = result_df_mean["中心y"] / np.cos(np.deg2rad(horizon_angle))
- result_df["中心y"] = result_df["中心y"] / np.cos(np.deg2rad(horizon_angle))
- return result_df_mean, result_df, turbines_processed
- def radius_cal(border_rows, meas_angle, cen_dist, cen_angle, angle_main, angle_rotate):
- aero_dist = (pd.concat([df['distance'] for df in border_rows]).mean())
- radius = np.abs(aero_dist * np.sin(np.deg2rad(meas_angle - angle_main))
- - cen_dist * np.sin(np.deg2rad(cen_angle - angle_main)))
- return radius
- def blade_angle_aero_dist(border_rows: List[pd.DataFrame], radius: float, full_cycle: int,
- tower_dist: float, v_angle: float):
- v_speed = 2 * np.pi * radius / full_cycle
- aero_dist_list = []
- cen_blade = []
- for turbine in border_rows:
- mean_col2 = (turbine.iloc[1, 1] + turbine.iloc[0, 1]) / 2
- aero_dist = abs(mean_col2 - tower_dist) * np.cos(np.deg2rad(v_angle))
- aero_dist_list.append(aero_dist)
- cen_blade.append(mean_col2)
- aero_dist_list.append(np.mean(aero_dist_list))
- aero_dist_list = [round(num, 2) for num in aero_dist_list]
- return aero_dist_list, v_speed, cen_blade
- def blade_angle(border_rows: List[pd.DataFrame], cen_data: pd.DataFrame, radius: float, full_cycle: int,
- v_angle: float):
- v_speed = 2 * np.pi * radius / full_cycle
- values = []
- for df in border_rows:
- if df.shape[0] >= 2 and df.shape[1] >= 2:
- values.append(df.iloc[0, 1])
- values.append(df.iloc[1, 1])
- mean_value = sum(values) / len(values) if values else float('nan')
- for i in [0, 1, 2]:
- if np.abs(cen_data['中心y'].iloc[i] - mean_value) > 0.5:
- print('原本:' + str(cen_data['中心y'].iloc[i]) + '标准:' + str(mean_value))
- cen_data['中心y'].iloc[i] = mean_value
- print('y_change')
- if cen_data['中心x'].iloc[i] > 1.5:
- cen_data['中心x'].iloc[i] = 1.5
- print('x_change')
- if cen_data['中心x'].iloc[i] < 0.75:
- cen_data['中心x'].iloc[i] = 0.75
- print('x_change')
- print(cen_data['中心x'].iloc[i])
- pitch_angle_list = []
- for idx, turbine in enumerate(border_rows, start=1):
- diff_time = np.abs(cen_data['中心x'].iloc[idx - 1] - turbine.iloc[1, 0] * v_speed)
- diff_len = np.abs((cen_data['中心y'].iloc[idx - 1] - turbine.iloc[1, 1]) * np.cos(np.deg2rad(v_angle)))
- pitch_angle = np.degrees(np.arctan(diff_len / diff_time))
- pitch_angle_list.append(pitch_angle)
- pitch_mean = np.mean(pitch_angle_list)
- pitch_angle_list = [angle - pitch_mean for angle in pitch_angle_list]
- pitch_angle_list.append(max(pitch_angle_list) - min(pitch_angle_list))
- pitch_angle_list = [round(num, 2) for num in pitch_angle_list]
- return pitch_angle_list, v_speed, cen_data
- def find_param(path: str):
- path = path.replace('\\', '/')
- last_slash_index = path.rfind('/')
- result = path[last_slash_index + 1:]
- underscore_indices = []
- start = 0
- while True:
- index = result.find('_', start)
- if index == -1:
- break
- underscore_indices.append(index)
- start = index + 1
- wind_name = result[: underscore_indices[0]]
- turbine_code = result[underscore_indices[0] + 1: underscore_indices[1]]
- time_code = result[underscore_indices[1] + 1: underscore_indices[2]]
- sampling_fq = int(result[underscore_indices[2] + 1: underscore_indices[3]])
- tunnel_1 = float(result[underscore_indices[3] + 1: underscore_indices[4]])
- tunnel_2 = float(result[underscore_indices[4] + 1: -4])
- dt = datetime.strptime(time_code, "%Y%m%d%H%M%S")
- standard_time_str = dt.strftime("%Y-%m-%d %H:%M:%S")
- return wind_name, turbine_code, standard_time_str, sampling_fq, tunnel_1, tunnel_2
- def blade_dist_distribute_cal(data_group: pd.DataFrame, start_points: pd.DataFrame, end_points: pd.DataFrame,
- tower_dist: float, v_angle: float, blade_cen_dist: list):
- combined_df_sorted = pd.concat([start_points, end_points]).sort_values(by='time')
-
- if combined_df_sorted.iloc[0].equals(end_points.iloc[0]):
- combined_df_sorted = combined_df_sorted.iloc[1:]
- if combined_df_sorted.iloc[-1].equals(start_points.iloc[-1]):
- combined_df_sorted = combined_df_sorted.iloc[:-1]
- combined_df_sorted.reset_index(drop=True, inplace=True)
-
- start_times = combined_df_sorted['time'].tolist()
- normalize_cycle = start_times[1] - start_times[0]
- tower_clearance = [pd.DataFrame() for _ in range(3)]
-
- for i in range(0, len(start_times) - 2, 2):
-
- start_time = start_times[i]
- end_time = start_times[i + 1]
-
- segment = data_group[(data_group['time'] > start_time) & (data_group['time'] <= end_time)]
- min_distance = segment['distance'].min()
- clearance = np.abs(tower_dist - min_distance - blade_cen_dist[i % 3]) * np.cos(np.deg2rad(v_angle))
- r_speed = round(60 / ((start_times[i + 2] - start_times[i]) * 3 / 5000000), 2)
-
- ratio = (end_time - start_time) / normalize_cycle
- segment.loc[:, 'time'] = (segment['time'] - start_time) / ratio
- new_df = pd.DataFrame({
- 'r_speed': [r_speed],
- 'clearance': [clearance]
- })
-
- tower_clearance[i % 3] = pd.concat([tower_clearance[i % 3], new_df])
- tower_clearance = [df.sort_values(by='r_speed') for df in tower_clearance]
- return tower_clearance
|