Help: online piloting stuck on "initialising the experiment"

The code: https://gitlab.pavlovia.org/s8yuzhao/homer00ps_b
The link to experiment: https://run.pavlovia.org/s8yuzhao/homer00ps_b/html/

Description of the problem:

Dear experts/programmers,

I just came across a similar issue of stucking on “initialising the experiment” for my master thesis… I’ve read all the posts of relevant questions but the answer seems to be different to mine and not easy to apply for a green hand of programming…Would you please have a look at the document of the experiment? I’ve made the code public. Thanks in advance!

When it gets stuck, try opening the browser’s JavaScript console (in Chrome, go to View -> Developer) and see if it’s throwing error messages. At a glance I’m guessing it has to do with this:

import * as string from 'string';

I think this is part of a “begin experiment” code component? (I just looked at the JS script directly rather than the psyexp file). It seems to be repeated several times. It also seems to be used to reference Python-specific functions like “ascii_lowercase”, which do not exist in JavaScript. You will need to find some JS alternative to accomplish the same thing. What are you trying to do with these functions?

@wakecarter has made a useful guide for things that will and won’t work in code components:

Hello dear Jonathan,

many thanks for your quick reply! I applied “ascii_lowercase” to get typed answers from the participants, since in this mathematical experiments, participants have to type out their answers on every page and we are measuring their correctness and response time.

I deleted other 8 places of “import * as string from ‘string’;” and added the following JS code that I found on the Internet, but it still doesn’t work:

module.exports = function ascii_lowercase () {
const length = 26
let i = 65 + length + 6

return […Array(length)]
.reduce(function (accumulator) {
return accumulator + String.fromCharCode(i++)
}, ‘’)
}

Is it because I used Import? In the document you sent from wakecarter it’s suggested that we not use “import” at all… What is your idea? Thanks a lot in advance!

This is by the way where my edited code is: No repository · Yue / HoMer00PS_B · GitLab

For text entry, I would recommend looking at the demo experiments in this post: Transcription task online

The main thing is that import doesn’t work the same way in JavaScript, and you don’t have access to the same libraries that you do in Python. It looks like you’re trying to define a module or add something to a module in your code here, but I would avoid that if at all possible. If you need to define a custom function, just define the function itself, but I suspect with the code from the demo task you can do this in a much simpler way.

1 Like

Dear Jonathan,

thanks for the reply! I somehow managed to solve the problem and entered piloting after putting a participant’s name. But an error tag showed up, saying:

Unfortunately we encountered the following error:

when setting the image of ImageStim: imagewhen getting the value of resource: images/Vortest/Pre0.jpgunknown resource

Try to run the experiment again. If the error persists, contact the experiment designer.

I checked my pictures, they are all correct. Do you have any idea why it happened? Thanks you so much!

Could be case sensitivity. In your actual images folder, it’s Pre0.JPG. Try to make the file extension uppercase in your experiment as well.

Thanks Jonathan for the help! I solved the problem as you suggested by changing the name in the cloud(there are always problems when I try to synchronize the program from local)!
But there is a new problem while my experiment goes into the third page(where I want to get typed answers). And the Python code event is always not found. This is strange because all the codes I saw used event or keys and they were fine.

Here is my code, because JS does not support try and except, I deleted these first four lines, but still, it stucks with the definition of “event”…
Here is the link to the codes and underneath is the part to get typed answer where it went wrong:

Begin routine:
textFill = ‘’

Each frame:
try:
shift_flag
except NameError:
shift_flag = False
keys = event.getKeys()

if ‘escape’ in keys:
core.quit()
else:
if keys:
if keys[0] == ‘space’:
textFill += ’ ’
elif keys[0] == ‘backspace’:
textFill = textFill[:-1] # Deletes
elif keys[0] == ‘return’:
textFill += ‘\n’
elif keys[0] == ‘right’:
# record the answer in your data file:
thisExp.addData(‘answer’, textFill)
# go on to the next trial:
continueRoutine = False
elif keys[0] in [‘lshift’, ‘rshift’]:
shift_flag=True
pass
elif keys[0] == ‘period’:
textFill = textFill+’.’
elif keys[0] == ‘plus’:
textFill = textFill+’+’
elif keys[0] == ‘minus’:
textFill = textFill+’-’
elif keys[0] == ‘comma’:
textFill = textFill+’,’
elif keys[0] == ‘capslock’:
shift_flag == True
elif shift_flag == True and keys[0] == ‘0’:
textFill = textFill+’=’
elif shift_flag == True and keys[0] == ‘8’:
textFill = textFill+’(’
elif shift_flag == True and keys[0] == ‘9’:
textFill = textFill+’)’
elif shift_flag == True and keys[0] == ‘ß’:
textFill = textFill+’?’
elif shift_flag == True:
textFill = textFill+keys[0].upper()
shift_flag = False

    else:
         textFill =  textFill+keys[0]

screenText3.setText(textFill) # Set new text on screen

End routine:
for index, word in enumerate(cornerText3.text.split(’\n’)):
word = word.strip(’ ')
if len(word):
thisExp.addData(“word{}”.format(index), word)

My friend who studied programming also have no idea how to solve the problem…I’m at a lost…

There’s a bunch of stuff going on here and it’s going to take some work. What you’ve posted here is Python code, and some of it we can change in the Python, but some of it is going to require making modifications to the JS directly after it’s been converted.

Step 1: Let’s modify the Python. For this part, keep the “code type” of your code component as “auto->JS”.

  1. core.quit() isn’t needed, and PsychoPy has other ways of detecting if the “escape” key has been pressed, so we don’t need that top-level “if” statement at all.

  2. That whole try/catch thing isn’t needed. shift_flag is declared much earlier anyways. In fact, you can just pick up from keys=event.getKeys()

Here’s what the Python code will look like:

Python code component (collapsed for space)
keys = event.getKeys()

if keys:
    if keys[0] == 'space':
        textFill += ' '
    elif keys[0] == 'backspace':
        textFill = textFill[:-1]  # Deletes
    elif keys[0] == 'return':
        textFill += '\n' 
    elif keys[0] == 'right':
        # record the answer in your data file:
        thisExp.addData('answer', textFill)
        # go on to the next trial:
        continueRoutine = False
    elif keys[0] in ['lshift', 'rshift']:
        shift_flag=True
        pass
    elif keys[0] == 'period':
        textFill = textFill+'.'
    elif keys[0] == 'plus':
        textFill = textFill+'+'
    elif keys[0] == 'minus':
        textFill = textFill+'-'
    elif keys[0] == 'comma':
        textFill = textFill+','
    elif keys[0] == 'capslock':
        shift_flag == True
    elif shift_flag == True and keys[0] == '0':
        textFill = textFill+'='
    elif shift_flag == True and keys[0] == '8':
        textFill = textFill+'('
    elif shift_flag == True and keys[0] == '9':
        textFill = textFill+')'
    elif shift_flag == True and keys[0] == 'ß':
        textFill = textFill+'?'
    elif shift_flag == True:
        textFill = textFill+keys[0].upper()
        shift_flag = False
    else:
         textFill =  textFill+keys[0]
screenText.setText(textFill)  # Set new text on screen

Once you’ve got that code in the left panel of your code component, change the code type from “Auto->JS” to “Both”. That will retain the auto-converted code, but you can now modify the JS directly in the right panel (this is so we don’t break the python code while we’re changing the JS). Everything else we do in the right-hand panel of the code component. It should look like this at first:

Initial JS code (collapsed for space)

var _pj;
function _pj_snippets(container) {
function in_es6(left, right) {
if (((right instanceof Array) || ((typeof right) === “string”))) {
return (right.indexOf(left) > (- 1));
} else {
if (((right instanceof Map) || (right instanceof Set) || (right instanceof WeakMap) || (right instanceof WeakSet))) {
return right.has(left);
} else {
return (left in right);
}
}
}
container[“in_es6”] = in_es6;
return container;
}
_pj = {};
_pj_snippets(_pj);
keys = event.getKeys();
if (keys) {
if ((keys[0] === “space”)) {
textFill += " ";
} else {
if ((keys[0] === “backspace”)) {
textFill = textFill.slice(0, (- 1));
} else {
if ((keys[0] === “return”)) {
textFill += “\n”;
} else {
if ((keys[0] === “right”)) {
thisExp.addData(“answer”, textFill);
continueRoutine = false;
} else {
if (_pj.in_es6(keys[0], [“lshift”, “rshift”])) {
shift_flag = true;
} else {
if ((keys[0] === “period”)) {
textFill = (textFill + “.”);
} else {
if ((keys[0] === “plus”)) {
textFill = (textFill + “+”);
} else {
if ((keys[0] === “minus”)) {
textFill = (textFill + “-”);
} else {
if ((keys[0] === “comma”)) {
textFill = (textFill + “,”);
} else {
if ((keys[0] === “capslock”)) {
(shift_flag === true);
} else {
if (((shift_flag === true) && (keys[0] === “0”))) {
textFill = (textFill + “=”);
} else {
if (((shift_flag === true) && (keys[0] === “8”))) {
textFill = (textFill + “(”);
} else {
if (((shift_flag === true) && (keys[0] === “9”))) {
textFill = (textFill + “)”);
} else {
if (((shift_flag === true) && (keys[0] === “\u00df”))) {
textFill = (textFill + “?”);
} else {
if ((shift_flag === true)) {
textFill = (textFill + keys[0].upper());
shift_flag = false;
} else {
textFill = (textFill + keys[0]);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
screenText.setText(textFill);

First thing we’ll need to change is the line keys=event.getKeys(); because that won’t work in JS. Instead, we change it to keys = psychoJS.eventManager.getKeys();

Next, if (keys){ probably won’t work as well as if (keys && keys.length){. This is just a belt-and-suspenders thing to make sure there’s actually something in the keys array. The underlying reasons to do this in JS but not Python involve how “if” statements work, a concept called “truthyness”, and a whole bunch of other stuff we don’t need to get into.

Then we need to replace thisExp.addData. PsychoJS just uses addData in a different way. Use psychoJS.experiment.addData instead.

Finally, keys[0].upper() won’t work, because .upper() is another Python function. There is a JS equivalent, however: keys[0].toUpperCase()

Ultimately, that will leave you with this JS code:

final JS code
var _pj;
function _pj_snippets(container) {
    function in_es6(left, right) {
        if (((right instanceof Array) || ((typeof right) === "string"))) {
            return (right.indexOf(left) > (- 1));
        } else {
            if (((right instanceof Map) || (right instanceof Set) || (right instanceof WeakMap) || (right instanceof WeakSet))) {
                return right.has(left);
            } else {
                return (left in right);
            }
        }
    }
    container["in_es6"] = in_es6;
    return container;
}
_pj = {};
_pj_snippets(_pj);
keys = psychoJS.eventManager.getKeys();
if (keys.length) {
    if ((keys[0] === "space")) {
        textFill += " ";
    } else {
        if ((keys[0] === "backspace")) {
            textFill = textFill.slice(0, (- 1));
        } else {
            if ((keys[0] === "return")) {
                textFill += "\n";
            } else {
                if ((keys[0] === "right")) {
                    psychoJS.experiment.addData("answer", textFill);
                    continueRoutine = false;
                } else {
                    if (_pj.in_es6(keys[0], ["lshift", "rshift"])) {
                        shift_flag = true;
                    } else {
                        if ((keys[0] === "period")) {
                            textFill = (textFill + ".");
                        } else {
                            if ((keys[0] === "plus")) {
                                textFill = (textFill + "+");
                            } else {
                                if ((keys[0] === "minus")) {
                                    textFill = (textFill + "-");
                                } else {
                                    if ((keys[0] === "comma")) {
                                        textFill = (textFill + ",");
                                    } else {
                                        if ((keys[0] === "capslock")) {
                                            (shift_flag === true);
                                        } else {
                                            if (((shift_flag === true) && (keys[0] === "0"))) {
                                                textFill = (textFill + "=");
                                            } else {
                                                if (((shift_flag === true) && (keys[0] === "8"))) {
                                                    textFill = (textFill + "(");
                                                } else {
                                                    if (((shift_flag === true) && (keys[0] === "9"))) {
                                                        textFill = (textFill + ")");
                                                    } else {
                                                        if (((shift_flag === true) && (keys[0] === "\u00df"))) {
                                                            textFill = (textFill + "?");
                                                        } else {
                                                            if ((shift_flag === true)) {
                                                                textFill = (textFill + keys[0].upper());
                                                                shift_flag = false;
                                                            } else {
                                                                textFill = (textFill + keys[0]);
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
screenText.setText(textFill);

You can actually copy that into the JS panel of your code component if the code type is set to “both”.

Looking at it there are a couple things in it that I’m not 100% sure will work, but I don’t have time to test it myself right now. I would recommend making these changes and piloting it on Pavlovia, and if it gives you any errors they will probably be different from what you were getting before, and informative as to what else might need to change.

1 Like

I’ve just added

Object.prototype.upper = “”.toUpperCase;

to the code_JS section of my crib sheet which will change this.

…except that it should have been String.prototype.upper = “”.toUpperCase;

Apologies to anyone who has had problems when using the wrong version.