frameDur is not defined error

URL of experiment: https://run.pavlovia.org/learningdevlab/3b_complex_binctl/html

Description of the problem: When I click to pilot my experiment, I get through the dialog box, but then immediately get a frameDur error

when I check the javascript console, my error is related to code that was generated automatically by psychopy/pavlovia
Screen Shot 2020-03-11 at 12.21.56 PM

// store frame rate of monitor if we can measure it successfully
  expInfo['frameRate'] = psychoJS.window.getActualFrameRate();
  if (typeof expInfo['frameRate'] != 'undefined')
    frameDur = 1.0 / Math.round(expInfo['frameRate']);
  else
    frameDur = 1.0 / 60.0; // couldn't get a reliable measure so guess

Does anyone know how I can fix this?
I used the upload function directly from psychopy builder in version 2020.1.2

Thanks!

That’s weird. Most experiments don’t raise this error. Are you doing anything unusual? Do you have any Code Components (especially any that refer to frameDur)?

We do have a number of code components, but none refer specifically to frameDur. A number do refer to sound status or duration.

OK, so, in your JS file it turns out there’s no line
var frameDur;
which is needed to define that variable name in JavaScript before it’s used. That line should have been generated while your experiment was compiled but seemingly wasn’t.

When you exported your study to html (e.g. by pressing sync) there wasn’t any message in PsychoPy was there, warning about invalid syntax maybe?

So the one error that I do get is this:

582.7943     ERROR     Line 2685: Unexpected token && in 3b_complex_binctl.js
584.4439     ERROR     Line 2689: Unexpected token && in 3b_complex_binctl-legacy-browsers.js

If I look at those lines in the code its referring to this block of code:

    // start/stop star_sound
    if (() && star_sound.status === PsychoJS.Status.NOT_STARTED) {
      // keep track of start time/frame for later
      star_sound.tStart = t;  // (not accounting for frame time here)
      star_sound.frameNStart = frameN;  // exact frame index

If I search for the same string of code ( if (() && (...) that is causing the unexpected token issue there are 7 other places that I find it. They all seem to refer to sounds that have no defined (blank) onset or duration in the builder, and that are referred to in code components and called via mouse click in an object. The particular lines that it is having an issue with are not part of our code components, but seem to be the auto generated JS lines for the builder components. If I go into the .js and legacy-browsers.js files and manually take out the (() && and leave the rest of the line, it exports fine and reports as successful.

I have the same issue and no syncing issue when exporting.

I have tried adding the line var frameDur; to the Begin Experiment tab of my code component but that didn’t work.

Best wishes,
Tom

Thanks @fetch I’ll obviously need to look into the code being generated there. Why would you have a sound with no defined onset? Blank duration makes sense (means infinite) but I can’t think what blank onset should aim to do.

I have the same issue but adding var frameDur works for me. And then I also onto this error

@jon we have an undefined onset because the sound plays on the condition of a mouse click in an object. I found another thread about changing “isClickedin” to a different call that is JS compatible, but that didn’t make a difference in this error. So all of the ones that have the issue with the code are ones that are set to onset/start as “on condition” and then the condition is defined in a code component referring to the mouse component.

@Xiaotong @jon I think these folks are getting similar errors to me. I went through and tried to add the var line but then it just throws the next error as an undefined INTROclock and then i added a var line to that, and it just jumps down to the next line and throws an error that wants you to add a var call to all of the variables throughout the entire code, so i just gave up.

yep im in the process of trying to add all the variables and its proving quite tiresome - hopefully there’s a far more efficient way to fix it!

I keep saying stop trying to fix the var statements. If the rest of your experiment is right then those will be added automatically. The issue with the var statements is caused by an issue with your study.

You need to find the component that’s breaking the code in the first place. When you remove things what causes the var lines to come back?

In @fetch 's case the these blank audio onsets are certainly an issue. If you want audio to start based on a certain condition then set that in the dialog box, rather than setting onset to be blank you need to set it to be start on condition and then set that conditional in the dialog box. Maybe you create a variable like startMySound and set that to True when you want the sound to play, but you can’t just leave the box blank. Doing that caused PsychoPy to write the code
if (() && star_sound.status === PsychoJS.Status.NOT_STARTED)
which doesn’t make sense.

So it would be great if you could spend some time working out which parts of your code are breaking the compiling step and letting us know. Then we can start inserting things to alert users before that goes wrong like, “The onset of an object can’t be blank”

cheers,
Jon

A thought: I eventually got this error when my study was running up until the routine with the code component in it:

SyntaxError: Illegal continue statement: no surrounding iteration statement

I then looked at my code and there’s only one bit with continue statements in it (attatched with corresponding py code):

js2 py2

Hope this helps,
Tom

Hi jon, my problem starts from here Infinite initializing experiment. I don’t have a programming background so I just tried an easier way – removing import * as random from 'random'; import * as xlrd from 'xlrd';. Then I got the frameDur is not defined error. Thank you.

For Tom: yes that error message is informative. First off, it would be easier (for you to paste and for us to read) if you pasted in code as text. You cna just select the code and Ctrl-C. Come here and type 3 back ticks like this ``` then paste your code and then do three more backticks to end it.

Anyway, I can certainly see an issue with your code given your error message about the continue. Your Python code says

if 0 in obs_dict.values() or 1 in obs_dict.values():
    continue

Now I don’t know what that code is meant to be doing (is it designed to skip the trial) but it isn’t really right, and that’s the part that then gets translated into something that fully raises an error in JavaScript. The issue is that the command continue doesn’t make sense in an “if” statement, only in a loop. Is the aim to skip over that trial?

if obs_dict == {}:
    for image in trials.trialList:
        image = image['object']
        obs_dict[image] = 0
        

correct = False

loc = trials.thisTrial['loc']
image = trials.thisTrial['object']
if obs_dict[image] == 2:
    if 0 in obs_dict.values() or 1 in obs_dict.values():
        continue
    else:
        trials.finished = True
        continue

Yes in a nutshell its meant to skip over a trial for which our learning criterion has been met (i.e., an object being placed in the correct location twice in a row). Then the last couple of lines were added because psychopy would crash when all the objects had been learned at the end of the routine.

Cheers,
Tom

Ah, OK. Yes, then I can see why that would work in the Python code (because that code is called within a loop of trials) but also why it won’t work in the current literal translation to JS (because that code is not then in a loop - it gets run inside a function). I’ll need to speak to someone with more JS skills to know what’s a sensible alternative for that.

Thanks for looking into it Jon I look forward to hearing from you.

Tom

Hi Jon did you have any luck?

Cheers,
Tom

It comes down to something like this. In the Routine where you currently have the continue you can do this

if obs_dict[image] == 2:
    skipThisTrial = True  # variable to use in feedback etc
    continueRoutine = False  # end this routine
    if 0 not in obs_dict.values() and 1 not in obs_dict.values():
        # end the whole trials loop
        trials.finished = True
else:
    skipThisTrial = False

The for your feedback routine you’d have something in the every frame to say:

if skipThisTrial:
    continueRoutine = False

I think something like that would work in both Python and JS (it isn’t tested but you can hopefully see the logic).

Again the issue is that, for the Python code, this is being executed in a loop whereas for the JS code it is not, so we need a different way to handle it

Thanks Jon, the code you sent makes sense but still doesn’t work - exactly when the whole trials loop is due to end I get this:

if mouse.x[0] in range(pos[0]-150, pos[0]+150):
IndexError: list index out of range

Also - something you might want to know - i tried to upload the task without any code components added and I STILL had the error of variables not being defined which surprised me. A much,much stripped down version of the task exists (my second session task) and this works fine so I just assumed it was the code component causing the trouble but apparently it isn’t. I’ll try and find out exactly where the problem is and get back to you.

Cheers,
Tom