Some of my participants (around 1/10 of them) reported that their experiment froze during a response screen. In this screen, I expect participants to enter some numbers using their keyboard and I print those numbers on the screen while they are typing. I present .mp3 files and also use a mouse component (before this problem occurs). I tried a thousand times and couldn’t replicate this problem. It doesn’t appear to be happening in a particular trial. I checked the developer tools and there isn’t any error (there are only some warnings that do not seem related to this issue).
The warnings I got were:
*The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page. *
[Deprecation] The ScriptProcessorNode is deprecated. Use AudioWorkletNode instead.
WARN unknown | setting the value of attribute: size in PsychObject: TextStim as: undefined
Because I wasn’t able to replicate it, I desperately asked participants who experienced this problem some questions. The only things that were common among the participants were 1) they were all windows users, 2) they had an external mouse or a keyboard plugged in (in addition to the touchpad or the internal keyboard of their laptops).
Here are some stuff I tried to replicate the problem and failed:
Exiting and re-entering fullscreen
Waiting for a long time to respond
Pressing other keys before pressing a valid key
Receiving notifications during the response screen
Using a mouse on a windows laptop
I would be really happy if anyone had any ideas, or experienced something similar to this and found a solution.
I am sorry in advance that this is very long and probably too complicated. I am using the builder with code components and in the end javascript looks like a mess.
var _key_resp_allKeys;
var resp_text;
var big_error;
var pressed_backspace;
var first_key;
var keyboard_responseComponents;
function keyboard_responseRoutineBegin(snapshot) {
return function () {
//------Prepare to start Routine 'keyboard_response'-------
t = 0;
keyboard_responseClock.reset(); // clock
frameN = -1;
continueRoutine = true; // until we're told otherwise
// update component parameters for each repeat
key_resp.keys = undefined;
key_resp.rt = undefined;
_key_resp_allKeys = [];
resp_text = new visual.TextStim({"win": win, "text": "", "color": red, "units": "pix", "height": (1.3 * ang_pix)});
big_error = new visual.TextStim({"win": win, "text": "13'ten b\u00fcy\u00fck bir say\u0131 girmeyiniz!", "pos": [0, (- 100)], "color": red, "units": "pix", "height": (1.3 * ang_pix)});
resp_text.text = "";
pressed_backspace = false;
end_key_resp = false;
first_key = true;
key_resp.clearEvents();
rt = 0;
// keep track of which components have finished
keyboard_responseComponents = [];
keyboard_responseComponents.push(key_resp);
for (const thisComponent of keyboard_responseComponents)
if ('status' in thisComponent)
thisComponent.status = PsychoJS.Status.NOT_STARTED;
return Scheduler.Event.NEXT;
}
}
var _pj;
var allkeys;
var quit_keys;
function keyboard_responseRoutineEachFrame(snapshot) {
return function () {
//------Loop for each frame of Routine 'keyboard_response'-------
// get current time
t = keyboard_responseClock.getTime();
frameN = frameN + 1;// number of completed frames (so 0 is the first frame)
// update/draw components on each frame
// *key_resp* updates
if (t >= 0.0 && key_resp.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
key_resp.tStart = t; // (not accounting for frame time here)
key_resp.frameNStart = frameN; // exact frame index
// keyboard checking is just starting
psychoJS.window.callOnFlip(function() { key_resp.clock.reset(); }); // t=0 on next screen flip
psychoJS.window.callOnFlip(function() { key_resp.start(); }); // start on screen flip
psychoJS.window.callOnFlip(function() { key_resp.clearEvents(); });
}
if ((key_resp.status === PsychoJS.Status.STARTED || key_resp.status === PsychoJS.Status.FINISHED) && Boolean(end_key_resp)) {
key_resp.status = PsychoJS.Status.FINISHED;
}
if (key_resp.status === PsychoJS.Status.STARTED) {
let theseKeys = key_resp.getKeys({keyList: [' '], waitRelease: false});
_key_resp_allKeys = _key_resp_allKeys.concat(theseKeys);
if (_key_resp_allKeys.length > 0) {
key_resp.keys = _key_resp_allKeys[_key_resp_allKeys.length - 1].name; // just the last key pressed
key_resp.rt = _key_resp_allKeys[_key_resp_allKeys.length - 1].rt;
}
}
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);
allkeys = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "backspace"];
win_rect.draw();
responses = key_resp.getKeys({"keyList": allkeys, "waitRelease": true, "clear": true});
quit_keys = key_resp.getKeys({"keyList": ["space"], "waitRelease": false});
if ((resp_text.text.length > 0)) {
if ((Number.parseInt(resp_text.text) > 13)) {
big_error.draw();
} else {
big_error.setAutoDraw(false);
}
for (var key, _pj_c = 0, _pj_a = quit_keys, _pj_b = _pj_a.length; (_pj_c < _pj_b); _pj_c += 1) {
key = _pj_a[_pj_c];
if ((key.name === "space")) {
end_key_resp = (Number.parseInt(resp_text.text) <= 13);
}
}
}
if ((responses.length > 0)) {
for (var key, _pj_c = 0, _pj_a = responses, _pj_b = _pj_a.length; (_pj_c < _pj_b); _pj_c += 1) {
key = _pj_a[_pj_c];
if ((key.name === "backspace")) {
pressed_backspace = true;
resp_text.text = resp_text.text.slice(0, (- 1));
} else {
if (_pj.in_es6(key.name, allkeys)) {
resp_text.text = (resp_text.text + key.name);
if (first_key) {
rt = key.rt;
first_key = false;
}
}
}
}
}
resp_text.draw();
// 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 keyboard_responseComponents)
if ('status' in thisComponent && thisComponent.status !== PsychoJS.Status.FINISHED) {
continueRoutine = true;
break;
}
// refresh the screen if continuing
if (continueRoutine) {
return Scheduler.Event.FLIP_REPEAT;
} else {
return Scheduler.Event.NEXT;
}
};
}
function keyboard_responseRoutineEnd(snapshot) {
return function () {
//------Ending Routine 'keyboard_response'-------
for (const thisComponent of keyboard_responseComponents) {
if (typeof thisComponent.setAutoDraw === 'function') {
thisComponent.setAutoDraw(false);
}
}
psychoJS.experiment.addData('key_resp.keys', key_resp.keys);
if (typeof key_resp.keys !== 'undefined') { // we had a response
psychoJS.experiment.addData('key_resp.rt', key_resp.rt);
}
key_resp.stop();
resp_text.setAutoDraw(false);
thisExp.addData("response", Number.parseInt(resp_text.text));
thisExp.addData("response_rt", rt);
thisExp.addData("pressed_backspace", pressed_backspace);
// the Routine "keyboard_response" was not non-slip safe, so reset the non-slip timer
routineTimer.reset();
return Scheduler.Event.NEXT;
};
}
I’d find it much easier to read the Python code in your Auto translated code compoents. However, I spotted this which seems redundant since it keeps getting reset to empty.
Thank you very much. I am definitely going to check if that’s something I’ve written.
Here is the python code. I also generated a keyboard component in gui that this code uses, which is called key_resp. It begins at t=0, ends when $end_key_resp.
Thank you sir, I always felt that this was a terrible way to collect keyboard responses but didn’t know the psychopy way to do things.
Can this be causing the problem? More specifically, can this cause an unsystematic error? I am asking because this is working for most of my participants, and even when it doesn’t when participants re-run the experiment they can run it without any problems.