心理实验中的试验处理与时间测量

1 投票
2 回答
1389 浏览
提问于 2025-04-18 06:16

我想用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 个回答

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

0

(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)

撰写回答