配置心理学实验时所须要的自变量是一个麻烦的问题,在这里,介绍一种简单快速配置实验变量的方法。这个方法确保了程序的简单、可读,减小了编程出bug的可能。python
呈现一个注视屏,上面有三个框,中间的框里有注视点,800ms编程
而后左边或右边的框中出现一个圆,圆的颜色是红、绿、蓝其中一种,200msapp
接着继续呈现注视屏,400ms或700msdom
再呈现目标刺激,是一个"*",被试须要当即按下'j'键。若是被试在"*"出现前按下按键,那么反馈"请看到*后再按键",若是被试超过1000ms都没有按键,那么反馈"请在*出现1秒内反馈"。反馈信息显示1000ms函数
最后呈现一个700ms的空屏测试
试次分为正常试次和探测试次。正常试次按以上流程,探测试次在呈现目标刺激阶段时,不呈现"*"。ui
color 线索颜色: 红、绿、蓝this
cloc 线索位置: 左边 右边spa
soa :400ms 700ms设计
tloc 目标刺激: 左边 右边 不呈现
被试的按键:"j"
按键反应时
其中,反应时为-1000表示被试提早按键,按键为timeout表示被试超时。
共360试次,其中80%正常试次,20%探测试次。在这两种试次中,自变量的各类状况都均匀分布。
被试id 试次 color cloc soa tloc key RT
ShowFixation1 | 显示第一个注视屏 | |
ShowCue | 显示线索屏幕 | |
ShowFixation2 | 显示第二个线索屏 须要检测是否提早按键 |
返回'timeout'说明被试没按键 返回'j'说明被试提早按键 |
ShowTarget | 显示目标刺激 | 返回('j', 789)表示被试正常按键 返回('timeout',0)表示被试超时 返回('q', 765)表示退出实验 |
ShowTimePre | 显示反应提早 | |
ShowTimeOut | 显示反应超时 | |
ShowBlank | 显示空屏 |
from itertools import * import random colors = ['red', 'blue', 'green'] clocs = ['left', 'right'] soas = [0.4, 0.7] tlocs = ['left', 'right'] # + [0] trails = list(product(colors, clocs, soas, tlocs))* 12 +\ list(product(colors, clocs, soas, [0])) * 6 random.shuffle(trails)
itertools里的product会生成一个迭代器,这个迭代器会依次返回多个循环器集合的笛卡尔积,至关于嵌套循环。在外面套上list把结果转换成列表。
例如list(product(['a', 'b', 'c'],[1, 2])),会生成[('a', 1), ('a', 2), ('b', 1), ('b', 2), ('c', 1), ('c', 2)]
执行完上面的操做后,trails里就有 3*2*2*2*12+3*2*2*1*6=360个元素了。
使用:
color, cloc, soa, tloc = trails[i]
就能够把每一个试次的自变量配置取出来。
COLOR = {'red': [220, 0, 0], 'green': [0, 165, 0], 'blue': [18, 18, 255], 'white': [255, 255, 255], 'black': [0, 0, 0], 'gray': [127, 127, 127] } CLOC = {'left' : (-224, 0), 'right': (224, 0) } TLOC = {'left' : (-224, -20), 'right': (224, -20), 0 : 0 }
有时候咱们会用嵌套的if和else来区分不一样变量下的详细配置,其实这是没有必要的,使用字典能够灵活地解决这个问题。
好比设置线索的颜色和位置,能够这样写:
color, cloc, soa, tloc = trails[i] circle = Circle(win, radius=16, edges=32, units = 'pix') circle.setFillColor(colorSpace = 'rgb255', color = COLOR[color]) circle.setLineColor(colorSpace = 'rgb255', color = COLOR[color]) circle.setPos(CLOC[cloc])
把每一个试次的按键和反应时都保存到results列表里
results.append((rKey, RT))
最后经过StoreResult把结果保存到文件。
def StoreResult(name, N, trails, results): fp = open(name + '.txt','w') fp.write("ID\tnum\tcolor\tcloc\tsoa\ttloc\trKey\tRT\n") def w(x): fp.write(str(x) + '\t') def n(): fp.write('\n') def k(x): #trans 1s to 1000ms return "%.0f" % (x * 1000) for i in range(N): color, cloc, soa, tloc = trails[i] rKey, RT = results[i] map(w, [name, i+1, color, cloc, k(soa), tloc, rKey, k(RT)]) n() fp.close()
在这里,map函数的意思是,分别执行w(name);w(i+1);w(color) ......
# -*- coding: utf-8 -*- """ Created on Tue Apr 12 10:31:15 2016 @author: zbg """ from psychopy.visual import Window, ImageStim, TextStim, BufferImageStim, Rect, Circle from psychopy import core, event, gui, clock import random from itertools import * #定义一些基本常量 fullscr = False COLOR = {'red': [220, 0, 0], 'green': [0, 165, 0], 'blue': [18, 18, 255], 'white': [255, 255, 255], 'black': [0, 0, 0], 'gray': [127, 127, 127] } CLOC = {'left' : (-224, 0), 'right': (224, 0) } TLOC = {'left' : (-224, -20), 'right': (224, -20), 0 : 0 } #准备实验参数与变量 N = 360 colors = ['red', 'blue', 'green'] clocs = ['left', 'right'] soas = [0.4, 0.7] tlocs = ['left', 'right'] # + [0] trails = list(product(colors, clocs, soas, tlocs))* 12 +\ list(product(colors, clocs, soas, [0])) * 6 random.shuffle(trails) results = [] #程序使用的各类函数 def MakeStimBackGround(win): t = TextStim(win, text = '+', pos = (0, 0), colorSpace = 'rgb255', color = COLOR['white'], units = 'pix', height = 32) cb = Rect(win, width=64, height= 64, units = 'pix') cb.setLineColor(colorSpace = 'rgb255', color = COLOR['black']) cb.setPos((0, 0)) rb = Rect(win, width=64, height= 64, units = 'pix') rb.setLineColor(colorSpace = 'rgb255', color = COLOR['black']) rb.setPos((224, 0)) lb = Rect(win, width=64, height= 64, units = 'pix') lb.setLineColor(colorSpace = 'rgb255', color = COLOR['black']) lb.setPos((-224, 0)) stimBackground = BufferImageStim(win, stim = [t, lb, cb, rb]) return stimBackground def MakeCircle(win): circle = Circle(win, radius=16, edges=32, units = 'pix') return circle def GetSubject(): """ 返回被试的id """ myDlg = gui.Dlg(title="Subject Information") myDlg.addField(u'被试ID:') myDlg.show() if myDlg.OK: thisInfo = myDlg.data else: exit(0) return thisInfo[0] def WaitTheKey(win, key = 'space'): event.clearEvents() while key not in event.getKeys(): pass def ShowTextAndWaitTheKey(win, text = '', wait = 0, key = 'space', pos=(0,-0.0), height = 55, units = "pix"): t =TextStim(win, text ,pos = pos, height = height, units = units) t.draw() event.clearEvents() clk = clock.CountdownTimer(wait) win.flip() while clk.getTime() > 0: pass while key not in event.getKeys(): pass def ShowTextAndWait(win, text = '', wait = 0, pos=(0,-0.0), height = 55, units = "pix"): t =TextStim(win, text ,pos = pos, height = height, units = units) t.draw() clk = clock.CountdownTimer(wait) win.flip() while clk.getTime() > 0: pass def ShowIntro(win): introduce =u""" 指导语 按[空格键]继续 """ ShowTextAndWaitTheKey(win, introduce) def ShowFixation1(win, stimBackground): clk = clock.CountdownTimer(0.8) stimBackground.draw() win.flip() while clk.getTime() > 0: pass def ShowCue(win, color, loc, stimBackground, circle): circle.setFillColor(colorSpace = 'rgb255', color = COLOR[color]) circle.setLineColor(colorSpace = 'rgb255', color = COLOR[color]) circle.setPos(CLOC[loc]) stimBackground.draw() circle.draw() clk = clock.CountdownTimer(0.2) win.flip() while clk.getTime() > 0: pass def ShowFixation2(win, soa, stimBackground): ''' 返回值有 ('timeout') 这个是想要的 (按键) 这个表示提早按键 ''' event.clearEvents() stimBackground.draw() clk = clock.CountdownTimer(soa) win.flip() while clk.getTime() > 0: pressedKeys = event.getKeys() if len(pressedKeys) > 0: return pressedKeys[0] return 'timeout' def ShowTarget(win, loc, stimBackground): """ 返回(按键, 反应时(s)) 状况分别有: ('f', 反应时) ('j', 反应时) ... ('q', 反应时) 一般表示退出 ('timeout', 0) """ event.clearEvents() if loc == 0: stimBackground.draw() else: t = TextStim(win, text = '*', pos = TLOC[loc], colorSpace = 'rgb255', color = COLOR['black'], units = 'pix', height = 96) stimBackground.draw() t.draw() clk = 0 clk = clock.CountdownTimer(1) win.flip() while clk.getTime() > 0: pressedKeys = event.getKeys() key = set(pressedKeys) & set(['q', 'j']) if len(key) > 0: return (key.pop(), 1 - clk.getTime()) return ('timeout', 0) def ShowTimePre(win): ShowTextAndWait(win, text = u'请看到*后再按键', wait = 1) def ShowTimeOut(win): ShowTextAndWait(win, text = u'请在*出现1秒内按键', wait = 1) def ShowBlank(win, wait = 0.7): ShowTextAndWait(win, wait = wait) def ShowBreak(win): ShowTextAndWaitTheKey(win, text = u"休息一下", key = 'space', wait = 10) def ShowEnd(win): introduce =u""" 结束了 按[空格键]退出 """ ShowTextAndWaitTheKey(win, text = introduce) def StoreResult(name, N, trails, results): fp = open(name + '.txt','w') fp.write("ID\tnum\tcolor\tcloc\tsoa\ttloc\trKey\tRT\n") def w(x): fp.write(str(x) + '\t') def n(): fp.write('\n') def k(x): #trans 1s to 1000ms return "%.0f" % (x * 1000) for i in range(N): color, cloc, soa, tloc = trails[i] rKey, RT = results[i] map(w, [name, i+1, color, cloc, k(soa), tloc, rKey, k(RT)]) n() fp.close() #实验开始 name = GetSubject() win = Window(fullscr = fullscr, colorSpace = 'rgb255', color = COLOR['gray']) stimBackground = MakeStimBackGround(win) circle = MakeCircle(win) ShowIntro(win) for i in range(N): color, cloc, soa, tloc = trails[i] RT = 0 rKey = 0 ShowFixation1(win, stimBackground) ShowCue(win, color, cloc, stimBackground, circle) key = ShowFixation2(win, soa, stimBackground) if key != 'timeout': ShowTimePre(win) RT = -1 rKey = 0 else: (rKey, RT) = ShowTarget(win, tloc, stimBackground) if tloc == 0 and rKey != 'timeout': ShowTimePre(win) elif tloc !=0 and rKey == 'timeout': ShowTimeOut(win) else: pass ShowBlank(win, 0.7) if rKey == 'q': StoreResult('exp-' + name, i, trails, results) win.close() exit(0) results.append((rKey, RT)) if i % 60 == 59: ShowBreak(win) StoreResult('exp-' + name, N, trails, results) ShowEnd(win) win.close()
引用和转载请注明本文连接,谢谢!