run_machine_events.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. """生成整机多缸振动事件标签、验证表和摘要。"""
  2. from __future__ import annotations
  3. import json
  4. import sys
  5. from pathlib import Path
  6. import pandas as pd
  7. ROOT = Path(__file__).resolve().parents[1]
  8. if str(ROOT) not in sys.path:
  9. sys.path.insert(0, str(ROOT))
  10. from _tmp_cylinder_vibration import config, machine_event_html, machine_events, unified_labels
  11. def main() -> None:
  12. frame = pd.read_csv(config.OUTPUT_DIR / "vibration_features_full_local.csv")
  13. frame["sample_time"] = pd.to_datetime(frame["sample_time"])
  14. labels = pd.read_csv(config.OUTPUT_DIR / "cylinder_vibration_label_unified.csv")
  15. hourly = pd.read_csv(config.OUTPUT_DIR / "vibration_hourly_labels.csv")
  16. hourly["start_hour"] = pd.to_datetime(hourly["start_hour"])
  17. runs = machine_events.build_runs(frame)
  18. events, candidates, windows = machine_events.build_machine_events(labels, frame, hourly, runs)
  19. validation = machine_events.validate_events(events)
  20. summary = machine_events.build_summary(events, candidates, validation, runs)
  21. events.to_csv(
  22. config.OUTPUT_DIR / "machine_vibration_events.csv",
  23. index=False,
  24. date_format="%Y-%m-%d %H:%M:%S",
  25. )
  26. candidates.to_csv(
  27. config.OUTPUT_DIR / "machine_event_candidates.csv",
  28. index=False,
  29. date_format="%Y-%m-%d %H:%M:%S",
  30. )
  31. validation.to_csv(
  32. config.OUTPUT_DIR / "machine_event_validation.csv",
  33. index=False,
  34. date_format="%Y-%m-%d %H:%M:%S",
  35. )
  36. (config.OUTPUT_DIR / "machine_event_summary.json").write_text(
  37. json.dumps(summary, ensure_ascii=False, indent=2, default=str),
  38. encoding="utf-8",
  39. )
  40. temperature = unified_labels._map_external(
  41. Path("/Users/zhouhao/Code/Python/Compressor/_tmp_temperature/out/温度异常段.csv"),
  42. "温度异常",
  43. "T",
  44. unit="5号机",
  45. )
  46. machine = events.reindex(columns=unified_labels.CORE_FIELDS)
  47. combined = pd.concat([temperature, machine], ignore_index=True)
  48. combined.to_csv(
  49. config.OUTPUT_DIR / "fault_label_unified_machine_preview.csv",
  50. index=False,
  51. date_format="%Y-%m-%d %H:%M:%S",
  52. )
  53. lines = [
  54. "# 5 号机缸体振动整机事件标签",
  55. "",
  56. "## 规则",
  57. "",
  58. "- 稳定运行段:开机后 6 小时、停机前 6 小时不生成最终事件;",
  59. "- 不排除首次基线预热段;4 月以前只是未取得数据;",
  60. "- 24 小时窗口内至少 4 个不同缸出现候选标签;",
  61. "- 其中至少 2 条达到“异常”或“严重异常”;",
  62. "- 相邻候选窗口合并为一个整机事件;",
  63. "- 事件不指定故障缸,故障缸只用于事后验证。",
  64. "",
  65. "## 结果",
  66. "",
  67. f"- 候选标签:{len(candidates)} 条;",
  68. f"- 整机事件:{len(events)} 个;",
  69. f"- 运行段:{len(runs)} 个;",
  70. f"- 有事件运行段:{summary['event_runs']} 个;",
  71. f"- 无事件运行段:{summary['normal_runs']} 个;",
  72. f"- 验证事件:{summary['validation']['hit']}/{summary['validation']['total']} 命中。",
  73. "",
  74. "## 事件列表",
  75. "",
  76. ]
  77. lines.append("| 标签ID | 开始 | 结束 | 等级 | 参与缸 | 异常缸 | 严重异常缸 | 验证提前量 |")
  78. lines.append("|---|---|---|---|---|---:|---:|---:|")
  79. lead_map = {
  80. row.machine_label_id: row.lead_days
  81. for row in validation.itertuples(index=False)
  82. if row.hit
  83. }
  84. for row in events.itertuples(index=False):
  85. lead = lead_map.get(row.标签ID)
  86. lines.append(
  87. f"| {row.标签ID} | {row.开始小时} | {row.结束小时} | {row.阶段} | "
  88. f"{row.参与缸} | {row.异常缸数} | {row.严重异常缸数} | "
  89. f"{'—' if lead is None else f'{lead:.2f} 天'} |"
  90. )
  91. lines.extend([
  92. "",
  93. "## 验证",
  94. "",
  95. "| 事件 | 故障缸 | 命中 | 整机事件 | 开始 | 结束 | 提前量 |",
  96. "|---|---|---|---|---|---|---:|",
  97. ])
  98. for row in validation.itertuples(index=False):
  99. lines.append(
  100. f"| {row.event_id} | {row.fault_cylinder} | {'是' if row.hit else '否'} | "
  101. f"{row.machine_label_id} | {row.start_time} | {row.end_time} | "
  102. f"{'—' if not row.hit else f'{row.lead_days:.2f} 天'} |"
  103. )
  104. (config.OUTPUT_DIR / "machine_event_labels.md").write_text("\n".join(lines) + "\n", encoding="utf-8")
  105. machine_event_html.export_machine_events(frame, events, candidates, validation)
  106. print(f"[machine] candidates={len(candidates)}, events={len(events)}, runs={len(runs)}, event_runs={summary['event_runs']}, preview={len(combined)}")
  107. print(f"[machine] validation={summary['validation']['hit']}/{summary['validation']['total']}")
  108. print(events[["标签ID", "开始小时", "结束小时", "阶段", "参与缸", "异常缸数", "严重异常缸数"]].to_string(index=False))
  109. if __name__ == "__main__":
  110. main()