What's the best way to alternate what is displayed on a screen for a certain amount of time?

I have been tasked with creating a study where I need to alternate between three different screens for each 60 second trial.

The sequence goes: image 1 for 560ms, grey screen for 80ms, image 2 for 560ms and do this for either 60 seconds or until the participant presses a key to indicate that they have noticed a difference between the two images.

Right now I have the following function to decide which screen to display:

isRunning = true;
image = 1;
startTime = Screen('Flip',mainWin);

while isRunning

    thisTime = Screen('Flip',mainWin);
    image = timeToChangeImage(thisTime, startTime);

    if image == 1
        display image 1
    elseif image == 2
        display image 2
    elseif image ==3 
        display image 3

    if (thisTime - startTime) > 60
        isRunning = false; 
    end

     if (keyPressed)
         isRunning = false; 
     end

end



function image = timeToChangeImage(time, startTime)

    picOneIntervals = {[0, 560], [1200, 1760], [2400, 2960], [3600, 4160], [4800, 5360]};
    greyIntervals   = {[560, 640], [1760, 1840], [2960, 3040], [4160, 4240], [5360, 5440]};
    picTwoIntervals = {[640, 1200], [1840, 2400], [3040, 3600], [4240, 4800], [5440, 6000]};
    current time = (time - startTime) * 1000;

    for interval = picOneIntervals
        if current time >= interval{1}(1) && current time <= interval{1}(2)
            image= 1;
        end
    end

    for interval = greyIntervals
        if current time >= interval{1}(1) && current time <= interval{1}(2)
            image= 2;
        end
    end

    for interval = picTwoIntervals
        if current time >= interval{1}(1) && current time <= interval{1}(2)
            image = 3;
        end
    end

end

This function has lists for the sub-intervals that each screen should be displayed within the trial. This is not a good solution though because I was first thinking that 6000ms was 60 seconds and this is obviously not the case so to use this solution for 60 seconds my lists for the intervals would all be 10 times longer.

So Iā€™m wondering what a better way to program the ā€œtimeToChangeImageā€ function would be. I need the function to tell the main while loop when to display each image. Or if there is a better way to program this within the while loop without using the function that would be good to know.

Thanks in advance for any help!

Something like this should do the trick

intervalDurations = [560 80 560];
totalDuration = 60000;
repetitions = ceil(totalDuration/sum(intervalDurations));
intervals = cumsum([0 repmat(intervalDurations,1,repetitions)]);
t=50000
[~,i]=histc(t,intervals)
whichInterval = rem(i,length(intervalDurations));
if whichInterval==0
whichInterval = length(intervalDurations);
end
whichInterval

By the way, What refresh rate does your screen run at? Is it capable of displaying 80ms and 560 ms intervals?

Hey thanks for the reply!

I am a little bit unsure of the purpose of the lines from t = 50000 and onwards. Would you mind explaining what that is for please? ā€œwhichIntervalā€ is always 3 is it not? I am not sure what Iā€™m missing about it.

The refresh rate is 60hz, I believe that means 16.66ms per frame so 4.8 frames for 80ms and 33.6 frames for 560ms. I was thinking I might have to use the Screen(ā€˜Flipā€™) function with the accurate timing parameters here. Does that sound correct?

Nevermind about the first part of my last comment. I see now that ā€œtā€ will vary depending on the current time.

Hi James,

Yeah right, sorry, should have commented a bit. t indeed is your current time (your input to the function), the rest of the code you can use as is.

You canā€™t display a frames for 4.8 refresh cycles, only for an integer number of refresh cycles (unless you have a VRR capable setup on Linux). So your durations need to be multiples of 16.66 ms.

Cheers,
Dee

1 Like