Hi Jon,
Thank you for your reply.
I’ve programmed it such that both the image and the video are set during a 2s ISI before the trial. I do this in the pre-trial ISI instead of at the beginning of the experiment because I’m reading in movie and png filenames from a conditions xlsx file for each trial.
Per your suggestion I coded up a simpler version of the experiment, using only one video. Now it (visually) seems to have the correct timing. I will test with a photodiode next.
Is there a difference between initiating a video object (here called ‘movie’) directly referencing the filename (see simple version below) compared to referencing a variable pulled from a condition file (see snippet from original version)? Or, are there other ways to preload video’s than using movie.setmovie during the static period?
Simple version of my code that seems to work:
movie = visual.MovieStim3(
win=win, name=‘movie’,
noAudio = True,
filename=u’Clips/FieldLate30_lowres.mov’,
ori=0, pos=(0, 0), opacity=1,
size=[960,540],
depth=-3.0,
)
# keep track of which components have finished
trialComponents = [text, ISI, movie, image]
for thisComponent in trialComponents:
if hasattr(thisComponent, ‘status’):
thisComponent.status = NOT_STARTED
# -------Start Routine "trial"-------
while continueRoutine:
# get current time
t = trialClock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *text* updates
if t >= 0.0 and text.status == NOT_STARTED:
# keep track of start time/frame for later
text.tStart = t
text.frameNStart = frameN # exact frame index
text.setAutoDraw(True)
# *movie* updates
if frameN >= MovStartFrame and movie.status == NOT_STARTED:
# keep track of start time/frame for later
movie.tStart = t
movie.frameNStart = frameN # exact frame index
movie.setAutoDraw(True)
if movie.status == FINISHED: # force-end the routine
continueRoutine = False
# *image* updates
if frameN >= StimStartFrame and image.status == NOT_STARTED:
# keep track of start time/frame for later
image.tStart = t
image.frameNStart = frameN # exact frame index
image.setAutoDraw(True)
if image.status == STARTED and frameN >= (image.frameNStart + StimDurFrame):
image.setAutoDraw(False)
# *ISI* period
if t >= 0.0 and ISI.status == NOT_STARTED:
# keep track of start time/frame for later
ISI.tStart = t
ISI.frameNStart = frameN # exact frame index
ISI.start(ISI_dur)
elif ISI.status == STARTED: # one frame should pass before updating params and completing
# updating other components during *ISI*
movie.setOpacity(1)
movie.setMovie(u'Clips/FieldLate30_lowres.mov')
movie.setPos((0, 0))
movie.setOri(0)
movie.setSize([960,540])
image.setOpacity(1)
image.setPos((200, 100))
image.setOri(0)
image.setImage(u'frog.png')
image.setSize((100, 100))
# component updates done
ISI.complete() # finish the static period
# check if all components have finished
if not continueRoutine: # a component has requested a forced-end of Routine
break
continueRoutine = False # will revert to True if at least one component still running
for thisComponent in trialComponents:
if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
continueRoutine = True
break # at least one component has not yet finished
# check for quit (the Esc key)
if endExpNow or event.getKeys(keyList=["escape"]):
core.quit()
# refresh the screen
if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
win.flip()
# -------Ending Routine "trial"-------
for thisComponent in trialComponents:
if hasattr(thisComponent, "setAutoDraw"):
thisComponent.setAutoDraw(False)
Code snippet from the original version that has large timing errors:
# ------Prepare to start Routine "trial"-------
t = 0
trialClock.reset() # clock
frameN = -1
continueRoutine = True
# update component parameters for each repeat
movie = visual.MovieStim3(
win=win, name='movie',units='pix',
noAudio = True,
filename=vidName, #from conditions file
ori=0, pos=[0, 0], opacity=1,
size=[960, 540],
depth=-2.0,
)
key_resp_4 = event.BuilderKeyResponse()
# In seconds
ISI_dur = 2. + random.uniform(0,jitter)
#MovStart = ISI_dur
#StimStart = DelaySecs + MovStart
# Convert seconds to frames
ISI_dur_frames = int(ISI_dur*FrameRate2) # int will round down to nearest integer
MovStartFrame = 1 # starts counting after ISI ends!
Key_frames_dur = int(3*FrameRate2) # now set to full length of video
StimStartFrame = MovStartFrame + int(DelaySecs*FrameRate2)
StimDurFrame = int(StimDur*FrameRate2)
polyFramesDur = int(polyDur * FrameRate2)
FixationFrames = ISI_dur_frames + Key_frames_dur
print(ISI_dur_frames)
# keep track of which components have finished
trialComponents = [ISI, Fixation, movie, Target]
for thisComponent in trialComponents:
if hasattr(thisComponent, 'status'):
thisComponent.status = NOT_STARTED
# -------Start Routine "trial"-------
while continueRoutine:
# get current time
t = trialClock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *Fixation* updates
if frameN >= 0 and Fixation.status == NOT_STARTED:
# keep track of start time/frame for later
Fixation.tStart = t
Fixation.frameNStart = frameN # exact frame index
Fixation.setAutoDraw(True)
if Fixation.status == STARTED and frameN >= (Fixation.frameNStart + FixationFrames):
Fixation.setAutoDraw(False)
# *movie* updates
if frameN >= MovStartFrame and movie.status == NOT_STARTED:
# keep track of start time/frame for later
movie.tStart = t
movie.frameNStart = frameN # exact frame index
movie.setAutoDraw(True)
if movie.status == FINISHED: # force-end the routine
continueRoutine = False
# check for quit:
if "escape" in theseKeys:
endExpNow = True
if len(theseKeys) > 0: # at least one key was pressed
key_resp_4.keys.extend(theseKeys) # storing all keys
key_resp_4.rt.append(key_resp_4.clock.getTime())
# *Target* updates
if frameN >= StimStartFrame and Target.status == NOT_STARTED:
# keep track of start time/frame for later
Target.tStart = t
Target.frameNStart = frameN # exact frame index
Target.setAutoDraw(True)
if Target.status == STARTED and frameN >= (Target.frameNStart + StimDurFrame):
Target.setAutoDraw(False)
# *ISI* period
if frameN >= 0 and ISI.status == NOT_STARTED:
# keep track of start time/frame for later
ISI.tStart = t
ISI.frameNStart = frameN # exact frame index
ISI.start(ISI_dur_frames*frameDur)
elif ISI.status == STARTED: # one frame should pass before updating params and completing
# updating other components during *ISI*
movie.setOpacity(1)
movie.setMovie(vidName)
movie.setPos([0, 0])
movie.setOri(0)
movie.setSize([960, 540])
Target.setOpacity(1)
Target.setPos(TargetLocation)
Target.setOri(0)
Target.setImage(TargetStim)
Target.setSize((60, 60))
# component updates done
ISI.complete() # finish the static period