Преглед на файлове

awg commit algorithm components

anweiguo преди 4 месеца
родител
ревизия
6b7776fd51

+ 0 - 1
data_processing/processing_limit_power/processing_limit_power_by_agcavc.py

@@ -1,5 +1,4 @@
 import pandas as pd
-from pymongo import MongoClient
 from sqlalchemy import create_engine
 from flask import Flask,request,jsonify
 import time

+ 104 - 16
evaluation_processing/analysis_report.py

@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-from plotly.subplots import make_subplots
+import numpy as np
 from flask import Flask,request
 import time
 import random
@@ -11,10 +11,11 @@ import plotly.express as px
 import plotly.graph_objects as go
 import pandas as pd
 import plotly.io as pio
-
+from bson.decimal128 import Decimal128
+import numbers
 app = Flask('analysis_report——service')
 
-def put_analysis_report_to_html(args,df_clean,df_accuracy):
+def put_analysis_report_to_html(args,df_clean, df_predict, df_accuracy):
     col_time = args['col_time']
     col_x_env = args['col_x_env']
     col_x_pre = args['col_x_pre']
@@ -139,29 +140,109 @@ def put_analysis_report_to_html(args,df_clean,df_accuracy):
     # -------------------- 预测功率与实际功率曲线 --------------------
 
     # 生成折线图(以 C_GLOBALR 和 NWP预测总辐射 为例)
-    fig_line = px.line(df_clean, x='dateTime', y=[label, label_pre], markers=True)
+    # 创建一个图表对象
+    fig = go.Figure()
 
-    # 自定义趋势图布局
-    fig_line.update_layout(
-        template='seaborn',
-        # title=dict(text=f"{label_pre}与{label}曲线",
-        # x=0.5, font=dict(size=24, color='darkblue')),
-        plot_bgcolor='rgba(255, 255, 255, 0.8)',  # 改为白色背景
+    # 获取所有的模型
+    models = df_predict['model'].unique()
+    # 添加实际功率曲线
+    fig.add_trace(go.Scatter(
+        x=df_predict[col_time],
+        y=df_predict[label],
+        mode='lines+markers',
+        name='实际功率',  # 实际功率
+        line=dict(dash='dot', width=2),  # 虚线
+        marker=dict(symbol='cross'),
+    ))
+    # 为每个模型添加预测值和实际功率的曲线
+    for model in models:
+        # 筛选该模型的数据
+        model_data = df_predict[df_predict['model'] == model]
+
+        # 添加预测值曲线
+        fig.add_trace(go.Scatter(
+            x=model_data[col_time],
+            y=model_data[label_pre],
+            mode='lines+markers',
+            name=f'{model} 预测值',  # 预测值
+            marker=dict(symbol='circle'),
+            line=dict(width=2)
+        ))
+
+    # 设置图表的标题和标签
+    fig.update_layout(
+        template='seaborn',  # 使用 seaborn 模板
+        title=dict(
+            text=f"{label_pre} 与 {label} 对比",  # 标题
+            x=0.5, font=dict(size=20, color='darkblue')  # 标题居中并设置字体大小和颜色
+        ),
+        plot_bgcolor='rgba(255, 255, 255, 0.8)',  # 背景色
         xaxis=dict(
             showgrid=True,
             gridcolor='rgba(200, 200, 200, 0.5)',  # 网格线颜色
+            title='时间',  # 时间轴标题
             rangeslider=dict(visible=True),  # 显示滚动条
             rangeselector=dict(visible=True)  # 显示预设的时间范围选择器
         ),
-        yaxis=dict(showgrid=True, gridcolor='rgba(200, 200, 200, 0.5)'),
-        legend=dict(x=0.01, y=0.99, bgcolor='rgba(255, 255, 255, 0.7)', bordercolor='black', borderwidth=1)
+        yaxis=dict(
+            showgrid=True,
+            gridcolor='rgba(200, 200, 200, 0.5)',
+            title='功率'  # y轴标题
+        ),
+        legend=dict(
+            x=0.01,
+            y=0.99,
+            bgcolor='rgba(255, 255, 255, 0.7)',  # 背景透明
+            bordercolor='black',
+            borderwidth=1,
+            font=dict(size=12)  # 字体大小
+        ),
+        hovermode='x unified',  # 鼠标悬停时显示统一的提示框
+        hoverlabel=dict(
+            bgcolor='white',
+            font_size=14,
+            font_family="Rockwell",  # 设置字体样式
+            bordercolor='black'
+        ),
+        margin=dict(l=50, r=50, t=50, b=50)  # 调整边距,避免标题或标签被遮挡
     )
-
     # 将折线图保存为 HTML 片段
-    power_html = pio.to_html(fig_line, full_html=False)
+    power_html = pio.to_html(fig, full_html=False)
 
     # -------------------- 准确率表展示--------------------
     acc_html = df_accuracy.to_html(classes='table table-bordered table-striped', index=False)
+    # -------------------- 准确率汇总展示--------------------
+    # 指定需要转换的列
+    cols_to_convert = ['MAE', 'accuracy', 'RMSE', 'deviationElectricity','deviationAssessment']
+    for col in cols_to_convert :
+        if col in df_accuracy.columns:
+            df_accuracy[col] = df_accuracy[col].apply(
+        lambda x: float(x.to_decimal()) if isinstance(x, Decimal128) else float(x) if isinstance(x, numbers.Number) else np.nan)
+
+    # 确定存在的列
+    agg_dict = {}
+    rename_cols = ['model']
+    if 'MAE' in df_accuracy.columns:
+        agg_dict['MAE'] = np.nanmean
+        rename_cols.append('MAE平均值')
+    if 'accuracy' in df_accuracy.columns:
+        agg_dict['accuracy'] = np.nanmean
+        rename_cols.append('准确率平均值')
+    if 'RMSE' in df_accuracy.columns:
+        agg_dict['RMSE'] = np.nanmean
+        rename_cols.append('RMSE平均值')
+    if 'deviationElectricity' in df_accuracy.columns:
+        agg_dict['deviationElectricity'] = [np.nanmean, np.nansum]
+        rename_cols.append('考核电量平均值')
+        rename_cols.append('考核总电量')
+    if 'deviationAssessment' in df_accuracy.columns:
+        agg_dict['deviationAssessment'] = [np.nanmean, np.nansum]
+        rename_cols.append('考核分数平均值')
+        rename_cols.append('考核总分数')
+    # 进行分组聚合,如果有需要聚合的列
+    summary_df = df_accuracy.groupby('model').agg(agg_dict).reset_index()
+    summary_df.columns =rename_cols
+    summary_html = summary_df.to_html(classes='table table-bordered table-striped', index=False)
     # -------------------- 生成完整 HTML 页面 --------------------
 
     html_content = f"""
@@ -201,6 +282,8 @@ def put_analysis_report_to_html(args,df_clean,df_accuracy):
                 overflow-x: auto;   /* 水平滚动条 */
                 max-width: 100%;     /* 限制宽度 */
                 white-space: nowrap; /* 防止内容换行 */
+                max-height: 500px;  /* 限制高度 */
+                overflow-y: auto;   /* 显示垂直滚动条 */
             }}
             table {{
                 width: 100%;
@@ -249,6 +332,11 @@ def put_analysis_report_to_html(args,df_clean,df_accuracy):
                 <h2>8. 准确率对比</h2>
                 {acc_html}
             </div>
+            <!-- Pandas DataFrame 表格 -->
+            <div class="table-container">
+                <h2>9. 准确率汇总对比</h2>
+                {summary_html}
+            </div>
         </div>
     </body>
     </html>
@@ -277,8 +365,8 @@ def analysis_report():
         print('args',args)
         logger.info(args)
         #获取数据
-        df_clean, df_accuracy = get_df_list_from_mongo(args)[0], get_df_list_from_mongo(args)[1]
-        path = put_analysis_report_to_html(args, df_clean, df_accuracy)
+        df_clean, df_predict, df_accuracy = get_df_list_from_mongo(args)[0], get_df_list_from_mongo(args)[1],get_df_list_from_mongo(args)[2]
+        path = put_analysis_report_to_html(args, df_clean, df_predict, df_accuracy)
         success = 1
     except Exception as e:
         my_exception = traceback.format_exc()

+ 77 - 0
post_processing/post_processing.py

@@ -0,0 +1,77 @@
+import pandas as pd
+from flask import Flask,request,jsonify
+import time
+import logging
+import traceback
+
+from common.database_dml import get_data_from_mongo,insert_data_into_mongo
+
+app = Flask('post_processing——service')
+
+
+@app.route('/hello', methods=['POST'])
+def hello():
+    return jsonify(message='Hello, World!')
+
+
+#1.AGC/AVC信号判断限电(有的场站准 有的不准) 1种方法  数据库数据有问题 暂时用不了
+def  predict_result_adjustment(df, args):
+    params = eval(args['params'])
+    df_res = pd.DataFrame()
+    model_names = params['new_names'].keys()
+    for model in params['adjustments']:
+        if model in model_names:
+            new_name = params['new_names'][model]
+        else:
+            new_name = model
+        rates = params['adjustments'][model].keys()
+        df_tmp = df[df['model']==model]
+        df_tmp['hour'] = df_tmp['dateTime'].apply(lambda x:x[11:13])
+        df_tmp['model'] = new_name
+        for rate in rates:
+            hours = params['adjustments'][model][rate]
+            # 提取小时部分(格式化为两位字符串
+            df_tmp.loc[df_tmp['hour'].isin(hours), 'predict'] *= float(rate)
+            # 删除临时的 hour 列
+        df_res = pd.concat([df_res,df_tmp],ignore_index=True)
+    return df_res.drop('hour', axis=1)
+
+
+@app.route('/post_processing', methods=['POST'])
+def data_join():
+    # 获取程序开始时间  
+    start_time = time.time()  
+    result = {}
+    success = 0
+    print("Program starts execution!")
+    try:
+        args = request.values.to_dict()
+        print('args',args)
+        logger.info(args)
+        df_pre = get_data_from_mongo(args)
+        res_df = predict_result_adjustment(df_pre, args)
+        insert_data_into_mongo(res_df,args)
+        success = 1
+    except Exception as e:
+        my_exception = traceback.format_exc()
+        my_exception.replace("\n","\t")
+        result['msg'] = my_exception
+    end_time = time.time()
+    result['success'] = success
+    result['args'] = args
+    result['start_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(start_time))
+    result['end_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(end_time))
+    print("Program execution ends!")
+    return result
+
+
+if __name__=="__main__":
+    print("Program starts execution!")
+    logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+    logger = logging.getLogger("post_processing")
+    from waitress import serve
+    serve(app, host="0.0.0.0", port=10098)
+    print("server start!")
+    
+   
+    

+ 1 - 0
run_all.py

@@ -15,6 +15,7 @@ services = [
     ("models_processing/model_predict/model_prediction_lightgbm.py", 10090),
     ("models_processing/model_train/model_training_lstm.py", 10096),
     ("models_processing/model_predict/model_prediction_lstm.py", 10097),
+    ("post_processing/post_processing.py", 10098),
 ]
 
 # 获取当前脚本所在的根目录