소스 검색

修改最小桨距角、动态偏航误差、变桨和叶尖速比及风能利用系数输出json格式

wenjia Li 4 달 전
부모
커밋
82fd67bbd3

+ 53 - 4
dataAnalysisBusiness/algorithm/minPitchAnalyst.py

@@ -22,10 +22,11 @@ class MinPitchAnalyst(AnalystWithGoodBadPoint):
 
     def turbinesAnalysis(self, outputAnalysisDir, conf: Contract, turbineCodes):
         dictionary = self.processTurbineData(turbineCodes,conf,self.selectColums())
+        turbineInfos = self.common.getTurbineInfos(conf.dataContract.dataFilter.powerFarmID, turbineCodes, self.turbineInfo)
         dataFrameMerge = self.userDataFrame(dictionary,conf.dataContract.configAnalysis,self)
-        return self.drawTrendGraph(dataFrameMerge, outputAnalysisDir, conf)
+        return self.drawTrendGraph(dataFrameMerge,turbineInfos, outputAnalysisDir, conf)
 
-    def drawTrendGraph(self, dataFrameMerge: pd.DataFrame, outputAnalysisDir, conf: Contract):
+    def drawTrendGraph(self, dataFrameMerge: pd.DataFrame,  turbineModelInfo: pd.Series,outputAnalysisDir, conf: Contract):
         """
         Generates pitch angle distribution scatter plots for turbines in a wind farm using plotly.
 
@@ -62,7 +63,8 @@ class MinPitchAnalyst(AnalystWithGoodBadPoint):
         # dataFrameMerge = dataFrameMerge[dataFrameMerge[Field_PitchAngel1] <= 5]
         grouped = dataFrameMerge.groupby(
             [Field_NameOfTurbine, Field_CodeOfTurbine])
-
+                # 创建一个列表来存储各个风电机组的数据
+        turbine_data_list = []
         result_rows = []
         for name, group in grouped:
             # Convert the date column to datetime type
@@ -88,6 +90,20 @@ class MinPitchAnalyst(AnalystWithGoodBadPoint):
             # df[pitchAngleRate] = df['count'] / df['total_count'] * 100
             # df[pitchAngleRate] = (df['count'] / df['total_count']).apply(lambda x: x ** 0.5)*100
             df[pitchAngleRate] = (df['count'] / df['total_count']) * 100
+            
+            # 提取数据
+            turbine_data = {
+                "engineName": name[0],
+                "engineCode": name[1],
+                "title":f' {name[0]}的最小桨距角分布',
+                "xData": df[Field_YearMonthDay].dt.strftime('%Y-%m-%d').tolist(),
+                "yData": df[fieldPitchAngleBin].tolist(),
+                "colorbar": df[pitchAngleRate].tolist(),
+                "colorbartitle": "百分比(%)"
+                
+            }
+
+            turbine_data_list.append(turbine_data)
             # Plotting using plotly
             fig = px.scatter(df,
                              x=Field_YearMonthDay,
@@ -119,6 +135,7 @@ class MinPitchAnalyst(AnalystWithGoodBadPoint):
                 # plot_bgcolor='rgb(240, 240, 240)'
             )
 
+
             # Set marker size if fixed size is needed
             # Fixed size for all points
             fig.update_traces(marker=dict(size=3, opacity=0.9))
@@ -146,7 +163,39 @@ class MinPitchAnalyst(AnalystWithGoodBadPoint):
                 Field_Return_FilePath: filePathOfHtml,
                 Field_Return_IsSaveDatabase: True
             })
-
+        # 确保从 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": "最小桨距角分析",
+            "engineCode":  engineTypeCode,    
+            "engineTypeName": engineTypeName, 
+            "xaixs": "时间",
+            "yaixs": "桨距角(度)",
+            "data": turbine_data_list
+        }
+
+        # 将JSON对象保存到文件
+        output_json_path = os.path.join(outputAnalysisDir, "min_pitch_analysis.json")
+        with open(output_json_path, 'w', encoding='utf-8') as f:
+            import json
+            json.dump(json_output, f, ensure_ascii=False, indent=4)
+
+        # 如果需要返回DataFrame,可以包含文件路径
+        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: output_json_path,
+            Field_Return_IsSaveDatabase: True
+        })
         result_df = pd.DataFrame(result_rows)
 
         return result_df

+ 49 - 3
dataAnalysisBusiness/algorithm/pitchTSRCpAnalyst.py

@@ -16,10 +16,11 @@ class PitchTSRCpAnalyst(AnalystWithGoodPoint):
     def turbinesAnalysis(self, outputAnalysisDir, conf: Contract, turbineCodes):
         dictionary=self.processTurbineData(turbineCodes,conf,[Field_DeviceCode,Field_Time,Field_PitchAngel1,Field_WindSpeed,Field_ActiverPower,Field_RotorSpeed,Field_GeneratorSpeed])
         dataFrameMerge=self.userDataFrame(dictionary,conf.dataContract.configAnalysis,self)
-        return self.windRoseAnalysis(dataFrameMerge, outputAnalysisDir, conf)
+        turbineInfos = self.common.getTurbineInfos(conf.dataContract.dataFilter.powerFarmID, turbineCodes, self.turbineInfo)
+        return self.windRoseAnalysis(dataFrameMerge,turbineInfos, outputAnalysisDir, conf)
 
 
-    def windRoseAnalysis(self, dataFrameMerge: pd.DataFrame, outputAnalysisDir, conf: Contract):
+    def windRoseAnalysis(self, dataFrameMerge: pd.DataFrame, turbineModelInfo: pd.Series,outputAnalysisDir, conf: Contract):
         """
         绘制3D曲面图。
 
@@ -38,7 +39,7 @@ class PitchTSRCpAnalyst(AnalystWithGoodPoint):
         # grouped = dataFrameMerge.groupby([Field_NameOfTurbine, Field_CodeOfTurbine])
 
         result_rows = []
-
+        turbine_data_list=[]
 
         ## 分图
         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]'])
@@ -64,6 +65,18 @@ class PitchTSRCpAnalyst(AnalystWithGoodPoint):
                     )
                     # name=f'Pitch: {name}'
                 ))
+                # 提取数据
+                turbine_data = {
+                    "engineName": turbine_name,
+                    "engineCode": turbine_code,
+                    "title":f' 风能利用系数 vs. 叶尖速比-{turbine_name}',
+                    "xData": group[Field_TSR].tolist(),
+                    "yData":group[Field_Cp].tolist(),
+                    "colorbar": pitch_bin,
+                    "colorbartitle": "桨距角"
+
+                }
+                turbine_data_list.append(turbine_data)
 
             # 更新布局
             fig.update_layout(
@@ -113,6 +126,39 @@ class PitchTSRCpAnalyst(AnalystWithGoodPoint):
                 Field_Return_FilePath: filePathOfHtml,
                 Field_Return_IsSaveDatabase: True
             })
+        # 确保从 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": "变桨和叶尖速比及风能利用系数分析",
+            "engineCode":  engineTypeCode,    
+            "engineTypeName": engineTypeName, 
+            "xaixs": "叶尖速比",
+            "yaixs": "风能利用系数",
+            "data": turbine_data_list
+        }
+
+        # 将JSON对象保存到文件
+        output_json_path = os.path.join(outputAnalysisDir, "pitch_TSR_cp.json")
+        with open(output_json_path, 'w', encoding='utf-8') as f:
+            import json
+            json.dump(json_output, f, ensure_ascii=False, indent=4)
+
+        # 如果需要返回DataFrame,可以包含文件路径
+        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: output_json_path,
+            Field_Return_IsSaveDatabase: True
+        })
 
         result_df = pd.DataFrame(result_rows)
 

+ 84 - 39
dataAnalysisBusiness/algorithm/yawErrorDensityAnalyst.py

@@ -7,6 +7,7 @@ from algorithmContract.contract import Contract
 from behavior.analystWithGoodPoint import AnalystWithGoodPoint
 from scipy.stats import binned_statistic_2d
 from scipy.stats import skew, kurtosis
+from utils.jsonUtil import JsonUtil
 
 class YawErrorDensityAnalyst(AnalystWithGoodPoint):
     """
@@ -19,49 +20,14 @@ class YawErrorDensityAnalyst(AnalystWithGoodPoint):
     def selectColumns(self):
         return [Field_DeviceCode,Field_Time,Field_WindSpeed,Field_ActiverPower,Field_YawError]
 
-    def calculateYawError(self, dataFrame: pd.DataFrame):
-        
-        dataFrame = dataFrame.dropna(
-            subset=[Field_NameOfTurbine, Field_YawError, Field_ActiverPower,Field_WindSpeed])
-
-        filtered_dataFrame = dataFrame[(dataFrame[Field_YawError].abs() <= 30)&(dataFrame[Field_WindSpeed] >= 0)&(dataFrame[Field_WindSpeed] <= 25)]
-        x=filtered_dataFrame[Field_YawError]
-        y=filtered_dataFrame[Field_WindSpeed]
-        # data = np.column_stack((x, y))  # 合并为两列数组
-        # 使用 binned_statistic_2d 来计算散点的密度分布
-        binSize_x = 60
-        binSize_y = 50
-        counts, x_edges, y_edges, binnumber = binned_statistic_2d(x, y, values=None, statistic='count', bins=[binSize_x, binSize_y])
-
-        # 将数据密度转化为颜色值
-        binX = np.digitize(x, x_edges) - 1
-        binY = np.digitize(y, y_edges) - 1
-
-        # 删除超出范围的下标
-        validIdx = (binX >= 0) & (binX < binSize_x) & (binY >= 0) & (binY < binSize_y)
-
-        # 获取有效下标的密度
-        density = np.zeros(len(x))
-        density[validIdx] = counts[binX[validIdx], binY[validIdx]]
-        # 将结果保存到 result 中
-        result = {
-            'x': x,
-            'y': y,
-            'density': density
-        }
-
-        # 将 result 转换为 DataFrame
-        result_df = pd.DataFrame(result)
-        
-        return result_df
-
     def turbinesAnalysis(self,  outputAnalysisDir, conf: Contract, turbineCodes):
         dictionary = self.processTurbineData(turbineCodes,conf,self.selectColumns())
         dataFrameMerge = self.userDataFrame(dictionary,conf.dataContract.configAnalysis,self)
-        # dataFrameMerge.to_csv('D:\dashengkeji\project\WTOAAM\debug_tset_20241008\dataFrameJHS_WOG00935.csv',index=False)
-        return self.yawErrorAnalysis(dataFrameMerge, outputAnalysisDir, conf)
+        turbineInfos = self.common.getTurbineInfos(conf.dataContract.dataFilter.powerFarmID, turbineCodes, self.turbineInfo)
+        results=self.yawErrorAnalysis(dataFrameMerge, turbineInfos,outputAnalysisDir, conf)
+        return results
 
-    def yawErrorAnalysis(self, dataFrameMerge: pd.DataFrame, outputAnalysisDir, conf: Contract):
+    def yawErrorAnalysis(self, dataFrameMerge: pd.DataFrame, turbineModelInfo: pd.Series, outputAnalysisDir, conf: Contract):
         # 检查所需列是否存在
         required_columns = {Field_ActiverPower, Field_YawError,Field_WindSpeed}
         if not required_columns.issubset(dataFrameMerge.columns):
@@ -99,6 +65,7 @@ class YawErrorDensityAnalyst(AnalystWithGoodPoint):
         fixed_colorscale = [
             [i / (len(fixed_colors) - 1), color] for i, color in enumerate(fixed_colors)
         ]
+        turbine_data_list=[]
         for name, group in grouped:
         
             df = self.calculateYawError(group)
@@ -128,6 +95,19 @@ class YawErrorDensityAnalyst(AnalystWithGoodPoint):
             }
             result = pd.DataFrame(result)
             print(f'{name[0]}指标:',result)
+             # 提取数据
+            turbine_data = {
+                "engineName": name[0],
+                "engineCode": name[1],
+                "title":f'动态偏航误差分析-{name[0]}',
+                "xData": df["x"].tolist(),
+                "yData": df["y"].tolist(),
+                "colorbar": df["density"].tolist(),
+                "colorbartitle": "密度"
+                
+            }
+
+            turbine_data_list.append(turbine_data)
             # 用密度作为颜色绘制散点图,并限制横坐标范围为 -20 到 20
             fig = go.Figure()
             fig.add_trace(go.Scattergl(
@@ -175,12 +155,77 @@ class YawErrorDensityAnalyst(AnalystWithGoodPoint):
             
             
             })
+         # 确保从 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": "动态偏航误差",
+            "engineCode":  engineTypeCode,    
+            "engineTypeName": engineTypeName, 
+            "xaixs": "对风角度(度)",
+            "yaixs": "风速(m/s)",
+            "data": turbine_data_list
+        }
+
+        # 将JSON对象保存到文件
+        output_json_path = os.path.join(outputAnalysisDir, "yaw_error_density.json")
+        with open(output_json_path, 'w', encoding='utf-8') as f:
+            import json
+            json.dump(json_output, f, ensure_ascii=False, indent=4)
+
+        # 如果需要返回DataFrame,可以包含文件路径
+        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: output_json_path,
+            Field_Return_IsSaveDatabase: True
+        })
 
 
         result_df = pd.DataFrame(result_rows)
 
         return result_df
+    
+    def calculateYawError(self, dataFrame: pd.DataFrame):
+        
+        dataFrame = dataFrame.dropna(
+            subset=[Field_NameOfTurbine, Field_YawError, Field_ActiverPower,Field_WindSpeed])
+
+        filtered_dataFrame = dataFrame[(dataFrame[Field_YawError].abs() <= 30)&(dataFrame[Field_WindSpeed] >= 0)&(dataFrame[Field_WindSpeed] <= 25)]
+        x=filtered_dataFrame[Field_YawError]
+        y=filtered_dataFrame[Field_WindSpeed]
+        # data = np.column_stack((x, y))  # 合并为两列数组
+        # 使用 binned_statistic_2d 来计算散点的密度分布
+        binSize_x = 60
+        binSize_y = 50
+        counts, x_edges, y_edges, binnumber = binned_statistic_2d(x, y, values=None, statistic='count', bins=[binSize_x, binSize_y])
 
+        # 将数据密度转化为颜色值
+        binX = np.digitize(x, x_edges) - 1
+        binY = np.digitize(y, y_edges) - 1
 
+        # 删除超出范围的下标
+        validIdx = (binX >= 0) & (binX < binSize_x) & (binY >= 0) & (binY < binSize_y)
 
+        # 获取有效下标的密度
+        density = np.zeros(len(x))
+        density[validIdx] = counts[binX[validIdx], binY[validIdx]]
+        # 将结果保存到 result 中
+        result = {
+            'x': x,
+            'y': y,
+            'density': density
+        }
 
+        # 将 result 转换为 DataFrame
+        result_df = pd.DataFrame(result)
+        
+        return result_df