psychopy.org | Reference | Downloads | Github

Execute code at a time offset in a loop in Builder

PsychoPy Builder components all have start and stop parameters to
control when stimuli are displayed, in particular this allows offsetting
the start of display.

I need to send a software event trigger at successive offset intervals from the start of the loop (whilst a video is playing).
This would be easy if it was a hardware trigger (eg using the parallel i/o component) but how can I easily do the same for a software trigger (to a separate application)?

I could use a code component and add code to run on every frame and monitor the time or count the number of frames but this is a pretty ugly solution.

It sounds like the sort of totally-custom use-case that absolutely needs a code component, but I don’t imagine it would be a very ugly one. For example, if you need something every 30 frames (0.5s) you could do this “on every frame”:

if frameN%30 == 0:
    win.callOnFlip(myParallalePort.setData, newValue)

Could you edit your post to indicate exactly what pattern of trigger timings you need?

A code component, “run every frame” with

if not frameN % 120:  # every 120 frames = 2 seconds on 60 Hz monitor
    # send software trigger here

looks OK? The % is a modulus operator in python. It’s handy for this kind of interval-detection on an incrementing integer.

Thanks both. Thought I had another way executing $() code in teh text field of a text component however that is executed at the start of the repeat rather at the component’s ‘start’ time, so I think I’ll have to make do with the modulus approach.
(though a code component that permitted a delayed offset/execution time would be nice :slight_smile: )

You don’t have to use modulus maths to make this work - that’s just a convenient way to know that the code gets run at a regular period.

You could also have:

#start of Routine
markSent = False

#each frame
if (someConditionHere) and not markSent:
    myParallelPort.setData(marker)
    markSent = True

Don’t worry that the if-statement is being run every frame - with regular components (like your text stimulus) that is being done anyway. The code above is essentially repeating the logic of standard components, except they have to track multiple ‘status’ options rather than just sent/notsent.