# -*- coding: utf-8 -*- """生成「运行形态塌陷 · 动态三维」交互页。 数据源: 如东 obs_sprt / mset_sprt 的 morphology_health_margin_grid.csv (各 1080 行 = 4 台 x 18 月 x 15 风速档)。 已脱敏: 台号重编为 机组 A-D, 不含场名与厂商。 边界(引自 method_metadata.json, 原文照搬, 不得删): - 本通道只用运行形态, 不含轴承/齿轮温度与振动特征 - 1 分钟源数据止于 2026-06-30 - 合格的 SPRT 候选是**审计条目, 不是部件故障结论** """ import csv, json, pathlib, collections SRC = pathlib.Path("/Users/yuanying/wind-analytics/outputs/rudong/integrated_diagnostic_report") SIM = pathlib.Path("/Users/yuanying/guanlan-rudong-v2/outputs/rudong/windscada/_demo/sim") def load(algo): rows = list(csv.DictReader(open(SRC/algo/"morphology_health_margin_grid.csv", encoding="utf-8-sig"))) meta = json.load(open(SRC/algo/"method_metadata.json", encoding="utf-8")) tids = sorted({r["tid"] for r in rows}) months = sorted({r["month"] for r in rows}) bins = sorted({int(float(r["wind_bin"])) for r in rows}) alias = {t: f"机组 {chr(65+i)}" for i, t in enumerate(tids)} # 脱敏: 台号重编 grid = {} for t in tids: z = [[None]*len(bins) for _ in months] for r in rows: if r["tid"] != t: continue v = r["health_margin"] if v in ("", "nan"): continue z[months.index(r["month"])][bins.index(int(float(r["wind_bin"])))] = round(float(v), 4) grid[alias[t]] = z return {"turbines": [alias[t] for t in tids], "months": months, "bins": bins, "grid": grid, "thr": next((meta[k] for k in ("obs_threshold_95","mset_threshold_95","threshold_95") if k in meta), None), "full_mset": not meta.get("not_true_mset", False), "limits": meta.get("limitations", []), "nfeat": len(meta.get("features", []))} DATA = {"简化记忆矩阵法": load("obs_sprt"), "完整相似算子法": load("mset_sprt")} J = json.dumps(DATA, ensure_ascii=False) HTML = f''' 运行形态塌陷 · 动态三维
运行形态塌陷 · 动态三维MORPHOLOGY COLLAPSE 3D
← 返回仿真集成台
实测 · 可旋转可缩放

健康曲面上戳下去的那几口井

横轴风速档、纵轴月份、高度是健康裕度。绿色平面是正常, 裕度掉到零平面以下就是形态塌陷 —— 在图上表现为从曲面往下扎的一口井。 拖动可旋转、滚轮可缩放、悬停看具体数值。

怎么读:零平面以上=该风速档该月的运行形态与参照机群一致; 往下扎的井=形态偏离,越深偏离越大。两种算法可切换对照 —— 同一口井两种算法都出现,才值得立案;只有一种算法出现的,先当候选。

⚠ 深度数值不可跨算法比。两法的诊断指标量纲差很远(阈值一个 0.754、一个 0.034),同一台机器在完整相似算子法下的井会深十几倍甚至上百倍 —— 那是量纲问题,不是它更坏。可比的只有位置模式:哪些风速档、哪些月份塌了。两法都在同一格出现井,才值得立案。
边界(引自方法元数据,原文照搬):
    观澜 · 运行形态塌陷动态三维 · 数据已脱敏(台号重编,不含场名与厂商)· 离线单文件(图形库本地)
    ''' p = SIM/"运行形态塌陷_动态三维.html" p.write_text(HTML, encoding="utf-8") print(f"written {p.name} {len(HTML)//1024} KB") for k,v in DATA.items(): print(f" {k}: {len(v['turbines'])} 台 x {len(v['months'])} 月 x {len(v['bins'])} 档 | 阈值 {v['thr']:.4f} | 完整MSET={v['full_mset']} | 限制 {len(v['limits'])} 条") leaks={k:HTML.count(k) for k in ["如东","33A","17B","23C","38B","rudong"] if HTML.count(k)} print(" 标识残留:", leaks or "0 ✓")