wenjia Li 4 달 전
부모
커밋
bb71f8c093

+ 162 - 40
dataAnalysisBusiness/algorithm/generatorSpeedPowerAnalyst.py

@@ -48,11 +48,11 @@ class GeneratorSpeedPowerAnalyst(AnalystWithGoodPoint):
             currDataFrameOfTurbines[Field_NameOfTurbine] = currDataFrameOfTurbines[Field_CodeOfTurbine].map(currTurbineInfos_dict).fillna("")
 
             result2D = self.drawScatter2DMonthly(
-                currDataFrameOfTurbines, outputAnalysisDir, conf)
+                currDataFrameOfTurbines, outputAnalysisDir, conf,currTurbineModeInfo)
             returnDatas.extend(result2D)
 
             result3D = self.drawScatterGraph(
-                currDataFrameOfTurbines, outputAnalysisDir, conf)
+                currDataFrameOfTurbines, outputAnalysisDir, conf,currTurbineModeInfo)
             returnDatas.extend(result3D)
 
             resultTotal = self.drawScatterGraphForTurbines(
@@ -63,7 +63,7 @@ class GeneratorSpeedPowerAnalyst(AnalystWithGoodPoint):
 
         return returnDataFrame
 
-    def drawScatter2DMonthlyOfTurbine(self, dataFrame: pd.DataFrame, outputAnalysisDir: str, conf: Contract, turbineName: str):
+    def drawScatter2DMonthlyOfTurbine(self, dataFrame: pd.DataFrame, outputAnalysisDir: str, conf: Contract, name: str,turbineModelInfo: pd.Series):
         # 设置颜色条参数
         dataFrame = dataFrame.sort_values(by=Field_YearMonth)
 
@@ -98,7 +98,7 @@ class GeneratorSpeedPowerAnalyst(AnalystWithGoodPoint):
         # 以下是以比例方式进行色彩的可视化处理
         fig.update_layout(
             title={
-                "text": f'月度发电机转速功率散点图: {turbineName}',
+                "text": f'月度发电机转速功率散点图: {name[0]}',
                 # "x": 0.5
             },
             xaxis=dict(
@@ -129,36 +129,78 @@ class GeneratorSpeedPowerAnalyst(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": "发电机转速(r/min)",
+            "yaixs": "功率(kw)",
+            "data": [{
+                "engineName": name[0],
+                "engineCode": name[1],
+                "title":f' 月度发电机转速功率散点图:{name[0]}',
+                "xData": dataFrame[Field_GeneratorSpeed].tolist(),
+                "yData":dataFrame[Field_ActiverPower].tolist(),
+                "color": dataFrame[Field_UnixYearMonth].tolist(),
+                "colorbartitle": "时间",
+                "mode":'markers'
+            
+        }]
+        }
+
 
         # 保存图片
         outputFilePathPNG = os.path.join(
-            outputAnalysisDir, f"{turbineName}.png")
+            outputAnalysisDir, f"{name[0]}.png")
         fig.write_image(outputFilePathPNG, width=800, height=600, scale=3)
-        # 保存html
-        outputFileHtml = os.path.join(outputAnalysisDir, f"{turbineName}.html")
-        fig.write_html(outputFileHtml)
-
+        # # 保存html
+        # outputFileHtml = os.path.join(outputAnalysisDir, f"{name[0]}.html")
+        # fig.write_html(outputFileHtml)
+         # 将JSON对象保存到文件
+        output_json_path = os.path.join(outputAnalysisDir, f"speed_power{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)
         result = []
+        # 如果需要返回DataFrame,可以包含文件路径
         result.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
-            Field_CodeOfTurbine: dataFrame[Field_CodeOfTurbine].iloc[0],
-            Field_Return_FilePath: outputFilePathPNG,
-            Field_Return_IsSaveDatabase: False
+            Field_CodeOfTurbine:  dataFrame[Field_CodeOfTurbine].iloc[0],
+            Field_Return_FilePath: output_json_path,
+            Field_Return_IsSaveDatabase: True
         })
+        result = []
         result.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
             Field_CodeOfTurbine: dataFrame[Field_CodeOfTurbine].iloc[0],
-            Field_Return_FilePath: outputFileHtml,
-            Field_Return_IsSaveDatabase: True
+            Field_Return_FilePath: outputFilePathPNG,
+            Field_Return_IsSaveDatabase: False
         })
+        # result.append({
+        #     Field_Return_TypeAnalyst: self.typeAnalyst(),
+        #     Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+        #     Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+        #     Field_CodeOfTurbine: dataFrame[Field_CodeOfTurbine].iloc[0],
+        #     Field_Return_FilePath: outputFileHtml,
+        #     Field_Return_IsSaveDatabase: True
+        # })
 
         return result
 
-    def drawScatterGraphOfTurbine(self, dataFrame: pd.DataFrame,  outputAnalysisDir: str, conf: Contract, turbineName: str):
+    def drawScatterGraphOfTurbine(self, dataFrame: pd.DataFrame,  outputAnalysisDir: str, conf: Contract, name: str,turbineModelInfo: pd.Series):
         # 创建3D散点图
         fig = px.scatter_3d(dataFrame,
                             x=Field_GeneratorSpeed,
@@ -175,7 +217,7 @@ class GeneratorSpeedPowerAnalyst(AnalystWithGoodPoint):
         # 更新图形的布局
         fig.update_layout(
             title={
-                "text": f'月度发电机转速功率3D散点图: {turbineName}',
+                "text": f'月度发电机转速功率3D散点图: {name[0]}',
                 # "x": 0.5
             },
             scene=dict(
@@ -213,39 +255,80 @@ class GeneratorSpeedPowerAnalyst(AnalystWithGoodPoint):
                 itemwidth=80  # Set the width of legend items to 50 pixels
             )
         )
-
-        # 保存图像
-        outputFileHtml = os.path.join(
-            outputAnalysisDir, "{}_3D.html".format(turbineName))
-        fig.write_html(outputFileHtml)
+         # 确保从 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": "发电机转速(r/min)",
+            "yaixs": "时间",
+            "zaixs": "有功功率(kw)",
+            "data": [{
+                "engineName": name[0],
+                "engineCode": name[1],
+                "title":f' 月度发电机转速功率3D散点图:{name[0]}',
+                "xData": dataFrame[Field_GeneratorSpeed].tolist(),
+                "yData":dataFrame[Field_YearMonth].tolist(),
+                "zData":dataFrame[Field_ActiverPower].tolist(),
+                "color": dataFrame[Field_YearMonth].tolist(),
+                "mode":'markers'
+            
+        }]
+        }
+        # # 保存图像
+        # outputFileHtml = os.path.join(
+        #     outputAnalysisDir, "{}_3D.html".format(name[0]))
+        # fig.write_html(outputFileHtml)
 
         result = []
-
+        # 将JSON对象保存到文件
+        output_json_path = os.path.join(outputAnalysisDir, f"3D_{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)
+        # 如果需要返回DataFrame,可以包含文件路径
         result.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
-            Field_CodeOfTurbine: dataFrame[Field_CodeOfTurbine].iloc[0],
-            Field_Return_FilePath: outputFileHtml,
+            Field_CodeOfTurbine: name[1],
+            Field_Return_FilePath: output_json_path,
             Field_Return_IsSaveDatabase: True
         })
+        # result.append({
+        #     Field_Return_TypeAnalyst: self.typeAnalyst(),
+        #     Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+        #     Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+        #     Field_CodeOfTurbine: dataFrame[Field_CodeOfTurbine].iloc[0],
+        #     Field_Return_FilePath: outputFileHtml,
+        #     Field_Return_IsSaveDatabase: True
+        # })
 
         return result
 
-    def drawScatter2DMonthly(self, dataFrameMerge: pd.DataFrame, outputAnalysisDir, conf: Contract):
+    def drawScatter2DMonthly(self, dataFrameMerge: pd.DataFrame, outputAnalysisDir, conf: Contract,turbineModelInfo: pd.Series):
         """
         生成每台风电机组二维有功功率、发电机转速散点图表
         """
         results = []
-        grouped = dataFrameMerge.groupby(Field_NameOfTurbine)
-        for groupKey, group in grouped:
+        grouped = dataFrameMerge.groupby(
+            [Field_NameOfTurbine, Field_CodeOfTurbine])
+        for name, group in grouped:
             result = self.drawScatter2DMonthlyOfTurbine(
-                group, outputAnalysisDir, conf, groupKey)
+                group, outputAnalysisDir, conf, name,turbineModelInfo)
             results.extend(result)
 
         return results
 
-    def drawScatterGraph(self, dataFrame: pd.DataFrame,  outputAnalysisDir: str, conf: Contract):
+    def drawScatterGraph(self, dataFrame: pd.DataFrame,  outputAnalysisDir: str, conf: Contract,turbineModelInfo: pd.Series):
         """
         绘制风速-功率分布图并保存为文件。
 
@@ -258,13 +341,14 @@ class GeneratorSpeedPowerAnalyst(AnalystWithGoodPoint):
         dataFrame = dataFrame[(dataFrame[Field_ActiverPower] > 0)].sort_values(
             by=Field_YearMonth)
 
-        grouped = dataFrame.groupby(Field_NameOfTurbine)
+        grouped = dataFrame.groupby(
+            [Field_NameOfTurbine, Field_CodeOfTurbine])
 
         # 遍历每个设备的数据
-        for groupKey, group in grouped:
+        for name, group in grouped:
             if len(group[Field_YearMonth].unique()) > 1:
                 result = self.drawScatterGraphOfTurbine(
-                    group, outputAnalysisDir, conf, groupKey)
+                    group, outputAnalysisDir, conf, name,turbineModelInfo)
                 results.extend(result)
 
         return results
@@ -332,21 +416,59 @@ class GeneratorSpeedPowerAnalyst(AnalystWithGoodPoint):
                 itemwidth=80  # Set the width of legend items to 50 pixels
             )
         )
-
-        # 保存图像
-        outputFileHtml = os.path.join(
-            outputAnalysisDir, "{}-{}.html".format(self.typeAnalyst(),turbineModelInfo[Field_MillTypeCode]))
-        fig.write_html(outputFileHtml)
+        # 确保从 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": "发电机转速(r/min)",
+            "yaixs": "机组",
+            "zaixs": "有功功率(kw)",
+            "data": [{
+                "title":f'风机发电机转速功率3D散点图-{turbineModelInfo[Field_MachineTypeCode]}',
+                "xData": dataFrame[Field_GeneratorSpeed].tolist(),
+                "yData":dataFrame[Field_NameOfTurbine].tolist(),
+                "zData":dataFrame[Field_ActiverPower].tolist(),
+                "color": dataFrame[Field_NameOfTurbine].tolist(),
+                "mode":'markers'
+            
+        }]
+        }
+        # # 保存图像
+        # outputFileHtml = os.path.join(
+        #     outputAnalysisDir, "{}-{}.html".format(self.typeAnalyst(),turbineModelInfo[Field_MillTypeCode]))
+        # fig.write_html(outputFileHtml)
 
         result = []
-
+        # 将JSON对象保存到文件
+        output_json_path = os.path.join(outputAnalysisDir, f"total_3D_{turbineModelInfo[Field_MillTypeCode]}.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.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: outputFileHtml,
+            Field_CodeOfTurbine:Const_Output_Total,
+            Field_Return_FilePath: output_json_path,
             Field_Return_IsSaveDatabase: True
         })
+        # result.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: outputFileHtml,
+        #     Field_Return_IsSaveDatabase: True
+        # })
 
         return result

+ 3 - 6
dataAnalysisBusiness/algorithm/generatorSpeedTorqueAnalyst.py

@@ -260,8 +260,7 @@ class GeneratorSpeedTorqueAnalyst(AnalystWithGoodPoint):
                 itemwidth=80  # Set the width of legend items to 50 pixels
             )
         )
-                # 构建最终的JSON对象
-                # 确保从 Series 中提取的是具体的值
+        
         # 确保从 Series 中提取的是具体的值
         engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
         if isinstance(engineTypeCode, pd.Series):
@@ -281,7 +280,7 @@ class GeneratorSpeedTorqueAnalyst(AnalystWithGoodPoint):
             "data": [{
                 "engineName": name[0],
                 "engineCode": name[1],
-                "title":f' 发电机转速和转矩分析{name[0]}',
+                "title":f' 月度发电机转速扭矩3D散点图:{name[0]}',
                 "xData": dataFrame[Field_GeneratorSpeed].tolist(),
                 "yData":dataFrame[Field_YearMonth].tolist(),
                 "zData":dataFrame[Field_GeneratorTorque].tolist(),
@@ -302,7 +301,6 @@ class GeneratorSpeedTorqueAnalyst(AnalystWithGoodPoint):
         with open(output_json_path, 'w', encoding='utf-8') as f:
             import json
             json.dump(json_output, f, ensure_ascii=False, indent=4)
-        result = []
         # 如果需要返回DataFrame,可以包含文件路径
         result.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
@@ -422,7 +420,7 @@ class GeneratorSpeedTorqueAnalyst(AnalystWithGoodPoint):
                 itemwidth=80  # Set the width of legend items to 50 pixels
             )
         )
-                # 确保从 Series 中提取的是具体的值
+        # 确保从 Series 中提取的是具体的值
         engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
         if isinstance(engineTypeCode, pd.Series):
             engineTypeCode = engineTypeCode.iloc[0]
@@ -460,7 +458,6 @@ class GeneratorSpeedTorqueAnalyst(AnalystWithGoodPoint):
         with open(output_json_path, 'w', encoding='utf-8') as f:
             import json
             json.dump(json_output, f, ensure_ascii=False, indent=4)
-        result = []
         # 如果需要返回DataFrame,可以包含文件路径
         result.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),

+ 50 - 12
dataAnalysisBusiness/algorithm/powerScatterAnalyst.py

@@ -34,8 +34,8 @@ class PowerScatterAnalyst(AnalystWithGoodBadPoint):
 
         # for groupByKey,contractPowerCurveOfMillType in grouped:
         #     break
-
-        return self.drawOfPowerCurveScatter(dataFrame, outputAnalysisDir, conf)
+        turbineInfos = self.common.getTurbineInfos(conf.dataContract.dataFilter.powerFarmID, turbineCodes, self.turbineInfo)
+        return self.drawOfPowerCurveScatter(dataFrame,turbineInfos, outputAnalysisDir, conf)
 
     """
     def contractGuaranteePowerCurveData(self, csvPowerCurveFilePath):
@@ -44,7 +44,7 @@ class PowerScatterAnalyst(AnalystWithGoodBadPoint):
 
         return dataFrameGuaranteePowerCurve
     """
-    def drawOfPowerCurveScatter(self, dataFrame: pd.DataFrame,  outputAnalysisDir, conf: Contract):
+    def drawOfPowerCurveScatter(self, dataFrame: pd.DataFrame,  turbineModelInfo: pd.Series, outputAnalysisDir, conf: Contract):
         """
         绘制风速-功率分布图并保存为文件。
 
@@ -54,9 +54,7 @@ class PowerScatterAnalyst(AnalystWithGoodBadPoint):
         outputAnalysisDir (str): 分析输出目录。
         conf (ConfBusiness): 配置
         """
-        # 按设备名分组数据
-        # colorsList = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd',
-        #               '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf', '#aec7e8', '#ffbb78']
+
         colorsList = [  
                         "#3E409C",
                         "#3586BF",
@@ -141,19 +139,59 @@ class PowerScatterAnalyst(AnalystWithGoodBadPoint):
                 margin=dict(t=50, b=10)  # t为顶部(top)间距,b为底部(bottom)间距
             )
 
-
-            # Save plot
-            filePathOfHtml = os.path.join(outputAnalysisDir, f"{name[0]}.html")
-            fig.write_html(filePathOfHtml)
-
+            # 确保从 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": "逐月有功功率散点3D分析",
+                "engineCode":  engineTypeCode,    
+                "engineTypeName": engineTypeName, 
+                "xaixs": "风速(m/s)",
+                "yaixs": "时间",
+                "zaixs": "有功功率(kw)",
+                "data": [{
+                        "engineName": name[0],
+                        "engineCode": name[1],
+                        "title":f'当月发电量: {name[0]}',
+                        "xData": group[Field_WindSpeed].tolist(),
+                        "xrange":[cut_in_ws, 25],
+                        "yData":group[Field_YearMonth].tolist(),
+                        "zData":group[Field_ActiverPower].tolist(),
+                        "zrange":[self.axisLowerLimitActivePower, self.axisUpperLimitActivePower]
+                        }]
+            }
+            # # Save plot
+            # filePathOfHtml = os.path.join(outputAnalysisDir, f"{name[0]}.html")
+            # fig.write_html(filePathOfHtml)
+            # 将JSON对象保存到文件
+            output_json_path = os.path.join(outputAnalysisDir, f"power_scatter{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)
+
+            # 如果需要返回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: filePathOfHtml,
+                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: filePathOfHtml,
+            #     Field_Return_IsSaveDatabase: True
+            # })
 
         result_df = pd.DataFrame(result_rows)