pitchTSRCpAnalyst.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import os
  2. import pandas as pd
  3. import plotly.graph_objects as go
  4. from algorithmContract.confBusiness import *
  5. from algorithmContract.contract import Contract
  6. from behavior.analystWithGoodPoint import AnalystWithGoodPoint
  7. from plotly.subplots import make_subplots
  8. class PitchTSRCpAnalyst(AnalystWithGoodPoint):
  9. def typeAnalyst(self):
  10. return "pitch_tsr_cp"
  11. def turbinesAnalysis(self, outputAnalysisDir, conf: Contract, turbineCodes):
  12. dictionary=self.processTurbineData(turbineCodes,conf,[Field_DeviceCode,Field_Time,Field_PitchAngel1,Field_WindSpeed,Field_ActiverPower,Field_RotorSpeed,Field_GeneratorSpeed])
  13. dataFrameMerge=self.userDataFrame(dictionary,conf.dataContract.configAnalysis,self)
  14. turbineInfos = self.common.getTurbineInfos(conf.dataContract.dataFilter.powerFarmID, turbineCodes, self.turbineInfo)
  15. return self.windRoseAnalysis(dataFrameMerge,turbineInfos, outputAnalysisDir, conf)
  16. def windRoseAnalysis(self, dataFrameMerge: pd.DataFrame, turbineModelInfo: pd.Series,outputAnalysisDir, conf: Contract):
  17. """
  18. 绘制3D曲面图。
  19. 参数:
  20. df: pandas.DataFrame, 必须包含Field_PitchAngel1, Field_TSR, 和 Field_Cp这三个字段。
  21. 返回:
  22. 一个Plotly图形对象。
  23. """
  24. # 检查所需列是否存在
  25. required_columns = {Field_PitchAngel1, Field_TSR, Field_Cp}
  26. if not required_columns.issubset(dataFrameMerge.columns):
  27. raise ValueError(f"DataFrame缺少必要的列。需要的列有: {required_columns},Available: {dataFrameMerge.columns}")
  28. # # 按设备名分组数据
  29. # grouped = dataFrameMerge.groupby([Field_NameOfTurbine, Field_CodeOfTurbine])
  30. result_rows = []
  31. turbine_data_list=[]
  32. ## 分图
  33. dataFrameMerge['PitchAngleBin'] = pd.cut(dataFrameMerge[Field_PitchAngel1], bins=[-1, 1, 3, 5, 7, 9], right=True, labels=['[-1,1]', '(1,3]', '(3,5]', '(5,7]', '(7,9]'])
  34. # turbines = dataFrameMerge[Field_NameOfTurbine].unique()
  35. turbines = dataFrameMerge.groupby([Field_NameOfTurbine, Field_CodeOfTurbine]).groups.keys()
  36. for turbine_name, turbine_code in turbines:
  37. fig = make_subplots(rows=1, cols=1)
  38. # 选择当前风力发电机的数据
  39. turbine_data = dataFrameMerge[dataFrameMerge[Field_NameOfTurbine] == turbine_name]
  40. # 按角区间分组
  41. grouped = turbine_data.groupby('PitchAngleBin')
  42. # 为每个区间添加一个数据迹
  43. for pitch_bin, group in grouped:
  44. fig.add_trace(go.Scatter(
  45. x=group[Field_TSR],
  46. y=group[Field_Cp],
  47. mode='markers',
  48. name=pitch_bin,
  49. marker=dict(
  50. size=3, # Smaller size, default is usually around 10
  51. opacity=0.8 # Reduced opacity, default is 1
  52. )
  53. # name=f'Pitch: {name}'
  54. ))
  55. # 提取数据
  56. turbine_data = {
  57. "engineName": turbine_name,
  58. "engineCode": turbine_code,
  59. "title":f' 风能利用系数 vs. 叶尖速比-{turbine_name}',
  60. "xData": group[Field_TSR].tolist(),
  61. "yData":group[Field_Cp].tolist(),
  62. "colorbar": pitch_bin,
  63. "colorbartitle": "桨距角"
  64. }
  65. turbine_data_list.append(turbine_data)
  66. # 更新布局
  67. fig.update_layout(
  68. title=f'风能利用系数 vs. 叶尖速比 : {turbine_name}',
  69. xaxis_title='叶尖速比',
  70. yaxis_title='风能利用系数',
  71. legend_title='桨距角',
  72. legend=dict(
  73. # orientation="h",
  74. itemsizing="constant", # Use constant size for legend items
  75. itemwidth=80 # Set the width of legend items to 50 pixels
  76. ),
  77. xaxis=dict(
  78. # dtick=2,
  79. range=[5,20]),
  80. yaxis=dict(
  81. dtick=self.axisStepCp,
  82. range=[self.axisLowerLimitCp,self.axisUpperLimitCp]
  83. )
  84. # legend=dict(
  85. # orientation="h",
  86. # xanchor="center",
  87. # x=0.5,
  88. # y=-0.2
  89. # )
  90. )
  91. # 保存html
  92. filePathOfPng = os.path.join(outputAnalysisDir, f"{turbine_name}.png")
  93. fig.write_image(filePathOfPng)
  94. filePathOfHtml = os.path.join(outputAnalysisDir, f"{turbine_name}.html")
  95. fig.write_html(filePathOfHtml)
  96. result_rows.append({
  97. Field_Return_TypeAnalyst: self.typeAnalyst(),
  98. Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
  99. Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
  100. Field_CodeOfTurbine: turbine_code,
  101. Field_Return_FilePath: filePathOfPng,
  102. Field_Return_IsSaveDatabase: False
  103. })
  104. result_rows.append({
  105. Field_Return_TypeAnalyst: self.typeAnalyst(),
  106. Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
  107. Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
  108. Field_CodeOfTurbine: turbine_code,
  109. Field_Return_FilePath: filePathOfHtml,
  110. Field_Return_IsSaveDatabase: True
  111. })
  112. # 确保从 Series 中提取的是具体的值
  113. engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
  114. if isinstance(engineTypeCode, pd.Series):
  115. engineTypeCode = engineTypeCode.iloc[0]
  116. engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
  117. if isinstance(engineTypeName, pd.Series):
  118. engineTypeName = engineTypeName.iloc[0]
  119. # 构建最终的JSON对象
  120. json_output = {
  121. "analysisTypeCode": "变桨和叶尖速比及风能利用系数分析",
  122. "engineCode": engineTypeCode,
  123. "engineTypeName": engineTypeName,
  124. "xaixs": "叶尖速比",
  125. "yaixs": "风能利用系数",
  126. "data": turbine_data_list
  127. }
  128. # 将JSON对象保存到文件
  129. output_json_path = os.path.join(outputAnalysisDir, "pitch_TSR_cp.json")
  130. with open(output_json_path, 'w', encoding='utf-8') as f:
  131. import json
  132. json.dump(json_output, f, ensure_ascii=False, indent=4)
  133. # 如果需要返回DataFrame,可以包含文件路径
  134. result_rows.append({
  135. Field_Return_TypeAnalyst: self.typeAnalyst(),
  136. Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
  137. Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
  138. Field_CodeOfTurbine: Const_Output_Total,
  139. Field_Return_FilePath: output_json_path,
  140. Field_Return_IsSaveDatabase: True
  141. })
  142. result_df = pd.DataFrame(result_rows)
  143. return result_df