psychopy.org | Reference | Downloads | Github

Pavlovia + phaser3: tips for writing data?

Hey Agnes, how is your project coming along? As it happens getting the data to save on demand like you describe requires first adding script tags for a few of the runtime dependencies for PsychoJS, like you do with phaser in your index.html, then importing the library in your code and calling the appropriate methods. You can see how in this fork -note the IIFE for initialising the psychoJS controller inside the platformerSceneA module because it’s an asynchronous call :blush:

You can test that below with data up to the second trial saved when you close the browser tab:

I suspect your use case is slightly more involved, but I’m hoping that should help get you started for now. On standby in case you need more details, x

Thanks so much for taking the time to do this, this is incredibly helpful! I’ll have a go at implementing this method (hopefully this week) and will let you know then if everything seems to be working OK.

:blush:

Hi, I am running into a few issues when trying to adapt this solution for use across modules (I suspect this might be due to my lack of js knowledge rather than anything specific to pavlovia…)

  1. I assume that I need to create a single PyschoJS object for the entire experiment by calling const psychoJS = new PsychoJS in the first scene/module (here, js/scenes/platformerSceneA.js). Within the scene, this object is updated on after trial using a function that calls to psychoJS.experiment.addData(key, value).

  2. So, when the next module (scene/stage of the experiment) starts (here, js/scenes/platformerSceneB.js), what I want to do is continue adding to the same psychoJS object as before.
    I think I have achieved this by using export/import across modules, i.e.:
    in platformerSceneA.js:
    export const psychoJS = new PsychoJS({ debug: true })
    in platformerSceneB.js:
    import { psychoJS } from "./platformerSceneA.js"

This seems to work, up until the end of the task (last module, js/scenes/taskEndScene.js, when I am getting a fatal javascript error if I either try to log the psychoJS object to the console (to check that everything is getting stored), or call psychoJS.experiment.save(); (see below):


FATAL unknown | {} [log4javascript.min.js:1:40074](https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js)

append https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1

doAppend https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1

callAppenders https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1

log https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1

fatal https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1

dialog https://run.pavlovia.org/agnes.norbury/study-game-1/lib/core-2020.2.js:1151

onerror https://run.pavlovia.org/agnes.norbury/study-game-1/lib/core-2020.2.js:1823

I am also not generating any csv datafiles on gitlab.

I am wondering if either I am doing something wrong in with import/export above, or if I am missing something simple in my script to communicate with the core library to say that I’m ending my experiment? (I am also getting a couple of uncaught type errors, TypeError: this._setRequiredKeys is undefined [at the start of the experiment, I think related to downloading resources, and assume I can ignore], and Uncaught TypeError: dialogElement is null [which I think might relate to the fatal error at the end, may something to do with not setting psychoJS.Status correctly]).

I don’t know if this makes a difference, but I am currently testing in pilot mode (so as not to consume credits), might this be adding an extra layer of complication?

Sorry for the very long message, I will keep trying to look into this this afternoon but any help would be much appreciated.

Best

Agnes

OK, alright, yes, I think I follow, please allow me some time to look into how to best make those adjustments, thanks, s.

1 Like

Hey Agnes,

I was able to get the study to save by assigning attaching the psychoJS instance to the window object, which in turn makes it globally available. There are other ways of achieving the same result in JS (e.g., using a Singleton), but none less complicated. I also added a ‘util’ module to host saveTrialData() for sharing across scenes.

The one resources related error at the very beginning is a PsychoJS bug I’m hoping to have fixed in the next few days.

Commenting out the taskEndScene.js#L100 psychoJS.quit() call seems to have made the rest of errors go away. That allowed for the data to be saved as expected I believe, but I could be missing something :blush:

x

2 Likes

That is amazing! Thank you so much for taking the time to work on this. I implemented the changes you suggested in my branch and can confirm that data from across all the different task scenes is saving as expected in the output .csv file.

Hopefully this will be useful for anyone in the future who wants to use Phaser for their experiments.

Thanks again,

Agnes

2 Likes

Thank you Agnes :blush:

Hey Sotiri,

I have been following Agnes’ example and your post to implement a similar data saving in my task (project). However, I have been getting this error “log4javascript is not defined” in the console.

I did script load in index.html, and borrowed Agnes’ code from enterID.js. I assume this is a problem with JS integration/loading module? Any thoughts or feedback will be appreciated!

best,
QN

Hi @XXXiV-QN, sounds like you are missing the log4javascript.js dependency. Could you give me developer access so I can look at your project? Or try adding a script tag for it to your index.html? Thanks, s.

1 Like

Hi Sotiri, just added you as the developer! I will take a look at the script tag you mentioned later. Thank you so much for all the help. I am very new to JavaScript and Pavlovia, so everything I have now are mostly taken from tutorials/examples.

Best,
QN

1 Like

Hi @XXXiV-QN, cool project :+1: As it happens, PsychoJS is wired to intercept and display every JS error across all page scripts. I believe it’s meant as a convenience for easier debugging, but in this case it seems to be getting in the way.

In particular, if you look at the browser console once the diver hits the sea bed, you should be able to confirm the source of the problem is how you are calling sprite.anims.play('swim', true); inside of Player.update_float() and Player.update_sink(). The sprite is missing that ‘swim’ animation somehow?

I don’t know phaser well enough to have this sorted out for you on the spot :blush: But it looks like you would need to tweak that anims.create(); call in your constructor to then let this.sprite know?

Please feel free to follow up if you need more support, x

1 Like

Dear Sotiri,

Thank you so much for the suggestion. It was indeed a logical mistake (trying to play animation on a sprite that’s already destroyed). I changed things around, and added the same PsychoJS code like yesterday, the error is gone! I think I will work from there to continue implementing data saving then.

Cheers! :partying_face:
QN

No problem QN, happy coding :sun_with_face:

Hi @sotiri!

Do you know if anything was changed in lib/core-2020.2.js recently? Today I’m getting a fatal error when I attempt to run the task, which seems to trace back to there:

FATAL unknown | {} log4javascript.min.js:1:40074
append https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1
doAppend https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1
callAppenders https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1
log https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1
fatal https://cdnjs.cloudflare.com/ajax/libs/log4javascript/1.4.9/log4javascript.min.js:1
dialog https://run.pavlovia.org/agnes.norbury/study-game-1/lib/core-2020.2.js:1157
onerror https://run.pavlovia.org/agnes.norbury/study-game-1/lib/core-2020.2.js:1847

In the previously working setup, we were using

import * as data from "../../lib/data-2020.2.js";

to grab some relevant data-saving functions from the pavlovia lib, if something has changed in the source code is there a way I can edit the above so to make it work again?

Thank you!

Agnes

If there have been changes to lib/data-2020.2.js, maybe the best solution would for me to host a local version of the older code as part of my experiment rather than relying on the lib files (which might be subject to change) - is this available anywhere?

Hi @agnesnorbury, thanks for flagging, I was just about to respond. The changes brought in recently should have no effect on your project, because the rendering is happening outside of PsychoJS.

That said, it can be a little confusing how PsychoJS tries to blanket intercept all errors on page, which is the reason you see that code-2020.js traceback entry.

You can break out of that behaviour by monkey patching PsychoJS._captureErrors() as in the support fork for example:

/* Place at the top of scences/enterID.js to prevent PsychoJS from
taking over error tracing */
PsychoJS.prototype._captureErrors = () => {};

I have been unable so far to pick out the part that is causing the program to break, but it seems phaser related:

Thanks for getting back to me, and the tip about the error handling.

I’m struggling to work out what’s changed (the other version of my task is also broken in the same way: https://run.pavlovia.org/agnes.norbury/study-game-2/), but it may well be phaser related. If I work out a solution I’ll post it here.

Best

Agnes

(FYI @XXXiV-QN I just looked at https://run.pavlovia.org/QxF/swim-task/ and it seems to be having the same issue unfortunately…)

1 Like

@agnesnorbury if I remove all references to psychoJS and related imports including saveTrialData() the problem remains. Sorry Pavlovia is having trouble staging the support fork for some reason, x