JavaScript - continueRoutine = false -- problem online

URL of experiment: https://run.pavlovia.org/MJB/immanentjustice/html/

Description of the problem:

The experiment flow contains catch trials which only run on set trial numbers.
There is a piece of code that runs at the start of the routine, which determines whether a catch trial is to be run. If not, the command is continueRoutine = false.
There is a separate code component set to run on each frame of the catch trial routine which handles what is shown on the trial.
This works well locally, but online it appear that the continueRoutine command is ignored and a catch trial is set to occur after EACH trial. This throws an error message because the components to be displayed on a catch trial are then not defined (they are defined in the piece of code at the beginning of the routine, but only when the right trial number is true).

My sense is that continueRoutine = false does not work on JS.
But it could also be that the timing with ‘begin Routine’ and ‘Each Frame’ works differently in JS than locally.

Can you please advise?

THanks!

Marc

Hi @Marc_Buehner, yes there are differences in how continueRoutine works in PsychoPy and PsychoJS. The main difference here being that, in PsychoJS, continueRoutine is assigned a true value on every frame. So, if you set the continueRoutine value to false in the Begin Routine tab, this will be overwritten in the Each Frame section of the code. The fix is to set the continueRoutine value conditionally in your Each Frame tab of the code component.

1 Like

Hello David – thank you for this.
I tried that, but now the catch trial is cancelled ALL the time, i.e. the code

if (nTrials in [1,2,4,5,6,7,9,10,11,13,14,15,16]) {
continueRoutine = false;
}

does not seem to work, and the routine is cancelled always, not just on the trials in the list.

url:
https://run.pavlovia.org/MJB/immanentjustice/html/

Many thanks
Marc

HI @dvbridges. Sorry to bother you – did you have any more thoughts on what could be going on with continueRoutine in the above case?
I also noticed that not only is the routine cancelled all the time, but that the experiment does not run the required N of trials – it displays an NaN when it should display text from a list.
This did not happen when the continueROutine = false code was in the BeginRoutine tab.
THanks
Marc

1 Like

Hi @Marc_Buehner, I was wondering if you had managed to find a workaround for this? I am having a similar problem in that when placed in beginRoutine, my conditional “= false” isn’t working.

Cheers,
Anthony

HI Anthony,

No I haven’t and David has gone quiet :frowning:

Marc

Very frustrating…

Hi @Marc_Buehner, you are getting NaN values because your string formatting in your code components is not compatible with JavaScript. A nice way of formatting JS is to use template literals. An example:

// Use backticks instead of quotation marks
`Which of the following events ${catchCorr} ...etc`

// Alternative string formatting
"Which of the following events " + catchCorr + " ...etc"

If you can fix the string formatting, then we can see if the task is running as required.

@Anthony, would you mind creating a new issue with a description of your problem so we can help?

Hi @dvbidges,

I have created a new issues.

Cheers,
Anthony

Hi @dvbridges.
Thanks for this. I changed the string formatting, but this has had no effect on continueRoutine = false. It now cancels all the trials and ignores the conditional.
Actually, it does not ignore it because after a long series of trials, the catch trial comes up, though the formatting of text is now all over the place and I am not sure why.

porting from PsychoPy to JS is certainly a hell of a lot harder than I thought – esp. if you don’t know JavaScript!

THanks

Thanks @Marc_Buehner, looks like there are still some changes needed:

  c1.setText(('%s %s' % [thisPerp, catchStims.pop()]));
  c2.setPos(catchTrialPos[1][0]);
  c2.setText(('%s %s' % [thisPerp, catchStims.pop()]));
  c3.setPos(catchTrialPos[2][0]);
  c3.setText(('%s %s' % [thisPerp, catchStims.pop()]));
  c4.setPos(catchTrialPos[3][0]);
  c4.setText(('%s %s' % [thisVict, catchStims.pop()]));
  c5.setPos(catchTrialPos[4][0]);
  c5.setText(('%s %s' % [thisVict, catchStims.pop()]));
1 Like

HI @dvbridges – my bad sorry about that.
I fixed that (I think) but the behaviour is still the same…

Some of your issues are with sizing and positioning. The text in the catch routine is off screen, so its needs centering. The sliders and their related text are not showing as the positions are being set with only a single value from your lists of positions etc. This is because of the way JavaScript handles round brackets - it does not treat them as a tuple like Python, it treats them as an expression where (0, 1) is evaluated to 1. This means some of your positions being indexed from lists e.g., :

catchTrialPos = 
  [[(-.85,.6),(.78,.6)],

…will not work, because only a single value is being passed as a position. To fix, change catchTrialPos (and any other instances of round brackets for list use) to square brackets:

catchTrialPos = 
  [[[-.85,.6],[.78,.6]], //...etc

@dvbridges Thanks as always.
I fixed the positioning with the round brackets as you suggested.
I am not sure what you mean with centering and sizing issues – the values are in units (between -1 and 1) but somehow that does not translate into JS.

The continue Routine = false bit still does not work btw.

Thanks
Marc

Well, I just meant that the text should be repositioned and resized to fit on screen.

I am not sure what is supposed to happen. The following code ends the routine for the first 16 trials where nTrials == 1 to 16. What should be happening here? It appears to end the catch trial, is that not happening?

if (nTrials in [1,2,4,5,6,7,9,10,11,13,14,15,16]) {
continueRoutine = false;
}

Ah, I think you want catch trials for trials 3,8 and 12?

Ah, I think you want catch trials for trials 3,8 and 12?


YES!

Well, I just meant that the text should be repositioned and resized to fit on screen.

Ah — Yes, I seem to have trouble with size and positioning in JS. What works in PsychoPy does not seem to work on JS.

Is there some resource I can use to figure out how to deal with sizing?

Thanks

Marc

Yes, I think this is another problem with how JavaScript in method works. I think it only checks whether the list index exists, not the actual value. Alternatives for using in for JavaScript are:

if ([1,2,4,5,6,7,9,10,11,13,14,15,16].includes(nTrials)) {
continueRoutine = false;
}

or

if ([1,2,4,5,6,7,9,10,11,13,14,15,16].indexOf(nTrials) > -1) {
continueRoutine = false;
}

There are other places where you have used in, so also change those to fix e.g.,

 if (nTrials in [3,8,12]) {
      catchStims.push(catchBDs.pop());

to

 if ([3,8,12].includes(nTrials)) {
      catchStims.push(catchBDs.pop()); //...etc

Also…:

for (let thisRater of catchList){
      if ([1,2].includes(thisRater.getRating())){

@Marc_Buehner, try switching your screen units in “Experiment Settings” to “height” units, this looks much better on my screen.