psychopy.org | Reference | Downloads | Github

Slow write speed at end of experiment

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()