Beispiel #1
0
 def __init__(self, win, filename="TEST.EDF"):
     self.win = win
     EyeLink.__init__(self)
     self._filename = filename
     self.openDataFile(filename)
     #EyeLinkCustomDisplay.__init__(self)
     self._surfs = pygame.display.get_surface()
     pylink.flushGetkeyQueue()
     col = 128
     pylink.setCalibrationColors(
         (0, 0, 0),
         (col, col, col))  #Sets the calibration target and background color
     self.sendCommand("screen_pixel_coords =  0 0 %d %d" %
                      (self._surfs.get_width(), self._surfs.get_height()))
     self.sendMessage("DISPLAY_COORDS  0 0 %d %d" %
                      (self._surfs.get_width(), self._surfs.get_height()))
     self.sendCommand("select_parser_configuration 0")
     self.setFileEventFilter(
         "LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
     self.setFileSampleFilter("LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
     self.setLinkEventFilter("LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
     self.setLinkSampleFilter("LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")
     self.sendCommand("button_function 5 'accept_target_fixation'")
     self.inner = visual.PatchStim(win,
                                   tex=None,
                                   mask='circle',
                                   units='pix',
                                   size=5,
                                   color=win.color)
     self.outer = visual.PatchStim(win,
                                   tex=None,
                                   mask='circle',
                                   units='pix',
                                   size=20,
                                   color=[128, 128, 128])
    def __init__(self, display, filename="TEST.EDF"):
        EyeLink.__init__(self)
        self._disp = display
        self._filename = filename
        self.openDataFile(filename)

        self._surfs = [0,0,1920,1080]#self._disp.get_rect()
        pylink.flushGetkeyQueue()
        
        col = 128
        print "1"
        pylink.setCalibrationColors((0, 0, 0), (col, col, col)) #Sets the calibration target and background color
        print int(self._surfs[3]/300)
#        pylink.setTargetSize(int(self._surfs[2]/70), int(self._surfs[3]/300)) #select best size for calibration target
        print "12"
        pylink.setCalibrationSounds("off", "off", "off")
        pylink.setDriftCorrectSounds("off", "off", "off")

        self.sendCommand("screen_pixel_coords =  0 0 %d %d" % (self._surfs[2], self._surfs[3]))
        self.sendMessage("DISPLAY_COORDS  0 0 %d %d" % (self._surfs[2], self._surfs[3]))
        
        #self.sendMessage("heuristic_filter" % (self._surfs[2], self._surfs[3]))
        #assert self.getTrackerVersion() == 2
        self.sendCommand("select_parser_configuration 0")
        self.setFileEventFilter("LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
        self.setFileSampleFilter("LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
        self.setLinkEventFilter("LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
        self.setLinkSampleFilter("LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")
        print "2"
        self.sendCommand("button_function 5 'accept_target_fixation'")
Beispiel #3
0
    def __init__(self, subjID, dataDir):
        self._init_graphics()
        self._init_datafiles(subjID, dataDir)
        self._init_tracker()
        self._init_calibration()

        pylink.flushGetkeyQueue()
        self.tracker.setOfflineMode()
        self.tracker.openDataFile(self.trackerDatafile)
Beispiel #4
0
 def setup_eyelink(self):
     
     '''Thank you very much
     
     '''
     # call for eyelink
     self.eyelink_tracker = pl.EyeLink("100.1.1.1")
     
     #parameters for eyelink
     self.monitor = monitors.Monitor('testMonitor')
     self.winSize = self.monitor.getSizePix()
     self.foreground = (250,250,250)
     self.background = (127,127,127)
     
     # create file
     self.edfFileName = "cbConfig" + str(self.subjectID)
     if len(self.edfFileName) > 8:
         self.edfFileName = self.edfFileName[0:8]
     pl.getEYELINK().openDataFile(self.edfFileName)
     pl.getEYELINK().setOfflineMode()
 
     #Eyelink - Gets the display surface and sends a mesage to EDF file;
     pl.getEYELINK().sendCommand("screen_pixel_coords =  0 0 %d %d"%(self.winSize[0]-1, self.winSize[1]-1))
     pl.getEYELINK().sendMessage("Resolution %d %d" %((self.winSize[0]-1, self.winSize[1]-1)))
     pl.getEYELINK().sendMessage("EyeToScreen %d" %(self.monitor.getDistance()))
     pl.getEYELINK().sendMessage("MonitorWidth %d" %(self.monitor.getWidth()))
 
     #EyeLink - Set data file contents
     pl.getEYELINK().sendCommand("file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET,INPUT")
     pl.getEYELINK().sendCommand("link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET,INPUT")
 
     #EyeLink - Set Filter contents
     pl.getEYELINK().sendCommand("file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT")
     pl.getEYELINK().sendCommand("link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON,INPUT")
 
     #EyeLink - Set Calibration Environment
     pl.setCalibrationColors(self.foreground, self.background);  	#Sets the calibration target and background color  - background color should match testing background        
     
     pl.flushGetkeyQueue()
     pl.getEYELINK().setOfflineMode()
     winX = int(self.winSize[0])
     winY = int(self.winSize[1])
     pl.openGraphics((winX,winY),32)
     pl.getEYELINK().doTrackerSetup()
     pl.closeGraphics()
     pl.setCalibrationSounds("", "", "");
     pl.setDriftCorrectSounds("", "off", "off");
     
     # close configuration file
     event.clearEvents()
     pl.getEYELINK().closeDataFile()
     transferFileName = self.edfFileName + '.edf' # fileName
     pl.getEYELINK().receiveDataFile(self.edfFileName, transferFileName)
    def __init__(self, window, edfname):
        # Pull out monitor info
        self.sres = window.size
        self.scenter = [self.sres[0] / 2.0, self.sres[1] / 2.0]
        self.win = window

        # Make filename
        fname = os.path.splitext(edfname)[0]  # strip away extension if present
        assert re.match(r'\w+$',
                        fname), 'Name must only include A-Z, 0-9, or _'
        assert len(fname) <= 8, 'Name must be <= 8 characters.'

        self.edfname = fname + '.edf'

        # Initialize connection with eyetracker
        try:
            self.tracker = pylink.EyeLink()
            self.realconnect = True
        except RuntimeError:
            self.tracker = pylink.EyeLink(None)
            self.realconnect = False

        # Check which eye is being recorded
        self.eye_used = self.tracker.eyeAvailable()

        # Make pylink accessible
        self.pylink = pylink

        # Open EDF
        self.tracker.openDataFile(self.edfname)
        pylink.flushGetkeyQueue()
        self.tracker.setOfflineMode()

        # Set content of edf file
        self.tracker.sendCommand(
            'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'
        )

        self.tracker.sendCommand(
            'link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON')

        self.tracker.sendCommand(
            'link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET')

        self.tracker.sendCommand(
            'file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET,INPUT'
        )

        # Set display coords for dataviewer
        self.tracker.sendMessage("screen_pixel_coords =  0 0 %d %d" %
                                 (x_size - 1, y_size - 1))
        self.tracker.sendMessage("DISPLAY_COORDS  0 0 %d %d" %
                                 (x_size - 1, y_size - 1))
Beispiel #6
0
    def __init__(self, window, edfname, address="100.1.1.1"):
        # Pull out monitor info
        self.sres = window.size
        self.scenter = [self.sres[0] / 2.0, self.sres[1] / 2.0]
        self.win = window

        # Make filename
        fname = os.path.splitext(edfname)[0]  # strip away extension if present
        assert re.match(r'\w+$',
                        fname), 'Name must only include A-Z, 0-9, or _'
        assert len(fname) <= 8, 'Name must be <= 8 characters.'

        self.edfname = fname + '.edf'

        # Initialize connection with eye-tracker
        try:
            self.tracker = pylink.EyeLink(address)
            self.realconnect = True
        except RuntimeError:
            self.tracker = pylink.EyeLink(None)
            self.realconnect = False

        # Make pylink accessible
        self.pylink = pylink

        # Open EDF
        #Close any open file first
        if self.tracker.getTrackerMode() == pylink.EL_RECORD_MODE:
            self.tracker.closeDataFile()
        self.tracker.openDataFile(self.edfname)
        pylink.flushGetkeyQueue()
        self.tracker.setOfflineMode()

        # Set content of edf file
        eftxt = 'LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'
        self.tracker.sendCommand('file_event_filter = ' + eftxt)

        lftxt = 'LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON'
        self.tracker.sendCommand('link_event_filter = ' + lftxt)

        lstxt = 'LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET'
        self.tracker.sendCommand('link_sample_data = ' + lstxt)

        fstxt = 'LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET,INPUT'
        self.tracker.sendCommand('file_sample_data = ' + fstxt)

        # Set display coords for dataviewer
        disptxt = 'DISPLAY_COORDS 0 0 {} {}'.format(*self.sres)
        self.tracker.sendMessage(disptxt)

        # Check which eye is being recorded
        self.eye_used = self.tracker.eyeAvailable()
Beispiel #7
0
    def _create_tracker(self):
        """ Creates tracker object upon initialization. """
        if not self.eyetracker_on or not PYLINK_AVAILABLE:
            return None

        tracker = pylink.EyeLink(self.et_settings.get('address'))
        pylink.flushGetkeyQueue()
        tracker.setOfflineMode()
        tracker.sendCommand('set_idle_mode')  # why?

        self.edf_name = datetime.now().strftime('%H_%M_%S.edf')
        tracker.openDataFile(self.edf_name)
        return tracker
Beispiel #8
0
    def __init__(self, size=[1024, 768], calibscale=1., ip='100.1.1.1', \
                 bgcolor=[127, 127, 127], fgcolor=[255, 255, 255], \
                 targetdiameter=20, targethole=5, calibrationtype='HV9', \
                 calibrationpacing=.9, viewdistance=None, screenwidth=None):

        self.size = tuple(size)
        # connect to tracker and do initial config
        self.tracker = pylink.EyeLink(ip)
        self.eyeused = None
        # flush out any pending key presses and get back to offline mode in
        # case we crashed out while recording
        pylink.flushGetkeyQueue()
        self.tracker.setOfflineMode()
        self.fgcolor = fgcolor
        self.bgcolor = bgcolor
        self.targetdiameter = targetdiameter
        self.targethole = targethole
        # month, day, hour, minute.
        self.remotefilename = time.strftime('%m%d%H%M')
        self.tracker.openDataFile(self.remotefilename)
        self.calibsize = (numpy.array(self.size) * calibscale)
        calibarea = numpy.round(numpy.array(self.size) - self.calibsize)
        alldims = (calibarea[0], calibarea[1], self.calibsize[0],
                   self.calibsize[1])
        self.tracker.sendCommand('screen_pixel_coords =  %d %d %d %d' % alldims)
        self.tracker.sendMessage("DISPLAY_COORDS  %d %d %d %d" % alldims)
        self.tracker.sendMessage("SCREEN_COORDS  0 0 %d %d" % self.size)
        # for robustness we set a bunch of other parameters so that any
        # weird defaults get overwritten
        if viewdistance:
            self.tracker.sendCommand('simulation_screen_distance=%d' % \
                                     (viewdistance * 10))
            self.tracker.sendMessage('VIEW_DISTANCE %d' % (viewdistance * 10))
        self.tracker.sendCommand('automatic_calibration_pacing=%d' % \
                                 (calibrationpacing * 1000))
        if screenwidth:
            self.tracker.sendMessage('SCREEN_WIDTH %d' % screenwidth)
        # NB this command is necessary whenever changing
        # screen_pixel_coords
        self.tracker.sendCommand('calibration_type=' + calibrationtype)
        if self.tracker.getTrackerVersion() == 2:
            self.tracker.sendCommand("select_parser_configuration 0")
        else:
            self.tracker.sendCommand("saccade_velocity_threshold = 35")
            self.tracker.sendCommand("saccade_acceleration_threshold = 9500")
            self.tracker.setFileEventFilter("LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
            self.tracker.setFileSampleFilter("LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
            self.tracker.setLinkEventFilter("LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
            self.tracker.setLinkSampleFilter("LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")
            self.tracker.sendCommand("button_function 5 'accept_target_fixation'")
        return
Beispiel #9
0
	def stop(self):
		"""Stops recording data from the eye tracker. 
				
		Called automatically at the end of each trial unless ``P.manual_eyelink_recording`` is
		True, in which case it must be called manually in order to stop recording at any point. 
		To resume recording after this method is called, use the :meth:`start` method.

		"""
		endRealTimeMode()
		pumpDelay(100)
		self.stopRecording()
		self.__recording = False
		self.sendMessage("TRIAL OK")
		flushGetkeyQueue()
Beispiel #10
0
    def initialize_tracker(self):
        if not self.edf_open:
            raise RuntimeError(
                'EDF file must be open before tracker can be initialized.')

        pl.flushGetkeyQueue()
        self.set_offline_mode()

        self.send_command("screen_pixel_coords = 0 0 %d %d" % self.resolution)
        self.send_message("DISPLAY_COORDS 0 0 %d %d" % self.resolution)

        self.tracker.setFileEventFilter(
            "LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
        self.tracker.setFileSampleFilter("LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
        self.tracker.setLinkEventFilter(
            "LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
        self.tracker.setLinkSampleFilter("LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")
Beispiel #11
0
	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 libeyelink(edfname):
    global realconnect
    global tracker
    global edfname
    # Make filename
    fname = os.path.splitext(edfname)[0]  # strip away extension if present
    assert re.match(r'\w+$', fname), 'Name must only include A-Z, 0-9, or _'
    assert len(fname) <= 8, 'Name must be <= 8 characters.'

    edfname = fname + '.edf'

    # Initialize connection with eyetracker
    try:
        tracker = pylink.EyeLink()
        realconnect = True
    except RuntimeError:
        tracker = pylink.EyeLink(None)
        realconnect = False

    # Open EDF
    pylink.getEYELINK().openDataFile(edfname)
    pylink.flushGetkeyQueue()
    pylink.getEYELINK().setOfflineMode()

    # Set content of edf file
    pylink.getEYELINK().sendCommand(
        'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT')
    
    pylink.getEYELINK().sendCommand(
        'link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON')

    pylink.getEYELINK().sendCommand(
        'link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET')

    pylink.getEYELINK().sendCommand(
        'file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET,INPUT')

    # Set display coords for dataviewer
    pylink.getEYELINK().sendMessage("screen_pixel_coords =  0 0 %d %d" %(w - 1, h - 1))
    pylink.getEYELINK().sendMessage("DISPLAY_COORDS  0 0 %d %d" %(w - 1, h - 1))
Beispiel #13
0
    def __init__(self, window, edfname):
        # Pull out monitor info
        self.sres = window.size
        self.win = window

        # Make filename
        self.edfname = edfname + '.edf'

        # Initialize connection with eye-tracker
        try:
            self.tracker = pylink.EyeLink()
            self.realconnect = True
        except:
            self.tracker = pylink.EyeLink(None)
            self.realconnect = False

        # Make pylink accessible
        self.pylink = pylink

        # Open EDF
        self.tracker.openDataFile(self.edfname)
        pylink.flushGetkeyQueue()
        self.tracker.setOfflineMode()

        # Set content of edf file
        eftxt = 'LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT'
        self.tracker.sendCommand('file_event_filter = ' + eftxt)

        lftxt = 'LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON'
        self.tracker.sendCommand('link_event_filter = ' + lftxt)

        lstxt = 'LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET'
        self.tracker.sendCommand('link_sample_data = ' + lstxt)

        fstxt = 'LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET,INPUT'
        self.tracker.sendCommand('file_sample_data = ' + fstxt)

        # Set display coords for dataviewer
        disptxt = 'DISPLAY_COORDS 0 0 {} {}'.format(*self.sres)
        self.tracker.sendMessage(disptxt)
Beispiel #14
0
    def __init__(self, window, edfname):
        # Pull out monitor info
        self.sres = window.size
        self.win = window
        
        # Make filename
        self.edfname = edfname + '.edf'
        
        # Initialize connection with eye-tracker
        try:
            self.tracker = pylink.EyeLink()
            self.realconnect = True
        except:
            self.tracker = pylink.EyeLink(None)
            self.realconnect = False
            
        # Make pylink accessible
        self.pylink = pylink
        
        # Open EDF
        self.tracker.openDataFile(self.edfname)		
        pylink.flushGetkeyQueue() 
        self.tracker.setOfflineMode()

        #Gets the display surface and send msg;
        surf = pygame.display.get_surface()
        getEYELINK().sendCommand("screen_pixel_coords =  0 0 %d %d" %(surf.get_rect().w, surf.get_rect().h))
        getEYELINK().sendMessage("DISPLAY_COORDS  0 0 %d %d" %(surf.get_rect().w, surf.get_rect().h))
        
        tracker_software_ver = 0
        eyelink_ver = getEYELINK().getTrackerVersion()
        if eyelink_ver == 3:
            tvstr = getEYELINK().getTrackerVersion()
            vindex = tvstr.find("EYELINK CL")
	        tracker_software_ver = int(float(tvstr[(vindex + len("EYELINK CL")):].strip()))
	    if eyelink_ver>=2:
	        getEYELINK().sendCommand("select_parser_configuration 0")
	    if eyelink_ver == 2: #turn off scenelink camera stuff
		    getEYELINK().sendCommand("scene_camera_gazemap = NO")
Beispiel #15
0
    def initialize_tracker(self):
        """Sends commands setting up basic settings that are unlikely to be changed.

        EDF file must be open before this function is called. Must be called before
        starting to record.
        """
        if not self.edf_open:
            raise RuntimeError(
                'EDF file must be open before tracker can be initialized.')

        pl.flushGetkeyQueue()
        self.set_offline_mode()

        self.send_command("screen_pixel_coords = 0 0 %d %d" % self.resolution)
        self.send_message("DISPLAY_COORDS 0 0 %d %d" % self.resolution)

        self.tracker.setFileEventFilter(
            "LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
        self.tracker.setFileSampleFilter("LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
        self.tracker.setLinkEventFilter(
            "LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
        self.tracker.setLinkSampleFilter("LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")
Beispiel #16
0
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
Beispiel #17
0
    def __init__(self,
                 win,
                 clock,
                 sj="TEST",
                 autoCalibration=True,
                 saccadeSensitivity=HIGH,
                 calibrationType='HV9',
                 calibrationTargetColor=WHITE,
                 calibrationBgColor=BLACK,
                 CalibrationSounds=False):
        '''
        win: psychopy visual window used for the experiment
 
        clock: psychopy time clock recording time for whole experiment
 
        sj: Subject identifier string (affects EDF filename)
 
        autoCalibration:
         True: enable auto-pacing during calibration
 
        saccadeSensitivity:
         HIGH: Pursuit and neurological work
         LOW:  Cognitive research
 
        calibrationType:
         H3: Horizontal 3-point
         HV3: 3-point calibration, poor linearization
         HV5: 5-point calibration, poor at corners
         HV9: 9-point calibration, best overall
 
        calibrationTargetColor and calibrationBgColor:
         RGB tuple, i.e., (255,0,0) for Red
         One of: BLACK, WHITE, GRAY
 
        calibrationSounds:
         True: enable feedback sounds when calibrating 
 
        '''
        self.edfFileName = str(sj) + ".EDF"
        print(self.edfFileName)
        inf = info.RunTimeInfo("J",
                               "1",
                               win,
                               refreshTest=None,
                               userProcsDetailed=False)
        self.screenSize = inf['windowSize_pix']
        self.units = inf['windowUnits']
        self.monitorName = inf['windowMonitor.name']
        monitor = monitors.Monitor(self.monitorName)

        print("Connecting to eyetracker.")
        self.tracker = pylink.EyeLink()
        self.timeCorrection = clock.getTime() - self.tracker.trackerTime()
        print("Loading custom graphics")
        genv = EyeLinkCoreGraphicsPsychopy(self.tracker, win, self.screenSize)
        self.tracker.openDataFile(self.edfFileName)
        pylink.flushGetkeyQueue()
        self.tracker.setOfflineMode()
        self.tracker.sendCommand("screen_pixel_coords =  0 0 %d %d" %
                                 (tuple(self.screenSize)))
        self.tracker.setCalibrationType(calibrationType)
        self.tracker.sendMessage("DISPLAY_COORDS  0 0 %d %d" %
                                 (tuple(self.screenSize)))

        eyelink_ver = self.tracker.getTrackerVersion()
        if eyelink_ver == 3:
            tvstr = self.tracker.getTrackerVersionString()
            vindex = tvstr.find("EYELINK CL")
            tracker_software_ver = int(
                float(tvstr[(vindex + len("EYELINK CL")):].strip()))
        else:
            tracker_software_ver = 0
        if eyelink_ver >= 2:
            self.tracker.sendCommand("select_parser_configuration %d" %
                                     saccadeSensitivity)
        else:
            if saccadeSensitivity == HIGH:
                svt, sat = 22, 5000
            else:
                svt, sat = 30, 9500
            self.tracker.sendCommand("saccade_velocity_threshold = %d" % svt)
            self.tracker.sendCommand("saccade_acceleration_threshold = %d" %
                                     sat)

        if eyelink_ver == 2:  #turn off scenelink camera stuff
            self.tracker.sendCommand("scene_camera_gazemap = NO")

        # set EDF file contents
        self.tracker.sendCommand(
            "file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON"
        )
        if tracker_software_ver >= 4:
            self.tracker.sendCommand(
                "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET"
            )
        else:
            self.tracker.sendCommand(
                "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
        # set link data (used for gaze cursor)
        self.tracker.sendCommand(
            "link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
        if tracker_software_ver >= 4:
            self.tracker.sendCommand(
                "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET"
            )
        else:
            self.tracker.sendCommand(
                "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")

        #Set the calibration settings:
        pylink.setCalibrationColors(calibrationTargetColor, calibrationBgColor)
        if CalibrationSounds:
            pylink.setCalibrationSounds("", "", "")
            pylink.setDriftCorrectSounds("", "off", "off")
        else:
            pylink.setCalibrationSounds("off", "off", "off")
            pylink.setDriftCorrectSounds("off", "off", "off")

        if autoCalibration:
            self.tracker.enableAutoCalibration
        else:
            self.tracker.disableAutoCalibration
        win.flip()
        print("Opening graphics")
        pylink.openGraphicsEx(genv)
        print("Begining tracker setup")
        self.tracker.doTrackerSetup()
        win.flip()
 def clearAllEventBuffers(self):
     pylink.flushGetkeyQueue()
     self.tracker.resetData()
     self._iohub_server.eventBuffer.clear()
     for d in self._iohub_server.devices:
         d.clearEvents()
    def __init__(self, win, clock, sj = "TEST", saccadeSensitivity = HIGH, calibrationType = 'HV9',calibrationTargetColor = WHITE,calibrationBgColor = BLACK, CalibrationSounds = False,screen=(1024,768)):
        '''win: psychopy visual window used for the experiment
          clock: psychopy time clock recording time for whole experiment
          sj: Subject identifier string (affects EDF filename)
          saccadeSensitivity:
            HIGH: Pursuit and neurological work
            LOW:  Cognitive research
          calibrationType:
            H3: Horizontal 3-point
            HV3: 3-point calibration, poor linearization
            HV5: 5-point calibration, poor at corners
            HV9: 9-point calibration, best overall
        calibrationTargetColor and calibrationBgColor:
            RGB tuple, i.e., (255,0,0) for Red
            One of: BLACK, WHITE, GRAY
        calibrationSounds:
            True: enable feedback sounds when calibrating'''
        self.edfFileName = str(sj)+".EDF"   # Subject name only can put 8 characters
        print("Connecting to eyetracker.")
        self.tracker = pylink.EyeLink()
        self.timeCorrection = clock.getTime() - self.tracker.trackerTime()
        print("Loading custom graphics")
        #Initializes Experiment Graphics
        genv = EyeLinkCoreGraphicsPsychopy(self.tracker, win, screen)
        pylink.openGraphicsEx(genv)
        # opendatafile
        self.tracker.openDataFile(self.edfFileName)
        
        #EyeLink Tracker Configuration
        pylink.flushGetkeyQueue();# Initializes the key queue used by getkey(). It may be called at any time to get rid any of old keys from the queue.
        self.tracker.setOfflineMode();#Places EyeLink tracker in off-line (idle) mode. Wait till the tracker has finished the mode transition
        self.tracker.sendCommand("screen_pixel_coords =  0 0 %d %d"%( tuple(screen) ))
        self.tracker.setCalibrationType(calibrationType)
        self.tracker.sendCommand("driftcorrect_cr_disable=OFF") #CF - OFF: turns on drift CORRECT; AUTO: Turns on drift CHECK; ON: Turns off both
        #self.tracker.sendCommand("generate_default_targets = NO") 
        #self.tracker.sendCommand("calibration_targets = 512,384 512,417 512,351 402,384 622,384 402,417 622,417 402,351 622,351")
        #self.tracker.sendCommand("validation_targets = 512,384 512,417 512,351 402,384 622,384 402,417 622,417 402,351 622,351")

        self.tracker.sendMessage("DISPLAY_COORDS  0 0 %d %d"%( tuple(screen) ))
        eyelink_ver = self.tracker.getTrackerVersion()
        if eyelink_ver == 3:
            tvstr = self.tracker.getTrackerVersionString()
            vindex = tvstr.find("EYELINK CL")
            tracker_software_ver = int(float(tvstr[(vindex + len("EYELINK CL")):].strip()))
        else: tracker_software_ver = 0
        if eyelink_ver>=2:
            self.tracker.sendCommand("select_parser_configuration %d" %saccadeSensitivity)
        else:
            if saccadeSensitivity == HIGH:svt, sat = 22, 5000  
            else: svt, sat = 30, 9500
            self.tracker.sendCommand("saccade_velocity_threshold = %d" %svt)   
            self.tracker.sendCommand("saccade_acceleration_threshold = %d" %sat)
        if eyelink_ver == 2: #turn off scenelink camera stuff
            self.tracker.sendCommand("scene_camera_gazemap = NO")
 
        # set EDF file contents
        self.tracker.setFileEventFilter("LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
        if tracker_software_ver>=4:self.tracker.setFileSampleFilter("LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET")
        else:self.tracker.setFileSampleFilter("LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
        
        # set link data (used for gaze cursor)
        self.tracker.setLinkEventFilter("LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
        if tracker_software_ver>=4:self.tracker.setLinkSampleFilter("LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET")
        else:self.tracker.setLinkSampleFilter("LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")
        
        #self.tracker.setAcceptTargetFixationButton(1) # This programs a specific button for use in drift correction.
        
          #Set the calibration settings:
        #pylink.setCalibrationColors(WHITE, BLACK) # Sets the calibration target and background color(foreground_color, background_color)
        if CalibrationSounds:
            pylink.setCalibrationSounds("", "", "")
            pylink.setDriftCorrectSounds("", "off", "off")
        else:
            pylink.setCalibrationSounds("off", "off", "off")
            pylink.setDriftCorrectSounds("off", "off", "off")
            
        print("Beginning tracker setup")
        self.tracker.doTrackerSetup()
def main(debug_mode):
    MyMonitor = utils.Monitor("labo-Tom-PC",1280,1024, distance = 72, width_cm = 36.6)
    print "Degrees per pixel: ", MyMonitor.degreesperpixel
    if debug_mode:
        dummy_mode = True
        full_screen = False
    else:
        dummy_mode= False
        full_screen = True

    ## there are 1600 trials
    START = 0 ## from what line of the table we should start
    NB_TRIALS = 800
    BREAK_INTERVAL = 200 #200 ## display the take-a-break screen every XX trials
    FRAME_RATE = 100.0 ## not used for now
    calib_type = "HV13" ## try HV13 for 13 dots
    file_asking = raw_input("Start with: [N]ew file, [O]pen a file, [T]est file: \n")

    ## Ask questions on conditions, check if the file already exist:
    if file_asking=="N":
        if debug_mode:
            NB_TRIALS = int(raw_input("(debug mode) How many trials? "))
            START = int(raw_input("From which trial would you like to start?"))
        info, table, path_to_table_file, path_to_eye_tracker_file = utils.initializeFromConditions(NB_TRIALS)
    elif file_asking == "O":
        import Tkinter, tkFileDialog
        root = Tkinter.Tk()
        root.withdraw()
        file_path = tkFileDialog.askopenfilename(title = "Open a Table file:")
        root.destroy()
        info, table, path_to_table_file, path_to_eye_tracker_file = utils.openTable(file_path)
        START = int(raw_input("From which trial would you like to continue?"))
    else:
        info, table, path_to_table_file, path_to_eye_tracker_file = utils.openTable("")

    print info

    if not dummy_mode:
        MyEyelink = pylink.EyeLink()
        MyMonitor.setFPSControl(0)
    else:
        ## this is my dummy, it works better than the official one
        MyEyelink = dummy.DummyEyeLink()
        MyMonitor.setFPSControl(FRAME_RATE) ## force 100 Hz during office-test ## switch to zero when running the experiment

    ## Initializes the graphics
    display.init()
    mouse.set_visible(False)

    ## do a new display surface
    if full_screen:
        display.set_mode((MyMonitor.w, MyMonitor.h), FULLSCREEN |DOUBLEBUF | HWSURFACE,32)
    else:
        display.set_mode((MyMonitor.w, MyMonitor.h), NOFRAME |DOUBLEBUF,32)

    surf = display.get_surface()
    MyEnv = utils.Environment(surf, MyMonitor,
        MyEyelink, table, info, calib_type = calib_type, units = 'deg')

    event = utils.runCalibration(MyEnv)

    ## Gets the new display surface and sends a mesage to EDF file;
    edfFileName = path_to_eye_tracker_file
    ## opens the EDF file.
    MyEyelink.openDataFile(edfFileName)
    pylink.flushGetkeyQueue();
    MyEyelink.setOfflineMode();
    utils.configEDFfile(MyEyelink)


    MyEyelink.sendMessage("Info Experiment: %s"%(str(info)))
    MyEyelink.sendCommand("screen_pixel_coords =  0 0 %d %d" %(surf.get_rect().w, surf.get_rect().h))
    MyEyelink.sendMessage("DISPLAY_COORDS  0 0 %d %d" %(surf.get_rect().w, surf.get_rect().h))

    error = 0
    stop_time = time.time()
    print time.strftime("Experiment started at %H:%M:%S", time.localtime(stop_time))
    try:
        if(MyEyelink.isConnected() and not MyEyelink.breakPressed()):
            print "Let's run the trials"
            error, saveFrames = run_trials.run_trials(MyEnv, START, BREAK_INTERVAL)
    except Exception, e:
        print "Caught:", e
Beispiel #21
0
w = window.winfo_screenwidth()
h = window.winfo_screenheight()
if not myDlg.OK:
    core.quit()

result['name'] = ok_data[0]
result['sex'] = ok_data[1]
result['age'] = ok_data[2]

# eyelinktracker = EyeLink(trackeraddress=None)
eyelinktracker = EyeLink()
# 眼动仪
pylink.openGraphics((w, h), 32)
edfFileName = "%s.EDF" % result['name']
getEYELINK().openDataFile(edfFileName)
pylink.flushGetkeyQueue()
getEYELINK().setOfflineMode()
getEYELINK().sendCommand("screen_pixel_coords =  0 0 %d %d" % (w - 1, h - 1))
getEYELINK().sendMessage("DISPLAY_COORDS  0 0 %d %d" % (w - 1, h - 1))
if getEYELINK().getTrackerVersion() == 2:
    getEYELINK().sendCommand("select_parser_configuration 0")
else:
    getEYELINK().sendCommand("saccade_velocity_threshold = 35")
    getEYELINK().sendCommand("saccade_acceleration_threshold = 9500")
getEYELINK().setFileEventFilter(
    "LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
getEYELINK().setFileSampleFilter("LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
getEYELINK().setLinkEventFilter("LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
getEYELINK().setLinkSampleFilter("LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")
getEYELINK().sendCommand("pupil_size_diameter = YES")
pylink.setCalibrationColors(
Beispiel #22
0
    def __init__(self, win, clock, sj = "TEST", autoCalibration=True, 
                 saccadeSensitivity = HIGH, calibrationType = 'HV9',
                 calibrationTargetColor = WHITE,
                 calibrationBgColor = BLACK, CalibrationSounds = False
                 ):
        '''
        win: psychopy visual window used for the experiment
 
        clock: psychopy time clock recording time for whole experiment
 
        sj: Subject identifier string (affects EDF filename)
 
        autoCalibration:
         True: enable auto-pacing during calibration
 
        saccadeSensitivity:
         HIGH: Pursuit and neurological work
         LOW:  Cognitive research
 
        calibrationType:
         H3: Horizontal 3-point
         HV3: 3-point calibration, poor linearization
         HV5: 5-point calibration, poor at corners
         HV9: 9-point calibration, best overall
 
        calibrationTargetColor and calibrationBgColor:
         RGB tuple, i.e., (255,0,0) for Red
         One of: BLACK, WHITE, GRAY
 
        calibrationSounds:
         True: enable feedback sounds when calibrating 
 
        '''
        self.edfFileName = str(sj)+".EDF"
        print(self.edfFileName)
        inf = info.RunTimeInfo("J","1",win, refreshTest=None, 
                             userProcsDetailed=False)
        self.screenSize = inf['windowSize_pix']
        self.units = inf['windowUnits']
        self.monitorName = inf['windowMonitor.name']
        monitor = monitors.Monitor(self.monitorName)
 
        print("Connecting to eyetracker.")
        self.tracker = pylink.EyeLink()
        self.timeCorrection = clock.getTime() - self.tracker.trackerTime()
        print("Loading custom graphics")
        genv = EyeLinkCoreGraphicsPsychopy(self.tracker, win, self.screenSize)
        self.tracker.openDataFile(self.edfFileName)
        pylink.flushGetkeyQueue();
        self.tracker.setOfflineMode();
        self.tracker.sendCommand("screen_pixel_coords =  0 0 %d %d"
                                    %( tuple(self.screenSize) ))
        self.tracker.setCalibrationType(calibrationType)
        self.tracker.sendMessage("DISPLAY_COORDS  0 0 %d %d"
                                    %( tuple(self.screenSize) ))
 
        eyelink_ver = self.tracker.getTrackerVersion()
        if eyelink_ver == 3:
            tvstr = self.tracker.getTrackerVersionString()
            vindex = tvstr.find("EYELINK CL")
            tracker_software_ver = int(float(tvstr[(vindex + len("EYELINK CL")):].strip()))
        else: tracker_software_ver = 0
        if eyelink_ver>=2:
            self.tracker.sendCommand("select_parser_configuration %d" %saccadeSensitivity)
        else:
            if saccadeSensitivity == HIGH:
                svt, sat = 22, 5000
            else: svt, sat = 30, 9500
            self.tracker.sendCommand("saccade_velocity_threshold = %d" %svt)
            self.tracker.sendCommand("saccade_acceleration_threshold = %d" %sat)
 
        if eyelink_ver == 2: #turn off scenelink camera stuff
            self.tracker.sendCommand("scene_camera_gazemap = NO")
 
        # set EDF file contents
        self.tracker.sendCommand("file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
        if tracker_software_ver>=4:
            self.tracker.sendCommand("file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET")
        else:
            self.tracker.sendCommand("file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
        # set link data (used for gaze cursor)
        self.tracker.sendCommand("link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
        if tracker_software_ver>=4:
            self.tracker.sendCommand("link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET")
        else:
            self.tracker.sendCommand("link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")
 
        #Set the calibration settings:
        pylink.setCalibrationColors( calibrationTargetColor, calibrationBgColor)
        if CalibrationSounds:
            pylink.setCalibrationSounds("", "", "")
            pylink.setDriftCorrectSounds("", "off", "off")
        else:
            pylink.setCalibrationSounds("off", "off", "off")
            pylink.setDriftCorrectSounds("off", "off", "off")
 
        if autoCalibration:
            self.tracker.enableAutoCalibration
        else: self.tracker.disableAutoCalibration
        win.flip()
        print("Opening graphics")
        pylink.openGraphicsEx(genv)
        print("Begining tracker setup")
        self.tracker.doTrackerSetup()
        win.flip()
Beispiel #23
0
    def __init__(self,
                 display,
                 resolution=settings.DISPSIZE,
                 data_file=settings.LOGFILENAME + ".edf",
                 fg_color=settings.FGC,
                 bg_color=settings.BGC,
                 eventdetection=settings.EVENTDETECTION,
                 saccade_velocity_threshold=35,
                 saccade_acceleration_threshold=9500,
                 blink_threshold=settings.BLINKTHRESH,
                 force_drift_correct=True,
                 pupil_size_mode=settings.EYELINKPUPILSIZEMODE,
                 **args):
        """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker"""

        # try to import copy docstring (but ignore it if it fails, as we do
        # not need it for actual functioning of the code)
        try:
            copy_docstr(BaseEyeTracker, libeyelink)
        except:
            # we're not even going to show a warning, since the copied
            # docstring is useful for code editors; these load the docs
            # in a non-verbose manner, so warning messages would be lost
            pass

        global _eyelink

        # Make sure that we have a valid data file. The local_data_file may
        # contain a folder. The eyelink_data_file is only a basename, i.e.
        # without folder. The eyelink_data_file must be at most eight characters
        # and end with a `.edf` extension.

        self.local_data_file = data_file
        self.eyelink_data_file = os.path.basename(data_file)
        stem, ext = os.path.splitext(self.eyelink_data_file)
        if len(stem) > 8 or ext.lower() != '.edf':
            raise Exception(
                "The EyeLink cannot handle filenames longer than eight "
                "characters (excluding '.edf' extension).")

        # properties
        self.display = display
        self.fontsize = 18
        self.scr = Screen(disptype=settings.DISPTYPE, mousevisible=False)
        self.kb = Keyboard(keylist=["escape", "q"], timeout=1)
        self.resolution = resolution
        self.recording = False
        self.saccade_velocity_treshold = saccade_velocity_threshold
        self.saccade_acceleration_treshold = saccade_acceleration_threshold
        self.blink_threshold = blink_threshold
        self.eye_used = None
        self.left_eye = 0
        self.right_eye = 1
        self.binocular = 2
        self.pupil_size_mode = pupil_size_mode
        self.prevsample = (-1, -1)
        self.prevps = -1

        # event detection properties
        # degrees; maximal distance from fixation start (if gaze wanders beyond
        # this, fixation has stopped)
        self.fixtresh = 1.5
        # milliseconds; amount of time gaze has to linger within self.fixtresh
        # to be marked as a fixation
        self.fixtimetresh = 100
        # degrees per second; saccade velocity threshold
        self.spdtresh = self.saccade_velocity_treshold
        # degrees per second**2; saccade acceleration threshold
        self.accthresh = self.saccade_acceleration_treshold
        self.set_detection_type(eventdetection)
        # weighted distance, used for determining whether a movement is due to
        # measurement error (1 is ok, higher is more conservative and will
        # result in only larger saccades to be detected)
        self.weightdist = 10
        # distance between participant and screen in cm
        self.screendist = settings.SCREENDIST
        # distance between participant and screen in cm
        self.screensize = settings.SCREENSIZE
        self.pixpercm = (self.resolution[0]/float(self.screensize[0]) + \
         self.resolution[1]/float(self.screensize[1])) / 2.0
        # only initialize eyelink once
        if _eyelink == None:
            try:
                _eyelink = pylink.EyeLink()
            except:
                raise Exception(
                    "Error in libeyelink.libeyelink.__init__(): Failed to "
                    "connect to the tracker!")
        # determine software version of tracker
        self.tracker_software_ver = 0
        self.eyelink_ver = pylink.getEYELINK().getTrackerVersion()
        if self.eyelink_ver == 3:
            tvstr = pylink.getEYELINK().getTrackerVersionString()
            vindex = tvstr.find("EYELINK CL")
            self.tracker_software_ver = int(float(tvstr[(vindex + \
             len("EYELINK CL")):].strip()))
        if self.eyelink_ver == 1:
            self.eyelink_model = 'EyeLink I'
        elif self.eyelink_ver == 2:
            self.eyelink_model = 'EyeLink II'
        elif self.eyelink_ver == 3:
            self.eyelink_model = 'EyeLink 1000'
        else:
            self.eyelink_model = 'EyeLink (model unknown)'
        # Open graphics
        self.eyelink_graphics = EyelinkGraphics(self, _eyelink)
        pylink.openGraphicsEx(self.eyelink_graphics)
        # Optionally force drift correction. For some reason this must be done
        # as (one of) the first things, otherwise a segmentation fault occurs.
        if force_drift_correct:
            try:
                self.send_command('driftcorrect_cr_disable = OFF')
            except:
                print('Failed to force drift correction (EyeLink 1000 only)')
        # Set pupil-size mode
        if self.pupil_size_mode == 'area':
            pylink.getEYELINK().setPupilSizeDiameter(False)
        elif self.pupil_size_mode == 'diameter':
            pylink.getEYELINK().setPupilSizeDiameter(True)
        else:
            raise Exception(
             "pupil_size_mode should be 'area' or 'diameter', not %s" \
             % self.pupil_size_mode)
        pylink.getEYELINK().openDataFile(self.eyelink_data_file)
        pylink.flushGetkeyQueue()
        pylink.getEYELINK().setOfflineMode()
        # notify eyelink of display resolution
        self.send_command("screen_pixel_coords = 0 0 %d %d" % \
         (self.resolution[0], self.resolution[1]))
        # get some configuration stuff
        if self.eyelink_ver >= 2:
            self.send_command("select_parser_configuration 0")
            if self.eyelink_ver == 2:  # turn off scenelink camera stuff
                self.send_command("scene_camera_gazemap = NO")
        # set EDF file contents (this specifies which data is written to the EDF
        # file)
        self.send_command(
            "file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON"
        )
        if self.tracker_software_ver >= 4:
            self.send_command(
                "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET"
            )
        else:
            self.send_command(
                "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
        # set link data (this specifies which data is sent through the link and
        # thus can be used in gaze contingent displays)
        self.send_command(
            "link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
        if self.tracker_software_ver >= 4:
            self.send_command(
                "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET"
            )
        else:
            self.send_command(
                "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")
        # not quite sure what this means (according to Sebastiaan Mathot, it
        # might be the button that is used to end drift correction?)
        self.send_command("button_function 5 'accept_target_fixation'")

        if not self.connected():
            raise Exception(
                "Error in libeyelink.libeyelink.__init__(): Failed to connect "
                "to the eyetracker!")
Beispiel #24
0
    def __init__(self,
                 resolution,
                 data_file="default.edf",
                 fg_color=(255, 255, 255),
                 bg_color=(0, 0, 0),
                 saccade_velocity_threshold=35,
                 saccade_acceleration_threshold=9500):
        """
		Initializes the connection to the Eyelink
	
		Parameters:
		_resolution: (width, height) tuple
		_data_file: the name of the EDF file
	
		Returns:
		True on connection success and False on connection failure       
		"""

        global _eyelink

        self.data_file = data_file
        self.resolution = resolution
        self.recording = False

        self.saccade_velocity_treshold = saccade_velocity_threshold
        self.saccade_acceleration_treshold = saccade_acceleration_threshold
        self.eye_used = None
        self.left_eye = 0
        self.right_eye = 1
        self.binocular = 2

        # Only initialize the eyelink once
        if _eyelink == None:
            try:
                _eyelink = pylink.EyeLink()
            except Exception as e:
                raise exceptions.runtime_error(
                    "Failed to connect to the tracker: %s" % e)

            graphics_env = eyelink_graphics(_eyelink)
            pylink.openGraphicsEx(graphics_env)

        pylink.getEYELINK().openDataFile(self.data_file)
        pylink.flushGetkeyQueue()
        pylink.getEYELINK().setOfflineMode()

        # Notify the eyelink of the display resolution
        self.send_command("screen_pixel_coords =  0 0 %d %d" %
                          (self.resolution[0], self.resolution[1]))

        # Determine the software version of the tracker
        self.tracker_software_ver = 0
        self.eyelink_ver = pylink.getEYELINK().getTrackerVersion()
        if self.eyelink_ver == 3:
            tvstr = pylink.getEYELINK().getTrackerVersionString()
            vindex = tvstr.find("EYELINK CL")
            self.tracker_software_ver = int(
                float(tvstr[(vindex + len("EYELINK CL")):].strip()))

        # Set some configuration stuff (not sure what the parser and gazemap mean)
        if self.eyelink_ver >= 2:
            self.send_command("select_parser_configuration 0")
            if self.eyelink_ver == 2:  #turn off scenelink camera stuff
                self.send_command("scene_camera_gazemap = NO")
        else:
            self.send_command("saccade_velocity_threshold = %d" %
                              self.saccade_velocity_threshold)
            self.send_command("saccade_acceleration_threshold = %s" %
                              self.saccade_acceleration_threshold)

        # Set EDF file contents. This specifies which data is written to the EDF file.
        self.send_command(
            "file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON"
        )
        if self.tracker_software_ver >= 4:
            self.send_command(
                "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET"
            )
        else:
            self.send_command(
                "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")

        # Set link data. This specifies which data is sent through the link and thus can
        # be used in gaze contingent displays
        self.send_command(
            "link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
        if self.tracker_software_ver >= 4:
            self.send_command(
                "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET"
            )
        else:
            self.send_command(
                "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")

        # Not sure what this means. Maybe the button that is used to end drift correction?
        self.send_command("button_function 5 'accept_target_fixation'")

        if not self.connected():
            raise exceptions.runtime_error(
                "Failed to connect to the eyetracker")
Beispiel #25
0
    def Start_exp(self):
        # ---------------------------------------------------
        # point de départ de l'expérience
        # ---------------------------------------------------
        pylink.openGraphics((self.screen_width_px, self.screen_height_px),
                            32)  # Initialise les graphiques
        self.eyelink.openDataFile(self.edfFileName)  # Ouvre le fichier EDF.

        # réinitialise les touches et réglez le mode de suivi en mode hors connexion.
        pylink.flushGetkeyQueue()
        self.eyelink.setOfflineMode()

        # Définit le système de coordonnées d'affichage et envoie un message à cet effet au fichier EDF;
        self.eyelink.sendCommand(
            "screen_pixel_coords =  0 0 %d %d" %
            (self.screen_width_px - 1, self.screen_height_px - 1))
        self.eyelink.sendMessage(
            "DISPLAY_COORDS  0 0 %d %d" %
            (self.screen_width_px - 1, self.screen_height_px - 1))

        # ---------------------------------------------------
        # NETOYER ??? version = 3
        # ---------------------------------------------------
        tracker_software_ver = 0
        eyelink_ver = self.eyelink.getTrackerVersion()

        if eyelink_ver == 3:
            tvstr = self.eyelink.getTrackerVersionString()
            vindex = tvstr.find("EYELINK CL")
            tracker_software_ver = int(
                float(tvstr[(vindex + len("EYELINK CL")):].strip()))

        if eyelink_ver >= 2:
            self.eyelink.sendCommand("select_parser_configuration 0")
            if eyelink_ver == 2:  # Éteignez les caméras scenelink
                self.eyelink.sendCommand("scene_camera_gazemap = NO")
        else:
            self.eyelink.sendCommand("saccade_velocity_threshold = 35")
            self.eyelink.sendCommand("saccade_acceleration_threshold = 9500")

        # Définir le contenu du fichier EDF
        self.eyelink.sendCommand(
            "file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT"
        )
        if tracker_software_ver >= 4:
            self.eyelink.sendCommand(
                "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET,INPUT"
            )
        else:
            self.eyelink.sendCommand(
                "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,INPUT"
            )

        # Définir les données du lien (utilisé pour le curseur du regard)
        self.eyelink.sendCommand(
            "link_event_filter = LEFT,RIGHT,FIXATION,FIXUPDATE,SACCADE,BLINK,BUTTON,INPUT"
        )
        if tracker_software_ver >= 4:
            self.eyelink.sendCommand(
                "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET,INPUT"
            )
        else:
            self.eyelink.sendCommand(
                "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,INPUT"
            )

        #############################
        # Calibration
        #############################
        pylink.setCalibrationColors(
            (255, 255, 255), (128, 128, 128)
        )  # Définit couleur de la cible d'étalonnage (blanc) et de l'arrière-plan (gris)
        pylink.setTargetSize(self.screen_width_px // 70,
                             self.screen_width_px //
                             300)  # Définit taille de la cible d'étalonnage
        pylink.setCalibrationSounds("", "", "")
        pylink.setDriftCorrectSounds("", "off", "off")
Beispiel #26
0
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 doSim(self, trial, road, duration, tau, doEyetrack):

        # Measure sample rate in order to calculate delay buffer
        sample_rate = self.screen.measure_refresh_rate(2.0)
        print "Sample rate: " + str(sample_rate)
        #sample_rate = 60

        self.doEyetrack = doEyetrack

        self.pos_ring = RingBuffer(self.center,
                                   int(math.floor(tau * sample_rate)) + 1)
        print("Ring Buffer:: size: " + str(self.pos_ring.size))

        if doEyetrack:
            import pylink
            from EyeLinkCoreGraphicsVE import EyeLinkCoreGraphicsVE

            self.tracker = pylink.EyeLink()
            if self.tracker == None:
                print "Error: Eyelink is not connected"
                sys.exit()

            genv = EyeLinkCoreGraphicsVE(self.screen, self.tracker)
            pylink.openGraphicsEx(genv)

            #Opens the EDF file.
            edfFileName = "TRIAL" + str(trial) + ".EDF"
            self.tracker.openDataFile(edfFileName)

            pylink.flushGetkeyQueue()

            self.tracker.sendCommand("screen_pixel_coords =	0 0 %d %d" %
                                     (VisionEgg.config.VISIONEGG_SCREEN_W,
                                      VisionEgg.config.VISIONEGG_SCREEN_H))

            tracker_software_ver = 0
            eyelink_ver = self.tracker.getTrackerVersion()
            if eyelink_ver == 3:
                tvstr = self.tracker.getTrackerVersionString()
                vindex = tvstr.find("EYELINK CL")
                tracker_software_ver = int(
                    float(tvstr[(vindex + len("EYELINK CL")):].strip()))

            if eyelink_ver >= 2:
                self.tracker.sendCommand("select_parser_configuration 0")
                if eyelink_ver == 2:  #turn off scenelink camera stuff
                    self.tracker.sendCommand("scene_camera_gazemap = NO")
            else:
                self.tracker.sendCommand("saccade_velocity_threshold = 35")
                self.tracker.sendCommand(
                    "saccade_acceleration_threshold = 9500")

            # set EDF file contents
            self.tracker.sendCommand(
                "file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON"
            )
            if tracker_software_ver >= 4:
                self.tracker.sendCommand(
                    "file_sample_data	= LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET"
                )
            else:
                self.tracker.sendCommand(
                    "file_sample_data	= LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")

            # set link data (used for gaze cursor)
            self.tracker.sendCommand(
                "link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
            if tracker_software_ver >= 4:
                self.tracker.sendCommand(
                    "link_sample_data	= LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET"
                )
            else:
                self.tracker.sendCommand(
                    "link_sample_data	= LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")

            if not self.doneSetup:
                self.tracker.doTrackerSetup()
                self.doneSetup = True
            else:
                while 1:
                    try:
                        error = self.tracker.doDriftCorrect(
                            self.screen.size[0] / 2, self.screen.size[1] / 2,
                            1, 1)
                        if error != 27:  # ?? from example
                            break
                        else:
                            self.tracker.doTrackerSetup()
                    except:
                        break

        self.screen.parameters.bgcolor = 106.0 / 255.0, 147.0 / 255.0, 0.0
        # Load road data from file and create an image
        roadArray = numpy.loadtxt('road' + str(road) + '.txt')

        # Convert to a Path
        roadPath = ImagePath.Path(
            map(lambda xy: (xy[0], xy[1]), roadArray.tolist()))

        # Use Path to create a plot of the road
        im = Image.new("RGB", (2000, 100), (50, 50, 50))
        draw = ImageDraw.Draw(im)

        # draw each side of the road separately
        draw.line(roadPath[:4000], fill=(200, 200, 200))
        draw.line(roadPath[4000:], fill=(200, 200, 200))

        del draw

        # Lay out a road texture in the x-z plane
        roadTexture = Texture(im)

        del im

        eye_height = 2.5

        vertices = [(-10, -eye_height, 0), (-10, -eye_height, -1000),
                    (10, -eye_height, 0), (10, -eye_height, -1000)]

        rect = TextureStimulus3D(texture=roadTexture,
                                 lowerleft=vertices[0],
                                 lowerright=vertices[1],
                                 upperleft=vertices[2],
                                 upperright=vertices[3])

        # We will use these later for our camera transforms
        self.camera_matrix = ModelView()
        self.frame_timer = FrameTimer()

        self.outf = open(
            'steersim-' + str(trial) + '-' + str(road) + '-out.txt', 'wb')

        # Vewport for the road
        viewport3D = Viewport(
            screen=self.screen,
            projection=SimplePerspectiveProjection(fov_x=75.2),
            camera_matrix=self.camera_matrix,
            stimuli=[rect])

        # Construct a sky
        sky_l = 0
        sky_r = self.screen.size[0]
        sky_t = self.screen.size[1]
        sky_b = self.screen.size[1] / 2

        sky_vertices = [(sky_l, sky_t, 0), (sky_r, sky_t, 0),
                        (sky_r, sky_b, 0), (sky_l, sky_b, 0)]

        sky = Rectangle3D(color=(144.0 / 255.0, 190.0 / 255.0, 1.0),
                          vertex1=sky_vertices[0],
                          vertex2=sky_vertices[1],
                          vertex3=sky_vertices[2],
                          vertex4=sky_vertices[3])

        wheelTexture = Texture('wheel.png')
        self.wheel = TextureStimulus(texture=wheelTexture,
                                     internal_format=gl.GL_RGBA,
                                     position=(self.center, -75),
                                     anchor='center')

        # display the sky in its own viewport
        viewport2D = Viewport(screen=self.screen)
        viewport2D.parameters.stimuli = [sky, self.wheel]

        self.init_state()

        askText = Text(text='Press a key to start',
                       anchor='center',
                       position=(self.center, self.screen.size[1] / 2))
        splash = Viewport(screen=self.screen)
        splash.parameters.stimuli = [askText]
        self.askForNext = Presentation(go_duration=(0.5, 'seconds'),
                                       viewports=[splash])
        self.askForNext.add_controller(
            None, None, FunctionController(during_go_func=self.wait_for_key))
        self.askForNext.parameters.enter_go_loop = True
        self.askForNext.run_forever()

        self.simPres = Presentation(go_duration=(duration, 'seconds'),
                                    viewports=[viewport3D, viewport2D],
                                    handle_event_callbacks=[
                                        (pygame.KEYDOWN, self.check_keypress)
                                    ])
        self.simPres.add_controller(
            None, None, FunctionController(during_go_func=self.update))

        if doEyetrack:
            startTime = pylink.currentTime()
            self.tracker.sendMessage("SYNCTIME %d" %
                                     (pylink.currentTime() - startTime))
            error = self.tracker.startRecording(1, 1, 1, 1)
            self.tracker.sendMessage("PRES %d START" % (trial))

        self.simPres.go()

        if doEyetrack:
            self.tracker.sendMessage("PRES %d END" % (trial))
            self.tracker.stopRecording()

            # File transfer and cleanup!
            self.tracker.setOfflineMode()
            pylink.msecDelay(500)
            #Close the file and transfer it to Display PC
            self.tracker.closeDataFile()
            self.tracker.receiveDataFile(edfFileName, edfFileName)

        self.outf.close()

        if self.quit:
            raise SystemExit
	def __init__(self, experiment, resolution, data_file=u'default.edf', fg_color=(255, 255, 255), bg_color=(0, 0, 0), saccade_velocity_threshold=35, saccade_acceleration_threshold=9500, force_drift_correct=False):
		"""<DOC>
		Constructor. Initializes the connection to the Eyelink.

		Arguments:
		experiment		--	The experiment object.
		resolution		--	A (width, height) tuple.

		Keyword arguments:

		data_file		--	The name of the EDF file. (default=u'default.edf')
		fg_color		--	The foreground color for the calibration screen. #
							(default=255,255,255)
		bg_color		--	The background color for the calibration screen. #
							(default=0,0,0)
		saccade_velocity_threshold		--	The velocity threshold used for #
											saccade detection. (default=35)
		saccade_acceleration_threshold	--	The acceleration threshold used #
											for saccade detection. #
											(default=9500)
		force_drift_correct				--	Indicates whether drift correction #
											should be enabled. This is useful #
											only for Eyelink 1000 models, for #
											which drift correction is disabled #
											by default. (default=False)							   

		Returns:
		True on connection success and False on connection failure.
		</DOC>"""

		global _eyelink

		stem, ext = os.path.splitext(data_file)
		if len(stem) > 8 or len(ext) > 4:
			raise exceptions.runtime_error( \
				u'The Eyelink cannot handle filenames longer than 8 characters (plus .EDF extension)')

		self.experiment = experiment
		self.data_file = data_file
		self.resolution = resolution
		self.recording = False
		self.cal_beep = True
		self.cal_target_size = 16		
		self.experiment.eyelink_esc_pressed = False
		self.saccade_velocity_treshold = saccade_velocity_threshold
		self.saccade_acceleration_treshold = saccade_acceleration_threshold
		self.eye_used = None
		self.left_eye = 0
		self.right_eye = 1
		self.binocular = 2
		
		# Only initialize the eyelink once
		if _eyelink == None:
			try:
				_eyelink = pylink.EyeLink()
			except Exception as e:
				raise exceptions.runtime_error( \
					u'Failed to connect to the tracker: %s' % e)					

			graphics_env = eyelink_graphics(self.experiment, _eyelink)
			pylink.openGraphicsEx(graphics_env)				
			
		# Optionally force drift correction. For some reason this must be done
		# as (one of) the first thingsm otherwise a segmentation fault occurs.
		if force_drift_correct:
			self.send_command('driftcorrect_cr_disable = OFF')	

		pylink.getEYELINK().openDataFile(self.data_file)
		pylink.flushGetkeyQueue()
		pylink.getEYELINK().setOfflineMode()

		# Notify the eyelink of the display resolution
		self.send_command('screen_pixel_coords =  0 0 %d %d' % ( \
			self.resolution[0], self.resolution[1]))

		# Determine the software version of the tracker
		self.tracker_software_ver = 0
		self.eyelink_ver = pylink.getEYELINK().getTrackerVersion()
		if self.eyelink_ver == 3:
			tvstr = pylink.getEYELINK().getTrackerVersionString()
			vindex = tvstr.find("EYELINK CL")
			self.tracker_software_ver = int(float(tvstr[(vindex + \
				len("EYELINK CL")):].strip()))

		# Some configuration stuff (not sure what the parser and gazemap mean)
		if self.eyelink_ver >= 2:
			self.send_command("select_parser_configuration 0")
			if self.eyelink_ver == 2: #turn off scenelink camera stuff
				self.send_command("scene_camera_gazemap = NO")
		else:
			self.send_command("saccade_velocity_threshold = %d" % \
				self.saccade_velocity_threshold)
			self.send_command("saccade_acceleration_threshold = %s" % \
				self.saccade_acceleration_threshold)

		# Set EDF file contents
		self.send_command( \
			"file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
		if self.tracker_software_ver >= 4:
			self.send_command( \
				"file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET")
		else:
			self.send_command( \
				"file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")

		# Set link data. This specifies which data is sent through the link and
		# thus be used in gaze contingent displays
		self.send_command( \
			"link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
		self.send_command( \
			"link_event_data = GAZE,GAZERES,HREF,AREA,VELOCITY,STATUS")
		if self.tracker_software_ver >= 4:
			self.send_command( \
				"link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET")
		else:
			self.send_command( \
				"link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")				

		# Not sure what this means. Maybe the button that is used to end drift
		# correction?
		self.send_command("button_function 5 'accept_target_fixation'")

		# Make sure that we are connected to the eyelink before we start
		# further communication
		if not self.connected():
			raise exceptions.runtime_error( \
				"Failed to connect to the eyetracker")
Beispiel #29
0
    def __init__(self,
                 display,
                 resolution=DISPSIZE,
                 data_file=LOGFILENAME + ".edf",
                 fg_color=FGC,
                 bg_color=BGC,
                 eventdetection=EVENTDETECTION,
                 saccade_velocity_threshold=35,
                 saccade_acceleration_threshold=9500,
                 force_drift_correct=True,
                 pupil_size_mode=EYELINKPUPILSIZEMODE,
                 **args):
        """See pygaze._eyetracker.baseeyetracker.BaseEyeTracker"""

        # try to import copy docstring (but ignore it if it fails, as we do
        # not need it for actual functioning of the code)
        try:
            copy_docstr(BaseEyeTracker, libeyelink)
        except:
            # we're not even going to show a warning, since the copied
            # docstring is useful for code editors; these load the docs
            # in a non-verbose manner, so warning messages would be lost
            pass

        global _eyelink

        # Make sure that we have a valid data file. The local_data_file may
        # contain a folder. The eyelink_data_file is only a basename, i.e.
        # without folder. The eyelink_data_file must be at most eight characters
        # and end with a `.edf` extension.
        self.local_data_file = data_file
        self.eyelink_data_file = os.path.basename(data_file)
        stem, ext = os.path.splitext(self.eyelink_data_file)
        if len(stem) > 8 or ext.lower() != '.edf':
            raise Exception(
                "The EyeLink cannot handle filenames longer than eight "
                "characters (excluding '.edf' extension).")

        # properties
        self.display = display
        self.fontsize = 18
        self.scr = Screen(disptype=DISPTYPE, mousevisible=False)
        self.kb = Keyboard(keylist=["escape", "q"], timeout=1)
        self.resolution = resolution
        self.recording = False
        self.saccade_velocity_treshold = saccade_velocity_threshold
        self.saccade_acceleration_treshold = saccade_acceleration_threshold
        self.eye_used = None
        self.left_eye = 0
        self.right_eye = 1
        self.binocular = 2
        self.pupil_size_mode = pupil_size_mode
        self.prevsample = (-1, -1)
        self.prevps = -1

        # event detection properties
        # degrees; maximal distance from fixation start (if gaze wanders beyond
        # this, fixation has stopped)
        self.fixtresh = 1.5
        # milliseconds; amount of time gaze has to linger within self.fixtresh
        # to be marked as a fixation
        self.fixtimetresh = 100
        # degrees per second; saccade velocity threshold
        self.spdtresh = self.saccade_velocity_treshold
        # degrees per second**2; saccade acceleration threshold
        self.accthresh = self.saccade_acceleration_treshold
        self.set_detection_type(eventdetection)
        # weighted distance, used for determining whether a movement is due to
        # measurement error (1 is ok, higher is more conservative and will
        # result in only larger saccades to be detected)
        self.weightdist = 10
        # distance between participant and screen in cm
        self.screendist = SCREENDIST
        # distance between participant and screen in cm
        self.screensize = SCREENSIZE
        self.pixpercm = (self.resolution[0]/float(self.screensize[0]) + \
         self.resolution[1]/float(self.screensize[1])) / 2.0
        # only initialize eyelink once
        if _eyelink == None:
            try:
                _eyelink = pylink.EyeLink()
            except:
                raise Exception(
                    "Error in libeyelink.libeyelink.__init__(): Failed to "
                    "connect to the tracker!")
        # determine software version of tracker
        self.tracker_software_ver = 0
        self.eyelink_ver = pylink.getEYELINK().getTrackerVersion()
        if self.eyelink_ver == 3:
            tvstr = pylink.getEYELINK().getTrackerVersionString()
            vindex = tvstr.find("EYELINK CL")
            self.tracker_software_ver = int(float(tvstr[(vindex + \
             len("EYELINK CL")):].strip()))
        if self.eyelink_ver == 1:
            self.eyelink_model = 'EyeLink I'
        elif self.eyelink_ver == 2:
            self.eyelink_model = 'EyeLink II'
        elif self.eyelink_ver == 3:
            self.eyelink_model = 'EyeLink 1000'
        else:
            self.eyelink_model = 'EyeLink (model unknown)'
        # Open graphics
        self.eyelink_graphics = EyelinkGraphics(self, _eyelink)
        pylink.openGraphicsEx(self.eyelink_graphics)
        # Optionally force drift correction. For some reason this must be done
        # as (one of) the first things, otherwise a segmentation fault occurs.
        if force_drift_correct:
            self.send_command('driftcorrect_cr_disable = OFF')
        # Set pupil-size mode
        if self.pupil_size_mode == 'area':
            pylink.getEYELINK().setPupilSizeDiameter(False)
        elif self.pupil_size_mode == 'diameter':
            pylink.getEYELINK().setPupilSizeDiameter(True)
        else:
            raise Exception(
             "pupil_size_mode should be 'area' or 'diameter', not %s" \
             % self.pupil_size_mode)
        pylink.getEYELINK().openDataFile(self.eyelink_data_file)
        pylink.flushGetkeyQueue()
        pylink.getEYELINK().setOfflineMode()
        # notify eyelink of display resolution
        self.send_command("screen_pixel_coords = 0 0 %d %d" % \
         (self.resolution[0], self.resolution[1]))
        # get some configuration stuff
        if self.eyelink_ver >= 2:
            self.send_command("select_parser_configuration 0")
            if self.eyelink_ver == 2:  # turn off scenelink camera stuff
                self.send_command("scene_camera_gazemap = NO")
        # set EDF file contents (this specifies which data is written to the EDF
        # file)
        self.send_command(
            "file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON"
        )
        if self.tracker_software_ver >= 4:
            self.send_command(
                "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET"
            )
        else:
            self.send_command(
                "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")
        # set link data (this specifies which data is sent through the link and
        # thus can be used in gaze contingent displays)
        self.send_command(
            "link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
        if self.tracker_software_ver >= 4:
            self.send_command(
                "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET"
            )
        else:
            self.send_command(
                "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")
        # not quite sure what this means (according to Sebastiaan Mathot, it
        # might be the button that is used to end drift correction?)
        self.send_command("button_function 5 'accept_target_fixation'")

        if not self.connected():
            raise Exception(
                "Error in libeyelink.libeyelink.__init__(): Failed to connect "
                "to the eyetracker!")
Beispiel #30
0
	def __init__(self, resolution, data_file = "default.edf", fg_color = (255, 255, 255), bg_color = (0, 0, 0), saccade_velocity_threshold = 35, saccade_acceleration_threshold = 9500):

		"""
		Initializes the connection to the Eyelink
	
		Parameters:
		_resolution: (width, height) tuple
		_data_file: the name of the EDF file
	
		Returns:
		True on connection success and False on connection failure       
		"""
		
		global _eyelink
	
		self.data_file = data_file
		self.resolution = resolution
		self.recording = False		
		
		self.saccade_velocity_treshold = saccade_velocity_threshold
		self.saccade_acceleration_treshold = saccade_acceleration_threshold
		self.eye_used = None
		self.left_eye = 0
		self.right_eye = 1
		self.binocular = 2
	
		# Only initialize the eyelink once		
		if _eyelink == None:
			try:
				_eyelink = pylink.EyeLink()
			except Exception as e:
				raise exceptions.runtime_error("Failed to connect to the tracker: %s" % e)
				
			graphics_env = eyelink_graphics(_eyelink)
			pylink.openGraphicsEx(graphics_env)	
					
		pylink.getEYELINK().openDataFile(self.data_file)		     
		pylink.flushGetkeyQueue()
		pylink.getEYELINK().setOfflineMode()
		
		# Notify the eyelink of the display resolution
		self.send_command("screen_pixel_coords =  0 0 %d %d" % (self.resolution[0], self.resolution[1]))

		# Determine the software version of the tracker
		self.tracker_software_ver = 0
		self.eyelink_ver = pylink.getEYELINK().getTrackerVersion()
		if self.eyelink_ver == 3:
			tvstr = pylink.getEYELINK().getTrackerVersionString()
			vindex = tvstr.find("EYELINK CL")
			self.tracker_software_ver = int(float(tvstr[(vindex + len("EYELINK CL")):].strip()))

		# Set some configuration stuff (not sure what the parser and gazemap mean)
		if self.eyelink_ver >= 2:
			self.send_command("select_parser_configuration 0")
			if self.eyelink_ver == 2: #turn off scenelink camera stuff
				self.send_command("scene_camera_gazemap = NO")
		else:
			self.send_command("saccade_velocity_threshold = %d" % self.saccade_velocity_threshold)
			self.send_command("saccade_acceleration_threshold = %s" % self.saccade_acceleration_threshold)
	
		# Set EDF file contents. This specifies which data is written to the EDF file.
		self.send_command("file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
		if self.tracker_software_ver >= 4:
			self.send_command("file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET")
		else:
			self.send_command("file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")

		# Set link data. This specifies which data is sent through the link and thus can
		# be used in gaze contingent displays
		self.send_command("link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
		if self.tracker_software_ver >= 4:
			self.send_command("link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET")
		else:
			self.send_command("link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS") 

		# Not sure what this means. Maybe the button that is used to end drift correction?
		self.send_command("button_function 5 'accept_target_fixation'")
					
		if not self.connected():
			raise exceptions.runtime_error("Failed to connect to the eyetracker")
Beispiel #31
0
 def clearAllEventBuffers(self):
     pylink.flushGetkeyQueue()
     self.tracker.resetData()
     self._iohub_server.eventBuffer.clear()
     for d in self._iohub_server.devices:
         d.clearEvents()
Beispiel #32
0
 def __init__(self,edfsubject):
     # Make filename
     self.fname = os.path.splitext(edfsubject)[0]  # strip away extension if present
     assert re.match(r'\w+$', self.fname), 'Name must only include A-Z, 0-9, or _'
     assert len(self.fname) <= 8, 'Name must be <= 8 characters.'
     # Make filename 
     self.edfname = self.fname + '.edf'
 
     # Initialize connection with eyetracker
     try:
         self.tracker = pylink.EyeLink()
         self.realconnect = True
     except RuntimeError:
         self.tracker = pylink.EyeLink(None)
         self.realconnect = False
     
     #properties
     #screen
     self.w = GetSystemMetrics(0)
     self.h = GetSystemMetrics(1)        
     #find out which eye
     self.left_eye = 0
     self.right_eye = 1
     self.binocular = 2        
     #gaze-timing
     self.GCWINDOW = .5 #500 msec
     self.DURATION = 2 #2000 msec
     self.gbox = 200 #gaze boundary
     self.inbox = False
     self.Finished = False
     self.Fixation = True        
     #gaze-bounding box
     self.sc = [self.w / 2.0, self.h / 2.0] #center of screen
     self.size = 100 #Length of one side of box
     self.xbdr = [self.sc[0] - self.size, self.sc[0] + self.size]
     self.ybdr = [self.sc[1] - self.size, self.sc[1] + self.size]        
     #calibration
     self.cnum = 13 # 13 pt calibration
     self.paval = 1000 #Pacing of calibration, t in milliseconds        
     #pupil
     self.red = 'red'
     self.green = 'green'
     self.blue = 'blue'
     # Open EDF
     pylink.getEYELINK().openDataFile(self.edfname)
     pylink.flushGetkeyQueue()
     pylink.getEYELINK().setOfflineMode()
     
     # notify eyelink of display resolution        
     pylink.getEYELINK().sendCommand("screen_pixel_coords =  0 0 %d %d" %(self.w - 1, self.h - 1))
     pylink.getEYELINK().sendMessage("DISPLAY_COORDS  0 0 %d %d" %(self.w - 1, self.h - 1))
     
     # Set content of edf file
     pylink.getEYELINK().sendCommand(
         'file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT')
     
     pylink.getEYELINK().sendCommand(
         'link_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON')
 
     pylink.getEYELINK().sendCommand(
         'link_sample_data = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET')
 
     pylink.getEYELINK().sendCommand(
         'file_sample_data = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET,INPUT')
 
     # Set display coords for dataviewer
     pylink.getEYELINK().sendMessage("screen_pixel_coords =  0 0 %d %d" %(self.w - 1, self.h - 1))
     pylink.getEYELINK().sendMessage("DISPLAY_COORDS  0 0 %d %d" %(self.w - 1, self.h - 1))
Beispiel #33
0
    def __init__(self,
                 win,
                 clock,
                 sj="TEST",
                 saccadeSensitivity=HIGH,
                 calibrationType='HV9',
                 calibrationTargetColor=WHITE,
                 calibrationBgColor=BLACK,
                 CalibrationSounds=False,
                 screen=(1024, 768)):
        '''win: psychopy visual window used for the experiment
          clock: psychopy time clock recording time for whole experiment
          sj: Subject identifier string (affects EDF filename)
          saccadeSensitivity:
            HIGH: Pursuit and neurological work
            LOW:  Cognitive research
          calibrationType:
            H3: Horizontal 3-point
            HV3: 3-point calibration, poor linearization
            HV5: 5-point calibration, poor at corners
            HV9: 9-point calibration, best overall
        calibrationTargetColor and calibrationBgColor:
            RGB tuple, i.e., (255,0,0) for Red
            One of: BLACK, WHITE, GRAY
        calibrationSounds:
            True: enable feedback sounds when calibrating'''
        self.edfFileName = str(
            sj) + ".EDF"  # Subject name only can put 8 characters
        print("Connecting to eyetracker.")
        self.tracker = pylink.EyeLink()
        self.timeCorrection = clock.getTime() - self.tracker.trackerTime()
        print("Loading custom graphics")
        #Initializes Experiment Graphics
        genv = EyeLinkCoreGraphicsPsychopy(self.tracker, win, screen)
        pylink.openGraphicsEx(genv)
        # opendatafile
        self.tracker.openDataFile(self.edfFileName)

        #EyeLink Tracker Configuration
        pylink.flushGetkeyQueue()
        # Initializes the key queue used by getkey(). It may be called at any time to get rid any of old keys from the queue.
        self.tracker.setOfflineMode()
        #Places EyeLink tracker in off-line (idle) mode. Wait till the tracker has finished the mode transition
        self.tracker.sendCommand("screen_pixel_coords =  0 0 %d %d" %
                                 (tuple(screen)))
        self.tracker.setCalibrationType(calibrationType)
        self.tracker.sendCommand(
            "driftcorrect_cr_disable=OFF"
        )  #CF - OFF: turns on drift CORRECT; AUTO: Turns on drift CHECK; ON: Turns off both
        #self.tracker.sendCommand("generate_default_targets = NO")
        #self.tracker.sendCommand("calibration_targets = 512,384 512,417 512,351 402,384 622,384 402,417 622,417 402,351 622,351")
        #self.tracker.sendCommand("validation_targets = 512,384 512,417 512,351 402,384 622,384 402,417 622,417 402,351 622,351")

        self.tracker.sendMessage("DISPLAY_COORDS  0 0 %d %d" % (tuple(screen)))
        eyelink_ver = self.tracker.getTrackerVersion()
        if eyelink_ver == 3:
            tvstr = self.tracker.getTrackerVersionString()
            vindex = tvstr.find("EYELINK CL")
            tracker_software_ver = int(
                float(tvstr[(vindex + len("EYELINK CL")):].strip()))
        else:
            tracker_software_ver = 0
        if eyelink_ver >= 2:
            self.tracker.sendCommand("select_parser_configuration %d" %
                                     saccadeSensitivity)
        else:
            if saccadeSensitivity == HIGH: svt, sat = 22, 5000
            else: svt, sat = 30, 9500
            self.tracker.sendCommand("saccade_velocity_threshold = %d" % svt)
            self.tracker.sendCommand("saccade_acceleration_threshold = %d" %
                                     sat)
        if eyelink_ver == 2:  #turn off scenelink camera stuff
            self.tracker.sendCommand("scene_camera_gazemap = NO")

        # set EDF file contents
        self.tracker.setFileEventFilter(
            "LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON")
        if tracker_software_ver >= 4:
            self.tracker.setFileSampleFilter(
                "LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,HTARGET")
        else:
            self.tracker.setFileSampleFilter(
                "LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS")

        # set link data (used for gaze cursor)
        self.tracker.setLinkEventFilter(
            "LEFT,RIGHT,FIXATION,SACCADE,BLINK,BUTTON")
        if tracker_software_ver >= 4:
            self.tracker.setLinkSampleFilter(
                "LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,HTARGET")
        else:
            self.tracker.setLinkSampleFilter(
                "LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS")

        #self.tracker.setAcceptTargetFixationButton(1) # This programs a specific button for use in drift correction.

        #Set the calibration settings:
        #pylink.setCalibrationColors(WHITE, BLACK) # Sets the calibration target and background color(foreground_color, background_color)
        if CalibrationSounds:
            pylink.setCalibrationSounds("", "", "")
            pylink.setDriftCorrectSounds("", "off", "off")
        else:
            pylink.setCalibrationSounds("off", "off", "off")
            pylink.setDriftCorrectSounds("off", "off", "off")

        print("Beginning tracker setup")
        self.tracker.doTrackerSetup()
def run(stim_path,
        idx_path,
        on_msec_length=300,
        off_msec_length=200,
        final_blank_sec_length=16,
        init_blank_sec_length=16,
        fix_pix_size=20,
        fix_button_prob=1 / 6.,
        eyetracker=None,
        edf_path=None,
        **monitor_kwargs):
    """run one run of the experiment

    stim_path specifies the path of the unshuffled experiment stimuli, while idx_path specifies the
    path of the shuffled indices to use for this run. This function will load in the stimuli at
    stim_path and rearrange them using the indices found at idx_path, then simply go through those
    stimuli in order, showing each stimuli for `on_msec_length` msecs and then a blank screen for
    `off_msec_length` msecs (or as close as possible, given the monitor's refresh rate).

    For fixation, we show a stream of digits whose colors alternate between black and white, with a
    `fix_button_prob` chance of repeating. Digits are presented with alternating stimuli ON and OFF
    blocks, so that a digit will be shown for on_msec_length+off_msec_length msecs and then there
    will be nothing at fixation for the next on_msec_length+off_msec_length msecs. For now, you
    can't change this.

    All stimuli loaded in from stim_path will be shown.


    Arguments
    ============

    stim_path: string, path to .npy file where stimuli are stored (as 3d array)

    idx_path: string, path to .npy file where shuffled indices are stored (as 1d array)

    on_msec_length: int, length of the ON blocks in milliseconds; that is, the length of time to
    display each stimulus before moving on

    off_msec_length: int, length of the OFF blocks in milliseconds; that is, the length of time to
    between stimuli

    fix_pix_size: int, the size of the fixation digits, in pixels.

    fix_button_prob: float. the probability that the fixation digit will repeat or the fixation dot
    will change color (will never repeat more than once in a row). For fixation digit, this
    probability is relative to each stimulus presentation / ON block starting; for fixation dot,
    it's each stimulus change (stimulus ON or OFF block starting).

    eyetracker: EyeLink object or None. if None, will not collect eyetracking data. if not None,
    will gather it. the EyeLink object must already be initialized (by calling the _setup_eyelink
    function, as is done in the expt function). if this is set, must also specify edf_path
    
    edf_path: str or None. if eyetracker is not None, this must be a string, which is where we
    will save the output of the eyetracker
    """
    stimuli, idx, expt_params, monitor_kwargs = _set_params(
        stim_path, idx_path, on_msec_length, off_msec_length, fix_button_prob,
        final_blank_sec_length, init_blank_sec_length, **monitor_kwargs)

    win = visual.Window(**monitor_kwargs)
    win.mouseVisible = False
    # linear gamma ramp
    win.gammaRamp = np.tile(np.linspace(0, 1, 256), (3, 1))

    fixation = visual.TextStim(win,
                               next(expt_params['fixation_text']),
                               height=fix_pix_size,
                               color=None)
    fixation.color = next(expt_params['fixation_color'])
    # first one is special: we preload it, but we still want to include it in the iterator so the
    # numbers all match up (we don't draw or wait during the on part of the first iteration)
    img = visual.ImageStim(win,
                           image=imagetools.array2image(stimuli[0]),
                           size=expt_params['stim_size'])

    if eyetracker is not None:
        assert edf_path is not None, "edf_path must be set so we can save the eyetracker output!"
        eyetracker.openDataFile('temp.EDF')
        pylink.flushGetkeyQueue()
        eyetracker.startRecording(1, 1, 1, 1)

    wait_text = visual.TextStim(
        win, ("Press 5 to start\nq will quit this run\nescape will quit "
              "this session"))
    wait_text.draw()
    win.flip()
    # preload these to save time
    img.draw()
    fixation.draw()

    clock = core.Clock()
    # wait until receive 5, which is the scanner trigger
    all_keys = event.waitKeys(keyList=['5', 'q', 'escape'], timeStamped=clock)
    if 'q' in [k[0] for k in all_keys] or 'escape' in [k[0] for k in all_keys]:
        win.close()
        return all_keys, [], [], expt_params, idx

    keys_pressed = [(key[0], key[1]) for key in all_keys]
    timings = [("start", "off", clock.getTime())]
    fixation_info = []
    for i, stim in enumerate(stimuli):
        if i > 0:
            # we don't wait the first time, and all these have been preloaded while we were waiting
            # for the scan trigger
            if "fixation_text" in expt_params:
                fixation.text = next(expt_params['fixation_text'])
            img.image = imagetools.array2image(stim)
            fixation.color = next(expt_params['fixation_color'])
            img.draw()
            fixation.draw()
            next_stim_time = (i * on_msec_length + i * off_msec_length -
                              2) / 1000.
            core.wait(abs(clock.getTime() - timings[0][2] - next_stim_time))
        if eyetracker is not None:
            eyetracker.sendMessage("TRIALID %02d" % i)
        win.flip()
        timings.append(("stimulus_%d" % i, "on", clock.getTime()))
        fixation_info.append((fixation.text, clock.getTime()))
        fixation.draw()
        next_stim_time = (
            (i + 1) * on_msec_length + i * off_msec_length - 1) / 1000.
        core.wait(abs(clock.getTime() - timings[0][2] - next_stim_time))
        win.flip()
        timings.append(("stimulus_%d" % i, "off", clock.getTime()))
        all_keys = event.getKeys(timeStamped=clock)
        if all_keys:
            keys_pressed.extend([(key[0], key[1]) for key in all_keys])
        if 'q' in [k[0]
                   for k in all_keys] or 'escape' in [k[0] for k in all_keys]:
            break
    if eyetracker is not None:
        eyetracker.stopRecording()
        eyetracker.closeDataFile()
        eyetracker.receiveDataFile('temp.EDF', edf_path)
    win.close()
    return keys_pressed, fixation_info, timings, expt_params, idx