GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

KeyStats   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 199
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 199
rs 10
wmc 24

11 Methods

Rating   Name   Duplication   Size   Complexity  
A key() 0 5 3
A initialize() 0 4 1
A lognorm_pdf() 0 3 1
B plot_histogram() 0 30 2
A update_stats_text() 0 11 2
A toggle_status() 0 10 2
A record() 0 4 1
A simulate() 0 18 3
A update_status() 0 10 3
B plot_char_stats() 0 34 5
A __init__() 0 54 1
1
import tkinter as tk
2
import time
3
import matplotlib.pyplot as plt
4
import numpy as np
5
6
class KeyStats(tk.Tk):
7
    def __init__(self):
8
        super().__init__()
9
        self.title("Key stats")
10
        row = 0
11
        tk.Label(self,
12
                 text="""Click button to start and Enter to stop 
13
                 recording""").grid(row=row,
14
                                    columnspan=2,
15
                                    padx=10,
16
                                    pady=10)
17
        self.status_text = tk.Label(self,
18
                                    foreground="red",
19
                                    text="")
20
        row += 1
21
        self.status_text.grid(row=row,
22
                             columnspan=2,
23
                             padx=10,
24
                             pady=10)
25
26
        self.stats_text = tk.Label(self,
27
                              text="")
28
        row += 1
29
        self.stats_text.grid(row=row,
30
                             columnspan=2,
31
                             padx=10,
32
                             pady=10)
33
34
        row += 1
35
        tk.Button(self,
36
                  text="Start recording",
37
                  command=self.toggle_status).grid(row=row,
38
                                                   column=0,
39
                                                   padx=10,
40
                                                   pady=10)
41
        tk.Button(self,
42
                  text="Start simulation",
43
                  command=self.simulate).grid(row=row,
44
                                              column=1,
45
                                              padx=10,
46
                                              pady=10)
47
48
        self.textbox = tk.Text(self)
49
        row += 1
50
        self.textbox.grid(row=row,
51
                          columnspan=2,
52
                          padx=10,
53
                          pady=10)
54
        
55
        
56
        self.bind("<Key>", self.key)
57
        self.times = []
58
        self.chars = []
59
        self.status = False
60
        self.after(500, self.update_status)
61
62
    def update_status(self):
63
        if self.status:
64
            if self.status_text['text'] == 'Recording':
65
                self.status_text['text'] =''
66
            else: self.status_text['text'] = 'Recording'
67
        else:
68
            self.status_text['text'] =''
69
        
70
        self.update()
71
        self.after(500, self.update_status)
72
        
73
    def initialize(self):
74
        self.textbox.delete(1.0, tk.END)
75
        self.chars = []
76
        self.times = []
77
78
        
79
    def toggle_status(self):
80
        self.status = not self.status
81
        if not self.status:
82
            self.times.append(time.time())
83
            self.plot_histogram()
84
            self.plot_char_stats()
85
        else:
86
            print("Started recording")
87
            self.initialize()
88
            self.textbox.focus_set()
89
90
    def plot_char_stats(self):
91
        if len(self.chars) < 2:
92
            return
93
        # Generate char dictionary
94
        intervals = self.times[1:] - self.times[:-1]
95
        char_dict = {}
96
        for i in range(len(self.chars)):
97
            char = self.chars[i]
98
            if repr(char) in char_dict:
99
                char_dict[repr(char)].add_interval(intervals[i])
100
            else:
101
                char_dict[repr(char)] = Char(repr(char), intervals[i])
102
103
        # Build bar plot of chars
104
        means = []
105
        stds = []
106
        labels = []
107
        for k,v in char_dict.items():
108
            labels.append(v.get_symbol())
109
            means.append(v.get_mean())
110
            stds.append(v.get_std())
111
112
        
113
        ind = np.arange(len(labels))  # the x locations for the bars
114
        width = 0.7
115
        fig, ax = plt.subplots()
116
        rects = ax.bar(ind, means, width, color='r', yerr=stds)
117
118
        ax.set_ylabel('Mean interval [ms]')
119
        ax.set_title('Key specific interval lengths')
120
        plt.xticks(ind + 0.5*width, labels, rotation=60)
121
        
122
        #ax.set_xticklabels(labels)
123
        plt.show()
124
        
125
126
    def plot_histogram(self):
127
        if len(self.chars) < 2:
128
            self.initialize()
129
            print("Press keys at least twice")
130
            return
131
        self.times = np.array(self.times)
132
        intervals = self.times[1:] - self.times[:-1]
133
        print("Mean key press interval: {}".format(np.mean(intervals)))
134
        print("Standard deviation of key press interval: {}".format(np.std(intervals)))
135
        orig_mu = np.mean(intervals)
136
        orig_sigma = np.std(intervals)
137
        intervals = np.log(intervals)
138
        mu = np.mean(intervals)
139
        sigma = np.std(intervals)
140
        print("You typed {} characters.".format(len(intervals)+1))
141
        print("Mean of log of key press interval: {}".format(mu))
142
        print("Standard deviation of log of key press interval: {}".format(sigma))
143
        bins = int(len(intervals)/10)
144
        n, bins, patches = plt.hist(np.exp(intervals), normed=1,
145
                                    facecolor='green', alpha=0.75)
146
        l = plt.plot(bins, self.lognorm_pdf(bins, mu, sigma), 'r--', linewidth=1)
147
        plt.xlabel('Key press interval [s]')
148
149
150
        plt.ylabel('Normalized frequency')
151
        plt.title("""Key press interval stats: 
152
        mean = {:.2f} s, std = {:.2f} s""".format(orig_mu,
153
                                                  orig_sigma))
154
        #plt.axis([40, 160, 0, 0.03])
155
        plt.grid(True)
156
157
        # Calculate char-wise stats
158
        
159
160
    def lognorm_pdf(self, x, mu, sigma):
161
        y = 1/(x*sigma*np.sqrt(2*np.pi))*np.exp(-(np.log(x)-mu)**2/(2*sigma**2))
162
        return y
163
    
164
    def update_stats_text(self):
165
        if len(self.times) < 2:
166
            return
167
        times = np.array(self.times)
168
        intervals = times[1:] - times[:-1] 
169
        orig_mu = np.mean(intervals)
170
        orig_sigma = np.std(intervals)
171
        self.stats_text['text'] = """Chars: {:d}, 
172
        Mean: {:d} ms, Std: {:d} ms""".format(len(self.times),
173
                                              int(1000 * orig_mu),
174
                                              int(1000 * orig_sigma))
175
176
    def simulate(self):
177
        times = np.array(self.times)
178
        intervals = times[1:] - times[:-1]
179
        intervals = np.log(intervals)
180
        mu = np.mean(intervals)
181
        sigma = np.std(intervals)
182
        intervals = np.exp(sigma * np.random.randn( len(self.chars)-1) + mu)
183
        self.textbox.delete(1.0, tk.END)
184
        self.textbox.insert(tk.END, self.chars[0])
185
        self.update()
186
        for i in range(len(intervals)):
187
            time.sleep(intervals[i])
188
            # Backspace
189
            if self.chars[i+1] == chr(8):
190
                self.textbox.delete('%s-2c' % tk.END, tk.END)
191
            else:
192
                self.textbox.insert(tk.END, self.chars[i+1])
193
            self.update()
194
195
    def key(self, event):
196
        if event.char == '\r':
197
            self.toggle_status()
198
        elif self.status:
199
            self.record(event.char)
200
            
201
    def record(self, key):
202
        self.times.append(time.time())
203
        self.chars.append(key)
204
        self.update_stats_text()
205
206
class Char:
207
    def __init__(self, symbol, interval):
208
        self.intervals = [interval]
209
        self.symbol = symbol
210
211
    def get_symbol(self):
212
        return str(self.symbol) + ' ' + str(len(self.get_intervals()))
213
214
    def get_intervals(self):
215
        return self.intervals
216
    
217
    def add_interval(self, interval):
218
        self.intervals.append(interval)
219
220
    def get_mean(self):
221
        # Value in milliseconds
222
        return 1000 * np.mean(np.array(self.get_intervals()))
223
        
224
    def get_std(self):
225
        # Value in milliseconds
226
        return 1000 * np.std(np.array(self.get_intervals()))
227
        
228
app = KeyStats()
229
app.mainloop()
230