Is there a simple builder example to wait for an fMRI trigger and create a timing file

Hello,

We are in need of some code that we can learn from that waits for an fMRI trigger, presents some text on the screen and produces a timing file with the amount of time from the fMRI trigger to each word presentation. Is this possible to do? I know there is the fMRI launch_scan but we would request something simpler to model our own code after.

Thank you,
Tom

3 Likes

Yes it’s possible but you haven’t specified what your MRI trigger is. Many just emulate a keypress at the beginning of the scan and/or each TR, and so there is nothing technical required. Others use serial ports and so on, which require more work.

We have the simpler keypress trigger at the beginning of each TR. IS it possible to produce the timing file with that keypress trigger and then the subsequent stimuli?

Thank you,
Tom

Sure (although it is probably best to just save the relevant timing in the main data file than produce something separate). This is very straightforward to do but you need to describe your actual experiment structure and task in order for us to suggest where you would insert the relevant code snippets.

Thanks again. We first wait for the start fmrI trigger (from a button box). Then we show a list of gibberish words very quickly and randomly show a sensible word. This is done in 2 blocks with 2 types of sensible words - positive and negative

OK. So you would structure things so that you have an initial routine set to last indefinitely, with a keyboard component set to end the routine when it receives the keypress from the MRI.

You then proceed on to the loop surrounding your experimental trial. Insert a code component in that routine and put something like this in the Each frame tab:

if your_loop_name.thisN == 0 and frameN == 0: # start of the loop
    loop_start_time = globalClock.getTime()
elif frameN == 1: # the zeroth frame has just been drawn
    stimulus_start_time = globalClock.getTime() - loop_start_time
    # store the data:
    thisExp.addData('stimulus_start_time', stimulus_start_time)

This should show that the first stimulus appears roughly 16 ms after the keypress (for a 60 Hz display). Subsequent ones will appear at some multiple of your intertrial interval after that.

What is a “frame tab” that you mention in your reply?

That was described above:

Did you insert a code component?

I see the timings in the data .csv. Is the time since the scanner trigger negligible or should I add the line:

loop_start_time = globalClock.getTime()

In the first screen that waits for the scanner trigger.

and then add the elif part in the loop with the words?

I ask this because there seems to be a long time between waiting for the scanner trigger and loading our long word list in the next routine of the workflow. So I would like to quantify this delay.

Sure. You could just put this line in the End routine tab of the routine that waits for the first MRI trigger:

trigger_time = globalClock.getTime()

Amend the other code in the next frame so that you can quantify any delay between the trigger being received and the loop starting:

if your_loop_name.thisN == 0 and frameN == 0: # start of the loop
    loop_start_time = globalClock.getTime() - trigger_time
elif frameN == 1: # the zeroth frame has just been drawn
    stimulus_start_time = globalClock.getTime() - trigger_time
    # store the data:
    thisExp.addData('stimulus_start_time', stimulus_start_time)

That seems to be working really nicely. Thank you for your help. Can you provide some more intuition as to why the second block of code goes in the “Each Frame” tab and not at the “Begin Routine” tab? What is a frame and does frameN ==1 (in the elif) coincide with the drawing of the text word we present each iteration of the loop?

Thank you,
Tom

You really do need to know this to make full use of PsychoPy. You display is updated at a constant rate (say 60 Hz). Code in this tab runs once on every such screen refresh. This allows you to do things like real-time animation. It also allows you to do things like send a trigger or log a time at a precise point (e.g. on just the first frame on which a stimulus is displayed).

The code in the “Each frame” tab runs before the next update of the screen. So when frameN == 0, when the code is running, what is on screen is still actually the last image from the previous routine. That is why we have this line:

elif frameN == 1: # the zeroth frame has just been drawn

as the code is running just immediately after the first (i.e. zeroth) frame of the current routine has been displayed to the screen. If we ran this code when frameN == 0, the code could be executing up to 16.7 ms before the frame ) actually appears on screen.

Thanks for the great explanations and all the advice. May I ask if there are any recommended tutorials or documentation that will get to this level of frames and even the use of different tabs in the code block? I took the tutorials on the site and even found some others online, but none to this level of depth. Any recommendations would be appreciated.

This level of detail has mainly been covered in workshops but not everyone can get to those, so @jon and I are working on a Builder textbook to address this need, which will come out mid-2018:

https://us.sagepub.com/en-us/nam/building-experiments-in-psychopy/book253480

Otherwise, some learning resources are linked to from here:
http://www.psychopy.org/resources/resources.html

And information specifically on code component usage is here:

http://www.psychopy.org/builder/components/code.html

Is there a way to save timings of the builder components relative to a custom clock? The custom clock being the one that starts when the trigger arrives?