Allow two different double-key-presses as possible correct responses

Hello,

I am trying to create a task where participants execute either a forced-choice or a free-choice response. Responses are either the double-press of the f key or the double press of the k key.

In forced-choice conditions, if they see a H they are to press the f key twice as fast as possible, if they see an X they are to press the k key twice as fast as possible.
In free-choice conditions an O appears which requires either a speeded double press of the f key or the k key.

I am having trouble figuring out how to log a correct response in free-choice conditions where the response could be ‘ff’ or ‘kk’.

So far I created a variable ‘bcorr’ which I list as the Correct Answer in builder and I created the following if statements to identify correct response for free-choice and forced-choice conditions, but this is not working. Wondering if anyone has any solutions for recording correct responses for free-choice conditions.

My code:

In the “Begin Experiment” tab I declare the new variable Bcorr =

In the “Begin Routine” tab I have the following if statements

if forced_free == “free” and Bresp1.keys == correctAnsB21 or correctAnsB22:
bcorr = 1
elif forced_free == “forced” and Bresp1.keys == correctAnsB21:
bcorr = 1
else:
bcorr = 0

if bcorr == 1:
Bresp1.corr = 1
else:
Bresp1.corr = 0

Attached are screenshots of my design as well.
B Data Loggin
B1 properties


Hello

there are some posts in the forum about multiple correct answers. You might want to look there

https://discourse.psychopy.org/search?q=multiple%20correct%20answers

is incorrect. The syntax is as follows:

if forced_free == “free” and Bresp1.keys == correctAnsB21 or Bresp1.keys == correctAnsB22:

Best wishes Jens

1 Like

Danke fĂźr den Vorschlag Jens! Strangely the code works when it is written as follows and the correct answer is set to bcorr:

if forced_free == ‘forced’ and Bresp1 == correctAnsB21:
bcorr = 1
elif forced_free == ‘free’ and Bresp1 == correctAnsB21 or correctAnsB22:
bcorr = 1
else:
bcorr = 0

But the code does not work when wrote as you suggested.

I added another if statement that should record the response as correct (Bresp1.corr == 1) when bcorr == 1, but this second if statement is not working, so although the feedback reports the response as correct and shows the RT, the data file column for Bresp1.corr is all 0s.

Second if statement that does not work is:
if bcorr == 1:
Bresp1.corr = 1
else:
Bresp1.corr = 0

Any thoughts on why this second if statement is not coding Bresp1.corr as 1?

Vielen dank!
Bcorr

Hello,

ok, I still don’t think that the code

elif forced_free == 'free' and Bresp1 == correctAnsB21 or correctAns ...

works. This is syntactically wrong. You could add print-statements to the if-elif-condition to check whether the condition was met.

...
elif  forced_free == 'free' and Bresp1 = correctAnsB21 or correctAns ...
    bcorr = 1
    print("elif is true")

Anyway, with regard to the second question. Simply add

Bresp1.corr = 1

to the respective if/elif-statement.

if forced_free == 'forced' and Bresp1 == correctAnsB21:
    bcorr = 1
    Bresp.corr = 1
....

Best wishes Jens

1 Like

Thank you for the advice Jens.

I meant to mention before, I am running MacOS Catalina 10.15.7, and PsychoPy v2023.2.3.

I rewrote my code as you suggested and it does seem to be coding free-choice responses accurately for the most part. I also added a statement in the End Routine tab to record the coded variable bcorr into the data to show when the responses was coded as correct.

However I am still having some strange issues with responses being coded wrong. I have not been able to find a solution for the following issues:

1.) Every first response is coded incorrect.
2.) Some responses I know are correct are coded incorrect (see data sheet attached).
3.) In the data sheet, bcorr is coded correct sometimes when one responses is given (should be incorrect because two presses are required).
4.) The if statement is not updating the Bresp.corr variable.

Any tips on how to resolve these issues would be greatly appreciated.

Thanks very much!


Codepic
DataImage
Output if results

Hello

Do you mind posting code surrounded by triple ` instead of screenshots? How do you end a trial? Can’t key-press.

BTW, the error-checking routine has to follow the reaction. So it has to go in the End Routine tab, not the Bgin Routine tab.

Best wishes Jens

Hello @richar3636

Ok, place a code-element at the bottom of your respective routine. In the Begin Experiment tab of the code-element add a line to initialise your variable.

correct = 0

In the End Routine tab, add the following code

if Bresp1.keys:
    if len(Bresp1.keys) > 1:
        if cond == "forcedX":
            if Bresp1.keys == ['k','k']:
                correct = 1
            else:
                correct = 0
        elif cond == "forcedH":
            if Bresp1.keys == ['f','f']:
                correct = 1
            else: 
                correct = 0
        elif cond == "free":
            if Bresp1.keys == ['f','f'] or Bresp1.keys == ['k','k']:
                correct = 1
            else:
                correct = 0
else:
    correct = 0

thisExp.addData('correct',correct)

Notice, I differentiate between the condition forcedX, the condition forcedH and the condition free. I coded the conditions in an Excel-file in a column named cond. I did not code the correct answers in the condition-file as this would require two columns.

loopDoubleKey.xlsx (18.0 KB)

I have found this to be simpler and you may want to analyse the X, H and O conditions anyway.

Best wishes Jens

1 Like

Wow this code works great! Thanks so much Jens!

I added len(Bresp1.keys) to limit button presses to 2.

Regarding ending trials. Currently I have it set to a 1.5 second time limit but I would like to end the routine as soon as the second press of the response is made. I added continueRoutine = False to the if statements, but this does not seem to be effective. I have also read in other posts folks having issues with continueRoutine(). Is there a way to end a routine as soon as the second button press is made?

My code now adjusted to be consistent with your suggestions is as follows (located in the End Routine tab):

if Bresp1.keys:
    if len(Bresp1.keys) > 1:
        if forced_free == "forcedX":
            if Bresp1.keys == ['k','k'] and len(Bresp1.keys) < 3:
                Bcorrect2 = 1
                Bresp1.corr = 1
                continueRoutine = False
            else:
                Bcorrect2 = 0
                Bresp1.corr = 0
                continueRoutine = True
        elif forced_free == "forcedH":
            if Bresp1.keys == ['f','f'] and len(Bresp1.keys) < 3:
                Bcorrect2 = 1
                Bresp1.corr = 1
                continueRoutine = False
            else: 
                Bcorrect2 = 0
                Bresp1.corr = 0
                continueRoutine = True
        elif forced_free == "free":
            if len(Bresp1.keys) < 3 and Bresp1.keys == ['f','f'] or Bresp1.keys == ['k','k']:
                Bcorrect2 = 1
                Bresp1.corr = 1
                continueRoutine = False
            else:
                Bcorrect2 = 0
                Bresp1.corr = 0
                continueRoutine = True
else:
    Bcorrect2 = 0
    Bresp1.corr = 0
    continueRoutine = True

thisExp.addData('Bcorrect2',Bcorrect2) 

Thanks very much!

Hello

you could add the following code to the Each frame-tab.

if Bresp1.keys:
    if len(Bresp1.keys) == 2:
        continueRoutine = False

Note that with this approach, the routine will only end after two key presses, unless you add an additional constraint, such as a time limit. Without a time limit, the routine would not end with just one key press.

The condition len(Bresp1.keys) < 3 becomes obsolete with this approach.

You don’t need continueRoutine = True as this is always true unless you set it to False.

Best wishes Jens

2 Likes

Thanks for your help Jens. It seems that if I apply the continueRoutine == False code, it still takes a brief period to end the routine before allowing the next response (another key sequence the participant was remembering) and it seems to count a response correct if more than two presses were made.

If I comment out the continueRoutine == False code and retain the len(Bresp1.keys) < 3 code in the if statement in the End of Routine tab, this correctly marks responses greater than 2 keypresses incorrect, but participants have to wait for the routine to end (what’s left of the 1 second response time window).

Is there a way to ensure only responses of two key presses are counted correct (responses > 2 key presses should be incorrect) and the routine ends immediately after the second key press is made so the next response can be made? Ideally the double key press response and the next response should be made almost as if they are one large key sequence.

Greatly appreciate your help!

Hello

please open a new thread when you have a new question as this has been marked as solved. It appears to me that this a an additional requirement given that the experiment is running as expected, am I correct?

Best wishes Jens

1 Like

Hello,

Yes no problem. The experiment is running smoothly. I will make a new post for the continueRoutine issue if I am unable to resolve it myself. Thanks very much for the assistance!