make_transition_labels.py 4.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #!/usr/bin/env python3
  2. """Build ``温度过渡段.csv`` from the legacy temperature events.
  3. The new run-state logic removes start/stop transition hours. The events below
  4. are the ones that disappeared for that reason; they are kept here as a separate
  5. "transition" review set, not as confirmed faults.
  6. """
  7. from __future__ import annotations
  8. import csv
  9. from pathlib import Path
  10. ROOT = Path(__file__).resolve().parent
  11. OUT = ROOT / "out"
  12. LEGACY = OUT / "legacy_temperature_events.csv"
  13. TRANSITIONS = [
  14. ("4号机", "2026-02-15 00:00:00", "持续偏高", "停机", "旧事件落在停机降温段"),
  15. ("4号机", "2026-03-24 10:00:00", "混合", "启动", "旧事件落在开机升温段"),
  16. ("4号机", "2026-04-04 17:00:00", "持续偏低", "启动", "旧事件落在开机升温段"),
  17. ("4号机", "2026-04-25 16:00:00", "持续偏高", "停机", "旧事件落在停机降温段"),
  18. ("4号机", "2026-04-26 17:00:00", "短时突升", "运行中", "运行中短时变化,非启停过渡"),
  19. ("4号机", "2026-05-30 16:00:00", "持续偏高", "停机", "旧事件落在停机降温段"),
  20. ("5号机", "2025-05-09 20:00:00", "混合", "停机", "旧事件落在停机降温段"),
  21. ("7号机", "2025-02-17 17:00:00", "持续偏高", "启动", "旧事件落在开机升温段"),
  22. ("8号机", "2025-01-18 10:00:00", "混合", "启动", "旧事件落在开机升温段"),
  23. ]
  24. FIELDS = [
  25. "key", "title", "机组", "批次", "周期编号", "级", "过渡类型", "温度阶段",
  26. "特征类型", "方向", "置信度", "开始小时", "结束小时", "持续自然小时数",
  27. "有效运行小时数", "峰值缸", "最高温度", "最大级差", "最大级差变化",
  28. "最大同级偏离", "最大同级偏低", "关联通道异常", "阶段触发依据", "关联旧事件", "过渡说明",
  29. ]
  30. def main() -> None:
  31. if not LEGACY.exists():
  32. raise SystemExit(f"缺少旧事件文件:{LEGACY}")
  33. with LEGACY.open(encoding="utf-8-sig", newline="") as handle:
  34. rows = [row for row in csv.DictReader(handle) if row.get("是否事件") == "是"]
  35. output = []
  36. for index, (unit, start, kind, transition, note) in enumerate(TRANSITIONS):
  37. match = next(
  38. (row for row in rows
  39. if row.get("机组") == unit and row.get("开始小时") == start and row.get("特征类型") == kind),
  40. None,
  41. )
  42. if match is None:
  43. print(f"未找到旧事件:{unit} {start} {kind}")
  44. continue
  45. level = match.get("温度阶段") or ""
  46. output.append({
  47. "key": f"transition:{index}",
  48. "title": f"{unit}-{match.get('级')}-{transition}过渡-{start[:16]}",
  49. "机组": unit,
  50. "批次": match.get("批次") or "",
  51. "周期编号": match.get("周期编号") or "",
  52. "级": match.get("级") or "",
  53. "过渡类型": transition,
  54. "温度阶段": level,
  55. "特征类型": kind,
  56. "方向": match.get("方向") or "",
  57. "置信度": match.get("置信度") or "",
  58. "开始小时": start,
  59. "结束小时": match.get("结束小时") or "",
  60. "持续自然小时数": match.get("持续自然小时数") or "",
  61. "有效运行小时数": match.get("有效运行小时数") or "",
  62. "峰值缸": match.get("峰值缸") or "",
  63. "最高温度": match.get("最高温度") or "",
  64. "最大级差": match.get("最大级差") or "",
  65. "最大级差变化": match.get("最大级差变化") or "",
  66. "最大同级偏离": match.get("最大同级偏离") or "",
  67. "最大同级偏低": match.get("最大同级偏低") or "",
  68. "关联通道异常": match.get("关联通道异常") or "",
  69. "阶段触发依据": ";".join(
  70. list(dict.fromkeys(
  71. item for item in (match.get("阶段触发依据") or "").split(";") if item
  72. ))
  73. ),
  74. "关联旧事件": f"{level}-{kind}",
  75. "过渡说明": note,
  76. })
  77. path = OUT / "温度过渡段.csv"
  78. with path.open("w", encoding="utf-8-sig", newline="") as handle:
  79. writer = csv.DictWriter(handle, fieldnames=FIELDS)
  80. writer.writeheader()
  81. writer.writerows(output)
  82. print(f"written {len(output)} rows -> {path}")
  83. if __name__ == "__main__":
  84. main()