Hi,
This is just an issue of needing to consider what happens within each loop. e.g. some things are constant and shouldn’t be in a loop at all. Other things change once per iteration of the for thisTrial in trials:
loop (i.e. once per trial), while other things need to happen once per iteration of the while mov.status != visual.FINISHED:
loop (i.e. once per screen refresh).
These things don’t change and so should happen before the trial loop even starts, so they just happen once:
currentLoop = trials # you don't refer to this variable
# anyway so it could probably just be dropped entirely.
Nothing about the movies changes, so you should just create two of them in advance, and use the correct one as required. This is particularly because creating movies is time-expensive, so ideally should be done outside of your trials, as it can cause delays and slow downs:
left_mov = visual.MovieStim3(win, 'Left_Turn.mp4', size=(800, 800), flipVert=False, flipHoriz=False, loop=False)
right_mov = visual.MovieStim3(win, 'Right_Turn.mp4', size=(800, 800), flipVert=False, flipHoriz=False, loop=False)
Then inside your trial loop, you just do this, which avoids re-creating the movies (instead, you just point your mov
variable to the required movie stimulus):
if turn == 'left':
mov = left_mov
and
elif turn == 'right':
mov = right_mov
Lastly, the issue with no being able to exit the trial is that you only check the keyboard once per trial, before the movie even starts playing. So if someone pushed a key during the movie, it wouldn’t be detected. So check the keyboard during the movie drawing loop (i.e. once per screen refresh):
while mov.status != visual.FINISHED:
mov.draw()
win.flip()
keys = event.getKeys() # needs to be done here
if keys:
# do whatever
Lastly, you are doubling up on converting types, e.g.
turn = str(thisTrial[u'turn']) # turn it into a string
print('angle:', angle) # print it
mov.setOri(int(angle)) # turn it back into an integer
Instead you could just do this:
angle = thisTrial['angle'] # no need to convert if it is already a number
print(f'angle:{angle}') # no need to convert in a formatted string (Python 3 only)
mov.setOri(angle) # use it directly as a number
Even angle = thisTrial['angle'])
may be unnecessary if you are using a TrialHandler
, as it will probably automatically do that for you.
Lastly lastly, notice also that by using just one variable for the movie name, you can remove the duplication of code. So here is a rough attempt at revising all of that code, taking into account the above suggestions:
# prepare for the trials:
left_mov = visual.MovieStim3(win, 'Left_Turn.mp4', size=(800, 800), flipVert=False, flipHoriz=False, loop=False)
right_mov = visual.MovieStim3(win, 'Right_Turn.mp4', size=(800, 800), flipVert=False, flipHoriz=False, loop=False)
currentLoop = trials # doesn't seem to be necessary
rt = [] # not used and probably better to use the TrialHandler to store data
#starting the trials
for thisTrial in trials:
# probably unnecessary if using a TrialHandler:
turn = thisTrial['turn']
angle = thisTrial['angle']
print(f'angle: {angle}')
print(f'turn: {turn}')
if turn == 'left':
mov = left_mov
else:
mov = right_mov
globalClock = core.Clock() # not sure why this is being set here (and unused)
mov.setOri(angle)
while mov.status != visual.FINISHED:
mov.draw()
win.flip()
keys = event.getKeys(keyList = ['esc', 'left', 'right']) # restrict the possible keys
if keys:
print(keys[0])
if keys[0] == 'esc':
shutdown()
elif keys[0] == turn: # only one check needed now
corr = 1
else: # must be wrong, whether left or right
corr = 0
# NB need to store this in the data, easy if using a TrialHandler:
trials.addData('correct', core)
mov.status = visual.FINISHED
Hopefully that is much more readable now and plainly contains less duplication.
Lastly lastly lastly, this sort of code:
# Proceed to next trial
trialnum += 1
thisTrial = trials.trialList[trialnum]
is unnecessary in Python for
loops. The line for thisTrial in trials:
does everything for you automatically and you don’t need to count iteration numbers like you do in many other languages. Python simply iterates over your list of trials (hopefully you are using a PsychoPy TrialHandler
object for that purpose).