心理实验中的试验处理与时间测量
我想用psychopy里的TrialHandler类来组织一个Go-NoGo任务中的图片数据。
trials = data.TrialHandler(ImageList, nReps=1, method='random')
现在我想写一个循环,让psychopy从字典里取数据,先展示第一组图片(比如A_n),然后再展示第二组,一直到第六组。我试过以下代码:
import glob, os, random, sys, time
import numpy.random as rnd
from psychopy import visual, core, event, monitors, gui, logging, data
im_a = glob.glob('./a*') # upload pictures of the a-type, gives out a List of .jpg-files
im_n = glob.glob('./n*') # n-type
im_e = glob.glob('./e*') # e-type
# combining Lists of Pictures
A_n = im_a + im_n
N_a = im_n + im_a
A_e = im_a + im_e
E_a = im_e + im_a
E_n = im_e + im_n
N_e = im_n + im_e
# making a Dictionary of Pictures and Conditions
PicList = [A_n, N_a, A_e, E_a, E_n, N_e] # just the six Combinations
CondList = [im_a,im_n,im_a,im_e,im_e,im_n] # images that are in the GO-Condition
ImageList = []
for imagelist, condition in zip(PicList, CondList):
ImageList.append({'imagelist':imagelist,'condition':condition}) # to associate the picturelist with the GO Conditionlist
在标题部分,我还问了一个额外的问题:如何合并和关联多个字典
# Set Experiment
win = visual.Window(color='white',units='pix', fullscr=False)
fixCross=visual.TextStim(win,text='+',color='black',pos=(0.0,0.0), height=40)
corrFb = visual.TextStim(win,text='O',height=40,color='green',pos=[0,0])
incorrFb = visual.TextStim(win,text='X',height=40, color='red',pos=[0,0])
# Start Experiement
trials = data.TrialHandler(ImageList, nReps=1, method='random')
rt_clock = core.Clock()
bitmap = visual.ImageStim(win)
for liste in ImageList[0:5]: # to loop through all 6 conditions
keys = []
for i,Pictures in enumerate(liste): # to loop through all pictures in each condition
bitmap.setImage(Pictures) # attribute error occurs, not if I use Pictures[0][0], even though in this case every pictures is the same
bitmap.draw()
win.flip()
rt_clock.reset()
resp = False
while rt_clock.getTime() < 2.0: # timelimit is defined 2 s
if not resp:
resp = event.getKeys(keyList=['space'])
rt = rt_clock.getTime()
if bool(resp) is (Pictures in CondList): # at this point python should have access to the Dictionary in which the associated GO Pictures are saved
corrFb.draw()
accu=1 # doesn't work yet
else:
incorrFb.draw()
accu=0
win.flip()
core.wait(0.5)
trials.addData('rt_'+str(i), rt) # is working well when loop: if trial in trials: ...; in this case trialHAndler is not used, therefor trials.addData is not working
trials.addData('accu_'+str(i), accu)
trials.saveAsExcel(datanames)
core.quit()
这段代码有几个问题:首先,它只展示了一张图片六次,而不是六张不同的图片[1]
其次,还有一个完全不同的问题[2]是时间测量和准确度的保存,TrialHandler会为每个试次进行这些操作。所以它会把每个试次的反应时间(RT)加在一起。我想要的是每张图片的反应时间。我试过一些方法,比如为刺激创建一个额外的stimulus.trialhandler,以及在最后加一个额外的循环来获取最后的RT,但不是每张图片的RT。--> 下面有回答!!!
for stimuli in stimulus: stimulus.addData('rt', rt)
我知道这四个问题对于一个问题来说有点多,但也许有人可以给我一些好的建议,帮我解决这些问题...谢谢大家!
2 个回答
你遇到的问题[1]的原因是你把图片设置为PicList[0][0],这个值是不会改变的。正如Mike上面所建议的,你需要:
for i,thisPic in enumerate(PicList):
bitmap.setImage(thisPic) #not PicList[0][0]
不过,也许你需要回到基础知识,这样你才能真正使用试验处理器来处理你的试验;-)
创建一个字典的列表,每个字典代表一个试验,然后按顺序运行这些试验(告诉试验处理器使用'顺序'而不是'随机')。所以你现在使用的循环应该只是用来创建条件字典的列表,而不是用来运行试验。然后把这个列表传给试验处理器:
trials = TrialHandler(trialTypes = myCondsListInOrder, nReps=1, method='sequential')
for thisTrial in trials:
pic = thisTrial['pic']
stim.setImage(pic)
...
trials.addData('rt', rt)
trials.addData('acc',acc)
另外,我建议你输出数据时不要使用Excel格式,而是使用'长宽'格式:
trials.saveAsWideText('mydataFile.csv')
祝好,
Jon
(A) 这部分内容虽然和你的问题无关,但可以提升性能。你在代码中的这一行:
bitmap = visual.ImageStim(win)
不应该放在循环里面。也就是说,你应该只初始化每个刺激一次,然后在循环中只更新这个刺激的属性,比如用 bitmap.setImage(…) 来更新。所以把这个初始化的代码移到最上面,也就是你创建 TextStims 的地方。
(B) [已删除:我之前没有注意到第一个代码块。]
(C)
bitmap.draw(pictures)
这一行不需要任何参数。它应该只是 bitmap.draw()。而且,'pictures' 这个词不太清楚指的是什么。记住,Python 是区分大小写的。这和上面循环中定义的 'Pictures' 是不一样的。我猜你是想更新显示的图片?如果是这样的话,你需要在这个循环里面使用 bitmap.setImage(…) 这一行,而不是在上面那样,这样每次试验中你总是会画出固定的图片,因为只有那一张会被设置。
(D) 关于反应时间(RTs),你每次试验只保存一次(检查一下缩进)。如果你想每张图片都保存一次,你需要再缩进这些代码行。此外,在数据输出中,每次试验只会有一行。如果你想在每次试验中记录多个反应时间,你需要给它们起不同的名字,比如 rt_1, rt_2, …, rt_6,这样它们才能出现在不同的列中。比如,你可以在这个循环中使用一个枚举器:
for i, picture in enumerate(Piclist)
# lots of code
# then save data:
trials.addData('rt_'+str(i), rt)