psychopy.org | Reference | Downloads | Github

Presenting images in nested loops and in multiple blocks

Mac OS X 10.9.5
PsychoPy version 1.80.03
Standard Standalone

Dear PsychoPy users,

I would like to check whether I am on the right track in building up the experiment. My design consists of presenting some pictures and then presenting a scenario and then answering two questions. There are 10 blocks in total. The same questions will be asked after each scenario but the presented scenario and the sets of pictures will be different in each block.
At first I started building up the experiment by having a loop to present the pictures, followed by the scenario routine and the questions routine but then I realised doing this 10 times will make the flow too long and crowded so I thought there should be an easier way and I came up with a solution but I want to make sure whether I am on the right track.
My plan is to have a pictures loop and a scenarios loop and 2 question routines which are nested by outer loop to select blocks. The part I am having difficulty is the pictures part. I have 10 different condition files with the image paths for the 10 different blocks but I don’t know where to locate each condition file.
In the attached flow, scenarioText loop will consist of the texts of the 10 scenarios and selectScenario loop will have a condition file to select 1 among 10 scenarios. SelectBlock loop will have a condition file to choose 1 among 10 blocks.

I hope I was clear in explaining. Many thanks for your help,
Ahu

Hi Ahu,

One way would be to have a code component that stores the names of the excel files in a list:

#Start of Experiment
condList = ['file1.xlsx', 'file2.xlsx','file3.xlsx']

You would then iterate through the list, assigning a conditions file on each repeat of the loop.

#Pics Loop CondiitonsFile
$thisCondList

Then you would have to switch to coder view and add a loop by hand. This would replace setBlock

for thisCondFile in condList:
     for thisPic in pics:
            currentLoop = selectBlock

Then select and indent everything from down to everything from:

for thisPic in pics:
#to the end of the question 2 block - easier to say just above the following.

# these shouldn't be strictly necessary (should auto-save)
thisExp.saveAsWideText(filename+'.csv')
thisExp.saveAsPickle(filename)

It will then loop through your list of condition file names, showing the scenarios and two questions each time.

BW

Oliver

Hi Oliver,

Many thanks for your reply. As a beginner level Python programmer, I can grasp the first two steps but I am having difficulty for the remaining parts as to where exactly to integrate in the script. Also, if I switch to Coder view and change the script, there is no possibility to see those changes in the Builder view right? So I am confused on how this will be reflected on the Builder. I am also lost in the last bit you wrote.

I really appreciate your help but I don’t want to waste your time with my limited coding knowledge, so sorry for any inconvenience.

Best,
Ahu

Hi Ahu,

There’s probably a way to do this without any programming at all. The outer loop could connect to a conditions file which just looks something like this:

pic_conditions      text_conditions
pic_01.csv          text_01.csv
pic_02.csv          text_02.csv
etc for 10 rows

Then in the Conditions field of the pics loop, just put $pic_conditions and similarly for the scenarioText loop, use $text_conditions. I’m not sure I really understand the structure here, but I guess the selectScenario loop might then be redundant and could be removed?

You did ask about where to put the conditions files. With so many, you might want to keep them in their own sub-folder to keep things tidy. So you can specify relative paths in the conditions files (i.e. the location relative to where the .psyexp file is), e.g. for a sub-folder called conditions:

pic_conditions                 text_conditions
conditions/pic_01.csv          conditions/text_01.csv
conditions/pic_02.csv          conditions/text_02.csv
2 Likes

Hi Michael,

Thank you very much, this approach is much easier for me. One question still remains, shall I put $pic_conditions and $text_conditions to the image property of the Image component? Or shall I put the column name in the spreadsheet? (Because the scenarios are long, I inserted each scenario as jpg so I used the Image component.)

When I try to run the attached flow I get the following error message (I downloaded the latest version 1.84.2)

raise InvalidFileException(msg)
openpyxl.utils.exceptions.InvalidFileException: openpyxl does not support .jpg file format, please check you can open it with Excel first. Supported formats are: .xlsx,.xlsm,.xltx,.xltm

Many thanks,
Ahu

Hello again,

This is just a follow-up. I changed my flow, apparently I tried to solve this by thinking in terms of single images rather than thinking as block-wise so I was having trouble. Now in the conditionsFile fearpic_conditions column represents the paths of the conditionFiles for the 10 different picture blocks and the second column represents relative paths for the 10 scenarios that will be presented as jpg images. I attach the conditions file.

The file organisation is as follows:
All images are in the folder named fearPics
For each block, there is an xlsx file (e.g fearblock1.xlsx) containing the path of each picture that will be used in that block. (e.g. fearPics/123.jpg)
fearpic_conditions column in the conditionsFile of the outer loop (trials) contains paths of all block conditions that will be used in the experiment. (e.g fearblock1…10.xlsx)

As Michael suggested, for the conditions part, I wrote $fearpic_conditions and $scenario_conditions for the pics and scenarioTexts loops respectively. But it is stated that no parameters are set (conditionsFile not found). The conditionsFile I attached is the conditions file for the trials loop.

Somehow it does not work. When I try to run the experiment I see one white square in the size of the image and another square which I guess is for the scenario. And I get the following error message:
IOError: Found file failed to load as an image.

Any suggestions on how to proceed? Also, I still could not figure out what to put on the image property of the Image component.

All the best,
Ahu

pic_and_scenario_FEAR.xlsx (44.7 KB)

Hi Ahu, your conditions files seem to be mixing different types of content (e.g. some of your errors arise because your a file contains the name of image (.jpg) files, when PsychoPy is actually expecting them to contain the name of a .xlsx conditions file.

You need to structure things so that the conditions file for the outer loop just contains the names of conditions files (i.e. paths to .xlsx files ). On each iteration through that “master” conditions file (i.e. once per block), a new pair of conditions file names will be chosen which can be used by the inner loops.

The conditions files to be used by the inner loops should themselves just contain image file names or text strings to be used for the stimuli (one row per trial). Once more, if the outer loop’s conditions file looks like this:

pic_conditions                 text_conditions
conditions/pic_01.xlsx          conditions/text_01.xlsx
conditions/pic_02.xlsx          conditions/text_02.xlsx

Then, say, pic_01.xlsx should look something like this:

image_file
cat.jpg
dog.jpg
frog.jpg

and text_01.xlsx something like this:

trial_text
"This is text for trial 1."
"And this will show on trial 2."

Then for the image stimulus in Builder, you would use the variable name image_file in the image field, and similarly, for the text stimuli, you would put this in the text field: $trial_text

Make sense?

1 Like

It works, thank you very much for your help Michael. :smile:

For those who may encounter similar problem in the future or have similar way to present their stimuli, I would like to share what I did after following Michael’s suggestions. Since I wanted to present 1 scenario among 10 at the end of each block, I inserted $random(1)*9 to the selected rows property of the inner loop.

Best,
Ahu

Hello all,

Although I marked the problem as solved, I encountered a problem. Michael’s suggestion worked without any problem but failed to do what I really wanted and my solution in the previous post to manipulate selected rows was erroneous. With the current flow, in each block 60 pictures are presented (all images in the experiment) and then the 10 scenarios are presented randomly but in a way that sometimes one scenario is presented more than once while another is never presented.

What do I want to do?
Present 30 images among 60 pictures --> present scenario #1 among 10 --> ask questions --> end the block --> present 30 images --> present scenario #2 --> ask questions… for 10 blocks

In blocks 1-3-5-7-9 pictures #1-30 will be presented in random order
In blocks 2-4-6-8-10 pictures #31-60 will be presented in random order

Solutions I found to present the images as described above:

  1. My pictures file has 60 images in total. Each picture will be presented 5 times throughout the whole experiment so in total subjects will see 300 pictures in 10 blocks. Right now I have the paths of all 60 images in the conditionFile of the pictures loop. By using the selected rows property, for half of the blocks I can select every second item starting from 1st item in the list [::2] and for the remaining half I can select every second item starting from the 2nd item in the list [1::2]. My question is how/where can I implement these 2 different indices to select different rows in different blocks?

OR

  1. I already have 10 condition files to present the pictures in 10 blocks arranged as I want them to be. I guess by adding the code component I can tell psychopy use this specific xlxs.x file to present the images in this block (order randomised). I know I need to create a list with all condition files and then write a for loop to make psychopy select one file per block. My question is how can I do this?

I don’t know which of the 2 solutions would be easier to achieve or would be more elegant.

I need to solve a similar issue with the presentation of the scenarios. I want to present #1…10 randomly and present one scenario in one block and make sure all 10 are presented.

All comments/advices are very much appreciated!

Best,

Hi, I saw the random row selection issue coming. In essence, your current scheme is selecting with replacement, so the same trial can be presented multiple times.

An option would be to do something like this. At the beginning of the experiment, create a randomised list:

# create a list from 0 to 9:
scenario_indices = range(10)

# randomise its order:
shuffle(scenario_indices)

Then in your 'selected rows field, try something like:

scenario_indices.pop()

This means that you are selecting an entry from the scenario list without replacement. So overall, each scenario will be presented once and only once, but in a random order.

EDIT: for those visiting from the future, range() works differently in Python 3 vs Python 2, and now that Python 3 is available (and preferred) for PsychoPy, you would need to convert the range iterator into a list to enable it to be shuffled:

# create a list from 0 to 9:
scenario_indices = list(range(10))

Hi Michael,

Many thanks for your reply. In the selected rows field I inserted $[scenario_indices.pop()] as inserting scenario_indices.pop() did not work. Now everything is in order except that after presenting the 10th scenario I get the following error message and the experiment stops running.

trialList=data.importConditions(‘senaryosALL.xlsx’, selection=[scenario_indices.pop()]),
IndexError: pop from empty list

Best,
Ahu

The list of indices only has 10 entries. This message means that the list has been exhausted (all entries have been popped from it). This thread has been running a bit long for me to keep up, but I’m guessing you have this loop running more than once? If so, you would need to recreate the list of 10 indices each time the loop runs, rather than just once at the beginning of the experiment.

So perhaps move the code from the Begin experiment tab to the Begin routine tab, and something like this so that the list is regenerated as needed on the first iteration of each loop:

# on the first iteration only:
if your_loop_name.thisN == 0:
    # create a list from 0 to 9:
    scenario_indices = range(10)

    # randomise its order:
    shuffle(scenario_indices)

Hi Michael,

Thank you for your reply. It still does not work (first there was an ordering problem, I solved it but now I am back to square one). I really don’t want to keep you busy with this any longer. I will try to find other way to make this work.

Many thanks,
Ahu

Hi Ahu.
I think I have a situation a lit of bit similar of what you had in 2016 and I hope you might give me any suggestion.
I need to present during scanning a positive or negative scenarios and then present different faces (representing that those scenarios happened to corresponding face (or person)). The situation is that either scenarios and faces changes on each trial (70 trials per run). I have tryed with loops but the problem is that the loop process the entire column of excel file (containing different scenarios) and therefore the flow does not jump to the pictures excel file until finish the complete excel scenarios file. Consequently, pictures don´t appear in the task until the loop finish reading the excel scenario files. Does it make sense?

I would not like to think that I would have to make each trial individually. This mean 70 trials on 4 runs!

By the way, I ´m trying this using the bulider not the coder.

Kind regards.

Jorge

Hi Jorge,

It has been a while since I worked on that project (which did not continue anyways). My guess would be to have 2 separate loops (scenarios and faces) surrounded by another outer loop. The outer master loop’s column/variable would have 2 rows where you write each loop’s (scenarios and faces) xlsx condition file name (ex. faces.xlsx) and outer loop’s file name (master.xlsx) can be added as $master where you usually attach the excel condition file. I am not sure if this will work but you might give it a try.

Best,
Ahu

Hi Jorge,
I am using 40 images divided in 4 blocks. I need participants to give a preference rating after every image and after every block(of ten images each) eye-tracking re-calibration. . How would you make the blocks of images so that they are randomly selected each time, and how would you test the order effect? Would you suggest dividing the images into 4 blocks and rotating images between and within blocks? I’m using the builder too. I would really appreciate your help.
Ayesha