psychopy.org | Reference | Downloads | Github

Selecting even number of images based on parameter


#1

Hi there!

I am using the newest MAC standalone version of PsychoPy (PsychoPy 3.0.2). I am building an experiment that requires the display of 20 images that are randomly selected based on one parameter (emotion).

I currently have 2 columns (parameters): 1 contains the file-path name of the images, and the other is the associated emotion.

I would like to show an even number of images based on 4 emotions ( happy, sad, fear, surprise) that are randomly picked out of a total of 120 images. Thus, I would to show 5 images of each of those 4 emotions, back to back.

How can I go about doing? Thank you for any insight!
Best,
G.


#2

In blocks of emotions (i.e. five consecutive trials of each emotion), or randomly interspersed (emotion varying from trial to trial)?


#3

Hi Michael,

Thanks for your reply!
Randomly interpersed.


#4

:confounded: that is trickier…

In blocks, they could be handled by a clever arrangement of loops within Builder. With the sort of randomisation scheme you need, Builder is not flexible enough to handle out-of-the-box. You will need to add a code component from the “custom” component panel to use some code to handle the randomisation for you. Put something like this in the “Begin Experiment” tab of that code component dialog, to randomly select 20 images:

stimulus_list = []

for emotion in ['happy', 'sad', 'fear', 'surprise']:
    # choose 5 out of the 30 possible images:
    selection = np.random.randint(low = 1, high = 31, size = 5)
    for number in selection:
        # store a dictionary containing the info for each trial:
        stimulus_list.append({'emotion': emotion,
                              'number': number,
                              'image_file': emotion + str(number) + '.jpg')}

# randomise the order:
shuffle(image_list)

Then in the “begin routine” tab, put something like this:

current_stimulus = stimulus_list.pop()
# need to store these variable manually in the data file so you know
# what was shown:
thisExp.addData:('emotion', current_stimulus['emotion'])
thisExp.addData:('emotion_number', current_stimulus['number'])

Then in your image stimulus component, put this in the “image” field, set to update “every repeat”:

$current_stimulus['image_file']

Make sure the code component appears above the image component, so the latter has access to the latest content of the 'current_stimulus ’ variable.


#5

Hi Michael!

Thanks for the help! I tried out the code you described, with some modifications. It seems to run semi-smoothly, but the error message I can’t shake off right now is the following:

IndexError: pop from empty list

Could you clarify what the .pop() function is supposed to do, so that I can adapt?

Thank you!


#6

.pop() removes the last item from a list, reducing its size by one. If you try to pop from an empty list, you get that error, as there are no more entries to extract.

There should be 20 entries in that list to start with, and your loop should therefore run 20 times. If the number of loop iterations exceeds the number of list entries, then you’re in trouble (which is actually a useful built-in check).

To debug, add:

print(len(stimulus_list))

immediately after it is created to check that it has 20 entries.

While the loop is running, you could also add code to run at the beginning of the routine to do this:

print(len(stimulus_list))
print(your_loop_name.thisN)

As one goes down, the other should go up…