windSpeedFrequencyAnalyst.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import os
  2. import pandas as pd
  3. import numpy as np
  4. import plotly.graph_objects as go
  5. import plotly.express as px
  6. from plotly.subplots import make_subplots
  7. from behavior.analystNotFilter import AnalystNotFilter
  8. from utils.directoryUtil import DirectoryUtil as dir
  9. import matplotlib.pyplot as plt
  10. from algorithmContract.confBusiness import *
  11. from algorithmContract.contract import Contract
  12. class WindSpeedFrequencyAnalyst(AnalystNotFilter):
  13. def typeAnalyst(self):
  14. return "wind_speed_frequency"
  15. # def filterCommon(self,dataFrame:pd.DataFrame, conf: Contract):
  16. # return dataFrame
  17. def turbinesAnalysis(self, outputAnalysisDir, conf: Contract, turbineCodes):
  18. dictionary=self.processTurbineData(turbineCodes,conf,[Field_DeviceCode,Field_Time,Field_WindSpeed,Field_ActiverPower])
  19. turbineInfos = self.common.getTurbineInfos(conf.dataContract.dataFilter.powerFarmID, turbineCodes,
  20. self.turbineInfo)
  21. dataFrameMerge=self.userDataFrame(dictionary,conf.dataContract.configAnalysis,self)
  22. return self.windRoseAnalysis(dataFrameMerge, turbineInfos, outputAnalysisDir, conf)
  23. def windRoseAnalysis(self, dataFrameMerge: pd.DataFrame, turbineModelInfo: pd.Series, outputAnalysisDir, conf: Contract):
  24. # 检查所需列是否存在
  25. required_columns = {Field_NameOfTurbine, Field_WindSpeed}
  26. if not required_columns.issubset(dataFrameMerge.columns):
  27. raise ValueError(f"DataFrame缺少必要的列。需要的列有: {required_columns}")
  28. wind_speed_bins = np.arange(0, 26, 0.5) # x轴风速范围 ,间隔0.5
  29. # 按设备名分组数据
  30. grouped = dataFrameMerge.groupby([Field_NameOfTurbine, Field_CodeOfTurbine])
  31. turbine_data_list = []
  32. result_rows = []
  33. for name, group in grouped:
  34. # 2. 计算风速频率
  35. # 首先,我们需要确定风速的范围并计算每个风速的频数
  36. # wind_speeds = group[Field_WindSpeed].unique()
  37. # 计算风速频率,确保频率没有零值(用很小的数代替零)
  38. wind_speed_freq = np.histogram(group[Field_WindSpeed], bins=wind_speed_bins)[0]
  39. wind_speed_freq = np.maximum(wind_speed_freq, 0.01) / len(group[Field_WindSpeed]) * 100
  40. wind_speed_freq1 = np.where(wind_speed_freq < 0.0001, 0, wind_speed_freq)
  41. # 3. & 4. 确定y轴风速频率的范围和间隔(这里直接计算了频率,所以不需要手动设置间隔)
  42. # 我们已经计算了风速频率,因此不需要再手动设置y轴的间隔和范围
  43. # 5. 使用plotly绘制风速频率分布柱状图
  44. # 为了使用plotly绘制柱状图,我们需要将风速范围的中点作为x轴的值
  45. x_values = (wind_speed_bins[:-1] + wind_speed_bins[1:]) / 2
  46. # 创建柱状图
  47. fig = px.bar(x=x_values, y=wind_speed_freq1)
  48. # 更新图形的布局
  49. fig.update_layout(
  50. title={
  51. 'text': f'风速频率: {name[0]}',
  52. # 'y': 0.95,
  53. 'x': 0.5,
  54. 'xanchor': 'center',
  55. 'yanchor': 'top'
  56. },
  57. xaxis=dict(
  58. title='风速 (m/s)',
  59. showgrid=True,
  60. range=[0, 26],
  61. dtick=1,
  62. tickangle=-45
  63. ),
  64. yaxis=dict(
  65. title='频率 (%)',
  66. showgrid=True,
  67. # range=[0, 1],
  68. ),
  69. margin=dict(t=50, b=10) # t为顶部(top)间距,b为底部(bottom)间距
  70. )
  71. # # 更新x轴和y轴的范围和标签
  72. # fig.update_yaxes(range=[0, max(wind_speed_freq) * 1.1 if max(wind_speed_freq) > 0 else 0.2], title='Frequency')
  73. # 确保从 Series 中提取的是具体的值
  74. engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
  75. if isinstance(engineTypeCode, pd.Series):
  76. engineTypeCode = engineTypeCode.iloc[0]
  77. engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
  78. if isinstance(engineTypeName, pd.Series):
  79. engineTypeName = engineTypeName.iloc[0]
  80. # 构建最终的JSON对象
  81. json_output = {
  82. "analysisTypeCode": "风速频率分析",
  83. "engineCode": engineTypeCode,
  84. "engineTypeName": engineTypeName,
  85. "xaixs": "风速(m/s)",
  86. "yaixs": "频率(%)",
  87. "data": [{
  88. "engineName": name[0],
  89. "engineCode": name[1],
  90. "title": f' 风速频率:{name[0]}',
  91. "xData": x_values.tolist(),
  92. "yData": wind_speed_freq.tolist(),
  93. }]
  94. }
  95. # Save plot
  96. filePathOfImage = os.path.join(outputAnalysisDir, f"{name[0]}.png")
  97. fig.write_image(filePathOfImage, scale=3)
  98. # filePathOfHtml = os.path.join(outputAnalysisDir, f"{name[0]}.html")
  99. # fig.write_html(filePathOfHtml)
  100. # 将JSON对象保存到文件
  101. output_json_path = os.path.join(outputAnalysisDir, f"wind_Speed_Frequency{name[0]}.json")
  102. with open(output_json_path, 'w', encoding='utf-8') as f:
  103. import json
  104. json.dump(json_output, f, ensure_ascii=False, indent=4)
  105. result_rows.append({
  106. Field_Return_TypeAnalyst: self.typeAnalyst(),
  107. Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
  108. Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
  109. Field_CodeOfTurbine: name[1],
  110. Field_Return_FilePath: filePathOfImage,
  111. Field_Return_IsSaveDatabase: False
  112. })
  113. result_rows.append({
  114. Field_Return_TypeAnalyst: self.typeAnalyst(),
  115. Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
  116. Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
  117. Field_CodeOfTurbine: name[1],
  118. Field_MillTypeCode: 'total',
  119. Field_Return_FilePath: output_json_path,
  120. Field_Return_IsSaveDatabase: True
  121. })
  122. result_df = pd.DataFrame(result_rows)
  123. return result_df