psychopy.org | Reference | Downloads | Github

How to simultaneously run two routines?


#1

Hi psychopy community,

I recently switched to Psychopy and using the Builder I’m trying to synchronize two routines. Specifically, I’d like to present an audio file lasting for about 90 secs, and while the audio is being presented I’d also like randomly sampled words to appear on the screen in specific intervals (say every 5 secs, for 5 secs). I also want a response to be collected for each word presented. I realize that an arduous way would be to create one simple routine, with one audio compoenent and 27 individual text components. However, I was wondering whether there would be a more efficient way of doing this. As I said I could imagine creating two routines (one for the audio presentation, one for the text) which are then somehow set to run simultaneously. The second routine would have a loop repeating it 27 times which would be connected to the xlsx file with the word conditions. I believe there is a way of inserting some script at the begining of the second routine to tell it to start simultaneously with (or embed it in) the first routine, but I’m afraid my very basic python knowledge does not go as far as this…

Any help would be much appreciated.


#2

#3

Hi Michael,

Thanks very much for your help. Nevertheless, the code you proposed makes the sound playing contigent on the word-presentation, whereas I would like it to be the other way round. I do not want the sound to start when the word loop is in iteration N= 1 but rather I want the loop to start once the sound starts playing. It might look similar but for this speceific pradimg it is not for, I will try to synchronize the word stimuli to certain phases of the audio. I had a look at the Builder-generate Python script and see that each routine sets (and resets) its own clock. I was wonderng whether it would be possible with a code component to interfere with this. For example to set the wordroutine.clock = audioroutine.clock or something along these lines. Or any other suggestion that might go in this direciton? Many thanks again!


#4

The example above is just to show the general technique required. ie only one routine can be operating at a time in Builder, and all stimuli in a routine have to be complete before the routine itself can terminate. Therefore if you want a sound stimulus to continue playing while other stimuli are displayed in a routine that runs in a loop, that sound needs to be created in code. That way, Builder doesn’t know about the sound stimulus, so it won’t prevent the text stimulus routine completing and going on to the next iteration of the loop.

Because there wouldn’t be an audio routine as such, you would be responsible for creating your own clock to keep track of when the audio started. e.g. something like this immediately after starting the sound:

audio_clock = core.Clock()

For each word trial, you would need to have a conditions file that lists the word itself, its start time in the song, and a duration. In the text component, set the start time to be a “condition”, and use an expression like:

audio_clock.getTime() >= your_time_variable

and a duration specified as required.

If the words don’t need to be synchronised to exact moments in the audio, but just presented every 5 s or so (as in your original post), then you don’t need to have a clock at all: just put in fixed start and stop times for your text stimulus.


#5

Hi Michael,

Thanks a million for this explanation. My aim is indeed to have the words appear at exact moments of the audio. For example, I want word1 to appear at s 2 of the audio file for a duration of 2 s; then I want word2 to appear at s 8 of the audio, again for a duration of 2 s. All my words should have a duration of 2 s. I only got to test your suggestion now and unfortunately it does not work.

In my conditions file I have included a $starting parameter specifying at which point each word should start. As suggested, the value of this parameter for word1 is 2 and for word2 8 etc.

First of all, I switched the >= part of the your_time_variable >= audio_clock.get command to <=, as the former seemed to start each trial immediately after the previous trial was over (so basically presenting each word every two seconds). The modified command seems to take better into account the audio_clock value, but the problem I’m having now is that the command seems to be interpreted locally and not globally as is my aim. Now, word1 does appear at s 2 of the audio file, but word2 appears at s 12 of the audio file (so 8+2 (time of the presentation for word1)+2(duration of the presentation of word1).

FYI I added the audio_clock = core.Clock() command in the Begin Routine tab of my code component, just after the command telling the audio file to start right at N= 0 of the word loop as follows.

if trial.thisN == 0:     
    background_sound.play()

audio_clock = core.Clock()

Any ideas on how I could get the text trials take into account the timing of the audio file globally rather than locally? I know I could try adjusting my $starting variable, but I’was wondering whether there is a more computationally elegant way of doing this.

Cheers,
Myrto


#6

White space is important in Python so you need to do this so we can be sure to read your code properly:

I’ve edited your post above, and if that code was pasted in correctly, then an issue is that you are re-setting the clock on the beginning of every iteration, rather than just at the start of the first iteration (when the sound file itself is played). i.e. with correct indentation, those two operations would be grouped together so that they are both conditional on this being the first iteration, like this:

# only at the beginning of the loop, both start a sound playing and
# start a clock to keep track of its progress:
if trial.thisN == 0:     
    background_sound.play()
    audio_clock = core.Clock()