pitchTSRCpAnalyst.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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. return self.windRoseAnalysis(dataFrameMerge, outputAnalysisDir, conf)
  15. def windRoseAnalysis(self, dataFrameMerge: pd.DataFrame, outputAnalysisDir, conf: Contract):
  16. """
  17. 绘制3D曲面图。
  18. 参数:
  19. df: pandas.DataFrame, 必须包含Field_PitchAngel1, Field_TSR, 和 Field_Cp这三个字段。
  20. 返回:
  21. 一个Plotly图形对象。
  22. """
  23. # 检查所需列是否存在
  24. required_columns = {Field_PitchAngel1, Field_TSR, Field_Cp}
  25. if not required_columns.issubset(dataFrameMerge.columns):
  26. raise ValueError(f"DataFrame缺少必要的列。需要的列有: {required_columns},Available: {dataFrameMerge.columns}")
  27. # # 按设备名分组数据
  28. # grouped = dataFrameMerge.groupby([Field_NameOfTurbine, Field_CodeOfTurbine])
  29. result_rows = []
  30. ## 分图
  31. 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]'])
  32. # turbines = dataFrameMerge[Field_NameOfTurbine].unique()
  33. turbines = dataFrameMerge.groupby([Field_NameOfTurbine, Field_CodeOfTurbine]).groups.keys()
  34. for turbine_name, turbine_code in turbines:
  35. fig = make_subplots(rows=1, cols=1)
  36. # 选择当前风力发电机的数据
  37. turbine_data = dataFrameMerge[dataFrameMerge[Field_NameOfTurbine] == turbine_name]
  38. # 按角区间分组
  39. grouped = turbine_data.groupby('PitchAngleBin')
  40. # 为每个区间添加一个数据迹
  41. for pitch_bin, group in grouped:
  42. fig.add_trace(go.Scatter(
  43. x=group[Field_TSR],
  44. y=group[Field_Cp],
  45. mode='markers',
  46. name=pitch_bin,
  47. marker=dict(
  48. size=3, # Smaller size, default is usually around 10
  49. opacity=0.8 # Reduced opacity, default is 1
  50. )
  51. # name=f'Pitch: {name}'
  52. ))
  53. # 更新布局
  54. fig.update_layout(
  55. title=f'风能利用系数 vs. 叶尖速比 : {turbine_name}',
  56. xaxis_title='叶尖速比',
  57. yaxis_title='风能利用系数',
  58. legend_title='桨距角',
  59. legend=dict(
  60. # orientation="h",
  61. itemsizing="constant", # Use constant size for legend items
  62. itemwidth=80 # Set the width of legend items to 50 pixels
  63. ),
  64. xaxis=dict(
  65. # dtick=2,
  66. range=[5,20]),
  67. yaxis=dict(
  68. dtick=self.axisStepCp,
  69. range=[self.axisLowerLimitCp,self.axisUpperLimitCp]
  70. )
  71. # legend=dict(
  72. # orientation="h",
  73. # xanchor="center",
  74. # x=0.5,
  75. # y=-0.2
  76. # )
  77. )
  78. # 保存html
  79. filePathOfPng = os.path.join(outputAnalysisDir, f"{turbine_name}.png")
  80. fig.write_image(filePathOfPng)
  81. filePathOfHtml = os.path.join(outputAnalysisDir, f"{turbine_name}.html")
  82. fig.write_html(filePathOfHtml)
  83. result_rows.append({
  84. Field_Return_TypeAnalyst: self.typeAnalyst(),
  85. Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
  86. Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
  87. Field_CodeOfTurbine: turbine_code,
  88. Field_Return_FilePath: filePathOfPng,
  89. Field_Return_IsSaveDatabase: False
  90. })
  91. result_rows.append({
  92. Field_Return_TypeAnalyst: self.typeAnalyst(),
  93. Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
  94. Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
  95. Field_CodeOfTurbine: turbine_code,
  96. Field_Return_FilePath: filePathOfHtml,
  97. Field_Return_IsSaveDatabase: True
  98. })
  99. result_df = pd.DataFrame(result_rows)
  100. return result_df