-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvisualization.py
More file actions
98 lines (75 loc) · 3.41 KB
/
Copy pathvisualization.py
File metadata and controls
98 lines (75 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# ============================================================
# visualization.py —— 可视化层
# ============================================================
# 这一层只干一件事:把"分数字典"画成图。它不关心这些分数
# 是怎么算出来的、也不关心是哪个模型给的——上层把 scores 传进来,
# 这里只管画图。以后想换画图库(比如从 matplotlib 换成 plotly),
# 只需要改这一个文件。
# ============================================================
import matplotlib.pyplot as plt
import numpy as np
# matplotlib 默认字体不一定支持中文(容易画出方块乱码),
# 所以图上的维度标签统一换成英文;报告正文本身仍然是中文,
# 不受影响。
_LABEL_TRANSLATION = {
"语言表达": "Verbal Expression",
"行为反应": "Behavior",
"情绪状态": "Emotional State",
"自我呈现": "Self Presentation",
"环境适应": "Adaptability",
}
def plot_radar_chart(scores: dict, title: str = "Consistency Profile", show: bool = True):
"""
把一次分析的五维度分数画成雷达图。
scores 为 None(比如上一步 JSON 解析失败)时不画图,返回 None,
避免因为一次解析失败就让整个程序崩溃。
"""
if scores is None:
print("没有可用的分数数据,无法画图(可能是上一步 JSON 解析失败)")
return None
labels = [_LABEL_TRANSLATION.get(key, key) for key in scores.keys()]
values = list(scores.values())
# 雷达图要画成一个封闭的多边形,所以把第一个点重复一遍接到末尾,
# 让线条首尾相连
values += values[:1]
num_vars = len(labels)
angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
angles += angles[:1]
fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True))
ax.plot(angles, values, linewidth=2, color="#7B2FF7")
ax.fill(angles, values, color="#7B2FF7", alpha=0.25)
ax.set_xticks(angles[:-1])
ax.set_xticklabels(labels, fontsize=11)
ax.set_ylim(0, 100)
ax.set_title(title, fontsize=14, pad=20)
if show:
plt.show()
return fig
def plot_trend_chart(records: list, show: bool = True):
"""
把多次历史记录的分数连成趋势折线图,每个维度一条线。
只用有 scores 的记录(跳过解析失败、scores 为 None 的记录),
并且至少要 2 条有效记录才能连成一条线。
"""
valid_records = [r for r in records if r.get("scores")]
if len(valid_records) < 2:
print("历史记录还不够多(至少需要2次有效记录),暂时无法画趋势图。")
return None
fig, ax = plt.subplots(figsize=(8, 5))
dimension_keys = list(valid_records[0]["scores"].keys())
session_numbers = list(range(1, len(valid_records) + 1))
for key in dimension_keys:
english_label = _LABEL_TRANSLATION.get(key, key)
values = [r["scores"].get(key, None) for r in valid_records]
ax.plot(session_numbers, values, marker="o", label=english_label)
ax.set_xlabel("Session Number")
ax.set_ylabel("Consistency Score")
ax.set_ylim(0, 100)
ax.set_xticks(session_numbers)
ax.set_title("Consistency Trend Over Time")
ax.legend(loc="upper center", bbox_to_anchor=(0.5, -0.15), ncol=3)
ax.grid(True, alpha=0.3)
fig.tight_layout()
if show:
plt.show()
return fig