Timing error for individual words displayed using loop

We have created a script for our fMRI experiment where one part of it involves showing participants a story and each word of the story is displayed on the screen for 500ms. To create the words and display each of them on the screen I have written this code:

def display_story():
    """Display stories to participants."""

    with open(story_path, mode='r', encoding='utf-8') as file:
        story = file.read()
        words = story.split()

    # Prepare stimuli from the story words
    word_list = [{'duration': 0.5, 'stimulus': word} for word in words]

    # Display each word for 500ms
    for word in word_list:
        word_to_screen = psychopy.visual.TextStim(win, pos=[0, 0.01], text=word["stimulus"])
        word_to_screen.draw()

        # Show the text on the window
        win.flip()
        core.wait(word["duration"])

The problem is that, for a story with 480 words, the total time should be exactly 4 minutes (480 x 0.5s == 240s, 240s/60s == 4m) but when timing the code using python’s time function as well as a stopwatch the loop takes 4m 5s. I assume this is just an accumulation of the time it takes to run necessary code before each word is displayed but I’m wondering if there is a way to account for this extra run time in order to make the total time 4 minutes exactly.

Right now we have just reduced the duration to 0.49s instead of 0.5s but I am hoping there is a better way because this is not exact.

I am assuming you need the total time to be exactly 4 minutes due to matching timing with the fMRI data output?

If this is the case, I would recommend you review this Communicating with fMRI — PsychoPy v2024.2.4 and specifically the section of non-slip timing: Non-slip timing for imaging — PsychoPy v2024.2.4

One method to fix this then, rather than having each trial last for exactly 0.5s, you would have each trial start and end at a specific time, relative to the global clock:
Example
Trial 1: 0.1 → 0.6
Trial 2: 0.7 → 1.2

Trial 45: 26.4 ->27

Hopefully this helps!

Issac

Hello

Another issue to consider is the refresh rate of your monitor. If it is a 60 Hz monitor, you will not see the word for 500 ms because the monitor can only refresh its screen every approximately 16.667 ms (500 / 16.667 ms = 29.99 ms) You may want to use frames instead of times to control the presentation duration of your stimuli.

Another option is to separate time-critical from non-time-critical code elements. Reading the file from disk and splitting the story into words could be done before presenting the words.

Best wishes Jens