OS: MacOS Ventura 13.4.1 (22F82)
PsychoPy version: v2023.2.2
Standard Standalone: yes
What are you trying to achieve?: To skip a given routine only if a condition has been met.
What did you try to make it work?:
I defined the following variables earlier in the task:
condition_1_met = false;
condition_2_met = false;
condition_3_met = false;
thresh_1 = 15;
thresh_2 = 30;
thresh_3 = 50;
trials_done_1 = (total_trial_count >= thresh_1);
trials_done_2 = (total_trial_count >= thresh_2);
trials_done_3 = (total_trial_count >= thresh_3);
// As well as
total_trial_count = 0;
And In the end routine code component in the chooseItem routine (purple, left of screenshot below), total_trial_count is updated like this:
total_trial_count = (total_trial_count + 1);
In red (right) is the ārecalibration_taskā routine I want to skip if the conditions arenāt met:
In this recalibration_task there I have the following begin routine code component:
// Check the conditions
if (trials_done_1 && !condition_1_met) {
// Code for when total_trial_number is greater than or equal to thresh_1
continueRoutine = true;
recalibration_loop_2.finished = false;
// Update the variable to indicate the condition has been met
condition_1_met = true;
}
if (trials_done_2 && !condition_2_met) {
// Code for when total_trial_number is greater than or equal to thresh_2
continueRoutine = true;
recalibration_loop_2.finished = false;
// Update the variable to indicate the condition has been met
condition_2_met = true;
}
if (trials_done_3 && !condition_3_met) {
// Code for when total_trial_number is greater than or equal to thresh_3
continueRoutine = true;
recalibration_loop_2.finished = false;
// Update the variable to indicate the condition has been met
condition_3_met = true;
}
What specifically went wrong when you tried that?:
With this current version of the code, the routine is not skipped and is run every time I finish a block.
(Editing the task layout and dividing it in 3, interleaved with calibration routines, would be way too much work, hopefully there is a way to do it using a few if statements?)
Thanks a lot!
Hi @Tristan_White,
Firstly, this might sound like an obvious question but this is only to be ran online I assume since youāre using JS rather than Python? Also, do you want to skip the whole recalibration_loop_2 or just one instance of the recalibration_task routine?
Either way, a couple of things might help:
continueRoutine
is set to true by default, therefore to use conditional statements youāll need to use continueRoutine = false
to skip the routine.
- The same logic applies to
loop.finished
. If the loop is there, Builder assumes it should be run. Therefore you can only change the default behaviour by either using loop.finished = true or setting the number of loop reps to 0.
Thanks,
Kim
Hi Kimberly, thanks for the reply.
- This is only to be run online, yes.
- And I want to skip the whole ārecalibration_loop_2ā loop if the conditions are not met.
Thanks for reminding me that I hadnāt delt with the default condition, so now Iāve got this loop, with the final āelseā statement that is meant to take care of the situations where the none of the 3 condition sets are met:
// Check the conditions and set continueRoutine and recalibration_loop_2.finished based on conditions
if (trials_done_1 && !condition_1_met) {
// Code for when total_trial_number is greater than or equal to threshold 1
condition_1_met = true;
continueRoutine = true;
recalibration_loop_2.finished = false;
} else if (trials_done_2 && !condition_2_met) {
// Code for when total_trial_number is greater than or equal to threshold 2
condition_2_met = true;
continueRoutine = true;
recalibration_loop_2.finished = false;
} else if (trials_done_3 && !condition_3_met) {
// Code for when total_trial_number is greater than or equal to threshold 3
condition_3_met = true;
continueRoutine = true;
recalibration_loop_2.finished = false;
} else {
continueRoutine = false;
recalibration_loop_2.finished = true;
}
Sadly itās still not working, the calibration is skipped every time, even when 1 of the 3 condition sets is met.
Itās possible that my code is flawed, Iām quite new at coding in JS.
What do you think ?
Thanks again
Tristan
I strongly recommend coding in Python auto components and only making changes to the JS when absolutely necessary.
To debug you need to add some print / console.log statements to check the values of trials_done_x and condition_x_met before the checks.
https://psychopy.org/online/psychoJSCodingDebugging.html
1 Like
I completely agree with @wakecarter here @Tristan_White, especially if (like me!) youāre not too familiar with JS.
If you werenāt already aware, setting the code type of a code component to Auto>JS allows you to type Python code on the left hand side and have it automatically transpiled to JS. This means you can check your logic works locally, using the print statements that Wakeās mentioned before testing online, which is generally a much quicker way of debugging.
My guess here, if the routine is now being skipped every time, is that all 3 of your if statements are returning false. Leaving your else statement to be the only thing thatās executed.
Hi both,
Thanks a lot for the replies.
Following your advice Iāve written the code component in python (Auto>JS), and with some more tweaks Iāve got the calibration routine to be run only 3 times, each after reaching their respective threshold conditions.
Thereās still one thing, it doesnāt loop, the routine is only ran once (instead of 8 in this case).
Hereās the code (the commented out recalibration_loop_2.finished = False/True code doesnāt seem to change anything):
# Check the conditions
if total_trial_count >= thresh_1 and not routine_run_1:
# Code for when total_trial_number is greater than or equal to 15
routine_run_1 = True
continueRoutine = True
# recalibration_loop_2.finished = False
elif total_trial_count >= thresh_2 and not routine_run_2:
# Code for when total_trial_number is greater than or equal to 30
routine_run_2 = True
continueRoutine = True
# recalibration_loop_2.finished = False
elif total_trial_count >= thresh_3 and not routine_run_3:
# Code for when total_trial_number is greater than or equal to 50
routine_run_3 = True
continueRoutine = True
# recalibration_loop_2.finished = False
else:
# Code for when none of the conditions are met
continueRoutine = False
# recalibration_loop_2.finished = True
I think thereās some specific psychopy knowledge that I donāt have that could help which is why Iām coming back to you guys, I donāt fully understand how the loop system works.
Iāll post the working code once it works!
Thanks again,
Tristan
Great to hear youāre making progress!
Could you show us how your loop is set up?
Thanks,
Kim
Sure, here are a couple screenshots, and the ācalibration_code_2ā component, do you need something else?
The xlsx file:

And the ācalibration_code_2ā component:
// Turn off mouse event listener
//window.webgazer.removeMouseEventListeners();
// Re-enable mouse events
window.webgazer.addMouseEventListeners();
// Hide video feed and container behind it, they prevent clicking on calibration dots behind them
//document.getElementById('webgazerFaceFeedbackBox').style.display = 'none';
//document.getElementById('webgazerVideoFeed').style.display = 'none';
//document.getElementById('webgazerVideoContainer').style.display = 'none';
// Save experiment window size
psychoJS.experiment.addData('window_width', psychoJS.window.size[0]);
psychoJS.experiment.addData('window_height', psychoJS.window.size[1]);
// Position calibration_square using width and height of window
//var canvas = psychoJS.window.size;
var scaling = [
canvas[0] <= canvas[1]? 1: canvas[0] / canvas[1],
canvas[1] <= canvas[0]? 1: canvas[1] / canvas[0]
];
var newPos = [
calibration_x * scaling[0],
calibration_y * scaling[1]
];
console.log(newPos); //calibration_square coordinates displayed in console and on screen might be slightly different (0.01 error margin by the looks of it)
recalibration_stim_2.setPos(newPos);
Thanks,
Tristan
Hi @Kimberley_Dundas, since I havenāt found a fix to this yet I was wondering if you had some input, let me know if you need something else.
Thanks again,
Tristan W
Hi @Tristan_White,
The conditional statements you have look like theyāre set up so that the routine will run as long as at least one of those 3 conditions are not met. As youāre not resetting anything, after routine_run_1/2/3 have happened, all of those if statements you have will not be met and the else statement will always be the thing thatās run. Therefore the routine will not be ran again. Depending on what you want to happen, youāll need to set routine_run_1/2/3 to be back to false at some point. You can check these things yourself as Wake suggested earlier by using print statements to check your logic.
Thanks,
Kim
For the record and to close the thread, I figured it out in the end, here is the code:
# Check the conditions
if total_trial_count + 1 >= maxTrials:
recalibration_loop_2.finished=True
accuracy_loop_3.finished=True
continueRoutine = False
elif total_trial_count >= thresh_1 and not routine_run_1:
# Code for when total_trial_number is greater than or equal to thresh 1
routine_run_1_counter += 1
if routine_run_1_counter >= n_reps_cal:
routine_run_1 = True
continueRoutine = True
# Check if WG needs to be reset (on every rep before routine_run_1_counter reaches n_reps_cal)
if not WG_reset1:
# Clear WG data
window.webgazer.clearData()
# Re-enable mouse events
window.webgazer.addMouseEventListeners()
# Set WG_reset to True
WG_reset1 = True
elif total_trial_count >= thresh_2 and not routine_run_2:
# Code for when total_trial_number is greater than or equal to thresh 2
routine_run_2_counter += 1
if routine_run_2_counter >= n_reps_cal:
routine_run_2 = True
continueRoutine = True
# Check if WG needs to be reset (only on first rep)
if not WG_reset2:
# Clear WG data
window.webgazer.clearData()
# Re-enable mouse events
window.webgazer.addMouseEventListeners()
# Set WG_reset to True
WG_reset2 = True
elif total_trial_count >= thresh_3 and not routine_run_3:
# Code for when total_trial_number is greater than or equal to thresh 3
routine_run_3_counter += 1
if routine_run_3_counter >= n_reps_cal:
routine_run_3 = True
continueRoutine = True
# Check if WG needs to be reset (only on first rep)
if not WG_reset3:
# Clear WG data
window.webgazer.clearData()
# Re-enable mouse events
window.webgazer.addMouseEventListeners()
# Set WG_reset to True
WG_reset3 = True
else:
# Code for when none of the conditions are met
continueRoutine = False
recalibration_loop_2.finished = True
Thanks for the help!
Tristan