def startEyeTracking(self,trial, calibTrial,widthPix,heightPix): #Set up each trial with the eye tracker if calibTrial: cond = "Test/Calibration Trial" else: cond = "Non-test/no calibration trial" message ="record_status_message 'Trial %d %s'"%(trial+1, cond) self.tracker.sendCommand(message) msg = "TRIALID %s"%trial self.tracker.sendMessage(msg) #The following does drift correction at the begin of each trial if calibTrial:# Does drift correction and handles the re-do camera setup situations while True: try: error = self.tracker.doDriftCorrect(widthPix/2,heightPix/2,1,1) # 0: the fixation target must be drawn by the user if error != 27: #self.tracker.applyDriftCorrect break else: self.tracker.doTrackerSetup() except: print("Exception") break #self.tracker.sendCommand('start_drift_correction DATA =1 1 1 1') #CF - start drift correct?? #self.tracker.applyDriftCorrect() #CF - added to actually correct for drift self.tracker.setOfflineMode() #CF adds this to stop skipping trials due to not recording pylink.msecDelay(50) error = self.tracker.startRecording(1,1,1,1)#start to recording (File_samples, File_events, Link_samples, Link_events); if 1, writes something to EDF file. If 0, disables something recording. if error: return error; pylink.beginRealTimeMode(100)
def start_recording(self): """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker""" self.recording = True i = 0 while True: # params: write samples, write event, send samples, send events print(u'starting recording ...') error = pylink.getEYELINK().startRecording(1, 1, 1, 1) print(u'returned %s' % error) if not error: break if i > self.MAX_TRY: raise Exception( "Error in libeyelink.libeyelink.start_recording(): Failed " "to start recording!") self.close() clock.expend() i += 1 print( ("WARNING libeyelink.libeyelink.start_recording(): Failed to " "start recording (attempt %d of %d)") % (i, self.MAX_TRY)) pylink.msecDelay(100) # don't know what this is print(u'Start realtime mode ...') pylink.msecDelay(100) pylink.beginRealTimeMode(100) # wait a bit until samples start coming in print(u'Wait for block start ...') pylink.msecDelay(100) if not pylink.getEYELINK().waitForBlockStart(100, 1, 0): raise Exception( "Error in libeyelink.libeyelink.start_recording(): Failed to " "start recording (waitForBlockStart error)!") print(u'done ...')
def start_recording(self): """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker""" self.recording = True i = 0 while True: # params: write samples, write event, send samples, send events print(u'starting recording ...') error = pylink.getEYELINK().startRecording(1, 1, 1, 1) print(u'returned %s' % error) if not error: break if i > self.MAX_TRY: raise Exception( "Error in libeyelink.libeyelink.start_recording(): Failed " "to start recording!") self.close() clock.expend() i += 1 print( ("WARNING libeyelink.libeyelink.start_recording(): Failed to " "start recording (attempt %d of %d)") % (i, self.MAX_TRY)) pylink.msecDelay(100) # don't know what this is print(u'Start realtime mode ...') pylink.msecDelay(100) pylink.beginRealTimeMode(100) # wait a bit until samples start coming in print(u'Wait for block start ...') pylink.msecDelay(100) if not pylink.getEYELINK().waitForBlockStart(100, 1, 0): raise Exception( "Error in libeyelink.libeyelink.start_recording(): Failed to " "start recording (waitForBlockStart error)!") print(u'done ...')
def startEyeTracking(self, trial, calibTrial, widthPix, heightPix): #Set up each trial with the eye tracker if calibTrial: cond = "Test/Calibration Trial" else: cond = "Non-test/no calibration trial" message = "record_status_message 'Trial %d %s'" % (trial + 1, cond) self.tracker.sendCommand(message) msg = "TRIALID %s" % trial self.tracker.sendMessage(msg) #The following does drift correction at the begin of each trial if calibTrial: # Does drift correction and handles the re-do camera setup situations while True: try: error = self.tracker.doDriftCorrect( widthPix / 2, heightPix / 2, 1, 1) # 0: the fixation target must be drawn by the user if error != 27: #self.tracker.applyDriftCorrect break else: self.tracker.doTrackerSetup() except: print("Exception") break #self.tracker.sendCommand('start_drift_correction DATA =1 1 1 1') #CF - start drift correct?? #self.tracker.applyDriftCorrect() #CF - added to actually correct for drift self.tracker.setOfflineMode( ) #CF adds this to stop skipping trials due to not recording pylink.msecDelay(50) error = self.tracker.startRecording( 1, 1, 1, 1 ) #start to recording (File_samples, File_events, Link_samples, Link_events); if 1, writes something to EDF file. If 0, disables something recording. if error: return error pylink.beginRealTimeMode(100)
def resume_recording(self): error = self.tracker.startRecording(1, 1, 1, 1) if error: self.display_message('Error occured.') print error raise RuntimeError(error) else: # introduce 100 millisecond delay after recording begins # to ensure that no data is missed before the trial starts. pylink.beginRealTimeMode(100)
def preTrial(self, trial, win, calibTrial=False): '''Set up each trial with the eye tracker ''' if calibTrial: cond = "Test/Calibration Trial" else: cond = "Non-test/no calibration trial" message = "record_status_message 'Trial %d %s'" % ( trial, cond) ####rajouter le run? self.tracker.sendCommand(message) msg = "TRIALID %s" % trial self.tracker.sendMessage(msg) #Do drift correction if necissary if calibTrial: win.flip() while True: try: error = self.tracker.doDriftCorrect( self.screenSize[0] / 2, self.screenSize[1] / 2, 1, 1) if error != 27: self.tracker.applyDriftCorrect break else: #self.tracker.doTrackerSetup() win.flip() #####refaire une calib? except: print("Exception") ######sert a rien break win.flip() ##################################################################################enlever au dessus + print("Switching to record mode") error = self.tracker.startRecording(1, 1, 1, 1) pylink.beginRealTimeMode(100) if error: return error #### if not self.tracker.waitForBlockStart(1000, 1, 0): ###### self.tracker.sendMessage("TRIAL ERROR") self.endTrial() #arreter l'enregistrement car il y a erreur print "ERROR: No link samples received!" return "TRIAL_ERROR" self.eye_used = self.tracker.eyeAvailable() #determine which eye(s) are available if self.eye_used == RIGHT_EYE: self.tracker.sendMessage("EYE_USED 1 RIGHT") elif self.eye_used == LEFT_EYE or self.eye_used == BINOCULAR: self.tracker.sendMessage("EYE_USED 0 LEFT") self.eye_used = LEFT_EYE else: print "Error in getting the eye information!" return "TRIAL_ERROR" self.tracker.sendMessage("TRIAL ERROR") self.tracker.flushKeybuttons(0)
def preTrial(self, trial, calibTrial, win): '''Set up each trial with the eye tracker ''' if calibTrial: cond = "Test/Calibration Trial" else: cond = "Non-test/no calibration trial" message ="record_status_message 'Trial %d %s'"%(trial+1, cond) self.tracker.sendCommand(message) msg = "TRIALID %s"%trial self.tracker.sendMessage(msg) #Do drift correction if necissary if calibTrial: win.flip() while True: try: error = self.tracker.doDriftCorrect(self.screenSize[0]/2,self.screenSize[1]/2,1,1) if error != 27: self.tracker.applyDriftCorrect break else: #self.tracker.doTrackerSetup() win.flip() except: print("Exception") break win.flip() print("Switching to record mode") error = self.tracker.startRecording(1,1,1,1) pylink.beginRealTimeMode(100) if error: return error if not self.tracker.waitForBlockStart(1000, 1, 0): endTrial() print "ERROR: No link samples received!" return "ABORT_EXPT" self.eye_used = self.tracker.eyeAvailable(); #determine which eye(s) are available if self.eye_used == RIGHT_EYE: self.tracker.sendMessage("EYE_USED 1 RIGHT") elif self.eye_used == LEFT_EYE or self.eye_used == BINOCULAR: self.tracker.sendMessage("EYE_USED 0 LEFT") self.eye_used = LEFT_EYE else: print "Error in getting the eye information!" return "ABORT_EXPT" self.tracker.flushKeybuttons(0)
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 do_trial(par): '''Does the simple trial''' id_number = str(par[0])+" TRIAL_TYPE "+str(par[1])+" CODE_TYPE "+str(par[-1]) ## par contains the trial parameters ##This supplies the title at the bottom of the eyetracker display # message ="record_status_message 'Trial %s'"%id_number # MyEyelink.sendCommand(message); ##Always send a TRIALID message before starting to record. ##EyeLink Data Viewer defines the start of a trial by the TRIALID message. ##This message is different than the start of recording message START that is logged when the trial recording begins. ##The Data viewer will not parse any messages, events, or samples, that exist in the data file prior to this message. msg = "TRIALID %s"%id_number; MyEyelink.sendMessage(msg); ##This TRIAL_VAR command specifies a trial variable and value for the given trial. ##Send one message for each pair of trial condition variable and its corresponding value. ## You can put this in a function updateStimuliFromParameters(par) #giveParametersToEyeTracker(par) ## you can do a drifcorrection if you want ## fonction() error = MyEyelink.startRecording(1,1,1,1) if error: return error; gc.disable(); # switch off the garbage collector #begin the realtime mode pylink.beginRealTimeMode(100) if not MyEyelink.waitForBlockStart(100, 1, 0): end_trial(); print "ERROR: No link samples received!"; return pylink.TRIAL_ERROR; ## we inserted the gap duration information at par[-4] and the type_code at par[-1] ## the fixation duration if now at par[-5] ## the gap duration is used by drawCondition ## (change from previous program: par[-3:] to par[-5:-1]) ret_value = drawCondition(*par[-5:-1].astype(int)); pylink.endRealTimeMode(); gc.enable(); return ret_value;
def _setup(self): """The EyeLink-specific part of the setup process. """ self.version = self.getTrackerVersionString() self.__custom_display = ELCustomDisplay() openGraphicsEx(self.__custom_display) flushGetkeyQueue() self.setOfflineMode() self.sendCommand("screen_pixel_coords = 0 0 {0} {1}".format(P.screen_x-1, P.screen_y-1)) self.setLinkEventFilter("FIXATION,SACCADE,BLINK,LEFT,RIGHT") self.setLinkEventData("GAZE, GAZERES, AREA, VELOCITY") # Enables fix/sacc start events self.openDataFile(self.edf_filename) self.write("DISPLAY_COORDS 0 0 {0} {1}".format(P.screen_x-1, P.screen_y-1)) self.setSaccadeVelocityThreshold(P.saccadic_velocity_threshold) self.setAccelerationThreshold(P.saccadic_acceleration_threshold) self.setMotionThreshold(P.saccadic_motion_threshold) beginRealTimeMode(10)
def Start_trial(self, trial): # Titre essai en cours au bas de l'écran d'eyetracker print(trial) message = "record_status_message 'Trial %d/%d'" % (trial + 1, self.N_trials) self.eyelink.sendCommand(message) # EyeLink Data Viewer définit le début d'un essai par le message TRIALID. msg = "TRIALID %d" % trial self.eyelink.sendMessage(msg) msg = "!V TRIAL_VAR_DATA %d" % trial self.eyelink.sendMessage(msg) # Commutez le tracker sur ide et donnez-lui le temps d'effectuer un interrupteur de mode complet self.eyelink.setOfflineMode() pylink.msecDelay(50) # Commencez à enregistrer des échantillons et des événements sur le fichier edf et sur le lien. error = self.eyelink.startRecording(1, 1, 1, 1) # 0 si tout se passe bien ! if error: self.End_trial() print('error =', error) #return error #gc.disable() # Désactiver la collecte python pour éviter les retards TESTER ENLEVER !!! pylink.beginRealTimeMode(100) # Commencer le mode temps réel # Lit et supprime les événements dans la file d'attente de données jusqu'à ce qu'ils soient dans un bloc d'enregistrement. try: self.eyelink.waitForBlockStart(100, 1, 0) except RuntimeError: if pylink.getLastError( )[0] == 0: # Temps d'attente expiré sans données de lien self.End_trial() self.eyelink.sendMessage("TRIAL ERROR") print("ERROR: No link samples received!") return pylink.TRIAL_ERROR else: raise
def EyelinkStart(dispsize, Name, win, bits=32, dummy=False, colors=((0, 0, 0), (192, 192, 192))): """ Performs startup routines for the EyeLink 1000 Plus eyetracker. **Author** : Wanja Mössing, WWU Münster | [email protected] \n *July 2017* Parameters: ----------- dispsize : tuple two-item tuple width & height in px Name : string filename for the edf. Doesn't have to, but can, end on '.edf' Maximum length is 8 (without '.edf'). Possible alphanumeric input: 'a-z', 'A-Z', '0-9', '-' & '_' win : window object You necessarily need to open a psychopy window first! bits : integer color-depth, defaults to 32 dummy : boolean Run tracker in dummy mode? colors : Tuple, Optional. Tuple with two RGB triplets Returns ------- 'el' the tracker object. This can be passed to other functions, although they can use pylink.getEYELINK() to find it automatically. """ print('. ') # get filename if '.edf' not in Name.lower(): if len(Name) > 8: print('EDF filename too long! (1-8 characters/letters)') raise SystemExit else: Name += '.edf' elif '.edf' in Name.lower(): if len(Name) > 12: print('EDF filename too long! (1-8 characters/letters)') raise SystemExit print('. ') # initialize tracker object if dummy: el = pylink.EyeLink(None) else: el = pylink.EyeLink("100.1.1.1") print('. ') # Open EDF file on host el.openDataFile(Name) print('. ') # set file preamble currentdir = path.basename(getcwd()) FilePreamble = "add_file_preamble_text \'" FilePreamble += "Eyetracking Dataset AE Busch WWU Muenster Experiment: " FilePreamble += currentdir + "\'" el.sendCommand(FilePreamble) print('. ') # this function calls the custom calibration routine # "EyeLinkCoreGraphicsPsychopy.py" genv = EyeLinkCoreGraphicsPsychoPy(el, win) pylink.openGraphicsEx(genv) print('. ') # set tracker offline to change configuration el.setOfflineMode() print('. ') # flush old keys pylink.flushGetkeyQueue() print('. ') # set sampling rate el.sendCommand('sample_rate 1000') print('. ') # Sets the display coordinate system and sends mesage to that # effect to EDF file; el.sendCommand("screen_pixel_coords = 0 0 %d %d" % (dispsize[0] - 1, dispsize[1] - 1)) el.sendMessage("DISPLAY_COORDS 0 0 %d %d" % (dispsize[0] - 1, dispsize[1] - 1)) print('. ') # select parser configuration for online saccade etc detection ELversion = el.getTrackerVersion() ELsoftVer = 0 if ELversion == 3: tmp = el.getTrackerVersionString() tmpidx = tmp.find('EYELINK CL') ELsoftVer = int(float(tmp[(tmpidx + len("EYELINK CL")):].strip())) if ELversion >= 2: el.sendCommand("select_parser_configuration 0") if ELversion == 2: # turn off scenelink stuff (that's an EL2 front-cam addon...) el.sendCommand("scene_camera_gazemap = NO") else: el.sendCommand("saccade_velocity_threshold = 35") el.sendCommand("saccade_acceleration_threshold = 9500") print('. ') # set EDF file contents AREA el.sendCommand("file_event_filter = LEFT,RIGHT,FIXATION," "SACCADE,BLINK,MESSAGE,BUTTON,INPUT") if ELsoftVer >= 4: el.sendCommand("file_sample_data = LEFT,RIGHT,GAZE,HREF," "AREA,HTARGET,GAZERES,STATUS,INPUT") else: el.sendCommand("file_sample_data = LEFT,RIGHT,GAZE,HREF," "AREA,GAZERES,STATUS,INPUT") print('. ') # set link data (online interaction)AREA el.sendCommand("link_event_filter = LEFT,RIGHT,FIXATION,SACCADE," "BLINK,MESSAGE,BUTTON,INPUT") if ELsoftVer >= 4: el.sendCommand("link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA," "HTARGET,STATUS,INPUT") else: el.sendCommand("link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA," "STATUS,INPUT") print('. ') # run initial calibration # 13-Pt Grid calibration el.sendCommand('calibration_type = HV13') el.doTrackerSetup(dispsize[0], dispsize[1]) # put tracker in idle mode and wait 50ms, then really start it. el.sendMessage('SETUP_FINISHED') el.setOfflineMode() pylink.msecDelay(500) # set to realtime mode pylink.beginRealTimeMode(200) # start recording # note: sending everything over the link *potentially* causes buffer # overflow. However, with modern PCs and EL1000+ this shouldn't be a real # problem el.startRecording(1, 1, 1, 1) # to activate parallel port readout without modifying the FINAL.INI on the # eyelink host pc, uncomment these lines # tyical settings for straight-through TTL cable (data pins -> data pins) el.sendCommand('write_ioport 0xA 0x20') el.sendCommand('create_button 1 8 0x01 0') el.sendCommand('create_button 2 8 0x02 0') el.sendCommand('create_button 3 8 0x04 0') el.sendCommand('create_button 4 8 0x08 0') el.sendCommand('create_button 5 8 0x10 0') el.sendCommand('create_button 6 8 0x20 0') el.sendCommand('create_button 7 8 0x40 0') el.sendCommand('create_button 8 8 0x80 0') el.sendCommand('input_data_ports = 8') el.sendCommand('input_data_masks = 0xFF') # tyical settings for crossover TTL cable (data pins -> status pins) # el.sendCommand('write_ioport 0xA 0x0') # el.sendCommand('create_button 1 9 0x20 1') # el.sendCommand('create_button 2 9 0x40 1') # el.sendCommand('create_button 3 9 0x08 1') # el.sendCommand('create_button 4 9 0x10 1') # el.sendCommand('create_button 5 9 0x80 0') # el.sendCommand('input_data_ports = 9') # el.sendCommand('input_data_masks = 0xFF') # mark end of Eyelinkstart in .edf el.sendMessage('>EndOfEyeLinkStart') # return Eyelink object return el
def runTrial(params, expInfo): """ pars should be a list, like ['red', 'red', 'left', 'cong'] dataFile is an opened csv file that use to store our data in a sheet. """ # unpacking the parameters text, textColor, correctAnswer, congruency = params # prepare the stimuli word = visual.TextStim(win=win, text=text, font='Arial', height=100.0, color=textColor) w, h = word.boundingBox # flush cached button presses (eyelink) tk.flushKeybuttons(0) tk.setOfflineMode() pylink.msecDelay(50) # OPTIONAL-- draw the text on the Host screen and show the bounding box tk.sendCommand('clear_screen 0') # clear the host Display first tk.sendCommand('draw_text %d %d 6 %s' % (scnWidth / 2, scnHeight / 2, text)) tk.sendCommand('draw_box %d %d %d %d 6' % (scnWidth / 2 - w / 2, scnHeight / 2 - h / 2, scnWidth / 2 + w / 2, scnHeight / 2 + h / 2)) # log trial onset message tk.sendMessage("TRIALID %s %s %s" % (text, textColor, congruency)) # record_status_message : show some info on the host PC tk.sendCommand("record_status_message 'congruency: %s'" % congruency) #Optional - start realtime mode pylink.beginRealTimeMode(100) # do driftcheck try: error = tk.doDriftCorrect(scnWidth / 2, scnHeight / 2, 1, 1) except: tk.doTrackerSetup() # start recording, parameters specify whether events and samples are # stored in file, and available over the link tk.startRecording(1, 1, 1, 1) pylink.msecDelay(50) # Clear bufferred events (in Psychopy) event.clearEvents(eventType='keyboard') # draw the target word on display word.draw() win.flip() tk.sendMessage("SYNCTIME") # message to mark the onset of visual stimuli # save a screenshot so we can use it in Data Viewer to superimpose the gaze if not os.path.exists('screenshotFolder'): os.mkdir('screenshotFolder') screenshot = 'screenshotFolder' + os.sep + 'cond_%s_%s.jpg' % (text, textColor) win.getMovieFrame() win.saveMovieFrames(screenshot) # send a Data Viewer integration message here, so DV knows which screenshot to load tk.sendMessage('!V IMGLOAD FILL %s' % ('..' + os.sep + screenshot)) # check for response & time out gotKey = False timeOut = False tStart = core.getTime() subjResp = ['None', 'None'] while not (gotKey or timeOut): # check for time out tNow = core.getTime() if tNow - tStart >= 10.0: timeOut = True # check for key presses keyPressed = event.getKeys(['left', 'right', 'down', 'escape']) if len(keyPressed) > 0: if 'escape' in keyPressed: tk.sendMessage("Quit") win.close() core.quit() # terminate the task if ESCAPE is pressed else: subjResp = [keyPressed[0], tNow] tk.sendMessage("RESPONSE %s" % (keyPressed[0])) gotKey = True # clear the subject display win.color = 'black' win.flip() # clear the host Display tk.sendCommand('clear_screen 0') # was the subject's response 'correct'? if subjResp[0] == correctAnswer: respAcc = 1 else: respAcc = 0 # OPTIONAL-- set an Interest Area for data viewer integraiton # a full list of Data Viewer integration messages and their syntax can be found in the Data Viewer Manual # (Help menu -> Contents -> Protocol for EyeLink Data To Viewer Integraiton). tk.sendMessage("!V IAREA RECTANGLE 1 %d %d %d %d target" % (scnWidth / 2 - w / 2, scnHeight / 2 - h / 2, scnWidth / 2 + w / 2, scnHeight / 2 + h / 2)) # EyeLink - Send Trialvar messages for data viewer integraiton # a full list of Data Viewer integration messages and their syntax can be found in the Data Viewer Manual # (Help menu -> Contents -> Protocol for EyeLink Data To Viewer Integraiton). tk.sendMessage("!V TRIAL_VAR word %s" % (text)) tk.sendMessage("!V TRIAL_VAR color %s" % (textColor)) tk.sendMessage("!V TRIAL_VAR congruency %s" % (congruency)) tk.sendMessage("!V TRIAL_VAR respAcc %d" % (respAcc)) # Optional-- end realtime mode pylink.endRealTimeMode() pylink.msecDelay(100) # send a message to mark the end of trial tk.sendMessage("TRIAL_RESULT %d" % (respAcc)) pylink.msecDelay(100) # EyeLink - stop recording eye data tk.stopRecording() pylink.msecDelay(50) tk.setOfflineMode()
tracker_software_ver = int(float(tvstr[(vindex + len("EYELINK CL")):].strip())) print 'tracker version', eyelink_ver print 'tracker software v', tracker_software_ver # set EDF file contents pylink.getEYELINK().sendCommand("file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON") if tracker_software_ver>=4: pylink.getEYELINK().sendCommand("file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET") else: pylink.getEYELINK().sendCommand("file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS") pylink.setCalibrationColors( (0, 0, 0),(255, 255, 255)); #Sets the calibration target and background color pylink.setTargetSize(int(window_size[0]/40), int(window_size[0]/30)); #select best size for calibration target #----------------------------------------------------------------------------- pylink.beginRealTimeMode(0) print 'started real time mode' pylink.getEYELINK().startRecording(1, 1, 0, 0) core.wait(3) pylink.endRealTimeMode() pylink.getEYELINK().setOfflineMode() win.close() if pylink.getEYELINK() != None: # File transfer and cleanup! pylink.getEYELINK().setOfflineMode(); pylink.msecDelay(500);
def EyelinkStart(dispsize, Name, win, bits=32, dummy=False, colors=((0, 0, 0), (192, 192, 192))): """ Performs startup routines for the EyeLink 1000 Plus eyetracker. **Author** : Wanja Mössing, WWU Münster | [email protected] \n *July 2017* Parameters: ----------- dispsize : tuple two-item tuple width & height in px Name : string filename for the edf. Doesn't have to, but can, end on '.edf' Maximum length is 8 (without '.edf'). Possible alphanumeric input: 'a-z', 'A-Z', '0-9', '-' & '_' win : window object You necessarily need to open a psychopy window first! bits : integer color-depth, defaults to 32 dummy : boolean Run tracker in dummy mode? colors : Tuple, Optional. Tuple with two RGB triplets Returns ------- 'el' the tracker object. This can be passed to other functions, although they can use pylink.getEYELINK() to find it automatically. """ print('. ') # get filename if '.edf' not in Name.lower(): if len(Name) > 8: print('EDF filename too long! (1-8 characters/letters)') raise SystemExit else: Name += '.edf' elif '.edf' in Name.lower(): if len(Name) > 12: print('EDF filename too long! (1-8 characters/letters)') raise SystemExit print('. ') # initialize tracker object if dummy: el = pylink.EyeLink(None) else: el = pylink.EyeLink("100.1.1.1") print('. ') # Open EDF file on host el.openDataFile(Name) print('. ') # set file preamble currentdir = path.basename(getcwd()) FilePreamble = "add_file_preamble_text \'" FilePreamble += "Eyetracking Dataset AE Busch WWU Muenster Experiment: " FilePreamble += currentdir + "\'" el.sendCommand(FilePreamble) print('. ') # this function calls the custom calibration routine # "EyeLinkCoreGraphicsPsychopy.py" genv = EyeLinkCoreGraphicsPsychoPy(el, win) pylink.openGraphicsEx(genv) print('. ') # set tracker offline to change configuration el.setOfflineMode() print('. ') # flush old keys pylink.flushGetkeyQueue() print('. ') # set sampling rate el.sendCommand('sample_rate 1000') print('. ') # Sets the display coordinate system and sends mesage to that # effect to EDF file; el.sendCommand("screen_pixel_coords = 0 0 %d %d" % (dispsize[0] - 1, dispsize[1] - 1)) el.sendMessage("DISPLAY_COORDS 0 0 %d %d" % (dispsize[0] - 1, dispsize[1] - 1)) print('. ') # select parser configuration for online saccade etc detection ELversion = el.getTrackerVersion() ELsoftVer = 0 if ELversion == 3: tmp = el.getTrackerVersionString() tmpidx = tmp.find('EYELINK CL') ELsoftVer = int(float(tmp[(tmpidx + len("EYELINK CL")):].strip())) if ELversion >= 2: el.sendCommand("select_parser_configuration 0") if ELversion == 2: # turn off scenelink stuff (that's an EL2 front-cam addon...) el.sendCommand("scene_camera_gazemap = NO") else: el.sendCommand("saccade_velocity_threshold = 35") el.sendCommand("saccade_acceleration_threshold = 9500") print('. ') # set EDF file contents AREA el.sendCommand("file_event_filter = LEFT,RIGHT,FIXATION," "SACCADE,BLINK,MESSAGE,BUTTON,INPUT") if ELsoftVer >= 4: el.sendCommand("file_sample_data = LEFT,RIGHT,GAZE,HREF," "AREA,HTARGET,GAZERES,STATUS,INPUT") else: el.sendCommand("file_sample_data = LEFT,RIGHT,GAZE,HREF," "AREA,GAZERES,STATUS,INPUT") print('. ') # set link data (online interaction)AREA el.sendCommand("link_event_filter = LEFT,RIGHT,FIXATION,SACCADE," "BLINK,MESSAGE,BUTTON,INPUT") if ELsoftVer >= 4: el.sendCommand("link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA," "HTARGET,STATUS,INPUT") else: el.sendCommand("link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA," "STATUS,INPUT") print('. ') # run initial calibration # 13-Pt Grid calibration el.sendCommand('calibration_type = HV13') EyelinkCalibrate(dispsize, el) print('. ') # put tracker in idle mode and wait 50ms, then really start it. el.sendMessage('SETUP_FINISHED') el.setOfflineMode() pylink.msecDelay(500) print('. ') # set to realtime mode pylink.beginRealTimeMode(200) # start recording # note: sending everything over the link *potentially* causes buffer # overflow. However, with modern PCs and EL1000+ this shouldn't be a real # problem el.startRecording(1, 1, 1, 1) # to activate parallel port readout without modifying the FINAL.INI on the # eyelink host pc, uncomment these lines # tyical settings for straight-through TTL cable (data pins -> data pins) el.sendCommand('write_ioport 0xA 0x20') el.sendCommand('create_button 1 8 0x01 0') el.sendCommand('create_button 2 8 0x02 0') el.sendCommand('create_button 3 8 0x04 0') el.sendCommand('create_button 4 8 0x08 0') el.sendCommand('create_button 5 8 0x10 0') el.sendCommand('create_button 6 8 0x20 0') el.sendCommand('create_button 7 8 0x40 0') el.sendCommand('create_button 8 8 0x80 0') el.sendCommand('input_data_ports = 8') el.sendCommand('input_data_masks = 0xFF') # tyical settings for crossover TTL cable (data pins -> status pins) # el.sendCommand('write_ioport 0xA 0x0') # el.sendCommand('create_button 1 9 0x20 1') # el.sendCommand('create_button 2 9 0x40 1') # el.sendCommand('create_button 3 9 0x08 1') # el.sendCommand('create_button 4 9 0x10 1') # el.sendCommand('create_button 5 9 0x80 0') # el.sendCommand('input_data_ports = 9') # el.sendCommand('input_data_masks = 0xFF') # mark end of Eyelinkstart in .edf el.sendMessage('>EndOfEyeLinkStart') # return Eyelink object return el
# set EDF file contents pylink.getEYELINK().sendCommand( "file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON") if tracker_software_ver >= 4: pylink.getEYELINK().sendCommand( "file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET") else: pylink.getEYELINK().sendCommand( "file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS") pylink.setCalibrationColors((0, 0, 0), (255, 255, 255)) #Sets the calibration target and background color pylink.setTargetSize(int(window_size[0] / 40), int(window_size[0] / 30)) #select best size for calibration target pylink.beginRealTimeMode(0) print('started real time mode') pylink.getEYELINK().startRecording(1, 1, 0, 0) core.wait(3) pylink.endRealTimeMode() pylink.getEYELINK().setOfflineMode() win.close() if pylink.getEYELINK() != None: # File transfer and cleanup! pylink.getEYELINK().setOfflineMode() pylink.msecDelay(500)
def preTrial(self, trial, calibTrial, win,autoDrift=False): '''Set up each trial with the eye tracker ''' self.tracker.doSetup=False if calibTrial: cond = "Test/Calibration Trial" else: cond = "Non-test/no calibration trial" message ="record_status_message 'Trial %d %s'"%(trial+1, cond) self.tracker.sendCommand(message) msg = "TRIALID %s"%trial self.tracker.sendMessage(msg) #Do drift correction if necissary if calibTrial: win.flip() while True: try: error = self.tracker.doDriftCorrect(self.screenSize[0]/2,self.screenSize[1]/2,1,1) if error != 27: self.tracker.applyDriftCorrect() break else: #self.tracker.doTrackerSetup() win.flip() except: print("Exception") break win.flip() print("Switching to record mode") error = self.tracker.startRecording(1,1,1,1) pylink.beginRealTimeMode(100) if error: return error if not self.tracker.waitForBlockStart(1000, 1, 0): endTrial() print "ERROR: No link samples received!" return "ABORT_EXPT" self.eye_used = self.tracker.eyeAvailable(); #determine which eye(s) are available if self.eye_used == RIGHT_EYE: self.tracker.sendMessage("PRETRIAL EYE_USED 1 RIGHT") elif self.eye_used == LEFT_EYE : self.tracker.sendMessage("PRETRIAL EYE_USED 0 LEFT") elif self.eye_used == BINOCULAR: self.tracker.sendMessage("PRETRIAL EYE_USED 2 BINOCULAR") else: print "Error in getting the eye information!" return "ABORT_EXPT" self.tracker.flushKeybuttons(0) if autoDrift: self.tracker.target.setPos((0, 0)) self.tracker.target.draw() win.flip() x,y=self.screenSize/2.0 i=0 leftFinished=False rightFinished=False core.wait(0.5) self.tracker.resetData() while i<10 and not (leftFinished and rightFinished): sampleType = self.tracker.getNextData() if sampleType == pylink.FIXUPDATE: sample = self.tracker.getFloatData() gazePos=sample.getAverageGaze() #self.sendMessage('eyePos %.3f %.3f type %d, eye %d'%(gazePos[0],gazePos[1],sample.getType(),sample.getEye())) if (( (x-gazePos[0])**2+(y-gazePos[1])**2)**0.5<misc.deg2pix(3,win.monitor) and gazePos[0]>0 and gazePos[0]<2*x and gazePos[1]>0 and gazePos[1]<2*y): cmd='drift_correction %f %f %f %f' % (x-gazePos[0], y-gazePos[1],x,y) if sample.getEye()==1: rightFinished=True; cmd+=' R' else: leftFinished=True; cmd+=' L' self.sendCommand(cmd) else: core.wait(0.1) self.tracker.resetData() i+=1 if i==10: self.postTrial() self.tracker.doTrackerSetup() self.preTrial(trial, calibTrial, win,autoDrift) else: core.wait(0.25+random.random()/2) return