Can you display only a random subset of incorrect/distractor trials?
I am creating an emotional identification study in which a target emotion is selected (e.g. happy) and then participants complete a set of trials in which they press 1 if the image shown displays a happy face and 2 if it displays any other emotion (from the basic 6). Simple so far.
This is then repeated with each different emotion set as the target emotion.
For each block I have 6 models with each displaying all 6 emotions meaning each block has 36 images but only 6 are actually correct. In total this means participants have to go through 216 trials for only 36 potential "hits". My actual study is more complicated (adding divided visual field components) and would end up with over 1000 trials (most of which incorrect) which is why I need to simplify.
Seeing as I don't care about the responses to the incorrect trials, is it possible to randomize each block so that participants see all of the correct trials and then a random selection of incorrect trials? For example, a "happy" block would show all 6 models displaying a happy face randomly between 10 incorrect trials showing any model displaying any emotion OTHER than happy (with no repeats).
I am somewhat comfortable with adding inline scripts which I know this will need.
Comments
Hi @Rrob,
Yes, this is certainly possible, but will indeed require some inline coding. Before getting into this, could you let us know whether you plan to run your study online or locally?
Cheers,
Lotje
Did you like my answer? Feel free to

Thanks @lvanderlinden !
I am running this locally and have built most everything using the GUI. I have attached a simplified version of the study.
Hi @Rrob,
I think you could do the following:
inline_scriptitem to the beginning of your dividedID_sequencewhere you will define the current list of trials (in thePrepare tab) like so (see comments for explanations):# Prepare the list of trials for the current block: # Make a list of all six emotions: list_emotions = ["anger", "disgust", "fear", "happy", "sad", "surprise"] # Make a list of all six models: list_models = ["f_01", "f_20", "f_33", "m_10", "m_17", "34"] # First, determine the file names of the 6 "target" pictures, # that is, the pictures with the current target emotion: list_target_files = [] for model in list_models: # Example: m_06_happy_100.png target_file = "%s_%s_100.png" % (model, var.block_emotion) # Append the current target file to the target list: list_target_files.append(target_file) # Next, we will make a list of all possible distractor files # (i.e. all the pictures with other emotions than the target emotion) # Make a list of the remaining emotions: list_distractor_emotions = list_emotions[:] # Copy of the list containing all 6 emotions list_distractor_emotions.remove(var.block_emotion) # Remove block emotion # Make a list with all possible distractor combinations: list_distractor_files = [] # We will use the built-in Python module intertoosl # to cross every emotion with every model: import itertools list_combinations = itertools.product(list_distractor_emotions, list_models) for emotion, model in list_combinations: # Determine the file name of the current distractor: # Example: m_06_happy_100.png target_file = "%s_%s_100.png" % (model, emotion) list_distractor_files.append(target_file) # Append to the distractor list # Shuffle the lists: # We will do this by using the built-in Python module random: import random random.shuffle(list_target_files) random.shuffle(list_distractor_files) # Get the first 10 distractor files # Note that this boils down to randomly selecting without # replacement: ten_distractors = list_distractor_files[:10] # Merge the ten distractors with the six targets in one list: trial_list = ten_distractors + list_target_files # Shuffle again: random.shuffle(trial_list)inline_scriptto the beginning of the trial_sequenceto determine the current value of the variable "filename"block_loop, you only have to define the variable "dvf_side" for 16 trials (6 target + 10 distractor trials)The structure of your experiment should now look something like this (for testing purposes I removed some items from your original file):
https://forum.cogsci.nl/uploads/956/8H947V3ABCR4.pngDid you like my answer? Feel free to

I uploaded an example script. (Because I don't have the images, I temporarily replaced the images with the file name in the
sketchpaditem "Divided".)Let me know whether this gives the desired behaviour.
Cheers,
Lotje
Did you like my answer? Feel free to

It definitely works for a component of my study! I have also learned a lot from reading through your script/comments.
I do have a few questions though.
For the divided visual field compnent I would also like to be able to ensure that the target trials related in a balanced manner (i.e. each photo shows up on the left and on the right side), but the distractors do not need to repeat. Is this possible as well?
Seeing as the script sets the actual filename, do I lose the attributes of each trial (e.g. gender, number, emotion) unless I re-split created file? This is not a big deal as I can deal with that when I analyze the data, but I am curious if information about the file can be saved into a variable in the loop table?
Hi @Rrob
First of all, I noticed a mistake in my previous code where I define the list of models. The last item in this list is not preceded by the letter indicating the gender.
should be changed to
In order to define the additional trial variables, you should indeed use the information from the file name. For example (in the
Pythonscript in the trial_sequence):# Pop one item from the trial list # Note that because the list is shuffled and we're using # the pop() function, this boils down to random selection # without replacement # Note that because we want the variable filename # to be available in the GUI (for the logger, # and for the square-bracket notation in the # sketchpad, we store the variable in the # var. object): var.filename = trial_list.pop() # Define additional trial variables: # Note that by storing them in the var object, # they become availabe in the interface and will # therefore be logged to the output file by # the logger item # Split the file name by underscores, # resulting in a list with separate items: list_trial_info = var.filename.split("_") # The first item contains the gender: # (Note that Python starts counting at 0) var.gender = list_trial_info[0] # The second item contains the model: var.model = list_trial_info[1] # Determine whether the current trial presents a target or # a distractor. # We do this by checking whether the block emotion is # in the file name (then the file is a target) or not # (then the file is a distractor) if var.block_emotion in var.filename: var.trial_type = "target" else: var.trial_type = "distractor" print(var.trial_type)For the divided visual field component I would also like to be able to ensure that the target trials related in a balanced manner (i.e. each photo shows up on the left and on the right side), but the distractors do not need to repeat. Is this possible as well?
Yes, it is! Before answering, could you indicate how the visual field side (left or right) should be divided among the distractor trials? (For the target trials, your description is clear.)
Cheers,
Lotje
Did you like my answer? Feel free to

Oh, yes! I caught that at well.
That is great, thanks! The distractors simply need to be balanced with an equal number of left/right presentations. The gender, model, and specific emotions for the distractors don't need special consideration for balancing as the randomness and number of blocks should more of less take care of it.
Hi @lvanderlinden,
I realized I didn’t tag you so this post probably got buried. Everything has been working great so far! If there is a way to balance the target trials between left/right I’m sure I can apply the code to the distractors after seeing how it is done! Your comments make it easy to follow.
-Raf
Hi @Rrob ,
Could you check whether this script gives the desired behaviour? Instead of making a list of PNG files, I made a "list of lists" (or actually, a list of tuples) where each tuple contains two items representing (1) the PNG file and (2) the dvf_side.
# Prepare the list of trials for the current block: # Make a list of all six emotions: list_emotions = ["anger", "disgust", "fear", "happy", "sad", "surprise"] # Make a list of all six models: list_models = ["f_01", "f_20", "f_33", "m_10", "m_17", "m_34"] # First, determine the file names of the 6 "target" pictures, # that is, the pictures with the current target emotion: list_target_files = [] for model in list_models: # Example: m_06_happy_100.png target_file = "%s_%s_100.png" % (model, var.block_emotion) # Append the current target file to the target list: list_target_files.append(target_file) # Next, we will make a list of all possible distractor files # (i.e. all the pictures with other emotions than the target emotion) # Make a list of the remaining emotions: list_distractor_emotions = list_emotions[:] # Copy of the list containing all 6 emotions list_distractor_emotions.remove(var.block_emotion) # Remove block emotion # Make a list with all possible distractor combinations: list_distractor_files = [] # We will use the built-in Python module intertoosl # to cross every emotion with every model: import itertools list_combinations = itertools.product(list_distractor_emotions, list_models) for emotion, model in list_combinations: # Determine the file name of the current distractor: # Example: m_06_happy_100.png distractor_file = "%s_%s_100.png" % (model, emotion) list_distractor_files.append(distractor_file) # Append to the distractor list # Shuffle the lists: # We will do this by using the built-in Python module random: import random random.shuffle(list_target_files) random.shuffle(list_distractor_files) # Get the first 10 distractor files # Note that this boils down to randomly selecting without # replacement: ten_distractors = list_distractor_files[:10] # Merge the ten distractors with the six targets in one list: # trial_list = ten_distractors + list_target_files # Make a list of tuples. # Each item in the list contains a tuple containing, again, two items: # - The H file # - The visual field trial_list = [] # Walk through the distractors: for _distractor in ten_distractors: # Randomly determine the dvf side: trial_list.append((_distractor, random.choice(["left", "right"]))) # Walk through the targets: for _target in list_target_files: # Walk through the two visual fields: for _side in ("left", "right"): trial_list.append((_target, _side)) # Shuffle again: random.shuffle(trial_list)I attached a new example script.
Best wishes,
Lotje
Did you like my answer? Feel free to

@lvanderlinden,
This is great! You have just cut the study time in half. I (and my future participants) thank you!
-Raf
You're most welcome @Rrob , and thanks so much for the coffee! :)
Did you like my answer? Feel free to
