Hi all,
I have an issue with slow write speeds at the end of my experiments. When the experiment and window closes I go back to the coder view, and there can be a very long lag while the various different events are displayed in the output window, and written to txt and csv files. Is there anything I can do in the way I have structured the experiment handler to speed this up?
I have a range of different experiments with this issue, below is an example of the simplest one.
FYI running this in Win 10, dell laptop, 16gb ram, i7, running an old version of Psychopy 1.90.3
Thanks!
George
from __future__ import absolute_import, division
import pandas as pd # these are for reading from excel files
import random, os, glob, pylab
from psychopy import visual, logging, core, event, data , sound, gui,locale_setup# import some libraries from PsychoPy
from psychopy.constants import (NOT_STARTED, STARTED, PLAYING, PAUSED,STOPPED, FINISHED, PRESSED, RELEASED, FOREVER)
import numpy as np # whole numpy lib is available, prepend 'np.'
from numpy import (sin, cos, tan, log, log10, pi, average,sqrt, std, deg2rad, rad2deg, linspace, asarray)
from numpy.random import random, randint, normal, shuffle # you can either just import random, then call random.shuffle or you can import the specific elements of random, e.g. shuffle, then you can just call shuffle
import os # handy system and path functions
import sys # to get file system encoding
import csv #useful for handling csv files
# Ensure that relative paths start from the same directory as this script
_thisDir = os.path.dirname(os.path.abspath(__file__)).decode(sys.getfilesystemencoding())
os.chdir(_thisDir)
rtimer=core.Clock()
trialtimer=core.Clock()
########################################################### Experiment handler #######################################################################
# Store info about the experiment session
expName = u'PVT' # from the Builder filename that created this script
expInfo = {'participant':'', 'session':'001'}
dlg = gui.DlgFromDict(dictionary=expInfo, title=expName)
if dlg.OK == False:
core.quit() # user pressed cancel
expInfo['date'] = data.getDateStr() # add a simple timestamp
expInfo['expName'] = expName
# Data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc
filename = _thisDir + os.sep + u'data/%s_%s_%s' % (expInfo['participant'], expName, expInfo['date'],)+'_PVT'
# An ExperimentHandler isn't essential but helps with data saving
thisExp = data.ExperimentHandler(name=expName, version='',extraInfo=expInfo, runtimeInfo=None,originPath=None,savePickle=False, saveWideText=True,dataFileName=filename)
########################################################### GLOBAL VARIABLES #######################################################################
# set your parameters here
totalloops = 30
imsize = 7 # size of the images
instrtextsize=1 # instruction text size
textsize = 3 # size of the text
########################################################### Window settings #######################################################################
#create a window
mywin = visual.Window(fullscr=True, monitor="dell", units="deg", color =[1,1,1],autoLog=False)# to set a window use size [800,600] and remove the fullscr arguement, you can choose "deg" = visual angle, or "pix" for pixels, this then use the approp units in your image defs below
mywin.setMouseVisible(False)# stops the mouse appearing ontop
# save a log file for detail verbose info
logFile = logging.LogFile(filename+'.log', level=logging.EXP)
########################################################### Instructions and text #######################################################################
#Define instruction presenter
def instpres(string):
IS=visual.TextStim(win=mywin, color='black', height=(instrtextsize), text=string, alignHoriz='center',wrapWidth=18,autoLog=False,font='verdana')# this is alignment to the screen not the text alignment, irritatingly
IS.draw()
mywin.flip()
core.wait(3)#prevent accidental presses.
#wait for response
responsegiven=False
while not responsegiven:
for key in event.getKeys(): ##EJD: I've removed "space" because (from the below code) you want to collect all key presses
if key in (['escape']):
mywin.close()
core.quit()
elif key in (['space']):
responsegiven=True
def stopwatch(string):
IS=visual.TextStim(win=mywin, color='black', height=(textsize), text=string, alignHoriz='center',autoLog=False, font='verdana')
pictureframe.draw()
pictureframe_inner.draw()
IS.draw()
mywin.flip()
def timer(string):
IS=visual.TextStim(win=mywin, color='black', height=(textsize), text=string, alignHoriz='center',wrapWidth=30,autoLog=False, font='verdana')
pictureframe.draw()
pictureframe_inner.draw()
IS.draw()
mywin.flip()
core.wait(1)
def fa(string):
IS=visual.TextStim(win=mywin, color='black', height=(instrtextsize), text=string, alignHoriz='center',wrapWidth=30,autoLog=False,font='verdana')# this is alignment to the screen not the text alignment, irritatingly
pictureframe.draw()
pictureframe_inner.draw()
IS.draw()
mywin.flip()
core.wait(1)
########################################################### Image set generation #######################################################################
# fixation square,
pictureframe = visual.Rect(mywin, width=(imsize+1), height=(imsize+1),opacity=1,fillColor='black',autoLog=False)
pictureframeISI = visual.Rect(mywin, width=(imsize+1), height=(imsize+1),opacity=1,fillColor='white',autoLog=False)#extra frame for 2AFC task
pictureframe_inner = visual.Rect(mywin, width=(imsize), height=(imsize),opacity=1,fillColor='white',autoLog=False)
#play the first instructions
instpres('Press the space bar as soon as you see the numbers appear\n\n\
The next three trials are practice trials\n\n\
Press the space bar to begin when you are ready')
#pause before trial starts
mywin.flip()
core.wait(3)
c=0
reactiontime=[]
########################################################### practice #######################################################################
while c < (3):
pictureframe.draw()
pictureframe_inner.draw()
rtimer.reset()
mywin.flip()
responsegiven=False
while not responsegiven:
rt=rtimer.getTime()# get rt
stopwatchdisp=str(round(rt, 1))
stopwatch(stopwatchdisp)
for key in event.getKeys():
if key in (['escape']): # if one of the key presses has been escape then quit
mywin.close()
core.quit()
elif key in (['space']): # if it matches the response
responsegiven=True
rt=rtimer.getTime()# get rt
rtdisp=str(round(rt, 1))# round the rt to 1 decimal place
timer(rtdisp)# display the rt with a 1sec pause
pictureframe.draw()
pictureframe_inner.draw()
#mywin.logOnFlip('ISI', level=logging.EXP)
mywin.flip()
ISI=randint(2,10)# generate a random ISI bw 2 and 10s long
for frameN in range(ISI*60): # ISI times 60 frames (1s)
pictureframe.draw()
pictureframe_inner.draw()
#mywin.logOnFlip('ISI', level=logging.EXP)
mywin.flip()
for key in event.getKeys():
if key in (['space']):
fa('false start!')
c+=1
########################################################### PVT #######################################################################
#play the first instructions
instpres('Now we are ready to begin the experiment. \n\n\
Press the space bar as soon as you see the numbers appear\n\n\
Press the space bar to begin when you are ready')
#pause before trial starts
mywin.flip()
core.wait(3)
c=0
reactiontime=[]
trialtimer.reset()# start a timer to measure the total duration
while c < (totalloops):
pictureframe.draw()
pictureframe_inner.draw()
rtimer.reset()
mywin.flip()
responsegiven=False
while not responsegiven:
rt=rtimer.getTime()# get rt
stopwatchdisp=str(round(rt, 1))
stopwatch(stopwatchdisp)
for key in event.getKeys():
if key in (['escape']): # if one of the key presses has been escape then quit
mywin.close()
core.quit()
elif key in (['space']): # if it matches the response
responsegiven=True
memresponses='hit'# add the response to the list
thisExp.addData('memresponses',memresponses) # this saves each trial as to whether they got it right or wrong
rt=rtimer.getTime()# get rt
rtdisp=str(round(rt, 1))# round the rt to 1 decimal place
timer(rtdisp)# display the rt with a 1sec pause
reactiontime.append(rt)# add it to the list
thisExp.addData('reactiontime', reactiontime[-1])#write it to logfile
thisExp.nextEntry()#move to next line
ISI=randint(2,10)# generate a random ISI bw 2 and 10s long
rtimer.reset()# record how long the ISI is for each trial just in case you ever need it
for frameN in range(ISI*60): # ISI times 60 frames (1s)
pictureframe.draw()
pictureframe_inner.draw()
#mywin.logOnFlip('ISI', level=logging.EXP)
mywin.flip()
for key in event.getKeys():
if key in (['space']):
fa('false start!')
memresponses='false alarm'# add the response to the list
thisExp.addData('memresponses',memresponses) # this saves each trial as to whether they got it right or wrong
rt=rtimer.getTime()# get rt
reactiontime.append(rt)# add it to the list
thisExp.addData('reactiontime', reactiontime[-1])#write it to logfile
thisExp.nextEntry()#move to next line
memresponses='ISI'# add the response to the list
thisExp.addData('memresponses',memresponses) # this saves each trial as to whether they got it right or wrong
rt=rtimer.getTime()# get rt
reactiontime.append(rt)# add it to the list
thisExp.addData('reactiontime', reactiontime[-1])#write it to logfile
thisExp.nextEntry()#move to next line
c+=1
memresponses='total time'# add the response to the list
thisExp.addData('memresponses',memresponses) # this saves each trial as to whether they got it right or wrong
rt=trialtimer.getTime()# get rt
reactiontime.append(rt)# add it to the list
thisExp.addData('reactiontime', reactiontime[-1])#write it to logfile
thisExp.nextEntry()
thisExp.close()
instpres('Thank you\n\n\
Please wait for your next instruction')
mywin.close()