Beispiel #1
0
	def __init__(self, display):

		"""Initiates an eyetracker dummy object, that simulates gaze position using the mouse
		
		arguments
		display		--	a pygaze display.Display instance
		
		keyword arguments
		None
		"""

		# try to copy docstrings (but ignore it if it fails, as we do
		# not need it for actual functioning of the code)
		try:
			copy_docstr(BaseEyeTracker, Dummy)
		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

		self.recording = False
		self.blinking = False
		self.bbpos = (settings.DISPSIZE[0]/2, settings.DISPSIZE[1]/2)
		self.resolution = settings.DISPSIZE[:]
		self.simulator = Mouse(disptype=settings.DISPTYPE, mousebuttonlist=None,
			timeout=2, visible=False)
		self.kb = Keyboard(disptype=settings.DISPTYPE, keylist=None,
			timeout=None)
		self.angrybeep = Sound(osc='saw',freq=100, length=100, attack=0,
			decay=0, soundfile=None)
		self.display = display
		self.screen = Screen(disptype=settings.DISPTYPE, mousevisible=False)
Beispiel #2
0
    def __init__(self, display, logfile=settings.LOGFILE, \
        alea_key=settings.ALEAKEY, \
        animated_calibration=settings.ALEAANIMATEDCALIBRATION, \
        eventdetection=settings.EVENTDETECTION, \
        saccade_velocity_threshold=35, \
        saccade_acceleration_threshold=9500, \
        blink_threshold=settings.BLINKTHRESH, \
        **args):
        """Initializes the AleaTracker object
        
        arguments
        display    -- a pygaze.display.Display instance
        
        keyword arguments
        logfile    -- logfile name (string value); note that this is the
                   name for the eye data log file (default = LOGFILE)
        """

        # try to copy docstrings (but ignore it if it fails, as we do
        # not need it for actual functioning of the code)
        try:
            copy_docstr(BaseEyeTracker, AleaTracker)
        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

        # object properties
        self.disp = display
        self.screen = Screen()
        self.dispsize = self.disp.dispsize  # display size in pixels
        self.screensize = settings.SCREENSIZE  # display size in cm
        self.kb = Keyboard(keylist=['space', 'escape', 'q'], timeout=1)
        self.errorbeep = Sound(osc='saw', freq=100, length=100)

        # show a message
        self.screen.clear()
        self.screen.draw_text(
            text="Initialising the eye tracker, please wait...", fontsize=20)
        self.disp.fill(self.screen)
        self.disp.show()

        # output file properties
        self.outputfile = logfile + '.tsv'

        # calibration properties
        self.animated_calibration = animated_calibration == True

        # eye tracker properties
        self.connected = False
        self.recording = False
        self.errdist = 2  # degrees; maximal error for drift correction
        self.pxerrdist = 30  # initial error in pixels
        self.maxtries = 100  # number of samples obtained before giving up (for obtaining accuracy and tracker distance information, as well as starting or stopping recording)
        self.prevsample = (-1, -1)
        self.prevps = -1

        # event detection properties
        self.fixtresh = 1.5  # degrees; maximal distance from fixation start (if gaze wanders beyond this, fixation has stopped)
        self.fixtimetresh = 100  # milliseconds; amount of time gaze has to linger within self.fixtresh to be marked as a fixation
        self.spdtresh = saccade_velocity_threshold  # degrees per second; saccade velocity threshold
        self.accthresh = saccade_acceleration_threshold  # degrees per second**2; saccade acceleration threshold
        self.blinkthresh = blink_threshold  # milliseconds; blink detection threshold used in PyGaze method
        self.eventdetection = eventdetection
        self.set_detection_type(self.eventdetection)
        self.weightdist = 10  # 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)

        # connect to the tracker
        self.alea = OGAleaTracker(alea_key, file_path=self.outputfile)

        # get info on the sample rate
        # TODO: Compute after streaming some samples?
        self.samplerate = 60.0
        self.sampletime = 1000.0 / self.samplerate

        # initiation report
        self.log("pygaze initiation report start")
        self.log("display resolution: {}x{}".format( \
            self.dispsize[0], self.dispsize[1]))
        self.log("display size in cm: {}x{}".format( \
            self.screensize[0], self.screensize[1]))
        self.log("samplerate: {} Hz".format(self.samplerate))
        self.log("sampletime: {} ms".format(self.sampletime))
        self.log("fixation threshold: {} degrees".format(self.fixtresh))
        self.log("speed threshold: {} degrees/second".format(self.spdtresh))
        self.log("acceleration threshold: {} degrees/second**2".format( \
            self.accthresh))
        self.log("pygaze initiation report end")
Beispiel #3
0
    def __init__(self,
                 display,
                 ip='127.0.0.1',
                 sendport=4444,
                 receiveport=5555,
                 logfile=settings.LOGFILE,
                 eventdetection=settings.EVENTDETECTION,
                 saccade_velocity_threshold=35,
                 saccade_acceleration_threshold=9500,
                 **args):
        """Initializes the SMItracker object
		
		arguments
		display	-- a pygaze.display.Display instance
		
		keyword arguments
		ip		-- internal ip address for iViewX (default = 
				   '127.0.0.1')
		sendport	-- port number for iViewX sending (default = 4444)
		receiveport	-- port number for iViewX receiving (default = 5555)
		logfile	-- logfile name (string value); note that this is the
				   name for the SMI logfile, NOT the .idf file
				   (default = LOGFILE)
		"""

        # try to copy docstrings (but ignore it if it fails, as we do
        # not need it for actual functioning of the code)
        try:
            copy_docstr(BaseEyeTracker, SMITracker)
        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

        # object properties
        self.disp = display
        self.screen = Screen()
        self.dispsize = settings.DISPSIZE  # display size in pixels
        self.screensize = settings.SCREENSIZE  # display size in cm
        self.kb = Keyboard(keylist=['space', 'escape', 'q'], timeout=1)
        self.errorbeep = Sound(osc='saw', freq=100, length=100)

        # output file properties
        self.outputfile = logfile
        self.description = "experiment"  # TODO: EXPERIMENT NAME
        self.participant = "participant"  # TODO: PP NAME

        # eye tracker properties
        self.connected = False
        self.recording = False
        self.eye_used = 0  # 0=left, 1=right, 2=binocular
        self.left_eye = 0
        self.right_eye = 1
        self.binocular = 2
        self.errdist = 2  # degrees; maximal error for drift correction
        self.maxtries = 100  # number of samples obtained before giving up (for obtaining accuracy and tracker distance information, as well as starting or stopping recording)
        self.prevsample = (-1, -1)
        self.prevps = -1

        # event detection properties
        self.fixtresh = 1.5  # degrees; maximal distance from fixation start (if gaze wanders beyond this, fixation has stopped)
        self.fixtimetresh = 100  # milliseconds; amount of time gaze has to linger within self.fixtresh to be marked as a fixation
        self.spdtresh = saccade_velocity_threshold  # degrees per second; saccade velocity threshold
        self.accthresh = saccade_acceleration_threshold  # degrees per second**2; saccade acceleration threshold
        self.eventdetection = eventdetection
        self.set_detection_type(self.eventdetection)
        self.weightdist = 10  # 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)

        # set logger
        res = iViewXAPI.iV_SetLogger(c_int(1),
                                     c_char_p(logfile + '_SMILOG.txt'))
        if res != 1:
            err = errorstring(res)
            raise Exception(
                "Error in libsmi.SMItracker.__init__: failed to set logger; %s"
                % err)
        # first logger argument is for logging type (I'm guessing these are decimal bit codes)
        # LOG status					bitcode
        # 1 = LOG_LEVEL_BUG			 00001
        # 2 = LOG_LEVEL_iV_FCT		  00010
        # 4 = LOG_LEVEL_ETCOM		   00100
        # 8 = LOG_LEVEL_ALL			 01000
        # 16 = LOG_LEVEL_IV_COMMAND	 10000
        # these can be used together, using a bitwise or, e.g.: 1|2|4 (bitcode 00111)

        # connect to iViewX
        res = iViewXAPI.iV_Connect(c_char_p(ip), c_int(sendport), c_char_p(ip),
                                   c_int(receiveport))
        if res == 1:
            res = iViewXAPI.iV_GetSystemInfo(byref(systemData))
            self.samplerate = systemData.samplerate
            self.sampletime = 1000.0 / self.samplerate
            if res != 1:
                err = errorstring(res)
                raise Exception(
                    "Error in libsmi.SMItracker.__init__: failed to get system information; %s"
                    % err)
        # handle connection errors
        else:
            self.connected = False
            err = errorstring(res)
            raise Exception(
                "Error in libsmi.SMItracker.__init__: establishing connection failed; %s"
                % err)

        # initiation report
        self.log("pygaze initiation report start")
        self.log("experiment: %s" % self.description)
        self.log("participant: %s" % self.participant)
        self.log("display resolution: %sx%s" %
                 (self.dispsize[0], self.dispsize[1]))
        self.log("display size in cm: %sx%s" %
                 (self.screensize[0], self.screensize[1]))
        self.log("samplerate: %s Hz" % self.samplerate)
        self.log("sampletime: %s ms" % self.sampletime)
        self.log("fixation threshold: %s degrees" % self.fixtresh)
        self.log("speed threshold: %s degrees/second" % self.spdtresh)
        self.log("acceleration threshold: %s degrees/second**2" %
                 self.accthresh)
        self.log("pygaze initiation report end")
Beispiel #4
0
# create instances

# initialize the display
disp = Display()

# initialize a screen
scr = Screen()

# initialize an EyeTracker
tracker = EyeTracker(disp)

# initialize a keyboard
kb = Keyboard(keylist=['space'], timeout=None)

# initialize a sound
snd = Sound(soundfile=soundfile)

# initialize a Timer
timer = Time()

# create a new logfile
log = Logfile(filename="test")
log.write(["test", "time"])

# # # # #
# welcome

scr.draw_text("Welcome to the PyGaze Supertest!\n\nYou're going to be testing \
your PyGaze installation today, using this interactive tool. Press Space \
to start!\n\n\nP.S. If you see this, the following functions work: \
\n- Screen.draw_text \
Beispiel #5
0
	def __init__(self, libeyelink, tracker):

		"""
		Constructor.

		Arguments:
		libeyelink	--	A libeyelink object.
		tracker		--	An tracker object as returned by pylink.EyeLink().
		"""

		pylink.EyeLinkCustomDisplay.__init__(self)

		# objects
		self.libeyelink = libeyelink
		self.display = libeyelink.display
		self.screen = Screen(disptype=DISPTYPE, mousevisible=False)
		self.kb = Keyboard(keylist=None, timeout=0)
		self.mouse = Mouse(timeout=0)
		if DISPTYPE == 'pygame':
			self.kb.set_timeout(timeout=0.001)
		# If we are using a DISPTYPE that cannot be used directly, we have to
		# save the camera image to a temporary file on each frame.
		#if DISPTYPE not in ('pygame', 'psychopy'):
		import tempfile
		import os
		self.tmp_file = os.path.join(tempfile.gettempdir(), '__eyelink__.jpg')
		# drawing properties
		self.xc = self.display.dispsize[0]/2
		self.yc = self.display.dispsize[1]/2
		self.extra_info = True
		self.ld = 40 # line distance
		self.fontsize = libeyelink.fontsize
		self.title = ""
		self.display_open = True
		# menu
		self.menuscreen = Screen(disptype=DISPTYPE, mousevisible=False)		
		self.menuscreen.draw_text(text="Eyelink calibration menu",
			pos=(self.xc,self.yc-6*self.ld), center=True, font='mono',
			fontsize=int(2*self.fontsize), antialias=True)
		self.menuscreen.draw_text(text="%s (pygaze %s, pylink %s)" \
			% (libeyelink.eyelink_model, pygaze.version, pylink.__version__),
			pos=(self.xc,self.yc-5*self.ld), center=True,
			font='mono', fontsize=int(.8*self.fontsize), antialias=True)
		self.menuscreen.draw_text(text="Press C to calibrate", 
			pos=(self.xc, self.yc-3*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(text="Press V to validate",
			pos=(self.xc, self.yc-2*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(text="Press A to auto-threshold",
			pos=(self.xc,self.yc-1*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(text="Press I to toggle extra info in camera image",
			pos=(self.xc,self.yc-0*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(text="Press Enter to show camera image",
			pos=(self.xc,self.yc+1*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(
			text="(then change between images using the arrow keys)",
			pos=(self.xc, self.yc+2*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(text="Press Escape to abort experiment",
			pos=(self.xc, self.yc+4*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)			
		self.menuscreen.draw_text(text="Press Q to exit menu",
			pos=(self.xc, self.yc+5*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		# beeps
		self.__target_beep__ = Sound(osc='sine', freq=440, length=50, 
			attack=0, decay=0, soundfile=None)
		self.__target_beep__done__ = Sound(osc='sine', freq=880, length=200,
			attack=0, decay=0, soundfile=None)
		self.__target_beep__error__ = Sound(osc='sine', freq=220, length=200,
			attack=0, decay=0, soundfile=None)
		# Colors
		self.color = {
			pylink.CR_HAIR_COLOR:			pygame.Color('white'),
			pylink.PUPIL_HAIR_COLOR:		pygame.Color('white'),
			pylink.PUPIL_BOX_COLOR:			pygame.Color('green'),
			pylink.SEARCH_LIMIT_BOX_COLOR:	pygame.Color('red'),
			pylink.MOUSE_CURSOR_COLOR:		pygame.Color('red'),	
			'font':							pygame.Color('white'),		
			}
		# Font
		pygame.font.init()
		self.font = pygame.font.SysFont('Courier New', 11)
		# further properties
		self.state = None
		self.pal = None
		
		self.size = (0,0)
		self.set_tracker(tracker)
		self.last_mouse_state = -1
		self.bit64 = '64bit' in platform.architecture()
		self.imagebuffer = self.new_array()		
Beispiel #6
0
    def __init__(self, display,
        logfile=settings.LOGFILE, \
        eventdetection=settings.EVENTDETECTION, \
        saccade_velocity_threshold=35, \
        saccade_acceleration_threshold=9500, \
        blink_threshold=settings.BLINKTHRESH, \
        **args):

        # try to copy docstrings (but ignore it if it fails, as we do
        # not need it for actual functioning of the code)
        try:
            copy_docstr(BaseEyeTracker, EyeLogicTracker)
        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

        self.disp = display
        self.screen = Screen()
        self.dispsize = self.disp.dispsize # display size in pixels
        self.screensize = settings.SCREENSIZE # display size in cm
        self.kb = Keyboard(keylist=['space', 'escape', 'q'], timeout=1)
        self.errorbeep = Sound(osc='saw', freq=100, length=100)

        # show a message
        self.screen.clear()
        self.screen.draw_text(
            text="Initialising the eye tracker, please wait...",
            fontsize=20)
        self.disp.fill(self.screen)
        self.disp.show()

        # output file properties
        self.logfile = logfile

        # eye tracker properties
        self._recording = Event()
        self._recording.clear()
        self._calibrated = Event()
        self._calibrated.clear()
        self.eye_used = 2 # 0=left, 1=right, 2=binocular
        self.sampleLock = Lock()
        self.lastSample = None
        self.maxtries = 100 # number of samples obtained before giving up (for obtaining accuracy and tracker distance information, as well as starting or stopping recording)

        # event detection properties
        self.pxfixtresh = 50;
        self.fixtresh = 1.5 # degrees; maximal distance from fixation start (if gaze wanders beyond this, fixation has stopped)
        self.fixtimetresh = 100 # milliseconds; amount of time gaze has to linger within self.fixtresh to be marked as a fixation

        self.spdtresh = saccade_velocity_threshold # degrees per second; saccade velocity threshold
        self.accthresh = saccade_acceleration_threshold # degrees per second**2; saccade acceleration threshold
        self.blinkthresh = blink_threshold # milliseconds; blink detection threshold used in PyGaze method
        self.eventdetection = eventdetection

        self._log_vars = [ \
            "timestampMicroSec", \
            "index", \
            "porFilteredX", \
            "porFilteredY", \
            "porLeftX", \
            "porLeftY", \
            "pupilRadiusLeft", \
            "porRightX", \
            "porRightY", \
            "pupilRadiusRight", \
            ]
        # Open a new log file.
        dir_name = os.path.dirname(logfile)
        file_name = os.path.basename(logfile)
        name, ext = os.path.splitext(file_name)
        self._data_file_path = os.path.join(dir_name, name+".eyelogic.csv")
        self._log_file = open(self._data_file_path, "w")
        # Write a header to the log.
        header = ["TYPE"]
        header.extend(self._log_vars)
        self._sep = ";"
        self._log_file.write("Sep="+self._sep+"\n")
        self._log_file.write(self._sep.join(map(str, header)))
        # Create a lock to prevent simultaneous access to the log file.
        self._logging_queue = Queue()
        self._logging_queue_empty = Event()
        self._logging_queue_empty.set()
        self._connected = Event()
        self._connected.set()
        self._log_counter = 0
        self._log_consolidation_freq = 60
        
        self._logging_thread = Thread( target=self.loggingThread, \
                name='PyGaze_EyeLogic_Logging', args=[])

        global g_api
        g_api = self

        # log
        self.log("pygaze initiation")
        #self.log("experiment = {}".format(self.description))
        #self.log("participant = {}".format(self.participant))
        self.log("display resolution = {}x{}".format(self.dispsize[0], \
            self.dispsize[1]))
        self.log("display size in cm = {}x{}".format(self.screensize[0], \
            self.screensize[1]))
        self.log("fixation threshold = {} degrees".format(self.fixtresh))
        self.log("speed threshold = {} degrees/second".format(self.spdtresh))
        self.log("acceleration threshold = {} degrees/second**2".format( \
            self.accthresh))

        # connect
        self.api = ELApi( "PyGaze" )
        self.api.registerGazeSampleCallback( gazeSampleCallback )
        self.api.registerEventCallback( eventCallback )

        resultConnect = self.api.connect()
        if (resultConnect != ELApi.ReturnConnect.SUCCESS):
            self._connected.clear()
            raise Exception("Cannot connect to EyeLogic server = {}".format(errorstringConnect(resultConnect)))
        self._connected.set()

        screenConfig = self.api.getScreenConfig()
        self.log("eye tracker is mounted on screen {}".format(screenConfig.id))
        self.rawResolution = (screenConfig.resolutionX, screenConfig.resolutionY)
        self.log("raw screen resolution = {}x{}".format(
            self.rawResolution[0], self.rawResolution[1]))
        self.log("end pygaze initiation")

        deviceConfig = self.api.getDeviceConfig()
        if (deviceConfig.deviceSerial == 0):
            raise Exception("no eye tracking device connected")
        if (len(deviceConfig.frameRates) == 0):
            raise Exception("failed to read out device configuration")
        g_api.sampleRate = deviceConfig.frameRates[0]
        g_api.sampleTime = 1000.0 / g_api.sampleRate
        g_api.log("samplerate = {} Hz".format(g_api.sampleRate))
        g_api.log("sampletime = {} ms".format(g_api.sampleTime))
        self._logging_thread.start()

        self.screen.clear()
        self.disp.fill(self.screen)
        self.disp.show()
Beispiel #7
0
	def __init__(self, display, logfile=LOGFILE, eventdetection=EVENTDETECTION, \
		saccade_velocity_threshold=35, saccade_acceleration_threshold=9500, \
		**args):

		"""Initializes the EyeTribeTracker object
		
		arguments
		display	-- a pygaze.display.Display instance
		
		keyword arguments
		logfile	-- logfile name (string value); note that this is the
				   name for the eye data log file (default = LOGFILE)
		"""

		# try to copy docstrings (but ignore it if it fails, as we do
		# not need it for actual functioning of the code)
		try:
			copy_docstr(BaseEyeTracker, EyeTribeTracker)
		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

		# object properties
		self.disp = display
		self.screen = Screen()
		self.dispsize = DISPSIZE # display size in pixels
		self.screensize = SCREENSIZE # display size in cm
		self.kb = Keyboard(keylist=['space', 'escape', 'q'], timeout=1)
		self.errorbeep = Sound(osc='saw',freq=100, length=100)
		
		# output file properties
		self.outputfile = logfile
		
		# eye tracker properties
		self.connected = False
		self.recording = False
		self.errdist = 2 # degrees; maximal error for drift correction
		self.pxerrdist = 30 # initial error in pixels
		self.maxtries = 100 # number of samples obtained before giving up (for obtaining accuracy and tracker distance information, as well as starting or stopping recording)
		self.prevsample = (-1,-1)
		self.prevps = -1
		
		# event detection properties
		self.fixtresh = 1.5 # degrees; maximal distance from fixation start (if gaze wanders beyond this, fixation has stopped)
		self.fixtimetresh = 100 # milliseconds; amount of time gaze has to linger within self.fixtresh to be marked as a fixation
		self.spdtresh = saccade_velocity_threshold # degrees per second; saccade velocity threshold
		self.accthresh = saccade_acceleration_threshold # degrees per second**2; saccade acceleration threshold
		self.eventdetection = eventdetection
		self.set_detection_type(self.eventdetection)
		self.weightdist = 10 # 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)

		# connect to the tracker
		self.eyetribe = EyeTribe(logfilename=logfile)

		# get info on the sample rate
		self.samplerate = self.eyetribe._samplefreq
		self.sampletime = 1000.0 * self.eyetribe._intsampletime

		# initiation report
		self.log("pygaze initiation report start")
		self.log("display resolution: %sx%s" % (self.dispsize[0],self.dispsize[1]))
		self.log("display size in cm: %sx%s" % (self.screensize[0],self.screensize[1]))
		self.log("samplerate: %.2f Hz" % self.samplerate)
		self.log("sampletime: %.2f ms" % self.sampletime)
		self.log("fixation threshold: %s degrees" % self.fixtresh)
		self.log("speed threshold: %s degrees/second" % self.spdtresh)
		self.log("acceleration threshold: %s degrees/second**2" % self.accthresh)
		self.log("pygaze initiation report end")
Beispiel #8
0
# create instances

# initialize the display
disp = Display()

# initialize a screen
scr = Screen()

# initialize a keyboard
kb = Keyboard(keylist=['space'],timeout=None)

# initialize a mouse
mouse = Mouse(mousebuttonlist=None, timeout=None)

# initialize a sound
snd = Sound(osc='sine', freq=4400, length=3000)
sounds = {
	'a sine wave (slightly oscillating)':Sound(osc='sine', freq=440, length=5000, attack=1000, decay=1000),
	'a saw wave':Sound(osc='saw', freq=880, length=5000, attack=0, decay=0),
	'a square wave':Sound(osc='square', freq=1760, length=5000, attack=0, decay=0),
	'white noise':Sound(osc='whitenoise'),
	'soundfile':Sound(soundfile=soundfile)
	}

# initialize a Timer
timer = Time()

# create a new logfile
log = Logfile(filename="test")
log.write(["test", "time"])
Beispiel #9
0
    def __init__(self,
                 display,
                 address='192.168.71.50',
                 udpport=49152,
                 logfile=settings.LOGFILE,
                 eventdetection=settings.EVENTDETECTION,
                 saccade_velocity_threshold=35,
                 saccade_acceleration_threshold=9500,
                 blink_threshold=settings.BLINKTHRESH,
                 **args):
        """Initializes a TobiiProGlassesTracker instance

		arguments
		display	--	a pygaze.display.Display instance

		keyword arguments
		address	-- internal ipv4/ipv6 address for Tobii Pro Glasses 2 (default =
				   '192.168.71.50', for IpV6 address use square brackets [fe80::xxxx:xxxx:xxxx:xxxx])
		udpport	-- UDP port number for Tobii Pro Glasses data streaming (default = 49152)
		"""

        # try to copy docstrings (but ignore it if it fails, as we do
        # not need it for actual functioning of the code)
        try:
            copy_docstr(BaseEyeTracker, TobiiProGlassesTracker)
        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

        # object properties
        self.disp = display
        self.screen = Screen()
        self.dispsize = settings.DISPSIZE  # display size in pixels
        self.screensize = settings.SCREENSIZE  # display size in cm
        self.screendist = settings.SCREENDIST  # distance between participant and screen in cm
        self.pixpercm = (self.dispsize[0] / float(self.screensize[0]) +
                         self.dispsize[1] / float(self.screensize[1])) / 2.0
        self.kb = Keyboard(keylist=['space', 'escape', 'q'], timeout=1)
        self.errorbeep = Sound(osc='saw', freq=100, length=100)

        # output file properties
        self.outputfile = logfile
        self.description = "experiment"  # TODO: EXPERIMENT NAME
        self.participant = "participant"  # TODO: PP NAME

        # eye tracker properties
        self.eye_used = 0  # 0=left, 1=right, 2=binocular
        self.left_eye = 0
        self.right_eye = 1
        self.binocular = 2

        self.maxtries = 100  # number of samples obtained before giving up (for obtaining accuracy and tracker distance information, as well as starting or stopping recording)
        self.prevsample = (-1, -1)

        # validation properties
        self.nvalsamples = 1000  # samples for one validation point

        # event detection properties
        self.fixtresh = 1.5  # degrees; maximal distance from fixation start (if gaze wanders beyond this, fixation has stopped)
        self.fixtimetresh = 100  # milliseconds; amount of time gaze has to linger within self.fixtresh to be marked as a fixation
        self.spdtresh = saccade_velocity_threshold  # degrees per second; saccade velocity threshold
        self.accthresh = saccade_acceleration_threshold  # degrees per second**2; saccade acceleration threshold
        self.blinkthresh = blink_threshold  # milliseconds; blink detection threshold used in PyGaze method
        self.eventdetection = eventdetection
        self.set_detection_type(self.eventdetection)
        self.weightdist = 10  # 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.tobiiglasses = TobiiGlassesController(udpport, address)

        self.triggers_values = {}

        self.logging = False
        self.current_recording_id = None
        self.current_participant_id = None
        self.current_project_id = None
Beispiel #10
0
    def __init__(self, libeyelink, tracker):
        """
		Constructor.

		Arguments:
		libeyelink	--	A libeyelink object.
		tracker		--	An tracker object as returned by pylink.EyeLink().
		"""

        pylink.EyeLinkCustomDisplay.__init__(self)

        # objects
        self.libeyelink = libeyelink
        self.display = libeyelink.display
        self.screen = Screen(disptype=settings.DISPTYPE, mousevisible=False)
        self.kb = Keyboard(keylist=None, timeout=0)
        self.mouse = Mouse(timeout=0)
        if settings.DISPTYPE == 'pygame':
            self.kb.set_timeout(timeout=0.001)
        # If we are using a DISPTYPE that cannot be used directly, we have to
        # save the camera image to a temporary file on each frame.
        #if DISPTYPE not in ('pygame', 'psychopy'):
        import tempfile
        import os
        self.tmp_file = os.path.join(tempfile.gettempdir(), '__eyelink__.jpg')
        # drawing properties
        self.xc = self.display.dispsize[0] / 2
        self.yc = self.display.dispsize[1] / 2
        self.extra_info = True
        self.ld = 40  # line distance
        self.fontsize = libeyelink.fontsize
        self.title = ""
        self.display_open = True
        self.draw_menu_screen()
        # beeps
        self.__target_beep__ = Sound(osc='sine',
                                     freq=440,
                                     length=50,
                                     attack=0,
                                     decay=0,
                                     soundfile=None)
        self.__target_beep__done__ = Sound(osc='sine',
                                           freq=880,
                                           length=200,
                                           attack=0,
                                           decay=0,
                                           soundfile=None)
        self.__target_beep__error__ = Sound(osc='sine',
                                            freq=220,
                                            length=200,
                                            attack=0,
                                            decay=0,
                                            soundfile=None)
        # Colors
        self.color = {
            pylink.CR_HAIR_COLOR: pygame.Color('white'),
            pylink.PUPIL_HAIR_COLOR: pygame.Color('white'),
            pylink.PUPIL_BOX_COLOR: pygame.Color('green'),
            pylink.SEARCH_LIMIT_BOX_COLOR: pygame.Color('red'),
            pylink.MOUSE_CURSOR_COLOR: pygame.Color('red'),
            'font': pygame.Color('white'),
        }
        # Font
        pygame.font.init()
        self.font = pygame.font.SysFont('Courier New', 11)
        # further properties
        self.state = None
        self.pal = None

        self.size = (0, 0)
        self.set_tracker(tracker)
        self.last_mouse_state = -1
        self.bit64 = '64bit' in platform.architecture()
        self.imagebuffer = self.new_array()
Beispiel #11
0
import random
from pygaze.display import Display
from pygaze.screen import Screen
from pygaze.keyboard import Keyboard
from pygaze.sound import Sound

# create a new Display instance (to interact with the
# monitor)
disp = Display()

# create a new Screen (to use as a canvas to draw on)
scr = Screen()

# Create two Sounds, one for nice and one for stern
# feedback
sine = Sound(osc='sine', freq=4000, length=500)
noise = Sound(osc='whitenoise', length=500)

# a list of vowels
vowels = ['a', 'e', 'i', 'o', 'u', 'y']

# create a new Keyboard instance, to monitor key presses
kb = Keyboard(keylist=vowels, timeout=None)

# randomly choose one vowel
letter = random.choice(vowels)

# draw the vowel on a Screen
scr.draw_text(text=letter, fontsize=128)

# fill the Display with a Screen and update the monitor
Beispiel #12
0
win.flip()
waitKeys()
win.flip()
wait(2)

## open log for participant data storage
log = open(str(pp) + "_data.txt", 'w')
log.write("pp\ttrial\tid\toutcome\tdif\tinterim_ability\n")

for j in range(trials):
    ## looking for min dif in ability
    diflist = abs(ability - dat['difficulty'])
    index = min((diflist[diflist.index[i]], i) for i in range(len(diflist)))
    ind = index[1]
    ## creating sounds
    snd1 = Sound(osc='sine', freq=dat['sound1'][dat.index[ind]], length=500)
    snd2 = Sound(osc='sine', freq=dat['sound2'][dat.index[ind]], length=500)
    win.flip()
    snd1.play()
    wait(1)
    snd2.play()
    ## indicating answer possibilities
    stim.draw()
    win.flip()
    keys = waitKeys(keyList=['q', 'z', 'slash'])
    press = keys[0]
    ## if the same and z then correct, else false. If not the same and z, correct etc.
    if press == 'q':
        break
    elif dat['sound1'][dat.index[ind]] == dat['sound2'][dat.index[ind]]:
        if press == 'z':
Beispiel #13
0
# create instances

# initialize the display
disp = Display()

# initialize a screen
scr = Screen()

# initialize a keyboard
kb = Keyboard(keylist=['space'], timeout=None)

# initialize a mouse
mouse = Mouse(mousebuttonlist=None, timeout=None)

# initialize a sound
snd = Sound(osc='sine', freq=4400, length=3000)
sounds = {
    'a sine wave (slightly oscillating)':
    Sound(osc='sine', freq=440, length=5000, attack=1000, decay=1000),
    'a saw wave':
    Sound(osc='saw', freq=880, length=5000, attack=0, decay=0),
    'a square wave':
    Sound(osc='square', freq=1760, length=5000, attack=0, decay=0),
    'white noise':
    Sound(osc='whitenoise'),
    'soundfile':
    Sound(soundfile=soundfile)
}

# initialize a Timer
timer = Time()
import pygaze.libtime as timer

# Create a new Display instance.
disp = Display()

# Create a new Keyboard instance.
kb = Keyboard()

# Create a new Logfile instance.
log = Logfile()
log.write(["trialnr", "trial_type", "stimulus", \
    "fix_onset", "stim_onset", "response", "RT", \
    "correct"])

# Create a BAD sound.
bad_sound = Sound(osc="whitenoise", length=200)
bad_sound.set_volume(1)
good_sound = Sound(osc="sine", freq=440, length=200)
good_sound.set_volume(0.5)

# Create a new Screen instance.
scr = Screen()
scr.draw_text("Welcome!", fontsize=100, \
    colour=(255,100,100))

# Pass the screen to the display.
disp.fill(scr)
disp.show()
timer.pause(3000)

# Create a list of all trials.
# Create a colour wheel to select colours from for the stimuli.
cw = create_colourwheel(STIML, STIMR, savefile='colourwheel.png')

# PYGAZE
# Initialise a new Display instance
disp = Display()

# Initialise a Screen instance for arbitrary drawing.
scr = Screen()
scr.draw_text(text="Initialising the experiment...", fontsize=FONTSIZE)
disp.fill(scr)
disp.show()

# Initialise the ka-ching sound.
kaching = Sound(soundfile=KACHING)

# Initialise a Keyboard and a Mouse instance for participant interaction.
kb = Keyboard()
mouse = Mouse()

# COMMUNICATIONS
timer.pause(5000)
_print("Initialising Client.")
# Initialise a new Client instance.
client = Client(multicast_ip)

# Establish a connection with the server.
scr.clear()
scr.draw_text(text="Connecting to the server...", fontsize=FONTSIZE)
disp.fill(scr)
    def __init__(self, libeyelink, tracker):
        """
        Constructor.

        Arguments:
        libeyelink    --    A libeyelink object.
        tracker        --    An tracker object as returned by pylink.EyeLink().
        """

        pylink.EyeLinkCustomDisplay.__init__(self)

        # objects
        self.libeyelink = libeyelink
        self.display = libeyelink.display
        self.screen = Screen(disptype=settings.DISPTYPE, mousevisible=False)
        self.kb = Keyboard(keylist=None, timeout=1)
        self.mouse = Mouse(timeout=1)
        # If we are using a DISPTYPE that cannot be used directly, we have to
        # save the camera image to a temporary file on each frame.
        #if DISPTYPE not in ('pygame', 'psychopy'):
        import tempfile
        import os
        self.tmp_file = os.path.join(tempfile.gettempdir(), "__eyelink__.jpg")
        # drawing properties
        self.xc = self.display.dispsize[0] / 2
        self.yc = self.display.dispsize[1] / 2
        self.extra_info = True
        self.ld = 40  # line distance
        self.fontsize = libeyelink.fontsize
        self.title = ""
        self.display_open = True
        self.draw_menu_screen()
        # A crosshair is drawn onto the eye image. This should be scaled in
        # pylink 1.1.0.5 (tested on Python 2.7) but not on pylink 1.11.0.0
        # (tested on Python 3.6). I'm not sure when this change happened, so
        # it's quite likely we'll have to update the minor version used here.
        pl_version = pylink.__version__.split(".")
        if int(pl_version[0]) > 1 or int(pl_version[1]) >= 11:
            self.scale_lines_in_eye_image = False
        else:
            self.scale_lines_in_eye_image = True
        # Beeps
        self.__target_beep__ = Sound(osc="sine",
                                     freq=440,
                                     length=50,
                                     attack=0,
                                     decay=0,
                                     soundfile=None)
        self.__target_beep__done__ = Sound(osc="sine",
                                           freq=880,
                                           length=200,
                                           attack=0,
                                           decay=0,
                                           soundfile=None)
        self.__target_beep__error__ = Sound(osc="sine",
                                            freq=220,
                                            length=200,
                                            attack=0,
                                            decay=0,
                                            soundfile=None)
        # Colors
        self.color = {
            pylink.CR_HAIR_COLOR: pygame.Color("white"),
            pylink.PUPIL_HAIR_COLOR: pygame.Color("white"),
            pylink.PUPIL_BOX_COLOR: pygame.Color("green"),
            pylink.SEARCH_LIMIT_BOX_COLOR: pygame.Color("red"),
            pylink.MOUSE_CURSOR_COLOR: pygame.Color("red"),
            'font': pygame.Color("white"),
        }
        # Font
        pygame.font.init()
        self.font = pygame.font.SysFont("Courier New", 11)
        # further properties
        self.state = None
        self.pal = None

        self.size = (0, 0)
        self.set_tracker(tracker)
        self.last_mouse_state = -1
        self.bit64 = "64bit" in platform.architecture()
        self.imagebuffer = self.new_array()