def stopRecording(): """Stop eyetracker recording """ if getExperiment().recording: pylink.endRealTimeMode() pylink.msecDelay(100) getTracker().stopRecording() getExperiment().recording = False
def sendRTperiod(self): """Lets the Data Viewer know the endpoints of the RT period, so data outside that period can easily be filtered out """ if not hasattr(self,'rtPeriod'): if hasattr(self,'dataViewerBG') and len(self.dataViewerBG['response_collectors']) > 0: self.rtPeriod = ("%s.SYNCTIME"%(self.dataViewerBG['name']),"%s.END_RT"%(self.dataViewerBG['response_collectors'][0]['name'])) else: return getTracker().sendMessage("!V V_CRT MESSAGE %s %s"%(self.rtPeriod))
def sendDataViewerBG(self): """Lets the Data Viewer know the names of the files containing the background image and the interest area definitions """ if hasattr(self,'dataViewerBG'): if self.dataViewerBG.params.get('screen_image_file',False): pygame.time.delay(2) getTracker().sendMessage("!V IMGLOAD FILL %s"%self.dataViewerBG['screen_image_file']) if self.dataViewerBG.get('interest_area_file',False): pygame.time.delay(2) getTracker().sendMessage("!V IAREA FILE %s"%self.dataViewerBG['interest_area_file'])
def checkEyeLink(self): """Check if the eyes have fixated in one of the areas listed in possible_resp, and have stayed there for the specified minimum time. If so, record rt, rt_time, and resp, and return True; otherwise return False. """ if self.fixatedArea: #We've already started fixating on one of the areas in possible_resp sample = getTracker().getNewestSample() # Retrieve the sample data from whichever eye we care about sampledata = sample and ( (self.eyeUsed == 1 and sample.isRightSample() and sample.getRightEye()) or (self.eyeUsed == 0 and sample.isLeftSample() and sample.getLeftEye())) if sampledata: if self.fixatedArea.contains(sampledata.getGaze()): # Check whether they've stayed in the interest area for the specified minimum time if sample.getTime( ) - self.fixtime > self.params['min_fixation']: self.params['rt_time'] = self.fixtime self.params['rt'] = self.params[ 'rt_time'] - self.params['onset_time'] self.params['resp'] = self.fixatedArea # TODO: Test the following code: # In particular: is the number specifying the offset # between here and the eye tracker meaningful and # correct? What's the meaning of this number anyway? # And what's it used for? getTracker().sendMessage("%s.END_RT" % self['name']) self.stop() return True else: # The eye has left the interest area. self.fixatedArea = None else: # Check whether we have a fixation in one of the areas in possible_resp eventType = getTracker().getNextData() if eventType == pylink.STARTFIX or eventType == pylink.FIXUPDATE or eventType == pylink.ENDFIX: event = getTracker().getFloatData() ## print "event.getEye(): %d"%(event.getEye()) ## print "event.getStartGaze(): (%d,%d)"%event.getStartGaze() if event.getType() == pylink.STARTFIX and event.getEye( ) == self.eyeUsed: for area in self.params['possible_resp']: if area.contains(event.getStartGaze()): self.fixtime = event.getStartTime() self.fixatedArea = area break if (event.getType() == pylink.FIXUPDATE or event.getType() == pylink.ENDFIX) and event.getEye() == self.eyeUsed: for area in self.params['possible_resp']: if area.contains(event.getAverageGaze()): self.fixtime = event.getStartTime() self.fixatedArea = area break return False
def handleEvent(self,event): """Check if the speech recognition detected a word in possible_resp """ if event.type == SPEECH_RECOGNITION: if event.word in self['possible_resp']: self['rt_time'] = event.time getTracker().sendMessage("%d %s.END_RT"%(event.time-pylink.currentTime(),self['name'])) self['resp'] = event.word self['rt'] = event.time - self['onset_time'] return True return False
def sendRTperiod(self): """Lets the Data Viewer know the endpoints of the RT period, so data outside that period can easily be filtered out """ if not hasattr(self, 'rtPeriod'): if hasattr(self, 'dataViewerBG') and len( self.dataViewerBG['response_collectors']) > 0: self.rtPeriod = ( "%s.SYNCTIME" % (self.dataViewerBG['name']), "%s.END_RT" % (self.dataViewerBG['response_collectors'][0]['name'])) else: return getTracker().sendMessage("!V V_CRT MESSAGE %s %s" % (self.rtPeriod))
def handleEvent(self, event): """Check if the speech recognition detected a word in possible_resp """ if event.type == SPEECH_RECOGNITION: if event.word in self['possible_resp']: self['rt_time'] = event.time getTracker().sendMessage( "%d %s.END_RT" % (event.time - pylink.currentTime(), self['name'])) self['resp'] = event.word self['rt'] = event.time - self['onset_time'] return True return False
def handleEvent(self,event): if event.type == CEDRUS_BUTTON_DOWN and event.key in self['possible_resp'] or "any" in self['possible_resp']: self['rt'] = event.time-self['onset_time'] self['rt_time'] = event.time self['resp'] = event.key getTracker().sendMessage("%d %s.END_RT"%(self['rt_time']-pylink.currentTime(),self['name'])) return True elif event.type == CEDRUS_BUTTON_UP and event.key == self['resp']: self['rt_offset'] = event.time - self['onset_time'] self['rt_offset_time'] = event.time getTracker().sendMessage("%d %s.offset"%(self['rt_offset_time']-pylink.currentTime(),self['name'])) self.stop() return False
def checkEyeLink(self): """Check if the eyes have fixated in one of the areas listed in possible_resp, and have stayed there for the specified minimum time. If so, record rt, rt_time, and resp, and return True; otherwise return False. """ if self.fixatedArea: #We've already started fixating on one of the areas in possible_resp sample = getTracker().getNewestSample() # Retrieve the sample data from whichever eye we care about sampledata = sample and ( (self.eyeUsed == 1 and sample.isRightSample() and sample.getRightEye()) or (self.eyeUsed == 0 and sample.isLeftSample() and sample.getLeftEye()) ) if sampledata: if self.fixatedArea.contains(sampledata.getGaze()): # Check whether they've stayed in the interest area for the specified minimum time if sample.getTime() - self.fixtime > self.params['min_fixation']: self.params['rt_time'] = self.fixtime self.params['rt'] = self.params['rt_time'] - self.params['onset_time'] self.params['resp'] = self.fixatedArea # TODO: Test the following code: # In particular: is the number specifying the offset # between here and the eye tracker meaningful and # correct? What's the meaning of this number anyway? # And what's it used for? getTracker().sendMessage("%s.END_RT" % self['name']) self.stop() return True else: # The eye has left the interest area. self.fixatedArea = None else: # Check whether we have a fixation in one of the areas in possible_resp eventType = getTracker().getNextData() if eventType == pylink.STARTFIX or eventType == pylink.FIXUPDATE or eventType == pylink.ENDFIX: event = getTracker().getFloatData() ## print "event.getEye(): %d"%(event.getEye()) ## print "event.getStartGaze(): (%d,%d)"%event.getStartGaze() if event.getType() == pylink.STARTFIX and event.getEye() == self.eyeUsed: for area in self.params['possible_resp']: if area.contains(event.getStartGaze()): self.fixtime=event.getStartTime() self.fixatedArea = area break if (event.getType() == pylink.FIXUPDATE or event.getType() == pylink.ENDFIX) and event.getEye() == self.eyeUsed: for area in self.params['possible_resp']: if area.contains(event.getAverageGaze()): self.fixtime=event.getStartTime() self.fixatedArea = area break return False
def sendDataViewerBG(self): """Lets the Data Viewer know the names of the files containing the background image and the interest area definitions """ if hasattr(self, 'dataViewerBG'): if self.dataViewerBG.params.get('screen_image_file', False): pygame.time.delay(2) getTracker().sendMessage( "!V IMGLOAD FILL %s" % self.dataViewerBG['screen_image_file']) if self.dataViewerBG.get('interest_area_file', False): pygame.time.delay(2) getTracker().sendMessage( "!V IAREA FILE %s" % self.dataViewerBG['interest_area_file'])
def handleEvent(self,event): """Check the buffer of keyboard input to see if an acceptable response was entered. If an acceptable response (i.e. listed in possible_resp) was detected, set the 'acc', 'resp', 'rt', and 'rt_time' parameters accordingly, and return True. Otherwise return False. """ if event.type == KEYDOWN and ("any" in self['possible_resp'] or (pygame.key.name(event.key) in self['possible_resp'])): #We got a legal response; handle it appropriately self['rt_time'] = event.time getTracker().sendMessage("%s.END_RT"%(self['name'])) self['rt'] = self['rt_time']-self['onset_time'] self['resp'] = pygame.key.name(event.key) self.stop() return True return False
def driftCorrect(color=None, bgcolor=None, target=None): """Draw a target and perform drift correction Arguments: color: An RGB 3-tuple specifying the foreground color for the drift correction screen. Default is the experiment 'color' parameter E.g. color = (0,0,0) is black, color = (1,1,1) is white. bgcolor: An RGB 3-tuple specifying the background color. Default is the experiment 'bgcolor' parameter target: A 2-tuple (x,y) specifying the coordinates of the fixation target to be displayed. Default is the center of the screen """ if getExperiment().recording: raise EyetrackerError( "Attempt to drift correct while recording in progress") # If no target is specified, the target is the center of the screen target = target or (getExperiment().params['screen_size'][0] / 2, getExperiment().params['screen_size'][1] / 2) color = color or getExperiment().params['color'] bgcolor = bgcolor or getExperiment().params['bgcolor'] getExperiment().eyelinkGraphics.setCalibrationColors(color, bgcolor) mouseVisibility = pygame.mouse.set_visible(False) while 1: try: error = getTracker().doDriftCorrect(target[0], target[1], 1, 1) if error == 27: calibrateTracker((color, bgcolor)) else: print "drift correct error %s" % error break except RuntimeError: pass pygame.mouse.set_visible(mouseVisibility)
def driftCorrect(color=None,bgcolor=None,target=None): """Draw a target and perform drift correction Arguments: color: An RGB 3-tuple specifying the foreground color for the drift correction screen. Default is the experiment 'color' parameter E.g. color = (0,0,0) is black, color = (1,1,1) is white. bgcolor: An RGB 3-tuple specifying the background color. Default is the experiment 'bgcolor' parameter target: A 2-tuple (x,y) specifying the coordinates of the fixation target to be displayed. Default is the center of the screen """ if getExperiment().recording: raise EyetrackerError("Attempt to drift correct while recording in progress") # If no target is specified, the target is the center of the screen target = target or (getExperiment().params['screen_size'][0]/2,getExperiment().params['screen_size'][1]/2) color = color or getExperiment().params['color'] bgcolor = bgcolor or getExperiment().params['bgcolor'] getExperiment().eyelinkGraphics.setCalibrationColors(color,bgcolor) mouseVisibility = pygame.mouse.set_visible(False) while 1: try: error=getTracker().doDriftCorrect(target[0],target[1],1,1) if error == 27: calibrateTracker((color,bgcolor)) else: print "drift correct error %s"%error break except RuntimeError: pass pygame.mouse.set_visible(mouseVisibility)
def draw(self,onset=None): """helper method, not directly called in EyeScript scripts in general. Actually draw the display to the screen. As the display is drawn, record onset_time and swap_time, start the response collectors, and inform the eyetracker Optional argument: onset, time in milliseconds when the screen is to be displayed (from the same baseline as for the times returned by pylink.currentTime() and recorded in the eyetracker data file) """ self.drawToBuffer() while pylink.currentTime() < onset: checkForResponse() self['onset_time']=pylink.currentTime() VisionEgg.Core.swap_buffers() for rc in self['response_collectors']: rc.start() self['swap_time']=pylink.currentTime()-self['onset_time'] getTracker().sendMessage("%s.SYNCTIME %d"%(self['name'],pylink.currentTime()-self['onset_time']))
def run(self): startRecording() starttime = pylink.currentTime() getExperiment().screen.parameters.bgcolor = self.bgcolor getTracker().sendMessage("SYNCTIME") if self.pattern == "continuous": iteration = 0 filler = False while iteration <= 1.25: if filler == False and iteration >= 0.25: # This is point where we're actually going to use the data # Before this was just to get the subject warmed up filler = True getTracker().sendMessage("END_FILLER") checkForResponse() t = (pylink.currentTime() - starttime) * 0.00012 t = t - sin(8 * t) / 64 iteration = t / (2 * pi) getExperiment().eyelinkGraphics.draw_cal_target( getExperiment()['screen_size'][0] / 2 + 153 * sin(t) + 204 * sin(9 * t), getExperiment()['screen_size'][1] / 2 + 153 * cos(t) + 204 * cos(9 * t)) elif self.pattern == "discrete": getExperiment().eyelinkGraphics.setCalibrationColors( self.color, self.bgcolor) targets = [] for i in range(3): for j in range(3): targets.append([ (i + 0.5) * getExperiment()['screen_size'][0] / 3, (j + 0.5) * getExperiment()['screen_size'][1] / 3 ]) for i in range(1, 3): for j in range(1, 3): targets.append([ i * getExperiment()['screen_size'][0] / 3, j * getExperiment()['screen_size'][1] / 3 ]) random.shuffle(targets) targets.append( targets[0] ) # Redo the first fixation point at the end so we can discard the first one for i, target in enumerate(targets): if i == 1: getTracker().sendMessage("END_FILLER") getExperiment().eyelinkGraphics.draw_cal_target(*target) starttime = pylink.currentTime() while pylink.currentTime() < 1500 + starttime: checkForResponse() else: raise "PupilCalibrationTrial: bad argument to pattern: %s" % self.pattern getTracker().sendMessage("END_RT") stopRecording()
def handleEvent(self, event): """Check the buffer of keyboard input to see if an acceptable response was entered. If an acceptable response (i.e. listed in possible_resp) was detected, set the 'acc', 'resp', 'rt', and 'rt_time' parameters accordingly, and return True. Otherwise return False. """ if event.type == KEYDOWN and ("any" in self['possible_resp'] or (pygame.key.name(event.key) in self['possible_resp'])): #We got a legal response; handle it appropriately self['rt_time'] = event.time getTracker().sendMessage("%s.END_RT" % (self['name'])) self['rt'] = self['rt_time'] - self['onset_time'] self['resp'] = pygame.key.name(event.key) self.stop() return True return False
def checkEyeLink(self): """Check if the eyes have fixated in one of the areas listed in possible_resp, and have stayed there for the specified minimum time. If so, record rt, rt_time, and resp, and return True; otherwise return False. """ if self.fixatedArea: #We've already started fixating on one of the areas in possible_resp sample = getTracker().getNewestSample() # Retrieve the sample data from whichever eye we care about sampledata = sample and ( (self.eyeUsed == 1 and sample.isRightSample() and sample.getRightEye()) or (self.eyeUsed == 0 and sample.isLeftSample() and sample.getLeftEye()) ) if sampledata: if self.fixatedArea.contains(sampledata.getGaze()): # Check whether they've stayed in the interest area for the specified minimum time if sample.getTime() - self.fixtime > self.params['min_fixation']: self.params['rt_time'] = self.fixtime self.params['rt'] = self.params['rt_time'] - self.params['onset_time'] self.params['resp'] = self.fixatedArea # print self.fixtime, self.params['rt'], self.params['rt_time'], self.params['onset_time'] # I'm not sure why we used to stop here if a response was recorded. I think we only want to stop when we time out -- Mike #self.stop() return True else: # The eye has left the interest area. self.fixatedArea = None else: # Check whether we have a fixation in one of the areas in possible_resp event = getTracker().getFloatData() ## print "event.getEye(): %d"%(event.getEye()) ## print "event.getStartGaze(): (%d,%d)"%event.getStartGaze() if event: if event.getType() == pylink.STARTFIX and event.getEye() == self.eyeUsed: for area in self.params['possible_resp']: if area.contains(event.getStartGaze()): self.fixtime=event.getStartTime() self.fixatedArea = area break if (event.getType() == pylink.FIXUPDATE or event.getType() == pylink.ENDFIX) and event.getEye() == self.eyeUsed: for area in self.params['possible_resp']: if area.contains(event.getAverageGaze()): self.fixtime=event.getStartTime() self.fixatedArea = area break return False
def handleEvent(self,event): if not getExperiment().recording: self.stop() return False if getTracker(): action = getTracker().isRecording() if action != pylink.TRIAL_OK: raise TrialAbort(action) return self.checkEyeLink() else: # So that the experiment can be tested without the eyetracker, # just fake a response after 2000 milliseconds. if pylink.currentTime() > self['onset_time'] + 2000: self['resp'] = self['possible_resp'] and self['possible_resp'][0] self['rt'] = 2000 self['rt_time'] = self['onset_time'] + 2000 self.stop() return True
def handleEvent(self, event): if event.type == CEDRUS_BUTTON_DOWN and event.key in self[ 'possible_resp'] or "any" in self['possible_resp']: self['rt'] = event.time - self['onset_time'] self['rt_time'] = event.time self['resp'] = event.key getTracker().sendMessage( "%d %s.END_RT" % (self['rt_time'] - pylink.currentTime(), self['name'])) return True elif event.type == CEDRUS_BUTTON_UP and event.key == self['resp']: self['rt_offset'] = event.time - self['onset_time'] self['rt_offset_time'] = event.time getTracker().sendMessage( "%d %s.offset" % (self['rt_offset_time'] - pylink.currentTime(), self['name'])) self.stop() return False
def draw(self,onset=None): """helper method, not directly called in EyeScript scripts in general. Actually present the audio stimulus As it's presented, record onset_time and swap_time, start the response collectors, and inform the eyetracker Optional argument: onset, time in milliseconds when the stimulus is to be displayed (from the same baseline as for the times returned by pylink.currentTime() and recorded in the eyetracker data file) """ while onset and pylink.currentTime() < onset - self['audio_latency']: checkForResponse() self['onset_time']=pylink.currentTime() + self['audio_latency'] for rc in self['response_collectors']: rc.start() if self['audio_package'] == 'winsound' and winsound: winsound.PlaySound(self.audiofile,winsound.SND_ASYNC | winsound.SND_FILENAME) elif self['audio_package'] == 'pygame': self.channel = self.sound.play() self['swap_time']=pylink.currentTime()-self['onset_time'] getTracker().sendMessage("%s.SYNCTIME %d"%(self['name'],pylink.currentTime()-self['onset_time']))
def handleEvent(self, event): if not getExperiment().recording: self.stop() return False if getTracker(): action = getTracker().isRecording() if action != pylink.TRIAL_OK: raise TrialAbort(action) return self.checkEyeLink() else: # So that the experiment can be tested without the eyetracker, # just fake a response after 2000 milliseconds. if pylink.currentTime() > self['onset_time'] + 2000: self['resp'] = self['possible_resp'] and self['possible_resp'][ 0] self['rt'] = 2000 self['rt_time'] = self['onset_time'] + 2000 self.stop() return True
def startRecording(): """Commence eyetracker recording and verify that it's working. """ getTracker().resetData() getTracker().startRecording(1,1,1,1) getExperiment().recording = True pylink.beginRealTimeMode(100) try: if not getTracker().waitForBlockStart(1000,1,1): raise Exception("waitForBlockStart failed") except Exception: getTracker().drawText("LINK DATA NOT RECEIVED!",pos=(1,20)) pylink.endRealTimeMode() pylink.msecDelay(2000) getTracker().stopRecording() print "LINK DATA NOT RECEIVED!" raise TrialAbort(pylink.TRIAL_ERROR)
def startRecording(): """Commence eyetracker recording and verify that it's working. """ getTracker().resetData() getTracker().startRecording(1, 1, 1, 1) getExperiment().recording = True pylink.beginRealTimeMode(100) try: if not getTracker().waitForBlockStart(1000, 1, 1): raise Exception("waitForBlockStart failed") except Exception: getTracker().drawText("LINK DATA NOT RECEIVED!", pos=(1, 20)) pylink.endRealTimeMode() pylink.msecDelay(2000) getTracker().stopRecording() print "LINK DATA NOT RECEIVED!" raise TrialAbort(pylink.TRIAL_ERROR)
def checkEyeLink(self): sample = getTracker().getNewestSample() sampledata = sample and ( (self.eyeUsed == 1 and sample.isRightSample() and sample.getRightEye()) or (self.eyeUsed == 0 and sample.isLeftSample() and sample.getLeftEye()) ) if sampledata: for area in self['possible_resp']: if area.contains(sampledata.getGaze()): self.params['rt_time'] = sample.getTime() self.params['rt'] = sample.getTime() - self.params['onset_time'] self.params['resp'] = area # TODO: Test the following code: # In particular: is the number specifying the offset # between here and the eye tracker meaningful and # correct? What's the meaning of this number anyway? # And what's it used for? getTracker().sendMessage("%s.END_RT"%(self['name'])) #getTracker().sendMessage("%d %s.END_RT"%(self['rt_time']-pylink.currentTime(), # self['name'])) self.stop() return True return False
def checkEyeLink(self): sample = getTracker().getNewestSample() sampledata = sample and ((self.eyeUsed == 1 and sample.isRightSample() and sample.getRightEye()) or (self.eyeUsed == 0 and sample.isLeftSample() and sample.getLeftEye())) if sampledata: for area in self['possible_resp']: if area.contains(sampledata.getGaze()): self.params['rt_time'] = sample.getTime() self.params['rt'] = sample.getTime( ) - self.params['onset_time'] self.params['resp'] = area # TODO: Test the following code: # In particular: is the number specifying the offset # between here and the eye tracker meaningful and # correct? What's the meaning of this number anyway? # And what's it used for? getTracker().sendMessage("%s.END_RT" % (self['name'])) #getTracker().sendMessage("%d %s.END_RT"%(self['rt_time']-pylink.currentTime(), # self['name'])) self.stop() return True return False
def poll(self): buttonBuffer = [] while 1: event_type, button, button_change, key_code, time = getTracker( ).readKeyButton() if event_type == pylink.KB_BUTTON and button_change in [ pylink.KB_PRESS, pylink.KB_RELEASE ]: pgev = pygame.event.Event( button_change == pylink.KB_PRESS and EYELINK_BUTTON_DOWN or EYELINK_BUTTON_UP, {'key': EYELINKBUTTONMAP[button]}) buttonBuffer.append(ESevent(pgev, time=time)) elif not event_type: break return buttonBuffer
def poll(self): buttonBuffer = [] while 1: event_type, button, button_change, key_code, time = getTracker().readKeyButton() if event_type == pylink.KB_BUTTON and button_change in [pylink.KB_PRESS,pylink.KB_RELEASE]: pgev = pygame.event.Event(button_change == pylink.KB_PRESS and EYELINK_BUTTON_DOWN or EYELINK_BUTTON_UP, {'key':EYELINKBUTTONMAP[button]} ) buttonBuffer.append(ESevent(pgev, time=time )) elif not event_type: break return buttonBuffer
def start(self): """Execute operations necessary when response collection is started. Check if the eyetracker is recording Check the eye being recorded from Initialize the fixatedArea attribute to None """ ResponseCollector.start(self) if not getExperiment().recording: raise "Must be recording to monitor gaze position!" self.eyeUsed = getTracker().eyeAvailable() if self.eyeUsed == 2: # binocular recording self.eyeUsed = getExperiment().params.get('eye_used',1) elif self.eyeUsed == -1: # neither eye available! raise TrialAbort(pylink.TRIAL_ERROR) ## getTracker().resetData() self.fixatedArea = None
def run(self): startRecording() starttime = pylink.currentTime() getExperiment().screen.parameters.bgcolor = self.bgcolor getTracker().sendMessage("SYNCTIME") if self.pattern == "continuous": iteration = 0 filler = False while iteration <= 1.25: if filler == False and iteration >= 0.25: # This is point where we're actually going to use the data # Before this was just to get the subject warmed up filler = True getTracker().sendMessage("END_FILLER") checkForResponse() t = (pylink.currentTime() - starttime) * 0.00012 t = t - sin(8*t)/64 iteration = t / (2*pi) getExperiment().eyelinkGraphics.draw_cal_target(getExperiment()['screen_size'][0]/2 + 153*sin(t) + 204*sin(9*t),getExperiment()['screen_size'][1]/2 + 153*cos(t) + 204*cos(9*t)) elif self.pattern == "discrete": getExperiment().eyelinkGraphics.setCalibrationColors(self.color,self.bgcolor) targets = [] for i in range(3): for j in range(3): targets.append([(i+0.5)*getExperiment()['screen_size'][0]/3,(j+0.5)*getExperiment()['screen_size'][1]/3]) for i in range(1,3): for j in range(1,3): targets.append([i*getExperiment()['screen_size'][0]/3,j*getExperiment()['screen_size'][1]/3]) random.shuffle(targets) targets.append(targets[0]) # Redo the first fixation point at the end so we can discard the first one for i,target in enumerate(targets): if i == 1: getTracker().sendMessage("END_FILLER") getExperiment().eyelinkGraphics.draw_cal_target(*target) starttime = pylink.currentTime() while pylink.currentTime() < 1500+starttime: checkForResponse() else: raise "PupilCalibrationTrial: bad argument to pattern: %s"%self.pattern getTracker().sendMessage("END_RT") stopRecording()
def start(self): """Execute operations necessary when response collection is started. Check if the eyetracker is recording Check the eye being recorded from Initialize the fixatedArea attribute to None """ ResponseCollector.start(self) if not getExperiment().recording: raise "Must be recording to monitor gaze position!" self.eyeUsed = getTracker().eyeAvailable() if self.eyeUsed == 2: # binocular recording self.eyeUsed = getExperiment().params.get('eye_used', 1) elif self.eyeUsed == -1: # neither eye available! raise TrialAbort(pylink.TRIAL_ERROR) ## getTracker().resetData() self.fixatedArea = None
def checkEyeLink(self): time = pylink.currentTime() sample = getTracker().getNewestSample() sampledata = sample and ( (self.eyeUsed == 1 and sample.isRightSample() and sample.getRightEye()) or (self.eyeUsed == 0 and sample.isLeftSample() and sample.getLeftEye()) ) if sampledata: for area in self['possible_resp']: if area.contains(sampledata.getGaze()): # self.params['rt_time'] = sample.getTime() # self.params['rt'] = sample.getTime() - self.params['onset_time'] self.params['rt_time'] = time self.params['rt'] = time - self.params['onset_time'] self.params['resp'] = area #This is used in GazePredictor, but it was cleaner to just put it here -- Craig self.params['xy_coords'] = sampledata.getGaze() # I'm not sure why we used to stop here if a response was recorded. I think we only want to stop when we time out -- Mike #self.stop() return True return False
def __init__(self): getTracker().flushKeybuttons(1)
def gcFixation(target=None,color=None,bgcolor=None,duration=None,buffer_size=None): """Displays a fixation point and waits until the subject has fixated on it for a minimum duration. The Eyetracker """ if buffer_size == None: buffer_size = getExperiment()['gcbuffer_size'] if not getExperiment().recording: raise EyetrackerError("Must be recording when gcFixation is called!") target = target or getExperiment().params.get('fixation_target',( getExperiment().params['screen_size'][0]/2,getExperiment().params['screen_size'][1]/2 ) ) color = color or getExperiment().params['color'] bgcolor = bgcolor or getExperiment().params['bgcolor'] duration = duration or getExperiment().params.get('min_fixation',800) getExperiment().eyelinkGraphics.setCalibrationColors(color,bgcolor) getExperiment().eyelinkGraphics.draw_cal_target(target[0],target[1]) if getTracker(): eyeUsed = getTracker().eyeAvailable() if eyeUsed == 2: # binocular recording eyeUsed = getExperiment().params.get('eye_used',1) elif eyeUsed == -1: # neither eye available! raise TrialAbort(pylink.TRIAL_ERROR) getTracker().resetData() ## getTracker().sendCommand("clear_cross %d %d %d"%(target[0],target[1],15)) fixarea = pygame.Rect(target[0]-buffer_size, target[1]-buffer_size, 2*buffer_size, 2*buffer_size ) infixarea = False while 1: action = getTracker().isRecording() if action != pylink.TRIAL_OK: raise TrialAbort(action) if infixarea: sample = getTracker().getNewestSample() sampledata = sample and ( (eyeUsed == 1 and sample.isRightSample() and sample.getRightEye()) or (eyeUsed == 0 and sample.isLeftSample() and sample.getLeftEye()) or False ) if sampledata: if fixarea.collidepoint(sampledata.getGaze()): if sample.getTime() - fixtime > duration: break else: infixarea = False getTracker().resetData() else: eventType = getTracker().getNextData() if eventType == pylink.STARTFIX or eventType == pylink.FIXUPDATE or eventType == pylink.ENDFIX: ## print "Fixation started" event = getTracker().getFloatData() ## print "event.getEye(): %d"%(event.getEye()) ## print "event.getStartGaze(): (%d,%d)"%event.getStartGaze() if ((event.getType() == pylink.STARTFIX and event.getEye() == eyeUsed and fixarea.collidepoint(event.getStartGaze())) or ((event.getType() == pylink.FIXUPDATE or event.getType() == pylink.ENDFIX) and event.getEye() == eyeUsed and fixarea.collidepoint(event.getAverageGaze()))): ## print "Fixation in critical area!" fixtime = event.getStartTime() infixarea = True else: pygame.time.delay(duration) getExperiment().eyelinkGraphics.erase_cal_target()
def setTrialVar(varName, value): """Sets the value of a trial variable, to inform the Data Viewer about trial metadata """ getTracker().sendMessage("!V TRIAL_VAR %s %s" % (varName, value))
def record(self, *args, **keywords): """Runs the trial displays while communicating with the eyetracker. TO-DO: currently contains a hack for stopping audio when trial is aborted. This needs to be done in a more general and implementation-independent way. """ while 1: getTracker().flushKeybuttons(1) Trial.trialNumber += 1 getLog().push() getLog().logAttributes(trialNumber=Trial.trialNumber) getLog().logAttributes(getattr(self, 'metadata', {})) getTracker().sendMessage('TRIALID %s' % (Trial.trialNumber)) getTracker().drawText("Trial_%s\n" % (Trial.trialNumber), pos=(1, 20)) getTracker().sendCommand("record_status_message 'TRIALID %s'" % (Trial.trialNumber)) self.sendDataViewerBG() self.sendRTperiod() try: result = self.run(*args, **keywords) except TrialAbort, abort: for rc in getExperiment().response_collectors: rc.stop() # HACK!!! # Need to find a good implementation-independent way of ensuring that sound streams get stopped. pygame.mixer.stop() getExperiment().recording = False pylink.endRealTimeMode() getLog().logAttributes(trial_abort=abort.abortAction) for key, value in getLog().currentData().iteritems(): setTrialVar(key, value) pygame.time.delay(1) getLog().pop() getTracker().sendMessage('TRIAL_RESULT %d' % (abort.abortAction)) if abort.abortAction == pylink.REPEAT_TRIAL: pass elif abort.abortAction == pylink.TRIAL_ERROR: calibrateTracker() elif abort.abortAction == pylink.SKIP_TRIAL: return None else: raise else: getLog().logAttributes(trial_abort=0) for key, value in getLog().currentData().iteritems(): setTrialVar(key, value) pygame.time.delay(1) getLog().pop() getTracker().sendMessage('TRIAL_RESULT 0') return result
def poll(self): """Updates the most recent datum from the link, which can then be accessed by ResponseCollector objects using getTracker().getFloatData(). """ getTracker().getNextData() return []
def checkEyeLink(self): GazeSample.checkEyeLink(self) self.prevAcc = self.rightAcceleration self.prevVel = self.rightXVelocity self.velAndAccel = getTracker().calculateOverallVelocityAndAcceleration(pylink.NINE_SAMPLE_MODEL) self.rightAcceleration = self.velAndAccel[1][1] self.velocityXY = getTracker().calculateVelocityXY(pylink.NINE_SAMPLE_MODEL) self.rightXVelocity = self.velocityXY[1][0] """f.write(str(self.rightAcceleration)) f.write(',') f.write(str(self.rightXVelocity)) f.write('\n')""" #Start of left saccade if self.rightAcceleration <= -self.params['acc_thresh'] and self.rightXVelocity <= -self.params['vel_thresh'] and not self.left and not self.right: self.left = True #This still isn't working quite right. Need to figure out how to restart the trial try: self.startingPoint = self.params['xy_coords'] #It seems that sometimes the Eyetracker is unable to obtain the current coordinates of the pupil except: self.startingPoint = (320,384) self.state = 0 #Midpoint of left saccade elif self.rightXVelocity > self.prevVel and self.rightAcceleration > self.prevAcc and self.left and not self.reachedMidpoint: self.reachedMidpoint = True self.predictedEndingIA = self.extrapolateEndingIA() self.state = 1 #End of left saccade elif self.rightAcceleration > -self.params['acc_thresh'] - 2000 and self.rightXVelocity - 15 > -self.params['vel_thresh'] and self.left and self.reachedMidpoint: self.left = False self.reachedMidpoint = False self.state = 2 #Start of right saccade elif self.rightAcceleration >= self.params['acc_thresh'] and self.rightXVelocity >= self.params['vel_thresh'] and not self.right and not self.left: self.right = True try: self.startingPoint = self.params['xy_coords'] except: self.startingPoint = (200,384) self.state = 3 #Midpoint of right saccade elif self.rightXVelocity < self.prevVel and self.rightAcceleration < self.prevAcc and self.right and not self.reachedMidpoint: self.reachedMidpoint = True self.predictedEndingIA = self.extrapolateEndingIA() self.state = 4 #End of right saccade elif self.rightAcceleration < self.params['acc_thresh'] + 2000 and self.rightXVelocity + 15 < self.params['vel_thresh'] and self.right and self.reachedMidpoint: self.right = False self.reachedMidpoint = False self.state = 5
def record(self,*args,**keywords): """Runs the trial displays while communicating with the eyetracker. TO-DO: currently contains a hack for stopping audio when trial is aborted. This needs to be done in a more general and implementation-independent way. """ while 1: getTracker().flushKeybuttons(1) Trial.trialNumber += 1 getLog().push() getLog().logAttributes(trialNumber=Trial.trialNumber) getLog().logAttributes(getattr(self,'metadata',{})) getTracker().sendMessage('TRIALID %s'%(Trial.trialNumber)) getTracker().drawText("Trial_%s\n"%(Trial.trialNumber),pos=(1,20)) getTracker().sendCommand("record_status_message 'TRIALID %s'"%(Trial.trialNumber)) self.sendDataViewerBG() self.sendRTperiod() try: result = self.run(*args,**keywords) except TrialAbort,abort: for rc in getExperiment().response_collectors: rc.stop() # HACK!!! # Need to find a good implementation-independent way of ensuring that sound streams get stopped. pygame.mixer.stop() getExperiment().recording = False pylink.endRealTimeMode() getLog().logAttributes(trial_abort=abort.abortAction) for key,value in getLog().currentData().iteritems(): setTrialVar(key,value) pygame.time.delay(1) getLog().pop() getTracker().sendMessage('TRIAL_RESULT %d'%(abort.abortAction)) if abort.abortAction == pylink.REPEAT_TRIAL: pass elif abort.abortAction == pylink.TRIAL_ERROR: calibrateTracker() elif abort.abortAction == pylink.SKIP_TRIAL: return None else: raise else: getLog().logAttributes(trial_abort=0) for key,value in getLog().currentData().iteritems(): setTrialVar(key,value) pygame.time.delay(1) getLog().pop() getTracker().sendMessage('TRIAL_RESULT 0') return result
def gcFixation(target=None, color=None, bgcolor=None, duration=None, buffer_size=None): """Displays a fixation point and waits until the subject has fixated on it for a minimum duration. The Eyetracker """ if buffer_size == None: buffer_size = getExperiment()['gcbuffer_size'] if not getExperiment().recording: raise EyetrackerError("Must be recording when gcFixation is called!") target = target or getExperiment().params.get( 'fixation_target', (getExperiment().params['screen_size'][0] / 2, getExperiment().params['screen_size'][1] / 2)) color = color or getExperiment().params['color'] bgcolor = bgcolor or getExperiment().params['bgcolor'] duration = duration or getExperiment().params.get('min_fixation', 800) getExperiment().eyelinkGraphics.setCalibrationColors(color, bgcolor) getExperiment().eyelinkGraphics.draw_cal_target(target[0], target[1]) if getTracker(): eyeUsed = getTracker().eyeAvailable() if eyeUsed == 2: # binocular recording eyeUsed = getExperiment().params.get('eye_used', 1) elif eyeUsed == -1: # neither eye available! raise TrialAbort(pylink.TRIAL_ERROR) getTracker().resetData() ## getTracker().sendCommand("clear_cross %d %d %d"%(target[0],target[1],15)) fixarea = pygame.Rect(target[0] - buffer_size, target[1] - buffer_size, 2 * buffer_size, 2 * buffer_size) infixarea = False while 1: action = getTracker().isRecording() if action != pylink.TRIAL_OK: raise TrialAbort(action) if infixarea: sample = getTracker().getNewestSample() sampledata = sample and ( (eyeUsed == 1 and sample.isRightSample() and sample.getRightEye()) or (eyeUsed == 0 and sample.isLeftSample() and sample.getLeftEye()) or False) if sampledata: if fixarea.collidepoint(sampledata.getGaze()): if sample.getTime() - fixtime > duration: break else: infixarea = False getTracker().resetData() else: eventType = getTracker().getNextData() if eventType == pylink.STARTFIX or eventType == pylink.FIXUPDATE or eventType == pylink.ENDFIX: ## print "Fixation started" event = getTracker().getFloatData() ## print "event.getEye(): %d"%(event.getEye()) ## print "event.getStartGaze(): (%d,%d)"%event.getStartGaze() if ((event.getType() == pylink.STARTFIX and event.getEye() == eyeUsed and fixarea.collidepoint(event.getStartGaze())) or ((event.getType() == pylink.FIXUPDATE or event.getType() == pylink.ENDFIX) and event.getEye() == eyeUsed and fixarea.collidepoint(event.getAverageGaze()))): ## print "Fixation in critical area!" fixtime = event.getStartTime() infixarea = True else: pygame.time.delay(duration) getExperiment().eyelinkGraphics.erase_cal_target()
def setTrialVar(varName,value): """Sets the value of a trial variable, to inform the Data Viewer about trial metadata """ getTracker().sendMessage("!V TRIAL_VAR %s %s"%(varName,value))
def __init__(self): getTracker().resetData()