================================================================================
  A14 底层算法库 — 工作人员操作文档
  版本 1.0  |  2026-07-08
================================================================================

【环境要求】
- Python 3.10+
- 依赖：pip install pandas numpy scipy scikit-learn statsmodels matplotlib pytest

【目录结构】
backend/app/algorithms/
├── preprocess.py   数据清洗
├── segment.py      动态数据截取（Rhinehart算法）
├── quality.py      质量评分
├── delay.py        时滞分析
├── collinear.py    共线性分析（VIF + PCA）
├── identify.py     系统辨识（ARX模型）
├── visualize.py    可视化图表生成
└── __init__.py     统一入口

data/synthetic/
└── generate_data.py  仿真测试数据生成器


════════════════════════════════════════════════════════
  一、快速验证（运行测试）
════════════════════════════════════════════════════════

cd backend/
python -m pytest tests/test_algorithms.py -v

预期：32 passed

如果失败，先确认依赖安装完整：
  pip install -r requirements.txt


════════════════════════════════════════════════════════
  二、各模块功能与调用示例
════════════════════════════════════════════════════════

以下所有示例代码均可直接在 backend/ 目录下 python 交互式运行。
（前提：先 from app.algorithms.xxx import ...）


2.1 仿真数据生成
────────────────────────────────────────
文件：data/synthetic/generate_data.py

  from data.synthetic.generate_data import generate_synthetic_data
  # (如果 import 路径不对，直接把该文件内容复制到当前目录运行)

  df = generate_synthetic_data(
      n_samples=2000,      # 采样点数
      n_variables=4,       # 变量数
      noise_level=0.1,     # 噪声水平，越大越嘈杂
      seed=42,             # 随机种子，固定可复现
  )
  df.to_csv("test_data.csv")
  print(df.columns)
  # ['MV1_InletFlow', 'CV1_Temperature', 'CV2_Pressure', 'DV1_AmbientTemp']

生成的数据特点：
  - MV1_InletFlow：含两次阶跃 + 异常尖峰（阶跃点在1/5和3/5处）
  - CV1_Temperature：与 MV1 相关，滞后 30 个采样点
  - CV2_Pressure：自回归 + MV1 耦合
  - DV1_AmbientTemp：纯噪声扰动变量


2.2 数据清洗（preprocess.py）
────────────────────────────────────────

  from app.algorithms.preprocess import clean_pipeline

  df_clean, stats = clean_pipeline(
      df,
      cols=["MV1_InletFlow", "CV1_Temperature", "CV2_Pressure", "DV1_AmbientTemp"],
      outlier_method="3sigma",    # 或 "iqr"
      outlier_threshold=3.0,      # 3σ，IQR因子时填 1.5
      missing_method="interpolate", # "ffill" | "bfill" | "drop" | "mean"
  )

  print(stats)
  # {
  #   "original_shape": (2000, 4),
  #   "cleaned_shape": (2000, 4),
  #   "outliers_detected": 12,      ← 检测到的异常值个数
  #   "columns_processed": [...],
  #   "outlier_method": "3sigma",
  #   ...
  # }

单独调用：
  from app.algorithms.preprocess import detect_outliers_3sigma, handle_missing

  df = detect_outliers_3sigma(df, cols=["MV1_InletFlow"], threshold=3.0)
  df = handle_missing(df, cols=["MV1_InletFlow"], method="interpolate")


2.3 动态数据截取（segment.py）★ 核心亮点
────────────────────────────────────────
基于 Rhinehart 2013 论文算法，自动区分稳态段和瞬态段。

  from app.algorithms.segment import identify_steady_transient, extract_dynamic_data

  # 方式一：单变量识别
  labels = identify_steady_transient(
      df_clean["MV1_InletFlow"].values,
      method="rhinehart",    # "rhinehart" | "rate"
      window=60,             # 滑动窗口大小
      threshold=0.5,         # 判定阈值，越大越严格
  )
  # labels: bool数组，True=瞬态点，False=稳态点

  # 方式二：一键截取动态段
  result = extract_dynamic_data(
      df_clean,
      var_cols=["MV1_InletFlow"],
      method="rhinehart",
      window=60,
      threshold=0.5,
      min_segment_length=20,
      expand_margin=30,
  )
  print(f"截取到 {len(result['segments'])} 个动态段")
  # result['combined_df'] 是所有瞬态段拼接的结果
  # result['labels'] 是标注数组
  # result['dataframes'] 是各段 DataFrame 的列表

参数调优建议：
  - 窗口 window 越大越平滑，但响应变慢。建议 30~100
  - threshold 越大越严格（只识别剧烈瞬态）。建议 0.3~1.0
  - 如果识别到的瞬态段太多，增大 threshold
  - 如果识别到的太少，减小 threshold


2.4 质量评分（quality.py）
────────────────────────────────────────

  from app.algorithms.quality import score_segment, rank_segments

  # 对单个段评分
  info = score_segment(df_segment, var_cols=["MV1_InletFlow", "CV1_Temperature"])
  print(info)
  # {
  #   "total_score": 68.5,        ← 综合分 (0-100)
  #   "snr_score": 72.3,          ← 信噪比得分
  #   "dynamic_score": 58.1,      ← 动态丰富度得分
  #   "stationarity_score": 45.2, ← 平稳性得分（适中最优）
  #   "length_score": 83.3,       ← 长度得分
  #   "snr_values": {"MV1_InletFlow": 12.5, "CV1_Temperature": 8.3},
  # }

  # 对多个段排序
  ranked = rank_segments(result["dataframes"])
  for r in ranked:
      print(f"段{r['segment_index']}: 总分={r['total_score']}")


2.5 时滞分析（delay.py）
────────────────────────────────────────

  from app.algorithms.delay import compute_time_delay, time_delay_matrix, compensate_delay

  # 两变量时滞计算
  result = compute_time_delay(
      df["MV1_InletFlow"].values,
      df["CV1_Temperature"].values,
      max_lag=100,   # 最大搜索范围（采样点）
      dt=1.0,        # 采样间隔（秒）
  )
  print(f"时滞: {result['lag_samples']} 采样点 ({result['lag_seconds']}秒)")
  print(f"互相关系数: {result['correlation']}")
  # 正值 = MV1 超前 CV1（CV1 的响应滞后）

  # 多变量时滞矩阵
  matrix = time_delay_matrix(df, var_cols=["MV1_InletFlow", "CV1_Temperature", "CV2_Pressure"])
  print(matrix)
  #                   MV1_InletFlow  CV1_Temperature  CV2_Pressure
  # MV1_InletFlow               0               30            -5
  # CV1_Temperature            -30                0           -35
  # CV2_Pressure                 5               35             0

  # 时滞补偿
  df_aligned = compensate_delay(df, matrix, reference_col="MV1_InletFlow")


2.6 共线性分析（collinear.py）
────────────────────────────────────────

  from app.algorithms.collinear import compute_vif, find_redundant_variables, pca_reduce

  # VIF 检测
  vif_df = compute_vif(df_clean, cols=["MV1_InletFlow", "CV1_Temperature", "CV2_Pressure", "DV1_AmbientTemp"])
  print(vif_df)
  #   variable           VIF
  #   CV2_Pressure      8.23
  #   MV1_InletFlow     5.41
  #   CV1_Temperature   3.12
  #   DV1_AmbientTemp   1.05
  # VIF > 10 表示严重共线性，建议剔除

  # 自动找冗余变量
  result = find_redundant_variables(df_clean, vif_threshold=10.0)
  print(f"保留: {result['keep']}")
  print(f"建议剔除: {result['redundant']}")

  # PCA 降维
  pca_result = pca_reduce(df_clean, variance_threshold=0.95)
  print(f"保留 {pca_result['n_components_kept']} 个主成分")
  print(f"累积方差解释率: {pca_result['cumulative_variance']}")


2.7 系统辨识（identify.py）
────────────────────────────────────────

  from app.algorithms.identify import ARXModel, auto_select_order

  # 手动指定阶次
  model = ARXModel(na=2, nb=2, nk=1)   # na=输出历史, nb=输入历史, nk=输入延迟
  info = model.fit(
      y=df_clean["CV1_Temperature"].values,   # 输出变量
      u=df_clean["MV1_InletFlow"].values,     # 输入变量
  )
  print(f"FIT%:{info['FIT_percent']:.2f}  FPE:{info['FPE']:.6f}  AIC:{info['AIC']:.1f}")
  # FIT% 越接近 100 越好，工业场景 70%+ 就算好
  # FPE/AIC 越小越好

  # 预测
  y_pred = model.predict(y, u)

  # 自动选阶次
  best = auto_select_order(
      y, u,
      na_range=(1, 5),    # 搜索 na 1~5
      nb_range=(1, 5),    # 搜索 nb 1~5
      nk=1,
      criterion="AIC",    # "AIC" | "FPE" | "FIT"
  )
  print(f"最佳阶次: na={best['best_na']}, nb={best['best_nb']}")


2.8 可视化（visualize.py）
────────────────────────────────────────
所有函数返回 base64 编码的 PNG 字符串，可直接嵌入 HTML/JSON。

  from app.algorithms.visualize import (
      plot_cleaning_comparison, plot_dynamic_segments,
      plot_correlation_heatmap, plot_delay_heatmap,
      plot_convergence_curve, plot_prediction_vs_actual,
  )

  # 清洗前后对比图
  img = plot_cleaning_comparison(raw_df, clean_df, "MV1_InletFlow")
  # img 是 base64 字符串，前端: <img src="data:image/png;base64,{{img}}">

  # 动态区段波形高亮图（红底=瞬态，绿底=稳态）
  img = plot_dynamic_segments(df, "MV1_InletFlow", labels)

  # 相关性热力图
  img = plot_correlation_heatmap(df)

  # 时滞矩阵热力图
  img = plot_delay_heatmap(delay_matrix)

  # 闭环寻优收敛曲线
  img = plot_convergence_curve(
      iterations=[1,2,3,4,5],
      scores=[60, 72, 85, 88, 87],
      metric_name="FIT%",
  )

  # ARX 预测 vs 实际
  img = plot_prediction_vs_actual(y_true, y_pred, fit_pct=85.3)

保存图片到文件的方式：
  import base64
  with open("output.png", "wb") as f:
      f.write(base64.b64decode(img))


════════════════════════════════════════════════════════
  三、完整流水线脚本
════════════════════════════════════════════════════════

#!/usr/bin/env python
"""A14 完整数据处理流水线"""
import sys
sys.path.insert(0, ".")
from app.algorithms.preprocess import clean_pipeline
from app.algorithms.segment import extract_dynamic_data
from app.algorithms.quality import rank_segments
from app.algorithms.delay import time_delay_matrix
from app.algorithms.collinear import collinearity_pipeline
from app.algorithms.identify import ARXModel

# 假设已有 DataFrame df
# 1. 清洗
df, stats = clean_pipeline(df, outlier_method="3sigma")

# 2. 截取动态段
result = extract_dynamic_data(df, var_cols=["MV1_InletFlow"], method="rhinehart")

# 3. 质量排序
scores = rank_segments(result["dataframes"])
print(f"最优段: 总分={scores[0]['total_score']}")

# 4. 时滞
matrix = time_delay_matrix(df)

# 5. 共线性
coll = collinearity_pipeline(df)

# 6. ARX 辨识（用最优段）
best_seg = result["dataframes"][scores[0]["segment_index"]]
model = ARXModel(na=2, nb=2, nk=1)
info = model.fit(
    y=best_seg["CV1_Temperature"].values,
    u=best_seg["MV1_InletFlow"].values,
)
print(f"FIT% = {info['FIT_percent']:.2f}%")
