Wrong assignation of key press in >1 possible correct choice in a 2AFC multi-staircase experiment

OS (e.g. Win10): Windows 10/11 (tried in both)
PsychoPy version (e.g. 1.84.x): from 2022.2.2. to 2023.2.0 (from GitHub release)
What are you trying to achieve?:
I am currently building an experiment where I present 3 different random dot kinetograms and the subject needs to evaluate changes between them in 3 of their dimensions (for example, the difference in orientation, color, coherence, etc. between the 1st and the 3rd kinetogram). The comparison is always between the 1st and the 3rd. I built up 3 simple staircases one for each dimension that I changed (such that the values of the 3rd one relate directly on the values from the 1st one).
In the context of a 2 alternative force choice task (2AFC), the subject needs to decide which dimension changed ** by pressing a keyboard among the letters a,s,d,f**. It’s a 2AFC because each option integrates how sure are you about your choice (e.g. a: first choice, not sure, s: first choice, very sure).

What did you try to make it work?:
I generate a function that based on the dimension that changed, it shows one of the possible pairs among the 3 dimensions, and assesses the correctness of the key pressed. Essentially, the correct key response (“Key result”) is assigned to any of the correct_keys that the subject presses if it is in that list. If it is not, then it picks the first item of the correct keys variable.

The chunk of code is relatively short and not hard so hopefully it is not so long for the standards mentioned in Jon’s blog post

# Display options including the correct choice 
# List of possible pairs.
orientation_pairs = ["orientation - dots", "color  - orientation"]
color_pairs = ["color - dots"," orientation - color"]
dots_pairs = ["dots - color"," orientation  -dots"]

## Define correct and confidence variables 
confidence = ''
low_confidence = ['a','d']
high_confidence = ['s','f']
feedback = ''

# Define a function to handle the logic for each category
def handle_category(selected_option, pairs, key_pressed):
    if selected_option == pairs[0]:
        correct_keys = ['a','s']
    elif selected_option == pairs[1]:
        correct_keys = ['d','f']

    is_correct = 1 if key_pressed in correct_keys else 0
    feedback = is_correct
    if key_pressed in correct_keys:
        key_result = key_pressed
        key_result = correct_keys[0]

    return correct_keys, is_correct, feedback, key_result

# Correct response based on category:
if category == 'orientation':
    selected_option = rd.choice(orientation_pairs)
    correct_response = 'orientation'
    correct_keys, key_2AFCresp.corr, feedback, key_result = handle_category(selected_option, orientation_pairs, key_2AFCresp.keys)

elif category == 'speed':
    selected_option = rd.choice(speed_pairs)
    correct_response = 'speed'
    correct_keys, key_2AFCresp.corr, feedback, key_result = handle_category(selected_option, speed_pairs, key_2AFCresp.keys)

elif category == 'density':
    selected_option = rd.choice(density_pairs)
    correct_response = 'density'
    correct_keys, key_2AFCresp.corr, feedback, key_result = handle_category(selected_option, density_pairs, key_2AFCresp.keys)

# Classification of confidence judgments:
confidence = ''
for key in [key_2AFCresp.keys]:
    if key in low_confidence:
        confidence = 'low confidence
    elif key in high_confidence:
        confidence = 'high confidence

What specifically went wrong when you tried that?:
The main issue is that with this approach, sometimes (about 1/7 of the total trials) when the subject presses the key “s” ** AND IT IS CORRECT **, the experiment stores a different key “f” in the variable keyboard.keys from the keyboard component. It does not happen systematically, and weirdly enough it happens in the CSV file BUT NOT in the log file where it stores correctly.

Lastly, the variable is not changed explicitly in the code until it is saved, so it should not overwrite, and simulating the experiment with computer responses does not generate the mismatch, nor only making the loops over the keyboard. component without the 3 staircases involved. Previously, I coded the if statement for each particular condition to see if it was the function and it was not. The staircase-dependent processes (e.g. level modifications) alone, work well as well. I have not seen a similar post either, so that could also potentially help.

Our current best guess is that it is storing randomly the correct key from the 2 possible correct choices and since it does not identify the match, it changes the key_press value to reject the correct choice and shows the negative feedback. However, given the nature of the experiment, we need that the task allows 2 possible correct choices and that it assigns the respective feedback accordingly.

It was really hard to spot the error but it has been even harder to try to solve it for us.
Any suggestion thought, or advice is highly appreciated :).
Thanks in advance !!

Update: After a couple of days of reading and looking into blogs, psychopy website I realized that the keyboard component only allowed a single correct key variable and that if I based the logic of the code component on the key pressed from the keyboard.keys attribute, given the order of the components the logic would not work properly.

Instead, the solution was to erase the keyboard component and just code the keyboard responses with multiple answers depending on the specific condition from scratch in the code component. It integrated succesfully in the experiment.

Hopefully this works for someone in the future,
Thank you!