-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkeyboard_plot.py
More file actions
127 lines (107 loc) · 3.12 KB
/
keyboard_plot.py
File metadata and controls
127 lines (107 loc) · 3.12 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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import csv
from collections import defaultdict
import matplotlib.pyplot as plt
CSV_PATH = "keyboard_freq.csv"
FIG_SCALE = 1.0
KEY_ALIAS = {
"[space]": "SPACE",
"[shift]": "SHIFT",
"[shift_r]": "RSHIFT",
"[ctrl_l]": "CTRL",
"[alt_l]": "ALT",
"[alt_gr]": "RALT",
"[cmd]": "WIN",
"[esc]": "ESC",
"[enter]": "ENTER",
"[tab]": "TAB",
"[backspace]": "BACKSPACE",
"[insert]": "INS",
"[delete]": "DEL",
"[page_up]": "PGUP",
"[page_down]": "PGDN",
"[up]": "↑",
"[down]": "↓",
"[left]": "←",
"[right]": "→",
"[caps_lock]": "CAPS LOCK",
}
KEY_ALIAS.update({f"[f{i}]": f"F{i}" for i in range(1, 13)})
CHAR_MAPPING = {
"`": "` ~", "~": "` ~",
"1": "1 !", "!": "1 !",
"2": "2 @", "@": "2 @",
"3": "3 #", "#": "3 #",
"4": "4 $", "$": "4 $",
"5": "5 %", "%": "5 %",
"6": "6 ^", "^": "6 ^",
"7": "7 &", "&": "7 &",
"8": "8 *", "*": "8 *",
"9": "9 (", "(": "9 (",
"0": "0 )", ")": "0 )",
"-": "- _", "_": "- _",
"=": "= +", "+": "= +",
"[": "[ {", "{": "[ {",
"]": "] }", "}": "] }",
"\\": "\\ |", "|": "\\ |",
";": "; :", ":": "; :",
"'": "' \"", "\"": "' \"",
",": ", <", "<": ", <",
".": ". >", ">": ". >",
"/": "/ ?", "?": "/ ?",
}
IGNORE_KEYS = {"\x16", "[f23]"}
def normalize_key_name(name):
if name in IGNORE_KEYS:
return None
if name in KEY_ALIAS:
return KEY_ALIAS[name]
if len(name) == 1:
if name.isalpha():
return name.upper()
if name in CHAR_MAPPING:
return CHAR_MAPPING[name]
return name
def load_freq(path):
freq = {}
with open(path, "r", encoding="utf-8") as f:
for row in csv.DictReader(f):
k = row["key"]
c = int(row["count"])
freq[k] = freq.get(k, 0) + c
return freq
def build_display_freq(raw_freq):
disp = defaultdict(int)
for k, c in raw_freq.items():
label = normalize_key_name(k)
if label is not None:
disp[label] += c
return dict(disp)
def main():
raw = load_freq(CSV_PATH)
disp = build_display_freq(raw)
total = sum(disp.values())
if total == 0:
return
prob = {k: v / total for k, v in disp.items()}
top10 = sorted(prob.items(), key=lambda x: x[1], reverse=True)[:10]
labels = [k for k, _ in top10]
probs = [v for _, v in top10]
percents = [p * 100 for p in probs]
fig, (ax_pie, ax_bar) = plt.subplots(1, 2, figsize=(FIG_SCALE * 12, FIG_SCALE * 6))
wedges, texts, autotexts = ax_pie.pie(
probs, labels=labels, autopct="%1.1f%%", startangle=90
)
for t, p in zip(autotexts, percents):
t.set_text(f"{p:.1f}%")
ax_pie.set_title("Top 10 Keys (Pie, %)")
ax_bar.bar(range(len(percents)), percents)
ax_bar.set_xticks(range(len(labels)))
ax_bar.set_xticklabels(labels, rotation=45, ha="right")
ax_bar.set_ylabel("Percentage")
ax_bar.set_title("Top 10 Keys (Bar, %)")
ax_bar.set_ylim(0, max(percents) * 1.1)
plt.tight_layout()
plt.savefig("keyboard_plot.png", dpi=300)
plt.show()
if __name__ == "__main__":
main()