我是python和psychopy的新手,但是我在编程和设计实验方面拥有丰富的经验(使用Matlab和EPrime)。我正在运行RSVP(快速视觉序列演示)实验,每X ms显示不同的视觉刺激(X是实验变量,可以是100 ms到1000 ms)。由于这是一个生理学实验,我需要在刺激开始时通过并行端口发送触发器。我使用示波器和光电传感器测试触发和视觉开始之间的同步。但是,当我在win.flip()之前或之后发送我的触发器时,即使使用windowBlanking = False参数,我仍然会在刺激的开始和代码的开始之间产生差异。
附上我的代码:
im=[]
for pic in picnames:
im.append(visual.ImageStim(myWin,image=pic,pos=[0,0],autoLog=True))
myWin.flip() # to get to the next vertical blank
while tm < and t < len(codes):
im[tm].draw()
parallel.setData(codes[t]) # before
myWin.flip()
#parallel.setData(codes[t]) # after
ttime.append(myClock.getTime())
core.wait(0.01)
parallel.setData(0)
dur=(myClock.getTime()-ttime[t])*1000
while dur < stimDur-frameDurAvg+1:
dur=(myClock.getTime()-ttime[t])*1000
t=t+1
tm=tm+1
myWin.flip()
如何将刺激开始与触发器同步?我不确定这是否是显卡问题(我正在使用带有板载Intel显卡的LCD ACER屏幕)。非常感谢,
沙尼
答案 0 :(得分:5)
win.flip()
等待下一次监视器更新。这意味着当监视器开始绘制帧时,win.flip()
之后的下一行几乎完全执行。这就是你想要发送你的触发器的地方。 win.flip()
之前的那一行可能差不多一帧,例如在60Hz监视器上16.7 ms,因此您的触发器会过早到达。
有两种几乎相同的方法可以做到这一点。让我们从最容易理解的开始:
win.flip()
parallel.setData(255)
core.wait(0.01)
parallel.setData(0)
...所以在图像被推到显示器后立即发送信号。
准确度稍高的方法可以节省0.01毫秒(加上减去一个数量级)。在脚本早期的某个地方定义
def sendTrigger(code):
parallel.setData(code)
core.wait(0.01)
parallel.setData(0)
然后在循环中做
win.callOnFlip(sendTrigger, code=255)
win.flip()
这将在翻转之后调用该功能,然后心理状态会进行一些清理。同样,与其他因素相比,时间上的这种差异是微不足道的,这不是一个性能问题,而是风格偏好。
答案 1 :(得分:0)
有一个通常被忽略的隐藏时序变量 - 监视器输入滞后,我认为这是延迟的原因。简而言之,即使在从显卡获得输入后,显示器也需要一些时间来显示图像。此延迟与刷新率(屏幕切换缓冲区的次数)或监视器的响应时间无关。
在我的显示器中,当我使用callOnFlip()发送触发器时,我发现延迟为23毫秒。我如何纠正它:floor(23 / 16.667)= 1,23%16.667 = 6.333。所以我在第二帧上调用callOnFlip,等待6.3 ms并触发端口。这有效。我没有试过WaitBlanking = True,它等待显卡的消隐启动,因为这给了我更多的时间来准备下一个缓冲区。但是,我认为即使使用WaitBlanking = True,效果也会存在。 (测试后更多!)
最佳, Suddha
答案 2 :(得分:0)
至少有一个例程可用于将触发延迟标准化为屏幕刷新率。我只是用一个光电传感器单元对其进行了测试,然后从触发和刺激显示之间的平均延迟为13毫秒(sd = 3.5毫秒),变为了4.8毫秒(sd = 3.1毫秒)的平均延迟。
过程如下:
这不能确保您现在的所有延迟都为零,因为您无法掌握win.flip()命令与屏幕当前状态之间的同步,但是它将使延迟居中于零。至少对我有用。
因此代码可以更新如下:
refr_rate = 85.05
mean_delay_ms = (1000 / refr_rate)
mean_delay_sec = mean_delay_ms / 1000 # Psychopy needs timing values in seconds
def send_trigger(port, value):
core.wait(mean_delay_sec)
parallel.setData(value)
core.wait(0.001)
parallel.setData(0)
[...]
stimulus.draw()
win.flip()
send_trigger(port, value)
[...]