Trigger delays are highly variable and imprecise

OS : win10
PsychoPy version (e.g. 2024.2.4 Py 3.8):
Standard Standalone Installation? y
Do you want it to also run online? n
What are you trying to achieve?: I have developped a task with different steps (presentation of stimulus, learning phase and retrieval) and am now testing trigger delays and noticing that delays are not constant. I am wondering if the way in which I am sending triggers is the correct one.

In this “stimulus presentation” task, for example, I have a loop and, at each trial, I show a figure (abstract_image) for 2.5 sec in a specific position of a memory_arena; then the abstract_image disappears and the memory_arena is showed empty for 1 more second. I want to send a trigger when the abstract_image appears and when it disappears. So at the beginning, I used these commands in the “begin routine” and “end routine” of the code component in the trial routine.

“win.callOnFlip(pulse, IMG_ONSET_CODE)“

“win.callOnFlip(pulse, IMG_OFFSET_CODE)“

As this did not work, I am now using this in the “each frame” of the code component in the trial routine:

“if (abstract_image.status == pc.STARTED) and (not _img_onset_sent):
win.callOnFlip(pulse, IMG_ONSET_CODE)
_img_onset_sent = True”

and this in the “end routine” of the code component of the same routine:

“if _img_onset_sent and not _img_offset_sent:
win.callOnFlip(pulse, IMG_OFFSET_CODE)
_img_offset_sent = True”

The IMG_ONSET_CODE and the IMG_OFFSET_CODE should be 2.5 seconds apart so 2500 samples when collecting at 1000 Hz. However, this is the list of samples between each pair of triggers (2384, 2318, 2368, 2401, 2402, 2418, 2368, 2435, 2334, 2367, 2435, 2402, 2434, 2434, 2451)……Am I sending triggers in the right way or is there a better one?

This is the screenshot of the “trial” routine and the code is publicly available here (1_stim_presentation · master · Isotta Rigoni / test_visual_memory · GitLab):

I think this is interference from trying to load an image at the same time - try loading the image in a Static Component :static: prior to its onset

I am not sure what you mean by “static component”… I have moved up the code component where I send the triggers, hoping that it introduces less delay.

However, as I am loading each image at each trial iteration, I am not sure how can I load the image before the trial… would you have a solution for this? Should I introduce an extra routine before the routine “trial” to just load the image and then display it in the routine “trial”? Would that improve the situation?

I have another related question on how I am sending triggers… at the moment I using this function pulse, which is defined like this:

PULSE_MS = 20 # ms

def pulse(code, dur_ms=PULSE_MS):
port.setData(int(code))
if dur_ms and dur_ms > 0:
core.wait(dur_ms / 1000.0)
port.setData(0)

is this ok or there are better ways of defining a trigger function?

Thank you so much for this help

A static component is also known as an ISI. Once you have one then there is an option to load media during the ISI instead of "every repeat” or “constant”.

Hello, I tried to do it but I am not 100% this is actually the right way of doing it. Here is a snapshot of my trial, where I load the abstract image during the ISI:

this seems indeed to give better results (here are the delays over 4 trials, that should be 2500 samples apart: [2463; 2499; 2497; 2500; 2497; 2500; 2499; 2500; 2496; 2497; 2496; 2498; 2495; 2496; 2499; 2495; 2496; 2499; 2495; 2496; 2499; 2495; 2496; 2496; 2496; 2496; 2497; 2495; 2499; 2497; 2499; 2497; 2499; 2497; 2499; 2498; 2497; 2499; 2497; 2499; 2497; 2499; 2498; 2497; 2499; 2497; 2479; 2483; 2483; 2499; 2497; 2499; 2499; 2497; 2500; 2500; 2500; 2500; 2511; 2511]), so it has definitely improved from before…

However, could you confirm me if this is the right way of using it or if there is a better and more efficient way of loading images at the beginning of the trial to avoid delays? Here’s the code to the this new version: 1_stim_presentation_v2 · master · Isotta Rigoni / test_visual_memory · GitLab

thanks a lot in advance!!

Best wishes,

Isotta

What you have looks correct, though you could try putting the ISI in “trial_memory_arena” except that it would need to appear before trial in the loop.

You’ll notice that the first trial is generally the worst.

Hello @IRIO

Do you know that there is parallel_port component in PsychoPy?. You could bind its onset to the presentation of your image.

Best wishes Jens