Jessica C
Jessica C

Reputation: 31

How to output data to file?

So i am trying to write a Stroop experiment from scratch. Ideally this is how i could like the experiment to be set up:

  1. Enter participant information
  2. Instruction pages (click x to continue)
  3. Instruction page 2 (click x to continue)
  4. Experiment Start
  5. Break between trial
  6. Experiment trial 2
  7. End

(there will be more than 2 trials but for testing just 2 will be used)

I'm having difficulty writing the data to a text file. The second trial records perfectly with the different values per each loop. However the first trial shows up as duplicates and each trial has the same values in the text file.

In addition, i can't figure out how to write the data from the pop-up into my text file. (ie. subject name, age, id)

Also is there a way I can input the file name each time? Without changing code? -perhaps like a popup to choose the path and file name?

Thank you!

from psychopy import visual, core
import random
import time
import datetime
import sys
from psychopy import gui
from psychopy import event



#Write to file, need to figure out how to choose file name in each instance
file = open ("Test Output.txt", 'w')


#Pop up subject information - need to figure out how to output this data
myDlg = gui.Dlg(title="TEST TEXT BOX")
myDlg.addText('Subject info')
myDlg.addField('Name:')
myDlg.addField('Age:', )
myDlg.addText('Experiment Info')
myDlg.addField('Subject ID', "#" )
myDlg.addField('Group:', choices=["Test", "Control"])
ok_data = myDlg.show()
if myDlg.OK:
    print(ok_data)
else:
    print('user cancelled')

#opens up window w/ text, 
win = visual.Window([800,800],monitor="testmonitor", units="deg")
msg = visual.TextStim(win, text="Hello")
msg.draw()
win.flip()
event.waitKeys(maxWait=10, keyList=None, timeStamped=False) #page remains until keyboard input, or max of 10 seconds

#with keyboard input, second screen will come up
msg = visual.TextStim(win, text="Instructions 1")
msg.draw()
win.flip()
event.waitKeys(maxWait=10, keyList=None, timeStamped=False)

#3rd screen will pop up with keyboard input
msg = visual.TextStim(win, text="Trial 1")
msg.draw()
win.flip()
event.waitKeys(maxWait=10, keyList=None, timeStamped=False)


#Trial starts,
for frameN in range(5):
    MyColor = random.choice(['red','blue','green','yellow'])
    Phrase = random.choice(["Red","Green", "Blue", "Yellow"])
    time = str(datetime.datetime.now())
    key = str(event.getKeys(keyList=['1','2','3','4','5'], ))
    pause = random.randint(1200,2200)/1000.0
    length = str(pause)
    msg = visual.TextStim(win, text=Phrase,pos=[0,+1],color=MyColor)
    msg.draw()
    win.flip()
    core.wait(pause)


msg = visual.TextStim(win, text="Break between trial")
msg.draw()
win.flip()
event.waitKeys(maxWait=10, keyList=None, timeStamped=False)

#trial 2
for frameN in range(5):
    MyColor2 = random.choice(['red','blue','green','yellow'])
    Phrase2 = random.choice(["Red","Green", "Blue", "Yellow"])
    time2 = str(datetime.datetime.now())
    key2 = str(event.getKeys(keyList=['1','2','3','4','5'], ))
    pause2 = random.randint(1200,2200)/1000.0
    length2 = str(pause2)
    msg = visual.TextStim(win, text=Phrase2,pos=[0,+1],color=MyColor2)
    msg.draw()
    win.flip()
    core.wait(pause2)

#specifying which data will be recorded into the file
    data = "Stimuli:"+ MyColor + ',' + Phrase + ','+  time + ',' + key + ',' + length + MyColor2 + ',' + Phrase2 + ','+  time2 + ',' + key2 + ',' + length2

    file.write(data  + '\n')









#Jessica's Code.

Upvotes: 1

Views: 1157

Answers (2)

Michael MacAskill
Michael MacAskill

Reputation: 2421

You should really consider using the TrialHandler and/or ExperimentHandler classes that are built into PsychoPy: they have solved this (and many more issues) for you already. You don't need to re-invent the wheel.

i.e. define the trial parameters (in your case, colours and phrases) and feed them to the TrialHandler when it is created. It will then automatically cycle through each trial (in sequence or randomly, as required), and handle saving the data for you in structured files automatically. Data gathered from the experiment info dialog is saved with the data, as the dictionary of info gathered from the dialog can be passed as the extraInfo parameter when a TrialHandler or ExperimentHandler is created.

The PsychoPy data API is here: http://www.psychopy.org/api/data.html and there are examples of using the TrialHandler and ExperimentHandler under the Demosexp control menu. Or examine any simple Builder-generated code for an experiment which contains a loop. For example, the Builder Stroop demo ;-) Builder code is quite verbose, but just look at the part where the Trial/Experiment handlers are created and how the experimental loop is controlled.

Upvotes: 1

Kush
Kush

Reputation: 1036

Have you considered using command line arguments? This would let you pass in file names at the start of your script. For example:

python myscript.py InputFile1 InputFile2 OutputFile1 OutputFile2

There is a really nice module that does a lot of the heavy lifting for you called argparse: https://docs.python.org/3/library/argparse.html

Here is a tutorial that the docs provide if you are a little intimidated: https://docs.python.org/3/howto/argparse.html

If you need Python 2 documentation, you can just change the 3 into a 2 in the URL. Here is a little code sample to show you what you can do with it as well:

import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", required = True, help = "Path to input file")
ap.add_argument("-o", "--output", required = True, help = "Path to output file")
args  = vars(ap.parse_args())

print(args["input"])
print(args["output"])

You then can call this from your terminal to pass your file locations (or whatever else you want to pass):

python myscript.py -i File1.txt -o File2.txt

You will then get the following output from the two print statements in the code above:

File1.txt
File2.txt

So you can now use args["input"] and args["output"] to tell your program where it needs to get its input and output from without directly putting it in your code.

Upvotes: 0

Related Questions