psychopy.org | Reference | Downloads | Github

Collecting reaction times with Keyboard Class

I want to programm a dual task and collect the reaction times. My problem is that the function is only returning 666 as buttonR1Code and buttonR2Code although I hit ‘x’ or ‘y’ and ‘,’ or ‘.’. 666 should only be given if no response was collected. How can I fix this? Any suggestions?
I’m using PsychoPy3, Coder, OS Win 10 (64-Bit).

def StimPresent(a_soa, b_s1, c_s2):
    """
    Function StimPresent(a, b, c) presents stimulus_1 (b) for SOA ((a) number of frames),
    then it adds stimulus_2 (d) and shows both for max 60 frames
    and returns time of stimulus onset (tim)
    """
    kbR1 = keyboard.Keyboard()
    kbR2 = keyboard.Keyboard()
    allkeys = 0

    while allkeys < 2:
        if event.getKeys(keyList='escape'):
            myWin.close()
            core.quit()

        for frameN in range(a_soa):
            b_s1.draw() 
            fixation.draw()

            if frameN == 0:                     # RT S1 starting immediately after flip
                onsetS1 = RT1.getTime()
                kbR1.clock.reset()

            keyR1 = kbR1.getKeys(['y', 'x'], waitRelease=True)

            if keyR1 == 'y':
                buttonR1 = 55
                allkeys += 1
                buttonR1Iden = keyR1.name
                buttonR1Dur = keyR1.duration
                theRT1 = keyR1.rt  
            elif keyR1 == 'x':
                buttonR1 = 44
                allkeys += 1
                buttonR1Iden = keyR1.name
                buttonR1Dur = keyR1.duration
                theRT1 = keyR1.rt  
            myWin.flip()

        for frameN in range(a_soa, (a_soa+60)):
            b_s1.draw()
            fixation.draw()
            c_s2.draw()
            if frameN == (a_soa+1):
                onsetS2 = RT2.getTime()         #RT S2 starting immediately after soa flip
                kbR2.clock.reset()

            keyR1 = kbR1.getKeys(['y', 'x'], waitRelease=True)
            keyR2 = kbR2.getKeys(['.', ','], waitRelease=True)

            if allkeys == 0:
                if keyR1 == 'y':
                    buttonR1 = 55
                    allkeys += 1
                    buttonR1Iden = keyR1.name
                    buttonR1Dur = keyR1.duration
                    theRT1 = keyR1.rt  
                elif keyR1 == 'x':
                    buttonR1 = 44
                    allkeys += 1
                    buttonR1Iden = keyR1.name
                    buttonR1Dur = keyR1.duration
                    theRT1 = keyR1.rt 
            if allkeys == 1:    
                if kbR2 == '.':
                    buttonR2 = 55
                    allkeys += 1
                    buttonR2Iden = kbR2.name
                    buttonR2Dur = kbR2.duration
                    theRT2 = kbR2.rt  
                elif kbR2 == ',':
                    buttonR2 = 44
                    allkeys += 1
                    buttonR2Iden = kbR2.name
                    buttonR2Dur = kbR2.duration
                    theRT2 = kbR2.rt

            myWin.flip()

        for frameN in range((a_soa+60), 300):
            fixation.draw()

            deadlineS1 = 210
            deadlineS2 = 210

            keyR1 = kbR1.getKeys(['y', 'x'], waitRelease=True)
            keyR2 = kbR2.getKeys(['.', ','], waitRelease=True)

            if allkeys == 0: 
                if keyR1 == 'y':
                    buttonR1 = 55
                    allkeys += 1
                    buttonR1Iden = keyR1.name
                    buttonR1Dur = keyR1.duration
                    theRT1 = keyR1.rt  
                elif keyR1 == 'x':
                    buttonR1 = 44
                    allkeys += 1
                    buttonR1Iden = keyR1.name
                    buttonR1Dur = keyR1.duration
                    theRT1 = keyR1.rt 
                elif frameN > deadlineS1:
                    buttonR1 = 666
                    allkeys += 1
                    buttonR1Iden = 'NaN'
                    buttonR1Dur = 'NaN'
                    theRT1 = 'NaN'
            if allkeys == 1:     
                if kbR2 == '.'
                    buttonR2 = 55
                    allkeys += 1
                    buttonR2Iden = kbR2.name
                    buttonR2Dur = kbR2.duration
                    theRT2 = kbR2.rt  
                elif kbR2 == ',':
                    buttonR2 = 44
                    allkeys += 1
                    buttonR2Iden = kbR2.name
                    buttonR2Dur = kbR2.duration
                    theRT2 = kbR2.rt
                elif frameN > deadlineS2:
                    buttonR2 = 666
                    allkeys += 1
                    buttonR2Iden = 'NaN'
                    buttonR2Dur = 'NaN'
                    theRT2 = 'NaN'

            myWin.flip()

    return [b_s1, onsetS1, buttonR1, buttonR1Iden, buttonR1Dur, theRT1, c_s2, onsetS2, buttonR1, buttonR1Iden, buttonR1Dur, theRT2, a_soa]

Thank you!

Hi @Inga, the first issue to address is how you are testing your key presses for equality. The getKeys function now returns a keypress object, and you have to use attributes of those objects to know what key was pressed, and when (see keyboard docs). It looks like you have this already, based on how you are storing the key press name and rt, but it also needs to apply to your conditional statements.

Try the following:

if allkeys == 0: 
    if keyR1.name == 'y':
    # etc

Hi @dvbridges,
I tried your suggestion but I’m running into an error. This is its message:

AttributeError: 'list' object has no attribute 'name'

Ah ok, yes it returns a list of objects. So, try

if keyR1[0].name == 'y':

Unfortunately, another error message…

IndexError: list index out of range

That error has occurred because you are attempting to index an empty list, meaning that a key press has not occurred at the point the test of equality occurs. To fix, you will have to check whether a key has been pressed before you make the test for equality in the if statement, so try:

if len(keyR1) and keyR1[0].name == 'y':

1 Like

This is working! Thank you so much!!
BUT: I adapted it to the kbRt2 and now I’m only getting 666 as code for the second response. Do you have any clue why this is happening?

Would you mind sharing your new code with the changes?

def StimPresent(a_soa, b_s1, c_s2):
    """
    Function StimPresent(a, b, c) presents stimulus_1 (b) for SOA ((a) number of frames),
    then it adds stimulus_2 (d) and shows both for max 60 frames
    and returns time of stimulus onset (tim)
    """
    kbR1 = keyboard.Keyboard()
    kbR2 = keyboard.Keyboard()
    allkeys = 0

    while allkeys < 2:
        if event.getKeys(keyList='escape'):
            myWin.close()
            core.quit()
        
        for frameN in range(a_soa):
            b_s1.draw() 
            fixation.draw()
    
            if frameN == 0:                     # RT S1 starting immediately after flip
                onsetS1 = RT1.getTime()
                kbR1.clock.reset()
                
            keyR1 = kbR1.getKeys(['y', 'x'], waitRelease=True)
            
            if len(keyR1) and keyR1[0].name == 'y':
                buttonR1 = 55
                allkeys += 1
                buttonR1Iden = keyR1[0].name
                buttonR1Dur = keyR1[0].duration
                theRT1 = keyR1[0].rt  
            elif len(keyR1) and keyR1[0].name == 'x':
                buttonR1 = 44
                allkeys += 1
                buttonR1Iden = keyR1[0].name
                buttonR1Dur = keyR1[0].duration
                theRT1 = keyR1[0].rt  
            myWin.flip()
        
        for frameN in range(a_soa, (a_soa+60)):
            b_s1.draw()
            fixation.draw()
            c_s2.draw()
            if frameN == (a_soa+1):
                onsetS2 = RT2.getTime()         #RT S2 starting immediately after soa flip
                kbR2.clock.reset()
            
            keyR1 = kbR1.getKeys(['y', 'x'], waitRelease=True)
            keyR2 = kbR2.getKeys(['.', ','], waitRelease=True)
                        
            if allkeys == 0:
                if len(keyR1) and keyR1[0].name == 'y':
                    buttonR1 = 55
                    allkeys += 1
                    buttonR1Iden = keyR1[0].name
                    buttonR1Dur = keyR1[0].duration
                    theRT1 = keyR1[0].rt  
                elif len(keyR1) and keyR1[0].name == 'x':
                    buttonR1 = 44
                    allkeys += 1
                    buttonR1Iden = keyR1[0].name
                    buttonR1Dur = keyR1[0].duration
                    theRT1 = keyR1[0].rt 
            if allkeys == 1:    
                if len(keyR2) and keyR2[0].name == '.':
                    buttonR2 = 55
                    allkeys += 1
                    buttonR2Iden = kbR2[0].name
                    buttonR2Dur = kbR2[0].duration
                    theRT2 = kbR2[0].rt  
                elif len(keyR2) and keyR2[0].name == ',':
                    buttonR2 = 44
                    allkeys += 1
                    buttonR2Iden = kbR2[0].name
                    buttonR2Dur = kbR2[0].duration
                    theRT2 = kbR2[0].rt
                
            myWin.flip()
        
        for frameN in range((a_soa+60), 300):
            fixation.draw()
            
            deadlineS1 = 210
            deadlineS2 = 210
            
            keyR1 = kbR1.getKeys(['y', 'x'], waitRelease=True)
            keyR2 = kbR2.getKeys(['.', ','], waitRelease=True)
            
            if allkeys == 0: 
                if len(keyR1) and keyR1[0].name == 'y':
                    buttonR1 = 55
                    allkeys += 1
                    buttonR1Iden = keyR1[0].name
                    buttonR1Dur = keyR1[0].duration
                    theRT1 = keyR1[0].rt  
                elif len(keyR1) and keyR1[0].name == 'x':
                    buttonR1 = 44
                    allkeys += 1
                    buttonR1Iden = keyR1[0].name
                    buttonR1Dur = keyR1[0].duration
                    theRT1 = keyR1[0].rt 
                elif frameN > deadlineS1:
                    buttonR1 = 666
                    allkeys += 1
                    buttonR1Iden = 'NaN'
                    buttonR1Dur = 'NaN'
                    theRT1 = 'NaN'
            if allkeys == 1:     
                if len(keyR2) and keyR2[0].name == '.':
                    buttonR2 = 55
                    allkeys += 1
                    buttonR2Iden = kbR2[0].name
                    buttonR2Dur = kbR2[0].duration
                    theRT2 = kbR2[0].rt  
                elif len(keyR2) and keyR2[0].name == ',':
                    buttonR2 = 44
                    allkeys += 1
                    buttonR2Iden = kbR2[0].name
                    buttonR2Dur = kbR2[0].duration
                    theRT2 = kbR2[0].rt
                elif frameN > deadlineS2:
                    buttonR2 = 666
                    allkeys += 1
                    buttonR2Iden = 'NaN'
                    buttonR2Dur = 'NaN'
                    theRT2 = 'NaN'
                
            myWin.flip()
        
    return [b_s1, onsetS1, buttonR1, buttonR1Iden, buttonR1Dur, theRT1, c_s2, onsetS2, buttonR2, buttonR2Iden, buttonR2Dur, theRT2, a_soa]

No worries! I found the mistake myself. It a logical one: My deadlines are both equally long, starting from frame 0. I need to adapt this for the second deadline, so that it is actually counting the frames onwards from S2 onset.
I’ll try this first.

1 Like

Okay, I changed my deadlineS2 into 210+a_soa but 666 is still given to buttonR2.
The code line looks like this:

for frameN in range((a_soa+60), 300):
            fixation.draw()
            
            deadlineS1 = 210
            deadlineS2 = (210+a_soa)
            
            keyR1 = kbR1.getKeys(['y', 'x'], waitRelease=True)
            keyR2 = kbR2.getKeys(['.', ','], waitRelease=True)
            
            if allkeys == 0: 
                if len(keyR1) and keyR1[0].name == 'y':
                    buttonR1 = 55
                    allkeys += 1
                    buttonR1Iden = keyR1[0].name
                    buttonR1Dur = keyR1[0].duration
                    theRT1 = keyR1[0].rt  
                elif len(keyR1) and keyR1[0].name == 'x':
                    buttonR1 = 44
                    allkeys += 1
                    buttonR1Iden = keyR1[0].name
                    buttonR1Dur = keyR1[0].duration
                    theRT1 = keyR1[0].rt 
                elif frameN > deadlineS1:
                    buttonR1 = 666
                    allkeys += 1
                    buttonR1Iden = 'NaN'
                    buttonR1Dur = 'NaN'
                    theRT1 = 'NaN'
            if allkeys == 1:     
                if len(keyR2) and keyR2[0].name == '.':
                    buttonR2 = 55
                    allkeys += 1
                    buttonR2Iden = kbR2[0].name
                    buttonR2Dur = kbR2[0].duration
                    theRT2 = kbR2[0].rt  
                elif len(keyR2) and keyR2[0].name == ',':
                    buttonR2 = 44
                    allkeys += 1
                    buttonR2Iden = kbR2[0].name
                    buttonR2Dur = kbR2[0].duration
                    theRT2 = kbR2[0].rt
                elif len(keyR2) and frameN > deadlineS2:
                    buttonR2 = 666
                    allkeys += 1
                    buttonR2Iden = 'NaN'
                    buttonR2Dur = 'NaN'
                    theRT2 = 'NaN'
                
            myWin.flip()

Try using 'period' and 'comma' instead of the actual character for those things.

1 Like

Yes, this works! Thanks a thousand times!