123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- import os
- import pandas as pd
- import math
- import numpy as np
- from plotly.subplots import make_subplots
- import plotly.express as px
- import pandas as pd
- import plotly.graph_objects as go
- import seaborn as sns
- from matplotlib.ticker import MultipleLocator
- from behavior.analystWithGoodPoint import AnalystWithGoodPoint
- from utils.directoryUtil import DirectoryUtil as dir
- from algorithmContract.confBusiness import *
- from algorithmContract.contract import Contract
- class TSRCpPowerScatterAnalyst(AnalystWithGoodPoint):
- """
- 风电机组叶尖速比-Cp-功率散点分析
- """
- def typeAnalyst(self):
- return "tsr_cp_power_scatter"
- def turbinesAnalysis(self, outputAnalysisDir, conf: Contract, turbineCodes):
- dictionary = self.processTurbineData(turbineCodes,conf,[Field_DeviceCode,Field_Time,Field_WindSpeed,Field_ActiverPower,Field_RotorSpeed,Field_GeneratorSpeed])
- turbineInfos = self.common.getTurbineInfos(conf.dataContract.dataFilter.powerFarmID, turbineCodes,
- self.turbineInfo)
- dataFrameMerge = self.userDataFrame(dictionary,conf.dataContract.configAnalysis,self)
- # return self.plot_tsr_distribution(self.tsr(dataFrameMerge), outputAnalysisDir, conf)
- dataFrameMerge[Field_PowerFarmName] = self.currPowerFarmInfo.loc[Field_PowerFarmName]
- # Ensure the necessary columns are of float type
- dataFrameMerge[Field_WindSpeed] = dataFrameMerge[Field_WindSpeed].astype(float)
- dataFrameMerge[Field_RotorSpeed] = dataFrameMerge[Field_RotorSpeed].astype(float)
- dataFrameMerge[Field_Cp] = dataFrameMerge[Field_Cp].astype(float)
- dataFrameMerge[Field_ActiverPower] = dataFrameMerge[Field_ActiverPower].astype(float)
- dataFrameMerge[Field_GeneratorSpeed] = dataFrameMerge[Field_GeneratorSpeed].astype(float)
- max_cutin = self.turbineModelInfo[Field_CutInWS].max()
- min_rated = self.turbineModelInfo[Field_RatedWindSpeed].min()
- dataFrameMerge = dataFrameMerge[(dataFrameMerge[Field_WindSpeed] > max_cutin) & (dataFrameMerge[Field_WindSpeed] < min_rated)]
- # Group by 'power_floor' and calculate median, max, and min of TSR
- dataFrameMerge[Field_TSRModified] = dataFrameMerge[Field_TSR] / (dataFrameMerge[Field_Cp] ** (1/3))
- return self.plot_tsrcp_distribution(dataFrameMerge, turbineInfos, outputAnalysisDir, conf)
- def plot_tsrcp_distribution(self, dataFrameMerge: pd.DataFrame, turbineModelInfo: pd.Series, outputAnalysisDir, conf: Contract, encoding=charset_unify):
- """
- Generates tsr distribution plots for turbines in a wind farm.
- Parameters:
- - outputAnalysisDir: str, path to the directory containing input CSV files.
- - farm_name: str, name of the wind farm.
- - encoding: str, encoding of the input CSV files. Defaults to 'utf-8'.
- """
- x_name = Field_ActiverPower
- y_name = Field_TSRModified
- upLimitOfTSR = 20
- result_rows = []
- # 绘制每个设备的TSR分布图
- for name, group in dataFrameMerge.groupby([Field_NameOfTurbine, Field_CodeOfTurbine]):
- fig = px.scatter(group,x=x_name, y=y_name)
- fig.update_layout(
- title={"text": '机组: {}'.format(name[0])},
- xaxis=dict(
- title='功率',
- dtick=200,
- tickangle=-45,
- range=[0, 1800]),
- yaxis=dict(
- title= '叶尖速比/风能利用系数分析^(1/3)', # r"$\frac{TSR}{Cp^{1/3}}$" # 仅在.png格式下正确显示
- dtick=self.axisStepTSR,
- range=[self.axisLowerLimitTSR,
- self.axisUpperLimitTSR]
- )
- )
- fig.update_traces(marker=dict(size=3))
- fig.update_xaxes(tickangle=-45)
- # 确保从 Series 中提取的是具体的值
- engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
- if isinstance(engineTypeCode, pd.Series):
- engineTypeCode = engineTypeCode.iloc[0]
- engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
- if isinstance(engineTypeName, pd.Series):
- engineTypeName = engineTypeName.iloc[0]
- # 构建最终的JSON对象
- json_output = {
- "analysisTypeCode": "机组叶尖速比-Cp-功率散点分析",
- "engineCode": engineTypeCode,
- "engineTypeName": engineTypeName,
- "xaixs": "功率(kW)",
- "yaixs": "叶尖速比/风能利用系数分析^(1/3)",
- "data": [{
- "engineName": name[0], # Field_NameOfTurbine
- "engineCode": name[1], # Field_CodeOfTurbine
- "title": f' 机组: {format(name[0])}',
- "xData": group[x_name].tolist(),
- "yData": group[y_name].tolist(),
- }]
- }
- # 保存图像
- # pngFileName = f"{name[0]}.png"
- # pngFilePath = os.path.join(outputAnalysisDir, pngFileName)
- # fig.write_image(pngFilePath, scale=3)
- # 将JSON对象保存到文件
- output_json_path = os.path.join(outputAnalysisDir, f"{name[0]}.json")
- with open(output_json_path, 'w', encoding='utf-8') as f:
- import json
- json.dump(json_output, f, ensure_ascii=False, indent=4)
- # 保存HTML
- # htmlFileName = f"{name[0]}.html"
- # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
- # fig.write_html(htmlFilePath)
- # 如果需要返回DataFrame,可以包含文件路径
- result_rows.append({
- Field_Return_TypeAnalyst: self.typeAnalyst(),
- Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
- Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
- Field_CodeOfTurbine: name[1],
- Field_Return_FilePath: output_json_path,
- Field_Return_IsSaveDatabase: True
- })
- # result_rows.append({
- # Field_Return_TypeAnalyst: self.typeAnalyst(),
- # Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
- # Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
- # Field_CodeOfTurbine: name[1],
- # Field_Return_FilePath: pngFilePath,
- # Field_Return_IsSaveDatabase: False
- # })
- # result_rows.append({
- # Field_Return_TypeAnalyst: self.typeAnalyst(),
- # Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
- # Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
- # Field_CodeOfTurbine: name[1],
- # Field_Return_FilePath: htmlFilePath,
- # Field_Return_IsSaveDatabase: True
- # })
- result_df = pd.DataFrame(result_rows)
- return result_df
|