#! /usr/local/bin/python2.5
"""measure your JND in orientation using a staircase method"""
from psychopy import core,visual,gui,data,misc,event
import time, numpy
try:#try to get a previous parameters file
expInfo = misc.fromFile('lastParams.pickle')
except:#if not there then use a default set
expInfo = {'observer':'jwp', 'refOrientation':0}
dateStr = time.strftime("%b_%d_%H%M", time.localtime())#add the current time
#present a dialogue to change params
dlg = gui.DlgFromDict(expInfo, title='simple JND Exp', fixed=['date'])
if dlg.OK:
misc.toFile('lastParams.pickle', expInfo)#save params to file for next time
else:
core.quit()#the user hit cancel so exit
#make a text file to save data
fileName = expInfo['observer'] + dateStr
dataFile = open(fileName+'.txt', 'w')
dataFile.write('targetSide oriIncrement correct\n')
#create window and stimuli
globalClock = core.Clock()#to keep track of time
trialClock = core.Clock()#to keep track of time
win = visual.Window([800,600],allowGUI=False, monitor='testMonitor', units='deg')
foil = visual.PatchStim(win, sf=1, size=4, mask='gauss', ori=expInfo['refOrientation'])
target = visual.PatchStim(win, sf=1, size=4, mask='gauss', ori=expInfo['refOrientation'])
fixation = visual.PatchStim(win, rgb=-1, tex=None, mask='circle',size=0.2)
message1 = visual.TextStim(win, pos=[0,+3],text='Hit a key when ready.')
message2 = visual.TextStim(win, pos=[0,-3], text="Then press left or right to identify the %.1fdegree probe." %(expInfo['refOrientation']))
#create the staircase handler
staircase = data.StairHandler(startVal = 20.0,
stepType = 'db', stepSizes=[8,4,4,2,2,1,1], #reduce step size every two reversals
nUp=1, nDown=3, #will home in on the 80% threshold
nTrials=50)
#display instructions and wait
message1.draw()
message2.draw()
fixation.draw()
win.flip()
#check for a keypress
event.waitKeys()
for thisIncrement in staircase: #will step through the staircase
#set location of stimuli
targetSide= round(numpy.random.random())*2-1 #will be either +1(right) or -1(left)
foil.setPos([-5*targetSide, 0])
target.setPos([5*targetSide, 0]) #in other location
#set orientation of probe
foil.setOri(expInfo['refOrientation'] + thisIncrement)
#draw all stimuli
foil.draw()
target.draw()
fixation.draw()
win.flip()
core.wait(0.5)#wait 500ms (use a loop of x frames for more accurate timing)
#blank screen
fixation.draw()
win.flip()
#get response
thisResp=None
while thisResp==None:
allKeys=event.waitKeys()
for thisKey in allKeys:
if (thisKey=='left' and targetSide==-1) or (thisKey=='right' and targetSide==1):
thisResp = 1#correct
elif (thisKey=='right' and targetSide==-1) or (thisKey=='left' and targetSide==1):
thisResp = 0#incorrect
elif thisKey in ['q', 'escape']:
core.quit()#abort experiment
event.clearEvents() #must clear other events (like mouse) in case they clog the event buffer
#add the data to the staircase so it can calculate the next level
staircase.addData(thisResp)
dataFile.write('%i %.3f %i\n' %(targetSide, thisIncrement, thisResp))
#staircase has ended
dataFile.close()
staircase.saveAsPickle(fileName)#special python binary file to save all the info
#give some output to user
print 'reversals:'
print staircase.reversalIntensities
print 'mean of final 6 reversals = %.3f' %(numpy.average(staircase.reversalIntensities[-6:]))
core.quit()
|