Skip to content

Instantly share code, notes, and snippets.

@seankmartin
Last active March 7, 2022 13:47
Show Gist options
  • Save seankmartin/f660eff4787b586f94d5f678932bcd27 to your computer and use it in GitHub Desktop.
Save seankmartin/f660eff4787b586f94d5f678932bcd27 to your computer and use it in GitHub Desktop.
Keypress Timer - A small python program to cumulatively time keypresses
@echo off
python -m PyInstaller ^
--noconfirm --log-level WARN ^
--onefile --nowindow ^
--name KeyTime ^
cli.py
from keyboardpress import main
if __name__ == "__main__":
main()
import pygame
import datetime
import time
def text_to_screen(
screen, text, x, y, size=50, color=(000, 000, 000), font_type="Comic Sans MS"
):
try:
text = str(text)
font = pygame.font.SysFont(font_type, 12)
text = font.render(text, True, color)
screen.blit(text, (x, y))
except Exception as e:
print("Font Error, saw it coming")
raise e
def print_info(screen, keys, key_strs, times):
for i, (key, e_time, key_str) in enumerate(zip(keys, times, key_strs)):
print_str = "Time {}, key {}:".format(i + 1, key_str)
text_to_screen(screen, print_str, 20, 20 * (i + 1))
print_str = "Elapsed time(s) {:.2f}".format(e_time)
text_to_screen(screen, print_str, 140, 20 * (i + 1))
text_to_screen(screen, "Press End to reset", 20, 20 * (len(keys) + 2))
def save_times(times, key_strs, ctrs, filename=None):
now = datetime.datetime.now()
whole_time = now.strftime("%Y-%m-%d--%H-%M-%S")
filename = f"pytimer_count_{whole_time}.csv"
print("Saving current times to {}".format(filename))
with open(filename, "w") as f:
f.write("Number,Key,Time(s)\n")
for i, (e_time, key_str) in enumerate(zip(times, key_strs)):
f.write("{},{},{:.4f}\n".format(i + 1, key_str, e_time))
filename = f"pytimer_timestamps_{whole_time}.csv"
print("Saving timestamps to {}".format(filename))
with open(filename, "w") as f:
f.write("Number,Key,Time(ms)\n")
for i, (key_str, e_time) in enumerate(ctrs):
f.write("{},{},{:.4f}\n".format(i + 1, key_str, e_time))
def main():
background_colour = (255, 255, 255)
(width, height) = (300, 200)
pygame.init()
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Keypress Timers")
screen.fill(background_colour)
pygame.display.flip()
running = True
clock = pygame.time.Clock()
key_strs = ["A", "S", "D", "Left", "Down", "Right"]
keys = [
pygame.K_a,
pygame.K_s,
pygame.K_d,
pygame.K_LEFT,
pygame.K_DOWN,
pygame.K_RIGHT,
]
times = [0 for _ in keys]
counters = [0 for _ in keys]
time_log = []
start_time = time.time()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
break
if event.type == pygame.KEYDOWN:
for i, key in enumerate(keys):
if event.key == key:
counters[i] = time.time()
ctr_adj = counters[i] - start_time
ctr_adj_ms = ctr_adj * 1000
time_log.append((key_strs[i], ctr_adj_ms))
print(f"Pressed key {key_strs[i]} at time {ctr_adj_ms:.0f}ms")
if event.key == pygame.K_END:
save_times(times, key_strs, time_log, None)
times = [0 for _ in keys]
counters = [0 for _ in keys]
start_time = time.time()
if event.type == pygame.KEYUP:
for i, key in enumerate(keys):
if event.key == key:
counters[i] = time.time() - counters[i]
times[i] += counters[i]
ms_counter = 1000 * counters[i]
print(f"Held key {key_strs[i]} for {ms_counter:.0f}ms")
screen.fill(background_colour)
print_info(screen, keys, key_strs, times)
pygame.display.update()
clock.tick(60)
save_times(times, key_strs, time_log, None)
if __name__ == "__main__":
main()
# This small python script with build script times the length of keypresses
@adarsh1109
Copy link

Hi, do you know the code for getting a timeline for each keypress (1, 2, 3, 4, space)? For example, key 1 pressed at 12223ms, key 3 at 15452ms, key 1 again at 19112ms. I need to keep track of all these keypresses (11223ms, 15452ms, 19112ms, etc.) from the beginning of the experiment in OpenSesame/Psychopy, which runs on python.

@seankmartin
Copy link
Author

Hi, I have updated the gist so it should do what you are looking for. You can set the beginning of the experiment by pressing End (a button which can be rebound on line 86 pygame.K_END).
If you are specifically looking to use keys 1, 2, 3, 4, and space - you just need to rebind them in the lists on lines 59 and 60, like so:

key_strs = ["1", "2", "3", "4", "Space"]
keys = [pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_4, pygame.K_SPACE]

@adarsh1109
Copy link

Thanks for your reply. I tried this earlier. The experiment ran, but I am still unable to access the timeline corresponding to keypresses. Under which heading (variable name) the keypress timeline is supposed to appear in the output CSV file?

@seankmartin
Copy link
Author

seankmartin commented Mar 7, 2022

There should be two separate output files that are named pytimer_count_{current-time}.csv and pytimer_timestamps_{current-time}.csv
The timeline of keypresses should be in the latter file (heading Time (ms))

@adarsh1109
Copy link

I am running this script as an inline python script (titled "KeypressTimeline") in OpenSesame.

@seankmartin
Copy link
Author

Oh I understand now sorry, I missed that

@adarsh1109
Copy link

It didn't generate any separate output file other than the main experiment CSV file where it logs all data related to the experiment.

@seankmartin
Copy link
Author

I'm not very familiar with opensesame, so I'm not sure if it can run a pygame based python script inside of it? Because this uses pygame to record the keypresses.
If you run this script by itself outside of opensesame using just python you should see a window pop up, I don't know if this window pops up in opensesame and the window is needed!

@seankmartin
Copy link
Author

Most likely (?) keyboard capturing from opensesame would need to be used instead

@adarsh1109
Copy link

There is no such pop-up window appearing. And even if it will, it will create disturbance during the experiment administration (for the participant). I think I should figure it out some other way.
Thank you for giving your time!

@seankmartin
Copy link
Author

No worries at all, best of luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment