Description of the problem: Hi, I am skipping a routine with continueRoutine = False. It works fine locally but does not skip the routine in online trials. I saw in previous posts it was suggested to put the condition in EachFrame since continueRoutine get true value in each frame. I did put it in the each frame part but nothing changed.
function sound_2RoutineEachFrame(trials) {
return function () {
//------Loop for each frame of Routine 'sound_2'-------
let continueRoutine = true; // until we're told otherwise
// get current time
t = sound_2Clock.getTime();
frameN = frameN + 1;// number of completed frames (so 0 is the first frame)
// update/draw components on each frame
if (((automatic === false) && (key_press.keys === null))) {
continueRoutine = false;
}
if (((key_press.keys === "space") && (outcome === 0))) {
continueRoutine = false;
}
Do you know any other possible reason for this problem?
I tried your experiment and didnât have the error you mentioned. Instead I was getting an unexptected identifier error in line 913. Apart from that, maybe it might worth using ââ==ââ instead of ââ===ââ in your if statements. You could have a look at their difference here: https://www.w3schools.com/js/js_comparisons.asp
Sorry, I do not get that identifier error I am a bit confused. But beside that not skipping the routine does not create any error in the code. But when I run the experiment, the routine that should be skipped is not skipped. I tried to change ââ==", it is again the same.
What I try to do is not generate the sound output if there is no key press. But regardless of whether the key is pressed or not the sound comes. So, actually condition in the each frame part is completely ignored and the sound routine continues in any cases.
Less that the condition is ignored and more that it isnât being met for some reason. I recommend you add some logging:
unction sound_2RoutineEachFrame(trials) {
return function () {
//------Loop for each frame of Routine 'sound_2'-------
let continueRoutine = true; // until we're told otherwise
// get current time
t = sound_2Clock.getTime();
frameN = frameN + 1;// number of completed frames (so 0 is the first frame)
// update/draw components on each frame
console.log(automatic);
console.log(key_press.keys);
console.log(outcome);
if (((automatic === false) && (key_press.keys === null))) {
console.log("No keys pressed");
continueRoutine = false;
}
if (((key_press.keys === "space") && (outcome === 0))) {
console.log("Space pressed and outcome is 0");
continueRoutine = false;
}
This will tell you if the things that go into your conditional statements have the values you expect, and if not you can either change the conditionals or start tracing those back to figure out why. These messages will appear in your browserâs JS console (in Chrome, you can find this in view->developer)
Hi, I tried your suggestion and realized that it actually enters the conditional and changes continueRoutine to false but it checks for continueRoutine at the end of the routine which means that sound has already come. Like this:
âââ
function sound_2RoutineEachFrame(trials) {
return function () {
//------Loop for each frame of Routine âsound_2â-------
let continueRoutine = true; // until weâre told otherwise
// get current time
t = sound_2Clock.getTime();
frameN = frameN + 1;// number of completed frames (so 0 is the first frame)
// update/draw components on each frame
if (((automatic === false) && (key_press.keys === undefined))) {
continueRoutine = false;
}
if (((key_press.keys === âspaceâ) && (outcome === 0))) {
continueRoutine = false;
}
// start/stop sound_1
if (t >= 0.0 && sound_1.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
sound_1.tStart = t; // (not accounting for frame time here)
sound_1.frameNStart = frameN; // exact frame index
psychoJS.window.callOnFlip(function(){ sound_1.play(); }); // screen flip
sound_1.status = PsychoJS.Status.STARTED;
}
frameRemains = 0.0 + 0.1 - psychoJS.window.monitorFramePeriod * 0.75; // most of one frame period left
if (sound_1.status === PsychoJS.Status.STARTED && t >= frameRemains) {
if (0.1 > 0.5) { sound_1.stop(); // stop the sound (if longer than duration)
sound_1.status = PsychoJS.Status.FINISHED;
}
}
// check for quit (typically the Esc key)
if (psychoJS.experiment.experimentEnded || psychoJS.eventManager.getKeys({keyList:['escape']}).length > 0) {
return quitPsychoJS('The [Escape] key was pressed. Goodbye!', false);
}
// check if the Routine should terminate
if (!continueRoutine) { // a component has requested a forced-end of Routine
return Scheduler.Event.NEXT;
}
continueRoutine = false; // reverts to True if at least one component still running
for (const thisComponent of sound_2Components)
if ('status' in thisComponent && thisComponent.status !== PsychoJS.Status.FINISHED) {
continueRoutine = true;
break;
}
âââ
So, I actually solved my problem by putting check if (!continueRoutine) part right after my conditional but I wonder why it would happen. Do you have any idea? Since this was the automatic translation of builder maybe there is a logic behind its being put like this that I do not see.
Itâs a quirk of tripping this on the very first frame before anything has happened. PsychoPy doesnât really assume you would create a trial that displays stimuli immediately but then cancel it on the first frame (which is basically what youâre doing here), so the way the builder code works is âplug code component in at start of frame, then check if itâs time to play these stimuli and change their status if needed, then check if itâs time to endâ, which makes sense most of the time but not here.
The other solution that would likely have worked is if you set the start time of the sound stimulus to 100ms (or even 50ms) after the start of trial, because then it wouldnât try to start the sound on the same frame that it realizes it should cancel the trial. That might be better long-term because if you recompile your code from the builder, the change youâre describing might get over-written by the auto-generated code.
I am having the same problem (using Psychopy 2020.2.4 on Macbook Pro Mojave) in my Pavlovia Experiment. I have a code component with continueRoutine = True or False depending on the rep of the outer loop (LRblock). This works perfectly well in Psychopy Builder but it does not work on Pavlovia. In the builder version, I had the code component in the Begin Routine tab but I have moved it to the Each Frame tab as that seems to work better when working with Pavlovia.
This is what I am putting in my simple code component (see the pic of it below too):
So basically, the LRpause routine should only continue if the LRblock is on the first (==0) or second (==1) loop. It should NOT continue if it is on the third (==2) loop. As of now, it is continuing even when LRblock.thisN == 2 in the pavlovia verison.
I have tried replace .thisN with .thisTrialN too and that did not work.
I also made sure that the text that is part of the LRpause routine does not start until after 1sec as suggested above but this did not work either.
I hope someone can help! My experiment is in pilot private mode right now but I am happy to move it to public mode if that would help!
Unfortunately, .thisN doesnât work in versions 2020.2 to 2020.24. Iâve been switching my code to using an index variable Idx which I increment at the end of each loop.
OK yes so by printing thisN (using the method I mentioned trying) you would have then seen in the console that thisN wasnât increasing as you would expect (which would show you it is the issue wakefield mentions) - So essentially, you can skip my step and, as wakefield says, you make yourself a numeric variable that increases by 1 on each trial (your making yourself a version of thisN to use )
Thanks so much for your help. I tried doing what wakecarter said but it still did not work. The LRpause routine is still continuing after the third iteration of LRblock⌠I may have misunderstood (high probability ). This is what I have: