I have been working to understand the Psychopy API, and there are many ways to handle time. One of the most fundamental confusions for me is that getTime() is defined differently in core and clock. But regardless of whether a clock is constructed using core.Clock or clock.Clock, they both seem to operate based on clock.getTime()
# clocks-example.py
from psychopy import (core,clock)
t0_monoclock = clock.monotonicClock.getTime()
t0_core_T = core.getTime(True)
t0_core_F = core.getTime(False)
t0_clock = clock.getTime()
x = core.Clock()
y = clock.Clock()
m_lastResetTime = clock.monotonicClock.getLastResetTime()
x_lastResetTime = x.getLastResetTime()
y_lastResetTime = y.getLastResetTime()
print(f"t0 clock.monotonicClock : {t0_monoclock:f}")
print(f"t0 core.getTime(True) : {t0_core_T:f}")
print(f"t0 core.getTime(False) : {t0_core_F:f}")
print(f"t0 clock.getTime() : {t0_clock:f}")
print(f"lastResetTime clock.monotonicClock : {m_lastResetTime:f}")
print(f"lastResetTime core.Clock : {x_lastResetTime:f}")
print(f"lastResetTime clock.Clock : {y_lastResetTime:f}")
# EXAMPLE EXECUTION OF clocks-example.py SCRIPT
> & "C:\Program Files\PsychoPy\python.exe" .\clocks-example.py
t0 clock.monotonicClock : 0.075200
t0 core.getTime(True) : 0.075208
t0 core.getTime(False) : 1758804816.684122
t0 clock.getTime() : 977521.716676
lastResetTime clock.monotonicClock : 977521.641462
lastResetTime core.Clock : 977521.716681
lastResetTime clock.Clock : 977521.716684
My questions are:
- What is
core.getTime()used for, if anything? - Since
Clockis imported from theclockmodule into thecoremodule, and the general idiom seems to be to initialize clocks withcore.Clockrather than importing and usingclock.Clockdirectly, is it best to avoid interacting with theclockmodule directly? - There are some functions, like
visual.window.timeOnFlip()that do not take a clock as an argument and so reference some “default” clock. I think this is the instance ofmonotonicClockthat gets initialized when importing theclockmodule. Do I have this right?
Especially when trying to get my head around the helper functions that hide some of the complexity, I have found it confusing to keep things straight. Thanks for help and insight!
Edit: digging into things some more, it seems that visual.window.timeOnFlip() does NOT reference the default monotonicClock. It actually references whatever clock is set as the default for logging, which will might be that default monotonicClock if you don’t set it to something else. But visual.window.timeOnFlip() is simply reading out a time that was already recorded: win.flip() stores a timestamp in win._frameTime (which, again, is determined by whatever the logging.defaultClock is).
So, for this particular helper function, for order of operations is something like:
- You tell Psychopy that you want to store the time of the next
flipinto a specific field of a specified object immediately after that flip happens. - This event is scheduled using
win.callOnFlip() - When the
fliphappens, a time stamp is stored inwin._frameTime. - After the
flip, the scheduled event happens, and the value ofwin._frameTimeis returned.