psychopy.org | Reference | Downloads | Github

Synchronized strobing dots over a movie

OS (e.g. Win10): Win 10
PsychoPy version (e.g. 1.84.x): 3.1.5
Standard Standalone? (y/n) If not then what?: y
What are you trying to achieve?:
Hello,

I am trying to make a flashing dots appear over a movie at 7.5Hz. Importantly I need the 100 dots to be synchronized such that they disappear and reappear at the same time. The dots also need to be in a new location when they reappear. This is to elicit and steady state visually evoked potential for EEG. A simplified example can be seen below.

What did you try to make it work?:
I’ve used the RDK stimulus in builder with 0 direction and a speed of 0.

What specifically went wrong when you tried that?:
I can get the flashing effect by making multiple RDK elements (see image below) but I would need to add about 38 dot stimuli because that would be equal to 7.5Hz over a 5 second movie. This would obviously be time consuming and may also slow down the presentation. I could eventually code something more efficient, but I don’t want to lose all the useful timing elements that come with the builder version. Does anyone have any advice for this problem?

Thank you so much,
Andrew

I think it would be simpler to do this with just one RDK stimulus. You can tell it in code to not autodraw, and instead draw it manually on just every 8th frame, giving you the 7.5 Hz rate you want (assuming you have a 60 Hz display).

Insert a code component from the “custom” component panel, and in its “begin routine” tab, put something like this:

dots.autoDraw = False # don't draw it on every frame

and in the “every frame” tab, something like this:

# draw only on every 8th frame:
if frameN % 8 == 0:
    dots.draw()

frameN is a counter that keeps track of the current frame number on this routine. The % modulus operator returns the remainder when dividing by 8. If the remainder is 0, then this frame number is an integer multiple of 8.

In this case, I guess you do want the dot stimulus to have parameters that allow the dots to move, so that you get the animation across strobes that you want.

It looks a lot better! I just have a couple more questions. Now the dots appear behind the movie no matter how I position the code or dots in builder. How do I make them drawn above the movie and fixation cross?

I’d also like the data output to give the experimental time in which the dots were drawn so I can double check they are appearing at a consistent rate. How would I go about implementing this?

I should probably mention that I had to change the dots duration to be zero (as can be seen in the screenshot) to get the flickering effect. If I didn’t do this the dots appeared above the movie, but were drawn on every frame.

I guess this is a clash with the order of Builder’s autoDraw queue, so we should work with that rather than fight it:

if frameN % 8 == 0:
    dots.autoDraw = True
else:
    dots.autoDraw = False

This worked! I put that code in the each frame box and deleted the dots.autoDraw = False from the begin routine box.

Thank you for your help and if you can think of a way to get the data output to indicate the time when the dots appeared on each 8th frame that would be great.

This is a little tricky, as you will need to store multiple times per trial. We can either store a list of times in one column of the data file, which is easy but hard to work with later, or store each time in its own column, which is easier to analyse but grows your data file quite a bit in terms of number of columns. Here is the list approach:

“Begin routine” tab:

dot_times = []

“Each frame”:

if frameN % 8 == 0:
    dots.autoDraw = True
    dot_times.append(t) # store the current time in the list
    thisExp.addData('dot_times', dot_times) # add the list to the data file
else:
    dots.autoDraw = False

The time stored here will be a variable number of milliseconds earlier than the time the stimulus is actually displayed. If you want the time to be stored exactly as per the time the next screen refresh occurs, you should look into the callOnFlip() function of the Window class:

https://www.psychopy.org/api/visual/window.html#psychopy.visual.Window.callOnFlip

1 Like