|
@@ -71,6 +71,9 @@ class CpAnalyst(AnalystWithGoodPoint):
|
|
# Create Subplots
|
|
# Create Subplots
|
|
fig = make_subplots(specs=[[{"secondary_y": False}]])
|
|
fig = make_subplots(specs=[[{"secondary_y": False}]])
|
|
|
|
|
|
|
|
+ # 创建一个列表来存储各个风电机组的数据
|
|
|
|
+ turbine_data_list = []
|
|
|
|
+
|
|
# colors = px.colors.sequential.Turbo
|
|
# colors = px.colors.sequential.Turbo
|
|
# Plotting the turbine lines
|
|
# Plotting the turbine lines
|
|
for turbineCode in grouped[Field_CodeOfTurbine].unique():
|
|
for turbineCode in grouped[Field_CodeOfTurbine].unique():
|
|
@@ -85,6 +88,15 @@ class CpAnalyst(AnalystWithGoodPoint):
|
|
name=currTurbineInfo[Field_NameOfTurbine])
|
|
name=currTurbineInfo[Field_NameOfTurbine])
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+ # 提取数据
|
|
|
|
+ turbine_data_total = {
|
|
|
|
+ "engineName": currTurbineInfo[Field_NameOfTurbine],
|
|
|
|
+ "engineCode": turbineCode,
|
|
|
|
+ "xData": turbine_data[Field_PowerFloor].tolist(),
|
|
|
|
+ "yData": turbine_data[Field_CpMedian].tolist(),
|
|
|
|
+ }
|
|
|
|
+ turbine_data_list.append(turbine_data_total)
|
|
|
|
+
|
|
# Plotting the contract guarantee Cp curve
|
|
# Plotting the contract guarantee Cp curve
|
|
fig.add_trace(
|
|
fig.add_trace(
|
|
go.Scatter(x=dataFrameOfContractPowerCurve[Field_PowerFloor],
|
|
go.Scatter(x=dataFrameOfContractPowerCurve[Field_PowerFloor],
|
|
@@ -124,31 +136,77 @@ class CpAnalyst(AnalystWithGoodPoint):
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+ 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": "风电机组风能利用系数分析",
|
|
|
|
+ "typecode": turbineModelInfo[Field_MillTypeCode],
|
|
|
|
+ "engineCode": engineTypeCode,
|
|
|
|
+ "engineTypeName": engineTypeName,
|
|
|
|
+ "title": f'风能利用系数分布-{turbineModelInfo[Field_MachineTypeCode]}',
|
|
|
|
+ "xaixs": "功率(kW)",
|
|
|
|
+ "yaixs": "风能利用系数",
|
|
|
|
+ "contract_Cp_curve_xData": dataFrameOfContractPowerCurve[Field_PowerFloor].tolist(),
|
|
|
|
+ "contract_Cp_curve_yData": dataFrameOfContractPowerCurve[Field_Cp].tolist(),
|
|
|
|
+ "data": turbine_data_list
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # 将JSON对象保存到文件
|
|
|
|
+ output_json_path = os.path.join(outputAnalysisDir, f"{self.powerFarmInfo[Field_PowerFarmName].iloc[0]}-{turbineModelInfo[Field_MillTypeCode]}-Cp-Distribution_total.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
|
|
# 保存html
|
|
- htmlFileName = f"{self.powerFarmInfo[Field_PowerFarmName].iloc[0]}-{turbineModelInfo[Field_MillTypeCode]}-Cp-Distribution.html"
|
|
|
|
- htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
|
|
|
|
- fig.write_html(htmlFilePath)
|
|
|
|
|
|
+ # htmlFileName = f"{self.powerFarmInfo[Field_PowerFarmName].iloc[0]}-{turbineModelInfo[Field_MillTypeCode]}-Cp-Distribution.html"
|
|
|
|
+ # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
|
|
|
|
+ # fig.write_html(htmlFilePath)
|
|
|
|
|
|
result_rows = []
|
|
result_rows = []
|
|
|
|
+ # result_rows.append({
|
|
|
|
+ # Field_Return_TypeAnalyst: self.typeAnalyst(),
|
|
|
|
+ # Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
|
|
|
|
+ # Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
|
|
|
|
+ # Field_CodeOfTurbine: Const_Output_Total,
|
|
|
|
+ # Field_Return_FilePath: htmlFilePath,
|
|
|
|
+ # Field_Return_IsSaveDatabase: True
|
|
|
|
+ # })
|
|
|
|
+
|
|
|
|
+ # 如果需要返回DataFrame,可以包含文件路径
|
|
result_rows.append({
|
|
result_rows.append({
|
|
Field_Return_TypeAnalyst: self.typeAnalyst(),
|
|
Field_Return_TypeAnalyst: self.typeAnalyst(),
|
|
Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
|
|
Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
|
|
Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
|
|
Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
|
|
- Field_CodeOfTurbine: Const_Output_Total,
|
|
|
|
- Field_Return_FilePath: htmlFilePath,
|
|
|
|
|
|
+ Field_CodeOfTurbine: turbineModelInfo[Field_MillTypeCode],
|
|
|
|
+ Field_Return_FilePath: output_json_path,
|
|
Field_Return_IsSaveDatabase: True
|
|
Field_Return_IsSaveDatabase: True
|
|
})
|
|
})
|
|
|
|
|
|
|
|
+
|
|
# Individual turbine graphs
|
|
# Individual turbine graphs
|
|
for turbineCode, group in grouped.groupby(Field_CodeOfTurbine):
|
|
for turbineCode, group in grouped.groupby(Field_CodeOfTurbine):
|
|
fig = go.Figure()
|
|
fig = go.Figure()
|
|
|
|
|
|
currTurbineInfo = self.common.getTurbineInfo(
|
|
currTurbineInfo = self.common.getTurbineInfo(
|
|
conf.dataContract.dataFilter.powerFarmID, turbineCode, self.turbineInfo)
|
|
conf.dataContract.dataFilter.powerFarmID, turbineCode, self.turbineInfo)
|
|
|
|
+
|
|
|
|
+ # 创建一个列表来存储各个风电机组的数据
|
|
|
|
+ turbine_data_list_each = []
|
|
|
|
+
|
|
# Flag to add legend only once
|
|
# Flag to add legend only once
|
|
# add_legend = True
|
|
# add_legend = True
|
|
# Plot other turbines data
|
|
# Plot other turbines data
|
|
for other_name, other_group in grouped[grouped[Field_CodeOfTurbine] != turbineCode].groupby(Field_CodeOfTurbine):
|
|
for other_name, other_group in grouped[grouped[Field_CodeOfTurbine] != turbineCode].groupby(Field_CodeOfTurbine):
|
|
|
|
+ tempTurbineInfo = self.common.getTurbineInfo(
|
|
|
|
+ conf.dataContract.dataFilter.powerFarmID, other_name, self.turbineInfo)
|
|
fig.add_trace(
|
|
fig.add_trace(
|
|
go.Scatter(
|
|
go.Scatter(
|
|
x=other_group[Field_PowerFloor],
|
|
x=other_group[Field_PowerFloor],
|
|
@@ -159,12 +217,31 @@ class CpAnalyst(AnalystWithGoodPoint):
|
|
showlegend=False
|
|
showlegend=False
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
+
|
|
|
|
+ # 提取数据
|
|
|
|
+ turbine_data_other_each = {
|
|
|
|
+ "engineName": tempTurbineInfo[Field_NameOfTurbine],
|
|
|
|
+ "engineCode": other_name,
|
|
|
|
+ "xData": other_group[Field_PowerFloor].tolist(),
|
|
|
|
+ "yData": other_group[Field_CpMedian].tolist(),
|
|
|
|
+ }
|
|
|
|
+ turbine_data_list_each.append(turbine_data_other_each)
|
|
|
|
+
|
|
add_legend = False # Only add legend item for the first other turbine
|
|
add_legend = False # Only add legend item for the first other turbine
|
|
# Add trace for the current turbine
|
|
# Add trace for the current turbine
|
|
fig.add_trace(
|
|
fig.add_trace(
|
|
go.Scatter(x=group[Field_PowerFloor], y=group[Field_CpMedian],
|
|
go.Scatter(x=group[Field_PowerFloor], y=group[Field_CpMedian],
|
|
mode='lines', name=currTurbineInfo[Field_NameOfTurbine], line=dict(color='darkblue'))
|
|
mode='lines', name=currTurbineInfo[Field_NameOfTurbine], line=dict(color='darkblue'))
|
|
)
|
|
)
|
|
|
|
+
|
|
|
|
+ turbine_data_curr = {
|
|
|
|
+ "engineName": currTurbineInfo[Field_NameOfTurbine],
|
|
|
|
+ "engineCode": currTurbineInfo[Field_CodeOfTurbine],
|
|
|
|
+ "xData": group[Field_PowerFloor].tolist(),
|
|
|
|
+ "yData": group[Field_CpMedian].tolist(),
|
|
|
|
+ }
|
|
|
|
+ turbine_data_list_each.append(turbine_data_curr)
|
|
|
|
+
|
|
fig.add_trace(
|
|
fig.add_trace(
|
|
go.Scatter(x=dataFrameOfContractPowerCurve[Field_PowerFloor],
|
|
go.Scatter(x=dataFrameOfContractPowerCurve[Field_PowerFloor],
|
|
y=dataFrameOfContractPowerCurve[Field_Cp],
|
|
y=dataFrameOfContractPowerCurve[Field_Cp],
|
|
@@ -189,15 +266,44 @@ class CpAnalyst(AnalystWithGoodPoint):
|
|
legend=dict(x=1.05, y=0.5)
|
|
legend=dict(x=1.05, y=0.5)
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+ 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": "风电机组风能利用系数分析",
|
|
|
|
+ "typecode": turbineModelInfo[Field_MillTypeCode],
|
|
|
|
+ "engineCode": engineTypeCode,
|
|
|
|
+ "engineTypeName": engineTypeName,
|
|
|
|
+ "title": f'机组: {currTurbineInfo[Field_NameOfTurbine]}',
|
|
|
|
+ "xaixs": "功率(kW)",
|
|
|
|
+ "yaixs": "风能利用系数",
|
|
|
|
+ "contract_Cp_curve_xData": dataFrameOfContractPowerCurve[Field_PowerFloor].tolist(),
|
|
|
|
+ "contract_Cp_curve_yData": dataFrameOfContractPowerCurve[Field_Cp].tolist(),
|
|
|
|
+ "data": turbine_data_list_each
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # 将JSON对象保存到文件
|
|
|
|
+ output_json_path_each = os.path.join(outputAnalysisDir,
|
|
|
|
+ f"{currTurbineInfo[Field_NameOfTurbine]}.json")
|
|
|
|
+ with open(output_json_path_each, 'w', encoding='utf-8') as f:
|
|
|
|
+ import json
|
|
|
|
+ json.dump(json_output, f, ensure_ascii=False, indent=4)
|
|
|
|
+
|
|
# 保存图像
|
|
# 保存图像
|
|
pngFileName = f"{currTurbineInfo[Field_NameOfTurbine]}.png"
|
|
pngFileName = f"{currTurbineInfo[Field_NameOfTurbine]}.png"
|
|
pngFilePath = os.path.join(outputAnalysisDir, pngFileName)
|
|
pngFilePath = os.path.join(outputAnalysisDir, pngFileName)
|
|
fig.write_image(pngFilePath, scale=3)
|
|
fig.write_image(pngFilePath, scale=3)
|
|
|
|
|
|
# 保存HTML
|
|
# 保存HTML
|
|
- htmlFileName = f"{currTurbineInfo[Field_NameOfTurbine]}.html"
|
|
|
|
- htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
|
|
|
|
- fig.write_html(htmlFilePath)
|
|
|
|
|
|
+ # htmlFileName = f"{currTurbineInfo[Field_NameOfTurbine]}.html"
|
|
|
|
+ # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
|
|
|
|
+ # fig.write_html(htmlFilePath)
|
|
|
|
|
|
result_rows.append({
|
|
result_rows.append({
|
|
Field_Return_TypeAnalyst: self.typeAnalyst(),
|
|
Field_Return_TypeAnalyst: self.typeAnalyst(),
|
|
@@ -208,14 +314,25 @@ class CpAnalyst(AnalystWithGoodPoint):
|
|
Field_Return_IsSaveDatabase: False
|
|
Field_Return_IsSaveDatabase: False
|
|
})
|
|
})
|
|
|
|
|
|
|
|
+ # 如果需要返回DataFrame,可以包含文件路径
|
|
result_rows.append({
|
|
result_rows.append({
|
|
Field_Return_TypeAnalyst: self.typeAnalyst(),
|
|
Field_Return_TypeAnalyst: self.typeAnalyst(),
|
|
Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
|
|
Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
|
|
Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
|
|
Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
|
|
Field_CodeOfTurbine: turbineCode,
|
|
Field_CodeOfTurbine: turbineCode,
|
|
- Field_Return_FilePath: htmlFilePath,
|
|
|
|
|
|
+ Field_Return_FilePath: output_json_path_each,
|
|
Field_Return_IsSaveDatabase: True
|
|
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: turbineCode,
|
|
|
|
+ # Field_Return_FilePath: htmlFilePath,
|
|
|
|
+ # Field_Return_IsSaveDatabase: True
|
|
|
|
+ # })
|
|
|
|
+
|
|
result_df = pd.DataFrame(result_rows)
|
|
result_df = pd.DataFrame(result_rows)
|
|
return result_df
|
|
return result_df
|