psychopy.org | Reference | Downloads | Github

How to store ALL key press RTs in Coder

I’m coding a behavioral data collection task using the Coder. I’ve previously dealt only with the Builder, so there’s been a steep learning curve for me! I made the switch because presentation of longer video stim is very glitchy in the Builder, leading to audiovisual mismatches and dropped frames (see this thread where we tried unsuccessfully to resolve this problem). This issue is resolved by presenting the stimuli using the Coder instead.

The task is simple - participants watch through a loop of 5 videos (each ~5 minutes long), presented sequentially, and are asked to press the space bar when they think one event in the video ends and another one begins. I would like my output .csv to contain 5 columns - one for each video, each with a list of the RT for all keys pressed during that video (effectively communicating the times during each video at which that participant is demarcating an event).

I’ve gotten the loop to work and the time to restart with each video so that RTs are video-specific rather than experiment-specific, and I’ve been able to store the RT for the first key pressed in a separate column for each video, but I want it to store the RT for all keys pressed during each video. In the Builder, I’ve always been able to simply select “store all keys” from the drop-down menu, but this obviously isn’t possible using the Coder.

I’m assuming I need to create a list and append each RT to that list to be saved in the .csv later, but I’ve not been able to get it to work.

Here’s the code just for the video presentation and response key collection:

while n != 6: #will play the 5 video clips
    timer.reset()
    video_selected = project_dir+'/'+video_dir+'/'+video_clip[n] #selects each video clip
    
    videopath = str(video_selected) #set path for video
    if not os.path.exists(videopath):
        raise RuntimeError("Video File could not be found:" + videopath)

#play the video using VLCMovieStim
    mov = visual.VlcMovieStim(win, videopath,
        size=None,  # set as `None` to use the native video size
        pos=[0, 0],  
        flipVert=False, 
        flipHoriz=False, 
        loop=False,  # replay the video when it reaches the end
        autoStart=True)  # start the video automatically when first drawn

#while the video plays...
    while not mov.isFinished:
        keys = kb.getKeys(['space', 'escape']) #define allowed keys
        for thisKey in keys:
            RT = timer.getTime()
            if thisKey=='escape': #if escape selected, quit the program
                mov.stop()
                core.quit()
            else:
                thisExp.addData('RTvid'+str(n+1), RT) #if space selected, add response time to the csv

   # draw elements
        mov.draw() #bring the movie onto the screen
        win.flip() 
    
    n = n + 1

I’m sure this is incredibly simple to solve, but I’m (clearly) a coding amateur. Any help you can provide would be greatly appreciated!

Here’s a screen shot of what my current output looks like:

And here’s what I’d like it to look like:

The last thing is that each of the videos is ~5 minutes long, and running this program appears to be incredibly computationally intensive, and sometimes it crashes. Any suggestions for how to mediate that would be appreciated.

This might be helpful https://workshops.psychopy.org/3days/day3/improvements.html#getting-an-early-keypress… You essentially want to call getkeys() at the point where you start watching for responses then keys.rt contains a list of rts https://psychopy.org/api/hardware/keyboard.html

I think you want to update something like this:

# restart the keyboard clock
kb.clock.reset()

# start watching the keys
keys = kb.getKeys(keyList = ['left','right','escape'])

#while the video plays...
    while not mov.isFinished:
        if 'escape' in keys.name:
            mov.stop()
            core.quit()

thisExp.addaData('RTvid'+str(n+1), kb.rt)#save key rts
thisExp.addaData('RTvid'+str(n+1), kb.duration)#save key durations
thisExp.addaData('RTvid'+str(n+1), kb.name)#save key names



Hi Becca,

Thanks so much for this response! Unfortunately, I tried dozens of iterations of what you suggested here, and the experiment either crashes or the key presses don’t register at all (leaving me unable to ‘escape’ out of the experiment and with no RTs stored in my .csv). It seems like if I call the keyboard prior to the second while loop (the not mov.isFinished one you listed), it just doesn’t register any keys at all. But I’m assuming what you’re saying is that my calling it within that loop is what’s causing the task to store only the first RT.

I’ve attached my full experiment if it’s helpful to see the whole thing. As attached, the program runs (although it occasionally crashes bc I’m assuming the task is too computationally demanding), but stores only the first key press RT, rather than all of them.

codetest.py (3.9 KB)

Ah my apologies, yes getKeys should be in the while loop, like this:

from psychopy.hardware import keyboard
from psychopy import core, visual

# A keyboard object
kb = keyboard.Keyboard()

# A window to show stuff in 
window = visual.Window(monitor = 'testMonitor')

# Some text to write in the window
text = visual.TextStim(win = window, text = 'hi')

# A clock
myClock = core.Clock()

# Wait time in seconds (how long to wait and watch keypresses (e.g. a movie duration)
WAIT= 5

# Reset the clock
myClock.reset()
kb.clock.reset()# reset the keyboard clock
allKeys = []

while myClock.getTime() < WAIT:
    keys = kb.getKeys()# start watching
    for key in keys: allKeys.append(key.name)
    text.text = 'time: ' + str(int(myClock.getTime()))+ '\nkeys:' + str(allKeys)
    text.draw()
    window.flip()

in your case this while loop would correspond to your movie loop (I think the original issue was not using the kb object to get times but using a timer) Hope that helps!
Becca