Saving data from Stroop task into .csv file

I am trying to save some data from my Stroop task into a .csv file with the following headers: ‘Trialnum’, ‘Colourtext’, Colourname’, ‘Condition’, ‘Response’, ‘Reactiontime’, ‘Correct’. I am having some trouble with this as firstly, I am not sure how to save the reaction time. Every time I have tried psychopy either crashes, with errors like ‘float object is not iterable’ or ‘tuple object is not iterable’ etc etc… or when I tried a different method the reaction time was calculated in terms of the start of the experiment, not the onset of each stimulus presentation (which is what I want). In regards to the other headers, I am not sure how to extract the relevant information from my data in order to fill those criteria in the .csv file. I am VERY new and inexperienced to python and psychopy.
this is my code.

from psychopy import visual, core, event, gui
from csv import DictWriter
from random import shuffle, random
from datetime import datetime

data = {'Expdate': datetime.now().strftime('%Y%m%d_%H%M'), 'ID': '', 'Age': '', 'Gender': ''}
dlg = gui.DlgFromDict(data, title='Input participant info', fixed='Expdate', order=['ID', 'Age', 'Gender','Expdate'])

if not dlg.OK:
    print("User exited")
    core.quit()
    
filename = 'part_{}_{}_{}_{}.csv'.format(data['ID'], data['Age'], data['Gender'], data['Expdate'])



f = open(filename, 'w')
csvfile = DictWriter(f, fieldnames = ['RT'])
csvfile.writeheader()

#create 2 dictionaries made of pairs - value 0 of pair is word and value 1 is colour of word
congruent_pairs = 15 * [('red', 'red'), ('blue', 'blue'), ('green', 'green'), ('yellow', 'yellow')]
incongruent_pairs = 5 * [('red', 'blue'), ('red', 'green'), ('red', 'yellow'), ('blue', 'red'), ('blue', 'green'), ('blue', 'yellow'), ('green', 'red'), ('green', 'blue'), ('green', 'yellow'), ('yellow', 'red'), ('yellow', 'blue'), ('yellow', 'green')]

pairs = congruent_pairs + incongruent_pairs


#want the pairs to appear in a random order when presented as trials 
shuffle(congruent_pairs)
shuffle(incongruent_pairs)
shuffle(pairs)
#create a dictionary variable to hold the correct answer keys for each colour of the words 
answer_keys = {'f': 'red', 'g': 'blue', 'h': 'green', 'j': 'yellow'}

rts = []

#we want a full screen window with a black background to run the experiment on 
#CHANGE TO FULL SCREEN BEFORE SUBMITTING!!!
win = visual.Window([1024, 768], fullscr = False, \
                    allowGUI=True, units="pix", color = (-1, -1, -1))

stim = visual.TextStim(win)

instructionText = visual.TextStim(win, "Thank you for choosing to participate in this experiment. You will be presented with different names of colours. In some trials the colour of the word will match the name of the colour, in some the colour of the word \
                                  will be different to the name of the colour. Your task is to identify the colour of the word, ignoring the word itself. Coloured stickers on the keyboard in front of you correspond to the key you should press to indicate your response.\
                                  \
                                  \
                                  PRESS 'ENTER' TO CONTINUE", color=(1, 1, 1))
instructionText.draw()

win.flip()

event.waitKeys(keyList=['return'])
#create and prepare ready text so participant can prepare before experiment - repeat any instructions
readyText = visual.TextStim(win, "Ready?", color=(1, 1, 1))

readyText.draw()

#present ready text on the screen 
win.flip()

#wait for user to press return key 
event.waitKeys(keyList=['return'])





#iterate over the congruent pair list to present stimuli 
#NEED TO COMBINE CONGRUENT AND INCONGRUENT LISTS (STILL NEED TO REPORT WHICH LIST EACH TRIAL CAME FROM)
for pair in pairs:
        

    # Create a text stimulus
        stim.text = pair[0]
        stim.color = pair[1]


   # Draw the text stimulus
        stim.draw()
        event.clearEvents()
      
        displaytime = win.flip()
        
        

#list of keys the participant can press are those listed in the answer key dictionary
#want to record reaction time and whether they are answering correctly 
        
        key, rt = event.waitKeys(keyList=answer_keys.keys(), timeStamped=True)[0] 
        
      
        
        
        #WITH JUST TIMESTAMPED - IT RECORDS WHEN THE KEY WAS PRESSED IN TERMS OF THE WHOLE EXPERIMENT
        #NOT IN TERMS OF WHEN THE WORD WAS PRESENTED - TRY AND ALTER CODE SO IT DOES ACTUAL RT
        
        score = answer_keys[key] == pair[1]#means that the correct answer corresponds to the colour of the word
        
        
        #ABOVE WORKS TO RUN THROUGH THE PAIRS (combined list) - NEED TO NOW SAVE TO FILE 
        #this section displays feedback on whether the participant is correct or incorrect 
        #and their reaction time 
        #don't really need this - should adapt to save this info into the file not on the screen 
        stim.text = 'CORRECT!' if score else 'INCORRECT'
        stim.text += '\nRT=%i ms' %(rt*1000)
        stim.draw()
        win.flip()
        event.waitKeys()
        
        
        
        #NEED TO WORK OUT HOW TO SAVE THE DATA TO A CSV FILE
     
       
        




      #want a message to thank the participant for their time
thankYou = visual.TextStim(win, "Thank you for participating.", color=(1, 1, 1))

thankYou.draw()

#present it on the screen
win.flip()

#wait for user to press return key
event.waitKeys(keyList=['return'])



#close the window

win.close()
core.quit()  ```

Hi Amelia,

You have a lot of the details in place. But for ease of use, I’d suggest that you simply put your conditions into an external .csv or .xlsx file. i.e. it would have three columns and I think 120 rows (although you could be clever and have fewer rows and use the nReps value of the TrialHandler to repeat them multiple times):

condition     colour_text   colour_name
congruent     red           red      
incongruent   red           green
# etc etc

Then you create a TrialHandler object to read through that file, getting the conditions from each row to apply for each trial. The TrialHandler will also handle your randomisation for you, as well as saving all of the data to a data file (the values from the conditions file and the info dialog, as well as anything else you add manually). This will greatly reduce the amount of house-keeping code you currently have.

from psychopy import data, gui, core

#create a dictionary variable to hold the correct answer keys for each colour of the words 
answer_keys = {'f': 'red', 'g': 'blue', 'h': 'green', 'j': 'yellow'}

data = {'Expdate': datetime.now().strftime('%Y%m%d_%H%M'), 'ID': '', 'Age': '', 'Gender': ''}
dlg = gui.DlgFromDict(data, title='Input participant info', fixed='Expdate', order=['ID', 'Age', 'Gender','Expdate'])

if not dlg.OK:
    print("User exited")
    core.quit()
    
filename = 'part_{}_{}_{}_{}.csv'.format(data['ID'], data['Age'], data['Gender'], data['Expdate'])

# An ExperimentHandler isn't essential but helps with data saving:
thisExp = data.ExperimentHandler(name = 'Your expt', version='',
    extraInfo = expInfo, # include this info
    dataFileName = filename) # in this saved data file

# set up a loop handler to look after randomisation of conditions etc:
trials = data.TrialHandler(nReps = 1, method = 'random', 
    trialList = data.importConditions('your_conditions.csv'),
    name = 'trials')

thisExp.addLoop(trials)  # add the loop to the experiment

Now once you’ve set up your window and stimuli and so on, you just loop through the TrialHandler, which acts just like a list of dictionaries:

for thisTrial in trials:
    # display stimulus:
    stim.text = thisTrial['colour_text']
    stim.color = thisTrial['colour_name']
    stim.draw()
    displaytime = win.flip()

    # get response:
    key, rt = event.waitKeys(keyList = answer_keys.keys(), timeStamped = core.Clock())

    # save response in data file:
    thisExp.addData('rt', rt)
    thisExp.addData('response', key)
    # decide if response was correct:
    thisExp.addData('correct', answer_keys[key] == thisTrial['colour_name'])

    # now cycle to next trial automatically

# all done, so terminate the session.
# I think this will tell the expt handler to save the data as it shuts down:
core.quit()
1 Like

thank you very much, this has been so so helpful!

I have just tried running this code, editing it to input my own specified values e.g. my filenames etc. However, every time I try to run it, the experiment runs fine but the data does not save to the csv file. Only the headers save. Also, some of the headers are referring to things I do not recognise e.g. “trials.thisRepN”, “trials.thisTrialN”, “trials.thisN”, “trials.thisIndex”. Could you please explain to me what these mean and how I could remove them from the file? I only need trialnum, rt, response(key), correct(true/false), colour_text, colour_name, condition. Thanks again for the help! :slight_smile: