Hi! I am new to PsychoPy and I’m trying to code a self-paced reading experiment with 2 lists. The script should present a either list1 or list2 one word at a time in the center of the screen and allows the participant to do self-paced reading by pressing the space bar and for each word, the script measures the reaction time.
My script so far does not run after the introduction message. I hope to get some help with this. Thank you in advance.
Script:
# load modules
from psychopy import visual, core, event, gui
import random
import glob
import pandas as pd
# define dialogue box
box = gui.Dlg(title = "Barry The Bat")
box.addField("Participant Id:")
box.addField("Age:")
box.addField("Gender:", choices = ["female", "male", "other"])
box.show()
if box.OK:
ID = box.data[0]
AGE = box.data[1]
GENDER = box.data[2]
elif box.Cancel:
core.quit()
# define window
win = visual.Window()
# define stop watch
stopwatch = core.Clock
# define logfile
columns = ["id", "age", "gender", "condition", "word", "reaction_time"]
logfile = pd.DataFrame(columns=columns)
# instructions
instructions = '''
Welcome to the experiment!
In a moment, you will be presented two versions of a short text about Barry the Bat one word at a time.
You will do a self-paced reading by pressing the spacebar to skip to the next word.
Press spacebar when you are ready to begin the experiment...
'''
goodbye = '''
You have completed the experiment. Thank you for your participation'''
# define functionsht
list1 = "Barry the bat was just three months old. Sometimes when Barry was sleeping upside down in his cave, he would wake up suddenly and get afraid of the light. When he became frightened like this, he would cry and chirp. Mom would come flying over right away. She would ask Barry if he is alright? Barry would ask his mom if she could leave the darkness on all night because he did not want it to be all scary and bright. Mother bat hugged Barry and gave him a kiss on the forehead and he swayed upside down off to sleep.".split()
list2 = "Barry the bat was just three months old. Sometimes when Barry was sleeping upside down in his cave, he would wake up suddenly and get afraid of the light. When he became frightened like this, he would cry and chirp. Mom would come flying over right away. She would ask Barry if he is alright? Barry would ask his mom if she could leave the darkness on all night because he did not want it to be all scary and bright. Mother bat hugged Barry and gave him a smack on the forehead and he swayed upside down off to sleep.".split()
# define function
# function for showing text and waiting for key press
def msg(txt):
msg = visual.TextStim(win, text = txt)
msg .draw()
win.flip()
key = event.waitKeys(keyList = ["space"])
# Begin Experiment
# show instructions
msg(instructions)
# prepare text1
for i in [list1, list2] :
conditions = random.shuffle(list1, list2)
msg1 = visual.TextStim(win, text = i)
msg1.draw()
win.flip()
stopwatch.reset()
key = event.waitKeys(keyList = ["space"])
reaction_time = stopwatch.getTime()
logfile = logfile.append({
"id": ID,
"age": AGE,
"gender": GENDER,
"word": i,
"reaction_time": reaction_time,
"condition": conditions}, ignore_index = True)
# save the logfile
logfile_name = "logfiles/logfile_{}.csv".format(ID)
logfile.to_csv(logfile_name)
# show goodbye message
msg(goodbye)
Presumably there is an error message? I think I can guess what that might be but help is most likely to come if you can narrow things down for us.
But even if we deal with that error, this code is unlikely to be doing what you want it to. You probably need to sit back and think what you want to achieve, and review whether that matches the way your code is structured. It can be really helpful to sketch out a flowchart on a piece of paper to get your thoughts straight. e.g. you want to present one word at at time, but your loop is currently structured to (attempt to) show an entire list at a time. i.e. for a start, it would seem that you might need a word-by-word loop nested within your sentence-by-sentence loop.
Lastly, and this is just an optimisation thing, you really shouldn’t be recreating your text stimulus from scratch all the time. Just create it once at the beginning of your script, and then update its text content as needed. Creating stimuli is a time-expensive process.
Hi Michael, thank you for your time in taking a look at my script! I used .split() function at the end of my list in hopes that it will show the words one by one. And also the current error message is typeError: ‘list’ object is not callable. I would really appreciate any assistance one this! Thank you
That’s the problem with computers, that don’t do what we hope they will do, only what we explicitly tell them to do
So you need to have two loops, one to iterate over your sentences, and then another loop within that to iterate over each word in that sentence, e.g. something like this (skeleton code –please fill out as needed):
# use numpy's random functions rather than Python's own:
from numpy.random import shuffle
# create this only once, before the loops start:
word_stim = visual.TextStim(win, text = 'XXXX')
sentences = [list1, list2]
shuffle(sentences) # am assuming you want this randomised
for sentence in sentences:
# draw each word:
for word in sentence:
word_stim.text = word # don't recreate the stimulus here, just update it
word_stim.draw()
win.flip()
# wait for a response
key = event.waitKeys(keyList = ["space"])
Hi Micheal, I have tried incorporating your suggested code into my scrip and your assumption that I want it randomised is correct:). However, the window is showing list1 word by word followed by list2. Is it possible to show only either list1 or list2?
this is my current script:
# load modules
from psychopy import visual, core, event, gui
import random
import glob
import pandas as pd
from numpy.random import shuffle
# define dialogue box
box = gui.Dlg(title = "Barry The Bat")
box.addField("Participant Id:")
box.addField("Age:")
box.addField("Gender:", choices = ["female", "male", "other"])
box.show()
if box.OK:
ID = box.data[0]
AGE = box.data[1]
GENDER = box.data[2]
elif box.Cancel:
core.quit()
# define window
win = visual.Window()
# define stop watch
stopwatch = core.Clock()
# define logfile
columns = ["id", "age", "gender", "condition", "word", "reaction_time"]
logfile = pd.DataFrame(columns=columns)
# instructions
instructions = '''
Welcome to the experiment!
In a moment, you will be presented a short text about Barry the Bat one word at a time.
You will do self-paced reading by pressing the spacebar to skip to the next word.
Press spacebar when you are ready to begin the experiment...
'''
goodbye = '''
You have completed the experiment. Thank you for your participation'''
# define functionsht
list1 = "Barry the bat was just three months old. Sometimes when Barry was sleeping upside down in his cave, he would wake up suddenly and get afraid of the light. When he became frightened like this, he would cry and chirp. Mom would come flying over right away. She would ask Barry if he is alright? Barry would ask his mom if she could leave the darkness on all night because he did not want it to be all scary and bright. Mother bat hugged Barry and gave him a kiss on the forehead and he swayed upside down off to sleep.".split()
list2 = "Barry the bat was just three months old. Sometimes when Barry was sleeping upside down in his cave, he would wake up suddenly and get afraid of the light. When he became frightened like this, he would cry and chirp. Mom would come flying over right away. She would ask Barry if he is alright? Barry would ask his mom if she could leave the darkness on all night because he did not want it to be all scary and bright. Mother bat hugged Barry and gave him a smack on the forehead and he swayed upside down off to sleep.".split()
# define function
# function for showing text and waiting for key press
def msg(txt):
msg = visual.TextStim(win, text = txt)
msg.draw()
win.flip()
key = event.waitKeys(keyList = ["space"])
#stimulus
word_stim = visual.TextStim(win, text = 'XXXX')
# Begin Experiment
# show instructions
msg(instructions)
# prepare text
sentences = [list1, list2]
shuffle(sentences)
for sentence in sentences:
for word in sentence:
word_stim.text = word
word_stim.draw()
win.flip()
stopwatch.reset()
key = event.waitKeys(keyList = ["space"])
reaction_time = stopwatch.getTime()
logfile = logfile.append({
"id": ID,
"age": AGE,
"gender": GENDER,
"condition": sentence,
"word": word,
"reaction_time": reaction_time,}, ignore_index = True)
# define logfile name
logfile_name = "logfiles/logfile_{}_{}.csv".format(ID, date)
#save data to directory
logfile.to_csv(logfile_name)
# show goodbye message
msg(goodbye)
# prepare text
sentences = [list1, list2]
shuffle(sentences) # randomise the order
for word in sentences[0]: # just work with one of them
word_stim.text = word
# etc