psychopy.org | Reference | Downloads | Github

Static stimuli presenting with slight flicker; potential frame rate issue?


#1

Hi everyone

To preface, OS is windows 8.1 / 10, running psychopy 1.83.04 and have built my study using coder.

I’m having trouble with what appears to be a slight flicker / frame rate issue.

To give some context, within a 1000 ms time period, I have a set of stimuli that should remain static for approximately 600 ms, and should then change orientation and remain static but at this different orientation for the remainder of time. I have achieved this by simply setting the stimuli to one orientation for approx. 42 frames (60 hz, 16.6 ms per frame; 672ms) and then alter the orientation for the remainder frames.

The problem is that from merely observing the stimuli it seems that there is a very subtle flicker, which indicates to me that it is likely that stimuli are orienting to all directions at random for a single frame or so (as this is the behaviour of the global form stimulus when it is simply set to draw with no frame conditionals). Regardless, the point isn’t so much as to what its doing specifically, but that they are making an additional movement within what appears to be a single frame, which creates a flicker. This is of course something I don’t want in my EEG experiment!

I can’t exactly tell where it is occurring (and I am not at all deft at trouble shooting it!)

Below is a sample of the script.

         if t < 60.0: #trial is 1 min long
             globForm.draw()
             frameN += 1
        if frameN >= 59: #refresh rate of 60hz; setting to 59 makes stimuli timing consistent and not losing 1-2 stimuli per trial
            frameN = 0
            print "frameN reset"

        if frameN in range(0,43,42): #hav altered these between 42/43 to attempt a fix if i was somehow missign a frame here, but no fix
            globForm.oris = numpy.random.rand(N) * 360 #what is the 360 for? the 360 makes the values integers divisible by 360 degrees rather than floats in the range of 0-1
            globForm.draw()

        if frameN in range(42,61,18): #have altered these between 18/19 frames to attempt a fix if i was somehow missing a frame here, again no fix
            globForm.oris = numpy.random.rand(N) * 360
            globForm.draw()

It could be a simple miscalculation on my part with regard to the framerate; but if it is then I’ve missed it. I don’t know whether this is an obvious issue that I’m missing or something deeper. But if anyone has any insight it would be massively appreciated. I’m in the midst of pilot testing currently so if I’m able to get this fixed prior to data collection that would be absolutely fantastic.

P.s. I am unsure if this is relevant, but on the off chance it is, i will clarify by saying that frameN is set to reset after 59, rather than 60, as there was a loss of 1-2 stimuli per trial (depending on if framerate is running optimally), which was fixed by moving this to 59. There was a loss of - on average - 16 ms between stimuli presentations. Reducing to 59 means it resets 1 frame earlier which covers the frame loss by giving the overall 1 min an additional 16 frameN’s. Furthermore when looking at the timing of the presentations in the output, it makes them much more consistently timed around the 707-714ms time period, which is much less variation than when frameN was set to 60.

Thanks so much in advance for any help!


#2

A bit hard to tell, as you don’t show where the win.flip() is, but with a single win.flip() it is impossible to get flicker within a frame. The drawing is done to an off-screen buffer, and at win.flip() then entire buffer is sent to be displayed simultaneously. There can’t be any incremental display of stimuli within a single screen update. In the code above, you are sometimes drawing the stimulus twice within a frame, but that won’t matter, as only the final draw counts. But the code below shows how you could rationalise things a bit.

I suspect the issue is that you are missing time-based checks (if t < 60.0:) with everything else being based on frame counting. Stick to the latter, as every now and then, the time will get out of sync with the screen update cycle, meaning you might get an extra frame drawn at some points, or one less than expected.

e.g.

frameN = 0
globForm.ori = numpy.random.rand(N) * 360 # initial orientation for first 600 ms

while frameN < 60:

    if frameN == 36: # 600 ms (frames 0 to 35) have elapsed 
        globForm.ori = numpy.random.rand(N) * 360 # orientation for remainder

    globForm.draw()
    win.flip()
    frameN += 1

#3

Hi Michael,

Firstly, thanks so much for the swift response and suggestion, and sorry for the delay in getting back.

The code I’ve built uses a trial handler where win.flip() is called on the conditional if continueroutine = true, i.e.

#-------Start Routine "pracTrial"-------
continueRoutine = True
while continueRoutine:
    
    if t < 60.0:
         #experiment stuff here

    if continueRoutine: 
        win.flip()

Unfortunately I’ve tried playing around with what you’ve suggested and haven’t had any luck. But at the very least I can appreciate the point that flipping every frame is going to end up more likely causing a flicker issue than if I flipped once or twice only when was necessary; so I’m in the midst of troubleshooting it now with that in mind, and I will update the thread if I get a fix!

Cheers
Bmau


#4

I hope it works out. I’d emphasise however that it is usually a good idea to aim to flip on every frame. That way you keep up with the hardware timing cycle of the display. Rather, what needs to be rationalised is the updating of stimulus attributes. i.e. aim to keep drawing stimuli to the screen on every screen refresh, even if their attributes haven’t changed. That also makes it more likely that you’ll pick up errors in your code (e.g. changing the stimulus more often than you intend to), which is only visible when a stimulus is both drawn and flipped.