Saving data from GUI input

Hello! I am a complete beginner with Psychopy and Python so please bare with me if this is very basic.
I am asking participants to fill in some experiment-relevant information using a gui with this code:

import psychopy.gui

gui = psychopy.gui.Dlg()
gui.addField("SubjectID:")
gui.addField("Name:")
gui.addField("Age:")

gui.show()

sub_ID = gui.data[0]
name = gui.data[1]
age = gui.data[2]

This is probably incredibly basic, but how do I get this information to save in an excel format? There may also be a much easier/logical way to save this information!

When in doubt, compile a Builder experiment to a .py file and see how it does things. Even a blank Builder file would show this code:

from psychopy import gui

# Store info about the experiment session
psychopyVersion = '3.2.3'
expName = 'untitled'  # from the Builder filename that created this script
expInfo = {'participant': '', 'session': '001'}
dlg = gui.DlgFromDict(dictionary=expInfo, sortKeys=False, title=expName)
if dlg.OK == False:
    core.quit()  # user pressed cancel
expInfo['date'] = data.getDateStr()  # add a simple timestamp
expInfo['expName'] = expName
expInfo['psychopyVersion'] = psychopyVersion

i.e. create a dictionary holding the fields of info you want, and feed that to the gui.DlgFromDict() function. That way you still have access to the dictionary afterwards, and can read or add values to it by name.

Lastly, to save the data, it is easiest just to pass this dictionary to your ExperimentHandler or TrialHandler class that you will likely use to run your trials. That means that all of these fields will be saved automatically in each row of your data output file:

https://www.psychopy.org/api/data.html

Again, look into a Builder-generated file to see how an expInfo dictionary can be passed to one of these classes, or look into the relevant demos from the Coder-view Demos menu. (demos -> experiment control - > )

1 Like

Thank you so much this has been so kind of you to reply.

I have written the following code, I am able to create the excel spreadsheet using the variables I am interested in, however the inputed values aren’t being saved as part of the data file - I think I need to add a step before the ‘addData’ section, but I can’t quite tell what that would be!

import psychopy.gui
from psychopy import gui, data

info = {'SubjectID': '','Name': '','Age': ''}
infoDlg = gui.DlgFromDict(dictionary=info, title='Naming Info')
if infoDlg.OK:  
    pass

namingFilename = 'namingdata/' + info['SubjectID'] + '_NAMING PHASE DATA' 
nameData = data.ExperimentHandler(name='namingdata', 
                version='3.2.3',
                extraInfo=info,
                runtimeInfo=None,
                originPath=None,
                savePickle=False,
                saveWideText=True,
                dataFileName=namingFilename)

nameData.addData('Name', condition['Name'])
nameData.addData('Age', condition['Age'])

The way that the ExperimentHandler and TrialHandler classes work is that they save a row of data for every trial. You’re not seeing any content in your data file at this stage, because there haven’t been any actual trials run - the experiment has ended without doing anything, so there is no data to record.

However, by passing the info dictionary to one of the handler classes, the fields in it will be automatically written on every row of data. So you don’t need to manually use .addData for those variables - they will be handled for you automatically. Here is an example just using a TrialHandler:

import psychopy.gui
from psychopy import gui, data, core
from numpy.random import random

info = {'SubjectID': '007','Name': 'JB','Age': '99'}
infoDlg = gui.DlgFromDict(dictionary=info, title='Naming Info')
if not infoDlg.OK:  
    core.quit()

namingFilename = 'namingdata/' + info['SubjectID'] + '_NAMING PHASE DATA.csv'

# create some junk experimental conditions:
conditions = [{'colour': 'red', 'ITI': 0.5}, {'colour': 'blue', 'ITI': 1.0}] * 10
trials = data.TrialHandler(trialList = conditions, nReps = 1, extraInfo = info)

# now actually runs some trials:
for trial in trials:
    # pretend to show stimuli:
    print(f'Trial number: {trials.thisN}')
    # simulate some trial data:
    trials.addData('reaction_time', random())

# now explicitly save the data (although can happen automatically).
# Will include not just the RT variable but automatically also the 
# experimental conditions and info fields:
trials.saveAsWideText(namingFilename)
1 Like