Randomization of three lists simultanously

**OS Win10
**PsychoPy version 1.84
**Standard Standalone
Hello,
I’m struggling with an experiment for while, tried several approaches, but none of them was successful (not independently from the fact that I’m a novice to Psychopy).

The experiment shortly: the goal is to present 10 facial images out of 30 randomly, and pair them with either a negative or a positive prime (i.e. faces will be preceded with either a negative or a positive image.)

So, basically I have three lists: one containing 5 positive, an other with 5 negative, and a third with 30 facial images. I’d like to pair 5 random faces with ALL of the negative images once, another 5 random faces with ALL the negatives. Negative and positive conditions should be randomized.

I. First I tried to use a code found here on the forum ( shuffle(all_rows) ). In builder I set the selected rows option to use the first 5 rows (to pair the first 5 faces from the randomized list with the primes (I made two separate routines for the conditions, but I will get back to this later). The problem with it was that when my xlsx file containt three colums, all them will be randomized, so sometimes I get blank screen instead of primes.

Question: is it possible the shuffle only one column of an excel sheet instead of shuffling all? Or is it possible to use multiple sheets for the same loop?

II.I tried to put the the conditions (negative, positive) in two separate routines and make a loop around them to chose randomly between to two until all possible pairings have been shown. My main problem was that prime/face pairings seem to be fixed, but it should show all possible pairs (if a face is preceded by a negative prime once, at the next repetition is should be another one from the negative list). So 5 repetition for each face, 5 repetition of each prime.

Question: how can I present all possible prime/face combinations randomly?

III. I also tried to split the priming routine to separate prime + face routines. This also failed because I was unable to break to prime loop befor the 5 repetitions was finished (I got 5 primes, THEN 5 faces). When I set to repetion times to one, and made an outer loop with five repetitions, it seemed I lost control of whether the same prime is repeated or not (I also had the intention to make another outer loop to choose randomly between negative and positive conditions each made of two routines, but at that point I gave up).

Ultimate question: can any of my approaches lead to success?

Sorry if I made nonsense questions. I’ll try to rephrase if necessary.
Any advice will be appreciated!
many thanks

1 Like

Just to make sure I understand your goal:

  • You need to randomly select 10 faces from a list of 30.
  • 5 of these will only be shown with negative primes, and 5 will only be shown with positive primes.
  • There are 5 negative primes and 5 positive primes.
  • Each negative prime will be paired once with each negative face, and each positive prime will be paired once with each positive face.

This results in:

5 pos face X 5 pos prime = 25
5 neg face X 5 neg prime = 25

So if I understood correctly, you will want the combinations contained in this excel file, except randomized (and the faces will be drawn randomly from among 30):

faceCombinations.xlsx (5.3 KB)

Did I get that right?

While we await your response, it sounds like you’re going to have to add some custom code components to do what you need (someone correct me if I’m wrong). We can help, but it wouldn’t hurt your understanding to do a quick tutorial on python and get your feet wet if you haven’t yet. :slight_smile:

Hi there,
thats right, I’d like to do exactly what you wrote. The table shows the combinations I need.
I started an online course about python a couple of months ago, never finished though, but I am familiar with the most basic concepts and syntax (how to make if-else statements, set and change counters, make lists etc.) So having to work with a scripts sounds interesting rather than scary (hopefully I will still have the same opinion after your reply…)
thank you in advance!

So I had a thought. I was trying to think of a way of avoiding having to code the whole experiment, so that we could rely on psychopy’s built-in randomization and data saving. My thought is to use the faceCombinations.xlsx file as a conditions file, and treat the values in that file as keys to dictionaries that we will build at the beginning of the experiment.

So in the beginning of the experiment, we read in a file which is a list of your thirty face image files, select ten at random and create a dictionary like this:

faceDict = {
    'posFace1': 'images/face16.jpg',
    'posFace2': 'images/face7.jpg',
    'negFace1': 'images/face28.jpg',
   ...etc.
}

Then in the image component in the builder, we set its path to:

faceDict[$face]

…with “$face” being the key from our conditions file.

We can do a similar thing with the primes. We’ll make a dictionary where the values of the “prime” in faceCombinations.xlsx will be keys to a dictionary. At the beginning of the experiment, we create this dictionary using a spreadsheet (here “primes.xlsx”), with a column containing the key, and another with the value:

primeKey        primeText
posPrime1       This is a positive prime.
posPrime2       This is also a positive prime.

We end up with a dictionary like this:

primeDict = {
    'posPrime1': 'This is a positive prime.',
    ...etc.
}

And set the text value on our text stim to

primeDict[$prime]

So in short, we have three spreadsheets:

  • faceCombinations.xlsx (our conditions file),

  • faceList.xlsx (list of face images), and

  • primes.xlsx (containing keys and values to build a dictionary).

Here’s some code to put in its own routine at the beginning of the experiment;

import random

# use psychopy's method to get a list of dictionaries
# {'colName', 'colValue'}
faceDictList = data.importConditions("faceList.xlsx")
# convert to a simple list
faceListAll = [x['faceFile'] for x in faceDictList]

# randomly select 10 of these
faceList = []
while len(faceList) < 10: 
    rF = random.choice(faceListAll)
    if not rF in faceList:
        faceList.append(rF) 

# build the faceDict, with the file names as values
faceDict = {}
faceListInd = 0 
for posNeg in [u"negFace", u"posFace"]:
    for ni in range(0, 5): 
        posNegKey = posNeg + unicode(ni + 1)  
        faceDict[posNegKey] = faceList[faceListInd]
        faceListInd += 1

# read in the primes spreadsheet
primeDictList = data.importConditions("primes.xlsx")

# convert to our prime dict
primeDict = {}
for pd in primeDictList:
    key = pd["primeKey"]
    val = pd["primeText"]
    primeDict[key] = val

At the end of the routines, we need to add a code component if we want to save which image was used:

End Routine

thisExp.addData('faceFile', faceDict[face])

And we could do the same with the prime text to be thorough (in case we ever change the text for future runs, we know what happened).

So here’s a mockup that does all of this:

faceCombinations.xlsx (5.3 KB)

faceList.xlsx (5.0 KB)

primes.xlsx (4.9 KB)

faces.psyexp (11.4 KB)

wow, this looks cool! I hope I can handle all these thing. I’ll give feedback when I had a bit time to try this out.
thanks a lot!

Hello,
it worked nicely! The only thing I had to change was the column primeText in the primes.xlsx, as I wanted to use images as primes, instead of text. Accordingly, the stimulus type also had to be changed. Thank you for the miraculous solution!
best wishes

I know this is a bit of a long-shot but I was hoping to get a bit of advice about this…
I am trying to set up an experiment with a similar structure.
I have around 300 images that sort into three categories - happy, angry and neutral - and I also want to display the words ‘happy’, ‘neutral’, and ‘angry’ alongside the images in every combination.
I have a csv file with all of the image file paths in and I’ve imported this into PsychoPy and organised them into a dictionary based on the category they fall into. I also have a conditions csv file which has the words and the key that the file paths are sorted by.
Based on this I’ve then set the image component to FaceDict[$emotion] like in this example however, I get the error message ‘OSError: Couldn’t find image FaceDict[$emotion]; check path? (tried: C:\Users_\Documents_\FaceDict[$emotion])’. This file path is correct, it just seems as though PsychoPy is not using the dictionary relatievly.
I was wondering if you would be able to shed any light on this?
This is the code I used to sort the list of image paths into the dictionary:

ImageFiles = data.importConditions(“filepaths.csv”)
faceListAll = [x[‘FaceFile’] for x in ImageFiles]

FaceDict = {‘happy’: , ‘anger’: , ‘neutral’: }
for filename in faceListAll:
if ‘happy’ in filename:
FaceDict[‘happy’].append(filename)
if ‘anger’ in filename:
FaceDict[‘anger’].append(filename)
if ‘neutral’ in filename:
FaceDict[‘neutral’].append(filename)

Thanks.