Exemple #1
0
    def __init__(self, disptype=settings.DISPTYPE, pos="centre", dist=125, \
        size=200):
        """Initializes FRL object
        
        arguments
        None
        
        keyword arguments
        disptype    --    display type, either "psychopy" or "pygame"
                    (default = DISPTYPE)
        pos        --    a string indicating the FRL position in relation to
                    gaze position; allowed are "centre", "top",
                    "topright", "right", "bottomright", "bottom",
                    "bottomleft", "left", "topleft" (default =
                    "centre")
        dist        --    distance between gaze position and FRL center in
                    pixels (default = 125)
        size        --    FRL diameter in pixels (default = 200)
        """

        # FRL characteristics
        self.pos = pos
        self.dist = dist
        self.size = size

        # FRL distance
        # horizontal distance between gaze position and FRL-centre
        self.frlxdis = ((self.dist**2) / 2)**0.5
        # vertical distance between gaze position and FRL-centre
        self.frlydis = ((self.dist**2) / 2)**0.5
        # FRL position
        if pos in ["center", "centre"]:
            self.frlcor = (0, 0)
        elif pos == "top":
            self.frlcor = (0, -self.dist)
        elif pos == "topright":
            self.frlcor = (-self.frlxdis, self.frlydis)
        elif pos == "right":
            self.frlcor = (self.dist, 0)
        elif pos == "bottomright":
            self.frlcor = (-self.frlxdis, -self.frlydis)
        elif pos == "bottom":
            self.frlcor = (0, self.dist)
        elif pos == "bottomleft":
            self.frlcor = (self.frlxdis, -self.frlydis)
        elif pos == "left":
            self.frlcor = (-self.dist, 0)
        elif pos == "topleft":
            self.frlcor = (self.frlxdis, self.frlydis)
        else:
            print(
                "WARNING! plugins.frl.__init__: FRL position argument '{}' not recognized; FRL position set to 'centre'."
                .format(pos))
            self.frlcor = (0, 0)

        if disptype in ["pygame", "psychopy"]:
            self.disptype = disptype
        else:
            raise Exception(
                "Error in plugins.frl.__init__: disptype '{}' not recognized".
                format(disptype))

        if self.disptype == "pygame":
            self.__class__ = PyGameFRL
        elif self.disptype == "psychopy":
            self.__class__ = PsychoPyFRL
            self.frl = Aperture(pygaze.expdisplay, self.size, \
                pos=pos2psychopos(self.frlcor), shape="circle", units="pix")
class frl(item.item):
	
	"""A plug-in to limit stimulus visibility using a forced retinal location"""
	
	def __init__(self, name, experiment, string=None):

		"""
		Constructor

		Arguments:
		name		--	item name
		experiment	--	an experiment object

		Keyword arguments:
		string		--	a definitional string (default=None)
		"""
		
		self.item_type = u"frl"
		self.sketchpad = u""
		self.timeout = 50000
		self.size = 150
		self.dist = 100
		self.angle = 45
		self.frltype = u'circle' # possibly add Gauss and raised cosine in future
		self.description = \
			u"Limits canvas visibility using a forced retinal location, until a key is pressed, or a timeout is reached"
		item.item.__init__(self, name, experiment, string)
	
	def prepare(self):

		"""
		Prepare the plug-in

		Returns:
		True
		"""

		item.item.prepare(self)
		
		# check for eyetracker
		if not hasattr(self.experiment, "eyetracker"):
			raise exceptions.runtime_error( \
				u"Please connect to the eyetracker using the the eyetracker_calibrate plugin before using the FRL plugin")
		
		# canvas
		self.cv = canvas(self.experiment)
		self.cv.copy(self.experiment.items[self.get(u'sketchpad')].canvas)
		self.drawcv = canvas(self.experiment)
		
		# keyboard
		self.kb = keyboard(self.experiment, keylist=None, timeout=1)
		
		# timeout
		self.notimeout = False
		if type(self.timeout) in [int, tuple]:
			if self.timeout <= 0:
				self.notimeout = True
		elif type(self.timeout) in [None, u'None']:
			self.notimeout = True
		else:
			raise exceptions.runtime_error( \
				u"FRL timeout should be an integer value (use None or 0 milliseconds for no timeout)")
		
		# FRL properties
		self.frlcor = pol2car(self.get(u'dist'), self.get(u'angle'))
		
		# psycho
		if self.get("canvas_backend") == u'psycho':
			# create Aperture
			from psychopy.visual import Aperture
			self.frl = Aperture(self.experiment.window, self.get(u'size'), pos=pos2psychopos(self.frlcor,self.experiment.resolution()), shape='circle', units='pix')
			# update function
			self.updatefunc = self.psychoupdate
			
		# legacy and xpyriment
		elif self.get("canvas_backend") in [u'legacy',u'xpyriment']:
			# PyGame specific properties
			self.r = self.get(u'size')/2
			self.h = 1 # updaterect height; increase to lower FRL resolution (which increases processing speed)
			# update function
			self.updatefunc = self.pygameupdate
			pass
		
		# any other backend produces an error
		else:
			raise exceptions.runtime_error( \
				u"Unsupported canvas backend: FRL plugin only supports legacy, psycho, and xpyriment backends")
		
		return True
	
	def pygameupdate(self, gazepos):
		
		"""update frl using PyGame; for internal use"""
		
		# frl position
		frlpos = (gazepos[0]-self.frlcor[0], gazepos[1]-self.frlcor[1])
		
		# clear canvas
		self.drawcv.clear()
				
		# top half
		for y in range(0,int(self.r/self.h)):
			y = self.r - y
			x = (self.r**2-y**2)**0.5
			updaterect = [frlpos[0]-x,frlpos[1]-self.h*y,2*x,self.h]
			self.drawcv.surface.set_clip(updaterect)
			self.drawcv.surface.blit(self.cv.surface,(0,0))
		# bottom half
		for y in range(0,int((self.r+1)/self.h)):
			x = (self.r**2-y**2)**0.5
			updaterect = [frlpos[0]-x,frlpos[1]+self.h*y,2*x,self.h]
			self.drawcv.surface.set_clip(updaterect)
			self.drawcv.surface.blit(self.cv.surface,(0,0))
		
		# unset clip and show canvas
		self.drawcv.surface.set_clip(None)
		self.drawcv.show()
		
	
	def psychoupdate(self, gazepos):
		
		"""update frl using PsychoPy; for internal use"""
		
		# frl position in PsychoPy coordinates
		gazepos = pos2psychopos(gazepos, self.experiment.resolution())
		frlpos = (gazepos[0]-self.frlcor[0], gazepos[1]+self.frlcor[1])
		# apply frl
		self.frl.setPos(frlpos)
		self.frl.enable()
		self.cv.show()
		self.frl.disable()
		
	
	def run(self):

		"""
		Run the plug-in

		Returns:
		True
		"""

		self.set_item_onset()
		
		stop = False
		t0 = self.time()
		
		while not stop:
			# get gaze position
			gazepos = self.experiment.eyetracker.sample()
			
			# update frl accordingly
			self.updatefunc(gazepos)
			
			# response
			response, t1 = self.kb.get_key()

			# timeout
			if (self.time() - t0 > self.timeout and not self.notimeout) or (response != None):
				stop = True
		
		self.experiment.set(u'response', response)
		self.experiment.set(u'response_time', t1-t0)
		
		return True
Exemple #3
0
    def __init__(self,
                 disptype=settings.DISPTYPE,
                 pos='centre',
                 dist=125,
                 size=200):
        """Initializes FRL object
		
		arguments
		None
		
		keyword arguments
		disptype	--	display type, either 'psychopy' or 'pygame'
					(default = DISPTYPE)
		pos		--	a string indicating the FRL position in relation to
					gaze position; allowed are 'centre', 'top',
					'topright', 'right', 'bottomright', 'bottom',
					'bottomleft', 'left', 'topleft' (default =
					'centre')
		dist		--	distance between gaze position and FRL center in
					pixels (default = 125)
		size		--	FRL diameter in pixels (default = 200)
		"""

        # FRL characteristics
        self.pos = pos
        self.dist = dist
        self.size = size

        # FRL distance
        self.frlxdis = (
            (self.dist**2) /
            2)**0.5  # horizontal distance between gaze position and FRL-centre
        self.frlydis = (
            (self.dist**2) /
            2)**0.5  # vertical distance between gaze position and FRL-centre
        # FRL position
        if pos in ['center', 'centre']:
            self.frlcor = (0, 0)
        elif pos == 'top':
            self.frlcor = (0, -self.dist)
        elif pos == 'topright':
            self.frlcor = (-self.frlxdis, self.frlydis)
        elif pos == 'right':
            self.frlcor = (self.dist, 0)
        elif pos == 'bottomright':
            self.frlcor = (-self.frlxdis, -self.frlydis)
        elif pos == 'bottom':
            self.frlcor = (0, self.dist)
        elif pos == 'bottomleft':
            self.frlcor = (self.frlxdis, -self.frlydis)
        elif pos == 'left':
            self.frlcor = (-self.dist, 0)
        elif pos == 'topleft':
            self.frlcor = (self.frlxdis, self.frlydis)
        else:
            print(
                "WARNING! plugins.frl.__init__: FRL position argument '%s' not recognized; FRL position set to 'centre'."
                % pos)
            self.frlcor = (0, 0)

        if disptype in ['pygame', 'psychopy']:
            self.disptype = disptype
        else:
            raise Exception(
                "Error in plugins.frl.__init__: disptype '%s' not recognized" %
                disptype)

        if self.disptype == 'pygame':
            self.__class__ = PyGameFRL
        elif self.disptype == 'psychopy':
            self.__class__ = PsychoPyFRL
            self.frl = Aperture(pygaze.expdisplay,
                                self.size,
                                pos=pos2psychopos(self.frlcor),
                                shape='circle',
                                units='pix')
	def prepare(self):

		"""
		Prepare the plug-in

		Returns:
		True
		"""

		item.item.prepare(self)
		
		# check for eyetracker
		if not hasattr(self.experiment, "eyetracker"):
			raise exceptions.runtime_error( \
				u"Please connect to the eyetracker using the the eyetracker_calibrate plugin before using the FRL plugin")
		
		# canvas
		self.cv = canvas(self.experiment)
		self.cv.copy(self.experiment.items[self.get(u'sketchpad')].canvas)
		self.drawcv = canvas(self.experiment)
		
		# keyboard
		self.kb = keyboard(self.experiment, keylist=None, timeout=1)
		
		# timeout
		self.notimeout = False
		if type(self.timeout) in [int, tuple]:
			if self.timeout <= 0:
				self.notimeout = True
		elif type(self.timeout) in [None, u'None']:
			self.notimeout = True
		else:
			raise exceptions.runtime_error( \
				u"FRL timeout should be an integer value (use None or 0 milliseconds for no timeout)")
		
		# FRL properties
		self.frlcor = pol2car(self.get(u'dist'), self.get(u'angle'))
		
		# psycho
		if self.get("canvas_backend") == u'psycho':
			# create Aperture
			from psychopy.visual import Aperture
			self.frl = Aperture(self.experiment.window, self.get(u'size'), pos=pos2psychopos(self.frlcor,self.experiment.resolution()), shape='circle', units='pix')
			# update function
			self.updatefunc = self.psychoupdate
			
		# legacy and xpyriment
		elif self.get("canvas_backend") in [u'legacy',u'xpyriment']:
			# PyGame specific properties
			self.r = self.get(u'size')/2
			self.h = 1 # updaterect height; increase to lower FRL resolution (which increases processing speed)
			# update function
			self.updatefunc = self.pygameupdate
			pass
		
		# any other backend produces an error
		else:
			raise exceptions.runtime_error( \
				u"Unsupported canvas backend: FRL plugin only supports legacy, psycho, and xpyriment backends")
		
		return True