Adding precise measure of system clock to psychopy output

OS: Win10 64-bit
PsychoPy version : 3.1.2
Standard Standalone?: Y

What are you trying to achieve?:
I am recording participants with a webcam as they complete a psychopy experiment. I need to be able to synchronize the recorded video and the psychopy output so that I know when (in video time) certain events occurred in the experiment.

My plan for this is to do both the webcam recording and the psychopy experiment on the same computer. Then I can hopefully get the system clock and compare the offset from when the webcam started and when the psychopy experiment started. The system time when recording starts is already written to the video metadata, so I just need to add a precise system time when the experiment starts to psychopy output.

What did you try to make it work?:
I compiled my experiment from Builder as a script and added the following at the top near the other imports:
from datetime import datetime

Then I added the following to the section where the experiment session info is stored:
expInfo['time'] = datetime.now().strftime("%H:%M:%S.%f")

When I run the experiment, a nice column is added to the output containing a timecode that is in the expected format. It seems plausible that this timecode is the system time at experiment start (the H and M is the same) but it is hard to know for sure whether the seconds and especially the fractions are correct (and these are important for synchronization with the video).

What specifically went wrong when you tried that?:
Above is my attempt at solving this problem and I think it looks reasonable, but I’d appreciate it if people who know more about python and psychopy could confirm whether this is a good approach and if you have suggestions on improving it.

Specifically, can someone confirm that running datetime.now() right after data.getDateStr() will return the same timestamp used to calculate the relative time in core.Clock()? Or is there something relevant already built into psychopy that I am not aware of? Thanks in advance.

Hi @jmgirard, the data.getDateStr() uses the time module, which uses the system clock to determine the time (from epoch), which is equivalent to how datetime fetches the time. For this purpose they are equivalent. You can check this by printing the output of these modules before and after the expInfo entries are created:

import time
from datetime import datetime

print(time.time(), datetime.now().timestamp())
# Your expInfo calls
print(time.time(), datetime.now().timestamp())

You should find that there is no observable difference in the times reported, except in the number of decimal places reported. I think it might be best if you set your baseline time from the Begin experiment tab in the code component. E.g.,

thisExp.addData("baseTime", time.time())

At the start of each routine, make another call in the Begin Routine tab

thisExp.addData("routineStart", time.time())

Then, for every event you will want to get your timing synced with the screen refresh, so for example your timestamp is saved exactly when your stimuli appear on screen. You do this with the windows callOnFlip method, which is passed the function and its parameters that need to be called on the screen refresh E.g.,

win.callOnFlip(thisExp.addData, "screenTime", time.time() )

By the way, you can also set up a webcam from within your Builder experiment using a code component. This might help you log times of when your webcam is initialised.

Also @dvbridges suggestions will let you avoid doing this manual editing of the experiment script. If you need to insert custom code, insert a code component from the “custom” component panel instead. That means you can continue to work in the graphical Builder environment, and let Builder take care of where in the script to insert your custom code snippets.

Where should I put this code? At the beginning of each routine with events?

@jmgirard, you would want to use this line of code on every frame, but run it conditionally at the onset of your video or event of interest.