No, there’s no chance we could work out the problem in your code from that little information. Sorry.
Share with us the minimal amount of code that has a problem; no code about loading stimuli or collecting responses, just the code that shows the bad timing problem.
FYI, the while loop shown above does not end in that way. I just cut some part of the loop and showed with the printing part (self.stimOnset - self.startTime)
OK, yes. From your code the reason is clear enough.
On each frame you wait until the time has exceeded your duration rather than testing whether you’re within one frame of your intended duration. If you arrive at that if-statement 1ms short of the experiment.onsetfix_dur then you present another frame, and you overshoot by 15ms (on a 60Hz monitor). If you do the same the next trial you gradually acrue a large overshoot.
use frames for timing if you’re confident you never drop frames
use an if-statement that stops if you have more than 1/2 a frame duration remaining (fine if your intended duration is a correct multiple of the frame rate)
use countdown timer and add the intended duration to accommodate gradual slippage in either direction
At first, I used CountdownTimer() and now I’m using MonotonicClock()
timer = core.MonotonicClock()
# while t < totalDuration:
while timer.getTime()<totalDuration:
if event.getKeys(["escape"]):
core.quit()
# t = time.time() - self.trialStart
if presentOnsetFix:
experiment.win.clearBuffer()
experiment.experimentPlan[self.trialIndex][0].draw()
self.fix1.draw()
self.fix2.draw()
experiment.win.update()
self.stimOnset = time.time()
presentOnsetFix = 0
elif timer.getTime() >= experiment.stim_dur and presentISI:
self.fix1.draw()
self.fix2.draw()
-- so on --
Right yes, that’s clear now. You aren’t using the countdown timer correctly.
The point of the countdown timer is that you use it to countdown to zero and you “add” time to it which allows for the fact that the last event might have gone ‘negative’ and any overshoot gets combined with the next event.
Here’s a minimal script to demonstrate:
from psychopy import visual, core
#set parameters
stimDuration = 1.0
oneFrame = 1/60.0
#create stimuli
win = visual.Window([800,600])
stim = visual.TextStim(win)
clock = core.Clock()
timer = core.CountdownTimer()
timer.reset() # (not needed here but good idea!)
for thisTrialN in range(5):
stim.text = "trial {}".format(thisTrialN)
# ecah trial you add duration to the residual from last
timer.add(stimDuration)
#then wait until zero
while timer.getTime() > oneFrame/2:
stim.draw()
win.flip()
print clock.getTime()