python心理学实验程序
使用psychopy做了个小实验。
任务主要包括:选词任务;呈现图片和字母,对字母进行判断;选数任务。
选词任务:10个词语呈现顺序随机,选择其中3个。
字母判断任务:字母Q或O出现在图片的左边或右边,判断字母为哪个。20张图片字母q/o字母位置左右 = 80种条件。80种随机,同时不能连续呈现一样的图片。
选数任务:从1-7选择一个数字。
程序中涉及实验材料的部分被省略。
本实验的pygame版本在我的另一篇文章中
pygame写的程序可以很方便地打包为exe程序,
而psychopy写的程序打包时总会遇到各种问题。
(欢迎读者与我交流)
# import libraries
import random, base64
from psychopy import visual, core, event
# some constants
left = (-210, 0)
right = (210, 0)
center = (0, 0)
grey = (0, 0, 0)
# trial lists
group_list = ['11', '12', '22', '21']
wordtrials = [] # 10个供挑选的词语
letter_trials = [['L', 'Q'],
['L', 'O'],
['R', 'Q'],
['R', 'O']]
ele7 = # 先将图片转为base64 编码的字节,再存放在代码中,之后便不需要调用图片。
ele27 =
sex3 =
sex15 =
……
pictrials_prac = [[ele7, 'ele', '7'],
[ele27, 'ele', '27'],
[sex3, 'sex', '3'],
[sex15, 'sex', '15']]
pictrials = [[ele2, 'ele', '2'], [ele3, 'ele', '3'],
[ele4, 'ele', '4'], [ele6, 'ele', '6'],
[ele10, 'ele', '10'],
[ele11, 'ele', '11'],
[ele16, 'ele', '16'],
[ele19, 'ele', '19'],
[ele26, 'ele', '26'],
[ele29, 'ele', '29'],
[sex7, 'sex', '7'],
[sex8, 'sex', '8'],
[sex10, 'sex', '10'],
[sex13, 'sex', '13'],
[sex14, 'sex', '14'],
[sex21, 'sex', '21'],
[sex22, 'sex', '22'],
[sex26, 'sex', '26'],
[sex28, 'sex', '28'],
[sex30, 'sex', '30']]
# some functions
# get subject info
def get_subj_info():
print('请输入被试信息并按回车键')
subj_id = input('编号: ')
subj_group = input('组: ')
while subj_group not in group_list:
subj_group = input('组(刚刚的输入不符合要求,请重新输入): ')
subj_age = input('年龄: ')
return [subj_id, subj_group, subj_age]
# run a single trial
def run_pictrial(pars, letter_pars, data_file, subj_info):
file, catog, num= pars
l, letter = letter_pars
if l == 'R': loc = right
if l == 'L': loc = left
# present the fixation
text_msg.setText('+')
text_msg.setPos((0, 0))
text_msg.height = 50
text_msg.draw()
win.flip()
core.wait(1)
# present the pic
img_data = base64.b64decode(file)
with open('001.jpg', 'wb') as f:
f.write(img_data)
pic = visual.ImageStim(win, image='001.jpg')
pic.draw()
win.flip()
core.wait(0.6)
# present the pic & letter
pic.draw()
text_msg.setText(letter)
text_msg.setPos(loc)
text_msg.height = 50
text_msg.bold = False
text_msg.draw()
win.flip()
core.wait(0.05)
# present the pic
timer = core.Clock()
timer.reset()
pic.draw()
win.flip()
resp = event.waitKeys(maxWait=1.2, keyList=['q', 'o', 'z'], timeStamped=True)
rtime = timer.getTime()
a = list(str(rtime).split())
# write data to file
if resp == None:
keyletter = list('X')
acc = '0'
rrr = 0
else:
rrr = resp[0][0]
keyletter = list(resp[0][0])
if resp[0][0] == 'q':
ans = 'Q'
if resp[0][0] == 'o':
ans = 'O'
if resp[0][0] == 'z':
ans = 'z'
if ans == letter:
acc = '1'
else:
acc = '0'
trial_data = list([catog]) + list([num]) + letter_pars + list(keyletter) + list(acc) + a
trial_data = map(str, trial_data)
trial_data = ','.join(trial_data) + '\n'
data_file.write(trial_data)
# blank
win.setColor(grey)
win.flip()
core.wait(0.500)
return rrr
def pretext(text, positi, size, bold):
text_msg.setText(text)
text_msg.setPos(positi)
text_msg.height = size
text_msg.bold = bold
text_msg.draw()
# real experiment starts here
subj = get_subj_info()
# open a data file
# if not os.path.exists('data_file'): os.mkdir('data_file')# build a file
d_file = open('_'.join(subj[:2]) + '.csv', 'a')
# create a window
win = visual.Window((1024, 768), units='pix', fullscr=True)
# step 1
text_msg = visual.TextStim(win, text='message', pos=(0.0, 0.0))
pretext(u'您好,欢迎参加本次实验!', (0, 70), 20, False)
pretext(u'\n接下来将呈现一段故事描述,该故事设定在实验中还需要再次回忆。', (0, 25), 20, False)
pretext(u'\n请仔细阅读,并想象此经历正在你身上发生。', (0, -20), 20, False)
pretext(u'\n准备好后,请按“空格键”开始。', (0, -70), 20, False)
win.flip()
event.waitKeys(keyList=['space'])
if subj[1] == '11' or subj[1] == '12': # 两种条件的故事(略)
pretext(u'', (0, 115), 25, False)
pretext(u'\n', (0,90), 25, False)
pretext(u'\n', (15, 50), 25, False)
pretext(u'\n', (0, 10), 25, False)
pretext(u'\n', (-98, -30), 25, False)
else:
pretext(u'', (0, 115), 25, False)
pretext(u'\n', (0, 90), 25, False)
pretext(u'\n', (15, 50), 25, False)
pretext(u'\n', (0, 10), 25, False)
pretext(u'\n', (-98, -30), 25, False)
pretext(u'\n请仔细阅读,想象此情景中……', (0, -100), 20, False)
pretext(u'\n准备好后,按“空格键”进行下一步。', (0, -130), 20, False)
win.flip()
event.waitKeys(keyList=['space'])
random.shuffle(wordtrials)
pretext(u'请从以下词语中挑选出3个你认为……最可能具备的特点。', (0, 100), 20, False)
pretext(u'\n(在键盘上按下对应数字选择,最后按“空格键”进行下一步)', (0, 80), 20, False)
strr = '\t'
pretext(strr.join(wordtrials[0:5]), (0, 20), 25, False)
pretext(u'\n0\t\t1\t\t2\t\t3\t\t4\n', (0, -10), 25, False)
pretext(u'\n' + strr.join(wordtrials[5:]), (0, -50), 25, False)
pretext(u'\n5\t\t6\t\t7\t\t8\t\t9', (0, -80), 25, False)
win.flip()
word_resp1 = event.waitKeys(maxWait=120, keyList=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], timeStamped=True)
word_resp2 = event.waitKeys(maxWait=120, keyList=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], timeStamped=True)
word_resp3 = event.waitKeys(maxWait=120, keyList=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], timeStamped=True)
event.waitKeys(keyList=['space'])
# write data to file
trial_data = subj + list([wordtrials[int(word_resp1[0][0])]]) + list([wordtrials[int(word_resp2[0][0])]]) \
+ list([wordtrials[int(word_resp3[0][0])]])
trial_data = map(str, trial_data)
trial_data = ','.join(trial_data) + '\n'
d_file.write(trial_data)
# step 2
# step 2 practice
pretext(u'屏幕中央首先会出现一个“+”注视点,提醒你开始实验。', (0, 90), 20, False)
pretext(u'\n接下来你将看到一张图片,在图片的左侧或右侧会出现一个字母。', (0, 60), 20, False)
pretext(u'\n请判断该字母是O还是Q,是O则按“O”键,是Q则按“Q键”。', (0, 30), 20, True)
pretext(u'\n请集中注意,又快又准地作出判断。', (0, -50), 20, False)
pretext(u'\n准备好后,按“空格键”开始练习。', (0, -90), 20, False)
win.flip()
event.waitKeys(keyList=['space'])
aa = list(range(4))
random.shuffle(aa)
for t in aa:
ll = letter_trials[t]
pp = pictrials_prac[t]
run_pictrial(pp, ll, d_file, subj)
pretext(u'练习完毕,准备好后按“空格键”进入正式实验。', (0, 0), 20, False)
win.flip()
event.waitKeys(keyList=['space'])
# step 2 real
aa = list(range(80)) # 20张图片*字母q/o*字母位置左右=80种
random.shuffle(aa)
trial_data = 'experi2' + '\n'
d_file.write(trial_data)
for aaa in range(7): # 80种随机,同时不能连续呈现一样的图片
if aa[aaa]//4 == aa[aaa+1]//4:
zz = 0
while zz == 0:
bb = aa[aaa+1:]
random.shuffle(bb)
aa = aa[0:aaa+1]
aa.extend(bb)
if aa[aaa]//4 != aa[aaa+1]//4:
zz = 1
for t in aa:
ll = letter_trials[t%4]
pp = pictrials[t//4]
rr = run_pictrial(pp, ll, d_file, subj)
if rr == 'z': # 按z键退出trial循环,进入下一步
break
# step 3
pretext(u'请稍作休息,回忆实验开始时阅读过的场景,想象场景中……。', (0, 70), 20, False)
pretext(u'\n接下来将出现一段补充描述,你有10秒时间阅读。', (0, 20), 20, False)
pretext(u'\n材料消失后,请并根据指示进行评定。', (0, -20), 20, False)
pretext(u'\n准备好后,按“空格键”进行下一步。', (0, -70), 20, False)
win.flip()
event.waitKeys(keyList=['space'])
pretext(u'情境中你结识的,是一位', (-120, 0), 20, False)
if subj[1] == '11' or subj[1] == '21': # 两种条件的描述
pretext(u'……', (64, 0), 20, True)
else:
pretext(u'……', (64, 0), 20, True)
pretext(u'的……', (170, 0), 20, False)
win.flip()
pretext(u'\n这位……符合你心目中理想形象的程度为?', (0, 80), 20, True)
pretext(u'\n1-7代表“非常不符合”到“非常符合”。', (0, 50), 20, False)
pretext(u'\n1 2 3 4 5 6 7', (0, -20), 20, False)
pretext(u'\n请在键盘上按下对应数字选择,再按“空格键”进行下一步。', (0, -80), 20, False)
core.wait(10)
win.flip()
pre_resp = event.waitKeys(maxWait=120, keyList=['1', '2', '3', '4', '5', '6', '7'], timeStamped=True)
event.waitKeys(keyList=['space'])
trial_data = map(str, list(pre_resp[0][0]))
trial_data = ','.join(trial_data) + '\n'
d_file.write(trial_data)
# blank
win.setColor(grey)
win.flip()
core.wait(1)
pretext(u'情境中你结识的,是一位', (-120, 10), 20, False)
if subj[1] == '11' or subj[1] == '21':
pretext(u'……', (64, 10), 20, True)
else:
pretext(u'……', (64, 10), 20, True)
pretext(u'的……。', (170, 10), 20, False)
pretext(u'\n偶然……', (-230, -20), 20, False)
pretext(u'……', (117, -30), 20, True)
win.flip()
pretext(u'\n这位……符合你心目中理想形象的程度为?', (0, 80), 20, True)
pretext(u'\n1-7代表“非常不符合”到“非常符合”。', (0, 50), 20, False)
pretext(u'\n1 2 3 4 5 6 7', (0, -20), 20, False)
pretext(u'\n请在键盘上按下对应数字选择,再按“空格键”进行下一步。', (0, -80), 20, False)
core.wait(10)
win.flip()
post_resp = event.waitKeys(maxWait=120, keyList=['1', '2', '3', '4', '5', '6', '7'], timeStamped=True)
event.waitKeys(keyList=['space'])
trial_data = map(str, list(post_resp[0][0]))
trial_data = ','.join(trial_data) + '\n'
d_file.write(trial_data)
pretext(u'实验结束!感谢参与!请按空格键退出。', (0, 0), 20, False)
win.flip()
event.waitKeys(keyList=['space'])
# close data file
d_file.close()
# exit
win.close()
core.quit()