psychopy.org | Reference | Downloads | Github

Import different lists on Psychopy

Dear All,

I am conducting an experiment of facial expression recognition and I decided to programme the experiment using Psychopy. I am writing to you since I am stuck in the following situation:

I have 36 lists of images (written in excel files) from which I want to create, for each participant, a new list composed by 36 images taken randomly from the primary lists, one image per list.

Since I am new both in Python and in Psychopy, I do not know how to figure out this problem (maybe trivial for you).

The only solution I found was to create a lot of Excel files containing a new randomized list per file, which I would like to insert in the coder. The idea was:

  • to create a list of Excel files
  • for each participant, randomly choose an Excel file from the list (or selected from the fist to the last)
  • to display images inside the selected excel file.

Nevertheless, this solution leads me to another problem: How to write an efficient code?

I am sorry for annoying you with these questions, but I will really appreciate any help you will decide to give me.

Thank you in advance for both your availability and your time.

  1. You might find it easier to work with csv files in code rather than Excel files.
  2. Use the glob function to get a list of all 36 .csv files in the given directory.
  3. Loop though each of those 36 filenames, opening them with a csv reader.
  4. Get the result into a list.
  5. Shuffle that list.
  6. Take the zeroth entry in that list and store it
  7. You now have a list of 36 image names, one from each list.
  8. Cycle though that list to create your stimuli.
  9. If needed, google how to do any of the steps above…

Thank you so much Michael and sorry for the late answer! I will try to follow you suggestions.
Just another question: in the second point you mentioned the glob function. According to your point of view, where should I write it in my script?

Thank you

Since the first solution suggested by @Michael was quite difficult for me, I tried the second I mentioned, here is the code:

import random
 ## my idea was to create a list of files from which select one file to pass in data.importConditions()
mylist=['maze1.xlsx','maze2.xlsx','maze3.xlsx'],
mam=random.choice(mylist),


trials = data.TrialHandler(nReps=1, method='sequential', 
    extraInfo=expInfo, originPath=-1,
    trialList=data.importConditions(mam),
    seed=None, name='trials')
thisExp.addLoop(trials)  # add the loop to the experiment
thisTrial = trials.trialList[0]  # so we can initialise stimuli with some values

Unfortunately, I got these errors:

Traceback (most recent call last):
  File "C:\Users\..\Desktop\experiment\exp.py", line 89, in <module>
    trialList=data.importConditions(mam),
  File "C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy-1.84.2-py2.7.egg\psychopy\data.py", line 2614, in importConditions
    if not os.path.isfile(fileName):
  File "C:\Program Files (x86)\PsychoPy2\lib\genericpath.py", line 37, in isfile
    st = os.stat(path)
TypeError: coercing to Unicode: need string or buffer, tuple found

Is there a way to figure out the problem? Thank you in advance for your attention

Well I’m going to back track and give you an implementation of @Michael 's suggestion, because I think it’s a good one, and you should learn how to do stuff like this. :slight_smile:

Here’s some code to create a folder called “stimLists”, and create 36 spreadsheets with a column named “imPath” in each, and instead of actual paths, the rows are numbers 1-1, 1-2, 1-3 … etc. for list 1, 2-1, 2-2, 2-3 … etc. for list 2, etc. This won’t be helpful for your final implementation, but it lets us quickly write some test code to make sure these steps work.

import os
targetDir = "stimLists"
os.mkdir(targetDir)

for i in range(1, 37):
    outFil = os.path.join(targetDir, u"list" + unicode(i) + ".csv")
    with open(outFil, "w") as f:
        f.write("imPath\n")
        for j in range(1, 37):
            f.write(unicode(i) + u"-" + unicode(j) + "\n")

Now for the real script that open each of these 36 files, randomly selects one line, puts it in a list, then shuffles this list.

#!/usr/bin/env python
#-*- coding: utf-8 -*-

from psychopy import data
from glob import glob
# don't want to interfere with numpy's random,
# so importing random under a different name, just in case
import random as rnd

# folder containing spreadsheets
spreadPath = u"stimLists"
# Extention of spreadsheets, You would use this for your excel sheets
#spreadExt = u".xlsx"
spreadExt = u".csv"

spreadsheets = glob(spreadPath + "/*" + spreadExt)

chosenImages = []
for ss in spreadsheets:

    sData = data.importConditions(ss)
    # choose one conditions file line at random
    rl = rnd.choice(sData)
    chosenImages.append(rl)

# now mix up the chosenImages
rnd.shuffle(chosenImages)

# print them out to have a look and see that
# it's working.
for ci in chosenImages:
    print(ci)

## You should be able to give "chosenImages" to a trial handler

As a side note, I would include a column with a unique label for each line like the one here (24-2 = spreadsheet 24, item 2), since it will help make sense of data later, if you aren’t doing so already.

Again, sorry I’m not answering your latest question, but if it were me I might try a solution like this. But as to that error, I’m not sure what it might be, but the issue is frequently an excel sheet with some “noise”, like extra rows, or left over cruft from editing of excel files. @Michael is right about .csv files being easier to manipulate in code. If you decide to go the route you last suggested, my first step would be to see if the problem still exists with a single fresh spreadsheet.

1 Like

Thanks to Daniel for putting in more effort than I was able to…

It was likely simply due to randomly sprinkling commas at the end of some lines:

mylist=['maze1.xlsx','maze2.xlsx','maze3.xlsx'],
mam=random.choice(mylist),

Try running that code without those random commas, and you’ll see that mam because a string (as desired), rather than a tuple, which is the case of your type error. If that doesn’t make sense, then I think you need to spend some time on some basic Python language tutorials before trying to actually write PsychoP- specific code: the danger is that even with very useful code contributed by people like Daniel, without some understanding of basic issues like Python variable types, it will be very easy to go astray.

Perhaps a good way to go here would be to stick with the Builder interface, but integrate Daniel’s suggestions within a code component set to run at the beginning of the experiment.

Good luck.

Hi Daniel,

Thanks for sharing this code! I’m new to PsychoPy and was looking for a way to select dynamically the file to be used as source in a loop. Having currently no knowledge of Python, I would not have been able to write anything like it (so thanks a lot for taking the time, but I understand what it does.

However, I’m a little lost as to where to insert that code in the PsychoPy Builder (at the moment I’ve inserted it in the “Begin Routine” section but I’m really not sure that’s where it should go.

Then I’m not sure how to specify the content of the ci variable as the source for the conditions of the trials…

Sorry if this all sound very naïve… I’m hoping you could point me in the right direction.

Many thanks in advance!

Fabrice.

You can’t specify a variable to be used in defining a loop with code that will itself run within that loop: that is putting the cart before the horse. So instead of having such code run at the beginning of the routine, put it in the “begin experiment” tab, so that your variable is created before the loop needs to refer to it.

Many thanks! Of course! Gosh, I feel a little dumb :wink:
I’ve now managed to adapt the code to what I wanted to do (actually very basic: selecting a .csv file at random). So now I can carry on developing my first task in PsychoPy. Many thanks!
Fabrice.