python心理学实验程序(psychopy)

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

你可能感兴趣的:(心理学实验程序)