Keypress time is being evaluated wrongly

Hi!
I have a time-sensitive task in which participants will be presented with a stimulus and two response options on the screen, three tones will be played, and they need to respond with pressing either right or left arrow keys when the third tone is being played.

Three things might happen based on their response timing and accuracy:

  1. “too soon”: regardless of response accuracy, the participants press the key quicker than they should (i.e. keytonediff and the 0.1 second tolerance)

  2. “too late”: regardless of response accuracy, the participants press the key slower than they should (i.e. keytonediff and the 0.1 second tolerance)

  3. “on time” : the participants press the key the exact same time as than they should (i.e. keytonediff and the 0.1 second tolerance) so the code will check the response accuracy and enables the outcome loops (i.e. correctloop or incorrect loop) based on it.

Below is the python code that I use on Psychopy locally and it does what I want it to do:

if rightleft_choice_training.keys:
    keyToneDiff = 1.2-t
    keypressTime = tThisFlipGlobal
    keyPressed = rightleft_choice_training.keys
    
    rightleft_choice_training.keys = []
    
    rightleft_choice_training.status = FINISHED
    continueTxt.status = FINISHED
    continueKey.status = FINISHED
    
    if keyPressed == CorrResp:
        trialCorrect = 1
    else:
        trialCorrect = 0

    if keyToneDiff >= (0.1+frameTolerance):
        feedbackTxt = "Too soon!"
        timeFeedback.setAutoDraw(True)
        timeFeedback.status == STARTED
        timeFeedback.tStartRefresh = tThisFlipGlobal
    elif keyToneDiff <= (-0.1-frameTolerance):
        feedbackTxt = "Too late!"
        timeFeedback.color = 'red'
        timeFeedback.setAutoDraw(True)
        timeFeedback.status == STARTED
        timeFeedback.tStartRefresh = tThisFlipGlobal
    else:
        feedbackTxt = "On time!"
        timeFeedback.color = "green"
        timeFeedback.setAutoDraw(True)
        timeFeedback.status == STARTED
        timeFeedback.tStartRefresh = tThisFlipGlobal
        if trialCorrect == 1:
            correctReps = 1
            points = points + 95
        else:
            incorrectReps = 1
            points = points - 5

My JS code (with the explanation of the issue below):

if (rightleft_choice_training.keys) {
    keyToneDiff = (1.2 - t);
    keypressTime = globalClock.getTime();
    keyPressed = rightleft_choice_training.keys;
    rightleft_choice_training.keys = [];
    rightleft_choice_training.status = PsychoJS.Status.FINISHED;
    continueTxt.status = PsychoJS.Status.FINISHED;
    continueKey.status = PsychoJS.Status.FINISHED;
    if ((keyPressed === CorrResp)) {
        trialCorrect = 1;
    } else {
        trialCorrect = 0;
    }

    
    if (keyToneDiff >= 0.1) {
        feedbackTxt = "Too soon!";
        timeFeedback.color = "red";
        timeFeedback_Dev.setAutoDraw(true);
        timeFeedback_Dev.status === PsychoJS.Status.STARTED;
        timeFeedback_Dev.tStartRefresh = globalClock.getTime();
    } else if (keyToneDiff <= -0.1) {
        feedbackTxt = "Too late!";
        timeFeedback.color = "red";
        timeFeedback.setAutoDraw(true);
        timeFeedback.status === PsychoJS.Status.STARTED;
        timeFeedback.tStartRefresh = globalClock.getTime();
    } else {
        feedbackTxt = "On time!";
        timeFeedback.color = "green";
        timeFeedback.setAutoDraw(true);
        timeFeedback.status === PsychoJS.Status.STARTED;
        timeFeedback.tStartRefresh = globalClock.getTime();
        if (trialCorrect === 1) {
            correctReps = 1;
            points = points + 95;
        } else {
            incorrectReps = 1;
            points = points - 5;
        }
    }
}

Problem on Pavlovia:
I get overlapping and chaotic feedback texts on screen “on time” and “too late” at the same time regardless of my response accuracy and my key responses are not being evaluated correctly (also, despite responding correctly and seeing the message “on time!”, it doesn’t lead me to the correct_loop). I think something should be wrong with the timings, especially after I removed frameTolerance from my JS code since it was causing an error on Pavlovia (not on Psychopy).

I just set my project to public (internal) for you to kindly take a look ( (IMPORTANT: please check RL_Task_cost.psyexp not the old one)

https://gitlab.pavlovia.org/Parnianrafei/rl_task

URL of experiment:
https://run.pavlovia.org/Parnianrafei/rl_task/?__pilotToken=70efdf2ec9b086079795c442636b55fb&__oauthToken=12f71e2f405ccb6cf54b617a56a056743ef66f3b5207985d3c2ab29d4dd7c6fb

I would be more than grateful if someone with more experience can take a look and help me – THANKS!

I am still stuck here after thoroughly reviewing the discourse and playing around with numbers in the specific bit of my JS code:
:sleepy:

 if (keyToneDiff >= 0.1) {
        feedbackTxt = "Too soon!";
.
.
.
   } else if (keyToneDiff <= -0.1) {
        feedbackTxt = "Too late!";
.
.
.
} else {
        feedbackTxt = "On time!";
..

I will deeply appreciate any guidance from anyone who might know how to solve this, thanks! @Becca @wakecarter @TParsons :pray:

I would recommend that you add print/console.log statements to see which variable is different from what you are expecting.

Thanks a lot for your response!
I did so and noticed a confusing thing:


I ran the experiment locally on psychopy and on then on pavlvoia and noticed that the “frameTolerance” for the psychopy version THAT WORKS PERFECTLY is always 0.001 when printed; I tried adding frameTolerance = 0.001 manually to the JS code, but it didn’t work, then set that to frameTolerance = [] but it’s again not working and gives me overlapping keypress time evaluations. The keyToneDiff (keyToneDiff = (1.2 - t) key and beep tone difference) values are also strangely quite different in the online and offline version (values are always minus and big and usually between -1.49 to -1.51 for the faulty online version, which makes sense given the below screenshot):

This is the screenshot of my code snippet, every frame:

Do you know where the issue is stemming from? :frowning_face:

Line 1 is true from when a key has been pressed. If pressing a key ends the routine then most of the rest of the code could be in End Routine. If it doesn’t then keyToneDiff is going to change (and get smaller) every frame from that point on. You could add a flag to line 1 e.g. “and keyPressed == -1” so it doesn’t continue to be true.

Thank you very much!

If your problem is now solved, please could you mark the post that solved it as the solution?

Sure, many thanks!

I just created a blank (with one space) text component for feedback_text and edited my code in the every frame section as follows and it worked!

var frameTolerance;
frameTolerance = 0.001;

if (rightleft_choice_training.keys == "q" || rightleft_choice_training.keys == "p" ) {
    console.log("keypress");
    keyToneDiff = (1.2 - t);
    keypressTime = globalClock.getTime();
    console.log("kpt",keypressTime);
    console.log("t",t);
    console.log(rightleft_choice_training.keys);
    keyPressed = rightleft_choice_training.keys;
    rightleft_choice_training.keys = [];
    rightleft_choice_training.status = PsychoJS.Status.FINISHED;
    continueTxt.status = PsychoJS.Status.FINISHED;
    continueKey.status = PsychoJS.Status.FINISHED;
    
    if ((keyPressed === "q")) {
            left_rect_tr.opacity = 0;
            right_rect_tr.opacity = 0.5;
            }
        
    if ((keyPressed === "p")) {
            left_rect_tr.opacity = 0.5;
            right_rect_tr.opacity = 0;
        }

    
    if ((keyPressed === CorrResp)) {
        trialCorrect = 1;
    } else {
        trialCorrect = 0;
    }

    if (keyToneDiff >= 0.1+frameTolerance) {
        feedbackTxt = "Too soon!";
        timeFeedback.text = feedbackTxt;
        timeFeedback.color = "red";
        timeFeedback.setAutoDraw(true);
        timeFeedback.status === PsychoJS.Status.STARTED;
        timeFeedback.tStartRefresh = globalClock.getTime();
    } else if (keyToneDiff <= (-0.1-frameTolerance)) {
        feedbackTxt = "Too late!";
        timeFeedback.text = feedbackTxt;
        timeFeedback.color = "red";
        timeFeedback.setAutoDraw(true);
        timeFeedback.status === PsychoJS.Status.STARTED;
        timeFeedback.tStartRefresh = globalClock.getTime();
    } else {
        feedbackTxt = " ";
        timeFeedback.text = feedbackTxt;
        timeFeedback.color = "white";
        timeFeedback.setAutoDraw(true);
        timeFeedback.status === PsychoJS.Status.STARTED;
        timeFeedback.tStartRefresh = globalClock.getTime();
        
        if (trialCorrect === 1) {
            correctReps = 1;
            points = points + 95;
        } else {
            incorrectReps = 1;
            points = points - 5;
        }
    }
}

console.log(timeFeedback.text)
console.log(feedbackTxt)
1 Like