General question about psychopy and fMRI

Hi All,

I’m new to Psychopy, so please go easy. I’m trying to use it to run a simple fMRI experiment, and am having some trouble (probably conceptually) about how to use scanner triggers to control experimental flow (i.e. timing).

I would normally have my experiment wait for a certain number of triggers to have been received before proceeding to show a stimulus, followed by rest, then a rating period, before returning to the fixation cross (default position) waiting for the a number of triggers to have been received before showing the next picture, and so on…

In pseudo-code this looks like (TR = 3 sec), sorry can’t get tabs to work, so formatting is horrible

triggers = 3
triggerCount = 0

[main loop]
while expt is running:
display fixation cross
flip display

get incoming keypresses (looking for '5’s)
if key is ‘5’:
add one to triggerCount

if triggerCount > triggers: # start stimulation section

[update triggers to set ITI]
triggers += 10

[present stimulus]
show picture
flip display
core.wait (5.0)

[present fixation]
show fixation
flip display
core.wait (8.0)

[present rating scale (configured to display for 8.0 seconds, no accept button allowed)]
myRatingScale

[end stimulation section]

[end of main loop]

My problem is that I would like the 2nd period of stimulation to occur when more than 13 triggers have been received, but because I’m stuck in my stimulation section, where there are lots of core.waits, Psychopy is “missing” (i.e. not counting) the '5’s that keep on rolling in.

I.e. the first stimulus should be presented after 9 seconds (triggerCount > 3), and then the second should be presented after 39 seconds (triggerCount > 13), the next after 69 seconds (triggerCount>23), and so on (ITI is 30seconds).

What are the “tricks” for achieving this?

Best wishes,

Jon

p.s. any hints on how to get tab characters when using this webpage would be much appreciated.

1 Like

Hi,

event.getKeys() returns a list of keys in the buffer, which will continue to be filled even during core.wait(), so in theory that shouldn’t be an issue.

When calling getKeys you will need to check the entire list to determine how many 5’s there are in the whole thing before updating your triggerCount. A simple way of doing that could be:

triggerCount += event.getKeys().count('5')

I don’t know much about fMRI so I’m guessing you’re controlling the timing of experiment flow with an external clock?

Basically, avoid ever using core.wait() You are ceding a lot of control for the benefit of not writing some code.

Look through some of the examples under the Coder Demo menu and see how they are structured to continually draw to the screen, even during uninteresting periods like displaying a static image. This allows you to keep actively checking for key presses and so on. e.g. instead of this:

picture.draw()
win.flip()
core.wait(5.0)

Do something like this, actively refreshing the screen and checking for a keypress on every screen refresh:

while some_clock.getTime() <= 5.0:
    # refresh the stimuli (or set to autoDraw):
    picture.draw()
    
    # check for MRI trigger:
    keys = event.getKeys()
    if '5' in keys:
        trigger_counter += 1
    
    # refresh the screen
    win.flip()

This gives you a lot of flexibility. For example, you could define the stimulus durations in terms of numbers of triggers received rather than in time durations, e.g.

while trigger_counter < 5: # i.e. for a 15 s period
    # continue doing some stuff, including updating the trigger counter,
    
    # and then refresh the screen:
    win.flip()
1 Like

To get proper formatting of code indents, use three back-ticks ` on a line by themselves, then the code, then three more back ticks

1 Like

Thank you for all the really helpful responses - I can revert back to counting triggers - which makes me very happy!