Most efficient way to set the position and orientation of stimuli randomly on every trial

OS (e.g. Win10): win10
PsychoPy version (e.g. 1.84.x): v2020.2.5
**Standard Standalone? (y/n): Y
I am building an experiment where participants are presented with pairs of colored triangles during lots of trials. (example of a screenshot attached)

Across trials, the triangles change their color, their position on the screen, and their orientation (up/down). The colors for each trial are determined with an xlsx conditions file.
I would like the other two things to be set randomly on every trial: a) the positions of each colored triangle (e.g. whether the green triangle appears left or right), and b) Which of the two triangles is oriented up vs. down.
I managed to do that randomization by including a code component prior to the trial loop. So that, before each trial, such random values (position and orientation) are computed, but the problem is that doing such calculations before each trial results in a delayed presentation of the triangles, and my ITI seems to be longer than it actually should be (1 second).
I am looking for an alternative way to do this randomization and I have two options in mind:

  1. Calculate those random values for each trial myself using “something” (manually, software, whatever) and add the resulting random values to the xlsx conditions file. I do not like this option because that random assignment will be the same across participants and can result in some weird effect. Also, that would imply changing a lot my conditions file. I have just 8 conditions that are repeated 28 times. If I had to assign a value to each trial, the conditions file will have 224 conditions.
  2. Do the randomization with code (as I have it now) but find a way to do the calculations during the ITI (which is 1 second). I’ve seen that the orientation and position of stimuli can be “set during: ITI.ISI”. But I am not sure if that will work, or where in the loop I should put the code component in case I want to use that option.

Now, my trial loop has 3 routines:
a) the triangles screen (2 secs) (where participants have to respond) ,
b) feedback screen (3 secs), and
c) ISI (1 second).
As I mentioned, I have the code component placed before the trial-loop.
Does anybody know which is the best way to do it, or has another better idea? Any help would be appreciated!

Hi Paula,

Please could you show the current calculations that seem to be taking the time?

One way to hide a long calculation would be to start a 1 Frame routine and a timer and then have the following routine end when the timer from the first routine has reached the desired time…if the calculations can be performed in under 1 or 3 seconds depending on where you put it.

1 Like

Yes, of course!

The flow looks like this

codealone_phase1a routine: this contains the calculations to do before each trial. The routine has 3 elements:


randomarray= [1,2]; #create an array of two elements (1 and 2)
shuffle(randomarray) #shuffle those elements
if randomarray == [1,2]: #if the resulting array is [1,2]...
    posrel=[-0.5,0] # POSition of RELevant cue on the left
    posirrel=[0.5,0] # POSition of IRRELevant cue on the right
else: #if the resulting array is [2,1]
    posrel=[0.5,0] #relevant cue on the right
    posirrel=[-0.5,0] #relevant cue onthe left

thisExp.addData('posrel', posrel) #writes the position of relevant cue value in the output file
thisExp.addData('posirrel', posirrel) #same for the irrelevant cue.


randomarray2= [1,2]; #another random array
if randomarray2 == [1,2]: 
    orientrel=180 # ORIENTation of RELevant cue: down
    orientirrel=0 # ORIENTation of IRRELevant cue: up
    orientrel=0 # relevant cue oriented up
    orientirrel= 180 # irrelevant cue oriented down

thisExp.addData('orientrel', orientrel)
thisExp.addData('orientirrel', orientirrel)

Then, the SELECT_CONDITIONS_FILE CODE is aimed at alternating between two xlsx conditions files. On odd trials participants are presented the “AL” task, on even trials, they have to do the SEL task. Each task has 4 different conditions that specify different color combinations. The screen is equal for both task except for the letters that are displayed between the triangles. Participants must press different keys depending on the task and thus the correct answer is also different depending on the task.

al_indices=list(range(4)) #list the 4 conditions of the AL task
sel_indices=list(range(4))#same for SEL conditions

shuffle(al_indices) #Suffle the order in which the AL conditions will be presented
shuffle(sel_indices)#Same for SEL conditions

if Phase1a_block.thisN% 2 == 0: #on even trials
    conditions_file ='al_trials.xlsx' #use the conditions file of the AL trials
    selected_rows=al_indices[-1:] #take the first condition (as determined randomly on the begin exp tab)
    al_indices=al_indices[:-1] #remove it from further selections
else: #odd trials
        conditions_file ='sel_trials.xlsx' #use the conditions file of the SEL trials
        selected_rows=sel_indices[-1:] #take the first condition 
        sel_indices=sel_indices[:-1] # remove it from further selections
        if randomarray2==[1,2]: # If orientation_code resulted in the relevant cue oriented down
            corrAns='m' #correct answer is M (participants in the sel task have to report the orientation of the triangle pressing M when oriented down and K when oriented up)

Code restart: When the 8 trials (4 from the AL task and 4 from the SEL task) have been presented, this code component after the trial loop allows repetition of the conditions as many times as specified in the outer loop.



You seem to keep recreating arrays.

How about:

Begin Experiment


Begin Routine



if orientrel==180:

Why do you need al_indices=list(range(4)) and sel_indices=list(range(4)) in Begin Routine if you already have it in Begin Experiment?

If you want to shuffle instead then just put randomarray=[1,2] in Begin Experiment and then shuffle if (without recreating) before each choice. Then test if randomarray[0]==1 instead of equating the whole array.


can be replaced with

1 Like

Hi @wakecarter,

Thanks for your time with this.

I have used the code you suggested about the position and orientation. It works (both things are set randomly) but the delay is still there.

I think I need this at the end of the 8 trial-block because, in each trial, I am eliminating one of the indices with this line of code:


So that after the 8-trial block the list of al_indices and sel_indices is empty.

Also… I have changed this


But after the change the experiment does not run. I get this error

File “C:\Program Files\PsychoPy3\lib\site-packages\psychopy\data\”, line 438, in importConditions
elif len(selection) > 0:
TypeError: object of type ‘int’ has no len()

Which refers to this part of the code

I am starting to doubt that the problem is the number of calculations, but I do not know what else can generate the problem.

How is selection created?

1 Like

Do you mean selection of the different conditions?

Sorry I thought that was your code. Was that the whole error message?

1 Like

Sorry, I did not make that clear.

This is the message that appears in the stdout section:

1.4160 WARNING We strongly recommend you activate the PTB sound engine in PsychoPy prefs as the preferred audio engine. Its timing is vastly superior. Your prefs are currently set to use [‘sounddevice’, ‘PTB’, ‘pyo’, ‘pygame’] (in that order).
Traceback (most recent call last):
File “C:\Users\Paula\xxx\xxx\xxx\”, line 2334, in
trialList=data.importConditions(conditions_file, selection=selected_rows),
File “C:\Program Files\PsychoPy3\lib\site-packages\psychopy\data\”, line 438, in importConditions
elif len(selection) > 0:
TypeError: object of type ‘int’ has no len()

Experiment ended.

I have also another warning because I have around 20 duplicated variable names. I know it is better to use a single routine when, but I do not know why it is better. Can that be the cause of the delay? In a previous experiment, I had different names for each variable, and worked well (though it was not exactly the same experiment)

This is the error:

105.9177 WARNING duplicate variable names: irrelevant_colorcode, trial_type, prompt_down, orientirrel, corrAns, allowed_keys, left_image, posrel, opacity_left, relevant_colorcode, color_set, posirrel, opacity_right, relevant_color, middle_image, prompt_middle, text_down, irrelevant_color, orientrel, prompt_up, text_middle, right_image, text_up

Please could you show the definition of your loops? Maybe you have blank nReps

The warning is probably a new feature to check that you know that you are reusing variable names. You shouldn’t have a variable name that matches an Excel column title but you can use the same variable name several times.

You can’t reuse object names. So, for example, is middle_image an image component or an image filename?

1 Like

The loops that display the instructions of the experiment had 0 repetitions to test the experiment faster. I put 1 repetition instead but the experiment crashes when the “trials section” is supposed to begin. The error message I get is exactly the same.

The number of repetitions of the trials section is this:

I do not have any other loop (before or after this section) with 0 repetitions. (I am afraid the size of the flow is too big to show it in a single image)

I DO have variable names that match an excel column title :frowning:

Middle_image is the title of one of the columns I am using in the instructions xlsx file, and contains cells with this type of content.

nReps=0 is fine. The issue is when it’s blank.

middle_image is in one of your Excel files. Where else does it appear (other than referring to that column)?

I actually meant looking inside a loop definition

1 Like

I use that column as a variable in an image component. This is how I am using it

Middle_image appears as a column title in several excel files that provide different instructions at different moments in the experiment.

Oh ok. This is how they look like:

Outer loop

middle loop

inner loop

Thanks for your help so far!

I’m puzzled why any code is required here at all. This is a textbook example of a design that can be expressed by having all levels of several factors fully crossed in a balanced way and then presented in random order. i.e. can’t your single, fixed Excel conditions file just contain one row for each possible combination of factor levels, and then set the loop dialog to present those in a random or full random order, with an nReps value > 1 if necessary?

Using a combination of auto-fill and copy and paste, you can create such a balanced design in an Excel file in about two minutes. All PsychoPy would have to do is (automatically) handle the randomisation and repetition, via the loop dialog settings.


Hi @Michael and @wakecarter,

That seems to be the best way. I wanted to randomize those variables (instead of counterbalancing them) because I did a public pre-registration of the experiment and I specified that those variables would be set randomly. But changing that from the pre-registration to the potential paper is actually not that a big problem.

Thanks for your help and time :slight_smile:
I’ve learned useful things trying to solve this issue.


Sorry, I didn’t mean to squash your intended design. The word ‘random’ is very overloaded in experimental design - I interpreted it here as primarily about a random order of presentation and just implicitly thought that balancing would have been desired. If true random sampling of parameters is desired, then yes, a coding approach is the right way, at the cost of slight unbalancing, depending on the number of trials.

Oh! I see what you understood.

The orientation and position of the triangles are not important in the experiment, so we do not need strong control over them.

Anyways… It seems that the delay I am getting when using the code is going to give me a headache, and counterbalancing those variables does not affect my number of trials or any other important thing (I think), so I’ll try and use that approach.

Thanks again!