psychopy.org | Reference | Downloads | Github

Accurate timing for online studies

I’m implementing a backward masking experiment with psychopy to run online on pavlovia. I’m a little bit in confusion with frame indexing given that I want to use frame as time units.
I have to present a stimulus for 50ms (~3 frames at 60hz) than a mask for 200ms (~12frames). Between the stimulus and the mask, I have a 0 or 100 (~6 frames) SOA.

I’ve also noticed that there is no precise way to assess the stimulus timing and the actual monitor refresh rate (there is this method)

Given that I’m using the builder, it is correct the following approach?
Target
image
Mask
image

I have within the xlsx file the number of frames for each duration. I use the +1 because I have reasoned that if the target lasts for 3 frames, the next frame will be the first available for the mask.

Hi There,

This implementation seems fine (although I am not sure that the +1 is needed because something can be “undrawn” and another thing “drawn” on the same frame if that makes sense).

Now something that you may wish to consider for online use, timing by frames will be very sensitive to things that could place processing demands on your users computer, causing frames to drop (e.g. do they have 5000 tabs open and streaming game of thrones in another tab). Dropping frames would change the timing of your stimuli on that computer. Be wary to ask your participants to limit what else they have going on when running your experiment.

Another thing is you will want to detect the framerate of the monitor the participant is using, in order to determine the correct number of frames to present something for. This is fetched automatically and available using the variable expInfo['frameRate'] BUT if frame rate cannot be measured reliably (e.g. because lots of frames are being dropped) a 60Hz refresh rate is assumed.

Of course, for completely precise control over timing we need to calibrate set ups - but this isn’t practical online. So, this is a natural limitation of taking research online that you might want to consider if you are wishing to time by frames.

Hope this info is helpful
Becca

Hi Becca,
As always, thank you for your information.
Just few clarification in order to see if I get the point.

This implementation seems fine (although I am not sure that the +1 is needed because something can be “undrawn” and another thing “drawn” on the same frame if that makes sense).

Yes, this was my first concern about how to work with frame duration (instead of seconds). My reasoning was that starting from 0 my stimulus lasts for 3 frames. If I want to set the mask starting point, I have to set the first available frame after the target duration. Do you think that is better to drop the +1?

This is fetched automatically and available using the variable expInfo['frameRate'] BUT if frame rate cannot be measured reliably (e.g. because lots of frames are being dropped) a 60Hz refresh rate is assumed.

This is great. However in this post this method they said that the frame rate estimation of online studies is not implemented yet (JSDoc: Source: core/Window.js).

Given your information, my final approach should be:

  • Choosing a stimuli duration in seconds (maybe 60hz friendly)
  • Estimating the refresh rate using the above methods
  • Finding the closest number of frames that ensure the desired duration
  • Set these frame as experiment timing
    What do you think?

Hi There,

To get a better idea here - are you able to look at the stimulus start and stop times in your output file when you run locally? do they appear to run the timelines you expect with the frames you have specified?

Aha thanks very much for clarifying that ! I was thrown by expInfo['frameRate'] = psychoJS.window.getActualFrameRate(); but see actually this is still a blank function returning 60! JSDoc: Source: core/Window.js looks like there is PR in to fix that very soon though! Implement Window.getActualFrameRate() to dynamically update monitorFramePeriod by thewhodidthis · Pull Request #268 · psychopy/psychojs · GitHub :raised_hands:

For your specific points:

  1. timing will still be influenced by dropped frames if stimuli are presented in seconds (but I wanted to highlight because often timing by frames is used when timing is very specific - so that could be relevant to yourself!).

for all your other point yeah that sounds reasonable!

Becca

This sounds great! Actually, I had some troubles with running it locally because there are some js specific parts directly written in javascript.

  1. timing will still be influenced by dropped frames if stimuli are presented in seconds (but I wanted to highlight because often timing by frames is used when timing is very specific - so that could be relevant to yourself!).

yes, in this case, I would like to have as much control as possible online. If I work with frames, I should be confident that the stimulus lasts for at least the specified frames. If I set a stimulus that start at 0 and then lasts for 100ms and then I want a second stimulus start from 100ms and lasts for 100ms I will not sure about what is going to happen.
In frames I thought that a stimulus that lasts for 3 frames is followed by another stimulus that at least start from the first available frame after the first.