Running psychopy and a DLP projector at 180Hz. True 180Hz?

I am currently working with a Texas intruments lightcrafter evaluation module and I would like to get the projector and psycopy to display my stimulus at 180hz. I have enabled the FramePacker functuion and if I run scripts with psychopy’s internal frame counter enabled I do get a readout of about 180 fps. Regarding the projector itself, I enabled it to run in monocrome mode with a grayscale depth of 7bits, which gives it an output of 180hz. I varified if the the projector is really displaying psychopy stimuli at 180hz, by running a script that displays a simple gray bar with an opacity of 0.8 and then measured the refresh rate with a photodiode. This is the reading from the photodiode:

The lenght of a single frame appears to be 5.55ms which corresponds to a refresh rate of 180hz.

I also tried this script, which makes a flickering rectangle, which I got from another post:

mywin = visual.Window([912, 1140], 
                      fullscr=True,
                      monitor="DLP",
                      units="cm",
                      screen=2,
                      useFBO= True)
framePacker = ProjectorFramePacker(mywin)

photodiode = visual.Rect(win=mywin,
                         width=10,
                         height=10,
                         pos=[0, 0],
                         lineColor=[1, 1, 1],
                         fillColor = [1, 1, 1])

while True:
    photodiode.contrast *= -1
    photodiode.draw()
    mywin.flip()

And got this output, it flickers at 180hz it seems.

The last thing I did was to check how many frames it dropped during use. I plotted the graph and got quite the surprise:

From the graph it looks as if it draws one frame really slowly (frame interval = 15ms) and two really quickly (frame interval is less than 2ms).

My question is if I evaluted this correctly, it seems to be running at 180hz but I can’t be sure. I really don’t get the frame inteval plot, why is it doing that, is it normal?

Also is it possible to somehow “trick” the projector to display double the amount of frames, thus raising the frequency to 360hz?

How did you get the frame interval plot? Is that directly from the demos? Also, can you tell us what happens with waitBlanking=True and waitBlanking=False?

Thank you for replying Jon, I would first like to congratulate you on making an excellent piece of software. The interval plot was generated just by using plt.plot(win.frameIntervals), taken from an example in the documentation. Adding the waitBlanking = True argument to the win class resulted in a slight change:

On the left graph waitBlanking is set to True and on the right waitBlanking is set to False. A slight offset in the rendering time of the second and third frame is visible on the second graph.

I’ve just had a look at the code and my guess is that this is to do with the framepacking code having a variable flipThisFrame but I’m not sure when that gets set to False and for what purpose. (Is it something like the fact that sequential frames are packed into different color channels, so PsychoPy should be updating the contents of the framebuffer less often than the projector does?). We might need Jay Borseth, who wrote that code, to comment. I don’t have one of these projectors to test on myself.

I think ultimately, though, the answer is that the frames are being rendered correctly becuase the diodie tells you that, and it’s the internal timing of those frames by PsychoPy that’s in error due to some technical aspect to do with how the projector updates.

From my understanding of the way the timing code was working when I was trying to understand this issue, this is the expected behavior with the way framepacking is coded.

Psychopy is able to generate your 3 frames that get packed into the single frame very quickly. For the last 2 frames, it doesn’t have to wait for the waitBlank period to end to start generating next one, since they get packed right away. The 1st frame in the framepack has to wait until the projector is ready to receive the next frame, which is only once every ~16 ms, so that’s what you’re seeing. Each frame clearly gets generated very quickly, but only one in three has to actually wait out the remainder of the waitBlank period.

Hope that clears out some stuff. Also, if you’re interested, I wrote a python API for the LCR 4500, mostly for setting up pattern sequences. You can find it our labs Github: Sivyerlab

1 Like