pitchGeneratorSpeedAnalyst.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import os
  2. from datetime import datetime
  3. import numpy as np
  4. import pandas as pd
  5. import plotly.graph_objects as go
  6. from algorithmContract.confBusiness import *
  7. from algorithmContract.contract import Contract
  8. from behavior.analystWithGoodBadPoint import AnalystWithGoodBadPoint
  9. class PitchGeneratorSpeedAnalyst(AnalystWithGoodBadPoint):
  10. """
  11. 风电机组变桨-发电机转速分析
  12. """
  13. def typeAnalyst(self):
  14. return "pitch_generator_speed"
  15. # def recalculation(self, turbineModelInfo: pd.Series, dataFrame: pd.DataFrame):
  16. # return self.recalculationOfGeneratorSpeed(
  17. # dataFrame, Field_RotorSpeed, Field_GeneratorSpeed, self.turbineModelInfo[Field_RSR].iloc[0])
  18. def selectColumns(self):
  19. return [Field_DeviceCode, Field_Time,Field_WindSpeed,Field_ActiverPower,Field_PitchAngel1, Field_GeneratorSpeed]
  20. def turbinesAnalysis(self, outputAnalysisDir, conf: Contract, turbineCodes):
  21. dictionary = self.processTurbineData(turbineCodes, conf,self.selectColumns())
  22. turbineInfos = self.common.getTurbineInfos(conf.dataContract.dataFilter.powerFarmID, turbineCodes,
  23. self.turbineInfo)
  24. dataFrame = self.userDataFrame(dictionary,conf.dataContract.configAnalysis,self)
  25. return self.plot_speed_pitch_angle(dataFrame, turbineInfos, outputAnalysisDir, conf, )
  26. def plot_speed_pitch_angle(self, dataFrameMerge, turbineModelInfo: pd.Series, outputAnalysisDir, conf: Contract):
  27. # 按设备名分组数据
  28. dataFrameMerge = dataFrameMerge[(dataFrameMerge[Field_ActiverPower] > 0)].sort_values(by=Field_YearMonth)
  29. grouped = dataFrameMerge.groupby([Field_NameOfTurbine, Field_CodeOfTurbine])
  30. # 遍历每个设备并绘制散点图
  31. result_rows = []
  32. for name, group in grouped:
  33. groupNew = group.copy()
  34. # 处理直驱转速与非直驱的差异
  35. # if not self.common.isNone(conf.value_gen_speed_multiple):
  36. # groupNew[fieldGeneratorSpeed] = group[fieldGeneratorSpeed] * \
  37. # conf.value_gen_speed_multiple
  38. # 创建图形
  39. fig = go.Figure()
  40. # 添加散点图
  41. fig.add_trace(go.Scatter(
  42. x=groupNew[Field_GeneratorSpeed],
  43. y=groupNew[Field_PitchAngel1],
  44. mode='markers',
  45. # marker=dict(color='blue', size=3.5)
  46. marker=dict(
  47. color=group[Field_UnixYearMonth],
  48. colorscale='Rainbow',
  49. size=3,
  50. opacity=0.7,
  51. colorbar=dict(
  52. tickvals=np.linspace(
  53. group[Field_UnixYearMonth].min(), group[Field_UnixYearMonth].max(), 6),
  54. ticktext=[datetime.fromtimestamp(ts).strftime('%Y-%m') for ts in np.linspace(
  55. group[Field_UnixYearMonth].min(), group[Field_UnixYearMonth].max(), 6)],
  56. thickness=18,
  57. len=1, # 设置颜色条的长度,使其占据整个图的高度
  58. outlinecolor='rgba(255,255,255,0)'
  59. ),
  60. showscale=True
  61. ),
  62. showlegend=False
  63. ))
  64. # 设置图形布局
  65. fig.update_layout(
  66. title=f'机组: {name[0]}',
  67. xaxis=dict(
  68. title='发电机转速',
  69. range=[self.axisLowerLimitGeneratorSpeed, self.axisUpperLimitGeneratorSpeed],
  70. dtick=self.axisStepGeneratorSpeed,
  71. tickangle=-45 # 设置x轴刻度值旋转角度为45度,如果需要
  72. ),
  73. yaxis=dict(
  74. title='桨距角',
  75. range=[self.axisLowerLimitPitchAngle, self.axisUpperLimitPitchAngle],
  76. dtick=self.axisStepPitchAngle
  77. ),
  78. coloraxis=dict(
  79. colorbar=dict(
  80. title="时间",
  81. ticks="outside",
  82. len=1, # 设置颜色条的长度,使其占据整个图的高度
  83. thickness=20, # 调整颜色条的宽度
  84. orientation='v', # 设置颜色条为垂直方向
  85. tickmode='array', # 确保刻度按顺序排列
  86. tickvals=dataFrameMerge[Field_YearMonth].unique(
  87. ).tolist(), # 确保刻度为唯一的年月
  88. ticktext=dataFrameMerge[Field_YearMonth].unique(
  89. ).tolist() # 以%Y-%m格式显示标签
  90. )
  91. )
  92. )
  93. # 确保从 Series 中提取的是具体的值
  94. engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
  95. if isinstance(engineTypeCode, pd.Series):
  96. engineTypeCode = engineTypeCode.iloc[0]
  97. engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
  98. if isinstance(engineTypeName, pd.Series):
  99. engineTypeName = engineTypeName.iloc[0]
  100. # 构建最终的JSON对象
  101. group[Field_UnixYearMonth] = pd.to_datetime(group[Field_UnixYearMonth])
  102. json_output = {
  103. "analysisTypeCode": "变桨和发电机转速协调性分析",
  104. "engineCode": engineTypeCode,
  105. "engineTypeName": engineTypeName,
  106. "xaixs": "发电机转速(r/min)",
  107. "yaixs": "桨距角(°)",
  108. "data": [{
  109. "engineName": name[0],
  110. "engineCode": name[1],
  111. "title": f' 机组: {name[0]}',
  112. "xData": groupNew[Field_GeneratorSpeed].tolist(),
  113. "yData": groupNew[Field_PitchAngel1].tolist(),
  114. "colorbar": dataFrameMerge[Field_YearMonth].unique().tolist(),
  115. }]
  116. }
  117. # Save plot
  118. filePathOfImage = os.path.join(outputAnalysisDir, f"{name[0]}.png")
  119. fig.write_image(filePathOfImage, scale=3)
  120. # filePathOfHtml = os.path.join(outputAnalysisDir, f"{name[0]}.html")
  121. # fig.write_html(filePathOfHtml)
  122. # 将JSON对象保存到文件
  123. output_json_path = os.path.join(outputAnalysisDir, f"pitch_GeneratorSpeed_Analyst{name[0]}.json")
  124. with open(output_json_path, 'w', encoding='utf-8') as f:
  125. import json
  126. json.dump(json_output, f, ensure_ascii=False, indent=4)
  127. result_rows.append({
  128. Field_Return_TypeAnalyst: self.typeAnalyst(),
  129. Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
  130. Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
  131. Field_CodeOfTurbine: name[1],
  132. Field_Return_FilePath: filePathOfImage,
  133. Field_Return_IsSaveDatabase: False
  134. })
  135. result_rows.append({
  136. Field_Return_TypeAnalyst: self.typeAnalyst(),
  137. Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
  138. Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
  139. Field_CodeOfTurbine: name[1],
  140. Field_MillTypeCode: 'total',
  141. Field_Return_FilePath: output_json_path,
  142. Field_Return_IsSaveDatabase: True
  143. })
  144. result_df = pd.DataFrame(result_rows)
  145. return result_df