psychopy.org | Reference | Downloads | Github

A multi-level randomization of a face task with equal number of its different factors

randomization
#1

Dear All,

I intend to build a task that presents two faces simultaneously, one at the right side of the screen and one on the left side. There are several factors that should be randomized but with equal number at the end.

1- Face gender: One of the faces should always be male and the other face, a female one. There should be equal number of gender at the end.

2- Emotions of the faces: one of the faces in each pair should always be neutral and the other face emotional (disgust or happy). The task should have equal number of neutral male and females and equal number of each emotion (disgust, happy) for each gender (male, female).

3- Sides of the screen (left, right): each pair of faces should randomly be presented in different possible conditions regarding the location. But at the end, each gender and emotions should be presented equally at each side of the screen.

4- Presentation time (500 ms, 1000 ms, and 1500 ms): each pair should be randomly presented with one of these presentation times but with the equal number of each presentation time.

The number of faces we will use are 24 people each gender (24 female, 24 male), with 3 faces each (one for each emotion), for a total of 144 images. This is important that if a face was used in a pair, it should not be selected again for another pair (for example, if a neutral face was randomly selected from the “Male 5” (by Male 5, I mean the name of that character in the dataset), no other face should be selected from “Male 5” for the next pairs even disgust or happy. Regarding the total number of trials, there should be 144 trials at the end by repeating the randomization process for the 24 first trials. Please let me know if more information is needed.

I really appreciate your comments and help.Attentional task programming.xlsx (10.4 KB)

0 Likes

#2

Hi,

This is a nice and precise description of your design constraints but we need a few other pieces of information:

  • it is not clear when you are referring to “faces” whether you mean people or faces of those people. i.e. are there 24 people each gender, with 3 faces each (one for each emotion), for a total of 144 images, or eight people with three emotions, for a total of 24 images? The former seems to be what is implied in your .xlsx file, but it would be good to be explicit about it.
  • given all of the above constraints, how many trials should be presented (my guess is 24, as faces can’t be repeated?)
  • the trickiest question is about the unbalanced numbers of emotions. In any session, only half of the neutral faces and one third of each of the disgusted or happy faces can be presented. If you are happy for this selection to be random within a session, then this is easy to achieve. If each image must be presented equally across subjects, then this is the most challenging thing to achieve: it isn’t trivial at all.
  • although the post is classified as coding, can you clarify whether you are writing the experiment from scratch, or working within the Builder view?

Lastly, the face on the left at least seems to be a little distorted. It can be worth specifying that the units of the window are in height units rather than norm, which allows the original aspect ratio of the images to be preserved, regardless of the dimensions of the monitor.

0 Likes

#3

Hi Michael,

Thank you for your precise questions that helped to make my question clearer. For the first two questions, I added answers to the description of my design (there are 144 total images). Regarding the unbalanced numbers of emotions, I am happy for the selection to be random within a session that makes it easier. But if any of the emotions of a face was used in a pair (trial), this face and other emotions of that person (for example “Male 5”) should not be used for the rest of that 24 trials but obviously they can be selected for the next 24 round of pairs.
I changed the category of my question to Builder as I am working with that but have a problem with the code to make the randomization happens.

0 Likes

#4

This is just a quick sketch to deal with 24 trials at a time, hopefully this puts you on the right road:

# set up design:
males = list(range(1, 25))
females = list(range(1, 25))
shuffle(males)
shuffle(females)

emotions = ['d'] * 12 + ['h'] * 12
neutral_genders  = ['M'] * 12 + ['F'] * 12
neutral_sides =  [-500] * 12 + [500] * 12  # use your actual values 
shuffle(emotions)
shuffle(neutral_genders)
shuffle(neutral_sides)

# create mirror conditions in a clunky way:
emotion_genders = []
for gender in neutral_genders:
    if gender == 'M':
        emotion_genders.append('F')
    else:
        emotion_genders.append('M')

emotion_sides = []
for side in neutral_sides:
    emotion_sides.append(side * -1)

# create conditions for each trial:
conditions = [] # an initial empty list

for emotion in emotions:
    condition = {} # an empty dictionary
    condition['emotion_gender'] = emotion_genders.pop()
    condition['emotion'] = emotion
    condition['neutral_gender'] = neutral_genders.pop()

    if condition['emotion_gender'] == 'M':
        condition['emotion_number'] = males.pop()
        condition['neutral_number'] = females.pop()
    else:
        condition['emotion_number'] = females.pop()
        condition['neutral_number'] = males.pop()

    condition['emotion_side'] = emotion_sides.pop()
    condition['neutral_side'] = neutral_sides.pop()

    conditions.append(condition)

This gives you a list of dictionaries. On each trial, you can pop one of those dictionaries from the list and use it to control the attributes of your stimuli.

e.g. say you have a stimulus for the emotional and neutral faces, then in the “Begin routine” tab, do something like this:

condition = conditions.pop()

emotion_stim.pos = [condition['emotion_side'], 0]
neutral_stim.pos = [condition['neutral_side'], 0]

neutral_stim.image = condition['neutral_gender'] + 
                     condition['neutral_number'] + '_n.jpg'

emotion_stim.image = condition['emotion_gender'] + 
                     condition['emotion_number'] + '_' +
                     condition['emotion']  + '.jpg'

As these conditions are being generated by you rather than Builder, they will need to be saved manually in the data file, e.g:

thisExp.addData('neutral_gender', condition['neutral_gender']) # etc etc
1 Like

#5

Dear Michael,

Many thanks for your help and the code you wrote. I ran the code in the Spyder and get the results into an excel file to check if everything is correct. The number of genders and emotions are correct as one of the faces is always emotional and the other neutral, and one female and the other is male. However, the problem is that the number of male and female faces in each emotion is not equal.
For example, from 24 emotional faces, 12 should be male and 12 female. This is always the case (the number of emotions are also equal). But the number of neutral male and females are not equal, or the number of male with disgust and happy faces are not equal. The same problem exists with the right and left sides as it is not the case the 6 neutral males be at right and the other 6 be at left.

Here is the code which I run (without the parts which give the results into excel file)

import random
import xlsxwriter

# set up design:
males = list(range(1, 25))
# print(males)
females = list(range(1, 25))
random.shuffle(males)
random.shuffle(females)

emotions = ['d'] * 12 + ['h'] * 12
neutral_genders  = ['M'] * 12 + ['F'] * 12
neutral_sides =  ['L'] * 12 + ['R'] * 12  # use your actual values 
random.shuffle(emotions)
random.shuffle(neutral_genders)
random.shuffle(neutral_sides)

# create mirror conditions in a clunky way:
emotion_genders = []
for gender in neutral_genders:
    if gender == 'M':
        emotion_genders.append('F')
    else:
        emotion_genders.append('M')
        

emotion_sides = []
for side in neutral_sides:
    if side == 'L':
        emotion_sides.append('R')
    else:
        emotion_sides.append('L')

# create conditions for each trial:
conditions = [] # an initial empty list

for emotion in emotions:
    condition = {} # an empty dictionary
    condition['emotion_gender'] = emotion_genders.pop()
    condition['emotion'] = emotion
    condition['neutral_gender'] = neutral_genders.pop()
 if condition['emotion_gender'] == 'M':
        condition['emotion_number'] = males.pop()
        condition['neutral_number'] = females.pop()
    else:
        condition['emotion_number'] = females.pop()
        condition['neutral_number'] = males.pop()lockquote

condition['emotion_side'] = emotion_sides.pop()
    condition['neutral_side'] = neutral_sides.pop()
    
    
    conditions.append(condition)

Many thanks for your help.

0 Likes

#6

So either the code is wrong, or I didn’t understand your design, or both. But this was really just designed as a hint to show you you one can balance and randomise factors. I think you’d be the one best placed to make tweaks and take this code from an initial suggestion to an algorithm that gives you the precise arrangement you need for your design.

Certainly come back to us with any specific questions that arise.

0 Likes