Nonslip timing issue: launchScan (MRI) timing lags at scanner, but not when testing on other machines

OS (e.g. Win10): Windows 10 (testing PC, scanner PC TBD)
PsychoPy version (e.g. 1.84.x): 2021.2.3
Standard Standalone? (y/n) : yes
What are you trying to achieve?: non-slip timing, consistent trial syncing with scanner signals (in our case, a keypress of “5”)

Hi all, any help you can provide is much appreciated!

We have a working Builder script (with a few code components inserted) that we want to use for an fMRI experiment. We have the launchScan function set to sync with the scanner’s trigger pulse (a keypress of “5”) at the beginning of the trials. When I test this on my office PC, the nonslip timing works perfectly. The image stimulus that is meant to be triggered by the scanner pulse appears around .25s after the pulse and then stays consistent within a range of about .15 to .33s after the scanner pulse throughout the trials.

Yesterday, we ran our first participant at the MRI scanner. The PC there is older but I don’t have its information handy. I will check on it and post an update later this afternoon in case this is important. We noticed as the experiment went on that the final item on each trial (a single word) was staying on the screen for longer than intended (it is meant to appear for 1s). The length of each run was also noticeably longer than expected. This morning I took a look at the trial timing in the data files. I have attached the data files from our first participant’s first run here. The .log file shows that the first “5” keypress (scanner syncing signal) occurred at 644.725 and our first image stimulus (the beginning of the trial) appeared at 645.188. This is a lag of 0.46 which is longer than we found in prior tests but workable if it stayed consistent throughout the run. Unfortunately, the lag between a scanner pulse and the beginning of each subsequent trial increased by approximately 0.1s. By the 13th trial, the syncing was 1.88s off. The scanner pulses occur at 2s intervals, so at that point the syncing is back on track but then gets gradually offset again over the next trials. (I added columns FY, FZ, and GA in the .csv data file to highlight the trial start time, scanner pulse time for that trial, and the difference between those two times.)

I’m attaching a truncated version of our Builder script here. The images required to make it run are 2 to 4MB a piece so I haven’t included them. As you can see, the “Trials” and “variable_ISI” routines are green, indicating that they should run with non-slip timing. The only other item in the trial loop is “distractor_code1” which is a set of code components with no stimulus presentation. Given that it is blue, I’m wondering if that is creating the delay, even though the code doesn’t actually print anything to the screen?

To facilitate examination of those code components, I have pasted them here. Note that the last bit of code is the launchScan function, which has to be included in order to sync to the scanner. Is there any other way to incorporate it without breaking the nonslip timing? (If that is what is happening here.) All of these bits of code are in the “Begin Routine” tab:

new_dir = _thisDir + "/cmd/" + str(int(expInfo['participant'])) + "/study1.csv"
new_conds = pd.read_csv(new_dir, index_col = False)
isi_cond = pd.DataFrame(new_conds, columns = ['TrialNum', 'objectname', 'reps', 'Dist_type'])
if trials1.thisN == 0:
    first_target_image = isi_cond.objectname.iloc[trials1.thisN]
    target_image.setImage(first_target_image)
    if isi_cond.Dist_type.iloc[trials1.thisN] == 2:
       words = _thisDir + "/dist2.csv"
    else:
        words = _thisDir + "/dist1.csv" 

thisISI = str(isi_cond.reps.iloc[trials1.thisN])        
get = sample(range(70), int(thisISI))

if trials1.thisN == 0:
    vol = launchScan(win, MR_settings, globalClock=globalClock, mode='Scan', log=True)

SampleBadDataFromScanner.zip (496.9 KB)
fMRI_Study_List1_2_15_Help.psyexp (156.0 KB)
fMRI_Study_List1_2_15_Help_lastrun.py (70.0 KB)

Many many thanks if you can help us. I’m going to continue attempting to troubleshoot, including testing on the scanner PC this afternoon and will update if I learn anything new.
Best,
Rachel

An update: the computer where I am having the issue is running Windows 7 and PsychoPy 2021.2.3

I found Arboc’s response in this thread: Confusion about how to implement non-slip timing for trials with known end points - #8 by Arboc

while troubleshooting this afternoon and the idea of “tricking” PsychoPy into using non-slip timing led me to realize that even though the blue Routine block isn’t presenting any stimuli, it is a gap in the continuous non-slip timing of my loop. I figured out that the code components will show up as non-slip eligible (green) if I added a text component, then reset its time, and then deleted it again. When I tested that version of the script I still got some increasing delay (which shouldn’t happen with non-slip timing) but it was much improved.

My next test will be to just move the code components into the already-green routine rather than having (blue) routine that is all code. It didn’t occur to me before that the code component would affect the timing and I can easily put it in the main part of the trial instead.

I now have a version of my script in which all trial components show up green in builder, indicating that non-slip timing is being used. This script runs fine, with accurate launchScan syncing when run under most circumstances. It has substantial lag when the monitor is duplicated to the projector and the scanner is running.

After some troublehsooting, I think that the timing issue might be caused by the projector that displays the stimuli for the scanner. The script runs much better when I am only using a single display instead of duplicating the PC monitor to the projector.

Has anyone encountered this before? The projector is a Hitachi CP-SX635 “Multimedia LCD projector”.

To wrap up this thread: I learned that ANY blue routine within a loop, even if it only contains code, will prevent nonslip timing from working perfectly. If all of the routines within a loop are green, the script will stay synced to your launchScan trigger.

However, your stimuli may still experience timing delays and lag, just within the synced time limit. My script has the following time sequence as a loop:
picture stimulus, 2s
response scale and fixation, 2s
distractor word 1s
distractor word 1s

There are a variable number of distractor words on each trial (always in multiples of 2) but this is controlled in such a way that non-slip timing is still used (the routine is green). Within each separate PsychoPy script, there are 3 of these loops, one after the other. There are 4 separate PsychoPy scripts but each of them was created by saving the original and then modifying only the input csv file names.

The first script, while running the scanner and duplicating to the projector, has nearly perfect timing with maybe an extra 250ms on the final distractor word on each trial. This does not create a problem for the syncing. I haven’t calculated exactly what gets truncated, but earlier parts of the trial are likely shorter by undetectable amounts.

After the first script ends, loading the second script and running it produces similar behavior but the final distractor word very gradually gets longer and longer beyond its 1s intended run time. Eventually the 2s fixation and response screen starts to get noticeably shorter. This gets progressively worse throughout the 2nd, 3rd, and 4th scripts even though they are separate PsychoPy programs. By the end of the 4th script, the fixation and response screen does not appear at all. The image appears and then the distractor words appear, with the last word staying on the screen far longer than 1s.

After finishing the whole run, we opened the 1st PsychoPy program again and ran it. It still showed its original pattern: the timing was almost perfectly accurate on each trial. We concluded that there is something getting reset in the first version of the script but cannot determine what it is. It could be something in the script itself, it could be the 10 minute delay between the 4th run and retrying the 1st run (or something that happened on the PC running the program during that time).

Unfortunately we also concluded that we cannot use PsychoPy at the scanner. We spent months developing and testing our script only to find that it behaved differently when a projector is attached. We are now stuck because we can’t understand why our script timing is not working as programmed. Hopefully the information above will be useful for someone else in the future.