It appears that neither the escape key or return key are able to perform their jobs until after the user has made a mouse click somewhere on the screen. I think this has something to do with the event.Mouse() I call in order for the user to use the mouse wheel to provide a continuous rating of the video on screen. If anyone can point out what is happening, that would be much appreciated- or direct me to the documentation that will explain.
from psychopy import visual
from psychopy import gui, data, core,event
import csv
import time
from time import localtime, strftime, gmtime
from datetime import datetime
import os.path
# Kill switch for Psychopy3
esc_key= 'escape'
def quit():
""" quit programme"""
print ('User exited')
win.close()
core.quit()
# call globalKeys so that whenever user presses escape, quit function called
event.globalKeys.add(key=esc_key, func=quit)
# User should set cwd to the experiment directory
os.chdir('\\\\storage.its.york.ac.uk\\pshome\\blam500\\Downloads\\movie_study_0.8')
# User should set directory for output files to be stored
save_path= '\\\\storage.its.york.ac.uk\\pshome\\blam500\\Downloads\\movie_study_0.8\\output\\continuous'
# instructions for the task can be updated here
fear = """You will be presented with several videos.
\nThese videos will contain dangerous behaviour, strong language, disturbing images,threat and violence.If you find these types of videos distressing ,please do not participate and let the experimenter know.
\nIf at any point, you become distressed and would like to stop the task, please inform the experimenter.
You will not be penalised for withdrawing from the study.
\nPlease continuously rate how frightening you feel the video is moment-to-moment using the wheel of the mouse.
\nPress Enter to begin."""
uc = """You will be presented with several videos.
\nThese videos will contain dangerous behaviour, strong language, disturbing images,threat and violence.If you find these types of videos distressing ,please do not participate and let the experimenter know.
\nIf at any point, you become distressed and would like to stop the task, please inform the experimenter.
You will not be penalised for withdrawing from the study.
\nPlease continuously rate how uncertain you feel the threat in the video is moment-to-moment using the wheel of the mouse.
\nPress Enter to begin."""
# Create a dictionary to store information from the dialogue box
inputbox = {'expdate': datetime.now().strftime('%Y%m%d_%H%M'),'part_number':'','videoCondition':'','ratingCondition':''}
# Create dialogue box
# user enters participant number + video condition + rating required
dlg=gui.DlgFromDict(inputbox, title = 'Input participation info',
fixed='expdate',
order=['expdate', 'part_number','videoCondition','ratingCondition'])
# If the user doesn't press ok, the programme will quit and inform user.
if not dlg.OK:
print ("User exited")
core.quit()
# Store participant number, videoCondition, ratingCondition and expdate provided by user as variables for later use
part_number = inputbox['part_number']
videoCondition = inputbox['videoCondition']
expdate = inputbox['expdate']
ratingCondition = inputbox ['ratingCondition']
# create filename based on user input
filename = '{}_{}_{}_{}.csv'.format(part_number, expdate, videoCondition,ratingCondition)
# update filename to include absolute path so that it is stored in output directory
completeName = os.path.join(save_path, filename)
# open file for writing
outputfile = open(completeName, "w",newline='')
# Create list of headers for output csv file
fieldnames = ['videoName','Timestamp', 'Rating']
# create variable which calls DictWriter to write to outputfile and specifies fieldnames
writer = csv.DictWriter(outputfile, fieldnames)
# writes headers using fieldnames as specified above when creating writer variable
writer.writeheader()
#function to present break and end screen
def break_end(video_name, participant_number, last=0):
# Present break screen at the end of each set of questions
if last==0:
stim.setText("""You are welcome to take a break if you need to.
\nPress enter when you are ready to continue.""")
stim.draw()
win.flip()
# Wait for user to press Return to continue
key = event.waitKeys(keyList=(['return']), timeStamped = True)
else:
# Presents end screen at the end of task
stim.setText("""You have reached the end of the experiment.
\nPlease let the experimenter know you have finished.
\nThank you for your participation.""")
stim.draw()
win.flip()
# Waits for user to press escape to exit experiment
key = event.waitKeys(keyList=(['return']), timeStamped = True)
# Create white window for stimuli to be presented on throughout task
win = visual.Window(size=[1024, 768], color=[1,1,1,], monitor="testMonitor", fullscr= True, allowGUI = False)
# Create text stimuli to be updated for start screen, break and end
stim = visual.TextStim(win, "", color = [-1,-1,-1], wrapWidth = 1300, units = "pix", height=40)
# Use trialhandler to sequentially present films listed in filmlist csv file
filmDict = data.TrialHandler(nReps = 1, method = 'sequential', trialList = data.importConditions('references\\filmList.csv'), name = 'filmList')
# Create sliding scale to take continuous rating of uncertainty or fear while movie plays
if ratingCondition == 'uc':
slidingscale = visual.Slider(win, ticks = [0,100], labels = ['certain', 'uncertain'], pos = (0.0, -0.7), granularity = 0)
elif ratingCondition == 'f':
slidingscale = visual.Slider(win, ticks = [0,100], labels = ['frightening', 'not frightening'], pos = (0.0, -0.7), granularity = 0)
# Name mouse to be able to use for continuous rating below
mouse = event.Mouse()
# Update and show text to include instructions for task depending on rating condition entered in inputbox
if ratingCondition == 'f':
stim.setText(fear)
stim.draw()
win.flip()
# Wait for user to press Return to continue
key = event.waitKeys(keyList=(['return']), timeStamped = True)
else:
stim.setText(uc)
stim.draw()
win.flip()
# Wait for user to press Return to continue
key = event.waitKeys(keyList=(['return']), timeStamped = True)
# Loop through each film stored in filmDict created above using trialhandler
for film in filmDict:
# Store video name in thisRunDict to write to outputfile
thisRunDict= {'videoName': film[videoCondition] }
# present movie using moviestim3
mov = visual.MovieStim3 (win, film[videoCondition], size=(720,480), flipVert=False, flipHoriz=False, loop=False) #TO DO: fix size of video
# create a clock at the start of movie presentation
clock = core.Clock()
clock.reset()
# set position of marker to middle of slider at the start of each video
slidingscale.markerPos = 50
# create variable to use in loop to record rating every n seconds
rtscaleframe = 0
# While moving is playing, present slidingscale and record marker position and timestamp in outputfile
while mov.status != visual.FINISHED:
slidingscale.markerPos += mouse.getWheelRel()[1] # move marker according to mouse wheel movement
slidingscale.draw()
mov.draw()
win.flip()
# Run every 0.5 sec
if rtscaleframe % 30 == 0:
rating = slidingscale.markerPos # store marker position as rating
thisRunDict['Rating'] = str(rating) # store rating in thisRunDict to write to outputfile
thisRunDict['Timestamp'] = str(clock.getTime()) # store Timestamp of video to write to outputfile
# write responses and timings stored in thisRunDict to outputfile
writer.writerows([thisRunDict])
rtscaleframe += 1 # needed to collect rating every 0.5 sec
# If statement to either present break screen or end screen
nextTrial = filmDict.getFutureTrial(n=1) #fixes error for end screen
if nextTrial is None or nextTrial[videoCondition] != None:
break_end(film[videoCondition], part_number)
else:
break_end(film[videoCondition], part_number,1)
outputfile.flush()