Hello again Jon, no worries at all. We use PsychoPy extensively and the PsychoPy community is always helpful, so happy to help whenever the opportunity arises 
So, I did a bit more troubleshooting and have 2 key things to highlight that might help you troubleshoot more specifically,
- Movie component and when it is set
So, to the working version (0.75 s gap, no static component, and both, image and movie, set to every repeat), all I added was a) a static component for the same duration and, b) set both, image and movie, to load during the ISI period. This is as below,
Interestingly, when I compiled the script for this, I noticed an anomaly. The ‘trial’ component of the script is below,
for thisBlock1 in Block1:
currentLoop = Block1
# abbreviate parameter names if possible (e.g. rgb = thisBlock1.rgb)
if thisBlock1 != None:
for paramName in thisBlock1:
exec('{} = thisBlock1[paramName]'.format(paramName))
# ------Prepare to start Routine "trial"-------
t = 0
trialClock.reset() # clock
frameN = -1
continueRoutine = True
routineTimer.add(4.000000)
# update component parameters for each repeat
GridStimulus = visual.MovieStim3(
win=win, name='GridStimulus',
noAudio = True,
filename=StimulusMovie,
ori=0, pos=[0, 0], opacity=1,
loop=False,
depth=-2.0,
)
Resp = keyboard.Keyboard()
# keep track of which components have finished
trialComponents = [ISI, BiasImageCue, GridStimulus, Resp, p_port]
for thisComponent in trialComponents:
thisComponent.tStart = None
thisComponent.tStop = None
thisComponent.tStartRefresh = None
thisComponent.tStopRefresh = None
if hasattr(thisComponent, 'status'):
thisComponent.status = NOT_STARTED
# -------Start Routine "trial"-------
while continueRoutine and routineTimer.getTime() > 0:
# 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
# *BiasImageCue* updates
if t >= 0.75 and BiasImageCue.status == NOT_STARTED:
# keep track of start time/frame for later
BiasImageCue.tStart = t # not accounting for scr refresh
BiasImageCue.frameNStart = frameN # exact frame index
win.timeOnFlip(BiasImageCue, 'tStartRefresh') # time at next scr refresh
BiasImageCue.setAutoDraw(True)
frameRemains = 0.75 + .75- win.monitorFramePeriod * 0.75 # most of one frame period left
if BiasImageCue.status == STARTED and t >= frameRemains:
# keep track of stop time/frame for later
BiasImageCue.tStop = t # not accounting for scr refresh
BiasImageCue.frameNStop = frameN # exact frame index
win.timeOnFlip(BiasImageCue, 'tStopRefresh') # time at next scr refresh
BiasImageCue.setAutoDraw(False)
# *GridStimulus* updates
if t >= 2 and GridStimulus.status == NOT_STARTED:
# keep track of start time/frame for later
GridStimulus.tStart = t # not accounting for scr refresh
GridStimulus.frameNStart = frameN # exact frame index
win.timeOnFlip(GridStimulus, 'tStartRefresh') # time at next scr refresh
GridStimulus.setAutoDraw(True)
frameRemains = 4 - win.monitorFramePeriod * 0.75 # most of one frame period left
if GridStimulus.status == STARTED and t >= frameRemains:
# keep track of stop time/frame for later
GridStimulus.tStop = t # not accounting for scr refresh
GridStimulus.frameNStop = frameN # exact frame index
win.timeOnFlip(GridStimulus, 'tStopRefresh') # time at next scr refresh
GridStimulus.setAutoDraw(False)
if GridStimulus.status == FINISHED: # force-end the routine
continueRoutine = False
# *Resp* updates
if t >= 2 and Resp.status == NOT_STARTED:
# keep track of start time/frame for later
Resp.tStart = t # not accounting for scr refresh
Resp.frameNStart = frameN # exact frame index
win.timeOnFlip(Resp, 'tStartRefresh') # time at next scr refresh
Resp.status = STARTED
# keyboard checking is just starting
win.callOnFlip(Resp.clock.reset) # t=0 on next screen flip
Resp.clearEvents(eventType='keyboard')
frameRemains = 4 - win.monitorFramePeriod * 0.75 # most of one frame period left
if Resp.status == STARTED and t >= frameRemains:
# keep track of stop time/frame for later
Resp.tStop = t # not accounting for scr refresh
Resp.frameNStop = frameN # exact frame index
win.timeOnFlip(Resp, 'tStopRefresh') # time at next scr refresh
Resp.status = FINISHED
if Resp.status == STARTED:
theseKeys = Resp.getKeys(keyList=['g', 'k', 'None'], waitRelease=False)
if len(theseKeys):
theseKeys = theseKeys[0] # at least one key was pressed
# check for quit:
if "escape" == theseKeys:
endExpNow = True
if Resp.keys == []: # then this was the first keypress
Resp.keys = theseKeys.name # just the first key pressed
Resp.rt = theseKeys.rt
# was this 'correct'?
if (Resp.keys == str(CorrAns)) or (Resp.keys == CorrAns):
Resp.corr = 1
else:
Resp.corr = 0
# a response ends the routine
continueRoutine = False
# *p_port* updates
if t >= 0.75 and p_port.status == NOT_STARTED:
# keep track of start time/frame for later
p_port.tStart = t # not accounting for scr refresh
p_port.frameNStart = frameN # exact frame index
win.timeOnFlip(p_port, 'tStartRefresh') # time at next scr refresh
p_port.status = STARTED
win.callOnFlip(p_port.setData, int(1))
frameRemains = 0.75 + .1- win.monitorFramePeriod * 0.75 # most of one frame period left
if p_port.status == STARTED and t >= frameRemains:
# keep track of stop time/frame for later
p_port.tStop = t # not accounting for scr refresh
p_port.frameNStop = frameN # exact frame index
win.timeOnFlip(p_port, 'tStopRefresh') # time at next scr refresh
p_port.status = FINISHED
win.callOnFlip(p_port.setData, int(0))
# *ISI* period
if t >= 0 and ISI.status == NOT_STARTED:
# keep track of start time/frame for later
ISI.tStart = t # not accounting for scr refresh
ISI.frameNStart = frameN # exact frame index
win.timeOnFlip(ISI, 'tStartRefresh') # time at next scr refresh
ISI.start(0.75)
elif ISI.status == STARTED: # one frame should pass before updating params and completing
# updating other components during *ISI*
BiasImageCue.setImage(BiasCue)
GridStimulus.setMovie(StimulusMovie)
# component updates done
ISI.complete() # finish the static period
# check for quit (typically the Esc key)
if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
core.quit()
# 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
# 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)
Block1.addData('ISI.started', ISI.tStart)
Block1.addData('ISI.stopped', ISI.tStop)
Block1.addData('BiasImageCue.started', BiasImageCue.tStartRefresh)
Block1.addData('BiasImageCue.stopped', BiasImageCue.tStopRefresh)
Block1.addData('GridStimulus.started', GridStimulus.tStartRefresh)
Block1.addData('GridStimulus.stopped', GridStimulus.tStopRefresh)
# check responses
if Resp.keys in ['', [], None]: # No response was made
Resp.keys = None
# was no response the correct answer?!
if str(CorrAns).lower() == 'none':
Resp.corr = 1; # correct non-response
else:
Resp.corr = 0; # failed to respond (incorrectly)
# store data for Block1 (TrialHandler)
Block1.addData('Resp.keys',Resp.keys)
Block1.addData('Resp.corr', Resp.corr)
if Resp.keys != None: # we had a response
Block1.addData('Resp.rt', Resp.rt)
Block1.addData('Resp.started', Resp.tStartRefresh)
Block1.addData('Resp.stopped', Resp.tStopRefresh)
if p_port.status == STARTED:
win.callOnFlip(p_port.setData, int(0))
Block1.addData('p_port.started', p_port.tStartRefresh)
Block1.addData('p_port.stopped', p_port.tStopRefresh)
The movie component (i.e., GridStimulus) is under the comment of ‘update component parameters for each repeat’ and not initialised early on in the script as the image component is (i.e., BiasImageCue)
Moreover, when I set the movie component to ‘during repeat’ and compile the script, as below, it looks similar to the one compiled above (i.e., set during ISI),
for thisBlock1 in Block1:
currentLoop = Block1
# abbreviate parameter names if possible (e.g. rgb = thisBlock1.rgb)
if thisBlock1 != None:
for paramName in thisBlock1:
exec('{} = thisBlock1[paramName]'.format(paramName))
# ------Prepare to start Routine "trial"-------
t = 0
trialClock.reset() # clock
frameN = -1
continueRoutine = True
routineTimer.add(4.000000)
# update component parameters for each repeat
GridStimulus = visual.MovieStim3(
win=win, name='GridStimulus',
noAudio = True,
filename=StimulusMovie,
ori=0, pos=[0, 0], opacity=1,
loop=False,
depth=-2.0,
)
Resp = keyboard.Keyboard()
# keep track of which components have finished
trialComponents = [ISI, BiasImageCue, GridStimulus, Resp, p_port]
for thisComponent in trialComponents:
thisComponent.tStart = None
thisComponent.tStop = None
thisComponent.tStartRefresh = None
thisComponent.tStopRefresh = None
if hasattr(thisComponent, 'status'):
thisComponent.status = NOT_STARTED
# -------Start Routine "trial"-------
while continueRoutine and routineTimer.getTime() > 0:
# 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
# *BiasImageCue* updates
if t >= 0.75 and BiasImageCue.status == NOT_STARTED:
# keep track of start time/frame for later
BiasImageCue.tStart = t # not accounting for scr refresh
BiasImageCue.frameNStart = frameN # exact frame index
win.timeOnFlip(BiasImageCue, 'tStartRefresh') # time at next scr refresh
BiasImageCue.setAutoDraw(True)
frameRemains = 0.75 + .75- win.monitorFramePeriod * 0.75 # most of one frame period left
if BiasImageCue.status == STARTED and t >= frameRemains:
# keep track of stop time/frame for later
BiasImageCue.tStop = t # not accounting for scr refresh
BiasImageCue.frameNStop = frameN # exact frame index
win.timeOnFlip(BiasImageCue, 'tStopRefresh') # time at next scr refresh
BiasImageCue.setAutoDraw(False)
# *GridStimulus* updates
if t >= 2 and GridStimulus.status == NOT_STARTED:
# keep track of start time/frame for later
GridStimulus.tStart = t # not accounting for scr refresh
GridStimulus.frameNStart = frameN # exact frame index
win.timeOnFlip(GridStimulus, 'tStartRefresh') # time at next scr refresh
GridStimulus.setAutoDraw(True)
frameRemains = 4 - win.monitorFramePeriod * 0.75 # most of one frame period left
if GridStimulus.status == STARTED and t >= frameRemains:
# keep track of stop time/frame for later
GridStimulus.tStop = t # not accounting for scr refresh
GridStimulus.frameNStop = frameN # exact frame index
win.timeOnFlip(GridStimulus, 'tStopRefresh') # time at next scr refresh
GridStimulus.setAutoDraw(False)
if GridStimulus.status == FINISHED: # force-end the routine
continueRoutine = False
# *Resp* updates
if t >= 2 and Resp.status == NOT_STARTED:
# keep track of start time/frame for later
Resp.tStart = t # not accounting for scr refresh
Resp.frameNStart = frameN # exact frame index
win.timeOnFlip(Resp, 'tStartRefresh') # time at next scr refresh
Resp.status = STARTED
# keyboard checking is just starting
win.callOnFlip(Resp.clock.reset) # t=0 on next screen flip
Resp.clearEvents(eventType='keyboard')
frameRemains = 4 - win.monitorFramePeriod * 0.75 # most of one frame period left
if Resp.status == STARTED and t >= frameRemains:
# keep track of stop time/frame for later
Resp.tStop = t # not accounting for scr refresh
Resp.frameNStop = frameN # exact frame index
win.timeOnFlip(Resp, 'tStopRefresh') # time at next scr refresh
Resp.status = FINISHED
if Resp.status == STARTED:
theseKeys = Resp.getKeys(keyList=['g', 'k', 'None'], waitRelease=False)
if len(theseKeys):
theseKeys = theseKeys[0] # at least one key was pressed
# check for quit:
if "escape" == theseKeys:
endExpNow = True
if Resp.keys == []: # then this was the first keypress
Resp.keys = theseKeys.name # just the first key pressed
Resp.rt = theseKeys.rt
# was this 'correct'?
if (Resp.keys == str(CorrAns)) or (Resp.keys == CorrAns):
Resp.corr = 1
else:
Resp.corr = 0
# a response ends the routine
continueRoutine = False
# *p_port* updates
if t >= 0.75 and p_port.status == NOT_STARTED:
# keep track of start time/frame for later
p_port.tStart = t # not accounting for scr refresh
p_port.frameNStart = frameN # exact frame index
win.timeOnFlip(p_port, 'tStartRefresh') # time at next scr refresh
p_port.status = STARTED
win.callOnFlip(p_port.setData, int(1))
frameRemains = 0.75 + .1- win.monitorFramePeriod * 0.75 # most of one frame period left
if p_port.status == STARTED and t >= frameRemains:
# keep track of stop time/frame for later
p_port.tStop = t # not accounting for scr refresh
p_port.frameNStop = frameN # exact frame index
win.timeOnFlip(p_port, 'tStopRefresh') # time at next scr refresh
p_port.status = FINISHED
win.callOnFlip(p_port.setData, int(0))
# *ISI* period
if t >= 0 and ISI.status == NOT_STARTED:
# keep track of start time/frame for later
ISI.tStart = t # not accounting for scr refresh
ISI.frameNStart = frameN # exact frame index
win.timeOnFlip(ISI, 'tStartRefresh') # time at next scr refresh
ISI.start(0.75)
elif ISI.status == STARTED: # one frame should pass before updating params and completing
# updating other components during *ISI*
BiasImageCue.setImage(BiasCue)
# component updates done
ISI.complete() # finish the static period
# check for quit (typically the Esc key)
if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
core.quit()
# 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
# 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)
Block1.addData('ISI.started', ISI.tStart)
Block1.addData('ISI.stopped', ISI.tStop)
Block1.addData('BiasImageCue.started', BiasImageCue.tStartRefresh)
Block1.addData('BiasImageCue.stopped', BiasImageCue.tStopRefresh)
Block1.addData('GridStimulus.started', GridStimulus.tStartRefresh)
Block1.addData('GridStimulus.stopped', GridStimulus.tStopRefresh)
# check responses
if Resp.keys in ['', [], None]: # No response was made
Resp.keys = None
# was no response the correct answer?!
if str(CorrAns).lower() == 'none':
Resp.corr = 1; # correct non-response
else:
Resp.corr = 0; # failed to respond (incorrectly)
# store data for Block1 (TrialHandler)
Block1.addData('Resp.keys',Resp.keys)
Block1.addData('Resp.corr', Resp.corr)
if Resp.keys != None: # we had a response
Block1.addData('Resp.rt', Resp.rt)
Block1.addData('Resp.started', Resp.tStartRefresh)
Block1.addData('Resp.stopped', Resp.tStopRefresh)
if p_port.status == STARTED:
win.callOnFlip(p_port.setData, int(0))
Block1.addData('p_port.started', p_port.tStartRefresh)
Block1.addData('p_port.stopped', p_port.tStopRefresh)
Coding isn’t my strength at the moment but I wonder if the ISI script is not placing the movie component correctly to be set during the ISI? Or is the only difference between the script - GridStimulus.setMovie(StimulusMovie)
- in the ISI updates section of the first script the correct way to set it during the ISI period?
- ISI being loaded later
So, with this, I made sure to select the ISI period and use the ‘move it to the top’ option, which I believe makes it execute first? I’m not completely sure but this may be reflected in the order of components in the trialComponents
variable, which does list ISI first. Interestingly, and again I don’t know a lot about the coding side of things, in the section of the script where each component updates, ISI is placed not first, but last.