Files
zyt/app/scripts/render_patient_ai_report_layout.py
2026-08-18 14:08:38 +08:00

120 lines
3.7 KiB
Python

"""Render patient-level AI report layout regressions with the offscreen Qt backend."""
from __future__ import annotations
import os
from pathlib import Path
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
from PySide6.QtGui import QFontDatabase
from PySide6.QtWidgets import QApplication, QLabel, QScrollArea
from doctor_workstation.ui.pages.reception import _ReceptionAiAnalysisDialog
def _report_payload(model_key: str) -> dict[str, object]:
model_label = "OpenAI" if model_key == "openai" else "千问"
return {
"model_key": model_key,
"model_label": model_label,
"generated_at": "2026-08-17 10:20:00",
"diagnosis_advice": [
"2型糖尿病,HbA1c 7.5%,近期空腹血糖仍有波动。",
"建议:1. 监测空腹血糖 2. 记录餐后2小时血糖 3. 复核低血糖症状",
r"保留患者原始报告结构。\n结合复诊记录动态调整随访频率。",
],
"risk_assessment": [
{"label": "低血糖", "level": "high"},
{"label": "依从性风险", "level": "medium"},
{"label": "并发症筛查延误风险", "level": "low"},
{"label": "复诊中断风险", "level": "medium"},
{
"label": "肾功能变化可能影响二甲双胍方案,需要结合复查结果持续评估。",
"level": "high",
},
{"label": "饮食波动风险", "level": "low"},
],
"treatment_advice": [
r"二甲双胍 0.5g,每日2次。\n复查肾功能后再评估剂量。",
"继续糖尿病饮食教育,并记录运动后的血糖变化。",
"如出现心悸、出汗或意识异常,及时复测血糖并按流程处置。",
],
}
def _render(
app: QApplication,
output: Path,
*,
width: int,
height: int,
) -> None:
histories = {
"qwen": [_report_payload("qwen")],
"openai": [_report_payload("openai")],
}
dialog = _ReceptionAiAnalysisDialog(histories, preferred_model="qwen")
dialog.resize(width, height)
dialog.show()
for _index in range(3):
app.processEvents()
pixmap = dialog.grab()
if pixmap.width() != width or pixmap.height() != height:
raise RuntimeError(
f"unexpected render size: {pixmap.width()}x{pixmap.height()} "
f"(expected {width}x{height})"
)
output.parent.mkdir(parents=True, exist_ok=True)
if not pixmap.save(str(output), "PNG"):
raise RuntimeError(f"failed to save {output}")
scrolls = dialog.findChildren(QScrollArea)
risks = [
label
for label in dialog.findChildren(QLabel)
if label.property("dialogAiRisk")
]
print(
"PATIENT_AI_LAYOUT",
f"{width}x{height}",
f"scrolls={len(scrolls)}",
f"horizontal_max={dialog.scroll_area.horizontalScrollBar().maximum()}",
f"risk_rows={len({label.y() for label in risks})}",
f"body_height={dialog.scroll_area.widget().height()}",
)
print(output)
dialog.close()
app.processEvents()
def main() -> int:
app = QApplication.instance() or QApplication([])
font_path = Path(r"C:\Windows\Fonts\msyh.ttc")
if font_path.is_file():
QFontDatabase.addApplicationFont(str(font_path))
output_dir = (
Path(__file__).resolve().parents[1]
/ "artifacts"
/ "patient_ai_report_layout"
)
_render(
app,
output_dir / "patient_ai_report_920x760.png",
width=920,
height=760,
)
_render(
app,
output_dir / "patient_ai_report_720x560.png",
width=720,
height=560,
)
return 0
if __name__ == "__main__":
raise SystemExit(main())