]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/ergodox_ez/keymaps/algernon/tools/log-to-heatmap.py
Merge pull request #584 from algernon/ergodox-ez/algernon
[qmk_firmware.git] / keyboards / ergodox_ez / keymaps / algernon / tools / log-to-heatmap.py
1 #! /usr/bin/env python
2 import json
3 import os
4 import sys
5 import re
6
7 from math import floor
8
9 cr_coord_map = [
10     [
11         # Row 0
12         [ 4,  0], [ 4,  2], [ 2,  0], [ 1,  0], [ 2,  2], [ 3,  0], [ 3,  2],
13         [ 3,  4], [ 3,  6], [ 2,  4], [ 1,  2], [ 2,  6], [ 4,  4], [ 4,  6],
14     ],
15     [
16         # Row 1
17         [ 8,  0], [ 8,  2], [ 6,  0], [ 5,  0], [ 6,  2], [ 7,  0], [ 7,  2],
18         [ 7,  4], [ 7,  6], [ 6,  4], [ 5,  2], [ 6,  6], [ 8,  4], [ 8,  6],
19     ],
20     [
21         # Row 2
22         [12,  0], [12,  2], [10,  0], [ 9,  0], [10,  2], [11, 0], [     ],
23         [      ], [11,  2], [10,  4], [ 9,  2], [10,  6], [12, 4], [12, 6],
24     ],
25     [
26         # Row 3
27         [17,  0], [17,  2], [15,  0], [14,  0], [15,  2], [16,  0], [13,  0],
28         [13,  2], [16,  2], [15,  4], [14,  2], [15,  6], [17,  4], [17,  6],
29     ],
30     [
31         # Row 4
32         [20,  0], [20,  2], [19,  0], [18,  0], [19,  2], [], [], [], [],
33         [19,  4], [18,  2], [19,  6], [20,  4], [20,  6],
34     ],
35     [
36         # Row 5
37         [     ], [23,  0], [22,  2], [22,  0], [22,  4], [21,  0], [21,  2],
38         [24, 0], [24,  2], [25,  0], [25,  4], [25,  2], [26,  0], [      ],
39     ],
40 ]
41
42 def set_attr_at(j, b, n, attr, fn, val):
43     blk = j[b][n]
44     if attr in blk:
45         blk[attr] = fn(blk[attr], val)
46     else:
47         blk[attr] = fn(None, val)
48
49 def coord(col, row):
50     return cr_coord_map[row][col]
51
52 def set_attr(orig, new):
53     return new
54
55 def set_bg(j, (b, n), color):
56     set_attr_at(j, b, n, "c", set_attr, color)
57     #set_attr_at(j, b, n, "g", set_attr, False)
58
59 def _set_tap_info(o, count, cap):
60     ns = 4 - o.count ("\n")
61     return o + "\n" * ns + "%.02f%%" % (float(count) / float(cap) * 100)
62
63 def set_tap_info(j, (b, n), count, cap):
64     j[b][n + 1] = _set_tap_info (j[b][n + 1], count, cap)
65
66 def heatmap_color (v):
67     colors = [ [0.3, 0.3, 1], [0.3, 1, 0.3], [1, 1, 0.3], [1, 0.3, 0.3]]
68     fb = 0
69     if v <= 0:
70         idx1, idx2 = 0, 0
71     elif v >= 1:
72         idx1, idx2 = len(colors) - 1, len(colors) - 1
73     else:
74         val = v * (len(colors) - 1)
75         idx1 = int(floor(val))
76         idx2 = idx1 + 1
77         fb = val - float(idx1)
78
79     r = (colors[idx2][0] - colors[idx1][0]) * fb + colors[idx1][0]
80     g = (colors[idx2][1] - colors[idx1][1]) * fb + colors[idx1][1]
81     b = (colors[idx2][2] - colors[idx1][2]) * fb + colors[idx1][2]
82
83     r, g, b = [x * 255 for x in r, g, b]
84     return "#%02x%02x%02x" % (r, g, b)
85
86 # Load the keylog
87 def load_keylog(fname, restrict_row):
88     keylog = {}
89     total = 0
90     with open(fname, "r") as f:
91         lines = f.readlines()
92     for line in lines:
93         m = re.search ('KL: col=(\d+), row=(\d+)', line)
94         if not m:
95             continue
96         (c, r) = (int(m.group (2)), int(m.group (1)))
97         if restrict_row != None and r != int(restrict_row):
98             continue
99         if (c, r) in keylog:
100             keylog[(c, r)] = keylog[(c, r)] + 1
101         else:
102             keylog[(c, r)] = 1
103         total = total + 1
104     return total / 2, keylog
105
106 def l_flat(s):
107     f = s.split("\n")
108     return ", ".join (f)
109
110 def main(base_fn, log_fn, restrict_row = None):
111
112     with open(base_fn, "r") as f:
113         layout = json.load (f)
114
115     ## Reset colors
116     for row in cr_coord_map:
117         for col in row:
118             if col != []:
119                 set_bg (layout, col, "#d9dae0")
120                 #set_attr_at (layout, col[0], col[1], "g", set_attr, True)
121
122     total, log = load_keylog (log_fn, restrict_row)
123     max_cnt = 0
124     for (c, r) in log:
125         max_cnt = max(max_cnt, log[(c, r)])
126
127     # Create the heatmap
128     for (c, r) in log:
129         coords = coord(c, r)
130         b, n = coords
131         cap = max_cnt
132         v = float(log[(c, r)]) / cap
133         print >> sys.stderr, "%s => %d/%d => %f = %s" % (l_flat(layout[b][n+1]), log[(c,r)], cap, v, heatmap_color(v))
134         set_bg (layout, coord(c, r), heatmap_color (v))
135         set_tap_info (layout, coord (c, r), log[(c, r)], total)
136
137     print json.dumps(layout)
138
139 if __name__ == "__main__":
140     if len(sys.argv) < 3:
141         print """Log to Heatmap -- creates a heatmap out of keyboard logs
142
143 Usage: log-to-heatmap.py base-layout.json logfile [row] >layout.json"""
144         sys.exit (1)
145     main(*sys.argv[1:])