TypeError: Cannot read property 'addChild' of undefined

URL of experiment: https://pavlovia.org/Wake/ebbinghaus-darts

Description of the problem:

PsychoJS -
Begin Experiment
sin = function (a) {
return Math.sin(a);
}

cos = function (a) {
return Math.cos(a);
}

pi=Math.pi
win = psychoJS.window

Begin Routine
pic = [];
points = [];
for (var Idx = 0, _pj_a = 36; (Idx < _pj_a); Idx += 1) {
points.push([(((0.5 * scale) * dflanker) * cos((((Idx * 2) * pi) / 36))), (((0.5 * scale) * dflanker) * sin((((Idx * 2) * pi) / 36)))]);
}
for (var Idx = 0, _pj_a = nflankers; (Idx < _pj_a); Idx += 1) {
pic.push(new visual.ShapeStim({“win”: win, “fillColor”: flankercolour, “lineColor”: “black”, “vertices”: points, “pos”: [((scale * cos((((Idx * 2) * pi) / nflankers))) * ((dtarget + offset) + (dflanker / 2))), (voffset + ((scale * sin((((Idx * 2) * pi) / nflankers))) * ((dtarget + offset) + (dflanker / 2))))]}));
}

Each Frame
for (var Idx = 0, _pj_a = nflankers; (Idx < _pj_a); Idx += 1) {
pic[Idx].draw();
}
if (rec_4.contains(mouse)) {
continueRoutine = false;
}

On my iPhone I get the error:
TypeError: undefined is not an object (evaluating “this.win._container.addChild”)

Is the problem that I have to replace win with psychoJS.window at every instance rather than defining it globally? I thought I’d previously tested that, but it may be that there was a different issue then.

Best wishes,

Wakefield

Just bumping this in case anyone can help.

My Ebbinghaus darts “game” now works quite well locally on a touchscreen laptop but I can’t test it on a mobile until I can sort out the PsychoJS.

I’ve set the experiment to public in case anyone would like to try it out.

Best wishes,

Wakefield

Interesting. The error suggests that defining “win” isn’t working for some reason. At a minimum, replacing each instance of “win” with psychoJS.window is a good first step in troubleshooting. If it gives you a different error, at the very least it’s informative.

The error is the same when explicitly adding psychoJS.window

I’m wondering whether it’s related to having an array of ShapeStims

After some investigation, it’s that you’re calling .draw(), which doesn’t work in psychoJS. I made a copy and got it to work (or at least, to do something on my laptop web browser) by replacing each instance of .draw with .setAutoDraw(True) (lowercase t in JS).

Thank you, that’s a great step forward. Yesterday I was thinking I might need to start again from scratch with different software.

I’ve added

for Idx in range(nflankers):
pic[Idx].setAutoDraw(True)

to Each Frame, though logically it should probably be in Begin Routine. I’ve tried in both locations and also tried pic[Idx].AutoDraw = True

The program now runs on my laptop without any errors. However the “petals” of the flower do not actually get displayed and the dandelion dart disappears as soon as it gets touched. It should move to the location of the touch and then be swipeable upwards to “throw” it. The data file is giving NaN or 0 as the distance between the dart and the target which suggests that it isn’t working as intended as well as not displaying.

My next theory is that perhaps it doesn’t like some images (the target and the dart) being displayed via builder components and others being displayed via code. However, experimenting with that will have to wait for another day.

Best wishes,

Wakefield

P.S. This is also giving some odd behaviour when running in standalone mode. The petals from previous trials are still there in addition to the new ones.

I suspect that’s because setAutoDraw is never set to false. Objects created by the builder sort of clean themselves up, but the petals are made in the code component, so you probably need to put something in end routine to manually turn them off. EDIT: Actually, on further thought, it’s probably that you never clear out the array! Try wiping the array during endroutine.

More broadly you’re right that making some things in the builder and others in code can lead to some unpredictable behavior. I’m not sure what part of your code is controlling this “throwing” behavior so I can’t really comment on that, nothing in the first post looks like it would do that, or indeed update the position of the things at all.

I was setting pic = [] in the Begin Routine.

However, I wasn’t setting AutoDraw to false. Setting it to true in the Begin Routine and then false in the End Routine seems to have solved the issue for PsychoPy standalone.

Did you manage to get the StimShapes to display when you tried it?

I’ll try moving the target and dart to code over the weekend.

Best wishes,

Wakefield

Having moved all of the visual stimuli to code I’m now getting TypeError: Cannot read property ‘map’ of undefined. Interestingly on my iPhone, I’m getting TypeError: undefined is not an object (evaluating ‘color.rgb.map’) which suggests it’s to do with the colour space. My code for creating the objects is now as follows:

Python
Begin Experiment
tpoints = []
for Idx in range(36):
tpoints.append([.5scaledtargetcos(Idx2pi/36),.5scaledflankersin(Idx2pi/36)])

bg=visual.ShapeStim(
win=win, name=“bg”,
fillColor=(0, 1, 0), fillColorSpace=‘rgb’,
lineColor=(0, 1, 0), lineColorSpace=‘rgb’,
vertices=[[-1,1],[1,1],[1,-1],[-1,-1]]
)
errorrec=visual.ShapeStim(
win=win, name=“errorrec”,
fillColor=[.2,.2,.2], fillColorSpace=‘rgb’,
lineColor=[1,1,1], lineColorSpace=‘rgb’,
vertices=[[.18,.49],[.42,.49],[.42,.40],[.18,.40]]
)
target_3 = visual.ShapeStim(
win=win,
fillColor=“yellow”, fillColorSpace=‘rgb’,
lineColor=“black”, lineColorSpace=‘rgb’,
vertices=tpoints,
pos = [0, voffset],
)
errortext = visual.TextStim(win=win, name=‘errortext’,
text=‘NA’,
font=‘Arial’,
pos=(0.3, .45), height=0.08, wrapWidth=None, ori=0,
color=‘white’, colorSpace=‘rgb’, opacity=1,
languageStyle=‘LTR’,
depth=-2.0);
dart = visual.ImageStim(
win=win,
name=‘dart’,
image=‘dandelion_dart.png’, ori=0, pos=[0,-.35], size=[.25,.25],
color=[1,1,1], colorSpace=‘rgb’, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-4.0)

Begin Routine
points = []
for Idx in range(36):
points.append([.5scaledflankercos(Idx2pi/36),.5scaledflankersin(Idx2pi/36)])
pic = []
dartpos = [0, -.35]
dartsize = [.25,.25]
dartv = [0,0]
dartoldpos=[0,-.35]
inflight=0
drag = [.95,.90]
framecount = 0

for Idx in range(nflankers):
pic.append(visual.ShapeStim(
win=win,
fillColor=flankercolour,
lineColor=“black”,
vertices=points,
pos = [scalecos(Idx2pi/nflankers)(dtarget+offset+dflanker/2),voffset+scalesin(Idx2pi/nflankers)(dtarget+offset+dflanker/2)],
))

bg.setAutoDraw(True)
errorrec.setAutoDraw(True)
errortext.setAutoDraw(True)
target_3.setAutoDraw(True)

for Idx in range(nflankers):
pic[Idx].setAutoDraw(True)

dart.setAutoDraw(True)

PsychoJS
Begin Experiment
sin = function (a) {
return Math.sin(a);
}

cos = function (a) {
return Math.cos(a);
}

pi=Math.pi
win = psychoJS.window
tpoints = [];
for (var Idx = 0, _pj_a = 36; (Idx < _pj_a); Idx += 1) {
tpoints.push([(((0.5 * scale) * dtarget) * cos((((Idx * 2) * pi) / 36))), (((0.5 * scale) * dflanker) * sin((((Idx * 2) * pi) / 36)))]);
}
bg = new visual.ShapeStim({“win”: win, “name”: “bg”, “fillColor”: [0, 1, 0], “fillColorSpace”: “rgb”, “lineColor”: [0, 1, 0], “lineColorSpace”: “rgb”, “vertices”: [[(- 1), 1], [1, 1], [1, (- 1)], [(- 1), (- 1)]]});
errorrec = new visual.ShapeStim({“win”: win, “name”: “errorrec”, “fillColor”: [0.2, 0.2, 0.2], “fillColorSpace”: “rgb”, “lineColor”: [1, 1, 1], “lineColorSpace”: “rgb”, “vertices”: [[0.18, 0.49], [0.42, 0.49], [0.42, 0.4], [0.18, 0.4]]});
target_3 = new visual.ShapeStim({“win”: win, “fillColor”: “yellow”, “fillColorSpace”: “rgb”, “lineColor”: “black”, “lineColorSpace”: “rgb”, “vertices”: tpoints, “pos”: [0, voffset]});
errortext = new visual.TextStim({“win”: win, “name”: “errortext”, “text”: “NA”, “font”: “Arial”, “pos”: [0.3, 0.45], “height”: 0.08, “wrapWidth”: null, “ori”: 0, “color”: “white”, “colorSpace”: “rgb”, “opacity”: 1, “languageStyle”: “LTR”, “depth”: (- 2.0)});
dart = new visual.ImageStim({“win”: win, “name”: “dart”, “image”: “dandelion_dart.png”, “ori”: 0, “pos”: [0, (- 0.35)], “size”: [0.25, 0.25], “color”: [1, 1, 1], “colorSpace”: “rgb”, “opacity”: 1, “flipHoriz”: false, “flipVert”: false, “texRes”: 128, “interpolate”: true, “depth”: (- 4.0)});

Begin Routine
points = [];
for (var Idx = 0, _pj_a = 36; (Idx < _pj_a); Idx += 1) {
points.push([(((0.5 * scale) * dflanker) * cos((((Idx * 2) * pi) / 36))), (((0.5 * scale) * dflanker) * sin((((Idx * 2) * pi) / 36)))]);
}
pic = [];
dartpos = [0, (- 0.35)];
dartsize = [0.25, 0.25];
dartv = [0, 0];
dartoldpos = [0, (- 0.35)];
inflight = 0;
drag = [0.95, 0.9];
framecount = 0;
for (var Idx = 0, _pj_a = nflankers; (Idx < _pj_a); Idx += 1) {
pic.push(new visual.ShapeStim({“win”: win, “fillColor”: flankercolour, “lineColor”: “black”, “vertices”: points, “pos”: [((scale * cos((((Idx * 2) * pi) / nflankers))) * ((dtarget + offset) + (dflanker / 2))), (voffset + ((scale * sin((((Idx * 2) * pi) / nflankers))) * ((dtarget + offset) + (dflanker / 2))))]}));
}
bg.setAutoDraw(true);
errorrec.setAutoDraw(true);
errortext.setAutoDraw(true);
target_3.setAutoDraw(true);
for (var Idx = 0, _pj_a = nflankers; (Idx < _pj_a); Idx += 1) {
pic[Idx].setAutoDraw(true);
}
dart.setAutoDraw(true);

Currently I have to change .append to .push manually every time I change the code, as well as thisExp to psychoJS.experiment. I’m hoping to avoid having to keep changing win to psychoJS.window – my assumption is that I would be getting a different error message if that was the issue.

Best wishes,

Wakefield

I suspect it’s that flankercolour appears to be undefined. If not undefined, it’s pulling from a condition file, that could to run into the problem of JS reading arrays as strings when pulled from xlsx or csv files. Basically if you have something like [0,1,0] in a condition file, Python can read that as the array [0, 1, 0], but JS reads it as the string “[0,1,0]”. Fixing that requires having separate columns for each numeric value, so the color becomes [Rcolor, Gcolor, Bcolor].

Also just a formatting trick for the forums to make your code easier to read, if you put three ` before and after code blocks, they will format properly and not do things like randomly italicize between asterisks. So, for example, your Python begin routine code:



points = []
for Idx in range(36):
points.append([.5 *scale* dflanker *cos(Idx* 2 *pi/36),.5* scale *dflanker* sin(Idx *2* pi/36)])
pic = []
dartpos = [0, -.35]
dartsize = [.25,.25]
dartv = [0,0]
dartoldpos=[0,-.35]
inflight=0
drag = [.95,.90]
framecount = 0

for Idx in range(nflankers):
pic.append(visual.ShapeStim(
win=win,
fillColor=flankercolour,
lineColor=“black”,
vertices=points,
pos = [scale *cos(Idx* 2 *pi/nflankers)* (dtarget+offset+dflanker/2),voffset+scale *sin(Idx* 2 *pi/nflankers)* (dtarget+offset+dflanker/2)],
))

bg.setAutoDraw(True)
errorrec.setAutoDraw(True)
errortext.setAutoDraw(True)
target_3.setAutoDraw(True)

for Idx in range(nflankers):
pic[Idx].setAutoDraw(True)

dart.setAutoDraw(True)

I tried changing all colour definitions to arrays with no success. I’m not using a conditions file, but flankercolour = “white” (now [1,1,1]).

Thanks for the tip about code formatting.

I’m now going to go the other direction and create a version that has no visual stimuli in the code snippets.

Well that was surprising. If I create all of the images using components with all colours using three dimensional arrays, I still get the same error message as if I create all images using code.

Interesting. When you run it on your laptop, you can open the Javascript console (in chrome, go to view -> developer), and when that error pops up, it should register a more detailed error in the (probably two, one for the error and one for the error message). Could you copy those over into a post? It may give a more specific idea of where the error is coming from.

Here they are:

core-2020.1.js:1437 TypeError: Cannot read property 'map' of undefined
    at Rect.contains (visual-2020.1.js:468)
    at Scheduler._currentTask (ebbinghaus darts.js:954)
    at Scheduler._runNextTasks (util-2020.1.js:1091)
    at Scheduler._runNextTasks (util-2020.1.js:1094)
    at Scheduler._runNextTasks (util-2020.1.js:1094)
    at Scheduler._runNextTasks (util-2020.1.js:1094)
    at update (util-2020.1.js:1058)

and

log4javascript.min.js:1 FATAL unknown | {}
BrowserConsoleAppender.append	@	log4javascript.min.js:1
Appender.doAppend	@	log4javascript.min.js:1
Logger.callAppenders	@	log4javascript.min.js:1
Logger.log	@	log4javascript.min.js:1
fatal	@	log4javascript.min.js:1
dialog	@	core-2020.1.js:920
window.onerror	@	core-2020.1.js:1438

Line 954 is a component which seems to be working fine on earlier routines

mouseloc = mouse.getPos();
    if ((((mouseloc[0] === mouserec[0]) && (mouseloc[1] === mouserec[1])) && (inflight < 2))) {
    } else {
        if (rec_score.contains(mouse)) {
            mouserec = mouseloc;
            continueRoutine = false;
        } else {

Any ideas?

Interesting. I see you have that statement, or variants of it, several times throughout the code, and you’re saying it works fine on other trials. Looking at the other instances of that code, my best guess is that rec_score is not drawn before this is called. That is, the other three times this “contains” setup is used, the object you’re checking has “setAutoDraw = true” on an earlier line in the every-frame code for their respective trials. (If you do a search for “contains” in the js code you will see what I mean: https://gitlab.pavlovia.org/Wake/ebbinghaus-darts/blob/master/html/ebbinghaus%20darts.js). So, my guess is that because rec_score hasn’t been drawn yet, it can’t work out “contains” because “contains” requires the shape to be present on the screen.

The solution would be either to make sure rec_score is drawn before that line of code, or to add an additional check to the else statement to make sure it only gets to the contains statement if the shape has been drawn:

mouseloc = mouse.getPos();
    if ((((mouseloc[0] === mouserec[0]) && (mouseloc[1] === mouserec[1])) && (inflight < 2))) {
    } else if (rec_score.autoDraw === true){
        if (rec_score.contains(mouse)) {
            mouserec = mouseloc;
            continueRoutine = false;
        } else {

This is mostly an educated guess, but it seems like the most likely candidate given that this is the only instance of that code that has trouble.

edit: Misnamed the autoDraw variable.

The rectangle and the text within it are separate components.

However, I think by disabling all the components and then re-enabling them (I’m not sure if there are any real differences) I no longer get the Cannot read property ‘map’ of undefined error when running in full screen. I only get it when the developer console is active.

I’ve therefore started a new thread for the remaining issue that the polygons aren’t all displaying. Polygons and images not displaying online

Thanks for your help with getting me this far.

Best wishes,

Wakefield

That’s a good fix. My guess is that it just re-ordered the code a little bit so things happened in a better sequence. Well, as long as it works!

Dear @wakecarter

Thank you once more for your great help - contribution.

Suddenly today, my exp is loaded and doesn’t stuck at initializing but I started by getting an error "mouse.setPos(…) is not a function.

Then, after pain because I have the impression the system lags and doesn’t read the changes, I removed this part of the code (it’s purpose was to reset the mouse in the start of every trial. Anyway I try to get it work even without that).

At the moment I get the same error as you said here:
Cannot read property ‘map’ of undefined

Did you solve this or what does that mean ? I have 4 polygon stimuli in my Exp (and also 4 text stimuli) is that the problem ? I don’t understand what is this.

Please share your acquired wisdom.

Thank you a lot. :slight_smile:

TypeError: Cannot read property ‘map’ of undefined

If you are checking the mouse location, for example with “if rec.contains(mouse):”, ensure that the component for the object to be checked is above the code component that checks it.